blob: 25234813a8373bc880e27506efc5bcd94de2d916 [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 Bhata0398432014-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 Bhata0398432014-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 Bhata0398432014-01-20 20:08:01 +000081 return reinterpret_cast<jlong>(obj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082 }
83
Ashok Bhata0398432014-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 Bhata0398432014-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 Bhata0398432014-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 Bhata0398432014-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 Bhata0398432014-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);
158 GraphicsJNI::getNativePaint(env, paint)->setFilterBitmap(filterBitmap);
159 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700160
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800161 static void setDither(JNIEnv* env, jobject paint, jboolean dither) {
162 NPE_CHECK_RETURN_VOID(env, paint);
163 GraphicsJNI::getNativePaint(env, paint)->setDither(dither);
164 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700165
Ashok Bhata0398432014-01-20 20:08:01 +0000166 static jint getStyle(JNIEnv* env, jobject clazz,jlong objHandle) {
167 SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
168 return static_cast<jint>(obj->getStyle());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800169 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700170
Ashok Bhata0398432014-01-20 20:08:01 +0000171 static void setStyle(JNIEnv* env, jobject clazz, jlong objHandle, jint styleHandle) {
172 SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
173 SkPaint::Style style = static_cast<SkPaint::Style>(styleHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800174 obj->setStyle(style);
175 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700176
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800177 static jint getColor(JNIEnv* env, jobject paint) {
178 NPE_CHECK_RETURN_ZERO(env, paint);
Ashok Bhata0398432014-01-20 20:08:01 +0000179 int color;
180 color = GraphicsJNI::getNativePaint(env, paint)->getColor();
181 return static_cast<jint>(color);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800182 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700183
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800184 static jint getAlpha(JNIEnv* env, jobject paint) {
185 NPE_CHECK_RETURN_ZERO(env, paint);
Ashok Bhata0398432014-01-20 20:08:01 +0000186 int alpha;
187 alpha = GraphicsJNI::getNativePaint(env, paint)->getAlpha();
188 return static_cast<jint>(alpha);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800189 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700190
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800191 static void setColor(JNIEnv* env, jobject paint, jint color) {
192 NPE_CHECK_RETURN_VOID(env, paint);
193 GraphicsJNI::getNativePaint(env, paint)->setColor(color);
194 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700195
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800196 static void setAlpha(JNIEnv* env, jobject paint, jint a) {
197 NPE_CHECK_RETURN_VOID(env, paint);
198 GraphicsJNI::getNativePaint(env, paint)->setAlpha(a);
199 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700200
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800201 static jfloat getStrokeWidth(JNIEnv* env, jobject paint) {
202 NPE_CHECK_RETURN_ZERO(env, paint);
203 return SkScalarToFloat(GraphicsJNI::getNativePaint(env, paint)->getStrokeWidth());
204 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700205
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800206 static void setStrokeWidth(JNIEnv* env, jobject paint, jfloat width) {
207 NPE_CHECK_RETURN_VOID(env, paint);
208 GraphicsJNI::getNativePaint(env, paint)->setStrokeWidth(SkFloatToScalar(width));
209 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700210
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800211 static jfloat getStrokeMiter(JNIEnv* env, jobject paint) {
212 NPE_CHECK_RETURN_ZERO(env, paint);
213 return SkScalarToFloat(GraphicsJNI::getNativePaint(env, paint)->getStrokeMiter());
214 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700215
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800216 static void setStrokeMiter(JNIEnv* env, jobject paint, jfloat miter) {
217 NPE_CHECK_RETURN_VOID(env, paint);
218 GraphicsJNI::getNativePaint(env, paint)->setStrokeMiter(SkFloatToScalar(miter));
219 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700220
Ashok Bhata0398432014-01-20 20:08:01 +0000221 static jint getStrokeCap(JNIEnv* env, jobject clazz, jlong objHandle) {
222 SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
223 return static_cast<jint>(obj->getStrokeCap());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800224 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700225
Ashok Bhata0398432014-01-20 20:08:01 +0000226 static void setStrokeCap(JNIEnv* env, jobject clazz, jlong objHandle, jint capHandle) {
227 SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
228 SkPaint::Cap cap = static_cast<SkPaint::Cap>(capHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800229 obj->setStrokeCap(cap);
230 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700231
Ashok Bhata0398432014-01-20 20:08:01 +0000232 static jint getStrokeJoin(JNIEnv* env, jobject clazz, jlong objHandle) {
233 SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
234 return static_cast<jint>(obj->getStrokeJoin());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800235 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700236
Ashok Bhata0398432014-01-20 20:08:01 +0000237 static void setStrokeJoin(JNIEnv* env, jobject clazz, jlong objHandle, jint joinHandle) {
238 SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
239 SkPaint::Join join = (SkPaint::Join) joinHandle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800240 obj->setStrokeJoin(join);
241 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700242
Ashok Bhata0398432014-01-20 20:08:01 +0000243 static jboolean getFillPath(JNIEnv* env, jobject clazz, jlong objHandle, jlong srcHandle, jlong dstHandle) {
244 SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
245 SkPath* src = reinterpret_cast<SkPath*>(srcHandle);
246 SkPath* dst = reinterpret_cast<SkPath*>(dstHandle);
247 return obj->getFillPath(*src, dst) ? JNI_TRUE : JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800248 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700249
Ashok Bhata0398432014-01-20 20:08:01 +0000250 static jlong setShader(JNIEnv* env, jobject clazz, jlong objHandle, jlong shaderHandle) {
251 SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
252 SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle);
253 return reinterpret_cast<jlong>(obj->setShader(shader));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800254 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700255
Ashok Bhata0398432014-01-20 20:08:01 +0000256 static jlong setColorFilter(JNIEnv* env, jobject clazz, jlong objHandle, jlong filterHandle) {
257 SkPaint* obj = reinterpret_cast<SkPaint *>(objHandle);
258 SkColorFilter* filter = reinterpret_cast<SkColorFilter *>(filterHandle);
259 return reinterpret_cast<jlong>(obj->setColorFilter(filter));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800260 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700261
Ashok Bhata0398432014-01-20 20:08:01 +0000262 static jlong setXfermode(JNIEnv* env, jobject clazz, jlong objHandle, jlong xfermodeHandle) {
263 SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
264 SkXfermode* xfermode = reinterpret_cast<SkXfermode*>(xfermodeHandle);
265 return reinterpret_cast<jlong>(obj->setXfermode(xfermode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800266 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700267
Ashok Bhata0398432014-01-20 20:08:01 +0000268 static jlong setPathEffect(JNIEnv* env, jobject clazz, jlong objHandle, jlong effectHandle) {
269 SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
270 SkPathEffect* effect = reinterpret_cast<SkPathEffect*>(effectHandle);
271 return reinterpret_cast<jlong>(obj->setPathEffect(effect));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800272 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700273
Ashok Bhata0398432014-01-20 20:08:01 +0000274 static jlong setMaskFilter(JNIEnv* env, jobject clazz, jlong objHandle, jlong maskfilterHandle) {
275 SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
276 SkMaskFilter* maskfilter = reinterpret_cast<SkMaskFilter*>(maskfilterHandle);
277 return reinterpret_cast<jlong>(obj->setMaskFilter(maskfilter));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800278 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700279
Ashok Bhata0398432014-01-20 20:08:01 +0000280 static jlong setTypeface(JNIEnv* env, jobject clazz, jlong objHandle, jlong typefaceHandle) {
281 SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
282 SkTypeface* typeface = reinterpret_cast<SkTypeface*>(typefaceHandle);
283 return reinterpret_cast<jlong>(obj->setTypeface(typeface));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800284 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700285
Ashok Bhata0398432014-01-20 20:08:01 +0000286 static jlong setRasterizer(JNIEnv* env, jobject clazz, jlong objHandle, jlong rasterizerHandle) {
287 SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
288 SkRasterizer* rasterizer = reinterpret_cast<SkRasterizer*>(rasterizerHandle);
289 return reinterpret_cast<jlong>(obj->setRasterizer(rasterizer));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800290 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700291
Ashok Bhata0398432014-01-20 20:08:01 +0000292 static jint getTextAlign(JNIEnv* env, jobject clazz, jlong objHandle) {
293 SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
294 return static_cast<jint>(obj->getTextAlign());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800295 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700296
Ashok Bhata0398432014-01-20 20:08:01 +0000297 static void setTextAlign(JNIEnv* env, jobject clazz, jlong objHandle, jint alignHandle) {
298 SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
299 SkPaint::Align align = static_cast<SkPaint::Align>(alignHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800300 obj->setTextAlign(align);
301 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700302
Billy Hewlettac1cbaf2012-07-18 09:51:45 -0700303 // generate bcp47 identifier for the supplied locale
304 static void toLanguageTag(char* output, size_t outSize,
305 const char* locale) {
306 if (output == NULL || outSize <= 0) {
307 return;
308 }
309 if (locale == NULL) {
310 output[0] = '\0';
311 return;
312 }
313 char canonicalChars[ULOC_FULLNAME_CAPACITY];
314 UErrorCode uErr = U_ZERO_ERROR;
315 uloc_canonicalize(locale, canonicalChars, ULOC_FULLNAME_CAPACITY,
316 &uErr);
317 if (U_SUCCESS(uErr)) {
318 char likelyChars[ULOC_FULLNAME_CAPACITY];
319 uErr = U_ZERO_ERROR;
320 uloc_addLikelySubtags(canonicalChars, likelyChars,
321 ULOC_FULLNAME_CAPACITY, &uErr);
322 if (U_SUCCESS(uErr)) {
323 uErr = U_ZERO_ERROR;
324 uloc_toLanguageTag(likelyChars, output, outSize, FALSE, &uErr);
325 if (U_SUCCESS(uErr)) {
326 return;
327 } else {
328 ALOGD("uloc_toLanguageTag(\"%s\") failed: %s", likelyChars,
329 u_errorName(uErr));
330 }
331 } else {
332 ALOGD("uloc_addLikelySubtags(\"%s\") failed: %s",
333 canonicalChars, u_errorName(uErr));
334 }
335 } else {
336 ALOGD("uloc_canonicalize(\"%s\") failed: %s", locale,
337 u_errorName(uErr));
338 }
339 // unable to build a proper language identifier
340 output[0] = '\0';
341 }
342
Ashok Bhata0398432014-01-20 20:08:01 +0000343 static void setTextLocale(JNIEnv* env, jobject clazz, jlong objHandle, jstring locale) {
344 SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
Billy Hewlettac1cbaf2012-07-18 09:51:45 -0700345 ScopedUtfChars localeChars(env, locale);
346 char langTag[ULOC_FULLNAME_CAPACITY];
347 toLanguageTag(langTag, ULOC_FULLNAME_CAPACITY, localeChars.c_str());
Derek Sollenbergerd7a80772013-05-28 10:44:26 -0400348
349 SkPaintOptionsAndroid paintOpts = obj->getPaintOptionsAndroid();
350 paintOpts.setLanguage(langTag);
351 obj->setPaintOptionsAndroid(paintOpts);
Fabrice Di Meglio517825f2012-04-06 16:53:48 -0700352 }
353
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800354 static jfloat getTextSize(JNIEnv* env, jobject paint) {
355 NPE_CHECK_RETURN_ZERO(env, paint);
356 return SkScalarToFloat(GraphicsJNI::getNativePaint(env, paint)->getTextSize());
357 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700358
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800359 static void setTextSize(JNIEnv* env, jobject paint, jfloat textSize) {
360 NPE_CHECK_RETURN_VOID(env, paint);
361 GraphicsJNI::getNativePaint(env, paint)->setTextSize(SkFloatToScalar(textSize));
362 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700363
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800364 static jfloat getTextScaleX(JNIEnv* env, jobject paint) {
365 NPE_CHECK_RETURN_ZERO(env, paint);
366 return SkScalarToFloat(GraphicsJNI::getNativePaint(env, paint)->getTextScaleX());
367 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700368
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800369 static void setTextScaleX(JNIEnv* env, jobject paint, jfloat scaleX) {
370 NPE_CHECK_RETURN_VOID(env, paint);
371 GraphicsJNI::getNativePaint(env, paint)->setTextScaleX(SkFloatToScalar(scaleX));
372 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700373
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800374 static jfloat getTextSkewX(JNIEnv* env, jobject paint) {
375 NPE_CHECK_RETURN_ZERO(env, paint);
376 return SkScalarToFloat(GraphicsJNI::getNativePaint(env, paint)->getTextSkewX());
377 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700378
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800379 static void setTextSkewX(JNIEnv* env, jobject paint, jfloat skewX) {
380 NPE_CHECK_RETURN_VOID(env, paint);
381 GraphicsJNI::getNativePaint(env, paint)->setTextSkewX(SkFloatToScalar(skewX));
382 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700383
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800384 static jfloat ascent(JNIEnv* env, jobject paint) {
385 NPE_CHECK_RETURN_ZERO(env, paint);
386 SkPaint::FontMetrics metrics;
387 (void)GraphicsJNI::getNativePaint(env, paint)->getFontMetrics(&metrics);
388 return SkScalarToFloat(metrics.fAscent);
389 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700390
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800391 static jfloat descent(JNIEnv* env, jobject paint) {
392 NPE_CHECK_RETURN_ZERO(env, paint);
393 SkPaint::FontMetrics metrics;
394 (void)GraphicsJNI::getNativePaint(env, paint)->getFontMetrics(&metrics);
395 return SkScalarToFloat(metrics.fDescent);
396 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700397
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800398 static jfloat getFontMetrics(JNIEnv* env, jobject paint, jobject metricsObj) {
399 NPE_CHECK_RETURN_ZERO(env, paint);
400 SkPaint::FontMetrics metrics;
401 SkScalar spacing = GraphicsJNI::getNativePaint(env, paint)->getFontMetrics(&metrics);
402
403 if (metricsObj) {
404 SkASSERT(env->IsInstanceOf(metricsObj, gFontMetrics_class));
405 env->SetFloatField(metricsObj, gFontMetrics_fieldID.top, SkScalarToFloat(metrics.fTop));
406 env->SetFloatField(metricsObj, gFontMetrics_fieldID.ascent, SkScalarToFloat(metrics.fAscent));
407 env->SetFloatField(metricsObj, gFontMetrics_fieldID.descent, SkScalarToFloat(metrics.fDescent));
408 env->SetFloatField(metricsObj, gFontMetrics_fieldID.bottom, SkScalarToFloat(metrics.fBottom));
409 env->SetFloatField(metricsObj, gFontMetrics_fieldID.leading, SkScalarToFloat(metrics.fLeading));
410 }
411 return SkScalarToFloat(spacing);
412 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700413
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800414 static jint getFontMetricsInt(JNIEnv* env, jobject paint, jobject metricsObj) {
415 NPE_CHECK_RETURN_ZERO(env, paint);
416 SkPaint::FontMetrics metrics;
Elliott Hughes8451b252011-04-07 19:17:57 -0700417
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800418 GraphicsJNI::getNativePaint(env, paint)->getFontMetrics(&metrics);
419 int ascent = SkScalarRound(metrics.fAscent);
420 int descent = SkScalarRound(metrics.fDescent);
421 int leading = SkScalarRound(metrics.fLeading);
422
423 if (metricsObj) {
424 SkASSERT(env->IsInstanceOf(metricsObj, gFontMetricsInt_class));
425 env->SetIntField(metricsObj, gFontMetricsInt_fieldID.top, SkScalarFloor(metrics.fTop));
426 env->SetIntField(metricsObj, gFontMetricsInt_fieldID.ascent, ascent);
427 env->SetIntField(metricsObj, gFontMetricsInt_fieldID.descent, descent);
428 env->SetIntField(metricsObj, gFontMetricsInt_fieldID.bottom, SkScalarCeil(metrics.fBottom));
429 env->SetIntField(metricsObj, gFontMetricsInt_fieldID.leading, leading);
430 }
431 return descent - ascent + leading;
432 }
433
Ashok Bhata0398432014-01-20 20:08:01 +0000434 static jfloat measureText_CIII(JNIEnv* env, jobject jpaint, jcharArray text, jint index, jint count,
Victoria Lease626d3c22013-03-27 15:35:53 -0700435 jint bidiFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800436 NPE_CHECK_RETURN_ZERO(env, jpaint);
437 NPE_CHECK_RETURN_ZERO(env, text);
438
439 size_t textLength = env->GetArrayLength(text);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800440 if ((index | count) < 0 || (size_t)(index + count) > textLength) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700441 doThrowAIOOBE(env);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800442 return 0;
443 }
Fabrice Di Meglio6ab90ed2011-08-08 16:19:38 -0700444 if (count == 0) {
445 return 0;
446 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800447
Fabrice Di Meglio4f810c82011-04-19 14:53:58 -0700448 SkPaint* paint = GraphicsJNI::getNativePaint(env, jpaint);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800449 const jchar* textArray = env->GetCharArrayElements(text, NULL);
Fabrice Di Meglio4f810c82011-04-19 14:53:58 -0700450 jfloat result = 0;
Fabrice Di Megliob02d0ca2011-12-08 14:05:44 -0800451
Fabrice Di Meglio8fb50712011-05-13 18:51:21 -0700452 TextLayout::getTextRunAdvances(paint, textArray, index, count, textLength,
Victoria Lease626d3c22013-03-27 15:35:53 -0700453 bidiFlags, NULL /* dont need all advances */, &result);
Fabrice Di Megliob02d0ca2011-12-08 14:05:44 -0800454
Fabrice Di Meglio4f810c82011-04-19 14:53:58 -0700455 env->ReleaseCharArrayElements(text, const_cast<jchar*>(textArray), JNI_ABORT);
456 return result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800457 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700458
Ashok Bhata0398432014-01-20 20:08:01 +0000459 static jfloat measureText_StringIII(JNIEnv* env, jobject jpaint, jstring text, jint start, jint end,
Victoria Lease626d3c22013-03-27 15:35:53 -0700460 jint bidiFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800461 NPE_CHECK_RETURN_ZERO(env, jpaint);
462 NPE_CHECK_RETURN_ZERO(env, text);
Elliott Hughes8451b252011-04-07 19:17:57 -0700463
Fabrice Di Meglio51f383d2011-09-13 15:57:58 -0700464 size_t textLength = env->GetStringLength(text);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800465 int count = end - start;
Fabrice Di Meglio51f383d2011-09-13 15:57:58 -0700466 if ((start | count) < 0 || (size_t)end > textLength) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700467 doThrowAIOOBE(env);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800468 return 0;
469 }
Fabrice Di Meglio6ab90ed2011-08-08 16:19:38 -0700470 if (count == 0) {
471 return 0;
472 }
Fabrice Di Meglio6ab90ed2011-08-08 16:19:38 -0700473
474 const jchar* textArray = env->GetStringChars(text, NULL);
475 SkPaint* paint = GraphicsJNI::getNativePaint(env, jpaint);
Fabrice Di Meglio4f810c82011-04-19 14:53:58 -0700476 jfloat width = 0;
Elliott Hughes8451b252011-04-07 19:17:57 -0700477
Fabrice Di Meglio51f383d2011-09-13 15:57:58 -0700478 TextLayout::getTextRunAdvances(paint, textArray, start, count, textLength,
Victoria Lease626d3c22013-03-27 15:35:53 -0700479 bidiFlags, NULL /* dont need all advances */, &width);
Fabrice Di Meglio4f810c82011-04-19 14:53:58 -0700480
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800481 env->ReleaseStringChars(text, textArray);
482 return width;
483 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700484
Victoria Lease626d3c22013-03-27 15:35:53 -0700485 static jfloat measureText_StringI(JNIEnv* env, jobject jpaint, jstring text, jint bidiFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800486 NPE_CHECK_RETURN_ZERO(env, jpaint);
487 NPE_CHECK_RETURN_ZERO(env, text);
Elliott Hughes8451b252011-04-07 19:17:57 -0700488
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800489 size_t textLength = env->GetStringLength(text);
Fabrice Di Meglio6ab90ed2011-08-08 16:19:38 -0700490 if (textLength == 0) {
491 return 0;
492 }
493
494 const jchar* textArray = env->GetStringChars(text, NULL);
495 SkPaint* paint = GraphicsJNI::getNativePaint(env, jpaint);
Fabrice Di Meglio4f810c82011-04-19 14:53:58 -0700496 jfloat width = 0;
Fabrice Di Meglio6ab90ed2011-08-08 16:19:38 -0700497
Fabrice Di Meglio8fb50712011-05-13 18:51:21 -0700498 TextLayout::getTextRunAdvances(paint, textArray, 0, textLength, textLength,
Victoria Lease626d3c22013-03-27 15:35:53 -0700499 bidiFlags, NULL /* dont need all advances */, &width);
Fabrice Di Megliob02d0ca2011-12-08 14:05:44 -0800500
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800501 env->ReleaseStringChars(text, textArray);
502 return width;
503 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700504
Victoria Lease626d3c22013-03-27 15:35:53 -0700505 static int dotextwidths(JNIEnv* env, SkPaint* paint, const jchar text[], int count, jfloatArray widths,
506 jint bidiFlags) {
Fabrice Di Meglio6ab90ed2011-08-08 16:19:38 -0700507 NPE_CHECK_RETURN_ZERO(env, paint);
508 NPE_CHECK_RETURN_ZERO(env, text);
509
510 if (count < 0 || !widths) {
511 doThrowAIOOBE(env);
512 return 0;
513 }
514 if (count == 0) {
515 return 0;
516 }
517 size_t widthsLength = env->GetArrayLength(widths);
518 if ((size_t)count > widthsLength) {
519 doThrowAIOOBE(env);
520 return 0;
521 }
522
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800523 AutoJavaFloatArray autoWidths(env, widths, count);
524 jfloat* widthsArray = autoWidths.ptr();
Fabrice Di Meglio6ab90ed2011-08-08 16:19:38 -0700525
Fabrice Di Meglio8fb50712011-05-13 18:51:21 -0700526 TextLayout::getTextRunAdvances(paint, text, 0, count, count,
Victoria Lease626d3c22013-03-27 15:35:53 -0700527 bidiFlags, widthsArray, NULL /* dont need totalAdvance */);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800528
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800529 return count;
530 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700531
Ashok Bhata0398432014-01-20 20:08:01 +0000532 static jint getTextWidths___CIII_F(JNIEnv* env, jobject clazz, jlong paintHandle, jcharArray text,
533 jint index, jint count, jint bidiFlags, jfloatArray widths) {
534 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800535 const jchar* textArray = env->GetCharArrayElements(text, NULL);
Victoria Lease626d3c22013-03-27 15:35:53 -0700536 count = dotextwidths(env, paint, textArray + index, count, widths, bidiFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800537 env->ReleaseCharArrayElements(text, const_cast<jchar*>(textArray),
Elliott Hughes8451b252011-04-07 19:17:57 -0700538 JNI_ABORT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800539 return count;
540 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700541
Ashok Bhata0398432014-01-20 20:08:01 +0000542 static jint getTextWidths__StringIII_F(JNIEnv* env, jobject clazz, jlong paintHandle, jstring text,
543 jint start, jint end, jint bidiFlags, jfloatArray widths) {
544 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800545 const jchar* textArray = env->GetStringChars(text, NULL);
Victoria Lease626d3c22013-03-27 15:35:53 -0700546 int count = dotextwidths(env, paint, textArray + start, end - start, widths, bidiFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800547 env->ReleaseStringChars(text, textArray);
548 return count;
549 }
Doug Felt0c702b82010-05-14 10:55:42 -0700550
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700551 static int doTextGlyphs(JNIEnv* env, SkPaint* paint, const jchar* text, jint start, jint count,
552 jint contextCount, jint flags, jcharArray glyphs) {
553 NPE_CHECK_RETURN_ZERO(env, paint);
554 NPE_CHECK_RETURN_ZERO(env, text);
555
556 if ((start | count | contextCount) < 0 || contextCount < count || !glyphs) {
557 doThrowAIOOBE(env);
558 return 0;
559 }
560 if (count == 0) {
561 return 0;
562 }
563 size_t glypthsLength = env->GetArrayLength(glyphs);
564 if ((size_t)count > glypthsLength) {
565 doThrowAIOOBE(env);
566 return 0;
567 }
568
569 jchar* glyphsArray = env->GetCharArrayElements(glyphs, NULL);
570
571 sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint,
572 text, start, count, contextCount, flags);
573 const jchar* shapedGlyphs = value->getGlyphs();
574 size_t glyphsCount = value->getGlyphsCount();
575 memcpy(glyphsArray, shapedGlyphs, sizeof(jchar) * glyphsCount);
576
577 env->ReleaseCharArrayElements(glyphs, glyphsArray, JNI_ABORT);
578 return glyphsCount;
579 }
580
Ashok Bhata0398432014-01-20 20:08:01 +0000581 static jint getTextGlyphs__StringIIIII_C(JNIEnv* env, jobject clazz, jlong paintHandle,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700582 jstring text, jint start, jint end, jint contextStart, jint contextEnd, jint flags,
583 jcharArray glyphs) {
Ashok Bhata0398432014-01-20 20:08:01 +0000584 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700585 const jchar* textArray = env->GetStringChars(text, NULL);
586 int count = doTextGlyphs(env, paint, textArray + contextStart, start - contextStart,
587 end - start, contextEnd - contextStart, flags, glyphs);
588 env->ReleaseStringChars(text, textArray);
589 return count;
590 }
591
Doug Feltf7cb1f72010-07-01 16:20:43 -0700592 static jfloat doTextRunAdvances(JNIEnv *env, SkPaint *paint, const jchar *text,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700593 jint start, jint count, jint contextCount, jint flags,
Doug Felt0c702b82010-05-14 10:55:42 -0700594 jfloatArray advances, jint advancesIndex) {
Fabrice Di Meglio6ab90ed2011-08-08 16:19:38 -0700595 NPE_CHECK_RETURN_ZERO(env, paint);
596 NPE_CHECK_RETURN_ZERO(env, text);
597
598 if ((start | count | contextCount | advancesIndex) < 0 || contextCount < count) {
599 doThrowAIOOBE(env);
600 return 0;
601 }
602 if (count == 0) {
603 return 0;
604 }
605 if (advances) {
606 size_t advancesLength = env->GetArrayLength(advances);
607 if ((size_t)count > advancesLength) {
608 doThrowAIOOBE(env);
609 return 0;
610 }
611 }
Doug Felt0c702b82010-05-14 10:55:42 -0700612 jfloat advancesArray[count];
Fabrice Di Meglio6ab90ed2011-08-08 16:19:38 -0700613 jfloat totalAdvance = 0;
Doug Felt0c702b82010-05-14 10:55:42 -0700614
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700615 TextLayout::getTextRunAdvances(paint, text, start, count, contextCount, flags,
Fabrice Di Meglio79df5322011-09-19 15:17:56 -0700616 advancesArray, &totalAdvance);
Doug Felt0c702b82010-05-14 10:55:42 -0700617
618 if (advances != NULL) {
619 env->SetFloatArrayRegion(advances, advancesIndex, count, advancesArray);
620 }
621 return totalAdvance;
622 }
623
Ashok Bhata0398432014-01-20 20:08:01 +0000624 static jfloat getTextRunAdvances___CIIIII_FI(JNIEnv* env, jobject clazz, jlong paintHandle,
Doug Felt0c702b82010-05-14 10:55:42 -0700625 jcharArray text, jint index, jint count, jint contextIndex, jint contextCount,
Fabrice Di Meglio665f02c2013-03-20 14:56:05 -0700626 jint flags, jfloatArray advances, jint advancesIndex) {
Ashok Bhata0398432014-01-20 20:08:01 +0000627 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
Doug Felt0c702b82010-05-14 10:55:42 -0700628 jchar* textArray = env->GetCharArrayElements(text, NULL);
Fabrice Di Meglio665f02c2013-03-20 14:56:05 -0700629 jfloat result = doTextRunAdvances(env, paint, textArray + contextIndex,
630 index - contextIndex, count, contextCount, flags, advances, advancesIndex);
Doug Felt0c702b82010-05-14 10:55:42 -0700631 env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
632 return result;
633 }
634
Ashok Bhata0398432014-01-20 20:08:01 +0000635 static jfloat getTextRunAdvances__StringIIIII_FI(JNIEnv* env, jobject clazz, jlong paintHandle,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700636 jstring text, jint start, jint end, jint contextStart, jint contextEnd, jint flags,
Fabrice Di Meglio665f02c2013-03-20 14:56:05 -0700637 jfloatArray advances, jint advancesIndex) {
Ashok Bhata0398432014-01-20 20:08:01 +0000638 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
Doug Felt0c702b82010-05-14 10:55:42 -0700639 const jchar* textArray = env->GetStringChars(text, NULL);
Fabrice Di Meglio665f02c2013-03-20 14:56:05 -0700640 jfloat result = doTextRunAdvances(env, paint, textArray + contextStart,
641 start - contextStart, end - start, contextEnd - contextStart, flags,
642 advances, advancesIndex);
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -0700643 env->ReleaseStringChars(text, textArray);
644 return result;
645 }
646
Doug Felt0c702b82010-05-14 10:55:42 -0700647 static jint doTextRunCursor(JNIEnv *env, SkPaint* paint, const jchar *text, jint start,
Fabrice Di Meglioa4bf8112013-03-15 11:22:29 -0700648 jint count, jint flags, jint offset, jint opt) {
Fabrice Di Meglio4f810c82011-04-19 14:53:58 -0700649 jfloat scalarArray[count];
Fabrice Di Meglio9c418db2011-09-18 12:54:38 -0700650
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700651 TextLayout::getTextRunAdvances(paint, text, start, count, start + count, flags,
Fabrice Di Meglio79df5322011-09-19 15:17:56 -0700652 scalarArray, NULL /* dont need totalAdvance */);
Doug Felt0c702b82010-05-14 10:55:42 -0700653
Doug Felt0c702b82010-05-14 10:55:42 -0700654 jint pos = offset - start;
655 switch (opt) {
656 case AFTER:
657 if (pos < count) {
658 pos += 1;
659 }
660 // fall through
661 case AT_OR_AFTER:
662 while (pos < count && scalarArray[pos] == 0) {
663 ++pos;
664 }
665 break;
666 case BEFORE:
667 if (pos > 0) {
668 --pos;
669 }
670 // fall through
671 case AT_OR_BEFORE:
672 while (pos > 0 && scalarArray[pos] == 0) {
673 --pos;
674 }
675 break;
676 case AT:
677 default:
678 if (scalarArray[pos] == 0) {
679 pos = -1;
680 }
681 break;
682 }
683
684 if (pos != -1) {
685 pos += start;
686 }
687
688 return pos;
689 }
690
Ashok Bhata0398432014-01-20 20:08:01 +0000691 static jint getTextRunCursor___C(JNIEnv* env, jobject clazz, jlong paintHandle, jcharArray text,
Fabrice Di Meglioa4bf8112013-03-15 11:22:29 -0700692 jint contextStart, jint contextCount, jint flags, jint offset, jint cursorOpt) {
Ashok Bhata0398432014-01-20 20:08:01 +0000693 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
Doug Felt0c702b82010-05-14 10:55:42 -0700694 jchar* textArray = env->GetCharArrayElements(text, NULL);
Fabrice Di Meglioa4bf8112013-03-15 11:22:29 -0700695 jint result = doTextRunCursor(env, paint, textArray, contextStart, contextCount, flags,
Doug Felt0c702b82010-05-14 10:55:42 -0700696 offset, cursorOpt);
697 env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
698 return result;
699 }
700
Ashok Bhata0398432014-01-20 20:08:01 +0000701 static jint getTextRunCursor__String(JNIEnv* env, jobject clazz, jlong paintHandle, jstring text,
Fabrice Di Meglioa4bf8112013-03-15 11:22:29 -0700702 jint contextStart, jint contextEnd, jint flags, jint offset, jint cursorOpt) {
Ashok Bhata0398432014-01-20 20:08:01 +0000703 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
Doug Felt0c702b82010-05-14 10:55:42 -0700704 const jchar* textArray = env->GetStringChars(text, NULL);
705 jint result = doTextRunCursor(env, paint, textArray, contextStart,
Fabrice Di Meglioa4bf8112013-03-15 11:22:29 -0700706 contextEnd - contextStart, flags, offset, cursorOpt);
Doug Felt0c702b82010-05-14 10:55:42 -0700707 env->ReleaseStringChars(text, textArray);
708 return result;
709 }
710
Doug Feltf7cb1f72010-07-01 16:20:43 -0700711 static void getTextPath(JNIEnv* env, SkPaint* paint, const jchar* text, jint count,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700712 jint bidiFlags, jfloat x, jfloat y, SkPath *path) {
713 TextLayout::getTextPath(paint, text, count, bidiFlags, x, y, path);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800714 }
Doug Feltf7cb1f72010-07-01 16:20:43 -0700715
Ashok Bhata0398432014-01-20 20:08:01 +0000716 static void getTextPath___C(JNIEnv* env, jobject clazz, jlong paintHandle, jint bidiFlags,
717 jcharArray text, jint index, jint count, jfloat x, jfloat y, jlong pathHandle) {
718 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
719 SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
Doug Feltf7cb1f72010-07-01 16:20:43 -0700720 const jchar* textArray = env->GetCharArrayElements(text, NULL);
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700721 getTextPath(env, paint, textArray + index, count, bidiFlags, x, y, path);
Doug Feltf7cb1f72010-07-01 16:20:43 -0700722 env->ReleaseCharArrayElements(text, const_cast<jchar*>(textArray), JNI_ABORT);
723 }
724
Ashok Bhata0398432014-01-20 20:08:01 +0000725 static void getTextPath__String(JNIEnv* env, jobject clazz, jlong paintHandle, jint bidiFlags,
726 jstring text, jint start, jint end, jfloat x, jfloat y, jlong pathHandle) {
727 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
728 SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800729 const jchar* textArray = env->GetStringChars(text, NULL);
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700730 getTextPath(env, paint, textArray + start, end - start, bidiFlags, x, y, path);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800731 env->ReleaseStringChars(text, textArray);
732 }
Doug Feltf7cb1f72010-07-01 16:20:43 -0700733
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800734 static void setShadowLayer(JNIEnv* env, jobject jpaint, jfloat radius,
Ashok Bhata0398432014-01-20 20:08:01 +0000735 jfloat dx, jfloat dy, jint color) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800736 NPE_CHECK_RETURN_VOID(env, jpaint);
Elliott Hughes8451b252011-04-07 19:17:57 -0700737
738 SkPaint* paint = GraphicsJNI::getNativePaint(env, jpaint);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800739 if (radius <= 0) {
740 paint->setLooper(NULL);
741 }
742 else {
743 paint->setLooper(new SkBlurDrawLooper(SkFloatToScalar(radius),
744 SkFloatToScalar(dx),
745 SkFloatToScalar(dy),
746 (SkColor)color))->unref();
747 }
748 }
749
Fabrice Di Megliobd901de2012-01-20 17:41:55 -0800750 static int breakText(JNIEnv* env, SkPaint& paint, const jchar text[],
Victoria Lease626d3c22013-03-27 15:35:53 -0700751 int count, float maxWidth, jint bidiFlags, jfloatArray jmeasured,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800752 SkPaint::TextBufferDirection tbd) {
Fabrice Di Meglioa731b082012-01-23 18:18:45 -0800753 sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(&paint,
Victoria Lease626d3c22013-03-27 15:35:53 -0700754 text, 0, count, count, bidiFlags);
Fabrice Di Megliobd901de2012-01-20 17:41:55 -0800755 if (value == NULL) {
Fabrice Di Meglioa731b082012-01-23 18:18:45 -0800756 return 0;
Fabrice Di Megliobd901de2012-01-20 17:41:55 -0800757 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800758 SkScalar measured;
Fabrice Di Megliobd901de2012-01-20 17:41:55 -0800759 size_t bytes = paint.breakText(value->getGlyphs(), value->getGlyphsCount() << 1,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800760 SkFloatToScalar(maxWidth), &measured, tbd);
761 SkASSERT((bytes & 1) == 0);
762
763 if (jmeasured && env->GetArrayLength(jmeasured) > 0) {
764 AutoJavaFloatArray autoMeasured(env, jmeasured, 1);
765 jfloat* array = autoMeasured.ptr();
766 array[0] = SkScalarToFloat(measured);
767 }
768 return bytes >> 1;
769 }
770
Ashok Bhata0398432014-01-20 20:08:01 +0000771 static jint breakTextC(JNIEnv* env, jobject jpaint, jcharArray jtext,
772 jint index, jint count, jfloat maxWidth, jint bidiFlags, jfloatArray jmeasuredWidth) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800773 NPE_CHECK_RETURN_ZERO(env, jpaint);
774 NPE_CHECK_RETURN_ZERO(env, jtext);
775
776 SkPaint::TextBufferDirection tbd;
777 if (count < 0) {
778 tbd = SkPaint::kBackward_TextBufferDirection;
779 count = -count;
780 }
781 else {
782 tbd = SkPaint::kForward_TextBufferDirection;
783 }
784
785 if ((index < 0) || (index + count > env->GetArrayLength(jtext))) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700786 doThrowAIOOBE(env);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800787 return 0;
788 }
789
790 SkPaint* paint = GraphicsJNI::getNativePaint(env, jpaint);
791 const jchar* text = env->GetCharArrayElements(jtext, NULL);
792 count = breakText(env, *paint, text + index, count, maxWidth,
Victoria Lease626d3c22013-03-27 15:35:53 -0700793 bidiFlags, jmeasuredWidth, tbd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800794 env->ReleaseCharArrayElements(jtext, const_cast<jchar*>(text),
795 JNI_ABORT);
796 return count;
797 }
798
Ashok Bhata0398432014-01-20 20:08:01 +0000799 static jint breakTextS(JNIEnv* env, jobject jpaint, jstring jtext,
800 jboolean forwards, jfloat maxWidth, jint bidiFlags, jfloatArray jmeasuredWidth) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800801 NPE_CHECK_RETURN_ZERO(env, jpaint);
802 NPE_CHECK_RETURN_ZERO(env, jtext);
803
804 SkPaint::TextBufferDirection tbd = forwards ?
805 SkPaint::kForward_TextBufferDirection :
806 SkPaint::kBackward_TextBufferDirection;
807
808 SkPaint* paint = GraphicsJNI::getNativePaint(env, jpaint);
809 int count = env->GetStringLength(jtext);
810 const jchar* text = env->GetStringChars(jtext, NULL);
Victoria Lease626d3c22013-03-27 15:35:53 -0700811 count = breakText(env, *paint, text, count, maxWidth, bidiFlags, jmeasuredWidth, tbd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800812 env->ReleaseStringChars(jtext, text);
813 return count;
814 }
815
816 static void doTextBounds(JNIEnv* env, const jchar* text, int count,
Victoria Lease626d3c22013-03-27 15:35:53 -0700817 jobject bounds, const SkPaint& paint, jint bidiFlags) {
Romain Guy059e12c2012-11-28 17:35:51 -0800818 SkRect r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800819 SkIRect ir;
Elliott Hughes8451b252011-04-07 19:17:57 -0700820
Fabrice Di Meglioa731b082012-01-23 18:18:45 -0800821 sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(&paint,
Victoria Lease626d3c22013-03-27 15:35:53 -0700822 text, 0, count, count, bidiFlags);
Fabrice Di Megliobd901de2012-01-20 17:41:55 -0800823 if (value == NULL) {
Fabrice Di Meglioa731b082012-01-23 18:18:45 -0800824 return;
Fabrice Di Megliobd901de2012-01-20 17:41:55 -0800825 }
Fabrice Di Megliobd901de2012-01-20 17:41:55 -0800826 paint.measureText(value->getGlyphs(), value->getGlyphsCount() << 1, &r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800827 r.roundOut(&ir);
828 GraphicsJNI::irect_to_jrect(ir, env, bounds);
829 }
830
Ashok Bhata0398432014-01-20 20:08:01 +0000831 static void getStringBounds(JNIEnv* env, jobject, jlong paintHandle,
832 jstring text, jint start, jint end, jint bidiFlags, jobject bounds) {
833 const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800834 const jchar* textArray = env->GetStringChars(text, NULL);
Victoria Lease626d3c22013-03-27 15:35:53 -0700835 doTextBounds(env, textArray + start, end - start, bounds, *paint, bidiFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800836 env->ReleaseStringChars(text, textArray);
837 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700838
Ashok Bhata0398432014-01-20 20:08:01 +0000839 static void getCharArrayBounds(JNIEnv* env, jobject, jlong paintHandle,
840 jcharArray text, jint index, jint count, jint bidiFlags, jobject bounds) {
841 const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800842 const jchar* textArray = env->GetCharArrayElements(text, NULL);
Victoria Lease626d3c22013-03-27 15:35:53 -0700843 doTextBounds(env, textArray + index, count, bounds, *paint, bidiFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800844 env->ReleaseCharArrayElements(text, const_cast<jchar*>(textArray),
845 JNI_ABORT);
846 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700847
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800848};
849
850static JNINativeMethod methods[] = {
Ashok Bhata0398432014-01-20 20:08:01 +0000851 {"finalizer", "(J)V", (void*) SkPaintGlue::finalizer},
852 {"native_init","()J", (void*) SkPaintGlue::init},
853 {"native_initWithPaint","(J)J", (void*) SkPaintGlue::initWithPaint},
854 {"native_reset","(J)V", (void*) SkPaintGlue::reset},
855 {"native_set","(JJ)V", (void*) SkPaintGlue::assign},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800856 {"getFlags","()I", (void*) SkPaintGlue::getFlags},
857 {"setFlags","(I)V", (void*) SkPaintGlue::setFlags},
Dianne Hackbornf43fa572011-08-12 18:59:39 -0700858 {"getHinting","()I", (void*) SkPaintGlue::getHinting},
859 {"setHinting","(I)V", (void*) SkPaintGlue::setHinting},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800860 {"setAntiAlias","(Z)V", (void*) SkPaintGlue::setAntiAlias},
861 {"setSubpixelText","(Z)V", (void*) SkPaintGlue::setSubpixelText},
862 {"setLinearText","(Z)V", (void*) SkPaintGlue::setLinearText},
863 {"setUnderlineText","(Z)V", (void*) SkPaintGlue::setUnderlineText},
864 {"setStrikeThruText","(Z)V", (void*) SkPaintGlue::setStrikeThruText},
865 {"setFakeBoldText","(Z)V", (void*) SkPaintGlue::setFakeBoldText},
866 {"setFilterBitmap","(Z)V", (void*) SkPaintGlue::setFilterBitmap},
867 {"setDither","(Z)V", (void*) SkPaintGlue::setDither},
Ashok Bhata0398432014-01-20 20:08:01 +0000868 {"native_getStyle","(J)I", (void*) SkPaintGlue::getStyle},
869 {"native_setStyle","(JI)V", (void*) SkPaintGlue::setStyle},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800870 {"getColor","()I", (void*) SkPaintGlue::getColor},
871 {"setColor","(I)V", (void*) SkPaintGlue::setColor},
872 {"getAlpha","()I", (void*) SkPaintGlue::getAlpha},
873 {"setAlpha","(I)V", (void*) SkPaintGlue::setAlpha},
874 {"getStrokeWidth","()F", (void*) SkPaintGlue::getStrokeWidth},
875 {"setStrokeWidth","(F)V", (void*) SkPaintGlue::setStrokeWidth},
876 {"getStrokeMiter","()F", (void*) SkPaintGlue::getStrokeMiter},
877 {"setStrokeMiter","(F)V", (void*) SkPaintGlue::setStrokeMiter},
Ashok Bhata0398432014-01-20 20:08:01 +0000878 {"native_getStrokeCap","(J)I", (void*) SkPaintGlue::getStrokeCap},
879 {"native_setStrokeCap","(JI)V", (void*) SkPaintGlue::setStrokeCap},
880 {"native_getStrokeJoin","(J)I", (void*) SkPaintGlue::getStrokeJoin},
881 {"native_setStrokeJoin","(JI)V", (void*) SkPaintGlue::setStrokeJoin},
882 {"native_getFillPath","(JJJ)Z", (void*) SkPaintGlue::getFillPath},
883 {"native_setShader","(JJ)J", (void*) SkPaintGlue::setShader},
884 {"native_setColorFilter","(JJ)J", (void*) SkPaintGlue::setColorFilter},
885 {"native_setXfermode","(JJ)J", (void*) SkPaintGlue::setXfermode},
886 {"native_setPathEffect","(JJ)J", (void*) SkPaintGlue::setPathEffect},
887 {"native_setMaskFilter","(JJ)J", (void*) SkPaintGlue::setMaskFilter},
888 {"native_setTypeface","(JJ)J", (void*) SkPaintGlue::setTypeface},
889 {"native_setRasterizer","(JJ)J", (void*) SkPaintGlue::setRasterizer},
890 {"native_getTextAlign","(J)I", (void*) SkPaintGlue::getTextAlign},
891 {"native_setTextAlign","(JI)V", (void*) SkPaintGlue::setTextAlign},
892 {"native_setTextLocale","(JLjava/lang/String;)V", (void*) SkPaintGlue::setTextLocale},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800893 {"getTextSize","()F", (void*) SkPaintGlue::getTextSize},
894 {"setTextSize","(F)V", (void*) SkPaintGlue::setTextSize},
895 {"getTextScaleX","()F", (void*) SkPaintGlue::getTextScaleX},
896 {"setTextScaleX","(F)V", (void*) SkPaintGlue::setTextScaleX},
897 {"getTextSkewX","()F", (void*) SkPaintGlue::getTextSkewX},
898 {"setTextSkewX","(F)V", (void*) SkPaintGlue::setTextSkewX},
899 {"ascent","()F", (void*) SkPaintGlue::ascent},
900 {"descent","()F", (void*) SkPaintGlue::descent},
901 {"getFontMetrics", "(Landroid/graphics/Paint$FontMetrics;)F", (void*)SkPaintGlue::getFontMetrics},
902 {"getFontMetricsInt", "(Landroid/graphics/Paint$FontMetricsInt;)I", (void*)SkPaintGlue::getFontMetricsInt},
Victoria Lease626d3c22013-03-27 15:35:53 -0700903 {"native_measureText","([CIII)F", (void*) SkPaintGlue::measureText_CIII},
904 {"native_measureText","(Ljava/lang/String;I)F", (void*) SkPaintGlue::measureText_StringI},
905 {"native_measureText","(Ljava/lang/String;III)F", (void*) SkPaintGlue::measureText_StringIII},
906 {"native_breakText","([CIIFI[F)I", (void*) SkPaintGlue::breakTextC},
907 {"native_breakText","(Ljava/lang/String;ZFI[F)I", (void*) SkPaintGlue::breakTextS},
Ashok Bhata0398432014-01-20 20:08:01 +0000908 {"native_getTextWidths","(J[CIII[F)I", (void*) SkPaintGlue::getTextWidths___CIII_F},
909 {"native_getTextWidths","(JLjava/lang/String;III[F)I", (void*) SkPaintGlue::getTextWidths__StringIII_F},
910 {"native_getTextRunAdvances","(J[CIIIII[FI)F",
Fabrice Di Meglio665f02c2013-03-20 14:56:05 -0700911 (void*) SkPaintGlue::getTextRunAdvances___CIIIII_FI},
Ashok Bhata0398432014-01-20 20:08:01 +0000912 {"native_getTextRunAdvances","(JLjava/lang/String;IIIII[FI)F",
Fabrice Di Meglio665f02c2013-03-20 14:56:05 -0700913 (void*) SkPaintGlue::getTextRunAdvances__StringIIIII_FI},
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700914
915
Ashok Bhata0398432014-01-20 20:08:01 +0000916 {"native_getTextGlyphs","(JLjava/lang/String;IIIII[C)I",
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700917 (void*) SkPaintGlue::getTextGlyphs__StringIIIII_C},
Ashok Bhata0398432014-01-20 20:08:01 +0000918 {"native_getTextRunCursor", "(J[CIIIII)I", (void*) SkPaintGlue::getTextRunCursor___C},
919 {"native_getTextRunCursor", "(JLjava/lang/String;IIIII)I",
Doug Felt0c702b82010-05-14 10:55:42 -0700920 (void*) SkPaintGlue::getTextRunCursor__String},
Ashok Bhata0398432014-01-20 20:08:01 +0000921 {"native_getTextPath","(JI[CIIFFJ)V", (void*) SkPaintGlue::getTextPath___C},
922 {"native_getTextPath","(JILjava/lang/String;IIFFJ)V", (void*) SkPaintGlue::getTextPath__String},
923 {"nativeGetStringBounds", "(JLjava/lang/String;IIILandroid/graphics/Rect;)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800924 (void*) SkPaintGlue::getStringBounds },
Ashok Bhata0398432014-01-20 20:08:01 +0000925 {"nativeGetCharArrayBounds", "(J[CIIILandroid/graphics/Rect;)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800926 (void*) SkPaintGlue::getCharArrayBounds },
Romain Guy1e45aae2010-08-13 19:39:53 -0700927 {"nSetShadowLayer", "(FFFI)V", (void*)SkPaintGlue::setShadowLayer}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800928};
929
930static jfieldID req_fieldID(jfieldID id) {
931 SkASSERT(id);
932 return id;
933}
934
935int register_android_graphics_Paint(JNIEnv* env) {
936 gFontMetrics_class = env->FindClass("android/graphics/Paint$FontMetrics");
937 SkASSERT(gFontMetrics_class);
938 gFontMetrics_class = (jclass)env->NewGlobalRef(gFontMetrics_class);
939
940 gFontMetrics_fieldID.top = req_fieldID(env->GetFieldID(gFontMetrics_class, "top", "F"));
941 gFontMetrics_fieldID.ascent = req_fieldID(env->GetFieldID(gFontMetrics_class, "ascent", "F"));
942 gFontMetrics_fieldID.descent = req_fieldID(env->GetFieldID(gFontMetrics_class, "descent", "F"));
943 gFontMetrics_fieldID.bottom = req_fieldID(env->GetFieldID(gFontMetrics_class, "bottom", "F"));
944 gFontMetrics_fieldID.leading = req_fieldID(env->GetFieldID(gFontMetrics_class, "leading", "F"));
945
946 gFontMetricsInt_class = env->FindClass("android/graphics/Paint$FontMetricsInt");
947 SkASSERT(gFontMetricsInt_class);
948 gFontMetricsInt_class = (jclass)env->NewGlobalRef(gFontMetricsInt_class);
949
950 gFontMetricsInt_fieldID.top = req_fieldID(env->GetFieldID(gFontMetricsInt_class, "top", "I"));
951 gFontMetricsInt_fieldID.ascent = req_fieldID(env->GetFieldID(gFontMetricsInt_class, "ascent", "I"));
952 gFontMetricsInt_fieldID.descent = req_fieldID(env->GetFieldID(gFontMetricsInt_class, "descent", "I"));
953 gFontMetricsInt_fieldID.bottom = req_fieldID(env->GetFieldID(gFontMetricsInt_class, "bottom", "I"));
954 gFontMetricsInt_fieldID.leading = req_fieldID(env->GetFieldID(gFontMetricsInt_class, "leading", "I"));
955
956 int result = AndroidRuntime::registerNativeMethods(env, "android/graphics/Paint", methods,
957 sizeof(methods) / sizeof(methods[0]));
958 return result;
959}
960
961}