Home | History | Annotate | Download | only in jni
      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