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