• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* libs/android_runtime/android/graphics/Paint.cpp
2 **
3 ** Copyright 2006, The Android Open Source Project
4 **
5 ** 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
8 **
9 **     http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** 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
15 ** limitations under the License.
16 */
17 
18 // This file was generated from the C++ include file: SkPaint.h
19 // Any changes made to this file will be discarded by the build.
20 // To change this file, either edit the include, or device/tools/gluemaker/main.cpp,
21 // or one of the auxilary file specifications in device/tools/gluemaker.
22 
23 #include "jni.h"
24 #include "GraphicsJNI.h"
25 #include <android_runtime/AndroidRuntime.h>
26 
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"
34 
35 namespace android {
36 
37 struct JMetricsID {
38     jfieldID    top;
39     jfieldID    ascent;
40     jfieldID    descent;
41     jfieldID    bottom;
42     jfieldID    leading;
43 };
44 
45 static jclass   gFontMetrics_class;
46 static JMetricsID gFontMetrics_fieldID;
47 
48 static jclass   gFontMetricsInt_class;
49 static JMetricsID gFontMetricsInt_fieldID;
50 
defaultSettingsForAndroid(SkPaint * paint)51 static void defaultSettingsForAndroid(SkPaint* paint) {
52     // looks best we decided
53     paint->setHinting(SkPaint::kSlight_Hinting);
54     // utf16 is required for java
55     paint->setTextEncoding(SkPaint::kUTF16_TextEncoding);
56 }
57 
58 class SkPaintGlue {
59 public:
60 
finalizer(JNIEnv * env,jobject clazz,SkPaint * obj)61     static void finalizer(JNIEnv* env, jobject clazz, SkPaint* obj) {
62         delete obj;
63     }
64 
init(JNIEnv * env,jobject clazz)65     static SkPaint* init(JNIEnv* env, jobject clazz) {
66         SkPaint* obj = new SkPaint();
67         defaultSettingsForAndroid(obj);
68         return obj;
69     }
70 
intiWithPaint(JNIEnv * env,jobject clazz,SkPaint * paint)71     static SkPaint* intiWithPaint(JNIEnv* env, jobject clazz, SkPaint* paint) {
72         SkPaint* obj = new SkPaint(*paint);
73         return obj;
74     }
75 
reset(JNIEnv * env,jobject clazz,SkPaint * obj)76     static void reset(JNIEnv* env, jobject clazz, SkPaint* obj) {
77         obj->reset();
78         defaultSettingsForAndroid(obj);
79     }
80 
assign(JNIEnv * env,jobject clazz,SkPaint * dst,const SkPaint * src)81     static void assign(JNIEnv* env, jobject clazz, SkPaint* dst, const SkPaint* src) {
82         *dst = *src;
83     }
84 
getFlags(JNIEnv * env,jobject paint)85     static jint getFlags(JNIEnv* env, jobject paint) {
86         NPE_CHECK_RETURN_ZERO(env, paint);
87         return GraphicsJNI::getNativePaint(env, paint)->getFlags();
88     }
89 
setFlags(JNIEnv * env,jobject paint,jint flags)90     static void setFlags(JNIEnv* env, jobject paint, jint flags) {
91         NPE_CHECK_RETURN_VOID(env, paint);
92         GraphicsJNI::getNativePaint(env, paint)->setFlags(flags);
93     }
94 
setAntiAlias(JNIEnv * env,jobject paint,jboolean aa)95     static void setAntiAlias(JNIEnv* env, jobject paint, jboolean aa) {
96         NPE_CHECK_RETURN_VOID(env, paint);
97         GraphicsJNI::getNativePaint(env, paint)->setAntiAlias(aa);
98     }
99 
setLinearText(JNIEnv * env,jobject paint,jboolean linearText)100     static void setLinearText(JNIEnv* env, jobject paint, jboolean linearText) {
101         NPE_CHECK_RETURN_VOID(env, paint);
102         GraphicsJNI::getNativePaint(env, paint)->setLinearText(linearText);
103     }
104 
setSubpixelText(JNIEnv * env,jobject paint,jboolean subpixelText)105     static void setSubpixelText(JNIEnv* env, jobject paint, jboolean subpixelText) {
106         NPE_CHECK_RETURN_VOID(env, paint);
107         GraphicsJNI::getNativePaint(env, paint)->setSubpixelText(subpixelText);
108     }
109 
setUnderlineText(JNIEnv * env,jobject paint,jboolean underlineText)110     static void setUnderlineText(JNIEnv* env, jobject paint, jboolean underlineText) {
111         NPE_CHECK_RETURN_VOID(env, paint);
112         GraphicsJNI::getNativePaint(env, paint)->setUnderlineText(underlineText);
113     }
114 
setStrikeThruText(JNIEnv * env,jobject paint,jboolean strikeThruText)115     static void setStrikeThruText(JNIEnv* env, jobject paint, jboolean strikeThruText) {
116         NPE_CHECK_RETURN_VOID(env, paint);
117         GraphicsJNI::getNativePaint(env, paint)->setStrikeThruText(strikeThruText);
118     }
119 
setFakeBoldText(JNIEnv * env,jobject paint,jboolean fakeBoldText)120     static void setFakeBoldText(JNIEnv* env, jobject paint, jboolean fakeBoldText) {
121         NPE_CHECK_RETURN_VOID(env, paint);
122         GraphicsJNI::getNativePaint(env, paint)->setFakeBoldText(fakeBoldText);
123     }
124 
setFilterBitmap(JNIEnv * env,jobject paint,jboolean filterBitmap)125     static void setFilterBitmap(JNIEnv* env, jobject paint, jboolean filterBitmap) {
126         NPE_CHECK_RETURN_VOID(env, paint);
127         GraphicsJNI::getNativePaint(env, paint)->setFilterBitmap(filterBitmap);
128     }
129 
setDither(JNIEnv * env,jobject paint,jboolean dither)130     static void setDither(JNIEnv* env, jobject paint, jboolean dither) {
131         NPE_CHECK_RETURN_VOID(env, paint);
132         GraphicsJNI::getNativePaint(env, paint)->setDither(dither);
133     }
134 
getStyle(JNIEnv * env,jobject clazz,SkPaint * obj)135     static jint getStyle(JNIEnv* env, jobject clazz, SkPaint* obj) {
136         return obj->getStyle();
137     }
138 
setStyle(JNIEnv * env,jobject clazz,SkPaint * obj,SkPaint::Style style)139     static void setStyle(JNIEnv* env, jobject clazz, SkPaint* obj, SkPaint::Style style) {
140         obj->setStyle(style);
141     }
142 
getColor(JNIEnv * env,jobject paint)143     static jint getColor(JNIEnv* env, jobject paint) {
144         NPE_CHECK_RETURN_ZERO(env, paint);
145         return GraphicsJNI::getNativePaint(env, paint)->getColor();
146     }
147 
getAlpha(JNIEnv * env,jobject paint)148     static jint getAlpha(JNIEnv* env, jobject paint) {
149         NPE_CHECK_RETURN_ZERO(env, paint);
150         return GraphicsJNI::getNativePaint(env, paint)->getAlpha();
151     }
152 
setColor(JNIEnv * env,jobject paint,jint color)153     static void setColor(JNIEnv* env, jobject paint, jint color) {
154         NPE_CHECK_RETURN_VOID(env, paint);
155         GraphicsJNI::getNativePaint(env, paint)->setColor(color);
156     }
157 
setAlpha(JNIEnv * env,jobject paint,jint a)158     static void setAlpha(JNIEnv* env, jobject paint, jint a) {
159         NPE_CHECK_RETURN_VOID(env, paint);
160         GraphicsJNI::getNativePaint(env, paint)->setAlpha(a);
161     }
162 
getStrokeWidth(JNIEnv * env,jobject paint)163     static jfloat getStrokeWidth(JNIEnv* env, jobject paint) {
164         NPE_CHECK_RETURN_ZERO(env, paint);
165         return SkScalarToFloat(GraphicsJNI::getNativePaint(env, paint)->getStrokeWidth());
166     }
167 
setStrokeWidth(JNIEnv * env,jobject paint,jfloat width)168     static void setStrokeWidth(JNIEnv* env, jobject paint, jfloat width) {
169         NPE_CHECK_RETURN_VOID(env, paint);
170         GraphicsJNI::getNativePaint(env, paint)->setStrokeWidth(SkFloatToScalar(width));
171     }
172 
getStrokeMiter(JNIEnv * env,jobject paint)173     static jfloat getStrokeMiter(JNIEnv* env, jobject paint) {
174         NPE_CHECK_RETURN_ZERO(env, paint);
175         return SkScalarToFloat(GraphicsJNI::getNativePaint(env, paint)->getStrokeMiter());
176     }
177 
setStrokeMiter(JNIEnv * env,jobject paint,jfloat miter)178     static void setStrokeMiter(JNIEnv* env, jobject paint, jfloat miter) {
179         NPE_CHECK_RETURN_VOID(env, paint);
180         GraphicsJNI::getNativePaint(env, paint)->setStrokeMiter(SkFloatToScalar(miter));
181     }
182 
getStrokeCap(JNIEnv * env,jobject clazz,SkPaint * obj)183     static jint getStrokeCap(JNIEnv* env, jobject clazz, SkPaint* obj) {
184         return obj->getStrokeCap();
185     }
186 
setStrokeCap(JNIEnv * env,jobject clazz,SkPaint * obj,SkPaint::Cap cap)187     static void setStrokeCap(JNIEnv* env, jobject clazz, SkPaint* obj, SkPaint::Cap cap) {
188         obj->setStrokeCap(cap);
189     }
190 
getStrokeJoin(JNIEnv * env,jobject clazz,SkPaint * obj)191     static jint getStrokeJoin(JNIEnv* env, jobject clazz, SkPaint* obj) {
192         return obj->getStrokeJoin();
193     }
194 
setStrokeJoin(JNIEnv * env,jobject clazz,SkPaint * obj,SkPaint::Join join)195     static void setStrokeJoin(JNIEnv* env, jobject clazz, SkPaint* obj, SkPaint::Join join) {
196         obj->setStrokeJoin(join);
197     }
198 
getFillPath(JNIEnv * env,jobject clazz,SkPaint * obj,SkPath * src,SkPath * dst)199     static jboolean getFillPath(JNIEnv* env, jobject clazz, SkPaint* obj, SkPath* src, SkPath* dst) {
200         return obj->getFillPath(*src, dst);
201     }
202 
setShader(JNIEnv * env,jobject clazz,SkPaint * obj,SkShader * shader)203     static SkShader* setShader(JNIEnv* env, jobject clazz, SkPaint* obj, SkShader* shader) {
204         return obj->setShader(shader);
205     }
206 
setColorFilter(JNIEnv * env,jobject clazz,SkPaint * obj,SkColorFilter * filter)207     static SkColorFilter* setColorFilter(JNIEnv* env, jobject clazz, SkPaint* obj, SkColorFilter* filter) {
208         return obj->setColorFilter(filter);
209     }
210 
setXfermode(JNIEnv * env,jobject clazz,SkPaint * obj,SkXfermode * xfermode)211     static SkXfermode* setXfermode(JNIEnv* env, jobject clazz, SkPaint* obj, SkXfermode* xfermode) {
212         return obj->setXfermode(xfermode);
213     }
214 
setPathEffect(JNIEnv * env,jobject clazz,SkPaint * obj,SkPathEffect * effect)215     static SkPathEffect* setPathEffect(JNIEnv* env, jobject clazz, SkPaint* obj, SkPathEffect* effect) {
216         return obj->setPathEffect(effect);
217     }
218 
setMaskFilter(JNIEnv * env,jobject clazz,SkPaint * obj,SkMaskFilter * maskfilter)219     static SkMaskFilter* setMaskFilter(JNIEnv* env, jobject clazz, SkPaint* obj, SkMaskFilter* maskfilter) {
220         return obj->setMaskFilter(maskfilter);
221     }
222 
setTypeface(JNIEnv * env,jobject clazz,SkPaint * obj,SkTypeface * typeface)223     static SkTypeface* setTypeface(JNIEnv* env, jobject clazz, SkPaint* obj, SkTypeface* typeface) {
224         return obj->setTypeface(typeface);
225     }
226 
setRasterizer(JNIEnv * env,jobject clazz,SkPaint * obj,SkRasterizer * rasterizer)227     static SkRasterizer* setRasterizer(JNIEnv* env, jobject clazz, SkPaint* obj, SkRasterizer* rasterizer) {
228         return obj->setRasterizer(rasterizer);
229     }
230 
getTextAlign(JNIEnv * env,jobject clazz,SkPaint * obj)231     static jint getTextAlign(JNIEnv* env, jobject clazz, SkPaint* obj) {
232         return obj->getTextAlign();
233     }
234 
setTextAlign(JNIEnv * env,jobject clazz,SkPaint * obj,SkPaint::Align align)235     static void setTextAlign(JNIEnv* env, jobject clazz, SkPaint* obj, SkPaint::Align align) {
236         obj->setTextAlign(align);
237     }
238 
getTextSize(JNIEnv * env,jobject paint)239     static jfloat getTextSize(JNIEnv* env, jobject paint) {
240         NPE_CHECK_RETURN_ZERO(env, paint);
241         return SkScalarToFloat(GraphicsJNI::getNativePaint(env, paint)->getTextSize());
242     }
243 
setTextSize(JNIEnv * env,jobject paint,jfloat textSize)244     static void setTextSize(JNIEnv* env, jobject paint, jfloat textSize) {
245         NPE_CHECK_RETURN_VOID(env, paint);
246         GraphicsJNI::getNativePaint(env, paint)->setTextSize(SkFloatToScalar(textSize));
247     }
248 
getTextScaleX(JNIEnv * env,jobject paint)249     static jfloat getTextScaleX(JNIEnv* env, jobject paint) {
250         NPE_CHECK_RETURN_ZERO(env, paint);
251         return SkScalarToFloat(GraphicsJNI::getNativePaint(env, paint)->getTextScaleX());
252     }
253 
setTextScaleX(JNIEnv * env,jobject paint,jfloat scaleX)254     static void setTextScaleX(JNIEnv* env, jobject paint, jfloat scaleX) {
255         NPE_CHECK_RETURN_VOID(env, paint);
256         GraphicsJNI::getNativePaint(env, paint)->setTextScaleX(SkFloatToScalar(scaleX));
257     }
258 
getTextSkewX(JNIEnv * env,jobject paint)259     static jfloat getTextSkewX(JNIEnv* env, jobject paint) {
260         NPE_CHECK_RETURN_ZERO(env, paint);
261         return SkScalarToFloat(GraphicsJNI::getNativePaint(env, paint)->getTextSkewX());
262     }
263 
setTextSkewX(JNIEnv * env,jobject paint,jfloat skewX)264     static void setTextSkewX(JNIEnv* env, jobject paint, jfloat skewX) {
265         NPE_CHECK_RETURN_VOID(env, paint);
266         GraphicsJNI::getNativePaint(env, paint)->setTextSkewX(SkFloatToScalar(skewX));
267     }
268 
ascent(JNIEnv * env,jobject paint)269     static jfloat ascent(JNIEnv* env, jobject paint) {
270         NPE_CHECK_RETURN_ZERO(env, paint);
271         SkPaint::FontMetrics    metrics;
272         (void)GraphicsJNI::getNativePaint(env, paint)->getFontMetrics(&metrics);
273         return SkScalarToFloat(metrics.fAscent);
274     }
275 
descent(JNIEnv * env,jobject paint)276     static jfloat descent(JNIEnv* env, jobject paint) {
277         NPE_CHECK_RETURN_ZERO(env, paint);
278         SkPaint::FontMetrics    metrics;
279         (void)GraphicsJNI::getNativePaint(env, paint)->getFontMetrics(&metrics);
280         return SkScalarToFloat(metrics.fDescent);
281     }
282 
getFontMetrics(JNIEnv * env,jobject paint,jobject metricsObj)283     static jfloat getFontMetrics(JNIEnv* env, jobject paint, jobject metricsObj) {
284         NPE_CHECK_RETURN_ZERO(env, paint);
285         SkPaint::FontMetrics metrics;
286         SkScalar             spacing = GraphicsJNI::getNativePaint(env, paint)->getFontMetrics(&metrics);
287 
288         if (metricsObj) {
289             SkASSERT(env->IsInstanceOf(metricsObj, gFontMetrics_class));
290             env->SetFloatField(metricsObj, gFontMetrics_fieldID.top, SkScalarToFloat(metrics.fTop));
291             env->SetFloatField(metricsObj, gFontMetrics_fieldID.ascent, SkScalarToFloat(metrics.fAscent));
292             env->SetFloatField(metricsObj, gFontMetrics_fieldID.descent, SkScalarToFloat(metrics.fDescent));
293             env->SetFloatField(metricsObj, gFontMetrics_fieldID.bottom, SkScalarToFloat(metrics.fBottom));
294             env->SetFloatField(metricsObj, gFontMetrics_fieldID.leading, SkScalarToFloat(metrics.fLeading));
295         }
296         return SkScalarToFloat(spacing);
297     }
298 
getFontMetricsInt(JNIEnv * env,jobject paint,jobject metricsObj)299     static jint getFontMetricsInt(JNIEnv* env, jobject paint, jobject metricsObj) {
300         NPE_CHECK_RETURN_ZERO(env, paint);
301         SkPaint::FontMetrics metrics;
302 
303         GraphicsJNI::getNativePaint(env, paint)->getFontMetrics(&metrics);
304         int ascent = SkScalarRound(metrics.fAscent);
305         int descent = SkScalarRound(metrics.fDescent);
306         int leading = SkScalarRound(metrics.fLeading);
307 
308         if (metricsObj) {
309             SkASSERT(env->IsInstanceOf(metricsObj, gFontMetricsInt_class));
310             env->SetIntField(metricsObj, gFontMetricsInt_fieldID.top, SkScalarFloor(metrics.fTop));
311             env->SetIntField(metricsObj, gFontMetricsInt_fieldID.ascent, ascent);
312             env->SetIntField(metricsObj, gFontMetricsInt_fieldID.descent, descent);
313             env->SetIntField(metricsObj, gFontMetricsInt_fieldID.bottom, SkScalarCeil(metrics.fBottom));
314             env->SetIntField(metricsObj, gFontMetricsInt_fieldID.leading, leading);
315         }
316         return descent - ascent + leading;
317     }
318 
measureText_CII(JNIEnv * env,jobject jpaint,jcharArray text,int index,int count)319     static jfloat measureText_CII(JNIEnv* env, jobject jpaint, jcharArray text, int index, int count) {
320         NPE_CHECK_RETURN_ZERO(env, jpaint);
321         NPE_CHECK_RETURN_ZERO(env, text);
322 
323         size_t textLength = env->GetArrayLength(text);
324 
325         if ((index | count) < 0 || (size_t)(index + count) > textLength) {
326             doThrow(env, "java/lang/ArrayIndexOutOfBoundsException");
327             return 0;
328         }
329 
330         const SkPaint* paint = GraphicsJNI::getNativePaint(env, jpaint);
331         const jchar* textArray = env->GetCharArrayElements(text, NULL);
332         // we double count, since measureText wants a byteLength
333         SkScalar width = paint->measureText(textArray + index, count << 1);
334         env->ReleaseCharArrayElements(text, const_cast<jchar*>(textArray),
335                                       JNI_ABORT);
336 
337         return SkScalarToFloat(width);
338     }
339 
measureText_StringII(JNIEnv * env,jobject jpaint,jstring text,int start,int end)340     static jfloat measureText_StringII(JNIEnv* env, jobject jpaint, jstring text, int start, int end) {
341         NPE_CHECK_RETURN_ZERO(env, jpaint);
342         NPE_CHECK_RETURN_ZERO(env, text);
343 
344         SkPaint* paint = GraphicsJNI::getNativePaint(env, jpaint);
345         const jchar* textArray = env->GetStringChars(text, NULL);
346         size_t textLength = env->GetStringLength(text);
347 
348         int count = end - start;
349         if ((start | count) < 0 || (size_t)count > textLength) {
350             doThrow(env, "java/lang/IndexOutOfBoundsException");
351             return 0;
352         }
353 
354         jfloat width = SkScalarToFloat(paint->measureText(textArray + start, count << 1));
355         env->ReleaseStringChars(text, textArray);
356         return width;
357     }
358 
measureText_String(JNIEnv * env,jobject jpaint,jstring text)359     static jfloat measureText_String(JNIEnv* env, jobject jpaint, jstring text) {
360         NPE_CHECK_RETURN_ZERO(env, jpaint);
361         NPE_CHECK_RETURN_ZERO(env, text);
362 
363         SkPaint* paint = GraphicsJNI::getNativePaint(env, jpaint);
364         const jchar* textArray = env->GetStringChars(text, NULL);
365         size_t textLength = env->GetStringLength(text);
366 
367         jfloat width = SkScalarToFloat(paint->measureText(textArray, textLength << 1));
368         env->ReleaseStringChars(text, textArray);
369         return width;
370     }
371 
dotextwidths(JNIEnv * env,SkPaint * paint,const jchar text[],int count,jfloatArray widths)372     static int dotextwidths(JNIEnv* env, SkPaint* paint, const jchar text[], int count, jfloatArray widths) {
373         AutoJavaFloatArray autoWidths(env, widths, count);
374         jfloat* widthsArray = autoWidths.ptr();
375         SkScalar* scalarArray = (SkScalar*)widthsArray;
376 
377         count = paint->getTextWidths(text, count << 1, scalarArray);
378         for (int i = 0; i < count; i++) {
379             widthsArray[i] = SkScalarToFloat(scalarArray[i]);
380         }
381         return count;
382     }
383 
getTextWidths___CII_F(JNIEnv * env,jobject clazz,SkPaint * paint,jcharArray text,int index,int count,jfloatArray widths)384     static int getTextWidths___CII_F(JNIEnv* env, jobject clazz, SkPaint* paint, jcharArray text, int index, int count, jfloatArray widths) {
385         const jchar* textArray = env->GetCharArrayElements(text, NULL);
386         count = dotextwidths(env, paint, textArray + index, count, widths);
387         env->ReleaseCharArrayElements(text, const_cast<jchar*>(textArray),
388                                       JNI_ABORT);
389         return count;
390     }
391 
getTextWidths__StringII_F(JNIEnv * env,jobject clazz,SkPaint * paint,jstring text,int start,int end,jfloatArray widths)392     static int getTextWidths__StringII_F(JNIEnv* env, jobject clazz, SkPaint* paint, jstring text, int start, int end, jfloatArray widths) {
393         const jchar* textArray = env->GetStringChars(text, NULL);
394         int count = dotextwidths(env, paint, textArray + start, end - start, widths);
395         env->ReleaseStringChars(text, textArray);
396         return count;
397     }
398 
getTextPath___CIIFFPath(JNIEnv * env,jobject clazz,SkPaint * paint,jcharArray text,int index,int count,jfloat x,jfloat y,SkPath * path)399     static void getTextPath___CIIFFPath(JNIEnv* env, jobject clazz, SkPaint* paint, jcharArray text, int index, int count, jfloat x, jfloat y, SkPath* path) {
400         const jchar* textArray = env->GetCharArrayElements(text, NULL);
401         paint->getTextPath(textArray + index, count << 1, SkFloatToScalar(x), SkFloatToScalar(y), path);
402         env->ReleaseCharArrayElements(text, const_cast<jchar*>(textArray),
403                                       JNI_ABORT);
404     }
405 
getTextPath__StringIIFFPath(JNIEnv * env,jobject clazz,SkPaint * paint,jstring text,int start,int end,jfloat x,jfloat y,SkPath * path)406     static void getTextPath__StringIIFFPath(JNIEnv* env, jobject clazz, SkPaint* paint, jstring text, int start, int end, jfloat x, jfloat y, SkPath* path) {
407         const jchar* textArray = env->GetStringChars(text, NULL);
408         paint->getTextPath(textArray + start, (end - start) << 1, SkFloatToScalar(x), SkFloatToScalar(y), path);
409         env->ReleaseStringChars(text, textArray);
410     }
411 
setShadowLayer(JNIEnv * env,jobject jpaint,jfloat radius,jfloat dx,jfloat dy,int color)412     static void setShadowLayer(JNIEnv* env, jobject jpaint, jfloat radius,
413                                jfloat dx, jfloat dy, int color) {
414         NPE_CHECK_RETURN_VOID(env, jpaint);
415 
416         SkPaint* paint = GraphicsJNI::getNativePaint(env, jpaint);
417         if (radius <= 0) {
418             paint->setLooper(NULL);
419         }
420         else {
421             paint->setLooper(new SkBlurDrawLooper(SkFloatToScalar(radius),
422                                                   SkFloatToScalar(dx),
423                                                   SkFloatToScalar(dy),
424                                                   (SkColor)color))->unref();
425         }
426     }
427 
breakText(JNIEnv * env,const SkPaint & paint,const jchar text[],int count,float maxWidth,jfloatArray jmeasured,SkPaint::TextBufferDirection tbd)428     static int breakText(JNIEnv* env, const SkPaint& paint, const jchar text[],
429                          int count, float maxWidth, jfloatArray jmeasured,
430                          SkPaint::TextBufferDirection tbd) {
431         SkASSERT(paint.getTextEncoding() == SkPaint::kUTF16_TextEncoding);
432 
433         SkScalar     measured;
434         size_t       bytes = paint.breakText(text, count << 1,
435                                    SkFloatToScalar(maxWidth), &measured, tbd);
436         SkASSERT((bytes & 1) == 0);
437 
438         if (jmeasured && env->GetArrayLength(jmeasured) > 0) {
439             AutoJavaFloatArray autoMeasured(env, jmeasured, 1);
440             jfloat* array = autoMeasured.ptr();
441             array[0] = SkScalarToFloat(measured);
442         }
443         return bytes >> 1;
444     }
445 
breakTextC(JNIEnv * env,jobject jpaint,jcharArray jtext,int index,int count,float maxWidth,jfloatArray jmeasuredWidth)446     static int breakTextC(JNIEnv* env, jobject jpaint, jcharArray jtext,
447             int index, int count, float maxWidth, jfloatArray jmeasuredWidth) {
448         NPE_CHECK_RETURN_ZERO(env, jpaint);
449         NPE_CHECK_RETURN_ZERO(env, jtext);
450 
451         SkPaint::TextBufferDirection tbd;
452         if (count < 0) {
453             tbd = SkPaint::kBackward_TextBufferDirection;
454             count = -count;
455         }
456         else {
457             tbd = SkPaint::kForward_TextBufferDirection;
458         }
459 
460         if ((index < 0) || (index + count > env->GetArrayLength(jtext))) {
461             doThrow(env, "java/lang/ArrayIndexOutOfBoundsException");
462             return 0;
463         }
464 
465         SkPaint*     paint = GraphicsJNI::getNativePaint(env, jpaint);
466         const jchar* text = env->GetCharArrayElements(jtext, NULL);
467         count = breakText(env, *paint, text + index, count, maxWidth,
468                           jmeasuredWidth, tbd);
469         env->ReleaseCharArrayElements(jtext, const_cast<jchar*>(text),
470                                       JNI_ABORT);
471         return count;
472     }
473 
breakTextS(JNIEnv * env,jobject jpaint,jstring jtext,bool forwards,float maxWidth,jfloatArray jmeasuredWidth)474     static int breakTextS(JNIEnv* env, jobject jpaint, jstring jtext,
475                 bool forwards, float maxWidth, jfloatArray jmeasuredWidth) {
476         NPE_CHECK_RETURN_ZERO(env, jpaint);
477         NPE_CHECK_RETURN_ZERO(env, jtext);
478 
479         SkPaint::TextBufferDirection tbd = forwards ?
480                                         SkPaint::kForward_TextBufferDirection :
481                                         SkPaint::kBackward_TextBufferDirection;
482 
483         SkPaint* paint = GraphicsJNI::getNativePaint(env, jpaint);
484         int count = env->GetStringLength(jtext);
485         const jchar* text = env->GetStringChars(jtext, NULL);
486         count = breakText(env, *paint, text, count, maxWidth,
487                           jmeasuredWidth, tbd);
488         env->ReleaseStringChars(jtext, text);
489         return count;
490     }
491 
doTextBounds(JNIEnv * env,const jchar * text,int count,jobject bounds,const SkPaint & paint)492     static void doTextBounds(JNIEnv* env, const jchar* text, int count,
493                              jobject bounds, const SkPaint& paint)
494     {
495         SkRect  r;
496         SkIRect ir;
497 
498         paint.measureText(text, count << 1, &r);
499         r.roundOut(&ir);
500         GraphicsJNI::irect_to_jrect(ir, env, bounds);
501     }
502 
getStringBounds(JNIEnv * env,jobject,const SkPaint * paint,jstring text,int start,int end,jobject bounds)503     static void getStringBounds(JNIEnv* env, jobject, const SkPaint* paint,
504                                 jstring text, int start, int end, jobject bounds)
505     {
506         const jchar* textArray = env->GetStringChars(text, NULL);
507         doTextBounds(env, textArray + start, end - start, bounds, *paint);
508         env->ReleaseStringChars(text, textArray);
509     }
510 
getCharArrayBounds(JNIEnv * env,jobject,const SkPaint * paint,jcharArray text,int index,int count,jobject bounds)511     static void getCharArrayBounds(JNIEnv* env, jobject, const SkPaint* paint,
512                         jcharArray text, int index, int count, jobject bounds)
513     {
514         const jchar* textArray = env->GetCharArrayElements(text, NULL);
515         doTextBounds(env, textArray + index, count, bounds, *paint);
516         env->ReleaseCharArrayElements(text, const_cast<jchar*>(textArray),
517                                       JNI_ABORT);
518     }
519 
520 };
521 
522 static JNINativeMethod methods[] = {
523     {"finalizer", "(I)V", (void*) SkPaintGlue::finalizer},
524     {"native_init","()I", (void*) SkPaintGlue::init},
525     {"native_initWithPaint","(I)I", (void*) SkPaintGlue::intiWithPaint},
526     {"native_reset","(I)V", (void*) SkPaintGlue::reset},
527     {"native_set","(II)V", (void*) SkPaintGlue::assign},
528     {"getFlags","()I", (void*) SkPaintGlue::getFlags},
529     {"setFlags","(I)V", (void*) SkPaintGlue::setFlags},
530     {"setAntiAlias","(Z)V", (void*) SkPaintGlue::setAntiAlias},
531     {"setSubpixelText","(Z)V", (void*) SkPaintGlue::setSubpixelText},
532     {"setLinearText","(Z)V", (void*) SkPaintGlue::setLinearText},
533     {"setUnderlineText","(Z)V", (void*) SkPaintGlue::setUnderlineText},
534     {"setStrikeThruText","(Z)V", (void*) SkPaintGlue::setStrikeThruText},
535     {"setFakeBoldText","(Z)V", (void*) SkPaintGlue::setFakeBoldText},
536     {"setFilterBitmap","(Z)V", (void*) SkPaintGlue::setFilterBitmap},
537     {"setDither","(Z)V", (void*) SkPaintGlue::setDither},
538     {"native_getStyle","(I)I", (void*) SkPaintGlue::getStyle},
539     {"native_setStyle","(II)V", (void*) SkPaintGlue::setStyle},
540     {"getColor","()I", (void*) SkPaintGlue::getColor},
541     {"setColor","(I)V", (void*) SkPaintGlue::setColor},
542     {"getAlpha","()I", (void*) SkPaintGlue::getAlpha},
543     {"setAlpha","(I)V", (void*) SkPaintGlue::setAlpha},
544     {"getStrokeWidth","()F", (void*) SkPaintGlue::getStrokeWidth},
545     {"setStrokeWidth","(F)V", (void*) SkPaintGlue::setStrokeWidth},
546     {"getStrokeMiter","()F", (void*) SkPaintGlue::getStrokeMiter},
547     {"setStrokeMiter","(F)V", (void*) SkPaintGlue::setStrokeMiter},
548     {"native_getStrokeCap","(I)I", (void*) SkPaintGlue::getStrokeCap},
549     {"native_setStrokeCap","(II)V", (void*) SkPaintGlue::setStrokeCap},
550     {"native_getStrokeJoin","(I)I", (void*) SkPaintGlue::getStrokeJoin},
551     {"native_setStrokeJoin","(II)V", (void*) SkPaintGlue::setStrokeJoin},
552     {"native_getFillPath","(III)Z", (void*) SkPaintGlue::getFillPath},
553     {"native_setShader","(II)I", (void*) SkPaintGlue::setShader},
554     {"native_setColorFilter","(II)I", (void*) SkPaintGlue::setColorFilter},
555     {"native_setXfermode","(II)I", (void*) SkPaintGlue::setXfermode},
556     {"native_setPathEffect","(II)I", (void*) SkPaintGlue::setPathEffect},
557     {"native_setMaskFilter","(II)I", (void*) SkPaintGlue::setMaskFilter},
558     {"native_setTypeface","(II)I", (void*) SkPaintGlue::setTypeface},
559     {"native_setRasterizer","(II)I", (void*) SkPaintGlue::setRasterizer},
560     {"native_getTextAlign","(I)I", (void*) SkPaintGlue::getTextAlign},
561     {"native_setTextAlign","(II)V", (void*) SkPaintGlue::setTextAlign},
562     {"getTextSize","()F", (void*) SkPaintGlue::getTextSize},
563     {"setTextSize","(F)V", (void*) SkPaintGlue::setTextSize},
564     {"getTextScaleX","()F", (void*) SkPaintGlue::getTextScaleX},
565     {"setTextScaleX","(F)V", (void*) SkPaintGlue::setTextScaleX},
566     {"getTextSkewX","()F", (void*) SkPaintGlue::getTextSkewX},
567     {"setTextSkewX","(F)V", (void*) SkPaintGlue::setTextSkewX},
568     {"ascent","()F", (void*) SkPaintGlue::ascent},
569     {"descent","()F", (void*) SkPaintGlue::descent},
570     {"getFontMetrics", "(Landroid/graphics/Paint$FontMetrics;)F", (void*)SkPaintGlue::getFontMetrics},
571     {"getFontMetricsInt", "(Landroid/graphics/Paint$FontMetricsInt;)I", (void*)SkPaintGlue::getFontMetricsInt},
572     {"native_measureText","([CII)F", (void*) SkPaintGlue::measureText_CII},
573     {"native_measureText","(Ljava/lang/String;)F", (void*) SkPaintGlue::measureText_String},
574     {"native_measureText","(Ljava/lang/String;II)F", (void*) SkPaintGlue::measureText_StringII},
575     {"native_breakText","([CIIF[F)I", (void*) SkPaintGlue::breakTextC},
576     {"native_breakText","(Ljava/lang/String;ZF[F)I", (void*) SkPaintGlue::breakTextS},
577     {"native_getTextWidths","(I[CII[F)I", (void*) SkPaintGlue::getTextWidths___CII_F},
578     {"native_getTextWidths","(ILjava/lang/String;II[F)I", (void*) SkPaintGlue::getTextWidths__StringII_F},
579     {"native_getTextPath","(I[CIIFFI)V", (void*) SkPaintGlue::getTextPath___CIIFFPath},
580     {"native_getTextPath","(ILjava/lang/String;IIFFI)V", (void*) SkPaintGlue::getTextPath__StringIIFFPath},
581     {"nativeGetStringBounds", "(ILjava/lang/String;IILandroid/graphics/Rect;)V",
582                                         (void*) SkPaintGlue::getStringBounds },
583     {"nativeGetCharArrayBounds", "(I[CIILandroid/graphics/Rect;)V",
584                                     (void*) SkPaintGlue::getCharArrayBounds },
585     {"setShadowLayer", "(FFFI)V", (void*)SkPaintGlue::setShadowLayer}
586 };
587 
req_fieldID(jfieldID id)588 static jfieldID req_fieldID(jfieldID id) {
589     SkASSERT(id);
590     return id;
591 }
592 
register_android_graphics_Paint(JNIEnv * env)593 int register_android_graphics_Paint(JNIEnv* env) {
594     gFontMetrics_class = env->FindClass("android/graphics/Paint$FontMetrics");
595     SkASSERT(gFontMetrics_class);
596     gFontMetrics_class = (jclass)env->NewGlobalRef(gFontMetrics_class);
597 
598     gFontMetrics_fieldID.top = req_fieldID(env->GetFieldID(gFontMetrics_class, "top", "F"));
599     gFontMetrics_fieldID.ascent = req_fieldID(env->GetFieldID(gFontMetrics_class, "ascent", "F"));
600     gFontMetrics_fieldID.descent = req_fieldID(env->GetFieldID(gFontMetrics_class, "descent", "F"));
601     gFontMetrics_fieldID.bottom = req_fieldID(env->GetFieldID(gFontMetrics_class, "bottom", "F"));
602     gFontMetrics_fieldID.leading = req_fieldID(env->GetFieldID(gFontMetrics_class, "leading", "F"));
603 
604     gFontMetricsInt_class = env->FindClass("android/graphics/Paint$FontMetricsInt");
605     SkASSERT(gFontMetricsInt_class);
606     gFontMetricsInt_class = (jclass)env->NewGlobalRef(gFontMetricsInt_class);
607 
608     gFontMetricsInt_fieldID.top = req_fieldID(env->GetFieldID(gFontMetricsInt_class, "top", "I"));
609     gFontMetricsInt_fieldID.ascent = req_fieldID(env->GetFieldID(gFontMetricsInt_class, "ascent", "I"));
610     gFontMetricsInt_fieldID.descent = req_fieldID(env->GetFieldID(gFontMetricsInt_class, "descent", "I"));
611     gFontMetricsInt_fieldID.bottom = req_fieldID(env->GetFieldID(gFontMetricsInt_class, "bottom", "I"));
612     gFontMetricsInt_fieldID.leading = req_fieldID(env->GetFieldID(gFontMetricsInt_class, "leading", "I"));
613 
614     int result = AndroidRuntime::registerNativeMethods(env, "android/graphics/Paint", methods,
615         sizeof(methods) / sizeof(methods[0]));
616     return result;
617 }
618 
619 }
620