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,int red,int green,int blue,jfloatArray hsvArray)27 static void Color_RGBToHSV(JNIEnv* env, jobject, int red, int green, int 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,int alpha,jfloatArray hsvArray)39 static int Color_HSVToColor(JNIEnv* env, jobject, int alpha, jfloatArray hsvArray)
40 {
41 AutoJavaFloatArray autoHSV(env, hsvArray, 3);
42 float* values = autoHSV.ptr();;
43 SkScalar hsv[3];
44
45 for (int i = 0; i < 3; i++) {
46 hsv[i] = SkFloatToScalar(values[i]);
47 }
48
49 return SkHSVToColor(alpha, hsv);
50 }
51
52 ///////////////////////////////////////////////////////////////////////////////////////////////
53
Shader_destructor(JNIEnv * env,jobject o,SkShader * shader,SkiaShader * skiaShader)54 static void Shader_destructor(JNIEnv* env, jobject o, SkShader* shader, SkiaShader* skiaShader)
55 {
56 SkSafeUnref(shader);
57 // skiaShader == NULL when not !USE_OPENGL_RENDERER, so no need to delete it outside the ifdef
58 #ifdef USE_OPENGL_RENDERER
59 if (android::uirenderer::Caches::hasInstance()) {
60 android::uirenderer::Caches::getInstance().resourceCache.destructor(skiaShader);
61 } else {
62 delete skiaShader;
63 }
64 #endif
65 }
66
Shader_setLocalMatrix(JNIEnv * env,jobject o,SkShader * shader,SkiaShader * skiaShader,const SkMatrix * matrix)67 static void Shader_setLocalMatrix(JNIEnv* env, jobject o, SkShader* shader, SkiaShader* skiaShader,
68 const SkMatrix* matrix)
69 {
70 if (shader) {
71 if (NULL == matrix) {
72 shader->resetLocalMatrix();
73 }
74 else {
75 shader->setLocalMatrix(*matrix);
76 }
77 #ifdef USE_OPENGL_RENDERER
78 skiaShader->setMatrix(const_cast<SkMatrix*>(matrix));
79 #endif
80 }
81 }
82
83 ///////////////////////////////////////////////////////////////////////////////////////////////
84
BitmapShader_constructor(JNIEnv * env,jobject o,const SkBitmap * bitmap,int tileModeX,int tileModeY)85 static SkShader* BitmapShader_constructor(JNIEnv* env, jobject o, const SkBitmap* bitmap,
86 int tileModeX, int tileModeY)
87 {
88 SkShader* s = SkShader::CreateBitmapShader(*bitmap,
89 (SkShader::TileMode)tileModeX,
90 (SkShader::TileMode)tileModeY);
91
92 ThrowIAE_IfNull(env, s);
93 return s;
94 }
95
BitmapShader_postConstructor(JNIEnv * env,jobject o,SkShader * shader,SkBitmap * bitmap,int tileModeX,int tileModeY)96 static SkiaShader* BitmapShader_postConstructor(JNIEnv* env, jobject o, SkShader* shader,
97 SkBitmap* bitmap, int tileModeX, int tileModeY) {
98 #ifdef USE_OPENGL_RENDERER
99 SkiaShader* skiaShader = new SkiaBitmapShader(bitmap, shader,
100 static_cast<SkShader::TileMode>(tileModeX), static_cast<SkShader::TileMode>(tileModeY),
101 NULL, (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0);
102 return skiaShader;
103 #else
104 return NULL;
105 #endif
106 }
107
108 ///////////////////////////////////////////////////////////////////////////////////////////////
109
LinearGradient_create1(JNIEnv * env,jobject o,float x0,float y0,float x1,float y1,jintArray colorArray,jfloatArray posArray,int tileMode)110 static SkShader* LinearGradient_create1(JNIEnv* env, jobject o,
111 float x0, float y0, float x1, float y1,
112 jintArray colorArray, jfloatArray posArray, int tileMode)
113 {
114 SkPoint pts[2];
115 pts[0].set(SkFloatToScalar(x0), SkFloatToScalar(y0));
116 pts[1].set(SkFloatToScalar(x1), SkFloatToScalar(y1));
117
118 size_t count = env->GetArrayLength(colorArray);
119 const jint* colorValues = env->GetIntArrayElements(colorArray, NULL);
120
121 SkAutoSTMalloc<8, SkScalar> storage(posArray ? count : 0);
122 SkScalar* pos = NULL;
123
124 if (posArray) {
125 AutoJavaFloatArray autoPos(env, posArray, count);
126 const float* posValues = autoPos.ptr();
127 pos = (SkScalar*)storage.get();
128 for (size_t i = 0; i < count; i++) {
129 pos[i] = SkFloatToScalar(posValues[i]);
130 }
131 }
132
133 SkShader* shader = SkGradientShader::CreateLinear(pts,
134 reinterpret_cast<const SkColor*>(colorValues),
135 pos, count,
136 static_cast<SkShader::TileMode>(tileMode));
137
138 env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT);
139 ThrowIAE_IfNull(env, shader);
140 return shader;
141 }
142
LinearGradient_postCreate1(JNIEnv * env,jobject o,SkShader * shader,float x0,float y0,float x1,float y1,jintArray colorArray,jfloatArray posArray,int tileMode)143 static SkiaShader* LinearGradient_postCreate1(JNIEnv* env, jobject o, SkShader* shader,
144 float x0, float y0, float x1, float y1, jintArray colorArray,
145 jfloatArray posArray, int tileMode) {
146 #ifdef USE_OPENGL_RENDERER
147 size_t count = env->GetArrayLength(colorArray);
148 const jint* colorValues = env->GetIntArrayElements(colorArray, NULL);
149
150 jfloat* storedBounds = new jfloat[4];
151 storedBounds[0] = x0; storedBounds[1] = y0;
152 storedBounds[2] = x1; storedBounds[3] = y1;
153
154 bool missFirst = false;
155 bool missLast = false;
156 size_t stopCount = count;
157
158 jfloat* storedPositions = NULL;
159 if (posArray) {
160 AutoJavaFloatArray autoPos(env, posArray, count);
161 const float* posValues = autoPos.ptr();
162
163 missFirst = posValues[0] != 0.0f;
164 missLast = posValues[count - 1] != 1.0f;
165
166 stopCount += missFirst + missLast;
167 storedPositions = new jfloat[stopCount];
168
169 if (missFirst) {
170 storedPositions[0] = 0.0f;
171 }
172
173 for (size_t i = missFirst; i < count + missFirst; i++) {
174 storedPositions[i] = posValues[i - missFirst];
175 }
176
177 if (missLast) {
178 storedPositions[stopCount - 1] = 1.0f;
179 }
180 } else {
181 storedPositions = new jfloat[count];
182 storedPositions[0] = 0.0f;
183 const jfloat step = 1.0f / (count - 1);
184 for (size_t i = 1; i < count - 1; i++) {
185 storedPositions[i] = step * i;
186 }
187 storedPositions[count - 1] = 1.0f;
188 }
189
190 uint32_t* storedColors = new uint32_t[stopCount];
191
192 if (missFirst) {
193 storedColors[0] = static_cast<uint32_t>(colorValues[0]);
194 }
195
196 for (size_t i = missFirst; i < count + missFirst; i++) {
197 storedColors[i] = static_cast<uint32_t>(colorValues[i - missFirst]);
198 }
199
200 if (missLast) {
201 storedColors[stopCount - 1] = static_cast<uint32_t>(colorValues[count - 1]);
202 }
203
204 SkiaShader* skiaShader = new SkiaLinearGradientShader(storedBounds, storedColors,
205 storedPositions, stopCount, shader, static_cast<SkShader::TileMode>(tileMode), NULL,
206 (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0);
207
208 env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT);
209 return skiaShader;
210 #else
211 return NULL;
212 #endif
213 }
214
LinearGradient_postCreate2(JNIEnv * env,jobject o,SkShader * shader,float x0,float y0,float x1,float y1,int color0,int color1,int tileMode)215 static SkiaShader* LinearGradient_postCreate2(JNIEnv* env, jobject o, SkShader* shader,
216 float x0, float y0, float x1, float y1, int color0, int color1, int tileMode) {
217 #ifdef USE_OPENGL_RENDERER
218 float* storedBounds = new float[4];
219 storedBounds[0] = x0; storedBounds[1] = y0;
220 storedBounds[2] = x1; storedBounds[3] = y1;
221
222 float* storedPositions = new float[2];
223 storedPositions[0] = 0.0f;
224 storedPositions[1] = 1.0f;
225
226 uint32_t* storedColors = new uint32_t[2];
227 storedColors[0] = static_cast<uint32_t>(color0);
228 storedColors[1] = static_cast<uint32_t>(color1);
229
230 SkiaShader* skiaShader = new SkiaLinearGradientShader(storedBounds, storedColors,
231 storedPositions, 2, shader, static_cast<SkShader::TileMode>(tileMode), NULL,
232 (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0);
233
234 return skiaShader;
235 #else
236 return NULL;
237 #endif
238 }
239
LinearGradient_create2(JNIEnv * env,jobject o,float x0,float y0,float x1,float y1,int color0,int color1,int tileMode)240 static SkShader* LinearGradient_create2(JNIEnv* env, jobject o,
241 float x0, float y0, float x1, float y1,
242 int color0, int color1, int tileMode)
243 {
244 SkPoint pts[2];
245 pts[0].set(SkFloatToScalar(x0), SkFloatToScalar(y0));
246 pts[1].set(SkFloatToScalar(x1), SkFloatToScalar(y1));
247
248 SkColor colors[2];
249 colors[0] = color0;
250 colors[1] = color1;
251
252 SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL, 2, (SkShader::TileMode)tileMode);
253
254 ThrowIAE_IfNull(env, s);
255 return s;
256 }
257
258 ///////////////////////////////////////////////////////////////////////////////////////////////
259
RadialGradient_create1(JNIEnv * env,jobject,float x,float y,float radius,jintArray colorArray,jfloatArray posArray,int tileMode)260 static SkShader* RadialGradient_create1(JNIEnv* env, jobject, float x, float y, float radius,
261 jintArray colorArray, jfloatArray posArray, int tileMode) {
262 SkPoint center;
263 center.set(SkFloatToScalar(x), SkFloatToScalar(y));
264
265 size_t count = env->GetArrayLength(colorArray);
266 const jint* colorValues = env->GetIntArrayElements(colorArray, NULL);
267
268 SkAutoSTMalloc<8, SkScalar> storage(posArray ? count : 0);
269 SkScalar* pos = NULL;
270
271 if (posArray) {
272 AutoJavaFloatArray autoPos(env, posArray, count);
273 const float* posValues = autoPos.ptr();
274 pos = (SkScalar*)storage.get();
275 for (size_t i = 0; i < count; i++)
276 pos[i] = SkFloatToScalar(posValues[i]);
277 }
278
279 SkShader* shader = SkGradientShader::CreateRadial(center,
280 SkFloatToScalar(radius),
281 reinterpret_cast<const SkColor*>(colorValues),
282 pos, count,
283 static_cast<SkShader::TileMode>(tileMode));
284 env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues),
285 JNI_ABORT);
286
287 ThrowIAE_IfNull(env, shader);
288 return shader;
289 }
290
RadialGradient_create2(JNIEnv * env,jobject,float x,float y,float radius,int color0,int color1,int tileMode)291 static SkShader* RadialGradient_create2(JNIEnv* env, jobject, float x, float y, float radius,
292 int color0, int color1, int tileMode) {
293 SkPoint center;
294 center.set(SkFloatToScalar(x), SkFloatToScalar(y));
295
296 SkColor colors[2];
297 colors[0] = color0;
298 colors[1] = color1;
299
300 SkShader* s = SkGradientShader::CreateRadial(center, SkFloatToScalar(radius), colors, NULL,
301 2, (SkShader::TileMode)tileMode);
302 ThrowIAE_IfNull(env, s);
303 return s;
304 }
305
RadialGradient_postCreate1(JNIEnv * env,jobject o,SkShader * shader,float x,float y,float radius,jintArray colorArray,jfloatArray posArray,int tileMode)306 static SkiaShader* RadialGradient_postCreate1(JNIEnv* env, jobject o, SkShader* shader,
307 float x, float y, float radius, jintArray colorArray, jfloatArray posArray, int tileMode) {
308 #ifdef USE_OPENGL_RENDERER
309 size_t count = env->GetArrayLength(colorArray);
310 const jint* colorValues = env->GetIntArrayElements(colorArray, NULL);
311
312 jfloat* storedPositions = new jfloat[count];
313 uint32_t* storedColors = new uint32_t[count];
314 for (size_t i = 0; i < count; i++) {
315 storedColors[i] = static_cast<uint32_t>(colorValues[i]);
316 }
317
318 if (posArray) {
319 AutoJavaFloatArray autoPos(env, posArray, count);
320 const float* posValues = autoPos.ptr();
321 for (size_t i = 0; i < count; i++) {
322 storedPositions[i] = posValues[i];
323 }
324 } else {
325 storedPositions[0] = 0.0f;
326 const jfloat step = 1.0f / (count - 1);
327 for (size_t i = 1; i < count - 1; i++) {
328 storedPositions[i] = step * i;
329 }
330 storedPositions[count - 1] = 1.0f;
331 }
332
333 SkiaShader* skiaShader = new SkiaCircularGradientShader(x, y, radius, storedColors,
334 storedPositions, count, shader, (SkShader::TileMode) tileMode, NULL,
335 (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0);
336
337 env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT);
338 return skiaShader;
339 #else
340 return NULL;
341 #endif
342 }
343
RadialGradient_postCreate2(JNIEnv * env,jobject o,SkShader * shader,float x,float y,float radius,int color0,int color1,int tileMode)344 static SkiaShader* RadialGradient_postCreate2(JNIEnv* env, jobject o, SkShader* shader,
345 float x, float y, float radius, int color0, int color1, int tileMode) {
346 #ifdef USE_OPENGL_RENDERER
347 float* storedPositions = new float[2];
348 storedPositions[0] = 0.0f;
349 storedPositions[1] = 1.0f;
350
351 uint32_t* storedColors = new uint32_t[2];
352 storedColors[0] = static_cast<uint32_t>(color0);
353 storedColors[1] = static_cast<uint32_t>(color1);
354
355 SkiaShader* skiaShader = new SkiaCircularGradientShader(x, y, radius, storedColors,
356 storedPositions, 2, shader, (SkShader::TileMode) tileMode, NULL,
357 (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0);
358
359 return skiaShader;
360 #else
361 return NULL;
362 #endif
363 }
364
365 ///////////////////////////////////////////////////////////////////////////////
366
SweepGradient_create1(JNIEnv * env,jobject,float x,float y,jintArray jcolors,jfloatArray jpositions)367 static SkShader* SweepGradient_create1(JNIEnv* env, jobject, float x, float y,
368 jintArray jcolors, jfloatArray jpositions) {
369 size_t count = env->GetArrayLength(jcolors);
370 const jint* colors = env->GetIntArrayElements(jcolors, NULL);
371
372 SkAutoSTMalloc<8, SkScalar> storage(jpositions ? count : 0);
373 SkScalar* pos = NULL;
374
375 if (NULL != jpositions) {
376 AutoJavaFloatArray autoPos(env, jpositions, count);
377 const float* posValues = autoPos.ptr();
378 pos = (SkScalar*)storage.get();
379 for (size_t i = 0; i < count; i++) {
380 pos[i] = SkFloatToScalar(posValues[i]);
381 }
382 }
383
384 SkShader* shader = SkGradientShader::CreateSweep(SkFloatToScalar(x),
385 SkFloatToScalar(y),
386 reinterpret_cast<const SkColor*>(colors),
387 pos, count);
388 env->ReleaseIntArrayElements(jcolors, const_cast<jint*>(colors),
389 JNI_ABORT);
390 ThrowIAE_IfNull(env, shader);
391 return shader;
392 }
393
SweepGradient_create2(JNIEnv * env,jobject,float x,float y,int color0,int color1)394 static SkShader* SweepGradient_create2(JNIEnv* env, jobject, float x, float y,
395 int color0, int color1) {
396 SkColor colors[2];
397 colors[0] = color0;
398 colors[1] = color1;
399 SkShader* s = SkGradientShader::CreateSweep(SkFloatToScalar(x), SkFloatToScalar(y),
400 colors, NULL, 2);
401 ThrowIAE_IfNull(env, s);
402 return s;
403 }
404
SweepGradient_postCreate1(JNIEnv * env,jobject o,SkShader * shader,float x,float y,jintArray colorArray,jfloatArray posArray)405 static SkiaShader* SweepGradient_postCreate1(JNIEnv* env, jobject o, SkShader* shader,
406 float x, float y, jintArray colorArray, jfloatArray posArray) {
407 #ifdef USE_OPENGL_RENDERER
408 size_t count = env->GetArrayLength(colorArray);
409 const jint* colorValues = env->GetIntArrayElements(colorArray, NULL);
410
411 jfloat* storedPositions = new jfloat[count];
412 uint32_t* storedColors = new uint32_t[count];
413 for (size_t i = 0; i < count; i++) {
414 storedColors[i] = static_cast<uint32_t>(colorValues[i]);
415 }
416
417 if (posArray) {
418 AutoJavaFloatArray autoPos(env, posArray, count);
419 const float* posValues = autoPos.ptr();
420 for (size_t i = 0; i < count; i++) {
421 storedPositions[i] = posValues[i];
422 }
423 } else {
424 storedPositions[0] = 0.0f;
425 const jfloat step = 1.0f / (count - 1);
426 for (size_t i = 1; i < count - 1; i++) {
427 storedPositions[i] = step * i;
428 }
429 storedPositions[count - 1] = 1.0f;
430 }
431
432 SkiaShader* skiaShader = new SkiaSweepGradientShader(x, y, storedColors, storedPositions, count,
433 shader, NULL, (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0);
434
435 env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT);
436 return skiaShader;
437 #else
438 return NULL;
439 #endif
440 }
441
SweepGradient_postCreate2(JNIEnv * env,jobject o,SkShader * shader,float x,float y,int color0,int color1)442 static SkiaShader* SweepGradient_postCreate2(JNIEnv* env, jobject o, SkShader* shader,
443 float x, float y, int color0, int color1) {
444 #ifdef USE_OPENGL_RENDERER
445 float* storedPositions = new float[2];
446 storedPositions[0] = 0.0f;
447 storedPositions[1] = 1.0f;
448
449 uint32_t* storedColors = new uint32_t[2];
450 storedColors[0] = static_cast<uint32_t>(color0);
451 storedColors[1] = static_cast<uint32_t>(color1);
452
453 SkiaShader* skiaShader = new SkiaSweepGradientShader(x, y, storedColors, storedPositions, 2,
454 shader, NULL, (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0);
455
456 return skiaShader;
457 #else
458 return NULL;
459 #endif
460 }
461
462 ///////////////////////////////////////////////////////////////////////////////////////////////
463
ComposeShader_create1(JNIEnv * env,jobject o,SkShader * shaderA,SkShader * shaderB,SkXfermode * mode)464 static SkShader* ComposeShader_create1(JNIEnv* env, jobject o,
465 SkShader* shaderA, SkShader* shaderB, SkXfermode* mode)
466 {
467 return new SkComposeShader(shaderA, shaderB, mode);
468 }
469
ComposeShader_create2(JNIEnv * env,jobject o,SkShader * shaderA,SkShader * shaderB,SkPorterDuff::Mode porterDuffMode)470 static SkShader* ComposeShader_create2(JNIEnv* env, jobject o,
471 SkShader* shaderA, SkShader* shaderB, SkPorterDuff::Mode porterDuffMode)
472 {
473 SkAutoUnref au(SkPorterDuff::CreateXfermode(porterDuffMode));
474 SkXfermode* mode = (SkXfermode*) au.get();
475 return new SkComposeShader(shaderA, shaderB, mode);
476 }
477
ComposeShader_postCreate2(JNIEnv * env,jobject o,SkShader * shader,SkiaShader * shaderA,SkiaShader * shaderB,SkPorterDuff::Mode porterDuffMode)478 static SkiaShader* ComposeShader_postCreate2(JNIEnv* env, jobject o, SkShader* shader,
479 SkiaShader* shaderA, SkiaShader* shaderB, SkPorterDuff::Mode porterDuffMode) {
480 #ifdef USE_OPENGL_RENDERER
481 SkXfermode::Mode mode = SkPorterDuff::ToXfermodeMode(porterDuffMode);
482 return new SkiaComposeShader(shaderA, shaderB, mode, shader);
483 #else
484 return NULL;
485 #endif
486 }
487
ComposeShader_postCreate1(JNIEnv * env,jobject o,SkShader * shader,SkiaShader * shaderA,SkiaShader * shaderB,SkXfermode * mode)488 static SkiaShader* ComposeShader_postCreate1(JNIEnv* env, jobject o, SkShader* shader,
489 SkiaShader* shaderA, SkiaShader* shaderB, SkXfermode* mode) {
490 #ifdef USE_OPENGL_RENDERER
491 SkXfermode::Mode skiaMode;
492 if (!SkXfermode::IsMode(mode, &skiaMode)) {
493 // TODO: Support other modes
494 skiaMode = SkXfermode::kSrcOver_Mode;
495 }
496 return new SkiaComposeShader(shaderA, shaderB, skiaMode, shader);
497 #else
498 return NULL;
499 #endif
500 }
501
502 ///////////////////////////////////////////////////////////////////////////////////////////////
503
504 static JNINativeMethod gColorMethods[] = {
505 { "nativeRGBToHSV", "(III[F)V", (void*)Color_RGBToHSV },
506 { "nativeHSVToColor", "(I[F)I", (void*)Color_HSVToColor }
507 };
508
509 static JNINativeMethod gShaderMethods[] = {
510 { "nativeDestructor", "(II)V", (void*)Shader_destructor },
511 { "nativeSetLocalMatrix", "(III)V", (void*)Shader_setLocalMatrix }
512 };
513
514 static JNINativeMethod gBitmapShaderMethods[] = {
515 { "nativeCreate", "(III)I", (void*)BitmapShader_constructor },
516 { "nativePostCreate", "(IIII)I", (void*)BitmapShader_postConstructor }
517 };
518
519 static JNINativeMethod gLinearGradientMethods[] = {
520 { "nativeCreate1", "(FFFF[I[FI)I", (void*)LinearGradient_create1 },
521 { "nativeCreate2", "(FFFFIII)I", (void*)LinearGradient_create2 },
522 { "nativePostCreate1", "(IFFFF[I[FI)I", (void*)LinearGradient_postCreate1 },
523 { "nativePostCreate2", "(IFFFFIII)I", (void*)LinearGradient_postCreate2 }
524 };
525
526 static JNINativeMethod gRadialGradientMethods[] = {
527 { "nativeCreate1", "(FFF[I[FI)I", (void*)RadialGradient_create1 },
528 { "nativeCreate2", "(FFFIII)I", (void*)RadialGradient_create2 },
529 { "nativePostCreate1", "(IFFF[I[FI)I", (void*)RadialGradient_postCreate1 },
530 { "nativePostCreate2", "(IFFFIII)I", (void*)RadialGradient_postCreate2 }
531 };
532
533 static JNINativeMethod gSweepGradientMethods[] = {
534 { "nativeCreate1", "(FF[I[F)I", (void*)SweepGradient_create1 },
535 { "nativeCreate2", "(FFII)I", (void*)SweepGradient_create2 },
536 { "nativePostCreate1", "(IFF[I[F)I", (void*)SweepGradient_postCreate1 },
537 { "nativePostCreate2", "(IFFII)I", (void*)SweepGradient_postCreate2 }
538 };
539
540 static JNINativeMethod gComposeShaderMethods[] = {
541 { "nativeCreate1", "(III)I", (void*)ComposeShader_create1 },
542 { "nativeCreate2", "(III)I", (void*)ComposeShader_create2 },
543 { "nativePostCreate1", "(IIII)I", (void*)ComposeShader_postCreate1 },
544 { "nativePostCreate2", "(IIII)I", (void*)ComposeShader_postCreate2 }
545 };
546
547 #include <android_runtime/AndroidRuntime.h>
548
549 #define REG(env, name, array) \
550 result = android::AndroidRuntime::registerNativeMethods(env, name, array, SK_ARRAY_COUNT(array)); \
551 if (result < 0) return result
552
register_android_graphics_Shader(JNIEnv * env)553 int register_android_graphics_Shader(JNIEnv* env)
554 {
555 int result;
556
557 REG(env, "android/graphics/Color", gColorMethods);
558 REG(env, "android/graphics/Shader", gShaderMethods);
559 REG(env, "android/graphics/BitmapShader", gBitmapShaderMethods);
560 REG(env, "android/graphics/LinearGradient", gLinearGradientMethods);
561 REG(env, "android/graphics/RadialGradient", gRadialGradientMethods);
562 REG(env, "android/graphics/SweepGradient", gSweepGradientMethods);
563 REG(env, "android/graphics/ComposeShader", gComposeShaderMethods);
564
565 return result;
566 }
567