blob: 34877e054e554b8f5d1a788be4d086302cf56238 [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>
John Reck849911a2015-01-20 07:51:14 -080022#include <Canvas.h>
Derek Sollenberger4c5efe92015-07-10 13:56:39 -040023
24#include "Bitmap.h"
Derek Sollenbergeracb40992014-07-21 15:22:10 -040025#include "SkDrawFilter.h"
Derek Sollenberger8872b382014-06-23 14:13:53 -040026#include "SkGraphics.h"
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -040027#include "Paint.h"
Derek Sollenberger8872b382014-06-23 14:13:53 -040028#include "TypefaceImpl.h"
29
Derek Sollenberger8872b382014-06-23 14:13:53 -040030#include "MinikinUtils.h"
31
32namespace android {
33
34namespace CanvasJNI {
35
36static Canvas* get_canvas(jlong canvasHandle) {
37 return reinterpret_cast<Canvas*>(canvasHandle);
38}
39
Richard Uhler775873a2015-12-29 12:37:39 -080040static void delete_canvas(Canvas* canvas) {
41 delete canvas;
42}
43
44static jlong getNativeFinalizer(JNIEnv* env, jobject clazz) {
45 return static_cast<jlong>(reinterpret_cast<uintptr_t>(&delete_canvas));
Derek Sollenberger8872b382014-06-23 14:13:53 -040046}
47
48// Native wrapper constructor used by Canvas(Bitmap)
John Reckc1b33d62015-04-22 09:04:45 -070049static jlong initRaster(JNIEnv* env, jobject, jobject jbitmap) {
John Reck3731dc22015-04-13 15:20:29 -070050 SkBitmap bitmap;
John Reckc1b33d62015-04-22 09:04:45 -070051 if (jbitmap != NULL) {
John Reck3731dc22015-04-13 15:20:29 -070052 GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
John Reckc1b33d62015-04-22 09:04:45 -070053 }
John Reck3731dc22015-04-13 15:20:29 -070054 return reinterpret_cast<jlong>(Canvas::create_canvas(bitmap));
Derek Sollenberger8872b382014-06-23 14:13:53 -040055}
56
57// Set the given bitmap as the new draw target (wrapped in a new SkCanvas),
58// optionally copying canvas matrix & clip state.
John Reckc1b33d62015-04-22 09:04:45 -070059static void setBitmap(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap) {
John Reck3731dc22015-04-13 15:20:29 -070060 SkBitmap bitmap;
John Reckc1b33d62015-04-22 09:04:45 -070061 if (jbitmap != NULL) {
John Reck3731dc22015-04-13 15:20:29 -070062 GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
John Reckc1b33d62015-04-22 09:04:45 -070063 }
John Reck3731dc22015-04-13 15:20:29 -070064 get_canvas(canvasHandle)->setBitmap(bitmap);
Derek Sollenberger8872b382014-06-23 14:13:53 -040065}
66
67static jboolean isOpaque(JNIEnv*, jobject, jlong canvasHandle) {
68 return get_canvas(canvasHandle)->isOpaque() ? JNI_TRUE : JNI_FALSE;
69}
70
71static jint getWidth(JNIEnv*, jobject, jlong canvasHandle) {
72 return static_cast<jint>(get_canvas(canvasHandle)->width());
73}
74
75static jint getHeight(JNIEnv*, jobject, jlong canvasHandle) {
76 return static_cast<jint>(get_canvas(canvasHandle)->height());
77}
78
Derek Sollenberger6578a982015-07-13 13:24:29 -040079static void setHighContrastText(JNIEnv*, jobject, jlong canvasHandle, jboolean highContrastText) {
80 Canvas* canvas = get_canvas(canvasHandle);
81 canvas->setHighContrastText(highContrastText);
82}
83
Derek Sollenberger8872b382014-06-23 14:13:53 -040084static jint getSaveCount(JNIEnv*, jobject, jlong canvasHandle) {
85 return static_cast<jint>(get_canvas(canvasHandle)->getSaveCount());
86}
87
88static jint save(JNIEnv*, jobject, jlong canvasHandle, jint flagsHandle) {
89 SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
90 return static_cast<jint>(get_canvas(canvasHandle)->save(flags));
91}
92
93static jint saveLayer(JNIEnv* env, jobject, jlong canvasHandle, jfloat l, jfloat t,
94 jfloat r, jfloat b, jlong paintHandle, jint flagsHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -040095 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -040096 SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
97 return static_cast<jint>(get_canvas(canvasHandle)->saveLayer(l, t, r, b, paint, flags));
98}
99
100static jint saveLayerAlpha(JNIEnv* env, jobject, jlong canvasHandle, jfloat l, jfloat t,
101 jfloat r, jfloat b, jint alpha, jint flagsHandle) {
102 SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
103 return static_cast<jint>(get_canvas(canvasHandle)->saveLayerAlpha(l, t, r, b, alpha, flags));
104}
105
Chris Craik3891f3a2015-04-02 15:28:08 -0700106static void restore(JNIEnv* env, jobject, jlong canvasHandle, jboolean throwOnUnderflow) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400107 Canvas* canvas = get_canvas(canvasHandle);
108 if (canvas->getSaveCount() <= 1) { // cannot restore anymore
Chris Craik3891f3a2015-04-02 15:28:08 -0700109 if (throwOnUnderflow) {
110 doThrowISE(env, "Underflow in restore - more restores than saves");
111 }
112 return; // compat behavior - return without throwing
Derek Sollenberger8872b382014-06-23 14:13:53 -0400113 }
114 canvas->restore();
115}
116
Chris Craik3891f3a2015-04-02 15:28:08 -0700117static void restoreToCount(JNIEnv* env, jobject, jlong canvasHandle, jint restoreCount,
118 jboolean throwOnUnderflow) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400119 Canvas* canvas = get_canvas(canvasHandle);
120 if (restoreCount < 1 || restoreCount > canvas->getSaveCount()) {
Chris Craik3891f3a2015-04-02 15:28:08 -0700121 if (throwOnUnderflow) {
122 doThrowIAE(env, "Underflow in restoreToCount - more restores than saves");
123 return;
124 }
125 restoreCount = 1; // compat behavior - restore as far as possible
Derek Sollenberger8872b382014-06-23 14:13:53 -0400126 }
127 canvas->restoreToCount(restoreCount);
128}
129
130static void getCTM(JNIEnv* env, jobject, jlong canvasHandle, jlong matrixHandle) {
131 SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
132 get_canvas(canvasHandle)->getMatrix(matrix);
133}
134
135static void setMatrix(JNIEnv* env, jobject, jlong canvasHandle, jlong matrixHandle) {
136 const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
137 get_canvas(canvasHandle)->setMatrix(matrix ? *matrix : SkMatrix::I());
138}
139
140static void concat(JNIEnv* env, jobject, jlong canvasHandle, jlong matrixHandle) {
141 const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
142 get_canvas(canvasHandle)->concat(*matrix);
143}
144
145static void rotate(JNIEnv*, jobject, jlong canvasHandle, jfloat degrees) {
146 get_canvas(canvasHandle)->rotate(degrees);
147}
148
149static void scale(JNIEnv*, jobject, jlong canvasHandle, jfloat sx, jfloat sy) {
150 get_canvas(canvasHandle)->scale(sx, sy);
151}
152
153static void skew(JNIEnv*, jobject, jlong canvasHandle, jfloat sx, jfloat sy) {
154 get_canvas(canvasHandle)->skew(sx, sy);
155}
156
157static void translate(JNIEnv*, jobject, jlong canvasHandle, jfloat dx, jfloat dy) {
158 get_canvas(canvasHandle)->translate(dx, dy);
159}
160
161static jboolean getClipBounds(JNIEnv* env, jobject, jlong canvasHandle, jobject bounds) {
162 SkRect r;
163 SkIRect ir;
164 bool result = get_canvas(canvasHandle)->getClipBounds(&r);
165
166 if (!result) {
167 r.setEmpty();
168 }
169 r.round(&ir);
170
171 (void)GraphicsJNI::irect_to_jrect(ir, env, bounds);
172 return result ? JNI_TRUE : JNI_FALSE;
173}
174
175static jboolean quickRejectRect(JNIEnv* env, jobject, jlong canvasHandle,
176 jfloat left, jfloat top, jfloat right, jfloat bottom) {
177 bool result = get_canvas(canvasHandle)->quickRejectRect(left, top, right, bottom);
178 return result ? JNI_TRUE : JNI_FALSE;
179}
180
181static jboolean quickRejectPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle) {
182 SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
183 bool result = get_canvas(canvasHandle)->quickRejectPath(*path);
184 return result ? JNI_TRUE : JNI_FALSE;
185}
186
187static jboolean clipRect(JNIEnv*, jobject, jlong canvasHandle, jfloat l, jfloat t,
188 jfloat r, jfloat b, jint opHandle) {
189 SkRegion::Op op = static_cast<SkRegion::Op>(opHandle);
Chris Craik5ec6a282015-06-23 15:42:12 -0700190 bool nonEmptyClip = get_canvas(canvasHandle)->clipRect(l, t, r, b, op);
191 return nonEmptyClip ? JNI_TRUE : JNI_FALSE;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400192}
193
194static jboolean clipPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle,
195 jint opHandle) {
196 SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
197 SkRegion::Op op = static_cast<SkRegion::Op>(opHandle);
Chris Craik5ec6a282015-06-23 15:42:12 -0700198 bool nonEmptyClip = get_canvas(canvasHandle)->clipPath(path, op);
199 return nonEmptyClip ? JNI_TRUE : JNI_FALSE;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400200}
201
202static jboolean clipRegion(JNIEnv* env, jobject, jlong canvasHandle, jlong deviceRgnHandle,
203 jint opHandle) {
204 SkRegion* deviceRgn = reinterpret_cast<SkRegion*>(deviceRgnHandle);
205 SkRegion::Op op = static_cast<SkRegion::Op>(opHandle);
Chris Craik5ec6a282015-06-23 15:42:12 -0700206 bool nonEmptyClip = get_canvas(canvasHandle)->clipRegion(deviceRgn, op);
207 return nonEmptyClip ? JNI_TRUE : JNI_FALSE;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400208}
209
210static void drawColor(JNIEnv* env, jobject, jlong canvasHandle, jint color, jint modeHandle) {
Chris Craik1526a452015-03-06 18:42:15 +0000211 SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(modeHandle);
212 get_canvas(canvasHandle)->drawColor(color, mode);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400213}
214
215static void drawPaint(JNIEnv* env, jobject, jlong canvasHandle, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400216 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400217 get_canvas(canvasHandle)->drawPaint(*paint);
218}
219
220static void drawPoint(JNIEnv*, jobject, jlong canvasHandle, jfloat x, jfloat y,
221 jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400222 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400223 get_canvas(canvasHandle)->drawPoint(x, y, *paint);
224}
225
226static void drawPoints(JNIEnv* env, jobject, jlong canvasHandle, jfloatArray jptsArray,
227 jint offset, jint count, jlong paintHandle) {
228 NPE_CHECK_RETURN_VOID(env, jptsArray);
229 AutoJavaFloatArray autoPts(env, jptsArray);
230 float* floats = autoPts.ptr();
231 const int length = autoPts.length();
232
233 if ((offset | count) < 0 || offset + count > length) {
234 doThrowAIOOBE(env);
235 return;
236 }
237
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400238 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400239 get_canvas(canvasHandle)->drawPoints(floats + offset, count, *paint);
240}
241
242static void drawLine(JNIEnv* env, jobject, jlong canvasHandle, jfloat startX, jfloat startY,
243 jfloat stopX, jfloat stopY, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400244 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400245 get_canvas(canvasHandle)->drawLine(startX, startY, stopX, stopY, *paint);
246}
247
248static void drawLines(JNIEnv* env, jobject, jlong canvasHandle, jfloatArray jptsArray,
249 jint offset, jint count, jlong paintHandle) {
250 NPE_CHECK_RETURN_VOID(env, jptsArray);
251 AutoJavaFloatArray autoPts(env, jptsArray);
252 float* floats = autoPts.ptr();
253 const int length = autoPts.length();
254
255 if ((offset | count) < 0 || offset + count > length) {
256 doThrowAIOOBE(env);
257 return;
258 }
259
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400260 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400261 get_canvas(canvasHandle)->drawLines(floats + offset, count, *paint);
262}
263
264static void drawRect(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
265 jfloat right, jfloat bottom, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400266 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400267 get_canvas(canvasHandle)->drawRect(left, top, right, bottom, *paint);
268}
269
Derek Sollenberger94394b32015-07-10 09:58:41 -0400270static void drawRegion(JNIEnv* env, jobject, jlong canvasHandle, jlong regionHandle,
271 jlong paintHandle) {
272 const SkRegion* region = reinterpret_cast<SkRegion*>(regionHandle);
273 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
274 get_canvas(canvasHandle)->drawRegion(*region, *paint);
275}
276
Derek Sollenberger8872b382014-06-23 14:13:53 -0400277static void drawRoundRect(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
278 jfloat right, jfloat bottom, jfloat rx, jfloat ry, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400279 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400280 get_canvas(canvasHandle)->drawRoundRect(left, top, right, bottom, rx, ry, *paint);
281}
282
283static void drawCircle(JNIEnv* env, jobject, jlong canvasHandle, jfloat cx, jfloat cy,
284 jfloat radius, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400285 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400286 get_canvas(canvasHandle)->drawCircle(cx, cy, radius, *paint);
287}
288
289static void drawOval(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
290 jfloat right, jfloat bottom, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400291 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400292 get_canvas(canvasHandle)->drawOval(left, top, right, bottom, *paint);
293}
294
295static void drawArc(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
296 jfloat right, jfloat bottom, jfloat startAngle, jfloat sweepAngle,
297 jboolean useCenter, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400298 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400299 get_canvas(canvasHandle)->drawArc(left, top, right, bottom, startAngle, sweepAngle,
300 useCenter, *paint);
301}
302
303static void drawPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle,
304 jlong paintHandle) {
305 const SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400306 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400307 get_canvas(canvasHandle)->drawPath(*path, *paint);
308}
309
310static void drawVertices(JNIEnv* env, jobject, jlong canvasHandle,
311 jint modeHandle, jint vertexCount,
312 jfloatArray jverts, jint vertIndex,
313 jfloatArray jtexs, jint texIndex,
314 jintArray jcolors, jint colorIndex,
315 jshortArray jindices, jint indexIndex,
316 jint indexCount, jlong paintHandle) {
317 AutoJavaFloatArray vertA(env, jverts, vertIndex + vertexCount);
318 AutoJavaFloatArray texA(env, jtexs, texIndex + vertexCount);
319 AutoJavaIntArray colorA(env, jcolors, colorIndex + vertexCount);
320 AutoJavaShortArray indexA(env, jindices, indexIndex + indexCount);
321
322 const float* verts = vertA.ptr() + vertIndex;
323 const float* texs = texA.ptr() + vertIndex;
324 const int* colors = NULL;
325 const uint16_t* indices = NULL;
326
327 if (jcolors != NULL) {
328 colors = colorA.ptr() + colorIndex;
329 }
330 if (jindices != NULL) {
331 indices = (const uint16_t*)(indexA.ptr() + indexIndex);
332 }
333
334 SkCanvas::VertexMode mode = static_cast<SkCanvas::VertexMode>(modeHandle);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400335 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400336 get_canvas(canvasHandle)->drawVertices(mode, vertexCount, verts, texs, colors,
337 indices, indexCount, *paint);
338}
339
Derek Sollenberger4c5efe92015-07-10 13:56:39 -0400340static void drawNinePatch(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle,
341 jlong chunkHandle, jfloat left, jfloat top, jfloat right, jfloat bottom,
342 jlong paintHandle, jint dstDensity, jint srcDensity) {
343
344 Canvas* canvas = get_canvas(canvasHandle);
345 Bitmap* bitmap = reinterpret_cast<Bitmap*>(bitmapHandle);
346 SkBitmap skiaBitmap;
347 bitmap->getSkBitmap(&skiaBitmap);
348 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)) {
352 canvas->drawNinePatch(skiaBitmap, *chunk, left, top, right, bottom, paint);
353 } else {
354 canvas->save(SkCanvas::kMatrixClip_SaveFlag);
355
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
366 canvas->drawNinePatch(skiaBitmap, *chunk, 0, 0, (right-left)/scale, (bottom-top)/scale,
367 &filteredPaint);
368
369 canvas->restore();
370 }
371}
372
John Reck7c103a32015-04-15 15:52:10 -0700373static void drawBitmap(JNIEnv* env, jobject jcanvas, 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);
John Reck7c103a32015-04-15 15:52:10 -0700377 SkBitmap bitmap;
378 GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400379 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400380
381 if (canvasDensity == bitmapDensity || canvasDensity == 0 || bitmapDensity == 0) {
382 if (screenDensity != 0 && screenDensity != bitmapDensity) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400383 Paint filteredPaint;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400384 if (paint) {
385 filteredPaint = *paint;
386 }
Mike Reed2a1ce8a2015-03-16 11:16:09 -0400387 filteredPaint.setFilterQuality(kLow_SkFilterQuality);
John Reck7c103a32015-04-15 15:52:10 -0700388 canvas->drawBitmap(bitmap, left, top, &filteredPaint);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400389 } else {
John Reck7c103a32015-04-15 15:52:10 -0700390 canvas->drawBitmap(bitmap, left, top, paint);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400391 }
392 } else {
393 canvas->save(SkCanvas::kMatrixClip_SaveFlag);
394 SkScalar scale = canvasDensity / (float)bitmapDensity;
395 canvas->translate(left, top);
396 canvas->scale(scale, scale);
397
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400398 Paint filteredPaint;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400399 if (paint) {
400 filteredPaint = *paint;
401 }
Mike Reed2a1ce8a2015-03-16 11:16:09 -0400402 filteredPaint.setFilterQuality(kLow_SkFilterQuality);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400403
John Reck7c103a32015-04-15 15:52:10 -0700404 canvas->drawBitmap(bitmap, 0, 0, &filteredPaint);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400405 canvas->restore();
406 }
407}
408
John Reck7c103a32015-04-15 15:52:10 -0700409static void drawBitmapMatrix(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400410 jlong matrixHandle, jlong paintHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400411 const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400412 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
John Reck7c103a32015-04-15 15:52:10 -0700413 SkBitmap bitmap;
414 GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
415 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
John Reck7c103a32015-04-15 15:52:10 -0700425 SkBitmap bitmap;
426 GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400427 if (screenDensity != 0 && screenDensity != bitmapDensity) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400428 Paint filteredPaint;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400429 if (paint) {
430 filteredPaint = *paint;
431 }
Mike Reed2a1ce8a2015-03-16 11:16:09 -0400432 filteredPaint.setFilterQuality(kLow_SkFilterQuality);
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, &filteredPaint);
435 } else {
John Reck7c103a32015-04-15 15:52:10 -0700436 canvas->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400437 dstLeft, dstTop, dstRight, dstBottom, paint);
438 }
439}
440
441static void drawBitmapArray(JNIEnv* env, jobject, jlong canvasHandle,
442 jintArray jcolors, jint offset, jint stride,
443 jfloat x, jfloat y, jint width, jint height,
444 jboolean hasAlpha, jlong paintHandle) {
445 // Note: If hasAlpha is false, kRGB_565_SkColorType will be used, which will
446 // correct the alphaType to kOpaque_SkAlphaType.
447 SkImageInfo info = SkImageInfo::Make(width, height,
448 hasAlpha ? kN32_SkColorType : kRGB_565_SkColorType,
449 kPremul_SkAlphaType);
450 SkBitmap bitmap;
Derek Sollenberger3d4eed72014-12-04 15:20:29 -0500451 bitmap.setInfo(info);
452 if (!GraphicsJNI::allocatePixels(env, &bitmap, NULL)) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400453 return;
454 }
455
456 if (!GraphicsJNI::SetPixels(env, jcolors, offset, stride, 0, 0, width, height, bitmap)) {
457 return;
458 }
459
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400460 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400461 get_canvas(canvasHandle)->drawBitmap(bitmap, x, y, paint);
462}
463
John Reck7c103a32015-04-15 15:52:10 -0700464static void drawBitmapMesh(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400465 jint meshWidth, jint meshHeight, jfloatArray jverts,
466 jint vertIndex, jintArray jcolors, jint colorIndex, jlong paintHandle) {
467 const int ptCount = (meshWidth + 1) * (meshHeight + 1);
468 AutoJavaFloatArray vertA(env, jverts, vertIndex + (ptCount << 1));
469 AutoJavaIntArray colorA(env, jcolors, colorIndex + ptCount);
470
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400471 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
John Reck7c103a32015-04-15 15:52:10 -0700472 SkBitmap bitmap;
473 GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
474 get_canvas(canvasHandle)->drawBitmapMesh(bitmap, meshWidth, meshHeight,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400475 vertA.ptr(), colorA.ptr(), paint);
476}
477
Derek Sollenberger6578a982015-07-13 13:24:29 -0400478static void simplifyPaint(int color, SkPaint* paint) {
479 paint->setColor(color);
480 paint->setShader(nullptr);
481 paint->setColorFilter(nullptr);
482 paint->setLooper(nullptr);
483 paint->setStrokeWidth(4 + 0.04 * paint->getTextSize());
484 paint->setStrokeJoin(SkPaint::kRound_Join);
485 paint->setLooper(nullptr);
486}
487
Derek Sollenbergeracb40992014-07-21 15:22:10 -0400488class DrawTextFunctor {
489public:
490 DrawTextFunctor(const Layout& layout, Canvas* canvas, uint16_t* glyphs, float* pos,
Tom Hudson8dfaa492014-12-09 15:03:44 -0500491 const SkPaint& paint, float x, float y, MinikinRect& bounds,
492 float totalAdvance)
Derek Sollenbergeracb40992014-07-21 15:22:10 -0400493 : layout(layout), canvas(canvas), glyphs(glyphs), pos(pos), paint(paint),
Tom Hudson8dfaa492014-12-09 15:03:44 -0500494 x(x), y(y), bounds(bounds), totalAdvance(totalAdvance) { }
Derek Sollenbergeracb40992014-07-21 15:22:10 -0400495
496 void operator()(size_t start, size_t end) {
497 if (canvas->drawTextAbsolutePos()) {
498 for (size_t i = start; i < end; i++) {
499 glyphs[i] = layout.getGlyphId(i);
500 pos[2 * i] = x + layout.getX(i);
501 pos[2 * i + 1] = y + layout.getY(i);
502 }
503 } else {
504 for (size_t i = start; i < end; i++) {
505 glyphs[i] = layout.getGlyphId(i);
506 pos[2 * i] = layout.getX(i);
507 pos[2 * i + 1] = layout.getY(i);
508 }
509 }
510
511 size_t glyphCount = end - start;
Derek Sollenberger6578a982015-07-13 13:24:29 -0400512
513 if (CC_UNLIKELY(canvas->isHighContrastText())) {
514 // high contrast draw path
515 int color = paint.getColor();
516 int channelSum = SkColorGetR(color) + SkColorGetG(color) + SkColorGetB(color);
517 bool darken = channelSum < (128 * 3);
518
519 // outline
520 SkPaint outlinePaint(paint);
521 simplifyPaint(darken ? SK_ColorWHITE : SK_ColorBLACK, &outlinePaint);
522 outlinePaint.setStyle(SkPaint::kStrokeAndFill_Style);
523 canvas->drawText(glyphs + start, pos + (2 * start), glyphCount, outlinePaint, x, y,
524 bounds.mLeft, bounds.mTop, bounds.mRight, bounds.mBottom, totalAdvance);
525
526 // inner
527 SkPaint innerPaint(paint);
528 simplifyPaint(darken ? SK_ColorBLACK : SK_ColorWHITE, &innerPaint);
529 innerPaint.setStyle(SkPaint::kFill_Style);
530 canvas->drawText(glyphs + start, pos + (2 * start), glyphCount, innerPaint, x, y,
531 bounds.mLeft, bounds.mTop, bounds.mRight, bounds.mBottom, totalAdvance);
532 } else {
533 // standard draw path
534 canvas->drawText(glyphs + start, pos + (2 * start), glyphCount, paint, x, y,
535 bounds.mLeft, bounds.mTop, bounds.mRight, bounds.mBottom,
536 totalAdvance);
537 }
Derek Sollenbergeracb40992014-07-21 15:22:10 -0400538 }
539private:
540 const Layout& layout;
541 Canvas* canvas;
542 uint16_t* glyphs;
543 float* pos;
544 const SkPaint& paint;
545 float x;
546 float y;
547 MinikinRect& bounds;
Tom Hudson8dfaa492014-12-09 15:03:44 -0500548 float totalAdvance;
Derek Sollenbergeracb40992014-07-21 15:22:10 -0400549};
550
Derek Sollenbergeracb40992014-07-21 15:22:10 -0400551void drawText(Canvas* canvas, const uint16_t* text, int start, int count, int contextCount,
552 float x, float y, int bidiFlags, const Paint& origPaint, TypefaceImpl* typeface) {
553 // minikin may modify the original paint
554 Paint paint(origPaint);
555
556 Layout layout;
Behdad Esfahbod63c5c782014-07-25 14:54:46 -0400557 MinikinUtils::doLayout(&layout, &paint, bidiFlags, typeface, text, start, count, contextCount);
Derek Sollenbergeracb40992014-07-21 15:22:10 -0400558
559 size_t nGlyphs = layout.nGlyphs();
Chris Craika1717272015-11-19 13:02:43 -0800560 std::unique_ptr<uint16_t[]> glyphs(new uint16_t[nGlyphs]);
561 std::unique_ptr<float[]> pos(new float[nGlyphs * 2]);
Derek Sollenbergeracb40992014-07-21 15:22:10 -0400562
563 x += MinikinUtils::xOffsetForTextAlign(&paint, layout);
564
565 MinikinRect bounds;
566 layout.getBounds(&bounds);
Tom Hudson8dfaa492014-12-09 15:03:44 -0500567 if (!canvas->drawTextAbsolutePos()) {
568 bounds.offset(x, y);
569 }
Derek Sollenbergeracb40992014-07-21 15:22:10 -0400570
Chris Craika1717272015-11-19 13:02:43 -0800571 DrawTextFunctor f(layout, canvas, glyphs.get(), pos.get(),
572 paint, x, y, bounds, layout.getAdvance());
Derek Sollenbergeracb40992014-07-21 15:22:10 -0400573 MinikinUtils::forFontRun(layout, &paint, f);
Derek Sollenbergeracb40992014-07-21 15:22:10 -0400574}
575
Derek Sollenberger8872b382014-06-23 14:13:53 -0400576static void drawTextChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text,
577 jint index, jint count, jfloat x, jfloat y, jint bidiFlags,
578 jlong paintHandle, jlong typefaceHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400579 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400580 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
581 jchar* jchars = env->GetCharArrayElements(text, NULL);
Derek Sollenbergeracb40992014-07-21 15:22:10 -0400582 drawText(get_canvas(canvasHandle), jchars + index, 0, count, count, x, y,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400583 bidiFlags, *paint, typeface);
584 env->ReleaseCharArrayElements(text, jchars, JNI_ABORT);
585}
586
587static void drawTextString(JNIEnv* env, jobject, jlong canvasHandle, jstring text,
588 jint start, jint end, jfloat x, jfloat y, jint bidiFlags,
589 jlong paintHandle, jlong typefaceHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400590 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400591 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
592 const int count = end - start;
593 const jchar* jchars = env->GetStringChars(text, NULL);
Derek Sollenbergeracb40992014-07-21 15:22:10 -0400594 drawText(get_canvas(canvasHandle), jchars + start, 0, count, count, x, y,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400595 bidiFlags, *paint, typeface);
596 env->ReleaseStringChars(text, jchars);
597}
598
599static void drawTextRunChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text, jint index,
600 jint count, jint contextIndex, jint contextCount, jfloat x, jfloat y,
601 jboolean isRtl, jlong paintHandle, jlong typefaceHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400602 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400603 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
604
605 const int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
606 jchar* jchars = env->GetCharArrayElements(text, NULL);
Derek Sollenbergeracb40992014-07-21 15:22:10 -0400607 drawText(get_canvas(canvasHandle), jchars + contextIndex, index - contextIndex, count,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400608 contextCount, x, y, bidiFlags, *paint, typeface);
609 env->ReleaseCharArrayElements(text, jchars, JNI_ABORT);
610}
611
612static void drawTextRunString(JNIEnv* env, jobject obj, jlong canvasHandle, jstring text,
613 jint start, jint end, jint contextStart, jint contextEnd,
614 jfloat x, jfloat y, jboolean isRtl, jlong paintHandle,
615 jlong typefaceHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400616 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400617 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
618
619 int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
620 jint count = end - start;
621 jint contextCount = contextEnd - contextStart;
622 const jchar* jchars = env->GetStringChars(text, NULL);
Derek Sollenbergeracb40992014-07-21 15:22:10 -0400623 drawText(get_canvas(canvasHandle), jchars + contextStart, start - contextStart, count,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400624 contextCount, x, y, bidiFlags, *paint, typeface);
625 env->ReleaseStringChars(text, jchars);
626}
627
Derek Sollenberger8872b382014-06-23 14:13:53 -0400628class DrawTextOnPathFunctor {
629public:
630 DrawTextOnPathFunctor(const Layout& layout, Canvas* canvas, float hOffset,
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400631 float vOffset, const Paint& paint, const SkPath& path)
Derek Sollenberger8872b382014-06-23 14:13:53 -0400632 : layout(layout), canvas(canvas), hOffset(hOffset), vOffset(vOffset),
633 paint(paint), path(path) {
634 }
635 void operator()(size_t start, size_t end) {
636 uint16_t glyphs[1];
637 for (size_t i = start; i < end; i++) {
638 glyphs[0] = layout.getGlyphId(i);
639 float x = hOffset + layout.getX(i);
640 float y = vOffset + layout.getY(i);
641 canvas->drawTextOnPath(glyphs, 1, path, x, y, paint);
642 }
643 }
644private:
645 const Layout& layout;
646 Canvas* canvas;
647 float hOffset;
648 float vOffset;
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400649 const Paint& paint;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400650 const SkPath& path;
651};
652
653static void drawTextOnPath(Canvas* canvas, const uint16_t* text, int count, int bidiFlags,
654 const SkPath& path, float hOffset, float vOffset,
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400655 const Paint& paint, TypefaceImpl* typeface) {
656 Paint paintCopy(paint);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400657 Layout layout;
Behdad Esfahbod63c5c782014-07-25 14:54:46 -0400658 MinikinUtils::doLayout(&layout, &paintCopy, bidiFlags, typeface, text, 0, count, count);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400659 hOffset += MinikinUtils::hOffsetForTextAlign(&paintCopy, layout, path);
660
661 // Set align to left for drawing, as we don't want individual
662 // glyphs centered or right-aligned; the offset above takes
663 // care of all alignment.
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400664 paintCopy.setTextAlign(Paint::kLeft_Align);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400665
666 DrawTextOnPathFunctor f(layout, canvas, hOffset, vOffset, paintCopy, path);
667 MinikinUtils::forFontRun(layout, &paintCopy, f);
668}
669
670static void drawTextOnPathChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text,
671 jint index, jint count, jlong pathHandle, jfloat hOffset,
672 jfloat vOffset, jint bidiFlags, jlong paintHandle,
673 jlong typefaceHandle) {
674 SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400675 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400676 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
677
678 jchar* jchars = env->GetCharArrayElements(text, NULL);
679
680 drawTextOnPath(get_canvas(canvasHandle), jchars + index, count, bidiFlags, *path,
681 hOffset, vOffset, *paint, typeface);
682
683 env->ReleaseCharArrayElements(text, jchars, 0);
684}
685
686static void drawTextOnPathString(JNIEnv* env, jobject, jlong canvasHandle, jstring text,
687 jlong pathHandle, jfloat hOffset, jfloat vOffset,
688 jint bidiFlags, jlong paintHandle, jlong typefaceHandle) {
689 SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400690 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400691 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
692
693 const jchar* jchars = env->GetStringChars(text, NULL);
694 int count = env->GetStringLength(text);
695
696 drawTextOnPath(get_canvas(canvasHandle), jchars, count, bidiFlags, *path,
697 hOffset, vOffset, *paint, typeface);
698
699 env->ReleaseStringChars(text, jchars);
700}
701
702static void setDrawFilter(JNIEnv* env, jobject, jlong canvasHandle, jlong filterHandle) {
703 get_canvas(canvasHandle)->setDrawFilter(reinterpret_cast<SkDrawFilter*>(filterHandle));
704}
705
706static void freeCaches(JNIEnv* env, jobject) {
707 SkGraphics::PurgeFontCache();
708}
709
710static void freeTextLayoutCaches(JNIEnv* env, jobject) {
711 Layout::purgeCaches();
712}
713
714}; // namespace CanvasJNI
715
Daniel Micay76f6a862015-09-19 17:31:01 -0400716static const JNINativeMethod gMethods[] = {
Richard Uhler775873a2015-12-29 12:37:39 -0800717 {"getNativeFinalizer", "()J", (void*) CanvasJNI::getNativeFinalizer},
John Reckc1b33d62015-04-22 09:04:45 -0700718 {"initRaster", "(Landroid/graphics/Bitmap;)J", (void*) CanvasJNI::initRaster},
John Reck0dba1f62015-10-05 11:15:36 -0700719 {"native_setBitmap", "!(JLandroid/graphics/Bitmap;)V", (void*) CanvasJNI::setBitmap},
720 {"native_isOpaque","!(J)Z", (void*) CanvasJNI::isOpaque},
721 {"native_getWidth","!(J)I", (void*) CanvasJNI::getWidth},
722 {"native_getHeight","!(J)I", (void*) CanvasJNI::getHeight},
723 {"native_setHighContrastText","!(JZ)V", (void*) CanvasJNI::setHighContrastText},
724 {"native_save","!(JI)I", (void*) CanvasJNI::save},
725 {"native_saveLayer","!(JFFFFJI)I", (void*) CanvasJNI::saveLayer},
726 {"native_saveLayerAlpha","!(JFFFFII)I", (void*) CanvasJNI::saveLayerAlpha},
727 {"native_getSaveCount","!(J)I", (void*) CanvasJNI::getSaveCount},
728 {"native_restore","!(JZ)V", (void*) CanvasJNI::restore},
729 {"native_restoreToCount","!(JIZ)V", (void*) CanvasJNI::restoreToCount},
730 {"native_getCTM", "!(JJ)V", (void*)CanvasJNI::getCTM},
731 {"native_setMatrix","!(JJ)V", (void*) CanvasJNI::setMatrix},
732 {"native_concat","!(JJ)V", (void*) CanvasJNI::concat},
733 {"native_rotate","!(JF)V", (void*) CanvasJNI::rotate},
734 {"native_scale","!(JFF)V", (void*) CanvasJNI::scale},
735 {"native_skew","!(JFF)V", (void*) CanvasJNI::skew},
736 {"native_translate","!(JFF)V", (void*) CanvasJNI::translate},
737 {"native_getClipBounds","!(JLandroid/graphics/Rect;)Z", (void*) CanvasJNI::getClipBounds},
738 {"native_quickReject","!(JJ)Z", (void*) CanvasJNI::quickRejectPath},
739 {"native_quickReject","!(JFFFF)Z", (void*)CanvasJNI::quickRejectRect},
740 {"native_clipRect","!(JFFFFI)Z", (void*) CanvasJNI::clipRect},
741 {"native_clipPath","!(JJI)Z", (void*) CanvasJNI::clipPath},
742 {"native_clipRegion","!(JJI)Z", (void*) CanvasJNI::clipRegion},
743 {"native_drawColor","!(JII)V", (void*) CanvasJNI::drawColor},
744 {"native_drawPaint","!(JJ)V", (void*) CanvasJNI::drawPaint},
745 {"native_drawPoint", "!(JFFJ)V", (void*) CanvasJNI::drawPoint},
746 {"native_drawPoints", "!(J[FIIJ)V", (void*) CanvasJNI::drawPoints},
747 {"native_drawLine", "!(JFFFFJ)V", (void*) CanvasJNI::drawLine},
748 {"native_drawLines", "!(J[FIIJ)V", (void*) CanvasJNI::drawLines},
749 {"native_drawRect","!(JFFFFJ)V", (void*) CanvasJNI::drawRect},
750 {"native_drawRegion", "!(JJJ)V", (void*) CanvasJNI::drawRegion },
751 {"native_drawRoundRect","!(JFFFFFFJ)V", (void*) CanvasJNI::drawRoundRect},
752 {"native_drawCircle","!(JFFFJ)V", (void*) CanvasJNI::drawCircle},
753 {"native_drawOval","!(JFFFFJ)V", (void*) CanvasJNI::drawOval},
754 {"native_drawArc","!(JFFFFFFZJ)V", (void*) CanvasJNI::drawArc},
755 {"native_drawPath","!(JJJ)V", (void*) CanvasJNI::drawPath},
756 {"nativeDrawVertices", "!(JII[FI[FI[II[SIIJ)V", (void*)CanvasJNI::drawVertices},
757 {"native_drawNinePatch", "!(JJJFFFFJII)V", (void*)CanvasJNI::drawNinePatch},
758 {"native_drawBitmap","!(JLandroid/graphics/Bitmap;FFJIII)V", (void*) CanvasJNI::drawBitmap},
759 {"nativeDrawBitmapMatrix", "!(JLandroid/graphics/Bitmap;JJ)V", (void*)CanvasJNI::drawBitmapMatrix},
760 {"native_drawBitmap","!(JLandroid/graphics/Bitmap;FFFFFFFFJII)V", (void*) CanvasJNI::drawBitmapRect},
761 {"native_drawBitmap", "!(J[IIIFFIIZJ)V", (void*)CanvasJNI::drawBitmapArray},
762 {"nativeDrawBitmapMesh", "!(JLandroid/graphics/Bitmap;II[FI[IIJ)V", (void*)CanvasJNI::drawBitmapMesh},
763 {"native_drawText","!(J[CIIFFIJJ)V", (void*) CanvasJNI::drawTextChars},
764 {"native_drawText","!(JLjava/lang/String;IIFFIJJ)V", (void*) CanvasJNI::drawTextString},
765 {"native_drawTextRun","!(J[CIIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunChars},
766 {"native_drawTextRun","!(JLjava/lang/String;IIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunString},
767 {"native_drawTextOnPath","!(J[CIIJFFIJJ)V", (void*) CanvasJNI::drawTextOnPathChars},
768 {"native_drawTextOnPath","!(JLjava/lang/String;JFFIJJ)V", (void*) CanvasJNI::drawTextOnPathString},
769 {"nativeSetDrawFilter", "!(JJ)V", (void*) CanvasJNI::setDrawFilter},
Derek Sollenberger8872b382014-06-23 14:13:53 -0400770 {"freeCaches", "()V", (void*) CanvasJNI::freeCaches},
771 {"freeTextLayoutCaches", "()V", (void*) CanvasJNI::freeTextLayoutCaches}
772};
773
774int register_android_graphics_Canvas(JNIEnv* env) {
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800775 return RegisterMethodsOrDie(env, "android/graphics/Canvas", gMethods, NELEM(gMethods));
Derek Sollenberger8872b382014-06-23 14:13:53 -0400776}
777
778}; // namespace android