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