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