Home | History | Annotate | Download | only in graphics
      1 #include "jni.h"
      2 #include <android_runtime/AndroidRuntime.h>
      3 
      4 #include "GraphicsJNI.h"
      5 #include "SkStream.h"
      6 #include "SkTypeface.h"
      7 #include <android_runtime/android_util_AssetManager.h>
      8 #include <androidfw/AssetManager.h>
      9 
     10 using namespace android;
     11 
     12 class AutoJavaStringToUTF8 {
     13 public:
     14     AutoJavaStringToUTF8(JNIEnv* env, jstring str) : fEnv(env), fJStr(str)
     15     {
     16         fCStr = env->GetStringUTFChars(str, NULL);
     17     }
     18     ~AutoJavaStringToUTF8()
     19     {
     20         fEnv->ReleaseStringUTFChars(fJStr, fCStr);
     21     }
     22     const char* c_str() const { return fCStr; }
     23 
     24 private:
     25     JNIEnv*     fEnv;
     26     jstring     fJStr;
     27     const char* fCStr;
     28 };
     29 
     30 static SkTypeface* Typeface_create(JNIEnv* env, jobject, jstring name,
     31                                    SkTypeface::Style style) {
     32     SkTypeface* face;
     33 
     34     if (NULL == name) {
     35         face = SkTypeface::CreateFromName(NULL, (SkTypeface::Style)style);
     36     }
     37     else {
     38         AutoJavaStringToUTF8    str(env, name);
     39         face = SkTypeface::CreateFromName(str.c_str(), style);
     40     }
     41     return face;
     42 }
     43 
     44 static SkTypeface* Typeface_createFromTypeface(JNIEnv* env, jobject, SkTypeface* family, int style) {
     45     return SkTypeface::CreateFromTypeface(family, (SkTypeface::Style)style);
     46 }
     47 
     48 static void Typeface_unref(JNIEnv* env, jobject obj, SkTypeface* face) {
     49     SkSafeUnref(face);
     50 }
     51 
     52 static int Typeface_getStyle(JNIEnv* env, jobject obj, SkTypeface* face) {
     53     return face->style();
     54 }
     55 
     56 class AssetStream : public SkStream {
     57 public:
     58     AssetStream(Asset* asset, bool hasMemoryBase) : fAsset(asset)
     59     {
     60         fMemoryBase = hasMemoryBase ? fAsset->getBuffer(false) : NULL;
     61     }
     62 
     63     virtual ~AssetStream()
     64     {
     65         delete fAsset;
     66     }
     67 
     68     virtual const void* getMemoryBase()
     69     {
     70         return fMemoryBase;
     71     }
     72 
     73 	virtual bool rewind()
     74     {
     75         off64_t pos = fAsset->seek(0, SEEK_SET);
     76         return pos != (off64_t)-1;
     77     }
     78 
     79 	virtual size_t read(void* buffer, size_t size)
     80     {
     81         ssize_t amount;
     82 
     83         if (NULL == buffer)
     84         {
     85             if (0 == size)  // caller is asking us for our total length
     86                 return fAsset->getLength();
     87 
     88             // asset->seek returns new total offset
     89             // we want to return amount that was skipped
     90 
     91             off64_t oldOffset = fAsset->seek(0, SEEK_CUR);
     92             if (-1 == oldOffset)
     93                 return 0;
     94             off64_t newOffset = fAsset->seek(size, SEEK_CUR);
     95             if (-1 == newOffset)
     96                 return 0;
     97 
     98             amount = newOffset - oldOffset;
     99         }
    100         else
    101         {
    102             amount = fAsset->read(buffer, size);
    103         }
    104 
    105         if (amount < 0)
    106             amount = 0;
    107         return amount;
    108     }
    109 
    110 private:
    111     Asset*      fAsset;
    112     const void* fMemoryBase;
    113 };
    114 
    115 static SkTypeface* Typeface_createFromAsset(JNIEnv* env, jobject,
    116                                             jobject jassetMgr,
    117                                             jstring jpath) {
    118 
    119     NPE_CHECK_RETURN_ZERO(env, jassetMgr);
    120     NPE_CHECK_RETURN_ZERO(env, jpath);
    121 
    122     AssetManager* mgr = assetManagerForJavaObject(env, jassetMgr);
    123     if (NULL == mgr) {
    124         return NULL;
    125     }
    126 
    127     AutoJavaStringToUTF8    str(env, jpath);
    128     Asset* asset = mgr->open(str.c_str(), Asset::ACCESS_BUFFER);
    129     if (NULL == asset) {
    130         return NULL;
    131     }
    132 
    133     SkStream* stream = new AssetStream(asset, true);
    134     SkTypeface* face = SkTypeface::CreateFromStream(stream);
    135     // SkTypeFace::CreateFromStream calls ref() on the stream, so we
    136     // need to unref it here or it won't be freed later on
    137     stream->unref();
    138 
    139     return face;
    140 }
    141 
    142 static SkTypeface* Typeface_createFromFile(JNIEnv* env, jobject, jstring jpath) {
    143     NPE_CHECK_RETURN_ZERO(env, jpath);
    144 
    145     AutoJavaStringToUTF8 str(env, jpath);
    146 
    147     return SkTypeface::CreateFromFile(str.c_str());
    148 }
    149 
    150 #define MIN_GAMMA   (0.1f)
    151 #define MAX_GAMMA   (10.0f)
    152 static float pinGamma(float gamma) {
    153     if (gamma < MIN_GAMMA) {
    154         gamma = MIN_GAMMA;
    155     } else if (gamma > MAX_GAMMA) {
    156         gamma = MAX_GAMMA;
    157     }
    158     return gamma;
    159 }
    160 
    161 extern void skia_set_text_gamma(float, float);
    162 
    163 static void Typeface_setGammaForText(JNIEnv* env, jobject, jfloat blackGamma,
    164                                      jfloat whiteGamma) {
    165     // Comment this out for release builds. This is only used during development
    166     skia_set_text_gamma(pinGamma(blackGamma), pinGamma(whiteGamma));
    167 }
    168 
    169 ///////////////////////////////////////////////////////////////////////////////
    170 
    171 static JNINativeMethod gTypefaceMethods[] = {
    172     { "nativeCreate",        "(Ljava/lang/String;I)I", (void*)Typeface_create },
    173     { "nativeCreateFromTypeface", "(II)I", (void*)Typeface_createFromTypeface },
    174     { "nativeUnref",              "(I)V",  (void*)Typeface_unref },
    175     { "nativeGetStyle",           "(I)I",  (void*)Typeface_getStyle },
    176     { "nativeCreateFromAsset",    "(Landroid/content/res/AssetManager;Ljava/lang/String;)I",
    177                                            (void*)Typeface_createFromAsset },
    178     { "nativeCreateFromFile",     "(Ljava/lang/String;)I",
    179                                            (void*)Typeface_createFromFile },
    180     { "setGammaForText", "(FF)V", (void*)Typeface_setGammaForText },
    181 };
    182 
    183 int register_android_graphics_Typeface(JNIEnv* env)
    184 {
    185     return android::AndroidRuntime::registerNativeMethods(env,
    186                                                        "android/graphics/Typeface",
    187                                                        gTypefaceMethods,
    188                                                        SK_ARRAY_COUNT(gTypefaceMethods));
    189 }
    190