android_graphics_Canvas.cpp revision 94394b3fb048d5349a77b57950ab7f6b6e92ce34
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
21849911a9c4315fc552faa38516c842b2541b1909John Reck#include <Canvas.h>
22acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger#include "SkDrawFilter.h"
238872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger#include "SkGraphics.h"
246ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod#include "Paint.h"
258872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger#include "TypefaceImpl.h"
268872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
278872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger#include "MinikinUtils.h"
288872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
298872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergernamespace android {
308872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
318872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergernamespace CanvasJNI {
328872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
338872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic Canvas* get_canvas(jlong canvasHandle) {
348872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return reinterpret_cast<Canvas*>(canvasHandle);
358872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
368872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
378872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void finalizer(JNIEnv* env, jobject clazz, jlong canvasHandle) {
388872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    delete get_canvas(canvasHandle);
398872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
408872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
418872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger// Native wrapper constructor used by Canvas(Bitmap)
42c1b33d665c8caf5760f68c45c6ca0baa649b832aJohn Reckstatic jlong initRaster(JNIEnv* env, jobject, jobject jbitmap) {
433731dc220ed457e0f1e99d7ec2589e0a43872b59John Reck    SkBitmap bitmap;
44c1b33d665c8caf5760f68c45c6ca0baa649b832aJohn Reck    if (jbitmap != NULL) {
453731dc220ed457e0f1e99d7ec2589e0a43872b59John Reck        GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
46c1b33d665c8caf5760f68c45c6ca0baa649b832aJohn Reck    }
473731dc220ed457e0f1e99d7ec2589e0a43872b59John Reck    return reinterpret_cast<jlong>(Canvas::create_canvas(bitmap));
488872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
498872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
508872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger// Set the given bitmap as the new draw target (wrapped in a new SkCanvas),
518872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger// optionally copying canvas matrix & clip state.
52c1b33d665c8caf5760f68c45c6ca0baa649b832aJohn Reckstatic void setBitmap(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap) {
533731dc220ed457e0f1e99d7ec2589e0a43872b59John Reck    SkBitmap bitmap;
54c1b33d665c8caf5760f68c45c6ca0baa649b832aJohn Reck    if (jbitmap != NULL) {
553731dc220ed457e0f1e99d7ec2589e0a43872b59John Reck        GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
56c1b33d665c8caf5760f68c45c6ca0baa649b832aJohn Reck    }
573731dc220ed457e0f1e99d7ec2589e0a43872b59John Reck    get_canvas(canvasHandle)->setBitmap(bitmap);
588872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
598872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
608872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jboolean isOpaque(JNIEnv*, jobject, jlong canvasHandle) {
618872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return get_canvas(canvasHandle)->isOpaque() ? JNI_TRUE : JNI_FALSE;
628872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
638872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
648872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jint getWidth(JNIEnv*, jobject, jlong canvasHandle) {
658872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return static_cast<jint>(get_canvas(canvasHandle)->width());
668872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
678872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
688872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jint getHeight(JNIEnv*, jobject, jlong canvasHandle) {
698872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return static_cast<jint>(get_canvas(canvasHandle)->height());
708872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
718872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
728872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jint getSaveCount(JNIEnv*, jobject, jlong canvasHandle) {
738872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return static_cast<jint>(get_canvas(canvasHandle)->getSaveCount());
748872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
758872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
768872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jint save(JNIEnv*, jobject, jlong canvasHandle, jint flagsHandle) {
778872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
788872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return static_cast<jint>(get_canvas(canvasHandle)->save(flags));
798872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
808872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
818872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jint saveLayer(JNIEnv* env, jobject, jlong canvasHandle, jfloat l, jfloat t,
828872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                      jfloat r, jfloat b, jlong paintHandle, jint flagsHandle) {
836ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint  = reinterpret_cast<Paint*>(paintHandle);
848872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
858872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return static_cast<jint>(get_canvas(canvasHandle)->saveLayer(l, t, r, b, paint, flags));
868872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
878872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
888872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jint saveLayerAlpha(JNIEnv* env, jobject, jlong canvasHandle, jfloat l, jfloat t,
898872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           jfloat r, jfloat b, jint alpha, jint flagsHandle) {
908872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
918872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return static_cast<jint>(get_canvas(canvasHandle)->saveLayerAlpha(l, t, r, b, alpha, flags));
928872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
938872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
943891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craikstatic void restore(JNIEnv* env, jobject, jlong canvasHandle, jboolean throwOnUnderflow) {
958872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    Canvas* canvas = get_canvas(canvasHandle);
968872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if (canvas->getSaveCount() <= 1) {  // cannot restore anymore
973891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik        if (throwOnUnderflow) {
983891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik            doThrowISE(env, "Underflow in restore - more restores than saves");
993891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik        }
1003891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik        return; // compat behavior - return without throwing
1018872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
1028872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    canvas->restore();
1038872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1048872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1053891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craikstatic void restoreToCount(JNIEnv* env, jobject, jlong canvasHandle, jint restoreCount,
1063891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik        jboolean throwOnUnderflow) {
1078872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    Canvas* canvas = get_canvas(canvasHandle);
1088872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if (restoreCount < 1 || restoreCount > canvas->getSaveCount()) {
1093891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik        if (throwOnUnderflow) {
1103891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik            doThrowIAE(env, "Underflow in restoreToCount - more restores than saves");
1113891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik            return;
1123891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik        }
1133891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik        restoreCount = 1; // compat behavior - restore as far as possible
1148872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
1158872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    canvas->restoreToCount(restoreCount);
1168872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1178872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1188872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void getCTM(JNIEnv* env, jobject, jlong canvasHandle, jlong matrixHandle) {
1198872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
1208872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->getMatrix(matrix);
1218872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1228872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1238872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void setMatrix(JNIEnv* env, jobject, jlong canvasHandle, jlong matrixHandle) {
1248872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
1258872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->setMatrix(matrix ? *matrix : SkMatrix::I());
1268872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1278872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1288872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void concat(JNIEnv* env, jobject, jlong canvasHandle, jlong matrixHandle) {
1298872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
1308872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->concat(*matrix);
1318872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1328872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1338872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void rotate(JNIEnv*, jobject, jlong canvasHandle, jfloat degrees) {
1348872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->rotate(degrees);
1358872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1368872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1378872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void scale(JNIEnv*, jobject, jlong canvasHandle, jfloat sx, jfloat sy) {
1388872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->scale(sx, sy);
1398872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1408872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1418872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void skew(JNIEnv*, jobject, jlong canvasHandle, jfloat sx, jfloat sy) {
1428872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->skew(sx, sy);
1438872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1448872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1458872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void translate(JNIEnv*, jobject, jlong canvasHandle, jfloat dx, jfloat dy) {
1468872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->translate(dx, dy);
1478872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1488872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1498872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jboolean getClipBounds(JNIEnv* env, jobject, jlong canvasHandle, jobject bounds) {
1508872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkRect   r;
1518872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkIRect ir;
1528872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    bool result = get_canvas(canvasHandle)->getClipBounds(&r);
1538872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1548872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if (!result) {
1558872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        r.setEmpty();
1568872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
1578872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    r.round(&ir);
1588872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1598872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    (void)GraphicsJNI::irect_to_jrect(ir, env, bounds);
1608872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return result ? JNI_TRUE : JNI_FALSE;
1618872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1628872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1638872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jboolean quickRejectRect(JNIEnv* env, jobject, jlong canvasHandle,
1648872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                jfloat left, jfloat top, jfloat right, jfloat bottom) {
1658872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    bool result = get_canvas(canvasHandle)->quickRejectRect(left, top, right, bottom);
1668872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return result ? JNI_TRUE : JNI_FALSE;
1678872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1688872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1698872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jboolean quickRejectPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle) {
1708872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
1718872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    bool result = get_canvas(canvasHandle)->quickRejectPath(*path);
1728872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return result ? JNI_TRUE : JNI_FALSE;
1738872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1748872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1758872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jboolean clipRect(JNIEnv*, jobject, jlong canvasHandle, jfloat l, jfloat t,
1768872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                         jfloat r, jfloat b, jint opHandle) {
1778872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkRegion::Op op = static_cast<SkRegion::Op>(opHandle);
1785ec6a2878b2ad933c5da6fe2341c854155acc24cChris Craik    bool nonEmptyClip = get_canvas(canvasHandle)->clipRect(l, t, r, b, op);
1795ec6a2878b2ad933c5da6fe2341c854155acc24cChris Craik    return nonEmptyClip ? JNI_TRUE : JNI_FALSE;
1808872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1818872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1828872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jboolean clipPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle,
1838872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                         jint opHandle) {
1848872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
1858872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkRegion::Op op = static_cast<SkRegion::Op>(opHandle);
1865ec6a2878b2ad933c5da6fe2341c854155acc24cChris Craik    bool nonEmptyClip = get_canvas(canvasHandle)->clipPath(path, op);
1875ec6a2878b2ad933c5da6fe2341c854155acc24cChris Craik    return nonEmptyClip ? JNI_TRUE : JNI_FALSE;
1888872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1898872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1908872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jboolean clipRegion(JNIEnv* env, jobject, jlong canvasHandle, jlong deviceRgnHandle,
1918872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           jint opHandle) {
1928872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkRegion* deviceRgn = reinterpret_cast<SkRegion*>(deviceRgnHandle);
1938872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkRegion::Op op = static_cast<SkRegion::Op>(opHandle);
1945ec6a2878b2ad933c5da6fe2341c854155acc24cChris Craik    bool nonEmptyClip = get_canvas(canvasHandle)->clipRegion(deviceRgn, op);
1955ec6a2878b2ad933c5da6fe2341c854155acc24cChris Craik    return nonEmptyClip ? JNI_TRUE : JNI_FALSE;
1968872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1978872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1988872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawColor(JNIEnv* env, jobject, jlong canvasHandle, jint color, jint modeHandle) {
1991526a458a30184609f19b05e7334da3cbde81dd1Chris Craik    SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(modeHandle);
2001526a458a30184609f19b05e7334da3cbde81dd1Chris Craik    get_canvas(canvasHandle)->drawColor(color, mode);
2018872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2028872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2038872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawPaint(JNIEnv* env, jobject, jlong canvasHandle, jlong paintHandle) {
2046ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2058872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawPaint(*paint);
2068872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2078872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2088872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawPoint(JNIEnv*, jobject, jlong canvasHandle, jfloat x, jfloat y,
2098872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                      jlong paintHandle) {
2106ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2118872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawPoint(x, y, *paint);
2128872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2138872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2148872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawPoints(JNIEnv* env, jobject, jlong canvasHandle, jfloatArray jptsArray,
2158872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                       jint offset, jint count, jlong paintHandle) {
2168872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    NPE_CHECK_RETURN_VOID(env, jptsArray);
2178872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    AutoJavaFloatArray autoPts(env, jptsArray);
2188872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    float* floats = autoPts.ptr();
2198872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const int length = autoPts.length();
2208872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2218872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if ((offset | count) < 0 || offset + count > length) {
2228872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        doThrowAIOOBE(env);
2238872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        return;
2248872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
2258872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2266ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2278872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawPoints(floats + offset, count, *paint);
2288872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2298872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2308872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawLine(JNIEnv* env, jobject, jlong canvasHandle, jfloat startX, jfloat startY,
2318872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                     jfloat stopX, jfloat stopY, jlong paintHandle) {
2326ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2338872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawLine(startX, startY, stopX, stopY, *paint);
2348872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2358872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2368872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawLines(JNIEnv* env, jobject, jlong canvasHandle, jfloatArray jptsArray,
2378872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                      jint offset, jint count, jlong paintHandle) {
2388872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    NPE_CHECK_RETURN_VOID(env, jptsArray);
2398872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    AutoJavaFloatArray autoPts(env, jptsArray);
2408872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    float* floats = autoPts.ptr();
2418872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const int length = autoPts.length();
2428872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2438872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if ((offset | count) < 0 || offset + count > length) {
2448872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        doThrowAIOOBE(env);
2458872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        return;
2468872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
2478872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2486ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2498872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawLines(floats + offset, count, *paint);
2508872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2518872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2528872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawRect(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
2538872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                     jfloat right, jfloat bottom, jlong paintHandle) {
2546ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2558872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawRect(left, top, right, bottom, *paint);
2568872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2578872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
25894394b3fb048d5349a77b57950ab7f6b6e92ce34Derek Sollenbergerstatic void drawRegion(JNIEnv* env, jobject, jlong canvasHandle, jlong regionHandle,
25994394b3fb048d5349a77b57950ab7f6b6e92ce34Derek Sollenberger                       jlong paintHandle) {
26094394b3fb048d5349a77b57950ab7f6b6e92ce34Derek Sollenberger    const SkRegion* region = reinterpret_cast<SkRegion*>(regionHandle);
26194394b3fb048d5349a77b57950ab7f6b6e92ce34Derek Sollenberger    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
26294394b3fb048d5349a77b57950ab7f6b6e92ce34Derek Sollenberger    get_canvas(canvasHandle)->drawRegion(*region, *paint);
26394394b3fb048d5349a77b57950ab7f6b6e92ce34Derek Sollenberger}
26494394b3fb048d5349a77b57950ab7f6b6e92ce34Derek Sollenberger
2658872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawRoundRect(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
2668872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                          jfloat right, jfloat bottom, jfloat rx, jfloat ry, jlong paintHandle) {
2676ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2688872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawRoundRect(left, top, right, bottom, rx, ry, *paint);
2698872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2708872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2718872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawCircle(JNIEnv* env, jobject, jlong canvasHandle, jfloat cx, jfloat cy,
2728872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                       jfloat radius, jlong paintHandle) {
2736ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2748872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawCircle(cx, cy, radius, *paint);
2758872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2768872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2778872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawOval(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
2788872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                     jfloat right, jfloat bottom, jlong paintHandle) {
2796ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2808872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawOval(left, top, right, bottom, *paint);
2818872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2828872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2838872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawArc(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
2848872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                    jfloat right, jfloat bottom, jfloat startAngle, jfloat sweepAngle,
2858872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                    jboolean useCenter, jlong paintHandle) {
2866ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2878872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawArc(left, top, right, bottom, startAngle, sweepAngle,
2888872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                       useCenter, *paint);
2898872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2908872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2918872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle,
2928872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                     jlong paintHandle) {
2938872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
2946ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2958872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawPath(*path, *paint);
2968872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2978872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2988872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawVertices(JNIEnv* env, jobject, jlong canvasHandle,
2998872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                         jint modeHandle, jint vertexCount,
3008872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                         jfloatArray jverts, jint vertIndex,
3018872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                         jfloatArray jtexs, jint texIndex,
3028872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                         jintArray jcolors, jint colorIndex,
3038872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                         jshortArray jindices, jint indexIndex,
3048872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                         jint indexCount, jlong paintHandle) {
3058872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    AutoJavaFloatArray  vertA(env, jverts, vertIndex + vertexCount);
3068872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    AutoJavaFloatArray  texA(env, jtexs, texIndex + vertexCount);
3078872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    AutoJavaIntArray    colorA(env, jcolors, colorIndex + vertexCount);
3088872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    AutoJavaShortArray  indexA(env, jindices, indexIndex + indexCount);
3098872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3108872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const float* verts = vertA.ptr() + vertIndex;
3118872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const float* texs = texA.ptr() + vertIndex;
3128872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const int* colors = NULL;
3138872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const uint16_t* indices = NULL;
3148872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3158872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if (jcolors != NULL) {
3168872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        colors = colorA.ptr() + colorIndex;
3178872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
3188872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if (jindices != NULL) {
3198872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        indices = (const uint16_t*)(indexA.ptr() + indexIndex);
3208872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
3218872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3228872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkCanvas::VertexMode mode = static_cast<SkCanvas::VertexMode>(modeHandle);
3236ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
3248872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawVertices(mode, vertexCount, verts, texs, colors,
3258872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                           indices, indexCount, *paint);
3268872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
3278872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3287c103a36f60b690e3fe83c40210e1cb0c76bba43John Reckstatic void drawBitmap(JNIEnv* env, jobject jcanvas, jlong canvasHandle, jobject jbitmap,
3298872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                       jfloat left, jfloat top, jlong paintHandle, jint canvasDensity,
3308872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                       jint screenDensity, jint bitmapDensity) {
3318872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    Canvas* canvas = get_canvas(canvasHandle);
3327c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    SkBitmap bitmap;
3337c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
3346ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
3358872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3368872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if (canvasDensity == bitmapDensity || canvasDensity == 0 || bitmapDensity == 0) {
3378872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        if (screenDensity != 0 && screenDensity != bitmapDensity) {
3386ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod            Paint filteredPaint;
3398872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            if (paint) {
3408872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                filteredPaint = *paint;
3418872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            }
3422a1ce8a4e5258b6599cb8e86864eb816d24d69b4Mike Reed            filteredPaint.setFilterQuality(kLow_SkFilterQuality);
3437c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck            canvas->drawBitmap(bitmap, left, top, &filteredPaint);
3448872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        } else {
3457c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck            canvas->drawBitmap(bitmap, left, top, paint);
3468872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        }
3478872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    } else {
3488872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        canvas->save(SkCanvas::kMatrixClip_SaveFlag);
3498872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        SkScalar scale = canvasDensity / (float)bitmapDensity;
3508872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        canvas->translate(left, top);
3518872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        canvas->scale(scale, scale);
3528872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3536ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod        Paint filteredPaint;
3548872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        if (paint) {
3558872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            filteredPaint = *paint;
3568872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        }
3572a1ce8a4e5258b6599cb8e86864eb816d24d69b4Mike Reed        filteredPaint.setFilterQuality(kLow_SkFilterQuality);
3588872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3597c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck        canvas->drawBitmap(bitmap, 0, 0, &filteredPaint);
3608872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        canvas->restore();
3618872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
3628872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
3638872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3647c103a36f60b690e3fe83c40210e1cb0c76bba43John Reckstatic void drawBitmapMatrix(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap,
3658872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                             jlong matrixHandle, jlong paintHandle) {
3668872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
3676ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
3687c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    SkBitmap bitmap;
3697c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
3707c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    get_canvas(canvasHandle)->drawBitmap(bitmap, *matrix, paint);
3718872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
3728872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3737c103a36f60b690e3fe83c40210e1cb0c76bba43John Reckstatic void drawBitmapRect(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap,
3748872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           float srcLeft, float srcTop, float srcRight, float srcBottom,
3758872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           float dstLeft, float dstTop, float dstRight, float dstBottom,
3768872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           jlong paintHandle, jint screenDensity, jint bitmapDensity) {
3778872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    Canvas* canvas = get_canvas(canvasHandle);
3786ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
3798872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3807c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    SkBitmap bitmap;
3817c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
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, srcLeft, srcTop, srcRight, srcBottom,
3898872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           dstLeft, dstTop, dstRight, dstBottom, &filteredPaint);
3908872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    } else {
3917c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck        canvas->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom,
3928872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           dstLeft, dstTop, dstRight, dstBottom, paint);
3938872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
3948872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
3958872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3968872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawBitmapArray(JNIEnv* env, jobject, jlong canvasHandle,
3978872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                            jintArray jcolors, jint offset, jint stride,
3988872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                            jfloat x, jfloat y, jint width, jint height,
3998872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                            jboolean hasAlpha, jlong paintHandle) {
4008872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    // Note: If hasAlpha is false, kRGB_565_SkColorType will be used, which will
4018872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    // correct the alphaType to kOpaque_SkAlphaType.
4028872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkImageInfo info = SkImageInfo::Make(width, height,
4038872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           hasAlpha ? kN32_SkColorType : kRGB_565_SkColorType,
4048872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           kPremul_SkAlphaType);
4058872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkBitmap bitmap;
4063d4eed7f1aa99401dabe2e45b82f98fb4fc2d754Derek Sollenberger    bitmap.setInfo(info);
4073d4eed7f1aa99401dabe2e45b82f98fb4fc2d754Derek Sollenberger    if (!GraphicsJNI::allocatePixels(env, &bitmap, NULL)) {
4088872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        return;
4098872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
4108872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
4118872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if (!GraphicsJNI::SetPixels(env, jcolors, offset, stride, 0, 0, width, height, bitmap)) {
4128872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        return;
4138872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
4148872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
4156ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
4168872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawBitmap(bitmap, x, y, paint);
4178872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
4188872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
4197c103a36f60b690e3fe83c40210e1cb0c76bba43John Reckstatic void drawBitmapMesh(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap,
4208872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           jint meshWidth, jint meshHeight, jfloatArray jverts,
4218872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           jint vertIndex, jintArray jcolors, jint colorIndex, jlong paintHandle) {
4228872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const int ptCount = (meshWidth + 1) * (meshHeight + 1);
4238872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    AutoJavaFloatArray vertA(env, jverts, vertIndex + (ptCount << 1));
4248872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    AutoJavaIntArray colorA(env, jcolors, colorIndex + ptCount);
4258872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
4266ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
4277c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    SkBitmap bitmap;
4287c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
4297c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    get_canvas(canvasHandle)->drawBitmapMesh(bitmap, meshWidth, meshHeight,
4308872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                             vertA.ptr(), colorA.ptr(), paint);
4318872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
4328872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
433acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenbergerclass DrawTextFunctor {
434acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenbergerpublic:
435acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    DrawTextFunctor(const Layout& layout, Canvas* canvas, uint16_t* glyphs, float* pos,
4368dfaa4904205772cdceee63ef3989bcdedf1a914Tom Hudson                    const SkPaint& paint, float x, float y, MinikinRect& bounds,
4378dfaa4904205772cdceee63ef3989bcdedf1a914Tom Hudson                    float totalAdvance)
438acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            : layout(layout), canvas(canvas), glyphs(glyphs), pos(pos), paint(paint),
4398dfaa4904205772cdceee63ef3989bcdedf1a914Tom Hudson              x(x), y(y), bounds(bounds), totalAdvance(totalAdvance) { }
440acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
441acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    void operator()(size_t start, size_t end) {
442acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        if (canvas->drawTextAbsolutePos()) {
443acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            for (size_t i = start; i < end; i++) {
444acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger                glyphs[i] = layout.getGlyphId(i);
445acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger                pos[2 * i] = x + layout.getX(i);
446acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger                pos[2 * i + 1] = y + layout.getY(i);
447acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            }
448acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        } else {
449acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            for (size_t i = start; i < end; i++) {
450acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger                glyphs[i] = layout.getGlyphId(i);
451acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger                pos[2 * i] = layout.getX(i);
452acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger                pos[2 * i + 1] = layout.getY(i);
453acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            }
454acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        }
455acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
456acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        size_t glyphCount = end - start;
457acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        canvas->drawText(glyphs + start, pos + (2 * start), glyphCount, paint, x, y,
4588dfaa4904205772cdceee63ef3989bcdedf1a914Tom Hudson                         bounds.mLeft, bounds.mTop, bounds.mRight, bounds.mBottom,
4598dfaa4904205772cdceee63ef3989bcdedf1a914Tom Hudson                         totalAdvance);
460acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    }
461acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenbergerprivate:
462acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    const Layout& layout;
463acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    Canvas* canvas;
464acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    uint16_t* glyphs;
465acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    float* pos;
466acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    const SkPaint& paint;
467acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    float x;
468acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    float y;
469acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    MinikinRect& bounds;
4708dfaa4904205772cdceee63ef3989bcdedf1a914Tom Hudson    float totalAdvance;
471acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger};
472acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
473acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger// Same values used by Skia
474acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger#define kStdStrikeThru_Offset   (-6.0f / 21.0f)
475acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger#define kStdUnderline_Offset    (1.0f / 9.0f)
476acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger#define kStdUnderline_Thickness (1.0f / 18.0f)
477acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
478acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenbergervoid drawTextDecorations(Canvas* canvas, float x, float y, float length, const SkPaint& paint) {
479acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    uint32_t flags;
480acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    SkDrawFilter* drawFilter = canvas->getDrawFilter();
481acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    if (drawFilter) {
482acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        SkPaint paintCopy(paint);
483acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        drawFilter->filter(&paintCopy, SkDrawFilter::kText_Type);
484acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        flags = paintCopy.getFlags();
485acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    } else {
486acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        flags = paint.getFlags();
487acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    }
488acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    if (flags & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag)) {
489acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        SkScalar left = x;
490acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        SkScalar right = x + length;
491acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        float textSize = paint.getTextSize();
492acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        float strokeWidth = fmax(textSize * kStdUnderline_Thickness, 1.0f);
493acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        if (flags & SkPaint::kUnderlineText_Flag) {
494acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            SkScalar top = y + textSize * kStdUnderline_Offset - 0.5f * strokeWidth;
495acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            SkScalar bottom = y + textSize * kStdUnderline_Offset + 0.5f * strokeWidth;
496acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            canvas->drawRect(left, top, right, bottom, paint);
497acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        }
498acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        if (flags & SkPaint::kStrikeThruText_Flag) {
499acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            SkScalar top = y + textSize * kStdStrikeThru_Offset - 0.5f * strokeWidth;
500acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            SkScalar bottom = y + textSize * kStdStrikeThru_Offset + 0.5f * strokeWidth;
501acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            canvas->drawRect(left, top, right, bottom, paint);
502acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        }
503acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    }
504acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger}
505acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
506acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenbergervoid drawText(Canvas* canvas, const uint16_t* text, int start, int count, int contextCount,
507acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger             float x, float y, int bidiFlags, const Paint& origPaint, TypefaceImpl* typeface) {
508acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    // minikin may modify the original paint
509acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    Paint paint(origPaint);
510acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
511acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    Layout layout;
51263c5c78a72a21d57913e8601cc2a1ab72a424a02Behdad Esfahbod    MinikinUtils::doLayout(&layout, &paint, bidiFlags, typeface, text, start, count, contextCount);
513acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
514acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    size_t nGlyphs = layout.nGlyphs();
515acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    uint16_t* glyphs = new uint16_t[nGlyphs];
516acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    float* pos = new float[nGlyphs * 2];
517acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
518acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    x += MinikinUtils::xOffsetForTextAlign(&paint, layout);
519acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
520acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    MinikinRect bounds;
521acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    layout.getBounds(&bounds);
5228dfaa4904205772cdceee63ef3989bcdedf1a914Tom Hudson    if (!canvas->drawTextAbsolutePos()) {
5238dfaa4904205772cdceee63ef3989bcdedf1a914Tom Hudson        bounds.offset(x, y);
5248dfaa4904205772cdceee63ef3989bcdedf1a914Tom Hudson    }
525acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
5268dfaa4904205772cdceee63ef3989bcdedf1a914Tom Hudson    DrawTextFunctor f(layout, canvas, glyphs, pos, paint, x, y, bounds, layout.getAdvance());
527acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    MinikinUtils::forFontRun(layout, &paint, f);
528acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
529acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    drawTextDecorations(canvas, x, y, layout.getAdvance(), paint);
530acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
531acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    delete[] glyphs;
532acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    delete[] pos;
533acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger}
534acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
5358872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawTextChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text,
5368872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                          jint index, jint count, jfloat x, jfloat y, jint bidiFlags,
5378872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                          jlong paintHandle, jlong typefaceHandle) {
5386ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
5398872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
5408872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    jchar* jchars = env->GetCharArrayElements(text, NULL);
541acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    drawText(get_canvas(canvasHandle), jchars + index, 0, count, count, x, y,
5428872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                       bidiFlags, *paint, typeface);
5438872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    env->ReleaseCharArrayElements(text, jchars, JNI_ABORT);
5448872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
5458872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
5468872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawTextString(JNIEnv* env, jobject, jlong canvasHandle, jstring text,
5478872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           jint start, jint end, jfloat x, jfloat y, jint bidiFlags,
5488872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           jlong paintHandle, jlong typefaceHandle) {
5496ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
5508872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
5518872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const int count = end - start;
5528872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const jchar* jchars = env->GetStringChars(text, NULL);
553acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    drawText(get_canvas(canvasHandle), jchars + start, 0, count, count, x, y,
5548872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                       bidiFlags, *paint, typeface);
5558872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    env->ReleaseStringChars(text, jchars);
5568872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
5578872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
5588872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawTextRunChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text, jint index,
5598872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                             jint count, jint contextIndex, jint contextCount, jfloat x, jfloat y,
5608872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                             jboolean isRtl, jlong paintHandle, jlong typefaceHandle) {
5616ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
5628872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
5638872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
5648872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
5658872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    jchar* jchars = env->GetCharArrayElements(text, NULL);
566acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    drawText(get_canvas(canvasHandle), jchars + contextIndex, index - contextIndex, count,
5678872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                       contextCount, x, y, bidiFlags, *paint, typeface);
5688872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    env->ReleaseCharArrayElements(text, jchars, JNI_ABORT);
5698872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
5708872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
5718872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawTextRunString(JNIEnv* env, jobject obj, jlong canvasHandle, jstring text,
5728872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                              jint start, jint end, jint contextStart, jint contextEnd,
5738872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                              jfloat x, jfloat y, jboolean isRtl, jlong paintHandle,
5748872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                              jlong typefaceHandle) {
5756ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
5768872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
5778872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
5788872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
5798872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    jint count = end - start;
5808872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    jint contextCount = contextEnd - contextStart;
5818872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const jchar* jchars = env->GetStringChars(text, NULL);
582acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    drawText(get_canvas(canvasHandle), jchars + contextStart, start - contextStart, count,
5838872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                       contextCount, x, y, bidiFlags, *paint, typeface);
5848872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    env->ReleaseStringChars(text, jchars);
5858872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
5868872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
5878872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerclass DrawTextOnPathFunctor {
5888872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerpublic:
5898872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    DrawTextOnPathFunctor(const Layout& layout, Canvas* canvas, float hOffset,
5906ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod                float vOffset, const Paint& paint, const SkPath& path)
5918872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            : layout(layout), canvas(canvas), hOffset(hOffset), vOffset(vOffset),
5928872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                paint(paint), path(path) {
5938872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
5948872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    void operator()(size_t start, size_t end) {
5958872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        uint16_t glyphs[1];
5968872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        for (size_t i = start; i < end; i++) {
5978872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            glyphs[0] = layout.getGlyphId(i);
5988872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            float x = hOffset + layout.getX(i);
5998872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            float y = vOffset + layout.getY(i);
6008872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            canvas->drawTextOnPath(glyphs, 1, path, x, y, paint);
6018872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        }
6028872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
6038872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerprivate:
6048872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const Layout& layout;
6058872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    Canvas* canvas;
6068872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    float hOffset;
6078872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    float vOffset;
6086ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint& paint;
6098872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const SkPath& path;
6108872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger};
6118872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6128872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawTextOnPath(Canvas* canvas, const uint16_t* text, int count, int bidiFlags,
6138872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           const SkPath& path, float hOffset, float vOffset,
6146ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod                           const Paint& paint, TypefaceImpl* typeface) {
6156ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint paintCopy(paint);
6168872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    Layout layout;
61763c5c78a72a21d57913e8601cc2a1ab72a424a02Behdad Esfahbod    MinikinUtils::doLayout(&layout, &paintCopy, bidiFlags, typeface, text, 0, count, count);
6188872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    hOffset += MinikinUtils::hOffsetForTextAlign(&paintCopy, layout, path);
6198872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6208872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    // Set align to left for drawing, as we don't want individual
6218872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    // glyphs centered or right-aligned; the offset above takes
6228872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    // care of all alignment.
6236ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    paintCopy.setTextAlign(Paint::kLeft_Align);
6248872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6258872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    DrawTextOnPathFunctor f(layout, canvas, hOffset, vOffset, paintCopy, path);
6268872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    MinikinUtils::forFontRun(layout, &paintCopy, f);
6278872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
6288872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6298872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawTextOnPathChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text,
6308872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                jint index, jint count, jlong pathHandle, jfloat hOffset,
6318872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                jfloat vOffset, jint bidiFlags, jlong paintHandle,
6328872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                jlong typefaceHandle) {
6338872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
6346ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
6358872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
6368872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6378872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    jchar* jchars = env->GetCharArrayElements(text, NULL);
6388872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6398872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    drawTextOnPath(get_canvas(canvasHandle), jchars + index, count, bidiFlags, *path,
6408872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                   hOffset, vOffset, *paint, typeface);
6418872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6428872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    env->ReleaseCharArrayElements(text, jchars, 0);
6438872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
6448872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6458872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawTextOnPathString(JNIEnv* env, jobject, jlong canvasHandle, jstring text,
6468872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                 jlong pathHandle, jfloat hOffset, jfloat vOffset,
6478872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                 jint bidiFlags, jlong paintHandle, jlong typefaceHandle) {
6488872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
6496ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
6508872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
6518872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6528872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const jchar* jchars = env->GetStringChars(text, NULL);
6538872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    int count = env->GetStringLength(text);
6548872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6558872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    drawTextOnPath(get_canvas(canvasHandle), jchars, count, bidiFlags, *path,
6568872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                   hOffset, vOffset, *paint, typeface);
6578872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6588872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    env->ReleaseStringChars(text, jchars);
6598872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
6608872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6618872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void setDrawFilter(JNIEnv* env, jobject, jlong canvasHandle, jlong filterHandle) {
6628872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->setDrawFilter(reinterpret_cast<SkDrawFilter*>(filterHandle));
6638872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
6648872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6658872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void freeCaches(JNIEnv* env, jobject) {
6668872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkGraphics::PurgeFontCache();
6678872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
6688872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6698872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void freeTextLayoutCaches(JNIEnv* env, jobject) {
6708872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    Layout::purgeCaches();
6718872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
6728872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6738872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}; // namespace CanvasJNI
6748872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6758872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic JNINativeMethod gMethods[] = {
6768872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"finalizer", "(J)V", (void*) CanvasJNI::finalizer},
677c1b33d665c8caf5760f68c45c6ca0baa649b832aJohn Reck    {"initRaster", "(Landroid/graphics/Bitmap;)J", (void*) CanvasJNI::initRaster},
678c1b33d665c8caf5760f68c45c6ca0baa649b832aJohn Reck    {"native_setBitmap", "(JLandroid/graphics/Bitmap;)V", (void*) CanvasJNI::setBitmap},
6798872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_isOpaque","(J)Z", (void*) CanvasJNI::isOpaque},
6808872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_getWidth","(J)I", (void*) CanvasJNI::getWidth},
6818872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_getHeight","(J)I", (void*) CanvasJNI::getHeight},
6828872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_save","(JI)I", (void*) CanvasJNI::save},
6838872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_saveLayer","(JFFFFJI)I", (void*) CanvasJNI::saveLayer},
6848872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_saveLayerAlpha","(JFFFFII)I", (void*) CanvasJNI::saveLayerAlpha},
6858872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_getSaveCount","(J)I", (void*) CanvasJNI::getSaveCount},
6863891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik    {"native_restore","(JZ)V", (void*) CanvasJNI::restore},
6873891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik    {"native_restoreToCount","(JIZ)V", (void*) CanvasJNI::restoreToCount},
6888872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_getCTM", "(JJ)V", (void*)CanvasJNI::getCTM},
6898872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_setMatrix","(JJ)V", (void*) CanvasJNI::setMatrix},
6908872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_concat","(JJ)V", (void*) CanvasJNI::concat},
6918872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_rotate","(JF)V", (void*) CanvasJNI::rotate},
6928872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_scale","(JFF)V", (void*) CanvasJNI::scale},
6938872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_skew","(JFF)V", (void*) CanvasJNI::skew},
6948872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_translate","(JFF)V", (void*) CanvasJNI::translate},
6958872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_getClipBounds","(JLandroid/graphics/Rect;)Z", (void*) CanvasJNI::getClipBounds},
6968872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_quickReject","(JJ)Z", (void*) CanvasJNI::quickRejectPath},
6978872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_quickReject","(JFFFF)Z", (void*)CanvasJNI::quickRejectRect},
6988872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_clipRect","(JFFFFI)Z", (void*) CanvasJNI::clipRect},
6998872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_clipPath","(JJI)Z", (void*) CanvasJNI::clipPath},
7008872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_clipRegion","(JJI)Z", (void*) CanvasJNI::clipRegion},
7018872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawColor","(JII)V", (void*) CanvasJNI::drawColor},
7028872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawPaint","(JJ)V", (void*) CanvasJNI::drawPaint},
7038872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawPoint", "(JFFJ)V", (void*) CanvasJNI::drawPoint},
7048872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawPoints", "(J[FIIJ)V", (void*) CanvasJNI::drawPoints},
7058872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawLine", "(JFFFFJ)V", (void*) CanvasJNI::drawLine},
7068872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawLines", "(J[FIIJ)V", (void*) CanvasJNI::drawLines},
7078872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawRect","(JFFFFJ)V", (void*) CanvasJNI::drawRect},
70894394b3fb048d5349a77b57950ab7f6b6e92ce34Derek Sollenberger    {"native_drawRegion", "(JJJ)V", (void*) CanvasJNI::drawRegion },
7098872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawRoundRect","(JFFFFFFJ)V", (void*) CanvasJNI::drawRoundRect},
7108872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawCircle","(JFFFJ)V", (void*) CanvasJNI::drawCircle},
7118872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawOval","(JFFFFJ)V", (void*) CanvasJNI::drawOval},
7128872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawArc","(JFFFFFFZJ)V", (void*) CanvasJNI::drawArc},
7138872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawPath","(JJJ)V", (void*) CanvasJNI::drawPath},
7148872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"nativeDrawVertices", "(JII[FI[FI[II[SIIJ)V", (void*)CanvasJNI::drawVertices},
7157c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    {"native_drawBitmap","(JLandroid/graphics/Bitmap;FFJIII)V", (void*) CanvasJNI::drawBitmap},
7167c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    {"nativeDrawBitmapMatrix", "(JLandroid/graphics/Bitmap;JJ)V", (void*)CanvasJNI::drawBitmapMatrix},
7177c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    {"native_drawBitmap","(JLandroid/graphics/Bitmap;FFFFFFFFJII)V", (void*) CanvasJNI::drawBitmapRect},
7188872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawBitmap", "(J[IIIFFIIZJ)V", (void*)CanvasJNI::drawBitmapArray},
7197c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    {"nativeDrawBitmapMesh", "(JLandroid/graphics/Bitmap;II[FI[IIJ)V", (void*)CanvasJNI::drawBitmapMesh},
7208872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawText","(J[CIIFFIJJ)V", (void*) CanvasJNI::drawTextChars},
7218872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawText","(JLjava/lang/String;IIFFIJJ)V", (void*) CanvasJNI::drawTextString},
7228872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawTextRun","(J[CIIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunChars},
7238872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawTextRun","(JLjava/lang/String;IIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunString},
7248872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawTextOnPath","(J[CIIJFFIJJ)V", (void*) CanvasJNI::drawTextOnPathChars},
7258872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawTextOnPath","(JLjava/lang/String;JFFIJJ)V", (void*) CanvasJNI::drawTextOnPathString},
7268872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"nativeSetDrawFilter", "(JJ)V", (void*) CanvasJNI::setDrawFilter},
7278872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"freeCaches", "()V", (void*) CanvasJNI::freeCaches},
7288872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"freeTextLayoutCaches", "()V", (void*) CanvasJNI::freeTextLayoutCaches}
7298872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger};
7308872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
7318872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerint register_android_graphics_Canvas(JNIEnv* env) {
732ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    return RegisterMethodsOrDie(env, "android/graphics/Canvas", gMethods, NELEM(gMethods));
7338872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
7348872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
7358872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}; // namespace android
736