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 /** 18 * This is the implementation of the Typeface object. Historically, it has 19 * just been SkTypeface, but we are migrating to Minikin. For the time 20 * being, that choice is hidden under the USE_MINIKIN compile-time flag. 21 */ 22 23 #define LOG_TAG "TypefaceImpl" 24 25 #include "jni.h" // for jlong, remove when being passed proper type 26 27 #include "SkTypeface.h" 28 29 #include <vector> 30 #include <minikin/FontCollection.h> 31 #include <minikin/FontFamily.h> 32 #include <minikin/Layout.h> 33 #include "SkPaint.h" 34 #include "MinikinSkia.h" 35 36 #include "TypefaceImpl.h" 37 #include "Utils.h" 38 39 namespace android { 40 41 // Resolve the 1..9 weight based on base weight and bold flag 42 static void resolveStyle(TypefaceImpl* typeface) { 43 int weight = typeface->fBaseWeight / 100; 44 if (typeface->fSkiaStyle & SkTypeface::kBold) { 45 weight += 3; 46 } 47 if (weight > 9) { 48 weight = 9; 49 } 50 bool italic = (typeface->fSkiaStyle & SkTypeface::kItalic) != 0; 51 typeface->fStyle = FontStyle(weight, italic); 52 } 53 54 TypefaceImpl* gDefaultTypeface = NULL; 55 pthread_once_t gDefaultTypefaceOnce = PTHREAD_ONCE_INIT; 56 57 // This installs a default typeface (from a hardcoded path) that allows 58 // layouts to work (not crash on null pointer) before the default 59 // typeface is set. 60 // TODO: investigate why layouts are being created before Typeface.java 61 // class initialization. 62 static FontCollection *makeFontCollection() { 63 std::vector<FontFamily *>typefaces; 64 const char *fns[] = { 65 "/system/fonts/Roboto-Regular.ttf", 66 }; 67 68 FontFamily *family = new FontFamily(); 69 for (size_t i = 0; i < sizeof(fns)/sizeof(fns[0]); i++) { 70 const char *fn = fns[i]; 71 ALOGD("makeFontCollection adding %s", fn); 72 SkTypeface *skFace = SkTypeface::CreateFromFile(fn); 73 if (skFace != NULL) { 74 MinikinFont *font = new MinikinFontSkia(skFace); 75 family->addFont(font); 76 font->Unref(); 77 } else { 78 ALOGE("failed to create font %s", fn); 79 } 80 } 81 typefaces.push_back(family); 82 83 FontCollection *result = new FontCollection(typefaces); 84 family->Unref(); 85 return result; 86 } 87 88 static void getDefaultTypefaceOnce() { 89 Layout::init(); 90 if (gDefaultTypeface == NULL) { 91 // We expect the client to set a default typeface, but provide a 92 // default so we can make progress before that happens. 93 gDefaultTypeface = new TypefaceImpl; 94 gDefaultTypeface->fFontCollection = makeFontCollection(); 95 gDefaultTypeface->fSkiaStyle = SkTypeface::kNormal; 96 gDefaultTypeface->fBaseWeight = 400; 97 resolveStyle(gDefaultTypeface); 98 } 99 } 100 101 TypefaceImpl* TypefaceImpl_resolveDefault(TypefaceImpl* src) { 102 if (src == NULL) { 103 pthread_once(&gDefaultTypefaceOnce, getDefaultTypefaceOnce); 104 return gDefaultTypeface; 105 } else { 106 return src; 107 } 108 } 109 110 TypefaceImpl* TypefaceImpl_createFromTypeface(TypefaceImpl* src, SkTypeface::Style style) { 111 TypefaceImpl* resolvedFace = TypefaceImpl_resolveDefault(src); 112 TypefaceImpl* result = new TypefaceImpl; 113 if (result != 0) { 114 result->fFontCollection = resolvedFace->fFontCollection; 115 result->fFontCollection->Ref(); 116 result->fSkiaStyle = style; 117 result->fBaseWeight = resolvedFace->fBaseWeight; 118 resolveStyle(result); 119 } 120 return result; 121 } 122 123 TypefaceImpl* TypefaceImpl_createWeightAlias(TypefaceImpl* src, int weight) { 124 TypefaceImpl* resolvedFace = TypefaceImpl_resolveDefault(src); 125 TypefaceImpl* result = new TypefaceImpl; 126 if (result != 0) { 127 result->fFontCollection = resolvedFace->fFontCollection; 128 result->fFontCollection->Ref(); 129 result->fSkiaStyle = resolvedFace->fSkiaStyle; 130 result->fBaseWeight = weight; 131 resolveStyle(result); 132 } 133 return result; 134 } 135 136 TypefaceImpl* TypefaceImpl_createFromFamilies(const jlong* families, size_t size) { 137 std::vector<FontFamily *>familyVec; 138 for (size_t i = 0; i < size; i++) { 139 FontFamily* family = reinterpret_cast<FontFamily*>(families[i]); 140 familyVec.push_back(family); 141 } 142 TypefaceImpl* result = new TypefaceImpl; 143 result->fFontCollection = new FontCollection(familyVec); 144 if (size == 0) { 145 ALOGW("createFromFamilies creating empty collection"); 146 result->fSkiaStyle = SkTypeface::kNormal; 147 } else { 148 const FontStyle defaultStyle; 149 FontFamily* firstFamily = reinterpret_cast<FontFamily*>(families[0]); 150 MinikinFont* mf = firstFamily->getClosestMatch(defaultStyle).font; 151 if (mf != NULL) { 152 SkTypeface* skTypeface = reinterpret_cast<MinikinFontSkia*>(mf)->GetSkTypeface(); 153 // TODO: probably better to query more precise style from family, will be important 154 // when we open up API to access 100..900 weights 155 result->fSkiaStyle = skTypeface->style(); 156 } else { 157 result->fSkiaStyle = SkTypeface::kNormal; 158 } 159 } 160 result->fBaseWeight = 400; 161 resolveStyle(result); 162 return result; 163 } 164 165 void TypefaceImpl_unref(TypefaceImpl* face) { 166 if (face != NULL) { 167 face->fFontCollection->Unref(); 168 } 169 delete face; 170 } 171 172 int TypefaceImpl_getStyle(TypefaceImpl* face) { 173 return face->fSkiaStyle; 174 } 175 176 void TypefaceImpl_setDefault(TypefaceImpl* face) { 177 gDefaultTypeface = face; 178 } 179 180 } 181