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