blob: 80f6abe194b32383818d8dcb48d2e15252403211 [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"
Mike Reed3318f8b2017-02-13 16:14:10 -050030#include "SkRegion.h"
Mike Reed826deef2017-04-04 15:32:04 -040031#include "SkVertices.h"
Derek Sollenberger8872b382014-06-23 14:13:53 -040032
33namespace android {
34
35namespace CanvasJNI {
36
37static Canvas* get_canvas(jlong canvasHandle) {
38 return reinterpret_cast<Canvas*>(canvasHandle);
39}
40
Richard Uhler775873a2015-12-29 12:37:39 -080041static void delete_canvas(Canvas* canvas) {
42 delete canvas;
43}
44
45static jlong getNativeFinalizer(JNIEnv* env, jobject clazz) {
46 return static_cast<jlong>(reinterpret_cast<uintptr_t>(&delete_canvas));
Derek Sollenberger8872b382014-06-23 14:13:53 -040047}
48
49// Native wrapper constructor used by Canvas(Bitmap)
John Reckc1b33d62015-04-22 09:04:45 -070050static jlong initRaster(JNIEnv* env, jobject, jobject jbitmap) {
John Reck3731dc22015-04-13 15:20:29 -070051 SkBitmap bitmap;
John Reckc1b33d62015-04-22 09:04:45 -070052 if (jbitmap != NULL) {
John Reck3731dc22015-04-13 15:20:29 -070053 GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
John Reckc1b33d62015-04-22 09:04:45 -070054 }
John Reck3731dc22015-04-13 15:20:29 -070055 return reinterpret_cast<jlong>(Canvas::create_canvas(bitmap));
Derek Sollenberger8872b382014-06-23 14:13:53 -040056}
57
58// Set the given bitmap as the new draw target (wrapped in a new SkCanvas),
59// optionally copying canvas matrix & clip state.
John Reckc1b33d62015-04-22 09:04:45 -070060static void setBitmap(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap) {
John Reck3731dc22015-04-13 15:20:29 -070061 SkBitmap bitmap;
John Reckc1b33d62015-04-22 09:04:45 -070062 if (jbitmap != NULL) {
John Reck3731dc22015-04-13 15:20:29 -070063 GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
John Reckc1b33d62015-04-22 09:04:45 -070064 }
John Reck3731dc22015-04-13 15:20:29 -070065 get_canvas(canvasHandle)->setBitmap(bitmap);
Derek Sollenberger8872b382014-06-23 14:13:53 -040066}
67
Chris Craikbfa0b292017-01-19 19:12:36 -080068static jboolean isOpaque(jlong canvasHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -040069 return get_canvas(canvasHandle)->isOpaque() ? JNI_TRUE : JNI_FALSE;
70}
71
Chris Craikbfa0b292017-01-19 19:12:36 -080072static jint getWidth(jlong canvasHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -040073 return static_cast<jint>(get_canvas(canvasHandle)->width());
74}
75
Chris Craikbfa0b292017-01-19 19:12:36 -080076static jint getHeight(jlong canvasHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -040077 return static_cast<jint>(get_canvas(canvasHandle)->height());
78}
79
Chris Craikbfa0b292017-01-19 19:12:36 -080080static void setHighContrastText(jlong canvasHandle, jboolean highContrastText) {
Derek Sollenberger6578a982015-07-13 13:24:29 -040081 Canvas* canvas = get_canvas(canvasHandle);
82 canvas->setHighContrastText(highContrastText);
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.
Romain Guy253f2c22016-09-28 17:34:42 -0700451 SkImageInfo info = SkImageInfo::MakeN32(width, height, kPremul_SkAlphaType,
452 GraphicsJNI::defaultColorSpace());
Derek Sollenberger8872b382014-06-23 14:13:53 -0400453 SkBitmap bitmap;
Derek Sollenberger3d4eed72014-12-04 15:20:29 -0500454 bitmap.setInfo(info);
Leon Scroggins IIIf51a80d2017-07-12 10:46:35 -0400455 sk_sp<Bitmap> androidBitmap = Bitmap::allocateHeapBitmap(&bitmap);
sergeyvc1c54062016-10-19 18:47:26 -0700456 if (!androidBitmap) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400457 return;
458 }
459
460 if (!GraphicsJNI::SetPixels(env, jcolors, offset, stride, 0, 0, width, height, bitmap)) {
461 return;
462 }
463
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400464 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
sergeyvaed7f582016-10-14 16:30:21 -0700465 get_canvas(canvasHandle)->drawBitmap(*androidBitmap, x, y, paint);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400466}
467
John Reck7c103a32015-04-15 15:52:10 -0700468static void drawBitmapMesh(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400469 jint meshWidth, jint meshHeight, jfloatArray jverts,
470 jint vertIndex, jintArray jcolors, jint colorIndex, jlong paintHandle) {
471 const int ptCount = (meshWidth + 1) * (meshHeight + 1);
472 AutoJavaFloatArray vertA(env, jverts, vertIndex + (ptCount << 1));
473 AutoJavaIntArray colorA(env, jcolors, colorIndex + ptCount);
474
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400475 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
sergeyv5fd2a1c2016-10-20 15:04:28 -0700476 Bitmap& bitmap = android::bitmap::toBitmap(env, jbitmap);
John Reck7c103a32015-04-15 15:52:10 -0700477 get_canvas(canvasHandle)->drawBitmapMesh(bitmap, meshWidth, meshHeight,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400478 vertA.ptr(), colorA.ptr(), paint);
479}
480
481static void drawTextChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text,
482 jint index, jint count, jfloat x, jfloat y, jint bidiFlags,
483 jlong paintHandle, jlong typefaceHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400484 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
sergeyvbad99182016-03-17 11:24:22 -0700485 Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400486 jchar* jchars = env->GetCharArrayElements(text, NULL);
sergeyvdccca442016-03-21 15:38:21 -0700487 get_canvas(canvasHandle)->drawText(jchars + index, 0, count, count, x, y,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400488 bidiFlags, *paint, typeface);
489 env->ReleaseCharArrayElements(text, jchars, JNI_ABORT);
490}
491
492static void drawTextString(JNIEnv* env, jobject, jlong canvasHandle, jstring text,
493 jint start, jint end, jfloat x, jfloat y, jint bidiFlags,
494 jlong paintHandle, jlong typefaceHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400495 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
sergeyvbad99182016-03-17 11:24:22 -0700496 Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400497 const int count = end - start;
498 const jchar* jchars = env->GetStringChars(text, NULL);
sergeyvdccca442016-03-21 15:38:21 -0700499 get_canvas(canvasHandle)->drawText(jchars + start, 0, count, count, x, y,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400500 bidiFlags, *paint, typeface);
501 env->ReleaseStringChars(text, jchars);
502}
503
504static void drawTextRunChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text, jint index,
505 jint count, jint contextIndex, jint contextCount, jfloat x, jfloat y,
506 jboolean isRtl, jlong paintHandle, jlong typefaceHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400507 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
sergeyvbad99182016-03-17 11:24:22 -0700508 Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400509
Seigo Nonakaae1aa852016-06-09 19:42:51 +0900510 const int bidiFlags = isRtl ? minikin::kBidi_Force_RTL : minikin::kBidi_Force_LTR;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400511 jchar* jchars = env->GetCharArrayElements(text, NULL);
sergeyvdccca442016-03-21 15:38:21 -0700512 get_canvas(canvasHandle)->drawText(jchars + contextIndex, index - contextIndex, count,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400513 contextCount, x, y, bidiFlags, *paint, typeface);
514 env->ReleaseCharArrayElements(text, jchars, JNI_ABORT);
515}
516
517static void drawTextRunString(JNIEnv* env, jobject obj, jlong canvasHandle, jstring text,
518 jint start, jint end, jint contextStart, jint contextEnd,
519 jfloat x, jfloat y, jboolean isRtl, jlong paintHandle,
520 jlong typefaceHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400521 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
sergeyvbad99182016-03-17 11:24:22 -0700522 Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400523
Seigo Nonakaae1aa852016-06-09 19:42:51 +0900524 int bidiFlags = isRtl ? minikin::kBidi_Force_RTL : minikin::kBidi_Force_LTR;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400525 jint count = end - start;
526 jint contextCount = contextEnd - contextStart;
527 const jchar* jchars = env->GetStringChars(text, NULL);
sergeyvdccca442016-03-21 15:38:21 -0700528 get_canvas(canvasHandle)->drawText(jchars + contextStart, start - contextStart, count,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400529 contextCount, x, y, bidiFlags, *paint, typeface);
530 env->ReleaseStringChars(text, jchars);
531}
532
Derek Sollenberger8872b382014-06-23 14:13:53 -0400533static void drawTextOnPathChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text,
534 jint index, jint count, jlong pathHandle, jfloat hOffset,
535 jfloat vOffset, jint bidiFlags, jlong paintHandle,
536 jlong typefaceHandle) {
537 SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400538 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
sergeyvbad99182016-03-17 11:24:22 -0700539 Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400540
541 jchar* jchars = env->GetCharArrayElements(text, NULL);
542
sergeyvdccca442016-03-21 15:38:21 -0700543 get_canvas(canvasHandle)->drawTextOnPath(jchars + index, count, bidiFlags, *path,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400544 hOffset, vOffset, *paint, typeface);
545
546 env->ReleaseCharArrayElements(text, jchars, 0);
547}
548
549static void drawTextOnPathString(JNIEnv* env, jobject, jlong canvasHandle, jstring text,
550 jlong pathHandle, jfloat hOffset, jfloat vOffset,
551 jint bidiFlags, jlong paintHandle, jlong typefaceHandle) {
552 SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400553 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
sergeyvbad99182016-03-17 11:24:22 -0700554 Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400555
556 const jchar* jchars = env->GetStringChars(text, NULL);
557 int count = env->GetStringLength(text);
558
sergeyvdccca442016-03-21 15:38:21 -0700559 get_canvas(canvasHandle)->drawTextOnPath(jchars, count, bidiFlags, *path,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400560 hOffset, vOffset, *paint, typeface);
561
562 env->ReleaseStringChars(text, jchars);
563}
564
Chris Craikbfa0b292017-01-19 19:12:36 -0800565static void setDrawFilter(jlong canvasHandle, jlong filterHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400566 get_canvas(canvasHandle)->setDrawFilter(reinterpret_cast<SkDrawFilter*>(filterHandle));
567}
568
569static void freeCaches(JNIEnv* env, jobject) {
570 SkGraphics::PurgeFontCache();
571}
572
573static void freeTextLayoutCaches(JNIEnv* env, jobject) {
Seigo Nonakaae1aa852016-06-09 19:42:51 +0900574 minikin::Layout::purgeCaches();
Derek Sollenberger8872b382014-06-23 14:13:53 -0400575}
576
577}; // namespace CanvasJNI
578
Daniel Micay76f6a862015-09-19 17:31:01 -0400579static const JNINativeMethod gMethods[] = {
John Reckcaa08ff2016-10-07 13:21:36 -0700580 {"nGetNativeFinalizer", "()J", (void*) CanvasJNI::getNativeFinalizer},
581 {"nInitRaster", "(Landroid/graphics/Bitmap;)J", (void*) CanvasJNI::initRaster},
582 {"nFreeCaches", "()V", (void*) CanvasJNI::freeCaches},
583 {"nFreeTextLayoutCaches", "()V", (void*) CanvasJNI::freeTextLayoutCaches},
John Reck5cb74bc2016-10-07 11:24:44 -0700584
585 // ------------ @FastNative ----------------
John Reckcaa08ff2016-10-07 13:21:36 -0700586 {"nSetBitmap", "(JLandroid/graphics/Bitmap;)V", (void*) CanvasJNI::setBitmap},
Chris Craikbfa0b292017-01-19 19:12:36 -0800587 {"nGetClipBounds","(JLandroid/graphics/Rect;)Z", (void*) CanvasJNI::getClipBounds},
588
589 // ------------ @CriticalNative ----------------
John Reckcaa08ff2016-10-07 13:21:36 -0700590 {"nIsOpaque","(J)Z", (void*) CanvasJNI::isOpaque},
591 {"nGetWidth","(J)I", (void*) CanvasJNI::getWidth},
592 {"nGetHeight","(J)I", (void*) CanvasJNI::getHeight},
593 {"nSetHighContrastText","(JZ)V", (void*) CanvasJNI::setHighContrastText},
594 {"nSave","(JI)I", (void*) CanvasJNI::save},
595 {"nSaveLayer","(JFFFFJI)I", (void*) CanvasJNI::saveLayer},
596 {"nSaveLayerAlpha","(JFFFFII)I", (void*) CanvasJNI::saveLayerAlpha},
597 {"nGetSaveCount","(J)I", (void*) CanvasJNI::getSaveCount},
Chris Craikbfa0b292017-01-19 19:12:36 -0800598 {"nRestore","(J)Z", (void*) CanvasJNI::restore},
599 {"nRestoreToCount","(JI)V", (void*) CanvasJNI::restoreToCount},
600 {"nGetMatrix", "(JJ)V", (void*)CanvasJNI::getMatrix},
John Reckcaa08ff2016-10-07 13:21:36 -0700601 {"nSetMatrix","(JJ)V", (void*) CanvasJNI::setMatrix},
602 {"nConcat","(JJ)V", (void*) CanvasJNI::concat},
603 {"nRotate","(JF)V", (void*) CanvasJNI::rotate},
604 {"nScale","(JFF)V", (void*) CanvasJNI::scale},
605 {"nSkew","(JFF)V", (void*) CanvasJNI::skew},
606 {"nTranslate","(JFF)V", (void*) CanvasJNI::translate},
John Reckcaa08ff2016-10-07 13:21:36 -0700607 {"nQuickReject","(JJ)Z", (void*) CanvasJNI::quickRejectPath},
608 {"nQuickReject","(JFFFF)Z", (void*)CanvasJNI::quickRejectRect},
609 {"nClipRect","(JFFFFI)Z", (void*) CanvasJNI::clipRect},
610 {"nClipPath","(JJI)Z", (void*) CanvasJNI::clipPath},
John Reckcaa08ff2016-10-07 13:21:36 -0700611 {"nSetDrawFilter", "(JJ)V", (void*) CanvasJNI::setDrawFilter},
612};
613
614// If called from Canvas these are regular JNI
615// If called from DisplayListCanvas they are @FastNative
616static const JNINativeMethod gDrawMethods[] = {
617 {"nDrawColor","(JII)V", (void*) CanvasJNI::drawColor},
618 {"nDrawPaint","(JJ)V", (void*) CanvasJNI::drawPaint},
619 {"nDrawPoint", "(JFFJ)V", (void*) CanvasJNI::drawPoint},
620 {"nDrawPoints", "(J[FIIJ)V", (void*) CanvasJNI::drawPoints},
621 {"nDrawLine", "(JFFFFJ)V", (void*) CanvasJNI::drawLine},
622 {"nDrawLines", "(J[FIIJ)V", (void*) CanvasJNI::drawLines},
623 {"nDrawRect","(JFFFFJ)V", (void*) CanvasJNI::drawRect},
624 {"nDrawRegion", "(JJJ)V", (void*) CanvasJNI::drawRegion },
625 {"nDrawRoundRect","(JFFFFFFJ)V", (void*) CanvasJNI::drawRoundRect},
626 {"nDrawCircle","(JFFFJ)V", (void*) CanvasJNI::drawCircle},
627 {"nDrawOval","(JFFFFJ)V", (void*) CanvasJNI::drawOval},
628 {"nDrawArc","(JFFFFFFZJ)V", (void*) CanvasJNI::drawArc},
629 {"nDrawPath","(JJJ)V", (void*) CanvasJNI::drawPath},
630 {"nDrawVertices", "(JII[FI[FI[II[SIIJ)V", (void*)CanvasJNI::drawVertices},
631 {"nDrawNinePatch", "(JJJFFFFJII)V", (void*)CanvasJNI::drawNinePatch},
632 {"nDrawBitmapMatrix", "(JLandroid/graphics/Bitmap;JJ)V", (void*)CanvasJNI::drawBitmapMatrix},
633 {"nDrawBitmapMesh", "(JLandroid/graphics/Bitmap;II[FI[IIJ)V", (void*)CanvasJNI::drawBitmapMesh},
634 {"nDrawBitmap","(JLandroid/graphics/Bitmap;FFJIII)V", (void*) CanvasJNI::drawBitmap},
635 {"nDrawBitmap","(JLandroid/graphics/Bitmap;FFFFFFFFJII)V", (void*) CanvasJNI::drawBitmapRect},
636 {"nDrawBitmap", "(J[IIIFFIIZJ)V", (void*)CanvasJNI::drawBitmapArray},
637 {"nDrawText","(J[CIIFFIJJ)V", (void*) CanvasJNI::drawTextChars},
638 {"nDrawText","(JLjava/lang/String;IIFFIJJ)V", (void*) CanvasJNI::drawTextString},
639 {"nDrawTextRun","(J[CIIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunChars},
640 {"nDrawTextRun","(JLjava/lang/String;IIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunString},
641 {"nDrawTextOnPath","(J[CIIJFFIJJ)V", (void*) CanvasJNI::drawTextOnPathChars},
642 {"nDrawTextOnPath","(JLjava/lang/String;JFFIJJ)V", (void*) CanvasJNI::drawTextOnPathString},
Derek Sollenberger8872b382014-06-23 14:13:53 -0400643};
644
645int register_android_graphics_Canvas(JNIEnv* env) {
John Reckcaa08ff2016-10-07 13:21:36 -0700646 int ret = 0;
647 ret |= RegisterMethodsOrDie(env, "android/graphics/Canvas", gMethods, NELEM(gMethods));
648 ret |= RegisterMethodsOrDie(env, "android/graphics/BaseCanvas", gDrawMethods, NELEM(gDrawMethods));
649 ret |= RegisterMethodsOrDie(env, "android/view/RecordingCanvas", gDrawMethods, NELEM(gDrawMethods));
650 return ret;
651
Derek Sollenberger8872b382014-06-23 14:13:53 -0400652}
653
654}; // namespace android