android_graphics_Canvas.cpp revision acb4099deff72c2c631f7110a405a3331d3e8b27
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"
198872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger#include <android_runtime/AndroidRuntime.h>
208872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
218872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger#include "Canvas.h"
22acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger#include "SkDrawFilter.h"
238872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger#include "SkGraphics.h"
248872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger#include "SkPorterDuff.h"
256ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod#include "Paint.h"
268872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger#include "TypefaceImpl.h"
278872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
288872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger#include <minikin/Layout.h>
298872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger#include "MinikinSkia.h"
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
408872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void finalizer(JNIEnv* env, jobject clazz, jlong canvasHandle) {
418872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    delete get_canvas(canvasHandle);
428872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
438872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
448872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger// Native wrapper constructor used by Canvas(Bitmap)
458872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jlong initRaster(JNIEnv* env, jobject, jlong bitmapHandle) {
468872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
478872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    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.
528872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void setBitmap(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle,
538872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                      jboolean copyState) {
548872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
558872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->setBitmap(bitmap, copyState);
568872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
578872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
588872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jboolean isOpaque(JNIEnv*, jobject, jlong canvasHandle) {
598872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return get_canvas(canvasHandle)->isOpaque() ? JNI_TRUE : JNI_FALSE;
608872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
618872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
628872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jint getWidth(JNIEnv*, jobject, jlong canvasHandle) {
638872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return static_cast<jint>(get_canvas(canvasHandle)->width());
648872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
658872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
668872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jint getHeight(JNIEnv*, jobject, jlong canvasHandle) {
678872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return static_cast<jint>(get_canvas(canvasHandle)->height());
688872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
698872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
708872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jint getSaveCount(JNIEnv*, jobject, jlong canvasHandle) {
718872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return static_cast<jint>(get_canvas(canvasHandle)->getSaveCount());
728872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
738872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
748872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jint save(JNIEnv*, jobject, jlong canvasHandle, jint flagsHandle) {
758872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
768872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return static_cast<jint>(get_canvas(canvasHandle)->save(flags));
778872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
788872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
798872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jint saveLayer(JNIEnv* env, jobject, jlong canvasHandle, jfloat l, jfloat t,
808872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                      jfloat r, jfloat b, jlong paintHandle, jint flagsHandle) {
816ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint  = reinterpret_cast<Paint*>(paintHandle);
828872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
838872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return static_cast<jint>(get_canvas(canvasHandle)->saveLayer(l, t, r, b, paint, flags));
848872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
858872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
868872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jint saveLayerAlpha(JNIEnv* env, jobject, jlong canvasHandle, jfloat l, jfloat t,
878872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           jfloat r, jfloat b, jint alpha, jint flagsHandle) {
888872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
898872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return static_cast<jint>(get_canvas(canvasHandle)->saveLayerAlpha(l, t, r, b, alpha, flags));
908872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
918872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
928872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void restore(JNIEnv* env, jobject, jlong canvasHandle) {
938872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    Canvas* canvas = get_canvas(canvasHandle);
948872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if (canvas->getSaveCount() <= 1) {  // cannot restore anymore
958872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        doThrowISE(env, "Underflow in restore");
968872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        return;
978872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
988872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    canvas->restore();
998872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1008872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1018872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void restoreToCount(JNIEnv* env, jobject, jlong canvasHandle, jint restoreCount) {
1028872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    Canvas* canvas = get_canvas(canvasHandle);
1038872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if (restoreCount < 1 || restoreCount > canvas->getSaveCount()) {
1048872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        doThrowIAE(env, "Underflow in restoreToCount");
1058872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        return;
1068872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
1078872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    canvas->restoreToCount(restoreCount);
1088872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1098872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1108872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void getCTM(JNIEnv* env, jobject, jlong canvasHandle, jlong matrixHandle) {
1118872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
1128872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->getMatrix(matrix);
1138872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1148872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1158872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void setMatrix(JNIEnv* env, jobject, jlong canvasHandle, jlong matrixHandle) {
1168872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
1178872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->setMatrix(matrix ? *matrix : SkMatrix::I());
1188872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1198872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1208872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void concat(JNIEnv* env, jobject, jlong canvasHandle, jlong matrixHandle) {
1218872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
1228872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->concat(*matrix);
1238872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1248872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1258872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void rotate(JNIEnv*, jobject, jlong canvasHandle, jfloat degrees) {
1268872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->rotate(degrees);
1278872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1288872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1298872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void scale(JNIEnv*, jobject, jlong canvasHandle, jfloat sx, jfloat sy) {
1308872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->scale(sx, sy);
1318872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1328872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1338872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void skew(JNIEnv*, jobject, jlong canvasHandle, jfloat sx, jfloat sy) {
1348872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->skew(sx, sy);
1358872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1368872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1378872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void translate(JNIEnv*, jobject, jlong canvasHandle, jfloat dx, jfloat dy) {
1388872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->translate(dx, dy);
1398872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1408872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1418872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jboolean getClipBounds(JNIEnv* env, jobject, jlong canvasHandle, jobject bounds) {
1428872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkRect   r;
1438872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkIRect ir;
1448872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    bool result = get_canvas(canvasHandle)->getClipBounds(&r);
1458872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1468872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if (!result) {
1478872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        r.setEmpty();
1488872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
1498872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    r.round(&ir);
1508872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1518872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    (void)GraphicsJNI::irect_to_jrect(ir, env, bounds);
1528872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return result ? JNI_TRUE : JNI_FALSE;
1538872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1548872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1558872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jboolean quickRejectRect(JNIEnv* env, jobject, jlong canvasHandle,
1568872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                jfloat left, jfloat top, jfloat right, jfloat bottom) {
1578872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    bool result = get_canvas(canvasHandle)->quickRejectRect(left, top, right, bottom);
1588872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return result ? JNI_TRUE : JNI_FALSE;
1598872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1608872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1618872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jboolean quickRejectPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle) {
1628872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
1638872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    bool result = get_canvas(canvasHandle)->quickRejectPath(*path);
1648872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return result ? JNI_TRUE : JNI_FALSE;
1658872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1668872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1678872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jboolean clipRect(JNIEnv*, jobject, jlong canvasHandle, jfloat l, jfloat t,
1688872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                         jfloat r, jfloat b, jint opHandle) {
1698872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkRegion::Op op = static_cast<SkRegion::Op>(opHandle);
1708872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    bool emptyClip = get_canvas(canvasHandle)->clipRect(l, t, r, b, op);
1718872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return emptyClip ? JNI_FALSE : JNI_TRUE;
1728872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1738872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1748872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jboolean clipPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle,
1758872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                         jint opHandle) {
1768872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
1778872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkRegion::Op op = static_cast<SkRegion::Op>(opHandle);
1788872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    bool emptyClip = get_canvas(canvasHandle)->clipPath(path, op);
1798872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return emptyClip ? JNI_FALSE : JNI_TRUE;
1808872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1818872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1828872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jboolean clipRegion(JNIEnv* env, jobject, jlong canvasHandle, jlong deviceRgnHandle,
1838872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           jint opHandle) {
1848872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkRegion* deviceRgn = reinterpret_cast<SkRegion*>(deviceRgnHandle);
1858872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkRegion::Op op = static_cast<SkRegion::Op>(opHandle);
1868872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    bool emptyClip = get_canvas(canvasHandle)->clipRegion(deviceRgn, op);
1878872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return emptyClip ? JNI_FALSE : JNI_TRUE;
1888872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1898872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1908872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawColor(JNIEnv* env, jobject, jlong canvasHandle, jint color, jint modeHandle) {
1918872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger     SkPorterDuff::Mode mode = static_cast<SkPorterDuff::Mode>(modeHandle);
1928872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger     get_canvas(canvasHandle)->drawColor(color, SkPorterDuff::ToXfermodeMode(mode));
1938872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1948872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1958872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawPaint(JNIEnv* env, jobject, jlong canvasHandle, jlong paintHandle) {
1966ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
1978872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawPaint(*paint);
1988872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1998872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2008872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawPoint(JNIEnv*, jobject, jlong canvasHandle, jfloat x, jfloat y,
2018872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                      jlong paintHandle) {
2026ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2038872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawPoint(x, y, *paint);
2048872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2058872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2068872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawPoints(JNIEnv* env, jobject, jlong canvasHandle, jfloatArray jptsArray,
2078872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                       jint offset, jint count, jlong paintHandle) {
2088872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    NPE_CHECK_RETURN_VOID(env, jptsArray);
2098872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    AutoJavaFloatArray autoPts(env, jptsArray);
2108872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    float* floats = autoPts.ptr();
2118872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const int length = autoPts.length();
2128872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2138872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if ((offset | count) < 0 || offset + count > length) {
2148872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        doThrowAIOOBE(env);
2158872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        return;
2168872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
2178872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2186ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2198872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawPoints(floats + offset, count, *paint);
2208872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2218872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2228872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawLine(JNIEnv* env, jobject, jlong canvasHandle, jfloat startX, jfloat startY,
2238872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                     jfloat stopX, jfloat stopY, jlong paintHandle) {
2246ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2258872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawLine(startX, startY, stopX, stopY, *paint);
2268872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2278872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2288872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawLines(JNIEnv* env, jobject, jlong canvasHandle, jfloatArray jptsArray,
2298872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                      jint offset, jint count, jlong paintHandle) {
2308872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    NPE_CHECK_RETURN_VOID(env, jptsArray);
2318872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    AutoJavaFloatArray autoPts(env, jptsArray);
2328872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    float* floats = autoPts.ptr();
2338872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const int length = autoPts.length();
2348872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2358872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if ((offset | count) < 0 || offset + count > length) {
2368872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        doThrowAIOOBE(env);
2378872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        return;
2388872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
2398872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2406ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2418872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawLines(floats + offset, count, *paint);
2428872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2438872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2448872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawRect(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
2458872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                     jfloat right, jfloat bottom, jlong paintHandle) {
2466ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2478872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawRect(left, top, right, bottom, *paint);
2488872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2498872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2508872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawRoundRect(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
2518872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                          jfloat right, jfloat bottom, jfloat rx, jfloat ry, jlong paintHandle) {
2526ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2538872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawRoundRect(left, top, right, bottom, rx, ry, *paint);
2548872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2558872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2568872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawCircle(JNIEnv* env, jobject, jlong canvasHandle, jfloat cx, jfloat cy,
2578872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                       jfloat radius, jlong paintHandle) {
2586ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2598872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawCircle(cx, cy, radius, *paint);
2608872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2618872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2628872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawOval(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
2638872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                     jfloat right, jfloat bottom, jlong paintHandle) {
2646ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2658872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawOval(left, top, right, bottom, *paint);
2668872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2678872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2688872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawArc(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
2698872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                    jfloat right, jfloat bottom, jfloat startAngle, jfloat sweepAngle,
2708872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                    jboolean useCenter, jlong paintHandle) {
2716ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2728872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawArc(left, top, right, bottom, startAngle, sweepAngle,
2738872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                       useCenter, *paint);
2748872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2758872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2768872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle,
2778872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                     jlong paintHandle) {
2788872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
2796ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2808872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawPath(*path, *paint);
2818872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2828872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2838872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawVertices(JNIEnv* env, jobject, jlong canvasHandle,
2848872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                         jint modeHandle, jint vertexCount,
2858872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                         jfloatArray jverts, jint vertIndex,
2868872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                         jfloatArray jtexs, jint texIndex,
2878872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                         jintArray jcolors, jint colorIndex,
2888872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                         jshortArray jindices, jint indexIndex,
2898872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                         jint indexCount, jlong paintHandle) {
2908872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    AutoJavaFloatArray  vertA(env, jverts, vertIndex + vertexCount);
2918872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    AutoJavaFloatArray  texA(env, jtexs, texIndex + vertexCount);
2928872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    AutoJavaIntArray    colorA(env, jcolors, colorIndex + vertexCount);
2938872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    AutoJavaShortArray  indexA(env, jindices, indexIndex + indexCount);
2948872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2958872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const float* verts = vertA.ptr() + vertIndex;
2968872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const float* texs = texA.ptr() + vertIndex;
2978872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const int* colors = NULL;
2988872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const uint16_t* indices = NULL;
2998872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3008872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if (jcolors != NULL) {
3018872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        colors = colorA.ptr() + colorIndex;
3028872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
3038872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if (jindices != NULL) {
3048872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        indices = (const uint16_t*)(indexA.ptr() + indexIndex);
3058872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
3068872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3078872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkCanvas::VertexMode mode = static_cast<SkCanvas::VertexMode>(modeHandle);
3086ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
3098872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawVertices(mode, vertexCount, verts, texs, colors,
3108872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                           indices, indexCount, *paint);
3118872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
3128872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3138872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawBitmap(JNIEnv* env, jobject jcanvas, jlong canvasHandle, jlong bitmapHandle,
3148872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                       jfloat left, jfloat top, jlong paintHandle, jint canvasDensity,
3158872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                       jint screenDensity, jint bitmapDensity) {
3168872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    Canvas* canvas = get_canvas(canvasHandle);
3178872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
3186ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
3198872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3208872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if (canvasDensity == bitmapDensity || canvasDensity == 0 || bitmapDensity == 0) {
3218872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        if (screenDensity != 0 && screenDensity != bitmapDensity) {
3226ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod            Paint filteredPaint;
3238872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            if (paint) {
3248872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                filteredPaint = *paint;
3258872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            }
3266ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod            filteredPaint.setFilterLevel(Paint::kLow_FilterLevel);
3278872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            canvas->drawBitmap(*bitmap, left, top, &filteredPaint);
3288872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        } else {
3298872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            canvas->drawBitmap(*bitmap, left, top, paint);
3308872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        }
3318872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    } else {
3328872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        canvas->save(SkCanvas::kMatrixClip_SaveFlag);
3338872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        SkScalar scale = canvasDensity / (float)bitmapDensity;
3348872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        canvas->translate(left, top);
3358872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        canvas->scale(scale, scale);
3368872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3376ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod        Paint filteredPaint;
3388872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        if (paint) {
3398872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            filteredPaint = *paint;
3408872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        }
3416ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod        filteredPaint.setFilterLevel(Paint::kLow_FilterLevel);
3428872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3438872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        canvas->drawBitmap(*bitmap, 0, 0, &filteredPaint);
3448872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        canvas->restore();
3458872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
3468872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
3478872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3488872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawBitmapMatrix(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle,
3498872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                             jlong matrixHandle, jlong paintHandle) {
3508872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
3518872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
3526ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
3538872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawBitmap(*bitmap, *matrix, paint);
3548872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
3558872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3568872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawBitmapRect(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle,
3578872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           float srcLeft, float srcTop, float srcRight, float srcBottom,
3588872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           float dstLeft, float dstTop, float dstRight, float dstBottom,
3598872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           jlong paintHandle, jint screenDensity, jint bitmapDensity) {
3608872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    Canvas* canvas = get_canvas(canvasHandle);
3618872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
3626ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
3638872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3648872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if (screenDensity != 0 && screenDensity != bitmapDensity) {
3656ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod        Paint filteredPaint;
3668872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        if (paint) {
3678872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            filteredPaint = *paint;
3688872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        }
3696ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod        filteredPaint.setFilterLevel(Paint::kLow_FilterLevel);
3708872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        canvas->drawBitmap(*bitmap, srcLeft, srcTop, srcRight, srcBottom,
3718872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           dstLeft, dstTop, dstRight, dstBottom, &filteredPaint);
3728872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    } else {
3738872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        canvas->drawBitmap(*bitmap, srcLeft, srcTop, srcRight, srcBottom,
3748872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           dstLeft, dstTop, dstRight, dstBottom, paint);
3758872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
3768872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
3778872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3788872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawBitmapArray(JNIEnv* env, jobject, jlong canvasHandle,
3798872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                            jintArray jcolors, jint offset, jint stride,
3808872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                            jfloat x, jfloat y, jint width, jint height,
3818872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                            jboolean hasAlpha, jlong paintHandle) {
3828872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    // Note: If hasAlpha is false, kRGB_565_SkColorType will be used, which will
3838872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    // correct the alphaType to kOpaque_SkAlphaType.
3848872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkImageInfo info = SkImageInfo::Make(width, height,
3858872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           hasAlpha ? kN32_SkColorType : kRGB_565_SkColorType,
3868872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           kPremul_SkAlphaType);
3878872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkBitmap bitmap;
3888872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if (!bitmap.allocPixels(info)) {
3898872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        return;
3908872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
3918872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3928872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if (!GraphicsJNI::SetPixels(env, jcolors, offset, stride, 0, 0, width, height, bitmap)) {
3938872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        return;
3948872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
3958872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3966ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
3978872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawBitmap(bitmap, x, y, paint);
3988872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
3998872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
4008872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawBitmapMesh(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle,
4018872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           jint meshWidth, jint meshHeight, jfloatArray jverts,
4028872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           jint vertIndex, jintArray jcolors, jint colorIndex, jlong paintHandle) {
4038872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const int ptCount = (meshWidth + 1) * (meshHeight + 1);
4048872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    AutoJavaFloatArray vertA(env, jverts, vertIndex + (ptCount << 1));
4058872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    AutoJavaIntArray colorA(env, jcolors, colorIndex + ptCount);
4068872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
4078872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
4086ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
4098872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawBitmapMesh(*bitmap, meshWidth, meshHeight,
4108872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                             vertA.ptr(), colorA.ptr(), paint);
4118872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
4128872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
413acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenbergerclass DrawTextFunctor {
414acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenbergerpublic:
415acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    DrawTextFunctor(const Layout& layout, Canvas* canvas, uint16_t* glyphs, float* pos,
416acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger                    const SkPaint& paint, float x, float y, MinikinRect& bounds)
417acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            : layout(layout), canvas(canvas), glyphs(glyphs), pos(pos), paint(paint),
418acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger              x(x), y(y), bounds(bounds) { }
419acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
420acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    void operator()(size_t start, size_t end) {
421acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        if (canvas->drawTextAbsolutePos()) {
422acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            for (size_t i = start; i < end; i++) {
423acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger                glyphs[i] = layout.getGlyphId(i);
424acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger                pos[2 * i] = x + layout.getX(i);
425acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger                pos[2 * i + 1] = y + layout.getY(i);
426acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            }
427acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        } else {
428acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            for (size_t i = start; i < end; i++) {
429acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger                glyphs[i] = layout.getGlyphId(i);
430acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger                pos[2 * i] = layout.getX(i);
431acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger                pos[2 * i + 1] = layout.getY(i);
432acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            }
433acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        }
434acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
435acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        size_t glyphCount = end - start;
436acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        canvas->drawText(glyphs + start, pos + (2 * start), glyphCount, paint, x, y,
437acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger                         bounds.mLeft , bounds.mTop , bounds.mRight , bounds.mBottom);
438acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    }
439acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenbergerprivate:
440acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    const Layout& layout;
441acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    Canvas* canvas;
442acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    uint16_t* glyphs;
443acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    float* pos;
444acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    const SkPaint& paint;
445acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    float x;
446acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    float y;
447acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    MinikinRect& bounds;
448acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger};
449acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
450acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger// Same values used by Skia
451acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger#define kStdStrikeThru_Offset   (-6.0f / 21.0f)
452acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger#define kStdUnderline_Offset    (1.0f / 9.0f)
453acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger#define kStdUnderline_Thickness (1.0f / 18.0f)
454acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
455acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenbergervoid drawTextDecorations(Canvas* canvas, float x, float y, float length, const SkPaint& paint) {
456acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    uint32_t flags;
457acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    SkDrawFilter* drawFilter = canvas->getDrawFilter();
458acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    if (drawFilter) {
459acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        SkPaint paintCopy(paint);
460acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        drawFilter->filter(&paintCopy, SkDrawFilter::kText_Type);
461acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        flags = paintCopy.getFlags();
462acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    } else {
463acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        flags = paint.getFlags();
464acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    }
465acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    if (flags & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag)) {
466acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        SkScalar left = x;
467acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        SkScalar right = x + length;
468acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        float textSize = paint.getTextSize();
469acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        float strokeWidth = fmax(textSize * kStdUnderline_Thickness, 1.0f);
470acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        if (flags & SkPaint::kUnderlineText_Flag) {
471acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            SkScalar top = y + textSize * kStdUnderline_Offset - 0.5f * strokeWidth;
472acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            SkScalar bottom = y + textSize * kStdUnderline_Offset + 0.5f * strokeWidth;
473acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            canvas->drawRect(left, top, right, bottom, paint);
474acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        }
475acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        if (flags & SkPaint::kStrikeThruText_Flag) {
476acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            SkScalar top = y + textSize * kStdStrikeThru_Offset - 0.5f * strokeWidth;
477acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            SkScalar bottom = y + textSize * kStdStrikeThru_Offset + 0.5f * strokeWidth;
478acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            canvas->drawRect(left, top, right, bottom, paint);
479acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        }
480acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    }
481acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger}
482acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
483acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenbergervoid drawText(Canvas* canvas, const uint16_t* text, int start, int count, int contextCount,
484acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger             float x, float y, int bidiFlags, const Paint& origPaint, TypefaceImpl* typeface) {
485acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    // minikin may modify the original paint
486acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    Paint paint(origPaint);
487acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
488acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    Layout layout;
489acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    std::string css = MinikinUtils::setLayoutProperties(&layout, &paint, bidiFlags, typeface);
490acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    layout.doLayout(text, start, count, contextCount, css);
491acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
492acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    size_t nGlyphs = layout.nGlyphs();
493acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    uint16_t* glyphs = new uint16_t[nGlyphs];
494acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    float* pos = new float[nGlyphs * 2];
495acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
496acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    x += MinikinUtils::xOffsetForTextAlign(&paint, layout);
497acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
498acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    MinikinRect bounds;
499acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    layout.getBounds(&bounds);
500acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
501acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    DrawTextFunctor f(layout, canvas, glyphs, pos, paint, x, y, bounds);
502acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    MinikinUtils::forFontRun(layout, &paint, f);
503acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
504acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    drawTextDecorations(canvas, x, y, layout.getAdvance(), paint);
505acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
506acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    delete[] glyphs;
507acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    delete[] pos;
508acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger}
509acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
5108872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawTextChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text,
5118872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                          jint index, jint count, jfloat x, jfloat y, jint bidiFlags,
5128872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                          jlong paintHandle, jlong typefaceHandle) {
5136ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
5148872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
5158872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    jchar* jchars = env->GetCharArrayElements(text, NULL);
516acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    drawText(get_canvas(canvasHandle), jchars + index, 0, count, count, x, y,
5178872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                       bidiFlags, *paint, typeface);
5188872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    env->ReleaseCharArrayElements(text, jchars, JNI_ABORT);
5198872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
5208872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
5218872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawTextString(JNIEnv* env, jobject, jlong canvasHandle, jstring text,
5228872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           jint start, jint end, jfloat x, jfloat y, jint bidiFlags,
5238872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           jlong paintHandle, jlong typefaceHandle) {
5246ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
5258872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
5268872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const int count = end - start;
5278872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const jchar* jchars = env->GetStringChars(text, NULL);
528acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    drawText(get_canvas(canvasHandle), jchars + start, 0, count, count, x, y,
5298872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                       bidiFlags, *paint, typeface);
5308872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    env->ReleaseStringChars(text, jchars);
5318872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
5328872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
5338872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawTextRunChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text, jint index,
5348872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                             jint count, jint contextIndex, jint contextCount, jfloat x, jfloat y,
5358872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                             jboolean isRtl, jlong paintHandle, jlong typefaceHandle) {
5366ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
5378872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
5388872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
5398872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
5408872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    jchar* jchars = env->GetCharArrayElements(text, NULL);
541acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    drawText(get_canvas(canvasHandle), jchars + contextIndex, index - contextIndex, count,
5428872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                       contextCount, x, y, bidiFlags, *paint, typeface);
5438872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    env->ReleaseCharArrayElements(text, jchars, JNI_ABORT);
5448872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
5458872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
5468872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawTextRunString(JNIEnv* env, jobject obj, jlong canvasHandle, jstring text,
5478872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                              jint start, jint end, jint contextStart, jint contextEnd,
5488872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                              jfloat x, jfloat y, jboolean isRtl, jlong paintHandle,
5498872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                              jlong typefaceHandle) {
5506ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
5518872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
5528872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
5538872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
5548872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    jint count = end - start;
5558872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    jint contextCount = contextEnd - contextStart;
5568872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const jchar* jchars = env->GetStringChars(text, NULL);
557acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    drawText(get_canvas(canvasHandle), jchars + contextStart, start - contextStart, count,
5588872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                       contextCount, x, y, bidiFlags, *paint, typeface);
5598872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    env->ReleaseStringChars(text, jchars);
5608872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
5618872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
5628872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawPosTextChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text,
5638872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                             jint index, jint count, jfloatArray pos, jlong paintHandle) {
5646ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
5658872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    jchar* jchars = text ? env->GetCharArrayElements(text, NULL) : NULL;
5668872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    float* posArray = pos ? env->GetFloatArrayElements(pos, NULL) : NULL;
5678872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    int posCount = pos ? env->GetArrayLength(pos) >> 1: 0;
5688872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
5698872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawPosText(jchars + index, posArray, count << 1, posCount, *paint);
5708872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
5718872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if (text) {
5728872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        env->ReleaseCharArrayElements(text, jchars, 0);
5738872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
5748872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if (pos) {
5758872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        env->ReleaseFloatArrayElements(pos, posArray, 0);
5768872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
5778872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
5788872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
5798872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
5808872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawPosTextString(JNIEnv* env, jobject, jlong canvasHandle, jstring text,
5818872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                              jfloatArray pos, jlong paintHandle) {
5826ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
5838872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const jchar* jchars = text ? env->GetStringChars(text, NULL) : NULL;
5848872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    int byteLength = text ? env->GetStringLength(text) : 0;
5858872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    float* posArray = pos ? env->GetFloatArrayElements(pos, NULL) : NULL;
5868872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    int posCount = pos ? env->GetArrayLength(pos) >> 1: 0;
5878872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
5888872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawPosText(jchars , posArray, byteLength << 1, posCount, *paint);
5898872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
5908872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if (text) {
5918872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        env->ReleaseStringChars(text, jchars);
5928872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
5938872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if (pos) {
5948872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        env->ReleaseFloatArrayElements(pos, posArray, 0);
5958872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
5968872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
5978872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
5988872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerclass DrawTextOnPathFunctor {
5998872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerpublic:
6008872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    DrawTextOnPathFunctor(const Layout& layout, Canvas* canvas, float hOffset,
6016ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod                float vOffset, const Paint& paint, const SkPath& path)
6028872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            : layout(layout), canvas(canvas), hOffset(hOffset), vOffset(vOffset),
6038872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                paint(paint), path(path) {
6048872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
6058872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    void operator()(size_t start, size_t end) {
6068872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        uint16_t glyphs[1];
6078872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        for (size_t i = start; i < end; i++) {
6088872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            glyphs[0] = layout.getGlyphId(i);
6098872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            float x = hOffset + layout.getX(i);
6108872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            float y = vOffset + layout.getY(i);
6118872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            canvas->drawTextOnPath(glyphs, 1, path, x, y, paint);
6128872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        }
6138872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
6148872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerprivate:
6158872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const Layout& layout;
6168872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    Canvas* canvas;
6178872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    float hOffset;
6188872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    float vOffset;
6196ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint& paint;
6208872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const SkPath& path;
6218872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger};
6228872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6238872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawTextOnPath(Canvas* canvas, const uint16_t* text, int count, int bidiFlags,
6248872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           const SkPath& path, float hOffset, float vOffset,
6256ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod                           const Paint& paint, TypefaceImpl* typeface) {
6266ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint paintCopy(paint);
6278872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    Layout layout;
6288872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    std::string css = MinikinUtils::setLayoutProperties(&layout, &paintCopy, bidiFlags, typeface);
6298872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    layout.doLayout(text, 0, count, count, css);
6308872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    hOffset += MinikinUtils::hOffsetForTextAlign(&paintCopy, layout, path);
6318872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6328872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    // Set align to left for drawing, as we don't want individual
6338872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    // glyphs centered or right-aligned; the offset above takes
6348872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    // care of all alignment.
6356ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    paintCopy.setTextAlign(Paint::kLeft_Align);
6368872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6378872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    DrawTextOnPathFunctor f(layout, canvas, hOffset, vOffset, paintCopy, path);
6388872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    MinikinUtils::forFontRun(layout, &paintCopy, f);
6398872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
6408872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6418872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawTextOnPathChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text,
6428872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                jint index, jint count, jlong pathHandle, jfloat hOffset,
6438872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                jfloat vOffset, jint bidiFlags, jlong paintHandle,
6448872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                jlong typefaceHandle) {
6458872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
6466ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
6478872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
6488872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6498872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    jchar* jchars = env->GetCharArrayElements(text, NULL);
6508872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6518872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    drawTextOnPath(get_canvas(canvasHandle), jchars + index, count, bidiFlags, *path,
6528872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                   hOffset, vOffset, *paint, typeface);
6538872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6548872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    env->ReleaseCharArrayElements(text, jchars, 0);
6558872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
6568872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6578872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawTextOnPathString(JNIEnv* env, jobject, jlong canvasHandle, jstring text,
6588872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                 jlong pathHandle, jfloat hOffset, jfloat vOffset,
6598872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                 jint bidiFlags, jlong paintHandle, jlong typefaceHandle) {
6608872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
6616ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
6628872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
6638872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6648872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const jchar* jchars = env->GetStringChars(text, NULL);
6658872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    int count = env->GetStringLength(text);
6668872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6678872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    drawTextOnPath(get_canvas(canvasHandle), jchars, count, bidiFlags, *path,
6688872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                   hOffset, vOffset, *paint, typeface);
6698872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6708872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    env->ReleaseStringChars(text, jchars);
6718872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
6728872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6738872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void setDrawFilter(JNIEnv* env, jobject, jlong canvasHandle, jlong filterHandle) {
6748872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->setDrawFilter(reinterpret_cast<SkDrawFilter*>(filterHandle));
6758872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
6768872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6778872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void freeCaches(JNIEnv* env, jobject) {
6788872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkGraphics::PurgeFontCache();
6798872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
6808872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6818872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void freeTextLayoutCaches(JNIEnv* env, jobject) {
6828872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    Layout::purgeCaches();
6838872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
6848872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6858872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}; // namespace CanvasJNI
6868872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6878872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic JNINativeMethod gMethods[] = {
6888872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"finalizer", "(J)V", (void*) CanvasJNI::finalizer},
6898872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"initRaster", "(J)J", (void*) CanvasJNI::initRaster},
6908872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_setBitmap", "(JJZ)V", (void*) CanvasJNI::setBitmap},
6918872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_isOpaque","(J)Z", (void*) CanvasJNI::isOpaque},
6928872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_getWidth","(J)I", (void*) CanvasJNI::getWidth},
6938872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_getHeight","(J)I", (void*) CanvasJNI::getHeight},
6948872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_save","(JI)I", (void*) CanvasJNI::save},
6958872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_saveLayer","(JFFFFJI)I", (void*) CanvasJNI::saveLayer},
6968872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_saveLayerAlpha","(JFFFFII)I", (void*) CanvasJNI::saveLayerAlpha},
6978872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_getSaveCount","(J)I", (void*) CanvasJNI::getSaveCount},
6988872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_restore","(J)V", (void*) CanvasJNI::restore},
6998872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_restoreToCount","(JI)V", (void*) CanvasJNI::restoreToCount},
7008872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_getCTM", "(JJ)V", (void*)CanvasJNI::getCTM},
7018872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_setMatrix","(JJ)V", (void*) CanvasJNI::setMatrix},
7028872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_concat","(JJ)V", (void*) CanvasJNI::concat},
7038872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_rotate","(JF)V", (void*) CanvasJNI::rotate},
7048872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_scale","(JFF)V", (void*) CanvasJNI::scale},
7058872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_skew","(JFF)V", (void*) CanvasJNI::skew},
7068872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_translate","(JFF)V", (void*) CanvasJNI::translate},
7078872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_getClipBounds","(JLandroid/graphics/Rect;)Z", (void*) CanvasJNI::getClipBounds},
7088872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_quickReject","(JJ)Z", (void*) CanvasJNI::quickRejectPath},
7098872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_quickReject","(JFFFF)Z", (void*)CanvasJNI::quickRejectRect},
7108872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_clipRect","(JFFFFI)Z", (void*) CanvasJNI::clipRect},
7118872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_clipPath","(JJI)Z", (void*) CanvasJNI::clipPath},
7128872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_clipRegion","(JJI)Z", (void*) CanvasJNI::clipRegion},
7138872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawColor","(JII)V", (void*) CanvasJNI::drawColor},
7148872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawPaint","(JJ)V", (void*) CanvasJNI::drawPaint},
7158872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawPoint", "(JFFJ)V", (void*) CanvasJNI::drawPoint},
7168872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawPoints", "(J[FIIJ)V", (void*) CanvasJNI::drawPoints},
7178872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawLine", "(JFFFFJ)V", (void*) CanvasJNI::drawLine},
7188872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawLines", "(J[FIIJ)V", (void*) CanvasJNI::drawLines},
7198872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawRect","(JFFFFJ)V", (void*) CanvasJNI::drawRect},
7208872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawRoundRect","(JFFFFFFJ)V", (void*) CanvasJNI::drawRoundRect},
7218872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawCircle","(JFFFJ)V", (void*) CanvasJNI::drawCircle},
7228872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawOval","(JFFFFJ)V", (void*) CanvasJNI::drawOval},
7238872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawArc","(JFFFFFFZJ)V", (void*) CanvasJNI::drawArc},
7248872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawPath","(JJJ)V", (void*) CanvasJNI::drawPath},
7258872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"nativeDrawVertices", "(JII[FI[FI[II[SIIJ)V", (void*)CanvasJNI::drawVertices},
7268872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawBitmap","(JJFFJIII)V", (void*) CanvasJNI::drawBitmap},
7278872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"nativeDrawBitmapMatrix", "(JJJJ)V", (void*)CanvasJNI::drawBitmapMatrix},
7288872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawBitmap","(JJFFFFFFFFJII)V", (void*) CanvasJNI::drawBitmapRect},
7298872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawBitmap", "(J[IIIFFIIZJ)V", (void*)CanvasJNI::drawBitmapArray},
7308872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"nativeDrawBitmapMesh", "(JJII[FI[IIJ)V", (void*)CanvasJNI::drawBitmapMesh},
7318872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawText","(J[CIIFFIJJ)V", (void*) CanvasJNI::drawTextChars},
7328872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawText","(JLjava/lang/String;IIFFIJJ)V", (void*) CanvasJNI::drawTextString},
7338872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawTextRun","(J[CIIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunChars},
7348872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawTextRun","(JLjava/lang/String;IIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunString},
7358872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawTextOnPath","(J[CIIJFFIJJ)V", (void*) CanvasJNI::drawTextOnPathChars},
7368872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawTextOnPath","(JLjava/lang/String;JFFIJJ)V", (void*) CanvasJNI::drawTextOnPathString},
7378872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"nativeSetDrawFilter", "(JJ)V", (void*) CanvasJNI::setDrawFilter},
7388872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"freeCaches", "()V", (void*) CanvasJNI::freeCaches},
7398872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"freeTextLayoutCaches", "()V", (void*) CanvasJNI::freeTextLayoutCaches}
7408872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger};
7418872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
7428872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerint register_android_graphics_Canvas(JNIEnv* env) {
7438872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return AndroidRuntime::registerNativeMethods(env, "android/graphics/Canvas", gMethods, NELEM(gMethods));
7448872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
7458872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
7468872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}; // namespace android
747