19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* libs/android_runtime/android/graphics/Paint.cpp 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** Copyright 2006, The Android Open Source Project 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 58451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes** Licensed under the Apache License, Version 2.0 (the "License"); 68451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes** you may not use this file except in compliance with the License. 78451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes** You may obtain a copy of the License at 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 98451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes** http://www.apache.org/licenses/LICENSE-2.0 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 118451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes** Unless required by applicable law or agreed to in writing, software 128451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes** distributed under the License is distributed on an "AS IS" BASIS, 138451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 148451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes** See the License for the specific language governing permissions and 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** limitations under the License. 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project*/ 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18f43fa5746ee5b81a6e386d36594094d079ac8160Dianne Hackborn#define LOG_TAG "Paint" 19f43fa5746ee5b81a6e386d36594094d079ac8160Dianne Hackborn 20f43fa5746ee5b81a6e386d36594094d079ac8160Dianne Hackborn#include <utils/Log.h> 21f43fa5746ee5b81a6e386d36594094d079ac8160Dianne Hackborn 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "jni.h" 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "GraphicsJNI.h" 24ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe#include "core_jni_helpers.h" 252279b2534272282a5b5152723235da397e49195cSteven Moreland#include <nativehelper/ScopedStringChars.h> 262279b2534272282a5b5152723235da397e49195cSteven Moreland#include <nativehelper/ScopedUtfChars.h> 27ee23f61873497efc70045cc4794be9fdf18eed9fSeigo Nonaka#include <nativehelper/ScopedPrimitiveArray.h> 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SkBlurDrawLooper.h" 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SkColorFilter.h" 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SkMaskFilter.h" 32eba81d0f88f52ca097204ca526e796a83fdd57d5Derek Sollenberger#include "SkPath.h" 33260ab726486317496bc12a57d599ea96dcde3284Mike Reed#include "SkPathEffect.h" 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SkShader.h" 35c2f31df8b3b9a237e9abffc59c61804ad8495073Mike Reed#include "SkBlendMode.h" 36ac1cbaf2e5575ac75a0160e13089d51a0bb232faBilly Hewlett#include "unicode/uloc.h" 370c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt#include "unicode/ushape.h" 38c29a0a4664a4b9871fadd668b632469a0db240b9Derek Sollenberger#include "utils/Blur.h" 390c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt 40dccca44ffda4836b56a21da95a046c9708ffd49csergeyv#include <hwui/MinikinSkia.h> 41dccca44ffda4836b56a21da95a046c9708ffd49csergeyv#include <hwui/MinikinUtils.h> 42dccca44ffda4836b56a21da95a046c9708ffd49csergeyv#include <hwui/Paint.h> 43bad99183916ba2bac6659efc8a28273e344ba511sergeyv#include <hwui/Typeface.h> 44e368b6bcfd499543a876b4cae02f1ca563ff1cb6Raph Levien#include <minikin/GraphemeBreak.h> 4520866c140438a9aca3e1ad09fe646308678e9383Seigo Nonaka#include <minikin/LocaleList.h> 46a027ec5c2dbfbbf10cac9ea538f5e230b093be2fRaph Levien#include <minikin/Measurement.h> 47bb1a96647a82df5a134bf631fc9db342e7ef61deSeigo Nonaka#include <unicode/utf16.h> 481a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien 49f036ead2a218ffa43697fcaa999b666a4c6d13cfRoozbeh Pournader#include <cassert> 50f036ead2a218ffa43697fcaa999b666a4c6d13cfRoozbeh Pournader#include <cstring> 51536afe6ef79a663e59c3b9781c561f7029ee9319Keisuke Kuroyanagi#include <memory> 52f036ead2a218ffa43697fcaa999b666a4c6d13cfRoozbeh Pournader#include <vector> 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android { 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstruct JMetricsID { 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jfieldID top; 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jfieldID ascent; 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jfieldID descent; 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jfieldID bottom; 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jfieldID leading; 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jclass gFontMetrics_class; 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JMetricsID gFontMetrics_fieldID; 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jclass gFontMetricsInt_class; 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JMetricsID gFontMetricsInt_fieldID; 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 706ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbodstatic void defaultSettingsForAndroid(Paint* paint) { 71c511bee87cda99a252d1a62487f47c8f05aee78cFabrice Di Meglio // GlyphID encoding is required because we are using Harfbuzz shaping 726ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod paint->setTextEncoding(Paint::kGlyphID_TextEncoding); 733d63e0119dc763ed0a06fd7498375746fd391d80Mike Reed} 743d63e0119dc763ed0a06fd7498375746fd391d80Mike Reed 75dbffd250003e60c0f11ac3ad2b63f91f67962610John Recknamespace PaintGlue { 760c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt enum MoveOpt { 770c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt AFTER, AT_OR_AFTER, BEFORE, AT_OR_BEFORE, AT 780c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt }; 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 80775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhler static void deletePaint(Paint* paint) { 81775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhler delete paint; 82775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhler } 83775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhler 84775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhler static jlong getNativeFinalizer(JNIEnv*, jobject) { 85775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhler return static_cast<jlong>(reinterpret_cast<uintptr_t>(&deletePaint)); 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 88dbffd250003e60c0f11ac3ad2b63f91f67962610John Reck static jlong init(JNIEnv* env, jobject) { 89b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed static_assert(1 << 0 == SkPaint::kAntiAlias_Flag, "paint_flags_mismatch"); 90b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed static_assert(1 << 2 == SkPaint::kDither_Flag, "paint_flags_mismatch"); 91b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed static_assert(1 << 3 == SkPaint::kUnderlineText_ReserveFlag, "paint_flags_mismatch"); 92b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed static_assert(1 << 4 == SkPaint::kStrikeThruText_ReserveFlag, "paint_flags_mismatch"); 93b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed static_assert(1 << 5 == SkPaint::kFakeBoldText_Flag, "paint_flags_mismatch"); 94b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed static_assert(1 << 6 == SkPaint::kLinearText_Flag, "paint_flags_mismatch"); 95b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed static_assert(1 << 7 == SkPaint::kSubpixelText_Flag, "paint_flags_mismatch"); 96b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed static_assert(1 << 8 == SkPaint::kDevKernText_Flag, "paint_flags_mismatch"); 97b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed static_assert(1 << 10 == SkPaint::kEmbeddedBitmapText_Flag, "paint_flags_mismatch"); 980b8606266c1afc69cbeb73acda67c85d87943318Derek Sollenberger 996ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod Paint* obj = new Paint(); 1003d63e0119dc763ed0a06fd7498375746fd391d80Mike Reed defaultSettingsForAndroid(obj); 10136bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat return reinterpret_cast<jlong>(obj); 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat static jlong initWithPaint(JNIEnv* env, jobject clazz, jlong paintHandle) { 1056ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod Paint* paint = reinterpret_cast<Paint*>(paintHandle); 1066ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod Paint* obj = new Paint(*paint); 10736bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat return reinterpret_cast<jlong>(obj); 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1098451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 110318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka static int breakText(JNIEnv* env, const Paint& paint, const Typeface* typeface, 111318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka const jchar text[], int count, float maxWidth, jint bidiFlags, jfloatArray jmeasured, 112f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck const bool forwardScan) { 113f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck size_t measuredCount = 0; 114f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck float measured = 0; 1158451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 116f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck std::unique_ptr<float[]> advancesArray(new float[count]); 1177c93e868825225a270c993ac058687adde682626Seigo Nonaka MinikinUtils::measureText(&paint, static_cast<minikin::Bidi>(bidiFlags), typeface, text, 1187c93e868825225a270c993ac058687adde682626Seigo Nonaka 0, count, count, advancesArray.get()); 1194c9355c35a0f62805739823a62ad41ca1cbc6502Mike Reed 120f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck for (int i = 0; i < count; i++) { 121f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck // traverse in the given direction 122f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck int index = forwardScan ? i : (count - i - 1); 123f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck float width = advancesArray[index]; 124f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck if (measured + width > maxWidth) { 125f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck break; 126f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 127f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck // properly handle clusters when scanning backwards 128f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck if (forwardScan || width != 0.0f) { 129f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck measuredCount = i + 1; 130f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 131f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck measured += width; 1324c9355c35a0f62805739823a62ad41ca1cbc6502Mike Reed } 1338451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 134f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck if (jmeasured && env->GetArrayLength(jmeasured) > 0) { 135f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck AutoJavaFloatArray autoMeasured(env, jmeasured, 1); 136f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck jfloat* array = autoMeasured.ptr(); 137f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck array[0] = measured; 138f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 139f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return measuredCount; 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1418451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 142318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka static jint breakTextC(JNIEnv* env, jobject clazz, jlong paintHandle, jcharArray jtext, 143318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka jint index, jint count, jfloat maxWidth, jint bidiFlags, jfloatArray jmeasuredWidth) { 144f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck NPE_CHECK_RETURN_ZERO(env, jtext); 145f43fa5746ee5b81a6e386d36594094d079ac8160Dianne Hackborn 146f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck Paint* paint = reinterpret_cast<Paint*>(paintHandle); 147318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka const Typeface* typeface = paint->getAndroidTypeface(); 148f43fa5746ee5b81a6e386d36594094d079ac8160Dianne Hackborn 149f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck bool forwardTextDirection; 150f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck if (count < 0) { 151f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck forwardTextDirection = false; 152f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck count = -count; 153f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 154f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck else { 155f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck forwardTextDirection = true; 156f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 1578451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 158f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck if ((index < 0) || (index + count > env->GetArrayLength(jtext))) { 159f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck doThrowAIOOBE(env); 160f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return 0; 161f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 1628451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 163f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck const jchar* text = env->GetCharArrayElements(jtext, nullptr); 164f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck count = breakText(env, *paint, typeface, text + index, count, maxWidth, 165f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck bidiFlags, jmeasuredWidth, forwardTextDirection); 166f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck env->ReleaseCharArrayElements(jtext, const_cast<jchar*>(text), 167f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck JNI_ABORT); 168f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return count; 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1708451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 171318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka static jint breakTextS(JNIEnv* env, jobject clazz, jlong paintHandle, jstring jtext, 172318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka jboolean forwards, jfloat maxWidth, jint bidiFlags, jfloatArray jmeasuredWidth) { 173f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck NPE_CHECK_RETURN_ZERO(env, jtext); 1748451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 175f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck Paint* paint = reinterpret_cast<Paint*>(paintHandle); 176318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka const Typeface* typeface = paint->getAndroidTypeface(); 1778451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 178f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck int count = env->GetStringLength(jtext); 179f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck const jchar* text = env->GetStringChars(jtext, nullptr); 180f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck count = breakText(env, *paint, typeface, text, count, maxWidth, bidiFlags, jmeasuredWidth, forwards); 181f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck env->ReleaseStringChars(jtext, text); 182f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return count; 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1848451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 185318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka static jfloat doTextAdvances(JNIEnv *env, Paint *paint, const Typeface* typeface, 186f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck const jchar *text, jint start, jint count, jint contextCount, jint bidiFlags, 187f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck jfloatArray advances, jint advancesIndex) { 188f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck NPE_CHECK_RETURN_ZERO(env, text); 1898451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 190f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck if ((start | count | contextCount | advancesIndex) < 0 || contextCount < count) { 191f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck doThrowAIOOBE(env); 192f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return 0; 193f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 194f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck if (count == 0) { 195f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return 0; 196f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 197f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck if (advances) { 198f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck size_t advancesLength = env->GetArrayLength(advances); 199f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck if ((size_t)(count + advancesIndex) > advancesLength) { 200f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck doThrowAIOOBE(env); 201f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return 0; 202f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 203f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 204f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck std::unique_ptr<jfloat[]> advancesArray; 205f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck if (advances) { 206f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck advancesArray.reset(new jfloat[count]); 207f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 2087c93e868825225a270c993ac058687adde682626Seigo Nonaka const float advance = MinikinUtils::measureText(paint, 2097c93e868825225a270c993ac058687adde682626Seigo Nonaka static_cast<minikin::Bidi>(bidiFlags), typeface, text, start, count, contextCount, 2107c93e868825225a270c993ac058687adde682626Seigo Nonaka advancesArray.get()); 211f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck if (advances) { 212f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck env->SetFloatArrayRegion(advances, advancesIndex, count, advancesArray.get()); 213f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 214f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return advance; 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2168451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 217f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static jfloat getTextAdvances___CIIIII_FI(JNIEnv* env, jobject clazz, jlong paintHandle, 218f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck jcharArray text, jint index, jint count, jint contextIndex, jint contextCount, 219f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck jint bidiFlags, jfloatArray advances, jint advancesIndex) { 220f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck Paint* paint = reinterpret_cast<Paint*>(paintHandle); 221318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka const Typeface* typeface = paint->getAndroidTypeface(); 222f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck jchar* textArray = env->GetCharArrayElements(text, nullptr); 223f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck jfloat result = doTextAdvances(env, paint, typeface, textArray + contextIndex, 224f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck index - contextIndex, count, contextCount, bidiFlags, advances, advancesIndex); 225f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck env->ReleaseCharArrayElements(text, textArray, JNI_ABORT); 226f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return result; 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2288451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 229f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static jfloat getTextAdvances__StringIIIII_FI(JNIEnv* env, jobject clazz, jlong paintHandle, 230f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck jstring text, jint start, jint end, jint contextStart, jint contextEnd, jint bidiFlags, 231f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck jfloatArray advances, jint advancesIndex) { 232f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck Paint* paint = reinterpret_cast<Paint*>(paintHandle); 233318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka const Typeface* typeface = paint->getAndroidTypeface(); 234f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck const jchar* textArray = env->GetStringChars(text, nullptr); 235f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck jfloat result = doTextAdvances(env, paint, typeface, textArray + contextStart, 236f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck start - contextStart, end - start, contextEnd - contextStart, bidiFlags, 237f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck advances, advancesIndex); 238f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck env->ReleaseStringChars(text, textArray); 239f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return result; 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2418451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 242318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka static jint doTextRunCursor(JNIEnv *env, Paint* paint, const Typeface* typeface, 243318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka const jchar *text, jint start, jint count, jint dir, jint offset, jint opt) { 244f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck minikin::GraphemeBreak::MoveOpt moveOpt = minikin::GraphemeBreak::MoveOpt(opt); 2457c93e868825225a270c993ac058687adde682626Seigo Nonaka minikin::Bidi bidiFlags = dir == 1 ? minikin::Bidi::FORCE_RTL : minikin::Bidi::FORCE_LTR; 2465d74b1c76f5da4510a1d70d8d3b0e8c15765f231Roozbeh Pournader std::unique_ptr<float[]> advancesArray(new float[count]); 2475d74b1c76f5da4510a1d70d8d3b0e8c15765f231Roozbeh Pournader MinikinUtils::measureText(paint, bidiFlags, typeface, text, start, count, start + count, 2485d74b1c76f5da4510a1d70d8d3b0e8c15765f231Roozbeh Pournader advancesArray.get()); 2495d74b1c76f5da4510a1d70d8d3b0e8c15765f231Roozbeh Pournader size_t result = minikin::GraphemeBreak::getTextRunCursor(advancesArray.get(), text, 2505d74b1c76f5da4510a1d70d8d3b0e8c15765f231Roozbeh Pournader start, count, offset, moveOpt); 251f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return static_cast<jint>(result); 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2538451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 254318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka static jint getTextRunCursor___C(JNIEnv* env, jobject clazz, jlong paintHandle, jcharArray text, 255318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka jint contextStart, jint contextCount, jint dir, jint offset, jint cursorOpt) { 256f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck Paint* paint = reinterpret_cast<Paint*>(paintHandle); 257318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka const Typeface* typeface = paint->getAndroidTypeface(); 258f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck jchar* textArray = env->GetCharArrayElements(text, nullptr); 2595d74b1c76f5da4510a1d70d8d3b0e8c15765f231Roozbeh Pournader jint result = doTextRunCursor(env, paint, typeface, textArray, 2605d74b1c76f5da4510a1d70d8d3b0e8c15765f231Roozbeh Pournader contextStart, contextCount, dir, offset, cursorOpt); 261f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck env->ReleaseCharArrayElements(text, textArray, JNI_ABORT); 262f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return result; 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2648451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 2655d74b1c76f5da4510a1d70d8d3b0e8c15765f231Roozbeh Pournader static jint getTextRunCursor__String(JNIEnv* env, jobject clazz, jlong paintHandle, 266318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka jstring text, jint contextStart, jint contextEnd, jint dir, jint offset, 267318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka jint cursorOpt) { 268f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck Paint* paint = reinterpret_cast<Paint*>(paintHandle); 269318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka const Typeface* typeface = paint->getAndroidTypeface(); 270f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck const jchar* textArray = env->GetStringChars(text, nullptr); 2715d74b1c76f5da4510a1d70d8d3b0e8c15765f231Roozbeh Pournader jint result = doTextRunCursor(env, paint, typeface, textArray, 2725d74b1c76f5da4510a1d70d8d3b0e8c15765f231Roozbeh Pournader contextStart, contextEnd - contextStart, dir, offset, cursorOpt); 273f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck env->ReleaseStringChars(text, textArray); 274f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return result; 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2768451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 277f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck class GetTextFunctor { 278f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck public: 279f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck GetTextFunctor(const minikin::Layout& layout, SkPath* path, jfloat x, jfloat y, 280f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck Paint* paint, uint16_t* glyphs, SkPoint* pos) 281f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck : layout(layout), path(path), x(x), y(y), paint(paint), glyphs(glyphs), pos(pos) { 282f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 2838451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 284f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck void operator()(size_t start, size_t end) { 285f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck for (size_t i = start; i < end; i++) { 286f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck glyphs[i] = layout.getGlyphId(i); 287f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck pos[i].fX = x + layout.getX(i); 288f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck pos[i].fY = y + layout.getY(i); 289f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 290f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck if (start == 0) { 291f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck paint->getPosTextPath(glyphs + start, (end - start) << 1, pos + start, path); 292f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } else { 293f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck paint->getPosTextPath(glyphs + start, (end - start) << 1, pos + start, &tmpPath); 294f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck path->addPath(tmpPath); 295f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 296f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 297f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck private: 298f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck const minikin::Layout& layout; 299f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck SkPath* path; 300f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck jfloat x; 301f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck jfloat y; 302f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck Paint* paint; 303f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck uint16_t* glyphs; 304f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck SkPoint* pos; 305f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck SkPath tmpPath; 306f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck }; 3078451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 308318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka static void getTextPath(JNIEnv* env, Paint* paint, const Typeface* typeface, const jchar* text, 309f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck jint count, jint bidiFlags, jfloat x, jfloat y, SkPath* path) { 310c7064146f959caec058980ced144942c8044a169Seigo Nonaka minikin::Layout layout = MinikinUtils::doLayout( 311783f961d2fa6f916009844dafeaa08ffaf96a4d3Seigo Nonaka paint, static_cast<minikin::Bidi>(bidiFlags), typeface, text, 0, count, count, 31283143d005b38bf4d629825aaac037e759c68b8a6Seigo Nonaka nullptr); 313f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck size_t nGlyphs = layout.nGlyphs(); 314f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck uint16_t* glyphs = new uint16_t[nGlyphs]; 315f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck SkPoint* pos = new SkPoint[nGlyphs]; 3168451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 317f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck x += MinikinUtils::xOffsetForTextAlign(paint, layout); 318f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck Paint::Align align = paint->getTextAlign(); 319f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck paint->setTextAlign(Paint::kLeft_Align); 320f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck paint->setTextEncoding(Paint::kGlyphID_TextEncoding); 321f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck GetTextFunctor f(layout, path, x, y, paint, glyphs, pos); 322f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck MinikinUtils::forFontRun(layout, paint, f); 323f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck paint->setTextAlign(align); 324f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck delete[] glyphs; 325f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck delete[] pos; 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3278451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 328318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka static void getTextPath___C(JNIEnv* env, jobject clazz, jlong paintHandle, jint bidiFlags, 329f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck jcharArray text, jint index, jint count, jfloat x, jfloat y, jlong pathHandle) { 330f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck Paint* paint = reinterpret_cast<Paint*>(paintHandle); 331318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka const Typeface* typeface = paint->getAndroidTypeface(); 332f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck SkPath* path = reinterpret_cast<SkPath*>(pathHandle); 333f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck const jchar* textArray = env->GetCharArrayElements(text, nullptr); 334f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck getTextPath(env, paint, typeface, textArray + index, count, bidiFlags, x, y, path); 335f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck env->ReleaseCharArrayElements(text, const_cast<jchar*>(textArray), JNI_ABORT); 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3378451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 338318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka static void getTextPath__String(JNIEnv* env, jobject clazz, jlong paintHandle, jint bidiFlags, 339f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck jstring text, jint start, jint end, jfloat x, jfloat y, jlong pathHandle) { 340f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck Paint* paint = reinterpret_cast<Paint*>(paintHandle); 341318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka const Typeface* typeface = paint->getAndroidTypeface(); 342f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck SkPath* path = reinterpret_cast<SkPath*>(pathHandle); 343f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck const jchar* textArray = env->GetStringChars(text, nullptr); 344f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck getTextPath(env, paint, typeface, textArray + start, end - start, bidiFlags, x, y, path); 345f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck env->ReleaseStringChars(text, textArray); 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3478451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 348f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static void doTextBounds(JNIEnv* env, const jchar* text, int count, jobject bounds, 349318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka const Paint& paint, const Typeface* typeface, jint bidiFlags) { 350f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck SkRect r; 351f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck SkIRect ir; 352f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck 3537c93e868825225a270c993ac058687adde682626Seigo Nonaka minikin::Layout layout = MinikinUtils::doLayout(&paint, 35483143d005b38bf4d629825aaac037e759c68b8a6Seigo Nonaka static_cast<minikin::Bidi>(bidiFlags), typeface, text, 0, count, count, nullptr); 355f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck minikin::MinikinRect rect; 356f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck layout.getBounds(&rect); 357f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck r.fLeft = rect.mLeft; 358f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck r.fTop = rect.mTop; 359f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck r.fRight = rect.mRight; 360f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck r.fBottom = rect.mBottom; 361f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck r.roundOut(&ir); 362f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck GraphicsJNI::irect_to_jrect(ir, env, bounds); 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3648451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 365318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka static void getStringBounds(JNIEnv* env, jobject, jlong paintHandle, jstring text, jint start, 366318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka jint end, jint bidiFlags, jobject bounds) { 367f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 368318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka const Typeface* typeface = paint->getAndroidTypeface(); 369f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck const jchar* textArray = env->GetStringChars(text, nullptr); 370f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck doTextBounds(env, textArray + start, end - start, bounds, *paint, typeface, bidiFlags); 371f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck env->ReleaseStringChars(text, textArray); 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3738451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 374318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka static void getCharArrayBounds(JNIEnv* env, jobject, jlong paintHandle, jcharArray text, 375318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka jint index, jint count, jint bidiFlags, jobject bounds) { 376f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 377318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka const Typeface* typeface = paint->getAndroidTypeface(); 378f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck const jchar* textArray = env->GetCharArrayElements(text, nullptr); 379f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck doTextBounds(env, textArray + index, count, bounds, *paint, typeface, bidiFlags); 380f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck env->ReleaseCharArrayElements(text, const_cast<jchar*>(textArray), 381f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck JNI_ABORT); 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3838451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 384f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck // Returns true if the given string is exact one pair of regional indicators. 385f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static bool isFlag(const jchar* str, size_t length) { 386f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck const jchar RI_LEAD_SURROGATE = 0xD83C; 387f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck const jchar RI_TRAIL_SURROGATE_MIN = 0xDDE6; 388f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck const jchar RI_TRAIL_SURROGATE_MAX = 0xDDFF; 389f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck 390f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck if (length != 4) { 391f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return false; 392f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 393f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck if (str[0] != RI_LEAD_SURROGATE || str[2] != RI_LEAD_SURROGATE) { 394f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return false; 395f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 396f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return RI_TRAIL_SURROGATE_MIN <= str[1] && str[1] <= RI_TRAIL_SURROGATE_MAX && 397f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck RI_TRAIL_SURROGATE_MIN <= str[3] && str[3] <= RI_TRAIL_SURROGATE_MAX; 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3998451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 400f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static jboolean layoutContainsNotdef(const minikin::Layout& layout) { 401f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck for (size_t i = 0; i < layout.nGlyphs(); i++) { 402f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck if (layout.getGlyphId(i) == 0) { 403f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return true; 404f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 405f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 406f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return false; 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4088451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 409f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck // Don't count glyphs that are the recommended "space" glyph and are zero width. 410f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck // This logic makes assumptions about HarfBuzz layout, but does correctly handle 411f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck // cases where ligatures form and zero width space glyphs are left in as 412f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck // placeholders. 413f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static size_t countNonSpaceGlyphs(const minikin::Layout& layout) { 414f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck size_t count = 0; 415f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static unsigned int kSpaceGlyphId = 3; 416f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck for (size_t i = 0; i < layout.nGlyphs(); i++) { 417f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck if (layout.getGlyphId(i) != kSpaceGlyphId || layout.getCharAdvance(i) != 0.0) { 418f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck count++; 419f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 420f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 421f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return count; 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4238451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 424318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka static jboolean hasGlyph(JNIEnv *env, jclass, jlong paintHandle, jint bidiFlags, 425318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka jstring string) { 426f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 427318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka const Typeface* typeface = paint->getAndroidTypeface(); 428f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck ScopedStringChars str(env, string); 4295d31a293ad0a832c7b8b445c1a67fb1800e5da32John Reck 430f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck /* Start by rejecting unsupported base code point and variation selector pairs. */ 431f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck size_t nChars = 0; 432f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck const uint32_t kStartOfString = 0xFFFFFFFF; 433f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck uint32_t prevCp = kStartOfString; 434f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck for (size_t i = 0; i < str.size(); i++) { 435f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck jchar cu = str[i]; 436f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck uint32_t cp = cu; 437f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck if (U16_IS_TRAIL(cu)) { 438f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck // invalid UTF-16, unpaired trailing surrogate 439f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return false; 440f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } else if (U16_IS_LEAD(cu)) { 441f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck if (i + 1 == str.size()) { 442f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck // invalid UTF-16, unpaired leading surrogate at end of string 443f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return false; 444f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 445f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck i++; 446f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck jchar cu2 = str[i]; 447f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck if (!U16_IS_TRAIL(cu2)) { 448f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck // invalid UTF-16, unpaired leading surrogate 449f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return false; 450f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 451f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck cp = U16_GET_SUPPLEMENTARY(cu, cu2); 452f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 4538451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 454f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck if (prevCp != kStartOfString && 455f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck ((0xFE00 <= cp && cp <= 0xFE0F) || (0xE0100 <= cp && cp <= 0xE01EF))) { 456f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck bool hasVS = MinikinUtils::hasVariationSelector(typeface, prevCp, cp); 457f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck if (!hasVS) { 458f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck // No font has a glyph for the code point and variation selector pair. 459f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return false; 460f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } else if (nChars == 1 && i + 1 == str.size()) { 461f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck // The string is just a codepoint and a VS, we have an authoritative answer 462f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return true; 463f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 464f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 465f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck nChars++; 466f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck prevCp = cp; 467f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 4687c93e868825225a270c993ac058687adde682626Seigo Nonaka minikin::Layout layout = MinikinUtils::doLayout(paint, 4697c93e868825225a270c993ac058687adde682626Seigo Nonaka static_cast<minikin::Bidi>(bidiFlags), typeface, str.get(), 0, str.size(), 47083143d005b38bf4d629825aaac037e759c68b8a6Seigo Nonaka str.size(), nullptr); 471f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck size_t nGlyphs = countNonSpaceGlyphs(layout); 472f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck if (nGlyphs != 1 && nChars > 1) { 473f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck // multiple-character input, and was not a ligature 474f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck // TODO: handle ZWJ/ZWNJ characters specially so we can detect certain ligatures 475f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck // in joining scripts, such as Arabic and Mongolian. 476f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return false; 477f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 4788451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 479f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck if (nGlyphs == 0 || layoutContainsNotdef(layout)) { 480f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return false; // The collection doesn't have a glyph. 481f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 482f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck 483f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck if (nChars == 2 && isFlag(str.get(), str.size())) { 484f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck // Some font may have a special glyph for unsupported regional indicator pairs. 485f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck // To return false for this case, need to compare the glyph id with the one of ZZ 486f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck // since ZZ is reserved for unknown or invalid territory. 487f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck // U+1F1FF (REGIONAL INDICATOR SYMBOL LETTER Z) is \uD83C\uDDFF in UTF16. 488f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static const jchar ZZ_FLAG_STR[] = { 0xD83C, 0xDDFF, 0xD83C, 0xDDFF }; 4897c93e868825225a270c993ac058687adde682626Seigo Nonaka minikin::Layout zzLayout = MinikinUtils::doLayout(paint, 490783f961d2fa6f916009844dafeaa08ffaf96a4d3Seigo Nonaka static_cast<minikin::Bidi>(bidiFlags), typeface, ZZ_FLAG_STR, 0, 4, 4, 49183143d005b38bf4d629825aaac037e759c68b8a6Seigo Nonaka nullptr); 492f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck if (zzLayout.nGlyphs() != 1 || layoutContainsNotdef(zzLayout)) { 493f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck // The font collection doesn't have a glyph for unknown flag. Just return true. 494f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return true; 495f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 496f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return zzLayout.getGlyphId(0) != layout.getGlyphId(0); 497f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 498f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return true; 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5008451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 501318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka static jfloat doRunAdvance(const Paint* paint, const Typeface* typeface, const jchar buf[], 502f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck jint start, jint count, jint bufSize, jboolean isRtl, jint offset) { 5037c93e868825225a270c993ac058687adde682626Seigo Nonaka minikin::Bidi bidiFlags = isRtl ? minikin::Bidi::FORCE_RTL : minikin::Bidi::FORCE_LTR; 504f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck if (offset == start + count) { 505f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return MinikinUtils::measureText(paint, bidiFlags, typeface, buf, start, count, 506f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck bufSize, nullptr); 507f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 508f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck std::unique_ptr<float[]> advancesArray(new float[count]); 509f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck MinikinUtils::measureText(paint, bidiFlags, typeface, buf, start, count, bufSize, 510f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck advancesArray.get()); 511f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return minikin::getRunAdvance(advancesArray.get(), buf, start, count, offset); 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5138451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 514318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka static jfloat getRunAdvance___CIIIIZI_F(JNIEnv *env, jclass, jlong paintHandle, jcharArray text, 515318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka jint start, jint end, jint contextStart, jint contextEnd, jboolean isRtl, jint offset) { 516f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 517318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka const Typeface* typeface = paint->getAndroidTypeface(); 518ee23f61873497efc70045cc4794be9fdf18eed9fSeigo Nonaka ScopedCharArrayRO textArray(env, text); 519ee23f61873497efc70045cc4794be9fdf18eed9fSeigo Nonaka jfloat result = doRunAdvance(paint, typeface, textArray.get() + contextStart, 520f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck start - contextStart, end - start, contextEnd - contextStart, isRtl, 521f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck offset - contextStart); 522f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return result; 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5248451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 525318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka static jint doOffsetForAdvance(const Paint* paint, const Typeface* typeface, const jchar buf[], 526f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck jint start, jint count, jint bufSize, jboolean isRtl, jfloat advance) { 5277c93e868825225a270c993ac058687adde682626Seigo Nonaka minikin::Bidi bidiFlags = isRtl ? minikin::Bidi::FORCE_RTL : minikin::Bidi::FORCE_LTR; 528f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck std::unique_ptr<float[]> advancesArray(new float[count]); 529f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck MinikinUtils::measureText(paint, bidiFlags, typeface, buf, start, count, bufSize, 530f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck advancesArray.get()); 531f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return minikin::getOffsetForAdvance(advancesArray.get(), buf, start, count, advance); 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5338451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 534f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static jint getOffsetForAdvance___CIIIIZF_I(JNIEnv *env, jclass, jlong paintHandle, 535318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka jcharArray text, jint start, jint end, jint contextStart, jint contextEnd, 536318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka jboolean isRtl, jfloat advance) { 537f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 538318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka const Typeface* typeface = paint->getAndroidTypeface(); 539ee23f61873497efc70045cc4794be9fdf18eed9fSeigo Nonaka ScopedCharArrayRO textArray(env, text); 540ee23f61873497efc70045cc4794be9fdf18eed9fSeigo Nonaka jint result = doOffsetForAdvance(paint, typeface, textArray.get() + contextStart, 541f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck start - contextStart, end - start, contextEnd - contextStart, isRtl, advance); 542f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck result += contextStart; 543f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return result; 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5458451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 546f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck // ------------------ @FastNative --------------------------- 547f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck 548cfc607cf57d453f977c9c4bf09b41ac481c4bbecSeigo Nonaka static jint setTextLocales(JNIEnv* env, jobject clazz, jlong objHandle, jstring locales) { 5496ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod Paint* obj = reinterpret_cast<Paint*>(objHandle); 550f036ead2a218ffa43697fcaa999b666a4c6d13cfRoozbeh Pournader ScopedUtfChars localesChars(env, locales); 55120866c140438a9aca3e1ad09fe646308678e9383Seigo Nonaka jint minikinLocaleListId = minikin::registerLocaleList(localesChars.c_str()); 55220866c140438a9aca3e1ad09fe646308678e9383Seigo Nonaka obj->setMinikinLocaleListId(minikinLocaleListId); 55320866c140438a9aca3e1ad09fe646308678e9383Seigo Nonaka return minikinLocaleListId; 554cfc607cf57d453f977c9c4bf09b41ac481c4bbecSeigo Nonaka } 555d7a80774f0a2175f9ee81a7741f9a171c78e0b8bDerek Sollenberger 556805f6ebf17e2791624bb1a30834b4c1cc65583bfBehdad Esfahbod static void setFontFeatureSettings(JNIEnv* env, jobject clazz, jlong paintHandle, jstring settings) { 557805f6ebf17e2791624bb1a30834b4c1cc65583bfBehdad Esfahbod Paint* paint = reinterpret_cast<Paint*>(paintHandle); 558e9ad3931fae71c8a8cd000fd52d5df4be79b0895Behdad Esfahbod if (!settings) { 559805f6ebf17e2791624bb1a30834b4c1cc65583bfBehdad Esfahbod paint->setFontFeatureSettings(std::string()); 560e9ad3931fae71c8a8cd000fd52d5df4be79b0895Behdad Esfahbod } else { 561805f6ebf17e2791624bb1a30834b4c1cc65583bfBehdad Esfahbod ScopedUtfChars settingsChars(env, settings); 562805f6ebf17e2791624bb1a30834b4c1cc65583bfBehdad Esfahbod paint->setFontFeatureSettings(std::string(settingsChars.c_str(), settingsChars.size())); 563805f6ebf17e2791624bb1a30834b4c1cc65583bfBehdad Esfahbod } 564805f6ebf17e2791624bb1a30834b4c1cc65583bfBehdad Esfahbod } 565805f6ebf17e2791624bb1a30834b4c1cc65583bfBehdad Esfahbod 566318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka static SkScalar getMetricsInternal(jlong paintHandle, Paint::FontMetrics *metrics) { 56753c0077256afebb0312f01ef4f60a7445da1f5d9Raph Levien const int kElegantTop = 2500; 56853c0077256afebb0312f01ef4f60a7445da1f5d9Raph Levien const int kElegantBottom = -1000; 569817ef4ae79bd39b5e55fc6ca4e3b8e47e114579fRaph Levien const int kElegantAscent = 1900; 570817ef4ae79bd39b5e55fc6ca4e3b8e47e114579fRaph Levien const int kElegantDescent = -500; 57153c0077256afebb0312f01ef4f60a7445da1f5d9Raph Levien const int kElegantLeading = 0; 572dbffd250003e60c0f11ac3ad2b63f91f67962610John Reck Paint* paint = reinterpret_cast<Paint*>(paintHandle); 573318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka const Typeface* typeface = paint->getAndroidTypeface(); 574bad99183916ba2bac6659efc8a28273e344ba511sergeyv typeface = Typeface::resolveDefault(typeface); 575ae1aa85d0c7305bb621f1f8003bd674285aa3b63Seigo Nonaka minikin::FakedFont baseFont = typeface->fFontCollection->baseFontFaked(typeface->fStyle); 5760627ec08dcc2e87c17e9b85f045dfb27dc4884b3Raph Levien float saveSkewX = paint->getTextSkewX(); 5770627ec08dcc2e87c17e9b85f045dfb27dc4884b3Raph Levien bool savefakeBold = paint->isFakeBoldText(); 5780606a8874d9f50f13227497762ff0f0698415c50Seigo Nonaka MinikinFontSkia::populateSkPaint(paint, baseFont.font->typeface().get(), baseFont.fakery); 57953c0077256afebb0312f01ef4f60a7445da1f5d9Raph Levien SkScalar spacing = paint->getFontMetrics(metrics); 5800627ec08dcc2e87c17e9b85f045dfb27dc4884b3Raph Levien // The populateSkPaint call may have changed fake bold / text skew 5810627ec08dcc2e87c17e9b85f045dfb27dc4884b3Raph Levien // because we want to measure with those effects applied, so now 5820627ec08dcc2e87c17e9b85f045dfb27dc4884b3Raph Levien // restore the original settings. 5830627ec08dcc2e87c17e9b85f045dfb27dc4884b3Raph Levien paint->setTextSkewX(saveSkewX); 5840627ec08dcc2e87c17e9b85f045dfb27dc4884b3Raph Levien paint->setFakeBoldText(savefakeBold); 585c52075ee2bcfde4cf9b091e404517a74ff7cec60Seigo Nonaka if (paint->getFamilyVariant() == minikin::FontFamily::Variant::ELEGANT) { 58653c0077256afebb0312f01ef4f60a7445da1f5d9Raph Levien SkScalar size = paint->getTextSize(); 58753c0077256afebb0312f01ef4f60a7445da1f5d9Raph Levien metrics->fTop = -size * kElegantTop / 2048; 58853c0077256afebb0312f01ef4f60a7445da1f5d9Raph Levien metrics->fBottom = -size * kElegantBottom / 2048; 58953c0077256afebb0312f01ef4f60a7445da1f5d9Raph Levien metrics->fAscent = -size * kElegantAscent / 2048; 59053c0077256afebb0312f01ef4f60a7445da1f5d9Raph Levien metrics->fDescent = -size * kElegantDescent / 2048; 59153c0077256afebb0312f01ef4f60a7445da1f5d9Raph Levien metrics->fLeading = size * kElegantLeading / 2048; 59253c0077256afebb0312f01ef4f60a7445da1f5d9Raph Levien spacing = metrics->fDescent - metrics->fAscent + metrics->fLeading; 59353c0077256afebb0312f01ef4f60a7445da1f5d9Raph Levien } 59453c0077256afebb0312f01ef4f60a7445da1f5d9Raph Levien return spacing; 59553c0077256afebb0312f01ef4f60a7445da1f5d9Raph Levien } 59653c0077256afebb0312f01ef4f60a7445da1f5d9Raph Levien 597318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka static jfloat getFontMetrics(JNIEnv* env, jobject, jlong paintHandle, jobject metricsObj) { 5986ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod Paint::FontMetrics metrics; 599318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka SkScalar spacing = getMetricsInternal(paintHandle, &metrics); 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (metricsObj) { 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SkASSERT(env->IsInstanceOf(metricsObj, gFontMetrics_class)); 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->SetFloatField(metricsObj, gFontMetrics_fieldID.top, SkScalarToFloat(metrics.fTop)); 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->SetFloatField(metricsObj, gFontMetrics_fieldID.ascent, SkScalarToFloat(metrics.fAscent)); 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->SetFloatField(metricsObj, gFontMetrics_fieldID.descent, SkScalarToFloat(metrics.fDescent)); 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->SetFloatField(metricsObj, gFontMetrics_fieldID.bottom, SkScalarToFloat(metrics.fBottom)); 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->SetFloatField(metricsObj, gFontMetrics_fieldID.leading, SkScalarToFloat(metrics.fLeading)); 6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return SkScalarToFloat(spacing); 6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6118451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 612318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka static jint getFontMetricsInt(JNIEnv* env, jobject, jlong paintHandle, jobject metricsObj) { 6136ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod Paint::FontMetrics metrics; 6148451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 615318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka getMetricsInternal(paintHandle, &metrics); 61646cb9bdbf56b27cbf2ab878b41d21e30896a4feaLeon Scroggins int ascent = SkScalarRoundToInt(metrics.fAscent); 61746cb9bdbf56b27cbf2ab878b41d21e30896a4feaLeon Scroggins int descent = SkScalarRoundToInt(metrics.fDescent); 61846cb9bdbf56b27cbf2ab878b41d21e30896a4feaLeon Scroggins int leading = SkScalarRoundToInt(metrics.fLeading); 6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 620f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck if (metricsObj) { 621f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck SkASSERT(env->IsInstanceOf(metricsObj, gFontMetricsInt_class)); 622f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck env->SetIntField(metricsObj, gFontMetricsInt_fieldID.top, SkScalarFloorToInt(metrics.fTop)); 623f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck env->SetIntField(metricsObj, gFontMetricsInt_fieldID.ascent, ascent); 624f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck env->SetIntField(metricsObj, gFontMetricsInt_fieldID.descent, descent); 625f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck env->SetIntField(metricsObj, gFontMetricsInt_fieldID.bottom, SkScalarCeilToInt(metrics.fBottom)); 626f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck env->SetIntField(metricsObj, gFontMetricsInt_fieldID.leading, leading); 627f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 628f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return descent - ascent + leading; 629f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 630f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck 631f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck 632f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck // ------------------ @CriticalNative --------------------------- 633f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck 634f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static void reset(jlong objHandle) { 635f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck Paint* obj = reinterpret_cast<Paint*>(objHandle); 636f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck obj->reset(); 637f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck defaultSettingsForAndroid(obj); 638f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 639f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck 640f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static void assign(jlong dstPaintHandle, jlong srcPaintHandle) { 641f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck Paint* dst = reinterpret_cast<Paint*>(dstPaintHandle); 642f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck const Paint* src = reinterpret_cast<Paint*>(srcPaintHandle); 643f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck *dst = *src; 644f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 645f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck 646f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck // Equivalent to the Java Paint's FILTER_BITMAP_FLAG. 647f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static const uint32_t sFilterBitmapFlag = 0x02; 648f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck 649f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static jint getFlags(jlong paintHandle) { 650f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck Paint* nativePaint = reinterpret_cast<Paint*>(paintHandle); 651f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck uint32_t result = nativePaint->getFlags(); 652f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck result &= ~sFilterBitmapFlag; // Filtering no longer stored in this bit. Mask away. 653f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck if (nativePaint->getFilterQuality() != kNone_SkFilterQuality) { 654f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck result |= sFilterBitmapFlag; 655f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 656f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return static_cast<jint>(result); 657f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 658f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck 659f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static void setFlags(jlong paintHandle, jint flags) { 660f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck Paint* nativePaint = reinterpret_cast<Paint*>(paintHandle); 661f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck // Instead of modifying 0x02, change the filter level. 662f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck nativePaint->setFilterQuality(flags & sFilterBitmapFlag 663f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck ? kLow_SkFilterQuality 664f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck : kNone_SkFilterQuality); 665f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck // Don't pass through filter flag, which is no longer stored in paint's flags. 666f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck flags &= ~sFilterBitmapFlag; 667f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck // Use the existing value for 0x02. 668f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck const uint32_t existing0x02Flag = nativePaint->getFlags() & sFilterBitmapFlag; 669f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck flags |= existing0x02Flag; 670f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck nativePaint->setFlags(flags); 671f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 672f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck 673f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static jint getHinting(jlong paintHandle) { 674f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return reinterpret_cast<Paint*>(paintHandle)->getHinting() 675f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck == Paint::kNo_Hinting ? 0 : 1; 676f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 677f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck 678f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static void setHinting(jlong paintHandle, jint mode) { 679f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck reinterpret_cast<Paint*>(paintHandle)->setHinting( 680f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck mode == 0 ? Paint::kNo_Hinting : Paint::kNormal_Hinting); 681f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 682f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck 683f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static void setAntiAlias(jlong paintHandle, jboolean aa) { 684f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck reinterpret_cast<Paint*>(paintHandle)->setAntiAlias(aa); 685f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 686f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck 687f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static void setLinearText(jlong paintHandle, jboolean linearText) { 688f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck reinterpret_cast<Paint*>(paintHandle)->setLinearText(linearText); 689f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 690f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck 691f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static void setSubpixelText(jlong paintHandle, jboolean subpixelText) { 692f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck reinterpret_cast<Paint*>(paintHandle)->setSubpixelText(subpixelText); 693f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 694f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck 695f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static void setUnderlineText(jlong paintHandle, jboolean underlineText) { 696b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed Paint* paint = reinterpret_cast<Paint*>(paintHandle); 697b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed uint32_t flags = paint->getFlags(); 698b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed if (underlineText) { 699b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed flags |= Paint::kUnderlineText_ReserveFlag; 700b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed } else { 701b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed flags &= ~Paint::kUnderlineText_ReserveFlag; 702b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed } 703b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed paint->setFlags(flags); 704f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 705f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck 706f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static void setStrikeThruText(jlong paintHandle, jboolean strikeThruText) { 707b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed Paint* paint = reinterpret_cast<Paint*>(paintHandle); 708b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed uint32_t flags = paint->getFlags(); 709b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed if (strikeThruText) { 710b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed flags |= Paint::kStrikeThruText_ReserveFlag; 711b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed } else { 712b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed flags &= ~Paint::kStrikeThruText_ReserveFlag; 713b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed } 714b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed paint->setFlags(flags); 715f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 716f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck 717f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static void setFakeBoldText(jlong paintHandle, jboolean fakeBoldText) { 718f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck reinterpret_cast<Paint*>(paintHandle)->setFakeBoldText(fakeBoldText); 7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 721f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static void setFilterBitmap(jlong paintHandle, jboolean filterBitmap) { 722f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck reinterpret_cast<Paint*>(paintHandle)->setFilterQuality( 723f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck filterBitmap ? kLow_SkFilterQuality : kNone_SkFilterQuality); 724f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 7256ab90ed017fb52aac4493a2fac897299d345874fFabrice Di Meglio 726f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static void setDither(jlong paintHandle, jboolean dither) { 727f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck reinterpret_cast<Paint*>(paintHandle)->setDither(dither); 7280c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt } 7290c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt 730f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static jint getStyle(jlong objHandle) { 731f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck Paint* obj = reinterpret_cast<Paint*>(objHandle); 732f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return static_cast<jint>(obj->getStyle()); 7330c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt } 7340c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt 735f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static void setStyle(jlong objHandle, jint styleHandle) { 736f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck Paint* obj = reinterpret_cast<Paint*>(objHandle); 737f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck Paint::Style style = static_cast<Paint::Style>(styleHandle); 738f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck obj->setStyle(style); 739eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio } 740eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio 741f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static jint getColor(jlong paintHandle) { 742f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck int color; 743f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck color = reinterpret_cast<Paint*>(paintHandle)->getColor(); 744f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return static_cast<jint>(color); 7450c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt } 7460c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt 747f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static jint getAlpha(jlong paintHandle) { 748f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck int alpha; 749f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck alpha = reinterpret_cast<Paint*>(paintHandle)->getAlpha(); 750f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return static_cast<jint>(alpha); 7510c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt } 7520c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt 753f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static void setColor(jlong paintHandle, jint color) { 754f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck reinterpret_cast<Paint*>(paintHandle)->setColor(color); 7550c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt } 7560c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt 757f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static void setAlpha(jlong paintHandle, jint a) { 758f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck reinterpret_cast<Paint*>(paintHandle)->setAlpha(a); 759f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 760f2114d5646194100242206b267ddd6e7194b7da9Raph Levien 761f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static jfloat getStrokeWidth(jlong paintHandle) { 762f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return SkScalarToFloat(reinterpret_cast<Paint*>(paintHandle)->getStrokeWidth()); 763f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 764f2114d5646194100242206b267ddd6e7194b7da9Raph Levien 765f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static void setStrokeWidth(jlong paintHandle, jfloat width) { 766f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck reinterpret_cast<Paint*>(paintHandle)->setStrokeWidth(width); 767f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 768f2114d5646194100242206b267ddd6e7194b7da9Raph Levien 769f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static jfloat getStrokeMiter(jlong paintHandle) { 770f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return SkScalarToFloat(reinterpret_cast<Paint*>(paintHandle)->getStrokeMiter()); 771f7cb1f75fdaedf996cab7c4690b080adc7bc5b97Doug Felt } 772f7cb1f75fdaedf996cab7c4690b080adc7bc5b97Doug Felt 773f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static void setStrokeMiter(jlong paintHandle, jfloat miter) { 774f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck reinterpret_cast<Paint*>(paintHandle)->setStrokeMiter(miter); 7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 776f7cb1f75fdaedf996cab7c4690b080adc7bc5b97Doug Felt 777f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static jint getStrokeCap(jlong objHandle) { 778f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck Paint* obj = reinterpret_cast<Paint*>(objHandle); 779f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return static_cast<jint>(obj->getStrokeCap()); 7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 781f7cb1f75fdaedf996cab7c4690b080adc7bc5b97Doug Felt 782f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static void setStrokeCap(jlong objHandle, jint capHandle) { 783f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck Paint* obj = reinterpret_cast<Paint*>(objHandle); 784f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck Paint::Cap cap = static_cast<Paint::Cap>(capHandle); 785f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck obj->setStrokeCap(cap); 7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 788f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static jint getStrokeJoin(jlong objHandle) { 789f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck Paint* obj = reinterpret_cast<Paint*>(objHandle); 790f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return static_cast<jint>(obj->getStrokeJoin()); 791c29a0a4664a4b9871fadd668b632469a0db240b9Derek Sollenberger } 792c29a0a4664a4b9871fadd668b632469a0db240b9Derek Sollenberger 793f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static void setStrokeJoin(jlong objHandle, jint joinHandle) { 794f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck Paint* obj = reinterpret_cast<Paint*>(objHandle); 795f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck Paint::Join join = (Paint::Join) joinHandle; 796f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck obj->setStrokeJoin(join); 797f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 798a7aa1b0aa566b2ff310cb89fbc9437de4819f583Anish Athalye 799f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static jboolean getFillPath(jlong objHandle, jlong srcHandle, jlong dstHandle) { 800f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck Paint* obj = reinterpret_cast<Paint*>(objHandle); 801f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck SkPath* src = reinterpret_cast<SkPath*>(srcHandle); 802f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck SkPath* dst = reinterpret_cast<SkPath*>(dstHandle); 803f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return obj->getFillPath(*src, dst) ? JNI_TRUE : JNI_FALSE; 804f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 80557c4fed236cbec0944824b534fb9c828ac0d1f81Derek Sollenberger 806f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static jlong setShader(jlong objHandle, jlong shaderHandle) { 807f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck Paint* obj = reinterpret_cast<Paint*>(objHandle); 808f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle); 809260ab726486317496bc12a57d599ea96dcde3284Mike Reed obj->setShader(sk_ref_sp(shader)); 810260ab726486317496bc12a57d599ea96dcde3284Mike Reed return reinterpret_cast<jlong>(obj->getShader()); 811f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 813f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static jlong setColorFilter(jlong objHandle, jlong filterHandle) { 814f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck Paint* obj = reinterpret_cast<Paint *>(objHandle); 815f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck SkColorFilter* filter = reinterpret_cast<SkColorFilter *>(filterHandle); 816260ab726486317496bc12a57d599ea96dcde3284Mike Reed obj->setColorFilter(sk_ref_sp(filter)); 817260ab726486317496bc12a57d599ea96dcde3284Mike Reed return reinterpret_cast<jlong>(obj->getColorFilter()); 8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 820f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static void setXfermode(jlong paintHandle, jint xfermodeHandle) { 821f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck // validate that the Java enum values match our expectations 822260ab726486317496bc12a57d599ea96dcde3284Mike Reed static_assert(0 == static_cast<int>(SkBlendMode::kClear), "xfermode_mismatch"); 823260ab726486317496bc12a57d599ea96dcde3284Mike Reed static_assert(1 == static_cast<int>(SkBlendMode::kSrc), "xfermode_mismatch"); 824260ab726486317496bc12a57d599ea96dcde3284Mike Reed static_assert(2 == static_cast<int>(SkBlendMode::kDst), "xfermode_mismatch"); 825260ab726486317496bc12a57d599ea96dcde3284Mike Reed static_assert(3 == static_cast<int>(SkBlendMode::kSrcOver), "xfermode_mismatch"); 826260ab726486317496bc12a57d599ea96dcde3284Mike Reed static_assert(4 == static_cast<int>(SkBlendMode::kDstOver), "xfermode_mismatch"); 827260ab726486317496bc12a57d599ea96dcde3284Mike Reed static_assert(5 == static_cast<int>(SkBlendMode::kSrcIn), "xfermode_mismatch"); 828260ab726486317496bc12a57d599ea96dcde3284Mike Reed static_assert(6 == static_cast<int>(SkBlendMode::kDstIn), "xfermode_mismatch"); 829260ab726486317496bc12a57d599ea96dcde3284Mike Reed static_assert(7 == static_cast<int>(SkBlendMode::kSrcOut), "xfermode_mismatch"); 830260ab726486317496bc12a57d599ea96dcde3284Mike Reed static_assert(8 == static_cast<int>(SkBlendMode::kDstOut), "xfermode_mismatch"); 831260ab726486317496bc12a57d599ea96dcde3284Mike Reed static_assert(9 == static_cast<int>(SkBlendMode::kSrcATop), "xfermode_mismatch"); 832260ab726486317496bc12a57d599ea96dcde3284Mike Reed static_assert(10 == static_cast<int>(SkBlendMode::kDstATop), "xfermode_mismatch"); 833260ab726486317496bc12a57d599ea96dcde3284Mike Reed static_assert(11 == static_cast<int>(SkBlendMode::kXor), "xfermode_mismatch"); 834260ab726486317496bc12a57d599ea96dcde3284Mike Reed static_assert(16 == static_cast<int>(SkBlendMode::kDarken), "xfermode_mismatch"); 835260ab726486317496bc12a57d599ea96dcde3284Mike Reed static_assert(17 == static_cast<int>(SkBlendMode::kLighten), "xfermode_mismatch"); 836260ab726486317496bc12a57d599ea96dcde3284Mike Reed static_assert(13 == static_cast<int>(SkBlendMode::kModulate), "xfermode_mismatch"); 837260ab726486317496bc12a57d599ea96dcde3284Mike Reed static_assert(14 == static_cast<int>(SkBlendMode::kScreen), "xfermode_mismatch"); 838260ab726486317496bc12a57d599ea96dcde3284Mike Reed static_assert(12 == static_cast<int>(SkBlendMode::kPlus), "xfermode_mismatch"); 839260ab726486317496bc12a57d599ea96dcde3284Mike Reed static_assert(15 == static_cast<int>(SkBlendMode::kOverlay), "xfermode_mismatch"); 840260ab726486317496bc12a57d599ea96dcde3284Mike Reed 841260ab726486317496bc12a57d599ea96dcde3284Mike Reed SkBlendMode mode = static_cast<SkBlendMode>(xfermodeHandle); 8426ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod Paint* paint = reinterpret_cast<Paint*>(paintHandle); 843260ab726486317496bc12a57d599ea96dcde3284Mike Reed paint->setBlendMode(mode); 844f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 845a7aa1b0aa566b2ff310cb89fbc9437de4819f583Anish Athalye 846f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static jlong setPathEffect(jlong objHandle, jlong effectHandle) { 847f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck Paint* obj = reinterpret_cast<Paint*>(objHandle); 848f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck SkPathEffect* effect = reinterpret_cast<SkPathEffect*>(effectHandle); 849260ab726486317496bc12a57d599ea96dcde3284Mike Reed obj->setPathEffect(sk_ref_sp(effect)); 850260ab726486317496bc12a57d599ea96dcde3284Mike Reed return reinterpret_cast<jlong>(obj->getPathEffect()); 851f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 853f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static jlong setMaskFilter(jlong objHandle, jlong maskfilterHandle) { 854f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck Paint* obj = reinterpret_cast<Paint*>(objHandle); 855f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck SkMaskFilter* maskfilter = reinterpret_cast<SkMaskFilter*>(maskfilterHandle); 856260ab726486317496bc12a57d599ea96dcde3284Mike Reed obj->setMaskFilter(sk_ref_sp(maskfilter)); 857260ab726486317496bc12a57d599ea96dcde3284Mike Reed return reinterpret_cast<jlong>(obj->getMaskFilter()); 858f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 860318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka static void setTypeface(jlong objHandle, jlong typefaceHandle) { 861318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka Paint* paint = reinterpret_cast<Paint*>(objHandle); 862318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka paint->setAndroidTypeface(reinterpret_cast<Typeface*>(typefaceHandle)); 8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 865f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static jint getTextAlign(jlong objHandle) { 866f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck Paint* obj = reinterpret_cast<Paint*>(objHandle); 867f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return static_cast<jint>(obj->getTextAlign()); 868f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 869a7aa1b0aa566b2ff310cb89fbc9437de4819f583Anish Athalye 870f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static void setTextAlign(jlong objHandle, jint alignHandle) { 871f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck Paint* obj = reinterpret_cast<Paint*>(objHandle); 872f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck Paint::Align align = static_cast<Paint::Align>(alignHandle); 873f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck obj->setTextAlign(align); 8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 87620866c140438a9aca3e1ad09fe646308678e9383Seigo Nonaka static void setTextLocalesByMinikinLocaleListId(jlong objHandle, 87720866c140438a9aca3e1ad09fe646308678e9383Seigo Nonaka jint minikinLocaleListId) { 878f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck Paint* obj = reinterpret_cast<Paint*>(objHandle); 87920866c140438a9aca3e1ad09fe646308678e9383Seigo Nonaka obj->setMinikinLocaleListId(minikinLocaleListId); 880f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 8818451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 882f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static jboolean isElegantTextHeight(jlong paintHandle) { 883f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck Paint* obj = reinterpret_cast<Paint*>(paintHandle); 884c52075ee2bcfde4cf9b091e404517a74ff7cec60Seigo Nonaka return obj->getFamilyVariant() == minikin::FontFamily::Variant::ELEGANT; 8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 887f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static void setElegantTextHeight(jlong paintHandle, jboolean aa) { 888f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck Paint* obj = reinterpret_cast<Paint*>(paintHandle); 889c52075ee2bcfde4cf9b091e404517a74ff7cec60Seigo Nonaka obj->setFamilyVariant( 890c52075ee2bcfde4cf9b091e404517a74ff7cec60Seigo Nonaka aa ? minikin::FontFamily::Variant::ELEGANT : minikin::FontFamily::Variant::DEFAULT); 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8928451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 893f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static jfloat getTextSize(jlong paintHandle) { 894f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return SkScalarToFloat(reinterpret_cast<Paint*>(paintHandle)->getTextSize()); 8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8968451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 897f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static void setTextSize(jlong paintHandle, jfloat textSize) { 898f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck reinterpret_cast<Paint*>(paintHandle)->setTextSize(textSize); 899f7f969e67e9ab420404807b1b103dcd18d7aa7b7Raph Levien } 900f7f969e67e9ab420404807b1b103dcd18d7aa7b7Raph Levien 901f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static jfloat getTextScaleX(jlong paintHandle) { 902f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return SkScalarToFloat(reinterpret_cast<Paint*>(paintHandle)->getTextScaleX()); 9036141db3846356efbdea093756701c89bd5155421Raph Levien } 9046141db3846356efbdea093756701c89bd5155421Raph Levien 905f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static void setTextScaleX(jlong paintHandle, jfloat scaleX) { 906f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck reinterpret_cast<Paint*>(paintHandle)->setTextScaleX(scaleX); 907f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 908589cddc034f87fcd02adb24e168ef6b2ed851b82Seigo Nonaka 909f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static jfloat getTextSkewX(jlong paintHandle) { 910f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return SkScalarToFloat(reinterpret_cast<Paint*>(paintHandle)->getTextSkewX()); 911589cddc034f87fcd02adb24e168ef6b2ed851b82Seigo Nonaka } 912589cddc034f87fcd02adb24e168ef6b2ed851b82Seigo Nonaka 913f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static void setTextSkewX(jlong paintHandle, jfloat skewX) { 914f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck reinterpret_cast<Paint*>(paintHandle)->setTextSkewX(skewX); 915f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 916f7f969e67e9ab420404807b1b103dcd18d7aa7b7Raph Levien 917f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static jfloat getLetterSpacing(jlong paintHandle) { 918f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck Paint* paint = reinterpret_cast<Paint*>(paintHandle); 919f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return paint->getLetterSpacing(); 920f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 921bb1a96647a82df5a134bf631fc9db342e7ef61deSeigo Nonaka 922f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static void setLetterSpacing(jlong paintHandle, jfloat letterSpacing) { 923f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck Paint* paint = reinterpret_cast<Paint*>(paintHandle); 924f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck paint->setLetterSpacing(letterSpacing); 925f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 926589cddc034f87fcd02adb24e168ef6b2ed851b82Seigo Nonaka 927219e2c79490296b03e58ec36a3a4ff4a2ebf52e3Seigo Nonaka static jfloat getWordSpacing(jlong paintHandle) { 928219e2c79490296b03e58ec36a3a4ff4a2ebf52e3Seigo Nonaka Paint* paint = reinterpret_cast<Paint*>(paintHandle); 929219e2c79490296b03e58ec36a3a4ff4a2ebf52e3Seigo Nonaka return paint->getWordSpacing(); 930219e2c79490296b03e58ec36a3a4ff4a2ebf52e3Seigo Nonaka } 931219e2c79490296b03e58ec36a3a4ff4a2ebf52e3Seigo Nonaka 932219e2c79490296b03e58ec36a3a4ff4a2ebf52e3Seigo Nonaka static void setWordSpacing(jlong paintHandle, jfloat wordSpacing) { 933219e2c79490296b03e58ec36a3a4ff4a2ebf52e3Seigo Nonaka Paint* paint = reinterpret_cast<Paint*>(paintHandle); 934219e2c79490296b03e58ec36a3a4ff4a2ebf52e3Seigo Nonaka paint->setWordSpacing(wordSpacing); 935219e2c79490296b03e58ec36a3a4ff4a2ebf52e3Seigo Nonaka } 936219e2c79490296b03e58ec36a3a4ff4a2ebf52e3Seigo Nonaka 937f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static jint getHyphenEdit(jlong paintHandle, jint hyphen) { 938f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck Paint* paint = reinterpret_cast<Paint*>(paintHandle); 939f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return paint->getHyphenEdit(); 940f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 941589cddc034f87fcd02adb24e168ef6b2ed851b82Seigo Nonaka 942f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static void setHyphenEdit(jlong paintHandle, jint hyphen) { 943f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck Paint* paint = reinterpret_cast<Paint*>(paintHandle); 944f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck paint->setHyphenEdit((uint32_t)hyphen); 945f7f969e67e9ab420404807b1b103dcd18d7aa7b7Raph Levien } 946f7f969e67e9ab420404807b1b103dcd18d7aa7b7Raph Levien 947318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka static jfloat ascent(jlong paintHandle) { 948f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck Paint::FontMetrics metrics; 949318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka getMetricsInternal(paintHandle, &metrics); 950f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return SkScalarToFloat(metrics.fAscent); 951a027ec5c2dbfbbf10cac9ea538f5e230b093be2fRaph Levien } 952a027ec5c2dbfbbf10cac9ea538f5e230b093be2fRaph Levien 953318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka static jfloat descent(jlong paintHandle) { 954f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck Paint::FontMetrics metrics; 955318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka getMetricsInternal(paintHandle, &metrics); 956f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return SkScalarToFloat(metrics.fDescent); 957a027ec5c2dbfbbf10cac9ea538f5e230b093be2fRaph Levien } 958a027ec5c2dbfbbf10cac9ea538f5e230b093be2fRaph Levien 959318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka static jfloat getUnderlinePosition(jlong paintHandle) { 960ca8a04a36640eb227a556ad9ced925c48ced2495Roozbeh Pournader Paint::FontMetrics metrics; 961318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka getMetricsInternal(paintHandle, &metrics); 962ca8a04a36640eb227a556ad9ced925c48ced2495Roozbeh Pournader SkScalar position; 963ca8a04a36640eb227a556ad9ced925c48ced2495Roozbeh Pournader if (metrics.hasUnderlinePosition(&position)) { 964ca8a04a36640eb227a556ad9ced925c48ced2495Roozbeh Pournader return SkScalarToFloat(position); 965ca8a04a36640eb227a556ad9ced925c48ced2495Roozbeh Pournader } else { 966ca8a04a36640eb227a556ad9ced925c48ced2495Roozbeh Pournader const SkScalar textSize = reinterpret_cast<Paint*>(paintHandle)->getTextSize(); 967ca8a04a36640eb227a556ad9ced925c48ced2495Roozbeh Pournader return SkScalarToFloat(Paint::kStdUnderline_Top * textSize); 968ca8a04a36640eb227a556ad9ced925c48ced2495Roozbeh Pournader } 969ca8a04a36640eb227a556ad9ced925c48ced2495Roozbeh Pournader } 970ca8a04a36640eb227a556ad9ced925c48ced2495Roozbeh Pournader 971318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka static jfloat getUnderlineThickness(jlong paintHandle) { 972ca8a04a36640eb227a556ad9ced925c48ced2495Roozbeh Pournader Paint::FontMetrics metrics; 973318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka getMetricsInternal(paintHandle, &metrics); 974ca8a04a36640eb227a556ad9ced925c48ced2495Roozbeh Pournader SkScalar thickness; 975ca8a04a36640eb227a556ad9ced925c48ced2495Roozbeh Pournader if (metrics.hasUnderlineThickness(&thickness)) { 976ca8a04a36640eb227a556ad9ced925c48ced2495Roozbeh Pournader return SkScalarToFloat(thickness); 977ca8a04a36640eb227a556ad9ced925c48ced2495Roozbeh Pournader } else { 978ca8a04a36640eb227a556ad9ced925c48ced2495Roozbeh Pournader const SkScalar textSize = reinterpret_cast<Paint*>(paintHandle)->getTextSize(); 979ca8a04a36640eb227a556ad9ced925c48ced2495Roozbeh Pournader return SkScalarToFloat(Paint::kStdUnderline_Thickness * textSize); 980ca8a04a36640eb227a556ad9ced925c48ced2495Roozbeh Pournader } 981ca8a04a36640eb227a556ad9ced925c48ced2495Roozbeh Pournader } 982ca8a04a36640eb227a556ad9ced925c48ced2495Roozbeh Pournader 983318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka static jfloat getStrikeThruPosition(jlong paintHandle) { 9841378a9d72cb4a9f7a939f0a28a78fcfb87fb7879Roozbeh Pournader const SkScalar textSize = reinterpret_cast<Paint*>(paintHandle)->getTextSize(); 9851378a9d72cb4a9f7a939f0a28a78fcfb87fb7879Roozbeh Pournader return SkScalarToFloat(Paint::kStdStrikeThru_Top * textSize); 9861378a9d72cb4a9f7a939f0a28a78fcfb87fb7879Roozbeh Pournader } 9871378a9d72cb4a9f7a939f0a28a78fcfb87fb7879Roozbeh Pournader 988318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka static jfloat getStrikeThruThickness(jlong paintHandle) { 9891378a9d72cb4a9f7a939f0a28a78fcfb87fb7879Roozbeh Pournader const SkScalar textSize = reinterpret_cast<Paint*>(paintHandle)->getTextSize(); 9901378a9d72cb4a9f7a939f0a28a78fcfb87fb7879Roozbeh Pournader return SkScalarToFloat(Paint::kStdStrikeThru_Thickness * textSize); 9911378a9d72cb4a9f7a939f0a28a78fcfb87fb7879Roozbeh Pournader } 9921378a9d72cb4a9f7a939f0a28a78fcfb87fb7879Roozbeh Pournader 993f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static void setShadowLayer(jlong paintHandle, jfloat radius, 994f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck jfloat dx, jfloat dy, jint color) { 995f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck Paint* paint = reinterpret_cast<Paint*>(paintHandle); 996f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck if (radius <= 0) { 997f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck paint->setLooper(nullptr); 998f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 999f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck else { 1000f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck SkScalar sigma = android::uirenderer::Blur::convertRadiusToSigma(radius); 1001260ab726486317496bc12a57d599ea96dcde3284Mike Reed paint->setLooper(SkBlurDrawLooper::Make((SkColor)color, sigma, dx, dy)); 1002f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck } 1003a027ec5c2dbfbbf10cac9ea538f5e230b093be2fRaph Levien } 10044c8a52647814badd361ebd13813180b8db9b923eKeisuke Kuroyanagi 1005f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck static jboolean hasShadowLayer(jlong paintHandle) { 1006f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck Paint* paint = reinterpret_cast<Paint*>(paintHandle); 1007f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck return paint->getLooper() && paint->getLooper()->asABlurShadow(nullptr); 1008a027ec5c2dbfbbf10cac9ea538f5e230b093be2fRaph Levien } 1009a027ec5c2dbfbbf10cac9ea538f5e230b093be2fRaph Levien 1010beafa1f9d2845ee9b5ca352087de03ed0afe7db7Seigo Nonaka static jboolean equalsForTextMeasurement(jlong lPaint, jlong rPaint) { 1011beafa1f9d2845ee9b5ca352087de03ed0afe7db7Seigo Nonaka if (lPaint == rPaint) { 1012beafa1f9d2845ee9b5ca352087de03ed0afe7db7Seigo Nonaka return true; 1013beafa1f9d2845ee9b5ca352087de03ed0afe7db7Seigo Nonaka } 1014beafa1f9d2845ee9b5ca352087de03ed0afe7db7Seigo Nonaka Paint* leftPaint = reinterpret_cast<Paint*>(lPaint); 1015beafa1f9d2845ee9b5ca352087de03ed0afe7db7Seigo Nonaka Paint* rightPaint = reinterpret_cast<Paint*>(rPaint); 1016beafa1f9d2845ee9b5ca352087de03ed0afe7db7Seigo Nonaka 1017beafa1f9d2845ee9b5ca352087de03ed0afe7db7Seigo Nonaka const Typeface* leftTypeface = Typeface::resolveDefault(leftPaint->getAndroidTypeface()); 1018beafa1f9d2845ee9b5ca352087de03ed0afe7db7Seigo Nonaka const Typeface* rightTypeface = Typeface::resolveDefault(rightPaint->getAndroidTypeface()); 1019beafa1f9d2845ee9b5ca352087de03ed0afe7db7Seigo Nonaka minikin::MinikinPaint leftMinikinPaint 1020beafa1f9d2845ee9b5ca352087de03ed0afe7db7Seigo Nonaka = MinikinUtils::prepareMinikinPaint(leftPaint, leftTypeface); 1021beafa1f9d2845ee9b5ca352087de03ed0afe7db7Seigo Nonaka minikin::MinikinPaint rightMinikinPaint 1022beafa1f9d2845ee9b5ca352087de03ed0afe7db7Seigo Nonaka = MinikinUtils::prepareMinikinPaint(rightPaint, rightTypeface); 1023beafa1f9d2845ee9b5ca352087de03ed0afe7db7Seigo Nonaka 1024beafa1f9d2845ee9b5ca352087de03ed0afe7db7Seigo Nonaka return leftMinikinPaint == rightMinikinPaint; 1025beafa1f9d2845ee9b5ca352087de03ed0afe7db7Seigo Nonaka } 1026beafa1f9d2845ee9b5ca352087de03ed0afe7db7Seigo Nonaka 1027dbffd250003e60c0f11ac3ad2b63f91f67962610John Reck}; // namespace PaintGlue 10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 102976f6a86de25e1bf74717e047e55fd44b089673f3Daniel Micaystatic const JNINativeMethod methods[] = { 1030775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhler {"nGetNativeFinalizer", "()J", (void*) PaintGlue::getNativeFinalizer}, 1031dbffd250003e60c0f11ac3ad2b63f91f67962610John Reck {"nInit","()J", (void*) PaintGlue::init}, 1032dbffd250003e60c0f11ac3ad2b63f91f67962610John Reck {"nInitWithPaint","(J)J", (void*) PaintGlue::initWithPaint}, 1033318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka {"nBreakText","(J[CIIFI[F)I", (void*) PaintGlue::breakTextC}, 1034318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka {"nBreakText","(JLjava/lang/String;ZFI[F)I", (void*) PaintGlue::breakTextS}, 1035318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka {"nGetTextAdvances","(J[CIIIII[FI)F", 1036536afe6ef79a663e59c3b9781c561f7029ee9319Keisuke Kuroyanagi (void*) PaintGlue::getTextAdvances___CIIIII_FI}, 1037318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka {"nGetTextAdvances","(JLjava/lang/String;IIIII[FI)F", 1038536afe6ef79a663e59c3b9781c561f7029ee9319Keisuke Kuroyanagi (void*) PaintGlue::getTextAdvances__StringIIIII_FI}, 1039da12f389eb4be0c08ca3fa9ca7663f4977858df5Fabrice Di Meglio 1040318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka {"nGetTextRunCursor", "(J[CIIIII)I", (void*) PaintGlue::getTextRunCursor___C}, 1041318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka {"nGetTextRunCursor", "(JLjava/lang/String;IIIII)I", 1042a027ec5c2dbfbbf10cac9ea538f5e230b093be2fRaph Levien (void*) PaintGlue::getTextRunCursor__String}, 1043318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka {"nGetTextPath", "(JI[CIIFFJ)V", (void*) PaintGlue::getTextPath___C}, 1044318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka {"nGetTextPath", "(JILjava/lang/String;IIFFJ)V", (void*) PaintGlue::getTextPath__String}, 1045318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka {"nGetStringBounds", "(JLjava/lang/String;IIILandroid/graphics/Rect;)V", 1046a027ec5c2dbfbbf10cac9ea538f5e230b093be2fRaph Levien (void*) PaintGlue::getStringBounds }, 1047318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka {"nGetCharArrayBounds", "(J[CIIILandroid/graphics/Rect;)V", 1048a027ec5c2dbfbbf10cac9ea538f5e230b093be2fRaph Levien (void*) PaintGlue::getCharArrayBounds }, 1049318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka {"nHasGlyph", "(JILjava/lang/String;)Z", (void*) PaintGlue::hasGlyph }, 1050318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka {"nGetRunAdvance", "(J[CIIIIZI)F", (void*) PaintGlue::getRunAdvance___CIIIIZI_F}, 1051318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka {"nGetOffsetForAdvance", "(J[CIIIIZF)I", 1052a027ec5c2dbfbbf10cac9ea538f5e230b093be2fRaph Levien (void*) PaintGlue::getOffsetForAdvance___CIIIIZF_I}, 10534136a0aeac9bb95aa615d4fc1f12378829d26c80Chris Craik 1054f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck // --------------- @FastNative ---------------------- 1055f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck 1056f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nSetTextLocales","(JLjava/lang/String;)I", (void*) PaintGlue::setTextLocales}, 1057f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nSetFontFeatureSettings","(JLjava/lang/String;)V", 1058f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck (void*) PaintGlue::setFontFeatureSettings}, 1059318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka {"nGetFontMetrics", "(JLandroid/graphics/Paint$FontMetrics;)F", 1060f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck (void*)PaintGlue::getFontMetrics}, 1061318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka {"nGetFontMetricsInt", "(JLandroid/graphics/Paint$FontMetricsInt;)I", 1062f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck (void*)PaintGlue::getFontMetricsInt}, 1063f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck 1064f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck // --------------- @CriticalNative ------------------ 1065f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck 1066f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nReset","(J)V", (void*) PaintGlue::reset}, 1067f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nSet","(JJ)V", (void*) PaintGlue::assign}, 1068f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nGetFlags","(J)I", (void*) PaintGlue::getFlags}, 1069f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nSetFlags","(JI)V", (void*) PaintGlue::setFlags}, 1070f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nGetHinting","(J)I", (void*) PaintGlue::getHinting}, 1071f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nSetHinting","(JI)V", (void*) PaintGlue::setHinting}, 1072f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nSetAntiAlias","(JZ)V", (void*) PaintGlue::setAntiAlias}, 1073f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nSetSubpixelText","(JZ)V", (void*) PaintGlue::setSubpixelText}, 1074f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nSetLinearText","(JZ)V", (void*) PaintGlue::setLinearText}, 1075f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nSetUnderlineText","(JZ)V", (void*) PaintGlue::setUnderlineText}, 1076f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nSetStrikeThruText","(JZ)V", (void*) PaintGlue::setStrikeThruText}, 1077f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nSetFakeBoldText","(JZ)V", (void*) PaintGlue::setFakeBoldText}, 1078f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nSetFilterBitmap","(JZ)V", (void*) PaintGlue::setFilterBitmap}, 1079f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nSetDither","(JZ)V", (void*) PaintGlue::setDither}, 1080f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nGetStyle","(J)I", (void*) PaintGlue::getStyle}, 1081f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nSetStyle","(JI)V", (void*) PaintGlue::setStyle}, 1082f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nGetColor","(J)I", (void*) PaintGlue::getColor}, 1083f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nSetColor","(JI)V", (void*) PaintGlue::setColor}, 1084f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nGetAlpha","(J)I", (void*) PaintGlue::getAlpha}, 1085f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nSetAlpha","(JI)V", (void*) PaintGlue::setAlpha}, 1086f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nGetStrokeWidth","(J)F", (void*) PaintGlue::getStrokeWidth}, 1087f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nSetStrokeWidth","(JF)V", (void*) PaintGlue::setStrokeWidth}, 1088f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nGetStrokeMiter","(J)F", (void*) PaintGlue::getStrokeMiter}, 1089f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nSetStrokeMiter","(JF)V", (void*) PaintGlue::setStrokeMiter}, 1090f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nGetStrokeCap","(J)I", (void*) PaintGlue::getStrokeCap}, 1091f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nSetStrokeCap","(JI)V", (void*) PaintGlue::setStrokeCap}, 1092f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nGetStrokeJoin","(J)I", (void*) PaintGlue::getStrokeJoin}, 1093f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nSetStrokeJoin","(JI)V", (void*) PaintGlue::setStrokeJoin}, 1094f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nGetFillPath","(JJJ)Z", (void*) PaintGlue::getFillPath}, 1095f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nSetShader","(JJ)J", (void*) PaintGlue::setShader}, 1096f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nSetColorFilter","(JJ)J", (void*) PaintGlue::setColorFilter}, 1097f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nSetXfermode","(JI)V", (void*) PaintGlue::setXfermode}, 1098f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nSetPathEffect","(JJ)J", (void*) PaintGlue::setPathEffect}, 1099f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nSetMaskFilter","(JJ)J", (void*) PaintGlue::setMaskFilter}, 1100318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka {"nSetTypeface","(JJ)V", (void*) PaintGlue::setTypeface}, 1101f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nGetTextAlign","(J)I", (void*) PaintGlue::getTextAlign}, 1102f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nSetTextAlign","(JI)V", (void*) PaintGlue::setTextAlign}, 110320866c140438a9aca3e1ad09fe646308678e9383Seigo Nonaka {"nSetTextLocalesByMinikinLocaleListId","(JI)V", 110420866c140438a9aca3e1ad09fe646308678e9383Seigo Nonaka (void*) PaintGlue::setTextLocalesByMinikinLocaleListId}, 1105f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nIsElegantTextHeight","(J)Z", (void*) PaintGlue::isElegantTextHeight}, 1106f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nSetElegantTextHeight","(JZ)V", (void*) PaintGlue::setElegantTextHeight}, 1107f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nGetTextSize","(J)F", (void*) PaintGlue::getTextSize}, 1108f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nSetTextSize","(JF)V", (void*) PaintGlue::setTextSize}, 1109f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nGetTextScaleX","(J)F", (void*) PaintGlue::getTextScaleX}, 1110f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nSetTextScaleX","(JF)V", (void*) PaintGlue::setTextScaleX}, 1111f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nGetTextSkewX","(J)F", (void*) PaintGlue::getTextSkewX}, 1112f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nSetTextSkewX","(JF)V", (void*) PaintGlue::setTextSkewX}, 1113f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nGetLetterSpacing","(J)F", (void*) PaintGlue::getLetterSpacing}, 1114f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nSetLetterSpacing","(JF)V", (void*) PaintGlue::setLetterSpacing}, 1115219e2c79490296b03e58ec36a3a4ff4a2ebf52e3Seigo Nonaka {"nGetWordSpacing","(J)F", (void*) PaintGlue::getWordSpacing}, 1116219e2c79490296b03e58ec36a3a4ff4a2ebf52e3Seigo Nonaka {"nSetWordSpacing","(JF)V", (void*) PaintGlue::setWordSpacing}, 1117f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nGetHyphenEdit", "(J)I", (void*) PaintGlue::getHyphenEdit}, 1118f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nSetHyphenEdit", "(JI)V", (void*) PaintGlue::setHyphenEdit}, 1119318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka {"nAscent","(J)F", (void*) PaintGlue::ascent}, 1120318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka {"nDescent","(J)F", (void*) PaintGlue::descent}, 1121318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka {"nGetUnderlinePosition","(J)F", (void*) PaintGlue::getUnderlinePosition}, 1122318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka {"nGetUnderlineThickness","(J)F", (void*) PaintGlue::getUnderlineThickness}, 1123318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka {"nGetStrikeThruPosition","(J)F", (void*) PaintGlue::getStrikeThruPosition}, 1124318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonaka {"nGetStrikeThruThickness","(J)F", (void*) PaintGlue::getStrikeThruThickness}, 1125f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck {"nSetShadowLayer", "(JFFFI)V", (void*)PaintGlue::setShadowLayer}, 1126beafa1f9d2845ee9b5ca352087de03ed0afe7db7Seigo Nonaka {"nHasShadowLayer", "(J)Z", (void*)PaintGlue::hasShadowLayer}, 1127beafa1f9d2845ee9b5ca352087de03ed0afe7db7Seigo Nonaka {"nEqualsForTextMeasurement", "(JJ)Z", (void*)PaintGlue::equalsForTextMeasurement}, 11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint register_android_graphics_Paint(JNIEnv* env) { 1131ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe gFontMetrics_class = FindClassOrDie(env, "android/graphics/Paint$FontMetrics"); 1132ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe gFontMetrics_class = MakeGlobalRefOrDie(env, gFontMetrics_class); 1133ab22c1c792bc5f422a029a4ab6a23861e44136d8Derek Sollenberger 1134ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe gFontMetrics_fieldID.top = GetFieldIDOrDie(env, gFontMetrics_class, "top", "F"); 1135ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe gFontMetrics_fieldID.ascent = GetFieldIDOrDie(env, gFontMetrics_class, "ascent", "F"); 1136ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe gFontMetrics_fieldID.descent = GetFieldIDOrDie(env, gFontMetrics_class, "descent", "F"); 1137ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe gFontMetrics_fieldID.bottom = GetFieldIDOrDie(env, gFontMetrics_class, "bottom", "F"); 1138ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe gFontMetrics_fieldID.leading = GetFieldIDOrDie(env, gFontMetrics_class, "leading", "F"); 11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1140ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe gFontMetricsInt_class = FindClassOrDie(env, "android/graphics/Paint$FontMetricsInt"); 1141ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe gFontMetricsInt_class = MakeGlobalRefOrDie(env, gFontMetricsInt_class); 1142ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe 1143ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe gFontMetricsInt_fieldID.top = GetFieldIDOrDie(env, gFontMetricsInt_class, "top", "I"); 1144ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe gFontMetricsInt_fieldID.ascent = GetFieldIDOrDie(env, gFontMetricsInt_class, "ascent", "I"); 1145ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe gFontMetricsInt_fieldID.descent = GetFieldIDOrDie(env, gFontMetricsInt_class, "descent", "I"); 1146ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe gFontMetricsInt_fieldID.bottom = GetFieldIDOrDie(env, gFontMetricsInt_class, "bottom", "I"); 1147ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe gFontMetricsInt_fieldID.leading = GetFieldIDOrDie(env, gFontMetricsInt_class, "leading", "I"); 1148ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe 1149ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe return RegisterMethodsOrDie(env, "android/graphics/Paint", methods, NELEM(methods)); 11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1153