Shader.cpp revision a9aded1f6253afbea7906509992a8a3721f731ab
1#include <jni.h> 2#include "GraphicsJNI.h" 3 4#include "SkShader.h" 5#include "SkGradientShader.h" 6#include "SkComposeShader.h" 7#include "SkTemplates.h" 8#include "SkXfermode.h" 9 10#include <Caches.h> 11 12#include "core_jni_helpers.h" 13 14using namespace android::uirenderer; 15 16static void ThrowIAE_IfNull(JNIEnv* env, void* ptr) { 17 if (NULL == ptr) { 18 doThrowIAE(env); 19 } 20} 21 22static void Color_RGBToHSV(JNIEnv* env, jobject, jint red, jint green, jint blue, jfloatArray hsvArray) 23{ 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} 33 34static jint Color_HSVToColor(JNIEnv* env, jobject, jint alpha, jfloatArray hsvArray) 35{ 36 AutoJavaFloatArray autoHSV(env, hsvArray, 3); 37#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 42 43 return static_cast<jint>(SkHSVToColor(alpha, hsv)); 44} 45 46/////////////////////////////////////////////////////////////////////////////////////////////// 47 48static void Shader_destructor(JNIEnv* env, jobject o, jlong shaderHandle, jlong shaderWithLMHandle) 49{ 50 SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle); 51 SkSafeUnref(shader); 52} 53 54static jlong Shader_setLocalMatrix(JNIEnv* env, jobject o, jlong shaderHandle, jlong matrixHandle) 55{ 56 // ensure we have a valid matrix to use 57 const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle); 58 if (NULL == matrix) { 59 matrix = &SkMatrix::I(); 60 } 61 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(¤tMatrix)); 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)); 79} 80 81/////////////////////////////////////////////////////////////////////////////////////////////// 82 83static jlong BitmapShader_constructor(JNIEnv* env, jobject o, jlong bitmapHandle, 84 jint tileModeX, jint tileModeY) 85{ 86 const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle); 87 SkShader* s = SkShader::CreateBitmapShader(*bitmap, 88 (SkShader::TileMode)tileModeX, 89 (SkShader::TileMode)tileModeY); 90 91 ThrowIAE_IfNull(env, s); 92 return reinterpret_cast<jlong>(s); 93} 94 95/////////////////////////////////////////////////////////////////////////////////////////////// 96 97static jlong LinearGradient_create1(JNIEnv* env, jobject o, 98 jfloat x0, jfloat y0, jfloat x1, jfloat y1, 99 jintArray colorArray, jfloatArray posArray, jint tileMode) 100{ 101 SkPoint pts[2]; 102 pts[0].set(x0, y0); 103 pts[1].set(x1, y1); 104 105 size_t count = env->GetArrayLength(colorArray); 106 const jint* colorValues = env->GetIntArrayElements(colorArray, NULL); 107 108 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 114 115 SkShader* shader = SkGradientShader::CreateLinear(pts, 116 reinterpret_cast<const SkColor*>(colorValues), pos, count, 117 static_cast<SkShader::TileMode>(tileMode)); 118 119 env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT); 120 ThrowIAE_IfNull(env, shader); 121 return reinterpret_cast<jlong>(shader); 122} 123 124static jlong LinearGradient_create2(JNIEnv* env, jobject o, 125 jfloat x0, jfloat y0, jfloat x1, jfloat y1, 126 jint color0, jint color1, jint tileMode) 127{ 128 SkPoint pts[2]; 129 pts[0].set(x0, y0); 130 pts[1].set(x1, y1); 131 132 SkColor colors[2]; 133 colors[0] = color0; 134 colors[1] = color1; 135 136 SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL, 2, (SkShader::TileMode)tileMode); 137 138 ThrowIAE_IfNull(env, s); 139 return reinterpret_cast<jlong>(s); 140} 141 142/////////////////////////////////////////////////////////////////////////////////////////////// 143 144static jlong RadialGradient_create1(JNIEnv* env, jobject, jfloat x, jfloat y, jfloat radius, 145 jintArray colorArray, jfloatArray posArray, jint tileMode) { 146 SkPoint center; 147 center.set(x, y); 148 149 size_t count = env->GetArrayLength(colorArray); 150 const jint* colorValues = env->GetIntArrayElements(colorArray, NULL); 151 152 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 158 159 SkShader* shader = SkGradientShader::CreateRadial(center, radius, 160 reinterpret_cast<const SkColor*>(colorValues), pos, count, 161 static_cast<SkShader::TileMode>(tileMode)); 162 env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), 163 JNI_ABORT); 164 165 ThrowIAE_IfNull(env, shader); 166 return reinterpret_cast<jlong>(shader); 167} 168 169static jlong RadialGradient_create2(JNIEnv* env, jobject, jfloat x, jfloat y, jfloat radius, 170 jint color0, jint color1, jint tileMode) { 171 SkPoint center; 172 center.set(x, y); 173 174 SkColor colors[2]; 175 colors[0] = color0; 176 colors[1] = color1; 177 178 SkShader* s = SkGradientShader::CreateRadial(center, radius, colors, NULL, 2, 179 (SkShader::TileMode)tileMode); 180 ThrowIAE_IfNull(env, s); 181 return reinterpret_cast<jlong>(s); 182} 183 184/////////////////////////////////////////////////////////////////////////////// 185 186static jlong SweepGradient_create1(JNIEnv* env, jobject, jfloat x, jfloat y, 187 jintArray jcolors, jfloatArray jpositions) { 188 size_t count = env->GetArrayLength(jcolors); 189 const jint* colors = env->GetIntArrayElements(jcolors, NULL); 190 191 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 197 198 SkShader* shader = SkGradientShader::CreateSweep(x, y, 199 reinterpret_cast<const SkColor*>(colors), pos, count); 200 env->ReleaseIntArrayElements(jcolors, const_cast<jint*>(colors), 201 JNI_ABORT); 202 ThrowIAE_IfNull(env, shader); 203 return reinterpret_cast<jlong>(shader); 204} 205 206static jlong SweepGradient_create2(JNIEnv* env, jobject, jfloat x, jfloat y, 207 int color0, int color1) { 208 SkColor colors[2]; 209 colors[0] = color0; 210 colors[1] = color1; 211 SkShader* s = SkGradientShader::CreateSweep(x, y, colors, NULL, 2); 212 ThrowIAE_IfNull(env, s); 213 return reinterpret_cast<jlong>(s); 214} 215 216/////////////////////////////////////////////////////////////////////////////////////////////// 217 218static jlong ComposeShader_create1(JNIEnv* env, jobject o, 219 jlong shaderAHandle, jlong shaderBHandle, jlong modeHandle) 220{ 221 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); 226} 227 228static jlong ComposeShader_create2(JNIEnv* env, jobject o, 229 jlong shaderAHandle, jlong shaderBHandle, jint xfermodeHandle) 230{ 231 SkShader* shaderA = reinterpret_cast<SkShader *>(shaderAHandle); 232 SkShader* shaderB = reinterpret_cast<SkShader *>(shaderBHandle); 233 SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(xfermodeHandle); 234 SkAutoTUnref<SkXfermode> xfermode(SkXfermode::Create(mode)); 235 SkShader* shader = new SkComposeShader(shaderA, shaderB, xfermode.get()); 236 return reinterpret_cast<jlong>(shader); 237} 238 239/////////////////////////////////////////////////////////////////////////////////////////////// 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[] = { 247 { "nativeDestructor", "(J)V", (void*)Shader_destructor }, 248 { "nativeSetLocalMatrix", "(JJ)J", (void*)Shader_setLocalMatrix } 249}; 250 251static JNINativeMethod gBitmapShaderMethods[] = { 252 { "nativeCreate", "(JII)J", (void*)BitmapShader_constructor }, 253}; 254 255static JNINativeMethod gLinearGradientMethods[] = { 256 { "nativeCreate1", "(FFFF[I[FI)J", (void*)LinearGradient_create1 }, 257 { "nativeCreate2", "(FFFFIII)J", (void*)LinearGradient_create2 }, 258}; 259 260static JNINativeMethod gRadialGradientMethods[] = { 261 { "nativeCreate1", "(FFF[I[FI)J", (void*)RadialGradient_create1 }, 262 { "nativeCreate2", "(FFFIII)J", (void*)RadialGradient_create2 }, 263}; 264 265static JNINativeMethod gSweepGradientMethods[] = { 266 { "nativeCreate1", "(FF[I[F)J", (void*)SweepGradient_create1 }, 267 { "nativeCreate2", "(FFII)J", (void*)SweepGradient_create2 }, 268}; 269 270static JNINativeMethod gComposeShaderMethods[] = { 271 { "nativeCreate1", "(JJJ)J", (void*)ComposeShader_create1 }, 272 { "nativeCreate2", "(JJI)J", (void*)ComposeShader_create2 }, 273}; 274 275int register_android_graphics_Shader(JNIEnv* env) 276{ 277 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)); 291 292 return 0; 293} 294