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