#include #include "GraphicsJNI.h" #include "SkShader.h" #include "SkGradientShader.h" #include "SkPorterDuff.h" #include "SkComposeShader.h" #include "SkTemplates.h" #include "SkXfermode.h" static void ThrowIAE_IfNull(JNIEnv* env, void* ptr) { if (NULL == ptr) { doThrowIAE(env); } } static void Color_RGBToHSV(JNIEnv* env, jobject, int red, int green, int blue, jfloatArray hsvArray) { SkScalar hsv[3]; SkRGBToHSV(red, green, blue, hsv); AutoJavaFloatArray autoHSV(env, hsvArray, 3); float* values = autoHSV.ptr(); for (int i = 0; i < 3; i++) { values[i] = SkScalarToFloat(hsv[i]); } } static int Color_HSVToColor(JNIEnv* env, jobject, int alpha, jfloatArray hsvArray) { AutoJavaFloatArray autoHSV(env, hsvArray, 3); float* values = autoHSV.ptr();; SkScalar hsv[3]; for (int i = 0; i < 3; i++) { hsv[i] = SkFloatToScalar(values[i]); } return SkHSVToColor(alpha, hsv); } /////////////////////////////////////////////////////////////////////////////////////////////// static void Shader_destructor(JNIEnv* env, jobject, SkShader* shader) { shader->safeUnref(); } static bool Shader_getLocalMatrix(JNIEnv* env, jobject, const SkShader* shader, SkMatrix* matrix) { return shader ? shader->getLocalMatrix(matrix) : false; } static void Shader_setLocalMatrix(JNIEnv* env, jobject, SkShader* shader, const SkMatrix* matrix) { if (shader) { if (NULL == matrix) { shader->resetLocalMatrix(); } else { shader->setLocalMatrix(*matrix); } } } /////////////////////////////////////////////////////////////////////////////////////////////// static SkShader* BitmapShader_constructor(JNIEnv* env, jobject, const SkBitmap* bitmap, int tileModeX, int tileModeY) { SkShader* s = SkShader::CreateBitmapShader(*bitmap, (SkShader::TileMode)tileModeX, (SkShader::TileMode)tileModeY); ThrowIAE_IfNull(env, s); return s; } /////////////////////////////////////////////////////////////////////////////////////////////// static SkShader* LinearGradient_create1(JNIEnv* env, jobject, float x0, float y0, float x1, float y1, jintArray colorArray, jfloatArray posArray, int tileMode) { SkPoint pts[2]; pts[0].set(SkFloatToScalar(x0), SkFloatToScalar(y0)); pts[1].set(SkFloatToScalar(x1), SkFloatToScalar(y1)); size_t count = env->GetArrayLength(colorArray); const jint* colorValues = env->GetIntArrayElements(colorArray, NULL); SkAutoSTMalloc<8, SkScalar> storage(posArray ? count : 0); SkScalar* pos = NULL; if (posArray) { AutoJavaFloatArray autoPos(env, posArray, count); const float* posValues = autoPos.ptr(); pos = (SkScalar*)storage.get(); for (size_t i = 0; i < count; i++) pos[i] = SkFloatToScalar(posValues[i]); } SkShader* shader = SkGradientShader::CreateLinear(pts, reinterpret_cast(colorValues), pos, count, static_cast(tileMode)); env->ReleaseIntArrayElements(colorArray, const_cast(colorValues), JNI_ABORT); ThrowIAE_IfNull(env, shader); return shader; } static SkShader* LinearGradient_create2(JNIEnv* env, jobject, float x0, float y0, float x1, float y1, int color0, int color1, int tileMode) { SkPoint pts[2]; pts[0].set(SkFloatToScalar(x0), SkFloatToScalar(y0)); pts[1].set(SkFloatToScalar(x1), SkFloatToScalar(y1)); SkColor colors[2]; colors[0] = color0; colors[1] = color1; SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL, 2, (SkShader::TileMode)tileMode); ThrowIAE_IfNull(env, s); return s; } /////////////////////////////////////////////////////////////////////////////////////////////// static SkShader* RadialGradient_create1(JNIEnv* env, jobject, float x, float y, float radius, jintArray colorArray, jfloatArray posArray, int tileMode) { SkPoint center; center.set(SkFloatToScalar(x), SkFloatToScalar(y)); size_t count = env->GetArrayLength(colorArray); const jint* colorValues = env->GetIntArrayElements(colorArray, NULL); SkAutoSTMalloc<8, SkScalar> storage(posArray ? count : 0); SkScalar* pos = NULL; if (posArray) { AutoJavaFloatArray autoPos(env, posArray, count); const float* posValues = autoPos.ptr(); pos = (SkScalar*)storage.get(); for (size_t i = 0; i < count; i++) pos[i] = SkFloatToScalar(posValues[i]); } SkShader* shader = SkGradientShader::CreateRadial(center, SkFloatToScalar(radius), reinterpret_cast(colorValues), pos, count, static_cast(tileMode)); env->ReleaseIntArrayElements(colorArray, const_cast(colorValues), JNI_ABORT); ThrowIAE_IfNull(env, shader); return shader; } static SkShader* RadialGradient_create2(JNIEnv* env, jobject, float x, float y, float radius, int color0, int color1, int tileMode) { SkPoint center; center.set(SkFloatToScalar(x), SkFloatToScalar(y)); SkColor colors[2]; colors[0] = color0; colors[1] = color1; SkShader* s = SkGradientShader::CreateRadial(center, SkFloatToScalar(radius), colors, NULL, 2, (SkShader::TileMode)tileMode); ThrowIAE_IfNull(env, s); return s; } /////////////////////////////////////////////////////////////////////////////// static SkShader* SweepGradient_create1(JNIEnv* env, jobject, float x, float y, jintArray jcolors, jfloatArray jpositions) { size_t count = env->GetArrayLength(jcolors); const jint* colors = env->GetIntArrayElements(jcolors, NULL); SkAutoSTMalloc<8, SkScalar> storage(jpositions ? count : 0); SkScalar* pos = NULL; if (NULL != jpositions) { AutoJavaFloatArray autoPos(env, jpositions, count); const float* posValues = autoPos.ptr(); pos = (SkScalar*)storage.get(); for (size_t i = 0; i < count; i++) { pos[i] = SkFloatToScalar(posValues[i]); } } SkShader* shader = SkGradientShader::CreateSweep(SkFloatToScalar(x), SkFloatToScalar(y), reinterpret_cast(colors), pos, count); env->ReleaseIntArrayElements(jcolors, const_cast(colors), JNI_ABORT); ThrowIAE_IfNull(env, shader); return shader; } static SkShader* SweepGradient_create2(JNIEnv* env, jobject, float x, float y, int color0, int color1) { SkColor colors[2]; colors[0] = color0; colors[1] = color1; SkShader* s = SkGradientShader::CreateSweep(SkFloatToScalar(x), SkFloatToScalar(y), colors, NULL, 2); ThrowIAE_IfNull(env, s); return s; } /////////////////////////////////////////////////////////////////////////////////////////////// static SkShader* ComposeShader_create1(JNIEnv* env, jobject, SkShader* shaderA, SkShader* shaderB, SkXfermode* mode) { return new SkComposeShader(shaderA, shaderB, mode); } static SkShader* ComposeShader_create2(JNIEnv* env, jobject, SkShader* shaderA, SkShader* shaderB, SkPorterDuff::Mode mode) { SkAutoUnref au(SkPorterDuff::CreateXfermode(mode)); return new SkComposeShader(shaderA, shaderB, (SkXfermode*)au.get()); } /////////////////////////////////////////////////////////////////////////////////////////////// static JNINativeMethod gColorMethods[] = { { "nativeRGBToHSV", "(III[F)V", (void*)Color_RGBToHSV }, { "nativeHSVToColor", "(I[F)I", (void*)Color_HSVToColor } }; static JNINativeMethod gShaderMethods[] = { { "nativeDestructor", "(I)V", (void*)Shader_destructor }, { "nativeGetLocalMatrix", "(II)Z", (void*)Shader_getLocalMatrix }, { "nativeSetLocalMatrix", "(II)V", (void*)Shader_setLocalMatrix } }; static JNINativeMethod gBitmapShaderMethods[] = { { "nativeCreate", "(III)I", (void*)BitmapShader_constructor } }; static JNINativeMethod gLinearGradientMethods[] = { { "nativeCreate1", "(FFFF[I[FI)I", (void*)LinearGradient_create1 }, { "nativeCreate2", "(FFFFIII)I", (void*)LinearGradient_create2 } }; static JNINativeMethod gRadialGradientMethods[] = { {"nativeCreate1", "(FFF[I[FI)I", (void*)RadialGradient_create1 }, {"nativeCreate2", "(FFFIII)I", (void*)RadialGradient_create2 } }; static JNINativeMethod gSweepGradientMethods[] = { {"nativeCreate1", "(FF[I[F)I", (void*)SweepGradient_create1 }, {"nativeCreate2", "(FFII)I", (void*)SweepGradient_create2 } }; static JNINativeMethod gComposeShaderMethods[] = { {"nativeCreate1", "(III)I", (void*)ComposeShader_create1 }, {"nativeCreate2", "(III)I", (void*)ComposeShader_create2 } }; #include #define REG(env, name, array) \ result = android::AndroidRuntime::registerNativeMethods(env, name, array, SK_ARRAY_COUNT(array)); \ if (result < 0) return result int register_android_graphics_Shader(JNIEnv* env); int register_android_graphics_Shader(JNIEnv* env) { int result; REG(env, "android/graphics/Color", gColorMethods); REG(env, "android/graphics/Shader", gShaderMethods); REG(env, "android/graphics/BitmapShader", gBitmapShaderMethods); REG(env, "android/graphics/LinearGradient", gLinearGradientMethods); REG(env, "android/graphics/RadialGradient", gRadialGradientMethods); REG(env, "android/graphics/SweepGradient", gSweepGradientMethods); REG(env, "android/graphics/ComposeShader", gComposeShaderMethods); return result; }