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 21 static void ThrowIAE_IfNull(JNIEnv* env, void* ptr) { 22 if (NULL == ptr) { 23 doThrowIAE(env); 24 } 25 } 26 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 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 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 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 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 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 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 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 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 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 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 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 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 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