• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <jni.h>
2 #include "GraphicsJNI.h"
3 
4 #include "SkShader.h"
5 #include "SkGradientShader.h"
6 #include "SkPorterDuff.h"
7 #include "SkComposeShader.h"
8 #include "SkTemplates.h"
9 #include "SkXfermode.h"
10 
ThrowIAE_IfNull(JNIEnv * env,void * ptr)11 static void ThrowIAE_IfNull(JNIEnv* env, void* ptr) {
12     if (NULL == ptr) {
13         doThrowIAE(env);
14     }
15 }
16 
Color_RGBToHSV(JNIEnv * env,jobject,int red,int green,int blue,jfloatArray hsvArray)17 static void Color_RGBToHSV(JNIEnv* env, jobject, int red, int green, int blue, jfloatArray hsvArray)
18 {
19     SkScalar hsv[3];
20     SkRGBToHSV(red, green, blue, hsv);
21 
22     AutoJavaFloatArray  autoHSV(env, hsvArray, 3);
23     float* values = autoHSV.ptr();
24     for (int i = 0; i < 3; i++) {
25         values[i] = SkScalarToFloat(hsv[i]);
26     }
27 }
28 
Color_HSVToColor(JNIEnv * env,jobject,int alpha,jfloatArray hsvArray)29 static int Color_HSVToColor(JNIEnv* env, jobject, int alpha, jfloatArray hsvArray)
30 {
31     AutoJavaFloatArray  autoHSV(env, hsvArray, 3);
32     float*      values = autoHSV.ptr();;
33     SkScalar    hsv[3];
34 
35     for (int i = 0; i < 3; i++) {
36         hsv[i] = SkFloatToScalar(values[i]);
37     }
38 
39     return SkHSVToColor(alpha, hsv);
40 }
41 
42 ///////////////////////////////////////////////////////////////////////////////////////////////
43 
Shader_destructor(JNIEnv * env,jobject,SkShader * shader)44 static void Shader_destructor(JNIEnv* env, jobject, SkShader* shader)
45 {
46     shader->safeUnref();
47 }
48 
Shader_getLocalMatrix(JNIEnv * env,jobject,const SkShader * shader,SkMatrix * matrix)49 static bool Shader_getLocalMatrix(JNIEnv* env, jobject, const SkShader* shader, SkMatrix* matrix)
50 {
51     return shader ? shader->getLocalMatrix(matrix) : false;
52 }
53 
Shader_setLocalMatrix(JNIEnv * env,jobject,SkShader * shader,const SkMatrix * matrix)54 static void Shader_setLocalMatrix(JNIEnv* env, jobject, SkShader* shader, const SkMatrix* matrix)
55 {
56     if (shader) {
57         if (NULL == matrix) {
58             shader->resetLocalMatrix();
59         }
60         else {
61             shader->setLocalMatrix(*matrix);
62         }
63     }
64 }
65 
66 ///////////////////////////////////////////////////////////////////////////////////////////////
67 
BitmapShader_constructor(JNIEnv * env,jobject,const SkBitmap * bitmap,int tileModeX,int tileModeY)68 static SkShader* BitmapShader_constructor(JNIEnv* env, jobject, const SkBitmap* bitmap,
69                                           int tileModeX, int tileModeY)
70 {
71     SkShader* s = SkShader::CreateBitmapShader(*bitmap,
72                                         (SkShader::TileMode)tileModeX,
73                                         (SkShader::TileMode)tileModeY);
74     ThrowIAE_IfNull(env, s);
75     return s;
76 }
77 
78 ///////////////////////////////////////////////////////////////////////////////////////////////
79 
LinearGradient_create1(JNIEnv * env,jobject,float x0,float y0,float x1,float y1,jintArray colorArray,jfloatArray posArray,int tileMode)80 static SkShader* LinearGradient_create1(JNIEnv* env, jobject,
81                                         float x0, float y0, float x1, float y1,
82                                         jintArray colorArray, jfloatArray posArray, int tileMode)
83 {
84     SkPoint pts[2];
85     pts[0].set(SkFloatToScalar(x0), SkFloatToScalar(y0));
86     pts[1].set(SkFloatToScalar(x1), SkFloatToScalar(y1));
87 
88     size_t      count = env->GetArrayLength(colorArray);
89     const jint* colorValues = env->GetIntArrayElements(colorArray, NULL);
90 
91     SkAutoSTMalloc<8, SkScalar> storage(posArray ? count : 0);
92     SkScalar*                   pos = NULL;
93 
94     if (posArray) {
95         AutoJavaFloatArray autoPos(env, posArray, count);
96         const float* posValues = autoPos.ptr();
97         pos = (SkScalar*)storage.get();
98         for (size_t i = 0; i < count; i++)
99             pos[i] = SkFloatToScalar(posValues[i]);
100     }
101 
102     SkShader* shader = SkGradientShader::CreateLinear(pts,
103                                 reinterpret_cast<const SkColor*>(colorValues),
104                                 pos, count,
105                                 static_cast<SkShader::TileMode>(tileMode));
106     env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues),
107                                  JNI_ABORT);
108     ThrowIAE_IfNull(env, shader);
109     return shader;
110 }
111 
LinearGradient_create2(JNIEnv * env,jobject,float x0,float y0,float x1,float y1,int color0,int color1,int tileMode)112 static SkShader* LinearGradient_create2(JNIEnv* env, jobject,
113                                         float x0, float y0, float x1, float y1,
114                                         int color0, int color1, int tileMode)
115 {
116     SkPoint pts[2];
117     pts[0].set(SkFloatToScalar(x0), SkFloatToScalar(y0));
118     pts[1].set(SkFloatToScalar(x1), SkFloatToScalar(y1));
119 
120     SkColor colors[2];
121     colors[0] = color0;
122     colors[1] = color1;
123 
124     SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL, 2, (SkShader::TileMode)tileMode);
125     ThrowIAE_IfNull(env, s);
126     return s;
127 }
128 
129 ///////////////////////////////////////////////////////////////////////////////////////////////
130 
RadialGradient_create1(JNIEnv * env,jobject,float x,float y,float radius,jintArray colorArray,jfloatArray posArray,int tileMode)131 static SkShader* RadialGradient_create1(JNIEnv* env, jobject,
132                                         float x, float y, float radius,
133                                         jintArray colorArray, jfloatArray posArray, int tileMode)
134 {
135     SkPoint center;
136     center.set(SkFloatToScalar(x), SkFloatToScalar(y));
137 
138     size_t      count = env->GetArrayLength(colorArray);
139     const jint* colorValues = env->GetIntArrayElements(colorArray, NULL);
140 
141     SkAutoSTMalloc<8, SkScalar> storage(posArray ? count : 0);
142     SkScalar*                   pos = NULL;
143 
144     if (posArray) {
145         AutoJavaFloatArray autoPos(env, posArray, count);
146         const float* posValues = autoPos.ptr();
147         pos = (SkScalar*)storage.get();
148         for (size_t i = 0; i < count; i++)
149             pos[i] = SkFloatToScalar(posValues[i]);
150     }
151 
152     SkShader* shader = SkGradientShader::CreateRadial(center,
153                                 SkFloatToScalar(radius),
154                                 reinterpret_cast<const SkColor*>(colorValues),
155                                 pos, count,
156                                 static_cast<SkShader::TileMode>(tileMode));
157     env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues),
158                                  JNI_ABORT);
159 
160     ThrowIAE_IfNull(env, shader);
161     return shader;
162 }
163 
RadialGradient_create2(JNIEnv * env,jobject,float x,float y,float radius,int color0,int color1,int tileMode)164 static SkShader* RadialGradient_create2(JNIEnv* env, jobject,
165                                         float x, float y, float radius,
166                                         int color0, int color1, int tileMode)
167 {
168     SkPoint center;
169     center.set(SkFloatToScalar(x), SkFloatToScalar(y));
170 
171     SkColor colors[2];
172     colors[0] = color0;
173     colors[1] = color1;
174 
175     SkShader* s = SkGradientShader::CreateRadial(center, SkFloatToScalar(radius), colors, NULL,
176                                           2, (SkShader::TileMode)tileMode);
177     ThrowIAE_IfNull(env, s);
178     return s;
179 }
180 
181 ///////////////////////////////////////////////////////////////////////////////
182 
SweepGradient_create1(JNIEnv * env,jobject,float x,float y,jintArray jcolors,jfloatArray jpositions)183 static SkShader* SweepGradient_create1(JNIEnv* env, jobject, float x, float y,
184                                     jintArray jcolors, jfloatArray jpositions)
185 {
186     size_t      count = env->GetArrayLength(jcolors);
187     const jint* colors = env->GetIntArrayElements(jcolors, NULL);
188 
189     SkAutoSTMalloc<8, SkScalar> storage(jpositions ? count : 0);
190     SkScalar*                   pos = NULL;
191 
192     if (NULL != jpositions) {
193         AutoJavaFloatArray autoPos(env, jpositions, count);
194         const float* posValues = autoPos.ptr();
195         pos = (SkScalar*)storage.get();
196         for (size_t i = 0; i < count; i++) {
197             pos[i] = SkFloatToScalar(posValues[i]);
198         }
199     }
200 
201     SkShader* shader = SkGradientShader::CreateSweep(SkFloatToScalar(x),
202                                      SkFloatToScalar(y),
203                                      reinterpret_cast<const SkColor*>(colors),
204                                      pos, count);
205     env->ReleaseIntArrayElements(jcolors, const_cast<jint*>(colors),
206                                  JNI_ABORT);
207     ThrowIAE_IfNull(env, shader);
208     return shader;
209 }
210 
SweepGradient_create2(JNIEnv * env,jobject,float x,float y,int color0,int color1)211 static SkShader* SweepGradient_create2(JNIEnv* env, jobject, float x, float y,
212                                         int color0, int color1)
213 {
214     SkColor colors[2];
215     colors[0] = color0;
216     colors[1] = color1;
217     SkShader* s = SkGradientShader::CreateSweep(SkFloatToScalar(x), SkFloatToScalar(y),
218                                          colors, NULL, 2);
219     ThrowIAE_IfNull(env, s);
220     return s;
221 }
222 
223 ///////////////////////////////////////////////////////////////////////////////////////////////
224 
ComposeShader_create1(JNIEnv * env,jobject,SkShader * shaderA,SkShader * shaderB,SkXfermode * mode)225 static SkShader* ComposeShader_create1(JNIEnv* env, jobject,
226                                        SkShader* shaderA, SkShader* shaderB, SkXfermode* mode)
227 {
228     return new SkComposeShader(shaderA, shaderB, mode);
229 }
230 
ComposeShader_create2(JNIEnv * env,jobject,SkShader * shaderA,SkShader * shaderB,SkPorterDuff::Mode mode)231 static SkShader* ComposeShader_create2(JNIEnv* env, jobject,
232                                        SkShader* shaderA, SkShader* shaderB, SkPorterDuff::Mode mode)
233 {
234     SkAutoUnref au(SkPorterDuff::CreateXfermode(mode));
235 
236     return new SkComposeShader(shaderA, shaderB, (SkXfermode*)au.get());
237 }
238 
239 ///////////////////////////////////////////////////////////////////////////////////////////////
240 
241 static JNINativeMethod gColorMethods[] = {
242     { "nativeRGBToHSV",     "(III[F)V", (void*)Color_RGBToHSV   },
243     { "nativeHSVToColor",   "(I[F)I",   (void*)Color_HSVToColor }
244 };
245 
246 static JNINativeMethod gShaderMethods[] = {
247     { "nativeDestructor",        "(I)V",     (void*)Shader_destructor        },
248     { "nativeGetLocalMatrix",    "(II)Z",    (void*)Shader_getLocalMatrix    },
249     { "nativeSetLocalMatrix",    "(II)V",    (void*)Shader_setLocalMatrix    }
250 };
251 
252 static JNINativeMethod gBitmapShaderMethods[] = {
253     { "nativeCreate",   "(III)I",  (void*)BitmapShader_constructor }
254 };
255 
256 static JNINativeMethod gLinearGradientMethods[] = {
257     { "nativeCreate1",  "(FFFF[I[FI)I", (void*)LinearGradient_create1   },
258     { "nativeCreate2",  "(FFFFIII)I",   (void*)LinearGradient_create2   }
259 };
260 
261 static JNINativeMethod gRadialGradientMethods[] = {
262     {"nativeCreate1",   "(FFF[I[FI)I",  (void*)RadialGradient_create1   },
263     {"nativeCreate2",   "(FFFIII)I",    (void*)RadialGradient_create2   }
264 };
265 
266 static JNINativeMethod gSweepGradientMethods[] = {
267     {"nativeCreate1",   "(FF[I[F)I",  (void*)SweepGradient_create1   },
268     {"nativeCreate2",   "(FFII)I",    (void*)SweepGradient_create2   }
269 };
270 
271 static JNINativeMethod gComposeShaderMethods[] = {
272     {"nativeCreate1",  "(III)I",    (void*)ComposeShader_create1 },
273     {"nativeCreate2",  "(III)I",    (void*)ComposeShader_create2 }
274 };
275 
276 #include <android_runtime/AndroidRuntime.h>
277 
278 #define REG(env, name, array)                                                                       \
279     result = android::AndroidRuntime::registerNativeMethods(env, name, array, SK_ARRAY_COUNT(array));  \
280     if (result < 0) return result
281 
282 int register_android_graphics_Shader(JNIEnv* env);
register_android_graphics_Shader(JNIEnv * env)283 int register_android_graphics_Shader(JNIEnv* env)
284 {
285     int result;
286 
287     REG(env, "android/graphics/Color", gColorMethods);
288     REG(env, "android/graphics/Shader", gShaderMethods);
289     REG(env, "android/graphics/BitmapShader", gBitmapShaderMethods);
290     REG(env, "android/graphics/LinearGradient", gLinearGradientMethods);
291     REG(env, "android/graphics/RadialGradient", gRadialGradientMethods);
292     REG(env, "android/graphics/SweepGradient", gSweepGradientMethods);
293     REG(env, "android/graphics/ComposeShader", gComposeShaderMethods);
294 
295     return result;
296 }
297 
298