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