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