blob: b09c62b7d2b3e1e907c4d49c726c0be013d546a5 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001#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
11static void ThrowIAE_IfNull(JNIEnv* env, void* ptr) {
12 if (NULL == ptr) {
13 doThrowIAE(env);
14 }
15}
16
17static 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
29static 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
44static void Shader_destructor(JNIEnv* env, jobject, SkShader* shader)
45{
Mike Reed6af25522009-07-30 11:46:47 -040046 shader->safeUnref();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047}
48
49static bool Shader_getLocalMatrix(JNIEnv* env, jobject, const SkShader* shader, SkMatrix* matrix)
50{
Mike Reeda04e5552009-07-30 11:05:57 -040051 return shader ? shader->getLocalMatrix(matrix) : false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052}
53
54static void Shader_setLocalMatrix(JNIEnv* env, jobject, SkShader* shader, const SkMatrix* matrix)
55{
Mike Reeda04e5552009-07-30 11:05:57 -040056 if (shader) {
57 if (NULL == matrix) {
58 shader->resetLocalMatrix();
59 }
60 else {
61 shader->setLocalMatrix(*matrix);
62 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080063 }
64}
65
66///////////////////////////////////////////////////////////////////////////////////////////////
67
68static 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
80static 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
112static 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
131static 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
164static 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
183static 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
211static 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
225static SkShader* ComposeShader_create1(JNIEnv* env, jobject,
226 SkShader* shaderA, SkShader* shaderB, SkXfermode* mode)
227{
228 return new SkComposeShader(shaderA, shaderB, mode);
229}
230
231static 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
241static JNINativeMethod gColorMethods[] = {
242 { "nativeRGBToHSV", "(III[F)V", (void*)Color_RGBToHSV },
243 { "nativeHSVToColor", "(I[F)I", (void*)Color_HSVToColor }
244};
245
246static 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
252static JNINativeMethod gBitmapShaderMethods[] = {
253 { "nativeCreate", "(III)I", (void*)BitmapShader_constructor }
254};
255
256static JNINativeMethod gLinearGradientMethods[] = {
257 { "nativeCreate1", "(FFFF[I[FI)I", (void*)LinearGradient_create1 },
258 { "nativeCreate2", "(FFFFIII)I", (void*)LinearGradient_create2 }
259};
260
261static JNINativeMethod gRadialGradientMethods[] = {
262 {"nativeCreate1", "(FFF[I[FI)I", (void*)RadialGradient_create1 },
263 {"nativeCreate2", "(FFFIII)I", (void*)RadialGradient_create2 }
264};
265
266static JNINativeMethod gSweepGradientMethods[] = {
267 {"nativeCreate1", "(FF[I[F)I", (void*)SweepGradient_create1 },
268 {"nativeCreate2", "(FFII)I", (void*)SweepGradient_create2 }
269};
270
271static 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
282int register_android_graphics_Shader(JNIEnv* env);
283int 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