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