Home | History | Annotate | Download | only in graphics
      1 /*
      2  * Copyright (C) 2013 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 #include "jni.h"
     18 #include "core_jni_helpers.h"
     19 
     20 #include "FontUtils.h"
     21 #include "GraphicsJNI.h"
     22 #include <nativehelper/ScopedPrimitiveArray.h>
     23 #include "SkTypeface.h"
     24 #include <android_runtime/android_util_AssetManager.h>
     25 #include <androidfw/AssetManager.h>
     26 #include <hwui/Typeface.h>
     27 #include <minikin/FontFamily.h>
     28 
     29 using namespace android;
     30 
     31 static inline Typeface* toTypeface(jlong ptr) {
     32     return reinterpret_cast<Typeface*>(ptr);
     33 }
     34 
     35 template<typename Ptr> static inline jlong toJLong(Ptr ptr) {
     36     return reinterpret_cast<jlong>(ptr);
     37 }
     38 
     39 static jlong Typeface_createFromTypeface(JNIEnv* env, jobject, jlong familyHandle, jint style) {
     40     Typeface* family = toTypeface(familyHandle);
     41     Typeface* face = Typeface::createRelative(family, (Typeface::Style)style);
     42     // TODO: the following logic shouldn't be necessary, the above should always succeed.
     43     // Try to find the closest matching font, using the standard heuristic
     44     if (NULL == face) {
     45         face = Typeface::createRelative(family, (Typeface::Style)(style ^ Typeface::kItalic));
     46     }
     47     for (int i = 0; NULL == face && i < 4; i++) {
     48         face = Typeface::createRelative(family, (Typeface::Style)i);
     49     }
     50     return toJLong(face);
     51 }
     52 
     53 static jlong Typeface_createFromTypefaceWithExactStyle(JNIEnv* env, jobject, jlong nativeInstance,
     54         jint weight, jboolean italic) {
     55     return toJLong(Typeface::createAbsolute(toTypeface(nativeInstance), weight, italic));
     56 }
     57 
     58 static jlong Typeface_createFromTypefaceWithVariation(JNIEnv* env, jobject, jlong familyHandle,
     59         jobject listOfAxis) {
     60     std::vector<minikin::FontVariation> variations;
     61     ListHelper list(env, listOfAxis);
     62     for (jint i = 0; i < list.size(); i++) {
     63         jobject axisObject = list.get(i);
     64         if (axisObject == nullptr) {
     65             continue;
     66         }
     67         AxisHelper axis(env, axisObject);
     68         variations.push_back(minikin::FontVariation(axis.getTag(), axis.getStyleValue()));
     69     }
     70     return toJLong(Typeface::createFromTypefaceWithVariation(toTypeface(familyHandle), variations));
     71 }
     72 
     73 static jlong Typeface_createWeightAlias(JNIEnv* env, jobject, jlong familyHandle, jint weight) {
     74     return toJLong(Typeface::createWithDifferentBaseWeight(toTypeface(familyHandle), weight));
     75 }
     76 
     77 static void releaseFunc(jlong ptr) {
     78     delete toTypeface(ptr);
     79 }
     80 
     81 // CriticalNative
     82 static jlong Typeface_getReleaseFunc() {
     83     return toJLong(&releaseFunc);
     84 }
     85 
     86 // CriticalNative
     87 static jint Typeface_getStyle(jlong faceHandle) {
     88     return toTypeface(faceHandle)->fAPIStyle;
     89 }
     90 
     91 // CriticalNative
     92 static jint Typeface_getWeight(jlong faceHandle) {
     93     return toTypeface(faceHandle)->fStyle.weight();
     94 }
     95 
     96 static jlong Typeface_createFromArray(JNIEnv *env, jobject, jlongArray familyArray,
     97         int weight, int italic) {
     98     ScopedLongArrayRO families(env, familyArray);
     99     std::vector<std::shared_ptr<minikin::FontFamily>> familyVec;
    100     familyVec.reserve(families.size());
    101     for (size_t i = 0; i < families.size(); i++) {
    102         FontFamilyWrapper* family = reinterpret_cast<FontFamilyWrapper*>(families[i]);
    103         familyVec.emplace_back(family->family);
    104     }
    105     return toJLong(Typeface::createFromFamilies(std::move(familyVec), weight, italic));
    106 }
    107 
    108 // CriticalNative
    109 static void Typeface_setDefault(jlong faceHandle) {
    110     Typeface::setDefault(toTypeface(faceHandle));
    111 }
    112 
    113 static jobject Typeface_getSupportedAxes(JNIEnv *env, jobject, jlong faceHandle) {
    114     Typeface* face = toTypeface(faceHandle);
    115     const std::unordered_set<minikin::AxisTag>& tagSet = face->fFontCollection->getSupportedTags();
    116     const size_t length = tagSet.size();
    117     if (length == 0) {
    118         return nullptr;
    119     }
    120     std::vector<jint> tagVec(length);
    121     int index = 0;
    122     for (const auto& tag : tagSet) {
    123         tagVec[index++] = tag;
    124     }
    125     std::sort(tagVec.begin(), tagVec.end());
    126     const jintArray result = env->NewIntArray(length);
    127     env->SetIntArrayRegion(result, 0, length, tagVec.data());
    128     return result;
    129 }
    130 
    131 ///////////////////////////////////////////////////////////////////////////////
    132 
    133 static const JNINativeMethod gTypefaceMethods[] = {
    134     { "nativeCreateFromTypeface", "(JI)J", (void*)Typeface_createFromTypeface },
    135     { "nativeCreateFromTypefaceWithExactStyle", "(JIZ)J",
    136             (void*)Typeface_createFromTypefaceWithExactStyle },
    137     { "nativeCreateFromTypefaceWithVariation", "(JLjava/util/List;)J",
    138             (void*)Typeface_createFromTypefaceWithVariation },
    139     { "nativeCreateWeightAlias",  "(JI)J", (void*)Typeface_createWeightAlias },
    140     { "nativeGetReleaseFunc",     "()J",  (void*)Typeface_getReleaseFunc },
    141     { "nativeGetStyle",           "(J)I",  (void*)Typeface_getStyle },
    142     { "nativeGetWeight",      "(J)I",  (void*)Typeface_getWeight },
    143     { "nativeCreateFromArray",    "([JII)J",
    144                                            (void*)Typeface_createFromArray },
    145     { "nativeSetDefault",         "(J)V",   (void*)Typeface_setDefault },
    146     { "nativeGetSupportedAxes",   "(J)[I",  (void*)Typeface_getSupportedAxes },
    147 };
    148 
    149 int register_android_graphics_Typeface(JNIEnv* env)
    150 {
    151     return RegisterMethodsOrDie(env, "android/graphics/Typeface", gTypefaceMethods,
    152                                 NELEM(gTypefaceMethods));
    153 }
    154