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