Shader.cpp revision 866cf65cc3c53f67836c9157d5c661adfdbd25e1
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 14using namespace android::uirenderer; 15 16static struct { 17 jclass clazz; 18 jfieldID shader; 19} gShaderClassInfo; 20 21static void ThrowIAE_IfNull(JNIEnv* env, void* ptr) { 22 if (NULL == ptr) { 23 doThrowIAE(env); 24 } 25} 26 27static 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 39static 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 53static void Shader_destructor(JNIEnv* env, jobject o, jlong shaderHandle, jlong shaderWithLMHandle) 54{ 55 SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle); 56 SkSafeUnref(shader); 57 SkShader* shaderWithLM = reinterpret_cast<SkShader*>(shaderWithLMHandle); 58 SkSafeUnref(shaderWithLM); 59} 60 61static jlong Shader_setLocalMatrix(JNIEnv* env, jobject o, jlong shaderHandle, 62 jlong oldLocalMatrixShaderHandle, jlong matrixHandle) 63{ 64 // The old shader with local matrix is no longer needed, so unref it. 65 SkSafeUnref(reinterpret_cast<SkShader*>(oldLocalMatrixShaderHandle)); 66 67 SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle); 68 const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle); 69 if (shader) { 70 if (NULL == matrix) { 71 matrix = &SkMatrix::I(); 72 } 73 SkShader* newShader = SkShader::CreateLocalMatrixShader(shader, *matrix); 74 shader = newShader; 75 } 76 return reinterpret_cast<jlong>(shader); 77} 78 79/////////////////////////////////////////////////////////////////////////////////////////////// 80 81static jlong BitmapShader_constructor(JNIEnv* env, jobject o, jlong bitmapHandle, 82 jint tileModeX, jint tileModeY) 83{ 84 const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle); 85 SkShader* s = SkShader::CreateBitmapShader(*bitmap, 86 (SkShader::TileMode)tileModeX, 87 (SkShader::TileMode)tileModeY); 88 89 ThrowIAE_IfNull(env, s); 90 return reinterpret_cast<jlong>(s); 91} 92 93/////////////////////////////////////////////////////////////////////////////////////////////// 94 95static jlong LinearGradient_create1(JNIEnv* env, jobject o, 96 jfloat x0, jfloat y0, jfloat x1, jfloat y1, 97 jintArray colorArray, jfloatArray posArray, jint tileMode) 98{ 99 SkPoint pts[2]; 100 pts[0].set(x0, y0); 101 pts[1].set(x1, y1); 102 103 size_t count = env->GetArrayLength(colorArray); 104 const jint* colorValues = env->GetIntArrayElements(colorArray, NULL); 105 106 AutoJavaFloatArray autoPos(env, posArray, count); 107#ifdef SK_SCALAR_IS_FLOAT 108 SkScalar* pos = autoPos.ptr(); 109#else 110 #error Need to convert float array to SkScalar array before calling the following function. 111#endif 112 113 SkShader* shader = SkGradientShader::CreateLinear(pts, 114 reinterpret_cast<const SkColor*>(colorValues), pos, count, 115 static_cast<SkShader::TileMode>(tileMode)); 116 117 env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT); 118 ThrowIAE_IfNull(env, shader); 119 return reinterpret_cast<jlong>(shader); 120} 121 122static jlong LinearGradient_create2(JNIEnv* env, jobject o, 123 jfloat x0, jfloat y0, jfloat x1, jfloat y1, 124 jint color0, jint color1, jint tileMode) 125{ 126 SkPoint pts[2]; 127 pts[0].set(x0, y0); 128 pts[1].set(x1, y1); 129 130 SkColor colors[2]; 131 colors[0] = color0; 132 colors[1] = color1; 133 134 SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL, 2, (SkShader::TileMode)tileMode); 135 136 ThrowIAE_IfNull(env, s); 137 return reinterpret_cast<jlong>(s); 138} 139 140/////////////////////////////////////////////////////////////////////////////////////////////// 141 142static jlong RadialGradient_create1(JNIEnv* env, jobject, jfloat x, jfloat y, jfloat radius, 143 jintArray colorArray, jfloatArray posArray, jint tileMode) { 144 SkPoint center; 145 center.set(x, y); 146 147 size_t count = env->GetArrayLength(colorArray); 148 const jint* colorValues = env->GetIntArrayElements(colorArray, NULL); 149 150 AutoJavaFloatArray autoPos(env, posArray, count); 151#ifdef SK_SCALAR_IS_FLOAT 152 SkScalar* pos = autoPos.ptr(); 153#else 154 #error Need to convert float array to SkScalar array before calling the following function. 155#endif 156 157 SkShader* shader = SkGradientShader::CreateRadial(center, radius, 158 reinterpret_cast<const SkColor*>(colorValues), pos, count, 159 static_cast<SkShader::TileMode>(tileMode)); 160 env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), 161 JNI_ABORT); 162 163 ThrowIAE_IfNull(env, shader); 164 return reinterpret_cast<jlong>(shader); 165} 166 167static jlong RadialGradient_create2(JNIEnv* env, jobject, jfloat x, jfloat y, jfloat radius, 168 jint color0, jint color1, jint tileMode) { 169 SkPoint center; 170 center.set(x, y); 171 172 SkColor colors[2]; 173 colors[0] = color0; 174 colors[1] = color1; 175 176 SkShader* s = SkGradientShader::CreateRadial(center, radius, colors, NULL, 2, 177 (SkShader::TileMode)tileMode); 178 ThrowIAE_IfNull(env, s); 179 return reinterpret_cast<jlong>(s); 180} 181 182/////////////////////////////////////////////////////////////////////////////// 183 184static jlong SweepGradient_create1(JNIEnv* env, jobject, jfloat x, jfloat y, 185 jintArray jcolors, jfloatArray jpositions) { 186 size_t count = env->GetArrayLength(jcolors); 187 const jint* colors = env->GetIntArrayElements(jcolors, NULL); 188 189 AutoJavaFloatArray autoPos(env, jpositions, count); 190#ifdef SK_SCALAR_IS_FLOAT 191 SkScalar* pos = autoPos.ptr(); 192#else 193 #error Need to convert float array to SkScalar array before calling the following function. 194#endif 195 196 SkShader* shader = SkGradientShader::CreateSweep(x, y, 197 reinterpret_cast<const SkColor*>(colors), pos, count); 198 env->ReleaseIntArrayElements(jcolors, const_cast<jint*>(colors), 199 JNI_ABORT); 200 ThrowIAE_IfNull(env, shader); 201 return reinterpret_cast<jlong>(shader); 202} 203 204static jlong SweepGradient_create2(JNIEnv* env, jobject, jfloat x, jfloat y, 205 int color0, int color1) { 206 SkColor colors[2]; 207 colors[0] = color0; 208 colors[1] = color1; 209 SkShader* s = SkGradientShader::CreateSweep(x, y, colors, NULL, 2); 210 ThrowIAE_IfNull(env, s); 211 return reinterpret_cast<jlong>(s); 212} 213 214/////////////////////////////////////////////////////////////////////////////////////////////// 215 216static jlong ComposeShader_create1(JNIEnv* env, jobject o, 217 jlong shaderAHandle, jlong shaderBHandle, jlong modeHandle) 218{ 219 SkShader* shaderA = reinterpret_cast<SkShader *>(shaderAHandle); 220 SkShader* shaderB = reinterpret_cast<SkShader *>(shaderBHandle); 221 SkXfermode* mode = reinterpret_cast<SkXfermode *>(modeHandle); 222 SkShader* shader = new SkComposeShader(shaderA, shaderB, mode); 223 return reinterpret_cast<jlong>(shader); 224} 225 226static jlong ComposeShader_create2(JNIEnv* env, jobject o, 227 jlong shaderAHandle, jlong shaderBHandle, jint porterDuffModeHandle) 228{ 229 SkShader* shaderA = reinterpret_cast<SkShader *>(shaderAHandle); 230 SkShader* shaderB = reinterpret_cast<SkShader *>(shaderBHandle); 231 SkPorterDuff::Mode porterDuffMode = static_cast<SkPorterDuff::Mode>(porterDuffModeHandle); 232 SkAutoUnref au(SkPorterDuff::CreateXfermode(porterDuffMode)); 233 SkXfermode* mode = (SkXfermode*) au.get(); 234 SkShader* shader = new SkComposeShader(shaderA, shaderB, mode); 235 return reinterpret_cast<jlong>(shader); 236} 237 238/////////////////////////////////////////////////////////////////////////////////////////////// 239 240static JNINativeMethod gColorMethods[] = { 241 { "nativeRGBToHSV", "(III[F)V", (void*)Color_RGBToHSV }, 242 { "nativeHSVToColor", "(I[F)I", (void*)Color_HSVToColor } 243}; 244 245static JNINativeMethod gShaderMethods[] = { 246 { "nativeDestructor", "(JJ)V", (void*)Shader_destructor }, 247 { "nativeSetLocalMatrix", "(JJJ)J", (void*)Shader_setLocalMatrix } 248}; 249 250static JNINativeMethod gBitmapShaderMethods[] = { 251 { "nativeCreate", "(JII)J", (void*)BitmapShader_constructor }, 252}; 253 254static JNINativeMethod gLinearGradientMethods[] = { 255 { "nativeCreate1", "(FFFF[I[FI)J", (void*)LinearGradient_create1 }, 256 { "nativeCreate2", "(FFFFIII)J", (void*)LinearGradient_create2 }, 257}; 258 259static JNINativeMethod gRadialGradientMethods[] = { 260 { "nativeCreate1", "(FFF[I[FI)J", (void*)RadialGradient_create1 }, 261 { "nativeCreate2", "(FFFIII)J", (void*)RadialGradient_create2 }, 262}; 263 264static JNINativeMethod gSweepGradientMethods[] = { 265 { "nativeCreate1", "(FF[I[F)J", (void*)SweepGradient_create1 }, 266 { "nativeCreate2", "(FFII)J", (void*)SweepGradient_create2 }, 267}; 268 269static JNINativeMethod gComposeShaderMethods[] = { 270 { "nativeCreate1", "(JJJ)J", (void*)ComposeShader_create1 }, 271 { "nativeCreate2", "(JJI)J", (void*)ComposeShader_create2 }, 272}; 273 274#include <android_runtime/AndroidRuntime.h> 275 276#define REG(env, name, array) \ 277 result = android::AndroidRuntime::registerNativeMethods(env, name, array, SK_ARRAY_COUNT(array)); \ 278 if (result < 0) return result 279 280int register_android_graphics_Shader(JNIEnv* env) 281{ 282 int result; 283 284 REG(env, "android/graphics/Color", gColorMethods); 285 REG(env, "android/graphics/Shader", gShaderMethods); 286 REG(env, "android/graphics/BitmapShader", gBitmapShaderMethods); 287 REG(env, "android/graphics/LinearGradient", gLinearGradientMethods); 288 REG(env, "android/graphics/RadialGradient", gRadialGradientMethods); 289 REG(env, "android/graphics/SweepGradient", gSweepGradientMethods); 290 REG(env, "android/graphics/ComposeShader", gComposeShaderMethods); 291 292 return result; 293} 294