Typeface.cpp revision 2bb3ea162a58c0f1dddccdbe68b64e02456f11f9
1#include "jni.h"
2#include <android_runtime/AndroidRuntime.h>
3
4#include "GraphicsJNI.h"
5#include <android_runtime/android_util_AssetManager.h>
6#include "SkStream.h"
7#include "SkTypeface.h"
8#include <utils/AssetManager.h>
9
10using namespace android;
11
12class AutoJavaStringToUTF8 {
13public:
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
24private:
25    JNIEnv*     fEnv;
26    jstring     fJStr;
27    const char* fCStr;
28};
29
30static 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
44static SkTypeface* Typeface_createFromTypeface(JNIEnv* env, jobject, SkTypeface* family, int style) {
45    return SkTypeface::CreateFromTypeface(family, (SkTypeface::Style)style);
46}
47
48static void Typeface_unref(JNIEnv* env, jobject obj, SkTypeface* face) {
49    face->unref();
50}
51
52static int Typeface_getStyle(JNIEnv* env, jobject obj, SkTypeface* face) {
53    return face->style();
54}
55
56class AssetStream : public SkStream {
57public:
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        off_t pos = fAsset->seek(0, SEEK_SET);
76        return pos != (off_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            off_t oldOffset = fAsset->seek(0, SEEK_CUR);
92            if (-1 == oldOffset)
93                return 0;
94            off_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
110private:
111    Asset*      fAsset;
112    const void* fMemoryBase;
113};
114
115static 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    return SkTypeface::CreateFromStream(new AssetStream(asset, true));
134}
135
136static SkTypeface* Typeface_createFromFile(JNIEnv* env, jobject, jstring jpath) {
137    NPE_CHECK_RETURN_ZERO(env, jpath);
138
139    AutoJavaStringToUTF8 str(env, jpath);
140
141    return SkTypeface::CreateFromFile(str.c_str());
142}
143
144///////////////////////////////////////////////////////////////////////////////
145
146static JNINativeMethod gTypefaceMethods[] = {
147    { "nativeCreate",        "(Ljava/lang/String;I)I", (void*)Typeface_create },
148    { "nativeCreateFromTypeface", "(II)I", (void*)Typeface_createFromTypeface },
149    { "nativeUnref",              "(I)V",  (void*)Typeface_unref },
150    { "nativeGetStyle",           "(I)I",  (void*)Typeface_getStyle },
151    { "nativeCreateFromAsset",    "(Landroid/content/res/AssetManager;Ljava/lang/String;)I",
152                                           (void*)Typeface_createFromAsset },
153    { "nativeCreateFromFile",     "(Ljava/lang/String;)I",
154                                           (void*)Typeface_createFromFile }
155};
156
157int register_android_graphics_Typeface(JNIEnv* env);
158int register_android_graphics_Typeface(JNIEnv* env)
159{
160    return android::AndroidRuntime::registerNativeMethods(env,
161                                                       "android/graphics/Typeface",
162                                                       gTypefaceMethods,
163                                                       SK_ARRAY_COUNT(gTypefaceMethods));
164}
165