blob: 0ad3339ee05fc01850cc1a1669cf5118830eaddb [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
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +010021#ifdef __ANDROID_
Mike Reed322bc572018-03-20 13:37:04 -040022#include <android/api-level.h>
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +010023#else
24#define __ANDROID_API_P__ 28
25#endif
Derek Sollenberger4c5efe92015-07-10 13:56:39 -040026#include <androidfw/ResourceTypes.h>
sergeyvdccca442016-03-21 15:38:21 -070027#include <hwui/Canvas.h>
28#include <hwui/Paint.h>
Ben Wagner0ed10be2018-06-28 17:08:16 -040029#include <hwui/PaintFilter.h>
sergeyvbad99182016-03-17 11:24:22 -070030#include <hwui/Typeface.h>
sergeyvdccca442016-03-21 15:38:21 -070031#include <minikin/Layout.h>
Seigo Nonaka3a4217f2018-05-02 12:56:16 -070032#include <nativehelper/ScopedPrimitiveArray.h>
33#include <nativehelper/ScopedStringChars.h>
Derek Sollenberger4c5efe92015-07-10 13:56:39 -040034
35#include "Bitmap.h"
Derek Sollenberger8872b382014-06-23 14:13:53 -040036#include "SkGraphics.h"
Mike Reed3318f8b2017-02-13 16:14:10 -050037#include "SkRegion.h"
Mike Reed826deef2017-04-04 15:32:04 -040038#include "SkVertices.h"
Derek Sollenberger8872b382014-06-23 14:13:53 -040039
Seigo Nonaka783f9612018-01-20 12:11:13 -080040namespace minikin {
41class MeasuredText;
42} // namespace minikin
43
Derek Sollenberger8872b382014-06-23 14:13:53 -040044namespace android {
45
46namespace CanvasJNI {
47
48static Canvas* get_canvas(jlong canvasHandle) {
49 return reinterpret_cast<Canvas*>(canvasHandle);
50}
51
Richard Uhler775873a2015-12-29 12:37:39 -080052static void delete_canvas(Canvas* canvas) {
53 delete canvas;
54}
55
56static jlong getNativeFinalizer(JNIEnv* env, jobject clazz) {
57 return static_cast<jlong>(reinterpret_cast<uintptr_t>(&delete_canvas));
Derek Sollenberger8872b382014-06-23 14:13:53 -040058}
59
60// Native wrapper constructor used by Canvas(Bitmap)
Leon Scroggins III71fae622019-03-26 16:28:41 -040061static jlong initRaster(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reck3731dc22015-04-13 15:20:29 -070062 SkBitmap bitmap;
Leon Scroggins III71fae622019-03-26 16:28:41 -040063 if (bitmapHandle != 0) {
64 bitmap::toBitmap(bitmapHandle).getSkBitmap(&bitmap);
John Reckc1b33d62015-04-22 09:04:45 -070065 }
John Reck3731dc22015-04-13 15:20:29 -070066 return reinterpret_cast<jlong>(Canvas::create_canvas(bitmap));
Derek Sollenberger8872b382014-06-23 14:13:53 -040067}
68
69// Set the given bitmap as the new draw target (wrapped in a new SkCanvas),
70// optionally copying canvas matrix & clip state.
Leon Scroggins III71fae622019-03-26 16:28:41 -040071static void setBitmap(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle) {
John Reck3731dc22015-04-13 15:20:29 -070072 SkBitmap bitmap;
Leon Scroggins III71fae622019-03-26 16:28:41 -040073 if (bitmapHandle != 0) {
74 bitmap::toBitmap(bitmapHandle).getSkBitmap(&bitmap);
John Reckc1b33d62015-04-22 09:04:45 -070075 }
John Reck3731dc22015-04-13 15:20:29 -070076 get_canvas(canvasHandle)->setBitmap(bitmap);
Derek Sollenberger8872b382014-06-23 14:13:53 -040077}
78
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +010079static jboolean isOpaque(CRITICAL_JNI_PARAMS_COMMA jlong canvasHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -040080 return get_canvas(canvasHandle)->isOpaque() ? JNI_TRUE : JNI_FALSE;
81}
82
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +010083static jint getWidth(CRITICAL_JNI_PARAMS_COMMA jlong canvasHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -040084 return static_cast<jint>(get_canvas(canvasHandle)->width());
85}
86
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +010087static jint getHeight(CRITICAL_JNI_PARAMS_COMMA jlong canvasHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -040088 return static_cast<jint>(get_canvas(canvasHandle)->height());
89}
90
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +010091static jint save(CRITICAL_JNI_PARAMS_COMMA jlong canvasHandle, jint flagsHandle) {
Florin Malitaeecff562015-12-21 10:43:01 -050092 SaveFlags::Flags flags = static_cast<SaveFlags::Flags>(flagsHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -040093 return static_cast<jint>(get_canvas(canvasHandle)->save(flags));
94}
95
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +010096static jint saveLayer(CRITICAL_JNI_PARAMS_COMMA jlong canvasHandle, jfloat l, jfloat t,
Derek Sollenberger8872b382014-06-23 14:13:53 -040097 jfloat r, jfloat b, jlong paintHandle, jint flagsHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -040098 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Florin Malitaeecff562015-12-21 10:43:01 -050099 SaveFlags::Flags flags = static_cast<SaveFlags::Flags>(flagsHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400100 return static_cast<jint>(get_canvas(canvasHandle)->saveLayer(l, t, r, b, paint, flags));
101}
102
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +0100103static jint saveLayerAlpha(CRITICAL_JNI_PARAMS_COMMA jlong canvasHandle, jfloat l, jfloat t,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400104 jfloat r, jfloat b, jint alpha, jint flagsHandle) {
Florin Malitaeecff562015-12-21 10:43:01 -0500105 SaveFlags::Flags flags = static_cast<SaveFlags::Flags>(flagsHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400106 return static_cast<jint>(get_canvas(canvasHandle)->saveLayerAlpha(l, t, r, b, alpha, flags));
107}
108
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +0100109static jint saveUnclippedLayer(CRITICAL_JNI_PARAMS_COMMA jlong canvasHandle, jint l, jint t, jint r, jint b) {
Derek Sollenberger24fc9012018-12-07 14:12:12 -0500110 return reinterpret_cast<jint>(get_canvas(canvasHandle)->saveUnclippedLayer(l, t, r, b));
111}
112
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +0100113static void restoreUnclippedLayer(CRITICAL_JNI_PARAMS_COMMA jlong canvasHandle, jint saveCount, jlong paintHandle) {
Derek Sollenbergerac33a482019-04-22 16:28:09 -0400114 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
115 get_canvas(canvasHandle)->restoreUnclippedLayer(saveCount, *paint);
116}
117
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +0100118static bool restore(CRITICAL_JNI_PARAMS_COMMA jlong canvasHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400119 Canvas* canvas = get_canvas(canvasHandle);
Chris Craikbfa0b292017-01-19 19:12:36 -0800120 if (canvas->getSaveCount() <= 1) {
121 return false; // cannot restore anymore
Derek Sollenberger8872b382014-06-23 14:13:53 -0400122 }
123 canvas->restore();
Chris Craikbfa0b292017-01-19 19:12:36 -0800124 return true; // success
Derek Sollenberger8872b382014-06-23 14:13:53 -0400125}
126
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +0100127static void restoreToCount(CRITICAL_JNI_PARAMS_COMMA jlong canvasHandle, jint saveCount) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400128 Canvas* canvas = get_canvas(canvasHandle);
Chris Craikbfa0b292017-01-19 19:12:36 -0800129 canvas->restoreToCount(saveCount);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400130}
131
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +0100132static jint getSaveCount(CRITICAL_JNI_PARAMS_COMMA jlong canvasHandle) {
Chris Craikbfa0b292017-01-19 19:12:36 -0800133 return static_cast<jint>(get_canvas(canvasHandle)->getSaveCount());
134}
135
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +0100136static void getMatrix(CRITICAL_JNI_PARAMS_COMMA jlong canvasHandle, jlong matrixHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400137 SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
138 get_canvas(canvasHandle)->getMatrix(matrix);
139}
140
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +0100141static void setMatrix(CRITICAL_JNI_PARAMS_COMMA jlong canvasHandle, jlong matrixHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400142 const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
143 get_canvas(canvasHandle)->setMatrix(matrix ? *matrix : SkMatrix::I());
144}
145
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +0100146static void concat(CRITICAL_JNI_PARAMS_COMMA jlong canvasHandle, jlong matrixHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400147 const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
148 get_canvas(canvasHandle)->concat(*matrix);
149}
150
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +0100151static void rotate(CRITICAL_JNI_PARAMS_COMMA jlong canvasHandle, jfloat degrees) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400152 get_canvas(canvasHandle)->rotate(degrees);
153}
154
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +0100155static void scale(CRITICAL_JNI_PARAMS_COMMA jlong canvasHandle, jfloat sx, jfloat sy) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400156 get_canvas(canvasHandle)->scale(sx, sy);
157}
158
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +0100159static void skew(CRITICAL_JNI_PARAMS_COMMA jlong canvasHandle, jfloat sx, jfloat sy) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400160 get_canvas(canvasHandle)->skew(sx, sy);
161}
162
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +0100163static void translate(CRITICAL_JNI_PARAMS_COMMA jlong canvasHandle, jfloat dx, jfloat dy) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400164 get_canvas(canvasHandle)->translate(dx, dy);
165}
166
167static jboolean getClipBounds(JNIEnv* env, jobject, jlong canvasHandle, jobject bounds) {
168 SkRect r;
169 SkIRect ir;
170 bool result = get_canvas(canvasHandle)->getClipBounds(&r);
171
172 if (!result) {
173 r.setEmpty();
174 }
175 r.round(&ir);
176
177 (void)GraphicsJNI::irect_to_jrect(ir, env, bounds);
178 return result ? JNI_TRUE : JNI_FALSE;
179}
180
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +0100181static jboolean quickRejectRect(CRITICAL_JNI_PARAMS_COMMA jlong canvasHandle,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400182 jfloat left, jfloat top, jfloat right, jfloat bottom) {
183 bool result = get_canvas(canvasHandle)->quickRejectRect(left, top, right, bottom);
184 return result ? JNI_TRUE : JNI_FALSE;
185}
186
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +0100187static jboolean quickRejectPath(CRITICAL_JNI_PARAMS_COMMA jlong canvasHandle, jlong pathHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400188 SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
189 bool result = get_canvas(canvasHandle)->quickRejectPath(*path);
190 return result ? JNI_TRUE : JNI_FALSE;
191}
192
Mike Reed6e49c9f2016-12-02 15:36:59 -0500193// SkRegion::Op and SkClipOp are numerically identical, so we can freely cast
194// from one to the other (though SkClipOp is destined to become a strict subset)
Mike Reed6c67f1d2016-12-14 10:29:54 -0500195static_assert(SkRegion::kDifference_Op == static_cast<SkRegion::Op>(SkClipOp::kDifference), "");
196static_assert(SkRegion::kIntersect_Op == static_cast<SkRegion::Op>(SkClipOp::kIntersect), "");
Mike Reeda0a74d52017-03-13 13:26:00 -0400197static_assert(SkRegion::kUnion_Op == static_cast<SkRegion::Op>(SkClipOp::kUnion_deprecated), "");
198static_assert(SkRegion::kXOR_Op == static_cast<SkRegion::Op>(SkClipOp::kXOR_deprecated), "");
199static_assert(SkRegion::kReverseDifference_Op == static_cast<SkRegion::Op>(SkClipOp::kReverseDifference_deprecated), "");
200static_assert(SkRegion::kReplace_Op == static_cast<SkRegion::Op>(SkClipOp::kReplace_deprecated), "");
Mike Reed6e49c9f2016-12-02 15:36:59 -0500201
202static SkClipOp opHandleToClipOp(jint opHandle) {
203 // The opHandle is defined in Canvas.java to be Region::Op
204 SkRegion::Op rgnOp = static_cast<SkRegion::Op>(opHandle);
205
206 // In the future, when we no longer support the wide range of ops (e.g. Union, Xor)
207 // this function can perform a range check and throw an unsupported-exception.
208 // e.g. if (rgnOp != kIntersect && rgnOp != kDifference) throw...
209
210 // Skia now takes a different type, SkClipOp, as the parameter to clipping calls
211 // This type is binary compatible with SkRegion::Op, so a static_cast<> is safe.
212 return static_cast<SkClipOp>(rgnOp);
213}
214
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +0100215static jboolean clipRect(CRITICAL_JNI_PARAMS_COMMA jlong canvasHandle, jfloat l, jfloat t,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400216 jfloat r, jfloat b, jint opHandle) {
Mike Reed6e49c9f2016-12-02 15:36:59 -0500217 bool nonEmptyClip = get_canvas(canvasHandle)->clipRect(l, t, r, b,
218 opHandleToClipOp(opHandle));
Chris Craik5ec6a282015-06-23 15:42:12 -0700219 return nonEmptyClip ? JNI_TRUE : JNI_FALSE;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400220}
221
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +0100222static jboolean clipPath(CRITICAL_JNI_PARAMS_COMMA jlong canvasHandle, jlong pathHandle,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400223 jint opHandle) {
224 SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
Mike Reed6e49c9f2016-12-02 15:36:59 -0500225 bool nonEmptyClip = get_canvas(canvasHandle)->clipPath(path, opHandleToClipOp(opHandle));
Chris Craik5ec6a282015-06-23 15:42:12 -0700226 return nonEmptyClip ? JNI_TRUE : JNI_FALSE;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400227}
228
Derek Sollenberger8872b382014-06-23 14:13:53 -0400229static void drawColor(JNIEnv* env, jobject, jlong canvasHandle, jint color, jint modeHandle) {
Mike Reed260ab722016-10-07 15:59:20 -0400230 SkBlendMode mode = static_cast<SkBlendMode>(modeHandle);
Chris Craik1526a452015-03-06 18:42:15 +0000231 get_canvas(canvasHandle)->drawColor(color, mode);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400232}
233
Leon Scroggins IIIbee5e202019-01-11 13:36:39 -0500234static void drawColorLong(JNIEnv* env, jobject, jlong canvasHandle, jlong colorSpaceHandle,
235 jlong colorLong, jint modeHandle) {
236 SkColor4f color = GraphicsJNI::convertColorLong(colorLong);
237 sk_sp<SkColorSpace> cs = GraphicsJNI::getNativeColorSpace(colorSpaceHandle);
238 SkPaint p;
239 p.setColor4f(color, cs.get());
240
241 SkBlendMode mode = static_cast<SkBlendMode>(modeHandle);
242 p.setBlendMode(mode);
243 get_canvas(canvasHandle)->drawPaint(p);
244}
245
Derek Sollenberger8872b382014-06-23 14:13:53 -0400246static void drawPaint(JNIEnv* env, jobject, jlong canvasHandle, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400247 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400248 get_canvas(canvasHandle)->drawPaint(*paint);
249}
250
251static void drawPoint(JNIEnv*, jobject, jlong canvasHandle, jfloat x, jfloat y,
252 jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400253 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400254 get_canvas(canvasHandle)->drawPoint(x, y, *paint);
255}
256
257static void drawPoints(JNIEnv* env, jobject, jlong canvasHandle, jfloatArray jptsArray,
258 jint offset, jint count, jlong paintHandle) {
259 NPE_CHECK_RETURN_VOID(env, jptsArray);
260 AutoJavaFloatArray autoPts(env, jptsArray);
261 float* floats = autoPts.ptr();
262 const int length = autoPts.length();
263
264 if ((offset | count) < 0 || offset + count > length) {
265 doThrowAIOOBE(env);
266 return;
267 }
268
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400269 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400270 get_canvas(canvasHandle)->drawPoints(floats + offset, count, *paint);
271}
272
273static void drawLine(JNIEnv* env, jobject, jlong canvasHandle, jfloat startX, jfloat startY,
274 jfloat stopX, jfloat stopY, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400275 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400276 get_canvas(canvasHandle)->drawLine(startX, startY, stopX, stopY, *paint);
277}
278
279static void drawLines(JNIEnv* env, jobject, jlong canvasHandle, jfloatArray jptsArray,
280 jint offset, jint count, jlong paintHandle) {
281 NPE_CHECK_RETURN_VOID(env, jptsArray);
282 AutoJavaFloatArray autoPts(env, jptsArray);
283 float* floats = autoPts.ptr();
284 const int length = autoPts.length();
285
286 if ((offset | count) < 0 || offset + count > length) {
287 doThrowAIOOBE(env);
288 return;
289 }
290
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400291 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400292 get_canvas(canvasHandle)->drawLines(floats + offset, count, *paint);
293}
294
295static void drawRect(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
296 jfloat right, jfloat bottom, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400297 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400298 get_canvas(canvasHandle)->drawRect(left, top, right, bottom, *paint);
299}
300
Nader Jawadadfe1d92018-09-27 12:27:36 -0700301static void drawDoubleRoundRectXY(JNIEnv* env, jobject, jlong canvasHandle, jfloat outerLeft,
302 jfloat outerTop, jfloat outerRight, jfloat outerBottom, jfloat outerRx,
303 jfloat outerRy, jfloat innerLeft, jfloat innerTop, jfloat innerRight,
304 jfloat innerBottom, jfloat innerRx, jfloat innerRy, jlong paintHandle) {
305 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
306 get_canvas(canvasHandle)->drawDoubleRoundRectXY(
307 outerLeft, outerTop, outerRight, outerBottom, outerRx, outerRy,
308 innerLeft, innerTop, innerRight, innerBottom, innerRx, innerRy, *paint);
309}
310
311static void drawDoubleRoundRectRadii(JNIEnv* env, jobject, jlong canvasHandle, jfloat outerLeft,
312 jfloat outerTop, jfloat outerRight, jfloat outerBottom, jfloatArray jouterRadii,
313 jfloat innerLeft, jfloat innerTop, jfloat innerRight,
314 jfloat innerBottom, jfloatArray jinnerRadii, jlong paintHandle) {
315 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
316
317 float outerRadii[8];
318 float innerRadii[8];
319 env->GetFloatArrayRegion(jouterRadii, 0, 8, outerRadii);
320 env->GetFloatArrayRegion(jinnerRadii, 0, 8, innerRadii);
321 get_canvas(canvasHandle)->drawDoubleRoundRectRadii(
322 outerLeft, outerTop, outerRight, outerBottom, outerRadii,
323 innerLeft, innerTop, innerRight, innerBottom, innerRadii, *paint);
324
325}
326
Derek Sollenberger94394b32015-07-10 09:58:41 -0400327static void drawRegion(JNIEnv* env, jobject, jlong canvasHandle, jlong regionHandle,
328 jlong paintHandle) {
329 const SkRegion* region = reinterpret_cast<SkRegion*>(regionHandle);
330 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
331 get_canvas(canvasHandle)->drawRegion(*region, *paint);
332}
333
Derek Sollenberger8872b382014-06-23 14:13:53 -0400334static void drawRoundRect(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
335 jfloat right, jfloat bottom, jfloat rx, jfloat ry, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400336 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400337 get_canvas(canvasHandle)->drawRoundRect(left, top, right, bottom, rx, ry, *paint);
338}
339
340static void drawCircle(JNIEnv* env, jobject, jlong canvasHandle, jfloat cx, jfloat cy,
341 jfloat radius, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400342 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400343 get_canvas(canvasHandle)->drawCircle(cx, cy, radius, *paint);
344}
345
346static void drawOval(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
347 jfloat right, jfloat bottom, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400348 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400349 get_canvas(canvasHandle)->drawOval(left, top, right, bottom, *paint);
350}
351
352static void drawArc(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
353 jfloat right, jfloat bottom, jfloat startAngle, jfloat sweepAngle,
354 jboolean useCenter, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400355 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400356 get_canvas(canvasHandle)->drawArc(left, top, right, bottom, startAngle, sweepAngle,
357 useCenter, *paint);
358}
359
360static void drawPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle,
361 jlong paintHandle) {
362 const SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400363 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400364 get_canvas(canvasHandle)->drawPath(*path, *paint);
365}
366
367static void drawVertices(JNIEnv* env, jobject, jlong canvasHandle,
Mike Reed826deef2017-04-04 15:32:04 -0400368 jint modeHandle, jint floatCount,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400369 jfloatArray jverts, jint vertIndex,
370 jfloatArray jtexs, jint texIndex,
371 jintArray jcolors, jint colorIndex,
372 jshortArray jindices, jint indexIndex,
373 jint indexCount, jlong paintHandle) {
John Reckd51e9942018-08-01 13:34:37 -0700374
375 const int vertexCount = floatCount >> 1; // 2 floats per SkPoint
376
Mike Reed826deef2017-04-04 15:32:04 -0400377 AutoJavaFloatArray vertA(env, jverts, vertIndex + floatCount);
378 AutoJavaFloatArray texA(env, jtexs, texIndex + floatCount);
John Reckd51e9942018-08-01 13:34:37 -0700379 AutoJavaIntArray colorA(env, jcolors, colorIndex + vertexCount);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400380 AutoJavaShortArray indexA(env, jindices, indexIndex + indexCount);
381
382 const float* verts = vertA.ptr() + vertIndex;
383 const float* texs = texA.ptr() + vertIndex;
384 const int* colors = NULL;
385 const uint16_t* indices = NULL;
386
387 if (jcolors != NULL) {
388 colors = colorA.ptr() + colorIndex;
389 }
390 if (jindices != NULL) {
391 indices = (const uint16_t*)(indexA.ptr() + indexIndex);
392 }
393
Mike Reed826deef2017-04-04 15:32:04 -0400394 SkVertices::VertexMode mode = static_cast<SkVertices::VertexMode>(modeHandle);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400395 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Mike Reed826deef2017-04-04 15:32:04 -0400396 get_canvas(canvasHandle)->drawVertices(SkVertices::MakeCopy(mode, vertexCount,
397 reinterpret_cast<const SkPoint*>(verts),
398 reinterpret_cast<const SkPoint*>(texs),
399 reinterpret_cast<const SkColor*>(colors),
400 indexCount, indices).get(),
401 SkBlendMode::kModulate, *paint);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400402}
403
Derek Sollenberger4c5efe92015-07-10 13:56:39 -0400404static void drawNinePatch(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle,
405 jlong chunkHandle, jfloat left, jfloat top, jfloat right, jfloat bottom,
406 jlong paintHandle, jint dstDensity, jint srcDensity) {
407
408 Canvas* canvas = get_canvas(canvasHandle);
Leon Scroggins III71fae622019-03-26 16:28:41 -0400409 Bitmap& bitmap = android::bitmap::toBitmap(bitmapHandle);
Derek Sollenberger4c5efe92015-07-10 13:56:39 -0400410 const android::Res_png_9patch* chunk = reinterpret_cast<android::Res_png_9patch*>(chunkHandle);
411 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
412
413 if (CC_LIKELY(dstDensity == srcDensity || dstDensity == 0 || srcDensity == 0)) {
sergeyv5fd2a1c2016-10-20 15:04:28 -0700414 canvas->drawNinePatch(bitmap, *chunk, left, top, right, bottom, paint);
Derek Sollenberger4c5efe92015-07-10 13:56:39 -0400415 } else {
Florin Malitaeecff562015-12-21 10:43:01 -0500416 canvas->save(SaveFlags::MatrixClip);
Derek Sollenberger4c5efe92015-07-10 13:56:39 -0400417
418 SkScalar scale = dstDensity / (float)srcDensity;
419 canvas->translate(left, top);
420 canvas->scale(scale, scale);
421
422 Paint filteredPaint;
423 if (paint) {
424 filteredPaint = *paint;
425 }
426 filteredPaint.setFilterQuality(kLow_SkFilterQuality);
427
sergeyv5fd2a1c2016-10-20 15:04:28 -0700428 canvas->drawNinePatch(bitmap, *chunk, 0, 0, (right-left)/scale, (bottom-top)/scale,
Derek Sollenberger4c5efe92015-07-10 13:56:39 -0400429 &filteredPaint);
430
431 canvas->restore();
432 }
433}
434
Leon Scroggins III71fae622019-03-26 16:28:41 -0400435static void drawBitmap(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400436 jfloat left, jfloat top, jlong paintHandle, jint canvasDensity,
437 jint screenDensity, jint bitmapDensity) {
438 Canvas* canvas = get_canvas(canvasHandle);
Leon Scroggins III71fae622019-03-26 16:28:41 -0400439 Bitmap& bitmap = android::bitmap::toBitmap(bitmapHandle);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400440 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400441
442 if (canvasDensity == bitmapDensity || canvasDensity == 0 || bitmapDensity == 0) {
443 if (screenDensity != 0 && screenDensity != bitmapDensity) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400444 Paint filteredPaint;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400445 if (paint) {
446 filteredPaint = *paint;
447 }
Mike Reed2a1ce8a2015-03-16 11:16:09 -0400448 filteredPaint.setFilterQuality(kLow_SkFilterQuality);
John Reck7c103a32015-04-15 15:52:10 -0700449 canvas->drawBitmap(bitmap, left, top, &filteredPaint);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400450 } else {
John Reck7c103a32015-04-15 15:52:10 -0700451 canvas->drawBitmap(bitmap, left, top, paint);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400452 }
453 } else {
Florin Malitaeecff562015-12-21 10:43:01 -0500454 canvas->save(SaveFlags::MatrixClip);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400455 SkScalar scale = canvasDensity / (float)bitmapDensity;
456 canvas->translate(left, top);
457 canvas->scale(scale, scale);
458
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400459 Paint filteredPaint;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400460 if (paint) {
461 filteredPaint = *paint;
462 }
Mike Reed2a1ce8a2015-03-16 11:16:09 -0400463 filteredPaint.setFilterQuality(kLow_SkFilterQuality);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400464
John Reck7c103a32015-04-15 15:52:10 -0700465 canvas->drawBitmap(bitmap, 0, 0, &filteredPaint);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400466 canvas->restore();
467 }
468}
469
Leon Scroggins III71fae622019-03-26 16:28:41 -0400470static void drawBitmapMatrix(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400471 jlong matrixHandle, jlong paintHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400472 const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400473 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Leon Scroggins III71fae622019-03-26 16:28:41 -0400474 Bitmap& bitmap = android::bitmap::toBitmap(bitmapHandle);
John Reck7c103a32015-04-15 15:52:10 -0700475 get_canvas(canvasHandle)->drawBitmap(bitmap, *matrix, paint);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400476}
477
Leon Scroggins III71fae622019-03-26 16:28:41 -0400478static void drawBitmapRect(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400479 float srcLeft, float srcTop, float srcRight, float srcBottom,
480 float dstLeft, float dstTop, float dstRight, float dstBottom,
481 jlong paintHandle, jint screenDensity, jint bitmapDensity) {
482 Canvas* canvas = get_canvas(canvasHandle);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400483 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400484
Leon Scroggins III71fae622019-03-26 16:28:41 -0400485 Bitmap& bitmap = android::bitmap::toBitmap(bitmapHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400486 if (screenDensity != 0 && screenDensity != bitmapDensity) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400487 Paint filteredPaint;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400488 if (paint) {
489 filteredPaint = *paint;
490 }
Mike Reed2a1ce8a2015-03-16 11:16:09 -0400491 filteredPaint.setFilterQuality(kLow_SkFilterQuality);
John Reck7c103a32015-04-15 15:52:10 -0700492 canvas->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400493 dstLeft, dstTop, dstRight, dstBottom, &filteredPaint);
494 } else {
John Reck7c103a32015-04-15 15:52:10 -0700495 canvas->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400496 dstLeft, dstTop, dstRight, dstBottom, paint);
497 }
498}
499
500static void drawBitmapArray(JNIEnv* env, jobject, jlong canvasHandle,
501 jintArray jcolors, jint offset, jint stride,
502 jfloat x, jfloat y, jint width, jint height,
503 jboolean hasAlpha, jlong paintHandle) {
504 // Note: If hasAlpha is false, kRGB_565_SkColorType will be used, which will
505 // correct the alphaType to kOpaque_SkAlphaType.
John Recke9048f32018-03-30 13:44:35 -0700506 SkImageInfo info = SkImageInfo::Make(width, height,
507 hasAlpha ? kN32_SkColorType : kRGB_565_SkColorType,
508 kPremul_SkAlphaType);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400509 SkBitmap bitmap;
Derek Sollenberger3d4eed72014-12-04 15:20:29 -0500510 bitmap.setInfo(info);
Leon Scroggins IIIf51a80d2017-07-12 10:46:35 -0400511 sk_sp<Bitmap> androidBitmap = Bitmap::allocateHeapBitmap(&bitmap);
sergeyvc1c54062016-10-19 18:47:26 -0700512 if (!androidBitmap) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400513 return;
514 }
515
Brian Osman91c9c282018-08-17 16:57:15 -0400516 if (!GraphicsJNI::SetPixels(env, jcolors, offset, stride, 0, 0, width, height, &bitmap)) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400517 return;
518 }
519
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400520 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
sergeyvaed7f582016-10-14 16:30:21 -0700521 get_canvas(canvasHandle)->drawBitmap(*androidBitmap, x, y, paint);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400522}
523
Leon Scroggins III71fae622019-03-26 16:28:41 -0400524static void drawBitmapMesh(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400525 jint meshWidth, jint meshHeight, jfloatArray jverts,
526 jint vertIndex, jintArray jcolors, jint colorIndex, jlong paintHandle) {
Mike Reed322bc572018-03-20 13:37:04 -0400527 if (Canvas::GetApiLevel() < __ANDROID_API_P__) {
528 // Before P we forgot to respect these. Now that we do respect them, explicitly
529 // zero them for backward compatibility.
530 vertIndex = 0;
531 colorIndex = 0;
532 }
533
Derek Sollenberger8872b382014-06-23 14:13:53 -0400534 const int ptCount = (meshWidth + 1) * (meshHeight + 1);
535 AutoJavaFloatArray vertA(env, jverts, vertIndex + (ptCount << 1));
536 AutoJavaIntArray colorA(env, jcolors, colorIndex + ptCount);
537
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400538 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Leon Scroggins III71fae622019-03-26 16:28:41 -0400539 Bitmap& bitmap = android::bitmap::toBitmap(bitmapHandle);
John Reck7c103a32015-04-15 15:52:10 -0700540 get_canvas(canvasHandle)->drawBitmapMesh(bitmap, meshWidth, meshHeight,
Mike Reed322bc572018-03-20 13:37:04 -0400541 vertA.ptr() + vertIndex*2,
542 colorA.ptr() + colorIndex, paint);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400543}
544
Seigo Nonaka3a4217f2018-05-02 12:56:16 -0700545static void drawTextChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray charArray,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400546 jint index, jint count, jfloat x, jfloat y, jint bidiFlags,
Seigo Nonaka318ca042017-08-01 16:36:18 -0700547 jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400548 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Seigo Nonaka318ca042017-08-01 16:36:18 -0700549 const Typeface* typeface = paint->getAndroidTypeface();
Seigo Nonaka3a4217f2018-05-02 12:56:16 -0700550 ScopedCharArrayRO text(env, charArray);
Seigo Nonakaf307adc2018-10-19 19:10:02 -0700551 // drawTextString and drawTextChars doesn't use context info
Seigo Nonaka3a4217f2018-05-02 12:56:16 -0700552 get_canvas(canvasHandle)->drawText(
Seigo Nonakaf307adc2018-10-19 19:10:02 -0700553 text.get() + index, count, // text buffer
554 0, count, // draw range
555 0, count, // context range
Seigo Nonaka3a4217f2018-05-02 12:56:16 -0700556 x, y, // draw position
557 static_cast<minikin::Bidi>(bidiFlags), *paint, typeface, nullptr /* measured text */);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400558}
559
Seigo Nonaka3a4217f2018-05-02 12:56:16 -0700560static void drawTextString(JNIEnv* env, jobject, jlong canvasHandle, jstring strObj,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400561 jint start, jint end, jfloat x, jfloat y, jint bidiFlags,
Seigo Nonaka318ca042017-08-01 16:36:18 -0700562 jlong paintHandle) {
Seigo Nonaka3a4217f2018-05-02 12:56:16 -0700563 ScopedStringChars text(env, strObj);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400564 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Seigo Nonaka318ca042017-08-01 16:36:18 -0700565 const Typeface* typeface = paint->getAndroidTypeface();
Seigo Nonakaf307adc2018-10-19 19:10:02 -0700566 const int count = end - start;
567 // drawTextString and drawTextChars doesn't use context info
Seigo Nonaka3a4217f2018-05-02 12:56:16 -0700568 get_canvas(canvasHandle)->drawText(
Seigo Nonakaf307adc2018-10-19 19:10:02 -0700569 text.get() + start, count, // text buffer
570 0, count, // draw range
571 0, count, // context range
Seigo Nonaka3a4217f2018-05-02 12:56:16 -0700572 x, y, // draw position
573 static_cast<minikin::Bidi>(bidiFlags), *paint, typeface, nullptr /* measured text */);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400574}
575
Seigo Nonaka3a4217f2018-05-02 12:56:16 -0700576static void drawTextRunChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray charArray,
577 jint index, jint count, jint contextIndex, jint contextCount,
578 jfloat x, jfloat y, jboolean isRtl, jlong paintHandle,
579 jlong mtHandle) {
Seigo Nonaka783f9612018-01-20 12:11:13 -0800580 minikin::MeasuredText* mt = reinterpret_cast<minikin::MeasuredText*>(mtHandle);
Seigo Nonaka7c93e862017-10-25 16:34:48 -0700581 const minikin::Bidi bidiFlags = isRtl ? minikin::Bidi::FORCE_RTL : minikin::Bidi::FORCE_LTR;
Seigo Nonaka3a4217f2018-05-02 12:56:16 -0700582
583 ScopedCharArrayRO text(env, charArray);
584 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
585 const Typeface* typeface = paint->getAndroidTypeface();
586 get_canvas(canvasHandle)->drawText(
587 text.get(), text.size(), // text buffer
588 index, count, // draw range
589 contextIndex, contextCount, // context range,
590 x, y, // draw position
591 bidiFlags, *paint, typeface, mt);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400592}
593
Seigo Nonaka3a4217f2018-05-02 12:56:16 -0700594static void drawTextRunString(JNIEnv* env, jobject obj, jlong canvasHandle, jstring strObj,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400595 jint start, jint end, jint contextStart, jint contextEnd,
Seigo Nonaka318ca042017-08-01 16:36:18 -0700596 jfloat x, jfloat y, jboolean isRtl, jlong paintHandle) {
Seigo Nonaka3a4217f2018-05-02 12:56:16 -0700597 const minikin::Bidi bidiFlags = isRtl ? minikin::Bidi::FORCE_RTL : minikin::Bidi::FORCE_LTR;
598
599 ScopedStringChars text(env, strObj);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400600 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Seigo Nonaka318ca042017-08-01 16:36:18 -0700601 const Typeface* typeface = paint->getAndroidTypeface();
Seigo Nonaka3a4217f2018-05-02 12:56:16 -0700602 get_canvas(canvasHandle)->drawText(
603 text.get(), text.size(), // text buffer
604 start, end - start, // draw range
605 contextStart, contextEnd - contextStart, // context range
606 x, y, // draw position
607 bidiFlags, *paint, typeface, nullptr /* measured text */);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400608}
609
Derek Sollenberger8872b382014-06-23 14:13:53 -0400610static void drawTextOnPathChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text,
611 jint index, jint count, jlong pathHandle, jfloat hOffset,
Seigo Nonaka318ca042017-08-01 16:36:18 -0700612 jfloat vOffset, jint bidiFlags, jlong paintHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400613 SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400614 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Seigo Nonaka318ca042017-08-01 16:36:18 -0700615 const Typeface* typeface = paint->getAndroidTypeface();
Derek Sollenberger8872b382014-06-23 14:13:53 -0400616
617 jchar* jchars = env->GetCharArrayElements(text, NULL);
618
Seigo Nonaka7c93e862017-10-25 16:34:48 -0700619 get_canvas(canvasHandle)->drawTextOnPath(jchars + index, count,
620 static_cast<minikin::Bidi>(bidiFlags), *path, hOffset, vOffset, *paint, typeface);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400621
622 env->ReleaseCharArrayElements(text, jchars, 0);
623}
624
625static void drawTextOnPathString(JNIEnv* env, jobject, jlong canvasHandle, jstring text,
626 jlong pathHandle, jfloat hOffset, jfloat vOffset,
Seigo Nonaka318ca042017-08-01 16:36:18 -0700627 jint bidiFlags, jlong paintHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400628 SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400629 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Seigo Nonaka318ca042017-08-01 16:36:18 -0700630 const Typeface* typeface = paint->getAndroidTypeface();
Derek Sollenberger8872b382014-06-23 14:13:53 -0400631
632 const jchar* jchars = env->GetStringChars(text, NULL);
633 int count = env->GetStringLength(text);
634
Seigo Nonaka7c93e862017-10-25 16:34:48 -0700635 get_canvas(canvasHandle)->drawTextOnPath(jchars, count, static_cast<minikin::Bidi>(bidiFlags),
636 *path, hOffset, vOffset, *paint, typeface);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400637
638 env->ReleaseStringChars(text, jchars);
639}
640
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +0100641static void setPaintFilter(CRITICAL_JNI_PARAMS_COMMA jlong canvasHandle, jlong filterHandle) {
Ben Wagner0ed10be2018-06-28 17:08:16 -0400642 PaintFilter* paintFilter = reinterpret_cast<PaintFilter*>(filterHandle);
643 get_canvas(canvasHandle)->setPaintFilter(sk_ref_sp(paintFilter));
Derek Sollenberger8872b382014-06-23 14:13:53 -0400644}
645
646static void freeCaches(JNIEnv* env, jobject) {
647 SkGraphics::PurgeFontCache();
648}
649
650static void freeTextLayoutCaches(JNIEnv* env, jobject) {
Seigo Nonakaae1aa852016-06-09 19:42:51 +0900651 minikin::Layout::purgeCaches();
Derek Sollenberger8872b382014-06-23 14:13:53 -0400652}
653
Stan Iliev7717e222018-02-05 18:04:11 -0500654static void setCompatibilityVersion(JNIEnv* env, jobject, jint apiLevel) {
655 Canvas::setCompatibilityVersion(apiLevel);
656}
657
658
Derek Sollenberger8872b382014-06-23 14:13:53 -0400659}; // namespace CanvasJNI
660
Daniel Micay76f6a862015-09-19 17:31:01 -0400661static const JNINativeMethod gMethods[] = {
John Reckcaa08ff2016-10-07 13:21:36 -0700662 {"nGetNativeFinalizer", "()J", (void*) CanvasJNI::getNativeFinalizer},
John Reckcaa08ff2016-10-07 13:21:36 -0700663 {"nFreeCaches", "()V", (void*) CanvasJNI::freeCaches},
664 {"nFreeTextLayoutCaches", "()V", (void*) CanvasJNI::freeTextLayoutCaches},
Stan Iliev7717e222018-02-05 18:04:11 -0500665 {"nSetCompatibilityVersion", "(I)V", (void*) CanvasJNI::setCompatibilityVersion},
John Reck5cb74bc2016-10-07 11:24:44 -0700666
667 // ------------ @FastNative ----------------
Leon Scroggins III71fae622019-03-26 16:28:41 -0400668 {"nInitRaster", "(J)J", (void*) CanvasJNI::initRaster},
669 {"nSetBitmap", "(JJ)V", (void*) CanvasJNI::setBitmap},
Chris Craikbfa0b292017-01-19 19:12:36 -0800670 {"nGetClipBounds","(JLandroid/graphics/Rect;)Z", (void*) CanvasJNI::getClipBounds},
671
672 // ------------ @CriticalNative ----------------
John Reckcaa08ff2016-10-07 13:21:36 -0700673 {"nIsOpaque","(J)Z", (void*) CanvasJNI::isOpaque},
674 {"nGetWidth","(J)I", (void*) CanvasJNI::getWidth},
675 {"nGetHeight","(J)I", (void*) CanvasJNI::getHeight},
John Reckcaa08ff2016-10-07 13:21:36 -0700676 {"nSave","(JI)I", (void*) CanvasJNI::save},
677 {"nSaveLayer","(JFFFFJI)I", (void*) CanvasJNI::saveLayer},
678 {"nSaveLayerAlpha","(JFFFFII)I", (void*) CanvasJNI::saveLayerAlpha},
Derek Sollenberger24fc9012018-12-07 14:12:12 -0500679 {"nSaveUnclippedLayer","(JIIII)I", (void*) CanvasJNI::saveUnclippedLayer},
Derek Sollenbergerac33a482019-04-22 16:28:09 -0400680 {"nRestoreUnclippedLayer","(JIJ)V", (void*) CanvasJNI::restoreUnclippedLayer},
John Reckcaa08ff2016-10-07 13:21:36 -0700681 {"nGetSaveCount","(J)I", (void*) CanvasJNI::getSaveCount},
Chris Craikbfa0b292017-01-19 19:12:36 -0800682 {"nRestore","(J)Z", (void*) CanvasJNI::restore},
683 {"nRestoreToCount","(JI)V", (void*) CanvasJNI::restoreToCount},
684 {"nGetMatrix", "(JJ)V", (void*)CanvasJNI::getMatrix},
John Reckcaa08ff2016-10-07 13:21:36 -0700685 {"nSetMatrix","(JJ)V", (void*) CanvasJNI::setMatrix},
686 {"nConcat","(JJ)V", (void*) CanvasJNI::concat},
687 {"nRotate","(JF)V", (void*) CanvasJNI::rotate},
688 {"nScale","(JFF)V", (void*) CanvasJNI::scale},
689 {"nSkew","(JFF)V", (void*) CanvasJNI::skew},
690 {"nTranslate","(JFF)V", (void*) CanvasJNI::translate},
John Reckcaa08ff2016-10-07 13:21:36 -0700691 {"nQuickReject","(JJ)Z", (void*) CanvasJNI::quickRejectPath},
692 {"nQuickReject","(JFFFF)Z", (void*)CanvasJNI::quickRejectRect},
693 {"nClipRect","(JFFFFI)Z", (void*) CanvasJNI::clipRect},
694 {"nClipPath","(JJI)Z", (void*) CanvasJNI::clipPath},
Ben Wagner0ed10be2018-06-28 17:08:16 -0400695 {"nSetDrawFilter", "(JJ)V", (void*) CanvasJNI::setPaintFilter},
John Reckcaa08ff2016-10-07 13:21:36 -0700696};
697
698// If called from Canvas these are regular JNI
699// If called from DisplayListCanvas they are @FastNative
700static const JNINativeMethod gDrawMethods[] = {
701 {"nDrawColor","(JII)V", (void*) CanvasJNI::drawColor},
Leon Scroggins IIIbee5e202019-01-11 13:36:39 -0500702 {"nDrawColor","(JJJI)V", (void*) CanvasJNI::drawColorLong},
John Reckcaa08ff2016-10-07 13:21:36 -0700703 {"nDrawPaint","(JJ)V", (void*) CanvasJNI::drawPaint},
704 {"nDrawPoint", "(JFFJ)V", (void*) CanvasJNI::drawPoint},
705 {"nDrawPoints", "(J[FIIJ)V", (void*) CanvasJNI::drawPoints},
706 {"nDrawLine", "(JFFFFJ)V", (void*) CanvasJNI::drawLine},
707 {"nDrawLines", "(J[FIIJ)V", (void*) CanvasJNI::drawLines},
708 {"nDrawRect","(JFFFFJ)V", (void*) CanvasJNI::drawRect},
709 {"nDrawRegion", "(JJJ)V", (void*) CanvasJNI::drawRegion },
710 {"nDrawRoundRect","(JFFFFFFJ)V", (void*) CanvasJNI::drawRoundRect},
Nader Jawadadfe1d92018-09-27 12:27:36 -0700711 {"nDrawDoubleRoundRect", "(JFFFFFFFFFFFFJ)V", (void*) CanvasJNI::drawDoubleRoundRectXY},
712 {"nDrawDoubleRoundRect", "(JFFFF[FFFFF[FJ)V", (void*) CanvasJNI::drawDoubleRoundRectRadii},
John Reckcaa08ff2016-10-07 13:21:36 -0700713 {"nDrawCircle","(JFFFJ)V", (void*) CanvasJNI::drawCircle},
714 {"nDrawOval","(JFFFFJ)V", (void*) CanvasJNI::drawOval},
715 {"nDrawArc","(JFFFFFFZJ)V", (void*) CanvasJNI::drawArc},
716 {"nDrawPath","(JJJ)V", (void*) CanvasJNI::drawPath},
717 {"nDrawVertices", "(JII[FI[FI[II[SIIJ)V", (void*)CanvasJNI::drawVertices},
718 {"nDrawNinePatch", "(JJJFFFFJII)V", (void*)CanvasJNI::drawNinePatch},
Leon Scroggins III71fae622019-03-26 16:28:41 -0400719 {"nDrawBitmapMatrix", "(JJJJ)V", (void*)CanvasJNI::drawBitmapMatrix},
720 {"nDrawBitmapMesh", "(JJII[FI[IIJ)V", (void*)CanvasJNI::drawBitmapMesh},
721 {"nDrawBitmap","(JJFFJIII)V", (void*) CanvasJNI::drawBitmap},
722 {"nDrawBitmap","(JJFFFFFFFFJII)V", (void*) CanvasJNI::drawBitmapRect},
John Reckcaa08ff2016-10-07 13:21:36 -0700723 {"nDrawBitmap", "(J[IIIFFIIZJ)V", (void*)CanvasJNI::drawBitmapArray},
Seigo Nonaka318ca042017-08-01 16:36:18 -0700724 {"nDrawText","(J[CIIFFIJ)V", (void*) CanvasJNI::drawTextChars},
725 {"nDrawText","(JLjava/lang/String;IIFFIJ)V", (void*) CanvasJNI::drawTextString},
Seigo Nonaka83143d02018-03-14 17:08:28 -0700726 {"nDrawTextRun","(J[CIIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunChars},
Seigo Nonaka318ca042017-08-01 16:36:18 -0700727 {"nDrawTextRun","(JLjava/lang/String;IIIIFFZJ)V", (void*) CanvasJNI::drawTextRunString},
728 {"nDrawTextOnPath","(J[CIIJFFIJ)V", (void*) CanvasJNI::drawTextOnPathChars},
729 {"nDrawTextOnPath","(JLjava/lang/String;JFFIJ)V", (void*) CanvasJNI::drawTextOnPathString},
Derek Sollenberger8872b382014-06-23 14:13:53 -0400730};
731
732int register_android_graphics_Canvas(JNIEnv* env) {
John Reckcaa08ff2016-10-07 13:21:36 -0700733 int ret = 0;
734 ret |= RegisterMethodsOrDie(env, "android/graphics/Canvas", gMethods, NELEM(gMethods));
735 ret |= RegisterMethodsOrDie(env, "android/graphics/BaseCanvas", gDrawMethods, NELEM(gDrawMethods));
John Reck6b164402018-09-24 15:25:42 -0700736 ret |= RegisterMethodsOrDie(env, "android/graphics/BaseRecordingCanvas", gDrawMethods, NELEM(gDrawMethods));
John Reckcaa08ff2016-10-07 13:21:36 -0700737 return ret;
738
Derek Sollenberger8872b382014-06-23 14:13:53 -0400739}
740
741}; // namespace android