Shader.cpp revision 6af2552d244ff933dfd54570121db455cc7c3cda
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
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{
46    shader->safeUnref();
47}
48
49static bool Shader_getLocalMatrix(JNIEnv* env, jobject, const SkShader* shader, SkMatrix* matrix)
50{
51    return shader ? shader->getLocalMatrix(matrix) : false;
52}
53
54static 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
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
298