blob: 7a8c5c8a7b36da225c598d99f76f24dbcf131dd6 [file] [log] [blame]
Derek Sollenberger8872b382014-06-23 14:13:53 -04001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "jni.h"
18#include "GraphicsJNI.h"
Andreas Gampeed6b9df2014-11-20 22:02:20 -080019#include "core_jni_helpers.h"
Derek Sollenberger8872b382014-06-23 14:13:53 -040020
Mike Reed322bc572018-03-20 13:37:04 -040021#include <android/api-level.h>
Derek Sollenberger4c5efe92015-07-10 13:56:39 -040022#include <androidfw/ResourceTypes.h>
sergeyvdccca442016-03-21 15:38:21 -070023#include <hwui/Canvas.h>
24#include <hwui/Paint.h>
Ben Wagner0ed10be2018-06-28 17:08:16 -040025#include <hwui/PaintFilter.h>
sergeyvbad99182016-03-17 11:24:22 -070026#include <hwui/Typeface.h>
sergeyvdccca442016-03-21 15:38:21 -070027#include <minikin/Layout.h>
Seigo Nonaka3a4217f2018-05-02 12:56:16 -070028#include <nativehelper/ScopedPrimitiveArray.h>
29#include <nativehelper/ScopedStringChars.h>
Derek Sollenberger4c5efe92015-07-10 13:56:39 -040030
31#include "Bitmap.h"
Derek Sollenberger8872b382014-06-23 14:13:53 -040032#include "SkGraphics.h"
Mike Reed3318f8b2017-02-13 16:14:10 -050033#include "SkRegion.h"
Mike Reed826deef2017-04-04 15:32:04 -040034#include "SkVertices.h"
Derek Sollenberger8872b382014-06-23 14:13:53 -040035
Seigo Nonaka783f9612018-01-20 12:11:13 -080036namespace minikin {
37class MeasuredText;
38} // namespace minikin
39
Derek Sollenberger8872b382014-06-23 14:13:53 -040040namespace android {
41
42namespace CanvasJNI {
43
44static Canvas* get_canvas(jlong canvasHandle) {
45 return reinterpret_cast<Canvas*>(canvasHandle);
46}
47
Richard Uhler775873a2015-12-29 12:37:39 -080048static void delete_canvas(Canvas* canvas) {
49 delete canvas;
50}
51
52static jlong getNativeFinalizer(JNIEnv* env, jobject clazz) {
53 return static_cast<jlong>(reinterpret_cast<uintptr_t>(&delete_canvas));
Derek Sollenberger8872b382014-06-23 14:13:53 -040054}
55
56// Native wrapper constructor used by Canvas(Bitmap)
Leon Scroggins III71fae622019-03-26 16:28:41 -040057static jlong initRaster(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reck3731dc22015-04-13 15:20:29 -070058 SkBitmap bitmap;
Leon Scroggins III71fae622019-03-26 16:28:41 -040059 if (bitmapHandle != 0) {
60 bitmap::toBitmap(bitmapHandle).getSkBitmap(&bitmap);
John Reckc1b33d62015-04-22 09:04:45 -070061 }
John Reck3731dc22015-04-13 15:20:29 -070062 return reinterpret_cast<jlong>(Canvas::create_canvas(bitmap));
Derek Sollenberger8872b382014-06-23 14:13:53 -040063}
64
65// Set the given bitmap as the new draw target (wrapped in a new SkCanvas),
66// optionally copying canvas matrix & clip state.
Leon Scroggins III71fae622019-03-26 16:28:41 -040067static void setBitmap(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle) {
John Reck3731dc22015-04-13 15:20:29 -070068 SkBitmap bitmap;
Leon Scroggins III71fae622019-03-26 16:28:41 -040069 if (bitmapHandle != 0) {
70 bitmap::toBitmap(bitmapHandle).getSkBitmap(&bitmap);
John Reckc1b33d62015-04-22 09:04:45 -070071 }
John Reck3731dc22015-04-13 15:20:29 -070072 get_canvas(canvasHandle)->setBitmap(bitmap);
Derek Sollenberger8872b382014-06-23 14:13:53 -040073}
74
Chris Craikbfa0b292017-01-19 19:12:36 -080075static jboolean isOpaque(jlong canvasHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -040076 return get_canvas(canvasHandle)->isOpaque() ? JNI_TRUE : JNI_FALSE;
77}
78
Chris Craikbfa0b292017-01-19 19:12:36 -080079static jint getWidth(jlong canvasHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -040080 return static_cast<jint>(get_canvas(canvasHandle)->width());
81}
82
Chris Craikbfa0b292017-01-19 19:12:36 -080083static jint getHeight(jlong canvasHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -040084 return static_cast<jint>(get_canvas(canvasHandle)->height());
85}
86
Chris Craikbfa0b292017-01-19 19:12:36 -080087static jint save(jlong canvasHandle, jint flagsHandle) {
Florin Malitaeecff562015-12-21 10:43:01 -050088 SaveFlags::Flags flags = static_cast<SaveFlags::Flags>(flagsHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -040089 return static_cast<jint>(get_canvas(canvasHandle)->save(flags));
90}
91
Chris Craikbfa0b292017-01-19 19:12:36 -080092static jint saveLayer(jlong canvasHandle, jfloat l, jfloat t,
Derek Sollenberger8872b382014-06-23 14:13:53 -040093 jfloat r, jfloat b, jlong paintHandle, jint flagsHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -040094 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Florin Malitaeecff562015-12-21 10:43:01 -050095 SaveFlags::Flags flags = static_cast<SaveFlags::Flags>(flagsHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -040096 return static_cast<jint>(get_canvas(canvasHandle)->saveLayer(l, t, r, b, paint, flags));
97}
98
Chris Craikbfa0b292017-01-19 19:12:36 -080099static jint saveLayerAlpha(jlong canvasHandle, jfloat l, jfloat t,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400100 jfloat r, jfloat b, jint alpha, jint flagsHandle) {
Florin Malitaeecff562015-12-21 10:43:01 -0500101 SaveFlags::Flags flags = static_cast<SaveFlags::Flags>(flagsHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400102 return static_cast<jint>(get_canvas(canvasHandle)->saveLayerAlpha(l, t, r, b, alpha, flags));
103}
104
Derek Sollenberger24fc9012018-12-07 14:12:12 -0500105static jint saveUnclippedLayer(jlong canvasHandle, jint l, jint t, jint r, jint b) {
106 return reinterpret_cast<jint>(get_canvas(canvasHandle)->saveUnclippedLayer(l, t, r, b));
107}
108
Chris Craikbfa0b292017-01-19 19:12:36 -0800109static bool restore(jlong canvasHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400110 Canvas* canvas = get_canvas(canvasHandle);
Chris Craikbfa0b292017-01-19 19:12:36 -0800111 if (canvas->getSaveCount() <= 1) {
112 return false; // cannot restore anymore
Derek Sollenberger8872b382014-06-23 14:13:53 -0400113 }
114 canvas->restore();
Chris Craikbfa0b292017-01-19 19:12:36 -0800115 return true; // success
Derek Sollenberger8872b382014-06-23 14:13:53 -0400116}
117
Chris Craikbfa0b292017-01-19 19:12:36 -0800118static void restoreToCount(jlong canvasHandle, jint saveCount) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400119 Canvas* canvas = get_canvas(canvasHandle);
Chris Craikbfa0b292017-01-19 19:12:36 -0800120 canvas->restoreToCount(saveCount);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400121}
122
Chris Craikbfa0b292017-01-19 19:12:36 -0800123static jint getSaveCount(jlong canvasHandle) {
124 return static_cast<jint>(get_canvas(canvasHandle)->getSaveCount());
125}
126
127static void getMatrix(jlong canvasHandle, jlong matrixHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400128 SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
129 get_canvas(canvasHandle)->getMatrix(matrix);
130}
131
Chris Craikbfa0b292017-01-19 19:12:36 -0800132static void setMatrix(jlong canvasHandle, jlong matrixHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400133 const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
134 get_canvas(canvasHandle)->setMatrix(matrix ? *matrix : SkMatrix::I());
135}
136
Chris Craikbfa0b292017-01-19 19:12:36 -0800137static void concat(jlong canvasHandle, jlong matrixHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400138 const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
139 get_canvas(canvasHandle)->concat(*matrix);
140}
141
Chris Craikbfa0b292017-01-19 19:12:36 -0800142static void rotate(jlong canvasHandle, jfloat degrees) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400143 get_canvas(canvasHandle)->rotate(degrees);
144}
145
Chris Craikbfa0b292017-01-19 19:12:36 -0800146static void scale(jlong canvasHandle, jfloat sx, jfloat sy) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400147 get_canvas(canvasHandle)->scale(sx, sy);
148}
149
Chris Craikbfa0b292017-01-19 19:12:36 -0800150static void skew(jlong canvasHandle, jfloat sx, jfloat sy) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400151 get_canvas(canvasHandle)->skew(sx, sy);
152}
153
Chris Craikbfa0b292017-01-19 19:12:36 -0800154static void translate(jlong canvasHandle, jfloat dx, jfloat dy) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400155 get_canvas(canvasHandle)->translate(dx, dy);
156}
157
158static jboolean getClipBounds(JNIEnv* env, jobject, jlong canvasHandle, jobject bounds) {
159 SkRect r;
160 SkIRect ir;
161 bool result = get_canvas(canvasHandle)->getClipBounds(&r);
162
163 if (!result) {
164 r.setEmpty();
165 }
166 r.round(&ir);
167
168 (void)GraphicsJNI::irect_to_jrect(ir, env, bounds);
169 return result ? JNI_TRUE : JNI_FALSE;
170}
171
Chris Craikbfa0b292017-01-19 19:12:36 -0800172static jboolean quickRejectRect(jlong canvasHandle,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400173 jfloat left, jfloat top, jfloat right, jfloat bottom) {
174 bool result = get_canvas(canvasHandle)->quickRejectRect(left, top, right, bottom);
175 return result ? JNI_TRUE : JNI_FALSE;
176}
177
Chris Craikbfa0b292017-01-19 19:12:36 -0800178static jboolean quickRejectPath(jlong canvasHandle, jlong pathHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400179 SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
180 bool result = get_canvas(canvasHandle)->quickRejectPath(*path);
181 return result ? JNI_TRUE : JNI_FALSE;
182}
183
Mike Reed6e49c9f2016-12-02 15:36:59 -0500184// SkRegion::Op and SkClipOp are numerically identical, so we can freely cast
185// from one to the other (though SkClipOp is destined to become a strict subset)
Mike Reed6c67f1d2016-12-14 10:29:54 -0500186static_assert(SkRegion::kDifference_Op == static_cast<SkRegion::Op>(SkClipOp::kDifference), "");
187static_assert(SkRegion::kIntersect_Op == static_cast<SkRegion::Op>(SkClipOp::kIntersect), "");
Mike Reeda0a74d52017-03-13 13:26:00 -0400188static_assert(SkRegion::kUnion_Op == static_cast<SkRegion::Op>(SkClipOp::kUnion_deprecated), "");
189static_assert(SkRegion::kXOR_Op == static_cast<SkRegion::Op>(SkClipOp::kXOR_deprecated), "");
190static_assert(SkRegion::kReverseDifference_Op == static_cast<SkRegion::Op>(SkClipOp::kReverseDifference_deprecated), "");
191static_assert(SkRegion::kReplace_Op == static_cast<SkRegion::Op>(SkClipOp::kReplace_deprecated), "");
Mike Reed6e49c9f2016-12-02 15:36:59 -0500192
193static SkClipOp opHandleToClipOp(jint opHandle) {
194 // The opHandle is defined in Canvas.java to be Region::Op
195 SkRegion::Op rgnOp = static_cast<SkRegion::Op>(opHandle);
196
197 // In the future, when we no longer support the wide range of ops (e.g. Union, Xor)
198 // this function can perform a range check and throw an unsupported-exception.
199 // e.g. if (rgnOp != kIntersect && rgnOp != kDifference) throw...
200
201 // Skia now takes a different type, SkClipOp, as the parameter to clipping calls
202 // This type is binary compatible with SkRegion::Op, so a static_cast<> is safe.
203 return static_cast<SkClipOp>(rgnOp);
204}
205
Chris Craikbfa0b292017-01-19 19:12:36 -0800206static jboolean clipRect(jlong canvasHandle, jfloat l, jfloat t,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400207 jfloat r, jfloat b, jint opHandle) {
Mike Reed6e49c9f2016-12-02 15:36:59 -0500208 bool nonEmptyClip = get_canvas(canvasHandle)->clipRect(l, t, r, b,
209 opHandleToClipOp(opHandle));
Chris Craik5ec6a282015-06-23 15:42:12 -0700210 return nonEmptyClip ? JNI_TRUE : JNI_FALSE;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400211}
212
Chris Craikbfa0b292017-01-19 19:12:36 -0800213static jboolean clipPath(jlong canvasHandle, jlong pathHandle,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400214 jint opHandle) {
215 SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
Mike Reed6e49c9f2016-12-02 15:36:59 -0500216 bool nonEmptyClip = get_canvas(canvasHandle)->clipPath(path, opHandleToClipOp(opHandle));
Chris Craik5ec6a282015-06-23 15:42:12 -0700217 return nonEmptyClip ? JNI_TRUE : JNI_FALSE;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400218}
219
Derek Sollenberger8872b382014-06-23 14:13:53 -0400220static void drawColor(JNIEnv* env, jobject, jlong canvasHandle, jint color, jint modeHandle) {
Mike Reed260ab722016-10-07 15:59:20 -0400221 SkBlendMode mode = static_cast<SkBlendMode>(modeHandle);
Chris Craik1526a452015-03-06 18:42:15 +0000222 get_canvas(canvasHandle)->drawColor(color, mode);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400223}
224
Leon Scroggins IIIbee5e202019-01-11 13:36:39 -0500225static void drawColorLong(JNIEnv* env, jobject, jlong canvasHandle, jlong colorSpaceHandle,
226 jlong colorLong, jint modeHandle) {
227 SkColor4f color = GraphicsJNI::convertColorLong(colorLong);
228 sk_sp<SkColorSpace> cs = GraphicsJNI::getNativeColorSpace(colorSpaceHandle);
229 SkPaint p;
230 p.setColor4f(color, cs.get());
231
232 SkBlendMode mode = static_cast<SkBlendMode>(modeHandle);
233 p.setBlendMode(mode);
234 get_canvas(canvasHandle)->drawPaint(p);
235}
236
Derek Sollenberger8872b382014-06-23 14:13:53 -0400237static void drawPaint(JNIEnv* env, jobject, jlong canvasHandle, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400238 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400239 get_canvas(canvasHandle)->drawPaint(*paint);
240}
241
242static void drawPoint(JNIEnv*, jobject, jlong canvasHandle, jfloat x, jfloat y,
243 jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400244 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400245 get_canvas(canvasHandle)->drawPoint(x, y, *paint);
246}
247
248static void drawPoints(JNIEnv* env, jobject, jlong canvasHandle, jfloatArray jptsArray,
249 jint offset, jint count, jlong paintHandle) {
250 NPE_CHECK_RETURN_VOID(env, jptsArray);
251 AutoJavaFloatArray autoPts(env, jptsArray);
252 float* floats = autoPts.ptr();
253 const int length = autoPts.length();
254
255 if ((offset | count) < 0 || offset + count > length) {
256 doThrowAIOOBE(env);
257 return;
258 }
259
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400260 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400261 get_canvas(canvasHandle)->drawPoints(floats + offset, count, *paint);
262}
263
264static void drawLine(JNIEnv* env, jobject, jlong canvasHandle, jfloat startX, jfloat startY,
265 jfloat stopX, jfloat stopY, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400266 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400267 get_canvas(canvasHandle)->drawLine(startX, startY, stopX, stopY, *paint);
268}
269
270static void drawLines(JNIEnv* env, jobject, jlong canvasHandle, jfloatArray jptsArray,
271 jint offset, jint count, jlong paintHandle) {
272 NPE_CHECK_RETURN_VOID(env, jptsArray);
273 AutoJavaFloatArray autoPts(env, jptsArray);
274 float* floats = autoPts.ptr();
275 const int length = autoPts.length();
276
277 if ((offset | count) < 0 || offset + count > length) {
278 doThrowAIOOBE(env);
279 return;
280 }
281
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400282 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400283 get_canvas(canvasHandle)->drawLines(floats + offset, count, *paint);
284}
285
286static void drawRect(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
287 jfloat right, jfloat bottom, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400288 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400289 get_canvas(canvasHandle)->drawRect(left, top, right, bottom, *paint);
290}
291
Nader Jawadadfe1d92018-09-27 12:27:36 -0700292static void drawDoubleRoundRectXY(JNIEnv* env, jobject, jlong canvasHandle, jfloat outerLeft,
293 jfloat outerTop, jfloat outerRight, jfloat outerBottom, jfloat outerRx,
294 jfloat outerRy, jfloat innerLeft, jfloat innerTop, jfloat innerRight,
295 jfloat innerBottom, jfloat innerRx, jfloat innerRy, jlong paintHandle) {
296 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
297 get_canvas(canvasHandle)->drawDoubleRoundRectXY(
298 outerLeft, outerTop, outerRight, outerBottom, outerRx, outerRy,
299 innerLeft, innerTop, innerRight, innerBottom, innerRx, innerRy, *paint);
300}
301
302static void drawDoubleRoundRectRadii(JNIEnv* env, jobject, jlong canvasHandle, jfloat outerLeft,
303 jfloat outerTop, jfloat outerRight, jfloat outerBottom, jfloatArray jouterRadii,
304 jfloat innerLeft, jfloat innerTop, jfloat innerRight,
305 jfloat innerBottom, jfloatArray jinnerRadii, jlong paintHandle) {
306 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
307
308 float outerRadii[8];
309 float innerRadii[8];
310 env->GetFloatArrayRegion(jouterRadii, 0, 8, outerRadii);
311 env->GetFloatArrayRegion(jinnerRadii, 0, 8, innerRadii);
312 get_canvas(canvasHandle)->drawDoubleRoundRectRadii(
313 outerLeft, outerTop, outerRight, outerBottom, outerRadii,
314 innerLeft, innerTop, innerRight, innerBottom, innerRadii, *paint);
315
316}
317
Derek Sollenberger94394b32015-07-10 09:58:41 -0400318static void drawRegion(JNIEnv* env, jobject, jlong canvasHandle, jlong regionHandle,
319 jlong paintHandle) {
320 const SkRegion* region = reinterpret_cast<SkRegion*>(regionHandle);
321 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
322 get_canvas(canvasHandle)->drawRegion(*region, *paint);
323}
324
Derek Sollenberger8872b382014-06-23 14:13:53 -0400325static void drawRoundRect(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
326 jfloat right, jfloat bottom, jfloat rx, jfloat ry, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400327 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400328 get_canvas(canvasHandle)->drawRoundRect(left, top, right, bottom, rx, ry, *paint);
329}
330
331static void drawCircle(JNIEnv* env, jobject, jlong canvasHandle, jfloat cx, jfloat cy,
332 jfloat radius, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400333 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400334 get_canvas(canvasHandle)->drawCircle(cx, cy, radius, *paint);
335}
336
337static void drawOval(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
338 jfloat right, jfloat bottom, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400339 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400340 get_canvas(canvasHandle)->drawOval(left, top, right, bottom, *paint);
341}
342
343static void drawArc(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
344 jfloat right, jfloat bottom, jfloat startAngle, jfloat sweepAngle,
345 jboolean useCenter, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400346 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400347 get_canvas(canvasHandle)->drawArc(left, top, right, bottom, startAngle, sweepAngle,
348 useCenter, *paint);
349}
350
351static void drawPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle,
352 jlong paintHandle) {
353 const SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400354 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400355 get_canvas(canvasHandle)->drawPath(*path, *paint);
356}
357
358static void drawVertices(JNIEnv* env, jobject, jlong canvasHandle,
Mike Reed826deef2017-04-04 15:32:04 -0400359 jint modeHandle, jint floatCount,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400360 jfloatArray jverts, jint vertIndex,
361 jfloatArray jtexs, jint texIndex,
362 jintArray jcolors, jint colorIndex,
363 jshortArray jindices, jint indexIndex,
364 jint indexCount, jlong paintHandle) {
John Reckd51e9942018-08-01 13:34:37 -0700365
366 const int vertexCount = floatCount >> 1; // 2 floats per SkPoint
367
Mike Reed826deef2017-04-04 15:32:04 -0400368 AutoJavaFloatArray vertA(env, jverts, vertIndex + floatCount);
369 AutoJavaFloatArray texA(env, jtexs, texIndex + floatCount);
John Reckd51e9942018-08-01 13:34:37 -0700370 AutoJavaIntArray colorA(env, jcolors, colorIndex + vertexCount);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400371 AutoJavaShortArray indexA(env, jindices, indexIndex + indexCount);
372
373 const float* verts = vertA.ptr() + vertIndex;
374 const float* texs = texA.ptr() + vertIndex;
375 const int* colors = NULL;
376 const uint16_t* indices = NULL;
377
378 if (jcolors != NULL) {
379 colors = colorA.ptr() + colorIndex;
380 }
381 if (jindices != NULL) {
382 indices = (const uint16_t*)(indexA.ptr() + indexIndex);
383 }
384
Mike Reed826deef2017-04-04 15:32:04 -0400385 SkVertices::VertexMode mode = static_cast<SkVertices::VertexMode>(modeHandle);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400386 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Mike Reed826deef2017-04-04 15:32:04 -0400387 get_canvas(canvasHandle)->drawVertices(SkVertices::MakeCopy(mode, vertexCount,
388 reinterpret_cast<const SkPoint*>(verts),
389 reinterpret_cast<const SkPoint*>(texs),
390 reinterpret_cast<const SkColor*>(colors),
391 indexCount, indices).get(),
392 SkBlendMode::kModulate, *paint);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400393}
394
Derek Sollenberger4c5efe92015-07-10 13:56:39 -0400395static void drawNinePatch(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle,
396 jlong chunkHandle, jfloat left, jfloat top, jfloat right, jfloat bottom,
397 jlong paintHandle, jint dstDensity, jint srcDensity) {
398
399 Canvas* canvas = get_canvas(canvasHandle);
Leon Scroggins III71fae622019-03-26 16:28:41 -0400400 Bitmap& bitmap = android::bitmap::toBitmap(bitmapHandle);
Derek Sollenberger4c5efe92015-07-10 13:56:39 -0400401 const android::Res_png_9patch* chunk = reinterpret_cast<android::Res_png_9patch*>(chunkHandle);
402 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
403
404 if (CC_LIKELY(dstDensity == srcDensity || dstDensity == 0 || srcDensity == 0)) {
sergeyv5fd2a1c2016-10-20 15:04:28 -0700405 canvas->drawNinePatch(bitmap, *chunk, left, top, right, bottom, paint);
Derek Sollenberger4c5efe92015-07-10 13:56:39 -0400406 } else {
Florin Malitaeecff562015-12-21 10:43:01 -0500407 canvas->save(SaveFlags::MatrixClip);
Derek Sollenberger4c5efe92015-07-10 13:56:39 -0400408
409 SkScalar scale = dstDensity / (float)srcDensity;
410 canvas->translate(left, top);
411 canvas->scale(scale, scale);
412
413 Paint filteredPaint;
414 if (paint) {
415 filteredPaint = *paint;
416 }
417 filteredPaint.setFilterQuality(kLow_SkFilterQuality);
418
sergeyv5fd2a1c2016-10-20 15:04:28 -0700419 canvas->drawNinePatch(bitmap, *chunk, 0, 0, (right-left)/scale, (bottom-top)/scale,
Derek Sollenberger4c5efe92015-07-10 13:56:39 -0400420 &filteredPaint);
421
422 canvas->restore();
423 }
424}
425
Leon Scroggins III71fae622019-03-26 16:28:41 -0400426static void drawBitmap(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400427 jfloat left, jfloat top, jlong paintHandle, jint canvasDensity,
428 jint screenDensity, jint bitmapDensity) {
429 Canvas* canvas = get_canvas(canvasHandle);
Leon Scroggins III71fae622019-03-26 16:28:41 -0400430 Bitmap& bitmap = android::bitmap::toBitmap(bitmapHandle);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400431 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400432
433 if (canvasDensity == bitmapDensity || canvasDensity == 0 || bitmapDensity == 0) {
434 if (screenDensity != 0 && screenDensity != bitmapDensity) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400435 Paint filteredPaint;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400436 if (paint) {
437 filteredPaint = *paint;
438 }
Mike Reed2a1ce8a2015-03-16 11:16:09 -0400439 filteredPaint.setFilterQuality(kLow_SkFilterQuality);
John Reck7c103a32015-04-15 15:52:10 -0700440 canvas->drawBitmap(bitmap, left, top, &filteredPaint);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400441 } else {
John Reck7c103a32015-04-15 15:52:10 -0700442 canvas->drawBitmap(bitmap, left, top, paint);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400443 }
444 } else {
Florin Malitaeecff562015-12-21 10:43:01 -0500445 canvas->save(SaveFlags::MatrixClip);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400446 SkScalar scale = canvasDensity / (float)bitmapDensity;
447 canvas->translate(left, top);
448 canvas->scale(scale, scale);
449
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400450 Paint filteredPaint;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400451 if (paint) {
452 filteredPaint = *paint;
453 }
Mike Reed2a1ce8a2015-03-16 11:16:09 -0400454 filteredPaint.setFilterQuality(kLow_SkFilterQuality);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400455
John Reck7c103a32015-04-15 15:52:10 -0700456 canvas->drawBitmap(bitmap, 0, 0, &filteredPaint);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400457 canvas->restore();
458 }
459}
460
Leon Scroggins III71fae622019-03-26 16:28:41 -0400461static void drawBitmapMatrix(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400462 jlong matrixHandle, jlong paintHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400463 const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400464 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Leon Scroggins III71fae622019-03-26 16:28:41 -0400465 Bitmap& bitmap = android::bitmap::toBitmap(bitmapHandle);
John Reck7c103a32015-04-15 15:52:10 -0700466 get_canvas(canvasHandle)->drawBitmap(bitmap, *matrix, paint);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400467}
468
Leon Scroggins III71fae622019-03-26 16:28:41 -0400469static void drawBitmapRect(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400470 float srcLeft, float srcTop, float srcRight, float srcBottom,
471 float dstLeft, float dstTop, float dstRight, float dstBottom,
472 jlong paintHandle, jint screenDensity, jint bitmapDensity) {
473 Canvas* canvas = get_canvas(canvasHandle);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400474 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400475
Leon Scroggins III71fae622019-03-26 16:28:41 -0400476 Bitmap& bitmap = android::bitmap::toBitmap(bitmapHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400477 if (screenDensity != 0 && screenDensity != bitmapDensity) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400478 Paint filteredPaint;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400479 if (paint) {
480 filteredPaint = *paint;
481 }
Mike Reed2a1ce8a2015-03-16 11:16:09 -0400482 filteredPaint.setFilterQuality(kLow_SkFilterQuality);
John Reck7c103a32015-04-15 15:52:10 -0700483 canvas->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400484 dstLeft, dstTop, dstRight, dstBottom, &filteredPaint);
485 } else {
John Reck7c103a32015-04-15 15:52:10 -0700486 canvas->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400487 dstLeft, dstTop, dstRight, dstBottom, paint);
488 }
489}
490
491static void drawBitmapArray(JNIEnv* env, jobject, jlong canvasHandle,
492 jintArray jcolors, jint offset, jint stride,
493 jfloat x, jfloat y, jint width, jint height,
494 jboolean hasAlpha, jlong paintHandle) {
495 // Note: If hasAlpha is false, kRGB_565_SkColorType will be used, which will
496 // correct the alphaType to kOpaque_SkAlphaType.
John Recke9048f32018-03-30 13:44:35 -0700497 SkImageInfo info = SkImageInfo::Make(width, height,
498 hasAlpha ? kN32_SkColorType : kRGB_565_SkColorType,
499 kPremul_SkAlphaType);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400500 SkBitmap bitmap;
Derek Sollenberger3d4eed72014-12-04 15:20:29 -0500501 bitmap.setInfo(info);
Leon Scroggins IIIf51a80d2017-07-12 10:46:35 -0400502 sk_sp<Bitmap> androidBitmap = Bitmap::allocateHeapBitmap(&bitmap);
sergeyvc1c54062016-10-19 18:47:26 -0700503 if (!androidBitmap) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400504 return;
505 }
506
Brian Osman91c9c282018-08-17 16:57:15 -0400507 if (!GraphicsJNI::SetPixels(env, jcolors, offset, stride, 0, 0, width, height, &bitmap)) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400508 return;
509 }
510
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400511 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
sergeyvaed7f582016-10-14 16:30:21 -0700512 get_canvas(canvasHandle)->drawBitmap(*androidBitmap, x, y, paint);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400513}
514
Leon Scroggins III71fae622019-03-26 16:28:41 -0400515static void drawBitmapMesh(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400516 jint meshWidth, jint meshHeight, jfloatArray jverts,
517 jint vertIndex, jintArray jcolors, jint colorIndex, jlong paintHandle) {
Mike Reed322bc572018-03-20 13:37:04 -0400518 if (Canvas::GetApiLevel() < __ANDROID_API_P__) {
519 // Before P we forgot to respect these. Now that we do respect them, explicitly
520 // zero them for backward compatibility.
521 vertIndex = 0;
522 colorIndex = 0;
523 }
524
Derek Sollenberger8872b382014-06-23 14:13:53 -0400525 const int ptCount = (meshWidth + 1) * (meshHeight + 1);
526 AutoJavaFloatArray vertA(env, jverts, vertIndex + (ptCount << 1));
527 AutoJavaIntArray colorA(env, jcolors, colorIndex + ptCount);
528
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400529 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Leon Scroggins III71fae622019-03-26 16:28:41 -0400530 Bitmap& bitmap = android::bitmap::toBitmap(bitmapHandle);
John Reck7c103a32015-04-15 15:52:10 -0700531 get_canvas(canvasHandle)->drawBitmapMesh(bitmap, meshWidth, meshHeight,
Mike Reed322bc572018-03-20 13:37:04 -0400532 vertA.ptr() + vertIndex*2,
533 colorA.ptr() + colorIndex, paint);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400534}
535
Seigo Nonaka3a4217f2018-05-02 12:56:16 -0700536static void drawTextChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray charArray,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400537 jint index, jint count, jfloat x, jfloat y, jint bidiFlags,
Seigo Nonaka318ca042017-08-01 16:36:18 -0700538 jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400539 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Seigo Nonaka318ca042017-08-01 16:36:18 -0700540 const Typeface* typeface = paint->getAndroidTypeface();
Seigo Nonaka3a4217f2018-05-02 12:56:16 -0700541 ScopedCharArrayRO text(env, charArray);
Seigo Nonakaf307adc2018-10-19 19:10:02 -0700542 // drawTextString and drawTextChars doesn't use context info
Seigo Nonaka3a4217f2018-05-02 12:56:16 -0700543 get_canvas(canvasHandle)->drawText(
Seigo Nonakaf307adc2018-10-19 19:10:02 -0700544 text.get() + index, count, // text buffer
545 0, count, // draw range
546 0, count, // context range
Seigo Nonaka3a4217f2018-05-02 12:56:16 -0700547 x, y, // draw position
548 static_cast<minikin::Bidi>(bidiFlags), *paint, typeface, nullptr /* measured text */);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400549}
550
Seigo Nonaka3a4217f2018-05-02 12:56:16 -0700551static void drawTextString(JNIEnv* env, jobject, jlong canvasHandle, jstring strObj,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400552 jint start, jint end, jfloat x, jfloat y, jint bidiFlags,
Seigo Nonaka318ca042017-08-01 16:36:18 -0700553 jlong paintHandle) {
Seigo Nonaka3a4217f2018-05-02 12:56:16 -0700554 ScopedStringChars text(env, strObj);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400555 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Seigo Nonaka318ca042017-08-01 16:36:18 -0700556 const Typeface* typeface = paint->getAndroidTypeface();
Seigo Nonakaf307adc2018-10-19 19:10:02 -0700557 const int count = end - start;
558 // drawTextString and drawTextChars doesn't use context info
Seigo Nonaka3a4217f2018-05-02 12:56:16 -0700559 get_canvas(canvasHandle)->drawText(
Seigo Nonakaf307adc2018-10-19 19:10:02 -0700560 text.get() + start, count, // text buffer
561 0, count, // draw range
562 0, count, // context range
Seigo Nonaka3a4217f2018-05-02 12:56:16 -0700563 x, y, // draw position
564 static_cast<minikin::Bidi>(bidiFlags), *paint, typeface, nullptr /* measured text */);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400565}
566
Seigo Nonaka3a4217f2018-05-02 12:56:16 -0700567static void drawTextRunChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray charArray,
568 jint index, jint count, jint contextIndex, jint contextCount,
569 jfloat x, jfloat y, jboolean isRtl, jlong paintHandle,
570 jlong mtHandle) {
Seigo Nonaka783f9612018-01-20 12:11:13 -0800571 minikin::MeasuredText* mt = reinterpret_cast<minikin::MeasuredText*>(mtHandle);
Seigo Nonaka7c93e862017-10-25 16:34:48 -0700572 const minikin::Bidi bidiFlags = isRtl ? minikin::Bidi::FORCE_RTL : minikin::Bidi::FORCE_LTR;
Seigo Nonaka3a4217f2018-05-02 12:56:16 -0700573
574 ScopedCharArrayRO text(env, charArray);
575 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
576 const Typeface* typeface = paint->getAndroidTypeface();
577 get_canvas(canvasHandle)->drawText(
578 text.get(), text.size(), // text buffer
579 index, count, // draw range
580 contextIndex, contextCount, // context range,
581 x, y, // draw position
582 bidiFlags, *paint, typeface, mt);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400583}
584
Seigo Nonaka3a4217f2018-05-02 12:56:16 -0700585static void drawTextRunString(JNIEnv* env, jobject obj, jlong canvasHandle, jstring strObj,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400586 jint start, jint end, jint contextStart, jint contextEnd,
Seigo Nonaka318ca042017-08-01 16:36:18 -0700587 jfloat x, jfloat y, jboolean isRtl, jlong paintHandle) {
Seigo Nonaka3a4217f2018-05-02 12:56:16 -0700588 const minikin::Bidi bidiFlags = isRtl ? minikin::Bidi::FORCE_RTL : minikin::Bidi::FORCE_LTR;
589
590 ScopedStringChars text(env, strObj);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400591 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Seigo Nonaka318ca042017-08-01 16:36:18 -0700592 const Typeface* typeface = paint->getAndroidTypeface();
Seigo Nonaka3a4217f2018-05-02 12:56:16 -0700593 get_canvas(canvasHandle)->drawText(
594 text.get(), text.size(), // text buffer
595 start, end - start, // draw range
596 contextStart, contextEnd - contextStart, // context range
597 x, y, // draw position
598 bidiFlags, *paint, typeface, nullptr /* measured text */);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400599}
600
Derek Sollenberger8872b382014-06-23 14:13:53 -0400601static void drawTextOnPathChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text,
602 jint index, jint count, jlong pathHandle, jfloat hOffset,
Seigo Nonaka318ca042017-08-01 16:36:18 -0700603 jfloat vOffset, jint bidiFlags, jlong paintHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400604 SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400605 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Seigo Nonaka318ca042017-08-01 16:36:18 -0700606 const Typeface* typeface = paint->getAndroidTypeface();
Derek Sollenberger8872b382014-06-23 14:13:53 -0400607
608 jchar* jchars = env->GetCharArrayElements(text, NULL);
609
Seigo Nonaka7c93e862017-10-25 16:34:48 -0700610 get_canvas(canvasHandle)->drawTextOnPath(jchars + index, count,
611 static_cast<minikin::Bidi>(bidiFlags), *path, hOffset, vOffset, *paint, typeface);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400612
613 env->ReleaseCharArrayElements(text, jchars, 0);
614}
615
616static void drawTextOnPathString(JNIEnv* env, jobject, jlong canvasHandle, jstring text,
617 jlong pathHandle, jfloat hOffset, jfloat vOffset,
Seigo Nonaka318ca042017-08-01 16:36:18 -0700618 jint bidiFlags, jlong paintHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400619 SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400620 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Seigo Nonaka318ca042017-08-01 16:36:18 -0700621 const Typeface* typeface = paint->getAndroidTypeface();
Derek Sollenberger8872b382014-06-23 14:13:53 -0400622
623 const jchar* jchars = env->GetStringChars(text, NULL);
624 int count = env->GetStringLength(text);
625
Seigo Nonaka7c93e862017-10-25 16:34:48 -0700626 get_canvas(canvasHandle)->drawTextOnPath(jchars, count, static_cast<minikin::Bidi>(bidiFlags),
627 *path, hOffset, vOffset, *paint, typeface);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400628
629 env->ReleaseStringChars(text, jchars);
630}
631
Ben Wagner0ed10be2018-06-28 17:08:16 -0400632static void setPaintFilter(jlong canvasHandle, jlong filterHandle) {
633 PaintFilter* paintFilter = reinterpret_cast<PaintFilter*>(filterHandle);
634 get_canvas(canvasHandle)->setPaintFilter(sk_ref_sp(paintFilter));
Derek Sollenberger8872b382014-06-23 14:13:53 -0400635}
636
637static void freeCaches(JNIEnv* env, jobject) {
638 SkGraphics::PurgeFontCache();
639}
640
641static void freeTextLayoutCaches(JNIEnv* env, jobject) {
Seigo Nonakaae1aa852016-06-09 19:42:51 +0900642 minikin::Layout::purgeCaches();
Derek Sollenberger8872b382014-06-23 14:13:53 -0400643}
644
Stan Iliev7717e222018-02-05 18:04:11 -0500645static void setCompatibilityVersion(JNIEnv* env, jobject, jint apiLevel) {
646 Canvas::setCompatibilityVersion(apiLevel);
647}
648
649
Derek Sollenberger8872b382014-06-23 14:13:53 -0400650}; // namespace CanvasJNI
651
Daniel Micay76f6a862015-09-19 17:31:01 -0400652static const JNINativeMethod gMethods[] = {
John Reckcaa08ff2016-10-07 13:21:36 -0700653 {"nGetNativeFinalizer", "()J", (void*) CanvasJNI::getNativeFinalizer},
John Reckcaa08ff2016-10-07 13:21:36 -0700654 {"nFreeCaches", "()V", (void*) CanvasJNI::freeCaches},
655 {"nFreeTextLayoutCaches", "()V", (void*) CanvasJNI::freeTextLayoutCaches},
Stan Iliev7717e222018-02-05 18:04:11 -0500656 {"nSetCompatibilityVersion", "(I)V", (void*) CanvasJNI::setCompatibilityVersion},
John Reck5cb74bc2016-10-07 11:24:44 -0700657
658 // ------------ @FastNative ----------------
Leon Scroggins III71fae622019-03-26 16:28:41 -0400659 {"nInitRaster", "(J)J", (void*) CanvasJNI::initRaster},
660 {"nSetBitmap", "(JJ)V", (void*) CanvasJNI::setBitmap},
Chris Craikbfa0b292017-01-19 19:12:36 -0800661 {"nGetClipBounds","(JLandroid/graphics/Rect;)Z", (void*) CanvasJNI::getClipBounds},
662
663 // ------------ @CriticalNative ----------------
John Reckcaa08ff2016-10-07 13:21:36 -0700664 {"nIsOpaque","(J)Z", (void*) CanvasJNI::isOpaque},
665 {"nGetWidth","(J)I", (void*) CanvasJNI::getWidth},
666 {"nGetHeight","(J)I", (void*) CanvasJNI::getHeight},
John Reckcaa08ff2016-10-07 13:21:36 -0700667 {"nSave","(JI)I", (void*) CanvasJNI::save},
668 {"nSaveLayer","(JFFFFJI)I", (void*) CanvasJNI::saveLayer},
669 {"nSaveLayerAlpha","(JFFFFII)I", (void*) CanvasJNI::saveLayerAlpha},
Derek Sollenberger24fc9012018-12-07 14:12:12 -0500670 {"nSaveUnclippedLayer","(JIIII)I", (void*) CanvasJNI::saveUnclippedLayer},
John Reckcaa08ff2016-10-07 13:21:36 -0700671 {"nGetSaveCount","(J)I", (void*) CanvasJNI::getSaveCount},
Chris Craikbfa0b292017-01-19 19:12:36 -0800672 {"nRestore","(J)Z", (void*) CanvasJNI::restore},
673 {"nRestoreToCount","(JI)V", (void*) CanvasJNI::restoreToCount},
674 {"nGetMatrix", "(JJ)V", (void*)CanvasJNI::getMatrix},
John Reckcaa08ff2016-10-07 13:21:36 -0700675 {"nSetMatrix","(JJ)V", (void*) CanvasJNI::setMatrix},
676 {"nConcat","(JJ)V", (void*) CanvasJNI::concat},
677 {"nRotate","(JF)V", (void*) CanvasJNI::rotate},
678 {"nScale","(JFF)V", (void*) CanvasJNI::scale},
679 {"nSkew","(JFF)V", (void*) CanvasJNI::skew},
680 {"nTranslate","(JFF)V", (void*) CanvasJNI::translate},
John Reckcaa08ff2016-10-07 13:21:36 -0700681 {"nQuickReject","(JJ)Z", (void*) CanvasJNI::quickRejectPath},
682 {"nQuickReject","(JFFFF)Z", (void*)CanvasJNI::quickRejectRect},
683 {"nClipRect","(JFFFFI)Z", (void*) CanvasJNI::clipRect},
684 {"nClipPath","(JJI)Z", (void*) CanvasJNI::clipPath},
Ben Wagner0ed10be2018-06-28 17:08:16 -0400685 {"nSetDrawFilter", "(JJ)V", (void*) CanvasJNI::setPaintFilter},
John Reckcaa08ff2016-10-07 13:21:36 -0700686};
687
688// If called from Canvas these are regular JNI
689// If called from DisplayListCanvas they are @FastNative
690static const JNINativeMethod gDrawMethods[] = {
691 {"nDrawColor","(JII)V", (void*) CanvasJNI::drawColor},
Leon Scroggins IIIbee5e202019-01-11 13:36:39 -0500692 {"nDrawColor","(JJJI)V", (void*) CanvasJNI::drawColorLong},
John Reckcaa08ff2016-10-07 13:21:36 -0700693 {"nDrawPaint","(JJ)V", (void*) CanvasJNI::drawPaint},
694 {"nDrawPoint", "(JFFJ)V", (void*) CanvasJNI::drawPoint},
695 {"nDrawPoints", "(J[FIIJ)V", (void*) CanvasJNI::drawPoints},
696 {"nDrawLine", "(JFFFFJ)V", (void*) CanvasJNI::drawLine},
697 {"nDrawLines", "(J[FIIJ)V", (void*) CanvasJNI::drawLines},
698 {"nDrawRect","(JFFFFJ)V", (void*) CanvasJNI::drawRect},
699 {"nDrawRegion", "(JJJ)V", (void*) CanvasJNI::drawRegion },
700 {"nDrawRoundRect","(JFFFFFFJ)V", (void*) CanvasJNI::drawRoundRect},
Nader Jawadadfe1d92018-09-27 12:27:36 -0700701 {"nDrawDoubleRoundRect", "(JFFFFFFFFFFFFJ)V", (void*) CanvasJNI::drawDoubleRoundRectXY},
702 {"nDrawDoubleRoundRect", "(JFFFF[FFFFF[FJ)V", (void*) CanvasJNI::drawDoubleRoundRectRadii},
John Reckcaa08ff2016-10-07 13:21:36 -0700703 {"nDrawCircle","(JFFFJ)V", (void*) CanvasJNI::drawCircle},
704 {"nDrawOval","(JFFFFJ)V", (void*) CanvasJNI::drawOval},
705 {"nDrawArc","(JFFFFFFZJ)V", (void*) CanvasJNI::drawArc},
706 {"nDrawPath","(JJJ)V", (void*) CanvasJNI::drawPath},
707 {"nDrawVertices", "(JII[FI[FI[II[SIIJ)V", (void*)CanvasJNI::drawVertices},
708 {"nDrawNinePatch", "(JJJFFFFJII)V", (void*)CanvasJNI::drawNinePatch},
Leon Scroggins III71fae622019-03-26 16:28:41 -0400709 {"nDrawBitmapMatrix", "(JJJJ)V", (void*)CanvasJNI::drawBitmapMatrix},
710 {"nDrawBitmapMesh", "(JJII[FI[IIJ)V", (void*)CanvasJNI::drawBitmapMesh},
711 {"nDrawBitmap","(JJFFJIII)V", (void*) CanvasJNI::drawBitmap},
712 {"nDrawBitmap","(JJFFFFFFFFJII)V", (void*) CanvasJNI::drawBitmapRect},
John Reckcaa08ff2016-10-07 13:21:36 -0700713 {"nDrawBitmap", "(J[IIIFFIIZJ)V", (void*)CanvasJNI::drawBitmapArray},
Seigo Nonaka318ca042017-08-01 16:36:18 -0700714 {"nDrawText","(J[CIIFFIJ)V", (void*) CanvasJNI::drawTextChars},
715 {"nDrawText","(JLjava/lang/String;IIFFIJ)V", (void*) CanvasJNI::drawTextString},
Seigo Nonaka83143d02018-03-14 17:08:28 -0700716 {"nDrawTextRun","(J[CIIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunChars},
Seigo Nonaka318ca042017-08-01 16:36:18 -0700717 {"nDrawTextRun","(JLjava/lang/String;IIIIFFZJ)V", (void*) CanvasJNI::drawTextRunString},
718 {"nDrawTextOnPath","(J[CIIJFFIJ)V", (void*) CanvasJNI::drawTextOnPathChars},
719 {"nDrawTextOnPath","(JLjava/lang/String;JFFIJ)V", (void*) CanvasJNI::drawTextOnPathString},
Derek Sollenberger8872b382014-06-23 14:13:53 -0400720};
721
722int register_android_graphics_Canvas(JNIEnv* env) {
John Reckcaa08ff2016-10-07 13:21:36 -0700723 int ret = 0;
724 ret |= RegisterMethodsOrDie(env, "android/graphics/Canvas", gMethods, NELEM(gMethods));
725 ret |= RegisterMethodsOrDie(env, "android/graphics/BaseCanvas", gDrawMethods, NELEM(gDrawMethods));
John Reck6b164402018-09-24 15:25:42 -0700726 ret |= RegisterMethodsOrDie(env, "android/graphics/BaseRecordingCanvas", gDrawMethods, NELEM(gDrawMethods));
John Reckcaa08ff2016-10-07 13:21:36 -0700727 return ret;
728
Derek Sollenberger8872b382014-06-23 14:13:53 -0400729}
730
731}; // namespace android