LayoutDemos.cs
  1. //
  2. // This code is part of Document Solutions for Imaging demos.
  3. // Copyright (c) MESCIUS inc. All rights reserved.
  4. //
  5. using System;
  6. using System.IO;
  7. using System.Drawing;
  8. using System.Collections.Generic;
  9. using System.Linq;
  10. using System.Numerics;
  11. using GrapeCity.Documents.Drawing;
  12. using GrapeCity.Documents.Text;
  13. using GrapeCity.Documents.Imaging;
  14. using GrapeCity.Documents.Layout;
  15. using GrapeCity.Documents.Layout.Composition;
  16. using GCTEXT = GrapeCity.Documents.Text;
  17. using GCDRAW = GrapeCity.Documents.Drawing;
  18.  
  19. namespace DsImagingWeb.Demos
  20. {
  21. // This integrated demo shows how to use helper classes
  22. // in the GrapeCity.Documents.Layout.Composition namespace
  23. // to create complex and flexible constraint-based layouts
  24. // with custom z-order and clipping.
  25. public class LayoutDemos
  26. {
  27. static readonly Color
  28. PageColor = Color.FromArgb(39, 41, 43),
  29. BoxColor = Color.FromArgb(230, 230, 230),
  30. CodeColor = Color.FromArgb(132, 211, 232),
  31. RectColor = Color.FromArgb(64, 126, 148),
  32. DescColor = Color.White;
  33. delegate void DrawLayoutSample(GcGraphics g, Size pageSize);
  34. static readonly Dictionary<string, DrawLayoutSample> c_samples = new Dictionary<string, DrawLayoutSample>()
  35. {
  36. { "DrawSample1", DrawSample1 },
  37. { "DrawSample2", DrawSample2 },
  38. { "DrawSample3", DrawSample3 },
  39. { "DrawSample4", DrawSample4 },
  40. { "DrawSample5", DrawSample5 },
  41. { "DrawSample6", DrawSample6 },
  42. { "DrawSample7", DrawSample7 },
  43. { "DrawSample8", DrawSample8 },
  44. };
  45.  
  46. public GcBitmap GenerateImage(Size pixelSize, float dpi, bool opaque, string[] sampleParams = null)
  47. {
  48. if (!c_samples.TryGetValue(sampleParams[3], out DrawLayoutSample drawSample))
  49. throw new Exception($"Unknown parameterized sample: {sampleParams[3]}");
  50.  
  51. var bmp = new GcBitmap(pixelSize.Width, pixelSize.Height, opaque, dpi, dpi);
  52. using var g = bmp.CreateGraphics(PageColor);
  53. drawSample(g, pixelSize);
  54.  
  55. return bmp;
  56. }
  57.  
  58. public static List<string[]> GetSampleParamsList()
  59. {
  60. return new List<string[]>()
  61. {
  62. // Strings are name, description, info. Rest are arbitrary strings:
  63. new string[] { "Figures 1-4", "Figures 1-4: horizontal, vertical, alignment constraint and guidelines",
  64. null,
  65. "DrawSample1" },
  66. new string[] { "Figure 5", "Figure 5: Barrier constraint anchored to two visuals",
  67. null,
  68. "DrawSample2" },
  69. new string[] { "Figure 6", "Figure 6: Horizontal chain with weighted widths",
  70. null,
  71. "DrawSample3" },
  72. new string[] { "Figure 7", "Figure 7: Horizontal chain with evenly distributed rectangles and margins",
  73. null,
  74. "DrawSample4" },
  75. new string[] { "Figure 8", "Figure 8: Horizontal chain with evenly distributed rectangles, no margins",
  76. null,
  77. "DrawSample5" },
  78. new string[] { "Figure 9", "Figure 9: Weighted horizontal chain without margins",
  79. null,
  80. "DrawSample6" },
  81. new string[] { "Figure 10", "Figure 10: Horizontal chain with weighted margins and packed rectangles",
  82. null,
  83. "DrawSample7" },
  84. new string[] { "Text Flow", "Text flow in and around non-rectangular contours",
  85. null,
  86. "DrawSample8" },
  87. };
  88. }
  89.  
  90. // Figures 1-4: horizontal, vertical, alignment constraint and guidelines.
  91. static void DrawSample1(GcGraphics g, Size _)
  92. {
  93. g.Transform = Matrix3x2.CreateScale(1.4f);
  94.  
  95. // The Surface object can layout Visuals and draw them on the graphics.
  96. var surf = new Surface();
  97.  
  98. // view1
  99.  
  100. // The View object represents a group of Visuals with a transformation matrix.
  101. var view1 = surf.CreateView(250, 150).Translate(50, 40);
  102.  
  103. // Visual is an element with the associated LayoutRect used for its
  104. // positioning/ and a delegate that draws its content on the graphics.
  105. var v = view1.CreateVisual(DrawView);
  106. v.Tag = new FigureCaption(1, "A horizontal constraint to the parent:",
  107. "rA.SetLeft(null, AnchorParam.Left, 90);");
  108. v.LayoutRect.AnchorExact(null);
  109.  
  110. v = view1.CreateVisual(DrawRect);
  111. var rA = v.LayoutRect;
  112. rA.SetLeft(null, AnchorParam.Left, 90);
  113. rA.SetWidth(70);
  114. rA.SetHeight(40);
  115. rA.SetVerticalCenter(null, AnchorParam.VerticalCenter);
  116. v.Tag = "A";
  117.  
  118. var r = view1.CreateVisual(DrawLineWithLeftArrow).LayoutRect;
  119. r.AnchorTopBottom(rA, 0, 0);
  120. r.SetLeft(null, AnchorParam.Left);
  121. r.SetRight(rA, AnchorParam.Left);
  122.  
  123. // view2
  124. var view2 = surf.CreateView(250, 150).Translate(350, 40);
  125. v = view2.CreateVisual(DrawView);
  126. v.Tag = new FigureCaption(2, "An offset horizontal alignment constraint:",
  127. "rB.SetLeft(rA, AnchorParam.Left, 40);");
  128. v.LayoutRect.AnchorExact(null);
  129.  
  130. v = view2.CreateVisual(DrawRect);
  131. rA = v.LayoutRect;
  132. rA.AnchorTopLeft(null, 15, 70, 110, 60);
  133. v.Tag = "A";
  134.  
  135. v = view2.CreateVisual(DrawRect);
  136. var rB = v.LayoutRect;
  137. rB.SetLeft(rA, AnchorParam.Left, 40);
  138. rB.SetWidth(60);
  139. rB.SetHeight(35);
  140. rB.SetTop(rA, AnchorParam.Bottom, 20);
  141. v.Tag = "B";
  142.  
  143. r = view2.CreateVisual(DrawVertLineWithLeftArrow).LayoutRect;
  144. r.SetTop(rA, AnchorParam.VerticalCenter);
  145. r.SetBottom(rB, AnchorParam.VerticalCenter);
  146. r.SetLeft(rA, AnchorParam.Left);
  147. r.SetRight(rB, AnchorParam.Left);
  148.  
  149. // view3
  150. var view3 = surf.CreateView(250, 150).Translate(50, 260);
  151. v = view3.CreateVisual(DrawView);
  152. v.Tag = new FigureCaption(3, "Horizontal and vertical constraints:",
  153. "rB.SetLeft(rA, AnchorParam.Right, 50);\n" +
  154. "rC.SetTop(rA, AnchorParam.Bottom, 40);");
  155. v.LayoutRect.AnchorExact(null);
  156.  
  157. v = view3.CreateVisual(DrawRect);
  158. rA = v.LayoutRect;
  159. rA.AnchorTopLeft(null, 15, 30, 70, 40);
  160. v.Tag = "A";
  161.  
  162. v = view3.CreateVisual(DrawRect);
  163. rB = v.LayoutRect;
  164. rB.SetLeft(rA, AnchorParam.Right, 50);
  165. rB.SetWidth(70);
  166. rB.SetHeight(40);
  167. rB.SetTop(rA, AnchorParam.Top);
  168. v.Tag = "B";
  169.  
  170. v = view3.CreateVisual(DrawRect);
  171. var rC = v.LayoutRect;
  172. rC.SetTop(rA, AnchorParam.Bottom, 40);
  173. rC.SetWidth(70);
  174. rC.SetHeight(40);
  175. rC.SetLeft(rA, AnchorParam.Left);
  176. v.Tag = "C";
  177.  
  178. r = view3.CreateVisual(DrawLineWithLeftArrow).LayoutRect;
  179. r.AnchorTopBottom(rA, 0, 0);
  180. r.SetLeft(rA, AnchorParam.Right);
  181. r.SetRight(rB, AnchorParam.Left);
  182.  
  183. r = view3.CreateVisual(DrawLineWithUpArrow).LayoutRect;
  184. r.AnchorLeftRight(rA, 0, 0);
  185. r.SetTop(rA, AnchorParam.Bottom);
  186. r.SetBottom(rC, AnchorParam.Top);
  187.  
  188. // view4
  189. var view4 = surf.CreateView(250, 150).Translate(350, 260);
  190. var layoutView = view4.LayoutView;
  191. v = view4.CreateVisual(DrawView);
  192. v.Tag = new FigureCaption(4, "A rectangle constrained to a guideline:",
  193. "var anchorPoint = layoutView.CreatePoint(0.25f, 0);\n" +
  194. "rA.SetLeft(anchorPoint, 60);");
  195. v.LayoutRect.AnchorExact(null);
  196.  
  197. // An anchor point can work as the guideline on the X or the Y axes.
  198. var anchorPoint = layoutView.CreatePoint(0.25f, 0);
  199.  
  200. v = view4.CreateVisual(DrawVertGuideline);
  201. var rG = v.LayoutRect;
  202. rG.SetLeft(anchorPoint);
  203. rG.AnchorVerticalLine(null);
  204. v.Tag = "25 %";
  205.  
  206. v = view4.CreateVisual(DrawRect);
  207. rA = v.LayoutRect;
  208. rA.SetLeft(anchorPoint, 60);
  209. rA.SetWidth(70);
  210. rA.SetHeight(40);
  211. rA.SetVerticalCenter(null, AnchorParam.VerticalCenter);
  212. v.Tag = "A";
  213.  
  214. r = view4.CreateVisual(DrawLineWithLeftArrow).LayoutRect;
  215. r.AnchorTopBottom(rA, 0, 0);
  216. r.SetLeft(rG, AnchorParam.Left);
  217. r.SetRight(rA, AnchorParam.Left);
  218.  
  219. surf.Render(g);
  220. }
  221.  
  222. // Figure 5: Barrier constraint anchored to two visuals.
  223. static void DrawSample2(GcGraphics g, Size _)
  224. {
  225. g.Transform = Matrix3x2.CreateScale(2);
  226.  
  227. var surf = new Surface();
  228.  
  229. // View1
  230. var view1 = surf.CreateView(350, 160).Translate(30, 30);
  231. view1.CreateVisual(DrawView).LayoutRect.AnchorExact(null);
  232.  
  233. var v = view1.CreateVisual(DrawRect);
  234. var rA = v.LayoutRect;
  235. rA.AnchorTopLeft(null, 30, 50, 60, 40);
  236. v.Tag = "A";
  237.  
  238. v = view1.CreateVisual(DrawRect);
  239. var rB = v.LayoutRect;
  240. rB.AnchorTopLeft(null, 90, 50, 90, 40);
  241. v.Tag = "B";
  242.  
  243. v = view1.CreateVisual(DrawVertGuideline);
  244. var rG = v.LayoutRect;
  245.  
  246. // Adding multiple MinLeft constraints to the same rectangle creates
  247. // a barrier to be used as the base for other rectangles.
  248. rG.AppendMinLeft(rA, AnchorParam.Right);
  249. rG.AppendMinLeft(rB, AnchorParam.Right);
  250.  
  251. rG.AnchorVerticalLine(null);
  252.  
  253. v = view1.CreateVisual(DrawRect);
  254. var rC = v.LayoutRect;
  255. rC.AppendMinLeft(rA, AnchorParam.Right, 50);
  256. rC.AppendMinLeft(rB, AnchorParam.Right, 50);
  257. rC.SetWidth(70);
  258. rC.SetHeight(40);
  259. rC.SetVerticalCenter(null, AnchorParam.VerticalCenter);
  260. v.Tag = "C";
  261.  
  262. var r = view1.CreateVisual(DrawLineWithLeftArrow).LayoutRect;
  263. r.AnchorTopBottom(rC, 0, 0);
  264. r.SetLeft(rG, AnchorParam.Right);
  265. r.SetRight(rC, AnchorParam.Left);
  266.  
  267. // View2
  268. var view2 = surf.CreateView(350, 160).Translate(30, 210);
  269. v = view2.CreateVisual(DrawView);
  270. v.Tag = new FigureCaption(5, "C is constrained to a barrier, which moves based on\n" +
  271. "the position and size of both A and B:",
  272. "rC.AppendMinLeft(rA, AnchorParam.Right, 50);\n" +
  273. "rC.AppendMinLeft(rB, AnchorParam.Right, 50);");
  274. v.LayoutRect.AnchorExact(null);
  275.  
  276. v = view2.CreateVisual(DrawRect);
  277. rA = v.LayoutRect;
  278. rA.AnchorTopLeft(null, 30, 50, 130, 40);
  279. v.Tag = "A";
  280.  
  281. v = view2.CreateVisual(DrawRect);
  282. rB = v.LayoutRect;
  283. rB.AnchorTopLeft(null, 90, 50, 90, 40);
  284. v.Tag = "B";
  285.  
  286. v = view2.CreateVisual(DrawVertGuideline);
  287. rG = v.LayoutRect;
  288. rG.AppendMinLeft(rA, AnchorParam.Right);
  289. rG.AppendMinLeft(rB, AnchorParam.Right);
  290. rG.AnchorVerticalLine(null);
  291.  
  292. v = view2.CreateVisual(DrawRect);
  293. rC = v.LayoutRect;
  294. rC.AppendMinLeft(rA, AnchorParam.Right, 50);
  295. rC.AppendMinLeft(rB, AnchorParam.Right, 50);
  296. rC.SetWidth(70);
  297. rC.SetHeight(40);
  298. rC.SetVerticalCenter(null, AnchorParam.VerticalCenter);
  299. v.Tag = "C";
  300.  
  301. r = view2.CreateVisual(DrawLineWithLeftArrow).LayoutRect;
  302. r.AnchorTopBottom(rC, 0, 0);
  303. r.SetLeft(rG, AnchorParam.Right);
  304. r.SetRight(rC, AnchorParam.Left);
  305.  
  306. surf.Render(g);
  307. }
  308.  
  309. // Figure 6: Horizontal chain with weighted widths.
  310. static void DrawSample3(GcGraphics g, Size _)
  311. {
  312. g.Transform = Matrix3x2.CreateScale(2);
  313.  
  314. var surf = new Surface();
  315.  
  316. var view = surf.CreateView(350, 120).Translate(30, 40);
  317. var v = view.CreateVisual(DrawView);
  318. v.Tag = new FigureCaption(6, "A horizontal chain with two rectangles having weighted\nwidths and a fixed space between them:",
  319. "rA.SetLeft(null, AnchorParam.Left, 60);\n" +
  320. "rA.SetStarWidth(1);\n" +
  321. "rAB.SetLeftAndOpposite(rA, AnchorParam.Right);\n" +
  322. "rAB.SetWidth(50);\n" +
  323. "rB.SetLeftAndOpposite(rAB, AnchorParam.Right);\n" +
  324. "rB.SetStarWidth(2);\n" +
  325. "rB.SetRight(null, AnchorParam.Right, -60);");
  326. v.LayoutRect.AnchorExact(null);
  327.  
  328. v = view.CreateVisual(DrawRect);
  329. var rA = v.LayoutRect;
  330. rA.SetHeight(40);
  331. rA.SetVerticalCenter(null, AnchorParam.VerticalCenter);
  332. v.Tag = "A";
  333.  
  334. v = view.CreateVisual(DrawRect);
  335. var rB = v.LayoutRect;
  336. rB.SetHeight(40);
  337. rB.SetVerticalCenter(null, AnchorParam.VerticalCenter);
  338. v.Tag = "B";
  339.  
  340. var rAB = view.CreateVisual(DrawLeftRightLines).LayoutRect;
  341. rAB.AnchorTopBottom(rA, 0, 0);
  342.  
  343. // The SetStarWidth method sets the weight of width of that specific
  344. // rectangle relative to the width of other rectangles that belong
  345. // to the same chain and have the "star" width.
  346.  
  347. // SetLeftAndOpposite method makes a chain of rectangles that affect
  348. // the position of each other in both directions.
  349.  
  350. rA.SetLeft(null, AnchorParam.Left, 60);
  351. rA.SetStarWidth(1);
  352. rAB.SetLeftAndOpposite(rA, AnchorParam.Right);
  353. rAB.SetWidth(50);
  354. rB.SetLeftAndOpposite(rAB, AnchorParam.Right);
  355. rB.SetStarWidth(2);
  356. rB.SetRight(null, AnchorParam.Right, -60);
  357.  
  358. var r = view.CreateVisual(DrawLineWithLeftArrow).LayoutRect;
  359. r.AnchorTopBottom(rA, 0, 0);
  360. r.SetLeft(null, AnchorParam.Left);
  361. r.SetRight(rA, AnchorParam.Left);
  362.  
  363. r = view.CreateVisual(DrawLineWithRightArrow).LayoutRect;
  364. r.AnchorTopBottom(rB, 0, 0);
  365. r.SetLeft(rB, AnchorParam.Right);
  366. r.SetRight(null, AnchorParam.Right);
  367.  
  368. surf.Render(g);
  369. }
  370.  
  371. // Figure 7: Horizontal chain with evenly distributed rectangles and margins.
  372. static void DrawSample4(GcGraphics g, Size _)
  373. {
  374. g.Transform = Matrix3x2.CreateScale(1.8f);
  375.  
  376. var surf = new Surface();
  377.  
  378. var view = surf.CreateView(430, 120).Translate(30, 40);
  379. var v = view.CreateVisual(DrawView);
  380. v.Tag = new FigureCaption(7, "A horizontal chain with three evenly distributed rectangles\nafter margins are accounted for:",
  381. "rA.SetLeft(null, AnchorParam.Left, 60);\n" +
  382. "rA.SetWidth(70);\n" +
  383. "rAB.SetLeftAndOpposite(rA, AnchorParam.Right);\n" +
  384. "rAB.SetStarWidth(1);\n" +
  385. "rAB.SetRightAndOpposite(rB, AnchorParam.Left);\n" +
  386. "rB.SetWidth(70);\n" +
  387. "rBC.SetLeftAndOpposite(rB, AnchorParam.Right);\n" +
  388. "rBC.SetStarWidth(1);\n" +
  389. "rC.SetLeftAndOpposite(rBC, AnchorParam.Right);\n" +
  390. "rC.SetWidth(70);\n" +
  391. "rC.SetRight(null, AnchorParam.Right, -60);");
  392. v.LayoutRect.AnchorExact(null);
  393.  
  394. v = view.CreateVisual(DrawRect);
  395. var rA = v.LayoutRect;
  396. rA.SetHeight(40);
  397. rA.SetVerticalCenter(null, AnchorParam.VerticalCenter);
  398. v.Tag = "A";
  399.  
  400. v = view.CreateVisual(DrawRect);
  401. var rB = v.LayoutRect;
  402. rB.SetHeight(40);
  403. rB.SetVerticalCenter(null, AnchorParam.VerticalCenter);
  404. v.Tag = "B";
  405.  
  406. v = view.CreateVisual(DrawRect);
  407. var rC = v.LayoutRect;
  408. rC.SetHeight(40);
  409. rC.SetVerticalCenter(null, AnchorParam.VerticalCenter);
  410. v.Tag = "C";
  411.  
  412. var rAB = view.CreateVisual(DrawLeftRightLines).LayoutRect;
  413. rAB.AnchorTopBottom(rA, 0, 0);
  414.  
  415. var rBC = view.CreateVisual(DrawLeftRightLines).LayoutRect;
  416. rBC.AnchorTopBottom(rB, 0, 0);
  417.  
  418. rA.SetLeft(null, AnchorParam.Left, 60);
  419. rA.SetWidth(70);
  420. rAB.SetLeftAndOpposite(rA, AnchorParam.Right);
  421. rAB.SetStarWidth(1);
  422. rAB.SetRightAndOpposite(rB, AnchorParam.Left);
  423. rB.SetWidth(70);
  424. rBC.SetLeftAndOpposite(rB, AnchorParam.Right);
  425. rBC.SetStarWidth(1);
  426. rC.SetLeftAndOpposite(rBC, AnchorParam.Right);
  427. rC.SetWidth(70);
  428. rC.SetRight(null, AnchorParam.Right, -60);
  429.  
  430. var r = view.CreateVisual(DrawLineWithLeftArrow).LayoutRect;
  431. r.AnchorTopBottom(rA, 0, 0);
  432. r.SetLeft(null, AnchorParam.Left);
  433. r.SetRight(rA, AnchorParam.Left);
  434.  
  435. r = view.CreateVisual(DrawLineWithRightArrow).LayoutRect;
  436. r.AnchorTopBottom(rC, 0, 0);
  437. r.SetLeft(rC, AnchorParam.Right);
  438. r.SetRight(null, AnchorParam.Right);
  439.  
  440. surf.Render(g);
  441. }
  442.  
  443. // Figure 8: Horizontal chain with evenly distributed rectangles, no margins.
  444. static void DrawSample5(GcGraphics g, Size _)
  445. {
  446. g.Transform = Matrix3x2.CreateScale(2);
  447.  
  448. var surf = new Surface();
  449.  
  450. var view = surf.CreateView(340, 120).Translate(30, 40);
  451. var v = view.CreateVisual(DrawView);
  452. v.Tag = new FigureCaption(8, "Same as Figure 7, without accounting for the margins:",
  453. "rA.SetLeft(null, AnchorParam.Left);\n" +
  454. "rA.SetWidth(70);\n" +
  455. "rA.SetRightAndOpposite(rAB, AnchorParam.Left);\n" +
  456. "rAB.SetStarWidth(1);\n" +
  457. "rB.SetLeftAndOpposite(rAB, AnchorParam.Right);\n" +
  458. "rB.SetWidth(70);\n" +
  459. "rB.SetRightAndOpposite(rBC, AnchorParam.Left);\n" +
  460. "rBC.SetStarWidth(1);\n" +
  461. "rC.SetLeftAndOpposite(rBC, AnchorParam.Right);\n" +
  462. "rC.SetWidth(70);\n" +
  463. "rC.SetRight(null, AnchorParam.Right);");
  464. v.LayoutRect.AnchorExact(null);
  465.  
  466. v = view.CreateVisual(DrawRect);
  467. var rA = v.LayoutRect;
  468. rA.SetHeight(40);
  469. rA.SetVerticalCenter(null, AnchorParam.VerticalCenter);
  470. v.Tag = "A";
  471.  
  472. v = view.CreateVisual(DrawRect);
  473. var rB = v.LayoutRect;
  474. rB.SetHeight(40);
  475. rB.SetVerticalCenter(null, AnchorParam.VerticalCenter);
  476. v.Tag = "B";
  477.  
  478. v = view.CreateVisual(DrawRect);
  479. var rC = v.LayoutRect;
  480. rC.SetHeight(40);
  481. rC.SetVerticalCenter(null, AnchorParam.VerticalCenter);
  482. v.Tag = "C";
  483.  
  484. var rAB = view.CreateVisual(DrawLeftRightLines).LayoutRect;
  485. rAB.AnchorTopBottom(rA, 0, 0);
  486.  
  487. var rBC = view.CreateVisual(DrawLeftRightLines).LayoutRect;
  488. rBC.AnchorTopBottom(rB, 0, 0);
  489.  
  490. rA.SetLeft(null, AnchorParam.Left);
  491. rA.SetWidth(70);
  492. rA.SetRightAndOpposite(rAB, AnchorParam.Left);
  493. rAB.SetStarWidth(1);
  494. rB.SetLeftAndOpposite(rAB, AnchorParam.Right);
  495. rB.SetWidth(70);
  496. rB.SetRightAndOpposite(rBC, AnchorParam.Left);
  497. rBC.SetStarWidth(1);
  498. rC.SetLeftAndOpposite(rBC, AnchorParam.Right);
  499. rC.SetWidth(70);
  500. rC.SetRight(null, AnchorParam.Right);
  501.  
  502. surf.Render(g);
  503. }
  504.  
  505. // Figure 9: Weighted horizontal chain without margins.
  506. static void DrawSample6(GcGraphics g, Size _)
  507. {
  508. g.Transform = Matrix3x2.CreateScale(2);
  509.  
  510. var surf = new Surface();
  511.  
  512. var view = surf.CreateView(340, 120).Translate(30, 40);
  513. var v = view.CreateVisual(DrawView);
  514. v.Tag = new FigureCaption(9, "A weighted horizontal chain without margins:",
  515. "rA.SetLeft(null, AnchorParam.Left);\n" +
  516. "rA.SetStarWidth(1);\n" +
  517. "rA.SetRightAndOpposite(rB, AnchorParam.Left);\n" +
  518. "rB.SetStarWidth(2);\n" +
  519. "rB.SetRightAndOpposite(rC, AnchorParam.Left);\n" +
  520. "rC.SetStarWidth(2);\n" +
  521. "rC.SetRight(null, AnchorParam.Right);");
  522. v.LayoutRect.AnchorExact(null);
  523.  
  524. v = view.CreateVisual(DrawRect);
  525. var rA = v.LayoutRect;
  526. rA.SetHeight(40);
  527. rA.SetVerticalCenter(null, AnchorParam.VerticalCenter);
  528. v.Tag = "A";
  529.  
  530. v = view.CreateVisual(DrawRect);
  531. var rB = v.LayoutRect;
  532. rB.SetHeight(40);
  533. rB.SetVerticalCenter(null, AnchorParam.VerticalCenter);
  534. v.Tag = "B";
  535.  
  536. v = view.CreateVisual(DrawRect);
  537. var rC = v.LayoutRect;
  538. rC.SetHeight(40);
  539. rC.SetVerticalCenter(null, AnchorParam.VerticalCenter);
  540. v.Tag = "C";
  541.  
  542. rA.SetLeft(null, AnchorParam.Left);
  543. rA.SetStarWidth(1);
  544. rA.SetRightAndOpposite(rB, AnchorParam.Left);
  545. rB.SetStarWidth(2);
  546. rB.SetRightAndOpposite(rC, AnchorParam.Left);
  547. rC.SetStarWidth(2);
  548. rC.SetRight(null, AnchorParam.Right);
  549.  
  550. surf.Render(g);
  551. }
  552.  
  553. // Figure 10: Horizontal chain with weighted margins and packed rectangles.
  554. static void DrawSample7(GcGraphics g, Size _)
  555. {
  556. g.Transform = Matrix3x2.CreateScale(2);
  557.  
  558. var surf = new Surface();
  559.  
  560. var view = surf.CreateView(370, 120).Translate(30, 40);
  561. var v = view.CreateVisual(DrawView);
  562. v.Tag = new FigureCaption(10, "Rectangles are packed together after margins with weights\nare accounted for:",
  563. "rBeforeA.SetLeft(null, AnchorParam.Left);\n" +
  564. "rBeforeA.SetStarWidth(3);\n" +
  565. "rA.SetLeftAndOpposite(rBeforeA, AnchorParam.Right);\n" +
  566. "rA.SetWidth(70);\n" +
  567. "rB.SetLeftAndOpposite(rA, AnchorParam.Right);\n" +
  568. "rB.SetWidth(70);\n" +
  569. "rC.SetLeftAndOpposite(rB, AnchorParam.Right);\n" +
  570. "rC.SetWidth(70);\n" +
  571. "rAfterC.SetLeftAndOpposite(rC, AnchorParam.Right);\n" +
  572. "rAfterC.SetStarWidth(1);\n" +
  573. "rAfterC.SetRight(null, AnchorParam.Right);");
  574. v.LayoutRect.AnchorExact(null);
  575.  
  576. v = view.CreateVisual(DrawRect);
  577. var rA = v.LayoutRect;
  578. rA.SetHeight(40);
  579. rA.SetVerticalCenter(null, AnchorParam.VerticalCenter);
  580. v.Tag = "A";
  581.  
  582. v = view.CreateVisual(DrawRect);
  583. var rB = v.LayoutRect;
  584. rB.SetHeight(40);
  585. rB.SetVerticalCenter(null, AnchorParam.VerticalCenter);
  586. v.Tag = "B";
  587.  
  588. v = view.CreateVisual(DrawRect);
  589. var rC = v.LayoutRect;
  590. rC.SetHeight(40);
  591. rC.SetVerticalCenter(null, AnchorParam.VerticalCenter);
  592. v.Tag = "C";
  593.  
  594. var rBeforeA = view.CreateVisual(DrawLineWithLeftArrow).LayoutRect;
  595. rBeforeA.AnchorTopBottom(rA, 0, 0);
  596.  
  597. var rAfterC = view.CreateVisual(DrawLineWithRightArrow).LayoutRect;
  598. rAfterC.AnchorTopBottom(rC, 0, 0);
  599.  
  600. rBeforeA.SetLeft(null, AnchorParam.Left);
  601. rBeforeA.SetStarWidth(3);
  602. rA.SetLeftAndOpposite(rBeforeA, AnchorParam.Right);
  603. rA.SetWidth(70);
  604. rB.SetLeftAndOpposite(rA, AnchorParam.Right);
  605. rB.SetWidth(70);
  606. rC.SetLeftAndOpposite(rB, AnchorParam.Right);
  607. rC.SetWidth(70);
  608. rAfterC.SetLeftAndOpposite(rC, AnchorParam.Right);
  609. rAfterC.SetStarWidth(1);
  610. rAfterC.SetRight(null, AnchorParam.Right);
  611.  
  612. surf.Render(g);
  613. }
  614.  
  615. // Text flow in and around non-rectangular contours.
  616. static void DrawSample8(GcGraphics g, Size pageSize)
  617. {
  618. g.FillRectangle(new RectangleF(0, 0, pageSize.Width, pageSize.Height), Color.White);
  619.  
  620. var surf = new Surface();
  621.  
  622. // Contour objects can be referenced in constraints defined for text rectangles.
  623. CreateFigure1(surf, out Contour c1_outer);
  624. CreateFigure2(surf, out Contour c2_outer, out Contour c2_inner);
  625.  
  626. const float rowHeight = 24f;
  627. const float lineSpacing = 5f;
  628. const float paragraphSpacing = 10f;
  629. const float fontSize = 18f;
  630.  
  631. // The main View object that displays horizontal text.
  632. var view = surf.CreateView(pageSize.Width, pageSize.Height);
  633. var rcMargin = view.CreateSpace().LayoutRect;
  634. rcMargin.AnchorDeflate(null, 20);
  635.  
  636. var tf = new TextFormat
  637. {
  638. Font = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "calibri.ttf")),
  639. FontSizeInGraphicUnits = true,
  640. FontSize = fontSize,
  641. FontFeatures = new FontFeature[] { new FontFeature(FeatureTag.liga, false) }
  642. };
  643. var noRects = new List<ObjectRect>();
  644.  
  645. TextLayout tl = null;
  646.  
  647. var tso = new TextSplitOptions
  648. {
  649. RestObjectRects = noRects,
  650. AllowMovingAllToRest = true
  651. };
  652.  
  653. LayoutRect rcPrevTop = null;
  654. LayoutRect rcPrevLeft = null;
  655. bool paragraphStarted = false;
  656.  
  657. while (true)
  658. {
  659. var r0 = view.CreateVisual(DrawTextFragment).LayoutRect;
  660. if (rcPrevLeft != null)
  661. r0.SetTop(rcPrevLeft, AnchorParam.Top);
  662. else if (rcPrevTop != null)
  663. r0.SetTop(rcPrevTop, AnchorParam.Bottom, paragraphStarted ? lineSpacing : paragraphSpacing);
  664. else
  665. r0.SetTop(rcMargin, AnchorParam.Top);
  666. if (rcPrevLeft is null)
  667. r0.SetLeft(rcMargin, AnchorParam.Left);
  668. else
  669. r0.SetLeft(rcPrevLeft, AnchorParam.Right);
  670.  
  671. r0.SetHeight(rowHeight);
  672. r0.AppendMaxRight(rcMargin, AnchorParam.Right);
  673.  
  674. var r1 = view.CreateSpace().LayoutRect;
  675. r1.SetTop(r0, AnchorParam.Top);
  676. r1.SetHeight(rowHeight);
  677. r1.SetLeft(r0, AnchorParam.Right);
  678. r1.AppendMaxRight(rcMargin, AnchorParam.Right);
  679.  
  680. r0.AppendMaxRight(c1_outer, ContourPosition.FirstInOutside);
  681. r0.AppendMaxRight(c2_outer, ContourPosition.FirstInOutside);
  682.  
  683. r1.AppendMaxRight(c1_outer, ContourPosition.NextOutOutside);
  684. r1.AppendMaxRight(c2_outer, ContourPosition.NextOutOutside);
  685.  
  686. surf.PerformLayout();
  687.  
  688. if (!paragraphStarted)
  689. {
  690. // It is important to have the ObjectRects property set
  691. // to a not null value (an empty list works well) and
  692. // the AllowOverhangingWords property set to true.
  693.  
  694. tl = g.CreateTextLayout();
  695. tl.ObjectRects = noRects;
  696. tl.TextAlignment = TextAlignment.Justified;
  697. tl.AllowOverhangingWords = true;
  698. tl.FirstLineIndent = 40f;
  699. tl.JustifiedTextExtension = 0.1f;
  700.  
  701. tl.Append(Common.Util.LoremIpsum(1), tf);
  702.  
  703. tl.MaxWidth = r0.Width;
  704. tl.MaxHeight = r0.Height;
  705. ((Visual)r0.Tag).Tag = tl;
  706.  
  707. if (!tl.PerformLayout())
  708. {
  709. paragraphStarted = true;
  710. }
  711. }
  712. else
  713. {
  714. tso.RestMaxWidth = r0.Width;
  715. tso.RestMaxHeight = r0.Height;
  716. var res = tl.Split(tso, out TextLayout rest);
  717. if (res != SplitResult.CannotSplit)
  718. {
  719. tl = rest;
  720. ((Visual)r0.Tag).Tag = rest;
  721. if (tl.PerformLayout())
  722. {
  723. paragraphStarted = false;
  724. }
  725. }
  726. }
  727.  
  728. if (paragraphStarted && r1.Width > 0f)
  729. rcPrevLeft = r1;
  730. else
  731. {
  732. ((Space)r1.Tag).Detach();
  733. var spacing = paragraphStarted ? lineSpacing : paragraphSpacing;
  734. if (rcMargin.P2Y - r0.P2Y < spacing + rowHeight)
  735. {
  736. break;
  737. }
  738. rcPrevLeft = null;
  739. rcPrevTop = r0;
  740. }
  741. }
  742.  
  743. tl.Truncate(TrimmingGranularity.Word);
  744.  
  745. // The second View showing text in the ellipse.
  746. var view2 = surf.CreateView(pageSize.Width / 3, pageSize.Height / 2).Translate(520, 260).Rotate(15);
  747.  
  748. tf = new TextFormat(tf)
  749. {
  750. ForeColor = Color.Purple,
  751. FontSize = 14,
  752. };
  753. tl = g.CreateTextLayout();
  754. tl.ObjectRects = noRects;
  755. tl.TextAlignment = TextAlignment.Center;
  756. tl.AllowOverhangingWords = true;
  757.  
  758. tl.Append(Common.Util.LoremIpsum(1), tf);
  759.  
  760. rcPrevTop = null;
  761. paragraphStarted = false;
  762.  
  763. while (true)
  764. {
  765. var r0 = view2.CreateSpace().LayoutRect;
  766. if (rcPrevTop != null)
  767. r0.SetTop(rcPrevTop, AnchorParam.Bottom, 4);
  768. else
  769. r0.SetTop(null, AnchorParam.Top);
  770. r0.SetLeft(null, AnchorParam.Left);
  771.  
  772. r0.SetHeight(18);
  773. r0.AppendMaxRight(null, AnchorParam.Right);
  774.  
  775. var r1 = view2.CreateVisual(DrawTextFragment).LayoutRect;
  776. r1.SetTop(r0, AnchorParam.Top);
  777. r1.SetHeight(18);
  778. r1.SetLeft(r0, AnchorParam.Right);
  779. r1.AppendMaxRight(null, AnchorParam.Right);
  780.  
  781. r0.AppendMaxRight(c2_inner, ContourPosition.FirstInInside);
  782. r1.AppendMaxRight(c2_inner, ContourPosition.NextOutInside);
  783.  
  784. surf.PerformLayout();
  785. if (r1.Width == 0f)
  786. {
  787. ((Space)r1.Tag).Detach();
  788. if (paragraphStarted)
  789. {
  790. break;
  791. }
  792. }
  793. else if (!paragraphStarted)
  794. {
  795. tl.MaxWidth = r1.Width;
  796. tl.MaxHeight = r1.Height;
  797. ((Visual)r1.Tag).Tag = tl;
  798. if (tl.PerformLayout())
  799. {
  800. break;
  801. }
  802. paragraphStarted = true;
  803. }
  804. else
  805. {
  806. tso.RestMaxWidth = r1.Width;
  807. tso.RestMaxHeight = r1.Height;
  808. var res = tl.Split(tso, out TextLayout rest);
  809. if (res == SplitResult.FitAll)
  810. {
  811. ((Space)r1.Tag).Detach();
  812. break;
  813. }
  814. if (res == SplitResult.Split)
  815. {
  816. ((Visual)r1.Tag).Tag = rest;
  817. tl = rest;
  818. }
  819. }
  820. rcPrevTop = r0;
  821. }
  822.  
  823. tl.Truncate(TrimmingGranularity.Word);
  824.  
  825. surf.Render(g);
  826. }
  827.  
  828. //
  829. // Common utility classes and methods.
  830. //
  831.  
  832. class FigureCaption
  833. {
  834. public FigureCaption(int number, string description, string code = null)
  835. {
  836. Number = number;
  837. Description = description;
  838. Code = code;
  839. }
  840. public int Number { get; }
  841. public string Description { get; }
  842. public string Code { get; }
  843. }
  844.  
  845. static void DrawTextFragment(GcGraphics g, Visual v)
  846. {
  847. if (v.Tag is TextLayout tl)
  848. {
  849. g.DrawTextLayout(tl, new PointF(0, 0));
  850. }
  851. }
  852.  
  853. static void CreateFigure1(Surface surf, out Contour c_outer)
  854. {
  855. // A View for the yellow polygon.
  856. var view = surf.CreateView(0, 0).Translate(120, -40).Rotate(40);
  857. var lv = view.LayoutView;
  858.  
  859. var c = lv.CreateContour();
  860.  
  861. var v = view.CreateVisual(c, true, (g, v) =>
  862. {
  863. g.FillPolygon(v.Points, Color.LemonChiffon);
  864. g.DrawPolygon(v.Points, Color.Green, 3);
  865. });
  866. var rect = v.LayoutRect;
  867. rect.AnchorTopLeft(null, 100, 150, 170, 70);
  868.  
  869. c.AddPoints(new AnchorPoint[]
  870. {
  871. rect.CreatePoint(0, 0, -20, -20),
  872. rect.CreatePoint(1, 0, 20, -20),
  873. rect.CreatePoint(1, 0, 20, -120),
  874. rect.CreatePoint(1, 0, 120, -120),
  875. rect.CreatePoint(1, 1, 120, 20),
  876. rect.CreatePoint(0, 1, -20, 20)
  877. });
  878.  
  879. surf.PerformLayout();
  880.  
  881. var points = c.MapToView(lv);
  882.  
  883. // To make the outer offset from the Contour we convert
  884. // the Contour to a GraphicsPath, then apply the Widen
  885. // method with a thick pen. The resulting figure is
  886. // used for creating the outer Contour.
  887. var gp = new GraphicsPath(new FreeFormPolygon(points));
  888. var gp2 = gp.Widen(new GCDRAW.Pen(Color.White, 7 * 2));
  889.  
  890. var fig_outer = gp2.Figures[0];
  891.  
  892. fig_outer.Flatten();
  893. var outer_points = fig_outer.TransformedPoints;
  894.  
  895. c_outer = lv.CreateContour();
  896. for (int i = 0; i < outer_points.Length; i++)
  897. {
  898. var p = outer_points[i];
  899. c_outer.AddPoint(lv.CreatePoint(0f, 0f, p.X, p.Y));
  900. }
  901. }
  902.  
  903. static void CreateFigure2(Surface surf, out Contour c_outer, out Contour c_inner)
  904. {
  905. // A View for the rotated ellipse.
  906. var view = surf.CreateView(360, 150).Translate(450, 530).Rotate(-40);
  907. var lv = view.LayoutView;
  908.  
  909. var c = lv.CreateContour();
  910.  
  911. view.CreateVisual(c, false, (g, v) =>
  912. {
  913. g.DrawPolygon(v.Points, Color.DeepPink, 3);
  914. });
  915.  
  916. // To make the inner and the outer offsets from the ellipse
  917. // we convert the elliptic figure to an array of points which
  918. // is used later for creating a GraphicsPath. Then, we call
  919. // the GraphicsPath.Widen method with a thick pen.
  920. // The resulting outer and inner figures can be converted
  921. // into new contours for later use in constraints.
  922. IFigure ef = new EllipticFigure(lv.AsRectF());
  923. ef.Flatten();
  924. var points = ef.TransformedPoints;
  925. int count = points.Length;
  926. var list = new List<AnchorPoint>(count);
  927. for (int i = 0; i < count; i++)
  928. {
  929. var p = points[i];
  930. list.Add(lv.CreatePoint(0, 0, p.X, p.Y));
  931. }
  932. c.AddPoints(list);
  933.  
  934. var gp = new GraphicsPath(ef);
  935. var gp2 = gp.Widen(new GCDRAW.Pen(Color.White, 7 * 2));
  936.  
  937. var fig_outer = gp2.Figures[0];
  938. var fig_inner = gp2.Figures[1];
  939.  
  940. fig_outer.Flatten();
  941. var outer_points = fig_outer.TransformedPoints;
  942.  
  943. c_outer = lv.CreateContour();
  944. for (int i = 0; i < outer_points.Length; i++)
  945. {
  946. var p = outer_points[i];
  947. c_outer.AddPoint(lv.CreatePoint(0f, 0f, p.X, p.Y));
  948. }
  949.  
  950. fig_inner.Flatten();
  951. var inner_points = fig_inner.TransformedPoints;
  952.  
  953. c_inner = lv.CreateContour();
  954. for (int i = 0; i < inner_points.Length; i++)
  955. {
  956. var p = inner_points[i];
  957. c_inner.AddPoint(lv.CreatePoint(0f, 0f, p.X, p.Y));
  958. }
  959. }
  960.  
  961. static readonly TextFormat FormatBox = new TextFormat()
  962. {
  963. Font = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "segoeui.ttf")),
  964. FontSize = 14,
  965. FontSizeInGraphicUnits = true,
  966. ForeColor = BoxColor
  967. };
  968.  
  969. static readonly TextFormat FormatDesc = new TextFormat(FormatBox)
  970. {
  971. FontSize = 12,
  972. ForeColor = DescColor
  973. };
  974.  
  975. static readonly TextFormat FormatCaption = new TextFormat(FormatDesc)
  976. {
  977. FontBold = true
  978. };
  979.  
  980. static readonly TextFormat FormatCode = new TextFormat(FormatDesc)
  981. {
  982. Font = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "cour.ttf")),
  983. ForeColor = CodeColor
  984. };
  985.  
  986. static void DrawView(GcGraphics g, Visual v)
  987. {
  988. var rect = v.AsRectF();
  989. g.FillRectangle(rect, Color.FromArgb(31, 82, 100));
  990. g.DrawRectangle(rect, new GCDRAW.Pen(Color.FromArgb(200, 200, 200), 1)
  991. {
  992. DashPattern = new float[] { 7, 3 }
  993. });
  994. if (v.Tag is FigureCaption fc)
  995. {
  996. var tl = g.CreateTextLayout();
  997. tl.Append($"Figure {fc.Number}. ", FormatCaption);
  998. tl.AppendLine(fc.Description, FormatDesc);
  999. if (fc.Code != null)
  1000. {
  1001. tl.Append(fc.Code, FormatCode);
  1002. }
  1003. g.DrawTextLayout(tl, new PointF(0, v.Height + 5));
  1004. }
  1005. }
  1006.  
  1007. static void DrawVertGuideline(GcGraphics g, Visual v)
  1008. {
  1009. g.DrawLine(new PointF(0, 0), new PointF(0, v.Height), new GCDRAW.Pen(BoxColor, 1)
  1010. {
  1011. DashPattern = new float[] { 1, 2 }
  1012. });
  1013. if (v.Tag is string s)
  1014. {
  1015. var tl = g.CreateTextLayout();
  1016. tl.Append(s, FormatDesc);
  1017. tl.PerformLayout();
  1018. var rect = tl.ContentRectangle;
  1019. rect.X = -rect.Width * 0.5f;
  1020. rect.Y = 10;
  1021. rect.Inflate(3, 1);
  1022. g.FillRoundRect(rect, 3, RectColor);
  1023. g.DrawTextLayout(tl, new PointF(rect.X + 3, rect.Y + 1));
  1024. }
  1025. }
  1026.  
  1027. static void DrawRect(GcGraphics g, Visual v)
  1028. {
  1029. var rect = v.AsRectF();
  1030. g.FillRectangle(rect, RectColor);
  1031. g.DrawRectangle(rect, new GCDRAW.Pen(BoxColor, 1));
  1032. if (v.Tag is string s)
  1033. {
  1034. var tl = g.CreateTextLayout();
  1035. tl.MaxWidth = v.Width;
  1036. tl.MaxHeight = v.Height;
  1037. tl.TextAlignment = TextAlignment.Center;
  1038. tl.ParagraphAlignment = ParagraphAlignment.Center;
  1039. tl.Append(s, FormatBox);
  1040. g.DrawTextLayout(tl, new PointF(0, 0));
  1041. }
  1042. }
  1043.  
  1044. static void DrawLineWithLeftArrow(GcGraphics g, Visual v)
  1045. {
  1046. var y = v.Height * 0.5f;
  1047. g.DrawLine(new PointF(5, y), new PointF(v.Width, y), new GCDRAW.Pen(BoxColor, 0.7f));
  1048. DrawLeftArrow(g, 0, y);
  1049. }
  1050.  
  1051. static void DrawLineWithRightArrow(GcGraphics g, Visual v)
  1052. {
  1053. var y = v.Height * 0.5f;
  1054. g.DrawLine(new PointF(0, y), new PointF(v.Width - 5, y), new GCDRAW.Pen(BoxColor, 0.7f));
  1055. DrawRightArrow(g, v.Width, y);
  1056. }
  1057.  
  1058. static void DrawLeftRightLines(GcGraphics g, Visual v)
  1059. {
  1060. var y = v.Height * 0.33f;
  1061. g.DrawLine(new PointF(5, y), new PointF(v.Width, y), new GCDRAW.Pen(BoxColor, 0.7f));
  1062. DrawLeftArrow(g, 0, y);
  1063. y = v.Height * 0.66f;
  1064. g.DrawLine(new PointF(0, y), new PointF(v.Width - 5, y), new GCDRAW.Pen(BoxColor, 0.7f));
  1065. DrawRightArrow(g, v.Width, y);
  1066. }
  1067.  
  1068. static void DrawVertLineWithLeftArrow(GcGraphics g, Visual v)
  1069. {
  1070. var x = v.Width * 0.5f;
  1071. g.DrawLines(new PointF[]
  1072. {
  1073. new PointF(5, 0),
  1074. new PointF(x, 0),
  1075. new PointF(x, v.Height),
  1076. new PointF(v.Width, v.Height)
  1077. }, new GCDRAW.Pen(BoxColor, 0.7f));
  1078. DrawLeftArrow(g, 0, 0);
  1079. }
  1080.  
  1081. static void DrawLineWithUpArrow(GcGraphics g, Visual v)
  1082. {
  1083. var x = v.Width * 0.5f;
  1084. g.DrawLine(new PointF(x, 5), new PointF(x, v.Height), new GCDRAW.Pen(BoxColor, 0.7f));
  1085. DrawUpArrow(g, x, 0);
  1086. }
  1087.  
  1088. static void DrawLeftArrow(GcGraphics g, float x, float y)
  1089. {
  1090. var pts = new PointF[]
  1091. {
  1092. new PointF(x, y),
  1093. new PointF(x + 8, y - 2.5f),
  1094. new PointF(x + 8, y + 2.5f),
  1095. };
  1096. g.FillPolygon(pts, BoxColor);
  1097. }
  1098.  
  1099. static void DrawRightArrow(GcGraphics g, float x, float y)
  1100. {
  1101. var pts = new PointF[]
  1102. {
  1103. new PointF(x, y),
  1104. new PointF(x - 8, y + 2.5f),
  1105. new PointF(x - 8, y - 2.5f),
  1106. };
  1107. g.FillPolygon(pts, BoxColor);
  1108. }
  1109.  
  1110. static void DrawUpArrow(GcGraphics g, float x, float y)
  1111. {
  1112. var pts = new PointF[]
  1113. {
  1114. new PointF(x, y),
  1115. new PointF(x + 2.5f, y + 8),
  1116. new PointF(x - 2.5f, y + 8),
  1117. };
  1118. g.FillPolygon(pts, BoxColor);
  1119. }
  1120. }
  1121. }
  1122.