Typeface.cpp revision 5e49b497ae2019586937aae0e8159292363728b5
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 "Utils.h"
8#include <android_runtime/android_util_AssetManager.h>
9#include <androidfw/AssetManager.h>
10
11using namespace android;
12
13class AutoJavaStringToUTF8 {
14public:
15    AutoJavaStringToUTF8(JNIEnv* env, jstring str) : fEnv(env), fJStr(str)
16    {
17        fCStr = env->GetStringUTFChars(str, NULL);
18    }
19    ~AutoJavaStringToUTF8()
20    {
21        fEnv->ReleaseStringUTFChars(fJStr, fCStr);
22    }
23    const char* c_str() const { return fCStr; }
24
25private:
26    JNIEnv*     fEnv;
27    jstring     fJStr;
28    const char* fCStr;
29};
30
31static SkTypeface* Typeface_create(JNIEnv* env, jobject, jstring name,
32                                   SkTypeface::Style style) {
33    SkTypeface* face = NULL;
34
35    if (NULL != name) {
36        AutoJavaStringToUTF8    str(env, name);
37        face = SkTypeface::CreateFromName(str.c_str(), style);
38        // Try to find the closest matching font, using the standard heuristic
39        if (NULL == face) {
40            face = SkTypeface::CreateFromName(str.c_str(), (SkTypeface::Style)(style ^ SkTypeface::kItalic));
41        }
42        for (int i = 0; NULL == face && i < 4; i++) {
43            face = SkTypeface::CreateFromName(str.c_str(), (SkTypeface::Style)i);
44        }
45    }
46
47    // return the default font at the best style if no exact match exists
48    if (NULL == face) {
49        face = SkTypeface::CreateFromName(NULL, style);
50    }
51    return face;
52}
53
54static SkTypeface* Typeface_createFromTypeface(JNIEnv* env, jobject, SkTypeface* family, int style) {
55    SkTypeface* face = SkTypeface::CreateFromTypeface(family, (SkTypeface::Style)style);
56    // Try to find the closest matching font, using the standard heuristic
57    if (NULL == face) {
58        face = SkTypeface::CreateFromTypeface(family, (SkTypeface::Style)(style ^ SkTypeface::kItalic));
59    }
60    for (int i = 0; NULL == face && i < 4; i++) {
61        face = SkTypeface::CreateFromTypeface(family, (SkTypeface::Style)i);
62    }
63    if (NULL == face) {
64        face = SkTypeface::CreateFromName(NULL, (SkTypeface::Style)style);
65    }
66    return face;
67}
68
69static void Typeface_unref(JNIEnv* env, jobject obj, SkTypeface* face) {
70    SkSafeUnref(face);
71}
72
73static int Typeface_getStyle(JNIEnv* env, jobject obj, SkTypeface* face) {
74    return face->style();
75}
76
77static SkTypeface* Typeface_createFromAsset(JNIEnv* env, jobject,
78                                            jobject jassetMgr,
79                                            jstring jpath) {
80
81    NPE_CHECK_RETURN_ZERO(env, jassetMgr);
82    NPE_CHECK_RETURN_ZERO(env, jpath);
83
84    AssetManager* mgr = assetManagerForJavaObject(env, jassetMgr);
85    if (NULL == mgr) {
86        return NULL;
87    }
88
89    AutoJavaStringToUTF8    str(env, jpath);
90    Asset* asset = mgr->open(str.c_str(), Asset::ACCESS_BUFFER);
91    if (NULL == asset) {
92        return NULL;
93    }
94
95    SkStream* stream = new AssetStreamAdaptor(asset,
96                                              AssetStreamAdaptor::kYes_OwnAsset,
97                                              AssetStreamAdaptor::kYes_HasMemoryBase);
98    SkTypeface* face = SkTypeface::CreateFromStream(stream);
99    // SkTypeFace::CreateFromStream calls ref() on the stream, so we
100    // need to unref it here or it won't be freed later on
101    stream->unref();
102
103    return face;
104}
105
106static SkTypeface* Typeface_createFromFile(JNIEnv* env, jobject, jstring jpath) {
107    NPE_CHECK_RETURN_ZERO(env, jpath);
108
109    AutoJavaStringToUTF8 str(env, jpath);
110
111    return SkTypeface::CreateFromFile(str.c_str());
112}
113
114///////////////////////////////////////////////////////////////////////////////
115
116static JNINativeMethod gTypefaceMethods[] = {
117    { "nativeCreate",        "(Ljava/lang/String;I)I", (void*)Typeface_create },
118    { "nativeCreateFromTypeface", "(II)I", (void*)Typeface_createFromTypeface },
119    { "nativeUnref",              "(I)V",  (void*)Typeface_unref },
120    { "nativeGetStyle",           "(I)I",  (void*)Typeface_getStyle },
121    { "nativeCreateFromAsset",    "(Landroid/content/res/AssetManager;Ljava/lang/String;)I",
122                                           (void*)Typeface_createFromAsset },
123    { "nativeCreateFromFile",     "(Ljava/lang/String;)I",
124                                           (void*)Typeface_createFromFile },
125};
126
127int register_android_graphics_Typeface(JNIEnv* env)
128{
129    return android::AndroidRuntime::registerNativeMethods(env,
130                                                       "android/graphics/Typeface",
131                                                       gTypefaceMethods,
132                                                       SK_ARRAY_COUNT(gTypefaceMethods));
133}
134