• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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