1 /*
2 * Copyright 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17
18 #define LOG_TAG "SystemFonts"
19
20 #include <jni.h>
21
22 #include <array>
23 #include <string>
24 #include <vector>
25
26 #include <android/font.h>
27 #include <android/font_matcher.h>
28 #include <android/log.h>
29 #include <android/system_fonts.h>
30
31 namespace {
32
33 class ScopedUtfChars {
34 public:
ScopedUtfChars(JNIEnv * env,jstring s)35 ScopedUtfChars(JNIEnv* env, jstring s) : mEnv(env), mString(s) {
36 if (s == nullptr) {
37 mUtfChars = nullptr;
38 mSize = 0;
39 } else {
40 mUtfChars = mEnv->GetStringUTFChars(mString, nullptr);
41 mSize = mEnv->GetStringUTFLength(mString);
42 }
43 }
44
~ScopedUtfChars()45 ~ScopedUtfChars() {
46 if (mUtfChars) {
47 mEnv->ReleaseStringUTFChars(mString, mUtfChars);
48 }
49 }
50
c_str() const51 const char* c_str() const {
52 return mUtfChars;
53 }
54
size() const55 size_t size() const {
56 return mSize;
57 }
58
59 private:
60 JNIEnv* mEnv;
61 jstring mString;
62 const char* mUtfChars;
63 size_t mSize;
64 };
65
66 class ScopedStringChars {
67 public:
ScopedStringChars(JNIEnv * env,jstring s)68 ScopedStringChars(JNIEnv* env, jstring s) : mEnv(env), mString(s) {
69 if (s == nullptr) {
70 mChars = nullptr;
71 mSize = 0;
72 } else {
73 mChars = mEnv->GetStringChars(mString, NULL);
74 mSize = mEnv->GetStringLength(mString);
75 }
76 }
77
~ScopedStringChars()78 ~ScopedStringChars() {
79 if (mChars != nullptr) {
80 mEnv->ReleaseStringChars(mString, mChars);
81 }
82 }
83
get() const84 const jchar* get() const {
85 return mChars;
86 }
87
size() const88 size_t size() const {
89 return mSize;
90 }
91
92
93 private:
94 JNIEnv* const mEnv;
95 const jstring mString;
96 const jchar* mChars;
97 size_t mSize;
98 };
99
100 struct FontMatcherDeleter {
operator ()__anon6417662e0111::FontMatcherDeleter101 void operator()(AFontMatcher* matcher) { AFontMatcher_destroy(matcher); }
102 };
103
104 using FontMatcherUniquePtr = std::unique_ptr<AFontMatcher, FontMatcherDeleter>;
105
106 class FontMatcher {
107 public:
FontMatcher()108 FontMatcher() : mMatcher(AFontMatcher_create()) {}
109
setStyle(uint16_t weight,bool italic)110 FontMatcher& setStyle(uint16_t weight, bool italic) {
111 AFontMatcher_setStyle(mMatcher.get(), weight, italic);
112 return *this;
113 }
114
setLocales(const std::string & locales)115 FontMatcher& setLocales(const std::string& locales) {
116 AFontMatcher_setLocales(mMatcher.get(), locales.c_str());
117 return *this;
118 }
119
setFamilyVariant(uint32_t familyVariant)120 FontMatcher& setFamilyVariant(uint32_t familyVariant) {
121 AFontMatcher_setFamilyVariant(mMatcher.get(), familyVariant);
122 return *this;
123 }
124
match(const std::string familyName,const std::vector<uint16_t> & text)125 std::pair<AFont*, uint32_t> match(const std::string familyName,
126 const std::vector<uint16_t>& text) {
127 uint32_t runLength;
128 AFont* font = AFontMatcher_match(mMatcher.get(), familyName.c_str(), text.data(),
129 text.size(), &runLength);
130 return std::make_pair(font, runLength);
131 }
132
133 private:
134 FontMatcherUniquePtr mMatcher;
135 };
136
137
nOpenIterator(JNIEnv *,jclass)138 jlong nOpenIterator(JNIEnv*, jclass) {
139 return reinterpret_cast<jlong>(ASystemFontIterator_open());
140 }
141
nCloseIterator(JNIEnv *,jclass,jlong ptr)142 void nCloseIterator(JNIEnv*, jclass, jlong ptr) {
143 ASystemFontIterator_close(reinterpret_cast<ASystemFontIterator*>(ptr));
144 }
145
nGetNext(JNIEnv *,jclass,jlong ptr)146 jlong nGetNext(JNIEnv*, jclass, jlong ptr) {
147 return reinterpret_cast<jlong>(ASystemFontIterator_next(
148 reinterpret_cast<ASystemFontIterator*>(ptr)));
149 }
150
nCloseFont(JNIEnv *,jclass,jlong ptr)151 void nCloseFont(JNIEnv*, jclass, jlong ptr) {
152 return AFont_close(reinterpret_cast<AFont*>(ptr));
153 }
154
nGetFilePath(JNIEnv * env,jclass,jlong ptr)155 jstring nGetFilePath(JNIEnv* env, jclass, jlong ptr) {
156 return env->NewStringUTF(AFont_getFontFilePath(reinterpret_cast<AFont*>(ptr)));
157 }
158
nGetWeight(JNIEnv *,jclass,jlong ptr)159 jint nGetWeight(JNIEnv*, jclass, jlong ptr) {
160 return AFont_getWeight(reinterpret_cast<AFont*>(ptr));
161 }
162
nIsItalic(JNIEnv *,jclass,jlong ptr)163 jboolean nIsItalic(JNIEnv*, jclass, jlong ptr) {
164 return AFont_isItalic(reinterpret_cast<AFont*>(ptr));
165 }
166
nGetLocale(JNIEnv * env,jclass,jlong ptr)167 jstring nGetLocale(JNIEnv* env, jclass, jlong ptr) {
168 return env->NewStringUTF(AFont_getLocale(reinterpret_cast<AFont*>(ptr)));
169 }
170
nGetCollectionIndex(JNIEnv *,jclass,jlong ptr)171 jint nGetCollectionIndex(JNIEnv*, jclass, jlong ptr) {
172 return AFont_getCollectionIndex(reinterpret_cast<AFont*>(ptr));
173 }
174
nGetAxisCount(JNIEnv *,jclass,jlong ptr)175 jint nGetAxisCount(JNIEnv*, jclass, jlong ptr) {
176 return AFont_getAxisCount(reinterpret_cast<AFont*>(ptr));
177 }
178
nGetAxisTag(JNIEnv *,jclass,jlong ptr,jint axisIndex)179 jint nGetAxisTag(JNIEnv*, jclass, jlong ptr, jint axisIndex) {
180 return AFont_getAxisTag(reinterpret_cast<AFont*>(ptr), axisIndex);
181 }
182
nGetAxisValue(JNIEnv *,jclass,jlong ptr,jint axisIndex)183 jfloat nGetAxisValue(JNIEnv*, jclass, jlong ptr, jint axisIndex) {
184 return AFont_getAxisValue(reinterpret_cast<AFont*>(ptr), axisIndex);
185 }
186
nMatchFamilyStyleCharacter(JNIEnv * env,jclass,jstring familyName,jint weight,jboolean italic,jstring langTags,jint familyVariant,jstring text)187 jlong nMatchFamilyStyleCharacter(JNIEnv* env, jclass, jstring familyName, jint weight,
188 jboolean italic, jstring langTags, jint familyVariant,
189 jstring text) {
190 ScopedUtfChars familyNameChars(env, familyName);
191 ScopedUtfChars langTagsChars(env, langTags);
192 ScopedStringChars textChars(env, text);
193 std::vector<uint16_t> utf16(textChars.get(), textChars.get() + textChars.size());
194 return reinterpret_cast<jlong>(
195 FontMatcher()
196 .setStyle(weight, italic)
197 .setLocales(langTagsChars.c_str())
198 .setFamilyVariant(familyVariant)
199 .match(familyNameChars.c_str(), utf16).first);
200 }
201
nMatchFamilyStyleCharacter_runLength(JNIEnv * env,jclass,jstring familyName,jint weight,jboolean italic,jstring langTags,jint familyVariant,jstring text)202 jint nMatchFamilyStyleCharacter_runLength(JNIEnv* env, jclass, jstring familyName, jint weight,
203 jboolean italic, jstring langTags, jint familyVariant,
204 jstring text) {
205 ScopedUtfChars familyNameChars(env, familyName);
206 ScopedUtfChars langTagsChars(env, langTags);
207 ScopedStringChars textChars(env, text);
208 std::vector<uint16_t> utf16(textChars.get(), textChars.get() + textChars.size());
209 return FontMatcher()
210 .setStyle(weight, italic)
211 .setLocales(langTagsChars.c_str())
212 .setFamilyVariant(familyVariant)
213 .match(familyNameChars.c_str(), utf16).second;
214 }
215
216 const std::array<JNINativeMethod, 14> JNI_METHODS = {{
217 { "nOpenIterator", "()J", (void*) nOpenIterator },
218 { "nCloseIterator", "(J)V", (void*) nCloseIterator },
219 { "nNext", "(J)J", (void*) nGetNext },
220 { "nCloseFont", "(J)V", (void*) nCloseFont },
221 { "nGetFilePath", "(J)Ljava/lang/String;", (void*) nGetFilePath },
222 { "nGetWeight", "(J)I", (void*) nGetWeight },
223 { "nIsItalic", "(J)Z", (void*) nIsItalic },
224 { "nGetLocale", "(J)Ljava/lang/String;", (void*) nGetLocale },
225 { "nGetCollectionIndex", "(J)I", (void*) nGetCollectionIndex },
226 { "nGetAxisCount", "(J)I", (void*) nGetAxisCount },
227 { "nGetAxisTag", "(JI)I", (void*) nGetAxisTag },
228 { "nGetAxisValue", "(JI)F", (void*) nGetAxisValue },
229 { "nMatchFamilyStyleCharacter",
230 "(Ljava/lang/String;IZLjava/lang/String;ILjava/lang/String;)J",
231 (void*) nMatchFamilyStyleCharacter },
232 { "nMatchFamilyStyleCharacter_runLength",
233 "(Ljava/lang/String;IZLjava/lang/String;ILjava/lang/String;)I",
234 (void*) nMatchFamilyStyleCharacter_runLength },
235
236 }};
237
238 }
239
register_android_graphics_fonts_cts_SystemFontTest(JNIEnv * env)240 int register_android_graphics_fonts_cts_SystemFontTest(JNIEnv* env) {
241 jclass clazz = env->FindClass("android/graphics/fonts/NativeSystemFontHelper");
242 return env->RegisterNatives(clazz, JNI_METHODS.data(), JNI_METHODS.size());
243 }
244