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