Shader.cpp revision 76f6a86de25e1bf74717e047e55fd44b089673f3
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 <SkiaShader.h> 12#include <Caches.h> 13 14#include "core_jni_helpers.h" 15 16using namespace android::uirenderer; 17 18static void ThrowIAE_IfNull(JNIEnv* env, void* ptr) { 19 if (NULL == ptr) { 20 doThrowIAE(env); 21 } 22} 23 24static void Color_RGBToHSV(JNIEnv* env, jobject, jint red, jint green, jint blue, jfloatArray hsvArray) 25{ 26 SkScalar hsv[3]; 27 SkRGBToHSV(red, green, blue, hsv); 28 29 AutoJavaFloatArray autoHSV(env, hsvArray, 3); 30 float* values = autoHSV.ptr(); 31 for (int i = 0; i < 3; i++) { 32 values[i] = SkScalarToFloat(hsv[i]); 33 } 34} 35 36static jint Color_HSVToColor(JNIEnv* env, jobject, jint alpha, jfloatArray hsvArray) 37{ 38 AutoJavaFloatArray autoHSV(env, hsvArray, 3); 39#ifdef SK_SCALAR_IS_FLOAT 40 SkScalar* hsv = autoHSV.ptr(); 41#else 42 #error Need to convert float array to SkScalar array before calling the following function. 43#endif 44 45 return static_cast<jint>(SkHSVToColor(alpha, hsv)); 46} 47 48/////////////////////////////////////////////////////////////////////////////////////////////// 49 50static void Shader_destructor(JNIEnv* env, jobject o, jlong shaderHandle, jlong shaderWithLMHandle) 51{ 52 SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle); 53 SkSafeUnref(shader); 54} 55 56static void Shader_setLocalMatrix(JNIEnv* env, jobject o, jlong shaderHandle, jlong matrixHandle) 57{ 58 SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle); 59 const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle); 60 if (shader) { 61 if (matrix) { 62 shader->setLocalMatrix(*matrix); 63 } else { 64 shader->resetLocalMatrix(); 65 } 66 shader->setGenerationID(shader->getGenerationID() + 1); 67 } 68} 69 70/////////////////////////////////////////////////////////////////////////////////////////////// 71 72static jlong BitmapShader_constructor(JNIEnv* env, jobject o, jlong bitmapHandle, 73 jint tileModeX, jint tileModeY) 74{ 75 const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle); 76 SkShader* s = SkShader::CreateBitmapShader(*bitmap, 77 (SkShader::TileMode)tileModeX, 78 (SkShader::TileMode)tileModeY); 79 80 ThrowIAE_IfNull(env, s); 81 return reinterpret_cast<jlong>(s); 82} 83 84/////////////////////////////////////////////////////////////////////////////////////////////// 85 86static jlong LinearGradient_create1(JNIEnv* env, jobject o, 87 jfloat x0, jfloat y0, jfloat x1, jfloat y1, 88 jintArray colorArray, jfloatArray posArray, jint tileMode) 89{ 90 SkPoint pts[2]; 91 pts[0].set(x0, y0); 92 pts[1].set(x1, y1); 93 94 size_t count = env->GetArrayLength(colorArray); 95 const jint* colorValues = env->GetIntArrayElements(colorArray, NULL); 96 97 AutoJavaFloatArray autoPos(env, posArray, count); 98#ifdef SK_SCALAR_IS_FLOAT 99 SkScalar* pos = autoPos.ptr(); 100#else 101 #error Need to convert float array to SkScalar array before calling the following function. 102#endif 103 104 SkShader* shader = SkGradientShader::CreateLinear(pts, 105 reinterpret_cast<const SkColor*>(colorValues), pos, count, 106 static_cast<SkShader::TileMode>(tileMode)); 107 108 env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT); 109 ThrowIAE_IfNull(env, shader); 110 return reinterpret_cast<jlong>(shader); 111} 112 113static jlong LinearGradient_create2(JNIEnv* env, jobject o, 114 jfloat x0, jfloat y0, jfloat x1, jfloat y1, 115 jint color0, jint color1, jint tileMode) 116{ 117 SkPoint pts[2]; 118 pts[0].set(x0, y0); 119 pts[1].set(x1, y1); 120 121 SkColor colors[2]; 122 colors[0] = color0; 123 colors[1] = color1; 124 125 SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL, 2, (SkShader::TileMode)tileMode); 126 127 ThrowIAE_IfNull(env, s); 128 return reinterpret_cast<jlong>(s); 129} 130 131/////////////////////////////////////////////////////////////////////////////////////////////// 132 133static jlong RadialGradient_create1(JNIEnv* env, jobject, jfloat x, jfloat y, jfloat radius, 134 jintArray colorArray, jfloatArray posArray, jint tileMode) { 135 SkPoint center; 136 center.set(x, y); 137 138 size_t count = env->GetArrayLength(colorArray); 139 const jint* colorValues = env->GetIntArrayElements(colorArray, NULL); 140 141 AutoJavaFloatArray autoPos(env, posArray, count); 142#ifdef SK_SCALAR_IS_FLOAT 143 SkScalar* pos = autoPos.ptr(); 144#else 145 #error Need to convert float array to SkScalar array before calling the following function. 146#endif 147 148 SkShader* shader = SkGradientShader::CreateRadial(center, radius, 149 reinterpret_cast<const SkColor*>(colorValues), pos, count, 150 static_cast<SkShader::TileMode>(tileMode)); 151 env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), 152 JNI_ABORT); 153 154 ThrowIAE_IfNull(env, shader); 155 return reinterpret_cast<jlong>(shader); 156} 157 158static jlong RadialGradient_create2(JNIEnv* env, jobject, jfloat x, jfloat y, jfloat radius, 159 jint color0, jint color1, jint tileMode) { 160 SkPoint center; 161 center.set(x, y); 162 163 SkColor colors[2]; 164 colors[0] = color0; 165 colors[1] = color1; 166 167 SkShader* s = SkGradientShader::CreateRadial(center, radius, colors, NULL, 2, 168 (SkShader::TileMode)tileMode); 169 ThrowIAE_IfNull(env, s); 170 return reinterpret_cast<jlong>(s); 171} 172 173/////////////////////////////////////////////////////////////////////////////// 174 175static jlong SweepGradient_create1(JNIEnv* env, jobject, jfloat x, jfloat y, 176 jintArray jcolors, jfloatArray jpositions) { 177 size_t count = env->GetArrayLength(jcolors); 178 const jint* colors = env->GetIntArrayElements(jcolors, NULL); 179 180 AutoJavaFloatArray autoPos(env, jpositions, count); 181#ifdef SK_SCALAR_IS_FLOAT 182 SkScalar* pos = autoPos.ptr(); 183#else 184 #error Need to convert float array to SkScalar array before calling the following function. 185#endif 186 187 SkShader* shader = SkGradientShader::CreateSweep(x, y, 188 reinterpret_cast<const SkColor*>(colors), pos, count); 189 env->ReleaseIntArrayElements(jcolors, const_cast<jint*>(colors), 190 JNI_ABORT); 191 ThrowIAE_IfNull(env, shader); 192 return reinterpret_cast<jlong>(shader); 193} 194 195static jlong SweepGradient_create2(JNIEnv* env, jobject, jfloat x, jfloat y, 196 int color0, int color1) { 197 SkColor colors[2]; 198 colors[0] = color0; 199 colors[1] = color1; 200 SkShader* s = SkGradientShader::CreateSweep(x, y, colors, NULL, 2); 201 ThrowIAE_IfNull(env, s); 202 return reinterpret_cast<jlong>(s); 203} 204 205/////////////////////////////////////////////////////////////////////////////////////////////// 206 207static jlong ComposeShader_create1(JNIEnv* env, jobject o, 208 jlong shaderAHandle, jlong shaderBHandle, jlong modeHandle) 209{ 210 SkShader* shaderA = reinterpret_cast<SkShader *>(shaderAHandle); 211 SkShader* shaderB = reinterpret_cast<SkShader *>(shaderBHandle); 212 SkXfermode* mode = reinterpret_cast<SkXfermode *>(modeHandle); 213 SkShader* shader = new SkComposeShader(shaderA, shaderB, mode); 214 return reinterpret_cast<jlong>(shader); 215} 216 217static jlong ComposeShader_create2(JNIEnv* env, jobject o, 218 jlong shaderAHandle, jlong shaderBHandle, jint porterDuffModeHandle) 219{ 220 SkShader* shaderA = reinterpret_cast<SkShader *>(shaderAHandle); 221 SkShader* shaderB = reinterpret_cast<SkShader *>(shaderBHandle); 222 SkPorterDuff::Mode porterDuffMode = static_cast<SkPorterDuff::Mode>(porterDuffModeHandle); 223 SkAutoUnref au(SkPorterDuff::CreateXfermode(porterDuffMode)); 224 SkXfermode* mode = (SkXfermode*) au.get(); 225 SkShader* shader = new SkComposeShader(shaderA, shaderB, mode); 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)V", (void*)Shader_setLocalMatrix } 239}; 240 241static const JNINativeMethod gBitmapShaderMethods[] = { 242 { "nativeCreate", "(JII)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