blob: c49287ccddb29cdcc4356d7e28a7960051a3dbb8 [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
Derek Sollenberger4c5efe92015-07-10 13:56:39 -040021#include <androidfw/ResourceTypes.h>
sergeyvdccca442016-03-21 15:38:21 -070022#include <hwui/Canvas.h>
23#include <hwui/Paint.h>
sergeyvbad99182016-03-17 11:24:22 -070024#include <hwui/Typeface.h>
sergeyvdccca442016-03-21 15:38:21 -070025#include <minikin/Layout.h>
Derek Sollenberger4c5efe92015-07-10 13:56:39 -040026
27#include "Bitmap.h"
Derek Sollenbergeracb40992014-07-21 15:22:10 -040028#include "SkDrawFilter.h"
Derek Sollenberger8872b382014-06-23 14:13:53 -040029#include "SkGraphics.h"
Derek Sollenberger8872b382014-06-23 14:13:53 -040030
31namespace android {
32
33namespace CanvasJNI {
34
35static Canvas* get_canvas(jlong canvasHandle) {
36 return reinterpret_cast<Canvas*>(canvasHandle);
37}
38
Richard Uhler775873a2015-12-29 12:37:39 -080039static void delete_canvas(Canvas* canvas) {
40 delete canvas;
41}
42
43static jlong getNativeFinalizer(JNIEnv* env, jobject clazz) {
44 return static_cast<jlong>(reinterpret_cast<uintptr_t>(&delete_canvas));
Derek Sollenberger8872b382014-06-23 14:13:53 -040045}
46
47// Native wrapper constructor used by Canvas(Bitmap)
John Reckc1b33d62015-04-22 09:04:45 -070048static jlong initRaster(JNIEnv* env, jobject, jobject jbitmap) {
John Reck3731dc22015-04-13 15:20:29 -070049 SkBitmap bitmap;
John Reckc1b33d62015-04-22 09:04:45 -070050 if (jbitmap != NULL) {
John Reck3731dc22015-04-13 15:20:29 -070051 GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
John Reckc1b33d62015-04-22 09:04:45 -070052 }
John Reck3731dc22015-04-13 15:20:29 -070053 return reinterpret_cast<jlong>(Canvas::create_canvas(bitmap));
Derek Sollenberger8872b382014-06-23 14:13:53 -040054}
55
56// Set the given bitmap as the new draw target (wrapped in a new SkCanvas),
57// optionally copying canvas matrix & clip state.
John Reckc1b33d62015-04-22 09:04:45 -070058static void setBitmap(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap) {
John Reck3731dc22015-04-13 15:20:29 -070059 SkBitmap bitmap;
John Reckc1b33d62015-04-22 09:04:45 -070060 if (jbitmap != NULL) {
John Reck3731dc22015-04-13 15:20:29 -070061 GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
John Reckc1b33d62015-04-22 09:04:45 -070062 }
John Reck3731dc22015-04-13 15:20:29 -070063 get_canvas(canvasHandle)->setBitmap(bitmap);
Derek Sollenberger8872b382014-06-23 14:13:53 -040064}
65
Chris Craikbfa0b292017-01-19 19:12:36 -080066static jboolean isOpaque(jlong canvasHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -040067 return get_canvas(canvasHandle)->isOpaque() ? JNI_TRUE : JNI_FALSE;
68}
69
Chris Craikbfa0b292017-01-19 19:12:36 -080070static jint getWidth(jlong canvasHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -040071 return static_cast<jint>(get_canvas(canvasHandle)->width());
72}
73
Chris Craikbfa0b292017-01-19 19:12:36 -080074static jint getHeight(jlong canvasHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -040075 return static_cast<jint>(get_canvas(canvasHandle)->height());
76}
77
Chris Craikbfa0b292017-01-19 19:12:36 -080078static void setHighContrastText(jlong canvasHandle, jboolean highContrastText) {
Derek Sollenberger6578a982015-07-13 13:24:29 -040079 Canvas* canvas = get_canvas(canvasHandle);
80 canvas->setHighContrastText(highContrastText);
81}
82
Chris Craikbfa0b292017-01-19 19:12:36 -080083static jint save(jlong canvasHandle, jint flagsHandle) {
Florin Malitaeecff562015-12-21 10:43:01 -050084 SaveFlags::Flags flags = static_cast<SaveFlags::Flags>(flagsHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -040085 return static_cast<jint>(get_canvas(canvasHandle)->save(flags));
86}
87
Chris Craikbfa0b292017-01-19 19:12:36 -080088static jint saveLayer(jlong canvasHandle, jfloat l, jfloat t,
Derek Sollenberger8872b382014-06-23 14:13:53 -040089 jfloat r, jfloat b, jlong paintHandle, jint flagsHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -040090 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Florin Malitaeecff562015-12-21 10:43:01 -050091 SaveFlags::Flags flags = static_cast<SaveFlags::Flags>(flagsHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -040092 return static_cast<jint>(get_canvas(canvasHandle)->saveLayer(l, t, r, b, paint, flags));
93}
94
Chris Craikbfa0b292017-01-19 19:12:36 -080095static jint saveLayerAlpha(jlong canvasHandle, jfloat l, jfloat t,
Derek Sollenberger8872b382014-06-23 14:13:53 -040096 jfloat r, jfloat b, jint alpha, jint flagsHandle) {
Florin Malitaeecff562015-12-21 10:43:01 -050097 SaveFlags::Flags flags = static_cast<SaveFlags::Flags>(flagsHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -040098 return static_cast<jint>(get_canvas(canvasHandle)->saveLayerAlpha(l, t, r, b, alpha, flags));
99}
100
Chris Craikbfa0b292017-01-19 19:12:36 -0800101static bool restore(jlong canvasHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400102 Canvas* canvas = get_canvas(canvasHandle);
Chris Craikbfa0b292017-01-19 19:12:36 -0800103 if (canvas->getSaveCount() <= 1) {
104 return false; // cannot restore anymore
Derek Sollenberger8872b382014-06-23 14:13:53 -0400105 }
106 canvas->restore();
Chris Craikbfa0b292017-01-19 19:12:36 -0800107 return true; // success
Derek Sollenberger8872b382014-06-23 14:13:53 -0400108}
109
Chris Craikbfa0b292017-01-19 19:12:36 -0800110static void restoreToCount(jlong canvasHandle, jint saveCount) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400111 Canvas* canvas = get_canvas(canvasHandle);
Chris Craikbfa0b292017-01-19 19:12:36 -0800112 canvas->restoreToCount(saveCount);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400113}
114
Chris Craikbfa0b292017-01-19 19:12:36 -0800115static jint getSaveCount(jlong canvasHandle) {
116 return static_cast<jint>(get_canvas(canvasHandle)->getSaveCount());
117}
118
119static void getMatrix(jlong canvasHandle, jlong matrixHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400120 SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
121 get_canvas(canvasHandle)->getMatrix(matrix);
122}
123
Chris Craikbfa0b292017-01-19 19:12:36 -0800124static void setMatrix(jlong canvasHandle, jlong matrixHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400125 const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
126 get_canvas(canvasHandle)->setMatrix(matrix ? *matrix : SkMatrix::I());
127}
128
Chris Craikbfa0b292017-01-19 19:12:36 -0800129static void concat(jlong canvasHandle, jlong matrixHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400130 const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
131 get_canvas(canvasHandle)->concat(*matrix);
132}
133
Chris Craikbfa0b292017-01-19 19:12:36 -0800134static void rotate(jlong canvasHandle, jfloat degrees) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400135 get_canvas(canvasHandle)->rotate(degrees);
136}
137
Chris Craikbfa0b292017-01-19 19:12:36 -0800138static void scale(jlong canvasHandle, jfloat sx, jfloat sy) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400139 get_canvas(canvasHandle)->scale(sx, sy);
140}
141
Chris Craikbfa0b292017-01-19 19:12:36 -0800142static void skew(jlong canvasHandle, jfloat sx, jfloat sy) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400143 get_canvas(canvasHandle)->skew(sx, sy);
144}
145
Chris Craikbfa0b292017-01-19 19:12:36 -0800146static void translate(jlong canvasHandle, jfloat dx, jfloat dy) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400147 get_canvas(canvasHandle)->translate(dx, dy);
148}
149
150static jboolean getClipBounds(JNIEnv* env, jobject, jlong canvasHandle, jobject bounds) {
151 SkRect r;
152 SkIRect ir;
153 bool result = get_canvas(canvasHandle)->getClipBounds(&r);
154
155 if (!result) {
156 r.setEmpty();
157 }
158 r.round(&ir);
159
160 (void)GraphicsJNI::irect_to_jrect(ir, env, bounds);
161 return result ? JNI_TRUE : JNI_FALSE;
162}
163
Chris Craikbfa0b292017-01-19 19:12:36 -0800164static jboolean quickRejectRect(jlong canvasHandle,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400165 jfloat left, jfloat top, jfloat right, jfloat bottom) {
166 bool result = get_canvas(canvasHandle)->quickRejectRect(left, top, right, bottom);
167 return result ? JNI_TRUE : JNI_FALSE;
168}
169
Chris Craikbfa0b292017-01-19 19:12:36 -0800170static jboolean quickRejectPath(jlong canvasHandle, jlong pathHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400171 SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
172 bool result = get_canvas(canvasHandle)->quickRejectPath(*path);
173 return result ? JNI_TRUE : JNI_FALSE;
174}
175
Mike Reed6e49c9f2016-12-02 15:36:59 -0500176// SkRegion::Op and SkClipOp are numerically identical, so we can freely cast
177// from one to the other (though SkClipOp is destined to become a strict subset)
Mike Reed6c67f1d2016-12-14 10:29:54 -0500178static_assert(SkRegion::kDifference_Op == static_cast<SkRegion::Op>(SkClipOp::kDifference), "");
179static_assert(SkRegion::kIntersect_Op == static_cast<SkRegion::Op>(SkClipOp::kIntersect), "");
Chris Craik66b9d442016-12-16 17:49:48 +0000180static_assert(SkRegion::kUnion_Op == static_cast<SkRegion::Op>(SkClipOp::kUnion), "");
181static_assert(SkRegion::kXOR_Op == static_cast<SkRegion::Op>(SkClipOp::kXOR), "");
182static_assert(SkRegion::kReverseDifference_Op == static_cast<SkRegion::Op>(SkClipOp::kReverseDifference), "");
183static_assert(SkRegion::kReplace_Op == static_cast<SkRegion::Op>(SkClipOp::kReplace), "");
Mike Reed6e49c9f2016-12-02 15:36:59 -0500184
185static SkClipOp opHandleToClipOp(jint opHandle) {
186 // The opHandle is defined in Canvas.java to be Region::Op
187 SkRegion::Op rgnOp = static_cast<SkRegion::Op>(opHandle);
188
189 // In the future, when we no longer support the wide range of ops (e.g. Union, Xor)
190 // this function can perform a range check and throw an unsupported-exception.
191 // e.g. if (rgnOp != kIntersect && rgnOp != kDifference) throw...
192
193 // Skia now takes a different type, SkClipOp, as the parameter to clipping calls
194 // This type is binary compatible with SkRegion::Op, so a static_cast<> is safe.
195 return static_cast<SkClipOp>(rgnOp);
196}
197
Chris Craikbfa0b292017-01-19 19:12:36 -0800198static jboolean clipRect(jlong canvasHandle, jfloat l, jfloat t,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400199 jfloat r, jfloat b, jint opHandle) {
Mike Reed6e49c9f2016-12-02 15:36:59 -0500200 bool nonEmptyClip = get_canvas(canvasHandle)->clipRect(l, t, r, b,
201 opHandleToClipOp(opHandle));
Chris Craik5ec6a282015-06-23 15:42:12 -0700202 return nonEmptyClip ? JNI_TRUE : JNI_FALSE;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400203}
204
Chris Craikbfa0b292017-01-19 19:12:36 -0800205static jboolean clipPath(jlong canvasHandle, jlong pathHandle,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400206 jint opHandle) {
207 SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
Mike Reed6e49c9f2016-12-02 15:36:59 -0500208 bool nonEmptyClip = get_canvas(canvasHandle)->clipPath(path, opHandleToClipOp(opHandle));
Chris Craik5ec6a282015-06-23 15:42:12 -0700209 return nonEmptyClip ? JNI_TRUE : JNI_FALSE;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400210}
211
Derek Sollenberger8872b382014-06-23 14:13:53 -0400212static void drawColor(JNIEnv* env, jobject, jlong canvasHandle, jint color, jint modeHandle) {
Mike Reed260ab722016-10-07 15:59:20 -0400213 SkBlendMode mode = static_cast<SkBlendMode>(modeHandle);
Chris Craik1526a452015-03-06 18:42:15 +0000214 get_canvas(canvasHandle)->drawColor(color, mode);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400215}
216
217static void drawPaint(JNIEnv* env, jobject, jlong canvasHandle, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400218 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400219 get_canvas(canvasHandle)->drawPaint(*paint);
220}
221
222static void drawPoint(JNIEnv*, jobject, jlong canvasHandle, jfloat x, jfloat y,
223 jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400224 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400225 get_canvas(canvasHandle)->drawPoint(x, y, *paint);
226}
227
228static void drawPoints(JNIEnv* env, jobject, jlong canvasHandle, jfloatArray jptsArray,
229 jint offset, jint count, jlong paintHandle) {
230 NPE_CHECK_RETURN_VOID(env, jptsArray);
231 AutoJavaFloatArray autoPts(env, jptsArray);
232 float* floats = autoPts.ptr();
233 const int length = autoPts.length();
234
235 if ((offset | count) < 0 || offset + count > length) {
236 doThrowAIOOBE(env);
237 return;
238 }
239
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400240 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400241 get_canvas(canvasHandle)->drawPoints(floats + offset, count, *paint);
242}
243
244static void drawLine(JNIEnv* env, jobject, jlong canvasHandle, jfloat startX, jfloat startY,
245 jfloat stopX, jfloat stopY, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400246 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400247 get_canvas(canvasHandle)->drawLine(startX, startY, stopX, stopY, *paint);
248}
249
250static void drawLines(JNIEnv* env, jobject, jlong canvasHandle, jfloatArray jptsArray,
251 jint offset, jint count, jlong paintHandle) {
252 NPE_CHECK_RETURN_VOID(env, jptsArray);
253 AutoJavaFloatArray autoPts(env, jptsArray);
254 float* floats = autoPts.ptr();
255 const int length = autoPts.length();
256
257 if ((offset | count) < 0 || offset + count > length) {
258 doThrowAIOOBE(env);
259 return;
260 }
261
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400262 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400263 get_canvas(canvasHandle)->drawLines(floats + offset, count, *paint);
264}
265
266static void drawRect(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
267 jfloat right, jfloat bottom, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400268 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400269 get_canvas(canvasHandle)->drawRect(left, top, right, bottom, *paint);
270}
271
Derek Sollenberger94394b32015-07-10 09:58:41 -0400272static void drawRegion(JNIEnv* env, jobject, jlong canvasHandle, jlong regionHandle,
273 jlong paintHandle) {
274 const SkRegion* region = reinterpret_cast<SkRegion*>(regionHandle);
275 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
276 get_canvas(canvasHandle)->drawRegion(*region, *paint);
277}
278
Derek Sollenberger8872b382014-06-23 14:13:53 -0400279static void drawRoundRect(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
280 jfloat right, jfloat bottom, jfloat rx, jfloat ry, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400281 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400282 get_canvas(canvasHandle)->drawRoundRect(left, top, right, bottom, rx, ry, *paint);
283}
284
285static void drawCircle(JNIEnv* env, jobject, jlong canvasHandle, jfloat cx, jfloat cy,
286 jfloat radius, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400287 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400288 get_canvas(canvasHandle)->drawCircle(cx, cy, radius, *paint);
289}
290
291static void drawOval(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
292 jfloat right, jfloat bottom, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400293 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400294 get_canvas(canvasHandle)->drawOval(left, top, right, bottom, *paint);
295}
296
297static void drawArc(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
298 jfloat right, jfloat bottom, jfloat startAngle, jfloat sweepAngle,
299 jboolean useCenter, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400300 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400301 get_canvas(canvasHandle)->drawArc(left, top, right, bottom, startAngle, sweepAngle,
302 useCenter, *paint);
303}
304
305static void drawPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle,
306 jlong paintHandle) {
307 const SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400308 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400309 get_canvas(canvasHandle)->drawPath(*path, *paint);
310}
311
312static void drawVertices(JNIEnv* env, jobject, jlong canvasHandle,
313 jint modeHandle, jint vertexCount,
314 jfloatArray jverts, jint vertIndex,
315 jfloatArray jtexs, jint texIndex,
316 jintArray jcolors, jint colorIndex,
317 jshortArray jindices, jint indexIndex,
318 jint indexCount, jlong paintHandle) {
319 AutoJavaFloatArray vertA(env, jverts, vertIndex + vertexCount);
320 AutoJavaFloatArray texA(env, jtexs, texIndex + vertexCount);
321 AutoJavaIntArray colorA(env, jcolors, colorIndex + vertexCount);
322 AutoJavaShortArray indexA(env, jindices, indexIndex + indexCount);
323
324 const float* verts = vertA.ptr() + vertIndex;
325 const float* texs = texA.ptr() + vertIndex;
326 const int* colors = NULL;
327 const uint16_t* indices = NULL;
328
329 if (jcolors != NULL) {
330 colors = colorA.ptr() + colorIndex;
331 }
332 if (jindices != NULL) {
333 indices = (const uint16_t*)(indexA.ptr() + indexIndex);
334 }
335
336 SkCanvas::VertexMode mode = static_cast<SkCanvas::VertexMode>(modeHandle);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400337 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400338 get_canvas(canvasHandle)->drawVertices(mode, vertexCount, verts, texs, colors,
339 indices, indexCount, *paint);
340}
341
Derek Sollenberger4c5efe92015-07-10 13:56:39 -0400342static void drawNinePatch(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle,
343 jlong chunkHandle, jfloat left, jfloat top, jfloat right, jfloat bottom,
344 jlong paintHandle, jint dstDensity, jint srcDensity) {
345
346 Canvas* canvas = get_canvas(canvasHandle);
sergeyv5fd2a1c2016-10-20 15:04:28 -0700347 Bitmap& bitmap = android::bitmap::toBitmap(env, bitmapHandle);
Derek Sollenberger4c5efe92015-07-10 13:56:39 -0400348 const android::Res_png_9patch* chunk = reinterpret_cast<android::Res_png_9patch*>(chunkHandle);
349 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
350
351 if (CC_LIKELY(dstDensity == srcDensity || dstDensity == 0 || srcDensity == 0)) {
sergeyv5fd2a1c2016-10-20 15:04:28 -0700352 canvas->drawNinePatch(bitmap, *chunk, left, top, right, bottom, paint);
Derek Sollenberger4c5efe92015-07-10 13:56:39 -0400353 } else {
Florin Malitaeecff562015-12-21 10:43:01 -0500354 canvas->save(SaveFlags::MatrixClip);
Derek Sollenberger4c5efe92015-07-10 13:56:39 -0400355
356 SkScalar scale = dstDensity / (float)srcDensity;
357 canvas->translate(left, top);
358 canvas->scale(scale, scale);
359
360 Paint filteredPaint;
361 if (paint) {
362 filteredPaint = *paint;
363 }
364 filteredPaint.setFilterQuality(kLow_SkFilterQuality);
365
sergeyv5fd2a1c2016-10-20 15:04:28 -0700366 canvas->drawNinePatch(bitmap, *chunk, 0, 0, (right-left)/scale, (bottom-top)/scale,
Derek Sollenberger4c5efe92015-07-10 13:56:39 -0400367 &filteredPaint);
368
369 canvas->restore();
370 }
371}
372
John Reckcaa08ff2016-10-07 13:21:36 -0700373static void drawBitmap(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400374 jfloat left, jfloat top, jlong paintHandle, jint canvasDensity,
375 jint screenDensity, jint bitmapDensity) {
376 Canvas* canvas = get_canvas(canvasHandle);
sergeyvaed7f582016-10-14 16:30:21 -0700377 Bitmap& bitmap = android::bitmap::toBitmap(env, jbitmap);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400378 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400379
380 if (canvasDensity == bitmapDensity || canvasDensity == 0 || bitmapDensity == 0) {
381 if (screenDensity != 0 && screenDensity != bitmapDensity) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400382 Paint filteredPaint;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400383 if (paint) {
384 filteredPaint = *paint;
385 }
Mike Reed2a1ce8a2015-03-16 11:16:09 -0400386 filteredPaint.setFilterQuality(kLow_SkFilterQuality);
John Reck7c103a32015-04-15 15:52:10 -0700387 canvas->drawBitmap(bitmap, left, top, &filteredPaint);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400388 } else {
John Reck7c103a32015-04-15 15:52:10 -0700389 canvas->drawBitmap(bitmap, left, top, paint);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400390 }
391 } else {
Florin Malitaeecff562015-12-21 10:43:01 -0500392 canvas->save(SaveFlags::MatrixClip);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400393 SkScalar scale = canvasDensity / (float)bitmapDensity;
394 canvas->translate(left, top);
395 canvas->scale(scale, scale);
396
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400397 Paint filteredPaint;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400398 if (paint) {
399 filteredPaint = *paint;
400 }
Mike Reed2a1ce8a2015-03-16 11:16:09 -0400401 filteredPaint.setFilterQuality(kLow_SkFilterQuality);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400402
John Reck7c103a32015-04-15 15:52:10 -0700403 canvas->drawBitmap(bitmap, 0, 0, &filteredPaint);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400404 canvas->restore();
405 }
406}
407
John Reck7c103a32015-04-15 15:52:10 -0700408static void drawBitmapMatrix(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400409 jlong matrixHandle, jlong paintHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400410 const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400411 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
sergeyvfc9999502016-10-17 13:07:38 -0700412 Bitmap& bitmap = android::bitmap::toBitmap(env, jbitmap);
John Reck7c103a32015-04-15 15:52:10 -0700413 get_canvas(canvasHandle)->drawBitmap(bitmap, *matrix, paint);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400414}
415
John Reck7c103a32015-04-15 15:52:10 -0700416static void drawBitmapRect(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400417 float srcLeft, float srcTop, float srcRight, float srcBottom,
418 float dstLeft, float dstTop, float dstRight, float dstBottom,
419 jlong paintHandle, jint screenDensity, jint bitmapDensity) {
420 Canvas* canvas = get_canvas(canvasHandle);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400421 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400422
sergeyvfc9999502016-10-17 13:07:38 -0700423 Bitmap& bitmap = android::bitmap::toBitmap(env, jbitmap);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400424 if (screenDensity != 0 && screenDensity != bitmapDensity) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400425 Paint filteredPaint;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400426 if (paint) {
427 filteredPaint = *paint;
428 }
Mike Reed2a1ce8a2015-03-16 11:16:09 -0400429 filteredPaint.setFilterQuality(kLow_SkFilterQuality);
John Reck7c103a32015-04-15 15:52:10 -0700430 canvas->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400431 dstLeft, dstTop, dstRight, dstBottom, &filteredPaint);
432 } else {
John Reck7c103a32015-04-15 15:52:10 -0700433 canvas->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400434 dstLeft, dstTop, dstRight, dstBottom, paint);
435 }
436}
437
438static void drawBitmapArray(JNIEnv* env, jobject, jlong canvasHandle,
439 jintArray jcolors, jint offset, jint stride,
440 jfloat x, jfloat y, jint width, jint height,
441 jboolean hasAlpha, jlong paintHandle) {
442 // Note: If hasAlpha is false, kRGB_565_SkColorType will be used, which will
443 // correct the alphaType to kOpaque_SkAlphaType.
Romain Guy253f2c22016-09-28 17:34:42 -0700444 SkImageInfo info = SkImageInfo::MakeN32(width, height, kPremul_SkAlphaType,
445 GraphicsJNI::defaultColorSpace());
Derek Sollenberger8872b382014-06-23 14:13:53 -0400446 SkBitmap bitmap;
Derek Sollenberger3d4eed72014-12-04 15:20:29 -0500447 bitmap.setInfo(info);
sergeyvc1c54062016-10-19 18:47:26 -0700448 sk_sp<Bitmap> androidBitmap = Bitmap::allocateHeapBitmap(&bitmap, NULL);
449 if (!androidBitmap) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400450 return;
451 }
452
453 if (!GraphicsJNI::SetPixels(env, jcolors, offset, stride, 0, 0, width, height, bitmap)) {
454 return;
455 }
456
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400457 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
sergeyvaed7f582016-10-14 16:30:21 -0700458 get_canvas(canvasHandle)->drawBitmap(*androidBitmap, x, y, paint);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400459}
460
John Reck7c103a32015-04-15 15:52:10 -0700461static void drawBitmapMesh(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400462 jint meshWidth, jint meshHeight, jfloatArray jverts,
463 jint vertIndex, jintArray jcolors, jint colorIndex, jlong paintHandle) {
464 const int ptCount = (meshWidth + 1) * (meshHeight + 1);
465 AutoJavaFloatArray vertA(env, jverts, vertIndex + (ptCount << 1));
466 AutoJavaIntArray colorA(env, jcolors, colorIndex + ptCount);
467
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400468 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
sergeyv5fd2a1c2016-10-20 15:04:28 -0700469 Bitmap& bitmap = android::bitmap::toBitmap(env, jbitmap);
John Reck7c103a32015-04-15 15:52:10 -0700470 get_canvas(canvasHandle)->drawBitmapMesh(bitmap, meshWidth, meshHeight,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400471 vertA.ptr(), colorA.ptr(), paint);
472}
473
474static void drawTextChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text,
475 jint index, jint count, jfloat x, jfloat y, jint bidiFlags,
476 jlong paintHandle, jlong typefaceHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400477 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
sergeyvbad99182016-03-17 11:24:22 -0700478 Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400479 jchar* jchars = env->GetCharArrayElements(text, NULL);
sergeyvdccca442016-03-21 15:38:21 -0700480 get_canvas(canvasHandle)->drawText(jchars + index, 0, count, count, x, y,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400481 bidiFlags, *paint, typeface);
482 env->ReleaseCharArrayElements(text, jchars, JNI_ABORT);
483}
484
485static void drawTextString(JNIEnv* env, jobject, jlong canvasHandle, jstring text,
486 jint start, jint end, jfloat x, jfloat y, jint bidiFlags,
487 jlong paintHandle, jlong typefaceHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400488 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
sergeyvbad99182016-03-17 11:24:22 -0700489 Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400490 const int count = end - start;
491 const jchar* jchars = env->GetStringChars(text, NULL);
sergeyvdccca442016-03-21 15:38:21 -0700492 get_canvas(canvasHandle)->drawText(jchars + start, 0, count, count, x, y,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400493 bidiFlags, *paint, typeface);
494 env->ReleaseStringChars(text, jchars);
495}
496
497static void drawTextRunChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text, jint index,
498 jint count, jint contextIndex, jint contextCount, jfloat x, jfloat y,
499 jboolean isRtl, jlong paintHandle, jlong typefaceHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400500 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
sergeyvbad99182016-03-17 11:24:22 -0700501 Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400502
Seigo Nonakaae1aa852016-06-09 19:42:51 +0900503 const int bidiFlags = isRtl ? minikin::kBidi_Force_RTL : minikin::kBidi_Force_LTR;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400504 jchar* jchars = env->GetCharArrayElements(text, NULL);
sergeyvdccca442016-03-21 15:38:21 -0700505 get_canvas(canvasHandle)->drawText(jchars + contextIndex, index - contextIndex, count,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400506 contextCount, x, y, bidiFlags, *paint, typeface);
507 env->ReleaseCharArrayElements(text, jchars, JNI_ABORT);
508}
509
510static void drawTextRunString(JNIEnv* env, jobject obj, jlong canvasHandle, jstring text,
511 jint start, jint end, jint contextStart, jint contextEnd,
512 jfloat x, jfloat y, jboolean isRtl, jlong paintHandle,
513 jlong typefaceHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400514 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
sergeyvbad99182016-03-17 11:24:22 -0700515 Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400516
Seigo Nonakaae1aa852016-06-09 19:42:51 +0900517 int bidiFlags = isRtl ? minikin::kBidi_Force_RTL : minikin::kBidi_Force_LTR;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400518 jint count = end - start;
519 jint contextCount = contextEnd - contextStart;
520 const jchar* jchars = env->GetStringChars(text, NULL);
sergeyvdccca442016-03-21 15:38:21 -0700521 get_canvas(canvasHandle)->drawText(jchars + contextStart, start - contextStart, count,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400522 contextCount, x, y, bidiFlags, *paint, typeface);
523 env->ReleaseStringChars(text, jchars);
524}
525
Derek Sollenberger8872b382014-06-23 14:13:53 -0400526static void drawTextOnPathChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text,
527 jint index, jint count, jlong pathHandle, jfloat hOffset,
528 jfloat vOffset, jint bidiFlags, jlong paintHandle,
529 jlong typefaceHandle) {
530 SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400531 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
sergeyvbad99182016-03-17 11:24:22 -0700532 Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400533
534 jchar* jchars = env->GetCharArrayElements(text, NULL);
535
sergeyvdccca442016-03-21 15:38:21 -0700536 get_canvas(canvasHandle)->drawTextOnPath(jchars + index, count, bidiFlags, *path,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400537 hOffset, vOffset, *paint, typeface);
538
539 env->ReleaseCharArrayElements(text, jchars, 0);
540}
541
542static void drawTextOnPathString(JNIEnv* env, jobject, jlong canvasHandle, jstring text,
543 jlong pathHandle, jfloat hOffset, jfloat vOffset,
544 jint bidiFlags, jlong paintHandle, jlong typefaceHandle) {
545 SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400546 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
sergeyvbad99182016-03-17 11:24:22 -0700547 Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400548
549 const jchar* jchars = env->GetStringChars(text, NULL);
550 int count = env->GetStringLength(text);
551
sergeyvdccca442016-03-21 15:38:21 -0700552 get_canvas(canvasHandle)->drawTextOnPath(jchars, count, bidiFlags, *path,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400553 hOffset, vOffset, *paint, typeface);
554
555 env->ReleaseStringChars(text, jchars);
556}
557
Chris Craikbfa0b292017-01-19 19:12:36 -0800558static void setDrawFilter(jlong canvasHandle, jlong filterHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400559 get_canvas(canvasHandle)->setDrawFilter(reinterpret_cast<SkDrawFilter*>(filterHandle));
560}
561
562static void freeCaches(JNIEnv* env, jobject) {
563 SkGraphics::PurgeFontCache();
564}
565
566static void freeTextLayoutCaches(JNIEnv* env, jobject) {
Seigo Nonakaae1aa852016-06-09 19:42:51 +0900567 minikin::Layout::purgeCaches();
Derek Sollenberger8872b382014-06-23 14:13:53 -0400568}
569
570}; // namespace CanvasJNI
571
Daniel Micay76f6a862015-09-19 17:31:01 -0400572static const JNINativeMethod gMethods[] = {
John Reckcaa08ff2016-10-07 13:21:36 -0700573 {"nGetNativeFinalizer", "()J", (void*) CanvasJNI::getNativeFinalizer},
574 {"nInitRaster", "(Landroid/graphics/Bitmap;)J", (void*) CanvasJNI::initRaster},
575 {"nFreeCaches", "()V", (void*) CanvasJNI::freeCaches},
576 {"nFreeTextLayoutCaches", "()V", (void*) CanvasJNI::freeTextLayoutCaches},
John Reck5cb74bc2016-10-07 11:24:44 -0700577
578 // ------------ @FastNative ----------------
John Reckcaa08ff2016-10-07 13:21:36 -0700579 {"nSetBitmap", "(JLandroid/graphics/Bitmap;)V", (void*) CanvasJNI::setBitmap},
Chris Craikbfa0b292017-01-19 19:12:36 -0800580 {"nGetClipBounds","(JLandroid/graphics/Rect;)Z", (void*) CanvasJNI::getClipBounds},
581
582 // ------------ @CriticalNative ----------------
John Reckcaa08ff2016-10-07 13:21:36 -0700583 {"nIsOpaque","(J)Z", (void*) CanvasJNI::isOpaque},
584 {"nGetWidth","(J)I", (void*) CanvasJNI::getWidth},
585 {"nGetHeight","(J)I", (void*) CanvasJNI::getHeight},
586 {"nSetHighContrastText","(JZ)V", (void*) CanvasJNI::setHighContrastText},
587 {"nSave","(JI)I", (void*) CanvasJNI::save},
588 {"nSaveLayer","(JFFFFJI)I", (void*) CanvasJNI::saveLayer},
589 {"nSaveLayerAlpha","(JFFFFII)I", (void*) CanvasJNI::saveLayerAlpha},
590 {"nGetSaveCount","(J)I", (void*) CanvasJNI::getSaveCount},
Chris Craikbfa0b292017-01-19 19:12:36 -0800591 {"nRestore","(J)Z", (void*) CanvasJNI::restore},
592 {"nRestoreToCount","(JI)V", (void*) CanvasJNI::restoreToCount},
593 {"nGetMatrix", "(JJ)V", (void*)CanvasJNI::getMatrix},
John Reckcaa08ff2016-10-07 13:21:36 -0700594 {"nSetMatrix","(JJ)V", (void*) CanvasJNI::setMatrix},
595 {"nConcat","(JJ)V", (void*) CanvasJNI::concat},
596 {"nRotate","(JF)V", (void*) CanvasJNI::rotate},
597 {"nScale","(JFF)V", (void*) CanvasJNI::scale},
598 {"nSkew","(JFF)V", (void*) CanvasJNI::skew},
599 {"nTranslate","(JFF)V", (void*) CanvasJNI::translate},
John Reckcaa08ff2016-10-07 13:21:36 -0700600 {"nQuickReject","(JJ)Z", (void*) CanvasJNI::quickRejectPath},
601 {"nQuickReject","(JFFFF)Z", (void*)CanvasJNI::quickRejectRect},
602 {"nClipRect","(JFFFFI)Z", (void*) CanvasJNI::clipRect},
603 {"nClipPath","(JJI)Z", (void*) CanvasJNI::clipPath},
John Reckcaa08ff2016-10-07 13:21:36 -0700604 {"nSetDrawFilter", "(JJ)V", (void*) CanvasJNI::setDrawFilter},
605};
606
607// If called from Canvas these are regular JNI
608// If called from DisplayListCanvas they are @FastNative
609static const JNINativeMethod gDrawMethods[] = {
610 {"nDrawColor","(JII)V", (void*) CanvasJNI::drawColor},
611 {"nDrawPaint","(JJ)V", (void*) CanvasJNI::drawPaint},
612 {"nDrawPoint", "(JFFJ)V", (void*) CanvasJNI::drawPoint},
613 {"nDrawPoints", "(J[FIIJ)V", (void*) CanvasJNI::drawPoints},
614 {"nDrawLine", "(JFFFFJ)V", (void*) CanvasJNI::drawLine},
615 {"nDrawLines", "(J[FIIJ)V", (void*) CanvasJNI::drawLines},
616 {"nDrawRect","(JFFFFJ)V", (void*) CanvasJNI::drawRect},
617 {"nDrawRegion", "(JJJ)V", (void*) CanvasJNI::drawRegion },
618 {"nDrawRoundRect","(JFFFFFFJ)V", (void*) CanvasJNI::drawRoundRect},
619 {"nDrawCircle","(JFFFJ)V", (void*) CanvasJNI::drawCircle},
620 {"nDrawOval","(JFFFFJ)V", (void*) CanvasJNI::drawOval},
621 {"nDrawArc","(JFFFFFFZJ)V", (void*) CanvasJNI::drawArc},
622 {"nDrawPath","(JJJ)V", (void*) CanvasJNI::drawPath},
623 {"nDrawVertices", "(JII[FI[FI[II[SIIJ)V", (void*)CanvasJNI::drawVertices},
624 {"nDrawNinePatch", "(JJJFFFFJII)V", (void*)CanvasJNI::drawNinePatch},
625 {"nDrawBitmapMatrix", "(JLandroid/graphics/Bitmap;JJ)V", (void*)CanvasJNI::drawBitmapMatrix},
626 {"nDrawBitmapMesh", "(JLandroid/graphics/Bitmap;II[FI[IIJ)V", (void*)CanvasJNI::drawBitmapMesh},
627 {"nDrawBitmap","(JLandroid/graphics/Bitmap;FFJIII)V", (void*) CanvasJNI::drawBitmap},
628 {"nDrawBitmap","(JLandroid/graphics/Bitmap;FFFFFFFFJII)V", (void*) CanvasJNI::drawBitmapRect},
629 {"nDrawBitmap", "(J[IIIFFIIZJ)V", (void*)CanvasJNI::drawBitmapArray},
630 {"nDrawText","(J[CIIFFIJJ)V", (void*) CanvasJNI::drawTextChars},
631 {"nDrawText","(JLjava/lang/String;IIFFIJJ)V", (void*) CanvasJNI::drawTextString},
632 {"nDrawTextRun","(J[CIIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunChars},
633 {"nDrawTextRun","(JLjava/lang/String;IIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunString},
634 {"nDrawTextOnPath","(J[CIIJFFIJJ)V", (void*) CanvasJNI::drawTextOnPathChars},
635 {"nDrawTextOnPath","(JLjava/lang/String;JFFIJJ)V", (void*) CanvasJNI::drawTextOnPathString},
Derek Sollenberger8872b382014-06-23 14:13:53 -0400636};
637
638int register_android_graphics_Canvas(JNIEnv* env) {
John Reckcaa08ff2016-10-07 13:21:36 -0700639 int ret = 0;
640 ret |= RegisterMethodsOrDie(env, "android/graphics/Canvas", gMethods, NELEM(gMethods));
641 ret |= RegisterMethodsOrDie(env, "android/graphics/BaseCanvas", gDrawMethods, NELEM(gDrawMethods));
642 ret |= RegisterMethodsOrDie(env, "android/view/RecordingCanvas", gDrawMethods, NELEM(gDrawMethods));
643 return ret;
644
Derek Sollenberger8872b382014-06-23 14:13:53 -0400645}
646
647}; // namespace android