android_graphics_Canvas.cpp revision 4c5efe9290543b723b76a8bd48518da1ae1dcb26
18872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger/*
28872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger * Copyright (C) 2014 The Android Open Source Project
38872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger *
48872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger * Licensed under the Apache License, Version 2.0 (the "License");
58872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger * you may not use this file except in compliance with the License.
68872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger * You may obtain a copy of the License at
78872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger *
88872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger *      http://www.apache.org/licenses/LICENSE-2.0
98872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger *
108872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger * Unless required by applicable law or agreed to in writing, software
118872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger * distributed under the License is distributed on an "AS IS" BASIS,
128872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger * See the License for the specific language governing permissions and
148872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger * limitations under the License.
158872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger */
168872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
178872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger#include "jni.h"
188872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger#include "GraphicsJNI.h"
19ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe#include "core_jni_helpers.h"
208872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
214c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger#include <androidfw/ResourceTypes.h>
22849911a9c4315fc552faa38516c842b2541b1909John Reck#include <Canvas.h>
234c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger
244c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger#include "Bitmap.h"
25acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger#include "SkDrawFilter.h"
268872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger#include "SkGraphics.h"
276ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod#include "Paint.h"
288872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger#include "TypefaceImpl.h"
298872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
308872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger#include "MinikinUtils.h"
318872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
328872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergernamespace android {
338872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
348872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergernamespace CanvasJNI {
358872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
368872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic Canvas* get_canvas(jlong canvasHandle) {
378872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return reinterpret_cast<Canvas*>(canvasHandle);
388872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
398872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
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)
45c1b33d665c8caf5760f68c45c6ca0baa649b832aJohn Reckstatic jlong initRaster(JNIEnv* env, jobject, jobject jbitmap) {
463731dc220ed457e0f1e99d7ec2589e0a43872b59John Reck    SkBitmap bitmap;
47c1b33d665c8caf5760f68c45c6ca0baa649b832aJohn Reck    if (jbitmap != NULL) {
483731dc220ed457e0f1e99d7ec2589e0a43872b59John Reck        GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
49c1b33d665c8caf5760f68c45c6ca0baa649b832aJohn Reck    }
503731dc220ed457e0f1e99d7ec2589e0a43872b59John Reck    return reinterpret_cast<jlong>(Canvas::create_canvas(bitmap));
518872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
528872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
538872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger// Set the given bitmap as the new draw target (wrapped in a new SkCanvas),
548872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger// optionally copying canvas matrix & clip state.
55c1b33d665c8caf5760f68c45c6ca0baa649b832aJohn Reckstatic void setBitmap(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap) {
563731dc220ed457e0f1e99d7ec2589e0a43872b59John Reck    SkBitmap bitmap;
57c1b33d665c8caf5760f68c45c6ca0baa649b832aJohn Reck    if (jbitmap != NULL) {
583731dc220ed457e0f1e99d7ec2589e0a43872b59John Reck        GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
59c1b33d665c8caf5760f68c45c6ca0baa649b832aJohn Reck    }
603731dc220ed457e0f1e99d7ec2589e0a43872b59John Reck    get_canvas(canvasHandle)->setBitmap(bitmap);
618872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
628872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
638872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jboolean isOpaque(JNIEnv*, jobject, jlong canvasHandle) {
648872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return get_canvas(canvasHandle)->isOpaque() ? JNI_TRUE : JNI_FALSE;
658872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
668872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
678872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jint getWidth(JNIEnv*, jobject, jlong canvasHandle) {
688872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return static_cast<jint>(get_canvas(canvasHandle)->width());
698872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
708872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
718872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jint getHeight(JNIEnv*, jobject, jlong canvasHandle) {
728872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return static_cast<jint>(get_canvas(canvasHandle)->height());
738872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
748872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
756578a989566e585eee053095dc80e2552e125db2Derek Sollenbergerstatic void setHighContrastText(JNIEnv*, jobject, jlong canvasHandle, jboolean highContrastText) {
766578a989566e585eee053095dc80e2552e125db2Derek Sollenberger    Canvas* canvas = get_canvas(canvasHandle);
776578a989566e585eee053095dc80e2552e125db2Derek Sollenberger    canvas->setHighContrastText(highContrastText);
786578a989566e585eee053095dc80e2552e125db2Derek Sollenberger}
796578a989566e585eee053095dc80e2552e125db2Derek Sollenberger
808872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jint getSaveCount(JNIEnv*, jobject, jlong canvasHandle) {
818872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return static_cast<jint>(get_canvas(canvasHandle)->getSaveCount());
828872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
838872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
848872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jint save(JNIEnv*, jobject, jlong canvasHandle, jint flagsHandle) {
858872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
868872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return static_cast<jint>(get_canvas(canvasHandle)->save(flags));
878872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
888872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
898872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jint saveLayer(JNIEnv* env, jobject, jlong canvasHandle, jfloat l, jfloat t,
908872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                      jfloat r, jfloat b, jlong paintHandle, jint flagsHandle) {
916ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint  = reinterpret_cast<Paint*>(paintHandle);
928872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
938872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return static_cast<jint>(get_canvas(canvasHandle)->saveLayer(l, t, r, b, paint, flags));
948872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
958872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
968872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jint saveLayerAlpha(JNIEnv* env, jobject, jlong canvasHandle, jfloat l, jfloat t,
978872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           jfloat r, jfloat b, jint alpha, jint flagsHandle) {
988872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
998872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return static_cast<jint>(get_canvas(canvasHandle)->saveLayerAlpha(l, t, r, b, alpha, flags));
1008872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1018872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1023891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craikstatic void restore(JNIEnv* env, jobject, jlong canvasHandle, jboolean throwOnUnderflow) {
1038872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    Canvas* canvas = get_canvas(canvasHandle);
1048872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if (canvas->getSaveCount() <= 1) {  // cannot restore anymore
1053891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik        if (throwOnUnderflow) {
1063891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik            doThrowISE(env, "Underflow in restore - more restores than saves");
1073891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik        }
1083891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik        return; // compat behavior - return without throwing
1098872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
1108872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    canvas->restore();
1118872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1128872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1133891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craikstatic void restoreToCount(JNIEnv* env, jobject, jlong canvasHandle, jint restoreCount,
1143891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik        jboolean throwOnUnderflow) {
1158872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    Canvas* canvas = get_canvas(canvasHandle);
1168872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if (restoreCount < 1 || restoreCount > canvas->getSaveCount()) {
1173891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik        if (throwOnUnderflow) {
1183891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik            doThrowIAE(env, "Underflow in restoreToCount - more restores than saves");
1193891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik            return;
1203891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik        }
1213891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik        restoreCount = 1; // compat behavior - restore as far as possible
1228872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
1238872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    canvas->restoreToCount(restoreCount);
1248872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1258872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1268872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void getCTM(JNIEnv* env, jobject, jlong canvasHandle, jlong matrixHandle) {
1278872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
1288872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->getMatrix(matrix);
1298872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1308872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1318872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void setMatrix(JNIEnv* env, jobject, jlong canvasHandle, jlong matrixHandle) {
1328872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
1338872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->setMatrix(matrix ? *matrix : SkMatrix::I());
1348872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1358872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1368872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void concat(JNIEnv* env, jobject, jlong canvasHandle, jlong matrixHandle) {
1378872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
1388872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->concat(*matrix);
1398872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1408872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1418872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void rotate(JNIEnv*, jobject, jlong canvasHandle, jfloat degrees) {
1428872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->rotate(degrees);
1438872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1448872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1458872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void scale(JNIEnv*, jobject, jlong canvasHandle, jfloat sx, jfloat sy) {
1468872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->scale(sx, sy);
1478872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1488872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1498872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void skew(JNIEnv*, jobject, jlong canvasHandle, jfloat sx, jfloat sy) {
1508872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->skew(sx, sy);
1518872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1528872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1538872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void translate(JNIEnv*, jobject, jlong canvasHandle, jfloat dx, jfloat dy) {
1548872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->translate(dx, dy);
1558872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1568872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1578872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jboolean getClipBounds(JNIEnv* env, jobject, jlong canvasHandle, jobject bounds) {
1588872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkRect   r;
1598872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkIRect ir;
1608872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    bool result = get_canvas(canvasHandle)->getClipBounds(&r);
1618872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1628872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if (!result) {
1638872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        r.setEmpty();
1648872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
1658872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    r.round(&ir);
1668872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1678872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    (void)GraphicsJNI::irect_to_jrect(ir, env, bounds);
1688872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return result ? JNI_TRUE : JNI_FALSE;
1698872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1708872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1718872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jboolean quickRejectRect(JNIEnv* env, jobject, jlong canvasHandle,
1728872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                jfloat left, jfloat top, jfloat right, jfloat bottom) {
1738872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    bool result = get_canvas(canvasHandle)->quickRejectRect(left, top, right, bottom);
1748872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return result ? JNI_TRUE : JNI_FALSE;
1758872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1768872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1778872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jboolean quickRejectPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle) {
1788872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
1798872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    bool result = get_canvas(canvasHandle)->quickRejectPath(*path);
1808872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    return result ? JNI_TRUE : JNI_FALSE;
1818872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1828872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1838872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jboolean clipRect(JNIEnv*, jobject, jlong canvasHandle, jfloat l, jfloat t,
1848872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                         jfloat r, jfloat b, jint opHandle) {
1858872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkRegion::Op op = static_cast<SkRegion::Op>(opHandle);
1865ec6a2878b2ad933c5da6fe2341c854155acc24cChris Craik    bool nonEmptyClip = get_canvas(canvasHandle)->clipRect(l, t, r, b, op);
1875ec6a2878b2ad933c5da6fe2341c854155acc24cChris Craik    return nonEmptyClip ? JNI_TRUE : JNI_FALSE;
1888872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1898872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1908872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jboolean clipPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle,
1918872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                         jint opHandle) {
1928872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
1938872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkRegion::Op op = static_cast<SkRegion::Op>(opHandle);
1945ec6a2878b2ad933c5da6fe2341c854155acc24cChris Craik    bool nonEmptyClip = get_canvas(canvasHandle)->clipPath(path, op);
1955ec6a2878b2ad933c5da6fe2341c854155acc24cChris Craik    return nonEmptyClip ? JNI_TRUE : JNI_FALSE;
1968872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
1978872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
1988872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic jboolean clipRegion(JNIEnv* env, jobject, jlong canvasHandle, jlong deviceRgnHandle,
1998872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           jint opHandle) {
2008872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkRegion* deviceRgn = reinterpret_cast<SkRegion*>(deviceRgnHandle);
2018872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkRegion::Op op = static_cast<SkRegion::Op>(opHandle);
2025ec6a2878b2ad933c5da6fe2341c854155acc24cChris Craik    bool nonEmptyClip = get_canvas(canvasHandle)->clipRegion(deviceRgn, op);
2035ec6a2878b2ad933c5da6fe2341c854155acc24cChris Craik    return nonEmptyClip ? JNI_TRUE : JNI_FALSE;
2048872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2058872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2068872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawColor(JNIEnv* env, jobject, jlong canvasHandle, jint color, jint modeHandle) {
2071526a458a30184609f19b05e7334da3cbde81dd1Chris Craik    SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(modeHandle);
2081526a458a30184609f19b05e7334da3cbde81dd1Chris Craik    get_canvas(canvasHandle)->drawColor(color, mode);
2098872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2108872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2118872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawPaint(JNIEnv* env, jobject, jlong canvasHandle, jlong paintHandle) {
2126ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2138872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawPaint(*paint);
2148872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2158872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2168872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawPoint(JNIEnv*, jobject, jlong canvasHandle, jfloat x, jfloat y,
2178872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                      jlong paintHandle) {
2186ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2198872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawPoint(x, y, *paint);
2208872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2218872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2228872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawPoints(JNIEnv* env, jobject, jlong canvasHandle, jfloatArray jptsArray,
2238872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                       jint offset, jint count, jlong paintHandle) {
2248872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    NPE_CHECK_RETURN_VOID(env, jptsArray);
2258872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    AutoJavaFloatArray autoPts(env, jptsArray);
2268872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    float* floats = autoPts.ptr();
2278872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const int length = autoPts.length();
2288872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2298872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if ((offset | count) < 0 || offset + count > length) {
2308872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        doThrowAIOOBE(env);
2318872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        return;
2328872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
2338872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2346ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2358872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawPoints(floats + offset, count, *paint);
2368872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2378872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2388872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawLine(JNIEnv* env, jobject, jlong canvasHandle, jfloat startX, jfloat startY,
2398872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                     jfloat stopX, jfloat stopY, jlong paintHandle) {
2406ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2418872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawLine(startX, startY, stopX, stopY, *paint);
2428872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2438872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2448872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawLines(JNIEnv* env, jobject, jlong canvasHandle, jfloatArray jptsArray,
2458872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                      jint offset, jint count, jlong paintHandle) {
2468872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    NPE_CHECK_RETURN_VOID(env, jptsArray);
2478872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    AutoJavaFloatArray autoPts(env, jptsArray);
2488872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    float* floats = autoPts.ptr();
2498872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const int length = autoPts.length();
2508872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2518872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if ((offset | count) < 0 || offset + count > length) {
2528872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        doThrowAIOOBE(env);
2538872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        return;
2548872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
2558872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2566ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2578872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawLines(floats + offset, count, *paint);
2588872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2598872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2608872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawRect(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
2618872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                     jfloat right, jfloat bottom, jlong paintHandle) {
2626ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2638872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawRect(left, top, right, bottom, *paint);
2648872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2658872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
26694394b3fb048d5349a77b57950ab7f6b6e92ce34Derek Sollenbergerstatic void drawRegion(JNIEnv* env, jobject, jlong canvasHandle, jlong regionHandle,
26794394b3fb048d5349a77b57950ab7f6b6e92ce34Derek Sollenberger                       jlong paintHandle) {
26894394b3fb048d5349a77b57950ab7f6b6e92ce34Derek Sollenberger    const SkRegion* region = reinterpret_cast<SkRegion*>(regionHandle);
26994394b3fb048d5349a77b57950ab7f6b6e92ce34Derek Sollenberger    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
27094394b3fb048d5349a77b57950ab7f6b6e92ce34Derek Sollenberger    get_canvas(canvasHandle)->drawRegion(*region, *paint);
27194394b3fb048d5349a77b57950ab7f6b6e92ce34Derek Sollenberger}
27294394b3fb048d5349a77b57950ab7f6b6e92ce34Derek Sollenberger
2738872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawRoundRect(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
2748872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                          jfloat right, jfloat bottom, jfloat rx, jfloat ry, jlong paintHandle) {
2756ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2768872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawRoundRect(left, top, right, bottom, rx, ry, *paint);
2778872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2788872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2798872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawCircle(JNIEnv* env, jobject, jlong canvasHandle, jfloat cx, jfloat cy,
2808872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                       jfloat radius, jlong paintHandle) {
2816ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2828872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawCircle(cx, cy, radius, *paint);
2838872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2848872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2858872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawOval(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
2868872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                     jfloat right, jfloat bottom, jlong paintHandle) {
2876ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2888872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawOval(left, top, right, bottom, *paint);
2898872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2908872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2918872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawArc(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
2928872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                    jfloat right, jfloat bottom, jfloat startAngle, jfloat sweepAngle,
2938872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                    jboolean useCenter, jlong paintHandle) {
2946ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2958872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawArc(left, top, right, bottom, startAngle, sweepAngle,
2968872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                       useCenter, *paint);
2978872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
2988872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
2998872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle,
3008872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                     jlong paintHandle) {
3018872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
3026ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
3038872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawPath(*path, *paint);
3048872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
3058872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3068872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawVertices(JNIEnv* env, jobject, jlong canvasHandle,
3078872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                         jint modeHandle, jint vertexCount,
3088872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                         jfloatArray jverts, jint vertIndex,
3098872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                         jfloatArray jtexs, jint texIndex,
3108872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                         jintArray jcolors, jint colorIndex,
3118872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                         jshortArray jindices, jint indexIndex,
3128872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                         jint indexCount, jlong paintHandle) {
3138872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    AutoJavaFloatArray  vertA(env, jverts, vertIndex + vertexCount);
3148872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    AutoJavaFloatArray  texA(env, jtexs, texIndex + vertexCount);
3158872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    AutoJavaIntArray    colorA(env, jcolors, colorIndex + vertexCount);
3168872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    AutoJavaShortArray  indexA(env, jindices, indexIndex + indexCount);
3178872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3188872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const float* verts = vertA.ptr() + vertIndex;
3198872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const float* texs = texA.ptr() + vertIndex;
3208872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const int* colors = NULL;
3218872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const uint16_t* indices = NULL;
3228872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3238872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if (jcolors != NULL) {
3248872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        colors = colorA.ptr() + colorIndex;
3258872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
3268872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if (jindices != NULL) {
3278872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        indices = (const uint16_t*)(indexA.ptr() + indexIndex);
3288872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
3298872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3308872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkCanvas::VertexMode mode = static_cast<SkCanvas::VertexMode>(modeHandle);
3316ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
3328872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawVertices(mode, vertexCount, verts, texs, colors,
3338872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                           indices, indexCount, *paint);
3348872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
3358872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3364c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenbergerstatic void drawNinePatch(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle,
3374c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger        jlong chunkHandle, jfloat left, jfloat top, jfloat right, jfloat bottom,
3384c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger        jlong paintHandle, jint dstDensity, jint srcDensity) {
3394c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger
3404c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger    Canvas* canvas = get_canvas(canvasHandle);
3414c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger    Bitmap* bitmap = reinterpret_cast<Bitmap*>(bitmapHandle);
3424c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger    SkBitmap skiaBitmap;
3434c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger    bitmap->getSkBitmap(&skiaBitmap);
3444c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger    const android::Res_png_9patch* chunk = reinterpret_cast<android::Res_png_9patch*>(chunkHandle);
3454c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
3464c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger
3474c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger    if (CC_LIKELY(dstDensity == srcDensity || dstDensity == 0 || srcDensity == 0)) {
3484c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger        canvas->drawNinePatch(skiaBitmap, *chunk, left, top, right, bottom, paint);
3494c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger    } else {
3504c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger        canvas->save(SkCanvas::kMatrixClip_SaveFlag);
3514c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger
3524c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger        SkScalar scale = dstDensity / (float)srcDensity;
3534c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger        canvas->translate(left, top);
3544c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger        canvas->scale(scale, scale);
3554c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger
3564c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger        Paint filteredPaint;
3574c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger        if (paint) {
3584c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger            filteredPaint = *paint;
3594c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger        }
3604c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger        filteredPaint.setFilterQuality(kLow_SkFilterQuality);
3614c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger
3624c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger        canvas->drawNinePatch(skiaBitmap, *chunk, 0, 0, (right-left)/scale, (bottom-top)/scale,
3634c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger                &filteredPaint);
3644c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger
3654c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger        canvas->restore();
3664c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger    }
3674c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger}
3684c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger
3697c103a36f60b690e3fe83c40210e1cb0c76bba43John Reckstatic void drawBitmap(JNIEnv* env, jobject jcanvas, jlong canvasHandle, jobject jbitmap,
3708872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                       jfloat left, jfloat top, jlong paintHandle, jint canvasDensity,
3718872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                       jint screenDensity, jint bitmapDensity) {
3728872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    Canvas* canvas = get_canvas(canvasHandle);
3737c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    SkBitmap bitmap;
3747c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
3756ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
3768872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3778872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if (canvasDensity == bitmapDensity || canvasDensity == 0 || bitmapDensity == 0) {
3788872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        if (screenDensity != 0 && screenDensity != bitmapDensity) {
3796ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod            Paint filteredPaint;
3808872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            if (paint) {
3818872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                filteredPaint = *paint;
3828872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            }
3832a1ce8a4e5258b6599cb8e86864eb816d24d69b4Mike Reed            filteredPaint.setFilterQuality(kLow_SkFilterQuality);
3847c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck            canvas->drawBitmap(bitmap, left, top, &filteredPaint);
3858872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        } else {
3867c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck            canvas->drawBitmap(bitmap, left, top, paint);
3878872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        }
3888872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    } else {
3898872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        canvas->save(SkCanvas::kMatrixClip_SaveFlag);
3908872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        SkScalar scale = canvasDensity / (float)bitmapDensity;
3918872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        canvas->translate(left, top);
3928872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        canvas->scale(scale, scale);
3938872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
3946ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod        Paint filteredPaint;
3958872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        if (paint) {
3968872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            filteredPaint = *paint;
3978872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        }
3982a1ce8a4e5258b6599cb8e86864eb816d24d69b4Mike Reed        filteredPaint.setFilterQuality(kLow_SkFilterQuality);
3998872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
4007c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck        canvas->drawBitmap(bitmap, 0, 0, &filteredPaint);
4018872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        canvas->restore();
4028872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
4038872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
4048872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
4057c103a36f60b690e3fe83c40210e1cb0c76bba43John Reckstatic void drawBitmapMatrix(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap,
4068872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                             jlong matrixHandle, jlong paintHandle) {
4078872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
4086ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
4097c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    SkBitmap bitmap;
4107c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
4117c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    get_canvas(canvasHandle)->drawBitmap(bitmap, *matrix, paint);
4128872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
4138872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
4147c103a36f60b690e3fe83c40210e1cb0c76bba43John Reckstatic void drawBitmapRect(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap,
4158872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           float srcLeft, float srcTop, float srcRight, float srcBottom,
4168872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           float dstLeft, float dstTop, float dstRight, float dstBottom,
4178872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           jlong paintHandle, jint screenDensity, jint bitmapDensity) {
4188872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    Canvas* canvas = get_canvas(canvasHandle);
4196ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
4208872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
4217c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    SkBitmap bitmap;
4227c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
4238872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if (screenDensity != 0 && screenDensity != bitmapDensity) {
4246ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod        Paint filteredPaint;
4258872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        if (paint) {
4268872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            filteredPaint = *paint;
4278872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        }
4282a1ce8a4e5258b6599cb8e86864eb816d24d69b4Mike Reed        filteredPaint.setFilterQuality(kLow_SkFilterQuality);
4297c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck        canvas->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom,
4308872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           dstLeft, dstTop, dstRight, dstBottom, &filteredPaint);
4318872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    } else {
4327c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck        canvas->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom,
4338872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           dstLeft, dstTop, dstRight, dstBottom, paint);
4348872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
4358872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
4368872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
4378872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawBitmapArray(JNIEnv* env, jobject, jlong canvasHandle,
4388872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                            jintArray jcolors, jint offset, jint stride,
4398872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                            jfloat x, jfloat y, jint width, jint height,
4408872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                            jboolean hasAlpha, jlong paintHandle) {
4418872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    // Note: If hasAlpha is false, kRGB_565_SkColorType will be used, which will
4428872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    // correct the alphaType to kOpaque_SkAlphaType.
4438872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkImageInfo info = SkImageInfo::Make(width, height,
4448872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           hasAlpha ? kN32_SkColorType : kRGB_565_SkColorType,
4458872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           kPremul_SkAlphaType);
4468872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkBitmap bitmap;
4473d4eed7f1aa99401dabe2e45b82f98fb4fc2d754Derek Sollenberger    bitmap.setInfo(info);
4483d4eed7f1aa99401dabe2e45b82f98fb4fc2d754Derek Sollenberger    if (!GraphicsJNI::allocatePixels(env, &bitmap, NULL)) {
4498872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        return;
4508872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
4518872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
4528872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    if (!GraphicsJNI::SetPixels(env, jcolors, offset, stride, 0, 0, width, height, bitmap)) {
4538872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        return;
4548872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
4558872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
4566ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
4578872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->drawBitmap(bitmap, x, y, paint);
4588872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
4598872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
4607c103a36f60b690e3fe83c40210e1cb0c76bba43John Reckstatic void drawBitmapMesh(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap,
4618872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           jint meshWidth, jint meshHeight, jfloatArray jverts,
4628872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           jint vertIndex, jintArray jcolors, jint colorIndex, jlong paintHandle) {
4638872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const int ptCount = (meshWidth + 1) * (meshHeight + 1);
4648872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    AutoJavaFloatArray vertA(env, jverts, vertIndex + (ptCount << 1));
4658872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    AutoJavaIntArray colorA(env, jcolors, colorIndex + ptCount);
4668872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
4676ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
4687c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    SkBitmap bitmap;
4697c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
4707c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    get_canvas(canvasHandle)->drawBitmapMesh(bitmap, meshWidth, meshHeight,
4718872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                             vertA.ptr(), colorA.ptr(), paint);
4728872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
4738872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
4746578a989566e585eee053095dc80e2552e125db2Derek Sollenbergerstatic void simplifyPaint(int color, SkPaint* paint) {
4756578a989566e585eee053095dc80e2552e125db2Derek Sollenberger    paint->setColor(color);
4766578a989566e585eee053095dc80e2552e125db2Derek Sollenberger    paint->setShader(nullptr);
4776578a989566e585eee053095dc80e2552e125db2Derek Sollenberger    paint->setColorFilter(nullptr);
4786578a989566e585eee053095dc80e2552e125db2Derek Sollenberger    paint->setLooper(nullptr);
4796578a989566e585eee053095dc80e2552e125db2Derek Sollenberger    paint->setStrokeWidth(4 + 0.04 * paint->getTextSize());
4806578a989566e585eee053095dc80e2552e125db2Derek Sollenberger    paint->setStrokeJoin(SkPaint::kRound_Join);
4816578a989566e585eee053095dc80e2552e125db2Derek Sollenberger    paint->setLooper(nullptr);
4826578a989566e585eee053095dc80e2552e125db2Derek Sollenberger}
4836578a989566e585eee053095dc80e2552e125db2Derek Sollenberger
484acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenbergerclass DrawTextFunctor {
485acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenbergerpublic:
486acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    DrawTextFunctor(const Layout& layout, Canvas* canvas, uint16_t* glyphs, float* pos,
4878dfaa4904205772cdceee63ef3989bcdedf1a914Tom Hudson                    const SkPaint& paint, float x, float y, MinikinRect& bounds,
4888dfaa4904205772cdceee63ef3989bcdedf1a914Tom Hudson                    float totalAdvance)
489acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            : layout(layout), canvas(canvas), glyphs(glyphs), pos(pos), paint(paint),
4908dfaa4904205772cdceee63ef3989bcdedf1a914Tom Hudson              x(x), y(y), bounds(bounds), totalAdvance(totalAdvance) { }
491acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
492acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    void operator()(size_t start, size_t end) {
493acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        if (canvas->drawTextAbsolutePos()) {
494acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            for (size_t i = start; i < end; i++) {
495acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger                glyphs[i] = layout.getGlyphId(i);
496acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger                pos[2 * i] = x + layout.getX(i);
497acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger                pos[2 * i + 1] = y + layout.getY(i);
498acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            }
499acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        } else {
500acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            for (size_t i = start; i < end; i++) {
501acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger                glyphs[i] = layout.getGlyphId(i);
502acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger                pos[2 * i] = layout.getX(i);
503acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger                pos[2 * i + 1] = layout.getY(i);
504acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            }
505acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        }
506acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
507acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        size_t glyphCount = end - start;
5086578a989566e585eee053095dc80e2552e125db2Derek Sollenberger
5096578a989566e585eee053095dc80e2552e125db2Derek Sollenberger        if (CC_UNLIKELY(canvas->isHighContrastText())) {
5106578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            // high contrast draw path
5116578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            int color = paint.getColor();
5126578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            int channelSum = SkColorGetR(color) + SkColorGetG(color) + SkColorGetB(color);
5136578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            bool darken = channelSum < (128 * 3);
5146578a989566e585eee053095dc80e2552e125db2Derek Sollenberger
5156578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            // outline
5166578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            SkPaint outlinePaint(paint);
5176578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            simplifyPaint(darken ? SK_ColorWHITE : SK_ColorBLACK, &outlinePaint);
5186578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            outlinePaint.setStyle(SkPaint::kStrokeAndFill_Style);
5196578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            canvas->drawText(glyphs + start, pos + (2 * start), glyphCount, outlinePaint, x, y,
5206578a989566e585eee053095dc80e2552e125db2Derek Sollenberger                    bounds.mLeft, bounds.mTop, bounds.mRight, bounds.mBottom, totalAdvance);
5216578a989566e585eee053095dc80e2552e125db2Derek Sollenberger
5226578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            // inner
5236578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            SkPaint innerPaint(paint);
5246578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            simplifyPaint(darken ? SK_ColorBLACK : SK_ColorWHITE, &innerPaint);
5256578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            innerPaint.setStyle(SkPaint::kFill_Style);
5266578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            canvas->drawText(glyphs + start, pos + (2 * start), glyphCount, innerPaint, x, y,
5276578a989566e585eee053095dc80e2552e125db2Derek Sollenberger                    bounds.mLeft, bounds.mTop, bounds.mRight, bounds.mBottom, totalAdvance);
5286578a989566e585eee053095dc80e2552e125db2Derek Sollenberger        } else {
5296578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            // standard draw path
5306578a989566e585eee053095dc80e2552e125db2Derek Sollenberger            canvas->drawText(glyphs + start, pos + (2 * start), glyphCount, paint, x, y,
5316578a989566e585eee053095dc80e2552e125db2Derek Sollenberger                             bounds.mLeft, bounds.mTop, bounds.mRight, bounds.mBottom,
5326578a989566e585eee053095dc80e2552e125db2Derek Sollenberger                             totalAdvance);
5336578a989566e585eee053095dc80e2552e125db2Derek Sollenberger        }
534acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    }
535acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenbergerprivate:
536acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    const Layout& layout;
537acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    Canvas* canvas;
538acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    uint16_t* glyphs;
539acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    float* pos;
540acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    const SkPaint& paint;
541acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    float x;
542acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    float y;
543acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    MinikinRect& bounds;
5448dfaa4904205772cdceee63ef3989bcdedf1a914Tom Hudson    float totalAdvance;
545acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger};
546acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
547acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger// Same values used by Skia
548acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger#define kStdStrikeThru_Offset   (-6.0f / 21.0f)
549acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger#define kStdUnderline_Offset    (1.0f / 9.0f)
550acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger#define kStdUnderline_Thickness (1.0f / 18.0f)
551acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
552acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenbergervoid drawTextDecorations(Canvas* canvas, float x, float y, float length, const SkPaint& paint) {
553acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    uint32_t flags;
554acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    SkDrawFilter* drawFilter = canvas->getDrawFilter();
555acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    if (drawFilter) {
556acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        SkPaint paintCopy(paint);
557acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        drawFilter->filter(&paintCopy, SkDrawFilter::kText_Type);
558acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        flags = paintCopy.getFlags();
559acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    } else {
560acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        flags = paint.getFlags();
561acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    }
562acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    if (flags & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag)) {
563acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        SkScalar left = x;
564acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        SkScalar right = x + length;
565acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        float textSize = paint.getTextSize();
566acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        float strokeWidth = fmax(textSize * kStdUnderline_Thickness, 1.0f);
567acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        if (flags & SkPaint::kUnderlineText_Flag) {
568acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            SkScalar top = y + textSize * kStdUnderline_Offset - 0.5f * strokeWidth;
569acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            SkScalar bottom = y + textSize * kStdUnderline_Offset + 0.5f * strokeWidth;
570acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            canvas->drawRect(left, top, right, bottom, paint);
571acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        }
572acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        if (flags & SkPaint::kStrikeThruText_Flag) {
573acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            SkScalar top = y + textSize * kStdStrikeThru_Offset - 0.5f * strokeWidth;
574acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            SkScalar bottom = y + textSize * kStdStrikeThru_Offset + 0.5f * strokeWidth;
575acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger            canvas->drawRect(left, top, right, bottom, paint);
576acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger        }
577acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    }
578acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger}
579acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
580acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenbergervoid drawText(Canvas* canvas, const uint16_t* text, int start, int count, int contextCount,
581acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger             float x, float y, int bidiFlags, const Paint& origPaint, TypefaceImpl* typeface) {
582acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    // minikin may modify the original paint
583acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    Paint paint(origPaint);
584acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
585acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    Layout layout;
58663c5c78a72a21d57913e8601cc2a1ab72a424a02Behdad Esfahbod    MinikinUtils::doLayout(&layout, &paint, bidiFlags, typeface, text, start, count, contextCount);
587acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
588acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    size_t nGlyphs = layout.nGlyphs();
589acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    uint16_t* glyphs = new uint16_t[nGlyphs];
590acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    float* pos = new float[nGlyphs * 2];
591acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
592acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    x += MinikinUtils::xOffsetForTextAlign(&paint, layout);
593acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
594acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    MinikinRect bounds;
595acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    layout.getBounds(&bounds);
5968dfaa4904205772cdceee63ef3989bcdedf1a914Tom Hudson    if (!canvas->drawTextAbsolutePos()) {
5978dfaa4904205772cdceee63ef3989bcdedf1a914Tom Hudson        bounds.offset(x, y);
5988dfaa4904205772cdceee63ef3989bcdedf1a914Tom Hudson    }
599acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
6008dfaa4904205772cdceee63ef3989bcdedf1a914Tom Hudson    DrawTextFunctor f(layout, canvas, glyphs, pos, paint, x, y, bounds, layout.getAdvance());
601acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    MinikinUtils::forFontRun(layout, &paint, f);
602acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
603acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    drawTextDecorations(canvas, x, y, layout.getAdvance(), paint);
604acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
605acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    delete[] glyphs;
606acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    delete[] pos;
607acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger}
608acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger
6098872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawTextChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text,
6108872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                          jint index, jint count, jfloat x, jfloat y, jint bidiFlags,
6118872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                          jlong paintHandle, jlong typefaceHandle) {
6126ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
6138872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
6148872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    jchar* jchars = env->GetCharArrayElements(text, NULL);
615acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    drawText(get_canvas(canvasHandle), jchars + index, 0, count, count, x, y,
6168872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                       bidiFlags, *paint, typeface);
6178872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    env->ReleaseCharArrayElements(text, jchars, JNI_ABORT);
6188872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
6198872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6208872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawTextString(JNIEnv* env, jobject, jlong canvasHandle, jstring text,
6218872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           jint start, jint end, jfloat x, jfloat y, jint bidiFlags,
6228872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           jlong paintHandle, jlong typefaceHandle) {
6236ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
6248872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
6258872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const int count = end - start;
6268872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const jchar* jchars = env->GetStringChars(text, NULL);
627acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    drawText(get_canvas(canvasHandle), jchars + start, 0, count, count, x, y,
6288872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                       bidiFlags, *paint, typeface);
6298872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    env->ReleaseStringChars(text, jchars);
6308872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
6318872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6328872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawTextRunChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text, jint index,
6338872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                             jint count, jint contextIndex, jint contextCount, jfloat x, jfloat y,
6348872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                             jboolean isRtl, jlong paintHandle, jlong typefaceHandle) {
6356ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
6368872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
6378872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6388872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
6398872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    jchar* jchars = env->GetCharArrayElements(text, NULL);
640acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    drawText(get_canvas(canvasHandle), jchars + contextIndex, index - contextIndex, count,
6418872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                       contextCount, x, y, bidiFlags, *paint, typeface);
6428872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    env->ReleaseCharArrayElements(text, jchars, JNI_ABORT);
6438872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
6448872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6458872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawTextRunString(JNIEnv* env, jobject obj, jlong canvasHandle, jstring text,
6468872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                              jint start, jint end, jint contextStart, jint contextEnd,
6478872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                              jfloat x, jfloat y, jboolean isRtl, jlong paintHandle,
6488872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                              jlong typefaceHandle) {
6496ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
6508872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
6518872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6528872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
6538872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    jint count = end - start;
6548872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    jint contextCount = contextEnd - contextStart;
6558872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const jchar* jchars = env->GetStringChars(text, NULL);
656acb4099deff72c2c631f7110a405a3331d3e8b27Derek Sollenberger    drawText(get_canvas(canvasHandle), jchars + contextStart, start - contextStart, count,
6578872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                       contextCount, x, y, bidiFlags, *paint, typeface);
6588872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    env->ReleaseStringChars(text, jchars);
6598872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
6608872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6618872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerclass DrawTextOnPathFunctor {
6628872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerpublic:
6638872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    DrawTextOnPathFunctor(const Layout& layout, Canvas* canvas, float hOffset,
6646ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod                float vOffset, const Paint& paint, const SkPath& path)
6658872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            : layout(layout), canvas(canvas), hOffset(hOffset), vOffset(vOffset),
6668872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                paint(paint), path(path) {
6678872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
6688872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    void operator()(size_t start, size_t end) {
6698872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        uint16_t glyphs[1];
6708872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        for (size_t i = start; i < end; i++) {
6718872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            glyphs[0] = layout.getGlyphId(i);
6728872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            float x = hOffset + layout.getX(i);
6738872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            float y = vOffset + layout.getY(i);
6748872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger            canvas->drawTextOnPath(glyphs, 1, path, x, y, paint);
6758872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger        }
6768872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    }
6778872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerprivate:
6788872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const Layout& layout;
6798872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    Canvas* canvas;
6808872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    float hOffset;
6818872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    float vOffset;
6826ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const Paint& paint;
6838872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const SkPath& path;
6848872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger};
6858872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6868872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawTextOnPath(Canvas* canvas, const uint16_t* text, int count, int bidiFlags,
6878872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                           const SkPath& path, float hOffset, float vOffset,
6886ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod                           const Paint& paint, TypefaceImpl* typeface) {
6896ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint paintCopy(paint);
6908872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    Layout layout;
69163c5c78a72a21d57913e8601cc2a1ab72a424a02Behdad Esfahbod    MinikinUtils::doLayout(&layout, &paintCopy, bidiFlags, typeface, text, 0, count, count);
6928872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    hOffset += MinikinUtils::hOffsetForTextAlign(&paintCopy, layout, path);
6938872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6948872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    // Set align to left for drawing, as we don't want individual
6958872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    // glyphs centered or right-aligned; the offset above takes
6968872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    // care of all alignment.
6976ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    paintCopy.setTextAlign(Paint::kLeft_Align);
6988872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
6998872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    DrawTextOnPathFunctor f(layout, canvas, hOffset, vOffset, paintCopy, path);
7008872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    MinikinUtils::forFontRun(layout, &paintCopy, f);
7018872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
7028872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
7038872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawTextOnPathChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text,
7048872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                jint index, jint count, jlong pathHandle, jfloat hOffset,
7058872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                jfloat vOffset, jint bidiFlags, jlong paintHandle,
7068872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                jlong typefaceHandle) {
7078872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
7086ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
7098872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
7108872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
7118872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    jchar* jchars = env->GetCharArrayElements(text, NULL);
7128872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
7138872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    drawTextOnPath(get_canvas(canvasHandle), jchars + index, count, bidiFlags, *path,
7148872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                   hOffset, vOffset, *paint, typeface);
7158872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
7168872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    env->ReleaseCharArrayElements(text, jchars, 0);
7178872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
7188872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
7198872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void drawTextOnPathString(JNIEnv* env, jobject, jlong canvasHandle, jstring text,
7208872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                 jlong pathHandle, jfloat hOffset, jfloat vOffset,
7218872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                                 jint bidiFlags, jlong paintHandle, jlong typefaceHandle) {
7228872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
7236ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
7248872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
7258872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
7268872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    const jchar* jchars = env->GetStringChars(text, NULL);
7278872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    int count = env->GetStringLength(text);
7288872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
7298872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    drawTextOnPath(get_canvas(canvasHandle), jchars, count, bidiFlags, *path,
7308872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger                   hOffset, vOffset, *paint, typeface);
7318872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
7328872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    env->ReleaseStringChars(text, jchars);
7338872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
7348872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
7358872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void setDrawFilter(JNIEnv* env, jobject, jlong canvasHandle, jlong filterHandle) {
7368872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    get_canvas(canvasHandle)->setDrawFilter(reinterpret_cast<SkDrawFilter*>(filterHandle));
7378872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
7388872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
7398872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void freeCaches(JNIEnv* env, jobject) {
7408872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    SkGraphics::PurgeFontCache();
7418872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
7428872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
7438872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic void freeTextLayoutCaches(JNIEnv* env, jobject) {
7448872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    Layout::purgeCaches();
7458872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
7468872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
7478872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}; // namespace CanvasJNI
7488872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
7498872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerstatic JNINativeMethod gMethods[] = {
7508872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"finalizer", "(J)V", (void*) CanvasJNI::finalizer},
751c1b33d665c8caf5760f68c45c6ca0baa649b832aJohn Reck    {"initRaster", "(Landroid/graphics/Bitmap;)J", (void*) CanvasJNI::initRaster},
752c1b33d665c8caf5760f68c45c6ca0baa649b832aJohn Reck    {"native_setBitmap", "(JLandroid/graphics/Bitmap;)V", (void*) CanvasJNI::setBitmap},
7538872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_isOpaque","(J)Z", (void*) CanvasJNI::isOpaque},
7548872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_getWidth","(J)I", (void*) CanvasJNI::getWidth},
7558872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_getHeight","(J)I", (void*) CanvasJNI::getHeight},
7566578a989566e585eee053095dc80e2552e125db2Derek Sollenberger    {"native_setHighContrastText","(JZ)V", (void*) CanvasJNI::setHighContrastText},
7578872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_save","(JI)I", (void*) CanvasJNI::save},
7588872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_saveLayer","(JFFFFJI)I", (void*) CanvasJNI::saveLayer},
7598872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_saveLayerAlpha","(JFFFFII)I", (void*) CanvasJNI::saveLayerAlpha},
7608872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_getSaveCount","(J)I", (void*) CanvasJNI::getSaveCount},
7613891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik    {"native_restore","(JZ)V", (void*) CanvasJNI::restore},
7623891f3ad598561d5a82c07795e1fee7f1d3612d1Chris Craik    {"native_restoreToCount","(JIZ)V", (void*) CanvasJNI::restoreToCount},
7638872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_getCTM", "(JJ)V", (void*)CanvasJNI::getCTM},
7648872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_setMatrix","(JJ)V", (void*) CanvasJNI::setMatrix},
7658872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_concat","(JJ)V", (void*) CanvasJNI::concat},
7668872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_rotate","(JF)V", (void*) CanvasJNI::rotate},
7678872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_scale","(JFF)V", (void*) CanvasJNI::scale},
7688872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_skew","(JFF)V", (void*) CanvasJNI::skew},
7698872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_translate","(JFF)V", (void*) CanvasJNI::translate},
7708872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_getClipBounds","(JLandroid/graphics/Rect;)Z", (void*) CanvasJNI::getClipBounds},
7718872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_quickReject","(JJ)Z", (void*) CanvasJNI::quickRejectPath},
7728872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_quickReject","(JFFFF)Z", (void*)CanvasJNI::quickRejectRect},
7738872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_clipRect","(JFFFFI)Z", (void*) CanvasJNI::clipRect},
7748872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_clipPath","(JJI)Z", (void*) CanvasJNI::clipPath},
7758872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_clipRegion","(JJI)Z", (void*) CanvasJNI::clipRegion},
7768872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawColor","(JII)V", (void*) CanvasJNI::drawColor},
7778872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawPaint","(JJ)V", (void*) CanvasJNI::drawPaint},
7788872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawPoint", "(JFFJ)V", (void*) CanvasJNI::drawPoint},
7798872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawPoints", "(J[FIIJ)V", (void*) CanvasJNI::drawPoints},
7808872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawLine", "(JFFFFJ)V", (void*) CanvasJNI::drawLine},
7818872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawLines", "(J[FIIJ)V", (void*) CanvasJNI::drawLines},
7828872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawRect","(JFFFFJ)V", (void*) CanvasJNI::drawRect},
78394394b3fb048d5349a77b57950ab7f6b6e92ce34Derek Sollenberger    {"native_drawRegion", "(JJJ)V", (void*) CanvasJNI::drawRegion },
7848872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawRoundRect","(JFFFFFFJ)V", (void*) CanvasJNI::drawRoundRect},
7858872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawCircle","(JFFFJ)V", (void*) CanvasJNI::drawCircle},
7868872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawOval","(JFFFFJ)V", (void*) CanvasJNI::drawOval},
7878872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawArc","(JFFFFFFZJ)V", (void*) CanvasJNI::drawArc},
7888872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawPath","(JJJ)V", (void*) CanvasJNI::drawPath},
7898872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"nativeDrawVertices", "(JII[FI[FI[II[SIIJ)V", (void*)CanvasJNI::drawVertices},
7904c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger    {"native_drawNinePatch", "(JJJFFFFJII)V", (void*)CanvasJNI::drawNinePatch},
7917c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    {"native_drawBitmap","(JLandroid/graphics/Bitmap;FFJIII)V", (void*) CanvasJNI::drawBitmap},
7927c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    {"nativeDrawBitmapMatrix", "(JLandroid/graphics/Bitmap;JJ)V", (void*)CanvasJNI::drawBitmapMatrix},
7937c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    {"native_drawBitmap","(JLandroid/graphics/Bitmap;FFFFFFFFJII)V", (void*) CanvasJNI::drawBitmapRect},
7948872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawBitmap", "(J[IIIFFIIZJ)V", (void*)CanvasJNI::drawBitmapArray},
7957c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    {"nativeDrawBitmapMesh", "(JLandroid/graphics/Bitmap;II[FI[IIJ)V", (void*)CanvasJNI::drawBitmapMesh},
7968872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawText","(J[CIIFFIJJ)V", (void*) CanvasJNI::drawTextChars},
7978872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawText","(JLjava/lang/String;IIFFIJJ)V", (void*) CanvasJNI::drawTextString},
7988872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawTextRun","(J[CIIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunChars},
7998872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawTextRun","(JLjava/lang/String;IIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunString},
8008872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawTextOnPath","(J[CIIJFFIJJ)V", (void*) CanvasJNI::drawTextOnPathChars},
8018872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"native_drawTextOnPath","(JLjava/lang/String;JFFIJJ)V", (void*) CanvasJNI::drawTextOnPathString},
8028872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"nativeSetDrawFilter", "(JJ)V", (void*) CanvasJNI::setDrawFilter},
8038872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"freeCaches", "()V", (void*) CanvasJNI::freeCaches},
8048872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger    {"freeTextLayoutCaches", "()V", (void*) CanvasJNI::freeTextLayoutCaches}
8058872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger};
8068872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
8078872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenbergerint register_android_graphics_Canvas(JNIEnv* env) {
808ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    return RegisterMethodsOrDie(env, "android/graphics/Canvas", gMethods, NELEM(gMethods));
8098872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}
8108872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger
8118872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger}; // namespace android
812