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