blob: f08b89c8c988bc0d2f4b024ef55b1a7948903c61 [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 jint save(jlong canvasHandle, jint flagsHandle) {
Florin Malitaeecff562015-12-21 10:43:01 -050081 SaveFlags::Flags flags = static_cast<SaveFlags::Flags>(flagsHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -040082 return static_cast<jint>(get_canvas(canvasHandle)->save(flags));
83}
84
Chris Craikbfa0b292017-01-19 19:12:36 -080085static jint saveLayer(jlong canvasHandle, jfloat l, jfloat t,
Derek Sollenberger8872b382014-06-23 14:13:53 -040086 jfloat r, jfloat b, jlong paintHandle, jint flagsHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -040087 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Florin Malitaeecff562015-12-21 10:43:01 -050088 SaveFlags::Flags flags = static_cast<SaveFlags::Flags>(flagsHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -040089 return static_cast<jint>(get_canvas(canvasHandle)->saveLayer(l, t, r, b, paint, flags));
90}
91
Chris Craikbfa0b292017-01-19 19:12:36 -080092static jint saveLayerAlpha(jlong canvasHandle, jfloat l, jfloat t,
Derek Sollenberger8872b382014-06-23 14:13:53 -040093 jfloat r, jfloat b, jint alpha, jint flagsHandle) {
Florin Malitaeecff562015-12-21 10:43:01 -050094 SaveFlags::Flags flags = static_cast<SaveFlags::Flags>(flagsHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -040095 return static_cast<jint>(get_canvas(canvasHandle)->saveLayerAlpha(l, t, r, b, alpha, flags));
96}
97
Chris Craikbfa0b292017-01-19 19:12:36 -080098static bool restore(jlong canvasHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -040099 Canvas* canvas = get_canvas(canvasHandle);
Chris Craikbfa0b292017-01-19 19:12:36 -0800100 if (canvas->getSaveCount() <= 1) {
101 return false; // cannot restore anymore
Derek Sollenberger8872b382014-06-23 14:13:53 -0400102 }
103 canvas->restore();
Chris Craikbfa0b292017-01-19 19:12:36 -0800104 return true; // success
Derek Sollenberger8872b382014-06-23 14:13:53 -0400105}
106
Chris Craikbfa0b292017-01-19 19:12:36 -0800107static void restoreToCount(jlong canvasHandle, jint saveCount) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400108 Canvas* canvas = get_canvas(canvasHandle);
Chris Craikbfa0b292017-01-19 19:12:36 -0800109 canvas->restoreToCount(saveCount);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400110}
111
Chris Craikbfa0b292017-01-19 19:12:36 -0800112static jint getSaveCount(jlong canvasHandle) {
113 return static_cast<jint>(get_canvas(canvasHandle)->getSaveCount());
114}
115
116static void getMatrix(jlong canvasHandle, jlong matrixHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400117 SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
118 get_canvas(canvasHandle)->getMatrix(matrix);
119}
120
Chris Craikbfa0b292017-01-19 19:12:36 -0800121static void setMatrix(jlong canvasHandle, jlong matrixHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400122 const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
123 get_canvas(canvasHandle)->setMatrix(matrix ? *matrix : SkMatrix::I());
124}
125
Chris Craikbfa0b292017-01-19 19:12:36 -0800126static void concat(jlong canvasHandle, jlong matrixHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400127 const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
128 get_canvas(canvasHandle)->concat(*matrix);
129}
130
Chris Craikbfa0b292017-01-19 19:12:36 -0800131static void rotate(jlong canvasHandle, jfloat degrees) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400132 get_canvas(canvasHandle)->rotate(degrees);
133}
134
Chris Craikbfa0b292017-01-19 19:12:36 -0800135static void scale(jlong canvasHandle, jfloat sx, jfloat sy) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400136 get_canvas(canvasHandle)->scale(sx, sy);
137}
138
Chris Craikbfa0b292017-01-19 19:12:36 -0800139static void skew(jlong canvasHandle, jfloat sx, jfloat sy) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400140 get_canvas(canvasHandle)->skew(sx, sy);
141}
142
Chris Craikbfa0b292017-01-19 19:12:36 -0800143static void translate(jlong canvasHandle, jfloat dx, jfloat dy) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400144 get_canvas(canvasHandle)->translate(dx, dy);
145}
146
147static jboolean getClipBounds(JNIEnv* env, jobject, jlong canvasHandle, jobject bounds) {
148 SkRect r;
149 SkIRect ir;
150 bool result = get_canvas(canvasHandle)->getClipBounds(&r);
151
152 if (!result) {
153 r.setEmpty();
154 }
155 r.round(&ir);
156
157 (void)GraphicsJNI::irect_to_jrect(ir, env, bounds);
158 return result ? JNI_TRUE : JNI_FALSE;
159}
160
Chris Craikbfa0b292017-01-19 19:12:36 -0800161static jboolean quickRejectRect(jlong canvasHandle,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400162 jfloat left, jfloat top, jfloat right, jfloat bottom) {
163 bool result = get_canvas(canvasHandle)->quickRejectRect(left, top, right, bottom);
164 return result ? JNI_TRUE : JNI_FALSE;
165}
166
Chris Craikbfa0b292017-01-19 19:12:36 -0800167static jboolean quickRejectPath(jlong canvasHandle, jlong pathHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400168 SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
169 bool result = get_canvas(canvasHandle)->quickRejectPath(*path);
170 return result ? JNI_TRUE : JNI_FALSE;
171}
172
Mike Reed6e49c9f2016-12-02 15:36:59 -0500173// SkRegion::Op and SkClipOp are numerically identical, so we can freely cast
174// from one to the other (though SkClipOp is destined to become a strict subset)
Mike Reed6c67f1d2016-12-14 10:29:54 -0500175static_assert(SkRegion::kDifference_Op == static_cast<SkRegion::Op>(SkClipOp::kDifference), "");
176static_assert(SkRegion::kIntersect_Op == static_cast<SkRegion::Op>(SkClipOp::kIntersect), "");
Mike Reeda0a74d52017-03-13 13:26:00 -0400177static_assert(SkRegion::kUnion_Op == static_cast<SkRegion::Op>(SkClipOp::kUnion_deprecated), "");
178static_assert(SkRegion::kXOR_Op == static_cast<SkRegion::Op>(SkClipOp::kXOR_deprecated), "");
179static_assert(SkRegion::kReverseDifference_Op == static_cast<SkRegion::Op>(SkClipOp::kReverseDifference_deprecated), "");
180static_assert(SkRegion::kReplace_Op == static_cast<SkRegion::Op>(SkClipOp::kReplace_deprecated), "");
Mike Reed6e49c9f2016-12-02 15:36:59 -0500181
182static SkClipOp opHandleToClipOp(jint opHandle) {
183 // The opHandle is defined in Canvas.java to be Region::Op
184 SkRegion::Op rgnOp = static_cast<SkRegion::Op>(opHandle);
185
186 // In the future, when we no longer support the wide range of ops (e.g. Union, Xor)
187 // this function can perform a range check and throw an unsupported-exception.
188 // e.g. if (rgnOp != kIntersect && rgnOp != kDifference) throw...
189
190 // Skia now takes a different type, SkClipOp, as the parameter to clipping calls
191 // This type is binary compatible with SkRegion::Op, so a static_cast<> is safe.
192 return static_cast<SkClipOp>(rgnOp);
193}
194
Chris Craikbfa0b292017-01-19 19:12:36 -0800195static jboolean clipRect(jlong canvasHandle, jfloat l, jfloat t,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400196 jfloat r, jfloat b, jint opHandle) {
Mike Reed6e49c9f2016-12-02 15:36:59 -0500197 bool nonEmptyClip = get_canvas(canvasHandle)->clipRect(l, t, r, b,
198 opHandleToClipOp(opHandle));
Chris Craik5ec6a282015-06-23 15:42:12 -0700199 return nonEmptyClip ? JNI_TRUE : JNI_FALSE;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400200}
201
Chris Craikbfa0b292017-01-19 19:12:36 -0800202static jboolean clipPath(jlong canvasHandle, jlong pathHandle,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400203 jint opHandle) {
204 SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
Mike Reed6e49c9f2016-12-02 15:36:59 -0500205 bool nonEmptyClip = get_canvas(canvasHandle)->clipPath(path, opHandleToClipOp(opHandle));
Chris Craik5ec6a282015-06-23 15:42:12 -0700206 return nonEmptyClip ? JNI_TRUE : JNI_FALSE;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400207}
208
Derek Sollenberger8872b382014-06-23 14:13:53 -0400209static void drawColor(JNIEnv* env, jobject, jlong canvasHandle, jint color, jint modeHandle) {
Mike Reed260ab722016-10-07 15:59:20 -0400210 SkBlendMode mode = static_cast<SkBlendMode>(modeHandle);
Chris Craik1526a452015-03-06 18:42:15 +0000211 get_canvas(canvasHandle)->drawColor(color, mode);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400212}
213
214static void drawPaint(JNIEnv* env, jobject, jlong canvasHandle, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400215 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400216 get_canvas(canvasHandle)->drawPaint(*paint);
217}
218
219static void drawPoint(JNIEnv*, jobject, jlong canvasHandle, jfloat x, jfloat y,
220 jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400221 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400222 get_canvas(canvasHandle)->drawPoint(x, y, *paint);
223}
224
225static void drawPoints(JNIEnv* env, jobject, jlong canvasHandle, jfloatArray jptsArray,
226 jint offset, jint count, jlong paintHandle) {
227 NPE_CHECK_RETURN_VOID(env, jptsArray);
228 AutoJavaFloatArray autoPts(env, jptsArray);
229 float* floats = autoPts.ptr();
230 const int length = autoPts.length();
231
232 if ((offset | count) < 0 || offset + count > length) {
233 doThrowAIOOBE(env);
234 return;
235 }
236
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400237 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400238 get_canvas(canvasHandle)->drawPoints(floats + offset, count, *paint);
239}
240
241static void drawLine(JNIEnv* env, jobject, jlong canvasHandle, jfloat startX, jfloat startY,
242 jfloat stopX, jfloat stopY, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400243 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400244 get_canvas(canvasHandle)->drawLine(startX, startY, stopX, stopY, *paint);
245}
246
247static void drawLines(JNIEnv* env, jobject, jlong canvasHandle, jfloatArray jptsArray,
248 jint offset, jint count, jlong paintHandle) {
249 NPE_CHECK_RETURN_VOID(env, jptsArray);
250 AutoJavaFloatArray autoPts(env, jptsArray);
251 float* floats = autoPts.ptr();
252 const int length = autoPts.length();
253
254 if ((offset | count) < 0 || offset + count > length) {
255 doThrowAIOOBE(env);
256 return;
257 }
258
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400259 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400260 get_canvas(canvasHandle)->drawLines(floats + offset, count, *paint);
261}
262
263static void drawRect(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
264 jfloat right, jfloat bottom, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400265 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400266 get_canvas(canvasHandle)->drawRect(left, top, right, bottom, *paint);
267}
268
Derek Sollenberger94394b32015-07-10 09:58:41 -0400269static void drawRegion(JNIEnv* env, jobject, jlong canvasHandle, jlong regionHandle,
270 jlong paintHandle) {
271 const SkRegion* region = reinterpret_cast<SkRegion*>(regionHandle);
272 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
273 get_canvas(canvasHandle)->drawRegion(*region, *paint);
274}
275
Derek Sollenberger8872b382014-06-23 14:13:53 -0400276static void drawRoundRect(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
277 jfloat right, jfloat bottom, jfloat rx, jfloat ry, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400278 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400279 get_canvas(canvasHandle)->drawRoundRect(left, top, right, bottom, rx, ry, *paint);
280}
281
282static void drawCircle(JNIEnv* env, jobject, jlong canvasHandle, jfloat cx, jfloat cy,
283 jfloat radius, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400284 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400285 get_canvas(canvasHandle)->drawCircle(cx, cy, radius, *paint);
286}
287
288static void drawOval(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
289 jfloat right, jfloat bottom, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400290 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400291 get_canvas(canvasHandle)->drawOval(left, top, right, bottom, *paint);
292}
293
294static void drawArc(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
295 jfloat right, jfloat bottom, jfloat startAngle, jfloat sweepAngle,
296 jboolean useCenter, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400297 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400298 get_canvas(canvasHandle)->drawArc(left, top, right, bottom, startAngle, sweepAngle,
299 useCenter, *paint);
300}
301
302static void drawPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle,
303 jlong paintHandle) {
304 const SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400305 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400306 get_canvas(canvasHandle)->drawPath(*path, *paint);
307}
308
309static void drawVertices(JNIEnv* env, jobject, jlong canvasHandle,
Mike Reed826deef2017-04-04 15:32:04 -0400310 jint modeHandle, jint floatCount,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400311 jfloatArray jverts, jint vertIndex,
312 jfloatArray jtexs, jint texIndex,
313 jintArray jcolors, jint colorIndex,
314 jshortArray jindices, jint indexIndex,
315 jint indexCount, jlong paintHandle) {
Mike Reed826deef2017-04-04 15:32:04 -0400316 AutoJavaFloatArray vertA(env, jverts, vertIndex + floatCount);
317 AutoJavaFloatArray texA(env, jtexs, texIndex + floatCount);
318 AutoJavaIntArray colorA(env, jcolors, colorIndex + floatCount);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400319 AutoJavaShortArray indexA(env, jindices, indexIndex + indexCount);
320
321 const float* verts = vertA.ptr() + vertIndex;
322 const float* texs = texA.ptr() + vertIndex;
323 const int* colors = NULL;
324 const uint16_t* indices = NULL;
325
326 if (jcolors != NULL) {
327 colors = colorA.ptr() + colorIndex;
328 }
329 if (jindices != NULL) {
330 indices = (const uint16_t*)(indexA.ptr() + indexIndex);
331 }
332
Mike Reed826deef2017-04-04 15:32:04 -0400333 int vertexCount = floatCount >> 1; // 2 floats per SkPoint
334 SkVertices::VertexMode mode = static_cast<SkVertices::VertexMode>(modeHandle);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400335 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Mike Reed826deef2017-04-04 15:32:04 -0400336 get_canvas(canvasHandle)->drawVertices(SkVertices::MakeCopy(mode, vertexCount,
337 reinterpret_cast<const SkPoint*>(verts),
338 reinterpret_cast<const SkPoint*>(texs),
339 reinterpret_cast<const SkColor*>(colors),
340 indexCount, indices).get(),
341 SkBlendMode::kModulate, *paint);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400342}
343
Derek Sollenberger4c5efe92015-07-10 13:56:39 -0400344static void drawNinePatch(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle,
345 jlong chunkHandle, jfloat left, jfloat top, jfloat right, jfloat bottom,
346 jlong paintHandle, jint dstDensity, jint srcDensity) {
347
348 Canvas* canvas = get_canvas(canvasHandle);
sergeyv5fd2a1c2016-10-20 15:04:28 -0700349 Bitmap& bitmap = android::bitmap::toBitmap(env, bitmapHandle);
Derek Sollenberger4c5efe92015-07-10 13:56:39 -0400350 const android::Res_png_9patch* chunk = reinterpret_cast<android::Res_png_9patch*>(chunkHandle);
351 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
352
353 if (CC_LIKELY(dstDensity == srcDensity || dstDensity == 0 || srcDensity == 0)) {
sergeyv5fd2a1c2016-10-20 15:04:28 -0700354 canvas->drawNinePatch(bitmap, *chunk, left, top, right, bottom, paint);
Derek Sollenberger4c5efe92015-07-10 13:56:39 -0400355 } else {
Florin Malitaeecff562015-12-21 10:43:01 -0500356 canvas->save(SaveFlags::MatrixClip);
Derek Sollenberger4c5efe92015-07-10 13:56:39 -0400357
358 SkScalar scale = dstDensity / (float)srcDensity;
359 canvas->translate(left, top);
360 canvas->scale(scale, scale);
361
362 Paint filteredPaint;
363 if (paint) {
364 filteredPaint = *paint;
365 }
366 filteredPaint.setFilterQuality(kLow_SkFilterQuality);
367
sergeyv5fd2a1c2016-10-20 15:04:28 -0700368 canvas->drawNinePatch(bitmap, *chunk, 0, 0, (right-left)/scale, (bottom-top)/scale,
Derek Sollenberger4c5efe92015-07-10 13:56:39 -0400369 &filteredPaint);
370
371 canvas->restore();
372 }
373}
374
John Reckcaa08ff2016-10-07 13:21:36 -0700375static void drawBitmap(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400376 jfloat left, jfloat top, jlong paintHandle, jint canvasDensity,
377 jint screenDensity, jint bitmapDensity) {
378 Canvas* canvas = get_canvas(canvasHandle);
sergeyvaed7f582016-10-14 16:30:21 -0700379 Bitmap& bitmap = android::bitmap::toBitmap(env, jbitmap);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400380 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400381
382 if (canvasDensity == bitmapDensity || canvasDensity == 0 || bitmapDensity == 0) {
383 if (screenDensity != 0 && screenDensity != bitmapDensity) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400384 Paint filteredPaint;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400385 if (paint) {
386 filteredPaint = *paint;
387 }
Mike Reed2a1ce8a2015-03-16 11:16:09 -0400388 filteredPaint.setFilterQuality(kLow_SkFilterQuality);
John Reck7c103a32015-04-15 15:52:10 -0700389 canvas->drawBitmap(bitmap, left, top, &filteredPaint);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400390 } else {
John Reck7c103a32015-04-15 15:52:10 -0700391 canvas->drawBitmap(bitmap, left, top, paint);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400392 }
393 } else {
Florin Malitaeecff562015-12-21 10:43:01 -0500394 canvas->save(SaveFlags::MatrixClip);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400395 SkScalar scale = canvasDensity / (float)bitmapDensity;
396 canvas->translate(left, top);
397 canvas->scale(scale, scale);
398
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400399 Paint filteredPaint;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400400 if (paint) {
401 filteredPaint = *paint;
402 }
Mike Reed2a1ce8a2015-03-16 11:16:09 -0400403 filteredPaint.setFilterQuality(kLow_SkFilterQuality);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400404
John Reck7c103a32015-04-15 15:52:10 -0700405 canvas->drawBitmap(bitmap, 0, 0, &filteredPaint);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400406 canvas->restore();
407 }
408}
409
John Reck7c103a32015-04-15 15:52:10 -0700410static void drawBitmapMatrix(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400411 jlong matrixHandle, jlong paintHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400412 const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400413 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
sergeyvfc9999502016-10-17 13:07:38 -0700414 Bitmap& bitmap = android::bitmap::toBitmap(env, jbitmap);
John Reck7c103a32015-04-15 15:52:10 -0700415 get_canvas(canvasHandle)->drawBitmap(bitmap, *matrix, paint);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400416}
417
John Reck7c103a32015-04-15 15:52:10 -0700418static void drawBitmapRect(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400419 float srcLeft, float srcTop, float srcRight, float srcBottom,
420 float dstLeft, float dstTop, float dstRight, float dstBottom,
421 jlong paintHandle, jint screenDensity, jint bitmapDensity) {
422 Canvas* canvas = get_canvas(canvasHandle);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400423 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400424
sergeyvfc9999502016-10-17 13:07:38 -0700425 Bitmap& bitmap = android::bitmap::toBitmap(env, jbitmap);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400426 if (screenDensity != 0 && screenDensity != bitmapDensity) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400427 Paint filteredPaint;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400428 if (paint) {
429 filteredPaint = *paint;
430 }
Mike Reed2a1ce8a2015-03-16 11:16:09 -0400431 filteredPaint.setFilterQuality(kLow_SkFilterQuality);
John Reck7c103a32015-04-15 15:52:10 -0700432 canvas->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400433 dstLeft, dstTop, dstRight, dstBottom, &filteredPaint);
434 } else {
John Reck7c103a32015-04-15 15:52:10 -0700435 canvas->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400436 dstLeft, dstTop, dstRight, dstBottom, paint);
437 }
438}
439
440static void drawBitmapArray(JNIEnv* env, jobject, jlong canvasHandle,
441 jintArray jcolors, jint offset, jint stride,
442 jfloat x, jfloat y, jint width, jint height,
443 jboolean hasAlpha, jlong paintHandle) {
444 // Note: If hasAlpha is false, kRGB_565_SkColorType will be used, which will
445 // correct the alphaType to kOpaque_SkAlphaType.
Romain Guy253f2c22016-09-28 17:34:42 -0700446 SkImageInfo info = SkImageInfo::MakeN32(width, height, kPremul_SkAlphaType,
447 GraphicsJNI::defaultColorSpace());
Derek Sollenberger8872b382014-06-23 14:13:53 -0400448 SkBitmap bitmap;
Derek Sollenberger3d4eed72014-12-04 15:20:29 -0500449 bitmap.setInfo(info);
Leon Scroggins IIIf51a80d2017-07-12 10:46:35 -0400450 sk_sp<Bitmap> androidBitmap = Bitmap::allocateHeapBitmap(&bitmap);
sergeyvc1c54062016-10-19 18:47:26 -0700451 if (!androidBitmap) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400452 return;
453 }
454
455 if (!GraphicsJNI::SetPixels(env, jcolors, offset, stride, 0, 0, width, height, bitmap)) {
456 return;
457 }
458
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400459 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
sergeyvaed7f582016-10-14 16:30:21 -0700460 get_canvas(canvasHandle)->drawBitmap(*androidBitmap, x, y, paint);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400461}
462
John Reck7c103a32015-04-15 15:52:10 -0700463static void drawBitmapMesh(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400464 jint meshWidth, jint meshHeight, jfloatArray jverts,
465 jint vertIndex, jintArray jcolors, jint colorIndex, jlong paintHandle) {
466 const int ptCount = (meshWidth + 1) * (meshHeight + 1);
467 AutoJavaFloatArray vertA(env, jverts, vertIndex + (ptCount << 1));
468 AutoJavaIntArray colorA(env, jcolors, colorIndex + ptCount);
469
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400470 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
sergeyv5fd2a1c2016-10-20 15:04:28 -0700471 Bitmap& bitmap = android::bitmap::toBitmap(env, jbitmap);
John Reck7c103a32015-04-15 15:52:10 -0700472 get_canvas(canvasHandle)->drawBitmapMesh(bitmap, meshWidth, meshHeight,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400473 vertA.ptr(), colorA.ptr(), paint);
474}
475
476static void drawTextChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text,
477 jint index, jint count, jfloat x, jfloat y, jint bidiFlags,
Seigo Nonaka318ca042017-08-01 16:36:18 -0700478 jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400479 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Seigo Nonaka318ca042017-08-01 16:36:18 -0700480 const Typeface* typeface = paint->getAndroidTypeface();
Derek Sollenberger8872b382014-06-23 14:13:53 -0400481 jchar* jchars = env->GetCharArrayElements(text, NULL);
sergeyvdccca442016-03-21 15:38:21 -0700482 get_canvas(canvasHandle)->drawText(jchars + index, 0, count, count, x, y,
Seigo Nonaka7c93e862017-10-25 16:34:48 -0700483 static_cast<minikin::Bidi>(bidiFlags), *paint, typeface);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400484 env->ReleaseCharArrayElements(text, jchars, JNI_ABORT);
485}
486
487static void drawTextString(JNIEnv* env, jobject, jlong canvasHandle, jstring text,
488 jint start, jint end, jfloat x, jfloat y, jint bidiFlags,
Seigo Nonaka318ca042017-08-01 16:36:18 -0700489 jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400490 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Seigo Nonaka318ca042017-08-01 16:36:18 -0700491 const Typeface* typeface = paint->getAndroidTypeface();
Derek Sollenberger8872b382014-06-23 14:13:53 -0400492 const int count = end - start;
493 const jchar* jchars = env->GetStringChars(text, NULL);
sergeyvdccca442016-03-21 15:38:21 -0700494 get_canvas(canvasHandle)->drawText(jchars + start, 0, count, count, x, y,
Seigo Nonaka7c93e862017-10-25 16:34:48 -0700495 static_cast<minikin::Bidi>(bidiFlags), *paint, typeface);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400496 env->ReleaseStringChars(text, jchars);
497}
498
499static void drawTextRunChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text, jint index,
500 jint count, jint contextIndex, jint contextCount, jfloat x, jfloat y,
Seigo Nonaka318ca042017-08-01 16:36:18 -0700501 jboolean isRtl, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400502 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Seigo Nonaka318ca042017-08-01 16:36:18 -0700503 const Typeface* typeface = paint->getAndroidTypeface();
Derek Sollenberger8872b382014-06-23 14:13:53 -0400504
Seigo Nonaka7c93e862017-10-25 16:34:48 -0700505 const minikin::Bidi bidiFlags = isRtl ? minikin::Bidi::FORCE_RTL : minikin::Bidi::FORCE_LTR;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400506 jchar* jchars = env->GetCharArrayElements(text, NULL);
sergeyvdccca442016-03-21 15:38:21 -0700507 get_canvas(canvasHandle)->drawText(jchars + contextIndex, index - contextIndex, count,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400508 contextCount, x, y, bidiFlags, *paint, typeface);
509 env->ReleaseCharArrayElements(text, jchars, JNI_ABORT);
510}
511
512static void drawTextRunString(JNIEnv* env, jobject obj, jlong canvasHandle, jstring text,
513 jint start, jint end, jint contextStart, jint contextEnd,
Seigo Nonaka318ca042017-08-01 16:36:18 -0700514 jfloat x, jfloat y, jboolean isRtl, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400515 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Seigo Nonaka318ca042017-08-01 16:36:18 -0700516 const Typeface* typeface = paint->getAndroidTypeface();
Derek Sollenberger8872b382014-06-23 14:13:53 -0400517
Seigo Nonaka7c93e862017-10-25 16:34:48 -0700518 const minikin::Bidi bidiFlags = isRtl ? minikin::Bidi::FORCE_RTL : minikin::Bidi::FORCE_LTR;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400519 jint count = end - start;
520 jint contextCount = contextEnd - contextStart;
521 const jchar* jchars = env->GetStringChars(text, NULL);
sergeyvdccca442016-03-21 15:38:21 -0700522 get_canvas(canvasHandle)->drawText(jchars + contextStart, start - contextStart, count,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400523 contextCount, x, y, bidiFlags, *paint, typeface);
524 env->ReleaseStringChars(text, jchars);
525}
526
Derek Sollenberger8872b382014-06-23 14:13:53 -0400527static void drawTextOnPathChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text,
528 jint index, jint count, jlong pathHandle, jfloat hOffset,
Seigo Nonaka318ca042017-08-01 16:36:18 -0700529 jfloat vOffset, jint bidiFlags, jlong paintHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400530 SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400531 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Seigo Nonaka318ca042017-08-01 16:36:18 -0700532 const Typeface* typeface = paint->getAndroidTypeface();
Derek Sollenberger8872b382014-06-23 14:13:53 -0400533
534 jchar* jchars = env->GetCharArrayElements(text, NULL);
535
Seigo Nonaka7c93e862017-10-25 16:34:48 -0700536 get_canvas(canvasHandle)->drawTextOnPath(jchars + index, count,
537 static_cast<minikin::Bidi>(bidiFlags), *path, hOffset, vOffset, *paint, typeface);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400538
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,
Seigo Nonaka318ca042017-08-01 16:36:18 -0700544 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 const jchar* jchars = env->GetStringChars(text, NULL);
550 int count = env->GetStringLength(text);
551
Seigo Nonaka7c93e862017-10-25 16:34:48 -0700552 get_canvas(canvasHandle)->drawTextOnPath(jchars, count, static_cast<minikin::Bidi>(bidiFlags),
553 *path, hOffset, vOffset, *paint, typeface);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400554
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},
John Reckcaa08ff2016-10-07 13:21:36 -0700586 {"nSave","(JI)I", (void*) CanvasJNI::save},
587 {"nSaveLayer","(JFFFFJI)I", (void*) CanvasJNI::saveLayer},
588 {"nSaveLayerAlpha","(JFFFFII)I", (void*) CanvasJNI::saveLayerAlpha},
589 {"nGetSaveCount","(J)I", (void*) CanvasJNI::getSaveCount},
Chris Craikbfa0b292017-01-19 19:12:36 -0800590 {"nRestore","(J)Z", (void*) CanvasJNI::restore},
591 {"nRestoreToCount","(JI)V", (void*) CanvasJNI::restoreToCount},
592 {"nGetMatrix", "(JJ)V", (void*)CanvasJNI::getMatrix},
John Reckcaa08ff2016-10-07 13:21:36 -0700593 {"nSetMatrix","(JJ)V", (void*) CanvasJNI::setMatrix},
594 {"nConcat","(JJ)V", (void*) CanvasJNI::concat},
595 {"nRotate","(JF)V", (void*) CanvasJNI::rotate},
596 {"nScale","(JFF)V", (void*) CanvasJNI::scale},
597 {"nSkew","(JFF)V", (void*) CanvasJNI::skew},
598 {"nTranslate","(JFF)V", (void*) CanvasJNI::translate},
John Reckcaa08ff2016-10-07 13:21:36 -0700599 {"nQuickReject","(JJ)Z", (void*) CanvasJNI::quickRejectPath},
600 {"nQuickReject","(JFFFF)Z", (void*)CanvasJNI::quickRejectRect},
601 {"nClipRect","(JFFFFI)Z", (void*) CanvasJNI::clipRect},
602 {"nClipPath","(JJI)Z", (void*) CanvasJNI::clipPath},
John Reckcaa08ff2016-10-07 13:21:36 -0700603 {"nSetDrawFilter", "(JJ)V", (void*) CanvasJNI::setDrawFilter},
604};
605
606// If called from Canvas these are regular JNI
607// If called from DisplayListCanvas they are @FastNative
608static const JNINativeMethod gDrawMethods[] = {
609 {"nDrawColor","(JII)V", (void*) CanvasJNI::drawColor},
610 {"nDrawPaint","(JJ)V", (void*) CanvasJNI::drawPaint},
611 {"nDrawPoint", "(JFFJ)V", (void*) CanvasJNI::drawPoint},
612 {"nDrawPoints", "(J[FIIJ)V", (void*) CanvasJNI::drawPoints},
613 {"nDrawLine", "(JFFFFJ)V", (void*) CanvasJNI::drawLine},
614 {"nDrawLines", "(J[FIIJ)V", (void*) CanvasJNI::drawLines},
615 {"nDrawRect","(JFFFFJ)V", (void*) CanvasJNI::drawRect},
616 {"nDrawRegion", "(JJJ)V", (void*) CanvasJNI::drawRegion },
617 {"nDrawRoundRect","(JFFFFFFJ)V", (void*) CanvasJNI::drawRoundRect},
618 {"nDrawCircle","(JFFFJ)V", (void*) CanvasJNI::drawCircle},
619 {"nDrawOval","(JFFFFJ)V", (void*) CanvasJNI::drawOval},
620 {"nDrawArc","(JFFFFFFZJ)V", (void*) CanvasJNI::drawArc},
621 {"nDrawPath","(JJJ)V", (void*) CanvasJNI::drawPath},
622 {"nDrawVertices", "(JII[FI[FI[II[SIIJ)V", (void*)CanvasJNI::drawVertices},
623 {"nDrawNinePatch", "(JJJFFFFJII)V", (void*)CanvasJNI::drawNinePatch},
624 {"nDrawBitmapMatrix", "(JLandroid/graphics/Bitmap;JJ)V", (void*)CanvasJNI::drawBitmapMatrix},
625 {"nDrawBitmapMesh", "(JLandroid/graphics/Bitmap;II[FI[IIJ)V", (void*)CanvasJNI::drawBitmapMesh},
626 {"nDrawBitmap","(JLandroid/graphics/Bitmap;FFJIII)V", (void*) CanvasJNI::drawBitmap},
627 {"nDrawBitmap","(JLandroid/graphics/Bitmap;FFFFFFFFJII)V", (void*) CanvasJNI::drawBitmapRect},
628 {"nDrawBitmap", "(J[IIIFFIIZJ)V", (void*)CanvasJNI::drawBitmapArray},
Seigo Nonaka318ca042017-08-01 16:36:18 -0700629 {"nDrawText","(J[CIIFFIJ)V", (void*) CanvasJNI::drawTextChars},
630 {"nDrawText","(JLjava/lang/String;IIFFIJ)V", (void*) CanvasJNI::drawTextString},
631 {"nDrawTextRun","(J[CIIIIFFZJ)V", (void*) CanvasJNI::drawTextRunChars},
632 {"nDrawTextRun","(JLjava/lang/String;IIIIFFZJ)V", (void*) CanvasJNI::drawTextRunString},
633 {"nDrawTextOnPath","(J[CIIJFFIJ)V", (void*) CanvasJNI::drawTextOnPathChars},
634 {"nDrawTextOnPath","(JLjava/lang/String;JFFIJ)V", (void*) CanvasJNI::drawTextOnPathString},
Derek Sollenberger8872b382014-06-23 14:13:53 -0400635};
636
637int register_android_graphics_Canvas(JNIEnv* env) {
John Reckcaa08ff2016-10-07 13:21:36 -0700638 int ret = 0;
639 ret |= RegisterMethodsOrDie(env, "android/graphics/Canvas", gMethods, NELEM(gMethods));
640 ret |= RegisterMethodsOrDie(env, "android/graphics/BaseCanvas", gDrawMethods, NELEM(gDrawMethods));
641 ret |= RegisterMethodsOrDie(env, "android/view/RecordingCanvas", gDrawMethods, NELEM(gDrawMethods));
642 return ret;
643
Derek Sollenberger8872b382014-06-23 14:13:53 -0400644}
645
646}; // namespace android