• 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 "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