PageRenderTime 45ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/frameworks/base/core/jni/android/graphics/Shader.cpp

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