Home | History | Annotate | Download | only in graphics
      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