Shader.cpp revision 7fac2e18339f765320d759e8d4c090f92431959e
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 11static struct { 12 jclass clazz; 13 jfieldID bounds; 14 jfieldID colors; 15 jfieldID positions; 16} gLinearGradientClassInfo; 17 18static void ThrowIAE_IfNull(JNIEnv* env, void* ptr) { 19 if (NULL == ptr) { 20 doThrowIAE(env); 21 } 22} 23 24static void Color_RGBToHSV(JNIEnv* env, jobject, int red, int green, int blue, jfloatArray hsvArray) 25{ 26 SkScalar hsv[3]; 27 SkRGBToHSV(red, green, blue, hsv); 28 29 AutoJavaFloatArray autoHSV(env, hsvArray, 3); 30 float* values = autoHSV.ptr(); 31 for (int i = 0; i < 3; i++) { 32 values[i] = SkScalarToFloat(hsv[i]); 33 } 34} 35 36static int Color_HSVToColor(JNIEnv* env, jobject, int alpha, jfloatArray hsvArray) 37{ 38 AutoJavaFloatArray autoHSV(env, hsvArray, 3); 39 float* values = autoHSV.ptr();; 40 SkScalar hsv[3]; 41 42 for (int i = 0; i < 3; i++) { 43 hsv[i] = SkFloatToScalar(values[i]); 44 } 45 46 return SkHSVToColor(alpha, hsv); 47} 48 49/////////////////////////////////////////////////////////////////////////////////////////////// 50 51static void Shader_destructor(JNIEnv* env, jobject, SkShader* shader) 52{ 53 shader->safeUnref(); 54} 55 56static bool Shader_getLocalMatrix(JNIEnv* env, jobject, const SkShader* shader, SkMatrix* matrix) 57{ 58 return shader ? shader->getLocalMatrix(matrix) : false; 59} 60 61static void Shader_setLocalMatrix(JNIEnv* env, jobject, SkShader* shader, const SkMatrix* matrix) 62{ 63 if (shader) { 64 if (NULL == matrix) { 65 shader->resetLocalMatrix(); 66 } 67 else { 68 shader->setLocalMatrix(*matrix); 69 } 70 } 71} 72 73/////////////////////////////////////////////////////////////////////////////////////////////// 74 75static SkShader* BitmapShader_constructor(JNIEnv* env, jobject, const SkBitmap* bitmap, 76 int tileModeX, int tileModeY) 77{ 78 SkShader* s = SkShader::CreateBitmapShader(*bitmap, 79 (SkShader::TileMode)tileModeX, 80 (SkShader::TileMode)tileModeY); 81 ThrowIAE_IfNull(env, s); 82 return s; 83} 84 85/////////////////////////////////////////////////////////////////////////////////////////////// 86 87static void LinearGradient_destructor(JNIEnv* env, jobject o, SkShader* shader) 88{ 89 delete reinterpret_cast<jfloat*>(env->GetIntField(o, gLinearGradientClassInfo.bounds)); 90 delete reinterpret_cast<jint*>(env->GetIntField(o, gLinearGradientClassInfo.colors)); 91 delete reinterpret_cast<jfloat*>(env->GetIntField(o, gLinearGradientClassInfo.positions)); 92} 93 94static SkShader* LinearGradient_create1(JNIEnv* env, jobject o, 95 float x0, float y0, float x1, float y1, 96 jintArray colorArray, jfloatArray posArray, int tileMode) 97{ 98 SkPoint pts[2]; 99 pts[0].set(SkFloatToScalar(x0), SkFloatToScalar(y0)); 100 pts[1].set(SkFloatToScalar(x1), SkFloatToScalar(y1)); 101 102 size_t count = env->GetArrayLength(colorArray); 103 const jint* colorValues = env->GetIntArrayElements(colorArray, NULL); 104 105 SkAutoSTMalloc<8, SkScalar> storage(posArray ? count : 0); 106 SkScalar* pos = NULL; 107 108 jfloat* storedBounds = new jfloat[4]; 109 storedBounds[0] = x0; storedBounds[1] = y0; 110 storedBounds[2] = x1; storedBounds[3] = y1; 111 jfloat* storedPositions = new jfloat[count]; 112 jint* storedColors = new jint[count]; 113 memcpy(storedColors, colorValues, count); 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 storedPositions[i] = posValues[i]; 122 } 123 } else { 124 storedPositions[0] = 0.0f; 125 storedPositions[1] = 1.0f; 126 } 127 128 env->SetIntField(o, gLinearGradientClassInfo.bounds, reinterpret_cast<jint>(storedBounds)); 129 env->SetIntField(o, gLinearGradientClassInfo.colors, reinterpret_cast<jint>(storedColors)); 130 env->SetIntField(o, gLinearGradientClassInfo.positions, reinterpret_cast<jint>(storedPositions)); 131 132 SkShader* shader = SkGradientShader::CreateLinear(pts, 133 reinterpret_cast<const SkColor*>(colorValues), 134 pos, count, 135 static_cast<SkShader::TileMode>(tileMode)); 136 env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), 137 JNI_ABORT); 138 ThrowIAE_IfNull(env, shader); 139 return shader; 140} 141 142static SkShader* LinearGradient_create2(JNIEnv* env, jobject o, 143 float x0, float y0, float x1, float y1, 144 int color0, int color1, int tileMode) 145{ 146 SkPoint pts[2]; 147 pts[0].set(SkFloatToScalar(x0), SkFloatToScalar(y0)); 148 pts[1].set(SkFloatToScalar(x1), SkFloatToScalar(y1)); 149 150 SkColor colors[2]; 151 colors[0] = color0; 152 colors[1] = color1; 153 154 float* storedBounds = new float[4]; 155 storedBounds[0] = x0; storedBounds[1] = y0; 156 storedBounds[2] = x1; storedBounds[3] = y1; 157 158 float* storedPositions = new float[2]; 159 storedPositions[0] = 0.0f; 160 storedPositions[1] = 1.0f; 161 162 uint32_t* storedColors = new uint32_t[2]; 163 storedColors[0] = color0; 164 storedColors[1] = color1; 165 166 env->SetIntField(o, gLinearGradientClassInfo.bounds, reinterpret_cast<jint>(storedBounds)); 167 env->SetIntField(o, gLinearGradientClassInfo.colors, reinterpret_cast<jint>(storedColors)); 168 env->SetIntField(o, gLinearGradientClassInfo.positions, reinterpret_cast<jint>(storedPositions)); 169 170 SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL, 2, (SkShader::TileMode)tileMode); 171 ThrowIAE_IfNull(env, s); 172 return s; 173} 174 175/////////////////////////////////////////////////////////////////////////////////////////////// 176 177static SkShader* RadialGradient_create1(JNIEnv* env, jobject, 178 float x, float y, float radius, 179 jintArray colorArray, jfloatArray posArray, int tileMode) 180{ 181 SkPoint center; 182 center.set(SkFloatToScalar(x), SkFloatToScalar(y)); 183 184 size_t count = env->GetArrayLength(colorArray); 185 const jint* colorValues = env->GetIntArrayElements(colorArray, NULL); 186 187 SkAutoSTMalloc<8, SkScalar> storage(posArray ? count : 0); 188 SkScalar* pos = NULL; 189 190 if (posArray) { 191 AutoJavaFloatArray autoPos(env, posArray, count); 192 const float* posValues = autoPos.ptr(); 193 pos = (SkScalar*)storage.get(); 194 for (size_t i = 0; i < count; i++) 195 pos[i] = SkFloatToScalar(posValues[i]); 196 } 197 198 SkShader* shader = SkGradientShader::CreateRadial(center, 199 SkFloatToScalar(radius), 200 reinterpret_cast<const SkColor*>(colorValues), 201 pos, count, 202 static_cast<SkShader::TileMode>(tileMode)); 203 env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), 204 JNI_ABORT); 205 206 ThrowIAE_IfNull(env, shader); 207 return shader; 208} 209 210static SkShader* RadialGradient_create2(JNIEnv* env, jobject, 211 float x, float y, float radius, 212 int color0, int color1, int tileMode) 213{ 214 SkPoint center; 215 center.set(SkFloatToScalar(x), SkFloatToScalar(y)); 216 217 SkColor colors[2]; 218 colors[0] = color0; 219 colors[1] = color1; 220 221 SkShader* s = SkGradientShader::CreateRadial(center, SkFloatToScalar(radius), colors, NULL, 222 2, (SkShader::TileMode)tileMode); 223 ThrowIAE_IfNull(env, s); 224 return s; 225} 226 227/////////////////////////////////////////////////////////////////////////////// 228 229static SkShader* SweepGradient_create1(JNIEnv* env, jobject, float x, float y, 230 jintArray jcolors, jfloatArray jpositions) 231{ 232 size_t count = env->GetArrayLength(jcolors); 233 const jint* colors = env->GetIntArrayElements(jcolors, NULL); 234 235 SkAutoSTMalloc<8, SkScalar> storage(jpositions ? count : 0); 236 SkScalar* pos = NULL; 237 238 if (NULL != jpositions) { 239 AutoJavaFloatArray autoPos(env, jpositions, count); 240 const float* posValues = autoPos.ptr(); 241 pos = (SkScalar*)storage.get(); 242 for (size_t i = 0; i < count; i++) { 243 pos[i] = SkFloatToScalar(posValues[i]); 244 } 245 } 246 247 SkShader* shader = SkGradientShader::CreateSweep(SkFloatToScalar(x), 248 SkFloatToScalar(y), 249 reinterpret_cast<const SkColor*>(colors), 250 pos, count); 251 env->ReleaseIntArrayElements(jcolors, const_cast<jint*>(colors), 252 JNI_ABORT); 253 ThrowIAE_IfNull(env, shader); 254 return shader; 255} 256 257static SkShader* SweepGradient_create2(JNIEnv* env, jobject, float x, float y, 258 int color0, int color1) 259{ 260 SkColor colors[2]; 261 colors[0] = color0; 262 colors[1] = color1; 263 SkShader* s = SkGradientShader::CreateSweep(SkFloatToScalar(x), SkFloatToScalar(y), 264 colors, NULL, 2); 265 ThrowIAE_IfNull(env, s); 266 return s; 267} 268 269/////////////////////////////////////////////////////////////////////////////////////////////// 270 271static SkShader* ComposeShader_create1(JNIEnv* env, jobject, 272 SkShader* shaderA, SkShader* shaderB, SkXfermode* mode) 273{ 274 return new SkComposeShader(shaderA, shaderB, mode); 275} 276 277static SkShader* ComposeShader_create2(JNIEnv* env, jobject, 278 SkShader* shaderA, SkShader* shaderB, SkPorterDuff::Mode mode) 279{ 280 SkAutoUnref au(SkPorterDuff::CreateXfermode(mode)); 281 282 return new SkComposeShader(shaderA, shaderB, (SkXfermode*)au.get()); 283} 284 285/////////////////////////////////////////////////////////////////////////////////////////////// 286 287static JNINativeMethod gColorMethods[] = { 288 { "nativeRGBToHSV", "(III[F)V", (void*)Color_RGBToHSV }, 289 { "nativeHSVToColor", "(I[F)I", (void*)Color_HSVToColor } 290}; 291 292static JNINativeMethod gShaderMethods[] = { 293 { "nativeDestructor", "(I)V", (void*)Shader_destructor }, 294 { "nativeGetLocalMatrix", "(II)Z", (void*)Shader_getLocalMatrix }, 295 { "nativeSetLocalMatrix", "(II)V", (void*)Shader_setLocalMatrix } 296}; 297 298static JNINativeMethod gBitmapShaderMethods[] = { 299 { "nativeCreate", "(III)I", (void*)BitmapShader_constructor } 300}; 301 302static JNINativeMethod gLinearGradientMethods[] = { 303 { "nativeDestructor", "(I)V", (void*)LinearGradient_destructor }, 304 { "nativeCreate1", "(FFFF[I[FI)I", (void*)LinearGradient_create1 }, 305 { "nativeCreate2", "(FFFFIII)I", (void*)LinearGradient_create2 } 306}; 307 308static JNINativeMethod gRadialGradientMethods[] = { 309 {"nativeCreate1", "(FFF[I[FI)I", (void*)RadialGradient_create1 }, 310 {"nativeCreate2", "(FFFIII)I", (void*)RadialGradient_create2 } 311}; 312 313static JNINativeMethod gSweepGradientMethods[] = { 314 {"nativeCreate1", "(FF[I[F)I", (void*)SweepGradient_create1 }, 315 {"nativeCreate2", "(FFII)I", (void*)SweepGradient_create2 } 316}; 317 318static JNINativeMethod gComposeShaderMethods[] = { 319 {"nativeCreate1", "(III)I", (void*)ComposeShader_create1 }, 320 {"nativeCreate2", "(III)I", (void*)ComposeShader_create2 } 321}; 322 323#include <android_runtime/AndroidRuntime.h> 324 325#define REG(env, name, array) \ 326 result = android::AndroidRuntime::registerNativeMethods(env, name, array, SK_ARRAY_COUNT(array)); \ 327 if (result < 0) return result 328 329#define FIND_CLASS(var, className) \ 330 var = env->FindClass(className); \ 331 LOG_FATAL_IF(! var, "Unable to find class " className); \ 332 var = jclass(env->NewGlobalRef(var)); 333 334#define GET_FIELD_ID(var, clazz, fieldName, fieldType) \ 335 var = env->GetFieldID(clazz, fieldName, fieldType); \ 336 LOG_FATAL_IF(! var, "Unable to find field " fieldName); 337 338int register_android_graphics_Shader(JNIEnv* env); 339int register_android_graphics_Shader(JNIEnv* env) 340{ 341 int result; 342 343 REG(env, "android/graphics/Color", gColorMethods); 344 REG(env, "android/graphics/Shader", gShaderMethods); 345 REG(env, "android/graphics/BitmapShader", gBitmapShaderMethods); 346 REG(env, "android/graphics/LinearGradient", gLinearGradientMethods); 347 REG(env, "android/graphics/RadialGradient", gRadialGradientMethods); 348 REG(env, "android/graphics/SweepGradient", gSweepGradientMethods); 349 REG(env, "android/graphics/ComposeShader", gComposeShaderMethods); 350 351 FIND_CLASS(gLinearGradientClassInfo.clazz, "android/graphics/LinearGradient"); 352 GET_FIELD_ID(gLinearGradientClassInfo.bounds, gLinearGradientClassInfo.clazz, "bounds", "I"); 353 GET_FIELD_ID(gLinearGradientClassInfo.colors, gLinearGradientClassInfo.clazz, "colors", "I"); 354 GET_FIELD_ID(gLinearGradientClassInfo.positions, gLinearGradientClassInfo.clazz, "positions", "I"); 355 356 return result; 357} 358 359