android_graphics_Canvas.cpp revision b57dd722f1dc0663417da37d3a82f8283ad3c982
1500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev/* 2500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev * Copyright (C) 2014 The Android Open Source Project 3500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev * 4500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev * Licensed under the Apache License, Version 2.0 (the "License"); 5500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev * you may not use this file except in compliance with the License. 6500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev * You may obtain a copy of the License at 7500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev * 8500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev * http://www.apache.org/licenses/LICENSE-2.0 9500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev * 10500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev * Unless required by applicable law or agreed to in writing, software 11500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev * distributed under the License is distributed on an "AS IS" BASIS, 12500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev * See the License for the specific language governing permissions and 14500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev * limitations under the License. 15500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev */ 16500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 17500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev#include "jni.h" 18500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev#include "GraphicsJNI.h" 19500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev#include "core_jni_helpers.h" 20500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 21500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev#include <Canvas.h> 22500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev#include "SkDrawFilter.h" 23500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev#include "SkGraphics.h" 24500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev#include "Paint.h" 25500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev#include "TypefaceImpl.h" 26500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 27500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev#include "MinikinUtils.h" 28500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 29500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievnamespace android { 30500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 31500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievnamespace CanvasJNI { 32500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 33500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievstatic Canvas* get_canvas(jlong canvasHandle) { 34500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev return reinterpret_cast<Canvas*>(canvasHandle); 35500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev} 36500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 37500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievstatic void finalizer(JNIEnv* env, jobject clazz, jlong canvasHandle) { 38500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev delete get_canvas(canvasHandle); 39500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev} 40500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 41500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev// Native wrapper constructor used by Canvas(Bitmap) 42500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievstatic jlong initRaster(JNIEnv* env, jobject, jobject jbitmap) { 43500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev SkBitmap bitmap; 44500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev if (jbitmap != NULL) { 45500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); 46500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev } 47500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev return reinterpret_cast<jlong>(Canvas::create_canvas(bitmap)); 48500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev} 49b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger 50b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger// Set the given bitmap as the new draw target (wrapped in a new SkCanvas), 51189e87498f666e94dc8c8201e7bac56bb09b9251Derek Sollenberger// optionally copying canvas matrix & clip state. 52189e87498f666e94dc8c8201e7bac56bb09b9251Derek Sollenbergerstatic void setBitmap(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap) { 53189e87498f666e94dc8c8201e7bac56bb09b9251Derek Sollenberger SkBitmap bitmap; 54189e87498f666e94dc8c8201e7bac56bb09b9251Derek Sollenberger if (jbitmap != NULL) { 55189e87498f666e94dc8c8201e7bac56bb09b9251Derek Sollenberger GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); 56b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger } 57b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger get_canvas(canvasHandle)->setBitmap(bitmap); 58b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger} 59b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger 60b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenbergerstatic jboolean isOpaque(JNIEnv*, jobject, jlong canvasHandle) { 61b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger return get_canvas(canvasHandle)->isOpaque() ? JNI_TRUE : JNI_FALSE; 62b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger} 63b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger 64b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenbergerstatic jint getWidth(JNIEnv*, jobject, jlong canvasHandle) { 65b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger return static_cast<jint>(get_canvas(canvasHandle)->width()); 66b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger} 67500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 68500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievstatic jint getHeight(JNIEnv*, jobject, jlong canvasHandle) { 69500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev return static_cast<jint>(get_canvas(canvasHandle)->height()); 70500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev} 71500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 72500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievstatic jint getSaveCount(JNIEnv*, jobject, jlong canvasHandle) { 73500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev return static_cast<jint>(get_canvas(canvasHandle)->getSaveCount()); 74500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev} 75500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 76500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievstatic jint save(JNIEnv*, jobject, jlong canvasHandle, jint flagsHandle) { 77500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle); 78500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev return static_cast<jint>(get_canvas(canvasHandle)->save(flags)); 79500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev} 80500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 81500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievstatic jint saveLayer(JNIEnv* env, jobject, jlong canvasHandle, jfloat l, jfloat t, 82500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev jfloat r, jfloat b, jlong paintHandle, jint flagsHandle) { 83500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev Paint* paint = reinterpret_cast<Paint*>(paintHandle); 84500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle); 85500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev return static_cast<jint>(get_canvas(canvasHandle)->saveLayer(l, t, r, b, paint, flags)); 86500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev} 87500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 88500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievstatic jint saveLayerAlpha(JNIEnv* env, jobject, jlong canvasHandle, jfloat l, jfloat t, 89500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev jfloat r, jfloat b, jint alpha, jint flagsHandle) { 90500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle); 91500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev return static_cast<jint>(get_canvas(canvasHandle)->saveLayerAlpha(l, t, r, b, alpha, flags)); 92500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev} 93500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 94500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievstatic void restore(JNIEnv* env, jobject, jlong canvasHandle, jboolean throwOnUnderflow) { 95500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev Canvas* canvas = get_canvas(canvasHandle); 96500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev if (canvas->getSaveCount() <= 1) { // cannot restore anymore 97500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev if (throwOnUnderflow) { 98500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev doThrowISE(env, "Underflow in restore - more restores than saves"); 99500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev } 100500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev return; // compat behavior - return without throwing 101500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev } 102500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev canvas->restore(); 103500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev} 104500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 105500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievstatic void restoreToCount(JNIEnv* env, jobject, jlong canvasHandle, jint restoreCount, 106500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev jboolean throwOnUnderflow) { 107500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev Canvas* canvas = get_canvas(canvasHandle); 108500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev if (restoreCount < 1 || restoreCount > canvas->getSaveCount()) { 109500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev if (throwOnUnderflow) { 110500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev doThrowIAE(env, "Underflow in restoreToCount - more restores than saves"); 111500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev return; 112500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev } 113500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev restoreCount = 1; // compat behavior - restore as far as possible 114500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev } 115500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev canvas->restoreToCount(restoreCount); 116500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev} 117500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 118500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievstatic void getCTM(JNIEnv* env, jobject, jlong canvasHandle, jlong matrixHandle) { 119500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle); 120500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev get_canvas(canvasHandle)->getMatrix(matrix); 121500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev} 122500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 123500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievstatic void setMatrix(JNIEnv* env, jobject, jlong canvasHandle, jlong matrixHandle) { 124500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle); 125500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev get_canvas(canvasHandle)->setMatrix(matrix ? *matrix : SkMatrix::I()); 126500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev} 127500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 128500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievstatic void concat(JNIEnv* env, jobject, jlong canvasHandle, jlong matrixHandle) { 129500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle); 130500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev get_canvas(canvasHandle)->concat(*matrix); 131500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev} 132500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 133500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievstatic void rotate(JNIEnv*, jobject, jlong canvasHandle, jfloat degrees) { 134500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev get_canvas(canvasHandle)->rotate(degrees); 135500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev} 136500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 137500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievstatic void scale(JNIEnv*, jobject, jlong canvasHandle, jfloat sx, jfloat sy) { 138500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev get_canvas(canvasHandle)->scale(sx, sy); 139500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev} 140500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 141500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievstatic void skew(JNIEnv*, jobject, jlong canvasHandle, jfloat sx, jfloat sy) { 142500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev get_canvas(canvasHandle)->skew(sx, sy); 143500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev} 144500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 145500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievstatic void translate(JNIEnv*, jobject, jlong canvasHandle, jfloat dx, jfloat dy) { 146500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev get_canvas(canvasHandle)->translate(dx, dy); 147500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev} 148500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 149500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievstatic jboolean getClipBounds(JNIEnv* env, jobject, jlong canvasHandle, jobject bounds) { 150500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev SkRect r; 151500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev SkIRect ir; 152500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev bool result = get_canvas(canvasHandle)->getClipBounds(&r); 153500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 154500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev if (!result) { 155500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev r.setEmpty(); 156500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev } 157500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev r.round(&ir); 158500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 159500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev (void)GraphicsJNI::irect_to_jrect(ir, env, bounds); 160500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev return result ? JNI_TRUE : JNI_FALSE; 161500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev} 162500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 163500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievstatic jboolean quickRejectRect(JNIEnv* env, jobject, jlong canvasHandle, 164500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev jfloat left, jfloat top, jfloat right, jfloat bottom) { 165500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev bool result = get_canvas(canvasHandle)->quickRejectRect(left, top, right, bottom); 166500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev return result ? JNI_TRUE : JNI_FALSE; 167500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev} 168500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 169500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievstatic jboolean quickRejectPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle) { 170500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev SkPath* path = reinterpret_cast<SkPath*>(pathHandle); 171500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev bool result = get_canvas(canvasHandle)->quickRejectPath(*path); 172500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev return result ? JNI_TRUE : JNI_FALSE; 173500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev} 174500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 175500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievstatic jboolean clipRect(JNIEnv*, jobject, jlong canvasHandle, jfloat l, jfloat t, 176500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev jfloat r, jfloat b, jint opHandle) { 177500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev SkRegion::Op op = static_cast<SkRegion::Op>(opHandle); 178500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev bool nonEmptyClip = get_canvas(canvasHandle)->clipRect(l, t, r, b, op); 179500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev return nonEmptyClip ? JNI_TRUE : JNI_FALSE; 180500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev} 181500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 182500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievstatic jboolean clipPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle, 183500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev jint opHandle) { 184500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev SkPath* path = reinterpret_cast<SkPath*>(pathHandle); 185500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev SkRegion::Op op = static_cast<SkRegion::Op>(opHandle); 186500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev bool nonEmptyClip = get_canvas(canvasHandle)->clipPath(path, op); 187500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev return nonEmptyClip ? JNI_TRUE : JNI_FALSE; 188500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev} 189500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 190500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievstatic jboolean clipRegion(JNIEnv* env, jobject, jlong canvasHandle, jlong deviceRgnHandle, 191500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev jint opHandle) { 192500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev SkRegion* deviceRgn = reinterpret_cast<SkRegion*>(deviceRgnHandle); 193500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev SkRegion::Op op = static_cast<SkRegion::Op>(opHandle); 194500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev bool nonEmptyClip = get_canvas(canvasHandle)->clipRegion(deviceRgn, op); 195500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev return nonEmptyClip ? JNI_TRUE : JNI_FALSE; 196500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev} 197500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 198500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievstatic void drawColor(JNIEnv* env, jobject, jlong canvasHandle, jint color, jint modeHandle) { 199500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(modeHandle); 200500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev get_canvas(canvasHandle)->drawColor(color, mode); 201500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev} 202500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 203500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievstatic void drawPaint(JNIEnv* env, jobject, jlong canvasHandle, jlong paintHandle) { 204500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev Paint* paint = reinterpret_cast<Paint*>(paintHandle); 205500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev get_canvas(canvasHandle)->drawPaint(*paint); 206500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev} 207500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 208500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievstatic void drawPoint(JNIEnv*, jobject, jlong canvasHandle, jfloat x, jfloat y, 209500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev jlong paintHandle) { 210500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 211500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev get_canvas(canvasHandle)->drawPoint(x, y, *paint); 212500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev} 213500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 214500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievstatic void drawPoints(JNIEnv* env, jobject, jlong canvasHandle, jfloatArray jptsArray, 215500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev jint offset, jint count, jlong paintHandle) { 216500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev NPE_CHECK_RETURN_VOID(env, jptsArray); 217500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev AutoJavaFloatArray autoPts(env, jptsArray); 218500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev float* floats = autoPts.ptr(); 219500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev const int length = autoPts.length(); 220500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 221500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev if ((offset | count) < 0 || offset + count > length) { 222500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev doThrowAIOOBE(env); 223500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev return; 224500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev } 225500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 226500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 227500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev get_canvas(canvasHandle)->drawPoints(floats + offset, count, *paint); 228500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev} 229500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 230500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievstatic void drawLine(JNIEnv* env, jobject, jlong canvasHandle, jfloat startX, jfloat startY, 231500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev jfloat stopX, jfloat stopY, jlong paintHandle) { 232500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev Paint* paint = reinterpret_cast<Paint*>(paintHandle); 233500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev get_canvas(canvasHandle)->drawLine(startX, startY, stopX, stopY, *paint); 234500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev} 235500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 236500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievstatic void drawLines(JNIEnv* env, jobject, jlong canvasHandle, jfloatArray jptsArray, 237500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev jint offset, jint count, jlong paintHandle) { 238500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev NPE_CHECK_RETURN_VOID(env, jptsArray); 239500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev AutoJavaFloatArray autoPts(env, jptsArray); 240500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev float* floats = autoPts.ptr(); 241500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev const int length = autoPts.length(); 242500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 243500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev if ((offset | count) < 0 || offset + count > length) { 244500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev doThrowAIOOBE(env); 245500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev return; 246500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev } 247500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 248500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 249500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev get_canvas(canvasHandle)->drawLines(floats + offset, count, *paint); 250500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev} 251500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 252500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievstatic void drawRect(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top, 253500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev jfloat right, jfloat bottom, jlong paintHandle) { 254500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 255500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev get_canvas(canvasHandle)->drawRect(left, top, right, bottom, *paint); 256500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev} 257500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 258500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievstatic void drawRoundRect(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top, 259500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev jfloat right, jfloat bottom, jfloat rx, jfloat ry, jlong paintHandle) { 260500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 261500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev get_canvas(canvasHandle)->drawRoundRect(left, top, right, bottom, rx, ry, *paint); 262500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev} 263500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 264500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievstatic void drawCircle(JNIEnv* env, jobject, jlong canvasHandle, jfloat cx, jfloat cy, 265500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev jfloat radius, jlong paintHandle) { 266500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 267500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev get_canvas(canvasHandle)->drawCircle(cx, cy, radius, *paint); 268500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev} 269500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 270500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievstatic void drawOval(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top, 2714bda6bfaa6b8cb775f18f2453720d05f4cb29152Matt Sarett jfloat right, jfloat bottom, jlong paintHandle) { 2724bda6bfaa6b8cb775f18f2453720d05f4cb29152Matt Sarett const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 2734bda6bfaa6b8cb775f18f2453720d05f4cb29152Matt Sarett get_canvas(canvasHandle)->drawOval(left, top, right, bottom, *paint); 2744bda6bfaa6b8cb775f18f2453720d05f4cb29152Matt Sarett} 2754bda6bfaa6b8cb775f18f2453720d05f4cb29152Matt Sarett 2764bda6bfaa6b8cb775f18f2453720d05f4cb29152Matt Sarettstatic void drawArc(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top, 2774bda6bfaa6b8cb775f18f2453720d05f4cb29152Matt Sarett jfloat right, jfloat bottom, jfloat startAngle, jfloat sweepAngle, 2784bda6bfaa6b8cb775f18f2453720d05f4cb29152Matt Sarett jboolean useCenter, jlong paintHandle) { 2794bda6bfaa6b8cb775f18f2453720d05f4cb29152Matt Sarett const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 2804bda6bfaa6b8cb775f18f2453720d05f4cb29152Matt Sarett get_canvas(canvasHandle)->drawArc(left, top, right, bottom, startAngle, sweepAngle, 2814bda6bfaa6b8cb775f18f2453720d05f4cb29152Matt Sarett useCenter, *paint); 2824bda6bfaa6b8cb775f18f2453720d05f4cb29152Matt Sarett} 2834bda6bfaa6b8cb775f18f2453720d05f4cb29152Matt Sarett 2844bda6bfaa6b8cb775f18f2453720d05f4cb29152Matt Sarettstatic void drawPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle, 285500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev jlong paintHandle) { 286500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev const SkPath* path = reinterpret_cast<SkPath*>(pathHandle); 287500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 288 get_canvas(canvasHandle)->drawPath(*path, *paint); 289} 290 291static void drawVertices(JNIEnv* env, jobject, jlong canvasHandle, 292 jint modeHandle, jint vertexCount, 293 jfloatArray jverts, jint vertIndex, 294 jfloatArray jtexs, jint texIndex, 295 jintArray jcolors, jint colorIndex, 296 jshortArray jindices, jint indexIndex, 297 jint indexCount, jlong paintHandle) { 298 AutoJavaFloatArray vertA(env, jverts, vertIndex + vertexCount); 299 AutoJavaFloatArray texA(env, jtexs, texIndex + vertexCount); 300 AutoJavaIntArray colorA(env, jcolors, colorIndex + vertexCount); 301 AutoJavaShortArray indexA(env, jindices, indexIndex + indexCount); 302 303 const float* verts = vertA.ptr() + vertIndex; 304 const float* texs = texA.ptr() + vertIndex; 305 const int* colors = NULL; 306 const uint16_t* indices = NULL; 307 308 if (jcolors != NULL) { 309 colors = colorA.ptr() + colorIndex; 310 } 311 if (jindices != NULL) { 312 indices = (const uint16_t*)(indexA.ptr() + indexIndex); 313 } 314 315 SkCanvas::VertexMode mode = static_cast<SkCanvas::VertexMode>(modeHandle); 316 const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 317 get_canvas(canvasHandle)->drawVertices(mode, vertexCount, verts, texs, colors, 318 indices, indexCount, *paint); 319} 320 321static void drawBitmap(JNIEnv* env, jobject jcanvas, jlong canvasHandle, jobject jbitmap, 322 jfloat left, jfloat top, jlong paintHandle, jint canvasDensity, 323 jint screenDensity, jint bitmapDensity) { 324 Canvas* canvas = get_canvas(canvasHandle); 325 SkBitmap bitmap; 326 GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); 327 const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 328 329 if (canvasDensity == bitmapDensity || canvasDensity == 0 || bitmapDensity == 0) { 330 if (screenDensity != 0 && screenDensity != bitmapDensity) { 331 Paint filteredPaint; 332 if (paint) { 333 filteredPaint = *paint; 334 } 335 filteredPaint.setFilterQuality(kLow_SkFilterQuality); 336 canvas->drawBitmap(bitmap, left, top, &filteredPaint); 337 } else { 338 canvas->drawBitmap(bitmap, left, top, paint); 339 } 340 } else { 341 canvas->save(SkCanvas::kMatrixClip_SaveFlag); 342 SkScalar scale = canvasDensity / (float)bitmapDensity; 343 canvas->translate(left, top); 344 canvas->scale(scale, scale); 345 346 Paint filteredPaint; 347 if (paint) { 348 filteredPaint = *paint; 349 } 350 filteredPaint.setFilterQuality(kLow_SkFilterQuality); 351 352 canvas->drawBitmap(bitmap, 0, 0, &filteredPaint); 353 canvas->restore(); 354 } 355} 356 357static void drawBitmapMatrix(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap, 358 jlong matrixHandle, jlong paintHandle) { 359 const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle); 360 const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 361 SkBitmap bitmap; 362 GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); 363 get_canvas(canvasHandle)->drawBitmap(bitmap, *matrix, paint); 364} 365 366static void drawBitmapRect(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap, 367 float srcLeft, float srcTop, float srcRight, float srcBottom, 368 float dstLeft, float dstTop, float dstRight, float dstBottom, 369 jlong paintHandle, jint screenDensity, jint bitmapDensity) { 370 Canvas* canvas = get_canvas(canvasHandle); 371 const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 372 373 SkBitmap bitmap; 374 GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); 375 if (screenDensity != 0 && screenDensity != bitmapDensity) { 376 Paint filteredPaint; 377 if (paint) { 378 filteredPaint = *paint; 379 } 380 filteredPaint.setFilterQuality(kLow_SkFilterQuality); 381 canvas->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom, 382 dstLeft, dstTop, dstRight, dstBottom, &filteredPaint); 383 } else { 384 canvas->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom, 385 dstLeft, dstTop, dstRight, dstBottom, paint); 386 } 387} 388 389static void drawBitmapArray(JNIEnv* env, jobject, jlong canvasHandle, 390 jintArray jcolors, jint offset, jint stride, 391 jfloat x, jfloat y, jint width, jint height, 392 jboolean hasAlpha, jlong paintHandle) { 393 // Note: If hasAlpha is false, kRGB_565_SkColorType will be used, which will 394 // correct the alphaType to kOpaque_SkAlphaType. 395 SkImageInfo info = SkImageInfo::Make(width, height, 396 hasAlpha ? kN32_SkColorType : kRGB_565_SkColorType, 397 kPremul_SkAlphaType); 398 SkBitmap bitmap; 399 bitmap.setInfo(info); 400 if (!GraphicsJNI::allocatePixels(env, &bitmap, NULL)) { 401 return; 402 } 403 404 if (!GraphicsJNI::SetPixels(env, jcolors, offset, stride, 0, 0, width, height, bitmap)) { 405 return; 406 } 407 408 const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 409 get_canvas(canvasHandle)->drawBitmap(bitmap, x, y, paint); 410} 411 412static void drawBitmapMesh(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap, 413 jint meshWidth, jint meshHeight, jfloatArray jverts, 414 jint vertIndex, jintArray jcolors, jint colorIndex, jlong paintHandle) { 415 const int ptCount = (meshWidth + 1) * (meshHeight + 1); 416 AutoJavaFloatArray vertA(env, jverts, vertIndex + (ptCount << 1)); 417 AutoJavaIntArray colorA(env, jcolors, colorIndex + ptCount); 418 419 const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 420 SkBitmap bitmap; 421 GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); 422 get_canvas(canvasHandle)->drawBitmapMesh(bitmap, meshWidth, meshHeight, 423 vertA.ptr(), colorA.ptr(), paint); 424} 425 426class DrawTextFunctor { 427public: 428 DrawTextFunctor(const Layout& layout, Canvas* canvas, uint16_t* glyphs, float* pos, 429 const SkPaint& paint, float x, float y, MinikinRect& bounds, 430 float totalAdvance) 431 : layout(layout), canvas(canvas), glyphs(glyphs), pos(pos), paint(paint), 432 x(x), y(y), bounds(bounds), totalAdvance(totalAdvance) { } 433 434 void operator()(size_t start, size_t end) { 435 if (canvas->drawTextAbsolutePos()) { 436 for (size_t i = start; i < end; i++) { 437 glyphs[i] = layout.getGlyphId(i); 438 pos[2 * i] = x + layout.getX(i); 439 pos[2 * i + 1] = y + layout.getY(i); 440 } 441 } else { 442 for (size_t i = start; i < end; i++) { 443 glyphs[i] = layout.getGlyphId(i); 444 pos[2 * i] = layout.getX(i); 445 pos[2 * i + 1] = layout.getY(i); 446 } 447 } 448 449 size_t glyphCount = end - start; 450 canvas->drawText(glyphs + start, pos + (2 * start), glyphCount, paint, x, y, 451 bounds.mLeft, bounds.mTop, bounds.mRight, bounds.mBottom, 452 totalAdvance); 453 } 454private: 455 const Layout& layout; 456 Canvas* canvas; 457 uint16_t* glyphs; 458 float* pos; 459 const SkPaint& paint; 460 float x; 461 float y; 462 MinikinRect& bounds; 463 float totalAdvance; 464}; 465 466// Same values used by Skia 467#define kStdStrikeThru_Offset (-6.0f / 21.0f) 468#define kStdUnderline_Offset (1.0f / 9.0f) 469#define kStdUnderline_Thickness (1.0f / 18.0f) 470 471void drawTextDecorations(Canvas* canvas, float x, float y, float length, const SkPaint& paint) { 472 uint32_t flags; 473 SkDrawFilter* drawFilter = canvas->getDrawFilter(); 474 if (drawFilter) { 475 SkPaint paintCopy(paint); 476 drawFilter->filter(&paintCopy, SkDrawFilter::kText_Type); 477 flags = paintCopy.getFlags(); 478 } else { 479 flags = paint.getFlags(); 480 } 481 if (flags & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag)) { 482 SkScalar left = x; 483 SkScalar right = x + length; 484 float textSize = paint.getTextSize(); 485 float strokeWidth = fmax(textSize * kStdUnderline_Thickness, 1.0f); 486 if (flags & SkPaint::kUnderlineText_Flag) { 487 SkScalar top = y + textSize * kStdUnderline_Offset - 0.5f * strokeWidth; 488 SkScalar bottom = y + textSize * kStdUnderline_Offset + 0.5f * strokeWidth; 489 canvas->drawRect(left, top, right, bottom, paint); 490 } 491 if (flags & SkPaint::kStrikeThruText_Flag) { 492 SkScalar top = y + textSize * kStdStrikeThru_Offset - 0.5f * strokeWidth; 493 SkScalar bottom = y + textSize * kStdStrikeThru_Offset + 0.5f * strokeWidth; 494 canvas->drawRect(left, top, right, bottom, paint); 495 } 496 } 497} 498 499void drawText(Canvas* canvas, const uint16_t* text, int start, int count, int contextCount, 500 float x, float y, int bidiFlags, const Paint& origPaint, TypefaceImpl* typeface) { 501 // minikin may modify the original paint 502 Paint paint(origPaint); 503 504 Layout layout; 505 MinikinUtils::doLayout(&layout, &paint, bidiFlags, typeface, text, start, count, contextCount); 506 507 size_t nGlyphs = layout.nGlyphs(); 508 uint16_t* glyphs = new uint16_t[nGlyphs]; 509 float* pos = new float[nGlyphs * 2]; 510 511 x += MinikinUtils::xOffsetForTextAlign(&paint, layout); 512 513 MinikinRect bounds; 514 layout.getBounds(&bounds); 515 if (!canvas->drawTextAbsolutePos()) { 516 bounds.offset(x, y); 517 } 518 519 DrawTextFunctor f(layout, canvas, glyphs, pos, paint, x, y, bounds, layout.getAdvance()); 520 MinikinUtils::forFontRun(layout, &paint, f); 521 522 drawTextDecorations(canvas, x, y, layout.getAdvance(), paint); 523 524 delete[] glyphs; 525 delete[] pos; 526} 527 528static void drawTextChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text, 529 jint index, jint count, jfloat x, jfloat y, jint bidiFlags, 530 jlong paintHandle, jlong typefaceHandle) { 531 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 532 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle); 533 jchar* jchars = env->GetCharArrayElements(text, NULL); 534 drawText(get_canvas(canvasHandle), jchars + index, 0, count, count, x, y, 535 bidiFlags, *paint, typeface); 536 env->ReleaseCharArrayElements(text, jchars, JNI_ABORT); 537} 538 539static void drawTextString(JNIEnv* env, jobject, jlong canvasHandle, jstring text, 540 jint start, jint end, jfloat x, jfloat y, jint bidiFlags, 541 jlong paintHandle, jlong typefaceHandle) { 542 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 543 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle); 544 const int count = end - start; 545 const jchar* jchars = env->GetStringChars(text, NULL); 546 drawText(get_canvas(canvasHandle), jchars + start, 0, count, count, x, y, 547 bidiFlags, *paint, typeface); 548 env->ReleaseStringChars(text, jchars); 549} 550 551static void drawTextRunChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text, jint index, 552 jint count, jint contextIndex, jint contextCount, jfloat x, jfloat y, 553 jboolean isRtl, jlong paintHandle, jlong typefaceHandle) { 554 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 555 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle); 556 557 const int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR; 558 jchar* jchars = env->GetCharArrayElements(text, NULL); 559 drawText(get_canvas(canvasHandle), jchars + contextIndex, index - contextIndex, count, 560 contextCount, x, y, bidiFlags, *paint, typeface); 561 env->ReleaseCharArrayElements(text, jchars, JNI_ABORT); 562} 563 564static void drawTextRunString(JNIEnv* env, jobject obj, jlong canvasHandle, jstring text, 565 jint start, jint end, jint contextStart, jint contextEnd, 566 jfloat x, jfloat y, jboolean isRtl, jlong paintHandle, 567 jlong typefaceHandle) { 568 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 569 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle); 570 571 int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR; 572 jint count = end - start; 573 jint contextCount = contextEnd - contextStart; 574 const jchar* jchars = env->GetStringChars(text, NULL); 575 drawText(get_canvas(canvasHandle), jchars + contextStart, start - contextStart, count, 576 contextCount, x, y, bidiFlags, *paint, typeface); 577 env->ReleaseStringChars(text, jchars); 578} 579 580class DrawTextOnPathFunctor { 581public: 582 DrawTextOnPathFunctor(const Layout& layout, Canvas* canvas, float hOffset, 583 float vOffset, const Paint& paint, const SkPath& path) 584 : layout(layout), canvas(canvas), hOffset(hOffset), vOffset(vOffset), 585 paint(paint), path(path) { 586 } 587 void operator()(size_t start, size_t end) { 588 uint16_t glyphs[1]; 589 for (size_t i = start; i < end; i++) { 590 glyphs[0] = layout.getGlyphId(i); 591 float x = hOffset + layout.getX(i); 592 float y = vOffset + layout.getY(i); 593 canvas->drawTextOnPath(glyphs, 1, path, x, y, paint); 594 } 595 } 596private: 597 const Layout& layout; 598 Canvas* canvas; 599 float hOffset; 600 float vOffset; 601 const Paint& paint; 602 const SkPath& path; 603}; 604 605static void drawTextOnPath(Canvas* canvas, const uint16_t* text, int count, int bidiFlags, 606 const SkPath& path, float hOffset, float vOffset, 607 const Paint& paint, TypefaceImpl* typeface) { 608 Paint paintCopy(paint); 609 Layout layout; 610 MinikinUtils::doLayout(&layout, &paintCopy, bidiFlags, typeface, text, 0, count, count); 611 hOffset += MinikinUtils::hOffsetForTextAlign(&paintCopy, layout, path); 612 613 // Set align to left for drawing, as we don't want individual 614 // glyphs centered or right-aligned; the offset above takes 615 // care of all alignment. 616 paintCopy.setTextAlign(Paint::kLeft_Align); 617 618 DrawTextOnPathFunctor f(layout, canvas, hOffset, vOffset, paintCopy, path); 619 MinikinUtils::forFontRun(layout, &paintCopy, f); 620} 621 622static void drawTextOnPathChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text, 623 jint index, jint count, jlong pathHandle, jfloat hOffset, 624 jfloat vOffset, jint bidiFlags, jlong paintHandle, 625 jlong typefaceHandle) { 626 SkPath* path = reinterpret_cast<SkPath*>(pathHandle); 627 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 628 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle); 629 630 jchar* jchars = env->GetCharArrayElements(text, NULL); 631 632 drawTextOnPath(get_canvas(canvasHandle), jchars + index, count, bidiFlags, *path, 633 hOffset, vOffset, *paint, typeface); 634 635 env->ReleaseCharArrayElements(text, jchars, 0); 636} 637 638static void drawTextOnPathString(JNIEnv* env, jobject, jlong canvasHandle, jstring text, 639 jlong pathHandle, jfloat hOffset, jfloat vOffset, 640 jint bidiFlags, jlong paintHandle, jlong typefaceHandle) { 641 SkPath* path = reinterpret_cast<SkPath*>(pathHandle); 642 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 643 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle); 644 645 const jchar* jchars = env->GetStringChars(text, NULL); 646 int count = env->GetStringLength(text); 647 648 drawTextOnPath(get_canvas(canvasHandle), jchars, count, bidiFlags, *path, 649 hOffset, vOffset, *paint, typeface); 650 651 env->ReleaseStringChars(text, jchars); 652} 653 654static void setDrawFilter(JNIEnv* env, jobject, jlong canvasHandle, jlong filterHandle) { 655 get_canvas(canvasHandle)->setDrawFilter(reinterpret_cast<SkDrawFilter*>(filterHandle)); 656} 657 658static void freeCaches(JNIEnv* env, jobject) { 659 SkGraphics::PurgeFontCache(); 660} 661 662static void freeTextLayoutCaches(JNIEnv* env, jobject) { 663 Layout::purgeCaches(); 664} 665 666}; // namespace CanvasJNI 667 668static const JNINativeMethod gMethods[] = { 669 {"finalizer", "(J)V", (void*) CanvasJNI::finalizer}, 670 {"initRaster", "(Landroid/graphics/Bitmap;)J", (void*) CanvasJNI::initRaster}, 671 {"native_setBitmap", "(JLandroid/graphics/Bitmap;)V", (void*) CanvasJNI::setBitmap}, 672 {"native_isOpaque","(J)Z", (void*) CanvasJNI::isOpaque}, 673 {"native_getWidth","(J)I", (void*) CanvasJNI::getWidth}, 674 {"native_getHeight","(J)I", (void*) CanvasJNI::getHeight}, 675 {"native_save","(JI)I", (void*) CanvasJNI::save}, 676 {"native_saveLayer","(JFFFFJI)I", (void*) CanvasJNI::saveLayer}, 677 {"native_saveLayerAlpha","(JFFFFII)I", (void*) CanvasJNI::saveLayerAlpha}, 678 {"native_getSaveCount","(J)I", (void*) CanvasJNI::getSaveCount}, 679 {"native_restore","(JZ)V", (void*) CanvasJNI::restore}, 680 {"native_restoreToCount","(JIZ)V", (void*) CanvasJNI::restoreToCount}, 681 {"native_getCTM", "(JJ)V", (void*)CanvasJNI::getCTM}, 682 {"native_setMatrix","(JJ)V", (void*) CanvasJNI::setMatrix}, 683 {"native_concat","(JJ)V", (void*) CanvasJNI::concat}, 684 {"native_rotate","(JF)V", (void*) CanvasJNI::rotate}, 685 {"native_scale","(JFF)V", (void*) CanvasJNI::scale}, 686 {"native_skew","(JFF)V", (void*) CanvasJNI::skew}, 687 {"native_translate","(JFF)V", (void*) CanvasJNI::translate}, 688 {"native_getClipBounds","(JLandroid/graphics/Rect;)Z", (void*) CanvasJNI::getClipBounds}, 689 {"native_quickReject","(JJ)Z", (void*) CanvasJNI::quickRejectPath}, 690 {"native_quickReject","(JFFFF)Z", (void*)CanvasJNI::quickRejectRect}, 691 {"native_clipRect","(JFFFFI)Z", (void*) CanvasJNI::clipRect}, 692 {"native_clipPath","(JJI)Z", (void*) CanvasJNI::clipPath}, 693 {"native_clipRegion","(JJI)Z", (void*) CanvasJNI::clipRegion}, 694 {"native_drawColor","(JII)V", (void*) CanvasJNI::drawColor}, 695 {"native_drawPaint","(JJ)V", (void*) CanvasJNI::drawPaint}, 696 {"native_drawPoint", "(JFFJ)V", (void*) CanvasJNI::drawPoint}, 697 {"native_drawPoints", "(J[FIIJ)V", (void*) CanvasJNI::drawPoints}, 698 {"native_drawLine", "(JFFFFJ)V", (void*) CanvasJNI::drawLine}, 699 {"native_drawLines", "(J[FIIJ)V", (void*) CanvasJNI::drawLines}, 700 {"native_drawRect","(JFFFFJ)V", (void*) CanvasJNI::drawRect}, 701 {"native_drawRoundRect","(JFFFFFFJ)V", (void*) CanvasJNI::drawRoundRect}, 702 {"native_drawCircle","(JFFFJ)V", (void*) CanvasJNI::drawCircle}, 703 {"native_drawOval","(JFFFFJ)V", (void*) CanvasJNI::drawOval}, 704 {"native_drawArc","(JFFFFFFZJ)V", (void*) CanvasJNI::drawArc}, 705 {"native_drawPath","(JJJ)V", (void*) CanvasJNI::drawPath}, 706 {"nativeDrawVertices", "(JII[FI[FI[II[SIIJ)V", (void*)CanvasJNI::drawVertices}, 707 {"native_drawBitmap","(JLandroid/graphics/Bitmap;FFJIII)V", (void*) CanvasJNI::drawBitmap}, 708 {"nativeDrawBitmapMatrix", "(JLandroid/graphics/Bitmap;JJ)V", (void*)CanvasJNI::drawBitmapMatrix}, 709 {"native_drawBitmap","(JLandroid/graphics/Bitmap;FFFFFFFFJII)V", (void*) CanvasJNI::drawBitmapRect}, 710 {"native_drawBitmap", "(J[IIIFFIIZJ)V", (void*)CanvasJNI::drawBitmapArray}, 711 {"nativeDrawBitmapMesh", "(JLandroid/graphics/Bitmap;II[FI[IIJ)V", (void*)CanvasJNI::drawBitmapMesh}, 712 {"native_drawText","(J[CIIFFIJJ)V", (void*) CanvasJNI::drawTextChars}, 713 {"native_drawText","(JLjava/lang/String;IIFFIJJ)V", (void*) CanvasJNI::drawTextString}, 714 {"native_drawTextRun","(J[CIIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunChars}, 715 {"native_drawTextRun","(JLjava/lang/String;IIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunString}, 716 {"native_drawTextOnPath","(J[CIIJFFIJJ)V", (void*) CanvasJNI::drawTextOnPathChars}, 717 {"native_drawTextOnPath","(JLjava/lang/String;JFFIJJ)V", (void*) CanvasJNI::drawTextOnPathString}, 718 {"nativeSetDrawFilter", "(JJ)V", (void*) CanvasJNI::setDrawFilter}, 719 {"freeCaches", "()V", (void*) CanvasJNI::freeCaches}, 720 {"freeTextLayoutCaches", "()V", (void*) CanvasJNI::freeTextLayoutCaches} 721}; 722 723int register_android_graphics_Canvas(JNIEnv* env) { 724 return RegisterMethodsOrDie(env, "android/graphics/Canvas", gMethods, NELEM(gMethods)); 725} 726 727}; // namespace android 728