Typeface.cpp revision 89ec829908c8ff405b88b82f9e3a67bb53caefa3
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
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 = NULL;
33
34    if (NULL != name) {
35        AutoJavaStringToUTF8    str(env, name);
36        face = SkTypeface::CreateFromName(str.c_str(), style);
37    }
38
39    // return the default font at the best style if no exact match exists
40    if (NULL == face) {
41        face = SkTypeface::CreateFromName(NULL, style);
42    }
43    return face;
44}
45
46static SkTypeface* Typeface_createFromTypeface(JNIEnv* env, jobject, SkTypeface* family, int style) {
47    return SkTypeface::CreateFromTypeface(family, (SkTypeface::Style)style);
48}
49
50static void Typeface_unref(JNIEnv* env, jobject obj, SkTypeface* face) {
51    SkSafeUnref(face);
52}
53
54static int Typeface_getStyle(JNIEnv* env, jobject obj, SkTypeface* face) {
55    return face->style();
56}
57
58class AssetStream : public SkStream {
59public:
60    AssetStream(Asset* asset, bool hasMemoryBase) : fAsset(asset)
61    {
62        fMemoryBase = hasMemoryBase ? fAsset->getBuffer(false) : NULL;
63    }
64
65    virtual ~AssetStream()
66    {
67        delete fAsset;
68    }
69
70    virtual const void* getMemoryBase()
71    {
72        return fMemoryBase;
73    }
74
75	virtual bool rewind()
76    {
77        off64_t pos = fAsset->seek(0, SEEK_SET);
78        return pos != (off64_t)-1;
79    }
80
81	virtual size_t read(void* buffer, size_t size)
82    {
83        ssize_t amount;
84
85        if (NULL == buffer)
86        {
87            if (0 == size)  // caller is asking us for our total length
88                return fAsset->getLength();
89
90            // asset->seek returns new total offset
91            // we want to return amount that was skipped
92
93            off64_t oldOffset = fAsset->seek(0, SEEK_CUR);
94            if (-1 == oldOffset)
95                return 0;
96            off64_t newOffset = fAsset->seek(size, SEEK_CUR);
97            if (-1 == newOffset)
98                return 0;
99
100            amount = newOffset - oldOffset;
101        }
102        else
103        {
104            amount = fAsset->read(buffer, size);
105        }
106
107        if (amount < 0)
108            amount = 0;
109        return amount;
110    }
111
112private:
113    Asset*      fAsset;
114    const void* fMemoryBase;
115};
116
117static SkTypeface* Typeface_createFromAsset(JNIEnv* env, jobject,
118                                            jobject jassetMgr,
119                                            jstring jpath) {
120
121    NPE_CHECK_RETURN_ZERO(env, jassetMgr);
122    NPE_CHECK_RETURN_ZERO(env, jpath);
123
124    AssetManager* mgr = assetManagerForJavaObject(env, jassetMgr);
125    if (NULL == mgr) {
126        return NULL;
127    }
128
129    AutoJavaStringToUTF8    str(env, jpath);
130    Asset* asset = mgr->open(str.c_str(), Asset::ACCESS_BUFFER);
131    if (NULL == asset) {
132        return NULL;
133    }
134
135    SkStream* stream = new AssetStream(asset, true);
136    SkTypeface* face = SkTypeface::CreateFromStream(stream);
137    // SkTypeFace::CreateFromStream calls ref() on the stream, so we
138    // need to unref it here or it won't be freed later on
139    stream->unref();
140
141    return face;
142}
143
144static SkTypeface* Typeface_createFromFile(JNIEnv* env, jobject, jstring jpath) {
145    NPE_CHECK_RETURN_ZERO(env, jpath);
146
147    AutoJavaStringToUTF8 str(env, jpath);
148
149    return SkTypeface::CreateFromFile(str.c_str());
150}
151
152///////////////////////////////////////////////////////////////////////////////
153
154static JNINativeMethod gTypefaceMethods[] = {
155    { "nativeCreate",        "(Ljava/lang/String;I)I", (void*)Typeface_create },
156    { "nativeCreateFromTypeface", "(II)I", (void*)Typeface_createFromTypeface },
157    { "nativeUnref",              "(I)V",  (void*)Typeface_unref },
158    { "nativeGetStyle",           "(I)I",  (void*)Typeface_getStyle },
159    { "nativeCreateFromAsset",    "(Landroid/content/res/AssetManager;Ljava/lang/String;)I",
160                                           (void*)Typeface_createFromAsset },
161    { "nativeCreateFromFile",     "(Ljava/lang/String;)I",
162                                           (void*)Typeface_createFromFile },
163};
164
165int register_android_graphics_Typeface(JNIEnv* env)
166{
167    return android::AndroidRuntime::registerNativeMethods(env,
168                                                       "android/graphics/Typeface",
169                                                       gTypefaceMethods,
170                                                       SK_ARRAY_COUNT(gTypefaceMethods));
171}
172