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