Paint.cpp revision 775873a66a946fae2b0535abb51df9817bd1b20c
14aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy/* libs/android_runtime/android/graphics/Paint.cpp 24aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy** 34aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy** Copyright 2006, The Android Open Source Project 44aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy** 54aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy** Licensed under the Apache License, Version 2.0 (the "License"); 64aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy** you may not use this file except in compliance with the License. 74aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy** You may obtain a copy of the License at 84aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy** 94aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy** http://www.apache.org/licenses/LICENSE-2.0 104aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy** 114aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy** Unless required by applicable law or agreed to in writing, software 124aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy** distributed under the License is distributed on an "AS IS" BASIS, 134aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 144aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy** See the License for the specific language governing permissions and 154aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy** limitations under the License. 164aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy*/ 174aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy 184aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy#define LOG_TAG "Paint" 19d5a85fb63d91a9297e8d9a11016f3b3ed60dfbabRomain Guy 20c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy#include <utils/Log.h> 219c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase 226554943a1dd6854c0f4976900956e556767b49e1Romain Guy#include "jni.h" 236554943a1dd6854c0f4976900956e556767b49e1Romain Guy#include "GraphicsJNI.h" 24a35778c799e8073a42b9e22191bde9d838327ab7John Reck#include "core_jni_helpers.h" 25c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik#include <ScopedStringChars.h> 269c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase#include <ScopedUtfChars.h> 272af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik 284aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy#include "SkBlurDrawLooper.h" 29113e0824d6bddf4376240681f9cf6a2deded9498John Reck#include "SkColorFilter.h" 3013631f3da855f200a151e7837ed9f6b079622b58Romain Guy#include "SkMaskFilter.h" 314aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy#include "SkPath.h" 324aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy#include "SkRasterizer.h" 334aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy#include "SkShader.h" 34cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik#include "SkTypeface.h" 35984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson#include "SkXfermode.h" 36088c514cb13f3b8f8683588c2f398f18df1547c9John Reck#include "unicode/uloc.h" 378afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik#include "unicode/ushape.h" 38cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik#include "utils/Blur.h" 39cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik 408afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik#include <minikin/GraphemeBreak.h> 41cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik#include <minikin/Measurement.h> 42cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik#include <unicode/utf16.h> 434aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy#include "MinikinSkia.h" 444aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy#include "MinikinUtils.h" 454aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy#include "Paint.h" 4644fd8d24f761f82d21e9b00932648a1b6bf91449John Reck#include "TypefaceImpl.h" 4744fd8d24f761f82d21e9b00932648a1b6bf91449John Reck 484aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy#include <cassert> 494aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy#include <cstring> 5044fd8d24f761f82d21e9b00932648a1b6bf91449John Reck#include <memory> 5144fd8d24f761f82d21e9b00932648a1b6bf91449John Reck#include <vector> 5244fd8d24f761f82d21e9b00932648a1b6bf91449John Reck 53d34dd71800d9a1077e58c3b7f2511c46848da417Chet Haasenamespace android { 5444fd8d24f761f82d21e9b00932648a1b6bf91449John Reck 5543ccf4663c822ddd435b7683cc05221f6169c6c3Romain Guystruct JMetricsID { 56735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy jfieldID top; 572fc941e4650d618ff6e122f28b616d9032ffa134Romain Guy jfieldID ascent; 5844fd8d24f761f82d21e9b00932648a1b6bf91449John Reck jfieldID descent; 5944fd8d24f761f82d21e9b00932648a1b6bf91449John Reck jfieldID bottom; 6044fd8d24f761f82d21e9b00932648a1b6bf91449John Reck jfieldID leading; 615977baa1fa24125c148a72699b53e62abaf08960Chet Haase}; 625977baa1fa24125c148a72699b53e62abaf08960Chet Haase 63107843de4507b3511006cb9c77b8d0364374385aTom Hudsonstatic jclass gFontMetrics_class; 647d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guystatic JMetricsID gFontMetrics_fieldID; 6544fd8d24f761f82d21e9b00932648a1b6bf91449John Reck 6644fd8d24f761f82d21e9b00932648a1b6bf91449John Reckstatic jclass gFontMetricsInt_class; 6744fd8d24f761f82d21e9b00932648a1b6bf91449John Reckstatic JMetricsID gFontMetricsInt_fieldID; 6844fd8d24f761f82d21e9b00932648a1b6bf91449John Reck 6944fd8d24f761f82d21e9b00932648a1b6bf91449John Reckstatic void defaultSettingsForAndroid(Paint* paint) { 70984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson // GlyphID encoding is required because we are using Harfbuzz shaping 7145e4c3df6c00ac98ff6144de9af574877d4fff19Romain Guy paint->setTextEncoding(Paint::kGlyphID_TextEncoding); 728afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik} 73984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson 7427454a42de8b3c54cdd3b2b2a12446c2c10c8cb9Romain Guynamespace PaintGlue { 7527454a42de8b3c54cdd3b2b2a12446c2c10c8cb9Romain Guy enum MoveOpt { 7627454a42de8b3c54cdd3b2b2a12446c2c10c8cb9Romain Guy AFTER, AT_OR_AFTER, BEFORE, AT_OR_BEFORE, AT 77107843de4507b3511006cb9c77b8d0364374385aTom Hudson }; 788afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik 798afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik static void deletePaint(Paint* paint) { 80107843de4507b3511006cb9c77b8d0364374385aTom Hudson delete paint; 81b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy } 82b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy 83daf98e941e140e8739458126640183b9f296a2abChet Haase static jlong getNativeFinalizer(JNIEnv*, jobject) { 84daf98e941e140e8739458126640183b9f296a2abChet Haase return static_cast<jlong>(reinterpret_cast<uintptr_t>(&deletePaint)); 85daf98e941e140e8739458126640183b9f296a2abChet Haase } 862b1847ea60650a9f68372abe860415f18b55081dRomain Guy 874aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy static jlong init(JNIEnv* env, jobject) { 884aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy static_assert(1 << 0 == SkPaint::kAntiAlias_Flag, "paint_flags_mismatch"); 89107843de4507b3511006cb9c77b8d0364374385aTom Hudson static_assert(1 << 2 == SkPaint::kDither_Flag, "paint_flags_mismatch"); 90cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy static_assert(1 << 3 == SkPaint::kUnderlineText_Flag, "paint_flags_mismatch"); 912af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik static_assert(1 << 4 == SkPaint::kStrikeThruText_Flag, "paint_flags_mismatch"); 9209d5cddf67b676018700bcc10a72242641cd7eecJohn Reck static_assert(1 << 5 == SkPaint::kFakeBoldText_Flag, "paint_flags_mismatch"); 93daf98e941e140e8739458126640183b9f296a2abChet Haase static_assert(1 << 6 == SkPaint::kLinearText_Flag, "paint_flags_mismatch"); 94daf98e941e140e8739458126640183b9f296a2abChet Haase static_assert(1 << 7 == SkPaint::kSubpixelText_Flag, "paint_flags_mismatch"); 954aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy static_assert(1 << 8 == SkPaint::kDevKernText_Flag, "paint_flags_mismatch"); 962af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik static_assert(1 << 10 == SkPaint::kEmbeddedBitmapText_Flag, "paint_flags_mismatch"); 97984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson 984aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy Paint* obj = new Paint(); 994aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy defaultSettingsForAndroid(obj); 1004aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy return reinterpret_cast<jlong>(obj); 10104c9d8c2ffd028c35c750bac0a4a7b79e48059b5Romain Guy } 10233f6beb10f98e8ba96250e284876d607055d278dRomain Guy 10333f6beb10f98e8ba96250e284876d607055d278dRomain Guy static jlong initWithPaint(JNIEnv* env, jobject clazz, jlong paintHandle) { 10404c9d8c2ffd028c35c750bac0a4a7b79e48059b5Romain Guy Paint* paint = reinterpret_cast<Paint*>(paintHandle); 10533f6beb10f98e8ba96250e284876d607055d278dRomain Guy Paint* obj = new Paint(*paint); 10633f6beb10f98e8ba96250e284876d607055d278dRomain Guy return reinterpret_cast<jlong>(obj); 1078afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik } 108984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson 1094aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy static void reset(JNIEnv* env, jobject clazz, jlong objHandle) { 1104aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy Paint* obj = reinterpret_cast<Paint*>(objHandle); 1114aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy obj->reset(); 11227454a42de8b3c54cdd3b2b2a12446c2c10c8cb9Romain Guy defaultSettingsForAndroid(obj); 1138afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik } 114984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson 1154aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy static void assign(JNIEnv* env, jobject clazz, jlong dstPaintHandle, jlong srcPaintHandle) { 1164aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy Paint* dst = reinterpret_cast<Paint*>(dstPaintHandle); 1174aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy const Paint* src = reinterpret_cast<Paint*>(srcPaintHandle); 118d44fbe55a9f434cb5bb0e34c143ba1445141990dDerek Sollenberger *dst = *src; 1194ace7305608442ab35ea9aa65a4220df152c187fChris Craik } 1204ace7305608442ab35ea9aa65a4220df152c187fChris Craik 1214ace7305608442ab35ea9aa65a4220df152c187fChris Craik // Equivalent to the Java Paint's FILTER_BITMAP_FLAG. 122d44fbe55a9f434cb5bb0e34c143ba1445141990dDerek Sollenberger static const uint32_t sFilterBitmapFlag = 0x02; 123d44fbe55a9f434cb5bb0e34c143ba1445141990dDerek Sollenberger 124984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson static jint getFlags(JNIEnv* env, jobject, jlong paintHandle) { 1255b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy Paint* nativePaint = reinterpret_cast<Paint*>(paintHandle); 1265b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy uint32_t result = nativePaint->getFlags(); 127b458942bb6e6cf13c68341dda35ef5cee060f5aeChris Craik result &= ~sFilterBitmapFlag; // Filtering no longer stored in this bit. Mask away. 128b458942bb6e6cf13c68341dda35ef5cee060f5aeChris Craik if (nativePaint->getFilterQuality() != kNone_SkFilterQuality) { 1298afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik result |= sFilterBitmapFlag; 13033f6beb10f98e8ba96250e284876d607055d278dRomain Guy } 13133f6beb10f98e8ba96250e284876d607055d278dRomain Guy return static_cast<jint>(result); 1328afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik } 133984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson 1344aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy static void setFlags(JNIEnv* env, jobject, jlong paintHandle, jint flags) { 1354aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy Paint* nativePaint = reinterpret_cast<Paint*>(paintHandle); 1364aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy // Instead of modifying 0x02, change the filter level. 1372af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik nativePaint->setFilterQuality(flags & sFilterBitmapFlag 138984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson ? kLow_SkFilterQuality 1394aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy : kNone_SkFilterQuality); 1404aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy // Don't pass through filter flag, which is no longer stored in paint's flags. 1414aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy flags &= ~sFilterBitmapFlag; 1422af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik // Use the existing value for 0x02. 143984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson const uint32_t existing0x02Flag = nativePaint->getFlags() & sFilterBitmapFlag; 1444aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy flags |= existing0x02Flag; 1454aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy nativePaint->setFlags(flags); 146807daf7df615b60ce6fc41355aabe3aa353cebabRomain Guy } 1472af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik 148984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson static jint getHinting(JNIEnv* env, jobject, jlong paintHandle) { 149807daf7df615b60ce6fc41355aabe3aa353cebabRomain Guy return reinterpret_cast<Paint*>(paintHandle)->getHinting() 150807daf7df615b60ce6fc41355aabe3aa353cebabRomain Guy == Paint::kNo_Hinting ? 0 : 1; 151139088228faa7f3c446af7387e017933998a5570Derek Sollenberger } 1522af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik 153984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson static void setHinting(JNIEnv* env, jobject, jlong paintHandle, jint mode) { 1544aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy reinterpret_cast<Paint*>(paintHandle)->setHinting( 1554aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy mode == 0 ? Paint::kNo_Hinting : Paint::kNormal_Hinting); 156139088228faa7f3c446af7387e017933998a5570Derek Sollenberger } 1572af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik 158984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson static void setAntiAlias(JNIEnv* env, jobject, jlong paintHandle, jboolean aa) { 1594aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy reinterpret_cast<Paint*>(paintHandle)->setAntiAlias(aa); 1604aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy } 1614aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy 1624aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy static void setLinearText(JNIEnv* env, jobject, jlong paintHandle, jboolean linearText) { 1632af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik reinterpret_cast<Paint*>(paintHandle)->setLinearText(linearText); 164984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson } 1654aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy 1664aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy static void setSubpixelText(JNIEnv* env, jobject, jlong paintHandle, jboolean subpixelText) { 167d218a92c0afb8c0d98135b20b52ac87236e1c935Chris Craik reinterpret_cast<Paint*>(paintHandle)->setSubpixelText(subpixelText); 1682af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik } 1692af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik 170984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson static void setUnderlineText(JNIEnv* env, jobject, jlong paintHandle, jboolean underlineText) { 171735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy reinterpret_cast<Paint*>(paintHandle)->setUnderlineText(underlineText); 172735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy } 173d218a92c0afb8c0d98135b20b52ac87236e1c935Chris Craik 1742af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik static void setStrikeThruText(JNIEnv* env, jobject, jlong paintHandle, jboolean strikeThruText) { 1752af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik reinterpret_cast<Paint*>(paintHandle)->setStrikeThruText(strikeThruText); 176984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson } 177735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy 178735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy static void setFakeBoldText(JNIEnv* env, jobject, jlong paintHandle, jboolean fakeBoldText) { 179107843de4507b3511006cb9c77b8d0364374385aTom Hudson reinterpret_cast<Paint*>(paintHandle)->setFakeBoldText(fakeBoldText); 1808afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik } 1818afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik 182cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy static void setFilterBitmap(JNIEnv* env, jobject, jlong paintHandle, jboolean filterBitmap) { 183cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy reinterpret_cast<Paint*>(paintHandle)->setFilterQuality( 184984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson filterBitmap ? kLow_SkFilterQuality : kNone_SkFilterQuality); 1858afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik } 1860fe478ea04720a57ef3919dbc23711bc7eba517fRomain Guy 1870fe478ea04720a57ef3919dbc23711bc7eba517fRomain Guy static void setDither(JNIEnv* env, jobject, jlong paintHandle, jboolean dither) { 188107843de4507b3511006cb9c77b8d0364374385aTom Hudson reinterpret_cast<Paint*>(paintHandle)->setDither(dither); 1890e89e2b7bcb2c035e8cee77f93120e7c5617f8d2John Reck } 190a08f95cfeca7217f9c533b03663bf0dceedd259aChris Craik 1916c319ca1275c8db892c39b48fc54864c949f9171Romain Guy static jint getStyle(JNIEnv* env, jobject clazz,jlong objHandle) { 1926c319ca1275c8db892c39b48fc54864c949f9171Romain Guy Paint* obj = reinterpret_cast<Paint*>(objHandle); 193107843de4507b3511006cb9c77b8d0364374385aTom Hudson return static_cast<jint>(obj->getStyle()); 1942af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik } 1952af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik 1962af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik static void setStyle(JNIEnv* env, jobject clazz, jlong objHandle, jint styleHandle) { 197796475006f5d670e8383a2050f11719522437a43Chris Craik Paint* obj = reinterpret_cast<Paint*>(objHandle); 1984aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy Paint::Style style = static_cast<Paint::Style>(styleHandle); 1994aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy obj->setStyle(style); 200107843de4507b3511006cb9c77b8d0364374385aTom Hudson } 2014aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy 202d218a92c0afb8c0d98135b20b52ac87236e1c935Chris Craik static jint getColor(JNIEnv* env, jobject, jlong paintHandle) { 203796475006f5d670e8383a2050f11719522437a43Chris Craik int color; 204796475006f5d670e8383a2050f11719522437a43Chris Craik color = reinterpret_cast<Paint*>(paintHandle)->getColor(); 205796475006f5d670e8383a2050f11719522437a43Chris Craik return static_cast<jint>(color); 206796475006f5d670e8383a2050f11719522437a43Chris Craik } 207527a3aace1dd72432c2e0472a570e030ad04bf16Chris Craik 208796475006f5d670e8383a2050f11719522437a43Chris Craik static jint getAlpha(JNIEnv* env, jobject, jlong paintHandle) { 209796475006f5d670e8383a2050f11719522437a43Chris Craik int alpha; 210796475006f5d670e8383a2050f11719522437a43Chris Craik alpha = reinterpret_cast<Paint*>(paintHandle)->getAlpha(); 211796475006f5d670e8383a2050f11719522437a43Chris Craik return static_cast<jint>(alpha); 212796475006f5d670e8383a2050f11719522437a43Chris Craik } 213796475006f5d670e8383a2050f11719522437a43Chris Craik 214796475006f5d670e8383a2050f11719522437a43Chris Craik static void setColor(JNIEnv* env, jobject, jlong paintHandle, jint color) { 215796475006f5d670e8383a2050f11719522437a43Chris Craik reinterpret_cast<Paint*>(paintHandle)->setColor(color); 216796475006f5d670e8383a2050f11719522437a43Chris Craik } 217796475006f5d670e8383a2050f11719522437a43Chris Craik 218796475006f5d670e8383a2050f11719522437a43Chris Craik static void setAlpha(JNIEnv* env, jobject, jlong paintHandle, jint a) { 219527a3aace1dd72432c2e0472a570e030ad04bf16Chris Craik reinterpret_cast<Paint*>(paintHandle)->setAlpha(a); 2204aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy } 2214aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy 222107843de4507b3511006cb9c77b8d0364374385aTom Hudson static jfloat getStrokeWidth(JNIEnv* env, jobject, jlong paintHandle) { 2232af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik return SkScalarToFloat(reinterpret_cast<Paint*>(paintHandle)->getStrokeWidth()); 2242af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik } 2252af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik 226796475006f5d670e8383a2050f11719522437a43Chris Craik static void setStrokeWidth(JNIEnv* env, jobject, jlong paintHandle, jfloat width) { 227e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy reinterpret_cast<Paint*>(paintHandle)->setStrokeWidth(width); 228e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy } 229107843de4507b3511006cb9c77b8d0364374385aTom Hudson 230d218a92c0afb8c0d98135b20b52ac87236e1c935Chris Craik static jfloat getStrokeMiter(JNIEnv* env, jobject, jlong paintHandle) { 2310664fef9e2a36025b3fad85b57b4d10617b4d66eChris Craik return SkScalarToFloat(reinterpret_cast<Paint*>(paintHandle)->getStrokeMiter()); 2322af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik } 2330664fef9e2a36025b3fad85b57b4d10617b4d66eChris Craik 2342af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik static void setStrokeMiter(JNIEnv* env, jobject, jlong paintHandle, jfloat miter) { 2350664fef9e2a36025b3fad85b57b4d10617b4d66eChris Craik reinterpret_cast<Paint*>(paintHandle)->setStrokeMiter(miter); 2362af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik } 2372af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik 2382af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik static jint getStrokeCap(JNIEnv* env, jobject clazz, jlong objHandle) { 2395a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy Paint* obj = reinterpret_cast<Paint*>(objHandle); 2405a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy return static_cast<jint>(obj->getStrokeCap()); 241107843de4507b3511006cb9c77b8d0364374385aTom Hudson } 242d218a92c0afb8c0d98135b20b52ac87236e1c935Chris Craik 2432af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik static void setStrokeCap(JNIEnv* env, jobject clazz, jlong objHandle, jint capHandle) { 244e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy Paint* obj = reinterpret_cast<Paint*>(objHandle); 24516ea8d373b03b1e115dd505af70dbee4e3a3a182Romain Guy Paint::Cap cap = static_cast<Paint::Cap>(capHandle); 2462af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik obj->setStrokeCap(cap); 24703c00b5a135e68d22ca5bb829b899ebda6ed7e9dRomain Guy } 2484aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy 2494aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy static jint getStrokeJoin(JNIEnv* env, jobject clazz, jlong objHandle) { 250107843de4507b3511006cb9c77b8d0364374385aTom Hudson Paint* obj = reinterpret_cast<Paint*>(objHandle); 2512af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik return static_cast<jint>(obj->getStrokeJoin()); 2524aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy } 2534aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy 254107843de4507b3511006cb9c77b8d0364374385aTom Hudson static void setStrokeJoin(JNIEnv* env, jobject clazz, jlong objHandle, jint joinHandle) { 255d218a92c0afb8c0d98135b20b52ac87236e1c935Chris Craik Paint* obj = reinterpret_cast<Paint*>(objHandle); 2562af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik Paint::Join join = (Paint::Join) joinHandle; 2572af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik obj->setStrokeJoin(join); 2584aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy } 2594aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy 260107843de4507b3511006cb9c77b8d0364374385aTom Hudson static jboolean getFillPath(JNIEnv* env, jobject clazz, jlong objHandle, jlong srcHandle, jlong dstHandle) { 261d218a92c0afb8c0d98135b20b52ac87236e1c935Chris Craik Paint* obj = reinterpret_cast<Paint*>(objHandle); 2622af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik SkPath* src = reinterpret_cast<SkPath*>(srcHandle); 2632af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik SkPath* dst = reinterpret_cast<SkPath*>(dstHandle); 26401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy return obj->getFillPath(*src, dst) ? JNI_TRUE : JNI_FALSE; 26501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy } 266107843de4507b3511006cb9c77b8d0364374385aTom Hudson 267072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi static jlong setShader(JNIEnv* env, jobject clazz, jlong objHandle, jlong shaderHandle) { 268072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi Paint* obj = reinterpret_cast<Paint*>(objHandle); 269072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle); 270072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi return reinterpret_cast<jlong>(obj->setShader(shader)); 2710e89e2b7bcb2c035e8cee77f93120e7c5617f8d2John Reck } 2720e89e2b7bcb2c035e8cee77f93120e7c5617f8d2John Reck 2730e89e2b7bcb2c035e8cee77f93120e7c5617f8d2John Reck static jlong setColorFilter(JNIEnv* env, jobject clazz, jlong objHandle, jlong filterHandle) { 2740e89e2b7bcb2c035e8cee77f93120e7c5617f8d2John Reck Paint* obj = reinterpret_cast<Paint *>(objHandle); 2750e89e2b7bcb2c035e8cee77f93120e7c5617f8d2John Reck SkColorFilter* filter = reinterpret_cast<SkColorFilter *>(filterHandle); 2760e89e2b7bcb2c035e8cee77f93120e7c5617f8d2John Reck return reinterpret_cast<jlong>(obj->setColorFilter(filter)); 2770e89e2b7bcb2c035e8cee77f93120e7c5617f8d2John Reck } 278072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 279072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi static jlong setXfermode(JNIEnv* env, jobject clazz, jlong objHandle, jlong xfermodeHandle) { 280072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi Paint* obj = reinterpret_cast<Paint*>(objHandle); 281072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi SkXfermode* xfermode = reinterpret_cast<SkXfermode*>(xfermodeHandle); 282107843de4507b3511006cb9c77b8d0364374385aTom Hudson return reinterpret_cast<jlong>(obj->setXfermode(xfermode)); 2832af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik } 2842af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik 28501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy static jlong setPathEffect(JNIEnv* env, jobject clazz, jlong objHandle, jlong effectHandle) { 28601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy Paint* obj = reinterpret_cast<Paint*>(objHandle); 287107843de4507b3511006cb9c77b8d0364374385aTom Hudson SkPathEffect* effect = reinterpret_cast<SkPathEffect*>(effectHandle); 28852244fff29042926e21fa897ef5ab11148e35299John Reck return reinterpret_cast<jlong>(obj->setPathEffect(effect)); 2890e89e2b7bcb2c035e8cee77f93120e7c5617f8d2John Reck } 2900e89e2b7bcb2c035e8cee77f93120e7c5617f8d2John Reck 2910e89e2b7bcb2c035e8cee77f93120e7c5617f8d2John Reck static jlong setMaskFilter(JNIEnv* env, jobject clazz, jlong objHandle, jlong maskfilterHandle) { 2920e89e2b7bcb2c035e8cee77f93120e7c5617f8d2John Reck Paint* obj = reinterpret_cast<Paint*>(objHandle); 29352244fff29042926e21fa897ef5ab11148e35299John Reck SkMaskFilter* maskfilter = reinterpret_cast<SkMaskFilter*>(maskfilterHandle); 29452244fff29042926e21fa897ef5ab11148e35299John Reck return reinterpret_cast<jlong>(obj->setMaskFilter(maskfilter)); 29552244fff29042926e21fa897ef5ab11148e35299John Reck } 29652244fff29042926e21fa897ef5ab11148e35299John Reck 297107843de4507b3511006cb9c77b8d0364374385aTom Hudson static jlong setTypeface(JNIEnv* env, jobject clazz, jlong objHandle, jlong typefaceHandle) { 298d218a92c0afb8c0d98135b20b52ac87236e1c935Chris Craik // TODO: in Paint refactoring, set typeface on android Paint, not Paint 2992af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik return NULL; 3002af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik } 301c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy 302c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy static jlong setRasterizer(JNIEnv* env, jobject clazz, jlong objHandle, jlong rasterizerHandle) { 303107843de4507b3511006cb9c77b8d0364374385aTom Hudson Paint* obj = reinterpret_cast<Paint*>(objHandle); 304d218a92c0afb8c0d98135b20b52ac87236e1c935Chris Craik SkAutoTUnref<SkRasterizer> rasterizer(GraphicsJNI::refNativeRasterizer(rasterizerHandle)); 305544e524db6e4da526af1c897fe5314036ede5012Chris Craik return reinterpret_cast<jlong>(obj->setRasterizer(rasterizer)); 306107843de4507b3511006cb9c77b8d0364374385aTom Hudson } 307107843de4507b3511006cb9c77b8d0364374385aTom Hudson 308107843de4507b3511006cb9c77b8d0364374385aTom Hudson static jint getTextAlign(JNIEnv* env, jobject clazz, jlong objHandle) { 309107843de4507b3511006cb9c77b8d0364374385aTom Hudson Paint* obj = reinterpret_cast<Paint*>(objHandle); 310107843de4507b3511006cb9c77b8d0364374385aTom Hudson return static_cast<jint>(obj->getTextAlign()); 3116ac174b97246ed40fe780b29561603b61770fa17Chris Craik } 3128b2f5267f16c295f12faab810527cd6311997e34Romain Guy 3138b2f5267f16c295f12faab810527cd6311997e34Romain Guy static void setTextAlign(JNIEnv* env, jobject clazz, jlong objHandle, jint alignHandle) { 314107843de4507b3511006cb9c77b8d0364374385aTom Hudson Paint* obj = reinterpret_cast<Paint*>(objHandle); 3152af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik Paint::Align align = static_cast<Paint::Align>(alignHandle); 3162af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik obj->setTextAlign(align); 3172af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik } 3182af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik 3194aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy static jint setTextLocales(JNIEnv* env, jobject clazz, jlong objHandle, jstring locales) { 3204aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy Paint* obj = reinterpret_cast<Paint*>(objHandle); 321107843de4507b3511006cb9c77b8d0364374385aTom Hudson ScopedUtfChars localesChars(env, locales); 3222af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik jint minikinLangListId = FontStyle::registerLanguageList(localesChars.c_str()); 3232af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik obj->setMinikinLangListId(minikinLangListId); 3242af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik return minikinLangListId; 3252af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik } 326ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy 327ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy static void setTextLocalesByMinikinLangListId(JNIEnv* env, jobject clazz, jlong objHandle, 328107843de4507b3511006cb9c77b8d0364374385aTom Hudson jint minikinLangListId) { 3292af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik Paint* obj = reinterpret_cast<Paint*>(objHandle); 3302af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik obj->setMinikinLangListId(minikinLangListId); 3312af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik } 3322af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik 3334aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy static jboolean isElegantTextHeight(JNIEnv* env, jobject, jlong paintHandle) { 3344aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy Paint* obj = reinterpret_cast<Paint*>(paintHandle); 335107843de4507b3511006cb9c77b8d0364374385aTom Hudson return obj->getFontVariant() == VARIANT_ELEGANT; 336d218a92c0afb8c0d98135b20b52ac87236e1c935Chris Craik } 337107843de4507b3511006cb9c77b8d0364374385aTom Hudson 3382af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik static void setElegantTextHeight(JNIEnv* env, jobject, jlong paintHandle, jboolean aa) { 3392af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik Paint* obj = reinterpret_cast<Paint*>(paintHandle); 3402af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik obj->setFontVariant(aa ? VARIANT_ELEGANT : VARIANT_DEFAULT); 3412af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik } 3422af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik 3432af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik static jfloat getTextSize(JNIEnv* env, jobject, jlong paintHandle) { 3442af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik return SkScalarToFloat(reinterpret_cast<Paint*>(paintHandle)->getTextSize()); 3450f6675332c04c74909425d1d328f02b32c0ff40eRomain Guy } 346996e57c84368058be793897ebc355b917a59abc2Raph Levien 347996e57c84368058be793897ebc355b917a59abc2Raph Levien static void setTextSize(JNIEnv* env, jobject, jlong paintHandle, jfloat textSize) { 348107843de4507b3511006cb9c77b8d0364374385aTom Hudson reinterpret_cast<Paint*>(paintHandle)->setTextSize(textSize); 349d218a92c0afb8c0d98135b20b52ac87236e1c935Chris Craik } 350107843de4507b3511006cb9c77b8d0364374385aTom Hudson 3512af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik static jfloat getTextScaleX(JNIEnv* env, jobject, jlong paintHandle) { 3522af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik return SkScalarToFloat(reinterpret_cast<Paint*>(paintHandle)->getTextScaleX()); 3532af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik } 3542af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik 3552af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik static void setTextScaleX(JNIEnv* env, jobject, jlong paintHandle, jfloat scaleX) { 3562af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik reinterpret_cast<Paint*>(paintHandle)->setTextScaleX(scaleX); 3570f6675332c04c74909425d1d328f02b32c0ff40eRomain Guy } 358996e57c84368058be793897ebc355b917a59abc2Raph Levien 359996e57c84368058be793897ebc355b917a59abc2Raph Levien static jfloat getTextSkewX(JNIEnv* env, jobject, jlong paintHandle) { 360cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik return SkScalarToFloat(reinterpret_cast<Paint*>(paintHandle)->getTextSkewX()); 361cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik } 362cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik 363cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik static void setTextSkewX(JNIEnv* env, jobject, jlong paintHandle, jfloat skewX) { 364cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik reinterpret_cast<Paint*>(paintHandle)->setTextSkewX(skewX); 365cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik } 366cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik 367cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik static jfloat getLetterSpacing(JNIEnv* env, jobject clazz, jlong paintHandle) { 368cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik Paint* paint = reinterpret_cast<Paint*>(paintHandle); 369cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik return paint->getLetterSpacing(); 370107843de4507b3511006cb9c77b8d0364374385aTom Hudson } 371d218a92c0afb8c0d98135b20b52ac87236e1c935Chris Craik 37241541825bc90dac740e424cdd41a8c997e15cdb7Chris Craik static void setLetterSpacing(JNIEnv* env, jobject clazz, jlong paintHandle, jfloat letterSpacing) { 373527a3aace1dd72432c2e0472a570e030ad04bf16Chris Craik Paint* paint = reinterpret_cast<Paint*>(paintHandle); 374107843de4507b3511006cb9c77b8d0364374385aTom Hudson paint->setLetterSpacing(letterSpacing); 37533f6beb10f98e8ba96250e284876d607055d278dRomain Guy } 3762af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik 3772af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik static void setFontFeatureSettings(JNIEnv* env, jobject clazz, jlong paintHandle, jstring settings) { 37833f6beb10f98e8ba96250e284876d607055d278dRomain Guy Paint* paint = reinterpret_cast<Paint*>(paintHandle); 379cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik if (!settings) { 380cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik paint->setFontFeatureSettings(std::string()); 381cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik } else { 382cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik ScopedUtfChars settingsChars(env, settings); 383cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik paint->setFontFeatureSettings(std::string(settingsChars.c_str(), settingsChars.size())); 384cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik } 385cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik } 386cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik 387cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik static jint getHyphenEdit(JNIEnv* env, jobject clazz, jlong paintHandle, jint hyphen) { 388cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik Paint* paint = reinterpret_cast<Paint*>(paintHandle); 389cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik return paint->getHyphenEdit(); 390cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik } 391cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik 392cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik static void setHyphenEdit(JNIEnv* env, jobject clazz, jlong paintHandle, jint hyphen) { 393cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik Paint* paint = reinterpret_cast<Paint*>(paintHandle); 394cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik paint->setHyphenEdit((uint32_t)hyphen); 395cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik } 396cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik 397cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik static SkScalar getMetricsInternal(jlong paintHandle, jlong typefaceHandle, 398cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik Paint::FontMetrics *metrics) { 399cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik const int kElegantTop = 2500; 400cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik const int kElegantBottom = -1000; 401cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik const int kElegantAscent = 1900; 402cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik const int kElegantDescent = -500; 403cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik const int kElegantLeading = 0; 404cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik Paint* paint = reinterpret_cast<Paint*>(paintHandle); 405cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle); 406672433d90fab7383cd28beac9d4485b566a90940Romain Guy typeface = TypefaceImpl_resolveDefault(typeface); 407672433d90fab7383cd28beac9d4485b566a90940Romain Guy FakedFont baseFont = typeface->fFontCollection->baseFontFaked(typeface->fStyle); 408107843de4507b3511006cb9c77b8d0364374385aTom Hudson float saveSkewX = paint->getTextSkewX(); 409107843de4507b3511006cb9c77b8d0364374385aTom Hudson bool savefakeBold = paint->isFakeBoldText(); 410672433d90fab7383cd28beac9d4485b566a90940Romain Guy MinikinFontSkia::populateSkPaint(paint, baseFont.font, baseFont.fakery); 4112af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik SkScalar spacing = paint->getFontMetrics(metrics); 4122af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik // The populateSkPaint call may have changed fake bold / text skew 4132af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik // because we want to measure with those effects applied, so now 414eb9a5367e8f0e970db8509ffb2584f5376bc62edRomain Guy // restore the original settings. 415eb9a5367e8f0e970db8509ffb2584f5376bc62edRomain Guy paint->setTextSkewX(saveSkewX); 41609c2d4fe15fbac2faf8a97ba2cc59132ee12222aDerek Sollenberger paint->setFakeBoldText(savefakeBold); 41709c2d4fe15fbac2faf8a97ba2cc59132ee12222aDerek Sollenberger if (paint->getFontVariant() == VARIANT_ELEGANT) { 4182af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik SkScalar size = paint->getTextSize(); 4192af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik metrics->fTop = -size * kElegantTop / 2048; 4208afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik metrics->fBottom = -size * kElegantBottom / 2048; 4218afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik metrics->fAscent = -size * kElegantAscent / 2048; 4228afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik metrics->fDescent = -size * kElegantDescent / 2048; 4238afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik metrics->fLeading = size * kElegantLeading / 2048; 4248afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik spacing = metrics->fDescent - metrics->fAscent + metrics->fLeading; 4258afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik } 4268afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik return spacing; 4272af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik } 4288afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik 4292af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik static jfloat ascent(JNIEnv* env, jobject, jlong paintHandle, jlong typefaceHandle) { 4302af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik Paint::FontMetrics metrics; 4312af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik getMetricsInternal(paintHandle, typefaceHandle, &metrics); 4322af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik return SkScalarToFloat(metrics.fAscent); 4338afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik } 4348afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik 4352af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik static jfloat descent(JNIEnv* env, jobject, jlong paintHandle, jlong typefaceHandle) { 4368afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik Paint::FontMetrics metrics; 4372af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik getMetricsInternal(paintHandle, typefaceHandle, &metrics); 4382af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik return SkScalarToFloat(metrics.fDescent); 4398afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik } 4402af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik 4412af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik static jfloat getFontMetrics(JNIEnv* env, jobject, jlong paintHandle, 4422af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik jlong typefaceHandle, jobject metricsObj) { 4438afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik Paint::FontMetrics metrics; 4448afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik SkScalar spacing = getMetricsInternal(paintHandle, typefaceHandle, &metrics); 4458afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik 4468afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik if (metricsObj) { 4478afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik SkASSERT(env->IsInstanceOf(metricsObj, gFontMetrics_class)); 4488afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik env->SetFloatField(metricsObj, gFontMetrics_fieldID.top, SkScalarToFloat(metrics.fTop)); 4498afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik env->SetFloatField(metricsObj, gFontMetrics_fieldID.ascent, SkScalarToFloat(metrics.fAscent)); 4508afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik env->SetFloatField(metricsObj, gFontMetrics_fieldID.descent, SkScalarToFloat(metrics.fDescent)); 4518afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik env->SetFloatField(metricsObj, gFontMetrics_fieldID.bottom, SkScalarToFloat(metrics.fBottom)); 4528afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik env->SetFloatField(metricsObj, gFontMetrics_fieldID.leading, SkScalarToFloat(metrics.fLeading)); 4538afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik } 4548afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik return SkScalarToFloat(spacing); 4558afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik } 4568afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik 4578afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik static jint getFontMetricsInt(JNIEnv* env, jobject, jlong paintHandle, 4588afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik jlong typefaceHandle, jobject metricsObj) { 4598afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik Paint::FontMetrics metrics; 4608afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik 4612af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik getMetricsInternal(paintHandle, typefaceHandle, &metrics); 4622af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik int ascent = SkScalarRoundToInt(metrics.fAscent); 4638afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik int descent = SkScalarRoundToInt(metrics.fDescent); 4648afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik int leading = SkScalarRoundToInt(metrics.fLeading); 4658afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik 4668afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik if (metricsObj) { 4678afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik SkASSERT(env->IsInstanceOf(metricsObj, gFontMetricsInt_class)); 4688afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik env->SetIntField(metricsObj, gFontMetricsInt_fieldID.top, SkScalarFloorToInt(metrics.fTop)); 4698afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik env->SetIntField(metricsObj, gFontMetricsInt_fieldID.ascent, ascent); 4708afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik env->SetIntField(metricsObj, gFontMetricsInt_fieldID.descent, descent); 4718afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik env->SetIntField(metricsObj, gFontMetricsInt_fieldID.bottom, SkScalarCeilToInt(metrics.fBottom)); 4728afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik env->SetIntField(metricsObj, gFontMetricsInt_fieldID.leading, leading); 4738afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik } 4742af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik return descent - ascent + leading; 4753b20251a355c88193c439f928a84ae69483fb488John Reck } 476f0a590781b2c3e34132b2011d3956135add73ae0Chris Craik 4772af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik static jfloat doTextAdvances(JNIEnv *env, Paint *paint, TypefaceImpl* typeface, 4782af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik const jchar *text, jint start, jint count, jint contextCount, jint bidiFlags, 4792af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik jfloatArray advances, jint advancesIndex) { 480c1c5f0870282b56dafe5a4d756e4b9e6884655a7Chris Craik NPE_CHECK_RETURN_ZERO(env, text); 48144fd8d24f761f82d21e9b00932648a1b6bf91449John Reck 4828afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik if ((start | count | contextCount | advancesIndex) < 0 || contextCount < count) { 4838afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik doThrowAIOOBE(env); 4848afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik return 0; 4858afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik } 4868afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik if (count == 0) { 4878afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik return 0; 4888afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik } 4898afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik if (advances) { 4908afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik size_t advancesLength = env->GetArrayLength(advances); 4918afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik if ((size_t)(count + advancesIndex) > advancesLength) { 4928afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik doThrowAIOOBE(env); 4938afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik return 0; 4948afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik } 4958afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik } 4968afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik 4978afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik Layout layout; 4985ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, text, start, count, 4995ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy contextCount); 5004aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy if (advances != NULL) { 5014aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy std::unique_ptr<jfloat> advancesArray(new jfloat[count]); 502 layout.getAdvances(advancesArray.get()); 503 env->SetFloatArrayRegion(advances, advancesIndex, count, advancesArray.get()); 504 } 505 return layout.getAdvance(); 506 } 507 508 static jfloat getTextAdvances___CIIIII_FI(JNIEnv* env, jobject clazz, jlong paintHandle, 509 jlong typefaceHandle, 510 jcharArray text, jint index, jint count, jint contextIndex, jint contextCount, 511 jint bidiFlags, jfloatArray advances, jint advancesIndex) { 512 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 513 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle); 514 jchar* textArray = env->GetCharArrayElements(text, NULL); 515 jfloat result = doTextAdvances(env, paint, typeface, textArray + contextIndex, 516 index - contextIndex, count, contextCount, bidiFlags, advances, advancesIndex); 517 env->ReleaseCharArrayElements(text, textArray, JNI_ABORT); 518 return result; 519 } 520 521 static jfloat getTextAdvances__StringIIIII_FI(JNIEnv* env, jobject clazz, jlong paintHandle, 522 jlong typefaceHandle, 523 jstring text, jint start, jint end, jint contextStart, jint contextEnd, jint bidiFlags, 524 jfloatArray advances, jint advancesIndex) { 525 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 526 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle); 527 const jchar* textArray = env->GetStringChars(text, NULL); 528 jfloat result = doTextAdvances(env, paint, typeface, textArray + contextStart, 529 start - contextStart, end - start, contextEnd - contextStart, bidiFlags, 530 advances, advancesIndex); 531 env->ReleaseStringChars(text, textArray); 532 return result; 533 } 534 535 static jint doTextRunCursor(JNIEnv *env, Paint* paint, const jchar *text, jint start, 536 jint count, jint flags, jint offset, jint opt) { 537 GraphemeBreak::MoveOpt moveOpt = GraphemeBreak::MoveOpt(opt); 538 size_t result = GraphemeBreak::getTextRunCursor(text, start, count, offset, moveOpt); 539 return static_cast<jint>(result); 540 } 541 542 static jint getTextRunCursor___C(JNIEnv* env, jobject clazz, jlong paintHandle, jcharArray text, 543 jint contextStart, jint contextCount, jint dir, jint offset, jint cursorOpt) { 544 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 545 jchar* textArray = env->GetCharArrayElements(text, NULL); 546 jint result = doTextRunCursor(env, paint, textArray, contextStart, contextCount, dir, 547 offset, cursorOpt); 548 env->ReleaseCharArrayElements(text, textArray, JNI_ABORT); 549 return result; 550 } 551 552 static jint getTextRunCursor__String(JNIEnv* env, jobject clazz, jlong paintHandle, jstring text, 553 jint contextStart, jint contextEnd, jint dir, jint offset, jint cursorOpt) { 554 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 555 const jchar* textArray = env->GetStringChars(text, NULL); 556 jint result = doTextRunCursor(env, paint, textArray, contextStart, 557 contextEnd - contextStart, dir, offset, cursorOpt); 558 env->ReleaseStringChars(text, textArray); 559 return result; 560 } 561 562 class GetTextFunctor { 563 public: 564 GetTextFunctor(const Layout& layout, SkPath* path, jfloat x, jfloat y, Paint* paint, 565 uint16_t* glyphs, SkPoint* pos) 566 : layout(layout), path(path), x(x), y(y), paint(paint), glyphs(glyphs), pos(pos) { 567 } 568 569 void operator()(size_t start, size_t end) { 570 for (size_t i = start; i < end; i++) { 571 glyphs[i] = layout.getGlyphId(i); 572 pos[i].fX = x + layout.getX(i); 573 pos[i].fY = y + layout.getY(i); 574 } 575 if (start == 0) { 576 paint->getPosTextPath(glyphs + start, (end - start) << 1, pos + start, path); 577 } else { 578 paint->getPosTextPath(glyphs + start, (end - start) << 1, pos + start, &tmpPath); 579 path->addPath(tmpPath); 580 } 581 } 582 private: 583 const Layout& layout; 584 SkPath* path; 585 jfloat x; 586 jfloat y; 587 Paint* paint; 588 uint16_t* glyphs; 589 SkPoint* pos; 590 SkPath tmpPath; 591 }; 592 593 static void getTextPath(JNIEnv* env, Paint* paint, TypefaceImpl* typeface, const jchar* text, 594 jint count, jint bidiFlags, jfloat x, jfloat y, SkPath* path) { 595 Layout layout; 596 MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, text, 0, count, count); 597 size_t nGlyphs = layout.nGlyphs(); 598 uint16_t* glyphs = new uint16_t[nGlyphs]; 599 SkPoint* pos = new SkPoint[nGlyphs]; 600 601 x += MinikinUtils::xOffsetForTextAlign(paint, layout); 602 Paint::Align align = paint->getTextAlign(); 603 paint->setTextAlign(Paint::kLeft_Align); 604 paint->setTextEncoding(Paint::kGlyphID_TextEncoding); 605 GetTextFunctor f(layout, path, x, y, paint, glyphs, pos); 606 MinikinUtils::forFontRun(layout, paint, f); 607 paint->setTextAlign(align); 608 delete[] glyphs; 609 delete[] pos; 610 } 611 612 static void getTextPath___C(JNIEnv* env, jobject clazz, jlong paintHandle, 613 jlong typefaceHandle, jint bidiFlags, 614 jcharArray text, jint index, jint count, jfloat x, jfloat y, jlong pathHandle) { 615 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 616 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle); 617 SkPath* path = reinterpret_cast<SkPath*>(pathHandle); 618 const jchar* textArray = env->GetCharArrayElements(text, NULL); 619 getTextPath(env, paint, typeface, textArray + index, count, bidiFlags, x, y, path); 620 env->ReleaseCharArrayElements(text, const_cast<jchar*>(textArray), JNI_ABORT); 621 } 622 623 static void getTextPath__String(JNIEnv* env, jobject clazz, jlong paintHandle, 624 jlong typefaceHandle, jint bidiFlags, 625 jstring text, jint start, jint end, jfloat x, jfloat y, jlong pathHandle) { 626 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 627 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle); 628 SkPath* path = reinterpret_cast<SkPath*>(pathHandle); 629 const jchar* textArray = env->GetStringChars(text, NULL); 630 getTextPath(env, paint, typeface, textArray + start, end - start, bidiFlags, x, y, path); 631 env->ReleaseStringChars(text, textArray); 632 } 633 634 static void setShadowLayer(JNIEnv* env, jobject clazz, jlong paintHandle, jfloat radius, 635 jfloat dx, jfloat dy, jint color) { 636 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 637 if (radius <= 0) { 638 paint->setLooper(NULL); 639 } 640 else { 641 SkScalar sigma = android::uirenderer::Blur::convertRadiusToSigma(radius); 642 paint->setLooper(SkBlurDrawLooper::Create((SkColor)color, sigma, dx, dy))->unref(); 643 } 644 } 645 646 static jboolean hasShadowLayer(JNIEnv* env, jobject clazz, jlong paintHandle) { 647 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 648 return paint->getLooper() && paint->getLooper()->asABlurShadow(NULL); 649 } 650 651 static int breakText(JNIEnv* env, const Paint& paint, TypefaceImpl* typeface, const jchar text[], 652 int count, float maxWidth, jint bidiFlags, jfloatArray jmeasured, 653 const bool forwardScan) { 654 size_t measuredCount = 0; 655 float measured = 0; 656 657 Layout layout; 658 MinikinUtils::doLayout(&layout, &paint, bidiFlags, typeface, text, 0, count, count); 659 float* advances = new float[count]; 660 layout.getAdvances(advances); 661 662 for (int i = 0; i < count; i++) { 663 // traverse in the given direction 664 int index = forwardScan ? i : (count - i - 1); 665 float width = advances[index]; 666 if (measured + width > maxWidth) { 667 break; 668 } 669 // properly handle clusters when scanning backwards 670 if (forwardScan || width != 0.0f) { 671 measuredCount = i + 1; 672 } 673 measured += width; 674 } 675 delete[] advances; 676 677 if (jmeasured && env->GetArrayLength(jmeasured) > 0) { 678 AutoJavaFloatArray autoMeasured(env, jmeasured, 1); 679 jfloat* array = autoMeasured.ptr(); 680 array[0] = measured; 681 } 682 return measuredCount; 683 } 684 685 static jint breakTextC(JNIEnv* env, jobject clazz, jlong paintHandle, jlong typefaceHandle, jcharArray jtext, 686 jint index, jint count, jfloat maxWidth, jint bidiFlags, jfloatArray jmeasuredWidth) { 687 NPE_CHECK_RETURN_ZERO(env, jtext); 688 689 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 690 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle); 691 692 bool forwardTextDirection; 693 if (count < 0) { 694 forwardTextDirection = false; 695 count = -count; 696 } 697 else { 698 forwardTextDirection = true; 699 } 700 701 if ((index < 0) || (index + count > env->GetArrayLength(jtext))) { 702 doThrowAIOOBE(env); 703 return 0; 704 } 705 706 const jchar* text = env->GetCharArrayElements(jtext, NULL); 707 count = breakText(env, *paint, typeface, text + index, count, maxWidth, 708 bidiFlags, jmeasuredWidth, forwardTextDirection); 709 env->ReleaseCharArrayElements(jtext, const_cast<jchar*>(text), 710 JNI_ABORT); 711 return count; 712 } 713 714 static jint breakTextS(JNIEnv* env, jobject clazz, jlong paintHandle, jlong typefaceHandle, jstring jtext, 715 jboolean forwards, jfloat maxWidth, jint bidiFlags, jfloatArray jmeasuredWidth) { 716 NPE_CHECK_RETURN_ZERO(env, jtext); 717 718 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 719 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle); 720 721 int count = env->GetStringLength(jtext); 722 const jchar* text = env->GetStringChars(jtext, NULL); 723 count = breakText(env, *paint, typeface, text, count, maxWidth, bidiFlags, jmeasuredWidth, forwards); 724 env->ReleaseStringChars(jtext, text); 725 return count; 726 } 727 728 static void doTextBounds(JNIEnv* env, const jchar* text, int count, jobject bounds, 729 const Paint& paint, TypefaceImpl* typeface, jint bidiFlags) { 730 SkRect r; 731 SkIRect ir; 732 733 Layout layout; 734 MinikinUtils::doLayout(&layout, &paint, bidiFlags, typeface, text, 0, count, count); 735 MinikinRect rect; 736 layout.getBounds(&rect); 737 r.fLeft = rect.mLeft; 738 r.fTop = rect.mTop; 739 r.fRight = rect.mRight; 740 r.fBottom = rect.mBottom; 741 r.roundOut(&ir); 742 GraphicsJNI::irect_to_jrect(ir, env, bounds); 743 } 744 745 static void getStringBounds(JNIEnv* env, jobject, jlong paintHandle, jlong typefaceHandle, 746 jstring text, jint start, jint end, jint bidiFlags, jobject bounds) { 747 const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 748 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle); 749 const jchar* textArray = env->GetStringChars(text, NULL); 750 doTextBounds(env, textArray + start, end - start, bounds, *paint, typeface, bidiFlags); 751 env->ReleaseStringChars(text, textArray); 752 } 753 754 static void getCharArrayBounds(JNIEnv* env, jobject, jlong paintHandle, jlong typefaceHandle, 755 jcharArray text, jint index, jint count, jint bidiFlags, jobject bounds) { 756 const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 757 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle); 758 const jchar* textArray = env->GetCharArrayElements(text, NULL); 759 doTextBounds(env, textArray + index, count, bounds, *paint, typeface, bidiFlags); 760 env->ReleaseCharArrayElements(text, const_cast<jchar*>(textArray), 761 JNI_ABORT); 762 } 763 764 static jboolean layoutContainsNotdef(const Layout& layout) { 765 for (size_t i = 0; i < layout.nGlyphs(); i++) { 766 if (layout.getGlyphId(i) == 0) { 767 return true; 768 } 769 } 770 return false; 771 } 772 773 static jboolean hasGlyph(JNIEnv *env, jclass, jlong paintHandle, jlong typefaceHandle, 774 jint bidiFlags, jstring string) { 775 const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 776 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle); 777 ScopedStringChars str(env, string); 778 779 /* Start by rejecting unsupported base code point and variation selector pairs. */ 780 size_t nChars = 0; 781 const uint32_t kStartOfString = 0xFFFFFFFF; 782 uint32_t prevCp = kStartOfString; 783 for (size_t i = 0; i < str.size(); i++) { 784 jchar cu = str[i]; 785 uint32_t cp = cu; 786 if (U16_IS_TRAIL(cu)) { 787 // invalid UTF-16, unpaired trailing surrogate 788 return false; 789 } else if (U16_IS_LEAD(cu)) { 790 if (i + 1 == str.size()) { 791 // invalid UTF-16, unpaired leading surrogate at end of string 792 return false; 793 } 794 i++; 795 jchar cu2 = str[i]; 796 if (!U16_IS_TRAIL(cu2)) { 797 // invalid UTF-16, unpaired leading surrogate 798 return false; 799 } 800 cp = U16_GET_SUPPLEMENTARY(cu, cu2); 801 } 802 803 if (prevCp != kStartOfString && 804 ((0xFE00 <= cp && cp <= 0xFE0F) || (0xE0100 <= cp && cp <= 0xE01EF)) && 805 !MinikinUtils::hasVariationSelector(typeface, prevCp, cp)) { 806 // No font has a glyph for the code point and variation selector pair. 807 return false; 808 } 809 nChars++; 810 prevCp = cp; 811 } 812 Layout layout; 813 MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, str.get(), 0, str.size(), 814 str.size()); 815 size_t nGlyphs = layout.nGlyphs(); 816 if (nGlyphs != 1 && nChars > 1) { 817 // multiple-character input, and was not a ligature 818 // TODO: handle ZWJ/ZWNJ characters specially so we can detect certain ligatures 819 // in joining scripts, such as Arabic and Mongolian. 820 return false; 821 } 822 return nGlyphs > 0 && !layoutContainsNotdef(layout); 823 } 824 825 static jfloat doRunAdvance(const Paint* paint, TypefaceImpl* typeface, const jchar buf[], 826 jint start, jint count, jint bufSize, jboolean isRtl, jint offset) { 827 Layout layout; 828 int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR; 829 MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, buf, start, count, bufSize); 830 return getRunAdvance(layout, buf, start, count, offset); 831 } 832 833 static jfloat getRunAdvance___CIIIIZI_F(JNIEnv *env, jclass, jlong paintHandle, 834 jlong typefaceHandle, jcharArray text, jint start, jint end, jint contextStart, 835 jint contextEnd, jboolean isRtl, jint offset) { 836 const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 837 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle); 838 jchar* textArray = (jchar*) env->GetPrimitiveArrayCritical(text, NULL); 839 jfloat result = doRunAdvance(paint, typeface, textArray + contextStart, 840 start - contextStart, end - start, contextEnd - contextStart, isRtl, 841 offset - contextStart); 842 env->ReleasePrimitiveArrayCritical(text, textArray, JNI_ABORT); 843 return result; 844 } 845 846 static jint doOffsetForAdvance(const Paint* paint, TypefaceImpl* typeface, const jchar buf[], 847 jint start, jint count, jint bufSize, jboolean isRtl, jfloat advance) { 848 Layout layout; 849 int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR; 850 MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, buf, start, count, bufSize); 851 return getOffsetForAdvance(layout, buf, start, count, advance); 852 } 853 static jint getOffsetForAdvance___CIIIIZF_I(JNIEnv *env, jclass, jlong paintHandle, 854 jlong typefaceHandle, jcharArray text, jint start, jint end, jint contextStart, 855 jint contextEnd, jboolean isRtl, jfloat advance) { 856 const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 857 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle); 858 jchar* textArray = (jchar*) env->GetPrimitiveArrayCritical(text, NULL); 859 jint result = doOffsetForAdvance(paint, typeface, textArray + contextStart, 860 start - contextStart, end - start, contextEnd - contextStart, isRtl, advance); 861 result += contextStart; 862 env->ReleasePrimitiveArrayCritical(text, textArray, JNI_ABORT); 863 return result; 864 } 865 866}; // namespace PaintGlue 867 868static const JNINativeMethod methods[] = { 869 {"nGetNativeFinalizer", "()J", (void*) PaintGlue::getNativeFinalizer}, 870 {"nInit","()J", (void*) PaintGlue::init}, 871 {"nInitWithPaint","(J)J", (void*) PaintGlue::initWithPaint}, 872 873 {"nReset","!(J)V", (void*) PaintGlue::reset}, 874 {"nSet","!(JJ)V", (void*) PaintGlue::assign}, 875 {"nGetFlags","!(J)I", (void*) PaintGlue::getFlags}, 876 {"nSetFlags","!(JI)V", (void*) PaintGlue::setFlags}, 877 {"nGetHinting","!(J)I", (void*) PaintGlue::getHinting}, 878 {"nSetHinting","!(JI)V", (void*) PaintGlue::setHinting}, 879 {"nSetAntiAlias","!(JZ)V", (void*) PaintGlue::setAntiAlias}, 880 {"nSetSubpixelText","!(JZ)V", (void*) PaintGlue::setSubpixelText}, 881 {"nSetLinearText","!(JZ)V", (void*) PaintGlue::setLinearText}, 882 {"nSetUnderlineText","!(JZ)V", (void*) PaintGlue::setUnderlineText}, 883 {"nSetStrikeThruText","!(JZ)V", (void*) PaintGlue::setStrikeThruText}, 884 {"nSetFakeBoldText","!(JZ)V", (void*) PaintGlue::setFakeBoldText}, 885 {"nSetFilterBitmap","!(JZ)V", (void*) PaintGlue::setFilterBitmap}, 886 {"nSetDither","!(JZ)V", (void*) PaintGlue::setDither}, 887 {"nGetStyle","!(J)I", (void*) PaintGlue::getStyle}, 888 {"nSetStyle","!(JI)V", (void*) PaintGlue::setStyle}, 889 {"nGetColor","!(J)I", (void*) PaintGlue::getColor}, 890 {"nSetColor","!(JI)V", (void*) PaintGlue::setColor}, 891 {"nGetAlpha","!(J)I", (void*) PaintGlue::getAlpha}, 892 {"nSetAlpha","!(JI)V", (void*) PaintGlue::setAlpha}, 893 {"nGetStrokeWidth","!(J)F", (void*) PaintGlue::getStrokeWidth}, 894 {"nSetStrokeWidth","!(JF)V", (void*) PaintGlue::setStrokeWidth}, 895 {"nGetStrokeMiter","!(J)F", (void*) PaintGlue::getStrokeMiter}, 896 {"nSetStrokeMiter","!(JF)V", (void*) PaintGlue::setStrokeMiter}, 897 {"nGetStrokeCap","!(J)I", (void*) PaintGlue::getStrokeCap}, 898 {"nSetStrokeCap","!(JI)V", (void*) PaintGlue::setStrokeCap}, 899 {"nGetStrokeJoin","!(J)I", (void*) PaintGlue::getStrokeJoin}, 900 {"nSetStrokeJoin","!(JI)V", (void*) PaintGlue::setStrokeJoin}, 901 {"nGetFillPath","!(JJJ)Z", (void*) PaintGlue::getFillPath}, 902 {"nSetShader","!(JJ)J", (void*) PaintGlue::setShader}, 903 {"nSetColorFilter","!(JJ)J", (void*) PaintGlue::setColorFilter}, 904 {"nSetXfermode","!(JJ)J", (void*) PaintGlue::setXfermode}, 905 {"nSetPathEffect","!(JJ)J", (void*) PaintGlue::setPathEffect}, 906 {"nSetMaskFilter","!(JJ)J", (void*) PaintGlue::setMaskFilter}, 907 {"nSetTypeface","!(JJ)J", (void*) PaintGlue::setTypeface}, 908 {"nSetRasterizer","!(JJ)J", (void*) PaintGlue::setRasterizer}, 909 {"nGetTextAlign","!(J)I", (void*) PaintGlue::getTextAlign}, 910 {"nSetTextAlign","!(JI)V", (void*) PaintGlue::setTextAlign}, 911 {"nSetTextLocales","!(JLjava/lang/String;)I", (void*) PaintGlue::setTextLocales}, 912 {"nSetTextLocalesByMinikinLangListId","!(JI)V", 913 (void*) PaintGlue::setTextLocalesByMinikinLangListId}, 914 {"nIsElegantTextHeight","!(J)Z", (void*) PaintGlue::isElegantTextHeight}, 915 {"nSetElegantTextHeight","!(JZ)V", (void*) PaintGlue::setElegantTextHeight}, 916 {"nGetTextSize","!(J)F", (void*) PaintGlue::getTextSize}, 917 {"nSetTextSize","!(JF)V", (void*) PaintGlue::setTextSize}, 918 {"nGetTextScaleX","!(J)F", (void*) PaintGlue::getTextScaleX}, 919 {"nSetTextScaleX","!(JF)V", (void*) PaintGlue::setTextScaleX}, 920 {"nGetTextSkewX","!(J)F", (void*) PaintGlue::getTextSkewX}, 921 {"nSetTextSkewX","!(JF)V", (void*) PaintGlue::setTextSkewX}, 922 {"nGetLetterSpacing","!(J)F", (void*) PaintGlue::getLetterSpacing}, 923 {"nSetLetterSpacing","!(JF)V", (void*) PaintGlue::setLetterSpacing}, 924 {"nSetFontFeatureSettings","(JLjava/lang/String;)V", 925 (void*) PaintGlue::setFontFeatureSettings}, 926 {"nGetHyphenEdit", "!(J)I", (void*) PaintGlue::getHyphenEdit}, 927 {"nSetHyphenEdit", "!(JI)V", (void*) PaintGlue::setHyphenEdit}, 928 {"nAscent","!(JJ)F", (void*) PaintGlue::ascent}, 929 {"nDescent","!(JJ)F", (void*) PaintGlue::descent}, 930 931 {"nGetFontMetrics", "!(JJLandroid/graphics/Paint$FontMetrics;)F", 932 (void*)PaintGlue::getFontMetrics}, 933 {"nGetFontMetricsInt", "!(JJLandroid/graphics/Paint$FontMetricsInt;)I", 934 (void*)PaintGlue::getFontMetricsInt}, 935 936 {"nBreakText","(JJ[CIIFI[F)I", (void*) PaintGlue::breakTextC}, 937 {"nBreakText","(JJLjava/lang/String;ZFI[F)I", (void*) PaintGlue::breakTextS}, 938 {"nGetTextAdvances","(JJ[CIIIII[FI)F", 939 (void*) PaintGlue::getTextAdvances___CIIIII_FI}, 940 {"nGetTextAdvances","(JJLjava/lang/String;IIIII[FI)F", 941 (void*) PaintGlue::getTextAdvances__StringIIIII_FI}, 942 943 {"nGetTextRunCursor", "(J[CIIIII)I", (void*) PaintGlue::getTextRunCursor___C}, 944 {"nGetTextRunCursor", "(JLjava/lang/String;IIIII)I", 945 (void*) PaintGlue::getTextRunCursor__String}, 946 {"nGetTextPath", "(JJI[CIIFFJ)V", (void*) PaintGlue::getTextPath___C}, 947 {"nGetTextPath", "(JJILjava/lang/String;IIFFJ)V", (void*) PaintGlue::getTextPath__String}, 948 {"nGetStringBounds", "(JJLjava/lang/String;IIILandroid/graphics/Rect;)V", 949 (void*) PaintGlue::getStringBounds }, 950 {"nGetCharArrayBounds", "(JJ[CIIILandroid/graphics/Rect;)V", 951 (void*) PaintGlue::getCharArrayBounds }, 952 {"nHasGlyph", "(JJILjava/lang/String;)Z", (void*) PaintGlue::hasGlyph }, 953 {"nGetRunAdvance", "(JJ[CIIIIZI)F", (void*) PaintGlue::getRunAdvance___CIIIIZI_F}, 954 {"nGetOffsetForAdvance", "(JJ[CIIIIZF)I", 955 (void*) PaintGlue::getOffsetForAdvance___CIIIIZF_I}, 956 957 {"nSetShadowLayer", "!(JFFFI)V", (void*)PaintGlue::setShadowLayer}, 958 {"nHasShadowLayer", "!(J)Z", (void*)PaintGlue::hasShadowLayer} 959}; 960 961int register_android_graphics_Paint(JNIEnv* env) { 962 gFontMetrics_class = FindClassOrDie(env, "android/graphics/Paint$FontMetrics"); 963 gFontMetrics_class = MakeGlobalRefOrDie(env, gFontMetrics_class); 964 965 gFontMetrics_fieldID.top = GetFieldIDOrDie(env, gFontMetrics_class, "top", "F"); 966 gFontMetrics_fieldID.ascent = GetFieldIDOrDie(env, gFontMetrics_class, "ascent", "F"); 967 gFontMetrics_fieldID.descent = GetFieldIDOrDie(env, gFontMetrics_class, "descent", "F"); 968 gFontMetrics_fieldID.bottom = GetFieldIDOrDie(env, gFontMetrics_class, "bottom", "F"); 969 gFontMetrics_fieldID.leading = GetFieldIDOrDie(env, gFontMetrics_class, "leading", "F"); 970 971 gFontMetricsInt_class = FindClassOrDie(env, "android/graphics/Paint$FontMetricsInt"); 972 gFontMetricsInt_class = MakeGlobalRefOrDie(env, gFontMetricsInt_class); 973 974 gFontMetricsInt_fieldID.top = GetFieldIDOrDie(env, gFontMetricsInt_class, "top", "I"); 975 gFontMetricsInt_fieldID.ascent = GetFieldIDOrDie(env, gFontMetricsInt_class, "ascent", "I"); 976 gFontMetricsInt_fieldID.descent = GetFieldIDOrDie(env, gFontMetricsInt_class, "descent", "I"); 977 gFontMetricsInt_fieldID.bottom = GetFieldIDOrDie(env, gFontMetricsInt_class, "bottom", "I"); 978 gFontMetricsInt_fieldID.leading = GetFieldIDOrDie(env, gFontMetricsInt_class, "leading", "I"); 979 980 return RegisterMethodsOrDie(env, "android/graphics/Paint", methods, NELEM(methods)); 981} 982 983} 984