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