Shader.cpp revision ddb80bebb0776e6d852aab6e8bba5d5591847a55
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, int red, int green, int 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 int Color_HSVToColor(JNIEnv* env, jobject, int alpha, jfloatArray hsvArray) 40{ 41 AutoJavaFloatArray autoHSV(env, hsvArray, 3); 42 float* values = autoHSV.ptr();; 43 SkScalar hsv[3]; 44 45 for (int i = 0; i < 3; i++) { 46 hsv[i] = SkFloatToScalar(values[i]); 47 } 48 49 return SkHSVToColor(alpha, hsv); 50} 51 52/////////////////////////////////////////////////////////////////////////////////////////////// 53 54static void Shader_destructor(JNIEnv* env, jobject o, SkShader* shader, SkiaShader* skiaShader) 55{ 56#ifdef USE_OPENGL_RENDERER 57 if (android::uirenderer::Caches::hasInstance()) { 58 android::uirenderer::Caches::getInstance().gradientCache.remove(shader); 59 } 60#endif 61 delete skiaShader; 62 shader->safeUnref(); 63} 64 65static bool Shader_getLocalMatrix(JNIEnv* env, jobject, const SkShader* shader, SkMatrix* matrix) 66{ 67 return shader ? shader->getLocalMatrix(matrix) : false; 68} 69 70static void Shader_setLocalMatrix(JNIEnv* env, jobject o, SkShader* shader, SkiaShader* skiaShader, 71 const SkMatrix* matrix) 72{ 73 if (shader) { 74 if (NULL == matrix) { 75 shader->resetLocalMatrix(); 76 } 77 else { 78 shader->setLocalMatrix(*matrix); 79 } 80#ifdef USE_OPENGL_RENDERER 81 skiaShader->setMatrix(const_cast<SkMatrix*>(matrix)); 82#endif 83 } 84} 85 86/////////////////////////////////////////////////////////////////////////////////////////////// 87 88static SkShader* BitmapShader_constructor(JNIEnv* env, jobject o, const SkBitmap* bitmap, 89 int tileModeX, int tileModeY) 90{ 91 SkShader* s = SkShader::CreateBitmapShader(*bitmap, 92 (SkShader::TileMode)tileModeX, 93 (SkShader::TileMode)tileModeY); 94 95 ThrowIAE_IfNull(env, s); 96 return s; 97} 98 99static SkiaShader* BitmapShader_postConstructor(JNIEnv* env, jobject o, SkShader* shader, 100 SkBitmap* bitmap, int tileModeX, int tileModeY) { 101#ifdef USE_OPENGL_RENDERER 102 SkiaShader* skiaShader = new SkiaBitmapShader(bitmap, shader, 103 static_cast<SkShader::TileMode>(tileModeX), static_cast<SkShader::TileMode>(tileModeY), 104 NULL, (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0); 105 return skiaShader; 106#else 107 return NULL; 108#endif 109} 110 111/////////////////////////////////////////////////////////////////////////////////////////////// 112 113static SkShader* LinearGradient_create1(JNIEnv* env, jobject o, 114 float x0, float y0, float x1, float y1, 115 jintArray colorArray, jfloatArray posArray, int tileMode) 116{ 117 SkPoint pts[2]; 118 pts[0].set(SkFloatToScalar(x0), SkFloatToScalar(y0)); 119 pts[1].set(SkFloatToScalar(x1), SkFloatToScalar(y1)); 120 121 size_t count = env->GetArrayLength(colorArray); 122 const jint* colorValues = env->GetIntArrayElements(colorArray, NULL); 123 124 SkAutoSTMalloc<8, SkScalar> storage(posArray ? count : 0); 125 SkScalar* pos = NULL; 126 127 if (posArray) { 128 AutoJavaFloatArray autoPos(env, posArray, count); 129 const float* posValues = autoPos.ptr(); 130 pos = (SkScalar*)storage.get(); 131 for (size_t i = 0; i < count; i++) { 132 pos[i] = SkFloatToScalar(posValues[i]); 133 } 134 } 135 136 SkShader* shader = SkGradientShader::CreateLinear(pts, 137 reinterpret_cast<const SkColor*>(colorValues), 138 pos, count, 139 static_cast<SkShader::TileMode>(tileMode)); 140 141 env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT); 142 ThrowIAE_IfNull(env, shader); 143 return shader; 144} 145 146static SkiaShader* LinearGradient_postCreate1(JNIEnv* env, jobject o, SkShader* shader, 147 float x0, float y0, float x1, float y1, jintArray colorArray, 148 jfloatArray posArray, int tileMode) { 149#ifdef USE_OPENGL_RENDERER 150 size_t count = env->GetArrayLength(colorArray); 151 const jint* colorValues = env->GetIntArrayElements(colorArray, NULL); 152 153 jfloat* storedBounds = new jfloat[4]; 154 storedBounds[0] = x0; storedBounds[1] = y0; 155 storedBounds[2] = x1; storedBounds[3] = y1; 156 jfloat* storedPositions = new jfloat[count]; 157 uint32_t* storedColors = new uint32_t[count]; 158 for (size_t i = 0; i < count; i++) { 159 storedColors[i] = static_cast<uint32_t>(colorValues[i]); 160 } 161 162 if (posArray) { 163 AutoJavaFloatArray autoPos(env, posArray, count); 164 const float* posValues = autoPos.ptr(); 165 for (size_t i = 0; i < count; i++) { 166 storedPositions[i] = posValues[i]; 167 } 168 } else { 169 storedPositions[0] = 0.0f; 170 storedPositions[1] = 1.0f; 171 } 172 173 SkiaShader* skiaShader = new SkiaLinearGradientShader(storedBounds, storedColors, 174 storedPositions, count, shader, static_cast<SkShader::TileMode>(tileMode), NULL, 175 (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0); 176 177 env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT); 178 return skiaShader; 179#else 180 return NULL; 181#endif 182} 183 184static SkiaShader* LinearGradient_postCreate2(JNIEnv* env, jobject o, SkShader* shader, 185 float x0, float y0, float x1, float y1, int color0, int color1, int tileMode) { 186#ifdef USE_OPENGL_RENDERER 187 float* storedBounds = new float[4]; 188 storedBounds[0] = x0; storedBounds[1] = y0; 189 storedBounds[2] = x1; storedBounds[3] = y1; 190 191 float* storedPositions = new float[2]; 192 storedPositions[0] = 0.0f; 193 storedPositions[1] = 1.0f; 194 195 uint32_t* storedColors = new uint32_t[2]; 196 storedColors[0] = static_cast<uint32_t>(color0); 197 storedColors[1] = static_cast<uint32_t>(color1); 198 199 SkiaShader* skiaShader = new SkiaLinearGradientShader(storedBounds, storedColors, 200 storedPositions, 2, shader, static_cast<SkShader::TileMode>(tileMode), NULL, 201 (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0); 202 203 return skiaShader; 204#else 205 return NULL; 206#endif 207} 208 209static SkShader* LinearGradient_create2(JNIEnv* env, jobject o, 210 float x0, float y0, float x1, float y1, 211 int color0, int color1, int tileMode) 212{ 213 SkPoint pts[2]; 214 pts[0].set(SkFloatToScalar(x0), SkFloatToScalar(y0)); 215 pts[1].set(SkFloatToScalar(x1), SkFloatToScalar(y1)); 216 217 SkColor colors[2]; 218 colors[0] = color0; 219 colors[1] = color1; 220 221 SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL, 2, (SkShader::TileMode)tileMode); 222 223 ThrowIAE_IfNull(env, s); 224 return s; 225} 226 227/////////////////////////////////////////////////////////////////////////////////////////////// 228 229static SkShader* RadialGradient_create1(JNIEnv* env, jobject, float x, float y, float radius, 230 jintArray colorArray, jfloatArray posArray, int tileMode) { 231 SkPoint center; 232 center.set(SkFloatToScalar(x), SkFloatToScalar(y)); 233 234 size_t count = env->GetArrayLength(colorArray); 235 const jint* colorValues = env->GetIntArrayElements(colorArray, NULL); 236 237 SkAutoSTMalloc<8, SkScalar> storage(posArray ? count : 0); 238 SkScalar* pos = NULL; 239 240 if (posArray) { 241 AutoJavaFloatArray autoPos(env, posArray, count); 242 const float* posValues = autoPos.ptr(); 243 pos = (SkScalar*)storage.get(); 244 for (size_t i = 0; i < count; i++) 245 pos[i] = SkFloatToScalar(posValues[i]); 246 } 247 248 SkShader* shader = SkGradientShader::CreateRadial(center, 249 SkFloatToScalar(radius), 250 reinterpret_cast<const SkColor*>(colorValues), 251 pos, count, 252 static_cast<SkShader::TileMode>(tileMode)); 253 env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), 254 JNI_ABORT); 255 256 ThrowIAE_IfNull(env, shader); 257 return shader; 258} 259 260static SkShader* RadialGradient_create2(JNIEnv* env, jobject, float x, float y, float radius, 261 int color0, int color1, int tileMode) { 262 SkPoint center; 263 center.set(SkFloatToScalar(x), SkFloatToScalar(y)); 264 265 SkColor colors[2]; 266 colors[0] = color0; 267 colors[1] = color1; 268 269 SkShader* s = SkGradientShader::CreateRadial(center, SkFloatToScalar(radius), colors, NULL, 270 2, (SkShader::TileMode)tileMode); 271 ThrowIAE_IfNull(env, s); 272 return s; 273} 274 275static SkiaShader* RadialGradient_postCreate1(JNIEnv* env, jobject o, SkShader* shader, 276 float x, float y, float radius, jintArray colorArray, jfloatArray posArray, int tileMode) { 277#ifdef USE_OPENGL_RENDERER 278 size_t count = env->GetArrayLength(colorArray); 279 const jint* colorValues = env->GetIntArrayElements(colorArray, NULL); 280 281 jfloat* storedPositions = new jfloat[count]; 282 uint32_t* storedColors = new uint32_t[count]; 283 for (size_t i = 0; i < count; i++) { 284 storedColors[i] = static_cast<uint32_t>(colorValues[i]); 285 } 286 287 if (posArray) { 288 AutoJavaFloatArray autoPos(env, posArray, count); 289 const float* posValues = autoPos.ptr(); 290 for (size_t i = 0; i < count; i++) { 291 storedPositions[i] = posValues[i]; 292 } 293 } else { 294 storedPositions[0] = 0.0f; 295 storedPositions[1] = 1.0f; 296 } 297 298 SkiaShader* skiaShader = new SkiaCircularGradientShader(x, y, radius, storedColors, 299 storedPositions, count, shader, (SkShader::TileMode) tileMode, NULL, 300 (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0); 301 302 env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT); 303 return skiaShader; 304#else 305 return NULL; 306#endif 307} 308 309static SkiaShader* RadialGradient_postCreate2(JNIEnv* env, jobject o, SkShader* shader, 310 float x, float y, float radius, int color0, int color1, int tileMode) { 311#ifdef USE_OPENGL_RENDERER 312 float* storedPositions = new float[2]; 313 storedPositions[0] = 0.0f; 314 storedPositions[1] = 1.0f; 315 316 uint32_t* storedColors = new uint32_t[2]; 317 storedColors[0] = static_cast<uint32_t>(color0); 318 storedColors[1] = static_cast<uint32_t>(color1); 319 320 SkiaShader* skiaShader = new SkiaCircularGradientShader(x, y, radius, storedColors, 321 storedPositions, 2, shader, (SkShader::TileMode) tileMode, NULL, 322 (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0); 323 324 return skiaShader; 325#else 326 return NULL; 327#endif 328} 329 330/////////////////////////////////////////////////////////////////////////////// 331 332static SkShader* SweepGradient_create1(JNIEnv* env, jobject, float x, float y, 333 jintArray jcolors, jfloatArray jpositions) { 334 size_t count = env->GetArrayLength(jcolors); 335 const jint* colors = env->GetIntArrayElements(jcolors, NULL); 336 337 SkAutoSTMalloc<8, SkScalar> storage(jpositions ? count : 0); 338 SkScalar* pos = NULL; 339 340 if (NULL != jpositions) { 341 AutoJavaFloatArray autoPos(env, jpositions, count); 342 const float* posValues = autoPos.ptr(); 343 pos = (SkScalar*)storage.get(); 344 for (size_t i = 0; i < count; i++) { 345 pos[i] = SkFloatToScalar(posValues[i]); 346 } 347 } 348 349 SkShader* shader = SkGradientShader::CreateSweep(SkFloatToScalar(x), 350 SkFloatToScalar(y), 351 reinterpret_cast<const SkColor*>(colors), 352 pos, count); 353 env->ReleaseIntArrayElements(jcolors, const_cast<jint*>(colors), 354 JNI_ABORT); 355 ThrowIAE_IfNull(env, shader); 356 return shader; 357} 358 359static SkShader* SweepGradient_create2(JNIEnv* env, jobject, float x, float y, 360 int color0, int color1) { 361 SkColor colors[2]; 362 colors[0] = color0; 363 colors[1] = color1; 364 SkShader* s = SkGradientShader::CreateSweep(SkFloatToScalar(x), SkFloatToScalar(y), 365 colors, NULL, 2); 366 ThrowIAE_IfNull(env, s); 367 return s; 368} 369 370static SkiaShader* SweepGradient_postCreate1(JNIEnv* env, jobject o, SkShader* shader, 371 float x, float y, jintArray colorArray, jfloatArray posArray) { 372#ifdef USE_OPENGL_RENDERER 373 size_t count = env->GetArrayLength(colorArray); 374 const jint* colorValues = env->GetIntArrayElements(colorArray, NULL); 375 376 jfloat* storedPositions = new jfloat[count]; 377 uint32_t* storedColors = new uint32_t[count]; 378 for (size_t i = 0; i < count; i++) { 379 storedColors[i] = static_cast<uint32_t>(colorValues[i]); 380 } 381 382 if (posArray) { 383 AutoJavaFloatArray autoPos(env, posArray, count); 384 const float* posValues = autoPos.ptr(); 385 for (size_t i = 0; i < count; i++) { 386 storedPositions[i] = posValues[i]; 387 } 388 } else { 389 storedPositions[0] = 0.0f; 390 storedPositions[1] = 1.0f; 391 } 392 393 SkiaShader* skiaShader = new SkiaSweepGradientShader(x, y, storedColors, storedPositions, count, 394 shader, NULL, (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0); 395 396 env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT); 397 return skiaShader; 398#else 399 return NULL; 400#endif 401} 402 403static SkiaShader* SweepGradient_postCreate2(JNIEnv* env, jobject o, SkShader* shader, 404 float x, float y, int color0, int color1) { 405#ifdef USE_OPENGL_RENDERER 406 float* storedPositions = new float[2]; 407 storedPositions[0] = 0.0f; 408 storedPositions[1] = 1.0f; 409 410 uint32_t* storedColors = new uint32_t[2]; 411 storedColors[0] = static_cast<uint32_t>(color0); 412 storedColors[1] = static_cast<uint32_t>(color1); 413 414 SkiaShader* skiaShader = new SkiaSweepGradientShader(x, y, storedColors, storedPositions, 2, 415 shader, NULL, (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0); 416 417 return skiaShader; 418#else 419 return NULL; 420#endif 421} 422 423/////////////////////////////////////////////////////////////////////////////////////////////// 424 425static SkShader* ComposeShader_create1(JNIEnv* env, jobject o, 426 SkShader* shaderA, SkShader* shaderB, SkXfermode* mode) 427{ 428 return new SkComposeShader(shaderA, shaderB, mode); 429} 430 431static SkShader* ComposeShader_create2(JNIEnv* env, jobject o, 432 SkShader* shaderA, SkShader* shaderB, SkPorterDuff::Mode porterDuffMode) 433{ 434 SkAutoUnref au(SkPorterDuff::CreateXfermode(porterDuffMode)); 435 SkXfermode* mode = (SkXfermode*) au.get(); 436 return new SkComposeShader(shaderA, shaderB, mode); 437} 438 439static SkiaShader* ComposeShader_postCreate2(JNIEnv* env, jobject o, SkShader* shader, 440 SkiaShader* shaderA, SkiaShader* shaderB, SkPorterDuff::Mode porterDuffMode) { 441#ifdef USE_OPENGL_RENDERER 442 SkXfermode::Mode mode = SkPorterDuff::ToXfermodeMode(porterDuffMode); 443 return new SkiaComposeShader(shaderA, shaderB, mode, shader); 444#else 445 return NULL; 446#endif 447} 448 449static SkiaShader* ComposeShader_postCreate1(JNIEnv* env, jobject o, SkShader* shader, 450 SkiaShader* shaderA, SkiaShader* shaderB, SkXfermode* mode) { 451#ifdef USE_OPENGL_RENDERER 452 SkXfermode::Mode skiaMode; 453 if (!SkXfermode::IsMode(mode, &skiaMode)) { 454 // TODO: Support other modes 455 skiaMode = SkXfermode::kSrcOver_Mode; 456 } 457 return new SkiaComposeShader(shaderA, shaderB, skiaMode, shader); 458#else 459 return NULL; 460#endif 461} 462 463/////////////////////////////////////////////////////////////////////////////////////////////// 464 465static JNINativeMethod gColorMethods[] = { 466 { "nativeRGBToHSV", "(III[F)V", (void*)Color_RGBToHSV }, 467 { "nativeHSVToColor", "(I[F)I", (void*)Color_HSVToColor } 468}; 469 470static JNINativeMethod gShaderMethods[] = { 471 { "nativeDestructor", "(II)V", (void*)Shader_destructor }, 472 { "nativeGetLocalMatrix", "(II)Z", (void*)Shader_getLocalMatrix }, 473 { "nativeSetLocalMatrix", "(III)V", (void*)Shader_setLocalMatrix } 474}; 475 476static JNINativeMethod gBitmapShaderMethods[] = { 477 { "nativeCreate", "(III)I", (void*)BitmapShader_constructor }, 478 { "nativePostCreate", "(IIII)I", (void*)BitmapShader_postConstructor } 479}; 480 481static JNINativeMethod gLinearGradientMethods[] = { 482 { "nativeCreate1", "(FFFF[I[FI)I", (void*)LinearGradient_create1 }, 483 { "nativeCreate2", "(FFFFIII)I", (void*)LinearGradient_create2 }, 484 { "nativePostCreate1", "(IFFFF[I[FI)I", (void*)LinearGradient_postCreate1 }, 485 { "nativePostCreate2", "(IFFFFIII)I", (void*)LinearGradient_postCreate2 } 486}; 487 488static JNINativeMethod gRadialGradientMethods[] = { 489 { "nativeCreate1", "(FFF[I[FI)I", (void*)RadialGradient_create1 }, 490 { "nativeCreate2", "(FFFIII)I", (void*)RadialGradient_create2 }, 491 { "nativePostCreate1", "(IFFF[I[FI)I", (void*)RadialGradient_postCreate1 }, 492 { "nativePostCreate2", "(IFFFIII)I", (void*)RadialGradient_postCreate2 } 493}; 494 495static JNINativeMethod gSweepGradientMethods[] = { 496 { "nativeCreate1", "(FF[I[F)I", (void*)SweepGradient_create1 }, 497 { "nativeCreate2", "(FFII)I", (void*)SweepGradient_create2 }, 498 { "nativePostCreate1", "(IFF[I[F)I", (void*)SweepGradient_postCreate1 }, 499 { "nativePostCreate2", "(IFFII)I", (void*)SweepGradient_postCreate2 } 500}; 501 502static JNINativeMethod gComposeShaderMethods[] = { 503 { "nativeCreate1", "(III)I", (void*)ComposeShader_create1 }, 504 { "nativeCreate2", "(III)I", (void*)ComposeShader_create2 }, 505 { "nativePostCreate1", "(IIII)I", (void*)ComposeShader_postCreate1 }, 506 { "nativePostCreate2", "(IIII)I", (void*)ComposeShader_postCreate2 } 507}; 508 509#include <android_runtime/AndroidRuntime.h> 510 511#define REG(env, name, array) \ 512 result = android::AndroidRuntime::registerNativeMethods(env, name, array, SK_ARRAY_COUNT(array)); \ 513 if (result < 0) return result 514 515int register_android_graphics_Shader(JNIEnv* env); 516int register_android_graphics_Shader(JNIEnv* env) 517{ 518 int result; 519 520 REG(env, "android/graphics/Color", gColorMethods); 521 REG(env, "android/graphics/Shader", gShaderMethods); 522 REG(env, "android/graphics/BitmapShader", gBitmapShaderMethods); 523 REG(env, "android/graphics/LinearGradient", gLinearGradientMethods); 524 REG(env, "android/graphics/RadialGradient", gRadialGradientMethods); 525 REG(env, "android/graphics/SweepGradient", gSweepGradientMethods); 526 REG(env, "android/graphics/ComposeShader", gComposeShaderMethods); 527 528 return result; 529} 530 531