blob: 1fe6358ebc48ac0222a23b62633cb9609ff5526e [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001#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
Romain Guy06f96e22010-07-30 19:18:16 -070011#include <SkiaShader.h>
Romain Guya2341a92010-09-08 18:04:33 -070012#include <Caches.h>
Romain Guy06f96e22010-07-30 19:18:16 -070013
14using namespace android::uirenderer;
15
Romain Guy7fac2e12010-07-16 17:10:13 -070016static struct {
17 jclass clazz;
Romain Guy06f96e22010-07-30 19:18:16 -070018 jfieldID shader;
19} gShaderClassInfo;
Romain Guy7fac2e12010-07-16 17:10:13 -070020
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080021static void ThrowIAE_IfNull(JNIEnv* env, void* ptr) {
22 if (NULL == ptr) {
23 doThrowIAE(env);
24 }
25}
26
Ashok Bhat36bef0b2014-01-20 20:08:01 +000027static void Color_RGBToHSV(JNIEnv* env, jobject, jint red, jint green, jint blue, jfloatArray hsvArray)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028{
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}
Elliott Hughes4cb17532011-04-12 16:10:26 -070038
Ashok Bhat36bef0b2014-01-20 20:08:01 +000039static jint Color_HSVToColor(JNIEnv* env, jobject, jint alpha, jfloatArray hsvArray)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040{
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 }
Elliott Hughes4cb17532011-04-12 16:10:26 -070048
Ashok Bhat36bef0b2014-01-20 20:08:01 +000049 return static_cast<jint>(SkHSVToColor(alpha, hsv));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050}
51
52///////////////////////////////////////////////////////////////////////////////////////////////
53
Ashok Bhat36bef0b2014-01-20 20:08:01 +000054static void Shader_destructor(JNIEnv* env, jobject o, jlong shaderHandle, jlong skiaShaderHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055{
Ashok Bhat36bef0b2014-01-20 20:08:01 +000056 SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle);
57 SkiaShader* skiaShader = reinterpret_cast<SkiaShader*>(skiaShaderHandle);
Derek Sollenberger6062c592011-02-22 13:55:04 -050058 SkSafeUnref(shader);
Chet Haase5c13d892010-10-08 08:37:55 -070059 // skiaShader == NULL when not !USE_OPENGL_RENDERER, so no need to delete it outside the ifdef
Romain Guya2341a92010-09-08 18:04:33 -070060#ifdef USE_OPENGL_RENDERER
61 if (android::uirenderer::Caches::hasInstance()) {
Chet Haase5c13d892010-10-08 08:37:55 -070062 android::uirenderer::Caches::getInstance().resourceCache.destructor(skiaShader);
Chet Haasead93c2b2010-10-22 16:17:12 -070063 } else {
64 delete skiaShader;
Romain Guya2341a92010-09-08 18:04:33 -070065 }
66#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080067}
68
Ashok Bhat36bef0b2014-01-20 20:08:01 +000069static void Shader_setLocalMatrix(JNIEnv* env, jobject o, jlong shaderHandle,
70 jlong skiaShaderHandle, jlong matrixHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071{
Ashok Bhat36bef0b2014-01-20 20:08:01 +000072 SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle);
73 SkiaShader* skiaShader = reinterpret_cast<SkiaShader*>(skiaShaderHandle);
74 const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
Mike Reeda04e5552009-07-30 11:05:57 -040075 if (shader) {
76 if (NULL == matrix) {
77 shader->resetLocalMatrix();
78 }
79 else {
80 shader->setLocalMatrix(*matrix);
81 }
Romain Guy16393512010-08-08 00:14:31 -070082#ifdef USE_OPENGL_RENDERER
Romain Guy06f96e22010-07-30 19:18:16 -070083 skiaShader->setMatrix(const_cast<SkMatrix*>(matrix));
Romain Guy16393512010-08-08 00:14:31 -070084#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085 }
86}
87
88///////////////////////////////////////////////////////////////////////////////////////////////
89
Ashok Bhat36bef0b2014-01-20 20:08:01 +000090static jlong BitmapShader_constructor(JNIEnv* env, jobject o, jlong bitmapHandle,
91 jint tileModeX, jint tileModeY)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080092{
Ashok Bhat36bef0b2014-01-20 20:08:01 +000093 const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080094 SkShader* s = SkShader::CreateBitmapShader(*bitmap,
95 (SkShader::TileMode)tileModeX,
96 (SkShader::TileMode)tileModeY);
Romain Guy06f96e22010-07-30 19:18:16 -070097
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080098 ThrowIAE_IfNull(env, s);
Ashok Bhat36bef0b2014-01-20 20:08:01 +000099 return reinterpret_cast<jlong>(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800100}
Romain Guy06f96e22010-07-30 19:18:16 -0700101
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000102static jlong BitmapShader_postConstructor(JNIEnv* env, jobject o, jlong shaderHandle,
103 jlong bitmapHandle, jint tileModeX, jint tileModeY) {
104 SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle);
105 SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
Romain Guy16393512010-08-08 00:14:31 -0700106#ifdef USE_OPENGL_RENDERER
Romain Guy06f96e22010-07-30 19:18:16 -0700107 SkiaShader* skiaShader = new SkiaBitmapShader(bitmap, shader,
108 static_cast<SkShader::TileMode>(tileModeX), static_cast<SkShader::TileMode>(tileModeY),
109 NULL, (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000110 return reinterpret_cast<jlong>(skiaShader);
Romain Guy16393512010-08-08 00:14:31 -0700111#else
112 return NULL;
113#endif
Romain Guy06f96e22010-07-30 19:18:16 -0700114}
Elliott Hughes4cb17532011-04-12 16:10:26 -0700115
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800116///////////////////////////////////////////////////////////////////////////////////////////////
117
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000118static jlong LinearGradient_create1(JNIEnv* env, jobject o,
119 jfloat x0, jfloat y0, jfloat x1, jfloat y1,
120 jintArray colorArray, jfloatArray posArray, jint tileMode)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800121{
122 SkPoint pts[2];
123 pts[0].set(SkFloatToScalar(x0), SkFloatToScalar(y0));
124 pts[1].set(SkFloatToScalar(x1), SkFloatToScalar(y1));
125
Romain Guy06f96e22010-07-30 19:18:16 -0700126 size_t count = env->GetArrayLength(colorArray);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800127 const jint* colorValues = env->GetIntArrayElements(colorArray, NULL);
128
129 SkAutoSTMalloc<8, SkScalar> storage(posArray ? count : 0);
Romain Guy7b5b6ab2011-03-14 18:05:08 -0700130 SkScalar* pos = NULL;
Romain Guy7fac2e12010-07-16 17:10:13 -0700131
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800132 if (posArray) {
133 AutoJavaFloatArray autoPos(env, posArray, count);
134 const float* posValues = autoPos.ptr();
135 pos = (SkScalar*)storage.get();
Romain Guy7fac2e12010-07-16 17:10:13 -0700136 for (size_t i = 0; i < count; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800137 pos[i] = SkFloatToScalar(posValues[i]);
Romain Guy06f96e22010-07-30 19:18:16 -0700138 }
139 }
Elliott Hughes4cb17532011-04-12 16:10:26 -0700140
Romain Guy06f96e22010-07-30 19:18:16 -0700141 SkShader* shader = SkGradientShader::CreateLinear(pts,
142 reinterpret_cast<const SkColor*>(colorValues),
143 pos, count,
144 static_cast<SkShader::TileMode>(tileMode));
145
146 env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT);
147 ThrowIAE_IfNull(env, shader);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000148 return reinterpret_cast<jlong>(shader);
Romain Guy06f96e22010-07-30 19:18:16 -0700149}
150
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000151static jlong LinearGradient_postCreate1(JNIEnv* env, jobject o, jlong shaderHandle,
152 jfloat x0, jfloat y0, jfloat x1, jfloat y1, jintArray colorArray,
153 jfloatArray posArray, jint tileMode) {
Romain Guy16393512010-08-08 00:14:31 -0700154#ifdef USE_OPENGL_RENDERER
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000155 SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle);
Romain Guy06f96e22010-07-30 19:18:16 -0700156 size_t count = env->GetArrayLength(colorArray);
157 const jint* colorValues = env->GetIntArrayElements(colorArray, NULL);
158
159 jfloat* storedBounds = new jfloat[4];
160 storedBounds[0] = x0; storedBounds[1] = y0;
161 storedBounds[2] = x1; storedBounds[3] = y1;
Romain Guy42e1e0d2012-07-30 14:47:51 -0700162
163 bool missFirst = false;
164 bool missLast = false;
165 size_t stopCount = count;
Romain Guy06f96e22010-07-30 19:18:16 -0700166
Romain Guy42e1e0d2012-07-30 14:47:51 -0700167 jfloat* storedPositions = NULL;
Romain Guy06f96e22010-07-30 19:18:16 -0700168 if (posArray) {
169 AutoJavaFloatArray autoPos(env, posArray, count);
170 const float* posValues = autoPos.ptr();
Romain Guy42e1e0d2012-07-30 14:47:51 -0700171
172 missFirst = posValues[0] != 0.0f;
173 missLast = posValues[count - 1] != 1.0f;
174
175 stopCount += missFirst + missLast;
176 storedPositions = new jfloat[stopCount];
177
178 if (missFirst) {
179 storedPositions[0] = 0.0f;
180 }
181
182 for (size_t i = missFirst; i < count + missFirst; i++) {
183 storedPositions[i] = posValues[i - missFirst];
184 }
185
186 if (missLast) {
187 storedPositions[stopCount - 1] = 1.0f;
Romain Guy7fac2e12010-07-16 17:10:13 -0700188 }
189 } else {
Romain Guy42e1e0d2012-07-30 14:47:51 -0700190 storedPositions = new jfloat[count];
Romain Guy7fac2e12010-07-16 17:10:13 -0700191 storedPositions[0] = 0.0f;
Romain Guy7b5b6ab2011-03-14 18:05:08 -0700192 const jfloat step = 1.0f / (count - 1);
193 for (size_t i = 1; i < count - 1; i++) {
194 storedPositions[i] = step * i;
195 }
196 storedPositions[count - 1] = 1.0f;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800197 }
Romain Guy06f96e22010-07-30 19:18:16 -0700198
Romain Guy42e1e0d2012-07-30 14:47:51 -0700199 uint32_t* storedColors = new uint32_t[stopCount];
200
201 if (missFirst) {
202 storedColors[0] = static_cast<uint32_t>(colorValues[0]);
203 }
204
205 for (size_t i = missFirst; i < count + missFirst; i++) {
206 storedColors[i] = static_cast<uint32_t>(colorValues[i - missFirst]);
207 }
208
209 if (missLast) {
210 storedColors[stopCount - 1] = static_cast<uint32_t>(colorValues[count - 1]);
211 }
212
Romain Guy06f96e22010-07-30 19:18:16 -0700213 SkiaShader* skiaShader = new SkiaLinearGradientShader(storedBounds, storedColors,
Romain Guy42e1e0d2012-07-30 14:47:51 -0700214 storedPositions, stopCount, shader, static_cast<SkShader::TileMode>(tileMode), NULL,
Romain Guy06f96e22010-07-30 19:18:16 -0700215 (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0);
216
217 env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000218 return reinterpret_cast<jlong>(skiaShader);
Romain Guy16393512010-08-08 00:14:31 -0700219#else
220 return NULL;
221#endif
Romain Guy06f96e22010-07-30 19:18:16 -0700222}
223
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000224static jlong LinearGradient_postCreate2(JNIEnv* env, jobject o, jlong shaderHandle,
225 jfloat x0, jfloat y0, jfloat x1, jfloat y1, jint color0, jint color1, jint tileMode) {
Romain Guy16393512010-08-08 00:14:31 -0700226#ifdef USE_OPENGL_RENDERER
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000227 SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle);
Romain Guy06f96e22010-07-30 19:18:16 -0700228 float* storedBounds = new float[4];
229 storedBounds[0] = x0; storedBounds[1] = y0;
230 storedBounds[2] = x1; storedBounds[3] = y1;
231
232 float* storedPositions = new float[2];
233 storedPositions[0] = 0.0f;
234 storedPositions[1] = 1.0f;
235
236 uint32_t* storedColors = new uint32_t[2];
Romain Guy61c8c9c2010-08-09 20:48:09 -0700237 storedColors[0] = static_cast<uint32_t>(color0);
238 storedColors[1] = static_cast<uint32_t>(color1);
Romain Guy06f96e22010-07-30 19:18:16 -0700239
240 SkiaShader* skiaShader = new SkiaLinearGradientShader(storedBounds, storedColors,
241 storedPositions, 2, shader, static_cast<SkShader::TileMode>(tileMode), NULL,
242 (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0);
243
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000244 return reinterpret_cast<jlong>(skiaShader);
Romain Guy16393512010-08-08 00:14:31 -0700245#else
246 return NULL;
247#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800248}
249
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000250static jlong LinearGradient_create2(JNIEnv* env, jobject o,
251 jfloat x0, jfloat y0, jfloat x1, jfloat y1,
252 jint color0, jint color1, jint tileMode)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800253{
254 SkPoint pts[2];
255 pts[0].set(SkFloatToScalar(x0), SkFloatToScalar(y0));
256 pts[1].set(SkFloatToScalar(x1), SkFloatToScalar(y1));
257
258 SkColor colors[2];
259 colors[0] = color0;
260 colors[1] = color1;
Elliott Hughes4cb17532011-04-12 16:10:26 -0700261
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800262 SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL, 2, (SkShader::TileMode)tileMode);
Romain Guy06f96e22010-07-30 19:18:16 -0700263
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800264 ThrowIAE_IfNull(env, s);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000265 return reinterpret_cast<jlong>(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800266}
267
268///////////////////////////////////////////////////////////////////////////////////////////////
269
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000270static jlong RadialGradient_create1(JNIEnv* env, jobject, jfloat x, jfloat y, jfloat radius,
271 jintArray colorArray, jfloatArray posArray, jint tileMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800272 SkPoint center;
273 center.set(SkFloatToScalar(x), SkFloatToScalar(y));
274
275 size_t count = env->GetArrayLength(colorArray);
276 const jint* colorValues = env->GetIntArrayElements(colorArray, NULL);
277
278 SkAutoSTMalloc<8, SkScalar> storage(posArray ? count : 0);
279 SkScalar* pos = NULL;
Elliott Hughes4cb17532011-04-12 16:10:26 -0700280
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800281 if (posArray) {
282 AutoJavaFloatArray autoPos(env, posArray, count);
283 const float* posValues = autoPos.ptr();
284 pos = (SkScalar*)storage.get();
285 for (size_t i = 0; i < count; i++)
286 pos[i] = SkFloatToScalar(posValues[i]);
287 }
288
289 SkShader* shader = SkGradientShader::CreateRadial(center,
290 SkFloatToScalar(radius),
291 reinterpret_cast<const SkColor*>(colorValues),
292 pos, count,
293 static_cast<SkShader::TileMode>(tileMode));
294 env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues),
295 JNI_ABORT);
296
297 ThrowIAE_IfNull(env, shader);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000298 return reinterpret_cast<jlong>(shader);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800299}
300
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000301static jlong RadialGradient_create2(JNIEnv* env, jobject, jfloat x, jfloat y, jfloat radius,
302 jint color0, jint color1, jint tileMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800303 SkPoint center;
304 center.set(SkFloatToScalar(x), SkFloatToScalar(y));
305
306 SkColor colors[2];
307 colors[0] = color0;
308 colors[1] = color1;
309
310 SkShader* s = SkGradientShader::CreateRadial(center, SkFloatToScalar(radius), colors, NULL,
311 2, (SkShader::TileMode)tileMode);
312 ThrowIAE_IfNull(env, s);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000313 return reinterpret_cast<jlong>(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800314}
315
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000316static jlong RadialGradient_postCreate1(JNIEnv* env, jobject o, jlong shaderHandle,
317 jfloat x, jfloat y, jfloat radius, jintArray colorArray, jfloatArray posArray, jint tileMode) {
Romain Guyddb80be2010-09-20 19:04:33 -0700318#ifdef USE_OPENGL_RENDERER
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000319 SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle);
Romain Guyddb80be2010-09-20 19:04:33 -0700320 size_t count = env->GetArrayLength(colorArray);
321 const jint* colorValues = env->GetIntArrayElements(colorArray, NULL);
322
323 jfloat* storedPositions = new jfloat[count];
324 uint32_t* storedColors = new uint32_t[count];
325 for (size_t i = 0; i < count; i++) {
326 storedColors[i] = static_cast<uint32_t>(colorValues[i]);
327 }
328
329 if (posArray) {
330 AutoJavaFloatArray autoPos(env, posArray, count);
331 const float* posValues = autoPos.ptr();
332 for (size_t i = 0; i < count; i++) {
333 storedPositions[i] = posValues[i];
334 }
335 } else {
336 storedPositions[0] = 0.0f;
Romain Guy7b5b6ab2011-03-14 18:05:08 -0700337 const jfloat step = 1.0f / (count - 1);
338 for (size_t i = 1; i < count - 1; i++) {
339 storedPositions[i] = step * i;
340 }
341 storedPositions[count - 1] = 1.0f;
Romain Guyddb80be2010-09-20 19:04:33 -0700342 }
343
344 SkiaShader* skiaShader = new SkiaCircularGradientShader(x, y, radius, storedColors,
345 storedPositions, count, shader, (SkShader::TileMode) tileMode, NULL,
346 (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0);
347
348 env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000349 return reinterpret_cast<jlong>(skiaShader);
Romain Guyddb80be2010-09-20 19:04:33 -0700350#else
351 return NULL;
352#endif
353}
354
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000355static jlong RadialGradient_postCreate2(JNIEnv* env, jobject o, jlong shaderHandle,
356 jfloat x, jfloat y, jfloat radius, jint color0, jint color1, jint tileMode) {
Romain Guyddb80be2010-09-20 19:04:33 -0700357#ifdef USE_OPENGL_RENDERER
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000358 SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle);
Romain Guyddb80be2010-09-20 19:04:33 -0700359 float* storedPositions = new float[2];
360 storedPositions[0] = 0.0f;
361 storedPositions[1] = 1.0f;
362
363 uint32_t* storedColors = new uint32_t[2];
364 storedColors[0] = static_cast<uint32_t>(color0);
365 storedColors[1] = static_cast<uint32_t>(color1);
366
367 SkiaShader* skiaShader = new SkiaCircularGradientShader(x, y, radius, storedColors,
368 storedPositions, 2, shader, (SkShader::TileMode) tileMode, NULL,
369 (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0);
370
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000371 return reinterpret_cast<jlong>(skiaShader);
Romain Guyddb80be2010-09-20 19:04:33 -0700372#else
373 return NULL;
374#endif
375}
376
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800377///////////////////////////////////////////////////////////////////////////////
378
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000379static jlong SweepGradient_create1(JNIEnv* env, jobject, jfloat x, jfloat y,
Romain Guyddb80be2010-09-20 19:04:33 -0700380 jintArray jcolors, jfloatArray jpositions) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800381 size_t count = env->GetArrayLength(jcolors);
382 const jint* colors = env->GetIntArrayElements(jcolors, NULL);
Elliott Hughes4cb17532011-04-12 16:10:26 -0700383
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800384 SkAutoSTMalloc<8, SkScalar> storage(jpositions ? count : 0);
385 SkScalar* pos = NULL;
Elliott Hughes4cb17532011-04-12 16:10:26 -0700386
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800387 if (NULL != jpositions) {
388 AutoJavaFloatArray autoPos(env, jpositions, count);
389 const float* posValues = autoPos.ptr();
390 pos = (SkScalar*)storage.get();
391 for (size_t i = 0; i < count; i++) {
392 pos[i] = SkFloatToScalar(posValues[i]);
393 }
394 }
395
396 SkShader* shader = SkGradientShader::CreateSweep(SkFloatToScalar(x),
397 SkFloatToScalar(y),
398 reinterpret_cast<const SkColor*>(colors),
399 pos, count);
400 env->ReleaseIntArrayElements(jcolors, const_cast<jint*>(colors),
401 JNI_ABORT);
402 ThrowIAE_IfNull(env, shader);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000403 return reinterpret_cast<jlong>(shader);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800404}
405
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000406static jlong SweepGradient_create2(JNIEnv* env, jobject, jfloat x, jfloat y,
Romain Guyddb80be2010-09-20 19:04:33 -0700407 int color0, int color1) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800408 SkColor colors[2];
409 colors[0] = color0;
410 colors[1] = color1;
411 SkShader* s = SkGradientShader::CreateSweep(SkFloatToScalar(x), SkFloatToScalar(y),
412 colors, NULL, 2);
413 ThrowIAE_IfNull(env, s);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000414 return reinterpret_cast<jlong>(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800415}
416
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000417static jlong SweepGradient_postCreate1(JNIEnv* env, jobject o, jlong shaderHandle,
418 jfloat x, jfloat y, jintArray colorArray, jfloatArray posArray) {
Romain Guyee916f12010-09-20 17:53:08 -0700419#ifdef USE_OPENGL_RENDERER
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000420 SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle);
Romain Guyee916f12010-09-20 17:53:08 -0700421 size_t count = env->GetArrayLength(colorArray);
422 const jint* colorValues = env->GetIntArrayElements(colorArray, NULL);
423
424 jfloat* storedPositions = new jfloat[count];
425 uint32_t* storedColors = new uint32_t[count];
426 for (size_t i = 0; i < count; i++) {
427 storedColors[i] = static_cast<uint32_t>(colorValues[i]);
428 }
429
430 if (posArray) {
431 AutoJavaFloatArray autoPos(env, posArray, count);
432 const float* posValues = autoPos.ptr();
433 for (size_t i = 0; i < count; i++) {
434 storedPositions[i] = posValues[i];
435 }
436 } else {
437 storedPositions[0] = 0.0f;
Romain Guy7b5b6ab2011-03-14 18:05:08 -0700438 const jfloat step = 1.0f / (count - 1);
439 for (size_t i = 1; i < count - 1; i++) {
440 storedPositions[i] = step * i;
441 }
442 storedPositions[count - 1] = 1.0f;
Romain Guyee916f12010-09-20 17:53:08 -0700443 }
444
445 SkiaShader* skiaShader = new SkiaSweepGradientShader(x, y, storedColors, storedPositions, count,
446 shader, NULL, (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0);
447
448 env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000449 return reinterpret_cast<jlong>(skiaShader);
Romain Guyee916f12010-09-20 17:53:08 -0700450#else
451 return NULL;
452#endif
453}
454
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000455static jlong SweepGradient_postCreate2(JNIEnv* env, jobject o, jlong shaderHandle,
456 jfloat x, jfloat y, jint color0, jint color1) {
Romain Guyee916f12010-09-20 17:53:08 -0700457#ifdef USE_OPENGL_RENDERER
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000458 SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle);
Romain Guyee916f12010-09-20 17:53:08 -0700459 float* storedPositions = new float[2];
460 storedPositions[0] = 0.0f;
461 storedPositions[1] = 1.0f;
462
463 uint32_t* storedColors = new uint32_t[2];
464 storedColors[0] = static_cast<uint32_t>(color0);
465 storedColors[1] = static_cast<uint32_t>(color1);
466
467 SkiaShader* skiaShader = new SkiaSweepGradientShader(x, y, storedColors, storedPositions, 2,
468 shader, NULL, (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0);
469
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000470 return reinterpret_cast<jlong>(skiaShader);
Romain Guyee916f12010-09-20 17:53:08 -0700471#else
472 return NULL;
473#endif
474}
475
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800476///////////////////////////////////////////////////////////////////////////////////////////////
477
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000478static jlong ComposeShader_create1(JNIEnv* env, jobject o,
479 jlong shaderAHandle, jlong shaderBHandle, jlong modeHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800480{
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000481 SkShader* shaderA = reinterpret_cast<SkShader *>(shaderAHandle);
482 SkShader* shaderB = reinterpret_cast<SkShader *>(shaderBHandle);
483 SkXfermode* mode = reinterpret_cast<SkXfermode *>(modeHandle);
484 SkShader* shader = new SkComposeShader(shaderA, shaderB, mode);
485 return reinterpret_cast<jlong>(shader);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800486}
487
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000488static jlong ComposeShader_create2(JNIEnv* env, jobject o,
489 jlong shaderAHandle, jlong shaderBHandle, jint porterDuffModeHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800490{
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000491 SkShader* shaderA = reinterpret_cast<SkShader *>(shaderAHandle);
492 SkShader* shaderB = reinterpret_cast<SkShader *>(shaderBHandle);
493 SkPorterDuff::Mode porterDuffMode = static_cast<SkPorterDuff::Mode>(porterDuffModeHandle);
Romain Guy06f96e22010-07-30 19:18:16 -0700494 SkAutoUnref au(SkPorterDuff::CreateXfermode(porterDuffMode));
495 SkXfermode* mode = (SkXfermode*) au.get();
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000496 SkShader* shader = new SkComposeShader(shaderA, shaderB, mode);
497 return reinterpret_cast<jlong>(shader);
Romain Guy06f96e22010-07-30 19:18:16 -0700498}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800499
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000500static jlong ComposeShader_postCreate2(JNIEnv* env, jobject o, jlong shaderHandle,
501 jlong shaderAHandle, jlong shaderBHandle, jint porterDuffModeHandle) {
Romain Guy16393512010-08-08 00:14:31 -0700502#ifdef USE_OPENGL_RENDERER
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000503 SkShader* shader = reinterpret_cast<SkShader *>(shaderHandle);
504 SkiaShader* shaderA = reinterpret_cast<SkiaShader *>(shaderAHandle);
505 SkiaShader* shaderB = reinterpret_cast<SkiaShader *>(shaderBHandle);
506 SkPorterDuff::Mode porterDuffMode = static_cast<SkPorterDuff::Mode>(porterDuffModeHandle);
Romain Guy48daa542010-08-10 19:21:34 -0700507 SkXfermode::Mode mode = SkPorterDuff::ToXfermodeMode(porterDuffMode);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000508 SkiaShader* skiaShader = new SkiaComposeShader(shaderA, shaderB, mode, shader);
509 return reinterpret_cast<jlong>(skiaShader);
Romain Guy16393512010-08-08 00:14:31 -0700510#else
511 return NULL;
512#endif
Romain Guy06f96e22010-07-30 19:18:16 -0700513}
514
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000515static jlong ComposeShader_postCreate1(JNIEnv* env, jobject o, jlong shaderHandle,
516 jlong shaderAHandle, jlong shaderBHandle, jlong modeHandle) {
Romain Guy16393512010-08-08 00:14:31 -0700517#ifdef USE_OPENGL_RENDERER
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000518 SkShader* shader = reinterpret_cast<SkShader *>(shaderHandle);
519 SkiaShader* shaderA = reinterpret_cast<SkiaShader *>(shaderAHandle);
520 SkiaShader* shaderB = reinterpret_cast<SkiaShader *>(shaderBHandle);
521 SkXfermode* mode = reinterpret_cast<SkXfermode *>(modeHandle);
Romain Guy06f96e22010-07-30 19:18:16 -0700522 SkXfermode::Mode skiaMode;
Chris Craik678625242014-02-28 12:26:34 -0800523 if (!SkXfermode::AsMode(mode, &skiaMode)) {
Romain Guy48daa542010-08-10 19:21:34 -0700524 // TODO: Support other modes
Romain Guy06f96e22010-07-30 19:18:16 -0700525 skiaMode = SkXfermode::kSrcOver_Mode;
526 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000527 SkiaShader* skiaShader = new SkiaComposeShader(shaderA, shaderB, skiaMode, shader);
528 return reinterpret_cast<jlong>(skiaShader);
Romain Guy16393512010-08-08 00:14:31 -0700529#else
530 return NULL;
531#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800532}
533
534///////////////////////////////////////////////////////////////////////////////////////////////
535
536static JNINativeMethod gColorMethods[] = {
537 { "nativeRGBToHSV", "(III[F)V", (void*)Color_RGBToHSV },
538 { "nativeHSVToColor", "(I[F)I", (void*)Color_HSVToColor }
539};
540
541static JNINativeMethod gShaderMethods[] = {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000542 { "nativeDestructor", "(JJ)V", (void*)Shader_destructor },
543 { "nativeSetLocalMatrix", "(JJJ)V", (void*)Shader_setLocalMatrix }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800544};
545
546static JNINativeMethod gBitmapShaderMethods[] = {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000547 { "nativeCreate", "(JII)J", (void*)BitmapShader_constructor },
548 { "nativePostCreate", "(JJII)J", (void*)BitmapShader_postConstructor }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800549};
550
551static JNINativeMethod gLinearGradientMethods[] = {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000552 { "nativeCreate1", "(FFFF[I[FI)J", (void*)LinearGradient_create1 },
553 { "nativeCreate2", "(FFFFIII)J", (void*)LinearGradient_create2 },
554 { "nativePostCreate1", "(JFFFF[I[FI)J", (void*)LinearGradient_postCreate1 },
555 { "nativePostCreate2", "(JFFFFIII)J", (void*)LinearGradient_postCreate2 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800556};
557
558static JNINativeMethod gRadialGradientMethods[] = {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000559 { "nativeCreate1", "(FFF[I[FI)J", (void*)RadialGradient_create1 },
560 { "nativeCreate2", "(FFFIII)J", (void*)RadialGradient_create2 },
561 { "nativePostCreate1", "(JFFF[I[FI)J", (void*)RadialGradient_postCreate1 },
562 { "nativePostCreate2", "(JFFFIII)J", (void*)RadialGradient_postCreate2 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800563};
564
565static JNINativeMethod gSweepGradientMethods[] = {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000566 { "nativeCreate1", "(FF[I[F)J", (void*)SweepGradient_create1 },
567 { "nativeCreate2", "(FFII)J", (void*)SweepGradient_create2 },
568 { "nativePostCreate1", "(JFF[I[F)J", (void*)SweepGradient_postCreate1 },
569 { "nativePostCreate2", "(JFFII)J", (void*)SweepGradient_postCreate2 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800570};
571
572static JNINativeMethod gComposeShaderMethods[] = {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000573 { "nativeCreate1", "(JJJ)J", (void*)ComposeShader_create1 },
574 { "nativeCreate2", "(JJI)J", (void*)ComposeShader_create2 },
575 { "nativePostCreate1", "(JJJJ)J", (void*)ComposeShader_postCreate1 },
576 { "nativePostCreate2", "(JJJI)J", (void*)ComposeShader_postCreate2 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800577};
578
579#include <android_runtime/AndroidRuntime.h>
580
581#define REG(env, name, array) \
582 result = android::AndroidRuntime::registerNativeMethods(env, name, array, SK_ARRAY_COUNT(array)); \
583 if (result < 0) return result
584
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800585int register_android_graphics_Shader(JNIEnv* env)
586{
587 int result;
Elliott Hughes4cb17532011-04-12 16:10:26 -0700588
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800589 REG(env, "android/graphics/Color", gColorMethods);
590 REG(env, "android/graphics/Shader", gShaderMethods);
591 REG(env, "android/graphics/BitmapShader", gBitmapShaderMethods);
592 REG(env, "android/graphics/LinearGradient", gLinearGradientMethods);
593 REG(env, "android/graphics/RadialGradient", gRadialGradientMethods);
594 REG(env, "android/graphics/SweepGradient", gSweepGradientMethods);
595 REG(env, "android/graphics/ComposeShader", gComposeShaderMethods);
Elliott Hughes4cb17532011-04-12 16:10:26 -0700596
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800597 return result;
598}