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