blob: a65262c0cb79fdbe730af728c9092e55d28e1d41 [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>
25
26#include "SkBlurDrawLooper.h"
27#include "SkColorFilter.h"
28#include "SkMaskFilter.h"
29#include "SkRasterizer.h"
30#include "SkShader.h"
31#include "SkTypeface.h"
32#include "SkXfermode.h"
Doug Felt0c702b82010-05-14 10:55:42 -070033#include "unicode/ushape.h"
Doug Feltf7cb1f72010-07-01 16:20:43 -070034#include "TextLayout.h"
Doug Felt0c702b82010-05-14 10:55:42 -070035
36// temporary for debugging
Chet Haase5c13d892010-10-08 08:37:55 -070037#include <Caches.h>
Doug Felt0c702b82010-05-14 10:55:42 -070038#include <utils/Log.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039
40namespace android {
41
42struct JMetricsID {
43 jfieldID top;
44 jfieldID ascent;
45 jfieldID descent;
46 jfieldID bottom;
47 jfieldID leading;
48};
49
50static jclass gFontMetrics_class;
51static JMetricsID gFontMetrics_fieldID;
52
53static jclass gFontMetricsInt_class;
54static JMetricsID gFontMetricsInt_fieldID;
55
Mike Reed3d63e012009-07-27 09:50:31 -040056static void defaultSettingsForAndroid(SkPaint* paint) {
Fabrice Di Meglioc511bee82012-01-05 13:30:54 -080057 // GlyphID encoding is required because we are using Harfbuzz shaping
58 paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding);
Mike Reed3d63e012009-07-27 09:50:31 -040059}
60
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061class SkPaintGlue {
62public:
Doug Felt0c702b82010-05-14 10:55:42 -070063 enum MoveOpt {
64 AFTER, AT_OR_AFTER, BEFORE, AT_OR_BEFORE, AT
65 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080066
67 static void finalizer(JNIEnv* env, jobject clazz, SkPaint* obj) {
68 delete obj;
69 }
70
71 static SkPaint* init(JNIEnv* env, jobject clazz) {
72 SkPaint* obj = new SkPaint();
Mike Reed3d63e012009-07-27 09:50:31 -040073 defaultSettingsForAndroid(obj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080074 return obj;
75 }
76
77 static SkPaint* intiWithPaint(JNIEnv* env, jobject clazz, SkPaint* paint) {
78 SkPaint* obj = new SkPaint(*paint);
79 return obj;
80 }
Elliott Hughes8451b252011-04-07 19:17:57 -070081
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082 static void reset(JNIEnv* env, jobject clazz, SkPaint* obj) {
83 obj->reset();
Mike Reed3d63e012009-07-27 09:50:31 -040084 defaultSettingsForAndroid(obj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085 }
Elliott Hughes8451b252011-04-07 19:17:57 -070086
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087 static void assign(JNIEnv* env, jobject clazz, SkPaint* dst, const SkPaint* src) {
88 *dst = *src;
89 }
Elliott Hughes8451b252011-04-07 19:17:57 -070090
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080091 static jint getFlags(JNIEnv* env, jobject paint) {
92 NPE_CHECK_RETURN_ZERO(env, paint);
93 return GraphicsJNI::getNativePaint(env, paint)->getFlags();
94 }
Elliott Hughes8451b252011-04-07 19:17:57 -070095
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096 static void setFlags(JNIEnv* env, jobject paint, jint flags) {
97 NPE_CHECK_RETURN_VOID(env, paint);
98 GraphicsJNI::getNativePaint(env, paint)->setFlags(flags);
99 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700100
Dianne Hackbornf43fa572011-08-12 18:59:39 -0700101 static jint getHinting(JNIEnv* env, jobject paint) {
102 NPE_CHECK_RETURN_ZERO(env, paint);
103 return GraphicsJNI::getNativePaint(env, paint)->getHinting()
104 == SkPaint::kNo_Hinting ? 0 : 1;
105 }
106
107 static void setHinting(JNIEnv* env, jobject paint, jint mode) {
108 NPE_CHECK_RETURN_VOID(env, paint);
109 GraphicsJNI::getNativePaint(env, paint)->setHinting(
110 mode == 0 ? SkPaint::kNo_Hinting : SkPaint::kSlight_Hinting);
111 }
112
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800113 static void setAntiAlias(JNIEnv* env, jobject paint, jboolean aa) {
114 NPE_CHECK_RETURN_VOID(env, paint);
115 GraphicsJNI::getNativePaint(env, paint)->setAntiAlias(aa);
116 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700117
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800118 static void setLinearText(JNIEnv* env, jobject paint, jboolean linearText) {
119 NPE_CHECK_RETURN_VOID(env, paint);
120 GraphicsJNI::getNativePaint(env, paint)->setLinearText(linearText);
121 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700122
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800123 static void setSubpixelText(JNIEnv* env, jobject paint, jboolean subpixelText) {
124 NPE_CHECK_RETURN_VOID(env, paint);
125 GraphicsJNI::getNativePaint(env, paint)->setSubpixelText(subpixelText);
126 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700127
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800128 static void setUnderlineText(JNIEnv* env, jobject paint, jboolean underlineText) {
129 NPE_CHECK_RETURN_VOID(env, paint);
130 GraphicsJNI::getNativePaint(env, paint)->setUnderlineText(underlineText);
131 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700132
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800133 static void setStrikeThruText(JNIEnv* env, jobject paint, jboolean strikeThruText) {
134 NPE_CHECK_RETURN_VOID(env, paint);
135 GraphicsJNI::getNativePaint(env, paint)->setStrikeThruText(strikeThruText);
136 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700137
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800138 static void setFakeBoldText(JNIEnv* env, jobject paint, jboolean fakeBoldText) {
139 NPE_CHECK_RETURN_VOID(env, paint);
140 GraphicsJNI::getNativePaint(env, paint)->setFakeBoldText(fakeBoldText);
141 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700142
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800143 static void setFilterBitmap(JNIEnv* env, jobject paint, jboolean filterBitmap) {
144 NPE_CHECK_RETURN_VOID(env, paint);
145 GraphicsJNI::getNativePaint(env, paint)->setFilterBitmap(filterBitmap);
146 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700147
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800148 static void setDither(JNIEnv* env, jobject paint, jboolean dither) {
149 NPE_CHECK_RETURN_VOID(env, paint);
150 GraphicsJNI::getNativePaint(env, paint)->setDither(dither);
151 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700152
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800153 static jint getStyle(JNIEnv* env, jobject clazz, SkPaint* obj) {
154 return obj->getStyle();
155 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700156
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800157 static void setStyle(JNIEnv* env, jobject clazz, SkPaint* obj, SkPaint::Style style) {
158 obj->setStyle(style);
159 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700160
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800161 static jint getColor(JNIEnv* env, jobject paint) {
162 NPE_CHECK_RETURN_ZERO(env, paint);
163 return GraphicsJNI::getNativePaint(env, paint)->getColor();
164 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700165
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800166 static jint getAlpha(JNIEnv* env, jobject paint) {
167 NPE_CHECK_RETURN_ZERO(env, paint);
168 return GraphicsJNI::getNativePaint(env, paint)->getAlpha();
169 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700170
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800171 static void setColor(JNIEnv* env, jobject paint, jint color) {
172 NPE_CHECK_RETURN_VOID(env, paint);
173 GraphicsJNI::getNativePaint(env, paint)->setColor(color);
174 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700175
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800176 static void setAlpha(JNIEnv* env, jobject paint, jint a) {
177 NPE_CHECK_RETURN_VOID(env, paint);
178 GraphicsJNI::getNativePaint(env, paint)->setAlpha(a);
179 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700180
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800181 static jfloat getStrokeWidth(JNIEnv* env, jobject paint) {
182 NPE_CHECK_RETURN_ZERO(env, paint);
183 return SkScalarToFloat(GraphicsJNI::getNativePaint(env, paint)->getStrokeWidth());
184 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700185
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800186 static void setStrokeWidth(JNIEnv* env, jobject paint, jfloat width) {
187 NPE_CHECK_RETURN_VOID(env, paint);
188 GraphicsJNI::getNativePaint(env, paint)->setStrokeWidth(SkFloatToScalar(width));
189 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700190
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800191 static jfloat getStrokeMiter(JNIEnv* env, jobject paint) {
192 NPE_CHECK_RETURN_ZERO(env, paint);
193 return SkScalarToFloat(GraphicsJNI::getNativePaint(env, paint)->getStrokeMiter());
194 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700195
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800196 static void setStrokeMiter(JNIEnv* env, jobject paint, jfloat miter) {
197 NPE_CHECK_RETURN_VOID(env, paint);
198 GraphicsJNI::getNativePaint(env, paint)->setStrokeMiter(SkFloatToScalar(miter));
199 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700200
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800201 static jint getStrokeCap(JNIEnv* env, jobject clazz, SkPaint* obj) {
202 return obj->getStrokeCap();
203 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700204
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800205 static void setStrokeCap(JNIEnv* env, jobject clazz, SkPaint* obj, SkPaint::Cap cap) {
206 obj->setStrokeCap(cap);
207 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700208
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800209 static jint getStrokeJoin(JNIEnv* env, jobject clazz, SkPaint* obj) {
210 return obj->getStrokeJoin();
211 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700212
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800213 static void setStrokeJoin(JNIEnv* env, jobject clazz, SkPaint* obj, SkPaint::Join join) {
214 obj->setStrokeJoin(join);
215 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700216
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800217 static jboolean getFillPath(JNIEnv* env, jobject clazz, SkPaint* obj, SkPath* src, SkPath* dst) {
218 return obj->getFillPath(*src, dst);
219 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700220
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800221 static SkShader* setShader(JNIEnv* env, jobject clazz, SkPaint* obj, SkShader* shader) {
222 return obj->setShader(shader);
223 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700224
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800225 static SkColorFilter* setColorFilter(JNIEnv* env, jobject clazz, SkPaint* obj, SkColorFilter* filter) {
226 return obj->setColorFilter(filter);
227 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700228
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800229 static SkXfermode* setXfermode(JNIEnv* env, jobject clazz, SkPaint* obj, SkXfermode* xfermode) {
230 return obj->setXfermode(xfermode);
231 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700232
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800233 static SkPathEffect* setPathEffect(JNIEnv* env, jobject clazz, SkPaint* obj, SkPathEffect* effect) {
234 return obj->setPathEffect(effect);
235 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700236
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800237 static SkMaskFilter* setMaskFilter(JNIEnv* env, jobject clazz, SkPaint* obj, SkMaskFilter* maskfilter) {
238 return obj->setMaskFilter(maskfilter);
239 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700240
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800241 static SkTypeface* setTypeface(JNIEnv* env, jobject clazz, SkPaint* obj, SkTypeface* typeface) {
242 return obj->setTypeface(typeface);
243 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700244
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800245 static SkRasterizer* setRasterizer(JNIEnv* env, jobject clazz, SkPaint* obj, SkRasterizer* rasterizer) {
246 return obj->setRasterizer(rasterizer);
247 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700248
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800249 static jint getTextAlign(JNIEnv* env, jobject clazz, SkPaint* obj) {
250 return obj->getTextAlign();
251 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700252
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800253 static void setTextAlign(JNIEnv* env, jobject clazz, SkPaint* obj, SkPaint::Align align) {
254 obj->setTextAlign(align);
255 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700256
Fabrice Di Meglio517825f2012-04-06 16:53:48 -0700257 static void setTextLocale(JNIEnv* env, jobject clazz, SkPaint* obj, jstring locale) {
258 const char* localeArray = env->GetStringUTFChars(locale, NULL);
259 SkString skLocale(localeArray);
260 obj->setTextLocale(skLocale);
261 env->ReleaseStringUTFChars(locale, localeArray);
262 }
263
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800264 static jfloat getTextSize(JNIEnv* env, jobject paint) {
265 NPE_CHECK_RETURN_ZERO(env, paint);
266 return SkScalarToFloat(GraphicsJNI::getNativePaint(env, paint)->getTextSize());
267 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700268
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800269 static void setTextSize(JNIEnv* env, jobject paint, jfloat textSize) {
270 NPE_CHECK_RETURN_VOID(env, paint);
271 GraphicsJNI::getNativePaint(env, paint)->setTextSize(SkFloatToScalar(textSize));
272 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700273
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800274 static jfloat getTextScaleX(JNIEnv* env, jobject paint) {
275 NPE_CHECK_RETURN_ZERO(env, paint);
276 return SkScalarToFloat(GraphicsJNI::getNativePaint(env, paint)->getTextScaleX());
277 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700278
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800279 static void setTextScaleX(JNIEnv* env, jobject paint, jfloat scaleX) {
280 NPE_CHECK_RETURN_VOID(env, paint);
281 GraphicsJNI::getNativePaint(env, paint)->setTextScaleX(SkFloatToScalar(scaleX));
282 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700283
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800284 static jfloat getTextSkewX(JNIEnv* env, jobject paint) {
285 NPE_CHECK_RETURN_ZERO(env, paint);
286 return SkScalarToFloat(GraphicsJNI::getNativePaint(env, paint)->getTextSkewX());
287 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700288
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800289 static void setTextSkewX(JNIEnv* env, jobject paint, jfloat skewX) {
290 NPE_CHECK_RETURN_VOID(env, paint);
291 GraphicsJNI::getNativePaint(env, paint)->setTextSkewX(SkFloatToScalar(skewX));
292 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700293
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800294 static jfloat ascent(JNIEnv* env, jobject paint) {
295 NPE_CHECK_RETURN_ZERO(env, paint);
296 SkPaint::FontMetrics metrics;
297 (void)GraphicsJNI::getNativePaint(env, paint)->getFontMetrics(&metrics);
298 return SkScalarToFloat(metrics.fAscent);
299 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700300
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800301 static jfloat descent(JNIEnv* env, jobject paint) {
302 NPE_CHECK_RETURN_ZERO(env, paint);
303 SkPaint::FontMetrics metrics;
304 (void)GraphicsJNI::getNativePaint(env, paint)->getFontMetrics(&metrics);
305 return SkScalarToFloat(metrics.fDescent);
306 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700307
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800308 static jfloat getFontMetrics(JNIEnv* env, jobject paint, jobject metricsObj) {
309 NPE_CHECK_RETURN_ZERO(env, paint);
310 SkPaint::FontMetrics metrics;
311 SkScalar spacing = GraphicsJNI::getNativePaint(env, paint)->getFontMetrics(&metrics);
312
313 if (metricsObj) {
314 SkASSERT(env->IsInstanceOf(metricsObj, gFontMetrics_class));
315 env->SetFloatField(metricsObj, gFontMetrics_fieldID.top, SkScalarToFloat(metrics.fTop));
316 env->SetFloatField(metricsObj, gFontMetrics_fieldID.ascent, SkScalarToFloat(metrics.fAscent));
317 env->SetFloatField(metricsObj, gFontMetrics_fieldID.descent, SkScalarToFloat(metrics.fDescent));
318 env->SetFloatField(metricsObj, gFontMetrics_fieldID.bottom, SkScalarToFloat(metrics.fBottom));
319 env->SetFloatField(metricsObj, gFontMetrics_fieldID.leading, SkScalarToFloat(metrics.fLeading));
320 }
321 return SkScalarToFloat(spacing);
322 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700323
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800324 static jint getFontMetricsInt(JNIEnv* env, jobject paint, jobject metricsObj) {
325 NPE_CHECK_RETURN_ZERO(env, paint);
326 SkPaint::FontMetrics metrics;
Elliott Hughes8451b252011-04-07 19:17:57 -0700327
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800328 GraphicsJNI::getNativePaint(env, paint)->getFontMetrics(&metrics);
329 int ascent = SkScalarRound(metrics.fAscent);
330 int descent = SkScalarRound(metrics.fDescent);
331 int leading = SkScalarRound(metrics.fLeading);
332
333 if (metricsObj) {
334 SkASSERT(env->IsInstanceOf(metricsObj, gFontMetricsInt_class));
335 env->SetIntField(metricsObj, gFontMetricsInt_fieldID.top, SkScalarFloor(metrics.fTop));
336 env->SetIntField(metricsObj, gFontMetricsInt_fieldID.ascent, ascent);
337 env->SetIntField(metricsObj, gFontMetricsInt_fieldID.descent, descent);
338 env->SetIntField(metricsObj, gFontMetricsInt_fieldID.bottom, SkScalarCeil(metrics.fBottom));
339 env->SetIntField(metricsObj, gFontMetricsInt_fieldID.leading, leading);
340 }
341 return descent - ascent + leading;
342 }
343
344 static jfloat measureText_CII(JNIEnv* env, jobject jpaint, jcharArray text, int index, int count) {
345 NPE_CHECK_RETURN_ZERO(env, jpaint);
346 NPE_CHECK_RETURN_ZERO(env, text);
347
348 size_t textLength = env->GetArrayLength(text);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800349 if ((index | count) < 0 || (size_t)(index + count) > textLength) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700350 doThrowAIOOBE(env);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800351 return 0;
352 }
Fabrice Di Meglio6ab90ed2011-08-08 16:19:38 -0700353 if (count == 0) {
354 return 0;
355 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800356
Fabrice Di Meglio4f810c82011-04-19 14:53:58 -0700357 SkPaint* paint = GraphicsJNI::getNativePaint(env, jpaint);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800358 const jchar* textArray = env->GetCharArrayElements(text, NULL);
Fabrice Di Meglio4f810c82011-04-19 14:53:58 -0700359 jfloat result = 0;
Fabrice Di Megliob02d0ca2011-12-08 14:05:44 -0800360
Fabrice Di Meglio8fb50712011-05-13 18:51:21 -0700361 TextLayout::getTextRunAdvances(paint, textArray, index, count, textLength,
Fabrice Di Meglio79df5322011-09-19 15:17:56 -0700362 paint->getFlags(), NULL /* dont need all advances */, &result);
Fabrice Di Megliob02d0ca2011-12-08 14:05:44 -0800363
Fabrice Di Meglio4f810c82011-04-19 14:53:58 -0700364 env->ReleaseCharArrayElements(text, const_cast<jchar*>(textArray), JNI_ABORT);
365 return result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800366 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700367
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800368 static jfloat measureText_StringII(JNIEnv* env, jobject jpaint, jstring text, int start, int end) {
369 NPE_CHECK_RETURN_ZERO(env, jpaint);
370 NPE_CHECK_RETURN_ZERO(env, text);
Elliott Hughes8451b252011-04-07 19:17:57 -0700371
Fabrice Di Meglio51f383d2011-09-13 15:57:58 -0700372 size_t textLength = env->GetStringLength(text);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800373 int count = end - start;
Fabrice Di Meglio51f383d2011-09-13 15:57:58 -0700374 if ((start | count) < 0 || (size_t)end > textLength) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700375 doThrowAIOOBE(env);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800376 return 0;
377 }
Fabrice Di Meglio6ab90ed2011-08-08 16:19:38 -0700378 if (count == 0) {
379 return 0;
380 }
Fabrice Di Meglio6ab90ed2011-08-08 16:19:38 -0700381
382 const jchar* textArray = env->GetStringChars(text, NULL);
383 SkPaint* paint = GraphicsJNI::getNativePaint(env, jpaint);
Fabrice Di Meglio4f810c82011-04-19 14:53:58 -0700384 jfloat width = 0;
Elliott Hughes8451b252011-04-07 19:17:57 -0700385
Fabrice Di Meglio51f383d2011-09-13 15:57:58 -0700386 TextLayout::getTextRunAdvances(paint, textArray, start, count, textLength,
Fabrice Di Meglio79df5322011-09-19 15:17:56 -0700387 paint->getFlags(), NULL /* dont need all advances */, &width);
Fabrice Di Meglio4f810c82011-04-19 14:53:58 -0700388
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800389 env->ReleaseStringChars(text, textArray);
390 return width;
391 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700392
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800393 static jfloat measureText_String(JNIEnv* env, jobject jpaint, jstring text) {
394 NPE_CHECK_RETURN_ZERO(env, jpaint);
395 NPE_CHECK_RETURN_ZERO(env, text);
Elliott Hughes8451b252011-04-07 19:17:57 -0700396
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800397 size_t textLength = env->GetStringLength(text);
Fabrice Di Meglio6ab90ed2011-08-08 16:19:38 -0700398 if (textLength == 0) {
399 return 0;
400 }
401
402 const jchar* textArray = env->GetStringChars(text, NULL);
403 SkPaint* paint = GraphicsJNI::getNativePaint(env, jpaint);
Fabrice Di Meglio4f810c82011-04-19 14:53:58 -0700404 jfloat width = 0;
Fabrice Di Meglio6ab90ed2011-08-08 16:19:38 -0700405
Fabrice Di Meglio8fb50712011-05-13 18:51:21 -0700406 TextLayout::getTextRunAdvances(paint, textArray, 0, textLength, textLength,
Fabrice Di Meglio79df5322011-09-19 15:17:56 -0700407 paint->getFlags(), NULL /* dont need all advances */, &width);
Fabrice Di Megliob02d0ca2011-12-08 14:05:44 -0800408
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800409 env->ReleaseStringChars(text, textArray);
410 return width;
411 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700412
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800413 static int dotextwidths(JNIEnv* env, SkPaint* paint, const jchar text[], int count, jfloatArray widths) {
Fabrice Di Meglio6ab90ed2011-08-08 16:19:38 -0700414 NPE_CHECK_RETURN_ZERO(env, paint);
415 NPE_CHECK_RETURN_ZERO(env, text);
416
417 if (count < 0 || !widths) {
418 doThrowAIOOBE(env);
419 return 0;
420 }
421 if (count == 0) {
422 return 0;
423 }
424 size_t widthsLength = env->GetArrayLength(widths);
425 if ((size_t)count > widthsLength) {
426 doThrowAIOOBE(env);
427 return 0;
428 }
429
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800430 AutoJavaFloatArray autoWidths(env, widths, count);
431 jfloat* widthsArray = autoWidths.ptr();
Fabrice Di Meglio6ab90ed2011-08-08 16:19:38 -0700432
Fabrice Di Meglio8fb50712011-05-13 18:51:21 -0700433 TextLayout::getTextRunAdvances(paint, text, 0, count, count,
Fabrice Di Meglio79df5322011-09-19 15:17:56 -0700434 paint->getFlags(), widthsArray, NULL /* dont need totalAdvance */);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800435
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800436 return count;
437 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700438
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800439 static int getTextWidths___CII_F(JNIEnv* env, jobject clazz, SkPaint* paint, jcharArray text, int index, int count, jfloatArray widths) {
440 const jchar* textArray = env->GetCharArrayElements(text, NULL);
441 count = dotextwidths(env, paint, textArray + index, count, widths);
442 env->ReleaseCharArrayElements(text, const_cast<jchar*>(textArray),
Elliott Hughes8451b252011-04-07 19:17:57 -0700443 JNI_ABORT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800444 return count;
445 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700446
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800447 static int getTextWidths__StringII_F(JNIEnv* env, jobject clazz, SkPaint* paint, jstring text,
448 int start, int end, jfloatArray widths) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800449 const jchar* textArray = env->GetStringChars(text, NULL);
450 int count = dotextwidths(env, paint, textArray + start, end - start, widths);
451 env->ReleaseStringChars(text, textArray);
452 return count;
453 }
Doug Felt0c702b82010-05-14 10:55:42 -0700454
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800455 static int doTextGlyphs(JNIEnv* env, SkPaint* paint, const jchar* text, jint start, jint count,
456 jint contextCount, jint flags, jcharArray glyphs) {
Fabrice Di Meglio6ab90ed2011-08-08 16:19:38 -0700457 NPE_CHECK_RETURN_ZERO(env, paint);
458 NPE_CHECK_RETURN_ZERO(env, text);
459
460 if ((start | count | contextCount) < 0 || contextCount < count || !glyphs) {
461 doThrowAIOOBE(env);
462 return 0;
463 }
464 if (count == 0) {
465 return 0;
466 }
467 size_t glypthsLength = env->GetArrayLength(glyphs);
468 if ((size_t)count > glypthsLength) {
469 doThrowAIOOBE(env);
470 return 0;
471 }
472
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800473 jchar* glyphsArray = env->GetCharArrayElements(glyphs, NULL);
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800474
Fabrice Di Meglioa731b082012-01-23 18:18:45 -0800475 sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint,
476 text, start, count, contextCount, flags);
477 const jchar* shapedGlyphs = value->getGlyphs();
478 size_t glyphsCount = value->getGlyphsCount();
Fabrice Di Meglio5c863f72011-10-05 18:11:59 -0700479 memcpy(glyphsArray, shapedGlyphs, sizeof(jchar) * glyphsCount);
480
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -0700481 env->ReleaseCharArrayElements(glyphs, glyphsArray, JNI_ABORT);
Fabrice Di Meglio5c863f72011-10-05 18:11:59 -0700482 return glyphsCount;
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800483 }
484
485 static int getTextGlyphs__StringIIIII_C(JNIEnv* env, jobject clazz, SkPaint* paint,
486 jstring text, jint start, jint end, jint contextStart, jint contextEnd, jint flags,
487 jcharArray glyphs) {
488 const jchar* textArray = env->GetStringChars(text, NULL);
489 int count = doTextGlyphs(env, paint, textArray + contextStart, start - contextStart,
490 end - start, contextEnd - contextStart, flags, glyphs);
491 env->ReleaseStringChars(text, textArray);
492 return count;
493 }
494
Doug Feltf7cb1f72010-07-01 16:20:43 -0700495 static jfloat doTextRunAdvances(JNIEnv *env, SkPaint *paint, const jchar *text,
496 jint start, jint count, jint contextCount, jint flags,
Doug Felt0c702b82010-05-14 10:55:42 -0700497 jfloatArray advances, jint advancesIndex) {
Fabrice Di Meglio6ab90ed2011-08-08 16:19:38 -0700498 NPE_CHECK_RETURN_ZERO(env, paint);
499 NPE_CHECK_RETURN_ZERO(env, text);
500
501 if ((start | count | contextCount | advancesIndex) < 0 || contextCount < count) {
502 doThrowAIOOBE(env);
503 return 0;
504 }
505 if (count == 0) {
506 return 0;
507 }
508 if (advances) {
509 size_t advancesLength = env->GetArrayLength(advances);
510 if ((size_t)count > advancesLength) {
511 doThrowAIOOBE(env);
512 return 0;
513 }
514 }
Doug Felt0c702b82010-05-14 10:55:42 -0700515 jfloat advancesArray[count];
Fabrice Di Meglio6ab90ed2011-08-08 16:19:38 -0700516 jfloat totalAdvance = 0;
Doug Felt0c702b82010-05-14 10:55:42 -0700517
Doug Feltf7cb1f72010-07-01 16:20:43 -0700518 TextLayout::getTextRunAdvances(paint, text, start, count, contextCount, flags,
Fabrice Di Meglio79df5322011-09-19 15:17:56 -0700519 advancesArray, &totalAdvance);
Doug Felt0c702b82010-05-14 10:55:42 -0700520
521 if (advances != NULL) {
522 env->SetFloatArrayRegion(advances, advancesIndex, count, advancesArray);
523 }
524 return totalAdvance;
525 }
526
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -0700527 static jfloat doTextRunAdvancesICU(JNIEnv *env, SkPaint *paint, const jchar *text,
528 jint start, jint count, jint contextCount, jint flags,
529 jfloatArray advances, jint advancesIndex) {
Fabrice Di Meglio6ab90ed2011-08-08 16:19:38 -0700530 NPE_CHECK_RETURN_ZERO(env, paint);
531 NPE_CHECK_RETURN_ZERO(env, text);
532
533 if ((start | count | contextCount | advancesIndex) < 0 || contextCount < count) {
534 doThrowAIOOBE(env);
535 return 0;
536 }
537 if (count == 0) {
538 return 0;
539 }
540 if (advances) {
541 size_t advancesLength = env->GetArrayLength(advances);
542 if ((size_t)count > advancesLength) {
543 doThrowAIOOBE(env);
544 return 0;
545 }
546 }
547
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -0700548 jfloat advancesArray[count];
Fabrice Di Meglio6ab90ed2011-08-08 16:19:38 -0700549 jfloat totalAdvance = 0;
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -0700550
551 TextLayout::getTextRunAdvancesICU(paint, text, start, count, contextCount, flags,
552 advancesArray, totalAdvance);
553
554 if (advances != NULL) {
555 env->SetFloatArrayRegion(advances, advancesIndex, count, advancesArray);
556 }
557 return totalAdvance;
558 }
559
Fabrice Di Meglio0a1413e2011-04-21 17:36:26 -0700560 static float getTextRunAdvances___CIIIII_FII(JNIEnv* env, jobject clazz, SkPaint* paint,
Doug Felt0c702b82010-05-14 10:55:42 -0700561 jcharArray text, jint index, jint count, jint contextIndex, jint contextCount,
Fabrice Di Meglio0a1413e2011-04-21 17:36:26 -0700562 jint flags, jfloatArray advances, jint advancesIndex, jint reserved) {
Doug Felt0c702b82010-05-14 10:55:42 -0700563 jchar* textArray = env->GetCharArrayElements(text, NULL);
Fabrice Di Meglio0a1413e2011-04-21 17:36:26 -0700564 jfloat result = (reserved == 0) ?
565 doTextRunAdvances(env, paint, textArray + contextIndex, index - contextIndex,
566 count, contextCount, flags, advances, advancesIndex) :
567 doTextRunAdvancesICU(env, paint, textArray + contextIndex, index - contextIndex,
568 count, contextCount, flags, advances, advancesIndex);
Doug Felt0c702b82010-05-14 10:55:42 -0700569 env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
570 return result;
571 }
572
Fabrice Di Meglio0a1413e2011-04-21 17:36:26 -0700573 static float getTextRunAdvances__StringIIIII_FII(JNIEnv* env, jobject clazz, SkPaint* paint,
Doug Felt0c702b82010-05-14 10:55:42 -0700574 jstring text, jint start, jint end, jint contextStart, jint contextEnd, jint flags,
Fabrice Di Meglio0a1413e2011-04-21 17:36:26 -0700575 jfloatArray advances, jint advancesIndex, jint reserved) {
Doug Felt0c702b82010-05-14 10:55:42 -0700576 const jchar* textArray = env->GetStringChars(text, NULL);
Fabrice Di Meglio0a1413e2011-04-21 17:36:26 -0700577 jfloat result = (reserved == 0) ?
578 doTextRunAdvances(env, paint, textArray + contextStart, start - contextStart,
579 end - start, contextEnd - contextStart, flags, advances, advancesIndex) :
580 doTextRunAdvancesICU(env, paint, textArray + contextStart, start - contextStart,
581 end - start, contextEnd - contextStart, flags, advances, advancesIndex);
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -0700582 env->ReleaseStringChars(text, textArray);
583 return result;
584 }
585
Doug Felt0c702b82010-05-14 10:55:42 -0700586 static jint doTextRunCursor(JNIEnv *env, SkPaint* paint, const jchar *text, jint start,
587 jint count, jint flags, jint offset, jint opt) {
Fabrice Di Meglio4f810c82011-04-19 14:53:58 -0700588 jfloat scalarArray[count];
Fabrice Di Meglio9c418db2011-09-18 12:54:38 -0700589
Fabrice Di Meglio4f810c82011-04-19 14:53:58 -0700590 TextLayout::getTextRunAdvances(paint, text, start, count, count, flags,
Fabrice Di Meglio79df5322011-09-19 15:17:56 -0700591 scalarArray, NULL /* dont need totalAdvance */);
Doug Felt0c702b82010-05-14 10:55:42 -0700592
Doug Felt0c702b82010-05-14 10:55:42 -0700593 jint pos = offset - start;
594 switch (opt) {
595 case AFTER:
596 if (pos < count) {
597 pos += 1;
598 }
599 // fall through
600 case AT_OR_AFTER:
601 while (pos < count && scalarArray[pos] == 0) {
602 ++pos;
603 }
604 break;
605 case BEFORE:
606 if (pos > 0) {
607 --pos;
608 }
609 // fall through
610 case AT_OR_BEFORE:
611 while (pos > 0 && scalarArray[pos] == 0) {
612 --pos;
613 }
614 break;
615 case AT:
616 default:
617 if (scalarArray[pos] == 0) {
618 pos = -1;
619 }
620 break;
621 }
622
623 if (pos != -1) {
624 pos += start;
625 }
626
627 return pos;
628 }
629
630 static jint getTextRunCursor___C(JNIEnv* env, jobject clazz, SkPaint* paint, jcharArray text,
631 jint contextStart, jint contextCount, jint flags, jint offset, jint cursorOpt) {
632 jchar* textArray = env->GetCharArrayElements(text, NULL);
633 jint result = doTextRunCursor(env, paint, textArray, contextStart, contextCount, flags,
634 offset, cursorOpt);
635 env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
636 return result;
637 }
638
639 static jint getTextRunCursor__String(JNIEnv* env, jobject clazz, SkPaint* paint, jstring text,
640 jint contextStart, jint contextEnd, jint flags, jint offset, jint cursorOpt) {
641 const jchar* textArray = env->GetStringChars(text, NULL);
642 jint result = doTextRunCursor(env, paint, textArray, contextStart,
643 contextEnd - contextStart, flags, offset, cursorOpt);
644 env->ReleaseStringChars(text, textArray);
645 return result;
646 }
647
Doug Feltf7cb1f72010-07-01 16:20:43 -0700648 static void getTextPath(JNIEnv* env, SkPaint* paint, const jchar* text, jint count,
649 jint bidiFlags, jfloat x, jfloat y, SkPath *path) {
650 TextLayout::getTextPath(paint, text, count, bidiFlags, x, y, path);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800651 }
Doug Feltf7cb1f72010-07-01 16:20:43 -0700652
653 static void getTextPath___C(JNIEnv* env, jobject clazz, SkPaint* paint, jint bidiFlags,
654 jcharArray text, int index, int count, jfloat x, jfloat y, SkPath* path) {
655 const jchar* textArray = env->GetCharArrayElements(text, NULL);
656 getTextPath(env, paint, textArray + index, count, bidiFlags, x, y, path);
657 env->ReleaseCharArrayElements(text, const_cast<jchar*>(textArray), JNI_ABORT);
658 }
659
660 static void getTextPath__String(JNIEnv* env, jobject clazz, SkPaint* paint, jint bidiFlags,
661 jstring text, int start, int end, jfloat x, jfloat y, SkPath* path) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800662 const jchar* textArray = env->GetStringChars(text, NULL);
Doug Feltf7cb1f72010-07-01 16:20:43 -0700663 getTextPath(env, paint, textArray + start, end - start, bidiFlags, x, y, path);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800664 env->ReleaseStringChars(text, textArray);
665 }
Doug Feltf7cb1f72010-07-01 16:20:43 -0700666
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800667 static void setShadowLayer(JNIEnv* env, jobject jpaint, jfloat radius,
668 jfloat dx, jfloat dy, int color) {
669 NPE_CHECK_RETURN_VOID(env, jpaint);
Elliott Hughes8451b252011-04-07 19:17:57 -0700670
671 SkPaint* paint = GraphicsJNI::getNativePaint(env, jpaint);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800672 if (radius <= 0) {
673 paint->setLooper(NULL);
674 }
675 else {
676 paint->setLooper(new SkBlurDrawLooper(SkFloatToScalar(radius),
677 SkFloatToScalar(dx),
678 SkFloatToScalar(dy),
679 (SkColor)color))->unref();
680 }
681 }
682
Fabrice Di Megliobd901de2012-01-20 17:41:55 -0800683 static int breakText(JNIEnv* env, SkPaint& paint, const jchar text[],
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800684 int count, float maxWidth, jfloatArray jmeasured,
685 SkPaint::TextBufferDirection tbd) {
Fabrice Di Meglioa731b082012-01-23 18:18:45 -0800686 sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(&paint,
687 text, 0, count, count, paint.getFlags());
Fabrice Di Megliobd901de2012-01-20 17:41:55 -0800688 if (value == NULL) {
Fabrice Di Meglioa731b082012-01-23 18:18:45 -0800689 return 0;
Fabrice Di Megliobd901de2012-01-20 17:41:55 -0800690 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800691 SkScalar measured;
Fabrice Di Megliobd901de2012-01-20 17:41:55 -0800692 size_t bytes = paint.breakText(value->getGlyphs(), value->getGlyphsCount() << 1,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800693 SkFloatToScalar(maxWidth), &measured, tbd);
694 SkASSERT((bytes & 1) == 0);
695
696 if (jmeasured && env->GetArrayLength(jmeasured) > 0) {
697 AutoJavaFloatArray autoMeasured(env, jmeasured, 1);
698 jfloat* array = autoMeasured.ptr();
699 array[0] = SkScalarToFloat(measured);
700 }
701 return bytes >> 1;
702 }
703
704 static int breakTextC(JNIEnv* env, jobject jpaint, jcharArray jtext,
705 int index, int count, float maxWidth, jfloatArray jmeasuredWidth) {
706 NPE_CHECK_RETURN_ZERO(env, jpaint);
707 NPE_CHECK_RETURN_ZERO(env, jtext);
708
709 SkPaint::TextBufferDirection tbd;
710 if (count < 0) {
711 tbd = SkPaint::kBackward_TextBufferDirection;
712 count = -count;
713 }
714 else {
715 tbd = SkPaint::kForward_TextBufferDirection;
716 }
717
718 if ((index < 0) || (index + count > env->GetArrayLength(jtext))) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700719 doThrowAIOOBE(env);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800720 return 0;
721 }
722
723 SkPaint* paint = GraphicsJNI::getNativePaint(env, jpaint);
724 const jchar* text = env->GetCharArrayElements(jtext, NULL);
725 count = breakText(env, *paint, text + index, count, maxWidth,
726 jmeasuredWidth, tbd);
727 env->ReleaseCharArrayElements(jtext, const_cast<jchar*>(text),
728 JNI_ABORT);
729 return count;
730 }
731
732 static int breakTextS(JNIEnv* env, jobject jpaint, jstring jtext,
733 bool forwards, float maxWidth, jfloatArray jmeasuredWidth) {
734 NPE_CHECK_RETURN_ZERO(env, jpaint);
735 NPE_CHECK_RETURN_ZERO(env, jtext);
736
737 SkPaint::TextBufferDirection tbd = forwards ?
738 SkPaint::kForward_TextBufferDirection :
739 SkPaint::kBackward_TextBufferDirection;
740
741 SkPaint* paint = GraphicsJNI::getNativePaint(env, jpaint);
742 int count = env->GetStringLength(jtext);
743 const jchar* text = env->GetStringChars(jtext, NULL);
744 count = breakText(env, *paint, text, count, maxWidth,
745 jmeasuredWidth, tbd);
746 env->ReleaseStringChars(jtext, text);
747 return count;
748 }
749
750 static void doTextBounds(JNIEnv* env, const jchar* text, int count,
751 jobject bounds, const SkPaint& paint)
752 {
753 SkRect r;
754 SkIRect ir;
Elliott Hughes8451b252011-04-07 19:17:57 -0700755
Fabrice Di Meglioa731b082012-01-23 18:18:45 -0800756 sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(&paint,
757 text, 0, count, count, paint.getFlags());
Fabrice Di Megliobd901de2012-01-20 17:41:55 -0800758 if (value == NULL) {
Fabrice Di Meglioa731b082012-01-23 18:18:45 -0800759 return;
Fabrice Di Megliobd901de2012-01-20 17:41:55 -0800760 }
Fabrice Di Megliobd901de2012-01-20 17:41:55 -0800761 paint.measureText(value->getGlyphs(), value->getGlyphsCount() << 1, &r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800762 r.roundOut(&ir);
763 GraphicsJNI::irect_to_jrect(ir, env, bounds);
764 }
765
766 static void getStringBounds(JNIEnv* env, jobject, const SkPaint* paint,
767 jstring text, int start, int end, jobject bounds)
768 {
769 const jchar* textArray = env->GetStringChars(text, NULL);
770 doTextBounds(env, textArray + start, end - start, bounds, *paint);
771 env->ReleaseStringChars(text, textArray);
772 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700773
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800774 static void getCharArrayBounds(JNIEnv* env, jobject, const SkPaint* paint,
775 jcharArray text, int index, int count, jobject bounds)
776 {
777 const jchar* textArray = env->GetCharArrayElements(text, NULL);
778 doTextBounds(env, textArray + index, count, bounds, *paint);
779 env->ReleaseCharArrayElements(text, const_cast<jchar*>(textArray),
780 JNI_ABORT);
781 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700782
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800783};
784
785static JNINativeMethod methods[] = {
786 {"finalizer", "(I)V", (void*) SkPaintGlue::finalizer},
787 {"native_init","()I", (void*) SkPaintGlue::init},
788 {"native_initWithPaint","(I)I", (void*) SkPaintGlue::intiWithPaint},
789 {"native_reset","(I)V", (void*) SkPaintGlue::reset},
790 {"native_set","(II)V", (void*) SkPaintGlue::assign},
791 {"getFlags","()I", (void*) SkPaintGlue::getFlags},
792 {"setFlags","(I)V", (void*) SkPaintGlue::setFlags},
Dianne Hackbornf43fa572011-08-12 18:59:39 -0700793 {"getHinting","()I", (void*) SkPaintGlue::getHinting},
794 {"setHinting","(I)V", (void*) SkPaintGlue::setHinting},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800795 {"setAntiAlias","(Z)V", (void*) SkPaintGlue::setAntiAlias},
796 {"setSubpixelText","(Z)V", (void*) SkPaintGlue::setSubpixelText},
797 {"setLinearText","(Z)V", (void*) SkPaintGlue::setLinearText},
798 {"setUnderlineText","(Z)V", (void*) SkPaintGlue::setUnderlineText},
799 {"setStrikeThruText","(Z)V", (void*) SkPaintGlue::setStrikeThruText},
800 {"setFakeBoldText","(Z)V", (void*) SkPaintGlue::setFakeBoldText},
801 {"setFilterBitmap","(Z)V", (void*) SkPaintGlue::setFilterBitmap},
802 {"setDither","(Z)V", (void*) SkPaintGlue::setDither},
803 {"native_getStyle","(I)I", (void*) SkPaintGlue::getStyle},
804 {"native_setStyle","(II)V", (void*) SkPaintGlue::setStyle},
805 {"getColor","()I", (void*) SkPaintGlue::getColor},
806 {"setColor","(I)V", (void*) SkPaintGlue::setColor},
807 {"getAlpha","()I", (void*) SkPaintGlue::getAlpha},
808 {"setAlpha","(I)V", (void*) SkPaintGlue::setAlpha},
809 {"getStrokeWidth","()F", (void*) SkPaintGlue::getStrokeWidth},
810 {"setStrokeWidth","(F)V", (void*) SkPaintGlue::setStrokeWidth},
811 {"getStrokeMiter","()F", (void*) SkPaintGlue::getStrokeMiter},
812 {"setStrokeMiter","(F)V", (void*) SkPaintGlue::setStrokeMiter},
813 {"native_getStrokeCap","(I)I", (void*) SkPaintGlue::getStrokeCap},
814 {"native_setStrokeCap","(II)V", (void*) SkPaintGlue::setStrokeCap},
815 {"native_getStrokeJoin","(I)I", (void*) SkPaintGlue::getStrokeJoin},
816 {"native_setStrokeJoin","(II)V", (void*) SkPaintGlue::setStrokeJoin},
817 {"native_getFillPath","(III)Z", (void*) SkPaintGlue::getFillPath},
818 {"native_setShader","(II)I", (void*) SkPaintGlue::setShader},
819 {"native_setColorFilter","(II)I", (void*) SkPaintGlue::setColorFilter},
820 {"native_setXfermode","(II)I", (void*) SkPaintGlue::setXfermode},
821 {"native_setPathEffect","(II)I", (void*) SkPaintGlue::setPathEffect},
822 {"native_setMaskFilter","(II)I", (void*) SkPaintGlue::setMaskFilter},
823 {"native_setTypeface","(II)I", (void*) SkPaintGlue::setTypeface},
824 {"native_setRasterizer","(II)I", (void*) SkPaintGlue::setRasterizer},
825 {"native_getTextAlign","(I)I", (void*) SkPaintGlue::getTextAlign},
826 {"native_setTextAlign","(II)V", (void*) SkPaintGlue::setTextAlign},
Fabrice Di Meglio517825f2012-04-06 16:53:48 -0700827 {"native_setTextLocale","(ILjava/lang/String;)V", (void*) SkPaintGlue::setTextLocale},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800828 {"getTextSize","()F", (void*) SkPaintGlue::getTextSize},
829 {"setTextSize","(F)V", (void*) SkPaintGlue::setTextSize},
830 {"getTextScaleX","()F", (void*) SkPaintGlue::getTextScaleX},
831 {"setTextScaleX","(F)V", (void*) SkPaintGlue::setTextScaleX},
832 {"getTextSkewX","()F", (void*) SkPaintGlue::getTextSkewX},
833 {"setTextSkewX","(F)V", (void*) SkPaintGlue::setTextSkewX},
834 {"ascent","()F", (void*) SkPaintGlue::ascent},
835 {"descent","()F", (void*) SkPaintGlue::descent},
836 {"getFontMetrics", "(Landroid/graphics/Paint$FontMetrics;)F", (void*)SkPaintGlue::getFontMetrics},
837 {"getFontMetricsInt", "(Landroid/graphics/Paint$FontMetricsInt;)I", (void*)SkPaintGlue::getFontMetricsInt},
Dianne Hackbornafa78962009-09-28 17:33:54 -0700838 {"native_measureText","([CII)F", (void*) SkPaintGlue::measureText_CII},
839 {"native_measureText","(Ljava/lang/String;)F", (void*) SkPaintGlue::measureText_String},
840 {"native_measureText","(Ljava/lang/String;II)F", (void*) SkPaintGlue::measureText_StringII},
841 {"native_breakText","([CIIF[F)I", (void*) SkPaintGlue::breakTextC},
842 {"native_breakText","(Ljava/lang/String;ZF[F)I", (void*) SkPaintGlue::breakTextS},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800843 {"native_getTextWidths","(I[CII[F)I", (void*) SkPaintGlue::getTextWidths___CII_F},
844 {"native_getTextWidths","(ILjava/lang/String;II[F)I", (void*) SkPaintGlue::getTextWidths__StringII_F},
Fabrice Di Meglio0a1413e2011-04-21 17:36:26 -0700845 {"native_getTextRunAdvances","(I[CIIIII[FII)F",
846 (void*) SkPaintGlue::getTextRunAdvances___CIIIII_FII},
847 {"native_getTextRunAdvances","(ILjava/lang/String;IIIII[FII)F",
848 (void*) SkPaintGlue::getTextRunAdvances__StringIIIII_FII},
849
850
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800851 {"native_getTextGlyphs","(ILjava/lang/String;IIIII[C)I",
852 (void*) SkPaintGlue::getTextGlyphs__StringIIIII_C},
Doug Felt0c702b82010-05-14 10:55:42 -0700853 {"native_getTextRunCursor", "(I[CIIIII)I", (void*) SkPaintGlue::getTextRunCursor___C},
854 {"native_getTextRunCursor", "(ILjava/lang/String;IIIII)I",
855 (void*) SkPaintGlue::getTextRunCursor__String},
Doug Feltf7cb1f72010-07-01 16:20:43 -0700856 {"native_getTextPath","(II[CIIFFI)V", (void*) SkPaintGlue::getTextPath___C},
857 {"native_getTextPath","(IILjava/lang/String;IIFFI)V", (void*) SkPaintGlue::getTextPath__String},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800858 {"nativeGetStringBounds", "(ILjava/lang/String;IILandroid/graphics/Rect;)V",
859 (void*) SkPaintGlue::getStringBounds },
860 {"nativeGetCharArrayBounds", "(I[CIILandroid/graphics/Rect;)V",
861 (void*) SkPaintGlue::getCharArrayBounds },
Romain Guy1e45aae2010-08-13 19:39:53 -0700862 {"nSetShadowLayer", "(FFFI)V", (void*)SkPaintGlue::setShadowLayer}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800863};
864
865static jfieldID req_fieldID(jfieldID id) {
866 SkASSERT(id);
867 return id;
868}
869
870int register_android_graphics_Paint(JNIEnv* env) {
871 gFontMetrics_class = env->FindClass("android/graphics/Paint$FontMetrics");
872 SkASSERT(gFontMetrics_class);
873 gFontMetrics_class = (jclass)env->NewGlobalRef(gFontMetrics_class);
874
875 gFontMetrics_fieldID.top = req_fieldID(env->GetFieldID(gFontMetrics_class, "top", "F"));
876 gFontMetrics_fieldID.ascent = req_fieldID(env->GetFieldID(gFontMetrics_class, "ascent", "F"));
877 gFontMetrics_fieldID.descent = req_fieldID(env->GetFieldID(gFontMetrics_class, "descent", "F"));
878 gFontMetrics_fieldID.bottom = req_fieldID(env->GetFieldID(gFontMetrics_class, "bottom", "F"));
879 gFontMetrics_fieldID.leading = req_fieldID(env->GetFieldID(gFontMetrics_class, "leading", "F"));
880
881 gFontMetricsInt_class = env->FindClass("android/graphics/Paint$FontMetricsInt");
882 SkASSERT(gFontMetricsInt_class);
883 gFontMetricsInt_class = (jclass)env->NewGlobalRef(gFontMetricsInt_class);
884
885 gFontMetricsInt_fieldID.top = req_fieldID(env->GetFieldID(gFontMetricsInt_class, "top", "I"));
886 gFontMetricsInt_fieldID.ascent = req_fieldID(env->GetFieldID(gFontMetricsInt_class, "ascent", "I"));
887 gFontMetricsInt_fieldID.descent = req_fieldID(env->GetFieldID(gFontMetricsInt_class, "descent", "I"));
888 gFontMetricsInt_fieldID.bottom = req_fieldID(env->GetFieldID(gFontMetricsInt_class, "bottom", "I"));
889 gFontMetricsInt_fieldID.leading = req_fieldID(env->GetFieldID(gFontMetricsInt_class, "leading", "I"));
890
891 int result = AndroidRuntime::registerNativeMethods(env, "android/graphics/Paint", methods,
892 sizeof(methods) / sizeof(methods[0]));
893 return result;
894}
895
896}