• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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