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