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