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