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