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 ///////////////////////////////////////////////////////////////////////////////
    151 
    152 static JNINativeMethod gTypefaceMethods[] = {
    153     { "nativeCreate",        "(Ljava/lang/String;I)I", (void*)Typeface_create },
    154     { "nativeCreateFromTypeface", "(II)I", (void*)Typeface_createFromTypeface },
    155     { "nativeUnref",              "(I)V",  (void*)Typeface_unref },
    156     { "nativeGetStyle",           "(I)I",  (void*)Typeface_getStyle },
    157     { "nativeCreateFromAsset",    "(Landroid/content/res/AssetManager;Ljava/lang/String;)I",
    158                                            (void*)Typeface_createFromAsset },
    159     { "nativeCreateFromFile",     "(Ljava/lang/String;)I",
    160                                            (void*)Typeface_createFromFile },
    161 };
    162 
    163 int register_android_graphics_Typeface(JNIEnv* env)
    164 {
    165     return android::AndroidRuntime::registerNativeMethods(env,
    166                                                        "android/graphics/Typeface",
    167                                                        gTypefaceMethods,
    168                                                        SK_ARRAY_COUNT(gTypefaceMethods));
    169 }
    170