1 /*
2 * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "skia_path.h"
17
18 #include "include/core/SkMatrix.h"
19 #include "include/pathops/SkPathOps.h"
20 #include "include/utils/SkParsePath.h"
21 #include "include/core/SkPathMeasure.h"
22 #include "include/core/SkString.h"
23 #include "skia_matrix.h"
24
25 #include "draw/path.h"
26
27 namespace OHOS {
28 namespace Rosen {
29 namespace Drawing {
SkiaPath()30 SkiaPath::SkiaPath() noexcept : path_() {}
31
SkiaPath(const SkiaPath & other)32 SkiaPath::SkiaPath(const SkiaPath& other) noexcept
33 {
34 path_ = other.path_;
35 }
36
operator =(const SkiaPath & other)37 SkiaPath& SkiaPath::operator=(const SkiaPath& other) noexcept
38 {
39 path_ = other.path_;
40 return *this;
41 }
42
Clone()43 PathImpl* SkiaPath::Clone()
44 {
45 return new SkiaPath(*this);
46 }
47
InitWithSVGString(const std::string & str)48 bool SkiaPath::InitWithSVGString(const std::string& str)
49 {
50 return SkParsePath::FromSVGString(str.c_str(), &path_);
51 }
52
ConvertToSVGString() const53 std::string SkiaPath::ConvertToSVGString() const
54 {
55 SkString skString;
56 SkParsePath::ToSVGString(path_, &skString);
57
58 return skString.c_str();
59 }
60
MoveTo(scalar x,scalar y)61 void SkiaPath::MoveTo(scalar x, scalar y)
62 {
63 path_.moveTo(x, y);
64 }
65
LineTo(scalar x,scalar y)66 void SkiaPath::LineTo(scalar x, scalar y)
67 {
68 path_.lineTo(x, y);
69 }
70
ArcTo(scalar pt1X,scalar pt1Y,scalar pt2X,scalar pt2Y,scalar startAngle,scalar sweepAngle)71 void SkiaPath::ArcTo(scalar pt1X, scalar pt1Y, scalar pt2X, scalar pt2Y, scalar startAngle, scalar sweepAngle)
72 {
73 path_.arcTo(SkRect::MakeLTRB(pt1X, pt1Y, pt2X, pt2Y), startAngle, sweepAngle, false);
74 }
75
ArcTo(scalar rx,scalar ry,scalar angle,PathDirection direction,scalar endX,scalar endY)76 void SkiaPath::ArcTo(scalar rx, scalar ry, scalar angle, PathDirection direction, scalar endX, scalar endY)
77 {
78 #if defined(USE_CANVASKIT0310_SKIA) || defined(NEW_SKIA)
79 SkPathDirection pathDir = static_cast<SkPathDirection>(direction);
80 #else
81 SkPath::Direction pathDir = static_cast<SkPath::Direction>(direction);
82 #endif
83 SkPath::ArcSize arcLarge = SkPath::ArcSize::kSmall_ArcSize;
84 path_.arcTo(rx, ry, angle, arcLarge, pathDir, endX, endY);
85 }
86
CubicTo(scalar ctrlPt1X,scalar ctrlPt1Y,scalar ctrlPt2X,scalar ctrlPt2Y,scalar endPtX,scalar endPtY)87 void SkiaPath::CubicTo(scalar ctrlPt1X, scalar ctrlPt1Y, scalar ctrlPt2X, scalar ctrlPt2Y, scalar endPtX, scalar endPtY)
88 {
89 path_.cubicTo(ctrlPt1X, ctrlPt1Y, ctrlPt2X, ctrlPt2Y, endPtX, endPtY);
90 }
91
QuadTo(scalar ctrlPtX,scalar ctrlPtY,scalar endPtX,scalar endPtY)92 void SkiaPath::QuadTo(scalar ctrlPtX, scalar ctrlPtY, scalar endPtX, scalar endPtY)
93 {
94 path_.quadTo(ctrlPtX, ctrlPtY, endPtX, endPtY);
95 }
96
AddRect(scalar left,scalar top,scalar right,scalar bottom,PathDirection dir)97 void SkiaPath::AddRect(scalar left, scalar top, scalar right, scalar bottom, PathDirection dir)
98 {
99 #if defined(USE_CANVASKIT0310_SKIA) || defined(NEW_SKIA)
100 SkPathDirection pathDir = static_cast<SkPathDirection>(dir);
101 #else
102 SkPath::Direction pathDir = static_cast<SkPath::Direction>(dir);
103 #endif
104 path_.addRect(SkRect::MakeLTRB(left, top, right, bottom), pathDir);
105 }
106
AddOval(scalar left,scalar top,scalar right,scalar bottom,PathDirection dir)107 void SkiaPath::AddOval(scalar left, scalar top, scalar right, scalar bottom, PathDirection dir)
108 {
109 #if defined(USE_CANVASKIT0310_SKIA) || defined(NEW_SKIA)
110 SkPathDirection pathDir = static_cast<SkPathDirection>(dir);
111 #else
112 SkPath::Direction pathDir = static_cast<SkPath::Direction>(dir);
113 #endif
114 path_.addOval(SkRect::MakeLTRB(left, top, right, bottom), pathDir);
115 }
116
AddArc(scalar left,scalar top,scalar right,scalar bottom,scalar startAngle,scalar sweepAngle)117 void SkiaPath::AddArc(scalar left, scalar top, scalar right, scalar bottom, scalar startAngle, scalar sweepAngle)
118 {
119 path_.addArc(SkRect::MakeLTRB(left, top, right, bottom), startAngle, sweepAngle);
120 }
121
AddPoly(const std::vector<Point> & points,int count,bool close)122 void SkiaPath::AddPoly(const std::vector<Point>& points, int count, bool close)
123 {
124 std::vector<SkPoint> pt;
125 for (auto i = 0; i < count; ++i) {
126 pt.emplace_back(SkPoint::Make(points[i].GetX(), points[i].GetY()));
127 }
128 path_.addPoly(&pt[0], count, close);
129 }
130
AddCircle(scalar x,scalar y,scalar radius,PathDirection dir)131 void SkiaPath::AddCircle(scalar x, scalar y, scalar radius, PathDirection dir)
132 {
133 #if defined(USE_CANVASKIT0310_SKIA) || defined(NEW_SKIA)
134 SkPathDirection pathDir = static_cast<SkPathDirection>(dir);
135 #else
136 SkPath::Direction pathDir = static_cast<SkPath::Direction>(dir);
137 #endif
138 path_.addCircle(x, y, radius, pathDir);
139 }
140
AddRoundRect(scalar left,scalar top,scalar right,scalar bottom,scalar xRadius,scalar yRadius,PathDirection dir)141 void SkiaPath::AddRoundRect(
142 scalar left, scalar top, scalar right, scalar bottom, scalar xRadius, scalar yRadius, PathDirection dir)
143 {
144 #if defined(USE_CANVASKIT0310_SKIA) || defined(NEW_SKIA)
145 SkPathDirection pathDir = static_cast<SkPathDirection>(dir);
146 #else
147 SkPath::Direction pathDir = static_cast<SkPath::Direction>(dir);
148 #endif
149 path_.addRoundRect(SkRect::MakeLTRB(left, top, right, bottom), xRadius, yRadius, pathDir);
150 }
151
AddRoundRect(const RoundRect & rrect,PathDirection dir)152 void SkiaPath::AddRoundRect(const RoundRect& rrect, PathDirection dir)
153 {
154 #if defined(USE_CANVASKIT0310_SKIA) || defined(NEW_SKIA)
155 SkPathDirection pathDir = static_cast<SkPathDirection>(dir);
156 #else
157 SkPath::Direction pathDir = static_cast<SkPath::Direction>(dir);
158 #endif
159
160 Rect rect = rrect.GetRect();
161 SkRect outer = SkRect::MakeLTRB(rect.GetLeft(), rect.GetTop(), rect.GetRight(), rect.GetBottom());
162
163 SkVector radii[4];
164 Point p;
165 p = rrect.GetCornerRadius(RoundRect::TOP_LEFT_POS);
166 radii[SkRRect::kUpperLeft_Corner] = { p.GetX(), p.GetY() };
167 p = rrect.GetCornerRadius(RoundRect::TOP_RIGHT_POS);
168 radii[SkRRect::kUpperRight_Corner] = { p.GetX(), p.GetY() };
169 p = rrect.GetCornerRadius(RoundRect::BOTTOM_RIGHT_POS);
170 radii[SkRRect::kLowerRight_Corner] = { p.GetX(), p.GetY() };
171 p = rrect.GetCornerRadius(RoundRect::BOTTOM_LEFT_POS);
172 radii[SkRRect::kLowerLeft_Corner] = { p.GetX(), p.GetY() };
173
174 SkRRect skRRect;
175 skRRect.setRectRadii(outer, radii);
176 path_.addRRect(skRRect, pathDir);
177 }
178
AddPath(const Path & src,scalar dx,scalar dy)179 void SkiaPath::AddPath(const Path& src, scalar dx, scalar dy)
180 {
181 auto skPathImpl = src.GetImpl<SkiaPath>();
182 if (skPathImpl != nullptr) {
183 path_.addPath(skPathImpl->GetPath(), dx, dy);
184 }
185 }
186
AddPath(const Path & src)187 void SkiaPath::AddPath(const Path& src)
188 {
189 auto skPathImpl = src.GetImpl<SkiaPath>();
190 if (skPathImpl != nullptr) {
191 path_.addPath(skPathImpl->GetPath());
192 }
193 }
194
ReverseAddPath(const Path & src)195 void SkiaPath::ReverseAddPath(const Path& src)
196 {
197 path_.reverseAddPath(src.GetImpl<SkiaPath>()->GetPath());
198 }
199
AddPathWithMatrix(const Path & src,const Matrix & matrix)200 void SkiaPath::AddPathWithMatrix(const Path& src, const Matrix& matrix)
201 {
202 auto skPathImpl = src.GetImpl<SkiaPath>();
203 auto skMatrixImpl = matrix.GetImpl<SkiaMatrix>();
204 if (skPathImpl != nullptr && skMatrixImpl != nullptr) {
205 path_.addPath(skPathImpl->GetPath(), skMatrixImpl->ExportSkiaMatrix());
206 }
207 }
208
GetBounds() const209 Rect SkiaPath::GetBounds() const
210 {
211 SkRect rect = path_.getBounds();
212 return Rect(rect.left(), rect.top(), rect.width(), rect.height());
213 }
214
SetFillStyle(PathFillType fillstyle)215 void SkiaPath::SetFillStyle(PathFillType fillstyle)
216 {
217 #if defined(USE_CANVASKIT0310_SKIA) || defined(NEW_SKIA)
218 SkPathFillType ft = static_cast<SkPathFillType>(fillstyle);
219 #else
220 SkPath::FillType ft = static_cast<SkPath::FillType>(fillstyle);
221 #endif
222 path_.setFillType(ft);
223 }
224
Interpolate(const Path & ending,scalar weight,Path & out)225 bool SkiaPath::Interpolate(const Path& ending, scalar weight, Path& out)
226 {
227 bool isSuccess = false;
228 auto skPathImpl1 = ending.GetImpl<SkiaPath>();
229 auto skPathImpl2 = out.GetImpl<SkiaPath>();
230 if (skPathImpl1 != nullptr && skPathImpl2 != nullptr) {
231 SkPath interp;
232 isSuccess = path_.interpolate(skPathImpl1->GetPath(), weight, &interp);
233 skPathImpl2->SetPath(interp);
234 }
235 return isSuccess;
236 }
237
InitWithInterpolate(const Path & srcPath,const Path & endingPath,scalar weight)238 bool SkiaPath::InitWithInterpolate(const Path& srcPath, const Path& endingPath, scalar weight)
239 {
240 const SkPath& srcSkPath = srcPath.GetImpl<SkiaPath>()->GetPath();
241 return srcSkPath.interpolate(endingPath.GetImpl<SkiaPath>()->GetPath(), weight, &path_);
242 }
243
Transform(const Matrix & matrix)244 void SkiaPath::Transform(const Matrix& matrix)
245 {
246 auto skMatrixImpl = matrix.GetImpl<SkiaMatrix>();
247 if (skMatrixImpl != nullptr) {
248 path_.transform(skMatrixImpl->ExportSkiaMatrix());
249 }
250 }
251
Offset(scalar dx,scalar dy)252 void SkiaPath::Offset(scalar dx, scalar dy)
253 {
254 path_.offset(dx, dy);
255 }
256
OpWith(const Path & path1,const Path & path2,PathOp op)257 bool SkiaPath::OpWith(const Path& path1, const Path& path2, PathOp op)
258 {
259 SkPathOp pathOp = static_cast<SkPathOp>(op);
260 bool isOpSuccess = false;
261
262 auto skPathImpl1 = path1.GetImpl<SkiaPath>();
263 auto skPathImpl2 = path2.GetImpl<SkiaPath>();
264 if (skPathImpl1 != nullptr && skPathImpl2 != nullptr) {
265 isOpSuccess = Op(skPathImpl1->GetPath(), skPathImpl2->GetPath(), pathOp, &path_);
266 }
267
268 if (isOpSuccess) {
269 return true;
270 }
271 return false;
272 }
273
IsValid() const274 bool SkiaPath::IsValid() const
275 {
276 return !path_.isEmpty();
277 }
278
Reset()279 void SkiaPath::Reset()
280 {
281 path_.reset();
282 }
283
Close()284 void SkiaPath::Close()
285 {
286 path_.close();
287 }
288
SetPath(const SkPath & path)289 void SkiaPath::SetPath(const SkPath& path)
290 {
291 path_ = path;
292 }
293
GetPath() const294 const SkPath& SkiaPath::GetPath() const
295 {
296 return path_;
297 }
298
GetLength(bool forceClosed) const299 scalar SkiaPath::GetLength(bool forceClosed) const
300 {
301 SkPathMeasure pathMeasure(path_, forceClosed);
302 return pathMeasure.getLength();
303 }
304
GetPositionAndTangent(scalar distance,Point & position,Point & tangent,bool forceClosed) const305 bool SkiaPath::GetPositionAndTangent(scalar distance, Point& position, Point& tangent, bool forceClosed) const
306 {
307 bool ret = false;
308 SkPoint skPosition;
309 SkVector skTangent;
310 SkPathMeasure pathMeasure(path_, forceClosed);
311 ret = pathMeasure.getPosTan(distance, &skPosition, &skTangent);
312 if (ret) {
313 position.SetX(skPosition.x());
314 position.SetY(skPosition.y());
315 tangent.SetX(skTangent.x());
316 tangent.SetY(skTangent.y());
317 }
318
319 return ret;
320 }
321
322 } // namespace Drawing
323 } // namespace Rosen
324 } // namespace OHOS
325