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"
25f7f969e67e9ab420404807b1b103dcd18d7aa7b7Raph Levien#include <ScopedStringChars.h>
26a027ec5c2dbfbbf10cac9ea538f5e230b093be2fRaph Levien#include <ScopedUtfChars.h>
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SkBlurDrawLooper.h"
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SkColorFilter.h"
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SkMaskFilter.h"
31eba81d0f88f52ca097204ca526e796a83fdd57d5Derek Sollenberger#include "SkPath.h"
32260ab726486317496bc12a57d599ea96dcde3284Mike Reed#include "SkPathEffect.h"
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SkShader.h"
34c2f31df8b3b9a237e9abffc59c61804ad8495073Mike Reed#include "SkBlendMode.h"
35ac1cbaf2e5575ac75a0160e13089d51a0bb232faBilly Hewlett#include "unicode/uloc.h"
360c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt#include "unicode/ushape.h"
37c29a0a4664a4b9871fadd668b632469a0db240b9Derek Sollenberger#include "utils/Blur.h"
380c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt
39dccca44ffda4836b56a21da95a046c9708ffd49csergeyv#include <hwui/MinikinSkia.h>
40dccca44ffda4836b56a21da95a046c9708ffd49csergeyv#include <hwui/MinikinUtils.h>
41dccca44ffda4836b56a21da95a046c9708ffd49csergeyv#include <hwui/Paint.h>
42bad99183916ba2bac6659efc8a28273e344ba511sergeyv#include <hwui/Typeface.h>
43e368b6bcfd499543a876b4cae02f1ca563ff1cb6Raph Levien#include <minikin/GraphemeBreak.h>
44a027ec5c2dbfbbf10cac9ea538f5e230b093be2fRaph Levien#include <minikin/Measurement.h>
45bb1a96647a82df5a134bf631fc9db342e7ef61deSeigo Nonaka#include <unicode/utf16.h>
461a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien
47f036ead2a218ffa43697fcaa999b666a4c6d13cfRoozbeh Pournader#include <cassert>
48f036ead2a218ffa43697fcaa999b666a4c6d13cfRoozbeh Pournader#include <cstring>
49536afe6ef79a663e59c3b9781c561f7029ee9319Keisuke Kuroyanagi#include <memory>
50f036ead2a218ffa43697fcaa999b666a4c6d13cfRoozbeh Pournader#include <vector>
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android {
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstruct JMetricsID {
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jfieldID    top;
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jfieldID    ascent;
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jfieldID    descent;
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jfieldID    bottom;
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jfieldID    leading;
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jclass   gFontMetrics_class;
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JMetricsID gFontMetrics_fieldID;
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jclass   gFontMetricsInt_class;
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JMetricsID gFontMetricsInt_fieldID;
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
686ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbodstatic void defaultSettingsForAndroid(Paint* paint) {
69c511bee87cda99a252d1a62487f47c8f05aee78cFabrice Di Meglio    // GlyphID encoding is required because we are using Harfbuzz shaping
706ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    paint->setTextEncoding(Paint::kGlyphID_TextEncoding);
713d63e0119dc763ed0a06fd7498375746fd391d80Mike Reed}
723d63e0119dc763ed0a06fd7498375746fd391d80Mike Reed
73dbffd250003e60c0f11ac3ad2b63f91f67962610John Recknamespace PaintGlue {
740c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt    enum MoveOpt {
750c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt        AFTER, AT_OR_AFTER, BEFORE, AT_OR_BEFORE, AT
760c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt    };
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
78775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhler    static void deletePaint(Paint* paint) {
79775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhler        delete paint;
80775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhler    }
81775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhler
82775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhler    static jlong getNativeFinalizer(JNIEnv*, jobject) {
83775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhler        return static_cast<jlong>(reinterpret_cast<uintptr_t>(&deletePaint));
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
86dbffd250003e60c0f11ac3ad2b63f91f67962610John Reck    static jlong init(JNIEnv* env, jobject) {
87b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed        static_assert(1 <<  0 == SkPaint::kAntiAlias_Flag,             "paint_flags_mismatch");
88b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed        static_assert(1 <<  2 == SkPaint::kDither_Flag,                "paint_flags_mismatch");
89b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed        static_assert(1 <<  3 == SkPaint::kUnderlineText_ReserveFlag,  "paint_flags_mismatch");
90b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed        static_assert(1 <<  4 == SkPaint::kStrikeThruText_ReserveFlag, "paint_flags_mismatch");
91b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed        static_assert(1 <<  5 == SkPaint::kFakeBoldText_Flag,          "paint_flags_mismatch");
92b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed        static_assert(1 <<  6 == SkPaint::kLinearText_Flag,            "paint_flags_mismatch");
93b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed        static_assert(1 <<  7 == SkPaint::kSubpixelText_Flag,          "paint_flags_mismatch");
94b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed        static_assert(1 <<  8 == SkPaint::kDevKernText_Flag,           "paint_flags_mismatch");
95b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed        static_assert(1 << 10 == SkPaint::kEmbeddedBitmapText_Flag,    "paint_flags_mismatch");
960b8606266c1afc69cbeb73acda67c85d87943318Derek Sollenberger
976ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod        Paint* obj = new Paint();
983d63e0119dc763ed0a06fd7498375746fd391d80Mike Reed        defaultSettingsForAndroid(obj);
9936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat        return reinterpret_cast<jlong>(obj);
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10236bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    static jlong initWithPaint(JNIEnv* env, jobject clazz, jlong paintHandle) {
1036ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod        Paint* paint = reinterpret_cast<Paint*>(paintHandle);
1046ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod        Paint* obj = new Paint(*paint);
10536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat        return reinterpret_cast<jlong>(obj);
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1078451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
108f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static int breakText(JNIEnv* env, const Paint& paint, Typeface* typeface, const jchar text[],
109f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            int count, float maxWidth, jint bidiFlags, jfloatArray jmeasured,
110f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            const bool forwardScan) {
111f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        size_t measuredCount = 0;
112f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        float measured = 0;
1138451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
114f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        std::unique_ptr<float[]> advancesArray(new float[count]);
115f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        MinikinUtils::measureText(&paint, bidiFlags, typeface, text, 0, count, count,
116f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                advancesArray.get());
1174c9355c35a0f62805739823a62ad41ca1cbc6502Mike Reed
118f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        for (int i = 0; i < count; i++) {
119f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            // traverse in the given direction
120f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            int index = forwardScan ? i : (count - i - 1);
121f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            float width = advancesArray[index];
122f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            if (measured + width > maxWidth) {
123f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                break;
124f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            }
125f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            // properly handle clusters when scanning backwards
126f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            if (forwardScan || width != 0.0f) {
127f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                measuredCount = i + 1;
128f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            }
129f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            measured += width;
1304c9355c35a0f62805739823a62ad41ca1cbc6502Mike Reed        }
1318451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
132f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        if (jmeasured && env->GetArrayLength(jmeasured) > 0) {
133f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            AutoJavaFloatArray autoMeasured(env, jmeasured, 1);
134f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            jfloat* array = autoMeasured.ptr();
135f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            array[0] = measured;
136f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        }
137f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        return measuredCount;
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1398451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
140f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static jint breakTextC(JNIEnv* env, jobject clazz, jlong paintHandle, jlong typefaceHandle,
141f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            jcharArray jtext, jint index, jint count, jfloat maxWidth, jint bidiFlags,
142f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            jfloatArray jmeasuredWidth) {
143f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        NPE_CHECK_RETURN_ZERO(env, jtext);
144f43fa5746ee5b81a6e386d36594094d079ac8160Dianne Hackborn
145f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        Paint* paint = reinterpret_cast<Paint*>(paintHandle);
146f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle);
147f43fa5746ee5b81a6e386d36594094d079ac8160Dianne Hackborn
148f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        bool forwardTextDirection;
149f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        if (count < 0) {
150f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            forwardTextDirection = false;
151f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            count = -count;
152f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        }
153f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        else {
154f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            forwardTextDirection = true;
155f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        }
1568451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
157f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        if ((index < 0) || (index + count > env->GetArrayLength(jtext))) {
158f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            doThrowAIOOBE(env);
159f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            return 0;
160f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        }
1618451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
162f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        const jchar* text = env->GetCharArrayElements(jtext, nullptr);
163f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        count = breakText(env, *paint, typeface, text + index, count, maxWidth,
164f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                          bidiFlags, jmeasuredWidth, forwardTextDirection);
165f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        env->ReleaseCharArrayElements(jtext, const_cast<jchar*>(text),
166f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                                      JNI_ABORT);
167f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        return count;
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1698451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
170f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static jint breakTextS(JNIEnv* env, jobject clazz, jlong paintHandle, jlong typefaceHandle, jstring jtext,
171f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                jboolean forwards, jfloat maxWidth, jint bidiFlags, jfloatArray jmeasuredWidth) {
172f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        NPE_CHECK_RETURN_ZERO(env, jtext);
1738451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
174f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        Paint* paint = reinterpret_cast<Paint*>(paintHandle);
175f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle);
1768451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
177f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        int count = env->GetStringLength(jtext);
178f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        const jchar* text = env->GetStringChars(jtext, nullptr);
179f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        count = breakText(env, *paint, typeface, text, count, maxWidth, bidiFlags, jmeasuredWidth, forwards);
180f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        env->ReleaseStringChars(jtext, text);
181f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        return count;
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1838451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
184f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static jfloat doTextAdvances(JNIEnv *env, Paint *paint, Typeface* typeface,
185f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            const jchar *text, jint start, jint count, jint contextCount, jint bidiFlags,
186f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            jfloatArray advances, jint advancesIndex) {
187f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        NPE_CHECK_RETURN_ZERO(env, text);
1888451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
189f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        if ((start | count | contextCount | advancesIndex) < 0 || contextCount < count) {
190f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            doThrowAIOOBE(env);
191f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            return 0;
192f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        }
193f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        if (count == 0) {
194f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            return 0;
195f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        }
196f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        if (advances) {
197f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            size_t advancesLength = env->GetArrayLength(advances);
198f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            if ((size_t)(count  + advancesIndex) > advancesLength) {
199f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                doThrowAIOOBE(env);
200f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                return 0;
201f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            }
202f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        }
203f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        std::unique_ptr<jfloat[]> advancesArray;
204f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        if (advances) {
205f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            advancesArray.reset(new jfloat[count]);
206f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        }
207f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        const float advance = MinikinUtils::measureText(paint, bidiFlags, typeface, text,
208f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                start, count, contextCount, advancesArray.get());
209f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        if (advances) {
210f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            env->SetFloatArrayRegion(advances, advancesIndex, count, advancesArray.get());
211f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        }
212f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        return advance;
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2148451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
215f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static jfloat getTextAdvances___CIIIII_FI(JNIEnv* env, jobject clazz, jlong paintHandle,
216f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            jlong typefaceHandle,
217f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            jcharArray text, jint index, jint count, jint contextIndex, jint contextCount,
218f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            jint bidiFlags, jfloatArray advances, jint advancesIndex) {
219f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        Paint* paint = reinterpret_cast<Paint*>(paintHandle);
220f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle);
221f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        jchar* textArray = env->GetCharArrayElements(text, nullptr);
222f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        jfloat result = doTextAdvances(env, paint, typeface, textArray + contextIndex,
223f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                index - contextIndex, count, contextCount, bidiFlags, advances, advancesIndex);
224f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
225f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        return result;
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2278451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
228f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static jfloat getTextAdvances__StringIIIII_FI(JNIEnv* env, jobject clazz, jlong paintHandle,
229f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            jlong typefaceHandle,
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);
233f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle);
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
2425d74b1c76f5da4510a1d70d8d3b0e8c15765f231Roozbeh Pournader    static jint doTextRunCursor(JNIEnv *env, Paint* paint, Typeface* typeface, const jchar *text,
2435d74b1c76f5da4510a1d70d8d3b0e8c15765f231Roozbeh Pournader            jint start, jint count, jint dir, jint offset, jint opt) {
244f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        minikin::GraphemeBreak::MoveOpt moveOpt = minikin::GraphemeBreak::MoveOpt(opt);
2455d74b1c76f5da4510a1d70d8d3b0e8c15765f231Roozbeh Pournader        int bidiFlags = dir == 1 ? minikin::kBidi_Force_RTL : minikin::kBidi_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
2545d74b1c76f5da4510a1d70d8d3b0e8c15765f231Roozbeh Pournader    static jint getTextRunCursor___C(JNIEnv* env, jobject clazz, jlong paintHandle,
2555d74b1c76f5da4510a1d70d8d3b0e8c15765f231Roozbeh Pournader            jlong typefaceHandle, jcharArray text, jint contextStart, jint contextCount, jint dir,
2565d74b1c76f5da4510a1d70d8d3b0e8c15765f231Roozbeh Pournader            jint offset, jint cursorOpt) {
257f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2585d74b1c76f5da4510a1d70d8d3b0e8c15765f231Roozbeh Pournader        Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle);
259f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        jchar* textArray = env->GetCharArrayElements(text, nullptr);
2605d74b1c76f5da4510a1d70d8d3b0e8c15765f231Roozbeh Pournader        jint result = doTextRunCursor(env, paint, typeface, textArray,
2615d74b1c76f5da4510a1d70d8d3b0e8c15765f231Roozbeh Pournader                contextStart, contextCount, dir, offset, cursorOpt);
262f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
263f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        return result;
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2658451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
2665d74b1c76f5da4510a1d70d8d3b0e8c15765f231Roozbeh Pournader    static jint getTextRunCursor__String(JNIEnv* env, jobject clazz, jlong paintHandle,
2675d74b1c76f5da4510a1d70d8d3b0e8c15765f231Roozbeh Pournader            jlong typefaceHandle, jstring text, jint contextStart, jint contextEnd, jint dir,
2685d74b1c76f5da4510a1d70d8d3b0e8c15765f231Roozbeh Pournader            jint offset, jint cursorOpt) {
269f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        Paint* paint = reinterpret_cast<Paint*>(paintHandle);
2705d74b1c76f5da4510a1d70d8d3b0e8c15765f231Roozbeh Pournader        Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle);
271f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        const jchar* textArray = env->GetStringChars(text, nullptr);
2725d74b1c76f5da4510a1d70d8d3b0e8c15765f231Roozbeh Pournader        jint result = doTextRunCursor(env, paint, typeface, textArray,
2735d74b1c76f5da4510a1d70d8d3b0e8c15765f231Roozbeh Pournader                contextStart, contextEnd - contextStart, dir, offset, cursorOpt);
274f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        env->ReleaseStringChars(text, textArray);
275f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        return result;
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2778451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
278f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    class GetTextFunctor {
279f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    public:
280f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        GetTextFunctor(const minikin::Layout& layout, SkPath* path, jfloat x, jfloat y,
281f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                    Paint* paint, uint16_t* glyphs, SkPoint* pos)
282f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                : layout(layout), path(path), x(x), y(y), paint(paint), glyphs(glyphs), pos(pos) {
283f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        }
2848451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
285f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        void operator()(size_t start, size_t end) {
286f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            for (size_t i = start; i < end; i++) {
287f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                glyphs[i] = layout.getGlyphId(i);
288f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                pos[i].fX = x + layout.getX(i);
289f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                pos[i].fY = y + layout.getY(i);
290f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            }
291f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            if (start == 0) {
292f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                paint->getPosTextPath(glyphs + start, (end - start) << 1, pos + start, path);
293f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            } else {
294f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                paint->getPosTextPath(glyphs + start, (end - start) << 1, pos + start, &tmpPath);
295f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                path->addPath(tmpPath);
296f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            }
297f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        }
298f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    private:
299f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        const minikin::Layout& layout;
300f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        SkPath* path;
301f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        jfloat x;
302f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        jfloat y;
303f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        Paint* paint;
304f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        uint16_t* glyphs;
305f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        SkPoint* pos;
306f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        SkPath tmpPath;
307f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    };
3088451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
309f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static void getTextPath(JNIEnv* env, Paint* paint, Typeface* typeface, const jchar* text,
310f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            jint count, jint bidiFlags, jfloat x, jfloat y, SkPath* path) {
311c7064146f959caec058980ced144942c8044a169Seigo Nonaka        minikin::Layout layout = MinikinUtils::doLayout(
312c7064146f959caec058980ced144942c8044a169Seigo Nonaka                paint, bidiFlags, typeface, text, 0, count, count);
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
328f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static void getTextPath___C(JNIEnv* env, jobject clazz, jlong paintHandle,
329f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            jlong typefaceHandle, jint bidiFlags,
330f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            jcharArray text, jint index, jint count, jfloat x, jfloat y, jlong pathHandle) {
331f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        Paint* paint = reinterpret_cast<Paint*>(paintHandle);
332f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle);
333f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
334f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        const jchar* textArray = env->GetCharArrayElements(text, nullptr);
335f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        getTextPath(env, paint, typeface, textArray + index, count, bidiFlags, x, y, path);
336f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        env->ReleaseCharArrayElements(text, const_cast<jchar*>(textArray), JNI_ABORT);
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3388451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
339f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static void getTextPath__String(JNIEnv* env, jobject clazz, jlong paintHandle,
340f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            jlong typefaceHandle, jint bidiFlags,
341f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            jstring text, jint start, jint end, jfloat x, jfloat y, jlong pathHandle) {
342f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        Paint* paint = reinterpret_cast<Paint*>(paintHandle);
343f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle);
344f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
345f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        const jchar* textArray = env->GetStringChars(text, nullptr);
346f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        getTextPath(env, paint, typeface, textArray + start, end - start, bidiFlags, x, y, path);
347f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        env->ReleaseStringChars(text, textArray);
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3498451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
350f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static void doTextBounds(JNIEnv* env, const jchar* text, int count, jobject bounds,
351f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            const Paint& paint, Typeface* typeface, jint bidiFlags) {
352f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        SkRect  r;
353f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        SkIRect ir;
354f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck
355c7064146f959caec058980ced144942c8044a169Seigo Nonaka        minikin::Layout layout = MinikinUtils::doLayout(
356c7064146f959caec058980ced144942c8044a169Seigo Nonaka                &paint, bidiFlags, typeface, text, 0, count, count);
357f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        minikin::MinikinRect rect;
358f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        layout.getBounds(&rect);
359f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        r.fLeft = rect.mLeft;
360f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        r.fTop = rect.mTop;
361f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        r.fRight = rect.mRight;
362f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        r.fBottom = rect.mBottom;
363f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        r.roundOut(&ir);
364f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        GraphicsJNI::irect_to_jrect(ir, env, bounds);
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3668451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
367f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static void getStringBounds(JNIEnv* env, jobject, jlong paintHandle, jlong typefaceHandle,
368f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                                jstring text, jint start, jint end, jint bidiFlags, jobject bounds) {
369f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
370f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle);
371f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        const jchar* textArray = env->GetStringChars(text, nullptr);
372f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        doTextBounds(env, textArray + start, end - start, bounds, *paint, typeface, bidiFlags);
373f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        env->ReleaseStringChars(text, textArray);
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3758451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
376f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static void getCharArrayBounds(JNIEnv* env, jobject, jlong paintHandle, jlong typefaceHandle,
377f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                        jcharArray text, jint index, jint count, jint bidiFlags, jobject bounds) {
378f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
379f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle);
380f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        const jchar* textArray = env->GetCharArrayElements(text, nullptr);
381f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        doTextBounds(env, textArray + index, count, bounds, *paint, typeface, bidiFlags);
382f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        env->ReleaseCharArrayElements(text, const_cast<jchar*>(textArray),
383f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                                      JNI_ABORT);
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3858451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
386f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    // Returns true if the given string is exact one pair of regional indicators.
387f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static bool isFlag(const jchar* str, size_t length) {
388f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        const jchar RI_LEAD_SURROGATE = 0xD83C;
389f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        const jchar RI_TRAIL_SURROGATE_MIN = 0xDDE6;
390f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        const jchar RI_TRAIL_SURROGATE_MAX = 0xDDFF;
391f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck
392f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        if (length != 4) {
393f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            return false;
394f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        }
395f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        if (str[0] != RI_LEAD_SURROGATE || str[2] != RI_LEAD_SURROGATE) {
396f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            return false;
397f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        }
398f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        return RI_TRAIL_SURROGATE_MIN <= str[1] && str[1] <= RI_TRAIL_SURROGATE_MAX &&
399f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            RI_TRAIL_SURROGATE_MIN <= str[3] && str[3] <= RI_TRAIL_SURROGATE_MAX;
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4018451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
402f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static jboolean layoutContainsNotdef(const minikin::Layout& layout) {
403f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        for (size_t i = 0; i < layout.nGlyphs(); i++) {
404f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            if (layout.getGlyphId(i) == 0) {
405f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                return true;
406f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            }
407f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        }
408f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        return false;
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4108451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
411f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    // Don't count glyphs that are the recommended "space" glyph and are zero width.
412f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    // This logic makes assumptions about HarfBuzz layout, but does correctly handle
413f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    // cases where ligatures form and zero width space glyphs are left in as
414f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    // placeholders.
415f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static size_t countNonSpaceGlyphs(const minikin::Layout& layout) {
416f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        size_t count = 0;
417f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        static unsigned int kSpaceGlyphId = 3;
418f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        for (size_t i = 0; i < layout.nGlyphs(); i++) {
419f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            if (layout.getGlyphId(i) != kSpaceGlyphId || layout.getCharAdvance(i) != 0.0) {
420f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                count++;
421f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            }
422f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        }
423f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        return count;
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4258451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
426f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static jboolean hasGlyph(JNIEnv *env, jclass, jlong paintHandle, jlong typefaceHandle,
427f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            jint bidiFlags, jstring string) {
428f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
429f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle);
430f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        ScopedStringChars str(env, string);
4315d31a293ad0a832c7b8b445c1a67fb1800e5da32John Reck
432f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        /* Start by rejecting unsupported base code point and variation selector pairs. */
433f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        size_t nChars = 0;
434f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        const uint32_t kStartOfString = 0xFFFFFFFF;
435f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        uint32_t prevCp = kStartOfString;
436f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        for (size_t i = 0; i < str.size(); i++) {
437f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            jchar cu = str[i];
438f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            uint32_t cp = cu;
439f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            if (U16_IS_TRAIL(cu)) {
440f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                // invalid UTF-16, unpaired trailing surrogate
441f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                return false;
442f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            } else if (U16_IS_LEAD(cu)) {
443f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                if (i + 1 == str.size()) {
444f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                    // invalid UTF-16, unpaired leading surrogate at end of string
445f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                    return false;
446f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                }
447f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                i++;
448f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                jchar cu2 = str[i];
449f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                if (!U16_IS_TRAIL(cu2)) {
450f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                    // invalid UTF-16, unpaired leading surrogate
451f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                    return false;
452f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                }
453f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                cp = U16_GET_SUPPLEMENTARY(cu, cu2);
454f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            }
4558451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
456f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            if (prevCp != kStartOfString &&
457f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                ((0xFE00 <= cp && cp <= 0xFE0F) || (0xE0100 <= cp && cp <= 0xE01EF))) {
458f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                bool hasVS = MinikinUtils::hasVariationSelector(typeface, prevCp, cp);
459f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                if (!hasVS) {
460f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                    // No font has a glyph for the code point and variation selector pair.
461f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                    return false;
462f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                } else if (nChars == 1 && i + 1 == str.size()) {
463f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                    // The string is just a codepoint and a VS, we have an authoritative answer
464f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                    return true;
465f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                }
466f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            }
467f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            nChars++;
468f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            prevCp = cp;
469f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        }
470c7064146f959caec058980ced144942c8044a169Seigo Nonaka        minikin::Layout layout = MinikinUtils::doLayout(
471c7064146f959caec058980ced144942c8044a169Seigo Nonaka                paint, bidiFlags, typeface, str.get(), 0, str.size(), str.size());
472f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        size_t nGlyphs = countNonSpaceGlyphs(layout);
473f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        if (nGlyphs != 1 && nChars > 1) {
474f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            // multiple-character input, and was not a ligature
475f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            // TODO: handle ZWJ/ZWNJ characters specially so we can detect certain ligatures
476f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            // in joining scripts, such as Arabic and Mongolian.
477f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            return false;
478f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        }
4798451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
480f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        if (nGlyphs == 0 || layoutContainsNotdef(layout)) {
481f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            return false;  // The collection doesn't have a glyph.
482f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        }
483f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck
484f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        if (nChars == 2 && isFlag(str.get(), str.size())) {
485f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            // Some font may have a special glyph for unsupported regional indicator pairs.
486f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            // To return false for this case, need to compare the glyph id with the one of ZZ
487f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            // since ZZ is reserved for unknown or invalid territory.
488f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            // U+1F1FF (REGIONAL INDICATOR SYMBOL LETTER Z) is \uD83C\uDDFF in UTF16.
489f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            static const jchar ZZ_FLAG_STR[] = { 0xD83C, 0xDDFF, 0xD83C, 0xDDFF };
490c7064146f959caec058980ced144942c8044a169Seigo Nonaka            minikin::Layout zzLayout = MinikinUtils::doLayout(
491c7064146f959caec058980ced144942c8044a169Seigo Nonaka                    paint, bidiFlags, typeface, ZZ_FLAG_STR, 0, 4, 4);
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
501f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static jfloat doRunAdvance(const Paint* paint, Typeface* typeface, const jchar buf[],
502f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            jint start, jint count, jint bufSize, jboolean isRtl, jint offset) {
503f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        int bidiFlags = isRtl ? minikin::kBidi_Force_RTL : minikin::kBidi_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
514f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static jfloat getRunAdvance___CIIIIZI_F(JNIEnv *env, jclass, jlong paintHandle,
515f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            jlong typefaceHandle, jcharArray text, jint start, jint end, jint contextStart,
516f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            jint contextEnd, jboolean isRtl, jint offset) {
517f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
518f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle);
519f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        jchar* textArray = (jchar*) env->GetPrimitiveArrayCritical(text, nullptr);
520f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        jfloat result = doRunAdvance(paint, typeface, textArray + contextStart,
521f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                start - contextStart, end - start, contextEnd - contextStart, isRtl,
522f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                offset - contextStart);
523f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        env->ReleasePrimitiveArrayCritical(text, textArray, JNI_ABORT);
524f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        return result;
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5268451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
527f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static jint doOffsetForAdvance(const Paint* paint, Typeface* typeface, const jchar buf[],
528f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            jint start, jint count, jint bufSize, jboolean isRtl, jfloat advance) {
529f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        int bidiFlags = isRtl ? minikin::kBidi_Force_RTL : minikin::kBidi_Force_LTR;
530f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        std::unique_ptr<float[]> advancesArray(new float[count]);
531f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        MinikinUtils::measureText(paint, bidiFlags, typeface, buf, start, count, bufSize,
532f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                advancesArray.get());
533f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        return minikin::getOffsetForAdvance(advancesArray.get(), buf, start, count, advance);
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5358451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
536f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static jint getOffsetForAdvance___CIIIIZF_I(JNIEnv *env, jclass, jlong paintHandle,
537f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            jlong typefaceHandle, jcharArray text, jint start, jint end, jint contextStart,
538f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            jint contextEnd, jboolean isRtl, jfloat advance) {
539f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
540f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle);
541f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        jchar* textArray = (jchar*) env->GetPrimitiveArrayCritical(text, nullptr);
542f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        jint result = doOffsetForAdvance(paint, typeface, textArray + contextStart,
543f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                start - contextStart, end - start, contextEnd - contextStart, isRtl, advance);
544f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        result += contextStart;
545f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        env->ReleasePrimitiveArrayCritical(text, textArray, JNI_ABORT);
546f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        return result;
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5488451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
549f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    // ------------------ @FastNative ---------------------------
550f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck
551cfc607cf57d453f977c9c4bf09b41ac481c4bbecSeigo Nonaka    static jint setTextLocales(JNIEnv* env, jobject clazz, jlong objHandle, jstring locales) {
5526ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod        Paint* obj = reinterpret_cast<Paint*>(objHandle);
553f036ead2a218ffa43697fcaa999b666a4c6d13cfRoozbeh Pournader        ScopedUtfChars localesChars(env, locales);
554ae1aa85d0c7305bb621f1f8003bd674285aa3b63Seigo Nonaka        jint minikinLangListId = minikin::FontStyle::registerLanguageList(localesChars.c_str());
555cfc607cf57d453f977c9c4bf09b41ac481c4bbecSeigo Nonaka        obj->setMinikinLangListId(minikinLangListId);
556cfc607cf57d453f977c9c4bf09b41ac481c4bbecSeigo Nonaka        return minikinLangListId;
557cfc607cf57d453f977c9c4bf09b41ac481c4bbecSeigo Nonaka    }
558d7a80774f0a2175f9ee81a7741f9a171c78e0b8bDerek Sollenberger
559805f6ebf17e2791624bb1a30834b4c1cc65583bfBehdad Esfahbod    static void setFontFeatureSettings(JNIEnv* env, jobject clazz, jlong paintHandle, jstring settings) {
560805f6ebf17e2791624bb1a30834b4c1cc65583bfBehdad Esfahbod        Paint* paint = reinterpret_cast<Paint*>(paintHandle);
561e9ad3931fae71c8a8cd000fd52d5df4be79b0895Behdad Esfahbod        if (!settings) {
562805f6ebf17e2791624bb1a30834b4c1cc65583bfBehdad Esfahbod            paint->setFontFeatureSettings(std::string());
563e9ad3931fae71c8a8cd000fd52d5df4be79b0895Behdad Esfahbod        } else {
564805f6ebf17e2791624bb1a30834b4c1cc65583bfBehdad Esfahbod            ScopedUtfChars settingsChars(env, settings);
565805f6ebf17e2791624bb1a30834b4c1cc65583bfBehdad Esfahbod            paint->setFontFeatureSettings(std::string(settingsChars.c_str(), settingsChars.size()));
566805f6ebf17e2791624bb1a30834b4c1cc65583bfBehdad Esfahbod        }
567805f6ebf17e2791624bb1a30834b4c1cc65583bfBehdad Esfahbod    }
568805f6ebf17e2791624bb1a30834b4c1cc65583bfBehdad Esfahbod
569dbffd250003e60c0f11ac3ad2b63f91f67962610John Reck    static SkScalar getMetricsInternal(jlong paintHandle, jlong typefaceHandle,
570dbffd250003e60c0f11ac3ad2b63f91f67962610John Reck            Paint::FontMetrics *metrics) {
57153c0077256afebb0312f01ef4f60a7445da1f5d9Raph Levien        const int kElegantTop = 2500;
57253c0077256afebb0312f01ef4f60a7445da1f5d9Raph Levien        const int kElegantBottom = -1000;
573817ef4ae79bd39b5e55fc6ca4e3b8e47e114579fRaph Levien        const int kElegantAscent = 1900;
574817ef4ae79bd39b5e55fc6ca4e3b8e47e114579fRaph Levien        const int kElegantDescent = -500;
57553c0077256afebb0312f01ef4f60a7445da1f5d9Raph Levien        const int kElegantLeading = 0;
576dbffd250003e60c0f11ac3ad2b63f91f67962610John Reck        Paint* paint = reinterpret_cast<Paint*>(paintHandle);
577bad99183916ba2bac6659efc8a28273e344ba511sergeyv        Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle);
578bad99183916ba2bac6659efc8a28273e344ba511sergeyv        typeface = Typeface::resolveDefault(typeface);
579ae1aa85d0c7305bb621f1f8003bd674285aa3b63Seigo Nonaka        minikin::FakedFont baseFont = typeface->fFontCollection->baseFontFaked(typeface->fStyle);
5800627ec08dcc2e87c17e9b85f045dfb27dc4884b3Raph Levien        float saveSkewX = paint->getTextSkewX();
5810627ec08dcc2e87c17e9b85f045dfb27dc4884b3Raph Levien        bool savefakeBold = paint->isFakeBoldText();
5821fc0fa87d42ce9268ece76b85b9edc834593e53aRaph Levien        MinikinFontSkia::populateSkPaint(paint, baseFont.font, baseFont.fakery);
58353c0077256afebb0312f01ef4f60a7445da1f5d9Raph Levien        SkScalar spacing = paint->getFontMetrics(metrics);
5840627ec08dcc2e87c17e9b85f045dfb27dc4884b3Raph Levien        // The populateSkPaint call may have changed fake bold / text skew
5850627ec08dcc2e87c17e9b85f045dfb27dc4884b3Raph Levien        // because we want to measure with those effects applied, so now
5860627ec08dcc2e87c17e9b85f045dfb27dc4884b3Raph Levien        // restore the original settings.
5870627ec08dcc2e87c17e9b85f045dfb27dc4884b3Raph Levien        paint->setTextSkewX(saveSkewX);
5880627ec08dcc2e87c17e9b85f045dfb27dc4884b3Raph Levien        paint->setFakeBoldText(savefakeBold);
589ae1aa85d0c7305bb621f1f8003bd674285aa3b63Seigo Nonaka        if (paint->getFontVariant() == minikin::VARIANT_ELEGANT) {
59053c0077256afebb0312f01ef4f60a7445da1f5d9Raph Levien            SkScalar size = paint->getTextSize();
59153c0077256afebb0312f01ef4f60a7445da1f5d9Raph Levien            metrics->fTop = -size * kElegantTop / 2048;
59253c0077256afebb0312f01ef4f60a7445da1f5d9Raph Levien            metrics->fBottom = -size * kElegantBottom / 2048;
59353c0077256afebb0312f01ef4f60a7445da1f5d9Raph Levien            metrics->fAscent = -size * kElegantAscent / 2048;
59453c0077256afebb0312f01ef4f60a7445da1f5d9Raph Levien            metrics->fDescent = -size * kElegantDescent / 2048;
59553c0077256afebb0312f01ef4f60a7445da1f5d9Raph Levien            metrics->fLeading = size * kElegantLeading / 2048;
59653c0077256afebb0312f01ef4f60a7445da1f5d9Raph Levien            spacing = metrics->fDescent - metrics->fAscent + metrics->fLeading;
59753c0077256afebb0312f01ef4f60a7445da1f5d9Raph Levien        }
59853c0077256afebb0312f01ef4f60a7445da1f5d9Raph Levien        return spacing;
59953c0077256afebb0312f01ef4f60a7445da1f5d9Raph Levien    }
60053c0077256afebb0312f01ef4f60a7445da1f5d9Raph Levien
601dbffd250003e60c0f11ac3ad2b63f91f67962610John Reck    static jfloat getFontMetrics(JNIEnv* env, jobject, jlong paintHandle,
602dbffd250003e60c0f11ac3ad2b63f91f67962610John Reck            jlong typefaceHandle, jobject metricsObj) {
6036ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod        Paint::FontMetrics metrics;
604dbffd250003e60c0f11ac3ad2b63f91f67962610John Reck        SkScalar spacing = getMetricsInternal(paintHandle, typefaceHandle, &metrics);
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (metricsObj) {
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            SkASSERT(env->IsInstanceOf(metricsObj, gFontMetrics_class));
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            env->SetFloatField(metricsObj, gFontMetrics_fieldID.top, SkScalarToFloat(metrics.fTop));
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            env->SetFloatField(metricsObj, gFontMetrics_fieldID.ascent, SkScalarToFloat(metrics.fAscent));
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            env->SetFloatField(metricsObj, gFontMetrics_fieldID.descent, SkScalarToFloat(metrics.fDescent));
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            env->SetFloatField(metricsObj, gFontMetrics_fieldID.bottom, SkScalarToFloat(metrics.fBottom));
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            env->SetFloatField(metricsObj, gFontMetrics_fieldID.leading, SkScalarToFloat(metrics.fLeading));
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return SkScalarToFloat(spacing);
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6168451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
617dbffd250003e60c0f11ac3ad2b63f91f67962610John Reck    static jint getFontMetricsInt(JNIEnv* env, jobject, jlong paintHandle,
618dbffd250003e60c0f11ac3ad2b63f91f67962610John Reck            jlong typefaceHandle, jobject metricsObj) {
6196ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod        Paint::FontMetrics metrics;
6208451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
621dbffd250003e60c0f11ac3ad2b63f91f67962610John Reck        getMetricsInternal(paintHandle, typefaceHandle, &metrics);
62246cb9bdbf56b27cbf2ab878b41d21e30896a4feaLeon Scroggins        int ascent = SkScalarRoundToInt(metrics.fAscent);
62346cb9bdbf56b27cbf2ab878b41d21e30896a4feaLeon Scroggins        int descent = SkScalarRoundToInt(metrics.fDescent);
62446cb9bdbf56b27cbf2ab878b41d21e30896a4feaLeon Scroggins        int leading = SkScalarRoundToInt(metrics.fLeading);
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
626f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        if (metricsObj) {
627f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            SkASSERT(env->IsInstanceOf(metricsObj, gFontMetricsInt_class));
628f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            env->SetIntField(metricsObj, gFontMetricsInt_fieldID.top, SkScalarFloorToInt(metrics.fTop));
629f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            env->SetIntField(metricsObj, gFontMetricsInt_fieldID.ascent, ascent);
630f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            env->SetIntField(metricsObj, gFontMetricsInt_fieldID.descent, descent);
631f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            env->SetIntField(metricsObj, gFontMetricsInt_fieldID.bottom, SkScalarCeilToInt(metrics.fBottom));
632f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            env->SetIntField(metricsObj, gFontMetricsInt_fieldID.leading, leading);
633f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        }
634f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        return descent - ascent + leading;
635f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    }
636f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck
637f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck
638f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    // ------------------ @CriticalNative ---------------------------
639f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck
640f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static void reset(jlong objHandle) {
641f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        Paint* obj = reinterpret_cast<Paint*>(objHandle);
642f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        obj->reset();
643f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        defaultSettingsForAndroid(obj);
644f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    }
645f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck
646f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static void assign(jlong dstPaintHandle, jlong srcPaintHandle) {
647f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        Paint* dst = reinterpret_cast<Paint*>(dstPaintHandle);
648f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        const Paint* src = reinterpret_cast<Paint*>(srcPaintHandle);
649f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        *dst = *src;
650f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    }
651f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck
652f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    // Equivalent to the Java Paint's FILTER_BITMAP_FLAG.
653f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static const uint32_t sFilterBitmapFlag = 0x02;
654f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck
655f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static jint getFlags(jlong paintHandle) {
656f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        Paint* nativePaint = reinterpret_cast<Paint*>(paintHandle);
657f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        uint32_t result = nativePaint->getFlags();
658f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        result &= ~sFilterBitmapFlag; // Filtering no longer stored in this bit. Mask away.
659f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        if (nativePaint->getFilterQuality() != kNone_SkFilterQuality) {
660f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck            result |= sFilterBitmapFlag;
661f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        }
662f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        return static_cast<jint>(result);
663f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    }
664f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck
665f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static void setFlags(jlong paintHandle, jint flags) {
666f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        Paint* nativePaint = reinterpret_cast<Paint*>(paintHandle);
667f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        // Instead of modifying 0x02, change the filter level.
668f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        nativePaint->setFilterQuality(flags & sFilterBitmapFlag
669f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                ? kLow_SkFilterQuality
670f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                : kNone_SkFilterQuality);
671f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        // Don't pass through filter flag, which is no longer stored in paint's flags.
672f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        flags &= ~sFilterBitmapFlag;
673f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        // Use the existing value for 0x02.
674f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        const uint32_t existing0x02Flag = nativePaint->getFlags() & sFilterBitmapFlag;
675f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        flags |= existing0x02Flag;
676f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        nativePaint->setFlags(flags);
677f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    }
678f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck
679f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static jint getHinting(jlong paintHandle) {
680f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        return reinterpret_cast<Paint*>(paintHandle)->getHinting()
681f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                == Paint::kNo_Hinting ? 0 : 1;
682f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    }
683f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck
684f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static void setHinting(jlong paintHandle, jint mode) {
685f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        reinterpret_cast<Paint*>(paintHandle)->setHinting(
686f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                mode == 0 ? Paint::kNo_Hinting : Paint::kNormal_Hinting);
687f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    }
688f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck
689f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static void setAntiAlias(jlong paintHandle, jboolean aa) {
690f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        reinterpret_cast<Paint*>(paintHandle)->setAntiAlias(aa);
691f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    }
692f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck
693f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static void setLinearText(jlong paintHandle, jboolean linearText) {
694f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        reinterpret_cast<Paint*>(paintHandle)->setLinearText(linearText);
695f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    }
696f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck
697f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static void setSubpixelText(jlong paintHandle, jboolean subpixelText) {
698f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        reinterpret_cast<Paint*>(paintHandle)->setSubpixelText(subpixelText);
699f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    }
700f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck
701f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static void setUnderlineText(jlong paintHandle, jboolean underlineText) {
702b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed        Paint* paint = reinterpret_cast<Paint*>(paintHandle);
703b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed        uint32_t flags = paint->getFlags();
704b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed        if (underlineText) {
705b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed            flags |= Paint::kUnderlineText_ReserveFlag;
706b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed        } else {
707b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed            flags &= ~Paint::kUnderlineText_ReserveFlag;
708b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed        }
709b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed        paint->setFlags(flags);
710f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    }
711f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck
712f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static void setStrikeThruText(jlong paintHandle, jboolean strikeThruText) {
713b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed        Paint* paint = reinterpret_cast<Paint*>(paintHandle);
714b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed        uint32_t flags = paint->getFlags();
715b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed        if (strikeThruText) {
716b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed            flags |= Paint::kStrikeThruText_ReserveFlag;
717b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed        } else {
718b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed            flags &= ~Paint::kStrikeThruText_ReserveFlag;
719b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed        }
720b216c21acdbcb0e8a2b970d6ff9f72e9bf185623Mike Reed        paint->setFlags(flags);
721f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    }
722f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck
723f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static void setFakeBoldText(jlong paintHandle, jboolean fakeBoldText) {
724f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        reinterpret_cast<Paint*>(paintHandle)->setFakeBoldText(fakeBoldText);
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
727f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static void setFilterBitmap(jlong paintHandle, jboolean filterBitmap) {
728f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        reinterpret_cast<Paint*>(paintHandle)->setFilterQuality(
729f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck                filterBitmap ? kLow_SkFilterQuality : kNone_SkFilterQuality);
730f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    }
7316ab90ed017fb52aac4493a2fac897299d345874fFabrice Di Meglio
732f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static void setDither(jlong paintHandle, jboolean dither) {
733f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        reinterpret_cast<Paint*>(paintHandle)->setDither(dither);
7340c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt    }
7350c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt
736f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static jint getStyle(jlong objHandle) {
737f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        Paint* obj = reinterpret_cast<Paint*>(objHandle);
738f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        return static_cast<jint>(obj->getStyle());
7390c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt    }
7400c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt
741f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static void setStyle(jlong objHandle, jint styleHandle) {
742f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        Paint* obj = reinterpret_cast<Paint*>(objHandle);
743f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        Paint::Style style = static_cast<Paint::Style>(styleHandle);
744f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        obj->setStyle(style);
745eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio    }
746eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio
747f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static jint getColor(jlong paintHandle) {
748f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        int color;
749f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        color = reinterpret_cast<Paint*>(paintHandle)->getColor();
750f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        return static_cast<jint>(color);
7510c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt    }
7520c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt
753f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static jint getAlpha(jlong paintHandle) {
754f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        int alpha;
755f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        alpha = reinterpret_cast<Paint*>(paintHandle)->getAlpha();
756f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        return static_cast<jint>(alpha);
7570c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt    }
7580c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt
759f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static void setColor(jlong paintHandle, jint color) {
760f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        reinterpret_cast<Paint*>(paintHandle)->setColor(color);
7610c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt    }
7620c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt
763f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static void setAlpha(jlong paintHandle, jint a) {
764f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        reinterpret_cast<Paint*>(paintHandle)->setAlpha(a);
765f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    }
766f2114d5646194100242206b267ddd6e7194b7da9Raph Levien
767f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static jfloat getStrokeWidth(jlong paintHandle) {
768f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        return SkScalarToFloat(reinterpret_cast<Paint*>(paintHandle)->getStrokeWidth());
769f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    }
770f2114d5646194100242206b267ddd6e7194b7da9Raph Levien
771f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static void setStrokeWidth(jlong paintHandle, jfloat width) {
772f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        reinterpret_cast<Paint*>(paintHandle)->setStrokeWidth(width);
773f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    }
774f2114d5646194100242206b267ddd6e7194b7da9Raph Levien
775f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static jfloat getStrokeMiter(jlong paintHandle) {
776f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        return SkScalarToFloat(reinterpret_cast<Paint*>(paintHandle)->getStrokeMiter());
777f7cb1f75fdaedf996cab7c4690b080adc7bc5b97Doug Felt    }
778f7cb1f75fdaedf996cab7c4690b080adc7bc5b97Doug Felt
779f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static void setStrokeMiter(jlong paintHandle, jfloat miter) {
780f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        reinterpret_cast<Paint*>(paintHandle)->setStrokeMiter(miter);
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
782f7cb1f75fdaedf996cab7c4690b080adc7bc5b97Doug Felt
783f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static jint getStrokeCap(jlong objHandle) {
784f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        Paint* obj = reinterpret_cast<Paint*>(objHandle);
785f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        return static_cast<jint>(obj->getStrokeCap());
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
787f7cb1f75fdaedf996cab7c4690b080adc7bc5b97Doug Felt
788f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static void setStrokeCap(jlong objHandle, jint capHandle) {
789f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        Paint* obj = reinterpret_cast<Paint*>(objHandle);
790f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        Paint::Cap cap = static_cast<Paint::Cap>(capHandle);
791f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        obj->setStrokeCap(cap);
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
794f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static jint getStrokeJoin(jlong objHandle) {
795f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        Paint* obj = reinterpret_cast<Paint*>(objHandle);
796f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        return static_cast<jint>(obj->getStrokeJoin());
797c29a0a4664a4b9871fadd668b632469a0db240b9Derek Sollenberger    }
798c29a0a4664a4b9871fadd668b632469a0db240b9Derek Sollenberger
799f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static void setStrokeJoin(jlong objHandle, jint joinHandle) {
800f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        Paint* obj = reinterpret_cast<Paint*>(objHandle);
801f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        Paint::Join join = (Paint::Join) joinHandle;
802f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        obj->setStrokeJoin(join);
803f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    }
804a7aa1b0aa566b2ff310cb89fbc9437de4819f583Anish Athalye
805f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static jboolean getFillPath(jlong objHandle, jlong srcHandle, jlong dstHandle) {
806f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        Paint* obj = reinterpret_cast<Paint*>(objHandle);
807f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        SkPath* src = reinterpret_cast<SkPath*>(srcHandle);
808f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        SkPath* dst = reinterpret_cast<SkPath*>(dstHandle);
809f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        return obj->getFillPath(*src, dst) ? JNI_TRUE : JNI_FALSE;
810f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    }
81157c4fed236cbec0944824b534fb9c828ac0d1f81Derek Sollenberger
812f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static jlong setShader(jlong objHandle, jlong shaderHandle) {
813f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        Paint* obj = reinterpret_cast<Paint*>(objHandle);
814f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle);
815260ab726486317496bc12a57d599ea96dcde3284Mike Reed        obj->setShader(sk_ref_sp(shader));
816260ab726486317496bc12a57d599ea96dcde3284Mike Reed        return reinterpret_cast<jlong>(obj->getShader());
817f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    }
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
819f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static jlong setColorFilter(jlong objHandle, jlong filterHandle) {
820f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        Paint* obj = reinterpret_cast<Paint *>(objHandle);
821f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        SkColorFilter* filter  = reinterpret_cast<SkColorFilter *>(filterHandle);
822260ab726486317496bc12a57d599ea96dcde3284Mike Reed        obj->setColorFilter(sk_ref_sp(filter));
823260ab726486317496bc12a57d599ea96dcde3284Mike Reed        return reinterpret_cast<jlong>(obj->getColorFilter());
8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
826f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static void setXfermode(jlong paintHandle, jint xfermodeHandle) {
827f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        // validate that the Java enum values match our expectations
828260ab726486317496bc12a57d599ea96dcde3284Mike Reed        static_assert(0 == static_cast<int>(SkBlendMode::kClear), "xfermode_mismatch");
829260ab726486317496bc12a57d599ea96dcde3284Mike Reed        static_assert(1 == static_cast<int>(SkBlendMode::kSrc), "xfermode_mismatch");
830260ab726486317496bc12a57d599ea96dcde3284Mike Reed        static_assert(2 == static_cast<int>(SkBlendMode::kDst), "xfermode_mismatch");
831260ab726486317496bc12a57d599ea96dcde3284Mike Reed        static_assert(3 == static_cast<int>(SkBlendMode::kSrcOver), "xfermode_mismatch");
832260ab726486317496bc12a57d599ea96dcde3284Mike Reed        static_assert(4 == static_cast<int>(SkBlendMode::kDstOver), "xfermode_mismatch");
833260ab726486317496bc12a57d599ea96dcde3284Mike Reed        static_assert(5 == static_cast<int>(SkBlendMode::kSrcIn), "xfermode_mismatch");
834260ab726486317496bc12a57d599ea96dcde3284Mike Reed        static_assert(6 == static_cast<int>(SkBlendMode::kDstIn), "xfermode_mismatch");
835260ab726486317496bc12a57d599ea96dcde3284Mike Reed        static_assert(7 == static_cast<int>(SkBlendMode::kSrcOut), "xfermode_mismatch");
836260ab726486317496bc12a57d599ea96dcde3284Mike Reed        static_assert(8 == static_cast<int>(SkBlendMode::kDstOut), "xfermode_mismatch");
837260ab726486317496bc12a57d599ea96dcde3284Mike Reed        static_assert(9 == static_cast<int>(SkBlendMode::kSrcATop), "xfermode_mismatch");
838260ab726486317496bc12a57d599ea96dcde3284Mike Reed        static_assert(10 == static_cast<int>(SkBlendMode::kDstATop), "xfermode_mismatch");
839260ab726486317496bc12a57d599ea96dcde3284Mike Reed        static_assert(11 == static_cast<int>(SkBlendMode::kXor), "xfermode_mismatch");
840260ab726486317496bc12a57d599ea96dcde3284Mike Reed        static_assert(16 == static_cast<int>(SkBlendMode::kDarken), "xfermode_mismatch");
841260ab726486317496bc12a57d599ea96dcde3284Mike Reed        static_assert(17 == static_cast<int>(SkBlendMode::kLighten), "xfermode_mismatch");
842260ab726486317496bc12a57d599ea96dcde3284Mike Reed        static_assert(13 == static_cast<int>(SkBlendMode::kModulate), "xfermode_mismatch");
843260ab726486317496bc12a57d599ea96dcde3284Mike Reed        static_assert(14 == static_cast<int>(SkBlendMode::kScreen), "xfermode_mismatch");
844260ab726486317496bc12a57d599ea96dcde3284Mike Reed        static_assert(12 == static_cast<int>(SkBlendMode::kPlus), "xfermode_mismatch");
845260ab726486317496bc12a57d599ea96dcde3284Mike Reed        static_assert(15 == static_cast<int>(SkBlendMode::kOverlay), "xfermode_mismatch");
846260ab726486317496bc12a57d599ea96dcde3284Mike Reed
847260ab726486317496bc12a57d599ea96dcde3284Mike Reed        SkBlendMode mode = static_cast<SkBlendMode>(xfermodeHandle);
8486ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod        Paint* paint = reinterpret_cast<Paint*>(paintHandle);
849260ab726486317496bc12a57d599ea96dcde3284Mike Reed        paint->setBlendMode(mode);
850f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    }
851a7aa1b0aa566b2ff310cb89fbc9437de4819f583Anish Athalye
852f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static jlong setPathEffect(jlong objHandle, jlong effectHandle) {
853f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        Paint* obj = reinterpret_cast<Paint*>(objHandle);
854f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        SkPathEffect* effect  = reinterpret_cast<SkPathEffect*>(effectHandle);
855260ab726486317496bc12a57d599ea96dcde3284Mike Reed        obj->setPathEffect(sk_ref_sp(effect));
856260ab726486317496bc12a57d599ea96dcde3284Mike Reed        return reinterpret_cast<jlong>(obj->getPathEffect());
857f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    }
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
859f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static jlong setMaskFilter(jlong objHandle, jlong maskfilterHandle) {
860f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        Paint* obj = reinterpret_cast<Paint*>(objHandle);
861f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        SkMaskFilter* maskfilter  = reinterpret_cast<SkMaskFilter*>(maskfilterHandle);
862260ab726486317496bc12a57d599ea96dcde3284Mike Reed        obj->setMaskFilter(sk_ref_sp(maskfilter));
863260ab726486317496bc12a57d599ea96dcde3284Mike Reed        return reinterpret_cast<jlong>(obj->getMaskFilter());
864f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    }
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
866f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static jlong setTypeface(jlong objHandle, jlong typefaceHandle) {
867f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        // TODO: in Paint refactoring, set typeface on android Paint, not Paint
868f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        return 0;
8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
871f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static jint getTextAlign(jlong objHandle) {
872f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        Paint* obj = reinterpret_cast<Paint*>(objHandle);
873f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck        return static_cast<jint>(obj->getTextAlign());
874f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    }
875a7aa1b0aa566b2ff310cb89fbc9437de4819f583Anish Athalye
876f22859757b7981cdb3e05579bbb5f782965b5ca9John Reck    static void setTextAlign(jlong objHandle, jint