|
1 | 1 | // Copyright (c) Six Labors. |
2 | 2 | // Licensed under the Six Labors Split License. |
3 | 3 |
|
| 4 | +using SixLabors.PolygonClipper; |
| 5 | + |
4 | 6 | namespace SixLabors.ImageSharp.Drawing.Shapes.PolygonClipper; |
5 | 7 |
|
6 | 8 | /// <summary> |
7 | 9 | /// Library to clip polygons. |
8 | 10 | /// </summary> |
9 | 11 | internal class Clipper |
10 | 12 | { |
11 | | - private readonly PolygonClipper polygonClipper; |
12 | | - |
13 | | - /// <summary> |
14 | | - /// Initializes a new instance of the <see cref="Clipper"/> class. |
15 | | - /// </summary> |
16 | | - public Clipper() |
17 | | - => this.polygonClipper = new PolygonClipper(); |
| 13 | + private SixLabors.PolygonClipper.Polygon? subject; |
| 14 | + private SixLabors.PolygonClipper.Polygon? clip; |
18 | 15 |
|
19 | 16 | /// <summary> |
20 | 17 | /// Generates the clipped shapes from the previously provided paths. |
21 | 18 | /// </summary> |
22 | 19 | /// <param name="operation">The clipping operation.</param> |
23 | 20 | /// <param name="rule">The intersection rule.</param> |
24 | 21 | /// <returns>The <see cref="T:IPath[]"/>.</returns> |
25 | | - public IPath[] GenerateClippedShapes(ClippingOperation operation, IntersectionRule rule) |
| 22 | + public IPath[] GenerateClippedShapes(BooleanOperation operation) |
26 | 23 | { |
27 | | - PathsF closedPaths = []; |
28 | | - PathsF openPaths = []; |
| 24 | + ArgumentNullException.ThrowIfNull(this.subject); |
| 25 | + ArgumentNullException.ThrowIfNull(this.clip); |
29 | 26 |
|
30 | | - FillRule fillRule = rule == IntersectionRule.EvenOdd ? FillRule.EvenOdd : FillRule.NonZero; |
31 | | - this.polygonClipper.Execute(operation, fillRule, closedPaths, openPaths); |
| 27 | + SixLabors.PolygonClipper.PolygonClipper polygonClipper = new(this.subject, this.clip, operation); |
32 | 28 |
|
33 | | - IPath[] shapes = new IPath[closedPaths.Count + openPaths.Count]; |
| 29 | + SixLabors.PolygonClipper.Polygon result = polygonClipper.Run(); |
34 | 30 |
|
35 | | - int index = 0; |
36 | | - for (int i = 0; i < closedPaths.Count; i++) |
37 | | - { |
38 | | - PathF path = closedPaths[i]; |
39 | | - PointF[] points = new PointF[path.Count]; |
40 | 31 |
|
41 | | - for (int j = 0; j < path.Count; j++) |
42 | | - { |
43 | | - points[j] = path[j]; |
44 | | - } |
| 32 | + IPath[] shapes = new IPath[result.Count]; |
45 | 33 |
|
46 | | - shapes[index++] = new Polygon(points); |
47 | | - } |
48 | | - |
49 | | - for (int i = 0; i < openPaths.Count; i++) |
| 34 | + int index = 0; |
| 35 | + for (int i = 0; i < result.Count; i++) |
50 | 36 | { |
51 | | - PathF path = openPaths[i]; |
52 | | - PointF[] points = new PointF[path.Count]; |
| 37 | + Contour contour = result[i]; |
| 38 | + PointF[] points = new PointF[contour.Count]; |
53 | 39 |
|
54 | | - for (int j = 0; j < path.Count; j++) |
| 40 | + for (int j = 0; j < contour.Count; j++) |
55 | 41 | { |
56 | | - points[j] = path[j]; |
| 42 | + Vertex vertex = contour[j]; |
| 43 | + points[j] = new PointF((float)vertex.X, (float)vertex.Y); |
57 | 44 | } |
58 | 45 |
|
59 | 46 | shapes[index++] = new Polygon(points); |
@@ -100,12 +87,25 @@ public void AddPath(IPath path, ClippingType clippingType) |
100 | 87 | internal void AddPath(ISimplePath path, ClippingType clippingType) |
101 | 88 | { |
102 | 89 | ReadOnlySpan<PointF> vectors = path.Points.Span; |
103 | | - PathF points = new(vectors.Length); |
104 | | - for (int i = 0; i < vectors.Length; i++) |
| 90 | + SixLabors.PolygonClipper.Polygon polygon = []; |
| 91 | + Contour contour = new(); |
| 92 | + polygon.Add(contour); |
| 93 | + |
| 94 | + foreach (PointF point in vectors) |
105 | 95 | { |
106 | | - points.Add(vectors[i]); |
| 96 | + contour.AddVertex(new Vertex(point.X, point.Y)); |
107 | 97 | } |
108 | 98 |
|
109 | | - this.polygonClipper.AddPath(points, clippingType, !path.IsClosed); |
| 99 | + switch (clippingType) |
| 100 | + { |
| 101 | + case ClippingType.Clip: |
| 102 | + this.clip = polygon; |
| 103 | + break; |
| 104 | + case ClippingType.Subject: |
| 105 | + this.subject = polygon; |
| 106 | + break; |
| 107 | + default: |
| 108 | + throw new ArgumentOutOfRangeException(nameof(clippingType), clippingType, null); |
| 109 | + } |
110 | 110 | } |
111 | 111 | } |
0 commit comments