android_graphics_Canvas.cpp revision 775873a66a946fae2b0535abb51df9817bd1b20c
18872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger/*
28872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger * Copyright (C) 2014 The Android Open Source Project
38872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger *
48872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger * Licensed under the Apache License, Version 2.0 (the "License");
58872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger * you may not use this file except in compliance with the License.
68872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger * You may obtain a copy of the License at
78872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger *
88872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger *      http://www.apache.org/licenses/LICENSE-2.0
98872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger *
108872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger * Unless required by applicable law or agreed to in writing, software
118872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger * distributed under the License is distributed on an "AS IS" BASIS,
128872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger * See the License for the specific language governing permissions and
148872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger * limitations under the License.
158872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger */
168872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
178872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger#include "jni.h"
188872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger#include "GraphicsJNI.h"
19ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe#include "core_jni_helpers.h"
208872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
214c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger#include <androidfw/ResourceTypes.h>
22849911a9c4315fc552faa38516c842b2541b1909John Reck#include <Canvas.h>
234c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger
244c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger#include "Bitmap.h"
25acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger#include "SkDrawFilter.h"
268872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger#include "SkGraphics.h"
276ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod#include "Paint.h"
288872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger#include "TypefaceImpl.h"
298872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
308872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger#include "MinikinUtils.h"
318872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
328872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergernamespace android {
338872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
348872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergernamespace CanvasJNI {
358872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
368872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic Canvas* get_canvas(jlong canvasHandle) {
378872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return reinterpret_cast<Canvas*>(canvasHandle);
388872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
398872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
40775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhlerstatic void delete_canvas(Canvas* canvas) {
41775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhler    delete canvas;
42775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhler}
43775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhler
44775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhlerstatic jlong getNativeFinalizer(JNIEnv* env, jobject clazz) {
45775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhler    return static_cast<jlong>(reinterpret_cast<uintptr_t>(&delete_canvas));
468872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
478872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
488872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger// Native wrapper constructor used by Canvas(Bitmap)
49c1b33d665c8caf5760f68c45c6ca0baa649b832aJohn Reckstatic jlong initRaster(JNIEnv* env, jobject, jobject jbitmap) {
503731dc220ed457e0f1e99d7ec2589e0a43872b59John Reck    SkBitmap bitmap;
51c1b33d665c8caf5760f68c45c6ca0baa649b832aJohn Reck    if (jbitmap != NULL) {
523731dc220ed457e0f1e99d7ec2589e0a43872b59John Reck        GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
53c1b33d665c8caf5760f68c45c6ca0baa649b832aJohn Reck    }
543731dc220ed457e0f1e99d7ec2589e0a43872b59John Reck    return reinterpret_cast<jlong>(Canvas::create_canvas(bitmap));
558872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
568872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
578872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger// Set the given bitmap as the new draw target (wrapped in a new SkCanvas),
588872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger// optionally copying canvas matrix & clip state.
59c1b33d665c8caf5760f68c45c6ca0baa649b832aJohn Reckstatic void setBitmap(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap) {
603731dc220ed457e0f1e99d7ec2589e0a43872b59John Reck    SkBitmap bitmap;
61c1b33d665c8caf5760f68c45c6ca0baa649b832aJohn Reck    if (jbitmap != NULL) {
623731dc220ed457e0f1e99d7ec2589e0a43872b59John Reck        GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
63c1b33d665c8caf5760f68c45c6ca0baa649b832aJohn Reck    }
643731dc220ed457e0f1e99d7ec2589e0a43872b59John Reck    get_canvas(canvasHandle)->setBitmap(bitmap);
658872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
668872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
678872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jboolean isOpaque(JNIEnv*, jobject, jlong canvasHandle) {
688872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return get_canvas(canvasHandle)->isOpaque() ? JNI_TRUE : JNI_FALSE;
698872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
708872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
718872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jint getWidth(JNIEnv*, jobject, jlong canvasHandle) {
728872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return static_cast<jint>(get_canvas(canvasHandle)->width());
738872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
748872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
758872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jint getHeight(JNIEnv*, jobject, jlong canvasHandle) {
768872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return static_cast<jint>(get_canvas(canvasHandle)->height());
778872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
788872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
796578a989566e585eee053095dc80e2552e125db2Derek Sollenbergerstatic void setHighContrastText(JNIEnv*, jobject, jlong canvasHandle, jboolean highContrastText) {
806578a989566e585eee053095dc80e2552e125db2Derek Sollenberger    Canvas* canvas = get_canvas(canvasHandle);
816578a989566e585eee053095dc80e2552e125db2Derek Sollenberger    canvas->setHighContrastText(highContrastText);
826578a989566e585eee053095dc80e2552e125db2Derek Sollenberger}
836578a989566e585eee053095dc80e2552e125db2Derek Sollenberger
848872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jint getSaveCount(JNIEnv*, jobject, jlong canvasHandle) {
858872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return static_cast<jint>(get_canvas(canvasHandle)->getSaveCount());
868872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
878872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
888872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jint save(JNIEnv*, jobject, jlong canvasHandle, jint flagsHandle) {
898872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
908872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return static_cast<jint>(get_canvas(canvasHandle)->save(flags));
918872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
928872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
938872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jint saveLayer(JNIEnv* env, jobject, jlong canvasHandle, jfloat l, jfloat t,
948872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                      jfloat r, jfloat b, jlong paintHandle, jint flagsHandle) {
956ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint  = reinterpret_cast<Paint*>(paintHandle);
968872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
978872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return static_cast<jint>(get_canvas(canvasHandle)->saveLayer(l, t, r, b, paint, flags));
988872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
998872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1008872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jint saveLayerAlpha(JNIEnv* env, jobject, jlong canvasHandle, jfloat l, jfloat t,
1018872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           jfloat r, jfloat b, jint alpha, jint flagsHandle) {
1028872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
1038872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return static_cast<jint>(get_canvas(canvasHandle)->saveLayerAlpha(l, t, r, b, alpha, flags));
1048872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1058872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1063891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craikstatic void restore(JNIEnv* env, jobject, jlong canvasHandle, jboolean throwOnUnderflow) {
1078872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    Canvas* canvas = get_canvas(canvasHandle);
1088872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if (canvas->getSaveCount() <= 1) {  // cannot restore anymore
1093891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik        if (throwOnUnderflow) {
1103891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik            doThrowISE(env, "Underflow in restore - more restores than saves");
1113891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik        }
1123891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik        return; // compat behavior - return without throwing
1138872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
1148872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    canvas->restore();
1158872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1168872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1173891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craikstatic void restoreToCount(JNIEnv* env, jobject, jlong canvasHandle, jint restoreCount,
1183891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik        jboolean throwOnUnderflow) {
1198872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    Canvas* canvas = get_canvas(canvasHandle);
1208872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if (restoreCount < 1 || restoreCount > canvas->getSaveCount()) {
1213891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik        if (throwOnUnderflow) {
1223891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik            doThrowIAE(env, "Underflow in restoreToCount - more restores than saves");
1233891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik            return;
1243891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik        }
1253891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik        restoreCount = 1; // compat behavior - restore as far as possible
1268872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
1278872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    canvas->restoreToCount(restoreCount);
1288872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1298872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1308872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void getCTM(JNIEnv* env, jobject, jlong canvasHandle, jlong matrixHandle) {
1318872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
1328872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->getMatrix(matrix);
1338872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1348872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1358872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void setMatrix(JNIEnv* env, jobject, jlong canvasHandle, jlong matrixHandle) {
1368872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
1378872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->setMatrix(matrix ? *matrix : SkMatrix::I());
1388872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1398872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1408872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void concat(JNIEnv* env, jobject, jlong canvasHandle, jlong matrixHandle) {
1418872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
1428872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->concat(*matrix);
1438872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1448872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1458872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void rotate(JNIEnv*, jobject, jlong canvasHandle, jfloat degrees) {
1468872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->rotate(degrees);
1478872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1488872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1498872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void scale(JNIEnv*, jobject, jlong canvasHandle, jfloat sx, jfloat sy) {
1508872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->scale(sx, sy);
1518872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1528872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1538872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void skew(JNIEnv*, jobject, jlong canvasHandle, jfloat sx, jfloat sy) {
1548872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->skew(sx, sy);
1558872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1568872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1578872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void translate(JNIEnv*, jobject, jlong canvasHandle, jfloat dx, jfloat dy) {
1588872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->translate(dx, dy);
1598872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1608872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1618872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jboolean getClipBounds(JNIEnv* env, jobject, jlong canvasHandle, jobject bounds) {
1628872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkRect   r;
1638872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkIRect ir;
1648872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    bool result = get_canvas(canvasHandle)->getClipBounds(&r);
1658872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1668872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if (!result) {
1678872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        r.setEmpty();
1688872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
1698872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    r.round(&ir);
1708872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1718872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    (void)GraphicsJNI::irect_to_jrect(ir, env, bounds);
1728872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return result ? JNI_TRUE : JNI_FALSE;
1738872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1748872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1758872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jboolean quickRejectRect(JNIEnv* env, jobject, jlong canvasHandle,
1768872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                jfloat left, jfloat top, jfloat right, jfloat bottom) {
1778872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    bool result = get_canvas(canvasHandle)->quickRejectRect(left, top, right, bottom);
1788872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return result ? JNI_TRUE : JNI_FALSE;
1798872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1808872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1818872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jboolean quickRejectPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle) {
1828872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
1838872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    bool result = get_canvas(canvasHandle)->quickRejectPath(*path);
1848872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return result ? JNI_TRUE : JNI_FALSE;
1858872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1868872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1878872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jboolean clipRect(JNIEnv*, jobject, jlong canvasHandle, jfloat l, jfloat t,
1888872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                         jfloat r, jfloat b, jint opHandle) {
1898872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkRegion::Op op = static_cast<SkRegion::Op>(opHandle);
1905ec6a2878b2ad933c5da6fe2341c854155acc24cChris Craik    bool nonEmptyClip = get_canvas(canvasHandle)->clipRect(l, t, r, b, op);
1915ec6a2878b2ad933c5da6fe2341c854155acc24cChris Craik    return nonEmptyClip ? JNI_TRUE : JNI_FALSE;
1928872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1938872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1948872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jboolean clipPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle,
1958872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                         jint opHandle) {
1968872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
1978872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkRegion::Op op = static_cast<SkRegion::Op>(opHandle);
1985ec6a2878b2ad933c5da6fe2341c854155acc24cChris Craik    bool nonEmptyClip = get_canvas(canvasHandle)->clipPath(path, op);
1995ec6a2878b2ad933c5da6fe2341c854155acc24cChris Craik    return nonEmptyClip ? JNI_TRUE : JNI_FALSE;
2008872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2018872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2028872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jboolean clipRegion(JNIEnv* env, jobject, jlong canvasHandle, jlong deviceRgnHandle,
2038872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           jint opHandle) {
2048872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkRegion* deviceRgn = reinterpret_cast<SkRegion*>(deviceRgnHandle);
2058872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkRegion::Op op = static_cast<SkRegion::Op>(opHandle);
2065ec6a2878b2ad933c5da6fe2341c854155acc24cChris Craik    bool nonEmptyClip = get_canvas(canvasHandle)->clipRegion(deviceRgn, op);
2075ec6a2878b2ad933c5da6fe2341c854155acc24cChris Craik    return nonEmptyClip ? JNI_TRUE : JNI_FALSE;
2088872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2098872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2108872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawColor(JNIEnv* env, jobject, jlong canvasHandle, jint color, jint modeHandle) {
2111526a458a30184609f19b05e7334da3cbde81dd1Chris Craik    SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(modeHandle);
2121526a458a30184609f19b05e7334da3cbde81dd1Chris Craik    get_canvas(canvasHandle)->drawColor(color, mode);
2138872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2148872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2158872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawPaint(JNIEnv* env, jobject, jlong canvasHandle, jlong paintHandle) {
2166ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2178872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawPaint(*paint);
2188872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2198872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2208872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawPoint(JNIEnv*, jobject, jlong canvasHandle, jfloat x, jfloat y,
2218872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                      jlong paintHandle) {
2226ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2238872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawPoint(x, y, *paint);
2248872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2258872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2268872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawPoints(JNIEnv* env, jobject, jlong canvasHandle, jfloatArray jptsArray,
2278872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                       jint offset, jint count, jlong paintHandle) {
2288872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    NPE_CHECK_RETURN_VOID(env, jptsArray);
2298872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    AutoJavaFloatArray autoPts(env, jptsArray);
2308872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    float* floats = autoPts.ptr();
2318872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const int length = autoPts.length();
2328872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2338872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if ((offset | count) < 0 || offset + count > length) {
2348872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        doThrowAIOOBE(env);
2358872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        return;
2368872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
2378872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2386ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2398872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawPoints(floats + offset, count, *paint);
2408872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2418872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2428872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawLine(JNIEnv* env, jobject, jlong canvasHandle, jfloat startX, jfloat startY,
2438872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                     jfloat stopX, jfloat stopY, jlong paintHandle) {
2446ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2458872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawLine(startX, startY, stopX, stopY, *paint);
2468872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2478872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2488872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawLines(JNIEnv* env, jobject, jlong canvasHandle, jfloatArray jptsArray,
2498872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                      jint offset, jint count, jlong paintHandle) {
2508872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    NPE_CHECK_RETURN_VOID(env, jptsArray);
2518872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    AutoJavaFloatArray autoPts(env, jptsArray);
2528872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    float* floats = autoPts.ptr();
2538872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const int length = autoPts.length();
2548872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2558872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if ((offset | count) < 0 || offset + count > length) {
2568872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        doThrowAIOOBE(env);
2578872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        return;
2588872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
2598872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2606ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2618872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawLines(floats + offset, count, *paint);
2628872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2638872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2648872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawRect(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
2658872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                     jfloat right, jfloat bottom, jlong paintHandle) {
2666ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2678872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawRect(left, top, right, bottom, *paint);
2688872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2698872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
27094394b3fb048d5349a77b57950ab7f6b6e92ce34Derek Sollenbergerstatic void drawRegion(JNIEnv* env, jobject, jlong canvasHandle, jlong regionHandle,
27194394b3fb048d5349a77b57950ab7f6b6e92ce34Derek Sollenberger                       jlong paintHandle) {
27294394b3fb048d5349a77b57950ab7f6b6e92ce34Derek Sollenberger    const SkRegion* region = reinterpret_cast<SkRegion*>(regionHandle);
27394394b3fb048d5349a77b57950ab7f6b6e92ce34Derek Sollenberger    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
27494394b3fb048d5349a77b57950ab7f6b6e92ce34Derek Sollenberger    get_canvas(canvasHandle)->drawRegion(*region, *paint);
27594394b3fb048d5349a77b57950ab7f6b6e92ce34Derek Sollenberger}
27694394b3fb048d5349a77b57950ab7f6b6e92ce34Derek Sollenberger
2778872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawRoundRect(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
2788872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                          jfloat right, jfloat bottom, jfloat rx, jfloat ry, jlong paintHandle) {
2796ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2808872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawRoundRect(left, top, right, bottom, rx, ry, *paint);
2818872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2828872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2838872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawCircle(JNIEnv* env, jobject, jlong canvasHandle, jfloat cx, jfloat cy,
2848872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                       jfloat radius, jlong paintHandle) {
2856ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2868872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawCircle(cx, cy, radius, *paint);
2878872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2888872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2898872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawOval(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
2908872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                     jfloat right, jfloat bottom, jlong paintHandle) {
2916ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2928872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawOval(left, top, right, bottom, *paint);
2938872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2948872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2958872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawArc(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
2968872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                    jfloat right, jfloat bottom, jfloat startAngle, jfloat sweepAngle,
2978872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                    jboolean useCenter, jlong paintHandle) {
2986ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2998872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawArc(left, top, right, bottom, startAngle, sweepAngle,
3008872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                       useCenter, *paint);
3018872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
3028872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3038872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle,
3048872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                     jlong paintHandle) {
3058872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
3066ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
3078872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawPath(*path, *paint);
3088872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
3098872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3108872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawVertices(JNIEnv* env, jobject, jlong canvasHandle,
3118872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                         jint modeHandle, jint vertexCount,
3128872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                         jfloatArray jverts, jint vertIndex,
3138872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                         jfloatArray jtexs, jint texIndex,
3148872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                         jintArray jcolors, jint colorIndex,
3158872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                         jshortArray jindices, jint indexIndex,
3168872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                         jint indexCount, jlong paintHandle) {
3178872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    AutoJavaFloatArray  vertA(env, jverts, vertIndex + vertexCount);
3188872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    AutoJavaFloatArray  texA(env, jtexs, texIndex + vertexCount);
3198872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    AutoJavaIntArray    colorA(env, jcolors, colorIndex + vertexCount);
3208872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    AutoJavaShortArray  indexA(env, jindices, indexIndex + indexCount);
3218872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3228872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const float* verts = vertA.ptr() + vertIndex;
3238872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const float* texs = texA.ptr() + vertIndex;
3248872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const int* colors = NULL;
3258872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const uint16_t* indices = NULL;
3268872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3278872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if (jcolors != NULL) {
3288872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        colors = colorA.ptr() + colorIndex;
3298872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
3308872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if (jindices != NULL) {
3318872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        indices = (const uint16_t*)(indexA.ptr() + indexIndex);
3328872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
3338872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3348872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkCanvas::VertexMode mode = static_cast<SkCanvas::VertexMode>(modeHandle);
3356ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
3368872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawVertices(mode, vertexCount, verts, texs, colors,
3378872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                           indices, indexCount, *paint);
3388872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
3398872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3404c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenbergerstatic void drawNinePatch(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle,
3414c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger        jlong chunkHandle, jfloat left, jfloat top, jfloat right, jfloat bottom,
3424c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger        jlong paintHandle, jint dstDensity, jint srcDensity) {
3434c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger
3444c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger    Canvas* canvas = get_canvas(canvasHandle);
3454c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger    Bitmap* bitmap = reinterpret_cast<Bitmap*>(bitmapHandle);
3464c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger    SkBitmap skiaBitmap;
3474c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger    bitmap->getSkBitmap(&skiaBitmap);
3484c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger    const android::Res_png_9patch* chunk = reinterpret_cast<android::Res_png_9patch*>(chunkHandle);
3494c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
3504c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger
3514c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger    if (CC_LIKELY(dstDensity == srcDensity || dstDensity == 0 || srcDensity == 0)) {
3524c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger        canvas->drawNinePatch(skiaBitmap, *chunk, left, top, right, bottom, paint);
3534c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger    } else {
3544c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger        canvas->save(SkCanvas::kMatrixClip_SaveFlag);
3554c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger
3564c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger        SkScalar scale = dstDensity / (float)srcDensity;
3574c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger        canvas->translate(left, top);
3584c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger        canvas->scale(scale, scale);
3594c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger
3604c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger        Paint filteredPaint;
3614c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger        if (paint) {
3624c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger            filteredPaint = *paint;
3634c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger        }
3644c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger        filteredPaint.setFilterQuality(kLow_SkFilterQuality);
3654c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger
3664c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger        canvas->drawNinePatch(skiaBitmap, *chunk, 0, 0, (right-left)/scale, (bottom-top)/scale,
3674c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger                &filteredPaint);
3684c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger
3694c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger        canvas->restore();
3704c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger    }
3714c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger}
3724c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger
3737c103a36f60b690e3fe83c40210e1cb0c76bba43John Reckstatic void drawBitmap(JNIEnv* env, jobject jcanvas, jlong canvasHandle, jobject jbitmap,
3748872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                       jfloat left, jfloat top, jlong paintHandle, jint canvasDensity,
3758872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                       jint screenDensity, jint bitmapDensity) {
3768872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    Canvas* canvas = get_canvas(canvasHandle);
3777c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    SkBitmap bitmap;
3787c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
3796ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
3808872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3818872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if (canvasDensity == bitmapDensity || canvasDensity == 0 || bitmapDensity == 0) {
3828872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        if (screenDensity != 0 && screenDensity != bitmapDensity) {
3836ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod            Paint filteredPaint;
3848872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            if (paint) {
3858872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                filteredPaint = *paint;
3868872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            }
3872a1ce8a4e5258b6599cb8e86864eb816d24d69b4Mike Reed            filteredPaint.setFilterQuality(kLow_SkFilterQuality);
3887c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck            canvas->drawBitmap(bitmap, left, top, &filteredPaint);
3898872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        } else {
3907c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck            canvas->drawBitmap(bitmap, left, top, paint);
3918872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        }
3928872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    } else {
3938872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        canvas->save(SkCanvas::kMatrixClip_SaveFlag);
3948872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        SkScalar scale = canvasDensity / (float)bitmapDensity;
3958872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        canvas->translate(left, top);
3968872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        canvas->scale(scale, scale);
3978872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3986ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod        Paint filteredPaint;
3998872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        if (paint) {
4008872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            filteredPaint = *paint;
4018872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        }
4022a1ce8a4e5258b6599cb8e86864eb816d24d69b4Mike Reed        filteredPaint.setFilterQuality(kLow_SkFilterQuality);
4038872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
4047c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck        canvas->drawBitmap(bitmap, 0, 0, &filteredPaint);
4058872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        canvas->restore();
4068872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
4078872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
4088872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
4097c103a36f60b690e3fe83c40210e1cb0c76bba43John Reckstatic void drawBitmapMatrix(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap,
4108872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                             jlong matrixHandle, jlong paintHandle) {
4118872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
4126ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
4137c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    SkBitmap bitmap;
4147c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
4157c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    get_canvas(canvasHandle)->drawBitmap(bitmap, *matrix, paint);
4168872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
4178872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
4187c103a36f60b690e3fe83c40210e1cb0c76bba43John Reckstatic void drawBitmapRect(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap,
4198872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           float srcLeft, float srcTop, float srcRight, float srcBottom,
4208872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           float dstLeft, float dstTop, float dstRight, float dstBottom,
4218872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           jlong paintHandle, jint screenDensity, jint bitmapDensity) {
4228872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    Canvas* canvas = get_canvas(canvasHandle);
4236ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
4248872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
4257c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    SkBitmap bitmap;
4267c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
4278872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if (screenDensity != 0 && screenDensity != bitmapDensity) {
4286ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod        Paint filteredPaint;
4298872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        if (paint) {
4308872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            filteredPaint = *paint;
4318872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        }
4322a1ce8a4e5258b6599cb8e86864eb816d24d69b4Mike Reed        filteredPaint.setFilterQuality(kLow_SkFilterQuality);
4337c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck        canvas->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom,
4348872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           dstLeft, dstTop, dstRight, dstBottom, &filteredPaint);
4358872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    } else {
4367c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck        canvas->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom,
4378872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           dstLeft, dstTop, dstRight, dstBottom, paint);
4388872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
4398872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
4408872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
4418872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawBitmapArray(JNIEnv* env, jobject, jlong canvasHandle,
4428872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                            jintArray jcolors, jint offset, jint stride,
4438872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                            jfloat x, jfloat y, jint width, jint height,
4448872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                            jboolean hasAlpha, jlong paintHandle) {
4458872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    // Note: If hasAlpha is false, kRGB_565_SkColorType will be used, which will
4468872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    // correct the alphaType to kOpaque_SkAlphaType.
4478872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkImageInfo info = SkImageInfo::Make(width, height,
4488872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           hasAlpha ? kN32_SkColorType : kRGB_565_SkColorType,
4498872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           kPremul_SkAlphaType);
4508872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkBitmap bitmap;
4513d4eed7f1aa99401dabe2e45b82f98fb4fc2d754Derek Sollenberger    bitmap.setInfo(info);
4523d4eed7f1aa99401dabe2e45b82f98fb4fc2d754Derek Sollenberger    if (!GraphicsJNI::allocatePixels(env, &bitmap, NULL)) {
4538872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        return;
4548872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
4558872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
4568872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if (!GraphicsJNI::SetPixels(env, jcolors, offset, stride, 0, 0, width, height, bitmap)) {
4578872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        return;
4588872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
4598872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
4606ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
4618872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawBitmap(bitmap, x, y, paint);
4628872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
4638872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
4647c103a36f60b690e3fe83c40210e1cb0c76bba43John Reckstatic void drawBitmapMesh(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap,
4658872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           jint meshWidth, jint meshHeight, jfloatArray jverts,
4668872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           jint vertIndex, jintArray jcolors, jint colorIndex, jlong paintHandle) {
4678872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const int ptCount = (meshWidth + 1) * (meshHeight + 1);
4688872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    AutoJavaFloatArray vertA(env, jverts, vertIndex + (ptCount << 1));
4698872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    AutoJavaIntArray colorA(env, jcolors, colorIndex + ptCount);
4708872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
4716ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
4727c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    SkBitmap bitmap;
4737c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
4747c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    get_canvas(canvasHandle)->drawBitmapMesh(bitmap, meshWidth, meshHeight,
4758872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                             vertA.ptr(), colorA.ptr(), paint);
4768872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
4778872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
4786578a989566e585eee053095dc80e2552e125db2Derek Sollenbergerstatic void simplifyPaint(int color, SkPaint* paint) {
4796578a989566e585eee053095dc80e2552e125db2Derek Sollenberger    paint->setColor(color);
4806578a989566e585eee053095dc80e2552e125db2Derek Sollenberger    paint->setShader(nullptr);
4816578a989566e585eee053095dc80e2552e125db2Derek Sollenberger    paint->setColorFilter(nullptr);
4826578a989566e585eee053095dc80e2552e125db2Derek Sollenberger    paint->setLooper(nullptr);
4836578a989566e585eee053095dc80e2552e125db2Derek Sollenberger    paint->setStrokeWidth(4 + 0.04 * paint->getTextSize());
4846578a989566e585eee053095dc80e2552e125db2Derek Sollenberger    paint->setStrokeJoin(SkPaint::kRound_Join);
4856578a989566e585eee053095dc80e2552e125db2Derek Sollenberger    paint->setLooper(nullptr);
4866578a989566e585eee053095dc80e2552e125db2Derek Sollenberger}
4876578a989566e585eee053095dc80e2552e125db2Derek Sollenberger
488acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenbergerclass DrawTextFunctor {
489acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenbergerpublic:
490acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    DrawTextFunctor(const Layout& layout, Canvas* canvas, uint16_t* glyphs, float* pos,
4918dfaa4904205772cdceee63ef3989bcdedf1a914Tom Hudson                    const SkPaint& paint, float x, float y, MinikinRect& bounds,
4928dfaa4904205772cdceee63ef3989bcdedf1a914Tom Hudson                    float totalAdvance)
493acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            : layout(layout), canvas(canvas), glyphs(glyphs), pos(pos), paint(paint),
4948dfaa4904205772cdceee63ef3989bcdedf1a914Tom Hudson              x(x), y(y), bounds(bounds), totalAdvance(totalAdvance) { }
495acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
496acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    void operator()(size_t start, size_t end) {
497acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        if (canvas->drawTextAbsolutePos()) {
498acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            for (size_t i = start; i < end; i++) {
499acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger                glyphs[i] = layout.getGlyphId(i);
500acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger                pos[2 * i] = x + layout.getX(i);
501acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger                pos[2 * i + 1] = y + layout.getY(i);
502acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            }
503acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        } else {
504acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            for (size_t i = start; i < end; i++) {
505acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger                glyphs[i] = layout.getGlyphId(i);
506acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger                pos[2 * i] = layout.getX(i);
507acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger                pos[2 * i + 1] = layout.getY(i);
508acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            }
509acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        }
510acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
511acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        size_t glyphCount = end - start;
5126578a989566e585eee053095dc80e2552e125db2Derek Sollenberger
5136578a989566e585eee053095dc80e2552e125db2Derek Sollenberger        if (CC_UNLIKELY(canvas->isHighContrastText())) {
5146578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            // high contrast draw path
5156578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            int color = paint.getColor();
5166578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            int channelSum = SkColorGetR(color) + SkColorGetG(color) + SkColorGetB(color);
5176578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            bool darken = channelSum < (128 * 3);
5186578a989566e585eee053095dc80e2552e125db2Derek Sollenberger
5196578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            // outline
5206578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            SkPaint outlinePaint(paint);
5216578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            simplifyPaint(darken ? SK_ColorWHITE : SK_ColorBLACK, &outlinePaint);
5226578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            outlinePaint.setStyle(SkPaint::kStrokeAndFill_Style);
5236578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            canvas->drawText(glyphs + start, pos + (2 * start), glyphCount, outlinePaint, x, y,
5246578a989566e585eee053095dc80e2552e125db2Derek Sollenberger                    bounds.mLeft, bounds.mTop, bounds.mRight, bounds.mBottom, totalAdvance);
5256578a989566e585eee053095dc80e2552e125db2Derek Sollenberger
5266578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            // inner
5276578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            SkPaint innerPaint(paint);
5286578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            simplifyPaint(darken ? SK_ColorBLACK : SK_ColorWHITE, &innerPaint);
5296578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            innerPaint.setStyle(SkPaint::kFill_Style);
5306578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            canvas->drawText(glyphs + start, pos + (2 * start), glyphCount, innerPaint, x, y,
5316578a989566e585eee053095dc80e2552e125db2Derek Sollenberger                    bounds.mLeft, bounds.mTop, bounds.mRight, bounds.mBottom, totalAdvance);
5326578a989566e585eee053095dc80e2552e125db2Derek Sollenberger        } else {
5336578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            // standard draw path
5346578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            canvas->drawText(glyphs + start, pos + (2 * start), glyphCount, paint, x, y,
5356578a989566e585eee053095dc80e2552e125db2Derek Sollenberger                             bounds.mLeft, bounds.mTop, bounds.mRight, bounds.mBottom,
5366578a989566e585eee053095dc80e2552e125db2Derek Sollenberger                             totalAdvance);
5376578a989566e585eee053095dc80e2552e125db2Derek Sollenberger        }
538acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    }
539acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenbergerprivate:
540acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    const Layout& layout;
541acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    Canvas* canvas;
542acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    uint16_t* glyphs;
543acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    float* pos;
544acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    const SkPaint& paint;
545acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    float x;
546acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    float y;
547acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    MinikinRect& bounds;
5488dfaa4904205772cdceee63ef3989bcdedf1a914Tom Hudson    float totalAdvance;
549acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger};
550acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
551acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenbergervoid drawText(Canvas* canvas, const uint16_t* text, int start, int count, int contextCount,
552acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger             float x, float y, int bidiFlags, const Paint& origPaint, TypefaceImpl* typeface) {
553acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    // minikin may modify the original paint
554acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    Paint paint(origPaint);
555acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
556acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    Layout layout;
55763c5c78a72a21d57913e8601cc2a1ab72a424a02Behdad Esfahbod    MinikinUtils::doLayout(&layout, &paint, bidiFlags, typeface, text, start, count, contextCount);
558acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
559acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    size_t nGlyphs = layout.nGlyphs();
560a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    std::unique_ptr<uint16_t[]> glyphs(new uint16_t[nGlyphs]);
561a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    std::unique_ptr<float[]> pos(new float[nGlyphs * 2]);
562acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
563acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    x += MinikinUtils::xOffsetForTextAlign(&paint, layout);
564acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
565acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    MinikinRect bounds;
566acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    layout.getBounds(&bounds);
5678dfaa4904205772cdceee63ef3989bcdedf1a914Tom Hudson    if (!canvas->drawTextAbsolutePos()) {
5688dfaa4904205772cdceee63ef3989bcdedf1a914Tom Hudson        bounds.offset(x, y);
5698dfaa4904205772cdceee63ef3989bcdedf1a914Tom Hudson    }
570acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
571a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    DrawTextFunctor f(layout, canvas, glyphs.get(), pos.get(),
572a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik            paint, x, y, bounds, layout.getAdvance());
573acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    MinikinUtils::forFontRun(layout, &paint, f);
574acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger}
575acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
5768872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawTextChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text,
5778872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                          jint index, jint count, jfloat x, jfloat y, jint bidiFlags,
5788872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                          jlong paintHandle, jlong typefaceHandle) {
5796ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
5808872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
5818872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    jchar* jchars = env->GetCharArrayElements(text, NULL);
582acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    drawText(get_canvas(canvasHandle), jchars + index, 0, count, count, x, y,
5838872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                       bidiFlags, *paint, typeface);
5848872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    env->ReleaseCharArrayElements(text, jchars, JNI_ABORT);
5858872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
5868872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
5878872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawTextString(JNIEnv* env, jobject, jlong canvasHandle, jstring text,
5888872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           jint start, jint end, jfloat x, jfloat y, jint bidiFlags,
5898872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           jlong paintHandle, jlong typefaceHandle) {
5906ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
5918872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
5928872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const int count = end - start;
5938872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const jchar* jchars = env->GetStringChars(text, NULL);
594acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    drawText(get_canvas(canvasHandle), jchars + start, 0, count, count, x, y,
5958872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                       bidiFlags, *paint, typeface);
5968872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    env->ReleaseStringChars(text, jchars);
5978872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
5988872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
5998872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawTextRunChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text, jint index,
6008872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                             jint count, jint contextIndex, jint contextCount, jfloat x, jfloat y,
6018872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                             jboolean isRtl, jlong paintHandle, jlong typefaceHandle) {
6026ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
6038872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
6048872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6058872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
6068872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    jchar* jchars = env->GetCharArrayElements(text, NULL);
607acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    drawText(get_canvas(canvasHandle), jchars + contextIndex, index - contextIndex, count,
6088872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                       contextCount, x, y, bidiFlags, *paint, typeface);
6098872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    env->ReleaseCharArrayElements(text, jchars, JNI_ABORT);
6108872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
6118872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6128872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawTextRunString(JNIEnv* env, jobject obj, jlong canvasHandle, jstring text,
6138872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                              jint start, jint end, jint contextStart, jint contextEnd,
6148872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                              jfloat x, jfloat y, jboolean isRtl, jlong paintHandle,
6158872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                              jlong typefaceHandle) {
6166ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
6178872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
6188872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6198872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
6208872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    jint count = end - start;
6218872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    jint contextCount = contextEnd - contextStart;
6228872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const jchar* jchars = env->GetStringChars(text, NULL);
623acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    drawText(get_canvas(canvasHandle), jchars + contextStart, start - contextStart, count,
6248872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                       contextCount, x, y, bidiFlags, *paint, typeface);
6258872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    env->ReleaseStringChars(text, jchars);
6268872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
6278872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6288872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerclass DrawTextOnPathFunctor {
6298872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerpublic:
6308872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    DrawTextOnPathFunctor(const Layout& layout, Canvas* canvas, float hOffset,
6316ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod                float vOffset, const Paint& paint, const SkPath& path)
6328872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            : layout(layout), canvas(canvas), hOffset(hOffset), vOffset(vOffset),
6338872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                paint(paint), path(path) {
6348872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
6358872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    void operator()(size_t start, size_t end) {
6368872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        uint16_t glyphs[1];
6378872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        for (size_t i = start; i < end; i++) {
6388872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            glyphs[0] = layout.getGlyphId(i);
6398872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            float x = hOffset + layout.getX(i);
6408872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            float y = vOffset + layout.getY(i);
6418872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            canvas->drawTextOnPath(glyphs, 1, path, x, y, paint);
6428872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        }
6438872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
6448872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerprivate:
6458872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const Layout& layout;
6468872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    Canvas* canvas;
6478872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    float hOffset;
6488872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    float vOffset;
6496ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint& paint;
6508872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const SkPath& path;
6518872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger};
6528872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6538872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawTextOnPath(Canvas* canvas, const uint16_t* text, int count, int bidiFlags,
6548872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           const SkPath& path, float hOffset, float vOffset,
6556ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod                           const Paint& paint, TypefaceImpl* typeface) {
6566ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint paintCopy(paint);
6578872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    Layout layout;
65863c5c78a72a21d57913e8601cc2a1ab72a424a02Behdad Esfahbod    MinikinUtils::doLayout(&layout, &paintCopy, bidiFlags, typeface, text, 0, count, count);
6598872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    hOffset += MinikinUtils::hOffsetForTextAlign(&paintCopy, layout, path);
6608872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6618872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    // Set align to left for drawing, as we don't want individual
6628872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    // glyphs centered or right-aligned; the offset above takes
6638872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    // care of all alignment.
6646ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    paintCopy.setTextAlign(Paint::kLeft_Align);
6658872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6668872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    DrawTextOnPathFunctor f(layout, canvas, hOffset, vOffset, paintCopy, path);
6678872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    MinikinUtils::forFontRun(layout, &paintCopy, f);
6688872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
6698872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6708872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawTextOnPathChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text,
6718872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                jint index, jint count, jlong pathHandle, jfloat hOffset,
6728872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                jfloat vOffset, jint bidiFlags, jlong paintHandle,
6738872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                jlong typefaceHandle) {
6748872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
6756ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
6768872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
6778872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6788872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    jchar* jchars = env->GetCharArrayElements(text, NULL);
6798872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6808872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    drawTextOnPath(get_canvas(canvasHandle), jchars + index, count, bidiFlags, *path,
6818872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                   hOffset, vOffset, *paint, typeface);
6828872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6838872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    env->ReleaseCharArrayElements(text, jchars, 0);
6848872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
6858872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6868872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawTextOnPathString(JNIEnv* env, jobject, jlong canvasHandle, jstring text,
6878872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                 jlong pathHandle, jfloat hOffset, jfloat vOffset,
6888872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                 jint bidiFlags, jlong paintHandle, jlong typefaceHandle) {
6898872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
6906ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
6918872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
6928872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6938872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const jchar* jchars = env->GetStringChars(text, NULL);
6948872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    int count = env->GetStringLength(text);
6958872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6968872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    drawTextOnPath(get_canvas(canvasHandle), jchars, count, bidiFlags, *path,
6978872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                   hOffset, vOffset, *paint, typeface);
6988872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6998872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    env->ReleaseStringChars(text, jchars);
7008872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
7018872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
7028872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void setDrawFilter(JNIEnv* env, jobject, jlong canvasHandle, jlong filterHandle) {
7038872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->setDrawFilter(reinterpret_cast<SkDrawFilter*>(filterHandle));
7048872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
7058872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
7068872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void freeCaches(JNIEnv* env, jobject) {
7078872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkGraphics::PurgeFontCache();
7088872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
7098872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
7108872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void freeTextLayoutCaches(JNIEnv* env, jobject) {
7118872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    Layout::purgeCaches();
7128872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
7138872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
7148872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}; // namespace CanvasJNI
7158872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
71676f6a86de25e1bf74717e047e55fd44b089673f3Daniel Micaystatic const JNINativeMethod gMethods[] = {
717775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhler    {"getNativeFinalizer", "()J", (void*) CanvasJNI::getNativeFinalizer},
718c1b33d665c8caf5760f68c45c6ca0baa649b832aJohn Reck    {"initRaster", "(Landroid/graphics/Bitmap;)J", (void*) CanvasJNI::initRaster},
7190dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_setBitmap", "!(JLandroid/graphics/Bitmap;)V", (void*) CanvasJNI::setBitmap},
7200dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_isOpaque","!(J)Z", (void*) CanvasJNI::isOpaque},
7210dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_getWidth","!(J)I", (void*) CanvasJNI::getWidth},
7220dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_getHeight","!(J)I", (void*) CanvasJNI::getHeight},
7230dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_setHighContrastText","!(JZ)V", (void*) CanvasJNI::setHighContrastText},
7240dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_save","!(JI)I", (void*) CanvasJNI::save},
7250dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_saveLayer","!(JFFFFJI)I", (void*) CanvasJNI::saveLayer},
7260dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_saveLayerAlpha","!(JFFFFII)I", (void*) CanvasJNI::saveLayerAlpha},
7270dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_getSaveCount","!(J)I", (void*) CanvasJNI::getSaveCount},
7280dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_restore","!(JZ)V", (void*) CanvasJNI::restore},
7290dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_restoreToCount","!(JIZ)V", (void*) CanvasJNI::restoreToCount},
7300dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_getCTM", "!(JJ)V", (void*)CanvasJNI::getCTM},
7310dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_setMatrix","!(JJ)V", (void*) CanvasJNI::setMatrix},
7320dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_concat","!(JJ)V", (void*) CanvasJNI::concat},
7330dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_rotate","!(JF)V", (void*) CanvasJNI::rotate},
7340dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_scale","!(JFF)V", (void*) CanvasJNI::scale},
7350dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_skew","!(JFF)V", (void*) CanvasJNI::skew},
7360dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_translate","!(JFF)V", (void*) CanvasJNI::translate},
7370dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_getClipBounds","!(JLandroid/graphics/Rect;)Z", (void*) CanvasJNI::getClipBounds},
7380dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_quickReject","!(JJ)Z", (void*) CanvasJNI::quickRejectPath},
7390dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_quickReject","!(JFFFF)Z", (void*)CanvasJNI::quickRejectRect},
7400dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_clipRect","!(JFFFFI)Z", (void*) CanvasJNI::clipRect},
7410dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_clipPath","!(JJI)Z", (void*) CanvasJNI::clipPath},
7420dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_clipRegion","!(JJI)Z", (void*) CanvasJNI::clipRegion},
7430dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_drawColor","!(JII)V", (void*) CanvasJNI::drawColor},
7440dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_drawPaint","!(JJ)V", (void*) CanvasJNI::drawPaint},
7450dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_drawPoint", "!(JFFJ)V", (void*) CanvasJNI::drawPoint},
7460dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_drawPoints", "!(J[FIIJ)V", (void*) CanvasJNI::drawPoints},
7470dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_drawLine", "!(JFFFFJ)V", (void*) CanvasJNI::drawLine},
7480dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_drawLines", "!(J[FIIJ)V", (void*) CanvasJNI::drawLines},
7490dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_drawRect","!(JFFFFJ)V", (void*) CanvasJNI::drawRect},
7500dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_drawRegion", "!(JJJ)V", (void*) CanvasJNI::drawRegion },
7510dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_drawRoundRect","!(JFFFFFFJ)V", (void*) CanvasJNI::drawRoundRect},
7520dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_drawCircle","!(JFFFJ)V", (void*) CanvasJNI::drawCircle},
7530dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_drawOval","!(JFFFFJ)V", (void*) CanvasJNI::drawOval},
7540dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_drawArc","!(JFFFFFFZJ)V", (void*) CanvasJNI::drawArc},
7550dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_drawPath","!(JJJ)V", (void*) CanvasJNI::drawPath},
7560dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"nativeDrawVertices", "!(JII[FI[FI[II[SIIJ)V", (void*)CanvasJNI::drawVertices},
7570dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_drawNinePatch", "!(JJJFFFFJII)V", (void*)CanvasJNI::drawNinePatch},
7580dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_drawBitmap","!(JLandroid/graphics/Bitmap;FFJIII)V", (void*) CanvasJNI::drawBitmap},
7590dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"nativeDrawBitmapMatrix", "!(JLandroid/graphics/Bitmap;JJ)V", (void*)CanvasJNI::drawBitmapMatrix},
7600dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_drawBitmap","!(JLandroid/graphics/Bitmap;FFFFFFFFJII)V", (void*) CanvasJNI::drawBitmapRect},
7610dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_drawBitmap", "!(J[IIIFFIIZJ)V", (void*)CanvasJNI::drawBitmapArray},
7620dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"nativeDrawBitmapMesh", "!(JLandroid/graphics/Bitmap;II[FI[IIJ)V", (void*)CanvasJNI::drawBitmapMesh},
7630dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_drawText","!(J[CIIFFIJJ)V", (void*) CanvasJNI::drawTextChars},
7640dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_drawText","!(JLjava/lang/String;IIFFIJJ)V", (void*) CanvasJNI::drawTextString},
7650dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_drawTextRun","!(J[CIIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunChars},
7660dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_drawTextRun","!(JLjava/lang/String;IIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunString},
7670dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_drawTextOnPath","!(J[CIIJFFIJJ)V", (void*) CanvasJNI::drawTextOnPathChars},
7680dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"native_drawTextOnPath","!(JLjava/lang/String;JFFIJJ)V", (void*) CanvasJNI::drawTextOnPathString},
7690dba1f611410e5075a910fb73ff3d3c703bbc5ceJohn Reck    {"nativeSetDrawFilter", "!(JJ)V", (void*) CanvasJNI::setDrawFilter},
7708872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"freeCaches", "()V", (void*) CanvasJNI::freeCaches},
7718872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"freeTextLayoutCaches", "()V", (void*) CanvasJNI::freeTextLayoutCaches}
7728872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger};
7738872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
7748872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerint register_android_graphics_Canvas(JNIEnv* env) {
775ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    return RegisterMethodsOrDie(env, "android/graphics/Canvas", gMethods, NELEM(gMethods));
7768872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
7778872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
7788872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}; // namespace android
779