• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2025 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/SkString.h"
22 #include "skia_matrix.h"
23 
24 #include "src/core/SkReadBuffer.h"
25 #include "src/core/SkWriteBuffer.h"
26 
27 #include "draw/path.h"
28 #include "utils/data.h"
29 #include "utils/log.h"
30 
31 namespace OHOS {
32 namespace Rosen {
33 namespace Drawing {
34 
SkiaPath(const SkiaPath & other)35 SkiaPath::SkiaPath(const SkiaPath& other) noexcept : path_(other.path_) {}
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 #ifdef USE_M133_SKIA
57     skString = SkParsePath::ToSVGString(path_);
58 #else
59     SkParsePath::ToSVGString(path_, &skString);
60 #endif
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     isChanged_ = true;
69 }
70 
LineTo(scalar x,scalar y)71 void SkiaPath::LineTo(scalar x, scalar y)
72 {
73     path_.lineTo(x, y);
74     isChanged_ = true;
75 }
76 
ArcTo(scalar pt1X,scalar pt1Y,scalar pt2X,scalar pt2Y,scalar startAngle,scalar sweepAngle)77 void SkiaPath::ArcTo(scalar pt1X, scalar pt1Y, scalar pt2X, scalar pt2Y, scalar startAngle, scalar sweepAngle)
78 {
79     path_.arcTo(SkRect::MakeLTRB(pt1X, pt1Y, pt2X, pt2Y), startAngle, sweepAngle, false);
80     isChanged_ = true;
81 }
82 
ArcTo(scalar rx,scalar ry,scalar angle,PathDirection direction,scalar endX,scalar endY)83 void SkiaPath::ArcTo(scalar rx, scalar ry, scalar angle, PathDirection direction, scalar endX, scalar endY)
84 {
85     SkPathDirection pathDir = static_cast<SkPathDirection>(direction);
86     SkPath::ArcSize arcLarge = SkPath::ArcSize::kSmall_ArcSize;
87     path_.arcTo(rx, ry, angle, arcLarge, pathDir, endX, endY);
88     isChanged_ = true;
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     isChanged_ = true;
95 }
96 
CubicTo(scalar ctrlPt1X,scalar ctrlPt1Y,scalar ctrlPt2X,scalar ctrlPt2Y,scalar endPtX,scalar endPtY)97 void SkiaPath::CubicTo(scalar ctrlPt1X, scalar ctrlPt1Y, scalar ctrlPt2X, scalar ctrlPt2Y, scalar endPtX, scalar endPtY)
98 {
99     path_.cubicTo(ctrlPt1X, ctrlPt1Y, ctrlPt2X, ctrlPt2Y, endPtX, endPtY);
100     isChanged_ = true;
101 }
102 
QuadTo(scalar ctrlPtX,scalar ctrlPtY,scalar endPtX,scalar endPtY)103 void SkiaPath::QuadTo(scalar ctrlPtX, scalar ctrlPtY, scalar endPtX, scalar endPtY)
104 {
105     path_.quadTo(ctrlPtX, ctrlPtY, endPtX, endPtY);
106     isChanged_ = true;
107 }
108 
ConicTo(scalar ctrlX,scalar ctrlY,scalar endX,scalar endY,scalar weight)109 void SkiaPath::ConicTo(scalar ctrlX, scalar ctrlY, scalar endX, scalar endY, scalar weight)
110 {
111     path_.conicTo(ctrlX, ctrlY, endX, endY, weight);
112     isChanged_ = true;
113 }
114 
RMoveTo(scalar dx,scalar dy)115 void SkiaPath::RMoveTo(scalar dx, scalar dy)
116 {
117     path_.rMoveTo(dx, dy);
118     isChanged_ = true;
119 }
120 
RLineTo(scalar dx,scalar dy)121 void SkiaPath::RLineTo(scalar dx, scalar dy)
122 {
123     path_.rLineTo(dx, dy);
124     isChanged_ = true;
125 }
126 
RArcTo(scalar rx,scalar ry,scalar angle,PathDirection direction,scalar dx,scalar dy)127 void SkiaPath::RArcTo(scalar rx, scalar ry, scalar angle, PathDirection direction, scalar dx, scalar dy)
128 {
129     SkPathDirection pathDir = static_cast<SkPathDirection>(direction);
130     SkPath::ArcSize arcLarge = SkPath::ArcSize::kSmall_ArcSize;
131     path_.rArcTo(rx, ry, angle, arcLarge, pathDir, dx, dy);
132     isChanged_ = true;
133 }
134 
RCubicTo(scalar dx1,scalar dy1,scalar dx2,scalar dy2,scalar dx3,scalar dy3)135 void SkiaPath::RCubicTo(scalar dx1, scalar dy1, scalar dx2, scalar dy2, scalar dx3, scalar dy3)
136 {
137     path_.rCubicTo(dx1, dy1, dx2, dy2, dx3, dy3);
138     isChanged_ = true;
139 }
140 
RConicTo(scalar ctrlPtX,scalar ctrlPtY,scalar endPtX,scalar endPtY,scalar weight)141 void SkiaPath::RConicTo(scalar ctrlPtX, scalar ctrlPtY, scalar endPtX, scalar endPtY, scalar weight)
142 {
143     path_.rConicTo(ctrlPtX, ctrlPtY, endPtX, endPtY, weight);
144     isChanged_ = true;
145 }
146 
RQuadTo(scalar dx1,scalar dy1,scalar dx2,scalar dy2)147 void SkiaPath::RQuadTo(scalar dx1, scalar dy1, scalar dx2, scalar dy2)
148 {
149     path_.rQuadTo(dx1, dy1, dx2, dy2);
150     isChanged_ = true;
151 }
152 
AddRect(scalar left,scalar top,scalar right,scalar bottom,PathDirection dir)153 void SkiaPath::AddRect(scalar left, scalar top, scalar right, scalar bottom, PathDirection dir)
154 {
155     SkPathDirection pathDir = static_cast<SkPathDirection>(dir);
156     path_.addRect(SkRect::MakeLTRB(left, top, right, bottom), pathDir);
157     isChanged_ = true;
158 }
159 
AddRect(const Rect & rect,unsigned start,PathDirection dir)160 void SkiaPath::AddRect(const Rect& rect, unsigned start, PathDirection dir)
161 {
162     SkPathDirection pathDir = static_cast<SkPathDirection>(dir);
163     path_.addRect(SkRect::MakeLTRB(rect.GetLeft(), rect.GetTop(), rect.GetRight(), rect.GetBottom()), pathDir, start);
164     isChanged_ = true;
165 }
166 
AddOval(scalar left,scalar top,scalar right,scalar bottom,PathDirection dir)167 void SkiaPath::AddOval(scalar left, scalar top, scalar right, scalar bottom, PathDirection dir)
168 {
169     SkPathDirection pathDir = static_cast<SkPathDirection>(dir);
170     path_.addOval(SkRect::MakeLTRB(left, top, right, bottom), pathDir);
171     isChanged_ = true;
172 }
173 
AddOval(scalar left,scalar top,scalar right,scalar bottom,unsigned start,PathDirection dir)174 void SkiaPath::AddOval(scalar left, scalar top, scalar right, scalar bottom, unsigned start, PathDirection dir)
175 {
176     SkPathDirection pathDir = static_cast<SkPathDirection>(dir);
177     path_.addOval(SkRect::MakeLTRB(left, top, right, bottom), pathDir, start);
178     isChanged_ = true;
179 }
180 
AddArc(scalar left,scalar top,scalar right,scalar bottom,scalar startAngle,scalar sweepAngle)181 void SkiaPath::AddArc(scalar left, scalar top, scalar right, scalar bottom, scalar startAngle, scalar sweepAngle)
182 {
183     path_.addArc(SkRect::MakeLTRB(left, top, right, bottom), startAngle, sweepAngle);
184     isChanged_ = true;
185 }
186 
AddPoly(const std::vector<Point> & points,int count,bool close)187 void SkiaPath::AddPoly(const std::vector<Point>& points, int count, bool close)
188 {
189     std::vector<SkPoint> pt;
190     for (auto i = 0; i < count; ++i) {
191         pt.emplace_back(SkPoint::Make(points[i].GetX(), points[i].GetY()));
192     }
193     path_.addPoly(&pt[0], count, close);
194     isChanged_ = true;
195 }
196 
AddCircle(scalar x,scalar y,scalar radius,PathDirection dir)197 void SkiaPath::AddCircle(scalar x, scalar y, scalar radius, PathDirection dir)
198 {
199     SkPathDirection pathDir = static_cast<SkPathDirection>(dir);
200     path_.addCircle(x, y, radius, pathDir);
201     isChanged_ = true;
202 }
203 
AddRoundRect(scalar left,scalar top,scalar right,scalar bottom,scalar xRadius,scalar yRadius,PathDirection dir)204 void SkiaPath::AddRoundRect(
205     scalar left, scalar top, scalar right, scalar bottom, scalar xRadius, scalar yRadius, PathDirection dir)
206 {
207     SkPathDirection pathDir = static_cast<SkPathDirection>(dir);
208     path_.addRoundRect(SkRect::MakeLTRB(left, top, right, bottom), xRadius, yRadius, pathDir);
209     isChanged_ = true;
210 }
211 
AddRoundRect(const RoundRect & rrect,PathDirection dir)212 void SkiaPath::AddRoundRect(const RoundRect& rrect, PathDirection dir)
213 {
214     SkPathDirection pathDir = static_cast<SkPathDirection>(dir);
215 
216     Rect rect = rrect.GetRect();
217     SkRect outer = SkRect::MakeLTRB(rect.GetLeft(), rect.GetTop(), rect.GetRight(), rect.GetBottom());
218 
219     SkVector radii[4];
220     Point p;
221     p = rrect.GetCornerRadius(RoundRect::TOP_LEFT_POS);
222     radii[SkRRect::kUpperLeft_Corner] = { p.GetX(), p.GetY() };
223     p = rrect.GetCornerRadius(RoundRect::TOP_RIGHT_POS);
224     radii[SkRRect::kUpperRight_Corner] = { p.GetX(), p.GetY() };
225     p = rrect.GetCornerRadius(RoundRect::BOTTOM_RIGHT_POS);
226     radii[SkRRect::kLowerRight_Corner] = { p.GetX(), p.GetY() };
227     p = rrect.GetCornerRadius(RoundRect::BOTTOM_LEFT_POS);
228     radii[SkRRect::kLowerLeft_Corner] = { p.GetX(), p.GetY() };
229 
230     SkRRect skRRect;
231     skRRect.setRectRadii(outer, radii);
232     path_.addRRect(skRRect, pathDir);
233     isChanged_ = true;
234 }
235 
AddPath(const Path & src,scalar dx,scalar dy,PathAddMode mode)236 void SkiaPath::AddPath(const Path& src, scalar dx, scalar dy, PathAddMode mode)
237 {
238     auto skPathImpl = src.GetImpl<SkiaPath>();
239     if (skPathImpl != nullptr) {
240         path_.addPath(skPathImpl->GetPath(), dx, dy, static_cast<SkPath::AddPathMode>(mode));
241         isChanged_ = true;
242     }
243 }
244 
AddPath(const Path & src,PathAddMode mode)245 void SkiaPath::AddPath(const Path& src, PathAddMode mode)
246 {
247     auto skPathImpl = src.GetImpl<SkiaPath>();
248     if (skPathImpl != nullptr) {
249         path_.addPath(skPathImpl->GetPath(), static_cast<SkPath::AddPathMode>(mode));
250         isChanged_ = true;
251     }
252 }
253 
Contains(scalar x,scalar y) const254 bool SkiaPath::Contains(scalar x, scalar y) const
255 {
256     return path_.contains(x, y);
257 }
258 
ReverseAddPath(const Path & src)259 void SkiaPath::ReverseAddPath(const Path& src)
260 {
261     path_.reverseAddPath(src.GetImpl<SkiaPath>()->GetPath());
262     isChanged_ = true;
263 }
264 
AddPath(const Path & src,const Matrix & matrix,PathAddMode mode)265 void SkiaPath::AddPath(const Path& src, const Matrix& matrix, PathAddMode mode)
266 {
267     auto skPathImpl = src.GetImpl<SkiaPath>();
268     auto skMatrixImpl = matrix.GetImpl<SkiaMatrix>();
269     if (skPathImpl != nullptr && skMatrixImpl != nullptr) {
270         path_.addPath(skPathImpl->GetPath(), skMatrixImpl->ExportSkiaMatrix(), static_cast<SkPath::AddPathMode>(mode));
271         isChanged_ = true;
272     }
273 }
274 
GetBounds() const275 Rect SkiaPath::GetBounds() const
276 {
277     SkRect rect = path_.getBounds();
278     return Rect(rect.left(), rect.top(), rect.right(), rect.bottom());
279 }
280 
SetFillStyle(PathFillType fillstyle)281 void SkiaPath::SetFillStyle(PathFillType fillstyle)
282 {
283     SkPathFillType ft = static_cast<SkPathFillType>(fillstyle);
284     path_.setFillType(ft);
285     isChanged_ = true;
286 }
287 
GetFillStyle() const288 PathFillType SkiaPath::GetFillStyle() const
289 {
290     PathFillType fillType = static_cast<PathFillType>(path_.getFillType());
291     return fillType;
292 }
293 
Interpolate(const Path & ending,scalar weight,Path & out)294 bool SkiaPath::Interpolate(const Path& ending, scalar weight, Path& out)
295 {
296     bool isSuccess = false;
297     auto skPathImpl1 = ending.GetImpl<SkiaPath>();
298     auto skPathImpl2 = out.GetImpl<SkiaPath>();
299     if (skPathImpl1 != nullptr && skPathImpl2 != nullptr) {
300         SkPath interp;
301         isSuccess = path_.interpolate(skPathImpl1->GetPath(), weight, &interp);
302         if (!isSuccess) {
303             return isSuccess;
304         }
305         skPathImpl2->SetPath(interp);
306         isChanged_ = true;
307     }
308     return isSuccess;
309 }
310 
CountVerbs() const311 int SkiaPath::CountVerbs() const
312 {
313     return path_.countVerbs();
314 }
315 
GetPoint(int index) const316 Point SkiaPath::GetPoint(int index) const
317 {
318     SkPoint point = path_.getPoint(index);
319     return Point(point.x(), point.y());
320 }
321 
IsInterpolate(const Path & other)322 bool SkiaPath::IsInterpolate(const Path& other)
323 {
324     bool isSuccess = false;
325     auto skPathImpl = other.GetImpl<SkiaPath>();
326     if (skPathImpl != nullptr) {
327         isSuccess = path_.isInterpolatable(skPathImpl->GetPath());
328     }
329     return isSuccess;
330 }
331 
InitWithInterpolate(const Path & srcPath,const Path & endingPath,scalar weight)332 bool SkiaPath::InitWithInterpolate(const Path& srcPath, const Path& endingPath, scalar weight)
333 {
334     const SkPath& srcSkPath = srcPath.GetImpl<SkiaPath>()->GetPath();
335     isChanged_ = true;
336     return srcSkPath.interpolate(endingPath.GetImpl<SkiaPath>()->GetPath(), weight, &path_);
337 }
338 
Transform(const Matrix & matrix)339 void SkiaPath::Transform(const Matrix& matrix)
340 {
341     auto skMatrixImpl = matrix.GetImpl<SkiaMatrix>();
342     if (skMatrixImpl != nullptr) {
343         path_.transform(skMatrixImpl->ExportSkiaMatrix());
344         isChanged_ = true;
345     }
346 }
347 
TransformWithPerspectiveClip(const Matrix & matrix,Path * dst,bool applyPerspectiveClip)348 void SkiaPath::TransformWithPerspectiveClip(const Matrix& matrix, Path* dst, bool applyPerspectiveClip)
349 {
350     auto skMatrixImpl = matrix.GetImpl<SkiaMatrix>();
351     if (skMatrixImpl == nullptr) {
352         LOGE("SkiaPath::TransformWithPerspectiveClip, skMatrixImpl is nullptr!");
353         return;
354     }
355     if (dst == nullptr) {
356         path_.transform(skMatrixImpl->ExportSkiaMatrix(), nullptr,
357             static_cast<SkApplyPerspectiveClip>(applyPerspectiveClip));
358         return;
359     }
360     auto dstPathImpl = dst->GetImpl<SkiaPath>();
361     if (dstPathImpl == nullptr) {
362         LOGE("SkiaPath::TransformWithPerspectiveClip, dstPathImpl is nullptr!");
363         return;
364     }
365     path_.transform(skMatrixImpl->ExportSkiaMatrix(), &dstPathImpl->path_,
366         static_cast<SkApplyPerspectiveClip>(applyPerspectiveClip));
367     isChanged_ = true;
368 }
369 
Offset(scalar dx,scalar dy)370 void SkiaPath::Offset(scalar dx, scalar dy)
371 {
372     path_.offset(dx, dy);
373     isChanged_ = true;
374 }
375 
Offset(Path * dst,scalar dx,scalar dy)376 void SkiaPath::Offset(Path* dst, scalar dx, scalar dy)
377 {
378     if (dst == nullptr) {
379         path_.offset(dx, dy, nullptr);
380         return;
381     }
382     auto dstPathImpl = dst->GetImpl<SkiaPath>();
383     if (dstPathImpl == nullptr) {
384         LOGE("SkiaPath::Offset, data is invalid!");
385         return;
386     }
387     path_.offset(dx, dy, &dstPathImpl->path_);
388     isChanged_ = true;
389 }
390 
OpWith(const Path & path1,const Path & path2,PathOp op)391 bool SkiaPath::OpWith(const Path& path1, const Path& path2, PathOp op)
392 {
393     SkPathOp pathOp = static_cast<SkPathOp>(op);
394     bool isOpSuccess = false;
395 
396     auto skPathImpl1 = path1.GetImpl<SkiaPath>();
397     auto skPathImpl2 = path2.GetImpl<SkiaPath>();
398     if (skPathImpl1 != nullptr && skPathImpl2 != nullptr) {
399         isOpSuccess = Op(skPathImpl1->GetPath(), skPathImpl2->GetPath(), pathOp, &path_);
400     }
401 
402     isChanged_ = true;
403     if (isOpSuccess) {
404         return true;
405     }
406     return false;
407 }
408 
IsValid() const409 bool SkiaPath::IsValid() const
410 {
411     return !path_.isEmpty();
412 }
413 
Reset()414 void SkiaPath::Reset()
415 {
416     path_.reset();
417     isChanged_ = true;
418 }
419 
SetLastPoint(scalar x,scalar y)420 void SkiaPath::SetLastPoint(scalar x, scalar y)
421 {
422     path_.setLastPt(x, y);
423 }
424 
ReWind()425 void SkiaPath::ReWind()
426 {
427     path_.rewind();
428 }
429 
Close()430 void SkiaPath::Close()
431 {
432     path_.close();
433     isChanged_ = true;
434 }
435 
SetPath(const SkPath & path)436 void SkiaPath::SetPath(const SkPath& path)
437 {
438     path_ = path;
439     isChanged_ = true;
440 }
441 
SetPath(const Path & path)442 void SkiaPath::SetPath(const Path& path)
443 {
444     auto skiaPathImpl = path.GetImpl<SkiaPath>();
445     if (skiaPathImpl == nullptr) {
446         return;
447     }
448     auto skPath = skiaPathImpl->GetPath();
449     path_ = skPath;
450 }
451 
GetPath() const452 const SkPath& SkiaPath::GetPath() const
453 {
454     return path_;
455 }
456 
GetMutablePath()457 SkPath& SkiaPath::GetMutablePath()
458 {
459     isChanged_ = true;
460     return path_;
461 }
462 
PathMeasureUpdate(bool forceClosed)463 void SkiaPath::PathMeasureUpdate(bool forceClosed)
464 {
465     if (pathMeasure_ == nullptr) {
466         pathMeasure_ = std::make_unique<SkPathMeasure>(path_, forceClosed);
467         isChanged_ = false;
468         forceClosed_ = forceClosed;
469         return;
470     }
471 
472     if (isChanged_ || forceClosed != forceClosed_) {
473         pathMeasure_->setPath(&path_, forceClosed);
474         isChanged_ = false;
475         forceClosed_ = forceClosed;
476     }
477 }
478 
GetLength(bool forceClosed)479 scalar SkiaPath::GetLength(bool forceClosed)
480 {
481     PathMeasureUpdate(forceClosed);
482     return pathMeasure_->getLength();
483 }
484 
GetPositionAndTangent(scalar distance,Point & position,Point & tangent,bool forceClosed)485 bool SkiaPath::GetPositionAndTangent(scalar distance, Point& position, Point& tangent, bool forceClosed)
486 {
487     PathMeasureUpdate(forceClosed);
488     bool ret = false;
489     SkPoint skPosition;
490     SkVector skTangent;
491     ret = pathMeasure_->getPosTan(distance, &skPosition, &skTangent);
492     if (ret) {
493         position.SetX(skPosition.x());
494         position.SetY(skPosition.y());
495         tangent.SetX(skTangent.x());
496         tangent.SetY(skTangent.y());
497     }
498 
499     return ret;
500 }
501 
GetSegment(scalar start,scalar stop,Path * dst,bool startWithMoveTo,bool forceClosed)502 bool SkiaPath::GetSegment(scalar start, scalar stop, Path* dst, bool startWithMoveTo, bool forceClosed)
503 {
504     if (dst == nullptr) {
505         return false;
506     }
507     auto skiaPath = dst->GetImpl<SkiaPath>();
508     if (skiaPath == nullptr) {
509         return false;
510     }
511     PathMeasureUpdate(forceClosed);
512     return pathMeasure_->getSegment(start, stop, &skiaPath->GetMutablePath(), startWithMoveTo);
513 }
514 
IsClosed(bool forceClosed)515 bool SkiaPath::IsClosed(bool forceClosed)
516 {
517     PathMeasureUpdate(forceClosed);
518     return pathMeasure_->isClosed();
519 }
520 
IsEmpty()521 bool SkiaPath::IsEmpty()
522 {
523     return path_.isEmpty();
524 }
525 
IsRect(Rect * rect,bool * isClosed,PathDirection * direction)526 bool SkiaPath::IsRect(Rect* rect, bool* isClosed, PathDirection* direction)
527 {
528     SkPathDirection* skDirection = reinterpret_cast<SkPathDirection*>(direction);
529     SkRect* skRect = reinterpret_cast<SkRect*>(rect);
530     return path_.isRect(skRect, isClosed, skDirection);
531 }
532 
GetMatrix(bool forceClosed,float distance,Matrix * matrix,PathMeasureMatrixFlags flag)533 bool SkiaPath::GetMatrix(bool forceClosed, float distance, Matrix* matrix, PathMeasureMatrixFlags flag)
534 {
535     if (matrix == nullptr) {
536         return false;
537     }
538     PathMeasureUpdate(forceClosed);
539     SkPathMeasure::MatrixFlags skFlag = SkPathMeasure::kGetPosAndTan_MatrixFlag;
540     if (flag == PathMeasureMatrixFlags::GET_POSITION_MATRIX) {
541         skFlag = SkPathMeasure::kGetPosition_MatrixFlag;
542     } else if (flag == PathMeasureMatrixFlags::GET_TANGENT_MATRIX) {
543         skFlag = SkPathMeasure::kGetTangent_MatrixFlag;
544     }
545     return pathMeasure_->getMatrix(distance,
546         &matrix->GetImpl<SkiaMatrix>()->ExportMatrix(), skFlag);
547 }
548 
Serialize() const549 std::shared_ptr<Data> SkiaPath::Serialize() const
550 {
551     if (path_.isEmpty()) {
552         LOGD("SkiaPath::Serialize, path is empty!");
553     }
554 #ifdef USE_M133_SKIA
555     SkBinaryWriteBuffer writer({});
556 #else
557     SkBinaryWriteBuffer writer;
558 #endif
559     writer.writePath(path_);
560     size_t length = writer.bytesWritten();
561     std::shared_ptr<Data> data = std::make_shared<Data>();
562     data->BuildUninitialized(length);
563     writer.writeToMemory(data->WritableData());
564     return data;
565 }
566 
Deserialize(std::shared_ptr<Data> data)567 bool SkiaPath::Deserialize(std::shared_ptr<Data> data)
568 {
569     if (data == nullptr) {
570         LOGE("SkiaPath::Deserialize, data is invalid!");
571         return false;
572     }
573 
574     SkReadBuffer reader(data->GetData(), data->GetSize());
575     reader.readPath(&path_);
576     return true;
577 }
578 
579 } // namespace Drawing
580 } // namespace Rosen
581 } // namespace OHOS
582