PageRenderTime 62ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/src/Core/PdnGraphicsPath.cs

https://bitbucket.org/tuldok89/openpdn
C# | 1206 lines | 962 code | 198 blank | 46 comment | 80 complexity | b88b712abdd2593ec254a42522a761cf MD5 | raw file
  1. /////////////////////////////////////////////////////////////////////////////////
  2. // Paint.NET //
  3. // Copyright (C) dotPDN LLC, Rick Brewster, Tom Jackson, and contributors. //
  4. // Portions Copyright (C) Microsoft Corporation. All Rights Reserved. //
  5. // See src/Resources/Files/License.txt for full licensing and attribution //
  6. // details. //
  7. // . //
  8. /////////////////////////////////////////////////////////////////////////////////
  9. using PaintDotNet.Base;
  10. using PaintDotNet.SystemLayer;
  11. using System;
  12. using System.Collections.Generic;
  13. using System.ComponentModel;
  14. using System.Drawing;
  15. using System.Drawing.Drawing2D;
  16. using System.Runtime.Serialization;
  17. namespace PaintDotNet
  18. {
  19. [Serializable]
  20. public sealed class PdnGraphicsPath
  21. : MarshalByRefObject,
  22. ICloneable,
  23. IDisposable,
  24. ISerializable
  25. {
  26. private GraphicsPath _gdiPath;
  27. private bool _tooComplex;
  28. internal PdnRegion RegionCache;
  29. public static implicit operator GraphicsPath(PdnGraphicsPath convert)
  30. {
  31. return convert._gdiPath;
  32. }
  33. internal PdnRegion GetRegionCache()
  34. {
  35. return RegionCache ?? (RegionCache = new PdnRegion(_gdiPath));
  36. }
  37. /*
  38. private GraphicsPath GdiPath
  39. {
  40. get
  41. {
  42. return _gdiPath;
  43. }
  44. }
  45. */ //SUSPECTED UNUSED PROPERTY
  46. private void Changed()
  47. {
  48. if (RegionCache == null) return;
  49. lock (RegionCache.SyncRoot)
  50. {
  51. RegionCache.Dispose();
  52. RegionCache = null;
  53. }
  54. }
  55. public PdnGraphicsPath()
  56. {
  57. Changed();
  58. _gdiPath = new GraphicsPath();
  59. }
  60. public PdnGraphicsPath(GraphicsPath wrapMe)
  61. {
  62. Changed();
  63. _gdiPath = wrapMe;
  64. }
  65. public PdnGraphicsPath(FillMode fillMode)
  66. {
  67. Changed();
  68. _gdiPath = new GraphicsPath(fillMode);
  69. }
  70. public PdnGraphicsPath(Point[] pts, byte[] types)
  71. {
  72. Changed();
  73. _gdiPath = new GraphicsPath(pts, types);
  74. }
  75. public PdnGraphicsPath(PointF[] pts, byte[] types)
  76. {
  77. Changed();
  78. _gdiPath = new GraphicsPath(pts, types);
  79. }
  80. public PdnGraphicsPath(Point[] pts, byte[] types, FillMode fillMode)
  81. {
  82. Changed();
  83. _gdiPath = new GraphicsPath(pts, types, fillMode);
  84. }
  85. public PdnGraphicsPath(PointF[] pts, byte[] types, FillMode fillMode)
  86. {
  87. Changed();
  88. _gdiPath = new GraphicsPath(pts, types, fillMode);
  89. }
  90. public PdnGraphicsPath(SerializationInfo info, StreamingContext context)
  91. {
  92. int ptCount = info.GetInt32("ptCount");
  93. PointF[] pts;
  94. byte[] types;
  95. if (ptCount == 0)
  96. {
  97. pts = new PointF[0];
  98. types = new byte[0];
  99. }
  100. else
  101. {
  102. pts = (PointF[])info.GetValue("pts", typeof(PointF[]));
  103. types = (byte[])info.GetValue("types", typeof(byte[]));
  104. }
  105. var fillMode = (FillMode)info.GetValue("fillMode", typeof(FillMode));
  106. Changed();
  107. _gdiPath = ptCount == 0 ? new GraphicsPath() : new GraphicsPath(pts, types, fillMode);
  108. _tooComplex = false;
  109. RegionCache = null;
  110. }
  111. public void GetObjectData(SerializationInfo info, StreamingContext context)
  112. {
  113. lock (this) // avoid race condition with Dispose()
  114. {
  115. info.AddValue("ptCount", _gdiPath.PointCount);
  116. if (_gdiPath.PointCount > 0)
  117. {
  118. info.AddValue("pts", _gdiPath.PathPoints);
  119. info.AddValue("types", _gdiPath.PathTypes);
  120. }
  121. info.AddValue("fillMode", _gdiPath.FillMode);
  122. }
  123. }
  124. public static PdnGraphicsPath FromRegion(PdnRegion region)
  125. {
  126. Rectangle[] scans = region.GetRegionScansReadOnlyInt();
  127. if (scans.Length == 1)
  128. {
  129. var path = new PdnGraphicsPath();
  130. path.AddRectangle(scans[0]);
  131. path.CloseFigure();
  132. return path;
  133. }
  134. else
  135. {
  136. Rectangle bounds = region.GetBoundsInt();
  137. var stencil = new BitVector2D(bounds.Width, bounds.Height);
  138. for (int i = 0; i < scans.Length; ++i)
  139. {
  140. Rectangle rect = scans[i];
  141. rect.X -= bounds.X;
  142. rect.Y -= bounds.Y;
  143. stencil.SetUnchecked(rect, true);
  144. }
  145. PdnGraphicsPath path = PathFromStencil(stencil, new Rectangle(0, 0, stencil.Width, stencil.Height));
  146. using (var matrix = new Matrix())
  147. {
  148. matrix.Reset();
  149. matrix.Translate(bounds.X, bounds.Y);
  150. path.Transform(matrix);
  151. }
  152. return path;
  153. }
  154. }
  155. public static PdnGraphicsPath FromRegions(PdnRegion lhs, CombineMode combineMode, PdnRegion rhs)
  156. {
  157. Rectangle lhsBounds = lhs.GetBoundsInt();
  158. Rectangle rhsBounds = rhs.GetBoundsInt();
  159. int left = Math.Min(lhsBounds.Left, rhsBounds.Left);
  160. int top = Math.Min(lhsBounds.Top, rhsBounds.Top);
  161. int right = Math.Max(lhsBounds.Right, rhsBounds.Right);
  162. int bottom = Math.Max(lhsBounds.Bottom, rhsBounds.Bottom);
  163. Rectangle bounds = Rectangle.FromLTRB(left, top, right, bottom);
  164. var stencil = new BitVector2D(bounds.Width, bounds.Height);
  165. Rectangle[] lhsScans = lhs.GetRegionScansReadOnlyInt();
  166. Rectangle[] rhsScans = rhs.GetRegionScansReadOnlyInt();
  167. switch (combineMode)
  168. {
  169. case CombineMode.Complement:
  170. case CombineMode.Intersect:
  171. case CombineMode.Replace:
  172. throw new ArgumentException("combineMode can't be Complement, Intersect, or Replace");
  173. default:
  174. break;
  175. }
  176. for (int i = 0; i < lhsScans.Length; ++i)
  177. {
  178. Rectangle rect = lhsScans[i];
  179. rect.X -= bounds.X;
  180. rect.Y -= bounds.Y;
  181. stencil.SetUnchecked(rect, true);
  182. }
  183. for (int i = 0; i < rhsScans.Length; ++i)
  184. {
  185. Rectangle rect = rhsScans[i];
  186. rect.X -= bounds.X;
  187. rect.Y -= bounds.Y;
  188. switch (combineMode)
  189. {
  190. case CombineMode.Xor:
  191. stencil.InvertUnchecked(rect);
  192. break;
  193. case CombineMode.Union:
  194. stencil.SetUnchecked(rect, true);
  195. break;
  196. case CombineMode.Exclude:
  197. stencil.SetUnchecked(rect, false);
  198. break;
  199. }
  200. }
  201. PdnGraphicsPath path = PathFromStencil(stencil, new Rectangle(0, 0, stencil.Width, stencil.Height));
  202. using (var matrix = new Matrix())
  203. {
  204. matrix.Reset();
  205. matrix.Translate(bounds.X, bounds.Y);
  206. path.Transform(matrix);
  207. }
  208. return path;
  209. }
  210. public static Point[][] PolygonSetFromStencil(IBitVector2D stencil, Rectangle bounds, int translateX, int translateY)
  211. {
  212. var polygons = new List<Point[]>();
  213. if (!stencil.IsEmpty)
  214. {
  215. Point start = bounds.Location;
  216. var pts = new List<Point>();
  217. int count = 0;
  218. // find all islands
  219. while (true)
  220. {
  221. bool startFound = false;
  222. while (true)
  223. {
  224. if (stencil[start])
  225. {
  226. startFound = true;
  227. break;
  228. }
  229. ++start.X;
  230. if (start.X < bounds.Right) continue;
  231. ++start.Y;
  232. start.X = bounds.Left;
  233. if (start.Y >= bounds.Bottom)
  234. {
  235. break;
  236. }
  237. }
  238. if (!startFound)
  239. {
  240. break;
  241. }
  242. pts.Clear();
  243. var last = new Point(start.X, start.Y + 1);
  244. var curr = new Point(start.X, start.Y);
  245. Point next = curr;
  246. Point left = Point.Empty;
  247. Point right = Point.Empty;
  248. // trace island outline
  249. while (true)
  250. {
  251. left.X = ((curr.X - last.X) + (curr.Y - last.Y) + 2) / 2 + curr.X - 1;
  252. left.Y = ((curr.Y - last.Y) - (curr.X - last.X) + 2) / 2 + curr.Y - 1;
  253. right.X = ((curr.X - last.X) - (curr.Y - last.Y) + 2) / 2 + curr.X - 1;
  254. right.Y = ((curr.Y - last.Y) + (curr.X - last.X) + 2) / 2 + curr.Y - 1;
  255. if (bounds.Contains(left) && stencil[left])
  256. {
  257. // go left
  258. next.X += curr.Y - last.Y;
  259. next.Y -= curr.X - last.X;
  260. }
  261. else if (bounds.Contains(right) && stencil[right])
  262. {
  263. // go straight
  264. next.X += curr.X - last.X;
  265. next.Y += curr.Y - last.Y;
  266. }
  267. else
  268. {
  269. // turn right
  270. next.X -= curr.Y - last.Y;
  271. next.Y += curr.X - last.X;
  272. }
  273. if (Math.Sign(next.X - curr.X) != Math.Sign(curr.X - last.X) ||
  274. Math.Sign(next.Y - curr.Y) != Math.Sign(curr.Y - last.Y))
  275. {
  276. pts.Add(curr);
  277. ++count;
  278. }
  279. last = curr;
  280. curr = next;
  281. if (next.X == start.X && next.Y == start.Y)
  282. {
  283. break;
  284. }
  285. }
  286. Point[] points = pts.ToArray();
  287. Scanline[] scans = Utility.GetScans(points);
  288. foreach (Scanline scan in scans)
  289. {
  290. stencil.Invert(scan);
  291. }
  292. Utility.TranslatePointsInPlace(points, translateX, translateY);
  293. polygons.Add(points);
  294. }
  295. }
  296. Point[][] returnVal = polygons.ToArray();
  297. return returnVal;
  298. }
  299. /// <summary>
  300. /// Creates a graphics path from the given stencil buffer. It should be filled with 'true' values
  301. /// to indicate the areas that should be outlined.
  302. /// </summary>
  303. /// <param name="stencil">The stencil buffer to read from. NOTE: The contents of this will be destroyed when this method returns.</param>
  304. /// <param name="bounds">The bounding box within the stencil buffer to limit discovery to.</param>
  305. /// <returns>A PdnGraphicsPath with traces that outline the various areas from the given stencil buffer.</returns>
  306. public static PdnGraphicsPath PathFromStencil(IBitVector2D stencil, Rectangle bounds)
  307. {
  308. if (stencil.IsEmpty)
  309. {
  310. return new PdnGraphicsPath();
  311. }
  312. var ret = new PdnGraphicsPath();
  313. Point start = bounds.Location;
  314. var pts = new Vector<Point>();
  315. int count = 0;
  316. // find all islands
  317. while (true)
  318. {
  319. bool startFound = false;
  320. while (true)
  321. {
  322. if (stencil[start])
  323. {
  324. startFound = true;
  325. break;
  326. }
  327. ++start.X;
  328. if (start.X < bounds.Right) continue;
  329. ++start.Y;
  330. start.X = bounds.Left;
  331. if (start.Y >= bounds.Bottom)
  332. {
  333. break;
  334. }
  335. }
  336. if (!startFound)
  337. {
  338. break;
  339. }
  340. pts.Clear();
  341. var last = new Point(start.X, start.Y + 1);
  342. var curr = new Point(start.X, start.Y);
  343. Point next = curr;
  344. Point left = Point.Empty;
  345. Point right = Point.Empty;
  346. // trace island outline
  347. while (true)
  348. {
  349. left.X = ((curr.X - last.X) + (curr.Y - last.Y) + 2) / 2 + curr.X - 1;
  350. left.Y = ((curr.Y - last.Y) - (curr.X - last.X) + 2) / 2 + curr.Y - 1;
  351. right.X = ((curr.X - last.X) - (curr.Y - last.Y) + 2) / 2 + curr.X - 1;
  352. right.Y = ((curr.Y - last.Y) + (curr.X - last.X) + 2) / 2 + curr.Y - 1;
  353. if (bounds.Contains(left) && stencil[left])
  354. {
  355. // go left
  356. next.X += curr.Y - last.Y;
  357. next.Y -= curr.X - last.X;
  358. }
  359. else if (bounds.Contains(right) && stencil[right])
  360. {
  361. // go straight
  362. next.X += curr.X - last.X;
  363. next.Y += curr.Y - last.Y;
  364. }
  365. else
  366. {
  367. // turn right
  368. next.X -= curr.Y - last.Y;
  369. next.Y += curr.X - last.X;
  370. }
  371. if (Math.Sign(next.X - curr.X) != Math.Sign(curr.X - last.X) ||
  372. Math.Sign(next.Y - curr.Y) != Math.Sign(curr.Y - last.Y))
  373. {
  374. pts.Add(curr);
  375. ++count;
  376. }
  377. last = curr;
  378. curr = next;
  379. if (next.X == start.X && next.Y == start.Y)
  380. {
  381. break;
  382. }
  383. }
  384. Point[] points = pts.ToArray();
  385. Scanline[] scans = Utility.GetScans(points);
  386. foreach (Scanline scan in scans)
  387. {
  388. stencil.Invert(scan);
  389. }
  390. ret.AddLines(points);
  391. ret.CloseFigure();
  392. }
  393. return ret;
  394. }
  395. public static PdnGraphicsPath Combine(PdnGraphicsPath subjectPath, CombineMode combineMode, PdnGraphicsPath clipPath)
  396. {
  397. switch (combineMode)
  398. {
  399. case CombineMode.Complement:
  400. return Combine(clipPath, CombineMode.Exclude, subjectPath);
  401. case CombineMode.Replace:
  402. return clipPath.Clone();
  403. case CombineMode.Xor:
  404. case CombineMode.Intersect:
  405. case CombineMode.Union:
  406. case CombineMode.Exclude:
  407. if (subjectPath.IsEmpty && clipPath.IsEmpty)
  408. {
  409. return new PdnGraphicsPath(); // empty path
  410. }
  411. if (subjectPath.IsEmpty)
  412. {
  413. switch (combineMode)
  414. {
  415. case CombineMode.Xor:
  416. case CombineMode.Union:
  417. return clipPath.Clone();
  418. case CombineMode.Intersect:
  419. case CombineMode.Exclude:
  420. return new PdnGraphicsPath();
  421. default:
  422. throw new InvalidEnumArgumentException();
  423. }
  424. }
  425. if (clipPath.IsEmpty)
  426. {
  427. switch (combineMode)
  428. {
  429. case CombineMode.Exclude:
  430. case CombineMode.Xor:
  431. case CombineMode.Union:
  432. return subjectPath.Clone();
  433. case CombineMode.Intersect:
  434. return new PdnGraphicsPath();
  435. default:
  436. throw new InvalidEnumArgumentException();
  437. }
  438. }
  439. GraphicsPath resultPath = PdnGraphics.ClipPath(subjectPath, combineMode, clipPath);
  440. return new PdnGraphicsPath(resultPath);
  441. default:
  442. throw new InvalidEnumArgumentException();
  443. }
  444. }
  445. ~PdnGraphicsPath()
  446. {
  447. Changed();
  448. Dispose(false);
  449. }
  450. public void Dispose()
  451. {
  452. Dispose(true);
  453. GC.SuppressFinalize(this);
  454. }
  455. private void Dispose(bool disposing)
  456. {
  457. if (!disposing) return;
  458. lock (this) // avoid race condition with GetObjectData()
  459. {
  460. if (_gdiPath != null)
  461. {
  462. _gdiPath.Dispose();
  463. _gdiPath = null;
  464. }
  465. if (RegionCache == null) return;
  466. RegionCache.Dispose();
  467. RegionCache = null;
  468. }
  469. }
  470. public FillMode FillMode
  471. {
  472. get
  473. {
  474. return _gdiPath.FillMode;
  475. }
  476. set
  477. {
  478. Changed();
  479. _gdiPath.FillMode = value;
  480. }
  481. }
  482. public PathData PathData
  483. {
  484. get
  485. {
  486. return _gdiPath.PathData;
  487. }
  488. }
  489. public PointF[] PathPoints
  490. {
  491. get
  492. {
  493. return _gdiPath.PathPoints;
  494. }
  495. }
  496. public byte[] PathTypes
  497. {
  498. get
  499. {
  500. return _gdiPath.PathTypes;
  501. }
  502. }
  503. public int PointCount
  504. {
  505. get
  506. {
  507. return _gdiPath.PointCount;
  508. }
  509. }
  510. public void AddArc(Rectangle rect, float startAngle, float sweepAngle)
  511. {
  512. Changed();
  513. _gdiPath.AddArc(rect, startAngle, sweepAngle);
  514. }
  515. public void AddArc(RectangleF rectF, float startAngle, float sweepAngle)
  516. {
  517. Changed();
  518. _gdiPath.AddArc(rectF, startAngle, sweepAngle);
  519. }
  520. public void AddArc(int x, int y, int width, int height, float startAngle, float sweepAngle)
  521. {
  522. Changed();
  523. _gdiPath.AddArc(x, y, width, height, startAngle, sweepAngle);
  524. }
  525. public void AddArc(float x, float y, float width, float height, float startAngle, float sweepAngle)
  526. {
  527. Changed();
  528. _gdiPath.AddArc(x, y, width, height, startAngle, sweepAngle);
  529. }
  530. public void AddBezier(Point pt1, Point pt2, Point pt3, Point pt4)
  531. {
  532. Changed();
  533. _gdiPath.AddBezier(pt1, pt2, pt3, pt4);
  534. }
  535. public void AddBezier(PointF pt1, PointF pt2, PointF pt3, PointF pt4)
  536. {
  537. Changed();
  538. _gdiPath.AddBezier(pt1, pt2, pt3, pt4);
  539. }
  540. public void AddBezier(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4)
  541. {
  542. Changed();
  543. _gdiPath.AddBezier(x1, y1, x2, y2, x3, y3, x4, y4);
  544. }
  545. public void AddBezier(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4)
  546. {
  547. Changed();
  548. _gdiPath.AddBezier(x1, y1, x2, y2, x3, y3, x4, y4);
  549. }
  550. public void AddBeziers(Point[] points)
  551. {
  552. Changed();
  553. _gdiPath.AddBeziers(points);
  554. }
  555. public void AddBeziers(PointF[] points)
  556. {
  557. Changed();
  558. _gdiPath.AddBeziers(points);
  559. }
  560. public void AddClosedCurve(Point[] points)
  561. {
  562. Changed();
  563. _gdiPath.AddClosedCurve(points);
  564. }
  565. public void AddClosedCurve(PointF[] points)
  566. {
  567. Changed();
  568. _gdiPath.AddClosedCurve(points);
  569. }
  570. public void AddClosedCurve(Point[] points, float tension)
  571. {
  572. Changed();
  573. _gdiPath.AddClosedCurve(points, tension);
  574. }
  575. public void AddClosedCurve(PointF[] points, float tension)
  576. {
  577. Changed();
  578. _gdiPath.AddClosedCurve(points, tension);
  579. }
  580. public void AddCurve(Point[] points)
  581. {
  582. Changed();
  583. _gdiPath.AddCurve(points);
  584. }
  585. public void AddCurve(PointF[] points)
  586. {
  587. Changed();
  588. _gdiPath.AddCurve(points);
  589. }
  590. public void AddCurve(Point[] points, float tension)
  591. {
  592. Changed();
  593. _gdiPath.AddCurve(points, tension);
  594. }
  595. public void AddCurve(PointF[] points, float tension)
  596. {
  597. Changed();
  598. _gdiPath.AddCurve(points, tension);
  599. }
  600. public void AddCurve(Point[] points, int offset, int numberOfSegments, float tension)
  601. {
  602. Changed();
  603. _gdiPath.AddCurve(points, offset, numberOfSegments, tension);
  604. }
  605. public void AddCurve(PointF[] points, int offset, int numberOfSegments, float tension)
  606. {
  607. Changed();
  608. _gdiPath.AddCurve(points, offset, numberOfSegments, tension);
  609. }
  610. public void AddEllipse(Rectangle rect)
  611. {
  612. Changed();
  613. _gdiPath.AddEllipse(rect);
  614. }
  615. public void AddEllipse(RectangleF rectF)
  616. {
  617. Changed();
  618. _gdiPath.AddEllipse(rectF);
  619. }
  620. public void AddEllipse(int x, int y, int width, int height)
  621. {
  622. Changed();
  623. _gdiPath.AddEllipse(x, y, width, height);
  624. }
  625. public void AddEllipse(float x, float y, float width, float height)
  626. {
  627. Changed();
  628. _gdiPath.AddEllipse(x, y, width, height);
  629. }
  630. public void AddLine(Point pt1, Point pt2)
  631. {
  632. Changed();
  633. _gdiPath.AddLine(pt1, pt2);
  634. }
  635. public void AddLine(PointF pt1, PointF pt2)
  636. {
  637. Changed();
  638. _gdiPath.AddLine(pt1, pt2);
  639. }
  640. public void AddLine(int x1, int y1, int x2, int y2)
  641. {
  642. Changed();
  643. _gdiPath.AddLine(x1, y1, x2, y2);
  644. }
  645. public void AddLine(float x1, float y1, float x2, float y2)
  646. {
  647. Changed();
  648. _gdiPath.AddLine(x1, y1, x2, y2);
  649. }
  650. public void AddLines(Point[] points)
  651. {
  652. Changed();
  653. _gdiPath.AddLines(points);
  654. }
  655. public void AddLines(PointF[] points)
  656. {
  657. Changed();
  658. _gdiPath.AddLines(points);
  659. }
  660. public void AddPath(GraphicsPath addingPath, bool connect)
  661. {
  662. if (addingPath.PointCount == 0) return;
  663. Changed();
  664. _gdiPath.AddPath(addingPath, connect);
  665. }
  666. public void AddPie(Rectangle rect, float startAngle, float sweepAngle)
  667. {
  668. Changed();
  669. _gdiPath.AddPie(rect, startAngle, sweepAngle);
  670. }
  671. public void AddPie(int x, int y, int width, int height, float startAngle, float sweepAngle)
  672. {
  673. Changed();
  674. _gdiPath.AddPie(x, y, width, height, startAngle, sweepAngle);
  675. }
  676. public void AddPie(float x, float y, float width, float height, float startAngle, float sweepAngle)
  677. {
  678. Changed();
  679. _gdiPath.AddPie(x, y, width, height, startAngle, sweepAngle);
  680. }
  681. public void AddPolygon(Point[] points)
  682. {
  683. Changed();
  684. _gdiPath.AddPolygon(points);
  685. }
  686. public void AddPolygon(PointF[] points)
  687. {
  688. Changed();
  689. _gdiPath.AddPolygon(points);
  690. }
  691. public void AddPolygons(PointF[][] polygons)
  692. {
  693. foreach (PointF[] polygon in polygons)
  694. {
  695. AddPolygon(polygon);
  696. CloseFigure();
  697. }
  698. }
  699. public void AddPolygons(Point[][] polygons)
  700. {
  701. foreach (Point[] polygon in polygons)
  702. {
  703. AddPolygon(polygon);
  704. CloseFigure();
  705. }
  706. }
  707. public void AddRectangle(Rectangle rect)
  708. {
  709. Changed();
  710. _gdiPath.AddRectangle(rect);
  711. }
  712. public void AddRectangle(RectangleF rectF)
  713. {
  714. Changed();
  715. _gdiPath.AddRectangle(rectF);
  716. }
  717. public void AddRectangles(Rectangle[] rects)
  718. {
  719. Changed();
  720. _gdiPath.AddRectangles(rects);
  721. }
  722. public void AddRectangles(RectangleF[] rectsF)
  723. {
  724. Changed();
  725. _gdiPath.AddRectangles(rectsF);
  726. }
  727. public void AddString(string s, FontFamily family, int style, float emSize, Point origin, StringFormat format)
  728. {
  729. Changed();
  730. _gdiPath.AddString(s, family, style, emSize, origin, format);
  731. }
  732. public void AddString(string s, FontFamily family, int style, float emSize, PointF origin, StringFormat format)
  733. {
  734. Changed();
  735. _gdiPath.AddString(s, family, style, emSize, origin, format);
  736. }
  737. public void AddString(string s, FontFamily family, int style, float emSize, Rectangle layoutRect, StringFormat format)
  738. {
  739. Changed();
  740. _gdiPath.AddString(s, family, style, emSize, layoutRect, format);
  741. }
  742. public void AddString(string s, FontFamily family, int style, float emSize, RectangleF layoutRect, StringFormat format)
  743. {
  744. Changed();
  745. _gdiPath.AddString(s, family, style, emSize, layoutRect, format);
  746. }
  747. public void ClearMarkers()
  748. {
  749. Changed();
  750. _gdiPath.ClearMarkers();
  751. }
  752. object ICloneable.Clone()
  753. {
  754. return Clone();
  755. }
  756. public PdnGraphicsPath Clone()
  757. {
  758. var path = new PdnGraphicsPath((GraphicsPath)_gdiPath.Clone()) {_tooComplex = _tooComplex};
  759. return path;
  760. }
  761. public void CloseAllFigures()
  762. {
  763. Changed();
  764. _gdiPath.CloseAllFigures();
  765. }
  766. public void CloseFigure()
  767. {
  768. Changed();
  769. _gdiPath.CloseFigure();
  770. }
  771. public void Draw(Graphics g, Pen pen)
  772. {
  773. Draw(g, pen, false);
  774. }
  775. /// <summary>
  776. /// Draws the path to the given Graphics context using the given Pen.
  777. /// </summary>
  778. /// <param name="g">The Graphics context to draw to.</param>
  779. /// <param name="pen">The Pen to draw with.</param>
  780. /// <param name="presentationIntent">
  781. /// If true, gives a hint that the path is being drawn to be presented to the user.
  782. /// </param>
  783. /// <remarks>
  784. /// If the path is "too complex," and if presentationIntent is true, then the path will
  785. /// not be drawn. To force the path to be drawn, set presentationIntent to false.
  786. /// </remarks>
  787. public void Draw(Graphics g, Pen pen, bool presentationIntent)
  788. {
  789. try
  790. {
  791. if (!_tooComplex || !presentationIntent)
  792. {
  793. int start = Environment.TickCount;
  794. g.DrawPath(pen, _gdiPath);
  795. int end = Environment.TickCount;
  796. if ((end - start) > 1000)
  797. {
  798. _tooComplex = true;
  799. }
  800. }
  801. }
  802. catch (OutOfMemoryException ex)
  803. {
  804. _tooComplex = true;
  805. Tracing.Ping("DrawPath exception: " + ex);
  806. }
  807. }
  808. public void Flatten()
  809. {
  810. Changed();
  811. _gdiPath.Flatten();
  812. }
  813. public void Flatten(Matrix matrix)
  814. {
  815. Changed();
  816. _gdiPath.Flatten(matrix);
  817. }
  818. public void Flatten(Matrix matrix, float flatness)
  819. {
  820. Changed();
  821. _gdiPath.Flatten(matrix, flatness);
  822. }
  823. public RectangleF GetBounds2()
  824. {
  825. if (PointCount == 0)
  826. {
  827. return RectangleF.Empty;
  828. }
  829. PointF[] points = PathPoints;
  830. if (points.Length == 0)
  831. {
  832. return RectangleF.Empty;
  833. }
  834. float left = points[0].X;
  835. float right = points[0].X;
  836. float top = points[0].Y;
  837. float bottom = points[0].Y;
  838. for (int i = 1; i < points.Length; ++i)
  839. {
  840. if (points[i].X < left)
  841. {
  842. left = points[i].X;
  843. }
  844. if (points[i].Y < top)
  845. {
  846. top = points[i].Y;
  847. }
  848. if (points[i].X > right)
  849. {
  850. right = points[i].X;
  851. }
  852. if (points[i].Y > bottom)
  853. {
  854. bottom = points[i].Y;
  855. }
  856. }
  857. return RectangleF.FromLTRB(left, top, right, bottom);
  858. }
  859. public RectangleF GetBounds()
  860. {
  861. return _gdiPath.GetBounds();
  862. }
  863. public RectangleF GetBounds(Matrix matrix)
  864. {
  865. return _gdiPath.GetBounds(matrix);
  866. }
  867. public RectangleF GetBounds(Matrix matrix, Pen pen)
  868. {
  869. return _gdiPath.GetBounds(matrix, pen);
  870. }
  871. public PointF GetLastPoint()
  872. {
  873. return _gdiPath.GetLastPoint();
  874. }
  875. public bool IsEmpty
  876. {
  877. get
  878. {
  879. return PointCount == 0;
  880. }
  881. }
  882. public bool IsOutlineVisible(Point point, Pen pen)
  883. {
  884. return _gdiPath.IsOutlineVisible(point, pen);
  885. }
  886. public bool IsOutlineVisible(PointF point, Pen pen)
  887. {
  888. return _gdiPath.IsOutlineVisible(point, pen);
  889. }
  890. public bool IsOutlineVisible(int x, int y, Pen pen)
  891. {
  892. return _gdiPath.IsOutlineVisible(x, y, pen);
  893. }
  894. public bool IsOutlineVisible(Point point, Pen pen, Graphics g)
  895. {
  896. return _gdiPath.IsOutlineVisible(point, pen, g);
  897. }
  898. public bool IsOutlineVisible(PointF point, Pen pen, Graphics g)
  899. {
  900. return _gdiPath.IsOutlineVisible(point, pen, g);
  901. }
  902. public bool IsOutlineVisible(float x, float y, Pen pen)
  903. {
  904. return _gdiPath.IsOutlineVisible(x, y, pen);
  905. }
  906. public bool IsOutlineVisible(int x, int y, Pen pen, Graphics g)
  907. {
  908. return _gdiPath.IsOutlineVisible(x, y, pen, g);
  909. }
  910. public bool IsOutlineVisible(float x, float y, Pen pen, Graphics g)
  911. {
  912. return _gdiPath.IsOutlineVisible(x, y, pen, g);
  913. }
  914. public bool IsVisible(Point point)
  915. {
  916. return _gdiPath.IsVisible(point);
  917. }
  918. public bool IsVisible(PointF point)
  919. {
  920. return _gdiPath.IsVisible(point);
  921. }
  922. public bool IsVisible(int x, int y)
  923. {
  924. return _gdiPath.IsVisible(x, y);
  925. }
  926. public bool IsVisible(Point point, Graphics g)
  927. {
  928. return _gdiPath.IsVisible(point, g);
  929. }
  930. public bool IsVisible(PointF point, Graphics g)
  931. {
  932. return _gdiPath.IsVisible(point, g);
  933. }
  934. public bool IsVisible(float x, float y)
  935. {
  936. return _gdiPath.IsVisible(x, y);
  937. }
  938. public bool IsVisible(int x, int y, Graphics g)
  939. {
  940. return _gdiPath.IsVisible(x, y, g);
  941. }
  942. public bool IsVisible(float x, float y, Graphics g)
  943. {
  944. return _gdiPath.IsVisible(x, y, g);
  945. }
  946. public void Reset()
  947. {
  948. Changed();
  949. _tooComplex = false;
  950. _gdiPath.Reset();
  951. }
  952. public void Reverse()
  953. {
  954. Changed();
  955. _gdiPath.Reverse();
  956. }
  957. public void SetMarkers()
  958. {
  959. Changed();
  960. _gdiPath.SetMarkers();
  961. }
  962. public void StartFigure()
  963. {
  964. Changed();
  965. _gdiPath.StartFigure();
  966. }
  967. public void Transform(Matrix matrix)
  968. {
  969. Changed();
  970. _gdiPath.Transform(matrix);
  971. }
  972. public void Warp(PointF[] destPoints, RectangleF srcRect)
  973. {
  974. Changed();
  975. _gdiPath.Warp(destPoints, srcRect);
  976. }
  977. public void Warp(PointF[] destPoints, RectangleF srcRect, Matrix matrix)
  978. {
  979. Changed();
  980. _gdiPath.Warp(destPoints, srcRect, matrix);
  981. }
  982. public void Warp(PointF[] destPoints, RectangleF srcRect, Matrix matrix, WarpMode warpMode)
  983. {
  984. Changed();
  985. _gdiPath.Warp(destPoints, srcRect, matrix, warpMode);
  986. }
  987. public void Warp(PointF[] destPoints, RectangleF srcRect, Matrix matrix, WarpMode warpMode, float flatness)
  988. {
  989. Changed();
  990. _gdiPath.Warp(destPoints, srcRect, matrix, warpMode, flatness);
  991. }
  992. public void Widen(Pen pen)
  993. {
  994. Changed();
  995. _gdiPath.Widen(pen);
  996. }
  997. public void Widen(Pen pen, Matrix matrix)
  998. {
  999. Changed();
  1000. _gdiPath.Widen(pen, matrix);
  1001. }
  1002. public void Widen(Pen pen, Matrix matrix, float flatness)
  1003. {
  1004. Changed();
  1005. _gdiPath.Widen(pen, matrix, flatness);
  1006. }
  1007. }
  1008. }