This repository was archived by the owner on May 1, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
/
Copy pathGeometryExtensions.cs
201 lines (173 loc) · 8.54 KB
/
GeometryExtensions.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
using System;
using System.Collections.Generic;
using CoreGraphics;
using Xamarin.Forms.Shapes;
#if __MOBILE__
namespace Xamarin.Forms.Platform.iOS
#else
namespace Xamarin.Forms.Platform.MacOS
#endif
{
public static class GeometryExtensions
{
public static PathData ToCGPath(this Geometry geometry, Transform renderTransform = null)
{
PathData pathData = new PathData
{
Data = new CGPath()
};
CGAffineTransform transform;
if (renderTransform == null)
transform = CGAffineTransform.MakeIdentity();
else
transform = renderTransform.ToCGAffineTransform();
if (geometry is LineGeometry)
{
LineGeometry lineGeometry = geometry as LineGeometry;
pathData.Data.MoveToPoint(transform, lineGeometry.StartPoint.ToPointF());
pathData.Data.AddLineToPoint(transform, lineGeometry.EndPoint.ToPointF());
}
else if (geometry is RectangleGeometry)
{
Rect rect = (geometry as RectangleGeometry).Rect;
pathData.Data.AddRect(transform, new CGRect(rect.X, rect.Y, rect.Width, rect.Height));
}
else if (geometry is EllipseGeometry)
{
EllipseGeometry ellipseGeometry = geometry as EllipseGeometry;
CGRect rect = new CGRect(
ellipseGeometry.Center.X - ellipseGeometry.RadiusX,
ellipseGeometry.Center.Y - ellipseGeometry.RadiusY,
ellipseGeometry.RadiusX * 2,
ellipseGeometry.RadiusY * 2);
pathData.Data.AddEllipseInRect(transform, rect);
}
else if (geometry is GeometryGroup)
{
GeometryGroup geometryGroup = geometry as GeometryGroup;
pathData.IsNonzeroFillRule = geometryGroup.FillRule == FillRule.Nonzero;
foreach (Geometry child in geometryGroup.Children)
{
PathData pathChild = child.ToCGPath(renderTransform);
pathData.Data.AddPath(pathChild.Data);
}
}
else if (geometry is PathGeometry)
{
PathGeometry pathGeometry = geometry as PathGeometry;
pathData.IsNonzeroFillRule = pathGeometry.FillRule == FillRule.Nonzero;
foreach (PathFigure pathFigure in pathGeometry.Figures)
{
pathData.Data.MoveToPoint(transform, pathFigure.StartPoint.ToPointF());
Point lastPoint = pathFigure.StartPoint;
foreach (PathSegment pathSegment in pathFigure.Segments)
{
// LineSegment
if (pathSegment is LineSegment)
{
LineSegment lineSegment = pathSegment as LineSegment;
pathData.Data.AddLineToPoint(transform, lineSegment.Point.ToPointF());
lastPoint = lineSegment.Point;
}
// PolyLineSegment
else if (pathSegment is PolyLineSegment)
{
PolyLineSegment polylineSegment = pathSegment as PolyLineSegment;
PointCollection points = polylineSegment.Points;
for (int i = 0; i < points.Count; i++)
pathData.Data.AddLineToPoint(transform, points[i].ToPointF());
lastPoint = points.Count > 0 ? points[points.Count - 1] : Point.Zero;
}
// BezierSegment
else if (pathSegment is BezierSegment)
{
BezierSegment bezierSegment = pathSegment as BezierSegment;
pathData.Data.AddCurveToPoint(
transform,
bezierSegment.Point1.ToPointF(),
bezierSegment.Point2.ToPointF(),
bezierSegment.Point3.ToPointF());
lastPoint = bezierSegment.Point3;
}
// PolyBezierSegment
else if (pathSegment is PolyBezierSegment)
{
PolyBezierSegment polyBezierSegment = pathSegment as PolyBezierSegment;
PointCollection points = polyBezierSegment.Points;
if (points.Count >= 3)
{
for (int i = 0; i < points.Count; i += 3)
{
pathData.Data.AddCurveToPoint(
transform,
points[i].ToPointF(),
points[i + 1].ToPointF(),
points[i + 2].ToPointF());
}
}
lastPoint = points.Count > 0 ? points[points.Count - 1] : Point.Zero;
}
// QuadraticBezierSegment
else if (pathSegment is QuadraticBezierSegment)
{
QuadraticBezierSegment bezierSegment = pathSegment as QuadraticBezierSegment;
pathData.Data.AddQuadCurveToPoint(
transform,
new nfloat(bezierSegment.Point1.X),
new nfloat(bezierSegment.Point1.Y),
new nfloat(bezierSegment.Point2.X),
new nfloat(bezierSegment.Point2.Y));
lastPoint = bezierSegment.Point2;
}
// PolyQuadraticBezierSegment
else if (pathSegment is PolyQuadraticBezierSegment)
{
PolyQuadraticBezierSegment polyBezierSegment = pathSegment as PolyQuadraticBezierSegment;
PointCollection points = polyBezierSegment.Points;
if (points.Count >= 2)
{
for (int i = 0; i < points.Count; i += 2)
{
pathData.Data.AddQuadCurveToPoint(
transform,
new nfloat(points[i + 0].X),
new nfloat(points[i + 0].Y),
new nfloat(points[i + 1].X),
new nfloat(points[i + 1].Y));
}
}
lastPoint = points.Count > 0 ? points[points.Count - 1] : Point.Zero;
}
// ArcSegment
else if (pathSegment is ArcSegment)
{
ArcSegment arcSegment = pathSegment as ArcSegment;
List<Point> points = new List<Point>();
GeometryHelper.FlattenArc(
points,
lastPoint,
arcSegment.Point,
arcSegment.Size.Width,
arcSegment.Size.Height,
arcSegment.RotationAngle,
arcSegment.IsLargeArc,
arcSegment.SweepDirection == SweepDirection.CounterClockwise,
1);
for (int i = 0; i < points.Count; i++)
{
pathData.Data.AddLineToPoint(
(nfloat)points[i].X,
(nfloat)points[i].Y);
}
if (points.Count > 0)
lastPoint = points[points.Count - 1];
}
}
if (pathFigure.IsClosed)
pathData.Data.CloseSubpath();
}
}
return pathData;
}
}
}