1 #include "jni.h"
2 #include <android_runtime/AndroidRuntime.h>
3
4 #include "GraphicsJNI.h"
5 #include <android_runtime/android_util_AssetManager.h>
6 #include "SkStream.h"
7 #include "SkTypeface.h"
8 #include <utils/AssetManager.h>
9
10 using namespace android;
11
12 class AutoJavaStringToUTF8 {
13 public:
AutoJavaStringToUTF8(JNIEnv * env,jstring str)14 AutoJavaStringToUTF8(JNIEnv* env, jstring str) : fEnv(env), fJStr(str)
15 {
16 fCStr = env->GetStringUTFChars(str, NULL);
17 }
~AutoJavaStringToUTF8()18 ~AutoJavaStringToUTF8()
19 {
20 fEnv->ReleaseStringUTFChars(fJStr, fCStr);
21 }
c_str() const22 const char* c_str() const { return fCStr; }
23
24 private:
25 JNIEnv* fEnv;
26 jstring fJStr;
27 const char* fCStr;
28 };
29
Typeface_create(JNIEnv * env,jobject,jstring name,SkTypeface::Style style)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
Typeface_createFromTypeface(JNIEnv * env,jobject,SkTypeface * family,int style)44 static SkTypeface* Typeface_createFromTypeface(JNIEnv* env, jobject, SkTypeface* family, int style) {
45 return SkTypeface::CreateFromTypeface(family, (SkTypeface::Style)style);
46 }
47
Typeface_unref(JNIEnv * env,jobject obj,SkTypeface * face)48 static void Typeface_unref(JNIEnv* env, jobject obj, SkTypeface* face) {
49 face->unref();
50 }
51
Typeface_getStyle(JNIEnv * env,jobject obj,SkTypeface * face)52 static int Typeface_getStyle(JNIEnv* env, jobject obj, SkTypeface* face) {
53 return face->style();
54 }
55
56 class AssetStream : public SkStream {
57 public:
AssetStream(Asset * asset,bool hasMemoryBase)58 AssetStream(Asset* asset, bool hasMemoryBase) : fAsset(asset)
59 {
60 fMemoryBase = hasMemoryBase ? fAsset->getBuffer(false) : NULL;
61 }
62
~AssetStream()63 virtual ~AssetStream()
64 {
65 delete fAsset;
66 }
67
getMemoryBase()68 virtual const void* getMemoryBase()
69 {
70 return fMemoryBase;
71 }
72
rewind()73 virtual bool rewind()
74 {
75 off_t pos = fAsset->seek(0, SEEK_SET);
76 return pos != (off_t)-1;
77 }
78
read(void * buffer,size_t size)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 off_t oldOffset = fAsset->seek(0, SEEK_CUR);
92 if (-1 == oldOffset)
93 return 0;
94 off_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
Typeface_createFromAsset(JNIEnv * env,jobject,jobject jassetMgr,jstring jpath)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 return SkTypeface::CreateFromStream(new AssetStream(asset, true));
134 }
135
Typeface_createFromFile(JNIEnv * env,jobject,jstring jpath)136 static SkTypeface* Typeface_createFromFile(JNIEnv* env, jobject, jstring jpath) {
137 NPE_CHECK_RETURN_ZERO(env, jpath);
138
139 AutoJavaStringToUTF8 str(env, jpath);
140
141 return SkTypeface::CreateFromFile(str.c_str());
142 }
143
144 #define MIN_GAMMA (0.1f)
145 #define MAX_GAMMA (10.0f)
pinGamma(float gamma)146 static float pinGamma(float gamma) {
147 if (gamma < MIN_GAMMA) {
148 gamma = MIN_GAMMA;
149 } else if (gamma > MAX_GAMMA) {
150 gamma = MAX_GAMMA;
151 }
152 return gamma;
153 }
154
155 extern void skia_set_text_gamma(float, float);
156
Typeface_setGammaForText(JNIEnv * env,jobject,jfloat blackGamma,jfloat whiteGamma)157 static void Typeface_setGammaForText(JNIEnv* env, jobject, jfloat blackGamma,
158 jfloat whiteGamma) {
159 // Comment this out for release builds. This is only used during development
160 skia_set_text_gamma(pinGamma(blackGamma), pinGamma(whiteGamma));
161 }
162
163 ///////////////////////////////////////////////////////////////////////////////
164
165 static JNINativeMethod gTypefaceMethods[] = {
166 { "nativeCreate", "(Ljava/lang/String;I)I", (void*)Typeface_create },
167 { "nativeCreateFromTypeface", "(II)I", (void*)Typeface_createFromTypeface },
168 { "nativeUnref", "(I)V", (void*)Typeface_unref },
169 { "nativeGetStyle", "(I)I", (void*)Typeface_getStyle },
170 { "nativeCreateFromAsset", "(Landroid/content/res/AssetManager;Ljava/lang/String;)I",
171 (void*)Typeface_createFromAsset },
172 { "nativeCreateFromFile", "(Ljava/lang/String;)I",
173 (void*)Typeface_createFromFile },
174 { "setGammaForText", "(FF)V", (void*)Typeface_setGammaForText },
175 };
176
177 int register_android_graphics_Typeface(JNIEnv* env);
register_android_graphics_Typeface(JNIEnv * env)178 int register_android_graphics_Typeface(JNIEnv* env)
179 {
180 return android::AndroidRuntime::registerNativeMethods(env,
181 "android/graphics/Typeface",
182 gTypefaceMethods,
183 SK_ARRAY_COUNT(gTypefaceMethods));
184 }
185