1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "flutter/lib/ui/painting/path.h"
6
7 // ACE PC preivew.
8 #ifndef WINDOWS_PLATFORM
9 // It cannot be passed to the sub-include of math.h, so define it in gn.
10 #define _USE_MATH_DEFINES
11 #endif
12
13 #include <math.h>
14
15 #include "flutter/lib/ui/painting/matrix.h"
16
17 namespace flutter {
18
19 typedef CanvasPath Path;
20
21 IMPLEMENT_WRAPPERTYPEINFO(ui, Path);
22
23 #define FOR_EACH_BINDING(V) \
24 V(Path, addArc) \
25 V(Path, addOval) \
26 V(Path, addPath) \
27 V(Path, addPolygon) \
28 V(Path, addRect) \
29 V(Path, addRRect) \
30 V(Path, arcTo) \
31 V(Path, arcToPoint) \
32 V(Path, close) \
33 V(Path, conicTo) \
34 V(Path, contains) \
35 V(Path, cubicTo) \
36 V(Path, extendWithPath) \
37 V(Path, extendWithPathAndMatrix) \
38 V(Path, getFillType) \
39 V(Path, lineTo) \
40 V(Path, moveTo) \
41 V(Path, quadraticBezierTo) \
42 V(Path, relativeArcToPoint) \
43 V(Path, relativeConicTo) \
44 V(Path, relativeCubicTo) \
45 V(Path, relativeLineTo) \
46 V(Path, relativeMoveTo) \
47 V(Path, relativeQuadraticBezierTo) \
48 V(Path, reset) \
49 V(Path, setFillType) \
50 V(Path, shift) \
51 V(Path, transform) \
52 V(Path, getBounds) \
53 V(Path, addPathWithMatrix) \
54 V(Path, op) \
55 V(Path, clone)
56
FOR_EACH_BINDING(DART_NATIVE_CALLBACK)57 FOR_EACH_BINDING(DART_NATIVE_CALLBACK)
58
59 void CanvasPath::RegisterNatives(tonic::DartLibraryNatives* natives) {}
60
CanvasPath()61 CanvasPath::CanvasPath() {}
62
~CanvasPath()63 CanvasPath::~CanvasPath() {}
64
getFillType()65 int CanvasPath::getFillType() {
66 return path_.getFillType();
67 }
68
setFillType(int fill_type)69 void CanvasPath::setFillType(int fill_type) {
70 path_.setFillType(static_cast<SkPath::FillType>(fill_type));
71 }
72
moveTo(float x,float y)73 void CanvasPath::moveTo(float x, float y) {
74 path_.moveTo(x, y);
75 }
76
relativeMoveTo(float x,float y)77 void CanvasPath::relativeMoveTo(float x, float y) {
78 path_.rMoveTo(x, y);
79 }
80
lineTo(float x,float y)81 void CanvasPath::lineTo(float x, float y) {
82 path_.lineTo(x, y);
83 }
84
relativeLineTo(float x,float y)85 void CanvasPath::relativeLineTo(float x, float y) {
86 path_.rLineTo(x, y);
87 }
88
quadraticBezierTo(float x1,float y1,float x2,float y2)89 void CanvasPath::quadraticBezierTo(float x1, float y1, float x2, float y2) {
90 path_.quadTo(x1, y1, x2, y2);
91 }
92
relativeQuadraticBezierTo(float x1,float y1,float x2,float y2)93 void CanvasPath::relativeQuadraticBezierTo(float x1,
94 float y1,
95 float x2,
96 float y2) {
97 path_.rQuadTo(x1, y1, x2, y2);
98 }
99
cubicTo(float x1,float y1,float x2,float y2,float x3,float y3)100 void CanvasPath::cubicTo(float x1,
101 float y1,
102 float x2,
103 float y2,
104 float x3,
105 float y3) {
106 path_.cubicTo(x1, y1, x2, y2, x3, y3);
107 }
108
relativeCubicTo(float x1,float y1,float x2,float y2,float x3,float y3)109 void CanvasPath::relativeCubicTo(float x1,
110 float y1,
111 float x2,
112 float y2,
113 float x3,
114 float y3) {
115 path_.rCubicTo(x1, y1, x2, y2, x3, y3);
116 }
117
conicTo(float x1,float y1,float x2,float y2,float w)118 void CanvasPath::conicTo(float x1, float y1, float x2, float y2, float w) {
119 path_.conicTo(x1, y1, x2, y2, w);
120 }
121
relativeConicTo(float x1,float y1,float x2,float y2,float w)122 void CanvasPath::relativeConicTo(float x1,
123 float y1,
124 float x2,
125 float y2,
126 float w) {
127 path_.rConicTo(x1, y1, x2, y2, w);
128 }
129
arcTo(float left,float top,float right,float bottom,float startAngle,float sweepAngle,bool forceMoveTo)130 void CanvasPath::arcTo(float left,
131 float top,
132 float right,
133 float bottom,
134 float startAngle,
135 float sweepAngle,
136 bool forceMoveTo) {
137 path_.arcTo(SkRect::MakeLTRB(left, top, right, bottom),
138 startAngle * 180.0 / M_PI, sweepAngle * 180.0 / M_PI,
139 forceMoveTo);
140 }
141
arcToPoint(float arcEndX,float arcEndY,float radiusX,float radiusY,float xAxisRotation,bool isLargeArc,bool isClockwiseDirection)142 void CanvasPath::arcToPoint(float arcEndX,
143 float arcEndY,
144 float radiusX,
145 float radiusY,
146 float xAxisRotation,
147 bool isLargeArc,
148 bool isClockwiseDirection) {
149 const auto arcSize = isLargeArc ? SkPath::ArcSize::kLarge_ArcSize
150 : SkPath::ArcSize::kSmall_ArcSize;
151 const auto direction = isClockwiseDirection
152 ? SkPath::Direction::kCW_Direction
153 : SkPath::Direction::kCCW_Direction;
154
155 path_.arcTo(radiusX, radiusY, xAxisRotation, arcSize, direction, arcEndX,
156 arcEndY);
157 }
158
relativeArcToPoint(float arcEndDeltaX,float arcEndDeltaY,float radiusX,float radiusY,float xAxisRotation,bool isLargeArc,bool isClockwiseDirection)159 void CanvasPath::relativeArcToPoint(float arcEndDeltaX,
160 float arcEndDeltaY,
161 float radiusX,
162 float radiusY,
163 float xAxisRotation,
164 bool isLargeArc,
165 bool isClockwiseDirection) {
166 const auto arcSize = isLargeArc ? SkPath::ArcSize::kLarge_ArcSize
167 : SkPath::ArcSize::kSmall_ArcSize;
168 const auto direction = isClockwiseDirection
169 ? SkPath::Direction::kCW_Direction
170 : SkPath::Direction::kCCW_Direction;
171 path_.rArcTo(radiusX, radiusY, xAxisRotation, arcSize, direction,
172 arcEndDeltaX, arcEndDeltaY);
173 }
174
addRect(float left,float top,float right,float bottom)175 void CanvasPath::addRect(float left, float top, float right, float bottom) {
176 path_.addRect(SkRect::MakeLTRB(left, top, right, bottom));
177 }
178
addOval(float left,float top,float right,float bottom)179 void CanvasPath::addOval(float left, float top, float right, float bottom) {
180 path_.addOval(SkRect::MakeLTRB(left, top, right, bottom));
181 }
182
addArc(float left,float top,float right,float bottom,float startAngle,float sweepAngle)183 void CanvasPath::addArc(float left,
184 float top,
185 float right,
186 float bottom,
187 float startAngle,
188 float sweepAngle) {
189 path_.addArc(SkRect::MakeLTRB(left, top, right, bottom),
190 startAngle * 180.0 / M_PI, sweepAngle * 180.0 / M_PI);
191 }
192
addPolygon(const tonic::Float32List & points,bool close)193 void CanvasPath::addPolygon(const tonic::Float32List& points, bool close) {
194 path_.addPoly(reinterpret_cast<const SkPoint*>(points.data()),
195 points.size() / 2, close);
196 }
197
addRRect(const RRect & rrect)198 void CanvasPath::addRRect(const RRect& rrect) {
199 path_.addRRect(rrect.sk_rrect);
200 }
201
addPath(CanvasPath * path,double dx,double dy)202 void CanvasPath::addPath(CanvasPath* path, double dx, double dy) {
203 if (!path) {
204 FML_LOG(ERROR) << "Path.addPath called with non-genuine Path.";
205 return;
206 }
207 path_.addPath(path->path(), dx, dy, SkPath::kAppend_AddPathMode);
208 }
209
addPathWithMatrix(CanvasPath * path,double dx,double dy,tonic::Float64List & matrix4)210 void CanvasPath::addPathWithMatrix(CanvasPath* path,
211 double dx,
212 double dy,
213 tonic::Float64List& matrix4) {
214 if (!path) {
215 FML_LOG(ERROR) << "Path.addPathWithMatrix called with non-genuine Path.";
216 return;
217 }
218 SkMatrix matrix = ToSkMatrix(matrix4);
219 matrix.setTranslateX(matrix.getTranslateX() + dx);
220 matrix.setTranslateY(matrix.getTranslateY() + dy);
221 path_.addPath(path->path(), matrix, SkPath::kAppend_AddPathMode);
222 }
223
extendWithPath(CanvasPath * path,double dx,double dy)224 void CanvasPath::extendWithPath(CanvasPath* path, double dx, double dy) {
225 if (!path) {
226 FML_LOG(ERROR) << "Path.extendWithPath called with non-genuine Path.";
227 return;
228 }
229 path_.addPath(path->path(), dx, dy, SkPath::kExtend_AddPathMode);
230 }
231
extendWithPathAndMatrix(CanvasPath * path,double dx,double dy,tonic::Float64List & matrix4)232 void CanvasPath::extendWithPathAndMatrix(CanvasPath* path,
233 double dx,
234 double dy,
235 tonic::Float64List& matrix4) {
236 if (!path) {
237 FML_LOG(ERROR) << "Path.addPathWithMatrix called with non-genuine Path.";
238 return;
239 }
240
241 SkMatrix matrix = ToSkMatrix(matrix4);
242 matrix.setTranslateX(matrix.getTranslateX() + dx);
243 matrix.setTranslateY(matrix.getTranslateY() + dy);
244 path_.addPath(path->path(), matrix, SkPath::kExtend_AddPathMode);
245 }
246
close()247 void CanvasPath::close() {
248 path_.close();
249 }
250
reset()251 void CanvasPath::reset() {
252 path_.reset();
253 }
254
contains(double x,double y)255 bool CanvasPath::contains(double x, double y) {
256 return path_.contains(x, y);
257 }
258
shift(double dx,double dy)259 fml::RefPtr<CanvasPath> CanvasPath::shift(double dx, double dy) {
260 fml::RefPtr<CanvasPath> path = CanvasPath::Create();
261 path_.offset(dx, dy, &path->path_);
262 return path;
263 }
264
transform(tonic::Float64List & matrix4)265 fml::RefPtr<CanvasPath> CanvasPath::transform(tonic::Float64List& matrix4) {
266 fml::RefPtr<CanvasPath> path = CanvasPath::Create();
267 path_.transform(ToSkMatrix(matrix4), &path->path_);
268 return path;
269 }
270
getBounds()271 tonic::Float32List CanvasPath::getBounds() {
272 tonic::Float32List rect(Dart_NewTypedData(Dart_TypedData_kFloat32, 4));
273 const SkRect& bounds = path_.getBounds();
274 rect[0] = bounds.left();
275 rect[1] = bounds.top();
276 rect[2] = bounds.right();
277 rect[3] = bounds.bottom();
278 return rect;
279 }
280
op(CanvasPath * path1,CanvasPath * path2,int operation)281 bool CanvasPath::op(CanvasPath* path1, CanvasPath* path2, int operation) {
282 return Op(path1->path(), path2->path(), (SkPathOp)operation, &path_);
283 }
284
clone()285 fml::RefPtr<CanvasPath> CanvasPath::clone() {
286 fml::RefPtr<CanvasPath> path = CanvasPath::Create();
287 // per Skia docs, this will create a fast copy
288 // data is shared until the source path or dest path are mutated
289 path->path_ = path_;
290 return path;
291 }
292
293 } // namespace flutter
294