1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "flutter/lib/ui/painting/path_measure.h"
6
7 #define _USE_MATH_DEFINES
8 #include <math.h>
9
10 #include "flutter/lib/ui/painting/matrix.h"
11
12 using tonic::ToDart;
13
14 namespace flutter {
15
16 typedef CanvasPathMeasure PathMeasure;
17
PathMeasure_constructor(Dart_NativeArguments args)18 static void PathMeasure_constructor(Dart_NativeArguments args) {
19 DartCallConstructor(&CanvasPathMeasure::Create, args);
20 }
21
22 IMPLEMENT_WRAPPERTYPEINFO(ui, PathMeasure);
23
24 #define FOR_EACH_BINDING(V) \
25 V(PathMeasure, setPath) \
26 V(PathMeasure, getLength) \
27 V(PathMeasure, getPosTan) \
28 V(PathMeasure, getSegment) \
29 V(PathMeasure, isClosed) \
30 V(PathMeasure, nextContour)
31
FOR_EACH_BINDING(DART_NATIVE_CALLBACK)32 FOR_EACH_BINDING(DART_NATIVE_CALLBACK)
33
34 void CanvasPathMeasure::RegisterNatives(tonic::DartLibraryNatives* natives) {
35 natives->Register(
36 {{"PathMeasure_constructor", PathMeasure_constructor, 3, true},
37 FOR_EACH_BINDING(DART_REGISTER_NATIVE)});
38 }
39
Create(const CanvasPath * path,bool forceClosed)40 fml::RefPtr<CanvasPathMeasure> CanvasPathMeasure::Create(const CanvasPath* path,
41 bool forceClosed) {
42 fml::RefPtr<CanvasPathMeasure> pathMeasure =
43 fml::MakeRefCounted<CanvasPathMeasure>();
44 if (path) {
45 const SkPath skPath = path->path();
46 SkScalar resScale = 1;
47 pathMeasure->path_measure_ =
48 std::make_unique<SkContourMeasureIter>(skPath, forceClosed, resScale);
49 } else {
50 pathMeasure->path_measure_ = std::make_unique<SkContourMeasureIter>();
51 }
52 return pathMeasure;
53 }
54
CanvasPathMeasure()55 CanvasPathMeasure::CanvasPathMeasure() {}
56
~CanvasPathMeasure()57 CanvasPathMeasure::~CanvasPathMeasure() {}
58
setPath(const CanvasPath * path,bool isClosed)59 void CanvasPathMeasure::setPath(const CanvasPath* path, bool isClosed) {
60 const SkPath& skPath = path->path();
61 path_measure_->reset(skPath, isClosed);
62 }
63
getLength(int contourIndex)64 float CanvasPathMeasure::getLength(int contourIndex) {
65 if (static_cast<std::vector<sk_sp<SkContourMeasure>>::size_type>(
66 contourIndex) < measures_.size()) {
67 return measures_[contourIndex]->length();
68 }
69 return -1;
70 }
71
getPosTan(int contourIndex,float distance)72 tonic::Float32List CanvasPathMeasure::getPosTan(int contourIndex,
73 float distance) {
74 tonic::Float32List posTan(Dart_NewTypedData(Dart_TypedData_kFloat32, 5));
75 posTan[0] = 0; // dart code will check for this for failure
76 if (static_cast<std::vector<sk_sp<SkContourMeasure>>::size_type>(
77 contourIndex) >= measures_.size()) {
78 return posTan;
79 }
80
81 SkPoint pos;
82 SkVector tan;
83 bool success = measures_[contourIndex]->getPosTan(distance, &pos, &tan);
84
85 if (success) {
86 posTan[0] = 1; // dart code will check for this for success
87 posTan[1] = pos.x();
88 posTan[2] = pos.y();
89 posTan[3] = tan.x();
90 posTan[4] = tan.y();
91 }
92
93 return posTan;
94 }
95
getSegment(int contourIndex,float startD,float stopD,bool startWithMoveTo)96 fml::RefPtr<CanvasPath> CanvasPathMeasure::getSegment(int contourIndex,
97 float startD,
98 float stopD,
99 bool startWithMoveTo) {
100 if (static_cast<std::vector<sk_sp<SkContourMeasure>>::size_type>(
101 contourIndex) >= measures_.size()) {
102 return CanvasPath::Create();
103 }
104 SkPath dst;
105 bool success =
106 measures_[contourIndex]->getSegment(startD, stopD, &dst, startWithMoveTo);
107 if (!success) {
108 return CanvasPath::Create();
109 } else {
110 return CanvasPath::CreateFrom(dst);
111 }
112 }
113
isClosed(int contourIndex)114 bool CanvasPathMeasure::isClosed(int contourIndex) {
115 if (static_cast<std::vector<sk_sp<SkContourMeasure>>::size_type>(
116 contourIndex) < measures_.size()) {
117 return measures_[contourIndex]->isClosed();
118 }
119 return false;
120 }
121
nextContour()122 bool CanvasPathMeasure::nextContour() {
123 auto measure = path_measure_->next();
124 if (measure) {
125 measures_.push_back(std::move(measure));
126 return true;
127 }
128 return false;
129 }
130
131 } // namespace flutter
132