Shader.cpp revision 163935113919a184122b8b3bd672ef08c8df65dc
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 13using namespace android::uirenderer; 14 15static struct { 16 jclass clazz; 17 jfieldID shader; 18} gShaderClassInfo; 19 20static void ThrowIAE_IfNull(JNIEnv* env, void* ptr) { 21 if (NULL == ptr) { 22 doThrowIAE(env); 23 } 24} 25 26static void Color_RGBToHSV(JNIEnv* env, jobject, int red, int green, int blue, jfloatArray hsvArray) 27{ 28 SkScalar hsv[3]; 29 SkRGBToHSV(red, green, blue, hsv); 30 31 AutoJavaFloatArray autoHSV(env, hsvArray, 3); 32 float* values = autoHSV.ptr(); 33 for (int i = 0; i < 3; i++) { 34 values[i] = SkScalarToFloat(hsv[i]); 35 } 36} 37 38static int Color_HSVToColor(JNIEnv* env, jobject, int alpha, jfloatArray hsvArray) 39{ 40 AutoJavaFloatArray autoHSV(env, hsvArray, 3); 41 float* values = autoHSV.ptr();; 42 SkScalar hsv[3]; 43 44 for (int i = 0; i < 3; i++) { 45 hsv[i] = SkFloatToScalar(values[i]); 46 } 47 48 return SkHSVToColor(alpha, hsv); 49} 50 51/////////////////////////////////////////////////////////////////////////////////////////////// 52 53static void Shader_destructor(JNIEnv* env, jobject o, SkShader* shader, SkiaShader* skiaShader) 54{ 55 delete skiaShader; 56 shader->safeUnref(); 57} 58 59static bool Shader_getLocalMatrix(JNIEnv* env, jobject, const SkShader* shader, SkMatrix* matrix) 60{ 61 return shader ? shader->getLocalMatrix(matrix) : false; 62} 63 64static void Shader_setLocalMatrix(JNIEnv* env, jobject o, SkShader* shader, SkiaShader* skiaShader, 65 const SkMatrix* matrix) 66{ 67 if (shader) { 68 if (NULL == matrix) { 69 shader->resetLocalMatrix(); 70 } 71 else { 72 shader->setLocalMatrix(*matrix); 73 } 74#ifdef USE_OPENGL_RENDERER 75 skiaShader->setMatrix(const_cast<SkMatrix*>(matrix)); 76#endif 77 } 78} 79 80/////////////////////////////////////////////////////////////////////////////////////////////// 81 82static SkShader* BitmapShader_constructor(JNIEnv* env, jobject o, const SkBitmap* bitmap, 83 int tileModeX, int tileModeY) 84{ 85 SkShader* s = SkShader::CreateBitmapShader(*bitmap, 86 (SkShader::TileMode)tileModeX, 87 (SkShader::TileMode)tileModeY); 88 89 ThrowIAE_IfNull(env, s); 90 return s; 91} 92 93static SkiaShader* BitmapShader_postConstructor(JNIEnv* env, jobject o, SkShader* shader, 94 SkBitmap* bitmap, int tileModeX, int tileModeY) { 95#ifdef USE_OPENGL_RENDERER 96 SkiaShader* skiaShader = new SkiaBitmapShader(bitmap, shader, 97 static_cast<SkShader::TileMode>(tileModeX), static_cast<SkShader::TileMode>(tileModeY), 98 NULL, (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0); 99 return skiaShader; 100#else 101 return NULL; 102#endif 103} 104 105/////////////////////////////////////////////////////////////////////////////////////////////// 106 107static SkShader* LinearGradient_create1(JNIEnv* env, jobject o, 108 float x0, float y0, float x1, float y1, 109 jintArray colorArray, jfloatArray posArray, int tileMode) 110{ 111 SkPoint pts[2]; 112 pts[0].set(SkFloatToScalar(x0), SkFloatToScalar(y0)); 113 pts[1].set(SkFloatToScalar(x1), SkFloatToScalar(y1)); 114 115 size_t count = env->GetArrayLength(colorArray); 116 const jint* colorValues = env->GetIntArrayElements(colorArray, NULL); 117 118 SkAutoSTMalloc<8, SkScalar> storage(posArray ? count : 0); 119 SkScalar* pos = NULL; 120 121 if (posArray) { 122 AutoJavaFloatArray autoPos(env, posArray, count); 123 const float* posValues = autoPos.ptr(); 124 pos = (SkScalar*)storage.get(); 125 for (size_t i = 0; i < count; i++) { 126 pos[i] = SkFloatToScalar(posValues[i]); 127 } 128 } 129 130 SkShader* shader = SkGradientShader::CreateLinear(pts, 131 reinterpret_cast<const SkColor*>(colorValues), 132 pos, count, 133 static_cast<SkShader::TileMode>(tileMode)); 134 135 env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT); 136 ThrowIAE_IfNull(env, shader); 137 return shader; 138} 139 140static SkiaShader* LinearGradient_postCreate1(JNIEnv* env, jobject o, SkShader* shader, 141 float x0, float y0, float x1, float y1, jintArray colorArray, 142 jfloatArray posArray, int tileMode) { 143#ifdef USE_OPENGL_RENDERER 144 size_t count = env->GetArrayLength(colorArray); 145 const jint* colorValues = env->GetIntArrayElements(colorArray, NULL); 146 147 jfloat* storedBounds = new jfloat[4]; 148 storedBounds[0] = x0; storedBounds[1] = y0; 149 storedBounds[2] = x1; storedBounds[3] = y1; 150 jfloat* storedPositions = new jfloat[count]; 151 uint32_t* storedColors = new uint32_t[count]; 152 memcpy(storedColors, colorValues, count); 153 154 if (posArray) { 155 AutoJavaFloatArray autoPos(env, posArray, count); 156 const float* posValues = autoPos.ptr(); 157 for (size_t i = 0; i < count; i++) { 158 storedPositions[i] = posValues[i]; 159 } 160 } else { 161 storedPositions[0] = 0.0f; 162 storedPositions[1] = 1.0f; 163 } 164 165 SkiaShader* skiaShader = new SkiaLinearGradientShader(storedBounds, storedColors, 166 storedPositions, count, shader, static_cast<SkShader::TileMode>(tileMode), NULL, 167 (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0); 168 169 env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT); 170 return skiaShader; 171#else 172 return NULL; 173#endif 174} 175 176static SkiaShader* LinearGradient_postCreate2(JNIEnv* env, jobject o, SkShader* shader, 177 float x0, float y0, float x1, float y1, int color0, int color1, int tileMode) { 178#ifdef USE_OPENGL_RENDERER 179 float* storedBounds = new float[4]; 180 storedBounds[0] = x0; storedBounds[1] = y0; 181 storedBounds[2] = x1; storedBounds[3] = y1; 182 183 float* storedPositions = new float[2]; 184 storedPositions[0] = 0.0f; 185 storedPositions[1] = 1.0f; 186 187 uint32_t* storedColors = new uint32_t[2]; 188 storedColors[0] = color0; 189 storedColors[1] = color1; 190 191 SkiaShader* skiaShader = new SkiaLinearGradientShader(storedBounds, storedColors, 192 storedPositions, 2, shader, static_cast<SkShader::TileMode>(tileMode), NULL, 193 (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0); 194 195 return skiaShader; 196#else 197 return NULL; 198#endif 199} 200 201static SkShader* LinearGradient_create2(JNIEnv* env, jobject o, 202 float x0, float y0, float x1, float y1, 203 int color0, int color1, int tileMode) 204{ 205 SkPoint pts[2]; 206 pts[0].set(SkFloatToScalar(x0), SkFloatToScalar(y0)); 207 pts[1].set(SkFloatToScalar(x1), SkFloatToScalar(y1)); 208 209 SkColor colors[2]; 210 colors[0] = color0; 211 colors[1] = color1; 212 213 SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL, 2, (SkShader::TileMode)tileMode); 214 215 ThrowIAE_IfNull(env, s); 216 return s; 217} 218 219/////////////////////////////////////////////////////////////////////////////////////////////// 220 221static SkShader* RadialGradient_create1(JNIEnv* env, jobject, 222 float x, float y, float radius, 223 jintArray colorArray, jfloatArray posArray, int tileMode) 224{ 225 SkPoint center; 226 center.set(SkFloatToScalar(x), SkFloatToScalar(y)); 227 228 size_t count = env->GetArrayLength(colorArray); 229 const jint* colorValues = env->GetIntArrayElements(colorArray, NULL); 230 231 SkAutoSTMalloc<8, SkScalar> storage(posArray ? count : 0); 232 SkScalar* pos = NULL; 233 234 if (posArray) { 235 AutoJavaFloatArray autoPos(env, posArray, count); 236 const float* posValues = autoPos.ptr(); 237 pos = (SkScalar*)storage.get(); 238 for (size_t i = 0; i < count; i++) 239 pos[i] = SkFloatToScalar(posValues[i]); 240 } 241 242 SkShader* shader = SkGradientShader::CreateRadial(center, 243 SkFloatToScalar(radius), 244 reinterpret_cast<const SkColor*>(colorValues), 245 pos, count, 246 static_cast<SkShader::TileMode>(tileMode)); 247 env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), 248 JNI_ABORT); 249 250 ThrowIAE_IfNull(env, shader); 251 return shader; 252} 253 254static SkShader* RadialGradient_create2(JNIEnv* env, jobject, 255 float x, float y, float radius, 256 int color0, int color1, int tileMode) 257{ 258 SkPoint center; 259 center.set(SkFloatToScalar(x), SkFloatToScalar(y)); 260 261 SkColor colors[2]; 262 colors[0] = color0; 263 colors[1] = color1; 264 265 SkShader* s = SkGradientShader::CreateRadial(center, SkFloatToScalar(radius), colors, NULL, 266 2, (SkShader::TileMode)tileMode); 267 ThrowIAE_IfNull(env, s); 268 return s; 269} 270 271/////////////////////////////////////////////////////////////////////////////// 272 273static SkShader* SweepGradient_create1(JNIEnv* env, jobject, float x, float y, 274 jintArray jcolors, jfloatArray jpositions) 275{ 276 size_t count = env->GetArrayLength(jcolors); 277 const jint* colors = env->GetIntArrayElements(jcolors, NULL); 278 279 SkAutoSTMalloc<8, SkScalar> storage(jpositions ? count : 0); 280 SkScalar* pos = NULL; 281 282 if (NULL != jpositions) { 283 AutoJavaFloatArray autoPos(env, jpositions, count); 284 const float* posValues = autoPos.ptr(); 285 pos = (SkScalar*)storage.get(); 286 for (size_t i = 0; i < count; i++) { 287 pos[i] = SkFloatToScalar(posValues[i]); 288 } 289 } 290 291 SkShader* shader = SkGradientShader::CreateSweep(SkFloatToScalar(x), 292 SkFloatToScalar(y), 293 reinterpret_cast<const SkColor*>(colors), 294 pos, count); 295 env->ReleaseIntArrayElements(jcolors, const_cast<jint*>(colors), 296 JNI_ABORT); 297 ThrowIAE_IfNull(env, shader); 298 return shader; 299} 300 301static SkShader* SweepGradient_create2(JNIEnv* env, jobject, float x, float y, 302 int color0, int color1) 303{ 304 SkColor colors[2]; 305 colors[0] = color0; 306 colors[1] = color1; 307 SkShader* s = SkGradientShader::CreateSweep(SkFloatToScalar(x), SkFloatToScalar(y), 308 colors, NULL, 2); 309 ThrowIAE_IfNull(env, s); 310 return s; 311} 312 313/////////////////////////////////////////////////////////////////////////////////////////////// 314 315static SkShader* ComposeShader_create1(JNIEnv* env, jobject o, 316 SkShader* shaderA, SkShader* shaderB, SkXfermode* mode) 317{ 318 return new SkComposeShader(shaderA, shaderB, mode); 319} 320 321static SkShader* ComposeShader_create2(JNIEnv* env, jobject o, 322 SkShader* shaderA, SkShader* shaderB, SkPorterDuff::Mode porterDuffMode) 323{ 324 SkAutoUnref au(SkPorterDuff::CreateXfermode(porterDuffMode)); 325 SkXfermode* mode = (SkXfermode*) au.get(); 326 return new SkComposeShader(shaderA, shaderB, mode); 327} 328 329static SkiaShader* ComposeShader_postCreate2(JNIEnv* env, jobject o, SkShader* shader, 330 SkiaShader* shaderA, SkiaShader* shaderB, SkPorterDuff::Mode porterDuffMode) { 331#ifdef USE_OPENGL_RENDERER 332 SkAutoUnref au(SkPorterDuff::CreateXfermode(porterDuffMode)); 333 SkXfermode* mode = (SkXfermode*) au.get(); 334 SkXfermode::Mode skiaMode; 335 if (!SkXfermode::IsMode(mode, &skiaMode)) { 336 skiaMode = SkXfermode::kSrcOver_Mode; 337 } 338 return new SkiaComposeShader(shaderA, shaderB, skiaMode, shader); 339#else 340 return NULL; 341#endif 342} 343 344static SkiaShader* ComposeShader_postCreate1(JNIEnv* env, jobject o, SkShader* shader, 345 SkiaShader* shaderA, SkiaShader* shaderB, SkXfermode* mode) { 346#ifdef USE_OPENGL_RENDERER 347 SkXfermode::Mode skiaMode; 348 if (!SkXfermode::IsMode(mode, &skiaMode)) { 349 skiaMode = SkXfermode::kSrcOver_Mode; 350 } 351 return new SkiaComposeShader(shaderA, shaderB, skiaMode, shader); 352#else 353 return NULL; 354#endif 355} 356 357/////////////////////////////////////////////////////////////////////////////////////////////// 358 359static JNINativeMethod gColorMethods[] = { 360 { "nativeRGBToHSV", "(III[F)V", (void*)Color_RGBToHSV }, 361 { "nativeHSVToColor", "(I[F)I", (void*)Color_HSVToColor } 362}; 363 364static JNINativeMethod gShaderMethods[] = { 365 { "nativeDestructor", "(II)V", (void*)Shader_destructor }, 366 { "nativeGetLocalMatrix", "(II)Z", (void*)Shader_getLocalMatrix }, 367 { "nativeSetLocalMatrix", "(III)V", (void*)Shader_setLocalMatrix } 368}; 369 370static JNINativeMethod gBitmapShaderMethods[] = { 371 { "nativeCreate", "(III)I", (void*)BitmapShader_constructor }, 372 { "nativePostCreate", "(IIII)I", (void*)BitmapShader_postConstructor } 373}; 374 375static JNINativeMethod gLinearGradientMethods[] = { 376 { "nativeCreate1", "(FFFF[I[FI)I", (void*)LinearGradient_create1 }, 377 { "nativeCreate2", "(FFFFIII)I", (void*)LinearGradient_create2 }, 378 { "nativePostCreate1", "(IFFFF[I[FI)I", (void*)LinearGradient_postCreate1 }, 379 { "nativePostCreate2", "(IFFFFIII)I", (void*)LinearGradient_postCreate2 } 380}; 381 382static JNINativeMethod gRadialGradientMethods[] = { 383 {"nativeCreate1", "(FFF[I[FI)I", (void*)RadialGradient_create1 }, 384 {"nativeCreate2", "(FFFIII)I", (void*)RadialGradient_create2 } 385}; 386 387static JNINativeMethod gSweepGradientMethods[] = { 388 {"nativeCreate1", "(FF[I[F)I", (void*)SweepGradient_create1 }, 389 {"nativeCreate2", "(FFII)I", (void*)SweepGradient_create2 } 390}; 391 392static JNINativeMethod gComposeShaderMethods[] = { 393 {"nativeCreate1", "(III)I", (void*)ComposeShader_create1 }, 394 {"nativeCreate2", "(III)I", (void*)ComposeShader_create2 }, 395 {"nativePostCreate1", "(IIII)I", (void*)ComposeShader_postCreate1 }, 396 {"nativePostCreate2", "(IIII)I", (void*)ComposeShader_postCreate2 } 397}; 398 399#include <android_runtime/AndroidRuntime.h> 400 401#define REG(env, name, array) \ 402 result = android::AndroidRuntime::registerNativeMethods(env, name, array, SK_ARRAY_COUNT(array)); \ 403 if (result < 0) return result 404 405int register_android_graphics_Shader(JNIEnv* env); 406int register_android_graphics_Shader(JNIEnv* env) 407{ 408 int result; 409 410 REG(env, "android/graphics/Color", gColorMethods); 411 REG(env, "android/graphics/Shader", gShaderMethods); 412 REG(env, "android/graphics/BitmapShader", gBitmapShaderMethods); 413 REG(env, "android/graphics/LinearGradient", gLinearGradientMethods); 414 REG(env, "android/graphics/RadialGradient", gRadialGradientMethods); 415 REG(env, "android/graphics/SweepGradient", gSweepGradientMethods); 416 REG(env, "android/graphics/ComposeShader", gComposeShaderMethods); 417 418 return result; 419} 420 421