blob: c66cdfec7d1c4802a7a031333227429dab13cb94 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/* libs/android_runtime/android/graphics/Paint.cpp
2**
3** Copyright 2006, The Android Open Source Project
4**
Elliott Hughes8451b252011-04-07 19:17:57 -07005** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008**
Elliott Hughes8451b252011-04-07 19:17:57 -07009** http://www.apache.org/licenses/LICENSE-2.0
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010**
Elliott Hughes8451b252011-04-07 19:17:57 -070011** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015** limitations under the License.
16*/
17
Dianne Hackbornf43fa572011-08-12 18:59:39 -070018#define LOG_TAG "Paint"
19
20#include <utils/Log.h>
21
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022#include "jni.h"
23#include "GraphicsJNI.h"
Andreas Gampeed6b9df2014-11-20 22:02:20 -080024#include "core_jni_helpers.h"
Raph Levienf7f969e62015-04-01 14:41:21 -070025#include <ScopedStringChars.h>
Raph Leviena027ec52015-04-06 16:21:59 -070026#include <ScopedUtfChars.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027
28#include "SkBlurDrawLooper.h"
29#include "SkColorFilter.h"
30#include "SkMaskFilter.h"
31#include "SkRasterizer.h"
32#include "SkShader.h"
33#include "SkTypeface.h"
34#include "SkXfermode.h"
Billy Hewlettac1cbaf2012-07-18 09:51:45 -070035#include "unicode/uloc.h"
Doug Felt0c702b82010-05-14 10:55:42 -070036#include "unicode/ushape.h"
Derek Sollenbergerc29a0a42014-03-31 13:52:39 -040037#include "utils/Blur.h"
Doug Felt0c702b82010-05-14 10:55:42 -070038
Raph Leviene368b6b2014-06-15 17:37:57 -070039#include <minikin/GraphemeBreak.h>
Raph Leviena027ec52015-04-06 16:21:59 -070040#include <minikin/Measurement.h>
Raph Levien1a73f7322014-01-30 16:06:28 -080041#include "MinikinSkia.h"
42#include "MinikinUtils.h"
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -040043#include "Paint.h"
Raph Levien3d528c402014-06-26 09:04:54 -070044#include "TypefaceImpl.h"
Raph Levien1a73f7322014-01-30 16:06:28 -080045
Raph Levienf7f969e62015-04-01 14:41:21 -070046#include <vector>
47
Doug Felt0c702b82010-05-14 10:55:42 -070048// temporary for debugging
Chet Haase5c13d892010-10-08 08:37:55 -070049#include <Caches.h>
Doug Felt0c702b82010-05-14 10:55:42 -070050#include <utils/Log.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080051
52namespace android {
53
54struct JMetricsID {
55 jfieldID top;
56 jfieldID ascent;
57 jfieldID descent;
58 jfieldID bottom;
59 jfieldID leading;
60};
61
62static jclass gFontMetrics_class;
63static JMetricsID gFontMetrics_fieldID;
64
65static jclass gFontMetricsInt_class;
66static JMetricsID gFontMetricsInt_fieldID;
67
Derek Sollenbergerab22c1c2014-09-03 14:12:47 -040068static jclass gPaint_class;
69static jfieldID gPaint_nativeInstanceID;
70static jfieldID gPaint_nativeTypefaceID;
71
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -040072static void defaultSettingsForAndroid(Paint* paint) {
Fabrice Di Meglioc511bee82012-01-05 13:30:54 -080073 // GlyphID encoding is required because we are using Harfbuzz shaping
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -040074 paint->setTextEncoding(Paint::kGlyphID_TextEncoding);
Mike Reed3d63e012009-07-27 09:50:31 -040075}
76
John Reck476f7152015-07-10 09:56:34 -070077struct LocaleCacheEntry {
78 std::string javaLocale;
79 std::string languageTag;
80};
81
82static thread_local LocaleCacheEntry sSingleEntryLocaleCache;
83
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -040084class PaintGlue {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085public:
Doug Felt0c702b82010-05-14 10:55:42 -070086 enum MoveOpt {
87 AFTER, AT_OR_AFTER, BEFORE, AT_OR_BEFORE, AT
88 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080089
Derek Sollenbergerab22c1c2014-09-03 14:12:47 -040090 static Paint* getNativePaint(JNIEnv* env, jobject paint) {
91 SkASSERT(env);
92 SkASSERT(paint);
93 SkASSERT(env->IsInstanceOf(paint, gPaint_class));
94 jlong paintHandle = env->GetLongField(paint, gPaint_nativeInstanceID);
95 android::Paint* p = reinterpret_cast<android::Paint*>(paintHandle);
96 SkASSERT(p);
97 return p;
98 }
99
100 static TypefaceImpl* getNativeTypeface(JNIEnv* env, jobject paint) {
101 SkASSERT(env);
102 SkASSERT(paint);
103 SkASSERT(env->IsInstanceOf(paint, gPaint_class));
104 jlong typefaceHandle = env->GetLongField(paint, gPaint_nativeTypefaceID);
105 android::TypefaceImpl* p = reinterpret_cast<android::TypefaceImpl*>(typefaceHandle);
106 return p;
107 }
108
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000109 static void finalizer(JNIEnv* env, jobject clazz, jlong objHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400110 Paint* obj = reinterpret_cast<Paint*>(objHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800111 delete obj;
112 }
113
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000114 static jlong init(JNIEnv* env, jobject clazz) {
Derek Sollenberger0b860622015-03-25 10:08:30 -0400115 SK_COMPILE_ASSERT(1 << 0 == SkPaint::kAntiAlias_Flag, paint_flags_mismatch);
116 SK_COMPILE_ASSERT(1 << 2 == SkPaint::kDither_Flag, paint_flags_mismatch);
117 SK_COMPILE_ASSERT(1 << 3 == SkPaint::kUnderlineText_Flag, paint_flags_mismatch);
118 SK_COMPILE_ASSERT(1 << 4 == SkPaint::kStrikeThruText_Flag, paint_flags_mismatch);
119 SK_COMPILE_ASSERT(1 << 5 == SkPaint::kFakeBoldText_Flag, paint_flags_mismatch);
120 SK_COMPILE_ASSERT(1 << 6 == SkPaint::kLinearText_Flag, paint_flags_mismatch);
121 SK_COMPILE_ASSERT(1 << 7 == SkPaint::kSubpixelText_Flag, paint_flags_mismatch);
122 SK_COMPILE_ASSERT(1 << 8 == SkPaint::kDevKernText_Flag, paint_flags_mismatch);
123 SK_COMPILE_ASSERT(1 << 10 == SkPaint::kEmbeddedBitmapText_Flag, paint_flags_mismatch);
124
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400125 Paint* obj = new Paint();
Mike Reed3d63e012009-07-27 09:50:31 -0400126 defaultSettingsForAndroid(obj);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000127 return reinterpret_cast<jlong>(obj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800128 }
129
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000130 static jlong initWithPaint(JNIEnv* env, jobject clazz, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400131 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
132 Paint* obj = new Paint(*paint);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000133 return reinterpret_cast<jlong>(obj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800134 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700135
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000136 static void reset(JNIEnv* env, jobject clazz, jlong objHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400137 Paint* obj = reinterpret_cast<Paint*>(objHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800138 obj->reset();
Mike Reed3d63e012009-07-27 09:50:31 -0400139 defaultSettingsForAndroid(obj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700141
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000142 static void assign(JNIEnv* env, jobject clazz, jlong dstPaintHandle, jlong srcPaintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400143 Paint* dst = reinterpret_cast<Paint*>(dstPaintHandle);
144 const Paint* src = reinterpret_cast<Paint*>(srcPaintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145 *dst = *src;
146 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700147
Mike Reed4c9355c2014-05-07 11:48:37 -0400148 // Equivalent to the Java Paint's FILTER_BITMAP_FLAG.
149 static const uint32_t sFilterBitmapFlag = 0x02;
150
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800151 static jint getFlags(JNIEnv* env, jobject paint) {
152 NPE_CHECK_RETURN_ZERO(env, paint);
Derek Sollenbergerab22c1c2014-09-03 14:12:47 -0400153 Paint* nativePaint = getNativePaint(env, paint);
Mike Reed4c9355c2014-05-07 11:48:37 -0400154 uint32_t result = nativePaint->getFlags();
155 result &= ~sFilterBitmapFlag; // Filtering no longer stored in this bit. Mask away.
Mike Reed2a1ce8a2015-03-16 11:16:09 -0400156 if (nativePaint->getFilterQuality() != kNone_SkFilterQuality) {
Mike Reed4c9355c2014-05-07 11:48:37 -0400157 result |= sFilterBitmapFlag;
158 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000159 return static_cast<jint>(result);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800160 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700161
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800162 static void setFlags(JNIEnv* env, jobject paint, jint flags) {
163 NPE_CHECK_RETURN_VOID(env, paint);
Derek Sollenbergerab22c1c2014-09-03 14:12:47 -0400164 Paint* nativePaint = getNativePaint(env, paint);
Mike Reed4c9355c2014-05-07 11:48:37 -0400165 // Instead of modifying 0x02, change the filter level.
Mike Reed2a1ce8a2015-03-16 11:16:09 -0400166 nativePaint->setFilterQuality(flags & sFilterBitmapFlag
167 ? kLow_SkFilterQuality
168 : kNone_SkFilterQuality);
Mike Reed4c9355c2014-05-07 11:48:37 -0400169 // Don't pass through filter flag, which is no longer stored in paint's flags.
170 flags &= ~sFilterBitmapFlag;
171 // Use the existing value for 0x02.
172 const uint32_t existing0x02Flag = nativePaint->getFlags() & sFilterBitmapFlag;
173 flags |= existing0x02Flag;
174 nativePaint->setFlags(flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800175 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700176
Dianne Hackbornf43fa572011-08-12 18:59:39 -0700177 static jint getHinting(JNIEnv* env, jobject paint) {
178 NPE_CHECK_RETURN_ZERO(env, paint);
Derek Sollenbergerab22c1c2014-09-03 14:12:47 -0400179 return getNativePaint(env, paint)->getHinting()
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400180 == Paint::kNo_Hinting ? 0 : 1;
Dianne Hackbornf43fa572011-08-12 18:59:39 -0700181 }
182
183 static void setHinting(JNIEnv* env, jobject paint, jint mode) {
184 NPE_CHECK_RETURN_VOID(env, paint);
Derek Sollenbergerab22c1c2014-09-03 14:12:47 -0400185 getNativePaint(env, paint)->setHinting(
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400186 mode == 0 ? Paint::kNo_Hinting : Paint::kNormal_Hinting);
Dianne Hackbornf43fa572011-08-12 18:59:39 -0700187 }
188
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800189 static void setAntiAlias(JNIEnv* env, jobject paint, jboolean aa) {
190 NPE_CHECK_RETURN_VOID(env, paint);
Derek Sollenbergerab22c1c2014-09-03 14:12:47 -0400191 getNativePaint(env, paint)->setAntiAlias(aa);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800192 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700193
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800194 static void setLinearText(JNIEnv* env, jobject paint, jboolean linearText) {
195 NPE_CHECK_RETURN_VOID(env, paint);
Derek Sollenbergerab22c1c2014-09-03 14:12:47 -0400196 getNativePaint(env, paint)->setLinearText(linearText);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800197 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700198
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800199 static void setSubpixelText(JNIEnv* env, jobject paint, jboolean subpixelText) {
200 NPE_CHECK_RETURN_VOID(env, paint);
Derek Sollenbergerab22c1c2014-09-03 14:12:47 -0400201 getNativePaint(env, paint)->setSubpixelText(subpixelText);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800202 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700203
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800204 static void setUnderlineText(JNIEnv* env, jobject paint, jboolean underlineText) {
205 NPE_CHECK_RETURN_VOID(env, paint);
Derek Sollenbergerab22c1c2014-09-03 14:12:47 -0400206 getNativePaint(env, paint)->setUnderlineText(underlineText);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800207 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700208
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800209 static void setStrikeThruText(JNIEnv* env, jobject paint, jboolean strikeThruText) {
210 NPE_CHECK_RETURN_VOID(env, paint);
Derek Sollenbergerab22c1c2014-09-03 14:12:47 -0400211 getNativePaint(env, paint)->setStrikeThruText(strikeThruText);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800212 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700213
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800214 static void setFakeBoldText(JNIEnv* env, jobject paint, jboolean fakeBoldText) {
215 NPE_CHECK_RETURN_VOID(env, paint);
Derek Sollenbergerab22c1c2014-09-03 14:12:47 -0400216 getNativePaint(env, paint)->setFakeBoldText(fakeBoldText);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800217 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700218
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800219 static void setFilterBitmap(JNIEnv* env, jobject paint, jboolean filterBitmap) {
220 NPE_CHECK_RETURN_VOID(env, paint);
Mike Reed2a1ce8a2015-03-16 11:16:09 -0400221 getNativePaint(env, paint)->setFilterQuality(
222 filterBitmap ? kLow_SkFilterQuality : kNone_SkFilterQuality);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800223 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700224
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800225 static void setDither(JNIEnv* env, jobject paint, jboolean dither) {
226 NPE_CHECK_RETURN_VOID(env, paint);
Derek Sollenbergerab22c1c2014-09-03 14:12:47 -0400227 getNativePaint(env, paint)->setDither(dither);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800228 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700229
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000230 static jint getStyle(JNIEnv* env, jobject clazz,jlong objHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400231 Paint* obj = reinterpret_cast<Paint*>(objHandle);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000232 return static_cast<jint>(obj->getStyle());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800233 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700234
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000235 static void setStyle(JNIEnv* env, jobject clazz, jlong objHandle, jint styleHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400236 Paint* obj = reinterpret_cast<Paint*>(objHandle);
237 Paint::Style style = static_cast<Paint::Style>(styleHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800238 obj->setStyle(style);
239 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700240
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800241 static jint getColor(JNIEnv* env, jobject paint) {
242 NPE_CHECK_RETURN_ZERO(env, paint);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000243 int color;
Derek Sollenbergerab22c1c2014-09-03 14:12:47 -0400244 color = getNativePaint(env, paint)->getColor();
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000245 return static_cast<jint>(color);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800246 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700247
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800248 static jint getAlpha(JNIEnv* env, jobject paint) {
249 NPE_CHECK_RETURN_ZERO(env, paint);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000250 int alpha;
Derek Sollenbergerab22c1c2014-09-03 14:12:47 -0400251 alpha = getNativePaint(env, paint)->getAlpha();
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000252 return static_cast<jint>(alpha);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800253 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700254
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800255 static void setColor(JNIEnv* env, jobject paint, jint color) {
256 NPE_CHECK_RETURN_VOID(env, paint);
Derek Sollenbergerab22c1c2014-09-03 14:12:47 -0400257 getNativePaint(env, paint)->setColor(color);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800258 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700259
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800260 static void setAlpha(JNIEnv* env, jobject paint, jint a) {
261 NPE_CHECK_RETURN_VOID(env, paint);
Derek Sollenbergerab22c1c2014-09-03 14:12:47 -0400262 getNativePaint(env, paint)->setAlpha(a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800263 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700264
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800265 static jfloat getStrokeWidth(JNIEnv* env, jobject paint) {
266 NPE_CHECK_RETURN_ZERO(env, paint);
Derek Sollenbergerab22c1c2014-09-03 14:12:47 -0400267 return SkScalarToFloat(getNativePaint(env, paint)->getStrokeWidth());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800268 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700269
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800270 static void setStrokeWidth(JNIEnv* env, jobject paint, jfloat width) {
271 NPE_CHECK_RETURN_VOID(env, paint);
Derek Sollenbergerab22c1c2014-09-03 14:12:47 -0400272 getNativePaint(env, paint)->setStrokeWidth(width);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800273 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700274
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800275 static jfloat getStrokeMiter(JNIEnv* env, jobject paint) {
276 NPE_CHECK_RETURN_ZERO(env, paint);
Derek Sollenbergerab22c1c2014-09-03 14:12:47 -0400277 return SkScalarToFloat(getNativePaint(env, paint)->getStrokeMiter());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800278 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700279
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800280 static void setStrokeMiter(JNIEnv* env, jobject paint, jfloat miter) {
281 NPE_CHECK_RETURN_VOID(env, paint);
Derek Sollenbergerab22c1c2014-09-03 14:12:47 -0400282 getNativePaint(env, paint)->setStrokeMiter(miter);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800283 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700284
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000285 static jint getStrokeCap(JNIEnv* env, jobject clazz, jlong objHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400286 Paint* obj = reinterpret_cast<Paint*>(objHandle);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000287 return static_cast<jint>(obj->getStrokeCap());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800288 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700289
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000290 static void setStrokeCap(JNIEnv* env, jobject clazz, jlong objHandle, jint capHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400291 Paint* obj = reinterpret_cast<Paint*>(objHandle);
292 Paint::Cap cap = static_cast<Paint::Cap>(capHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800293 obj->setStrokeCap(cap);
294 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700295
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000296 static jint getStrokeJoin(JNIEnv* env, jobject clazz, jlong objHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400297 Paint* obj = reinterpret_cast<Paint*>(objHandle);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000298 return static_cast<jint>(obj->getStrokeJoin());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800299 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700300
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000301 static void setStrokeJoin(JNIEnv* env, jobject clazz, jlong objHandle, jint joinHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400302 Paint* obj = reinterpret_cast<Paint*>(objHandle);
303 Paint::Join join = (Paint::Join) joinHandle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800304 obj->setStrokeJoin(join);
305 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700306
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000307 static jboolean getFillPath(JNIEnv* env, jobject clazz, jlong objHandle, jlong srcHandle, jlong dstHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400308 Paint* obj = reinterpret_cast<Paint*>(objHandle);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000309 SkPath* src = reinterpret_cast<SkPath*>(srcHandle);
310 SkPath* dst = reinterpret_cast<SkPath*>(dstHandle);
311 return obj->getFillPath(*src, dst) ? JNI_TRUE : JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800312 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700313
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000314 static jlong setShader(JNIEnv* env, jobject clazz, jlong objHandle, jlong shaderHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400315 Paint* obj = reinterpret_cast<Paint*>(objHandle);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000316 SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle);
317 return reinterpret_cast<jlong>(obj->setShader(shader));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800318 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700319
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000320 static jlong setColorFilter(JNIEnv* env, jobject clazz, jlong objHandle, jlong filterHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400321 Paint* obj = reinterpret_cast<Paint *>(objHandle);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000322 SkColorFilter* filter = reinterpret_cast<SkColorFilter *>(filterHandle);
323 return reinterpret_cast<jlong>(obj->setColorFilter(filter));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800324 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700325
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000326 static jlong setXfermode(JNIEnv* env, jobject clazz, jlong objHandle, jlong xfermodeHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400327 Paint* obj = reinterpret_cast<Paint*>(objHandle);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000328 SkXfermode* xfermode = reinterpret_cast<SkXfermode*>(xfermodeHandle);
329 return reinterpret_cast<jlong>(obj->setXfermode(xfermode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800330 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700331
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000332 static jlong setPathEffect(JNIEnv* env, jobject clazz, jlong objHandle, jlong effectHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400333 Paint* obj = reinterpret_cast<Paint*>(objHandle);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000334 SkPathEffect* effect = reinterpret_cast<SkPathEffect*>(effectHandle);
335 return reinterpret_cast<jlong>(obj->setPathEffect(effect));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800336 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700337
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000338 static jlong setMaskFilter(JNIEnv* env, jobject clazz, jlong objHandle, jlong maskfilterHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400339 Paint* obj = reinterpret_cast<Paint*>(objHandle);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000340 SkMaskFilter* maskfilter = reinterpret_cast<SkMaskFilter*>(maskfilterHandle);
341 return reinterpret_cast<jlong>(obj->setMaskFilter(maskfilter));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800342 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700343
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000344 static jlong setTypeface(JNIEnv* env, jobject clazz, jlong objHandle, jlong typefaceHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400345 // TODO: in Paint refactoring, set typeface on android Paint, not Paint
Raph Leviena0336302013-05-22 16:16:59 -0700346 return NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800347 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700348
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000349 static jlong setRasterizer(JNIEnv* env, jobject clazz, jlong objHandle, jlong rasterizerHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400350 Paint* obj = reinterpret_cast<Paint*>(objHandle);
Mike Reed4c9355c2014-05-07 11:48:37 -0400351 SkAutoTUnref<SkRasterizer> rasterizer(GraphicsJNI::refNativeRasterizer(rasterizerHandle));
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000352 return reinterpret_cast<jlong>(obj->setRasterizer(rasterizer));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800353 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700354
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000355 static jint getTextAlign(JNIEnv* env, jobject clazz, jlong objHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400356 Paint* obj = reinterpret_cast<Paint*>(objHandle);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000357 return static_cast<jint>(obj->getTextAlign());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800358 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700359
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000360 static void setTextAlign(JNIEnv* env, jobject clazz, jlong objHandle, jint alignHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400361 Paint* obj = reinterpret_cast<Paint*>(objHandle);
362 Paint::Align align = static_cast<Paint::Align>(alignHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800363 obj->setTextAlign(align);
364 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700365
Billy Hewlettac1cbaf2012-07-18 09:51:45 -0700366 // generate bcp47 identifier for the supplied locale
367 static void toLanguageTag(char* output, size_t outSize,
368 const char* locale) {
369 if (output == NULL || outSize <= 0) {
370 return;
371 }
372 if (locale == NULL) {
373 output[0] = '\0';
374 return;
375 }
376 char canonicalChars[ULOC_FULLNAME_CAPACITY];
377 UErrorCode uErr = U_ZERO_ERROR;
378 uloc_canonicalize(locale, canonicalChars, ULOC_FULLNAME_CAPACITY,
379 &uErr);
380 if (U_SUCCESS(uErr)) {
381 char likelyChars[ULOC_FULLNAME_CAPACITY];
382 uErr = U_ZERO_ERROR;
383 uloc_addLikelySubtags(canonicalChars, likelyChars,
384 ULOC_FULLNAME_CAPACITY, &uErr);
385 if (U_SUCCESS(uErr)) {
386 uErr = U_ZERO_ERROR;
387 uloc_toLanguageTag(likelyChars, output, outSize, FALSE, &uErr);
388 if (U_SUCCESS(uErr)) {
389 return;
390 } else {
391 ALOGD("uloc_toLanguageTag(\"%s\") failed: %s", likelyChars,
392 u_errorName(uErr));
393 }
394 } else {
395 ALOGD("uloc_addLikelySubtags(\"%s\") failed: %s",
396 canonicalChars, u_errorName(uErr));
397 }
398 } else {
399 ALOGD("uloc_canonicalize(\"%s\") failed: %s", locale,
400 u_errorName(uErr));
401 }
402 // unable to build a proper language identifier
403 output[0] = '\0';
404 }
405
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000406 static void setTextLocale(JNIEnv* env, jobject clazz, jlong objHandle, jstring locale) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400407 Paint* obj = reinterpret_cast<Paint*>(objHandle);
Billy Hewlettac1cbaf2012-07-18 09:51:45 -0700408 ScopedUtfChars localeChars(env, locale);
John Reck476f7152015-07-10 09:56:34 -0700409 if (sSingleEntryLocaleCache.javaLocale != localeChars.c_str()) {
410 sSingleEntryLocaleCache.javaLocale = localeChars.c_str();
411 char langTag[ULOC_FULLNAME_CAPACITY];
412 toLanguageTag(langTag, ULOC_FULLNAME_CAPACITY, localeChars.c_str());
413 sSingleEntryLocaleCache.languageTag = langTag;
414 }
Derek Sollenbergerd7a80772013-05-28 10:44:26 -0400415
John Reck476f7152015-07-10 09:56:34 -0700416 obj->setTextLocale(sSingleEntryLocaleCache.languageTag);
Fabrice Di Meglio517825f2012-04-06 16:53:48 -0700417 }
418
Raph Levien53c00772014-04-14 14:11:02 -0700419 static jboolean isElegantTextHeight(JNIEnv* env, jobject paint) {
420 NPE_CHECK_RETURN_ZERO(env, paint);
Derek Sollenbergerab22c1c2014-09-03 14:12:47 -0400421 Paint* obj = getNativePaint(env, paint);
Derek Sollenberger6f030232014-08-07 08:10:39 -0400422 return obj->getFontVariant() == VARIANT_ELEGANT;
Raph Levien53c00772014-04-14 14:11:02 -0700423 }
424
425 static void setElegantTextHeight(JNIEnv* env, jobject paint, jboolean aa) {
426 NPE_CHECK_RETURN_VOID(env, paint);
Derek Sollenbergerab22c1c2014-09-03 14:12:47 -0400427 Paint* obj = getNativePaint(env, paint);
Derek Sollenberger6f030232014-08-07 08:10:39 -0400428 obj->setFontVariant(aa ? VARIANT_ELEGANT : VARIANT_DEFAULT);
Raph Levien53c00772014-04-14 14:11:02 -0700429 }
430
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800431 static jfloat getTextSize(JNIEnv* env, jobject paint) {
432 NPE_CHECK_RETURN_ZERO(env, paint);
Derek Sollenbergerab22c1c2014-09-03 14:12:47 -0400433 return SkScalarToFloat(getNativePaint(env, paint)->getTextSize());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800434 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700435
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800436 static void setTextSize(JNIEnv* env, jobject paint, jfloat textSize) {
437 NPE_CHECK_RETURN_VOID(env, paint);
Derek Sollenbergerab22c1c2014-09-03 14:12:47 -0400438 getNativePaint(env, paint)->setTextSize(textSize);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800439 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700440
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800441 static jfloat getTextScaleX(JNIEnv* env, jobject paint) {
442 NPE_CHECK_RETURN_ZERO(env, paint);
Derek Sollenbergerab22c1c2014-09-03 14:12:47 -0400443 return SkScalarToFloat(getNativePaint(env, paint)->getTextScaleX());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800444 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700445
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800446 static void setTextScaleX(JNIEnv* env, jobject paint, jfloat scaleX) {
447 NPE_CHECK_RETURN_VOID(env, paint);
Derek Sollenbergerab22c1c2014-09-03 14:12:47 -0400448 getNativePaint(env, paint)->setTextScaleX(scaleX);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800449 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700450
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800451 static jfloat getTextSkewX(JNIEnv* env, jobject paint) {
452 NPE_CHECK_RETURN_ZERO(env, paint);
Derek Sollenbergerab22c1c2014-09-03 14:12:47 -0400453 return SkScalarToFloat(getNativePaint(env, paint)->getTextSkewX());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800454 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700455
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800456 static void setTextSkewX(JNIEnv* env, jobject paint, jfloat skewX) {
457 NPE_CHECK_RETURN_VOID(env, paint);
Derek Sollenbergerab22c1c2014-09-03 14:12:47 -0400458 getNativePaint(env, paint)->setTextSkewX(skewX);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800459 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700460
Behdad Esfahbodfa80f742014-07-17 19:10:39 -0400461 static jfloat getLetterSpacing(JNIEnv* env, jobject clazz, jlong paintHandle) {
462 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
463 return paint->getLetterSpacing();
464 }
465
466 static void setLetterSpacing(JNIEnv* env, jobject clazz, jlong paintHandle, jfloat letterSpacing) {
467 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
468 paint->setLetterSpacing(letterSpacing);
469 }
470
Behdad Esfahbod805f6eb2014-07-29 18:43:03 -0400471 static void setFontFeatureSettings(JNIEnv* env, jobject clazz, jlong paintHandle, jstring settings) {
472 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Behdad Esfahbode9ad3932014-07-30 19:46:53 -0400473 if (!settings) {
Behdad Esfahbod805f6eb2014-07-29 18:43:03 -0400474 paint->setFontFeatureSettings(std::string());
Behdad Esfahbode9ad3932014-07-30 19:46:53 -0400475 } else {
Behdad Esfahbod805f6eb2014-07-29 18:43:03 -0400476 ScopedUtfChars settingsChars(env, settings);
477 paint->setFontFeatureSettings(std::string(settingsChars.c_str(), settingsChars.size()));
478 }
479 }
480
Raph Levien210a1892015-03-09 14:42:14 -0700481 static jint getHyphenEdit(JNIEnv* env, jobject clazz, jlong paintHandle, jint hyphen) {
482 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
483 return paint->getHyphenEdit();
484 }
485
486 static void setHyphenEdit(JNIEnv* env, jobject clazz, jlong paintHandle, jint hyphen) {
487 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
488 paint->setHyphenEdit((uint32_t)hyphen);
489 }
490
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400491 static SkScalar getMetricsInternal(JNIEnv* env, jobject jpaint, Paint::FontMetrics *metrics) {
Raph Levien53c00772014-04-14 14:11:02 -0700492 const int kElegantTop = 2500;
493 const int kElegantBottom = -1000;
Raph Levien817ef4a2014-06-05 22:38:08 -0700494 const int kElegantAscent = 1900;
495 const int kElegantDescent = -500;
Raph Levien53c00772014-04-14 14:11:02 -0700496 const int kElegantLeading = 0;
Derek Sollenbergerab22c1c2014-09-03 14:12:47 -0400497 Paint* paint = getNativePaint(env, jpaint);
498 TypefaceImpl* typeface = getNativeTypeface(env, jpaint);
Raph Levien817ef4a2014-06-05 22:38:08 -0700499 typeface = TypefaceImpl_resolveDefault(typeface);
Raph Levien1fc0fa82014-06-06 18:05:22 -0700500 FakedFont baseFont = typeface->fFontCollection->baseFontFaked(typeface->fStyle);
Raph Levien0627ec02014-06-06 22:31:15 -0700501 float saveSkewX = paint->getTextSkewX();
502 bool savefakeBold = paint->isFakeBoldText();
Raph Levien1fc0fa82014-06-06 18:05:22 -0700503 MinikinFontSkia::populateSkPaint(paint, baseFont.font, baseFont.fakery);
Raph Levien53c00772014-04-14 14:11:02 -0700504 SkScalar spacing = paint->getFontMetrics(metrics);
Raph Levien0627ec02014-06-06 22:31:15 -0700505 // The populateSkPaint call may have changed fake bold / text skew
506 // because we want to measure with those effects applied, so now
507 // restore the original settings.
508 paint->setTextSkewX(saveSkewX);
509 paint->setFakeBoldText(savefakeBold);
Derek Sollenberger6f030232014-08-07 08:10:39 -0400510 if (paint->getFontVariant() == VARIANT_ELEGANT) {
Raph Levien53c00772014-04-14 14:11:02 -0700511 SkScalar size = paint->getTextSize();
512 metrics->fTop = -size * kElegantTop / 2048;
513 metrics->fBottom = -size * kElegantBottom / 2048;
514 metrics->fAscent = -size * kElegantAscent / 2048;
515 metrics->fDescent = -size * kElegantDescent / 2048;
516 metrics->fLeading = size * kElegantLeading / 2048;
517 spacing = metrics->fDescent - metrics->fAscent + metrics->fLeading;
518 }
519 return spacing;
520 }
521
Raph Levien817ef4a2014-06-05 22:38:08 -0700522 static jfloat ascent(JNIEnv* env, jobject paint) {
523 NPE_CHECK_RETURN_ZERO(env, paint);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400524 Paint::FontMetrics metrics;
Raph Levien817ef4a2014-06-05 22:38:08 -0700525 getMetricsInternal(env, paint, &metrics);
526 return SkScalarToFloat(metrics.fAscent);
527 }
528
529 static jfloat descent(JNIEnv* env, jobject paint) {
530 NPE_CHECK_RETURN_ZERO(env, paint);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400531 Paint::FontMetrics metrics;
Raph Levien817ef4a2014-06-05 22:38:08 -0700532 getMetricsInternal(env, paint, &metrics);
533 return SkScalarToFloat(metrics.fDescent);
534 }
535
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800536 static jfloat getFontMetrics(JNIEnv* env, jobject paint, jobject metricsObj) {
537 NPE_CHECK_RETURN_ZERO(env, paint);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400538 Paint::FontMetrics metrics;
Raph Levien817ef4a2014-06-05 22:38:08 -0700539 SkScalar spacing = getMetricsInternal(env, paint, &metrics);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800540
541 if (metricsObj) {
542 SkASSERT(env->IsInstanceOf(metricsObj, gFontMetrics_class));
543 env->SetFloatField(metricsObj, gFontMetrics_fieldID.top, SkScalarToFloat(metrics.fTop));
544 env->SetFloatField(metricsObj, gFontMetrics_fieldID.ascent, SkScalarToFloat(metrics.fAscent));
545 env->SetFloatField(metricsObj, gFontMetrics_fieldID.descent, SkScalarToFloat(metrics.fDescent));
546 env->SetFloatField(metricsObj, gFontMetrics_fieldID.bottom, SkScalarToFloat(metrics.fBottom));
547 env->SetFloatField(metricsObj, gFontMetrics_fieldID.leading, SkScalarToFloat(metrics.fLeading));
548 }
549 return SkScalarToFloat(spacing);
550 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700551
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800552 static jint getFontMetricsInt(JNIEnv* env, jobject paint, jobject metricsObj) {
553 NPE_CHECK_RETURN_ZERO(env, paint);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400554 Paint::FontMetrics metrics;
Elliott Hughes8451b252011-04-07 19:17:57 -0700555
Raph Levien817ef4a2014-06-05 22:38:08 -0700556 getMetricsInternal(env, paint, &metrics);
Leon Scroggins46cb9bd2014-03-06 15:36:39 -0500557 int ascent = SkScalarRoundToInt(metrics.fAscent);
558 int descent = SkScalarRoundToInt(metrics.fDescent);
559 int leading = SkScalarRoundToInt(metrics.fLeading);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800560
561 if (metricsObj) {
562 SkASSERT(env->IsInstanceOf(metricsObj, gFontMetricsInt_class));
Leon Scroggins46cb9bd2014-03-06 15:36:39 -0500563 env->SetIntField(metricsObj, gFontMetricsInt_fieldID.top, SkScalarFloorToInt(metrics.fTop));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800564 env->SetIntField(metricsObj, gFontMetricsInt_fieldID.ascent, ascent);
565 env->SetIntField(metricsObj, gFontMetricsInt_fieldID.descent, descent);
Leon Scroggins46cb9bd2014-03-06 15:36:39 -0500566 env->SetIntField(metricsObj, gFontMetricsInt_fieldID.bottom, SkScalarCeilToInt(metrics.fBottom));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800567 env->SetIntField(metricsObj, gFontMetricsInt_fieldID.leading, leading);
568 }
569 return descent - ascent + leading;
570 }
571
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000572 static jfloat measureText_CIII(JNIEnv* env, jobject jpaint, jcharArray text, jint index, jint count,
Victoria Lease626d3c22013-03-27 15:35:53 -0700573 jint bidiFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800574 NPE_CHECK_RETURN_ZERO(env, jpaint);
575 NPE_CHECK_RETURN_ZERO(env, text);
576
577 size_t textLength = env->GetArrayLength(text);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800578 if ((index | count) < 0 || (size_t)(index + count) > textLength) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700579 doThrowAIOOBE(env);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800580 return 0;
581 }
Fabrice Di Meglio6ab90ed2011-08-08 16:19:38 -0700582 if (count == 0) {
583 return 0;
584 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800585
Derek Sollenbergerab22c1c2014-09-03 14:12:47 -0400586 Paint* paint = getNativePaint(env, jpaint);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800587 const jchar* textArray = env->GetCharArrayElements(text, NULL);
Fabrice Di Meglio4f810c82011-04-19 14:53:58 -0700588 jfloat result = 0;
Fabrice Di Megliob02d0ca2011-12-08 14:05:44 -0800589
Raph Levien1a73f7322014-01-30 16:06:28 -0800590 Layout layout;
Derek Sollenbergerab22c1c2014-09-03 14:12:47 -0400591 TypefaceImpl* typeface = getNativeTypeface(env, jpaint);
Raph Levien80b485d2015-04-03 10:41:52 -0700592 MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, textArray + index, 0, count,
593 count);
Raph Levien1a73f7322014-01-30 16:06:28 -0800594 result = layout.getAdvance();
Fabrice Di Meglio4f810c82011-04-19 14:53:58 -0700595 env->ReleaseCharArrayElements(text, const_cast<jchar*>(textArray), JNI_ABORT);
596 return result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800597 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700598
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000599 static jfloat measureText_StringIII(JNIEnv* env, jobject jpaint, jstring text, jint start, jint end,
Victoria Lease626d3c22013-03-27 15:35:53 -0700600 jint bidiFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800601 NPE_CHECK_RETURN_ZERO(env, jpaint);
602 NPE_CHECK_RETURN_ZERO(env, text);
Elliott Hughes8451b252011-04-07 19:17:57 -0700603
Fabrice Di Meglio51f383d2011-09-13 15:57:58 -0700604 size_t textLength = env->GetStringLength(text);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800605 int count = end - start;
Fabrice Di Meglio51f383d2011-09-13 15:57:58 -0700606 if ((start | count) < 0 || (size_t)end > textLength) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700607 doThrowAIOOBE(env);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800608 return 0;
609 }
Fabrice Di Meglio6ab90ed2011-08-08 16:19:38 -0700610 if (count == 0) {
611 return 0;
612 }
Fabrice Di Meglio6ab90ed2011-08-08 16:19:38 -0700613
614 const jchar* textArray = env->GetStringChars(text, NULL);
Derek Sollenbergerab22c1c2014-09-03 14:12:47 -0400615 Paint* paint = getNativePaint(env, jpaint);
Fabrice Di Meglio4f810c82011-04-19 14:53:58 -0700616 jfloat width = 0;
Elliott Hughes8451b252011-04-07 19:17:57 -0700617
Raph Levien1a73f7322014-01-30 16:06:28 -0800618 Layout layout;
Derek Sollenbergerab22c1c2014-09-03 14:12:47 -0400619 TypefaceImpl* typeface = getNativeTypeface(env, jpaint);
Raph Levien1149cdc2015-06-24 09:36:31 -0700620 // Only the substring is used for measurement, so no additional context is passed in. This
621 // behavior is consistent between char[] and String specializations.
622 MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, textArray + start, 0, count, count);
Raph Levien1a73f7322014-01-30 16:06:28 -0800623 width = layout.getAdvance();
Fabrice Di Meglio4f810c82011-04-19 14:53:58 -0700624
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800625 env->ReleaseStringChars(text, textArray);
626 return width;
627 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700628
Victoria Lease626d3c22013-03-27 15:35:53 -0700629 static jfloat measureText_StringI(JNIEnv* env, jobject jpaint, jstring text, jint bidiFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800630 NPE_CHECK_RETURN_ZERO(env, jpaint);
631 NPE_CHECK_RETURN_ZERO(env, text);
Elliott Hughes8451b252011-04-07 19:17:57 -0700632
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800633 size_t textLength = env->GetStringLength(text);
Fabrice Di Meglio6ab90ed2011-08-08 16:19:38 -0700634 if (textLength == 0) {
635 return 0;
636 }
637
638 const jchar* textArray = env->GetStringChars(text, NULL);
Derek Sollenbergerab22c1c2014-09-03 14:12:47 -0400639 Paint* paint = getNativePaint(env, jpaint);
Fabrice Di Meglio4f810c82011-04-19 14:53:58 -0700640 jfloat width = 0;
Fabrice Di Meglio6ab90ed2011-08-08 16:19:38 -0700641
Raph Levien1a73f7322014-01-30 16:06:28 -0800642 Layout layout;
Derek Sollenbergerab22c1c2014-09-03 14:12:47 -0400643 TypefaceImpl* typeface = getNativeTypeface(env, jpaint);
Behdad Esfahbod63c5c782014-07-25 14:54:46 -0400644 MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, textArray, 0, textLength, textLength);
Raph Levien1a73f7322014-01-30 16:06:28 -0800645 width = layout.getAdvance();
Fabrice Di Megliob02d0ca2011-12-08 14:05:44 -0800646
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800647 env->ReleaseStringChars(text, textArray);
648 return width;
649 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700650
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400651 static int dotextwidths(JNIEnv* env, Paint* paint, TypefaceImpl* typeface, const jchar text[], int count,
Raph Levien1a73f7322014-01-30 16:06:28 -0800652 jfloatArray widths, jint bidiFlags) {
Fabrice Di Meglio6ab90ed2011-08-08 16:19:38 -0700653 NPE_CHECK_RETURN_ZERO(env, paint);
654 NPE_CHECK_RETURN_ZERO(env, text);
655
656 if (count < 0 || !widths) {
657 doThrowAIOOBE(env);
658 return 0;
659 }
660 if (count == 0) {
661 return 0;
662 }
663 size_t widthsLength = env->GetArrayLength(widths);
664 if ((size_t)count > widthsLength) {
665 doThrowAIOOBE(env);
666 return 0;
667 }
668
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800669 AutoJavaFloatArray autoWidths(env, widths, count);
670 jfloat* widthsArray = autoWidths.ptr();
Fabrice Di Meglio6ab90ed2011-08-08 16:19:38 -0700671
Raph Levien1a73f7322014-01-30 16:06:28 -0800672 Layout layout;
Behdad Esfahbod63c5c782014-07-25 14:54:46 -0400673 MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, text, 0, count, count);
Raph Levien1a73f7322014-01-30 16:06:28 -0800674 layout.getAdvances(widthsArray);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800675
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800676 return count;
677 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700678
Raph Levien1a73f7322014-01-30 16:06:28 -0800679 static jint getTextWidths___CIII_F(JNIEnv* env, jobject clazz, jlong paintHandle, jlong typefaceHandle, jcharArray text,
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000680 jint index, jint count, jint bidiFlags, jfloatArray widths) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400681 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Raph Levien1a73f7322014-01-30 16:06:28 -0800682 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800683 const jchar* textArray = env->GetCharArrayElements(text, NULL);
Raph Levien1a73f7322014-01-30 16:06:28 -0800684 count = dotextwidths(env, paint, typeface, textArray + index, count, widths, bidiFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800685 env->ReleaseCharArrayElements(text, const_cast<jchar*>(textArray),
Elliott Hughes8451b252011-04-07 19:17:57 -0700686 JNI_ABORT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800687 return count;
688 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700689
Raph Levien1a73f7322014-01-30 16:06:28 -0800690 static jint getTextWidths__StringIII_F(JNIEnv* env, jobject clazz, jlong paintHandle, jlong typefaceHandle, jstring text,
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000691 jint start, jint end, jint bidiFlags, jfloatArray widths) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400692 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Raph Levien1a73f7322014-01-30 16:06:28 -0800693 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800694 const jchar* textArray = env->GetStringChars(text, NULL);
Raph Levien1a73f7322014-01-30 16:06:28 -0800695 int count = dotextwidths(env, paint, typeface, textArray + start, end - start, widths, bidiFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800696 env->ReleaseStringChars(text, textArray);
697 return count;
698 }
Doug Felt0c702b82010-05-14 10:55:42 -0700699
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400700 static jfloat doTextRunAdvances(JNIEnv *env, Paint *paint, TypefaceImpl* typeface, const jchar *text,
Raph Levien051910b2014-06-15 18:25:29 -0700701 jint start, jint count, jint contextCount, jboolean isRtl,
Doug Felt0c702b82010-05-14 10:55:42 -0700702 jfloatArray advances, jint advancesIndex) {
Fabrice Di Meglio6ab90ed2011-08-08 16:19:38 -0700703 NPE_CHECK_RETURN_ZERO(env, paint);
704 NPE_CHECK_RETURN_ZERO(env, text);
705
706 if ((start | count | contextCount | advancesIndex) < 0 || contextCount < count) {
707 doThrowAIOOBE(env);
708 return 0;
709 }
710 if (count == 0) {
711 return 0;
712 }
713 if (advances) {
714 size_t advancesLength = env->GetArrayLength(advances);
715 if ((size_t)count > advancesLength) {
716 doThrowAIOOBE(env);
717 return 0;
718 }
719 }
Victoria Lease3af2a372014-03-17 16:03:28 -0700720 jfloat* advancesArray = new jfloat[count];
Fabrice Di Meglio6ab90ed2011-08-08 16:19:38 -0700721 jfloat totalAdvance = 0;
Doug Felt0c702b82010-05-14 10:55:42 -0700722
Raph Levien051910b2014-06-15 18:25:29 -0700723 int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
724
Raph Levien1a73f7322014-01-30 16:06:28 -0800725 Layout layout;
Behdad Esfahbod63c5c782014-07-25 14:54:46 -0400726 MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, text, start, count, contextCount);
Raph Levien1a73f7322014-01-30 16:06:28 -0800727 layout.getAdvances(advancesArray);
728 totalAdvance = layout.getAdvance();
Doug Felt0c702b82010-05-14 10:55:42 -0700729
730 if (advances != NULL) {
731 env->SetFloatArrayRegion(advances, advancesIndex, count, advancesArray);
732 }
Victoria Lease3af2a372014-03-17 16:03:28 -0700733 delete [] advancesArray;
Doug Felt0c702b82010-05-14 10:55:42 -0700734 return totalAdvance;
735 }
736
Raph Levien051910b2014-06-15 18:25:29 -0700737 static jfloat getTextRunAdvances___CIIIIZ_FI(JNIEnv* env, jobject clazz, jlong paintHandle,
Raph Levien1a73f7322014-01-30 16:06:28 -0800738 jlong typefaceHandle,
Doug Felt0c702b82010-05-14 10:55:42 -0700739 jcharArray text, jint index, jint count, jint contextIndex, jint contextCount,
Raph Levien051910b2014-06-15 18:25:29 -0700740 jboolean isRtl, jfloatArray advances, jint advancesIndex) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400741 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Raph Levien1a73f7322014-01-30 16:06:28 -0800742 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
Doug Felt0c702b82010-05-14 10:55:42 -0700743 jchar* textArray = env->GetCharArrayElements(text, NULL);
Raph Levien1a73f7322014-01-30 16:06:28 -0800744 jfloat result = doTextRunAdvances(env, paint, typeface, textArray + contextIndex,
Raph Levien051910b2014-06-15 18:25:29 -0700745 index - contextIndex, count, contextCount, isRtl, advances, advancesIndex);
Doug Felt0c702b82010-05-14 10:55:42 -0700746 env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
747 return result;
748 }
749
Raph Levien051910b2014-06-15 18:25:29 -0700750 static jfloat getTextRunAdvances__StringIIIIZ_FI(JNIEnv* env, jobject clazz, jlong paintHandle,
Raph Levien1a73f7322014-01-30 16:06:28 -0800751 jlong typefaceHandle,
Raph Levien051910b2014-06-15 18:25:29 -0700752 jstring text, jint start, jint end, jint contextStart, jint contextEnd, jboolean isRtl,
Fabrice Di Meglio665f02c2013-03-20 14:56:05 -0700753 jfloatArray advances, jint advancesIndex) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400754 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Raph Levien1a73f7322014-01-30 16:06:28 -0800755 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
Doug Felt0c702b82010-05-14 10:55:42 -0700756 const jchar* textArray = env->GetStringChars(text, NULL);
Raph Levien1a73f7322014-01-30 16:06:28 -0800757 jfloat result = doTextRunAdvances(env, paint, typeface, textArray + contextStart,
Raph Levien051910b2014-06-15 18:25:29 -0700758 start - contextStart, end - start, contextEnd - contextStart, isRtl,
Fabrice Di Meglio665f02c2013-03-20 14:56:05 -0700759 advances, advancesIndex);
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -0700760 env->ReleaseStringChars(text, textArray);
761 return result;
762 }
763
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400764 static jint doTextRunCursor(JNIEnv *env, Paint* paint, const jchar *text, jint start,
Fabrice Di Meglioa4bf8112013-03-15 11:22:29 -0700765 jint count, jint flags, jint offset, jint opt) {
Raph Leviene368b6b2014-06-15 17:37:57 -0700766 GraphemeBreak::MoveOpt moveOpt = GraphemeBreak::MoveOpt(opt);
767 size_t result = GraphemeBreak::getTextRunCursor(text, start, count, offset, moveOpt);
768 return static_cast<jint>(result);
Doug Felt0c702b82010-05-14 10:55:42 -0700769 }
770
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000771 static jint getTextRunCursor___C(JNIEnv* env, jobject clazz, jlong paintHandle, jcharArray text,
Raph Levien051910b2014-06-15 18:25:29 -0700772 jint contextStart, jint contextCount, jint dir, jint offset, jint cursorOpt) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400773 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Doug Felt0c702b82010-05-14 10:55:42 -0700774 jchar* textArray = env->GetCharArrayElements(text, NULL);
Raph Levien051910b2014-06-15 18:25:29 -0700775 jint result = doTextRunCursor(env, paint, textArray, contextStart, contextCount, dir,
Doug Felt0c702b82010-05-14 10:55:42 -0700776 offset, cursorOpt);
777 env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
778 return result;
779 }
780
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000781 static jint getTextRunCursor__String(JNIEnv* env, jobject clazz, jlong paintHandle, jstring text,
Raph Levien051910b2014-06-15 18:25:29 -0700782 jint contextStart, jint contextEnd, jint dir, jint offset, jint cursorOpt) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400783 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Doug Felt0c702b82010-05-14 10:55:42 -0700784 const jchar* textArray = env->GetStringChars(text, NULL);
785 jint result = doTextRunCursor(env, paint, textArray, contextStart,
Raph Levien051910b2014-06-15 18:25:29 -0700786 contextEnd - contextStart, dir, offset, cursorOpt);
Doug Felt0c702b82010-05-14 10:55:42 -0700787 env->ReleaseStringChars(text, textArray);
788 return result;
789 }
790
Raph Levienf2114d52014-06-01 15:54:47 -0700791 class GetTextFunctor {
792 public:
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400793 GetTextFunctor(const Layout& layout, SkPath* path, jfloat x, jfloat y, Paint* paint,
Raph Levienf2114d52014-06-01 15:54:47 -0700794 uint16_t* glyphs, SkPoint* pos)
795 : layout(layout), path(path), x(x), y(y), paint(paint), glyphs(glyphs), pos(pos) {
796 }
797
Raph Levien1fc0fa82014-06-06 18:05:22 -0700798 void operator()(size_t start, size_t end) {
Raph Levienf2114d52014-06-01 15:54:47 -0700799 for (size_t i = start; i < end; i++) {
800 glyphs[i] = layout.getGlyphId(i);
801 pos[i].fX = x + layout.getX(i);
802 pos[i].fY = y + layout.getY(i);
803 }
Raph Levienf2114d52014-06-01 15:54:47 -0700804 if (start == 0) {
805 paint->getPosTextPath(glyphs + start, (end - start) << 1, pos + start, path);
806 } else {
807 paint->getPosTextPath(glyphs + start, (end - start) << 1, pos + start, &tmpPath);
808 path->addPath(tmpPath);
809 }
810 }
811 private:
812 const Layout& layout;
813 SkPath* path;
814 jfloat x;
815 jfloat y;
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400816 Paint* paint;
Raph Levienf2114d52014-06-01 15:54:47 -0700817 uint16_t* glyphs;
818 SkPoint* pos;
819 SkPath tmpPath;
820 };
Raph Levienf2114d52014-06-01 15:54:47 -0700821
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400822 static void getTextPath(JNIEnv* env, Paint* paint, TypefaceImpl* typeface, const jchar* text,
Raph Levienf2114d52014-06-01 15:54:47 -0700823 jint count, jint bidiFlags, jfloat x, jfloat y, SkPath* path) {
Raph Levienf2114d52014-06-01 15:54:47 -0700824 Layout layout;
Behdad Esfahbod63c5c782014-07-25 14:54:46 -0400825 MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, text, 0, count, count);
Raph Levienf2114d52014-06-01 15:54:47 -0700826 size_t nGlyphs = layout.nGlyphs();
827 uint16_t* glyphs = new uint16_t[nGlyphs];
828 SkPoint* pos = new SkPoint[nGlyphs];
829
830 x += MinikinUtils::xOffsetForTextAlign(paint, layout);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400831 Paint::Align align = paint->getTextAlign();
832 paint->setTextAlign(Paint::kLeft_Align);
833 paint->setTextEncoding(Paint::kGlyphID_TextEncoding);
Raph Levienf2114d52014-06-01 15:54:47 -0700834 GetTextFunctor f(layout, path, x, y, paint, glyphs, pos);
Raph Levien1fc0fa82014-06-06 18:05:22 -0700835 MinikinUtils::forFontRun(layout, paint, f);
Raph Levienf2114d52014-06-01 15:54:47 -0700836 paint->setTextAlign(align);
837 delete[] glyphs;
838 delete[] pos;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800839 }
Doug Feltf7cb1f72010-07-01 16:20:43 -0700840
Raph Levienf2114d52014-06-01 15:54:47 -0700841 static void getTextPath___C(JNIEnv* env, jobject clazz, jlong paintHandle,
842 jlong typefaceHandle, jint bidiFlags,
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000843 jcharArray text, jint index, jint count, jfloat x, jfloat y, jlong pathHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400844 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Raph Levienf2114d52014-06-01 15:54:47 -0700845 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000846 SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
Doug Feltf7cb1f72010-07-01 16:20:43 -0700847 const jchar* textArray = env->GetCharArrayElements(text, NULL);
Raph Levienf2114d52014-06-01 15:54:47 -0700848 getTextPath(env, paint, typeface, textArray + index, count, bidiFlags, x, y, path);
Doug Feltf7cb1f72010-07-01 16:20:43 -0700849 env->ReleaseCharArrayElements(text, const_cast<jchar*>(textArray), JNI_ABORT);
850 }
851
Raph Levienf2114d52014-06-01 15:54:47 -0700852 static void getTextPath__String(JNIEnv* env, jobject clazz, jlong paintHandle,
853 jlong typefaceHandle, jint bidiFlags,
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000854 jstring text, jint start, jint end, jfloat x, jfloat y, jlong pathHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400855 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Raph Levienf2114d52014-06-01 15:54:47 -0700856 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000857 SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800858 const jchar* textArray = env->GetStringChars(text, NULL);
Raph Levienf2114d52014-06-01 15:54:47 -0700859 getTextPath(env, paint, typeface, textArray + start, end - start, bidiFlags, x, y, path);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800860 env->ReleaseStringChars(text, textArray);
861 }
Doug Feltf7cb1f72010-07-01 16:20:43 -0700862
Derek Sollenbergerc29a0a42014-03-31 13:52:39 -0400863 static void setShadowLayer(JNIEnv* env, jobject clazz, jlong paintHandle, jfloat radius,
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000864 jfloat dx, jfloat dy, jint color) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400865 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800866 if (radius <= 0) {
867 paint->setLooper(NULL);
868 }
869 else {
Derek Sollenbergerc29a0a42014-03-31 13:52:39 -0400870 SkScalar sigma = android::uirenderer::Blur::convertRadiusToSigma(radius);
Victoria Lease49f0db32014-05-19 16:00:17 -0700871 paint->setLooper(SkBlurDrawLooper::Create((SkColor)color, sigma, dx, dy))->unref();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800872 }
873 }
874
Derek Sollenbergerc29a0a42014-03-31 13:52:39 -0400875 static jboolean hasShadowLayer(JNIEnv* env, jobject clazz, jlong paintHandle) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400876 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Derek Sollenbergerc29a0a42014-03-31 13:52:39 -0400877 return paint->getLooper() && paint->getLooper()->asABlurShadow(NULL);
878 }
879
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400880 static int breakText(JNIEnv* env, const Paint& paint, TypefaceImpl* typeface, const jchar text[],
Victoria Lease626d3c22013-03-27 15:35:53 -0700881 int count, float maxWidth, jint bidiFlags, jfloatArray jmeasured,
Derek Sollenberger57c4fed2014-10-08 09:23:32 -0400882 const bool forwardScan) {
Anish Athalyea7aa1b02014-06-12 12:53:09 -0700883 size_t measuredCount = 0;
884 float measured = 0;
885
Anish Athalyea7aa1b02014-06-12 12:53:09 -0700886 Layout layout;
Behdad Esfahbod63c5c782014-07-25 14:54:46 -0400887 MinikinUtils::doLayout(&layout, &paint, bidiFlags, typeface, text, 0, count, count);
Anish Athalyea7aa1b02014-06-12 12:53:09 -0700888 float* advances = new float[count];
889 layout.getAdvances(advances);
Derek Sollenberger57c4fed2014-10-08 09:23:32 -0400890
Anish Athalyea7aa1b02014-06-12 12:53:09 -0700891 for (int i = 0; i < count; i++) {
892 // traverse in the given direction
893 int index = forwardScan ? i : (count - i - 1);
894 float width = advances[index];
895 if (measured + width > maxWidth) {
896 break;
897 }
898 // properly handle clusters when scanning backwards
899 if (forwardScan || width != 0.0f) {
900 measuredCount = i + 1;
901 }
902 measured += width;
903 }
904 delete[] advances;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800905
906 if (jmeasured && env->GetArrayLength(jmeasured) > 0) {
907 AutoJavaFloatArray autoMeasured(env, jmeasured, 1);
908 jfloat* array = autoMeasured.ptr();
Anish Athalyea7aa1b02014-06-12 12:53:09 -0700909 array[0] = measured;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800910 }
Anish Athalyea7aa1b02014-06-12 12:53:09 -0700911 return measuredCount;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800912 }
913
Anish Athalyea7aa1b02014-06-12 12:53:09 -0700914 static jint breakTextC(JNIEnv* env, jobject clazz, jlong paintHandle, jlong typefaceHandle, jcharArray jtext,
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000915 jint index, jint count, jfloat maxWidth, jint bidiFlags, jfloatArray jmeasuredWidth) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800916 NPE_CHECK_RETURN_ZERO(env, jtext);
917
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400918 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Anish Athalyea7aa1b02014-06-12 12:53:09 -0700919 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
920
Derek Sollenberger57c4fed2014-10-08 09:23:32 -0400921 bool forwardTextDirection;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800922 if (count < 0) {
Derek Sollenberger57c4fed2014-10-08 09:23:32 -0400923 forwardTextDirection = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800924 count = -count;
925 }
926 else {
Derek Sollenberger57c4fed2014-10-08 09:23:32 -0400927 forwardTextDirection = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800928 }
929
930 if ((index < 0) || (index + count > env->GetArrayLength(jtext))) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700931 doThrowAIOOBE(env);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800932 return 0;
933 }
934
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800935 const jchar* text = env->GetCharArrayElements(jtext, NULL);
Anish Athalyea7aa1b02014-06-12 12:53:09 -0700936 count = breakText(env, *paint, typeface, text + index, count, maxWidth,
Derek Sollenberger57c4fed2014-10-08 09:23:32 -0400937 bidiFlags, jmeasuredWidth, forwardTextDirection);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800938 env->ReleaseCharArrayElements(jtext, const_cast<jchar*>(text),
939 JNI_ABORT);
940 return count;
941 }
942
Anish Athalyea7aa1b02014-06-12 12:53:09 -0700943 static jint breakTextS(JNIEnv* env, jobject clazz, jlong paintHandle, jlong typefaceHandle, jstring jtext,
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000944 jboolean forwards, jfloat maxWidth, jint bidiFlags, jfloatArray jmeasuredWidth) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800945 NPE_CHECK_RETURN_ZERO(env, jtext);
946
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400947 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Anish Athalyea7aa1b02014-06-12 12:53:09 -0700948 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
949
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800950 int count = env->GetStringLength(jtext);
951 const jchar* text = env->GetStringChars(jtext, NULL);
Derek Sollenberger57c4fed2014-10-08 09:23:32 -0400952 count = breakText(env, *paint, typeface, text, count, maxWidth, bidiFlags, jmeasuredWidth, forwards);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800953 env->ReleaseStringChars(jtext, text);
954 return count;
955 }
956
Raph Levien854363e2014-06-03 19:56:05 -0700957 static void doTextBounds(JNIEnv* env, const jchar* text, int count, jobject bounds,
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400958 const Paint& paint, TypefaceImpl* typeface, jint bidiFlags) {
Romain Guy059e12c2012-11-28 17:35:51 -0800959 SkRect r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800960 SkIRect ir;
Elliott Hughes8451b252011-04-07 19:17:57 -0700961
Raph Levien854363e2014-06-03 19:56:05 -0700962 Layout layout;
Behdad Esfahbod63c5c782014-07-25 14:54:46 -0400963 MinikinUtils::doLayout(&layout, &paint, bidiFlags, typeface, text, 0, count, count);
Raph Levien854363e2014-06-03 19:56:05 -0700964 MinikinRect rect;
965 layout.getBounds(&rect);
966 r.fLeft = rect.mLeft;
967 r.fTop = rect.mTop;
968 r.fRight = rect.mRight;
969 r.fBottom = rect.mBottom;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800970 r.roundOut(&ir);
971 GraphicsJNI::irect_to_jrect(ir, env, bounds);
972 }
973
Raph Levien854363e2014-06-03 19:56:05 -0700974 static void getStringBounds(JNIEnv* env, jobject, jlong paintHandle, jlong typefaceHandle,
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000975 jstring text, jint start, jint end, jint bidiFlags, jobject bounds) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400976 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);;
Raph Levien854363e2014-06-03 19:56:05 -0700977 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800978 const jchar* textArray = env->GetStringChars(text, NULL);
Raph Levien854363e2014-06-03 19:56:05 -0700979 doTextBounds(env, textArray + start, end - start, bounds, *paint, typeface, bidiFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800980 env->ReleaseStringChars(text, textArray);
981 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700982
Raph Levien854363e2014-06-03 19:56:05 -0700983 static void getCharArrayBounds(JNIEnv* env, jobject, jlong paintHandle, jlong typefaceHandle,
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000984 jcharArray text, jint index, jint count, jint bidiFlags, jobject bounds) {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400985 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
Raph Levien854363e2014-06-03 19:56:05 -0700986 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800987 const jchar* textArray = env->GetCharArrayElements(text, NULL);
Raph Levien854363e2014-06-03 19:56:05 -0700988 doTextBounds(env, textArray + index, count, bounds, *paint, typeface, bidiFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800989 env->ReleaseCharArrayElements(text, const_cast<jchar*>(textArray),
990 JNI_ABORT);
991 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700992
Raph Levienf7f969e62015-04-01 14:41:21 -0700993 static jboolean layoutContainsNotdef(const Layout& layout) {
994 for (size_t i = 0; i < layout.nGlyphs(); i++) {
995 if (layout.getGlyphId(i) == 0) {
996 return true;
997 }
998 }
999 return false;
1000 }
1001
1002 static jboolean hasGlyphVariation(const Paint* paint, TypefaceImpl* typeface, jint bidiFlags,
1003 const jchar* chars, size_t size) {
1004 // TODO: query font for whether character has variation selector; requires a corresponding
1005 // function in Minikin.
1006 return false;
1007 }
1008
1009 static jboolean hasGlyph(JNIEnv *env, jclass, jlong paintHandle, jlong typefaceHandle,
1010 jint bidiFlags, jstring string) {
1011 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
1012 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
1013 ScopedStringChars str(env, string);
1014
1015 /* start by rejecting variation selectors (not supported yet) */
1016 size_t nChars = 0;
1017 for (size_t i = 0; i < str.size(); i++) {
1018 jchar c = str[i];
1019 if (0xDC00 <= c && c <= 0xDFFF) {
1020 // invalid UTF-16, unpaired trailing surrogate
1021 return false;
1022 } else if (0xD800 <= c && c <= 0xDBFF) {
1023 if (i + 1 == str.size()) {
1024 // invalid UTF-16, unpaired leading surrogate at end of string
1025 return false;
1026 }
1027 i++;
1028 jchar c2 = str[i];
1029 if (!(0xDC00 <= c2 && c2 <= 0xDFFF)) {
1030 // invalid UTF-16, unpaired leading surrogate
1031 return false;
1032 }
1033 // UTF-16 encoding of range U+E0100..U+E01EF is DB40 DD00 .. DB40 DDEF
1034 if (c == 0xDB40 && 0xDD00 <= c2 && c2 <= 0xDDEF) {
1035 return hasGlyphVariation(paint, typeface, bidiFlags, str.get(), str.size());
1036 }
1037 } else if (0xFE00 <= c && c <= 0xFE0F) {
1038 return hasGlyphVariation(paint, typeface, bidiFlags, str.get(), str.size());
1039 }
1040 nChars++;
1041 }
1042 Layout layout;
1043 MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, str.get(), 0, str.size(),
1044 str.size());
1045 size_t nGlyphs = layout.nGlyphs();
1046 if (nGlyphs != 1 && nChars > 1) {
1047 // multiple-character input, and was not a ligature
1048 // TODO: handle ZWJ/ZWNJ characters specially so we can detect certain ligatures
1049 // in joining scripts, such as Arabic and Mongolian.
1050 return false;
1051 }
1052 return nGlyphs > 0 && !layoutContainsNotdef(layout);
1053 }
1054
Raph Leviena027ec52015-04-06 16:21:59 -07001055 static jfloat doRunAdvance(const Paint* paint, TypefaceImpl* typeface, const jchar buf[],
1056 jint start, jint count, jint bufSize, jboolean isRtl, jint offset) {
1057 Layout layout;
1058 int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
1059 MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, buf, start, count, bufSize);
1060 return getRunAdvance(layout, buf, start, count, offset);
1061 }
1062
1063 static jfloat getRunAdvance___CIIIIZI_F(JNIEnv *env, jclass, jlong paintHandle,
1064 jlong typefaceHandle, jcharArray text, jint start, jint end, jint contextStart,
1065 jint contextEnd, jboolean isRtl, jint offset) {
1066 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
1067 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
John Reckc6024cd2015-07-10 10:55:49 -07001068 jchar* textArray = (jchar*) env->GetPrimitiveArrayCritical(text, NULL);
Raph Leviena027ec52015-04-06 16:21:59 -07001069 jfloat result = doRunAdvance(paint, typeface, textArray + contextStart,
Raph Levien36ff86c2015-06-03 10:58:33 -07001070 start - contextStart, end - start, contextEnd - contextStart, isRtl,
1071 offset - contextStart);
John Reckc6024cd2015-07-10 10:55:49 -07001072 env->ReleasePrimitiveArrayCritical(text, textArray, JNI_ABORT);
Raph Leviena027ec52015-04-06 16:21:59 -07001073 return result;
1074 }
1075
1076 static jint doOffsetForAdvance(const Paint* paint, TypefaceImpl* typeface, const jchar buf[],
1077 jint start, jint count, jint bufSize, jboolean isRtl, jfloat advance) {
1078 Layout layout;
1079 int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
1080 MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, buf, start, count, bufSize);
1081 return getOffsetForAdvance(layout, buf, start, count, advance);
1082 }
1083 static jint getOffsetForAdvance___CIIIIZF_I(JNIEnv *env, jclass, jlong paintHandle,
1084 jlong typefaceHandle, jcharArray text, jint start, jint end, jint contextStart,
1085 jint contextEnd, jboolean isRtl, jfloat advance) {
1086 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
1087 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
John Reckc6024cd2015-07-10 10:55:49 -07001088 jchar* textArray = (jchar*) env->GetPrimitiveArrayCritical(text, NULL);
Raph Leviena027ec52015-04-06 16:21:59 -07001089 jint result = doOffsetForAdvance(paint, typeface, textArray + contextStart,
1090 start - contextStart, end - start, contextEnd - contextStart, isRtl, advance);
1091 result += contextStart;
John Reckc6024cd2015-07-10 10:55:49 -07001092 env->ReleasePrimitiveArrayCritical(text, textArray, JNI_ABORT);
Raph Leviena027ec52015-04-06 16:21:59 -07001093 return result;
1094 }
1095
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001096};
1097
1098static JNINativeMethod methods[] = {
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -04001099 {"finalizer", "(J)V", (void*) PaintGlue::finalizer},
1100 {"native_init","()J", (void*) PaintGlue::init},
1101 {"native_initWithPaint","(J)J", (void*) PaintGlue::initWithPaint},
Chris Craik4136a0a2014-10-07 15:09:46 -07001102
1103 {"native_reset","!(J)V", (void*) PaintGlue::reset},
1104 {"native_set","!(JJ)V", (void*) PaintGlue::assign},
1105 {"getFlags","!()I", (void*) PaintGlue::getFlags},
1106 {"setFlags","!(I)V", (void*) PaintGlue::setFlags},
1107 {"getHinting","!()I", (void*) PaintGlue::getHinting},
1108 {"setHinting","!(I)V", (void*) PaintGlue::setHinting},
1109 {"setAntiAlias","!(Z)V", (void*) PaintGlue::setAntiAlias},
1110 {"setSubpixelText","!(Z)V", (void*) PaintGlue::setSubpixelText},
1111 {"setLinearText","!(Z)V", (void*) PaintGlue::setLinearText},
1112 {"setUnderlineText","!(Z)V", (void*) PaintGlue::setUnderlineText},
1113 {"setStrikeThruText","!(Z)V", (void*) PaintGlue::setStrikeThruText},
1114 {"setFakeBoldText","!(Z)V", (void*) PaintGlue::setFakeBoldText},
1115 {"setFilterBitmap","!(Z)V", (void*) PaintGlue::setFilterBitmap},
1116 {"setDither","!(Z)V", (void*) PaintGlue::setDither},
1117 {"native_getStyle","!(J)I", (void*) PaintGlue::getStyle},
1118 {"native_setStyle","!(JI)V", (void*) PaintGlue::setStyle},
1119 {"getColor","!()I", (void*) PaintGlue::getColor},
1120 {"setColor","!(I)V", (void*) PaintGlue::setColor},
1121 {"getAlpha","!()I", (void*) PaintGlue::getAlpha},
1122 {"setAlpha","!(I)V", (void*) PaintGlue::setAlpha},
1123 {"getStrokeWidth","!()F", (void*) PaintGlue::getStrokeWidth},
1124 {"setStrokeWidth","!(F)V", (void*) PaintGlue::setStrokeWidth},
1125 {"getStrokeMiter","!()F", (void*) PaintGlue::getStrokeMiter},
1126 {"setStrokeMiter","!(F)V", (void*) PaintGlue::setStrokeMiter},
1127 {"native_getStrokeCap","!(J)I", (void*) PaintGlue::getStrokeCap},
1128 {"native_setStrokeCap","!(JI)V", (void*) PaintGlue::setStrokeCap},
1129 {"native_getStrokeJoin","!(J)I", (void*) PaintGlue::getStrokeJoin},
1130 {"native_setStrokeJoin","!(JI)V", (void*) PaintGlue::setStrokeJoin},
1131 {"native_getFillPath","!(JJJ)Z", (void*) PaintGlue::getFillPath},
1132 {"native_setShader","!(JJ)J", (void*) PaintGlue::setShader},
1133 {"native_setColorFilter","!(JJ)J", (void*) PaintGlue::setColorFilter},
1134 {"native_setXfermode","!(JJ)J", (void*) PaintGlue::setXfermode},
1135 {"native_setPathEffect","!(JJ)J", (void*) PaintGlue::setPathEffect},
1136 {"native_setMaskFilter","!(JJ)J", (void*) PaintGlue::setMaskFilter},
1137 {"native_setTypeface","!(JJ)J", (void*) PaintGlue::setTypeface},
1138 {"native_setRasterizer","!(JJ)J", (void*) PaintGlue::setRasterizer},
1139 {"native_getTextAlign","!(J)I", (void*) PaintGlue::getTextAlign},
1140 {"native_setTextAlign","!(JI)V", (void*) PaintGlue::setTextAlign},
1141 {"native_setTextLocale","!(JLjava/lang/String;)V", (void*) PaintGlue::setTextLocale},
1142 {"isElegantTextHeight","!()Z", (void*) PaintGlue::isElegantTextHeight},
1143 {"setElegantTextHeight","!(Z)V", (void*) PaintGlue::setElegantTextHeight},
1144 {"getTextSize","!()F", (void*) PaintGlue::getTextSize},
1145 {"setTextSize","!(F)V", (void*) PaintGlue::setTextSize},
1146 {"getTextScaleX","!()F", (void*) PaintGlue::getTextScaleX},
1147 {"setTextScaleX","!(F)V", (void*) PaintGlue::setTextScaleX},
1148 {"getTextSkewX","!()F", (void*) PaintGlue::getTextSkewX},
1149 {"setTextSkewX","!(F)V", (void*) PaintGlue::setTextSkewX},
1150 {"native_getLetterSpacing","!(J)F", (void*) PaintGlue::getLetterSpacing},
1151 {"native_setLetterSpacing","!(JF)V", (void*) PaintGlue::setLetterSpacing},
Raph Leviena027ec52015-04-06 16:21:59 -07001152 {"native_setFontFeatureSettings","(JLjava/lang/String;)V",
1153 (void*) PaintGlue::setFontFeatureSettings},
Raph Levien210a1892015-03-09 14:42:14 -07001154 {"native_getHyphenEdit", "!(J)I", (void*) PaintGlue::getHyphenEdit},
1155 {"native_setHyphenEdit", "!(JI)V", (void*) PaintGlue::setHyphenEdit},
Chris Craik4136a0a2014-10-07 15:09:46 -07001156 {"ascent","!()F", (void*) PaintGlue::ascent},
1157 {"descent","!()F", (void*) PaintGlue::descent},
1158
John Reckc6024cd2015-07-10 10:55:49 -07001159 {"getFontMetrics", "!(Landroid/graphics/Paint$FontMetrics;)F",
Raph Leviena027ec52015-04-06 16:21:59 -07001160 (void*)PaintGlue::getFontMetrics},
John Reckc6024cd2015-07-10 10:55:49 -07001161 {"getFontMetricsInt", "!(Landroid/graphics/Paint$FontMetricsInt;)I",
Raph Leviena027ec52015-04-06 16:21:59 -07001162 (void*)PaintGlue::getFontMetricsInt},
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -04001163 {"native_measureText","([CIII)F", (void*) PaintGlue::measureText_CIII},
1164 {"native_measureText","(Ljava/lang/String;I)F", (void*) PaintGlue::measureText_StringI},
1165 {"native_measureText","(Ljava/lang/String;III)F", (void*) PaintGlue::measureText_StringIII},
1166 {"native_breakText","(JJ[CIIFI[F)I", (void*) PaintGlue::breakTextC},
1167 {"native_breakText","(JJLjava/lang/String;ZFI[F)I", (void*) PaintGlue::breakTextS},
1168 {"native_getTextWidths","(JJ[CIII[F)I", (void*) PaintGlue::getTextWidths___CIII_F},
Raph Leviena027ec52015-04-06 16:21:59 -07001169 {"native_getTextWidths","(JJLjava/lang/String;III[F)I",
1170 (void*) PaintGlue::getTextWidths__StringIII_F},
Raph Levien051910b2014-06-15 18:25:29 -07001171 {"native_getTextRunAdvances","(JJ[CIIIIZ[FI)F",
Raph Leviena027ec52015-04-06 16:21:59 -07001172 (void*) PaintGlue::getTextRunAdvances___CIIIIZ_FI},
Raph Levien051910b2014-06-15 18:25:29 -07001173 {"native_getTextRunAdvances","(JJLjava/lang/String;IIIIZ[FI)F",
Raph Leviena027ec52015-04-06 16:21:59 -07001174 (void*) PaintGlue::getTextRunAdvances__StringIIIIZ_FI},
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001175
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -04001176 {"native_getTextRunCursor", "(J[CIIIII)I", (void*) PaintGlue::getTextRunCursor___C},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001177 {"native_getTextRunCursor", "(JLjava/lang/String;IIIII)I",
Raph Leviena027ec52015-04-06 16:21:59 -07001178 (void*) PaintGlue::getTextRunCursor__String},
1179 {"native_getTextPath", "(JJI[CIIFFJ)V", (void*) PaintGlue::getTextPath___C},
1180 {"native_getTextPath", "(JJILjava/lang/String;IIFFJ)V", (void*) PaintGlue::getTextPath__String},
Raph Levien854363e2014-06-03 19:56:05 -07001181 {"nativeGetStringBounds", "(JJLjava/lang/String;IIILandroid/graphics/Rect;)V",
Raph Leviena027ec52015-04-06 16:21:59 -07001182 (void*) PaintGlue::getStringBounds },
Raph Levien854363e2014-06-03 19:56:05 -07001183 {"nativeGetCharArrayBounds", "(JJ[CIIILandroid/graphics/Rect;)V",
Raph Leviena027ec52015-04-06 16:21:59 -07001184 (void*) PaintGlue::getCharArrayBounds },
1185 {"native_hasGlyph", "(JJILjava/lang/String;)Z", (void*) PaintGlue::hasGlyph },
1186 {"native_getRunAdvance", "(JJ[CIIIIZI)F", (void*) PaintGlue::getRunAdvance___CIIIIZI_F},
1187 {"native_getOffsetForAdvance", "(JJ[CIIIIZF)I",
1188 (void*) PaintGlue::getOffsetForAdvance___CIIIIZF_I},
Chris Craik4136a0a2014-10-07 15:09:46 -07001189
1190 {"native_setShadowLayer", "!(JFFFI)V", (void*)PaintGlue::setShadowLayer},
1191 {"native_hasShadowLayer", "!(J)Z", (void*)PaintGlue::hasShadowLayer}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001192};
1193
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001194int register_android_graphics_Paint(JNIEnv* env) {
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001195 gFontMetrics_class = FindClassOrDie(env, "android/graphics/Paint$FontMetrics");
1196 gFontMetrics_class = MakeGlobalRefOrDie(env, gFontMetrics_class);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001197
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001198 gFontMetrics_fieldID.top = GetFieldIDOrDie(env, gFontMetrics_class, "top", "F");
1199 gFontMetrics_fieldID.ascent = GetFieldIDOrDie(env, gFontMetrics_class, "ascent", "F");
1200 gFontMetrics_fieldID.descent = GetFieldIDOrDie(env, gFontMetrics_class, "descent", "F");
1201 gFontMetrics_fieldID.bottom = GetFieldIDOrDie(env, gFontMetrics_class, "bottom", "F");
1202 gFontMetrics_fieldID.leading = GetFieldIDOrDie(env, gFontMetrics_class, "leading", "F");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001203
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001204 gFontMetricsInt_class = FindClassOrDie(env, "android/graphics/Paint$FontMetricsInt");
1205 gFontMetricsInt_class = MakeGlobalRefOrDie(env, gFontMetricsInt_class);
Derek Sollenbergerab22c1c2014-09-03 14:12:47 -04001206
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001207 gFontMetricsInt_fieldID.top = GetFieldIDOrDie(env, gFontMetricsInt_class, "top", "I");
1208 gFontMetricsInt_fieldID.ascent = GetFieldIDOrDie(env, gFontMetricsInt_class, "ascent", "I");
1209 gFontMetricsInt_fieldID.descent = GetFieldIDOrDie(env, gFontMetricsInt_class, "descent", "I");
1210 gFontMetricsInt_fieldID.bottom = GetFieldIDOrDie(env, gFontMetricsInt_class, "bottom", "I");
1211 gFontMetricsInt_fieldID.leading = GetFieldIDOrDie(env, gFontMetricsInt_class, "leading", "I");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001212
Andreas Gampe158b6c92014-11-21 14:03:34 -08001213 gPaint_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/Paint"));
1214 gPaint_nativeInstanceID = GetFieldIDOrDie(env, gPaint_class, "mNativePaint", "J");
1215 gPaint_nativeTypefaceID = GetFieldIDOrDie(env, gPaint_class, "mNativeTypeface", "J");
1216
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001217 return RegisterMethodsOrDie(env, "android/graphics/Paint", methods, NELEM(methods));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001218}
1219
1220}