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