blob: 1167bfe6125ee63d3dbe36cc102e78253b73994b [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"
24#include <android_runtime/AndroidRuntime.h>
Billy Hewlettac1cbaf2012-07-18 09:51:45 -070025#include <ScopedUtfChars.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026
27#include "SkBlurDrawLooper.h"
28#include "SkColorFilter.h"
29#include "SkMaskFilter.h"
30#include "SkRasterizer.h"
31#include "SkShader.h"
32#include "SkTypeface.h"
33#include "SkXfermode.h"
Billy Hewlettac1cbaf2012-07-18 09:51:45 -070034#include "unicode/uloc.h"
Doug Felt0c702b82010-05-14 10:55:42 -070035#include "unicode/ushape.h"
Doug Feltf7cb1f72010-07-01 16:20:43 -070036#include "TextLayout.h"
Doug Felt0c702b82010-05-14 10:55:42 -070037
38// temporary for debugging
Chet Haase5c13d892010-10-08 08:37:55 -070039#include <Caches.h>
Doug Felt0c702b82010-05-14 10:55:42 -070040#include <utils/Log.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041
42namespace android {
43
44struct JMetricsID {
45 jfieldID top;
46 jfieldID ascent;
47 jfieldID descent;
48 jfieldID bottom;
49 jfieldID leading;
50};
51
52static jclass gFontMetrics_class;
53static JMetricsID gFontMetrics_fieldID;
54
55static jclass gFontMetricsInt_class;
56static JMetricsID gFontMetricsInt_fieldID;
57
Mike Reed3d63e012009-07-27 09:50:31 -040058static void defaultSettingsForAndroid(SkPaint* paint) {
Fabrice Di Meglioc511bee82012-01-05 13:30:54 -080059 // GlyphID encoding is required because we are using Harfbuzz shaping
60 paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding);
Derek Sollenbergerd7a80772013-05-28 10:44:26 -040061
62 SkPaintOptionsAndroid paintOpts = paint->getPaintOptionsAndroid();
63 paintOpts.setUseFontFallbacks(true);
64 paint->setPaintOptionsAndroid(paintOpts);
Mike Reed3d63e012009-07-27 09:50:31 -040065}
66
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080067class SkPaintGlue {
68public:
Doug Felt0c702b82010-05-14 10:55:42 -070069 enum MoveOpt {
70 AFTER, AT_OR_AFTER, BEFORE, AT_OR_BEFORE, AT
71 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080072
Ashok Bhat36bef0b2014-01-20 20:08:01 +000073 static void finalizer(JNIEnv* env, jobject clazz, jlong objHandle) {
74 SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080075 delete obj;
76 }
77
Ashok Bhat36bef0b2014-01-20 20:08:01 +000078 static jlong init(JNIEnv* env, jobject clazz) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080079 SkPaint* obj = new SkPaint();
Mike Reed3d63e012009-07-27 09:50:31 -040080 defaultSettingsForAndroid(obj);
Ashok Bhat36bef0b2014-01-20 20:08:01 +000081 return reinterpret_cast<jlong>(obj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082 }
83
Ashok Bhat36bef0b2014-01-20 20:08:01 +000084 static jlong initWithPaint(JNIEnv* env, jobject clazz, jlong paintHandle) {
85 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080086 SkPaint* obj = new SkPaint(*paint);
Ashok Bhat36bef0b2014-01-20 20:08:01 +000087 return reinterpret_cast<jlong>(obj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080088 }
Elliott Hughes8451b252011-04-07 19:17:57 -070089
Ashok Bhat36bef0b2014-01-20 20:08:01 +000090 static void reset(JNIEnv* env, jobject clazz, jlong objHandle) {
91 SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080092 obj->reset();
Mike Reed3d63e012009-07-27 09:50:31 -040093 defaultSettingsForAndroid(obj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080094 }
Elliott Hughes8451b252011-04-07 19:17:57 -070095
Ashok Bhat36bef0b2014-01-20 20:08:01 +000096 static void assign(JNIEnv* env, jobject clazz, jlong dstPaintHandle, jlong srcPaintHandle) {
97 SkPaint* dst = reinterpret_cast<SkPaint*>(dstPaintHandle);
98 const SkPaint* src = reinterpret_cast<SkPaint*>(srcPaintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099 *dst = *src;
100 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700101
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102 static jint getFlags(JNIEnv* env, jobject paint) {
103 NPE_CHECK_RETURN_ZERO(env, paint);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000104 int result;
105 result = GraphicsJNI::getNativePaint(env, paint)->getFlags();
106 return static_cast<jint>(result);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800107 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700108
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109 static void setFlags(JNIEnv* env, jobject paint, jint flags) {
110 NPE_CHECK_RETURN_VOID(env, paint);
111 GraphicsJNI::getNativePaint(env, paint)->setFlags(flags);
112 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700113
Dianne Hackbornf43fa572011-08-12 18:59:39 -0700114 static jint getHinting(JNIEnv* env, jobject paint) {
115 NPE_CHECK_RETURN_ZERO(env, paint);
116 return GraphicsJNI::getNativePaint(env, paint)->getHinting()
117 == SkPaint::kNo_Hinting ? 0 : 1;
118 }
119
120 static void setHinting(JNIEnv* env, jobject paint, jint mode) {
121 NPE_CHECK_RETURN_VOID(env, paint);
122 GraphicsJNI::getNativePaint(env, paint)->setHinting(
Victoria Lease88705382013-06-14 16:15:41 -0700123 mode == 0 ? SkPaint::kNo_Hinting : SkPaint::kNormal_Hinting);
Dianne Hackbornf43fa572011-08-12 18:59:39 -0700124 }
125
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800126 static void setAntiAlias(JNIEnv* env, jobject paint, jboolean aa) {
127 NPE_CHECK_RETURN_VOID(env, paint);
128 GraphicsJNI::getNativePaint(env, paint)->setAntiAlias(aa);
129 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700130
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800131 static void setLinearText(JNIEnv* env, jobject paint, jboolean linearText) {
132 NPE_CHECK_RETURN_VOID(env, paint);
133 GraphicsJNI::getNativePaint(env, paint)->setLinearText(linearText);
134 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700135
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800136 static void setSubpixelText(JNIEnv* env, jobject paint, jboolean subpixelText) {
137 NPE_CHECK_RETURN_VOID(env, paint);
138 GraphicsJNI::getNativePaint(env, paint)->setSubpixelText(subpixelText);
139 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700140
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800141 static void setUnderlineText(JNIEnv* env, jobject paint, jboolean underlineText) {
142 NPE_CHECK_RETURN_VOID(env, paint);
143 GraphicsJNI::getNativePaint(env, paint)->setUnderlineText(underlineText);
144 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700145
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800146 static void setStrikeThruText(JNIEnv* env, jobject paint, jboolean strikeThruText) {
147 NPE_CHECK_RETURN_VOID(env, paint);
148 GraphicsJNI::getNativePaint(env, paint)->setStrikeThruText(strikeThruText);
149 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700150
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800151 static void setFakeBoldText(JNIEnv* env, jobject paint, jboolean fakeBoldText) {
152 NPE_CHECK_RETURN_VOID(env, paint);
153 GraphicsJNI::getNativePaint(env, paint)->setFakeBoldText(fakeBoldText);
154 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700155
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800156 static void setFilterBitmap(JNIEnv* env, jobject paint, jboolean filterBitmap) {
157 NPE_CHECK_RETURN_VOID(env, paint);
Derek Sollenbergerb644a3b2014-01-17 15:45:10 -0500158 GraphicsJNI::getNativePaint(env, paint)->setFilterLevel(
159 filterBitmap ? SkPaint::kLow_FilterLevel : SkPaint::kNone_FilterLevel);
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 setDither(JNIEnv* env, jobject paint, jboolean dither) {
163 NPE_CHECK_RETURN_VOID(env, paint);
164 GraphicsJNI::getNativePaint(env, paint)->setDither(dither);
165 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700166
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000167 static jint getStyle(JNIEnv* env, jobject clazz,jlong objHandle) {
168 SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
169 return static_cast<jint>(obj->getStyle());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800170 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700171
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000172 static void setStyle(JNIEnv* env, jobject clazz, jlong objHandle, jint styleHandle) {
173 SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
174 SkPaint::Style style = static_cast<SkPaint::Style>(styleHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800175 obj->setStyle(style);
176 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700177
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800178 static jint getColor(JNIEnv* env, jobject paint) {
179 NPE_CHECK_RETURN_ZERO(env, paint);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000180 int color;
181 color = GraphicsJNI::getNativePaint(env, paint)->getColor();
182 return static_cast<jint>(color);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800183 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700184
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800185 static jint getAlpha(JNIEnv* env, jobject paint) {
186 NPE_CHECK_RETURN_ZERO(env, paint);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000187 int alpha;
188 alpha = GraphicsJNI::getNativePaint(env, paint)->getAlpha();
189 return static_cast<jint>(alpha);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800190 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700191
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800192 static void setColor(JNIEnv* env, jobject paint, jint color) {
193 NPE_CHECK_RETURN_VOID(env, paint);
194 GraphicsJNI::getNativePaint(env, paint)->setColor(color);
195 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700196
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800197 static void setAlpha(JNIEnv* env, jobject paint, jint a) {
198 NPE_CHECK_RETURN_VOID(env, paint);
199 GraphicsJNI::getNativePaint(env, paint)->setAlpha(a);
200 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700201
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800202 static jfloat getStrokeWidth(JNIEnv* env, jobject paint) {
203 NPE_CHECK_RETURN_ZERO(env, paint);
204 return SkScalarToFloat(GraphicsJNI::getNativePaint(env, paint)->getStrokeWidth());
205 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700206
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800207 static void setStrokeWidth(JNIEnv* env, jobject paint, jfloat width) {
208 NPE_CHECK_RETURN_VOID(env, paint);
209 GraphicsJNI::getNativePaint(env, paint)->setStrokeWidth(SkFloatToScalar(width));
210 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700211
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800212 static jfloat getStrokeMiter(JNIEnv* env, jobject paint) {
213 NPE_CHECK_RETURN_ZERO(env, paint);
214 return SkScalarToFloat(GraphicsJNI::getNativePaint(env, paint)->getStrokeMiter());
215 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700216
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800217 static void setStrokeMiter(JNIEnv* env, jobject paint, jfloat miter) {
218 NPE_CHECK_RETURN_VOID(env, paint);
219 GraphicsJNI::getNativePaint(env, paint)->setStrokeMiter(SkFloatToScalar(miter));
220 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700221
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000222 static jint getStrokeCap(JNIEnv* env, jobject clazz, jlong objHandle) {
223 SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
224 return static_cast<jint>(obj->getStrokeCap());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800225 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700226
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000227 static void setStrokeCap(JNIEnv* env, jobject clazz, jlong objHandle, jint capHandle) {
228 SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
229 SkPaint::Cap cap = static_cast<SkPaint::Cap>(capHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800230 obj->setStrokeCap(cap);
231 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700232
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000233 static jint getStrokeJoin(JNIEnv* env, jobject clazz, jlong objHandle) {
234 SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
235 return static_cast<jint>(obj->getStrokeJoin());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800236 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700237
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000238 static void setStrokeJoin(JNIEnv* env, jobject clazz, jlong objHandle, jint joinHandle) {
239 SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
240 SkPaint::Join join = (SkPaint::Join) joinHandle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800241 obj->setStrokeJoin(join);
242 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700243
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000244 static jboolean getFillPath(JNIEnv* env, jobject clazz, jlong objHandle, jlong srcHandle, jlong dstHandle) {
245 SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
246 SkPath* src = reinterpret_cast<SkPath*>(srcHandle);
247 SkPath* dst = reinterpret_cast<SkPath*>(dstHandle);
248 return obj->getFillPath(*src, dst) ? JNI_TRUE : JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800249 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700250
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000251 static jlong setShader(JNIEnv* env, jobject clazz, jlong objHandle, jlong shaderHandle) {
252 SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
253 SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle);
254 return reinterpret_cast<jlong>(obj->setShader(shader));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800255 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700256
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000257 static jlong setColorFilter(JNIEnv* env, jobject clazz, jlong objHandle, jlong filterHandle) {
258 SkPaint* obj = reinterpret_cast<SkPaint *>(objHandle);
259 SkColorFilter* filter = reinterpret_cast<SkColorFilter *>(filterHandle);
260 return reinterpret_cast<jlong>(obj->setColorFilter(filter));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800261 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700262
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000263 static jlong setXfermode(JNIEnv* env, jobject clazz, jlong objHandle, jlong xfermodeHandle) {
264 SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
265 SkXfermode* xfermode = reinterpret_cast<SkXfermode*>(xfermodeHandle);
266 return reinterpret_cast<jlong>(obj->setXfermode(xfermode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800267 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700268
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000269 static jlong setPathEffect(JNIEnv* env, jobject clazz, jlong objHandle, jlong effectHandle) {
270 SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
271 SkPathEffect* effect = reinterpret_cast<SkPathEffect*>(effectHandle);
272 return reinterpret_cast<jlong>(obj->setPathEffect(effect));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800273 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700274
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000275 static jlong setMaskFilter(JNIEnv* env, jobject clazz, jlong objHandle, jlong maskfilterHandle) {
276 SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
277 SkMaskFilter* maskfilter = reinterpret_cast<SkMaskFilter*>(maskfilterHandle);
278 return reinterpret_cast<jlong>(obj->setMaskFilter(maskfilter));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800279 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700280
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000281 static jlong setTypeface(JNIEnv* env, jobject clazz, jlong objHandle, jlong typefaceHandle) {
Raph Leviena0336302013-05-22 16:16:59 -0700282#ifndef USE_MINIKIN
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000283 SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
284 SkTypeface* typeface = reinterpret_cast<SkTypeface*>(typefaceHandle);
285 return reinterpret_cast<jlong>(obj->setTypeface(typeface));
Raph Leviena0336302013-05-22 16:16:59 -0700286#else
287 // TODO(raph): not yet implemented
288 return NULL;
289#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800290 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700291
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000292 static jlong setRasterizer(JNIEnv* env, jobject clazz, jlong objHandle, jlong rasterizerHandle) {
293 SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
294 SkRasterizer* rasterizer = reinterpret_cast<SkRasterizer*>(rasterizerHandle);
295 return reinterpret_cast<jlong>(obj->setRasterizer(rasterizer));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800296 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700297
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000298 static jint getTextAlign(JNIEnv* env, jobject clazz, jlong objHandle) {
299 SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
300 return static_cast<jint>(obj->getTextAlign());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800301 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700302
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000303 static void setTextAlign(JNIEnv* env, jobject clazz, jlong objHandle, jint alignHandle) {
304 SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
305 SkPaint::Align align = static_cast<SkPaint::Align>(alignHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800306 obj->setTextAlign(align);
307 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700308
Billy Hewlettac1cbaf2012-07-18 09:51:45 -0700309 // generate bcp47 identifier for the supplied locale
310 static void toLanguageTag(char* output, size_t outSize,
311 const char* locale) {
312 if (output == NULL || outSize <= 0) {
313 return;
314 }
315 if (locale == NULL) {
316 output[0] = '\0';
317 return;
318 }
319 char canonicalChars[ULOC_FULLNAME_CAPACITY];
320 UErrorCode uErr = U_ZERO_ERROR;
321 uloc_canonicalize(locale, canonicalChars, ULOC_FULLNAME_CAPACITY,
322 &uErr);
323 if (U_SUCCESS(uErr)) {
324 char likelyChars[ULOC_FULLNAME_CAPACITY];
325 uErr = U_ZERO_ERROR;
326 uloc_addLikelySubtags(canonicalChars, likelyChars,
327 ULOC_FULLNAME_CAPACITY, &uErr);
328 if (U_SUCCESS(uErr)) {
329 uErr = U_ZERO_ERROR;
330 uloc_toLanguageTag(likelyChars, output, outSize, FALSE, &uErr);
331 if (U_SUCCESS(uErr)) {
332 return;
333 } else {
334 ALOGD("uloc_toLanguageTag(\"%s\") failed: %s", likelyChars,
335 u_errorName(uErr));
336 }
337 } else {
338 ALOGD("uloc_addLikelySubtags(\"%s\") failed: %s",
339 canonicalChars, u_errorName(uErr));
340 }
341 } else {
342 ALOGD("uloc_canonicalize(\"%s\") failed: %s", locale,
343 u_errorName(uErr));
344 }
345 // unable to build a proper language identifier
346 output[0] = '\0';
347 }
348
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000349 static void setTextLocale(JNIEnv* env, jobject clazz, jlong objHandle, jstring locale) {
350 SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
Billy Hewlettac1cbaf2012-07-18 09:51:45 -0700351 ScopedUtfChars localeChars(env, locale);
352 char langTag[ULOC_FULLNAME_CAPACITY];
353 toLanguageTag(langTag, ULOC_FULLNAME_CAPACITY, localeChars.c_str());
Derek Sollenbergerd7a80772013-05-28 10:44:26 -0400354
355 SkPaintOptionsAndroid paintOpts = obj->getPaintOptionsAndroid();
356 paintOpts.setLanguage(langTag);
357 obj->setPaintOptionsAndroid(paintOpts);
Fabrice Di Meglio517825f2012-04-06 16:53:48 -0700358 }
359
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800360 static jfloat getTextSize(JNIEnv* env, jobject paint) {
361 NPE_CHECK_RETURN_ZERO(env, paint);
362 return SkScalarToFloat(GraphicsJNI::getNativePaint(env, paint)->getTextSize());
363 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700364
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800365 static void setTextSize(JNIEnv* env, jobject paint, jfloat textSize) {
366 NPE_CHECK_RETURN_VOID(env, paint);
367 GraphicsJNI::getNativePaint(env, paint)->setTextSize(SkFloatToScalar(textSize));
368 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700369
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800370 static jfloat getTextScaleX(JNIEnv* env, jobject paint) {
371 NPE_CHECK_RETURN_ZERO(env, paint);
372 return SkScalarToFloat(GraphicsJNI::getNativePaint(env, paint)->getTextScaleX());
373 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700374
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800375 static void setTextScaleX(JNIEnv* env, jobject paint, jfloat scaleX) {
376 NPE_CHECK_RETURN_VOID(env, paint);
377 GraphicsJNI::getNativePaint(env, paint)->setTextScaleX(SkFloatToScalar(scaleX));
378 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700379
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800380 static jfloat getTextSkewX(JNIEnv* env, jobject paint) {
381 NPE_CHECK_RETURN_ZERO(env, paint);
382 return SkScalarToFloat(GraphicsJNI::getNativePaint(env, paint)->getTextSkewX());
383 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700384
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800385 static void setTextSkewX(JNIEnv* env, jobject paint, jfloat skewX) {
386 NPE_CHECK_RETURN_VOID(env, paint);
387 GraphicsJNI::getNativePaint(env, paint)->setTextSkewX(SkFloatToScalar(skewX));
388 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700389
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800390 static jfloat ascent(JNIEnv* env, jobject paint) {
391 NPE_CHECK_RETURN_ZERO(env, paint);
392 SkPaint::FontMetrics metrics;
393 (void)GraphicsJNI::getNativePaint(env, paint)->getFontMetrics(&metrics);
394 return SkScalarToFloat(metrics.fAscent);
395 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700396
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800397 static jfloat descent(JNIEnv* env, jobject paint) {
398 NPE_CHECK_RETURN_ZERO(env, paint);
399 SkPaint::FontMetrics metrics;
400 (void)GraphicsJNI::getNativePaint(env, paint)->getFontMetrics(&metrics);
401 return SkScalarToFloat(metrics.fDescent);
402 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700403
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800404 static jfloat getFontMetrics(JNIEnv* env, jobject paint, jobject metricsObj) {
405 NPE_CHECK_RETURN_ZERO(env, paint);
406 SkPaint::FontMetrics metrics;
407 SkScalar spacing = GraphicsJNI::getNativePaint(env, paint)->getFontMetrics(&metrics);
408
409 if (metricsObj) {
410 SkASSERT(env->IsInstanceOf(metricsObj, gFontMetrics_class));
411 env->SetFloatField(metricsObj, gFontMetrics_fieldID.top, SkScalarToFloat(metrics.fTop));
412 env->SetFloatField(metricsObj, gFontMetrics_fieldID.ascent, SkScalarToFloat(metrics.fAscent));
413 env->SetFloatField(metricsObj, gFontMetrics_fieldID.descent, SkScalarToFloat(metrics.fDescent));
414 env->SetFloatField(metricsObj, gFontMetrics_fieldID.bottom, SkScalarToFloat(metrics.fBottom));
415 env->SetFloatField(metricsObj, gFontMetrics_fieldID.leading, SkScalarToFloat(metrics.fLeading));
416 }
417 return SkScalarToFloat(spacing);
418 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700419
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800420 static jint getFontMetricsInt(JNIEnv* env, jobject paint, jobject metricsObj) {
421 NPE_CHECK_RETURN_ZERO(env, paint);
422 SkPaint::FontMetrics metrics;
Elliott Hughes8451b252011-04-07 19:17:57 -0700423
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800424 GraphicsJNI::getNativePaint(env, paint)->getFontMetrics(&metrics);
Leon Scroggins46cb9bd2014-03-06 15:36:39 -0500425 int ascent = SkScalarRoundToInt(metrics.fAscent);
426 int descent = SkScalarRoundToInt(metrics.fDescent);
427 int leading = SkScalarRoundToInt(metrics.fLeading);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800428
429 if (metricsObj) {
430 SkASSERT(env->IsInstanceOf(metricsObj, gFontMetricsInt_class));
Leon Scroggins46cb9bd2014-03-06 15:36:39 -0500431 env->SetIntField(metricsObj, gFontMetricsInt_fieldID.top, SkScalarFloorToInt(metrics.fTop));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800432 env->SetIntField(metricsObj, gFontMetricsInt_fieldID.ascent, ascent);
433 env->SetIntField(metricsObj, gFontMetricsInt_fieldID.descent, descent);
Leon Scroggins46cb9bd2014-03-06 15:36:39 -0500434 env->SetIntField(metricsObj, gFontMetricsInt_fieldID.bottom, SkScalarCeilToInt(metrics.fBottom));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800435 env->SetIntField(metricsObj, gFontMetricsInt_fieldID.leading, leading);
436 }
437 return descent - ascent + leading;
438 }
439
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000440 static jfloat measureText_CIII(JNIEnv* env, jobject jpaint, jcharArray text, jint index, jint count,
Victoria Lease626d3c22013-03-27 15:35:53 -0700441 jint bidiFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800442 NPE_CHECK_RETURN_ZERO(env, jpaint);
443 NPE_CHECK_RETURN_ZERO(env, text);
444
445 size_t textLength = env->GetArrayLength(text);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800446 if ((index | count) < 0 || (size_t)(index + count) > textLength) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700447 doThrowAIOOBE(env);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800448 return 0;
449 }
Fabrice Di Meglio6ab90ed2011-08-08 16:19:38 -0700450 if (count == 0) {
451 return 0;
452 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800453
Fabrice Di Meglio4f810c82011-04-19 14:53:58 -0700454 SkPaint* paint = GraphicsJNI::getNativePaint(env, jpaint);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800455 const jchar* textArray = env->GetCharArrayElements(text, NULL);
Fabrice Di Meglio4f810c82011-04-19 14:53:58 -0700456 jfloat result = 0;
Fabrice Di Megliob02d0ca2011-12-08 14:05:44 -0800457
Fabrice Di Meglio8fb50712011-05-13 18:51:21 -0700458 TextLayout::getTextRunAdvances(paint, textArray, index, count, textLength,
Victoria Lease626d3c22013-03-27 15:35:53 -0700459 bidiFlags, NULL /* dont need all advances */, &result);
Fabrice Di Megliob02d0ca2011-12-08 14:05:44 -0800460
Fabrice Di Meglio4f810c82011-04-19 14:53:58 -0700461 env->ReleaseCharArrayElements(text, const_cast<jchar*>(textArray), JNI_ABORT);
462 return result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800463 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700464
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000465 static jfloat measureText_StringIII(JNIEnv* env, jobject jpaint, jstring text, jint start, jint end,
Victoria Lease626d3c22013-03-27 15:35:53 -0700466 jint bidiFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800467 NPE_CHECK_RETURN_ZERO(env, jpaint);
468 NPE_CHECK_RETURN_ZERO(env, text);
Elliott Hughes8451b252011-04-07 19:17:57 -0700469
Fabrice Di Meglio51f383d2011-09-13 15:57:58 -0700470 size_t textLength = env->GetStringLength(text);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800471 int count = end - start;
Fabrice Di Meglio51f383d2011-09-13 15:57:58 -0700472 if ((start | count) < 0 || (size_t)end > textLength) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700473 doThrowAIOOBE(env);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800474 return 0;
475 }
Fabrice Di Meglio6ab90ed2011-08-08 16:19:38 -0700476 if (count == 0) {
477 return 0;
478 }
Fabrice Di Meglio6ab90ed2011-08-08 16:19:38 -0700479
480 const jchar* textArray = env->GetStringChars(text, NULL);
481 SkPaint* paint = GraphicsJNI::getNativePaint(env, jpaint);
Fabrice Di Meglio4f810c82011-04-19 14:53:58 -0700482 jfloat width = 0;
Elliott Hughes8451b252011-04-07 19:17:57 -0700483
Fabrice Di Meglio51f383d2011-09-13 15:57:58 -0700484 TextLayout::getTextRunAdvances(paint, textArray, start, count, textLength,
Victoria Lease626d3c22013-03-27 15:35:53 -0700485 bidiFlags, NULL /* dont need all advances */, &width);
Fabrice Di Meglio4f810c82011-04-19 14:53:58 -0700486
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800487 env->ReleaseStringChars(text, textArray);
488 return width;
489 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700490
Victoria Lease626d3c22013-03-27 15:35:53 -0700491 static jfloat measureText_StringI(JNIEnv* env, jobject jpaint, jstring text, jint bidiFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800492 NPE_CHECK_RETURN_ZERO(env, jpaint);
493 NPE_CHECK_RETURN_ZERO(env, text);
Elliott Hughes8451b252011-04-07 19:17:57 -0700494
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800495 size_t textLength = env->GetStringLength(text);
Fabrice Di Meglio6ab90ed2011-08-08 16:19:38 -0700496 if (textLength == 0) {
497 return 0;
498 }
499
500 const jchar* textArray = env->GetStringChars(text, NULL);
501 SkPaint* paint = GraphicsJNI::getNativePaint(env, jpaint);
Fabrice Di Meglio4f810c82011-04-19 14:53:58 -0700502 jfloat width = 0;
Fabrice Di Meglio6ab90ed2011-08-08 16:19:38 -0700503
Fabrice Di Meglio8fb50712011-05-13 18:51:21 -0700504 TextLayout::getTextRunAdvances(paint, textArray, 0, textLength, textLength,
Victoria Lease626d3c22013-03-27 15:35:53 -0700505 bidiFlags, NULL /* dont need all advances */, &width);
Fabrice Di Megliob02d0ca2011-12-08 14:05:44 -0800506
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800507 env->ReleaseStringChars(text, textArray);
508 return width;
509 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700510
Victoria Lease626d3c22013-03-27 15:35:53 -0700511 static int dotextwidths(JNIEnv* env, SkPaint* paint, const jchar text[], int count, jfloatArray widths,
512 jint bidiFlags) {
Fabrice Di Meglio6ab90ed2011-08-08 16:19:38 -0700513 NPE_CHECK_RETURN_ZERO(env, paint);
514 NPE_CHECK_RETURN_ZERO(env, text);
515
516 if (count < 0 || !widths) {
517 doThrowAIOOBE(env);
518 return 0;
519 }
520 if (count == 0) {
521 return 0;
522 }
523 size_t widthsLength = env->GetArrayLength(widths);
524 if ((size_t)count > widthsLength) {
525 doThrowAIOOBE(env);
526 return 0;
527 }
528
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800529 AutoJavaFloatArray autoWidths(env, widths, count);
530 jfloat* widthsArray = autoWidths.ptr();
Fabrice Di Meglio6ab90ed2011-08-08 16:19:38 -0700531
Fabrice Di Meglio8fb50712011-05-13 18:51:21 -0700532 TextLayout::getTextRunAdvances(paint, text, 0, count, count,
Victoria Lease626d3c22013-03-27 15:35:53 -0700533 bidiFlags, widthsArray, NULL /* dont need totalAdvance */);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800534
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800535 return count;
536 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700537
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000538 static jint getTextWidths___CIII_F(JNIEnv* env, jobject clazz, jlong paintHandle, jcharArray text,
539 jint index, jint count, jint bidiFlags, jfloatArray widths) {
540 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800541 const jchar* textArray = env->GetCharArrayElements(text, NULL);
Victoria Lease626d3c22013-03-27 15:35:53 -0700542 count = dotextwidths(env, paint, textArray + index, count, widths, bidiFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800543 env->ReleaseCharArrayElements(text, const_cast<jchar*>(textArray),
Elliott Hughes8451b252011-04-07 19:17:57 -0700544 JNI_ABORT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800545 return count;
546 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700547
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000548 static jint getTextWidths__StringIII_F(JNIEnv* env, jobject clazz, jlong paintHandle, jstring text,
549 jint start, jint end, jint bidiFlags, jfloatArray widths) {
550 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800551 const jchar* textArray = env->GetStringChars(text, NULL);
Victoria Lease626d3c22013-03-27 15:35:53 -0700552 int count = dotextwidths(env, paint, textArray + start, end - start, widths, bidiFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800553 env->ReleaseStringChars(text, textArray);
554 return count;
555 }
Doug Felt0c702b82010-05-14 10:55:42 -0700556
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700557 static int doTextGlyphs(JNIEnv* env, SkPaint* paint, const jchar* text, jint start, jint count,
558 jint contextCount, jint flags, jcharArray glyphs) {
559 NPE_CHECK_RETURN_ZERO(env, paint);
560 NPE_CHECK_RETURN_ZERO(env, text);
561
562 if ((start | count | contextCount) < 0 || contextCount < count || !glyphs) {
563 doThrowAIOOBE(env);
564 return 0;
565 }
566 if (count == 0) {
567 return 0;
568 }
569 size_t glypthsLength = env->GetArrayLength(glyphs);
570 if ((size_t)count > glypthsLength) {
571 doThrowAIOOBE(env);
572 return 0;
573 }
574
575 jchar* glyphsArray = env->GetCharArrayElements(glyphs, NULL);
576
577 sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint,
578 text, start, count, contextCount, flags);
579 const jchar* shapedGlyphs = value->getGlyphs();
580 size_t glyphsCount = value->getGlyphsCount();
581 memcpy(glyphsArray, shapedGlyphs, sizeof(jchar) * glyphsCount);
582
583 env->ReleaseCharArrayElements(glyphs, glyphsArray, JNI_ABORT);
584 return glyphsCount;
585 }
586
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000587 static jint getTextGlyphs__StringIIIII_C(JNIEnv* env, jobject clazz, jlong paintHandle,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700588 jstring text, jint start, jint end, jint contextStart, jint contextEnd, jint flags,
589 jcharArray glyphs) {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000590 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700591 const jchar* textArray = env->GetStringChars(text, NULL);
592 int count = doTextGlyphs(env, paint, textArray + contextStart, start - contextStart,
593 end - start, contextEnd - contextStart, flags, glyphs);
594 env->ReleaseStringChars(text, textArray);
595 return count;
596 }
597
Doug Feltf7cb1f72010-07-01 16:20:43 -0700598 static jfloat doTextRunAdvances(JNIEnv *env, SkPaint *paint, const jchar *text,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700599 jint start, jint count, jint contextCount, jint flags,
Doug Felt0c702b82010-05-14 10:55:42 -0700600 jfloatArray advances, jint advancesIndex) {
Fabrice Di Meglio6ab90ed2011-08-08 16:19:38 -0700601 NPE_CHECK_RETURN_ZERO(env, paint);
602 NPE_CHECK_RETURN_ZERO(env, text);
603
604 if ((start | count | contextCount | advancesIndex) < 0 || contextCount < count) {
605 doThrowAIOOBE(env);
606 return 0;
607 }
608 if (count == 0) {
609 return 0;
610 }
611 if (advances) {
612 size_t advancesLength = env->GetArrayLength(advances);
613 if ((size_t)count > advancesLength) {
614 doThrowAIOOBE(env);
615 return 0;
616 }
617 }
Victoria Lease3af2a372014-03-17 16:03:28 -0700618 jfloat* advancesArray = new jfloat[count];
Fabrice Di Meglio6ab90ed2011-08-08 16:19:38 -0700619 jfloat totalAdvance = 0;
Doug Felt0c702b82010-05-14 10:55:42 -0700620
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700621 TextLayout::getTextRunAdvances(paint, text, start, count, contextCount, flags,
Fabrice Di Meglio79df5322011-09-19 15:17:56 -0700622 advancesArray, &totalAdvance);
Doug Felt0c702b82010-05-14 10:55:42 -0700623
624 if (advances != NULL) {
625 env->SetFloatArrayRegion(advances, advancesIndex, count, advancesArray);
626 }
Victoria Lease3af2a372014-03-17 16:03:28 -0700627 delete [] advancesArray;
Doug Felt0c702b82010-05-14 10:55:42 -0700628 return totalAdvance;
629 }
630
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000631 static jfloat getTextRunAdvances___CIIIII_FI(JNIEnv* env, jobject clazz, jlong paintHandle,
Doug Felt0c702b82010-05-14 10:55:42 -0700632 jcharArray text, jint index, jint count, jint contextIndex, jint contextCount,
Fabrice Di Meglio665f02c2013-03-20 14:56:05 -0700633 jint flags, jfloatArray advances, jint advancesIndex) {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000634 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
Doug Felt0c702b82010-05-14 10:55:42 -0700635 jchar* textArray = env->GetCharArrayElements(text, NULL);
Fabrice Di Meglio665f02c2013-03-20 14:56:05 -0700636 jfloat result = doTextRunAdvances(env, paint, textArray + contextIndex,
637 index - contextIndex, count, contextCount, flags, advances, advancesIndex);
Doug Felt0c702b82010-05-14 10:55:42 -0700638 env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
639 return result;
640 }
641
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000642 static jfloat getTextRunAdvances__StringIIIII_FI(JNIEnv* env, jobject clazz, jlong paintHandle,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700643 jstring text, jint start, jint end, jint contextStart, jint contextEnd, jint flags,
Fabrice Di Meglio665f02c2013-03-20 14:56:05 -0700644 jfloatArray advances, jint advancesIndex) {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000645 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
Doug Felt0c702b82010-05-14 10:55:42 -0700646 const jchar* textArray = env->GetStringChars(text, NULL);
Fabrice Di Meglio665f02c2013-03-20 14:56:05 -0700647 jfloat result = doTextRunAdvances(env, paint, textArray + contextStart,
648 start - contextStart, end - start, contextEnd - contextStart, flags,
649 advances, advancesIndex);
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -0700650 env->ReleaseStringChars(text, textArray);
651 return result;
652 }
653
Doug Felt0c702b82010-05-14 10:55:42 -0700654 static jint doTextRunCursor(JNIEnv *env, SkPaint* paint, const jchar *text, jint start,
Fabrice Di Meglioa4bf8112013-03-15 11:22:29 -0700655 jint count, jint flags, jint offset, jint opt) {
Fabrice Di Meglio4f810c82011-04-19 14:53:58 -0700656 jfloat scalarArray[count];
Fabrice Di Meglio9c418db2011-09-18 12:54:38 -0700657
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700658 TextLayout::getTextRunAdvances(paint, text, start, count, start + count, flags,
Fabrice Di Meglio79df5322011-09-19 15:17:56 -0700659 scalarArray, NULL /* dont need totalAdvance */);
Doug Felt0c702b82010-05-14 10:55:42 -0700660
Doug Felt0c702b82010-05-14 10:55:42 -0700661 jint pos = offset - start;
662 switch (opt) {
663 case AFTER:
664 if (pos < count) {
665 pos += 1;
666 }
667 // fall through
668 case AT_OR_AFTER:
669 while (pos < count && scalarArray[pos] == 0) {
670 ++pos;
671 }
672 break;
673 case BEFORE:
674 if (pos > 0) {
675 --pos;
676 }
677 // fall through
678 case AT_OR_BEFORE:
679 while (pos > 0 && scalarArray[pos] == 0) {
680 --pos;
681 }
682 break;
683 case AT:
684 default:
685 if (scalarArray[pos] == 0) {
686 pos = -1;
687 }
688 break;
689 }
690
691 if (pos != -1) {
692 pos += start;
693 }
694
695 return pos;
696 }
697
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000698 static jint getTextRunCursor___C(JNIEnv* env, jobject clazz, jlong paintHandle, jcharArray text,
Fabrice Di Meglioa4bf8112013-03-15 11:22:29 -0700699 jint contextStart, jint contextCount, jint flags, jint offset, jint cursorOpt) {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000700 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
Doug Felt0c702b82010-05-14 10:55:42 -0700701 jchar* textArray = env->GetCharArrayElements(text, NULL);
Fabrice Di Meglioa4bf8112013-03-15 11:22:29 -0700702 jint result = doTextRunCursor(env, paint, textArray, contextStart, contextCount, flags,
Doug Felt0c702b82010-05-14 10:55:42 -0700703 offset, cursorOpt);
704 env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
705 return result;
706 }
707
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000708 static jint getTextRunCursor__String(JNIEnv* env, jobject clazz, jlong paintHandle, jstring text,
Fabrice Di Meglioa4bf8112013-03-15 11:22:29 -0700709 jint contextStart, jint contextEnd, jint flags, jint offset, jint cursorOpt) {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000710 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
Doug Felt0c702b82010-05-14 10:55:42 -0700711 const jchar* textArray = env->GetStringChars(text, NULL);
712 jint result = doTextRunCursor(env, paint, textArray, contextStart,
Fabrice Di Meglioa4bf8112013-03-15 11:22:29 -0700713 contextEnd - contextStart, flags, offset, cursorOpt);
Doug Felt0c702b82010-05-14 10:55:42 -0700714 env->ReleaseStringChars(text, textArray);
715 return result;
716 }
717
Doug Feltf7cb1f72010-07-01 16:20:43 -0700718 static void getTextPath(JNIEnv* env, SkPaint* paint, const jchar* text, jint count,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700719 jint bidiFlags, jfloat x, jfloat y, SkPath *path) {
720 TextLayout::getTextPath(paint, text, count, bidiFlags, x, y, path);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800721 }
Doug Feltf7cb1f72010-07-01 16:20:43 -0700722
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000723 static void getTextPath___C(JNIEnv* env, jobject clazz, jlong paintHandle, jint bidiFlags,
724 jcharArray text, jint index, jint count, jfloat x, jfloat y, jlong pathHandle) {
725 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
726 SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
Doug Feltf7cb1f72010-07-01 16:20:43 -0700727 const jchar* textArray = env->GetCharArrayElements(text, NULL);
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700728 getTextPath(env, paint, textArray + index, count, bidiFlags, x, y, path);
Doug Feltf7cb1f72010-07-01 16:20:43 -0700729 env->ReleaseCharArrayElements(text, const_cast<jchar*>(textArray), JNI_ABORT);
730 }
731
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000732 static void getTextPath__String(JNIEnv* env, jobject clazz, jlong paintHandle, jint bidiFlags,
733 jstring text, jint start, jint end, jfloat x, jfloat y, jlong pathHandle) {
734 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
735 SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800736 const jchar* textArray = env->GetStringChars(text, NULL);
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700737 getTextPath(env, paint, textArray + start, end - start, bidiFlags, x, y, path);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800738 env->ReleaseStringChars(text, textArray);
739 }
Doug Feltf7cb1f72010-07-01 16:20:43 -0700740
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800741 static void setShadowLayer(JNIEnv* env, jobject jpaint, jfloat radius,
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000742 jfloat dx, jfloat dy, jint color) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800743 NPE_CHECK_RETURN_VOID(env, jpaint);
Elliott Hughes8451b252011-04-07 19:17:57 -0700744
745 SkPaint* paint = GraphicsJNI::getNativePaint(env, jpaint);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800746 if (radius <= 0) {
747 paint->setLooper(NULL);
748 }
749 else {
750 paint->setLooper(new SkBlurDrawLooper(SkFloatToScalar(radius),
751 SkFloatToScalar(dx),
752 SkFloatToScalar(dy),
753 (SkColor)color))->unref();
754 }
755 }
756
Fabrice Di Megliobd901de2012-01-20 17:41:55 -0800757 static int breakText(JNIEnv* env, SkPaint& paint, const jchar text[],
Victoria Lease626d3c22013-03-27 15:35:53 -0700758 int count, float maxWidth, jint bidiFlags, jfloatArray jmeasured,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800759 SkPaint::TextBufferDirection tbd) {
Fabrice Di Meglioa731b082012-01-23 18:18:45 -0800760 sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(&paint,
Victoria Lease626d3c22013-03-27 15:35:53 -0700761 text, 0, count, count, bidiFlags);
Fabrice Di Megliobd901de2012-01-20 17:41:55 -0800762 if (value == NULL) {
Fabrice Di Meglioa731b082012-01-23 18:18:45 -0800763 return 0;
Fabrice Di Megliobd901de2012-01-20 17:41:55 -0800764 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800765 SkScalar measured;
Fabrice Di Megliobd901de2012-01-20 17:41:55 -0800766 size_t bytes = paint.breakText(value->getGlyphs(), value->getGlyphsCount() << 1,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800767 SkFloatToScalar(maxWidth), &measured, tbd);
768 SkASSERT((bytes & 1) == 0);
769
770 if (jmeasured && env->GetArrayLength(jmeasured) > 0) {
771 AutoJavaFloatArray autoMeasured(env, jmeasured, 1);
772 jfloat* array = autoMeasured.ptr();
773 array[0] = SkScalarToFloat(measured);
774 }
775 return bytes >> 1;
776 }
777
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000778 static jint breakTextC(JNIEnv* env, jobject jpaint, jcharArray jtext,
779 jint index, jint count, jfloat maxWidth, jint bidiFlags, jfloatArray jmeasuredWidth) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800780 NPE_CHECK_RETURN_ZERO(env, jpaint);
781 NPE_CHECK_RETURN_ZERO(env, jtext);
782
783 SkPaint::TextBufferDirection tbd;
784 if (count < 0) {
785 tbd = SkPaint::kBackward_TextBufferDirection;
786 count = -count;
787 }
788 else {
789 tbd = SkPaint::kForward_TextBufferDirection;
790 }
791
792 if ((index < 0) || (index + count > env->GetArrayLength(jtext))) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700793 doThrowAIOOBE(env);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800794 return 0;
795 }
796
797 SkPaint* paint = GraphicsJNI::getNativePaint(env, jpaint);
798 const jchar* text = env->GetCharArrayElements(jtext, NULL);
799 count = breakText(env, *paint, text + index, count, maxWidth,
Victoria Lease626d3c22013-03-27 15:35:53 -0700800 bidiFlags, jmeasuredWidth, tbd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800801 env->ReleaseCharArrayElements(jtext, const_cast<jchar*>(text),
802 JNI_ABORT);
803 return count;
804 }
805
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000806 static jint breakTextS(JNIEnv* env, jobject jpaint, jstring jtext,
807 jboolean forwards, jfloat maxWidth, jint bidiFlags, jfloatArray jmeasuredWidth) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800808 NPE_CHECK_RETURN_ZERO(env, jpaint);
809 NPE_CHECK_RETURN_ZERO(env, jtext);
810
811 SkPaint::TextBufferDirection tbd = forwards ?
812 SkPaint::kForward_TextBufferDirection :
813 SkPaint::kBackward_TextBufferDirection;
814
815 SkPaint* paint = GraphicsJNI::getNativePaint(env, jpaint);
816 int count = env->GetStringLength(jtext);
817 const jchar* text = env->GetStringChars(jtext, NULL);
Victoria Lease626d3c22013-03-27 15:35:53 -0700818 count = breakText(env, *paint, text, count, maxWidth, bidiFlags, jmeasuredWidth, tbd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800819 env->ReleaseStringChars(jtext, text);
820 return count;
821 }
822
823 static void doTextBounds(JNIEnv* env, const jchar* text, int count,
Victoria Lease626d3c22013-03-27 15:35:53 -0700824 jobject bounds, const SkPaint& paint, jint bidiFlags) {
Romain Guy059e12c2012-11-28 17:35:51 -0800825 SkRect r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800826 SkIRect ir;
Elliott Hughes8451b252011-04-07 19:17:57 -0700827
Fabrice Di Meglioa731b082012-01-23 18:18:45 -0800828 sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(&paint,
Victoria Lease626d3c22013-03-27 15:35:53 -0700829 text, 0, count, count, bidiFlags);
Fabrice Di Megliobd901de2012-01-20 17:41:55 -0800830 if (value == NULL) {
Fabrice Di Meglioa731b082012-01-23 18:18:45 -0800831 return;
Fabrice Di Megliobd901de2012-01-20 17:41:55 -0800832 }
Fabrice Di Megliobd901de2012-01-20 17:41:55 -0800833 paint.measureText(value->getGlyphs(), value->getGlyphsCount() << 1, &r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800834 r.roundOut(&ir);
835 GraphicsJNI::irect_to_jrect(ir, env, bounds);
836 }
837
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000838 static void getStringBounds(JNIEnv* env, jobject, jlong paintHandle,
839 jstring text, jint start, jint end, jint bidiFlags, jobject bounds) {
840 const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800841 const jchar* textArray = env->GetStringChars(text, NULL);
Victoria Lease626d3c22013-03-27 15:35:53 -0700842 doTextBounds(env, textArray + start, end - start, bounds, *paint, bidiFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800843 env->ReleaseStringChars(text, textArray);
844 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700845
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000846 static void getCharArrayBounds(JNIEnv* env, jobject, jlong paintHandle,
847 jcharArray text, jint index, jint count, jint bidiFlags, jobject bounds) {
848 const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800849 const jchar* textArray = env->GetCharArrayElements(text, NULL);
Victoria Lease626d3c22013-03-27 15:35:53 -0700850 doTextBounds(env, textArray + index, count, bounds, *paint, bidiFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800851 env->ReleaseCharArrayElements(text, const_cast<jchar*>(textArray),
852 JNI_ABORT);
853 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700854
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800855};
856
857static JNINativeMethod methods[] = {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000858 {"finalizer", "(J)V", (void*) SkPaintGlue::finalizer},
859 {"native_init","()J", (void*) SkPaintGlue::init},
860 {"native_initWithPaint","(J)J", (void*) SkPaintGlue::initWithPaint},
861 {"native_reset","(J)V", (void*) SkPaintGlue::reset},
862 {"native_set","(JJ)V", (void*) SkPaintGlue::assign},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800863 {"getFlags","()I", (void*) SkPaintGlue::getFlags},
864 {"setFlags","(I)V", (void*) SkPaintGlue::setFlags},
Dianne Hackbornf43fa572011-08-12 18:59:39 -0700865 {"getHinting","()I", (void*) SkPaintGlue::getHinting},
866 {"setHinting","(I)V", (void*) SkPaintGlue::setHinting},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800867 {"setAntiAlias","(Z)V", (void*) SkPaintGlue::setAntiAlias},
868 {"setSubpixelText","(Z)V", (void*) SkPaintGlue::setSubpixelText},
869 {"setLinearText","(Z)V", (void*) SkPaintGlue::setLinearText},
870 {"setUnderlineText","(Z)V", (void*) SkPaintGlue::setUnderlineText},
871 {"setStrikeThruText","(Z)V", (void*) SkPaintGlue::setStrikeThruText},
872 {"setFakeBoldText","(Z)V", (void*) SkPaintGlue::setFakeBoldText},
873 {"setFilterBitmap","(Z)V", (void*) SkPaintGlue::setFilterBitmap},
874 {"setDither","(Z)V", (void*) SkPaintGlue::setDither},
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000875 {"native_getStyle","(J)I", (void*) SkPaintGlue::getStyle},
876 {"native_setStyle","(JI)V", (void*) SkPaintGlue::setStyle},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800877 {"getColor","()I", (void*) SkPaintGlue::getColor},
878 {"setColor","(I)V", (void*) SkPaintGlue::setColor},
879 {"getAlpha","()I", (void*) SkPaintGlue::getAlpha},
880 {"setAlpha","(I)V", (void*) SkPaintGlue::setAlpha},
881 {"getStrokeWidth","()F", (void*) SkPaintGlue::getStrokeWidth},
882 {"setStrokeWidth","(F)V", (void*) SkPaintGlue::setStrokeWidth},
883 {"getStrokeMiter","()F", (void*) SkPaintGlue::getStrokeMiter},
884 {"setStrokeMiter","(F)V", (void*) SkPaintGlue::setStrokeMiter},
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000885 {"native_getStrokeCap","(J)I", (void*) SkPaintGlue::getStrokeCap},
886 {"native_setStrokeCap","(JI)V", (void*) SkPaintGlue::setStrokeCap},
887 {"native_getStrokeJoin","(J)I", (void*) SkPaintGlue::getStrokeJoin},
888 {"native_setStrokeJoin","(JI)V", (void*) SkPaintGlue::setStrokeJoin},
889 {"native_getFillPath","(JJJ)Z", (void*) SkPaintGlue::getFillPath},
890 {"native_setShader","(JJ)J", (void*) SkPaintGlue::setShader},
891 {"native_setColorFilter","(JJ)J", (void*) SkPaintGlue::setColorFilter},
892 {"native_setXfermode","(JJ)J", (void*) SkPaintGlue::setXfermode},
893 {"native_setPathEffect","(JJ)J", (void*) SkPaintGlue::setPathEffect},
894 {"native_setMaskFilter","(JJ)J", (void*) SkPaintGlue::setMaskFilter},
895 {"native_setTypeface","(JJ)J", (void*) SkPaintGlue::setTypeface},
896 {"native_setRasterizer","(JJ)J", (void*) SkPaintGlue::setRasterizer},
897 {"native_getTextAlign","(J)I", (void*) SkPaintGlue::getTextAlign},
898 {"native_setTextAlign","(JI)V", (void*) SkPaintGlue::setTextAlign},
899 {"native_setTextLocale","(JLjava/lang/String;)V", (void*) SkPaintGlue::setTextLocale},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800900 {"getTextSize","()F", (void*) SkPaintGlue::getTextSize},
901 {"setTextSize","(F)V", (void*) SkPaintGlue::setTextSize},
902 {"getTextScaleX","()F", (void*) SkPaintGlue::getTextScaleX},
903 {"setTextScaleX","(F)V", (void*) SkPaintGlue::setTextScaleX},
904 {"getTextSkewX","()F", (void*) SkPaintGlue::getTextSkewX},
905 {"setTextSkewX","(F)V", (void*) SkPaintGlue::setTextSkewX},
906 {"ascent","()F", (void*) SkPaintGlue::ascent},
907 {"descent","()F", (void*) SkPaintGlue::descent},
908 {"getFontMetrics", "(Landroid/graphics/Paint$FontMetrics;)F", (void*)SkPaintGlue::getFontMetrics},
909 {"getFontMetricsInt", "(Landroid/graphics/Paint$FontMetricsInt;)I", (void*)SkPaintGlue::getFontMetricsInt},
Victoria Lease626d3c22013-03-27 15:35:53 -0700910 {"native_measureText","([CIII)F", (void*) SkPaintGlue::measureText_CIII},
911 {"native_measureText","(Ljava/lang/String;I)F", (void*) SkPaintGlue::measureText_StringI},
912 {"native_measureText","(Ljava/lang/String;III)F", (void*) SkPaintGlue::measureText_StringIII},
913 {"native_breakText","([CIIFI[F)I", (void*) SkPaintGlue::breakTextC},
914 {"native_breakText","(Ljava/lang/String;ZFI[F)I", (void*) SkPaintGlue::breakTextS},
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000915 {"native_getTextWidths","(J[CIII[F)I", (void*) SkPaintGlue::getTextWidths___CIII_F},
916 {"native_getTextWidths","(JLjava/lang/String;III[F)I", (void*) SkPaintGlue::getTextWidths__StringIII_F},
917 {"native_getTextRunAdvances","(J[CIIIII[FI)F",
Fabrice Di Meglio665f02c2013-03-20 14:56:05 -0700918 (void*) SkPaintGlue::getTextRunAdvances___CIIIII_FI},
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000919 {"native_getTextRunAdvances","(JLjava/lang/String;IIIII[FI)F",
Fabrice Di Meglio665f02c2013-03-20 14:56:05 -0700920 (void*) SkPaintGlue::getTextRunAdvances__StringIIIII_FI},
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700921
922
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000923 {"native_getTextGlyphs","(JLjava/lang/String;IIIII[C)I",
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700924 (void*) SkPaintGlue::getTextGlyphs__StringIIIII_C},
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000925 {"native_getTextRunCursor", "(J[CIIIII)I", (void*) SkPaintGlue::getTextRunCursor___C},
926 {"native_getTextRunCursor", "(JLjava/lang/String;IIIII)I",
Doug Felt0c702b82010-05-14 10:55:42 -0700927 (void*) SkPaintGlue::getTextRunCursor__String},
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000928 {"native_getTextPath","(JI[CIIFFJ)V", (void*) SkPaintGlue::getTextPath___C},
929 {"native_getTextPath","(JILjava/lang/String;IIFFJ)V", (void*) SkPaintGlue::getTextPath__String},
930 {"nativeGetStringBounds", "(JLjava/lang/String;IIILandroid/graphics/Rect;)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800931 (void*) SkPaintGlue::getStringBounds },
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000932 {"nativeGetCharArrayBounds", "(J[CIIILandroid/graphics/Rect;)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800933 (void*) SkPaintGlue::getCharArrayBounds },
Romain Guy1e45aae2010-08-13 19:39:53 -0700934 {"nSetShadowLayer", "(FFFI)V", (void*)SkPaintGlue::setShadowLayer}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800935};
936
937static jfieldID req_fieldID(jfieldID id) {
938 SkASSERT(id);
939 return id;
940}
941
942int register_android_graphics_Paint(JNIEnv* env) {
943 gFontMetrics_class = env->FindClass("android/graphics/Paint$FontMetrics");
944 SkASSERT(gFontMetrics_class);
945 gFontMetrics_class = (jclass)env->NewGlobalRef(gFontMetrics_class);
946
947 gFontMetrics_fieldID.top = req_fieldID(env->GetFieldID(gFontMetrics_class, "top", "F"));
948 gFontMetrics_fieldID.ascent = req_fieldID(env->GetFieldID(gFontMetrics_class, "ascent", "F"));
949 gFontMetrics_fieldID.descent = req_fieldID(env->GetFieldID(gFontMetrics_class, "descent", "F"));
950 gFontMetrics_fieldID.bottom = req_fieldID(env->GetFieldID(gFontMetrics_class, "bottom", "F"));
951 gFontMetrics_fieldID.leading = req_fieldID(env->GetFieldID(gFontMetrics_class, "leading", "F"));
952
953 gFontMetricsInt_class = env->FindClass("android/graphics/Paint$FontMetricsInt");
954 SkASSERT(gFontMetricsInt_class);
955 gFontMetricsInt_class = (jclass)env->NewGlobalRef(gFontMetricsInt_class);
956
957 gFontMetricsInt_fieldID.top = req_fieldID(env->GetFieldID(gFontMetricsInt_class, "top", "I"));
958 gFontMetricsInt_fieldID.ascent = req_fieldID(env->GetFieldID(gFontMetricsInt_class, "ascent", "I"));
959 gFontMetricsInt_fieldID.descent = req_fieldID(env->GetFieldID(gFontMetricsInt_class, "descent", "I"));
960 gFontMetricsInt_fieldID.bottom = req_fieldID(env->GetFieldID(gFontMetricsInt_class, "bottom", "I"));
961 gFontMetricsInt_fieldID.leading = req_fieldID(env->GetFieldID(gFontMetricsInt_class, "leading", "I"));
962
963 int result = AndroidRuntime::registerNativeMethods(env, "android/graphics/Paint", methods,
964 sizeof(methods) / sizeof(methods[0]));
965 return result;
966}
967
968}