• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "src/core/SkReadBuffer.h"
26 #include "src/core/SkWriteBuffer.h"
27 
28 #include "draw/path.h"
29 #include "utils/data.h"
30 #include "utils/log.h"
31 
32 namespace OHOS {
33 namespace Rosen {
34 namespace Drawing {
35 
SkiaPath(const SkiaPath & other)36 SkiaPath::SkiaPath(const SkiaPath& other) noexcept
37 {
38     path_ = other.path_;
39 }
40 
operator =(const SkiaPath & other)41 SkiaPath& SkiaPath::operator=(const SkiaPath& other) noexcept
42 {
43     path_ = other.path_;
44     return *this;
45 }
46 
Clone()47 PathImpl* SkiaPath::Clone()
48 {
49     return new SkiaPath(*this);
50 }
51 
InitWithSVGString(const std::string & str)52 bool SkiaPath::InitWithSVGString(const std::string& str)
53 {
54     return SkParsePath::FromSVGString(str.c_str(), &path_);
55 }
56 
ConvertToSVGString() const57 std::string SkiaPath::ConvertToSVGString() const
58 {
59     SkString skString;
60     SkParsePath::ToSVGString(path_, &skString);
61 
62     return skString.c_str();
63 }
64 
MoveTo(scalar x,scalar y)65 void SkiaPath::MoveTo(scalar x, scalar y)
66 {
67     path_.moveTo(x, y);
68 }
69 
LineTo(scalar x,scalar y)70 void SkiaPath::LineTo(scalar x, scalar y)
71 {
72     path_.lineTo(x, y);
73 }
74 
ArcTo(scalar pt1X,scalar pt1Y,scalar pt2X,scalar pt2Y,scalar startAngle,scalar sweepAngle)75 void SkiaPath::ArcTo(scalar pt1X, scalar pt1Y, scalar pt2X, scalar pt2Y, scalar startAngle, scalar sweepAngle)
76 {
77     path_.arcTo(SkRect::MakeLTRB(pt1X, pt1Y, pt2X, pt2Y), startAngle, sweepAngle, false);
78 }
79 
ArcTo(scalar rx,scalar ry,scalar angle,PathDirection direction,scalar endX,scalar endY)80 void SkiaPath::ArcTo(scalar rx, scalar ry, scalar angle, PathDirection direction, scalar endX, scalar endY)
81 {
82 #if defined(USE_CANVASKIT0310_SKIA) || defined(NEW_SKIA)
83     SkPathDirection pathDir = static_cast<SkPathDirection>(direction);
84 #else
85     SkPath::Direction pathDir = static_cast<SkPath::Direction>(direction);
86 #endif
87     SkPath::ArcSize arcLarge = SkPath::ArcSize::kSmall_ArcSize;
88     path_.arcTo(rx, ry, angle, arcLarge, pathDir, endX, endY);
89 }
90 
ArcTo(scalar x1,scalar y1,scalar x2,scalar y2,scalar radius)91 void SkiaPath::ArcTo(scalar x1, scalar y1, scalar x2, scalar y2, scalar radius)
92 {
93     path_.arcTo(x1, y1, x2, y2, radius);
94 }
95 
CubicTo(scalar ctrlPt1X,scalar ctrlPt1Y,scalar ctrlPt2X,scalar ctrlPt2Y,scalar endPtX,scalar endPtY)96 void SkiaPath::CubicTo(scalar ctrlPt1X, scalar ctrlPt1Y, scalar ctrlPt2X, scalar ctrlPt2Y, scalar endPtX, scalar endPtY)
97 {
98     path_.cubicTo(ctrlPt1X, ctrlPt1Y, ctrlPt2X, ctrlPt2Y, endPtX, endPtY);
99 }
100 
QuadTo(scalar ctrlPtX,scalar ctrlPtY,scalar endPtX,scalar endPtY)101 void SkiaPath::QuadTo(scalar ctrlPtX, scalar ctrlPtY, scalar endPtX, scalar endPtY)
102 {
103     path_.quadTo(ctrlPtX, ctrlPtY, endPtX, endPtY);
104 }
105 
RMoveTo(scalar dx,scalar dy)106 void SkiaPath::RMoveTo(scalar dx, scalar dy)
107 {
108     path_.rMoveTo(dx, dy);
109 }
110 
RLineTo(scalar dx,scalar dy)111 void SkiaPath::RLineTo(scalar dx, scalar dy)
112 {
113     path_.rLineTo(dx, dy);
114 }
115 
RArcTo(scalar rx,scalar ry,scalar angle,PathDirection direction,scalar dx,scalar dy)116 void SkiaPath::RArcTo(scalar rx, scalar ry, scalar angle, PathDirection direction, scalar dx, scalar dy)
117 {
118 #if defined(USE_CANVASKIT0310_SKIA) || defined(NEW_SKIA)
119     SkPathDirection pathDir = static_cast<SkPathDirection>(direction);
120 #else
121     SkPath::Direction pathDir = static_cast<SkPath::Direction>(direction);
122 #endif
123     SkPath::ArcSize arcLarge = SkPath::ArcSize::kSmall_ArcSize;
124     path_.arcTo(rx, ry, angle, arcLarge, pathDir, dx, dy);
125 }
126 
RCubicTo(scalar dx1,scalar dy1,scalar dx2,scalar dy2,scalar dx3,scalar dy3)127 void SkiaPath::RCubicTo(scalar dx1, scalar dy1, scalar dx2, scalar dy2, scalar dx3, scalar dy3)
128 {
129     path_.rCubicTo(dx1, dy1, dx2, dy2, dx3, dy3);
130 }
131 
RQuadTo(scalar dx1,scalar dy1,scalar dx2,scalar dy2)132 void SkiaPath::RQuadTo(scalar dx1, scalar dy1, scalar dx2, scalar dy2)
133 {
134     path_.rQuadTo(dx1, dy1, dx2, dy2);
135 }
136 
AddRect(scalar left,scalar top,scalar right,scalar bottom,PathDirection dir)137 void SkiaPath::AddRect(scalar left, scalar top, scalar right, scalar bottom, PathDirection dir)
138 {
139 #if defined(USE_CANVASKIT0310_SKIA) || defined(NEW_SKIA)
140     SkPathDirection pathDir = static_cast<SkPathDirection>(dir);
141 #else
142     SkPath::Direction pathDir = static_cast<SkPath::Direction>(dir);
143 #endif
144     path_.addRect(SkRect::MakeLTRB(left, top, right, bottom), pathDir);
145 }
146 
AddOval(scalar left,scalar top,scalar right,scalar bottom,PathDirection dir)147 void SkiaPath::AddOval(scalar left, scalar top, scalar right, scalar bottom, PathDirection dir)
148 {
149 #if defined(USE_CANVASKIT0310_SKIA) || defined(NEW_SKIA)
150     SkPathDirection pathDir = static_cast<SkPathDirection>(dir);
151 #else
152     SkPath::Direction pathDir = static_cast<SkPath::Direction>(dir);
153 #endif
154     path_.addOval(SkRect::MakeLTRB(left, top, right, bottom), pathDir);
155 }
156 
AddArc(scalar left,scalar top,scalar right,scalar bottom,scalar startAngle,scalar sweepAngle)157 void SkiaPath::AddArc(scalar left, scalar top, scalar right, scalar bottom, scalar startAngle, scalar sweepAngle)
158 {
159     path_.addArc(SkRect::MakeLTRB(left, top, right, bottom), startAngle, sweepAngle);
160 }
161 
AddPoly(const std::vector<Point> & points,int count,bool close)162 void SkiaPath::AddPoly(const std::vector<Point>& points, int count, bool close)
163 {
164     std::vector<SkPoint> pt;
165     for (auto i = 0; i < count; ++i) {
166         pt.emplace_back(SkPoint::Make(points[i].GetX(), points[i].GetY()));
167     }
168     path_.addPoly(&pt[0], count, close);
169 }
170 
AddCircle(scalar x,scalar y,scalar radius,PathDirection dir)171 void SkiaPath::AddCircle(scalar x, scalar y, scalar radius, PathDirection dir)
172 {
173 #if defined(USE_CANVASKIT0310_SKIA) || defined(NEW_SKIA)
174     SkPathDirection pathDir = static_cast<SkPathDirection>(dir);
175 #else
176     SkPath::Direction pathDir = static_cast<SkPath::Direction>(dir);
177 #endif
178     path_.addCircle(x, y, radius, pathDir);
179 }
180 
AddRoundRect(scalar left,scalar top,scalar right,scalar bottom,scalar xRadius,scalar yRadius,PathDirection dir)181 void SkiaPath::AddRoundRect(
182     scalar left, scalar top, scalar right, scalar bottom, scalar xRadius, scalar yRadius, PathDirection dir)
183 {
184 #if defined(USE_CANVASKIT0310_SKIA) || defined(NEW_SKIA)
185     SkPathDirection pathDir = static_cast<SkPathDirection>(dir);
186 #else
187     SkPath::Direction pathDir = static_cast<SkPath::Direction>(dir);
188 #endif
189     path_.addRoundRect(SkRect::MakeLTRB(left, top, right, bottom), xRadius, yRadius, pathDir);
190 }
191 
AddRoundRect(const RoundRect & rrect,PathDirection dir)192 void SkiaPath::AddRoundRect(const RoundRect& rrect, PathDirection dir)
193 {
194 #if defined(USE_CANVASKIT0310_SKIA) || defined(NEW_SKIA)
195     SkPathDirection pathDir = static_cast<SkPathDirection>(dir);
196 #else
197     SkPath::Direction pathDir = static_cast<SkPath::Direction>(dir);
198 #endif
199 
200     Rect rect = rrect.GetRect();
201     SkRect outer = SkRect::MakeLTRB(rect.GetLeft(), rect.GetTop(), rect.GetRight(), rect.GetBottom());
202 
203     SkVector radii[4];
204     Point p;
205     p = rrect.GetCornerRadius(RoundRect::TOP_LEFT_POS);
206     radii[SkRRect::kUpperLeft_Corner] = { p.GetX(), p.GetY() };
207     p = rrect.GetCornerRadius(RoundRect::TOP_RIGHT_POS);
208     radii[SkRRect::kUpperRight_Corner] = { p.GetX(), p.GetY() };
209     p = rrect.GetCornerRadius(RoundRect::BOTTOM_RIGHT_POS);
210     radii[SkRRect::kLowerRight_Corner] = { p.GetX(), p.GetY() };
211     p = rrect.GetCornerRadius(RoundRect::BOTTOM_LEFT_POS);
212     radii[SkRRect::kLowerLeft_Corner] = { p.GetX(), p.GetY() };
213 
214     SkRRect skRRect;
215     skRRect.setRectRadii(outer, radii);
216     path_.addRRect(skRRect, pathDir);
217 }
218 
AddPath(const Path & src,scalar dx,scalar dy)219 void SkiaPath::AddPath(const Path& src, scalar dx, scalar dy)
220 {
221     auto skPathImpl = src.GetImpl<SkiaPath>();
222     if (skPathImpl != nullptr) {
223         path_.addPath(skPathImpl->GetPath(), dx, dy);
224     }
225 }
226 
AddPath(const Path & src)227 void SkiaPath::AddPath(const Path& src)
228 {
229     auto skPathImpl = src.GetImpl<SkiaPath>();
230     if (skPathImpl != nullptr) {
231         path_.addPath(skPathImpl->GetPath());
232     }
233 }
234 
Contains(scalar x,scalar y) const235 bool SkiaPath::Contains(scalar x, scalar y) const
236 {
237     return path_.contains(x, y);
238 }
239 
ReverseAddPath(const Path & src)240 void SkiaPath::ReverseAddPath(const Path& src)
241 {
242     path_.reverseAddPath(src.GetImpl<SkiaPath>()->GetPath());
243 }
244 
AddPathWithMatrix(const Path & src,const Matrix & matrix)245 void SkiaPath::AddPathWithMatrix(const Path& src, const Matrix& matrix)
246 {
247     auto skPathImpl = src.GetImpl<SkiaPath>();
248     auto skMatrixImpl = matrix.GetImpl<SkiaMatrix>();
249     if (skPathImpl != nullptr && skMatrixImpl != nullptr) {
250         path_.addPath(skPathImpl->GetPath(), skMatrixImpl->ExportSkiaMatrix());
251     }
252 }
253 
GetBounds() const254 Rect SkiaPath::GetBounds() const
255 {
256     SkRect rect = path_.getBounds();
257     return Rect(rect.left(), rect.top(), rect.right(), rect.bottom());
258 }
259 
SetFillStyle(PathFillType fillstyle)260 void SkiaPath::SetFillStyle(PathFillType fillstyle)
261 {
262 #if defined(USE_CANVASKIT0310_SKIA) || defined(NEW_SKIA)
263     SkPathFillType ft = static_cast<SkPathFillType>(fillstyle);
264 #else
265     SkPath::FillType ft = static_cast<SkPath::FillType>(fillstyle);
266 #endif
267     path_.setFillType(ft);
268 }
269 
Interpolate(const Path & ending,scalar weight,Path & out)270 bool SkiaPath::Interpolate(const Path& ending, scalar weight, Path& out)
271 {
272     bool isSuccess = false;
273     auto skPathImpl1 = ending.GetImpl<SkiaPath>();
274     auto skPathImpl2 = out.GetImpl<SkiaPath>();
275     if (skPathImpl1 != nullptr && skPathImpl2 != nullptr) {
276         SkPath interp;
277         isSuccess = path_.interpolate(skPathImpl1->GetPath(), weight, &interp);
278         skPathImpl2->SetPath(interp);
279     }
280     return isSuccess;
281 }
282 
InitWithInterpolate(const Path & srcPath,const Path & endingPath,scalar weight)283 bool SkiaPath::InitWithInterpolate(const Path& srcPath, const Path& endingPath, scalar weight)
284 {
285     const SkPath& srcSkPath = srcPath.GetImpl<SkiaPath>()->GetPath();
286     return srcSkPath.interpolate(endingPath.GetImpl<SkiaPath>()->GetPath(), weight, &path_);
287 }
288 
Transform(const Matrix & matrix)289 void SkiaPath::Transform(const Matrix& matrix)
290 {
291     auto skMatrixImpl = matrix.GetImpl<SkiaMatrix>();
292     if (skMatrixImpl != nullptr) {
293         path_.transform(skMatrixImpl->ExportSkiaMatrix());
294     }
295 }
296 
Offset(scalar dx,scalar dy)297 void SkiaPath::Offset(scalar dx, scalar dy)
298 {
299     path_.offset(dx, dy);
300 }
301 
OpWith(const Path & path1,const Path & path2,PathOp op)302 bool SkiaPath::OpWith(const Path& path1, const Path& path2, PathOp op)
303 {
304     SkPathOp pathOp = static_cast<SkPathOp>(op);
305     bool isOpSuccess = false;
306 
307     auto skPathImpl1 = path1.GetImpl<SkiaPath>();
308     auto skPathImpl2 = path2.GetImpl<SkiaPath>();
309     if (skPathImpl1 != nullptr && skPathImpl2 != nullptr) {
310         isOpSuccess = Op(skPathImpl1->GetPath(), skPathImpl2->GetPath(), pathOp, &path_);
311     }
312 
313     if (isOpSuccess) {
314         return true;
315     }
316     return false;
317 }
318 
IsValid() const319 bool SkiaPath::IsValid() const
320 {
321     return !path_.isEmpty();
322 }
323 
Reset()324 void SkiaPath::Reset()
325 {
326     path_.reset();
327 }
328 
Close()329 void SkiaPath::Close()
330 {
331     path_.close();
332 }
333 
SetPath(const SkPath & path)334 void SkiaPath::SetPath(const SkPath& path)
335 {
336     path_ = path;
337 }
338 
GetPath() const339 const SkPath& SkiaPath::GetPath() const
340 {
341     return path_;
342 }
343 
GetLength(bool forceClosed) const344 scalar SkiaPath::GetLength(bool forceClosed) const
345 {
346     SkPathMeasure pathMeasure(path_, forceClosed);
347     return pathMeasure.getLength();
348 }
349 
GetPositionAndTangent(scalar distance,Point & position,Point & tangent,bool forceClosed) const350 bool SkiaPath::GetPositionAndTangent(scalar distance, Point& position, Point& tangent, bool forceClosed) const
351 {
352     bool ret = false;
353     SkPoint skPosition;
354     SkVector skTangent;
355     SkPathMeasure pathMeasure(path_, forceClosed);
356     ret = pathMeasure.getPosTan(distance, &skPosition, &skTangent);
357     if (ret) {
358         position.SetX(skPosition.x());
359         position.SetY(skPosition.y());
360         tangent.SetX(skTangent.x());
361         tangent.SetY(skTangent.y());
362     }
363 
364     return ret;
365 }
366 
Serialize() const367 std::shared_ptr<Data> SkiaPath::Serialize() const
368 {
369     SkBinaryWriteBuffer writer;
370     writer.writePath(path_);
371     size_t length = writer.bytesWritten();
372     std::shared_ptr<Data> data = std::make_shared<Data>();
373     data->BuildUninitialized(length);
374     writer.writeToMemory(data->WritableData());
375     return data;
376 }
377 
Deserialize(std::shared_ptr<Data> data)378 bool SkiaPath::Deserialize(std::shared_ptr<Data> data)
379 {
380     if (data == nullptr) {
381         LOGD("SkiaPath::Deserialize, data is invalid!");
382         return false;
383     }
384 
385     SkReadBuffer reader(data->GetData(), data->GetSize());
386     reader.readPath(&path_);
387     return true;
388 }
389 
390 } // namespace Drawing
391 } // namespace Rosen
392 } // namespace OHOS
393