blob: 7f90d8ee3e4ebb497db4721acccc5b221f8f2a29 [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>
sergeyvbad99182016-03-17 11:24:22 -070025#include <hwui/Typeface.h>
sergeyvdccca442016-03-21 15:38:21 -070026#include <minikin/Layout.h>
Derek Sollenberger4c5efe92015-07-10 13:56:39 -040027
28#include "Bitmap.h"
Derek Sollenbergeracb40992014-07-21 15:22:10 -040029#include "SkDrawFilter.h"
Derek Sollenberger8872b382014-06-23 14:13:53 -040030#include "SkGraphics.h"
Mike Reed3318f8b2017-02-13 16:14:10 -050031#include "SkRegion.h"
Mike Reed826deef2017-04-04 15:32:04 -040032#include "SkVertices.h"
Derek Sollenberger8872b382014-06-23 14:13:53 -040033
Seigo Nonaka783f9612018-01-20 12:11:13 -080034namespace minikin {
35class MeasuredText;
36} // namespace minikin
37
Derek Sollenberger8872b382014-06-23 14:13:53 -040038namespace android {
39
40namespace CanvasJNI {
41
42static Canvas* get_canvas(jlong canvasHandle) {
43 return reinterpret_cast<Canvas*>(canvasHandle);
44}
45
Richard Uhler775873a2015-12-29 12:37:39 -080046static void delete_canvas(Canvas* canvas) {
47 delete canvas;
48}
49
50static jlong getNativeFinalizer(JNIEnv* env, jobject clazz) {
51 return static_cast<jlong>(reinterpret_cast<uintptr_t>(&delete_canvas));
Derek Sollenberger8872b382014-06-23 14:13:53 -040052}
53
54// Native wrapper constructor used by Canvas(Bitmap)
John Reckc1b33d62015-04-22 09:04:45 -070055static jlong initRaster(JNIEnv* env, jobject, jobject jbitmap) {
John Reck3731dc22015-04-13 15:20:29 -070056 SkBitmap bitmap;
John Reckc1b33d62015-04-22 09:04:45 -070057 if (jbitmap != NULL) {
John Reck3731dc22015-04-13 15:20:29 -070058 GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
John Reckc1b33d62015-04-22 09:04:45 -070059 }
John Reck3731dc22015-04-13 15:20:29 -070060 return reinterpret_cast<jlong>(Canvas::create_canvas(bitmap));
Derek Sollenberger8872b382014-06-23 14:13:53 -040061}
62
63// Set the given bitmap as the new draw target (wrapped in a new SkCanvas),
64// optionally copying canvas matrix & clip state.
John Reckc1b33d62015-04-22 09:04:45 -070065static void setBitmap(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap) {
John Reck3731dc22015-04-13 15:20:29 -070066 SkBitmap bitmap;
John Reckc1b33d62015-04-22 09:04:45 -070067 if (jbitmap != NULL) {
John Reck3731dc22015-04-13 15:20:29 -070068 GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
John Reckc1b33d62015-04-22 09:04:45 -070069 }
John Reck3731dc22015-04-13 15:20:29 -070070 get_canvas(canvasHandle)->setBitmap(bitmap);
Derek Sollenberger8872b382014-06-23 14:13:53 -040071}
72
Chris Craikbfa0b292017-01-19 19:12:36 -080073static jboolean isOpaque(jlong canvasHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -040074 return get_canvas(canvasHandle)->isOpaque() ? JNI_TRUE : JNI_FALSE;
75}
76
Chris Craikbfa0b292017-01-19 19:12:36 -080077static jint getWidth(jlong canvasHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -040078 return static_cast<jint>(get_canvas(canvasHandle)->width());
79}
80
Chris Craikbfa0b292017-01-19 19:12:36 -080081static jint getHeight(jlong canvasHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -040082 return static_cast<jint>(get_canvas(canvasHandle)->height());
83}
84
Chris Craikbfa0b292017-01-19 19:12:36 -080085static jint save(jlong canvasHandle, jint flagsHandle) {
Florin Malitaeecff562015-12-21 10:43:01 -050086 SaveFlags::Flags flags = static_cast<SaveFlags::Flags>(flagsHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -040087 return static_cast<jint>(get_canvas(canvasHandle)->save(flags));
88}
89
Chris Craikbfa0b292017-01-19 19:12:36 -080090static jint saveLayer(jlong canvasHandle, jfloat l, jfloat t,
Derek Sollenberger8872b382014-06-23 14:13:53 -040091 jfloat r, jfloat b, jlong paintHandle, jint flagsHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -040092 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Florin Malitaeecff562015-12-21 10:43:01 -050093 SaveFlags::Flags flags = static_cast<SaveFlags::Flags>(flagsHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -040094 return static_cast<jint>(get_canvas(canvasHandle)->saveLayer(l, t, r, b, paint, flags));
95}
96
Chris Craikbfa0b292017-01-19 19:12:36 -080097static jint saveLayerAlpha(jlong canvasHandle, jfloat l, jfloat t,
Derek Sollenberger8872b382014-06-23 14:13:53 -040098 jfloat r, jfloat b, jint alpha, jint flagsHandle) {
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)->saveLayerAlpha(l, t, r, b, alpha, flags));
101}
102
Chris Craikbfa0b292017-01-19 19:12:36 -0800103static bool restore(jlong canvasHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400104 Canvas* canvas = get_canvas(canvasHandle);
Chris Craikbfa0b292017-01-19 19:12:36 -0800105 if (canvas->getSaveCount() <= 1) {
106 return false; // cannot restore anymore
Derek Sollenberger8872b382014-06-23 14:13:53 -0400107 }
108 canvas->restore();
Chris Craikbfa0b292017-01-19 19:12:36 -0800109 return true; // success
Derek Sollenberger8872b382014-06-23 14:13:53 -0400110}
111
Chris Craikbfa0b292017-01-19 19:12:36 -0800112static void restoreToCount(jlong canvasHandle, jint saveCount) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400113 Canvas* canvas = get_canvas(canvasHandle);
Chris Craikbfa0b292017-01-19 19:12:36 -0800114 canvas->restoreToCount(saveCount);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400115}
116
Chris Craikbfa0b292017-01-19 19:12:36 -0800117static jint getSaveCount(jlong canvasHandle) {
118 return static_cast<jint>(get_canvas(canvasHandle)->getSaveCount());
119}
120
121static void getMatrix(jlong canvasHandle, jlong matrixHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400122 SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
123 get_canvas(canvasHandle)->getMatrix(matrix);
124}
125
Chris Craikbfa0b292017-01-19 19:12:36 -0800126static void setMatrix(jlong canvasHandle, jlong matrixHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400127 const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
128 get_canvas(canvasHandle)->setMatrix(matrix ? *matrix : SkMatrix::I());
129}
130
Chris Craikbfa0b292017-01-19 19:12:36 -0800131static void concat(jlong canvasHandle, jlong matrixHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400132 const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
133 get_canvas(canvasHandle)->concat(*matrix);
134}
135
Chris Craikbfa0b292017-01-19 19:12:36 -0800136static void rotate(jlong canvasHandle, jfloat degrees) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400137 get_canvas(canvasHandle)->rotate(degrees);
138}
139
Chris Craikbfa0b292017-01-19 19:12:36 -0800140static void scale(jlong canvasHandle, jfloat sx, jfloat sy) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400141 get_canvas(canvasHandle)->scale(sx, sy);
142}
143
Chris Craikbfa0b292017-01-19 19:12:36 -0800144static void skew(jlong canvasHandle, jfloat sx, jfloat sy) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400145 get_canvas(canvasHandle)->skew(sx, sy);
146}
147
Chris Craikbfa0b292017-01-19 19:12:36 -0800148static void translate(jlong canvasHandle, jfloat dx, jfloat dy) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400149 get_canvas(canvasHandle)->translate(dx, dy);
150}
151
152static jboolean getClipBounds(JNIEnv* env, jobject, jlong canvasHandle, jobject bounds) {
153 SkRect r;
154 SkIRect ir;
155 bool result = get_canvas(canvasHandle)->getClipBounds(&r);
156
157 if (!result) {
158 r.setEmpty();
159 }
160 r.round(&ir);
161
162 (void)GraphicsJNI::irect_to_jrect(ir, env, bounds);
163 return result ? JNI_TRUE : JNI_FALSE;
164}
165
Chris Craikbfa0b292017-01-19 19:12:36 -0800166static jboolean quickRejectRect(jlong canvasHandle,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400167 jfloat left, jfloat top, jfloat right, jfloat bottom) {
168 bool result = get_canvas(canvasHandle)->quickRejectRect(left, top, right, bottom);
169 return result ? JNI_TRUE : JNI_FALSE;
170}
171
Chris Craikbfa0b292017-01-19 19:12:36 -0800172static jboolean quickRejectPath(jlong canvasHandle, jlong pathHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400173 SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
174 bool result = get_canvas(canvasHandle)->quickRejectPath(*path);
175 return result ? JNI_TRUE : JNI_FALSE;
176}
177
Mike Reed6e49c9f2016-12-02 15:36:59 -0500178// SkRegion::Op and SkClipOp are numerically identical, so we can freely cast
179// from one to the other (though SkClipOp is destined to become a strict subset)
Mike Reed6c67f1d2016-12-14 10:29:54 -0500180static_assert(SkRegion::kDifference_Op == static_cast<SkRegion::Op>(SkClipOp::kDifference), "");
181static_assert(SkRegion::kIntersect_Op == static_cast<SkRegion::Op>(SkClipOp::kIntersect), "");
Mike Reeda0a74d52017-03-13 13:26:00 -0400182static_assert(SkRegion::kUnion_Op == static_cast<SkRegion::Op>(SkClipOp::kUnion_deprecated), "");
183static_assert(SkRegion::kXOR_Op == static_cast<SkRegion::Op>(SkClipOp::kXOR_deprecated), "");
184static_assert(SkRegion::kReverseDifference_Op == static_cast<SkRegion::Op>(SkClipOp::kReverseDifference_deprecated), "");
185static_assert(SkRegion::kReplace_Op == static_cast<SkRegion::Op>(SkClipOp::kReplace_deprecated), "");
Mike Reed6e49c9f2016-12-02 15:36:59 -0500186
187static SkClipOp opHandleToClipOp(jint opHandle) {
188 // The opHandle is defined in Canvas.java to be Region::Op
189 SkRegion::Op rgnOp = static_cast<SkRegion::Op>(opHandle);
190
191 // In the future, when we no longer support the wide range of ops (e.g. Union, Xor)
192 // this function can perform a range check and throw an unsupported-exception.
193 // e.g. if (rgnOp != kIntersect && rgnOp != kDifference) throw...
194
195 // Skia now takes a different type, SkClipOp, as the parameter to clipping calls
196 // This type is binary compatible with SkRegion::Op, so a static_cast<> is safe.
197 return static_cast<SkClipOp>(rgnOp);
198}
199
Chris Craikbfa0b292017-01-19 19:12:36 -0800200static jboolean clipRect(jlong canvasHandle, jfloat l, jfloat t,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400201 jfloat r, jfloat b, jint opHandle) {
Mike Reed6e49c9f2016-12-02 15:36:59 -0500202 bool nonEmptyClip = get_canvas(canvasHandle)->clipRect(l, t, r, b,
203 opHandleToClipOp(opHandle));
Chris Craik5ec6a282015-06-23 15:42:12 -0700204 return nonEmptyClip ? JNI_TRUE : JNI_FALSE;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400205}
206
Chris Craikbfa0b292017-01-19 19:12:36 -0800207static jboolean clipPath(jlong canvasHandle, jlong pathHandle,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400208 jint opHandle) {
209 SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
Mike Reed6e49c9f2016-12-02 15:36:59 -0500210 bool nonEmptyClip = get_canvas(canvasHandle)->clipPath(path, opHandleToClipOp(opHandle));
Chris Craik5ec6a282015-06-23 15:42:12 -0700211 return nonEmptyClip ? JNI_TRUE : JNI_FALSE;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400212}
213
Derek Sollenberger8872b382014-06-23 14:13:53 -0400214static void drawColor(JNIEnv* env, jobject, jlong canvasHandle, jint color, jint modeHandle) {
Mike Reed260ab722016-10-07 15:59:20 -0400215 SkBlendMode mode = static_cast<SkBlendMode>(modeHandle);
Chris Craik1526a452015-03-06 18:42:15 +0000216 get_canvas(canvasHandle)->drawColor(color, mode);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400217}
218
219static void drawPaint(JNIEnv* env, jobject, jlong canvasHandle, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400220 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400221 get_canvas(canvasHandle)->drawPaint(*paint);
222}
223
224static void drawPoint(JNIEnv*, jobject, jlong canvasHandle, jfloat x, jfloat y,
225 jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400226 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400227 get_canvas(canvasHandle)->drawPoint(x, y, *paint);
228}
229
230static void drawPoints(JNIEnv* env, jobject, jlong canvasHandle, jfloatArray jptsArray,
231 jint offset, jint count, jlong paintHandle) {
232 NPE_CHECK_RETURN_VOID(env, jptsArray);
233 AutoJavaFloatArray autoPts(env, jptsArray);
234 float* floats = autoPts.ptr();
235 const int length = autoPts.length();
236
237 if ((offset | count) < 0 || offset + count > length) {
238 doThrowAIOOBE(env);
239 return;
240 }
241
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400242 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400243 get_canvas(canvasHandle)->drawPoints(floats + offset, count, *paint);
244}
245
246static void drawLine(JNIEnv* env, jobject, jlong canvasHandle, jfloat startX, jfloat startY,
247 jfloat stopX, jfloat stopY, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400248 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400249 get_canvas(canvasHandle)->drawLine(startX, startY, stopX, stopY, *paint);
250}
251
252static void drawLines(JNIEnv* env, jobject, jlong canvasHandle, jfloatArray jptsArray,
253 jint offset, jint count, jlong paintHandle) {
254 NPE_CHECK_RETURN_VOID(env, jptsArray);
255 AutoJavaFloatArray autoPts(env, jptsArray);
256 float* floats = autoPts.ptr();
257 const int length = autoPts.length();
258
259 if ((offset | count) < 0 || offset + count > length) {
260 doThrowAIOOBE(env);
261 return;
262 }
263
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400264 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400265 get_canvas(canvasHandle)->drawLines(floats + offset, count, *paint);
266}
267
268static void drawRect(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
269 jfloat right, jfloat bottom, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400270 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400271 get_canvas(canvasHandle)->drawRect(left, top, right, bottom, *paint);
272}
273
Derek Sollenberger94394b32015-07-10 09:58:41 -0400274static void drawRegion(JNIEnv* env, jobject, jlong canvasHandle, jlong regionHandle,
275 jlong paintHandle) {
276 const SkRegion* region = reinterpret_cast<SkRegion*>(regionHandle);
277 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
278 get_canvas(canvasHandle)->drawRegion(*region, *paint);
279}
280
Derek Sollenberger8872b382014-06-23 14:13:53 -0400281static void drawRoundRect(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
282 jfloat right, jfloat bottom, jfloat rx, jfloat ry, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400283 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400284 get_canvas(canvasHandle)->drawRoundRect(left, top, right, bottom, rx, ry, *paint);
285}
286
287static void drawCircle(JNIEnv* env, jobject, jlong canvasHandle, jfloat cx, jfloat cy,
288 jfloat radius, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400289 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400290 get_canvas(canvasHandle)->drawCircle(cx, cy, radius, *paint);
291}
292
293static void drawOval(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
294 jfloat right, jfloat bottom, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400295 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400296 get_canvas(canvasHandle)->drawOval(left, top, right, bottom, *paint);
297}
298
299static void drawArc(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
300 jfloat right, jfloat bottom, jfloat startAngle, jfloat sweepAngle,
301 jboolean useCenter, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400302 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400303 get_canvas(canvasHandle)->drawArc(left, top, right, bottom, startAngle, sweepAngle,
304 useCenter, *paint);
305}
306
307static void drawPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle,
308 jlong paintHandle) {
309 const SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400310 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400311 get_canvas(canvasHandle)->drawPath(*path, *paint);
312}
313
314static void drawVertices(JNIEnv* env, jobject, jlong canvasHandle,
Mike Reed826deef2017-04-04 15:32:04 -0400315 jint modeHandle, jint floatCount,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400316 jfloatArray jverts, jint vertIndex,
317 jfloatArray jtexs, jint texIndex,
318 jintArray jcolors, jint colorIndex,
319 jshortArray jindices, jint indexIndex,
320 jint indexCount, jlong paintHandle) {
Mike Reed826deef2017-04-04 15:32:04 -0400321 AutoJavaFloatArray vertA(env, jverts, vertIndex + floatCount);
322 AutoJavaFloatArray texA(env, jtexs, texIndex + floatCount);
323 AutoJavaIntArray colorA(env, jcolors, colorIndex + floatCount);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400324 AutoJavaShortArray indexA(env, jindices, indexIndex + indexCount);
325
326 const float* verts = vertA.ptr() + vertIndex;
327 const float* texs = texA.ptr() + vertIndex;
328 const int* colors = NULL;
329 const uint16_t* indices = NULL;
330
331 if (jcolors != NULL) {
332 colors = colorA.ptr() + colorIndex;
333 }
334 if (jindices != NULL) {
335 indices = (const uint16_t*)(indexA.ptr() + indexIndex);
336 }
337
Mike Reed826deef2017-04-04 15:32:04 -0400338 int vertexCount = floatCount >> 1; // 2 floats per SkPoint
339 SkVertices::VertexMode mode = static_cast<SkVertices::VertexMode>(modeHandle);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400340 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Mike Reed826deef2017-04-04 15:32:04 -0400341 get_canvas(canvasHandle)->drawVertices(SkVertices::MakeCopy(mode, vertexCount,
342 reinterpret_cast<const SkPoint*>(verts),
343 reinterpret_cast<const SkPoint*>(texs),
344 reinterpret_cast<const SkColor*>(colors),
345 indexCount, indices).get(),
346 SkBlendMode::kModulate, *paint);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400347}
348
Derek Sollenberger4c5efe92015-07-10 13:56:39 -0400349static void drawNinePatch(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle,
350 jlong chunkHandle, jfloat left, jfloat top, jfloat right, jfloat bottom,
351 jlong paintHandle, jint dstDensity, jint srcDensity) {
352
353 Canvas* canvas = get_canvas(canvasHandle);
sergeyv5fd2a1c2016-10-20 15:04:28 -0700354 Bitmap& bitmap = android::bitmap::toBitmap(env, bitmapHandle);
Derek Sollenberger4c5efe92015-07-10 13:56:39 -0400355 const android::Res_png_9patch* chunk = reinterpret_cast<android::Res_png_9patch*>(chunkHandle);
356 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
357
358 if (CC_LIKELY(dstDensity == srcDensity || dstDensity == 0 || srcDensity == 0)) {
sergeyv5fd2a1c2016-10-20 15:04:28 -0700359 canvas->drawNinePatch(bitmap, *chunk, left, top, right, bottom, paint);
Derek Sollenberger4c5efe92015-07-10 13:56:39 -0400360 } else {
Florin Malitaeecff562015-12-21 10:43:01 -0500361 canvas->save(SaveFlags::MatrixClip);
Derek Sollenberger4c5efe92015-07-10 13:56:39 -0400362
363 SkScalar scale = dstDensity / (float)srcDensity;
364 canvas->translate(left, top);
365 canvas->scale(scale, scale);
366
367 Paint filteredPaint;
368 if (paint) {
369 filteredPaint = *paint;
370 }
371 filteredPaint.setFilterQuality(kLow_SkFilterQuality);
372
sergeyv5fd2a1c2016-10-20 15:04:28 -0700373 canvas->drawNinePatch(bitmap, *chunk, 0, 0, (right-left)/scale, (bottom-top)/scale,
Derek Sollenberger4c5efe92015-07-10 13:56:39 -0400374 &filteredPaint);
375
376 canvas->restore();
377 }
378}
379
John Reckcaa08ff2016-10-07 13:21:36 -0700380static void drawBitmap(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400381 jfloat left, jfloat top, jlong paintHandle, jint canvasDensity,
382 jint screenDensity, jint bitmapDensity) {
383 Canvas* canvas = get_canvas(canvasHandle);
sergeyvaed7f582016-10-14 16:30:21 -0700384 Bitmap& bitmap = android::bitmap::toBitmap(env, jbitmap);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400385 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400386
387 if (canvasDensity == bitmapDensity || canvasDensity == 0 || bitmapDensity == 0) {
388 if (screenDensity != 0 && screenDensity != bitmapDensity) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400389 Paint filteredPaint;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400390 if (paint) {
391 filteredPaint = *paint;
392 }
Mike Reed2a1ce8a2015-03-16 11:16:09 -0400393 filteredPaint.setFilterQuality(kLow_SkFilterQuality);
John Reck7c103a32015-04-15 15:52:10 -0700394 canvas->drawBitmap(bitmap, left, top, &filteredPaint);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400395 } else {
John Reck7c103a32015-04-15 15:52:10 -0700396 canvas->drawBitmap(bitmap, left, top, paint);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400397 }
398 } else {
Florin Malitaeecff562015-12-21 10:43:01 -0500399 canvas->save(SaveFlags::MatrixClip);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400400 SkScalar scale = canvasDensity / (float)bitmapDensity;
401 canvas->translate(left, top);
402 canvas->scale(scale, scale);
403
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400404 Paint filteredPaint;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400405 if (paint) {
406 filteredPaint = *paint;
407 }
Mike Reed2a1ce8a2015-03-16 11:16:09 -0400408 filteredPaint.setFilterQuality(kLow_SkFilterQuality);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400409
John Reck7c103a32015-04-15 15:52:10 -0700410 canvas->drawBitmap(bitmap, 0, 0, &filteredPaint);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400411 canvas->restore();
412 }
413}
414
John Reck7c103a32015-04-15 15:52:10 -0700415static void drawBitmapMatrix(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400416 jlong matrixHandle, jlong paintHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400417 const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400418 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
sergeyvfc9999502016-10-17 13:07:38 -0700419 Bitmap& bitmap = android::bitmap::toBitmap(env, jbitmap);
John Reck7c103a32015-04-15 15:52:10 -0700420 get_canvas(canvasHandle)->drawBitmap(bitmap, *matrix, paint);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400421}
422
John Reck7c103a32015-04-15 15:52:10 -0700423static void drawBitmapRect(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400424 float srcLeft, float srcTop, float srcRight, float srcBottom,
425 float dstLeft, float dstTop, float dstRight, float dstBottom,
426 jlong paintHandle, jint screenDensity, jint bitmapDensity) {
427 Canvas* canvas = get_canvas(canvasHandle);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400428 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400429
sergeyvfc9999502016-10-17 13:07:38 -0700430 Bitmap& bitmap = android::bitmap::toBitmap(env, jbitmap);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400431 if (screenDensity != 0 && screenDensity != bitmapDensity) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400432 Paint filteredPaint;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400433 if (paint) {
434 filteredPaint = *paint;
435 }
Mike Reed2a1ce8a2015-03-16 11:16:09 -0400436 filteredPaint.setFilterQuality(kLow_SkFilterQuality);
John Reck7c103a32015-04-15 15:52:10 -0700437 canvas->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400438 dstLeft, dstTop, dstRight, dstBottom, &filteredPaint);
439 } else {
John Reck7c103a32015-04-15 15:52:10 -0700440 canvas->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400441 dstLeft, dstTop, dstRight, dstBottom, paint);
442 }
443}
444
445static void drawBitmapArray(JNIEnv* env, jobject, jlong canvasHandle,
446 jintArray jcolors, jint offset, jint stride,
447 jfloat x, jfloat y, jint width, jint height,
448 jboolean hasAlpha, jlong paintHandle) {
449 // Note: If hasAlpha is false, kRGB_565_SkColorType will be used, which will
450 // correct the alphaType to kOpaque_SkAlphaType.
John Recke9048f32018-03-30 13:44:35 -0700451 SkImageInfo info = SkImageInfo::Make(width, height,
452 hasAlpha ? kN32_SkColorType : kRGB_565_SkColorType,
453 kPremul_SkAlphaType);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400454 SkBitmap bitmap;
Derek Sollenberger3d4eed72014-12-04 15:20:29 -0500455 bitmap.setInfo(info);
Leon Scroggins IIIf51a80d2017-07-12 10:46:35 -0400456 sk_sp<Bitmap> androidBitmap = Bitmap::allocateHeapBitmap(&bitmap);
sergeyvc1c54062016-10-19 18:47:26 -0700457 if (!androidBitmap) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400458 return;
459 }
460
461 if (!GraphicsJNI::SetPixels(env, jcolors, offset, stride, 0, 0, width, height, bitmap)) {
462 return;
463 }
464
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400465 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
sergeyvaed7f582016-10-14 16:30:21 -0700466 get_canvas(canvasHandle)->drawBitmap(*androidBitmap, x, y, paint);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400467}
468
John Reck7c103a32015-04-15 15:52:10 -0700469static void drawBitmapMesh(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400470 jint meshWidth, jint meshHeight, jfloatArray jverts,
471 jint vertIndex, jintArray jcolors, jint colorIndex, jlong paintHandle) {
Mike Reed322bc572018-03-20 13:37:04 -0400472 if (Canvas::GetApiLevel() < __ANDROID_API_P__) {
473 // Before P we forgot to respect these. Now that we do respect them, explicitly
474 // zero them for backward compatibility.
475 vertIndex = 0;
476 colorIndex = 0;
477 }
478
Derek Sollenberger8872b382014-06-23 14:13:53 -0400479 const int ptCount = (meshWidth + 1) * (meshHeight + 1);
480 AutoJavaFloatArray vertA(env, jverts, vertIndex + (ptCount << 1));
481 AutoJavaIntArray colorA(env, jcolors, colorIndex + ptCount);
482
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400483 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
sergeyv5fd2a1c2016-10-20 15:04:28 -0700484 Bitmap& bitmap = android::bitmap::toBitmap(env, jbitmap);
John Reck7c103a32015-04-15 15:52:10 -0700485 get_canvas(canvasHandle)->drawBitmapMesh(bitmap, meshWidth, meshHeight,
Mike Reed322bc572018-03-20 13:37:04 -0400486 vertA.ptr() + vertIndex*2,
487 colorA.ptr() + colorIndex, paint);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400488}
489
490static void drawTextChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text,
491 jint index, jint count, jfloat x, jfloat y, jint bidiFlags,
Seigo Nonaka318ca042017-08-01 16:36:18 -0700492 jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400493 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Seigo Nonaka318ca042017-08-01 16:36:18 -0700494 const Typeface* typeface = paint->getAndroidTypeface();
Derek Sollenberger8872b382014-06-23 14:13:53 -0400495 jchar* jchars = env->GetCharArrayElements(text, NULL);
sergeyvdccca442016-03-21 15:38:21 -0700496 get_canvas(canvasHandle)->drawText(jchars + index, 0, count, count, x, y,
Seigo Nonaka83143d02018-03-14 17:08:28 -0700497 static_cast<minikin::Bidi>(bidiFlags), *paint, typeface, nullptr);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400498 env->ReleaseCharArrayElements(text, jchars, JNI_ABORT);
499}
500
501static void drawTextString(JNIEnv* env, jobject, jlong canvasHandle, jstring text,
502 jint start, jint end, jfloat x, jfloat y, jint bidiFlags,
Seigo Nonaka318ca042017-08-01 16:36:18 -0700503 jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400504 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Seigo Nonaka318ca042017-08-01 16:36:18 -0700505 const Typeface* typeface = paint->getAndroidTypeface();
Derek Sollenberger8872b382014-06-23 14:13:53 -0400506 const int count = end - start;
507 const jchar* jchars = env->GetStringChars(text, NULL);
sergeyvdccca442016-03-21 15:38:21 -0700508 get_canvas(canvasHandle)->drawText(jchars + start, 0, count, count, x, y,
Seigo Nonaka83143d02018-03-14 17:08:28 -0700509 static_cast<minikin::Bidi>(bidiFlags), *paint, typeface, nullptr);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400510 env->ReleaseStringChars(text, jchars);
511}
512
513static void drawTextRunChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text, jint index,
514 jint count, jint contextIndex, jint contextCount, jfloat x, jfloat y,
Seigo Nonaka83143d02018-03-14 17:08:28 -0700515 jboolean isRtl, jlong paintHandle, jlong mtHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400516 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Seigo Nonaka783f9612018-01-20 12:11:13 -0800517 minikin::MeasuredText* mt = reinterpret_cast<minikin::MeasuredText*>(mtHandle);
Seigo Nonaka318ca042017-08-01 16:36:18 -0700518 const Typeface* typeface = paint->getAndroidTypeface();
Derek Sollenberger8872b382014-06-23 14:13:53 -0400519
Seigo Nonaka7c93e862017-10-25 16:34:48 -0700520 const minikin::Bidi bidiFlags = isRtl ? minikin::Bidi::FORCE_RTL : minikin::Bidi::FORCE_LTR;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400521 jchar* jchars = env->GetCharArrayElements(text, NULL);
sergeyvdccca442016-03-21 15:38:21 -0700522 get_canvas(canvasHandle)->drawText(jchars + contextIndex, index - contextIndex, count,
Seigo Nonaka83143d02018-03-14 17:08:28 -0700523 contextCount, x, y, bidiFlags, *paint, typeface, mt);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400524 env->ReleaseCharArrayElements(text, jchars, JNI_ABORT);
525}
526
527static void drawTextRunString(JNIEnv* env, jobject obj, jlong canvasHandle, jstring text,
528 jint start, jint end, jint contextStart, jint contextEnd,
Seigo Nonaka318ca042017-08-01 16:36:18 -0700529 jfloat x, jfloat y, jboolean isRtl, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400530 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Seigo Nonaka318ca042017-08-01 16:36:18 -0700531 const Typeface* typeface = paint->getAndroidTypeface();
Derek Sollenberger8872b382014-06-23 14:13:53 -0400532
Seigo Nonaka7c93e862017-10-25 16:34:48 -0700533 const minikin::Bidi bidiFlags = isRtl ? minikin::Bidi::FORCE_RTL : minikin::Bidi::FORCE_LTR;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400534 jint count = end - start;
535 jint contextCount = contextEnd - contextStart;
536 const jchar* jchars = env->GetStringChars(text, NULL);
sergeyvdccca442016-03-21 15:38:21 -0700537 get_canvas(canvasHandle)->drawText(jchars + contextStart, start - contextStart, count,
Seigo Nonaka83143d02018-03-14 17:08:28 -0700538 contextCount, x, y, bidiFlags, *paint, typeface, nullptr);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400539 env->ReleaseStringChars(text, jchars);
540}
541
Derek Sollenberger8872b382014-06-23 14:13:53 -0400542static void drawTextOnPathChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text,
543 jint index, jint count, jlong pathHandle, jfloat hOffset,
Seigo Nonaka318ca042017-08-01 16:36:18 -0700544 jfloat vOffset, jint bidiFlags, jlong paintHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400545 SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400546 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Seigo Nonaka318ca042017-08-01 16:36:18 -0700547 const Typeface* typeface = paint->getAndroidTypeface();
Derek Sollenberger8872b382014-06-23 14:13:53 -0400548
549 jchar* jchars = env->GetCharArrayElements(text, NULL);
550
Seigo Nonaka7c93e862017-10-25 16:34:48 -0700551 get_canvas(canvasHandle)->drawTextOnPath(jchars + index, count,
552 static_cast<minikin::Bidi>(bidiFlags), *path, hOffset, vOffset, *paint, typeface);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400553
554 env->ReleaseCharArrayElements(text, jchars, 0);
555}
556
557static void drawTextOnPathString(JNIEnv* env, jobject, jlong canvasHandle, jstring text,
558 jlong pathHandle, jfloat hOffset, jfloat vOffset,
Seigo Nonaka318ca042017-08-01 16:36:18 -0700559 jint bidiFlags, jlong paintHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400560 SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400561 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Seigo Nonaka318ca042017-08-01 16:36:18 -0700562 const Typeface* typeface = paint->getAndroidTypeface();
Derek Sollenberger8872b382014-06-23 14:13:53 -0400563
564 const jchar* jchars = env->GetStringChars(text, NULL);
565 int count = env->GetStringLength(text);
566
Seigo Nonaka7c93e862017-10-25 16:34:48 -0700567 get_canvas(canvasHandle)->drawTextOnPath(jchars, count, static_cast<minikin::Bidi>(bidiFlags),
568 *path, hOffset, vOffset, *paint, typeface);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400569
570 env->ReleaseStringChars(text, jchars);
571}
572
Chris Craikbfa0b292017-01-19 19:12:36 -0800573static void setDrawFilter(jlong canvasHandle, jlong filterHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400574 get_canvas(canvasHandle)->setDrawFilter(reinterpret_cast<SkDrawFilter*>(filterHandle));
575}
576
577static void freeCaches(JNIEnv* env, jobject) {
578 SkGraphics::PurgeFontCache();
579}
580
581static void freeTextLayoutCaches(JNIEnv* env, jobject) {
Seigo Nonakaae1aa852016-06-09 19:42:51 +0900582 minikin::Layout::purgeCaches();
Derek Sollenberger8872b382014-06-23 14:13:53 -0400583}
584
Stan Iliev7717e222018-02-05 18:04:11 -0500585static void setCompatibilityVersion(JNIEnv* env, jobject, jint apiLevel) {
586 Canvas::setCompatibilityVersion(apiLevel);
587}
588
589
Derek Sollenberger8872b382014-06-23 14:13:53 -0400590}; // namespace CanvasJNI
591
Daniel Micay76f6a862015-09-19 17:31:01 -0400592static const JNINativeMethod gMethods[] = {
John Reckcaa08ff2016-10-07 13:21:36 -0700593 {"nGetNativeFinalizer", "()J", (void*) CanvasJNI::getNativeFinalizer},
594 {"nInitRaster", "(Landroid/graphics/Bitmap;)J", (void*) CanvasJNI::initRaster},
595 {"nFreeCaches", "()V", (void*) CanvasJNI::freeCaches},
596 {"nFreeTextLayoutCaches", "()V", (void*) CanvasJNI::freeTextLayoutCaches},
Stan Iliev7717e222018-02-05 18:04:11 -0500597 {"nSetCompatibilityVersion", "(I)V", (void*) CanvasJNI::setCompatibilityVersion},
John Reck5cb74bc2016-10-07 11:24:44 -0700598
599 // ------------ @FastNative ----------------
John Reckcaa08ff2016-10-07 13:21:36 -0700600 {"nSetBitmap", "(JLandroid/graphics/Bitmap;)V", (void*) CanvasJNI::setBitmap},
Chris Craikbfa0b292017-01-19 19:12:36 -0800601 {"nGetClipBounds","(JLandroid/graphics/Rect;)Z", (void*) CanvasJNI::getClipBounds},
602
603 // ------------ @CriticalNative ----------------
John Reckcaa08ff2016-10-07 13:21:36 -0700604 {"nIsOpaque","(J)Z", (void*) CanvasJNI::isOpaque},
605 {"nGetWidth","(J)I", (void*) CanvasJNI::getWidth},
606 {"nGetHeight","(J)I", (void*) CanvasJNI::getHeight},
John Reckcaa08ff2016-10-07 13:21:36 -0700607 {"nSave","(JI)I", (void*) CanvasJNI::save},
608 {"nSaveLayer","(JFFFFJI)I", (void*) CanvasJNI::saveLayer},
609 {"nSaveLayerAlpha","(JFFFFII)I", (void*) CanvasJNI::saveLayerAlpha},
610 {"nGetSaveCount","(J)I", (void*) CanvasJNI::getSaveCount},
Chris Craikbfa0b292017-01-19 19:12:36 -0800611 {"nRestore","(J)Z", (void*) CanvasJNI::restore},
612 {"nRestoreToCount","(JI)V", (void*) CanvasJNI::restoreToCount},
613 {"nGetMatrix", "(JJ)V", (void*)CanvasJNI::getMatrix},
John Reckcaa08ff2016-10-07 13:21:36 -0700614 {"nSetMatrix","(JJ)V", (void*) CanvasJNI::setMatrix},
615 {"nConcat","(JJ)V", (void*) CanvasJNI::concat},
616 {"nRotate","(JF)V", (void*) CanvasJNI::rotate},
617 {"nScale","(JFF)V", (void*) CanvasJNI::scale},
618 {"nSkew","(JFF)V", (void*) CanvasJNI::skew},
619 {"nTranslate","(JFF)V", (void*) CanvasJNI::translate},
John Reckcaa08ff2016-10-07 13:21:36 -0700620 {"nQuickReject","(JJ)Z", (void*) CanvasJNI::quickRejectPath},
621 {"nQuickReject","(JFFFF)Z", (void*)CanvasJNI::quickRejectRect},
622 {"nClipRect","(JFFFFI)Z", (void*) CanvasJNI::clipRect},
623 {"nClipPath","(JJI)Z", (void*) CanvasJNI::clipPath},
John Reckcaa08ff2016-10-07 13:21:36 -0700624 {"nSetDrawFilter", "(JJ)V", (void*) CanvasJNI::setDrawFilter},
625};
626
627// If called from Canvas these are regular JNI
628// If called from DisplayListCanvas they are @FastNative
629static const JNINativeMethod gDrawMethods[] = {
630 {"nDrawColor","(JII)V", (void*) CanvasJNI::drawColor},
631 {"nDrawPaint","(JJ)V", (void*) CanvasJNI::drawPaint},
632 {"nDrawPoint", "(JFFJ)V", (void*) CanvasJNI::drawPoint},
633 {"nDrawPoints", "(J[FIIJ)V", (void*) CanvasJNI::drawPoints},
634 {"nDrawLine", "(JFFFFJ)V", (void*) CanvasJNI::drawLine},
635 {"nDrawLines", "(J[FIIJ)V", (void*) CanvasJNI::drawLines},
636 {"nDrawRect","(JFFFFJ)V", (void*) CanvasJNI::drawRect},
637 {"nDrawRegion", "(JJJ)V", (void*) CanvasJNI::drawRegion },
638 {"nDrawRoundRect","(JFFFFFFJ)V", (void*) CanvasJNI::drawRoundRect},
639 {"nDrawCircle","(JFFFJ)V", (void*) CanvasJNI::drawCircle},
640 {"nDrawOval","(JFFFFJ)V", (void*) CanvasJNI::drawOval},
641 {"nDrawArc","(JFFFFFFZJ)V", (void*) CanvasJNI::drawArc},
642 {"nDrawPath","(JJJ)V", (void*) CanvasJNI::drawPath},
643 {"nDrawVertices", "(JII[FI[FI[II[SIIJ)V", (void*)CanvasJNI::drawVertices},
644 {"nDrawNinePatch", "(JJJFFFFJII)V", (void*)CanvasJNI::drawNinePatch},
645 {"nDrawBitmapMatrix", "(JLandroid/graphics/Bitmap;JJ)V", (void*)CanvasJNI::drawBitmapMatrix},
646 {"nDrawBitmapMesh", "(JLandroid/graphics/Bitmap;II[FI[IIJ)V", (void*)CanvasJNI::drawBitmapMesh},
647 {"nDrawBitmap","(JLandroid/graphics/Bitmap;FFJIII)V", (void*) CanvasJNI::drawBitmap},
648 {"nDrawBitmap","(JLandroid/graphics/Bitmap;FFFFFFFFJII)V", (void*) CanvasJNI::drawBitmapRect},
649 {"nDrawBitmap", "(J[IIIFFIIZJ)V", (void*)CanvasJNI::drawBitmapArray},
Seigo Nonaka318ca042017-08-01 16:36:18 -0700650 {"nDrawText","(J[CIIFFIJ)V", (void*) CanvasJNI::drawTextChars},
651 {"nDrawText","(JLjava/lang/String;IIFFIJ)V", (void*) CanvasJNI::drawTextString},
Seigo Nonaka83143d02018-03-14 17:08:28 -0700652 {"nDrawTextRun","(J[CIIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunChars},
Seigo Nonaka318ca042017-08-01 16:36:18 -0700653 {"nDrawTextRun","(JLjava/lang/String;IIIIFFZJ)V", (void*) CanvasJNI::drawTextRunString},
654 {"nDrawTextOnPath","(J[CIIJFFIJ)V", (void*) CanvasJNI::drawTextOnPathChars},
655 {"nDrawTextOnPath","(JLjava/lang/String;JFFIJ)V", (void*) CanvasJNI::drawTextOnPathString},
Derek Sollenberger8872b382014-06-23 14:13:53 -0400656};
657
658int register_android_graphics_Canvas(JNIEnv* env) {
John Reckcaa08ff2016-10-07 13:21:36 -0700659 int ret = 0;
660 ret |= RegisterMethodsOrDie(env, "android/graphics/Canvas", gMethods, NELEM(gMethods));
661 ret |= RegisterMethodsOrDie(env, "android/graphics/BaseCanvas", gDrawMethods, NELEM(gDrawMethods));
662 ret |= RegisterMethodsOrDie(env, "android/view/RecordingCanvas", gDrawMethods, NELEM(gDrawMethods));
663 return ret;
664
Derek Sollenberger8872b382014-06-23 14:13:53 -0400665}
666
667}; // namespace android