1*d57664e9SAndroid Build Coastguard Worker /* libs/android_runtime/android/graphics/Path.cpp
2*d57664e9SAndroid Build Coastguard Worker **
3*d57664e9SAndroid Build Coastguard Worker ** Copyright 2006, The Android Open Source Project
4*d57664e9SAndroid Build Coastguard Worker **
5*d57664e9SAndroid Build Coastguard Worker ** Licensed under the Apache License, Version 2.0 (the "License");
6*d57664e9SAndroid Build Coastguard Worker ** you may not use this file except in compliance with the License.
7*d57664e9SAndroid Build Coastguard Worker ** You may obtain a copy of the License at
8*d57664e9SAndroid Build Coastguard Worker **
9*d57664e9SAndroid Build Coastguard Worker ** http://www.apache.org/licenses/LICENSE-2.0
10*d57664e9SAndroid Build Coastguard Worker **
11*d57664e9SAndroid Build Coastguard Worker ** Unless required by applicable law or agreed to in writing, software
12*d57664e9SAndroid Build Coastguard Worker ** distributed under the License is distributed on an "AS IS" BASIS,
13*d57664e9SAndroid Build Coastguard Worker ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*d57664e9SAndroid Build Coastguard Worker ** See the License for the specific language governing permissions and
15*d57664e9SAndroid Build Coastguard Worker ** limitations under the License.
16*d57664e9SAndroid Build Coastguard Worker */
17*d57664e9SAndroid Build Coastguard Worker
18*d57664e9SAndroid Build Coastguard Worker // This file was generated from the C++ include file: SkPath.h
19*d57664e9SAndroid Build Coastguard Worker // Any changes made to this file will be discarded by the build.
20*d57664e9SAndroid Build Coastguard Worker // To change this file, either edit the include, or device/tools/gluemaker/main.cpp,
21*d57664e9SAndroid Build Coastguard Worker // or one of the auxilary file specifications in device/tools/gluemaker.
22*d57664e9SAndroid Build Coastguard Worker
23*d57664e9SAndroid Build Coastguard Worker #include "GraphicsJNI.h"
24*d57664e9SAndroid Build Coastguard Worker
25*d57664e9SAndroid Build Coastguard Worker #include "SkPath.h"
26*d57664e9SAndroid Build Coastguard Worker #include "SkPathOps.h"
27*d57664e9SAndroid Build Coastguard Worker #include "SkGeometry.h" // WARNING: Internal Skia Header
28*d57664e9SAndroid Build Coastguard Worker
29*d57664e9SAndroid Build Coastguard Worker #include <vector>
30*d57664e9SAndroid Build Coastguard Worker #include <map>
31*d57664e9SAndroid Build Coastguard Worker
32*d57664e9SAndroid Build Coastguard Worker namespace android {
33*d57664e9SAndroid Build Coastguard Worker
34*d57664e9SAndroid Build Coastguard Worker class SkPathGlue {
35*d57664e9SAndroid Build Coastguard Worker public:
36*d57664e9SAndroid Build Coastguard Worker
finalizer(SkPath * obj)37*d57664e9SAndroid Build Coastguard Worker static void finalizer(SkPath* obj) {
38*d57664e9SAndroid Build Coastguard Worker delete obj;
39*d57664e9SAndroid Build Coastguard Worker }
40*d57664e9SAndroid Build Coastguard Worker
41*d57664e9SAndroid Build Coastguard Worker // ---------------- Regular JNI -----------------------------
42*d57664e9SAndroid Build Coastguard Worker
init(JNIEnv * env,jclass clazz)43*d57664e9SAndroid Build Coastguard Worker static jlong init(JNIEnv* env, jclass clazz) {
44*d57664e9SAndroid Build Coastguard Worker return reinterpret_cast<jlong>(new SkPath());
45*d57664e9SAndroid Build Coastguard Worker }
46*d57664e9SAndroid Build Coastguard Worker
init_Path(JNIEnv * env,jclass clazz,jlong valHandle)47*d57664e9SAndroid Build Coastguard Worker static jlong init_Path(JNIEnv* env, jclass clazz, jlong valHandle) {
48*d57664e9SAndroid Build Coastguard Worker SkPath* val = reinterpret_cast<SkPath*>(valHandle);
49*d57664e9SAndroid Build Coastguard Worker return reinterpret_cast<jlong>(new SkPath(*val));
50*d57664e9SAndroid Build Coastguard Worker }
51*d57664e9SAndroid Build Coastguard Worker
getFinalizer(JNIEnv * env,jclass clazz)52*d57664e9SAndroid Build Coastguard Worker static jlong getFinalizer(JNIEnv* env, jclass clazz) {
53*d57664e9SAndroid Build Coastguard Worker return static_cast<jlong>(reinterpret_cast<uintptr_t>(&finalizer));
54*d57664e9SAndroid Build Coastguard Worker }
55*d57664e9SAndroid Build Coastguard Worker
set(JNIEnv * env,jclass clazz,jlong dstHandle,jlong srcHandle)56*d57664e9SAndroid Build Coastguard Worker static void set(JNIEnv* env, jclass clazz, jlong dstHandle, jlong srcHandle) {
57*d57664e9SAndroid Build Coastguard Worker SkPath* dst = reinterpret_cast<SkPath*>(dstHandle);
58*d57664e9SAndroid Build Coastguard Worker const SkPath* src = reinterpret_cast<SkPath*>(srcHandle);
59*d57664e9SAndroid Build Coastguard Worker *dst = *src;
60*d57664e9SAndroid Build Coastguard Worker }
61*d57664e9SAndroid Build Coastguard Worker
computeBounds(JNIEnv * env,jclass clazz,jlong objHandle,jobject jbounds)62*d57664e9SAndroid Build Coastguard Worker static void computeBounds(JNIEnv* env, jclass clazz, jlong objHandle, jobject jbounds) {
63*d57664e9SAndroid Build Coastguard Worker SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
64*d57664e9SAndroid Build Coastguard Worker const SkRect& bounds = obj->getBounds();
65*d57664e9SAndroid Build Coastguard Worker GraphicsJNI::rect_to_jrectf(bounds, env, jbounds);
66*d57664e9SAndroid Build Coastguard Worker }
67*d57664e9SAndroid Build Coastguard Worker
incReserve(JNIEnv * env,jclass clazz,jlong objHandle,jint extraPtCount)68*d57664e9SAndroid Build Coastguard Worker static void incReserve(JNIEnv* env, jclass clazz, jlong objHandle, jint extraPtCount) {
69*d57664e9SAndroid Build Coastguard Worker SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
70*d57664e9SAndroid Build Coastguard Worker obj->incReserve(extraPtCount);
71*d57664e9SAndroid Build Coastguard Worker }
72*d57664e9SAndroid Build Coastguard Worker
moveTo__FF(JNIEnv * env,jclass clazz,jlong objHandle,jfloat x,jfloat y)73*d57664e9SAndroid Build Coastguard Worker static void moveTo__FF(JNIEnv* env, jclass clazz, jlong objHandle, jfloat x, jfloat y) {
74*d57664e9SAndroid Build Coastguard Worker SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
75*d57664e9SAndroid Build Coastguard Worker obj->moveTo(x, y);
76*d57664e9SAndroid Build Coastguard Worker }
77*d57664e9SAndroid Build Coastguard Worker
rMoveTo(JNIEnv * env,jclass clazz,jlong objHandle,jfloat dx,jfloat dy)78*d57664e9SAndroid Build Coastguard Worker static void rMoveTo(JNIEnv* env, jclass clazz, jlong objHandle, jfloat dx, jfloat dy) {
79*d57664e9SAndroid Build Coastguard Worker SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
80*d57664e9SAndroid Build Coastguard Worker obj->rMoveTo(dx, dy);
81*d57664e9SAndroid Build Coastguard Worker }
82*d57664e9SAndroid Build Coastguard Worker
lineTo__FF(JNIEnv * env,jclass clazz,jlong objHandle,jfloat x,jfloat y)83*d57664e9SAndroid Build Coastguard Worker static void lineTo__FF(JNIEnv* env, jclass clazz, jlong objHandle, jfloat x, jfloat y) {
84*d57664e9SAndroid Build Coastguard Worker SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
85*d57664e9SAndroid Build Coastguard Worker obj->lineTo(x, y);
86*d57664e9SAndroid Build Coastguard Worker }
87*d57664e9SAndroid Build Coastguard Worker
rLineTo(JNIEnv * env,jclass clazz,jlong objHandle,jfloat dx,jfloat dy)88*d57664e9SAndroid Build Coastguard Worker static void rLineTo(JNIEnv* env, jclass clazz, jlong objHandle, jfloat dx, jfloat dy) {
89*d57664e9SAndroid Build Coastguard Worker SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
90*d57664e9SAndroid Build Coastguard Worker obj->rLineTo(dx, dy);
91*d57664e9SAndroid Build Coastguard Worker }
92*d57664e9SAndroid Build Coastguard Worker
quadTo__FFFF(JNIEnv * env,jclass clazz,jlong objHandle,jfloat x1,jfloat y1,jfloat x2,jfloat y2)93*d57664e9SAndroid Build Coastguard Worker static void quadTo__FFFF(JNIEnv* env, jclass clazz, jlong objHandle, jfloat x1, jfloat y1,
94*d57664e9SAndroid Build Coastguard Worker jfloat x2, jfloat y2) {
95*d57664e9SAndroid Build Coastguard Worker SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
96*d57664e9SAndroid Build Coastguard Worker obj->quadTo(x1, y1, x2, y2);
97*d57664e9SAndroid Build Coastguard Worker }
98*d57664e9SAndroid Build Coastguard Worker
rQuadTo(JNIEnv * env,jclass clazz,jlong objHandle,jfloat dx1,jfloat dy1,jfloat dx2,jfloat dy2)99*d57664e9SAndroid Build Coastguard Worker static void rQuadTo(JNIEnv* env, jclass clazz, jlong objHandle, jfloat dx1, jfloat dy1,
100*d57664e9SAndroid Build Coastguard Worker jfloat dx2, jfloat dy2) {
101*d57664e9SAndroid Build Coastguard Worker SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
102*d57664e9SAndroid Build Coastguard Worker obj->rQuadTo(dx1, dy1, dx2, dy2);
103*d57664e9SAndroid Build Coastguard Worker }
104*d57664e9SAndroid Build Coastguard Worker
conicTo(JNIEnv * env,jclass clazz,jlong objHandle,jfloat x1,jfloat y1,jfloat x2,jfloat y2,jfloat weight)105*d57664e9SAndroid Build Coastguard Worker static void conicTo(JNIEnv* env, jclass clazz, jlong objHandle, jfloat x1, jfloat y1, jfloat x2,
106*d57664e9SAndroid Build Coastguard Worker jfloat y2, jfloat weight) {
107*d57664e9SAndroid Build Coastguard Worker SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
108*d57664e9SAndroid Build Coastguard Worker obj->conicTo(x1, y1, x2, y2, weight);
109*d57664e9SAndroid Build Coastguard Worker }
110*d57664e9SAndroid Build Coastguard Worker
rConicTo(JNIEnv * env,jclass clazz,jlong objHandle,jfloat dx1,jfloat dy1,jfloat dx2,jfloat dy2,jfloat weight)111*d57664e9SAndroid Build Coastguard Worker static void rConicTo(JNIEnv* env, jclass clazz, jlong objHandle, jfloat dx1, jfloat dy1,
112*d57664e9SAndroid Build Coastguard Worker jfloat dx2, jfloat dy2, jfloat weight) {
113*d57664e9SAndroid Build Coastguard Worker SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
114*d57664e9SAndroid Build Coastguard Worker obj->rConicTo(dx1, dy1, dx2, dy2, weight);
115*d57664e9SAndroid Build Coastguard Worker }
116*d57664e9SAndroid Build Coastguard Worker
cubicTo__FFFFFF(JNIEnv * env,jclass clazz,jlong objHandle,jfloat x1,jfloat y1,jfloat x2,jfloat y2,jfloat x3,jfloat y3)117*d57664e9SAndroid Build Coastguard Worker static void cubicTo__FFFFFF(JNIEnv* env, jclass clazz, jlong objHandle, jfloat x1, jfloat y1,
118*d57664e9SAndroid Build Coastguard Worker jfloat x2, jfloat y2, jfloat x3, jfloat y3) {
119*d57664e9SAndroid Build Coastguard Worker SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
120*d57664e9SAndroid Build Coastguard Worker obj->cubicTo(x1, y1, x2, y2, x3, y3);
121*d57664e9SAndroid Build Coastguard Worker }
122*d57664e9SAndroid Build Coastguard Worker
rCubicTo(JNIEnv * env,jclass clazz,jlong objHandle,jfloat x1,jfloat y1,jfloat x2,jfloat y2,jfloat x3,jfloat y3)123*d57664e9SAndroid Build Coastguard Worker static void rCubicTo(JNIEnv* env, jclass clazz, jlong objHandle, jfloat x1, jfloat y1,
124*d57664e9SAndroid Build Coastguard Worker jfloat x2, jfloat y2, jfloat x3, jfloat y3) {
125*d57664e9SAndroid Build Coastguard Worker SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
126*d57664e9SAndroid Build Coastguard Worker obj->rCubicTo(x1, y1, x2, y2, x3, y3);
127*d57664e9SAndroid Build Coastguard Worker }
128*d57664e9SAndroid Build Coastguard Worker
arcTo(JNIEnv * env,jclass clazz,jlong objHandle,jfloat left,jfloat top,jfloat right,jfloat bottom,jfloat startAngle,jfloat sweepAngle,jboolean forceMoveTo)129*d57664e9SAndroid Build Coastguard Worker static void arcTo(JNIEnv* env, jclass clazz, jlong objHandle, jfloat left, jfloat top,
130*d57664e9SAndroid Build Coastguard Worker jfloat right, jfloat bottom, jfloat startAngle, jfloat sweepAngle,
131*d57664e9SAndroid Build Coastguard Worker jboolean forceMoveTo) {
132*d57664e9SAndroid Build Coastguard Worker SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
133*d57664e9SAndroid Build Coastguard Worker SkRect oval = SkRect::MakeLTRB(left, top, right, bottom);
134*d57664e9SAndroid Build Coastguard Worker obj->arcTo(oval, startAngle, sweepAngle, forceMoveTo);
135*d57664e9SAndroid Build Coastguard Worker }
136*d57664e9SAndroid Build Coastguard Worker
close(JNIEnv * env,jclass clazz,jlong objHandle)137*d57664e9SAndroid Build Coastguard Worker static void close(JNIEnv* env, jclass clazz, jlong objHandle) {
138*d57664e9SAndroid Build Coastguard Worker SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
139*d57664e9SAndroid Build Coastguard Worker obj->close();
140*d57664e9SAndroid Build Coastguard Worker }
141*d57664e9SAndroid Build Coastguard Worker
addRect(JNIEnv * env,jclass clazz,jlong objHandle,jfloat left,jfloat top,jfloat right,jfloat bottom,jint dirHandle)142*d57664e9SAndroid Build Coastguard Worker static void addRect(JNIEnv* env, jclass clazz, jlong objHandle,
143*d57664e9SAndroid Build Coastguard Worker jfloat left, jfloat top, jfloat right, jfloat bottom, jint dirHandle) {
144*d57664e9SAndroid Build Coastguard Worker SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
145*d57664e9SAndroid Build Coastguard Worker SkPathDirection dir = static_cast<SkPathDirection>(dirHandle);
146*d57664e9SAndroid Build Coastguard Worker obj->addRect(left, top, right, bottom, dir);
147*d57664e9SAndroid Build Coastguard Worker }
148*d57664e9SAndroid Build Coastguard Worker
addOval(JNIEnv * env,jclass clazz,jlong objHandle,jfloat left,jfloat top,jfloat right,jfloat bottom,jint dirHandle)149*d57664e9SAndroid Build Coastguard Worker static void addOval(JNIEnv* env, jclass clazz, jlong objHandle,
150*d57664e9SAndroid Build Coastguard Worker jfloat left, jfloat top, jfloat right, jfloat bottom, jint dirHandle) {
151*d57664e9SAndroid Build Coastguard Worker SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
152*d57664e9SAndroid Build Coastguard Worker SkPathDirection dir = static_cast<SkPathDirection>(dirHandle);
153*d57664e9SAndroid Build Coastguard Worker SkRect oval = SkRect::MakeLTRB(left, top, right, bottom);
154*d57664e9SAndroid Build Coastguard Worker obj->addOval(oval, dir);
155*d57664e9SAndroid Build Coastguard Worker }
156*d57664e9SAndroid Build Coastguard Worker
addCircle(JNIEnv * env,jclass clazz,jlong objHandle,jfloat x,jfloat y,jfloat radius,jint dirHandle)157*d57664e9SAndroid Build Coastguard Worker static void addCircle(JNIEnv* env, jclass clazz, jlong objHandle, jfloat x, jfloat y,
158*d57664e9SAndroid Build Coastguard Worker jfloat radius, jint dirHandle) {
159*d57664e9SAndroid Build Coastguard Worker SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
160*d57664e9SAndroid Build Coastguard Worker SkPathDirection dir = static_cast<SkPathDirection>(dirHandle);
161*d57664e9SAndroid Build Coastguard Worker obj->addCircle(x, y, radius, dir);
162*d57664e9SAndroid Build Coastguard Worker }
163*d57664e9SAndroid Build Coastguard Worker
addArc(JNIEnv * env,jclass clazz,jlong objHandle,jfloat left,jfloat top,jfloat right,jfloat bottom,jfloat startAngle,jfloat sweepAngle)164*d57664e9SAndroid Build Coastguard Worker static void addArc(JNIEnv* env, jclass clazz, jlong objHandle, jfloat left, jfloat top,
165*d57664e9SAndroid Build Coastguard Worker jfloat right, jfloat bottom, jfloat startAngle, jfloat sweepAngle) {
166*d57664e9SAndroid Build Coastguard Worker SkRect oval = SkRect::MakeLTRB(left, top, right, bottom);
167*d57664e9SAndroid Build Coastguard Worker SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
168*d57664e9SAndroid Build Coastguard Worker obj->addArc(oval, startAngle, sweepAngle);
169*d57664e9SAndroid Build Coastguard Worker }
170*d57664e9SAndroid Build Coastguard Worker
addRoundRectXY(JNIEnv * env,jclass clazz,jlong objHandle,jfloat left,jfloat top,jfloat right,jfloat bottom,jfloat rx,jfloat ry,jint dirHandle)171*d57664e9SAndroid Build Coastguard Worker static void addRoundRectXY(JNIEnv* env, jclass clazz, jlong objHandle, jfloat left, jfloat top,
172*d57664e9SAndroid Build Coastguard Worker jfloat right, jfloat bottom, jfloat rx, jfloat ry, jint dirHandle) {
173*d57664e9SAndroid Build Coastguard Worker SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
174*d57664e9SAndroid Build Coastguard Worker SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
175*d57664e9SAndroid Build Coastguard Worker SkPathDirection dir = static_cast<SkPathDirection>(dirHandle);
176*d57664e9SAndroid Build Coastguard Worker obj->addRoundRect(rect, rx, ry, dir);
177*d57664e9SAndroid Build Coastguard Worker }
178*d57664e9SAndroid Build Coastguard Worker
addRoundRect8(JNIEnv * env,jclass clazz,jlong objHandle,jfloat left,jfloat top,jfloat right,jfloat bottom,jfloatArray array,jint dirHandle)179*d57664e9SAndroid Build Coastguard Worker static void addRoundRect8(JNIEnv* env, jclass clazz, jlong objHandle, jfloat left, jfloat top,
180*d57664e9SAndroid Build Coastguard Worker jfloat right, jfloat bottom, jfloatArray array, jint dirHandle) {
181*d57664e9SAndroid Build Coastguard Worker SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
182*d57664e9SAndroid Build Coastguard Worker SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
183*d57664e9SAndroid Build Coastguard Worker SkPathDirection dir = static_cast<SkPathDirection>(dirHandle);
184*d57664e9SAndroid Build Coastguard Worker AutoJavaFloatArray afa(env, array, 8);
185*d57664e9SAndroid Build Coastguard Worker const float* src = afa.ptr();
186*d57664e9SAndroid Build Coastguard Worker obj->addRoundRect(rect, src, dir);
187*d57664e9SAndroid Build Coastguard Worker }
188*d57664e9SAndroid Build Coastguard Worker
addPath__PathFF(JNIEnv * env,jclass clazz,jlong objHandle,jlong srcHandle,jfloat dx,jfloat dy)189*d57664e9SAndroid Build Coastguard Worker static void addPath__PathFF(JNIEnv* env, jclass clazz, jlong objHandle, jlong srcHandle,
190*d57664e9SAndroid Build Coastguard Worker jfloat dx, jfloat dy) {
191*d57664e9SAndroid Build Coastguard Worker SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
192*d57664e9SAndroid Build Coastguard Worker SkPath* src = reinterpret_cast<SkPath*>(srcHandle);
193*d57664e9SAndroid Build Coastguard Worker obj->addPath(*src, dx, dy);
194*d57664e9SAndroid Build Coastguard Worker }
195*d57664e9SAndroid Build Coastguard Worker
addPath__Path(JNIEnv * env,jclass clazz,jlong objHandle,jlong srcHandle)196*d57664e9SAndroid Build Coastguard Worker static void addPath__Path(JNIEnv* env, jclass clazz, jlong objHandle, jlong srcHandle) {
197*d57664e9SAndroid Build Coastguard Worker SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
198*d57664e9SAndroid Build Coastguard Worker SkPath* src = reinterpret_cast<SkPath*>(srcHandle);
199*d57664e9SAndroid Build Coastguard Worker obj->addPath(*src);
200*d57664e9SAndroid Build Coastguard Worker }
201*d57664e9SAndroid Build Coastguard Worker
addPath__PathMatrix(JNIEnv * env,jclass clazz,jlong objHandle,jlong srcHandle,jlong matrixHandle)202*d57664e9SAndroid Build Coastguard Worker static void addPath__PathMatrix(JNIEnv* env, jclass clazz, jlong objHandle, jlong srcHandle,
203*d57664e9SAndroid Build Coastguard Worker jlong matrixHandle) {
204*d57664e9SAndroid Build Coastguard Worker SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
205*d57664e9SAndroid Build Coastguard Worker SkPath* src = reinterpret_cast<SkPath*>(srcHandle);
206*d57664e9SAndroid Build Coastguard Worker SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
207*d57664e9SAndroid Build Coastguard Worker obj->addPath(*src, *matrix);
208*d57664e9SAndroid Build Coastguard Worker }
209*d57664e9SAndroid Build Coastguard Worker
offset__FF(JNIEnv * env,jclass clazz,jlong objHandle,jfloat dx,jfloat dy)210*d57664e9SAndroid Build Coastguard Worker static void offset__FF(JNIEnv* env, jclass clazz, jlong objHandle, jfloat dx, jfloat dy) {
211*d57664e9SAndroid Build Coastguard Worker SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
212*d57664e9SAndroid Build Coastguard Worker obj->offset(dx, dy);
213*d57664e9SAndroid Build Coastguard Worker }
214*d57664e9SAndroid Build Coastguard Worker
setLastPoint(JNIEnv * env,jclass clazz,jlong objHandle,jfloat dx,jfloat dy)215*d57664e9SAndroid Build Coastguard Worker static void setLastPoint(JNIEnv* env, jclass clazz, jlong objHandle, jfloat dx, jfloat dy) {
216*d57664e9SAndroid Build Coastguard Worker SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
217*d57664e9SAndroid Build Coastguard Worker obj->setLastPt(dx, dy);
218*d57664e9SAndroid Build Coastguard Worker }
219*d57664e9SAndroid Build Coastguard Worker
interpolate(JNIEnv * env,jclass clazz,jlong startHandle,jlong endHandle,jfloat t,jlong interpolatedHandle)220*d57664e9SAndroid Build Coastguard Worker static jboolean interpolate(JNIEnv* env, jclass clazz, jlong startHandle, jlong endHandle,
221*d57664e9SAndroid Build Coastguard Worker jfloat t, jlong interpolatedHandle) {
222*d57664e9SAndroid Build Coastguard Worker SkPath* startPath = reinterpret_cast<SkPath*>(startHandle);
223*d57664e9SAndroid Build Coastguard Worker SkPath* endPath = reinterpret_cast<SkPath*>(endHandle);
224*d57664e9SAndroid Build Coastguard Worker SkPath* interpolatedPath = reinterpret_cast<SkPath*>(interpolatedHandle);
225*d57664e9SAndroid Build Coastguard Worker return startPath->interpolate(*endPath, t, interpolatedPath);
226*d57664e9SAndroid Build Coastguard Worker }
227*d57664e9SAndroid Build Coastguard Worker
transform__MatrixPath(JNIEnv * env,jclass clazz,jlong objHandle,jlong matrixHandle,jlong dstHandle)228*d57664e9SAndroid Build Coastguard Worker static void transform__MatrixPath(JNIEnv* env, jclass clazz, jlong objHandle, jlong matrixHandle,
229*d57664e9SAndroid Build Coastguard Worker jlong dstHandle) {
230*d57664e9SAndroid Build Coastguard Worker SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
231*d57664e9SAndroid Build Coastguard Worker SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
232*d57664e9SAndroid Build Coastguard Worker SkPath* dst = reinterpret_cast<SkPath*>(dstHandle);
233*d57664e9SAndroid Build Coastguard Worker obj->transform(*matrix, dst);
234*d57664e9SAndroid Build Coastguard Worker }
235*d57664e9SAndroid Build Coastguard Worker
transform__Matrix(JNIEnv * env,jclass clazz,jlong objHandle,jlong matrixHandle)236*d57664e9SAndroid Build Coastguard Worker static void transform__Matrix(JNIEnv* env, jclass clazz, jlong objHandle, jlong matrixHandle) {
237*d57664e9SAndroid Build Coastguard Worker SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
238*d57664e9SAndroid Build Coastguard Worker SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
239*d57664e9SAndroid Build Coastguard Worker obj->transform(*matrix);
240*d57664e9SAndroid Build Coastguard Worker }
241*d57664e9SAndroid Build Coastguard Worker
op(JNIEnv * env,jclass clazz,jlong p1Handle,jlong p2Handle,jint opHandle,jlong rHandle)242*d57664e9SAndroid Build Coastguard Worker static jboolean op(JNIEnv* env, jclass clazz, jlong p1Handle, jlong p2Handle, jint opHandle,
243*d57664e9SAndroid Build Coastguard Worker jlong rHandle) {
244*d57664e9SAndroid Build Coastguard Worker SkPath* p1 = reinterpret_cast<SkPath*>(p1Handle);
245*d57664e9SAndroid Build Coastguard Worker SkPath* p2 = reinterpret_cast<SkPath*>(p2Handle);
246*d57664e9SAndroid Build Coastguard Worker SkPathOp op = static_cast<SkPathOp>(opHandle);
247*d57664e9SAndroid Build Coastguard Worker SkPath* r = reinterpret_cast<SkPath*>(rHandle);
248*d57664e9SAndroid Build Coastguard Worker return Op(*p1, *p2, op, r);
249*d57664e9SAndroid Build Coastguard Worker }
250*d57664e9SAndroid Build Coastguard Worker
251*d57664e9SAndroid Build Coastguard Worker typedef SkPoint (*bezierCalculation)(float t, const SkPoint* points);
252*d57664e9SAndroid Build Coastguard Worker
addMove(std::vector<SkPoint> & segmentPoints,std::vector<float> & lengths,const SkPoint & point)253*d57664e9SAndroid Build Coastguard Worker static void addMove(std::vector<SkPoint>& segmentPoints, std::vector<float>& lengths,
254*d57664e9SAndroid Build Coastguard Worker const SkPoint& point) {
255*d57664e9SAndroid Build Coastguard Worker float length = 0;
256*d57664e9SAndroid Build Coastguard Worker if (!lengths.empty()) {
257*d57664e9SAndroid Build Coastguard Worker length = lengths.back();
258*d57664e9SAndroid Build Coastguard Worker }
259*d57664e9SAndroid Build Coastguard Worker segmentPoints.push_back(point);
260*d57664e9SAndroid Build Coastguard Worker lengths.push_back(length);
261*d57664e9SAndroid Build Coastguard Worker }
262*d57664e9SAndroid Build Coastguard Worker
addLine(std::vector<SkPoint> & segmentPoints,std::vector<float> & lengths,const SkPoint & toPoint)263*d57664e9SAndroid Build Coastguard Worker static void addLine(std::vector<SkPoint>& segmentPoints, std::vector<float>& lengths,
264*d57664e9SAndroid Build Coastguard Worker const SkPoint& toPoint) {
265*d57664e9SAndroid Build Coastguard Worker if (segmentPoints.empty()) {
266*d57664e9SAndroid Build Coastguard Worker segmentPoints.push_back(SkPoint::Make(0, 0));
267*d57664e9SAndroid Build Coastguard Worker lengths.push_back(0);
268*d57664e9SAndroid Build Coastguard Worker } else if (segmentPoints.back() == toPoint) {
269*d57664e9SAndroid Build Coastguard Worker return; // Empty line
270*d57664e9SAndroid Build Coastguard Worker }
271*d57664e9SAndroid Build Coastguard Worker float length = lengths.back() + SkPoint::Distance(segmentPoints.back(), toPoint);
272*d57664e9SAndroid Build Coastguard Worker segmentPoints.push_back(toPoint);
273*d57664e9SAndroid Build Coastguard Worker lengths.push_back(length);
274*d57664e9SAndroid Build Coastguard Worker }
275*d57664e9SAndroid Build Coastguard Worker
cubicCoordinateCalculation(float t,float p0,float p1,float p2,float p3)276*d57664e9SAndroid Build Coastguard Worker static float cubicCoordinateCalculation(float t, float p0, float p1, float p2, float p3) {
277*d57664e9SAndroid Build Coastguard Worker float oneMinusT = 1 - t;
278*d57664e9SAndroid Build Coastguard Worker float oneMinusTSquared = oneMinusT * oneMinusT;
279*d57664e9SAndroid Build Coastguard Worker float oneMinusTCubed = oneMinusTSquared * oneMinusT;
280*d57664e9SAndroid Build Coastguard Worker float tSquared = t * t;
281*d57664e9SAndroid Build Coastguard Worker float tCubed = tSquared * t;
282*d57664e9SAndroid Build Coastguard Worker return (oneMinusTCubed * p0) + (3 * oneMinusTSquared * t * p1)
283*d57664e9SAndroid Build Coastguard Worker + (3 * oneMinusT * tSquared * p2) + (tCubed * p3);
284*d57664e9SAndroid Build Coastguard Worker }
285*d57664e9SAndroid Build Coastguard Worker
cubicBezierCalculation(float t,const SkPoint * points)286*d57664e9SAndroid Build Coastguard Worker static SkPoint cubicBezierCalculation(float t, const SkPoint* points) {
287*d57664e9SAndroid Build Coastguard Worker float x = cubicCoordinateCalculation(t, points[0].x(), points[1].x(),
288*d57664e9SAndroid Build Coastguard Worker points[2].x(), points[3].x());
289*d57664e9SAndroid Build Coastguard Worker float y = cubicCoordinateCalculation(t, points[0].y(), points[1].y(),
290*d57664e9SAndroid Build Coastguard Worker points[2].y(), points[3].y());
291*d57664e9SAndroid Build Coastguard Worker return SkPoint::Make(x, y);
292*d57664e9SAndroid Build Coastguard Worker }
293*d57664e9SAndroid Build Coastguard Worker
quadraticCoordinateCalculation(float t,float p0,float p1,float p2)294*d57664e9SAndroid Build Coastguard Worker static float quadraticCoordinateCalculation(float t, float p0, float p1, float p2) {
295*d57664e9SAndroid Build Coastguard Worker float oneMinusT = 1 - t;
296*d57664e9SAndroid Build Coastguard Worker return oneMinusT * ((oneMinusT * p0) + (t * p1)) + t * ((oneMinusT * p1) + (t * p2));
297*d57664e9SAndroid Build Coastguard Worker }
298*d57664e9SAndroid Build Coastguard Worker
quadraticBezierCalculation(float t,const SkPoint * points)299*d57664e9SAndroid Build Coastguard Worker static SkPoint quadraticBezierCalculation(float t, const SkPoint* points) {
300*d57664e9SAndroid Build Coastguard Worker float x = quadraticCoordinateCalculation(t, points[0].x(), points[1].x(), points[2].x());
301*d57664e9SAndroid Build Coastguard Worker float y = quadraticCoordinateCalculation(t, points[0].y(), points[1].y(), points[2].y());
302*d57664e9SAndroid Build Coastguard Worker return SkPoint::Make(x, y);
303*d57664e9SAndroid Build Coastguard Worker }
304*d57664e9SAndroid Build Coastguard Worker
305*d57664e9SAndroid Build Coastguard Worker // Subdivide a section of the Bezier curve, set the mid-point and the mid-t value.
306*d57664e9SAndroid Build Coastguard Worker // Returns true if further subdivision is necessary as defined by errorSquared.
subdividePoints(const SkPoint * points,bezierCalculation bezierFunction,float t0,const SkPoint & p0,float t1,const SkPoint & p1,float & midT,SkPoint & midPoint,float errorSquared)307*d57664e9SAndroid Build Coastguard Worker static bool subdividePoints(const SkPoint* points, bezierCalculation bezierFunction,
308*d57664e9SAndroid Build Coastguard Worker float t0, const SkPoint &p0, float t1, const SkPoint &p1,
309*d57664e9SAndroid Build Coastguard Worker float& midT, SkPoint &midPoint, float errorSquared) {
310*d57664e9SAndroid Build Coastguard Worker midT = (t1 + t0) / 2;
311*d57664e9SAndroid Build Coastguard Worker float midX = (p1.x() + p0.x()) / 2;
312*d57664e9SAndroid Build Coastguard Worker float midY = (p1.y() + p0.y()) / 2;
313*d57664e9SAndroid Build Coastguard Worker
314*d57664e9SAndroid Build Coastguard Worker midPoint = (*bezierFunction)(midT, points);
315*d57664e9SAndroid Build Coastguard Worker float xError = midPoint.x() - midX;
316*d57664e9SAndroid Build Coastguard Worker float yError = midPoint.y() - midY;
317*d57664e9SAndroid Build Coastguard Worker float midErrorSquared = (xError * xError) + (yError * yError);
318*d57664e9SAndroid Build Coastguard Worker return midErrorSquared > errorSquared;
319*d57664e9SAndroid Build Coastguard Worker }
320*d57664e9SAndroid Build Coastguard Worker
321*d57664e9SAndroid Build Coastguard Worker // Divides Bezier curves until linear interpolation is very close to accurate, using
322*d57664e9SAndroid Build Coastguard Worker // errorSquared as a metric. Cubic Bezier curves can have an inflection point that improperly
323*d57664e9SAndroid Build Coastguard Worker // short-circuit subdivision. If you imagine an S shape, the top and bottom points being the
324*d57664e9SAndroid Build Coastguard Worker // starting and end points, linear interpolation would mark the center where the curve places
325*d57664e9SAndroid Build Coastguard Worker // the point. It is clearly not the case that we can linearly interpolate at that point.
326*d57664e9SAndroid Build Coastguard Worker // doubleCheckDivision forces a second examination between subdivisions to ensure that linear
327*d57664e9SAndroid Build Coastguard Worker // interpolation works.
addBezier(const SkPoint * points,bezierCalculation bezierFunction,std::vector<SkPoint> & segmentPoints,std::vector<float> & lengths,float errorSquared,bool doubleCheckDivision)328*d57664e9SAndroid Build Coastguard Worker static void addBezier(const SkPoint* points,
329*d57664e9SAndroid Build Coastguard Worker bezierCalculation bezierFunction, std::vector<SkPoint>& segmentPoints,
330*d57664e9SAndroid Build Coastguard Worker std::vector<float>& lengths, float errorSquared, bool doubleCheckDivision) {
331*d57664e9SAndroid Build Coastguard Worker typedef std::map<float, SkPoint> PointMap;
332*d57664e9SAndroid Build Coastguard Worker PointMap tToPoint;
333*d57664e9SAndroid Build Coastguard Worker
334*d57664e9SAndroid Build Coastguard Worker tToPoint[0] = (*bezierFunction)(0, points);
335*d57664e9SAndroid Build Coastguard Worker tToPoint[1] = (*bezierFunction)(1, points);
336*d57664e9SAndroid Build Coastguard Worker
337*d57664e9SAndroid Build Coastguard Worker PointMap::iterator iter = tToPoint.begin();
338*d57664e9SAndroid Build Coastguard Worker PointMap::iterator next = iter;
339*d57664e9SAndroid Build Coastguard Worker ++next;
340*d57664e9SAndroid Build Coastguard Worker while (next != tToPoint.end()) {
341*d57664e9SAndroid Build Coastguard Worker bool needsSubdivision = true;
342*d57664e9SAndroid Build Coastguard Worker SkPoint midPoint;
343*d57664e9SAndroid Build Coastguard Worker do {
344*d57664e9SAndroid Build Coastguard Worker float midT;
345*d57664e9SAndroid Build Coastguard Worker needsSubdivision = subdividePoints(points, bezierFunction, iter->first,
346*d57664e9SAndroid Build Coastguard Worker iter->second, next->first, next->second, midT, midPoint, errorSquared);
347*d57664e9SAndroid Build Coastguard Worker if (!needsSubdivision && doubleCheckDivision) {
348*d57664e9SAndroid Build Coastguard Worker SkPoint quarterPoint;
349*d57664e9SAndroid Build Coastguard Worker float quarterT;
350*d57664e9SAndroid Build Coastguard Worker needsSubdivision = subdividePoints(points, bezierFunction, iter->first,
351*d57664e9SAndroid Build Coastguard Worker iter->second, midT, midPoint, quarterT, quarterPoint, errorSquared);
352*d57664e9SAndroid Build Coastguard Worker if (needsSubdivision) {
353*d57664e9SAndroid Build Coastguard Worker // Found an inflection point. No need to double-check.
354*d57664e9SAndroid Build Coastguard Worker doubleCheckDivision = false;
355*d57664e9SAndroid Build Coastguard Worker }
356*d57664e9SAndroid Build Coastguard Worker }
357*d57664e9SAndroid Build Coastguard Worker if (needsSubdivision) {
358*d57664e9SAndroid Build Coastguard Worker next = tToPoint.insert(iter, PointMap::value_type(midT, midPoint));
359*d57664e9SAndroid Build Coastguard Worker }
360*d57664e9SAndroid Build Coastguard Worker } while (needsSubdivision);
361*d57664e9SAndroid Build Coastguard Worker iter = next;
362*d57664e9SAndroid Build Coastguard Worker next++;
363*d57664e9SAndroid Build Coastguard Worker }
364*d57664e9SAndroid Build Coastguard Worker
365*d57664e9SAndroid Build Coastguard Worker // Now that each division can use linear interpolation with less than the allowed error
366*d57664e9SAndroid Build Coastguard Worker for (iter = tToPoint.begin(); iter != tToPoint.end(); ++iter) {
367*d57664e9SAndroid Build Coastguard Worker addLine(segmentPoints, lengths, iter->second);
368*d57664e9SAndroid Build Coastguard Worker }
369*d57664e9SAndroid Build Coastguard Worker }
370*d57664e9SAndroid Build Coastguard Worker
createVerbSegments(const SkPath::Iter & pathIter,SkPath::Verb verb,const SkPoint * points,std::vector<SkPoint> & segmentPoints,std::vector<float> & lengths,float errorSquared,float errorConic)371*d57664e9SAndroid Build Coastguard Worker static void createVerbSegments(const SkPath::Iter& pathIter, SkPath::Verb verb,
372*d57664e9SAndroid Build Coastguard Worker const SkPoint* points, std::vector<SkPoint>& segmentPoints,
373*d57664e9SAndroid Build Coastguard Worker std::vector<float>& lengths, float errorSquared, float errorConic) {
374*d57664e9SAndroid Build Coastguard Worker switch (verb) {
375*d57664e9SAndroid Build Coastguard Worker case SkPath::kMove_Verb:
376*d57664e9SAndroid Build Coastguard Worker addMove(segmentPoints, lengths, points[0]);
377*d57664e9SAndroid Build Coastguard Worker break;
378*d57664e9SAndroid Build Coastguard Worker case SkPath::kClose_Verb:
379*d57664e9SAndroid Build Coastguard Worker addLine(segmentPoints, lengths, points[0]);
380*d57664e9SAndroid Build Coastguard Worker break;
381*d57664e9SAndroid Build Coastguard Worker case SkPath::kLine_Verb:
382*d57664e9SAndroid Build Coastguard Worker addLine(segmentPoints, lengths, points[1]);
383*d57664e9SAndroid Build Coastguard Worker break;
384*d57664e9SAndroid Build Coastguard Worker case SkPath::kQuad_Verb:
385*d57664e9SAndroid Build Coastguard Worker addBezier(points, quadraticBezierCalculation, segmentPoints, lengths,
386*d57664e9SAndroid Build Coastguard Worker errorSquared, false);
387*d57664e9SAndroid Build Coastguard Worker break;
388*d57664e9SAndroid Build Coastguard Worker case SkPath::kCubic_Verb:
389*d57664e9SAndroid Build Coastguard Worker addBezier(points, cubicBezierCalculation, segmentPoints, lengths,
390*d57664e9SAndroid Build Coastguard Worker errorSquared, true);
391*d57664e9SAndroid Build Coastguard Worker break;
392*d57664e9SAndroid Build Coastguard Worker case SkPath::kConic_Verb: {
393*d57664e9SAndroid Build Coastguard Worker SkAutoConicToQuads converter;
394*d57664e9SAndroid Build Coastguard Worker const SkPoint* quads = converter.computeQuads(
395*d57664e9SAndroid Build Coastguard Worker points, pathIter.conicWeight(), errorConic);
396*d57664e9SAndroid Build Coastguard Worker for (int i = 0; i < converter.countQuads(); i++) {
397*d57664e9SAndroid Build Coastguard Worker // Note: offset each subsequent quad by 2, since end points are shared
398*d57664e9SAndroid Build Coastguard Worker const SkPoint* quad = quads + i * 2;
399*d57664e9SAndroid Build Coastguard Worker addBezier(quad, quadraticBezierCalculation, segmentPoints, lengths,
400*d57664e9SAndroid Build Coastguard Worker errorConic, false);
401*d57664e9SAndroid Build Coastguard Worker }
402*d57664e9SAndroid Build Coastguard Worker break;
403*d57664e9SAndroid Build Coastguard Worker }
404*d57664e9SAndroid Build Coastguard Worker default:
405*d57664e9SAndroid Build Coastguard Worker static_assert(SkPath::kMove_Verb == 0
406*d57664e9SAndroid Build Coastguard Worker && SkPath::kLine_Verb == 1
407*d57664e9SAndroid Build Coastguard Worker && SkPath::kQuad_Verb == 2
408*d57664e9SAndroid Build Coastguard Worker && SkPath::kConic_Verb == 3
409*d57664e9SAndroid Build Coastguard Worker && SkPath::kCubic_Verb == 4
410*d57664e9SAndroid Build Coastguard Worker && SkPath::kClose_Verb == 5
411*d57664e9SAndroid Build Coastguard Worker && SkPath::kDone_Verb == 6,
412*d57664e9SAndroid Build Coastguard Worker "Path enum changed, new types may have been added.");
413*d57664e9SAndroid Build Coastguard Worker break;
414*d57664e9SAndroid Build Coastguard Worker }
415*d57664e9SAndroid Build Coastguard Worker }
416*d57664e9SAndroid Build Coastguard Worker
417*d57664e9SAndroid Build Coastguard Worker // Returns a float[] with each point along the path represented by 3 floats
418*d57664e9SAndroid Build Coastguard Worker // * fractional length along the path that the point resides
419*d57664e9SAndroid Build Coastguard Worker // * x coordinate
420*d57664e9SAndroid Build Coastguard Worker // * y coordinate
421*d57664e9SAndroid Build Coastguard Worker // Note that more than one point may have the same length along the path in
422*d57664e9SAndroid Build Coastguard Worker // the case of a move.
423*d57664e9SAndroid Build Coastguard Worker // NULL can be returned if the Path is empty.
approximate(JNIEnv * env,jclass clazz,jlong pathHandle,float acceptableError)424*d57664e9SAndroid Build Coastguard Worker static jfloatArray approximate(JNIEnv* env, jclass clazz, jlong pathHandle,
425*d57664e9SAndroid Build Coastguard Worker float acceptableError) {
426*d57664e9SAndroid Build Coastguard Worker SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
427*d57664e9SAndroid Build Coastguard Worker SkASSERT(path);
428*d57664e9SAndroid Build Coastguard Worker SkPath::Iter pathIter(*path, false);
429*d57664e9SAndroid Build Coastguard Worker SkPath::Verb verb;
430*d57664e9SAndroid Build Coastguard Worker SkPoint points[4];
431*d57664e9SAndroid Build Coastguard Worker std::vector<SkPoint> segmentPoints;
432*d57664e9SAndroid Build Coastguard Worker std::vector<float> lengths;
433*d57664e9SAndroid Build Coastguard Worker float errorSquared = acceptableError * acceptableError;
434*d57664e9SAndroid Build Coastguard Worker float errorConic = acceptableError / 2; // somewhat arbitrary
435*d57664e9SAndroid Build Coastguard Worker
436*d57664e9SAndroid Build Coastguard Worker while ((verb = pathIter.next(points)) != SkPath::kDone_Verb) {
437*d57664e9SAndroid Build Coastguard Worker createVerbSegments(pathIter, verb, points, segmentPoints, lengths,
438*d57664e9SAndroid Build Coastguard Worker errorSquared, errorConic);
439*d57664e9SAndroid Build Coastguard Worker }
440*d57664e9SAndroid Build Coastguard Worker
441*d57664e9SAndroid Build Coastguard Worker if (segmentPoints.empty()) {
442*d57664e9SAndroid Build Coastguard Worker int numVerbs = path->countVerbs();
443*d57664e9SAndroid Build Coastguard Worker if (numVerbs == 1) {
444*d57664e9SAndroid Build Coastguard Worker addMove(segmentPoints, lengths, path->getPoint(0));
445*d57664e9SAndroid Build Coastguard Worker } else {
446*d57664e9SAndroid Build Coastguard Worker // Invalid or empty path. Fall back to point(0,0)
447*d57664e9SAndroid Build Coastguard Worker addMove(segmentPoints, lengths, SkPoint());
448*d57664e9SAndroid Build Coastguard Worker }
449*d57664e9SAndroid Build Coastguard Worker }
450*d57664e9SAndroid Build Coastguard Worker
451*d57664e9SAndroid Build Coastguard Worker float totalLength = lengths.back();
452*d57664e9SAndroid Build Coastguard Worker if (totalLength == 0) {
453*d57664e9SAndroid Build Coastguard Worker // Lone Move instructions should still be able to animate at the same value.
454*d57664e9SAndroid Build Coastguard Worker segmentPoints.push_back(segmentPoints.back());
455*d57664e9SAndroid Build Coastguard Worker lengths.push_back(1);
456*d57664e9SAndroid Build Coastguard Worker totalLength = 1;
457*d57664e9SAndroid Build Coastguard Worker }
458*d57664e9SAndroid Build Coastguard Worker
459*d57664e9SAndroid Build Coastguard Worker size_t numPoints = segmentPoints.size();
460*d57664e9SAndroid Build Coastguard Worker size_t approximationArraySize = numPoints * 3;
461*d57664e9SAndroid Build Coastguard Worker
462*d57664e9SAndroid Build Coastguard Worker float* approximation = new float[approximationArraySize];
463*d57664e9SAndroid Build Coastguard Worker
464*d57664e9SAndroid Build Coastguard Worker int approximationIndex = 0;
465*d57664e9SAndroid Build Coastguard Worker for (size_t i = 0; i < numPoints; i++) {
466*d57664e9SAndroid Build Coastguard Worker const SkPoint& point = segmentPoints[i];
467*d57664e9SAndroid Build Coastguard Worker approximation[approximationIndex++] = lengths[i] / totalLength;
468*d57664e9SAndroid Build Coastguard Worker approximation[approximationIndex++] = point.x();
469*d57664e9SAndroid Build Coastguard Worker approximation[approximationIndex++] = point.y();
470*d57664e9SAndroid Build Coastguard Worker }
471*d57664e9SAndroid Build Coastguard Worker
472*d57664e9SAndroid Build Coastguard Worker jfloatArray result = env->NewFloatArray(approximationArraySize);
473*d57664e9SAndroid Build Coastguard Worker env->SetFloatArrayRegion(result, 0, approximationArraySize, approximation);
474*d57664e9SAndroid Build Coastguard Worker delete[] approximation;
475*d57664e9SAndroid Build Coastguard Worker return result;
476*d57664e9SAndroid Build Coastguard Worker }
477*d57664e9SAndroid Build Coastguard Worker
478*d57664e9SAndroid Build Coastguard Worker // ---------------- @FastNative -----------------------------
479*d57664e9SAndroid Build Coastguard Worker
isRect(JNIEnv * env,jclass clazz,jlong objHandle,jobject jrect)480*d57664e9SAndroid Build Coastguard Worker static jboolean isRect(JNIEnv* env, jclass clazz, jlong objHandle, jobject jrect) {
481*d57664e9SAndroid Build Coastguard Worker SkRect rect;
482*d57664e9SAndroid Build Coastguard Worker SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
483*d57664e9SAndroid Build Coastguard Worker jboolean result = obj->isRect(&rect);
484*d57664e9SAndroid Build Coastguard Worker if (jrect) {
485*d57664e9SAndroid Build Coastguard Worker GraphicsJNI::rect_to_jrectf(rect, env, jrect);
486*d57664e9SAndroid Build Coastguard Worker }
487*d57664e9SAndroid Build Coastguard Worker return result;
488*d57664e9SAndroid Build Coastguard Worker }
489*d57664e9SAndroid Build Coastguard Worker
490*d57664e9SAndroid Build Coastguard Worker // ---------------- @CriticalNative -------------------------
491*d57664e9SAndroid Build Coastguard Worker
getGenerationID(CRITICAL_JNI_PARAMS_COMMA jlong pathHandle)492*d57664e9SAndroid Build Coastguard Worker static jint getGenerationID(CRITICAL_JNI_PARAMS_COMMA jlong pathHandle) {
493*d57664e9SAndroid Build Coastguard Worker return (reinterpret_cast<SkPath*>(pathHandle)->getGenerationID());
494*d57664e9SAndroid Build Coastguard Worker }
495*d57664e9SAndroid Build Coastguard Worker
isInterpolatable(CRITICAL_JNI_PARAMS_COMMA jlong startHandle,jlong endHandle)496*d57664e9SAndroid Build Coastguard Worker static jboolean isInterpolatable(CRITICAL_JNI_PARAMS_COMMA jlong startHandle, jlong endHandle) {
497*d57664e9SAndroid Build Coastguard Worker SkPath* startPath = reinterpret_cast<SkPath*>(startHandle);
498*d57664e9SAndroid Build Coastguard Worker SkPath* endPath = reinterpret_cast<SkPath*>(endHandle);
499*d57664e9SAndroid Build Coastguard Worker return startPath->isInterpolatable(*endPath);
500*d57664e9SAndroid Build Coastguard Worker }
501*d57664e9SAndroid Build Coastguard Worker
reset(CRITICAL_JNI_PARAMS_COMMA jlong objHandle)502*d57664e9SAndroid Build Coastguard Worker static void reset(CRITICAL_JNI_PARAMS_COMMA jlong objHandle) {
503*d57664e9SAndroid Build Coastguard Worker SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
504*d57664e9SAndroid Build Coastguard Worker obj->reset();
505*d57664e9SAndroid Build Coastguard Worker }
506*d57664e9SAndroid Build Coastguard Worker
rewind(CRITICAL_JNI_PARAMS_COMMA jlong objHandle)507*d57664e9SAndroid Build Coastguard Worker static void rewind(CRITICAL_JNI_PARAMS_COMMA jlong objHandle) {
508*d57664e9SAndroid Build Coastguard Worker SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
509*d57664e9SAndroid Build Coastguard Worker obj->rewind();
510*d57664e9SAndroid Build Coastguard Worker }
511*d57664e9SAndroid Build Coastguard Worker
isEmpty(CRITICAL_JNI_PARAMS_COMMA jlong objHandle)512*d57664e9SAndroid Build Coastguard Worker static jboolean isEmpty(CRITICAL_JNI_PARAMS_COMMA jlong objHandle) {
513*d57664e9SAndroid Build Coastguard Worker SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
514*d57664e9SAndroid Build Coastguard Worker return obj->isEmpty();
515*d57664e9SAndroid Build Coastguard Worker }
516*d57664e9SAndroid Build Coastguard Worker
isConvex(CRITICAL_JNI_PARAMS_COMMA jlong objHandle)517*d57664e9SAndroid Build Coastguard Worker static jboolean isConvex(CRITICAL_JNI_PARAMS_COMMA jlong objHandle) {
518*d57664e9SAndroid Build Coastguard Worker SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
519*d57664e9SAndroid Build Coastguard Worker return obj->isConvex();
520*d57664e9SAndroid Build Coastguard Worker }
521*d57664e9SAndroid Build Coastguard Worker
getFillType(CRITICAL_JNI_PARAMS_COMMA jlong objHandle)522*d57664e9SAndroid Build Coastguard Worker static jint getFillType(CRITICAL_JNI_PARAMS_COMMA jlong objHandle) {
523*d57664e9SAndroid Build Coastguard Worker SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
524*d57664e9SAndroid Build Coastguard Worker return static_cast<int>(obj->getFillType());
525*d57664e9SAndroid Build Coastguard Worker }
526*d57664e9SAndroid Build Coastguard Worker
setFillType(CRITICAL_JNI_PARAMS_COMMA jlong pathHandle,jint ftHandle)527*d57664e9SAndroid Build Coastguard Worker static void setFillType(CRITICAL_JNI_PARAMS_COMMA jlong pathHandle, jint ftHandle) {;
528*d57664e9SAndroid Build Coastguard Worker SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
529*d57664e9SAndroid Build Coastguard Worker SkPathFillType ft = static_cast<SkPathFillType>(ftHandle);
530*d57664e9SAndroid Build Coastguard Worker path->setFillType(ft);
531*d57664e9SAndroid Build Coastguard Worker }
532*d57664e9SAndroid Build Coastguard Worker };
533*d57664e9SAndroid Build Coastguard Worker
534*d57664e9SAndroid Build Coastguard Worker static const JNINativeMethod methods[] = {
535*d57664e9SAndroid Build Coastguard Worker {"nInit", "()J", (void*)SkPathGlue::init},
536*d57664e9SAndroid Build Coastguard Worker {"nInit", "(J)J", (void*)SkPathGlue::init_Path},
537*d57664e9SAndroid Build Coastguard Worker {"nGetFinalizer", "()J", (void*)SkPathGlue::getFinalizer},
538*d57664e9SAndroid Build Coastguard Worker {"nSet", "(JJ)V", (void*)SkPathGlue::set},
539*d57664e9SAndroid Build Coastguard Worker {"nComputeBounds", "(JLandroid/graphics/RectF;)V", (void*)SkPathGlue::computeBounds},
540*d57664e9SAndroid Build Coastguard Worker {"nIncReserve", "(JI)V", (void*)SkPathGlue::incReserve},
541*d57664e9SAndroid Build Coastguard Worker {"nMoveTo", "(JFF)V", (void*)SkPathGlue::moveTo__FF},
542*d57664e9SAndroid Build Coastguard Worker {"nRMoveTo", "(JFF)V", (void*)SkPathGlue::rMoveTo},
543*d57664e9SAndroid Build Coastguard Worker {"nLineTo", "(JFF)V", (void*)SkPathGlue::lineTo__FF},
544*d57664e9SAndroid Build Coastguard Worker {"nRLineTo", "(JFF)V", (void*)SkPathGlue::rLineTo},
545*d57664e9SAndroid Build Coastguard Worker {"nQuadTo", "(JFFFF)V", (void*)SkPathGlue::quadTo__FFFF},
546*d57664e9SAndroid Build Coastguard Worker {"nRQuadTo", "(JFFFF)V", (void*)SkPathGlue::rQuadTo},
547*d57664e9SAndroid Build Coastguard Worker {"nConicTo", "(JFFFFF)V", (void*)SkPathGlue::conicTo},
548*d57664e9SAndroid Build Coastguard Worker {"nRConicTo", "(JFFFFF)V", (void*)SkPathGlue::rConicTo},
549*d57664e9SAndroid Build Coastguard Worker {"nCubicTo", "(JFFFFFF)V", (void*)SkPathGlue::cubicTo__FFFFFF},
550*d57664e9SAndroid Build Coastguard Worker {"nRCubicTo", "(JFFFFFF)V", (void*)SkPathGlue::rCubicTo},
551*d57664e9SAndroid Build Coastguard Worker {"nArcTo", "(JFFFFFFZ)V", (void*)SkPathGlue::arcTo},
552*d57664e9SAndroid Build Coastguard Worker {"nClose", "(J)V", (void*)SkPathGlue::close},
553*d57664e9SAndroid Build Coastguard Worker {"nAddRect", "(JFFFFI)V", (void*)SkPathGlue::addRect},
554*d57664e9SAndroid Build Coastguard Worker {"nAddOval", "(JFFFFI)V", (void*)SkPathGlue::addOval},
555*d57664e9SAndroid Build Coastguard Worker {"nAddCircle", "(JFFFI)V", (void*)SkPathGlue::addCircle},
556*d57664e9SAndroid Build Coastguard Worker {"nAddArc", "(JFFFFFF)V", (void*)SkPathGlue::addArc},
557*d57664e9SAndroid Build Coastguard Worker {"nAddRoundRect", "(JFFFFFFI)V", (void*)SkPathGlue::addRoundRectXY},
558*d57664e9SAndroid Build Coastguard Worker {"nAddRoundRect", "(JFFFF[FI)V", (void*)SkPathGlue::addRoundRect8},
559*d57664e9SAndroid Build Coastguard Worker {"nAddPath", "(JJFF)V", (void*)SkPathGlue::addPath__PathFF},
560*d57664e9SAndroid Build Coastguard Worker {"nAddPath", "(JJ)V", (void*)SkPathGlue::addPath__Path},
561*d57664e9SAndroid Build Coastguard Worker {"nAddPath", "(JJJ)V", (void*)SkPathGlue::addPath__PathMatrix},
562*d57664e9SAndroid Build Coastguard Worker {"nInterpolate", "(JJFJ)Z", (void*)SkPathGlue::interpolate},
563*d57664e9SAndroid Build Coastguard Worker {"nOffset", "(JFF)V", (void*)SkPathGlue::offset__FF},
564*d57664e9SAndroid Build Coastguard Worker {"nSetLastPoint", "(JFF)V", (void*)SkPathGlue::setLastPoint},
565*d57664e9SAndroid Build Coastguard Worker {"nTransform", "(JJJ)V", (void*)SkPathGlue::transform__MatrixPath},
566*d57664e9SAndroid Build Coastguard Worker {"nTransform", "(JJ)V", (void*)SkPathGlue::transform__Matrix},
567*d57664e9SAndroid Build Coastguard Worker {"nOp", "(JJIJ)Z", (void*)SkPathGlue::op},
568*d57664e9SAndroid Build Coastguard Worker {"nApproximate", "(JF)[F", (void*)SkPathGlue::approximate},
569*d57664e9SAndroid Build Coastguard Worker
570*d57664e9SAndroid Build Coastguard Worker // ------- @FastNative below here ----------------------
571*d57664e9SAndroid Build Coastguard Worker {"nIsRect", "(JLandroid/graphics/RectF;)Z", (void*)SkPathGlue::isRect},
572*d57664e9SAndroid Build Coastguard Worker
573*d57664e9SAndroid Build Coastguard Worker // ------- @CriticalNative below here ------------------
574*d57664e9SAndroid Build Coastguard Worker {"nGetGenerationID", "(J)I", (void*)SkPathGlue::getGenerationID},
575*d57664e9SAndroid Build Coastguard Worker {"nIsInterpolatable", "(JJ)Z", (void*)SkPathGlue::isInterpolatable},
576*d57664e9SAndroid Build Coastguard Worker {"nReset", "(J)V", (void*)SkPathGlue::reset},
577*d57664e9SAndroid Build Coastguard Worker {"nRewind", "(J)V", (void*)SkPathGlue::rewind},
578*d57664e9SAndroid Build Coastguard Worker {"nIsEmpty", "(J)Z", (void*)SkPathGlue::isEmpty},
579*d57664e9SAndroid Build Coastguard Worker {"nIsConvex", "(J)Z", (void*)SkPathGlue::isConvex},
580*d57664e9SAndroid Build Coastguard Worker {"nGetFillType", "(J)I", (void*)SkPathGlue::getFillType},
581*d57664e9SAndroid Build Coastguard Worker {"nSetFillType", "(JI)V", (void*)SkPathGlue::setFillType},
582*d57664e9SAndroid Build Coastguard Worker };
583*d57664e9SAndroid Build Coastguard Worker
register_android_graphics_Path(JNIEnv * env)584*d57664e9SAndroid Build Coastguard Worker int register_android_graphics_Path(JNIEnv* env) {
585*d57664e9SAndroid Build Coastguard Worker return RegisterMethodsOrDie(env, "android/graphics/Path", methods, NELEM(methods));
586*d57664e9SAndroid Build Coastguard Worker
587*d57664e9SAndroid Build Coastguard Worker static_assert(0 == (int)SkPathDirection::kCW, "direction_mismatch");
588*d57664e9SAndroid Build Coastguard Worker static_assert(1 == (int)SkPathDirection::kCCW, "direction_mismatch");
589*d57664e9SAndroid Build Coastguard Worker }
590*d57664e9SAndroid Build Coastguard Worker
591*d57664e9SAndroid Build Coastguard Worker }
592