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: 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 45 ~ScopedUtfChars() { 46 if (mUtfChars) { 47 mEnv->ReleaseStringUTFChars(mString, mUtfChars); 48 } 49 } 50 51 const char* c_str() const { 52 return mUtfChars; 53 } 54 55 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: 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 78 ~ScopedStringChars() { 79 if (mChars != nullptr) { 80 mEnv->ReleaseStringChars(mString, mChars); 81 } 82 } 83 84 const jchar* get() const { 85 return mChars; 86 } 87 88 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 { 101 void operator()(AFontMatcher* matcher) { AFontMatcher_destroy(matcher); } 102 }; 103 104 using FontMatcherUniquePtr = std::unique_ptr<AFontMatcher, FontMatcherDeleter>; 105 106 class FontMatcher { 107 public: 108 FontMatcher() : mMatcher(AFontMatcher_create()) {} 109 110 FontMatcher& setStyle(uint16_t weight, bool italic) { 111 AFontMatcher_setStyle(mMatcher.get(), weight, italic); 112 return *this; 113 } 114 115 FontMatcher& setLocales(const std::string& locales) { 116 AFontMatcher_setLocales(mMatcher.get(), locales.c_str()); 117 return *this; 118 } 119 120 FontMatcher& setFamilyVariant(uint32_t familyVariant) { 121 AFontMatcher_setFamilyVariant(mMatcher.get(), familyVariant); 122 return *this; 123 } 124 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 138 jlong nOpenIterator(JNIEnv*, jclass) { 139 return reinterpret_cast<jlong>(ASystemFontIterator_open()); 140 } 141 142 void nCloseIterator(JNIEnv*, jclass, jlong ptr) { 143 ASystemFontIterator_close(reinterpret_cast<ASystemFontIterator*>(ptr)); 144 } 145 146 jlong nGetNext(JNIEnv*, jclass, jlong ptr) { 147 return reinterpret_cast<jlong>(ASystemFontIterator_next( 148 reinterpret_cast<ASystemFontIterator*>(ptr))); 149 } 150 151 void nCloseFont(JNIEnv*, jclass, jlong ptr) { 152 return AFont_close(reinterpret_cast<AFont*>(ptr)); 153 } 154 155 jstring nGetFilePath(JNIEnv* env, jclass, jlong ptr) { 156 return env->NewStringUTF(AFont_getFontFilePath(reinterpret_cast<AFont*>(ptr))); 157 } 158 159 jint nGetWeight(JNIEnv*, jclass, jlong ptr) { 160 return AFont_getWeight(reinterpret_cast<AFont*>(ptr)); 161 } 162 163 jboolean nIsItalic(JNIEnv*, jclass, jlong ptr) { 164 return AFont_isItalic(reinterpret_cast<AFont*>(ptr)); 165 } 166 167 jstring nGetLocale(JNIEnv* env, jclass, jlong ptr) { 168 return env->NewStringUTF(AFont_getLocale(reinterpret_cast<AFont*>(ptr))); 169 } 170 171 jint nGetCollectionIndex(JNIEnv*, jclass, jlong ptr) { 172 return AFont_getCollectionIndex(reinterpret_cast<AFont*>(ptr)); 173 } 174 175 jint nGetAxisCount(JNIEnv*, jclass, jlong ptr) { 176 return AFont_getAxisCount(reinterpret_cast<AFont*>(ptr)); 177 } 178 179 jint nGetAxisTag(JNIEnv*, jclass, jlong ptr, jint axisIndex) { 180 return AFont_getAxisTag(reinterpret_cast<AFont*>(ptr), axisIndex); 181 } 182 183 jfloat nGetAxisValue(JNIEnv*, jclass, jlong ptr, jint axisIndex) { 184 return AFont_getAxisValue(reinterpret_cast<AFont*>(ptr), axisIndex); 185 } 186 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 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 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