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