android_graphics_Canvas.cpp revision 6578a989566e585eee053095dc80e2552e125db2
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
726578a989566e585eee053095dc80e2552e125db2Derek Sollenbergerstatic void setHighContrastText(JNIEnv*, jobject, jlong canvasHandle, jboolean highContrastText) {
736578a989566e585eee053095dc80e2552e125db2Derek Sollenberger    Canvas* canvas = get_canvas(canvasHandle);
746578a989566e585eee053095dc80e2552e125db2Derek Sollenberger    canvas->setHighContrastText(highContrastText);
756578a989566e585eee053095dc80e2552e125db2Derek Sollenberger}
766578a989566e585eee053095dc80e2552e125db2Derek Sollenberger
778872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jint getSaveCount(JNIEnv*, jobject, jlong canvasHandle) {
788872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return static_cast<jint>(get_canvas(canvasHandle)->getSaveCount());
798872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
808872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
818872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jint save(JNIEnv*, jobject, jlong canvasHandle, jint flagsHandle) {
828872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
838872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return static_cast<jint>(get_canvas(canvasHandle)->save(flags));
848872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
858872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
868872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jint saveLayer(JNIEnv* env, jobject, jlong canvasHandle, jfloat l, jfloat t,
878872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                      jfloat r, jfloat b, jlong paintHandle, jint flagsHandle) {
886ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint  = reinterpret_cast<Paint*>(paintHandle);
898872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
908872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return static_cast<jint>(get_canvas(canvasHandle)->saveLayer(l, t, r, b, paint, flags));
918872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
928872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
938872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jint saveLayerAlpha(JNIEnv* env, jobject, jlong canvasHandle, jfloat l, jfloat t,
948872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           jfloat r, jfloat b, jint alpha, jint flagsHandle) {
958872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
968872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return static_cast<jint>(get_canvas(canvasHandle)->saveLayerAlpha(l, t, r, b, alpha, flags));
978872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
988872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
993891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craikstatic void restore(JNIEnv* env, jobject, jlong canvasHandle, jboolean throwOnUnderflow) {
1008872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    Canvas* canvas = get_canvas(canvasHandle);
1018872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if (canvas->getSaveCount() <= 1) {  // cannot restore anymore
1023891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik        if (throwOnUnderflow) {
1033891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik            doThrowISE(env, "Underflow in restore - more restores than saves");
1043891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik        }
1053891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik        return; // compat behavior - return without throwing
1068872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
1078872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    canvas->restore();
1088872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1098872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1103891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craikstatic void restoreToCount(JNIEnv* env, jobject, jlong canvasHandle, jint restoreCount,
1113891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik        jboolean throwOnUnderflow) {
1128872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    Canvas* canvas = get_canvas(canvasHandle);
1138872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if (restoreCount < 1 || restoreCount > canvas->getSaveCount()) {
1143891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik        if (throwOnUnderflow) {
1153891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik            doThrowIAE(env, "Underflow in restoreToCount - more restores than saves");
1163891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik            return;
1173891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik        }
1183891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik        restoreCount = 1; // compat behavior - restore as far as possible
1198872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
1208872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    canvas->restoreToCount(restoreCount);
1218872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1228872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1238872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void getCTM(JNIEnv* env, jobject, jlong canvasHandle, jlong matrixHandle) {
1248872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
1258872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->getMatrix(matrix);
1268872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1278872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1288872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void setMatrix(JNIEnv* env, jobject, jlong canvasHandle, jlong matrixHandle) {
1298872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
1308872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->setMatrix(matrix ? *matrix : SkMatrix::I());
1318872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1328872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1338872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void concat(JNIEnv* env, jobject, jlong canvasHandle, jlong matrixHandle) {
1348872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
1358872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->concat(*matrix);
1368872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1378872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1388872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void rotate(JNIEnv*, jobject, jlong canvasHandle, jfloat degrees) {
1398872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->rotate(degrees);
1408872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1418872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1428872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void scale(JNIEnv*, jobject, jlong canvasHandle, jfloat sx, jfloat sy) {
1438872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->scale(sx, sy);
1448872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1458872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1468872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void skew(JNIEnv*, jobject, jlong canvasHandle, jfloat sx, jfloat sy) {
1478872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->skew(sx, sy);
1488872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1498872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1508872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void translate(JNIEnv*, jobject, jlong canvasHandle, jfloat dx, jfloat dy) {
1518872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->translate(dx, dy);
1528872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1538872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1548872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jboolean getClipBounds(JNIEnv* env, jobject, jlong canvasHandle, jobject bounds) {
1558872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkRect   r;
1568872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkIRect ir;
1578872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    bool result = get_canvas(canvasHandle)->getClipBounds(&r);
1588872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1598872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if (!result) {
1608872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        r.setEmpty();
1618872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
1628872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    r.round(&ir);
1638872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1648872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    (void)GraphicsJNI::irect_to_jrect(ir, env, bounds);
1658872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return result ? JNI_TRUE : JNI_FALSE;
1668872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1678872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1688872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jboolean quickRejectRect(JNIEnv* env, jobject, jlong canvasHandle,
1698872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                jfloat left, jfloat top, jfloat right, jfloat bottom) {
1708872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    bool result = get_canvas(canvasHandle)->quickRejectRect(left, top, right, bottom);
1718872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return result ? JNI_TRUE : JNI_FALSE;
1728872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1738872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1748872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jboolean quickRejectPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle) {
1758872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
1768872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    bool result = get_canvas(canvasHandle)->quickRejectPath(*path);
1778872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return result ? JNI_TRUE : JNI_FALSE;
1788872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1798872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1808872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jboolean clipRect(JNIEnv*, jobject, jlong canvasHandle, jfloat l, jfloat t,
1818872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                         jfloat r, jfloat b, jint opHandle) {
1828872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkRegion::Op op = static_cast<SkRegion::Op>(opHandle);
1835ec6a2878b2ad933c5da6fe2341c854155acc24cChris Craik    bool nonEmptyClip = get_canvas(canvasHandle)->clipRect(l, t, r, b, op);
1845ec6a2878b2ad933c5da6fe2341c854155acc24cChris Craik    return nonEmptyClip ? JNI_TRUE : JNI_FALSE;
1858872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1868872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1878872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jboolean clipPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle,
1888872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                         jint opHandle) {
1898872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
1908872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkRegion::Op op = static_cast<SkRegion::Op>(opHandle);
1915ec6a2878b2ad933c5da6fe2341c854155acc24cChris Craik    bool nonEmptyClip = get_canvas(canvasHandle)->clipPath(path, op);
1925ec6a2878b2ad933c5da6fe2341c854155acc24cChris Craik    return nonEmptyClip ? JNI_TRUE : JNI_FALSE;
1938872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1948872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1958872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jboolean clipRegion(JNIEnv* env, jobject, jlong canvasHandle, jlong deviceRgnHandle,
1968872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           jint opHandle) {
1978872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkRegion* deviceRgn = reinterpret_cast<SkRegion*>(deviceRgnHandle);
1988872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkRegion::Op op = static_cast<SkRegion::Op>(opHandle);
1995ec6a2878b2ad933c5da6fe2341c854155acc24cChris Craik    bool nonEmptyClip = get_canvas(canvasHandle)->clipRegion(deviceRgn, op);
2005ec6a2878b2ad933c5da6fe2341c854155acc24cChris Craik    return nonEmptyClip ? JNI_TRUE : JNI_FALSE;
2018872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2028872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2038872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawColor(JNIEnv* env, jobject, jlong canvasHandle, jint color, jint modeHandle) {
2041526a458a30184609f19b05e7334da3cbde81dd1Chris Craik    SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(modeHandle);
2051526a458a30184609f19b05e7334da3cbde81dd1Chris Craik    get_canvas(canvasHandle)->drawColor(color, mode);
2068872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2078872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2088872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawPaint(JNIEnv* env, jobject, jlong canvasHandle, jlong paintHandle) {
2096ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2108872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawPaint(*paint);
2118872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2128872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2138872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawPoint(JNIEnv*, jobject, jlong canvasHandle, jfloat x, jfloat y,
2148872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                      jlong paintHandle) {
2156ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2168872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawPoint(x, y, *paint);
2178872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2188872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2198872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawPoints(JNIEnv* env, jobject, jlong canvasHandle, jfloatArray jptsArray,
2208872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                       jint offset, jint count, jlong paintHandle) {
2218872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    NPE_CHECK_RETURN_VOID(env, jptsArray);
2228872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    AutoJavaFloatArray autoPts(env, jptsArray);
2238872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    float* floats = autoPts.ptr();
2248872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const int length = autoPts.length();
2258872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2268872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if ((offset | count) < 0 || offset + count > length) {
2278872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        doThrowAIOOBE(env);
2288872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        return;
2298872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
2308872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2316ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2328872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawPoints(floats + offset, count, *paint);
2338872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2348872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2358872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawLine(JNIEnv* env, jobject, jlong canvasHandle, jfloat startX, jfloat startY,
2368872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                     jfloat stopX, jfloat stopY, jlong paintHandle) {
2376ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2388872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawLine(startX, startY, stopX, stopY, *paint);
2398872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2408872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2418872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawLines(JNIEnv* env, jobject, jlong canvasHandle, jfloatArray jptsArray,
2428872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                      jint offset, jint count, jlong paintHandle) {
2438872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    NPE_CHECK_RETURN_VOID(env, jptsArray);
2448872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    AutoJavaFloatArray autoPts(env, jptsArray);
2458872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    float* floats = autoPts.ptr();
2468872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const int length = autoPts.length();
2478872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2488872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if ((offset | count) < 0 || offset + count > length) {
2498872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        doThrowAIOOBE(env);
2508872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        return;
2518872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
2528872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2536ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2548872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawLines(floats + offset, count, *paint);
2558872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2568872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2578872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawRect(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
2588872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                     jfloat right, jfloat bottom, jlong paintHandle) {
2596ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2608872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawRect(left, top, right, bottom, *paint);
2618872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2628872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
26394394b3fb048d5349a77b57950ab7f6b6e92ce34Derek Sollenbergerstatic void drawRegion(JNIEnv* env, jobject, jlong canvasHandle, jlong regionHandle,
26494394b3fb048d5349a77b57950ab7f6b6e92ce34Derek Sollenberger                       jlong paintHandle) {
26594394b3fb048d5349a77b57950ab7f6b6e92ce34Derek Sollenberger    const SkRegion* region = reinterpret_cast<SkRegion*>(regionHandle);
26694394b3fb048d5349a77b57950ab7f6b6e92ce34Derek Sollenberger    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
26794394b3fb048d5349a77b57950ab7f6b6e92ce34Derek Sollenberger    get_canvas(canvasHandle)->drawRegion(*region, *paint);
26894394b3fb048d5349a77b57950ab7f6b6e92ce34Derek Sollenberger}
26994394b3fb048d5349a77b57950ab7f6b6e92ce34Derek Sollenberger
2708872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawRoundRect(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
2718872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                          jfloat right, jfloat bottom, jfloat rx, jfloat ry, jlong paintHandle) {
2726ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2738872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawRoundRect(left, top, right, bottom, rx, ry, *paint);
2748872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2758872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2768872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawCircle(JNIEnv* env, jobject, jlong canvasHandle, jfloat cx, jfloat cy,
2778872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                       jfloat radius, jlong paintHandle) {
2786ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2798872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawCircle(cx, cy, radius, *paint);
2808872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2818872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2828872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawOval(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
2838872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                     jfloat right, jfloat bottom, jlong paintHandle) {
2846ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2858872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawOval(left, top, right, bottom, *paint);
2868872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2878872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2888872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawArc(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
2898872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                    jfloat right, jfloat bottom, jfloat startAngle, jfloat sweepAngle,
2908872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                    jboolean useCenter, jlong paintHandle) {
2916ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2928872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawArc(left, top, right, bottom, startAngle, sweepAngle,
2938872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                       useCenter, *paint);
2948872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2958872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2968872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle,
2978872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                     jlong paintHandle) {
2988872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
2996ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
3008872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawPath(*path, *paint);
3018872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
3028872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3038872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawVertices(JNIEnv* env, jobject, jlong canvasHandle,
3048872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                         jint modeHandle, jint vertexCount,
3058872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                         jfloatArray jverts, jint vertIndex,
3068872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                         jfloatArray jtexs, jint texIndex,
3078872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                         jintArray jcolors, jint colorIndex,
3088872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                         jshortArray jindices, jint indexIndex,
3098872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                         jint indexCount, jlong paintHandle) {
3108872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    AutoJavaFloatArray  vertA(env, jverts, vertIndex + vertexCount);
3118872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    AutoJavaFloatArray  texA(env, jtexs, texIndex + vertexCount);
3128872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    AutoJavaIntArray    colorA(env, jcolors, colorIndex + vertexCount);
3138872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    AutoJavaShortArray  indexA(env, jindices, indexIndex + indexCount);
3148872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3158872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const float* verts = vertA.ptr() + vertIndex;
3168872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const float* texs = texA.ptr() + vertIndex;
3178872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const int* colors = NULL;
3188872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const uint16_t* indices = NULL;
3198872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3208872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if (jcolors != NULL) {
3218872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        colors = colorA.ptr() + colorIndex;
3228872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
3238872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if (jindices != NULL) {
3248872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        indices = (const uint16_t*)(indexA.ptr() + indexIndex);
3258872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
3268872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3278872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkCanvas::VertexMode mode = static_cast<SkCanvas::VertexMode>(modeHandle);
3286ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
3298872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawVertices(mode, vertexCount, verts, texs, colors,
3308872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                           indices, indexCount, *paint);
3318872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
3328872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3337c103a36f60b690e3fe83c40210e1cb0c76bba43John Reckstatic void drawBitmap(JNIEnv* env, jobject jcanvas, jlong canvasHandle, jobject jbitmap,
3348872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                       jfloat left, jfloat top, jlong paintHandle, jint canvasDensity,
3358872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                       jint screenDensity, jint bitmapDensity) {
3368872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    Canvas* canvas = get_canvas(canvasHandle);
3377c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    SkBitmap bitmap;
3387c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
3396ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
3408872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3418872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if (canvasDensity == bitmapDensity || canvasDensity == 0 || bitmapDensity == 0) {
3428872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        if (screenDensity != 0 && screenDensity != bitmapDensity) {
3436ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod            Paint filteredPaint;
3448872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            if (paint) {
3458872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                filteredPaint = *paint;
3468872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            }
3472a1ce8a4e5258b6599cb8e86864eb816d24d69b4Mike Reed            filteredPaint.setFilterQuality(kLow_SkFilterQuality);
3487c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck            canvas->drawBitmap(bitmap, left, top, &filteredPaint);
3498872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        } else {
3507c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck            canvas->drawBitmap(bitmap, left, top, paint);
3518872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        }
3528872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    } else {
3538872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        canvas->save(SkCanvas::kMatrixClip_SaveFlag);
3548872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        SkScalar scale = canvasDensity / (float)bitmapDensity;
3558872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        canvas->translate(left, top);
3568872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        canvas->scale(scale, scale);
3578872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3586ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod        Paint filteredPaint;
3598872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        if (paint) {
3608872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            filteredPaint = *paint;
3618872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        }
3622a1ce8a4e5258b6599cb8e86864eb816d24d69b4Mike Reed        filteredPaint.setFilterQuality(kLow_SkFilterQuality);
3638872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3647c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck        canvas->drawBitmap(bitmap, 0, 0, &filteredPaint);
3658872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        canvas->restore();
3668872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
3678872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
3688872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3697c103a36f60b690e3fe83c40210e1cb0c76bba43John Reckstatic void drawBitmapMatrix(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap,
3708872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                             jlong matrixHandle, jlong paintHandle) {
3718872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
3726ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
3737c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    SkBitmap bitmap;
3747c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
3757c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    get_canvas(canvasHandle)->drawBitmap(bitmap, *matrix, paint);
3768872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
3778872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3787c103a36f60b690e3fe83c40210e1cb0c76bba43John Reckstatic void drawBitmapRect(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap,
3798872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           float srcLeft, float srcTop, float srcRight, float srcBottom,
3808872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           float dstLeft, float dstTop, float dstRight, float dstBottom,
3818872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           jlong paintHandle, jint screenDensity, jint bitmapDensity) {
3828872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    Canvas* canvas = get_canvas(canvasHandle);
3836ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
3848872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3857c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    SkBitmap bitmap;
3867c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
3878872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if (screenDensity != 0 && screenDensity != bitmapDensity) {
3886ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod        Paint filteredPaint;
3898872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        if (paint) {
3908872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            filteredPaint = *paint;
3918872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        }
3922a1ce8a4e5258b6599cb8e86864eb816d24d69b4Mike Reed        filteredPaint.setFilterQuality(kLow_SkFilterQuality);
3937c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck        canvas->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom,
3948872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           dstLeft, dstTop, dstRight, dstBottom, &filteredPaint);
3958872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    } else {
3967c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck        canvas->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom,
3978872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           dstLeft, dstTop, dstRight, dstBottom, paint);
3988872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
3998872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
4008872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
4018872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawBitmapArray(JNIEnv* env, jobject, jlong canvasHandle,
4028872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                            jintArray jcolors, jint offset, jint stride,
4038872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                            jfloat x, jfloat y, jint width, jint height,
4048872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                            jboolean hasAlpha, jlong paintHandle) {
4058872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    // Note: If hasAlpha is false, kRGB_565_SkColorType will be used, which will
4068872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    // correct the alphaType to kOpaque_SkAlphaType.
4078872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkImageInfo info = SkImageInfo::Make(width, height,
4088872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           hasAlpha ? kN32_SkColorType : kRGB_565_SkColorType,
4098872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           kPremul_SkAlphaType);
4108872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkBitmap bitmap;
4113d4eed7f1aa99401dabe2e45b82f98fb4fc2d754Derek Sollenberger    bitmap.setInfo(info);
4123d4eed7f1aa99401dabe2e45b82f98fb4fc2d754Derek Sollenberger    if (!GraphicsJNI::allocatePixels(env, &bitmap, NULL)) {
4138872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        return;
4148872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
4158872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
4168872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if (!GraphicsJNI::SetPixels(env, jcolors, offset, stride, 0, 0, width, height, bitmap)) {
4178872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        return;
4188872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
4198872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
4206ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
4218872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawBitmap(bitmap, x, y, paint);
4228872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
4238872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
4247c103a36f60b690e3fe83c40210e1cb0c76bba43John Reckstatic void drawBitmapMesh(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap,
4258872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           jint meshWidth, jint meshHeight, jfloatArray jverts,
4268872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           jint vertIndex, jintArray jcolors, jint colorIndex, jlong paintHandle) {
4278872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const int ptCount = (meshWidth + 1) * (meshHeight + 1);
4288872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    AutoJavaFloatArray vertA(env, jverts, vertIndex + (ptCount << 1));
4298872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    AutoJavaIntArray colorA(env, jcolors, colorIndex + ptCount);
4308872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
4316ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
4327c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    SkBitmap bitmap;
4337c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
4347c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    get_canvas(canvasHandle)->drawBitmapMesh(bitmap, meshWidth, meshHeight,
4358872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                             vertA.ptr(), colorA.ptr(), paint);
4368872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
4378872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
4386578a989566e585eee053095dc80e2552e125db2Derek Sollenbergerstatic void simplifyPaint(int color, SkPaint* paint) {
4396578a989566e585eee053095dc80e2552e125db2Derek Sollenberger    paint->setColor(color);
4406578a989566e585eee053095dc80e2552e125db2Derek Sollenberger    paint->setShader(nullptr);
4416578a989566e585eee053095dc80e2552e125db2Derek Sollenberger    paint->setColorFilter(nullptr);
4426578a989566e585eee053095dc80e2552e125db2Derek Sollenberger    paint->setLooper(nullptr);
4436578a989566e585eee053095dc80e2552e125db2Derek Sollenberger    paint->setStrokeWidth(4 + 0.04 * paint->getTextSize());
4446578a989566e585eee053095dc80e2552e125db2Derek Sollenberger    paint->setStrokeJoin(SkPaint::kRound_Join);
4456578a989566e585eee053095dc80e2552e125db2Derek Sollenberger    paint->setLooper(nullptr);
4466578a989566e585eee053095dc80e2552e125db2Derek Sollenberger}
4476578a989566e585eee053095dc80e2552e125db2Derek Sollenberger
448acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenbergerclass DrawTextFunctor {
449acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenbergerpublic:
450acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    DrawTextFunctor(const Layout& layout, Canvas* canvas, uint16_t* glyphs, float* pos,
4518dfaa4904205772cdceee63ef3989bcdedf1a914Tom Hudson                    const SkPaint& paint, float x, float y, MinikinRect& bounds,
4528dfaa4904205772cdceee63ef3989bcdedf1a914Tom Hudson                    float totalAdvance)
453acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            : layout(layout), canvas(canvas), glyphs(glyphs), pos(pos), paint(paint),
4548dfaa4904205772cdceee63ef3989bcdedf1a914Tom Hudson              x(x), y(y), bounds(bounds), totalAdvance(totalAdvance) { }
455acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
456acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    void operator()(size_t start, size_t end) {
457acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        if (canvas->drawTextAbsolutePos()) {
458acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            for (size_t i = start; i < end; i++) {
459acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger                glyphs[i] = layout.getGlyphId(i);
460acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger                pos[2 * i] = x + layout.getX(i);
461acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger                pos[2 * i + 1] = y + layout.getY(i);
462acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            }
463acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        } else {
464acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            for (size_t i = start; i < end; i++) {
465acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger                glyphs[i] = layout.getGlyphId(i);
466acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger                pos[2 * i] = layout.getX(i);
467acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger                pos[2 * i + 1] = layout.getY(i);
468acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            }
469acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        }
470acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
471acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        size_t glyphCount = end - start;
4726578a989566e585eee053095dc80e2552e125db2Derek Sollenberger
4736578a989566e585eee053095dc80e2552e125db2Derek Sollenberger        if (CC_UNLIKELY(canvas->isHighContrastText())) {
4746578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            // high contrast draw path
4756578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            int color = paint.getColor();
4766578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            int channelSum = SkColorGetR(color) + SkColorGetG(color) + SkColorGetB(color);
4776578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            bool darken = channelSum < (128 * 3);
4786578a989566e585eee053095dc80e2552e125db2Derek Sollenberger
4796578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            // outline
4806578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            SkPaint outlinePaint(paint);
4816578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            simplifyPaint(darken ? SK_ColorWHITE : SK_ColorBLACK, &outlinePaint);
4826578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            outlinePaint.setStyle(SkPaint::kStrokeAndFill_Style);
4836578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            canvas->drawText(glyphs + start, pos + (2 * start), glyphCount, outlinePaint, x, y,
4846578a989566e585eee053095dc80e2552e125db2Derek Sollenberger                    bounds.mLeft, bounds.mTop, bounds.mRight, bounds.mBottom, totalAdvance);
4856578a989566e585eee053095dc80e2552e125db2Derek Sollenberger
4866578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            // inner
4876578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            SkPaint innerPaint(paint);
4886578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            simplifyPaint(darken ? SK_ColorBLACK : SK_ColorWHITE, &innerPaint);
4896578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            innerPaint.setStyle(SkPaint::kFill_Style);
4906578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            canvas->drawText(glyphs + start, pos + (2 * start), glyphCount, innerPaint, x, y,
4916578a989566e585eee053095dc80e2552e125db2Derek Sollenberger                    bounds.mLeft, bounds.mTop, bounds.mRight, bounds.mBottom, totalAdvance);
4926578a989566e585eee053095dc80e2552e125db2Derek Sollenberger        } else {
4936578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            // standard draw path
4946578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            canvas->drawText(glyphs + start, pos + (2 * start), glyphCount, paint, x, y,
4956578a989566e585eee053095dc80e2552e125db2Derek Sollenberger                             bounds.mLeft, bounds.mTop, bounds.mRight, bounds.mBottom,
4966578a989566e585eee053095dc80e2552e125db2Derek Sollenberger                             totalAdvance);
4976578a989566e585eee053095dc80e2552e125db2Derek Sollenberger        }
498acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    }
499acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenbergerprivate:
500acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    const Layout& layout;
501acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    Canvas* canvas;
502acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    uint16_t* glyphs;
503acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    float* pos;
504acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    const SkPaint& paint;
505acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    float x;
506acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    float y;
507acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    MinikinRect& bounds;
5088dfaa4904205772cdceee63ef3989bcdedf1a914Tom Hudson    float totalAdvance;
509acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger};
510acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
511acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger// Same values used by Skia
512acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger#define kStdStrikeThru_Offset   (-6.0f / 21.0f)
513acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger#define kStdUnderline_Offset    (1.0f / 9.0f)
514acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger#define kStdUnderline_Thickness (1.0f / 18.0f)
515acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
516acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenbergervoid drawTextDecorations(Canvas* canvas, float x, float y, float length, const SkPaint& paint) {
517acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    uint32_t flags;
518acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    SkDrawFilter* drawFilter = canvas->getDrawFilter();
519acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    if (drawFilter) {
520acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        SkPaint paintCopy(paint);
521acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        drawFilter->filter(&paintCopy, SkDrawFilter::kText_Type);
522acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        flags = paintCopy.getFlags();
523acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    } else {
524acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        flags = paint.getFlags();
525acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    }
526acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    if (flags & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag)) {
527acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        SkScalar left = x;
528acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        SkScalar right = x + length;
529acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        float textSize = paint.getTextSize();
530acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        float strokeWidth = fmax(textSize * kStdUnderline_Thickness, 1.0f);
531acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        if (flags & SkPaint::kUnderlineText_Flag) {
532acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            SkScalar top = y + textSize * kStdUnderline_Offset - 0.5f * strokeWidth;
533acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            SkScalar bottom = y + textSize * kStdUnderline_Offset + 0.5f * strokeWidth;
534acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            canvas->drawRect(left, top, right, bottom, paint);
535acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        }
536acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        if (flags & SkPaint::kStrikeThruText_Flag) {
537acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            SkScalar top = y + textSize * kStdStrikeThru_Offset - 0.5f * strokeWidth;
538acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            SkScalar bottom = y + textSize * kStdStrikeThru_Offset + 0.5f * strokeWidth;
539acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            canvas->drawRect(left, top, right, bottom, paint);
540acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        }
541acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    }
542acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger}
543acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
544acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenbergervoid drawText(Canvas* canvas, const uint16_t* text, int start, int count, int contextCount,
545acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger             float x, float y, int bidiFlags, const Paint& origPaint, TypefaceImpl* typeface) {
546acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    // minikin may modify the original paint
547acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    Paint paint(origPaint);
548acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
549acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    Layout layout;
55063c5c78a72a21d57913e8601cc2a1ab72a424a02Behdad Esfahbod    MinikinUtils::doLayout(&layout, &paint, bidiFlags, typeface, text, start, count, contextCount);
551acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
552acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    size_t nGlyphs = layout.nGlyphs();
553acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    uint16_t* glyphs = new uint16_t[nGlyphs];
554acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    float* pos = new float[nGlyphs * 2];
555acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
556acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    x += MinikinUtils::xOffsetForTextAlign(&paint, layout);
557acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
558acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    MinikinRect bounds;
559acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    layout.getBounds(&bounds);
5608dfaa4904205772cdceee63ef3989bcdedf1a914Tom Hudson    if (!canvas->drawTextAbsolutePos()) {
5618dfaa4904205772cdceee63ef3989bcdedf1a914Tom Hudson        bounds.offset(x, y);
5628dfaa4904205772cdceee63ef3989bcdedf1a914Tom Hudson    }
563acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
5648dfaa4904205772cdceee63ef3989bcdedf1a914Tom Hudson    DrawTextFunctor f(layout, canvas, glyphs, pos, paint, x, y, bounds, layout.getAdvance());
565acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    MinikinUtils::forFontRun(layout, &paint, f);
566acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
567acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    drawTextDecorations(canvas, x, y, layout.getAdvance(), paint);
568acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
569acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    delete[] glyphs;
570acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    delete[] pos;
571acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger}
572acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
5738872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawTextChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text,
5748872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                          jint index, jint count, jfloat x, jfloat y, jint bidiFlags,
5758872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                          jlong paintHandle, jlong typefaceHandle) {
5766ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
5778872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
5788872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    jchar* jchars = env->GetCharArrayElements(text, NULL);
579acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    drawText(get_canvas(canvasHandle), jchars + index, 0, count, count, x, y,
5808872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                       bidiFlags, *paint, typeface);
5818872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    env->ReleaseCharArrayElements(text, jchars, JNI_ABORT);
5828872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
5838872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
5848872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawTextString(JNIEnv* env, jobject, jlong canvasHandle, jstring text,
5858872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           jint start, jint end, jfloat x, jfloat y, jint bidiFlags,
5868872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           jlong paintHandle, jlong typefaceHandle) {
5876ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
5888872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
5898872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const int count = end - start;
5908872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const jchar* jchars = env->GetStringChars(text, NULL);
591acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    drawText(get_canvas(canvasHandle), jchars + start, 0, count, count, x, y,
5928872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                       bidiFlags, *paint, typeface);
5938872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    env->ReleaseStringChars(text, jchars);
5948872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
5958872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
5968872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawTextRunChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text, jint index,
5978872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                             jint count, jint contextIndex, jint contextCount, jfloat x, jfloat y,
5988872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                             jboolean isRtl, jlong paintHandle, jlong typefaceHandle) {
5996ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
6008872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
6018872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6028872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
6038872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    jchar* jchars = env->GetCharArrayElements(text, NULL);
604acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    drawText(get_canvas(canvasHandle), jchars + contextIndex, index - contextIndex, count,
6058872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                       contextCount, x, y, bidiFlags, *paint, typeface);
6068872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    env->ReleaseCharArrayElements(text, jchars, JNI_ABORT);
6078872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
6088872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6098872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawTextRunString(JNIEnv* env, jobject obj, jlong canvasHandle, jstring text,
6108872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                              jint start, jint end, jint contextStart, jint contextEnd,
6118872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                              jfloat x, jfloat y, jboolean isRtl, jlong paintHandle,
6128872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                              jlong typefaceHandle) {
6136ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
6148872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
6158872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6168872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
6178872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    jint count = end - start;
6188872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    jint contextCount = contextEnd - contextStart;
6198872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const jchar* jchars = env->GetStringChars(text, NULL);
620acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    drawText(get_canvas(canvasHandle), jchars + contextStart, start - contextStart, count,
6218872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                       contextCount, x, y, bidiFlags, *paint, typeface);
6228872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    env->ReleaseStringChars(text, jchars);
6238872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
6248872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6258872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerclass DrawTextOnPathFunctor {
6268872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerpublic:
6278872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    DrawTextOnPathFunctor(const Layout& layout, Canvas* canvas, float hOffset,
6286ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod                float vOffset, const Paint& paint, const SkPath& path)
6298872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            : layout(layout), canvas(canvas), hOffset(hOffset), vOffset(vOffset),
6308872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                paint(paint), path(path) {
6318872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
6328872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    void operator()(size_t start, size_t end) {
6338872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        uint16_t glyphs[1];
6348872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        for (size_t i = start; i < end; i++) {
6358872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            glyphs[0] = layout.getGlyphId(i);
6368872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            float x = hOffset + layout.getX(i);
6378872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            float y = vOffset + layout.getY(i);
6388872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            canvas->drawTextOnPath(glyphs, 1, path, x, y, paint);
6398872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        }
6408872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
6418872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerprivate:
6428872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const Layout& layout;
6438872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    Canvas* canvas;
6448872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    float hOffset;
6458872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    float vOffset;
6466ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint& paint;
6478872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const SkPath& path;
6488872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger};
6498872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6508872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawTextOnPath(Canvas* canvas, const uint16_t* text, int count, int bidiFlags,
6518872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           const SkPath& path, float hOffset, float vOffset,
6526ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod                           const Paint& paint, TypefaceImpl* typeface) {
6536ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint paintCopy(paint);
6548872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    Layout layout;
65563c5c78a72a21d57913e8601cc2a1ab72a424a02Behdad Esfahbod    MinikinUtils::doLayout(&layout, &paintCopy, bidiFlags, typeface, text, 0, count, count);
6568872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    hOffset += MinikinUtils::hOffsetForTextAlign(&paintCopy, layout, path);
6578872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6588872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    // Set align to left for drawing, as we don't want individual
6598872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    // glyphs centered or right-aligned; the offset above takes
6608872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    // care of all alignment.
6616ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    paintCopy.setTextAlign(Paint::kLeft_Align);
6628872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6638872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    DrawTextOnPathFunctor f(layout, canvas, hOffset, vOffset, paintCopy, path);
6648872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    MinikinUtils::forFontRun(layout, &paintCopy, f);
6658872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
6668872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6678872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawTextOnPathChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text,
6688872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                jint index, jint count, jlong pathHandle, jfloat hOffset,
6698872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                jfloat vOffset, jint bidiFlags, jlong paintHandle,
6708872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                jlong typefaceHandle) {
6718872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
6726ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
6738872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
6748872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6758872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    jchar* jchars = env->GetCharArrayElements(text, NULL);
6768872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6778872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    drawTextOnPath(get_canvas(canvasHandle), jchars + index, count, bidiFlags, *path,
6788872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                   hOffset, vOffset, *paint, typeface);
6798872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6808872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    env->ReleaseCharArrayElements(text, jchars, 0);
6818872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
6828872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6838872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawTextOnPathString(JNIEnv* env, jobject, jlong canvasHandle, jstring text,
6848872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                 jlong pathHandle, jfloat hOffset, jfloat vOffset,
6858872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                 jint bidiFlags, jlong paintHandle, jlong typefaceHandle) {
6868872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
6876ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
6888872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
6898872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6908872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const jchar* jchars = env->GetStringChars(text, NULL);
6918872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    int count = env->GetStringLength(text);
6928872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6938872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    drawTextOnPath(get_canvas(canvasHandle), jchars, count, bidiFlags, *path,
6948872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                   hOffset, vOffset, *paint, typeface);
6958872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6968872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    env->ReleaseStringChars(text, jchars);
6978872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
6988872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6998872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void setDrawFilter(JNIEnv* env, jobject, jlong canvasHandle, jlong filterHandle) {
7008872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->setDrawFilter(reinterpret_cast<SkDrawFilter*>(filterHandle));
7018872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
7028872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
7038872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void freeCaches(JNIEnv* env, jobject) {
7048872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkGraphics::PurgeFontCache();
7058872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
7068872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
7078872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void freeTextLayoutCaches(JNIEnv* env, jobject) {
7088872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    Layout::purgeCaches();
7098872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
7108872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
7118872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}; // namespace CanvasJNI
7128872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
7138872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic JNINativeMethod gMethods[] = {
7148872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"finalizer", "(J)V", (void*) CanvasJNI::finalizer},
715c1b33d665c8caf5760f68c45c6ca0baa649b832aJohn Reck    {"initRaster", "(Landroid/graphics/Bitmap;)J", (void*) CanvasJNI::initRaster},
716c1b33d665c8caf5760f68c45c6ca0baa649b832aJohn Reck    {"native_setBitmap", "(JLandroid/graphics/Bitmap;)V", (void*) CanvasJNI::setBitmap},
7178872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_isOpaque","(J)Z", (void*) CanvasJNI::isOpaque},
7188872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_getWidth","(J)I", (void*) CanvasJNI::getWidth},
7198872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_getHeight","(J)I", (void*) CanvasJNI::getHeight},
7206578a989566e585eee053095dc80e2552e125db2Derek Sollenberger    {"native_setHighContrastText","(JZ)V", (void*) CanvasJNI::setHighContrastText},
7218872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_save","(JI)I", (void*) CanvasJNI::save},
7228872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_saveLayer","(JFFFFJI)I", (void*) CanvasJNI::saveLayer},
7238872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_saveLayerAlpha","(JFFFFII)I", (void*) CanvasJNI::saveLayerAlpha},
7248872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_getSaveCount","(J)I", (void*) CanvasJNI::getSaveCount},
7253891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik    {"native_restore","(JZ)V", (void*) CanvasJNI::restore},
7263891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik    {"native_restoreToCount","(JIZ)V", (void*) CanvasJNI::restoreToCount},
7278872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_getCTM", "(JJ)V", (void*)CanvasJNI::getCTM},
7288872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_setMatrix","(JJ)V", (void*) CanvasJNI::setMatrix},
7298872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_concat","(JJ)V", (void*) CanvasJNI::concat},
7308872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_rotate","(JF)V", (void*) CanvasJNI::rotate},
7318872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_scale","(JFF)V", (void*) CanvasJNI::scale},
7328872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_skew","(JFF)V", (void*) CanvasJNI::skew},
7338872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_translate","(JFF)V", (void*) CanvasJNI::translate},
7348872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_getClipBounds","(JLandroid/graphics/Rect;)Z", (void*) CanvasJNI::getClipBounds},
7358872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_quickReject","(JJ)Z", (void*) CanvasJNI::quickRejectPath},
7368872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_quickReject","(JFFFF)Z", (void*)CanvasJNI::quickRejectRect},
7378872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_clipRect","(JFFFFI)Z", (void*) CanvasJNI::clipRect},
7388872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_clipPath","(JJI)Z", (void*) CanvasJNI::clipPath},
7398872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_clipRegion","(JJI)Z", (void*) CanvasJNI::clipRegion},
7408872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawColor","(JII)V", (void*) CanvasJNI::drawColor},
7418872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawPaint","(JJ)V", (void*) CanvasJNI::drawPaint},
7428872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawPoint", "(JFFJ)V", (void*) CanvasJNI::drawPoint},
7438872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawPoints", "(J[FIIJ)V", (void*) CanvasJNI::drawPoints},
7448872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawLine", "(JFFFFJ)V", (void*) CanvasJNI::drawLine},
7458872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawLines", "(J[FIIJ)V", (void*) CanvasJNI::drawLines},
7468872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawRect","(JFFFFJ)V", (void*) CanvasJNI::drawRect},
74794394b3fb048d5349a77b57950ab7f6b6e92ce34Derek Sollenberger    {"native_drawRegion", "(JJJ)V", (void*) CanvasJNI::drawRegion },
7488872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawRoundRect","(JFFFFFFJ)V", (void*) CanvasJNI::drawRoundRect},
7498872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawCircle","(JFFFJ)V", (void*) CanvasJNI::drawCircle},
7508872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawOval","(JFFFFJ)V", (void*) CanvasJNI::drawOval},
7518872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawArc","(JFFFFFFZJ)V", (void*) CanvasJNI::drawArc},
7528872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawPath","(JJJ)V", (void*) CanvasJNI::drawPath},
7538872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"nativeDrawVertices", "(JII[FI[FI[II[SIIJ)V", (void*)CanvasJNI::drawVertices},
7547c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    {"native_drawBitmap","(JLandroid/graphics/Bitmap;FFJIII)V", (void*) CanvasJNI::drawBitmap},
7557c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    {"nativeDrawBitmapMatrix", "(JLandroid/graphics/Bitmap;JJ)V", (void*)CanvasJNI::drawBitmapMatrix},
7567c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    {"native_drawBitmap","(JLandroid/graphics/Bitmap;FFFFFFFFJII)V", (void*) CanvasJNI::drawBitmapRect},
7578872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawBitmap", "(J[IIIFFIIZJ)V", (void*)CanvasJNI::drawBitmapArray},
7587c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    {"nativeDrawBitmapMesh", "(JLandroid/graphics/Bitmap;II[FI[IIJ)V", (void*)CanvasJNI::drawBitmapMesh},
7598872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawText","(J[CIIFFIJJ)V", (void*) CanvasJNI::drawTextChars},
7608872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawText","(JLjava/lang/String;IIFFIJJ)V", (void*) CanvasJNI::drawTextString},
7618872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawTextRun","(J[CIIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunChars},
7628872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawTextRun","(JLjava/lang/String;IIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunString},
7638872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawTextOnPath","(J[CIIJFFIJJ)V", (void*) CanvasJNI::drawTextOnPathChars},
7648872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawTextOnPath","(JLjava/lang/String;JFFIJJ)V", (void*) CanvasJNI::drawTextOnPathString},
7658872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"nativeSetDrawFilter", "(JJ)V", (void*) CanvasJNI::setDrawFilter},
7668872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"freeCaches", "()V", (void*) CanvasJNI::freeCaches},
7678872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"freeTextLayoutCaches", "()V", (void*) CanvasJNI::freeTextLayoutCaches}
7688872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger};
7698872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
7708872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerint register_android_graphics_Canvas(JNIEnv* env) {
771ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    return RegisterMethodsOrDie(env, "android/graphics/Canvas", gMethods, NELEM(gMethods));
7728872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
7738872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
7748872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}; // namespace android
775