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