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 10 using namespace android; 11 12 class AutoJavaStringToUTF8 { 13 public: 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 24 private: 25 JNIEnv* fEnv; 26 jstring fJStr; 27 const char* fCStr; 28 }; 29 30 static 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 44 static SkTypeface* Typeface_createFromTypeface(JNIEnv* env, jobject, SkTypeface* family, int style) { 45 return SkTypeface::CreateFromTypeface(family, (SkTypeface::Style)style); 46 } 47 48 static void Typeface_unref(JNIEnv* env, jobject obj, SkTypeface* face) { 49 SkSafeUnref(face); 50 } 51 52 static int Typeface_getStyle(JNIEnv* env, jobject obj, SkTypeface* face) { 53 return face->style(); 54 } 55 56 class AssetStream : public SkStream { 57 public: 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 off64_t pos = fAsset->seek(0, SEEK_SET); 76 return pos != (off64_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 off64_t oldOffset = fAsset->seek(0, SEEK_CUR); 92 if (-1 == oldOffset) 93 return 0; 94 off64_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 110 private: 111 Asset* fAsset; 112 const void* fMemoryBase; 113 }; 114 115 static 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 SkStream* stream = new AssetStream(asset, true); 134 SkTypeface* face = SkTypeface::CreateFromStream(stream); 135 // SkTypeFace::CreateFromStream calls ref() on the stream, so we 136 // need to unref it here or it won't be freed later on 137 stream->unref(); 138 139 return face; 140 } 141 142 static SkTypeface* Typeface_createFromFile(JNIEnv* env, jobject, jstring jpath) { 143 NPE_CHECK_RETURN_ZERO(env, jpath); 144 145 AutoJavaStringToUTF8 str(env, jpath); 146 147 return SkTypeface::CreateFromFile(str.c_str()); 148 } 149 150 #define MIN_GAMMA (0.1f) 151 #define MAX_GAMMA (10.0f) 152 static float pinGamma(float gamma) { 153 if (gamma < MIN_GAMMA) { 154 gamma = MIN_GAMMA; 155 } else if (gamma > MAX_GAMMA) { 156 gamma = MAX_GAMMA; 157 } 158 return gamma; 159 } 160 161 extern void skia_set_text_gamma(float, float); 162 163 static void Typeface_setGammaForText(JNIEnv* env, jobject, jfloat blackGamma, 164 jfloat whiteGamma) { 165 // Comment this out for release builds. This is only used during development 166 skia_set_text_gamma(pinGamma(blackGamma), pinGamma(whiteGamma)); 167 } 168 169 /////////////////////////////////////////////////////////////////////////////// 170 171 static JNINativeMethod gTypefaceMethods[] = { 172 { "nativeCreate", "(Ljava/lang/String;I)I", (void*)Typeface_create }, 173 { "nativeCreateFromTypeface", "(II)I", (void*)Typeface_createFromTypeface }, 174 { "nativeUnref", "(I)V", (void*)Typeface_unref }, 175 { "nativeGetStyle", "(I)I", (void*)Typeface_getStyle }, 176 { "nativeCreateFromAsset", "(Landroid/content/res/AssetManager;Ljava/lang/String;)I", 177 (void*)Typeface_createFromAsset }, 178 { "nativeCreateFromFile", "(Ljava/lang/String;)I", 179 (void*)Typeface_createFromFile }, 180 { "setGammaForText", "(FF)V", (void*)Typeface_setGammaForText }, 181 }; 182 183 int register_android_graphics_Typeface(JNIEnv* env) 184 { 185 return android::AndroidRuntime::registerNativeMethods(env, 186 "android/graphics/Typeface", 187 gTypefaceMethods, 188 SK_ARRAY_COUNT(gTypefaceMethods)); 189 } 190