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#include "flutter/lib/ui/ui_dart_state.h"
12#include "third_party/tonic/converter/dart_converter.h"
13#include "third_party/tonic/dart_args.h"
14#include "third_party/tonic/dart_binding_macros.h"
15#include "third_party/tonic/dart_library_natives.h"
16
17using tonic::ToDart;
18
19namespace flutter {
20
21typedef CanvasPathMeasure PathMeasure;
22
23static void PathMeasure_constructor(Dart_NativeArguments args) {
24 UIDartState::ThrowIfUIOperationsProhibited();
25 DartCallConstructor(&CanvasPathMeasure::Create, args);
26}
27
28IMPLEMENT_WRAPPERTYPEINFO(ui, PathMeasure);
29
30#define FOR_EACH_BINDING(V) \
31 V(PathMeasure, setPath) \
32 V(PathMeasure, getLength) \
33 V(PathMeasure, getPosTan) \
34 V(PathMeasure, getSegment) \
35 V(PathMeasure, isClosed) \
36 V(PathMeasure, nextContour)
37
38FOR_EACH_BINDING(DART_NATIVE_CALLBACK)
39
40void CanvasPathMeasure::RegisterNatives(tonic::DartLibraryNatives* natives) {
41 natives->Register(
42 {{"PathMeasure_constructor", PathMeasure_constructor, 3, true},
43 FOR_EACH_BINDING(DART_REGISTER_NATIVE)});
44}
45
46fml::RefPtr<CanvasPathMeasure> CanvasPathMeasure::Create(const CanvasPath* path,
47 bool forceClosed) {
48 fml::RefPtr<CanvasPathMeasure> pathMeasure =
49 fml::MakeRefCounted<CanvasPathMeasure>();
50 if (path) {
51 const SkPath skPath = path->path();
52 SkScalar resScale = 1;
53 pathMeasure->path_measure_ =
54 std::make_unique<SkContourMeasureIter>(skPath, forceClosed, resScale);
55 } else {
56 pathMeasure->path_measure_ = std::make_unique<SkContourMeasureIter>();
57 }
58 return pathMeasure;
59}
60
61CanvasPathMeasure::CanvasPathMeasure() {}
62
63CanvasPathMeasure::~CanvasPathMeasure() {}
64
65void CanvasPathMeasure::setPath(const CanvasPath* path, bool isClosed) {
66 const SkPath& skPath = path->path();
67 path_measure_->reset(skPath, isClosed);
68}
69
70float CanvasPathMeasure::getLength(int contour_index) {
71 if (static_cast<std::vector<sk_sp<SkContourMeasure>>::size_type>(
72 contour_index) < measures_.size()) {
73 return measures_[contour_index]->length();
74 }
75 return -1;
76}
77
78tonic::Float32List CanvasPathMeasure::getPosTan(int contour_index,
79 float distance) {
80 tonic::Float32List posTan(Dart_NewTypedData(Dart_TypedData_kFloat32, 5));
81 posTan[0] = 0; // dart code will check for this for failure
82 if (static_cast<std::vector<sk_sp<SkContourMeasure>>::size_type>(
83 contour_index) >= measures_.size()) {
84 return posTan;
85 }
86
87 SkPoint pos;
88 SkVector tan;
89 bool success = measures_[contour_index]->getPosTan(distance, &pos, &tan);
90
91 if (success) {
92 posTan[0] = 1; // dart code will check for this for success
93 posTan[1] = pos.x();
94 posTan[2] = pos.y();
95 posTan[3] = tan.x();
96 posTan[4] = tan.y();
97 }
98
99 return posTan;
100}
101
102void CanvasPathMeasure::getSegment(Dart_Handle path_handle,
103 int contour_index,
104 float start_d,
105 float stop_d,
106 bool start_with_move_to) {
107 if (static_cast<std::vector<sk_sp<SkContourMeasure>>::size_type>(
108 contour_index) >= measures_.size()) {
109 CanvasPath::Create(path_handle);
110 }
111 SkPath dst;
112 bool success = measures_[contour_index]->getSegment(start_d, stop_d, &dst,
113 start_with_move_to);
114 if (!success) {
115 CanvasPath::Create(path_handle);
116 } else {
117 CanvasPath::CreateFrom(path_handle, dst);
118 }
119}
120
121bool CanvasPathMeasure::isClosed(int contour_index) {
122 if (static_cast<std::vector<sk_sp<SkContourMeasure>>::size_type>(
123 contour_index) < measures_.size()) {
124 return measures_[contour_index]->isClosed();
125 }
126 return false;
127}
128
129bool CanvasPathMeasure::nextContour() {
130 auto measure = path_measure_->next();
131 if (measure) {
132 measures_.push_back(std::move(measure));
133 return true;
134 }
135 return false;
136}
137
138} // namespace flutter
139