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