blob: 6591d293cd34d44d69d614233ee19034f1f6de36 [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"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006#include "SkComposeShader.h"
7#include "SkTemplates.h"
8#include "SkXfermode.h"
9
Romain Guya2341a92010-09-08 18:04:33 -070010#include <Caches.h>
Romain Guy06f96e22010-07-30 19:18:16 -070011
Andreas Gampeed6b9df2014-11-20 22:02:20 -080012#include "core_jni_helpers.h"
13
Romain Guy06f96e22010-07-30 19:18:16 -070014using namespace android::uirenderer;
15
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080016static void ThrowIAE_IfNull(JNIEnv* env, void* ptr) {
17 if (NULL == ptr) {
18 doThrowIAE(env);
19 }
20}
21
Ashok Bhat36bef0b2014-01-20 20:08:01 +000022static void Color_RGBToHSV(JNIEnv* env, jobject, jint red, jint green, jint blue, jfloatArray hsvArray)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023{
24 SkScalar hsv[3];
25 SkRGBToHSV(red, green, blue, hsv);
26
27 AutoJavaFloatArray autoHSV(env, hsvArray, 3);
28 float* values = autoHSV.ptr();
29 for (int i = 0; i < 3; i++) {
30 values[i] = SkScalarToFloat(hsv[i]);
31 }
32}
Elliott Hughes4cb17532011-04-12 16:10:26 -070033
Ashok Bhat36bef0b2014-01-20 20:08:01 +000034static jint Color_HSVToColor(JNIEnv* env, jobject, jint alpha, jfloatArray hsvArray)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035{
36 AutoJavaFloatArray autoHSV(env, hsvArray, 3);
Leon Scroggins III2e0103e2014-04-04 17:05:24 -040037#ifdef SK_SCALAR_IS_FLOAT
38 SkScalar* hsv = autoHSV.ptr();
39#else
40 #error Need to convert float array to SkScalar array before calling the following function.
41#endif
Elliott Hughes4cb17532011-04-12 16:10:26 -070042
Ashok Bhat36bef0b2014-01-20 20:08:01 +000043 return static_cast<jint>(SkHSVToColor(alpha, hsv));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080044}
45
46///////////////////////////////////////////////////////////////////////////////////////////////
47
Leon Scroggins III866cf652014-07-22 17:25:22 -040048static void Shader_destructor(JNIEnv* env, jobject o, jlong shaderHandle, jlong shaderWithLMHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049{
Ashok Bhat36bef0b2014-01-20 20:08:01 +000050 SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle);
Derek Sollenberger6062c592011-02-22 13:55:04 -050051 SkSafeUnref(shader);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052}
53
Derek Sollenbergerdfba4d32014-09-02 15:42:54 -040054static jlong Shader_setLocalMatrix(JNIEnv* env, jobject o, jlong shaderHandle, jlong matrixHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055{
Derek Sollenbergerdfba4d32014-09-02 15:42:54 -040056 // ensure we have a valid matrix to use
Ashok Bhat36bef0b2014-01-20 20:08:01 +000057 const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
Derek Sollenbergerdfba4d32014-09-02 15:42:54 -040058 if (NULL == matrix) {
59 matrix = &SkMatrix::I();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080060 }
Derek Sollenbergerdfba4d32014-09-02 15:42:54 -040061
62 // The current shader will no longer need a direct reference owned by Shader.java
63 // as all the data needed is contained within the newly created LocalMatrixShader.
64 SkASSERT(shaderHandle);
65 SkAutoTUnref<SkShader> currentShader(reinterpret_cast<SkShader*>(shaderHandle));
66
67 SkMatrix currentMatrix;
68 SkAutoTUnref<SkShader> baseShader(currentShader->refAsALocalMatrixShader(&currentMatrix));
69 if (baseShader.get()) {
70 // if the matrices are same then there is no need to allocate a new
71 // shader that is identical to the existing one.
72 if (currentMatrix == *matrix) {
73 return reinterpret_cast<jlong>(currentShader.detach());
74 }
75 return reinterpret_cast<jlong>(SkShader::CreateLocalMatrixShader(baseShader, *matrix));
76 }
77
78 return reinterpret_cast<jlong>(SkShader::CreateLocalMatrixShader(currentShader, *matrix));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080079}
80
81///////////////////////////////////////////////////////////////////////////////////////////////
82
John Reck9d4efdf2015-04-17 20:45:40 +000083static jlong BitmapShader_constructor(JNIEnv* env, jobject o, jlong bitmapHandle,
Ashok Bhat36bef0b2014-01-20 20:08:01 +000084 jint tileModeX, jint tileModeY)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085{
John Reck9d4efdf2015-04-17 20:45:40 +000086 const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
87 SkShader* s = SkShader::CreateBitmapShader(*bitmap,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080088 (SkShader::TileMode)tileModeX,
89 (SkShader::TileMode)tileModeY);
Romain Guy06f96e22010-07-30 19:18:16 -070090
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080091 ThrowIAE_IfNull(env, s);
Ashok Bhat36bef0b2014-01-20 20:08:01 +000092 return reinterpret_cast<jlong>(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080093}
Romain Guy06f96e22010-07-30 19:18:16 -070094
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080095///////////////////////////////////////////////////////////////////////////////////////////////
96
Ashok Bhat36bef0b2014-01-20 20:08:01 +000097static jlong LinearGradient_create1(JNIEnv* env, jobject o,
98 jfloat x0, jfloat y0, jfloat x1, jfloat y1,
99 jintArray colorArray, jfloatArray posArray, jint tileMode)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800100{
101 SkPoint pts[2];
Leon Scroggins III2e0103e2014-04-04 17:05:24 -0400102 pts[0].set(x0, y0);
103 pts[1].set(x1, y1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800104
Romain Guy06f96e22010-07-30 19:18:16 -0700105 size_t count = env->GetArrayLength(colorArray);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106 const jint* colorValues = env->GetIntArrayElements(colorArray, NULL);
107
Leon Scroggins III2e0103e2014-04-04 17:05:24 -0400108 AutoJavaFloatArray autoPos(env, posArray, count);
109#ifdef SK_SCALAR_IS_FLOAT
110 SkScalar* pos = autoPos.ptr();
111#else
112 #error Need to convert float array to SkScalar array before calling the following function.
113#endif
Elliott Hughes4cb17532011-04-12 16:10:26 -0700114
Romain Guy06f96e22010-07-30 19:18:16 -0700115 SkShader* shader = SkGradientShader::CreateLinear(pts,
Leon Scroggins III2e0103e2014-04-04 17:05:24 -0400116 reinterpret_cast<const SkColor*>(colorValues), pos, count,
117 static_cast<SkShader::TileMode>(tileMode));
Romain Guy06f96e22010-07-30 19:18:16 -0700118
119 env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT);
120 ThrowIAE_IfNull(env, shader);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000121 return reinterpret_cast<jlong>(shader);
Romain Guy06f96e22010-07-30 19:18:16 -0700122}
123
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000124static jlong LinearGradient_create2(JNIEnv* env, jobject o,
125 jfloat x0, jfloat y0, jfloat x1, jfloat y1,
126 jint color0, jint color1, jint tileMode)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800127{
128 SkPoint pts[2];
Leon Scroggins III2e0103e2014-04-04 17:05:24 -0400129 pts[0].set(x0, y0);
130 pts[1].set(x1, y1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800131
132 SkColor colors[2];
133 colors[0] = color0;
134 colors[1] = color1;
Elliott Hughes4cb17532011-04-12 16:10:26 -0700135
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800136 SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL, 2, (SkShader::TileMode)tileMode);
Romain Guy06f96e22010-07-30 19:18:16 -0700137
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800138 ThrowIAE_IfNull(env, s);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000139 return reinterpret_cast<jlong>(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140}
141
142///////////////////////////////////////////////////////////////////////////////////////////////
143
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000144static jlong RadialGradient_create1(JNIEnv* env, jobject, jfloat x, jfloat y, jfloat radius,
145 jintArray colorArray, jfloatArray posArray, jint tileMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800146 SkPoint center;
Leon Scroggins III2e0103e2014-04-04 17:05:24 -0400147 center.set(x, y);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800148
149 size_t count = env->GetArrayLength(colorArray);
150 const jint* colorValues = env->GetIntArrayElements(colorArray, NULL);
151
Leon Scroggins III2e0103e2014-04-04 17:05:24 -0400152 AutoJavaFloatArray autoPos(env, posArray, count);
153#ifdef SK_SCALAR_IS_FLOAT
154 SkScalar* pos = autoPos.ptr();
155#else
156 #error Need to convert float array to SkScalar array before calling the following function.
157#endif
Elliott Hughes4cb17532011-04-12 16:10:26 -0700158
Leon Scroggins III2e0103e2014-04-04 17:05:24 -0400159 SkShader* shader = SkGradientShader::CreateRadial(center, radius,
160 reinterpret_cast<const SkColor*>(colorValues), pos, count,
161 static_cast<SkShader::TileMode>(tileMode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800162 env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues),
163 JNI_ABORT);
164
165 ThrowIAE_IfNull(env, shader);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000166 return reinterpret_cast<jlong>(shader);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800167}
168
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000169static jlong RadialGradient_create2(JNIEnv* env, jobject, jfloat x, jfloat y, jfloat radius,
170 jint color0, jint color1, jint tileMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800171 SkPoint center;
Leon Scroggins III2e0103e2014-04-04 17:05:24 -0400172 center.set(x, y);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800173
174 SkColor colors[2];
175 colors[0] = color0;
176 colors[1] = color1;
177
Leon Scroggins III2e0103e2014-04-04 17:05:24 -0400178 SkShader* s = SkGradientShader::CreateRadial(center, radius, colors, NULL, 2,
179 (SkShader::TileMode)tileMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800180 ThrowIAE_IfNull(env, s);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000181 return reinterpret_cast<jlong>(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800182}
183
184///////////////////////////////////////////////////////////////////////////////
185
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000186static jlong SweepGradient_create1(JNIEnv* env, jobject, jfloat x, jfloat y,
Romain Guyddb80be2010-09-20 19:04:33 -0700187 jintArray jcolors, jfloatArray jpositions) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800188 size_t count = env->GetArrayLength(jcolors);
189 const jint* colors = env->GetIntArrayElements(jcolors, NULL);
Elliott Hughes4cb17532011-04-12 16:10:26 -0700190
Leon Scroggins III2e0103e2014-04-04 17:05:24 -0400191 AutoJavaFloatArray autoPos(env, jpositions, count);
192#ifdef SK_SCALAR_IS_FLOAT
193 SkScalar* pos = autoPos.ptr();
194#else
195 #error Need to convert float array to SkScalar array before calling the following function.
196#endif
Elliott Hughes4cb17532011-04-12 16:10:26 -0700197
Leon Scroggins III2e0103e2014-04-04 17:05:24 -0400198 SkShader* shader = SkGradientShader::CreateSweep(x, y,
199 reinterpret_cast<const SkColor*>(colors), pos, count);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800200 env->ReleaseIntArrayElements(jcolors, const_cast<jint*>(colors),
201 JNI_ABORT);
202 ThrowIAE_IfNull(env, shader);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000203 return reinterpret_cast<jlong>(shader);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800204}
205
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000206static jlong SweepGradient_create2(JNIEnv* env, jobject, jfloat x, jfloat y,
Romain Guyddb80be2010-09-20 19:04:33 -0700207 int color0, int color1) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800208 SkColor colors[2];
209 colors[0] = color0;
210 colors[1] = color1;
Leon Scroggins III2e0103e2014-04-04 17:05:24 -0400211 SkShader* s = SkGradientShader::CreateSweep(x, y, colors, NULL, 2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800212 ThrowIAE_IfNull(env, s);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000213 return reinterpret_cast<jlong>(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800214}
215
216///////////////////////////////////////////////////////////////////////////////////////////////
217
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000218static jlong ComposeShader_create1(JNIEnv* env, jobject o,
219 jlong shaderAHandle, jlong shaderBHandle, jlong modeHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800220{
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000221 SkShader* shaderA = reinterpret_cast<SkShader *>(shaderAHandle);
222 SkShader* shaderB = reinterpret_cast<SkShader *>(shaderBHandle);
223 SkXfermode* mode = reinterpret_cast<SkXfermode *>(modeHandle);
224 SkShader* shader = new SkComposeShader(shaderA, shaderB, mode);
225 return reinterpret_cast<jlong>(shader);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800226}
227
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000228static jlong ComposeShader_create2(JNIEnv* env, jobject o,
Chris Craik1526a452015-03-06 18:42:15 +0000229 jlong shaderAHandle, jlong shaderBHandle, jint xfermodeHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800230{
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000231 SkShader* shaderA = reinterpret_cast<SkShader *>(shaderAHandle);
232 SkShader* shaderB = reinterpret_cast<SkShader *>(shaderBHandle);
Chris Craik1526a452015-03-06 18:42:15 +0000233 SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(xfermodeHandle);
234 SkAutoTUnref<SkXfermode> xfermode(SkXfermode::Create(mode));
235 SkShader* shader = new SkComposeShader(shaderA, shaderB, xfermode.get());
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000236 return reinterpret_cast<jlong>(shader);
Romain Guy06f96e22010-07-30 19:18:16 -0700237}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800238
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800239///////////////////////////////////////////////////////////////////////////////////////////////
240
241static JNINativeMethod gColorMethods[] = {
242 { "nativeRGBToHSV", "(III[F)V", (void*)Color_RGBToHSV },
243 { "nativeHSVToColor", "(I[F)I", (void*)Color_HSVToColor }
244};
245
246static JNINativeMethod gShaderMethods[] = {
John Reck01edef12014-08-22 11:15:37 -0700247 { "nativeDestructor", "(J)V", (void*)Shader_destructor },
Derek Sollenbergerdfba4d32014-09-02 15:42:54 -0400248 { "nativeSetLocalMatrix", "(JJ)J", (void*)Shader_setLocalMatrix }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800249};
250
251static JNINativeMethod gBitmapShaderMethods[] = {
John Reck9d4efdf2015-04-17 20:45:40 +0000252 { "nativeCreate", "(JII)J", (void*)BitmapShader_constructor },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800253};
254
255static JNINativeMethod gLinearGradientMethods[] = {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000256 { "nativeCreate1", "(FFFF[I[FI)J", (void*)LinearGradient_create1 },
257 { "nativeCreate2", "(FFFFIII)J", (void*)LinearGradient_create2 },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800258};
259
260static JNINativeMethod gRadialGradientMethods[] = {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000261 { "nativeCreate1", "(FFF[I[FI)J", (void*)RadialGradient_create1 },
262 { "nativeCreate2", "(FFFIII)J", (void*)RadialGradient_create2 },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800263};
264
265static JNINativeMethod gSweepGradientMethods[] = {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000266 { "nativeCreate1", "(FF[I[F)J", (void*)SweepGradient_create1 },
267 { "nativeCreate2", "(FFII)J", (void*)SweepGradient_create2 },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800268};
269
270static JNINativeMethod gComposeShaderMethods[] = {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000271 { "nativeCreate1", "(JJJ)J", (void*)ComposeShader_create1 },
272 { "nativeCreate2", "(JJI)J", (void*)ComposeShader_create2 },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800273};
274
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800275int register_android_graphics_Shader(JNIEnv* env)
276{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800277 android::RegisterMethodsOrDie(env, "android/graphics/Color", gColorMethods,
278 NELEM(gColorMethods));
279 android::RegisterMethodsOrDie(env, "android/graphics/Shader", gShaderMethods,
280 NELEM(gShaderMethods));
281 android::RegisterMethodsOrDie(env, "android/graphics/BitmapShader", gBitmapShaderMethods,
282 NELEM(gBitmapShaderMethods));
283 android::RegisterMethodsOrDie(env, "android/graphics/LinearGradient", gLinearGradientMethods,
284 NELEM(gLinearGradientMethods));
285 android::RegisterMethodsOrDie(env, "android/graphics/RadialGradient", gRadialGradientMethods,
286 NELEM(gRadialGradientMethods));
287 android::RegisterMethodsOrDie(env, "android/graphics/SweepGradient", gSweepGradientMethods,
288 NELEM(gSweepGradientMethods));
289 android::RegisterMethodsOrDie(env, "android/graphics/ComposeShader", gComposeShaderMethods,
290 NELEM(gComposeShaderMethods));
Elliott Hughes4cb17532011-04-12 16:10:26 -0700291
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800292 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800293}