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