blob: 43825adc7a805c3f1661f78010582179a8a19309 [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
John Reck849911a2015-01-20 07:51:14 -080021#include <Canvas.h>
Derek Sollenbergeracb40992014-07-21 15:22:10 -040022#include "SkDrawFilter.h"
Derek Sollenberger8872b382014-06-23 14:13:53 -040023#include "SkGraphics.h"
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -040024#include "Paint.h"
Derek Sollenberger8872b382014-06-23 14:13:53 -040025#include "TypefaceImpl.h"
26
Derek Sollenberger8872b382014-06-23 14:13:53 -040027#include "MinikinUtils.h"
28
29namespace android {
30
31namespace CanvasJNI {
32
33static Canvas* get_canvas(jlong canvasHandle) {
34 return reinterpret_cast<Canvas*>(canvasHandle);
35}
36
37static void finalizer(JNIEnv* env, jobject clazz, jlong canvasHandle) {
38 delete get_canvas(canvasHandle);
39}
40
41// Native wrapper constructor used by Canvas(Bitmap)
John Reckc1b33d62015-04-22 09:04:45 -070042static jlong initRaster(JNIEnv* env, jobject, jobject jbitmap) {
John Reck3731dc22015-04-13 15:20:29 -070043 SkBitmap bitmap;
John Reckc1b33d62015-04-22 09:04:45 -070044 if (jbitmap != NULL) {
John Reck3731dc22015-04-13 15:20:29 -070045 GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
John Reckc1b33d62015-04-22 09:04:45 -070046 }
John Reck3731dc22015-04-13 15:20:29 -070047 return reinterpret_cast<jlong>(Canvas::create_canvas(bitmap));
Derek Sollenberger8872b382014-06-23 14:13:53 -040048}
49
50// Set the given bitmap as the new draw target (wrapped in a new SkCanvas),
51// optionally copying canvas matrix & clip state.
John Reckc1b33d62015-04-22 09:04:45 -070052static void setBitmap(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap) {
John Reck3731dc22015-04-13 15:20:29 -070053 SkBitmap bitmap;
John Reckc1b33d62015-04-22 09:04:45 -070054 if (jbitmap != NULL) {
John Reck3731dc22015-04-13 15:20:29 -070055 GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
John Reckc1b33d62015-04-22 09:04:45 -070056 }
John Reck3731dc22015-04-13 15:20:29 -070057 get_canvas(canvasHandle)->setBitmap(bitmap);
Derek Sollenberger8872b382014-06-23 14:13:53 -040058}
59
60static jboolean isOpaque(JNIEnv*, jobject, jlong canvasHandle) {
61 return get_canvas(canvasHandle)->isOpaque() ? JNI_TRUE : JNI_FALSE;
62}
63
64static jint getWidth(JNIEnv*, jobject, jlong canvasHandle) {
65 return static_cast<jint>(get_canvas(canvasHandle)->width());
66}
67
68static jint getHeight(JNIEnv*, jobject, jlong canvasHandle) {
69 return static_cast<jint>(get_canvas(canvasHandle)->height());
70}
71
Derek Sollenberger6578a982015-07-13 13:24:29 -040072static void setHighContrastText(JNIEnv*, jobject, jlong canvasHandle, jboolean highContrastText) {
73 Canvas* canvas = get_canvas(canvasHandle);
74 canvas->setHighContrastText(highContrastText);
75}
76
Derek Sollenberger8872b382014-06-23 14:13:53 -040077static jint getSaveCount(JNIEnv*, jobject, jlong canvasHandle) {
78 return static_cast<jint>(get_canvas(canvasHandle)->getSaveCount());
79}
80
81static jint save(JNIEnv*, jobject, jlong canvasHandle, jint flagsHandle) {
82 SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
83 return static_cast<jint>(get_canvas(canvasHandle)->save(flags));
84}
85
86static jint saveLayer(JNIEnv* env, jobject, jlong canvasHandle, jfloat l, jfloat t,
87 jfloat r, jfloat b, jlong paintHandle, jint flagsHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -040088 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -040089 SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
90 return static_cast<jint>(get_canvas(canvasHandle)->saveLayer(l, t, r, b, paint, flags));
91}
92
93static jint saveLayerAlpha(JNIEnv* env, jobject, jlong canvasHandle, jfloat l, jfloat t,
94 jfloat r, jfloat b, jint alpha, jint flagsHandle) {
95 SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
96 return static_cast<jint>(get_canvas(canvasHandle)->saveLayerAlpha(l, t, r, b, alpha, flags));
97}
98
Chris Craik3891f3a2015-04-02 15:28:08 -070099static void restore(JNIEnv* env, jobject, jlong canvasHandle, jboolean throwOnUnderflow) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400100 Canvas* canvas = get_canvas(canvasHandle);
101 if (canvas->getSaveCount() <= 1) { // cannot restore anymore
Chris Craik3891f3a2015-04-02 15:28:08 -0700102 if (throwOnUnderflow) {
103 doThrowISE(env, "Underflow in restore - more restores than saves");
104 }
105 return; // compat behavior - return without throwing
Derek Sollenberger8872b382014-06-23 14:13:53 -0400106 }
107 canvas->restore();
108}
109
Chris Craik3891f3a2015-04-02 15:28:08 -0700110static void restoreToCount(JNIEnv* env, jobject, jlong canvasHandle, jint restoreCount,
111 jboolean throwOnUnderflow) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400112 Canvas* canvas = get_canvas(canvasHandle);
113 if (restoreCount < 1 || restoreCount > canvas->getSaveCount()) {
Chris Craik3891f3a2015-04-02 15:28:08 -0700114 if (throwOnUnderflow) {
115 doThrowIAE(env, "Underflow in restoreToCount - more restores than saves");
116 return;
117 }
118 restoreCount = 1; // compat behavior - restore as far as possible
Derek Sollenberger8872b382014-06-23 14:13:53 -0400119 }
120 canvas->restoreToCount(restoreCount);
121}
122
123static void getCTM(JNIEnv* env, jobject, jlong canvasHandle, jlong matrixHandle) {
124 SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
125 get_canvas(canvasHandle)->getMatrix(matrix);
126}
127
128static void setMatrix(JNIEnv* env, jobject, jlong canvasHandle, jlong matrixHandle) {
129 const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
130 get_canvas(canvasHandle)->setMatrix(matrix ? *matrix : SkMatrix::I());
131}
132
133static void concat(JNIEnv* env, jobject, jlong canvasHandle, jlong matrixHandle) {
134 const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
135 get_canvas(canvasHandle)->concat(*matrix);
136}
137
138static void rotate(JNIEnv*, jobject, jlong canvasHandle, jfloat degrees) {
139 get_canvas(canvasHandle)->rotate(degrees);
140}
141
142static void scale(JNIEnv*, jobject, jlong canvasHandle, jfloat sx, jfloat sy) {
143 get_canvas(canvasHandle)->scale(sx, sy);
144}
145
146static void skew(JNIEnv*, jobject, jlong canvasHandle, jfloat sx, jfloat sy) {
147 get_canvas(canvasHandle)->skew(sx, sy);
148}
149
150static void translate(JNIEnv*, jobject, jlong canvasHandle, jfloat dx, jfloat dy) {
151 get_canvas(canvasHandle)->translate(dx, dy);
152}
153
154static jboolean getClipBounds(JNIEnv* env, jobject, jlong canvasHandle, jobject bounds) {
155 SkRect r;
156 SkIRect ir;
157 bool result = get_canvas(canvasHandle)->getClipBounds(&r);
158
159 if (!result) {
160 r.setEmpty();
161 }
162 r.round(&ir);
163
164 (void)GraphicsJNI::irect_to_jrect(ir, env, bounds);
165 return result ? JNI_TRUE : JNI_FALSE;
166}
167
168static jboolean quickRejectRect(JNIEnv* env, jobject, jlong canvasHandle,
169 jfloat left, jfloat top, jfloat right, jfloat bottom) {
170 bool result = get_canvas(canvasHandle)->quickRejectRect(left, top, right, bottom);
171 return result ? JNI_TRUE : JNI_FALSE;
172}
173
174static jboolean quickRejectPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle) {
175 SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
176 bool result = get_canvas(canvasHandle)->quickRejectPath(*path);
177 return result ? JNI_TRUE : JNI_FALSE;
178}
179
180static jboolean clipRect(JNIEnv*, jobject, jlong canvasHandle, jfloat l, jfloat t,
181 jfloat r, jfloat b, jint opHandle) {
182 SkRegion::Op op = static_cast<SkRegion::Op>(opHandle);
Chris Craik5ec6a282015-06-23 15:42:12 -0700183 bool nonEmptyClip = get_canvas(canvasHandle)->clipRect(l, t, r, b, op);
184 return nonEmptyClip ? JNI_TRUE : JNI_FALSE;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400185}
186
187static jboolean clipPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle,
188 jint opHandle) {
189 SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
190 SkRegion::Op op = static_cast<SkRegion::Op>(opHandle);
Chris Craik5ec6a282015-06-23 15:42:12 -0700191 bool nonEmptyClip = get_canvas(canvasHandle)->clipPath(path, op);
192 return nonEmptyClip ? JNI_TRUE : JNI_FALSE;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400193}
194
195static jboolean clipRegion(JNIEnv* env, jobject, jlong canvasHandle, jlong deviceRgnHandle,
196 jint opHandle) {
197 SkRegion* deviceRgn = reinterpret_cast<SkRegion*>(deviceRgnHandle);
198 SkRegion::Op op = static_cast<SkRegion::Op>(opHandle);
Chris Craik5ec6a282015-06-23 15:42:12 -0700199 bool nonEmptyClip = get_canvas(canvasHandle)->clipRegion(deviceRgn, op);
200 return nonEmptyClip ? JNI_TRUE : JNI_FALSE;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400201}
202
203static void drawColor(JNIEnv* env, jobject, jlong canvasHandle, jint color, jint modeHandle) {
Chris Craik1526a452015-03-06 18:42:15 +0000204 SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(modeHandle);
205 get_canvas(canvasHandle)->drawColor(color, mode);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400206}
207
208static void drawPaint(JNIEnv* env, jobject, jlong canvasHandle, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400209 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400210 get_canvas(canvasHandle)->drawPaint(*paint);
211}
212
213static void drawPoint(JNIEnv*, jobject, jlong canvasHandle, jfloat x, jfloat y,
214 jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400215 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400216 get_canvas(canvasHandle)->drawPoint(x, y, *paint);
217}
218
219static void drawPoints(JNIEnv* env, jobject, jlong canvasHandle, jfloatArray jptsArray,
220 jint offset, jint count, jlong paintHandle) {
221 NPE_CHECK_RETURN_VOID(env, jptsArray);
222 AutoJavaFloatArray autoPts(env, jptsArray);
223 float* floats = autoPts.ptr();
224 const int length = autoPts.length();
225
226 if ((offset | count) < 0 || offset + count > length) {
227 doThrowAIOOBE(env);
228 return;
229 }
230
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400231 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400232 get_canvas(canvasHandle)->drawPoints(floats + offset, count, *paint);
233}
234
235static void drawLine(JNIEnv* env, jobject, jlong canvasHandle, jfloat startX, jfloat startY,
236 jfloat stopX, jfloat stopY, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400237 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400238 get_canvas(canvasHandle)->drawLine(startX, startY, stopX, stopY, *paint);
239}
240
241static void drawLines(JNIEnv* env, jobject, jlong canvasHandle, jfloatArray jptsArray,
242 jint offset, jint count, jlong paintHandle) {
243 NPE_CHECK_RETURN_VOID(env, jptsArray);
244 AutoJavaFloatArray autoPts(env, jptsArray);
245 float* floats = autoPts.ptr();
246 const int length = autoPts.length();
247
248 if ((offset | count) < 0 || offset + count > length) {
249 doThrowAIOOBE(env);
250 return;
251 }
252
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400253 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400254 get_canvas(canvasHandle)->drawLines(floats + offset, count, *paint);
255}
256
257static void drawRect(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
258 jfloat right, jfloat bottom, jlong paintHandle) {
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)->drawRect(left, top, right, bottom, *paint);
261}
262
Derek Sollenberger94394b32015-07-10 09:58:41 -0400263static void drawRegion(JNIEnv* env, jobject, jlong canvasHandle, jlong regionHandle,
264 jlong paintHandle) {
265 const SkRegion* region = reinterpret_cast<SkRegion*>(regionHandle);
266 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
267 get_canvas(canvasHandle)->drawRegion(*region, *paint);
268}
269
Derek Sollenberger8872b382014-06-23 14:13:53 -0400270static void drawRoundRect(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
271 jfloat right, jfloat bottom, jfloat rx, jfloat ry, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400272 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400273 get_canvas(canvasHandle)->drawRoundRect(left, top, right, bottom, rx, ry, *paint);
274}
275
276static void drawCircle(JNIEnv* env, jobject, jlong canvasHandle, jfloat cx, jfloat cy,
277 jfloat radius, 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)->drawCircle(cx, cy, radius, *paint);
280}
281
282static void drawOval(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
283 jfloat right, jfloat bottom, 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)->drawOval(left, top, right, bottom, *paint);
286}
287
288static void drawArc(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
289 jfloat right, jfloat bottom, jfloat startAngle, jfloat sweepAngle,
290 jboolean useCenter, 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)->drawArc(left, top, right, bottom, startAngle, sweepAngle,
293 useCenter, *paint);
294}
295
296static void drawPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle,
297 jlong paintHandle) {
298 const SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400299 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400300 get_canvas(canvasHandle)->drawPath(*path, *paint);
301}
302
303static void drawVertices(JNIEnv* env, jobject, jlong canvasHandle,
304 jint modeHandle, jint vertexCount,
305 jfloatArray jverts, jint vertIndex,
306 jfloatArray jtexs, jint texIndex,
307 jintArray jcolors, jint colorIndex,
308 jshortArray jindices, jint indexIndex,
309 jint indexCount, jlong paintHandle) {
310 AutoJavaFloatArray vertA(env, jverts, vertIndex + vertexCount);
311 AutoJavaFloatArray texA(env, jtexs, texIndex + vertexCount);
312 AutoJavaIntArray colorA(env, jcolors, colorIndex + vertexCount);
313 AutoJavaShortArray indexA(env, jindices, indexIndex + indexCount);
314
315 const float* verts = vertA.ptr() + vertIndex;
316 const float* texs = texA.ptr() + vertIndex;
317 const int* colors = NULL;
318 const uint16_t* indices = NULL;
319
320 if (jcolors != NULL) {
321 colors = colorA.ptr() + colorIndex;
322 }
323 if (jindices != NULL) {
324 indices = (const uint16_t*)(indexA.ptr() + indexIndex);
325 }
326
327 SkCanvas::VertexMode mode = static_cast<SkCanvas::VertexMode>(modeHandle);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400328 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400329 get_canvas(canvasHandle)->drawVertices(mode, vertexCount, verts, texs, colors,
330 indices, indexCount, *paint);
331}
332
John Reck7c103a32015-04-15 15:52:10 -0700333static void drawBitmap(JNIEnv* env, jobject jcanvas, jlong canvasHandle, jobject jbitmap,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400334 jfloat left, jfloat top, jlong paintHandle, jint canvasDensity,
335 jint screenDensity, jint bitmapDensity) {
336 Canvas* canvas = get_canvas(canvasHandle);
John Reck7c103a32015-04-15 15:52:10 -0700337 SkBitmap bitmap;
338 GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400339 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400340
341 if (canvasDensity == bitmapDensity || canvasDensity == 0 || bitmapDensity == 0) {
342 if (screenDensity != 0 && screenDensity != bitmapDensity) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400343 Paint filteredPaint;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400344 if (paint) {
345 filteredPaint = *paint;
346 }
Mike Reed2a1ce8a2015-03-16 11:16:09 -0400347 filteredPaint.setFilterQuality(kLow_SkFilterQuality);
John Reck7c103a32015-04-15 15:52:10 -0700348 canvas->drawBitmap(bitmap, left, top, &filteredPaint);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400349 } else {
John Reck7c103a32015-04-15 15:52:10 -0700350 canvas->drawBitmap(bitmap, left, top, paint);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400351 }
352 } else {
353 canvas->save(SkCanvas::kMatrixClip_SaveFlag);
354 SkScalar scale = canvasDensity / (float)bitmapDensity;
355 canvas->translate(left, top);
356 canvas->scale(scale, scale);
357
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400358 Paint filteredPaint;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400359 if (paint) {
360 filteredPaint = *paint;
361 }
Mike Reed2a1ce8a2015-03-16 11:16:09 -0400362 filteredPaint.setFilterQuality(kLow_SkFilterQuality);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400363
John Reck7c103a32015-04-15 15:52:10 -0700364 canvas->drawBitmap(bitmap, 0, 0, &filteredPaint);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400365 canvas->restore();
366 }
367}
368
John Reck7c103a32015-04-15 15:52:10 -0700369static void drawBitmapMatrix(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400370 jlong matrixHandle, jlong paintHandle) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400371 const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400372 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
John Reck7c103a32015-04-15 15:52:10 -0700373 SkBitmap bitmap;
374 GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
375 get_canvas(canvasHandle)->drawBitmap(bitmap, *matrix, paint);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400376}
377
John Reck7c103a32015-04-15 15:52:10 -0700378static void drawBitmapRect(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400379 float srcLeft, float srcTop, float srcRight, float srcBottom,
380 float dstLeft, float dstTop, float dstRight, float dstBottom,
381 jlong paintHandle, jint screenDensity, jint bitmapDensity) {
382 Canvas* canvas = get_canvas(canvasHandle);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400383 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400384
John Reck7c103a32015-04-15 15:52:10 -0700385 SkBitmap bitmap;
386 GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400387 if (screenDensity != 0 && screenDensity != bitmapDensity) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400388 Paint filteredPaint;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400389 if (paint) {
390 filteredPaint = *paint;
391 }
Mike Reed2a1ce8a2015-03-16 11:16:09 -0400392 filteredPaint.setFilterQuality(kLow_SkFilterQuality);
John Reck7c103a32015-04-15 15:52:10 -0700393 canvas->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400394 dstLeft, dstTop, dstRight, dstBottom, &filteredPaint);
395 } else {
John Reck7c103a32015-04-15 15:52:10 -0700396 canvas->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400397 dstLeft, dstTop, dstRight, dstBottom, paint);
398 }
399}
400
401static void drawBitmapArray(JNIEnv* env, jobject, jlong canvasHandle,
402 jintArray jcolors, jint offset, jint stride,
403 jfloat x, jfloat y, jint width, jint height,
404 jboolean hasAlpha, jlong paintHandle) {
405 // Note: If hasAlpha is false, kRGB_565_SkColorType will be used, which will
406 // correct the alphaType to kOpaque_SkAlphaType.
407 SkImageInfo info = SkImageInfo::Make(width, height,
408 hasAlpha ? kN32_SkColorType : kRGB_565_SkColorType,
409 kPremul_SkAlphaType);
410 SkBitmap bitmap;
Derek Sollenberger3d4eed72014-12-04 15:20:29 -0500411 bitmap.setInfo(info);
412 if (!GraphicsJNI::allocatePixels(env, &bitmap, NULL)) {
Derek Sollenberger8872b382014-06-23 14:13:53 -0400413 return;
414 }
415
416 if (!GraphicsJNI::SetPixels(env, jcolors, offset, stride, 0, 0, width, height, bitmap)) {
417 return;
418 }
419
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400420 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400421 get_canvas(canvasHandle)->drawBitmap(bitmap, x, y, paint);
422}
423
John Reck7c103a32015-04-15 15:52:10 -0700424static void drawBitmapMesh(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400425 jint meshWidth, jint meshHeight, jfloatArray jverts,
426 jint vertIndex, jintArray jcolors, jint colorIndex, jlong paintHandle) {
427 const int ptCount = (meshWidth + 1) * (meshHeight + 1);
428 AutoJavaFloatArray vertA(env, jverts, vertIndex + (ptCount << 1));
429 AutoJavaIntArray colorA(env, jcolors, colorIndex + ptCount);
430
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400431 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
John Reck7c103a32015-04-15 15:52:10 -0700432 SkBitmap bitmap;
433 GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
434 get_canvas(canvasHandle)->drawBitmapMesh(bitmap, meshWidth, meshHeight,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400435 vertA.ptr(), colorA.ptr(), paint);
436}
437
Derek Sollenberger6578a982015-07-13 13:24:29 -0400438static void simplifyPaint(int color, SkPaint* paint) {
439 paint->setColor(color);
440 paint->setShader(nullptr);
441 paint->setColorFilter(nullptr);
442 paint->setLooper(nullptr);
443 paint->setStrokeWidth(4 + 0.04 * paint->getTextSize());
444 paint->setStrokeJoin(SkPaint::kRound_Join);
445 paint->setLooper(nullptr);
446}
447
Derek Sollenbergeracb40992014-07-21 15:22:10 -0400448class DrawTextFunctor {
449public:
450 DrawTextFunctor(const Layout& layout, Canvas* canvas, uint16_t* glyphs, float* pos,
Tom Hudson8dfaa492014-12-09 15:03:44 -0500451 const SkPaint& paint, float x, float y, MinikinRect& bounds,
452 float totalAdvance)
Derek Sollenbergeracb40992014-07-21 15:22:10 -0400453 : layout(layout), canvas(canvas), glyphs(glyphs), pos(pos), paint(paint),
Tom Hudson8dfaa492014-12-09 15:03:44 -0500454 x(x), y(y), bounds(bounds), totalAdvance(totalAdvance) { }
Derek Sollenbergeracb40992014-07-21 15:22:10 -0400455
456 void operator()(size_t start, size_t end) {
457 if (canvas->drawTextAbsolutePos()) {
458 for (size_t i = start; i < end; i++) {
459 glyphs[i] = layout.getGlyphId(i);
460 pos[2 * i] = x + layout.getX(i);
461 pos[2 * i + 1] = y + layout.getY(i);
462 }
463 } else {
464 for (size_t i = start; i < end; i++) {
465 glyphs[i] = layout.getGlyphId(i);
466 pos[2 * i] = layout.getX(i);
467 pos[2 * i + 1] = layout.getY(i);
468 }
469 }
470
471 size_t glyphCount = end - start;
Derek Sollenberger6578a982015-07-13 13:24:29 -0400472
473 if (CC_UNLIKELY(canvas->isHighContrastText())) {
474 // high contrast draw path
475 int color = paint.getColor();
476 int channelSum = SkColorGetR(color) + SkColorGetG(color) + SkColorGetB(color);
477 bool darken = channelSum < (128 * 3);
478
479 // outline
480 SkPaint outlinePaint(paint);
481 simplifyPaint(darken ? SK_ColorWHITE : SK_ColorBLACK, &outlinePaint);
482 outlinePaint.setStyle(SkPaint::kStrokeAndFill_Style);
483 canvas->drawText(glyphs + start, pos + (2 * start), glyphCount, outlinePaint, x, y,
484 bounds.mLeft, bounds.mTop, bounds.mRight, bounds.mBottom, totalAdvance);
485
486 // inner
487 SkPaint innerPaint(paint);
488 simplifyPaint(darken ? SK_ColorBLACK : SK_ColorWHITE, &innerPaint);
489 innerPaint.setStyle(SkPaint::kFill_Style);
490 canvas->drawText(glyphs + start, pos + (2 * start), glyphCount, innerPaint, x, y,
491 bounds.mLeft, bounds.mTop, bounds.mRight, bounds.mBottom, totalAdvance);
492 } else {
493 // standard draw path
494 canvas->drawText(glyphs + start, pos + (2 * start), glyphCount, paint, x, y,
495 bounds.mLeft, bounds.mTop, bounds.mRight, bounds.mBottom,
496 totalAdvance);
497 }
Derek Sollenbergeracb40992014-07-21 15:22:10 -0400498 }
499private:
500 const Layout& layout;
501 Canvas* canvas;
502 uint16_t* glyphs;
503 float* pos;
504 const SkPaint& paint;
505 float x;
506 float y;
507 MinikinRect& bounds;
Tom Hudson8dfaa492014-12-09 15:03:44 -0500508 float totalAdvance;
Derek Sollenbergeracb40992014-07-21 15:22:10 -0400509};
510
511// Same values used by Skia
512#define kStdStrikeThru_Offset (-6.0f / 21.0f)
513#define kStdUnderline_Offset (1.0f / 9.0f)
514#define kStdUnderline_Thickness (1.0f / 18.0f)
515
516void drawTextDecorations(Canvas* canvas, float x, float y, float length, const SkPaint& paint) {
517 uint32_t flags;
518 SkDrawFilter* drawFilter = canvas->getDrawFilter();
519 if (drawFilter) {
520 SkPaint paintCopy(paint);
521 drawFilter->filter(&paintCopy, SkDrawFilter::kText_Type);
522 flags = paintCopy.getFlags();
523 } else {
524 flags = paint.getFlags();
525 }
526 if (flags & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag)) {
527 SkScalar left = x;
528 SkScalar right = x + length;
529 float textSize = paint.getTextSize();
530 float strokeWidth = fmax(textSize * kStdUnderline_Thickness, 1.0f);
531 if (flags & SkPaint::kUnderlineText_Flag) {
532 SkScalar top = y + textSize * kStdUnderline_Offset - 0.5f * strokeWidth;
533 SkScalar bottom = y + textSize * kStdUnderline_Offset + 0.5f * strokeWidth;
534 canvas->drawRect(left, top, right, bottom, paint);
535 }
536 if (flags & SkPaint::kStrikeThruText_Flag) {
537 SkScalar top = y + textSize * kStdStrikeThru_Offset - 0.5f * strokeWidth;
538 SkScalar bottom = y + textSize * kStdStrikeThru_Offset + 0.5f * strokeWidth;
539 canvas->drawRect(left, top, right, bottom, paint);
540 }
541 }
542}
543
544void drawText(Canvas* canvas, const uint16_t* text, int start, int count, int contextCount,
545 float x, float y, int bidiFlags, const Paint& origPaint, TypefaceImpl* typeface) {
546 // minikin may modify the original paint
547 Paint paint(origPaint);
548
549 Layout layout;
Behdad Esfahbod63c5c782014-07-25 14:54:46 -0400550 MinikinUtils::doLayout(&layout, &paint, bidiFlags, typeface, text, start, count, contextCount);
Derek Sollenbergeracb40992014-07-21 15:22:10 -0400551
552 size_t nGlyphs = layout.nGlyphs();
553 uint16_t* glyphs = new uint16_t[nGlyphs];
554 float* pos = new float[nGlyphs * 2];
555
556 x += MinikinUtils::xOffsetForTextAlign(&paint, layout);
557
558 MinikinRect bounds;
559 layout.getBounds(&bounds);
Tom Hudson8dfaa492014-12-09 15:03:44 -0500560 if (!canvas->drawTextAbsolutePos()) {
561 bounds.offset(x, y);
562 }
Derek Sollenbergeracb40992014-07-21 15:22:10 -0400563
Tom Hudson8dfaa492014-12-09 15:03:44 -0500564 DrawTextFunctor f(layout, canvas, glyphs, pos, paint, x, y, bounds, layout.getAdvance());
Derek Sollenbergeracb40992014-07-21 15:22:10 -0400565 MinikinUtils::forFontRun(layout, &paint, f);
566
567 drawTextDecorations(canvas, x, y, layout.getAdvance(), paint);
568
569 delete[] glyphs;
570 delete[] pos;
571}
572
Derek Sollenberger8872b382014-06-23 14:13:53 -0400573static void drawTextChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text,
574 jint index, jint count, jfloat x, jfloat y, jint bidiFlags,
575 jlong paintHandle, jlong typefaceHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400576 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400577 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
578 jchar* jchars = env->GetCharArrayElements(text, NULL);
Derek Sollenbergeracb40992014-07-21 15:22:10 -0400579 drawText(get_canvas(canvasHandle), jchars + index, 0, count, count, x, y,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400580 bidiFlags, *paint, typeface);
581 env->ReleaseCharArrayElements(text, jchars, JNI_ABORT);
582}
583
584static void drawTextString(JNIEnv* env, jobject, jlong canvasHandle, jstring text,
585 jint start, jint end, jfloat x, jfloat y, jint bidiFlags,
586 jlong paintHandle, jlong typefaceHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400587 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400588 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
589 const int count = end - start;
590 const jchar* jchars = env->GetStringChars(text, NULL);
Derek Sollenbergeracb40992014-07-21 15:22:10 -0400591 drawText(get_canvas(canvasHandle), jchars + start, 0, count, count, x, y,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400592 bidiFlags, *paint, typeface);
593 env->ReleaseStringChars(text, jchars);
594}
595
596static void drawTextRunChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text, jint index,
597 jint count, jint contextIndex, jint contextCount, jfloat x, jfloat y,
598 jboolean isRtl, jlong paintHandle, jlong typefaceHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400599 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400600 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
601
602 const int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
603 jchar* jchars = env->GetCharArrayElements(text, NULL);
Derek Sollenbergeracb40992014-07-21 15:22:10 -0400604 drawText(get_canvas(canvasHandle), jchars + contextIndex, index - contextIndex, count,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400605 contextCount, x, y, bidiFlags, *paint, typeface);
606 env->ReleaseCharArrayElements(text, jchars, JNI_ABORT);
607}
608
609static void drawTextRunString(JNIEnv* env, jobject obj, jlong canvasHandle, jstring text,
610 jint start, jint end, jint contextStart, jint contextEnd,
611 jfloat x, jfloat y, jboolean isRtl, jlong paintHandle,
612 jlong typefaceHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400613 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400614 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
615
616 int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
617 jint count = end - start;
618 jint contextCount = contextEnd - contextStart;
619 const jchar* jchars = env->GetStringChars(text, NULL);
Derek Sollenbergeracb40992014-07-21 15:22:10 -0400620 drawText(get_canvas(canvasHandle), jchars + contextStart, start - contextStart, count,
Derek Sollenberger8872b382014-06-23 14:13:53 -0400621 contextCount, x, y, bidiFlags, *paint, typeface);
622 env->ReleaseStringChars(text, jchars);
623}
624
Derek Sollenberger8872b382014-06-23 14:13:53 -0400625class DrawTextOnPathFunctor {
626public:
627 DrawTextOnPathFunctor(const Layout& layout, Canvas* canvas, float hOffset,
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400628 float vOffset, const Paint& paint, const SkPath& path)
Derek Sollenberger8872b382014-06-23 14:13:53 -0400629 : layout(layout), canvas(canvas), hOffset(hOffset), vOffset(vOffset),
630 paint(paint), path(path) {
631 }
632 void operator()(size_t start, size_t end) {
633 uint16_t glyphs[1];
634 for (size_t i = start; i < end; i++) {
635 glyphs[0] = layout.getGlyphId(i);
636 float x = hOffset + layout.getX(i);
637 float y = vOffset + layout.getY(i);
638 canvas->drawTextOnPath(glyphs, 1, path, x, y, paint);
639 }
640 }
641private:
642 const Layout& layout;
643 Canvas* canvas;
644 float hOffset;
645 float vOffset;
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400646 const Paint& paint;
Derek Sollenberger8872b382014-06-23 14:13:53 -0400647 const SkPath& path;
648};
649
650static void drawTextOnPath(Canvas* canvas, const uint16_t* text, int count, int bidiFlags,
651 const SkPath& path, float hOffset, float vOffset,
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400652 const Paint& paint, TypefaceImpl* typeface) {
653 Paint paintCopy(paint);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400654 Layout layout;
Behdad Esfahbod63c5c782014-07-25 14:54:46 -0400655 MinikinUtils::doLayout(&layout, &paintCopy, bidiFlags, typeface, text, 0, count, count);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400656 hOffset += MinikinUtils::hOffsetForTextAlign(&paintCopy, layout, path);
657
658 // Set align to left for drawing, as we don't want individual
659 // glyphs centered or right-aligned; the offset above takes
660 // care of all alignment.
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400661 paintCopy.setTextAlign(Paint::kLeft_Align);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400662
663 DrawTextOnPathFunctor f(layout, canvas, hOffset, vOffset, paintCopy, path);
664 MinikinUtils::forFontRun(layout, &paintCopy, f);
665}
666
667static void drawTextOnPathChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text,
668 jint index, jint count, jlong pathHandle, jfloat hOffset,
669 jfloat vOffset, jint bidiFlags, jlong paintHandle,
670 jlong typefaceHandle) {
671 SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400672 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400673 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
674
675 jchar* jchars = env->GetCharArrayElements(text, NULL);
676
677 drawTextOnPath(get_canvas(canvasHandle), jchars + index, count, bidiFlags, *path,
678 hOffset, vOffset, *paint, typeface);
679
680 env->ReleaseCharArrayElements(text, jchars, 0);
681}
682
683static void drawTextOnPathString(JNIEnv* env, jobject, jlong canvasHandle, jstring text,
684 jlong pathHandle, jfloat hOffset, jfloat vOffset,
685 jint bidiFlags, jlong paintHandle, jlong typefaceHandle) {
686 SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400687 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400688 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
689
690 const jchar* jchars = env->GetStringChars(text, NULL);
691 int count = env->GetStringLength(text);
692
693 drawTextOnPath(get_canvas(canvasHandle), jchars, count, bidiFlags, *path,
694 hOffset, vOffset, *paint, typeface);
695
696 env->ReleaseStringChars(text, jchars);
697}
698
699static void setDrawFilter(JNIEnv* env, jobject, jlong canvasHandle, jlong filterHandle) {
700 get_canvas(canvasHandle)->setDrawFilter(reinterpret_cast<SkDrawFilter*>(filterHandle));
701}
702
703static void freeCaches(JNIEnv* env, jobject) {
704 SkGraphics::PurgeFontCache();
705}
706
707static void freeTextLayoutCaches(JNIEnv* env, jobject) {
708 Layout::purgeCaches();
709}
710
711}; // namespace CanvasJNI
712
713static JNINativeMethod gMethods[] = {
714 {"finalizer", "(J)V", (void*) CanvasJNI::finalizer},
John Reckc1b33d62015-04-22 09:04:45 -0700715 {"initRaster", "(Landroid/graphics/Bitmap;)J", (void*) CanvasJNI::initRaster},
716 {"native_setBitmap", "(JLandroid/graphics/Bitmap;)V", (void*) CanvasJNI::setBitmap},
Derek Sollenberger8872b382014-06-23 14:13:53 -0400717 {"native_isOpaque","(J)Z", (void*) CanvasJNI::isOpaque},
718 {"native_getWidth","(J)I", (void*) CanvasJNI::getWidth},
719 {"native_getHeight","(J)I", (void*) CanvasJNI::getHeight},
Derek Sollenberger6578a982015-07-13 13:24:29 -0400720 {"native_setHighContrastText","(JZ)V", (void*) CanvasJNI::setHighContrastText},
Derek Sollenberger8872b382014-06-23 14:13:53 -0400721 {"native_save","(JI)I", (void*) CanvasJNI::save},
722 {"native_saveLayer","(JFFFFJI)I", (void*) CanvasJNI::saveLayer},
723 {"native_saveLayerAlpha","(JFFFFII)I", (void*) CanvasJNI::saveLayerAlpha},
724 {"native_getSaveCount","(J)I", (void*) CanvasJNI::getSaveCount},
Chris Craik3891f3a2015-04-02 15:28:08 -0700725 {"native_restore","(JZ)V", (void*) CanvasJNI::restore},
726 {"native_restoreToCount","(JIZ)V", (void*) CanvasJNI::restoreToCount},
Derek Sollenberger8872b382014-06-23 14:13:53 -0400727 {"native_getCTM", "(JJ)V", (void*)CanvasJNI::getCTM},
728 {"native_setMatrix","(JJ)V", (void*) CanvasJNI::setMatrix},
729 {"native_concat","(JJ)V", (void*) CanvasJNI::concat},
730 {"native_rotate","(JF)V", (void*) CanvasJNI::rotate},
731 {"native_scale","(JFF)V", (void*) CanvasJNI::scale},
732 {"native_skew","(JFF)V", (void*) CanvasJNI::skew},
733 {"native_translate","(JFF)V", (void*) CanvasJNI::translate},
734 {"native_getClipBounds","(JLandroid/graphics/Rect;)Z", (void*) CanvasJNI::getClipBounds},
735 {"native_quickReject","(JJ)Z", (void*) CanvasJNI::quickRejectPath},
736 {"native_quickReject","(JFFFF)Z", (void*)CanvasJNI::quickRejectRect},
737 {"native_clipRect","(JFFFFI)Z", (void*) CanvasJNI::clipRect},
738 {"native_clipPath","(JJI)Z", (void*) CanvasJNI::clipPath},
739 {"native_clipRegion","(JJI)Z", (void*) CanvasJNI::clipRegion},
740 {"native_drawColor","(JII)V", (void*) CanvasJNI::drawColor},
741 {"native_drawPaint","(JJ)V", (void*) CanvasJNI::drawPaint},
742 {"native_drawPoint", "(JFFJ)V", (void*) CanvasJNI::drawPoint},
743 {"native_drawPoints", "(J[FIIJ)V", (void*) CanvasJNI::drawPoints},
744 {"native_drawLine", "(JFFFFJ)V", (void*) CanvasJNI::drawLine},
745 {"native_drawLines", "(J[FIIJ)V", (void*) CanvasJNI::drawLines},
746 {"native_drawRect","(JFFFFJ)V", (void*) CanvasJNI::drawRect},
Derek Sollenberger94394b32015-07-10 09:58:41 -0400747 {"native_drawRegion", "(JJJ)V", (void*) CanvasJNI::drawRegion },
Derek Sollenberger8872b382014-06-23 14:13:53 -0400748 {"native_drawRoundRect","(JFFFFFFJ)V", (void*) CanvasJNI::drawRoundRect},
749 {"native_drawCircle","(JFFFJ)V", (void*) CanvasJNI::drawCircle},
750 {"native_drawOval","(JFFFFJ)V", (void*) CanvasJNI::drawOval},
751 {"native_drawArc","(JFFFFFFZJ)V", (void*) CanvasJNI::drawArc},
752 {"native_drawPath","(JJJ)V", (void*) CanvasJNI::drawPath},
753 {"nativeDrawVertices", "(JII[FI[FI[II[SIIJ)V", (void*)CanvasJNI::drawVertices},
John Reck7c103a32015-04-15 15:52:10 -0700754 {"native_drawBitmap","(JLandroid/graphics/Bitmap;FFJIII)V", (void*) CanvasJNI::drawBitmap},
755 {"nativeDrawBitmapMatrix", "(JLandroid/graphics/Bitmap;JJ)V", (void*)CanvasJNI::drawBitmapMatrix},
756 {"native_drawBitmap","(JLandroid/graphics/Bitmap;FFFFFFFFJII)V", (void*) CanvasJNI::drawBitmapRect},
Derek Sollenberger8872b382014-06-23 14:13:53 -0400757 {"native_drawBitmap", "(J[IIIFFIIZJ)V", (void*)CanvasJNI::drawBitmapArray},
John Reck7c103a32015-04-15 15:52:10 -0700758 {"nativeDrawBitmapMesh", "(JLandroid/graphics/Bitmap;II[FI[IIJ)V", (void*)CanvasJNI::drawBitmapMesh},
Derek Sollenberger8872b382014-06-23 14:13:53 -0400759 {"native_drawText","(J[CIIFFIJJ)V", (void*) CanvasJNI::drawTextChars},
760 {"native_drawText","(JLjava/lang/String;IIFFIJJ)V", (void*) CanvasJNI::drawTextString},
761 {"native_drawTextRun","(J[CIIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunChars},
762 {"native_drawTextRun","(JLjava/lang/String;IIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunString},
763 {"native_drawTextOnPath","(J[CIIJFFIJJ)V", (void*) CanvasJNI::drawTextOnPathChars},
764 {"native_drawTextOnPath","(JLjava/lang/String;JFFIJJ)V", (void*) CanvasJNI::drawTextOnPathString},
765 {"nativeSetDrawFilter", "(JJ)V", (void*) CanvasJNI::setDrawFilter},
766 {"freeCaches", "()V", (void*) CanvasJNI::freeCaches},
767 {"freeTextLayoutCaches", "()V", (void*) CanvasJNI::freeTextLayoutCaches}
768};
769
770int register_android_graphics_Canvas(JNIEnv* env) {
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800771 return RegisterMethodsOrDie(env, "android/graphics/Canvas", gMethods, NELEM(gMethods));
Derek Sollenberger8872b382014-06-23 14:13:53 -0400772}
773
774}; // namespace android