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