TypefaceImpl.cpp revision 1633caef58ebd0bc3b0c5da15dde2fb425b77c43
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 "SkStream.h" 28#include "SkTypeface.h" 29 30#ifdef USE_MINIKIN 31#include <vector> 32#include <minikin/FontCollection.h> 33#include <minikin/FontFamily.h> 34#include <minikin/Layout.h> 35#include "MinikinSkia.h" 36#endif 37 38#include "TypefaceImpl.h" 39#include "Utils.h" 40 41namespace android { 42 43#ifdef USE_MINIKIN 44 45// Any weight greater than or equal to this is considered "bold" for 46// legacy API. 47static const int kBoldThreshold = 6; 48 49static FontStyle styleFromSkiaStyle(SkTypeface::Style skiaStyle) { 50 int weight = (skiaStyle & SkTypeface::kBold) != 0 ? 7 : 4; 51 bool italic = (skiaStyle & SkTypeface::kItalic) != 0; 52 return FontStyle(weight, italic); 53} 54 55TypefaceImpl* gDefaultTypeface = NULL; 56pthread_once_t gDefaultTypefaceOnce = PTHREAD_ONCE_INIT; 57 58// This installs a default typeface (from a hardcoded path) that allows 59// layouts to work (not crash on null pointer) before the default 60// typeface is set. 61// TODO: investigate why layouts are being created before Typeface.java 62// class initialization. 63static FontCollection *makeFontCollection() { 64 std::vector<FontFamily *>typefaces; 65 const char *fns[] = { 66 "/system/fonts/Roboto-Regular.ttf", 67 }; 68 69 FontFamily *family = new FontFamily(); 70 for (size_t i = 0; i < sizeof(fns)/sizeof(fns[0]); i++) { 71 const char *fn = fns[i]; 72 ALOGD("makeFontCollection adding %s", fn); 73 SkTypeface *skFace = SkTypeface::CreateFromFile(fn); 74 if (skFace != NULL) { 75 MinikinFont *font = new MinikinFontSkia(skFace); 76 family->addFont(font); 77 font->Unref(); 78 } else { 79 ALOGE("failed to create font %s", fn); 80 } 81 } 82 typefaces.push_back(family); 83 84 FontCollection *result = new FontCollection(typefaces); 85 family->Unref(); 86 return result; 87} 88 89static void getDefaultTypefaceOnce() { 90 Layout::init(); 91 if (gDefaultTypeface == NULL) { 92 // We expect the client to set a default typeface, but provide a 93 // default so we can make progress before that happens. 94 gDefaultTypeface = new TypefaceImpl; 95 gDefaultTypeface->fFontCollection = makeFontCollection(); 96 gDefaultTypeface->fStyle = FontStyle(); 97 } 98} 99 100TypefaceImpl* TypefaceImpl_resolveDefault(TypefaceImpl* src) { 101 if (src == NULL) { 102 pthread_once(&gDefaultTypefaceOnce, getDefaultTypefaceOnce); 103 return gDefaultTypeface; 104 } else { 105 return src; 106 } 107} 108 109TypefaceImpl* TypefaceImpl_createFromTypeface(TypefaceImpl* src, SkTypeface::Style style) { 110 TypefaceImpl* resolvedFace = TypefaceImpl_resolveDefault(src); 111 TypefaceImpl* result = new TypefaceImpl; 112 if (result != 0) { 113 result->fFontCollection = resolvedFace->fFontCollection; 114 result->fFontCollection->Ref(); 115 result->fStyle = styleFromSkiaStyle(style); 116 } 117 return result; 118} 119 120static TypefaceImpl* createFromSkTypeface(SkTypeface* typeface) { 121 if (typeface == NULL) { 122 return NULL; 123 } 124 MinikinFont* minikinFont = new MinikinFontSkia(typeface); 125 std::vector<FontFamily *> typefaces; 126 FontFamily* family = new FontFamily(); 127 family->addFont(minikinFont); 128 minikinFont->Unref(); 129 typefaces.push_back(family); 130 TypefaceImpl* result = new TypefaceImpl; 131 result->fFontCollection = new FontCollection(typefaces); 132 family->Unref(); 133 result->fStyle = FontStyle(); // TODO: improve 134 return result; 135} 136 137// Delete when removing USE_MINIKIN ifdef 138TypefaceImpl* TypefaceImpl_createFromName(const char* name, SkTypeface::Style style) { 139 SkTypeface* face = SkTypeface::CreateFromName(name, style); 140 return createFromSkTypeface(face); 141} 142 143// Delete when removing USE_MINIKIN ifdef 144TypefaceImpl* TypefaceImpl_createFromFile(const char* filename) { 145 SkTypeface* face = SkTypeface::CreateFromFile(filename); 146 return createFromSkTypeface(face); 147} 148 149// Delete when removing USE_MINIKIN ifdef 150TypefaceImpl* TypefaceImpl_createFromAsset(Asset* asset) { 151 SkStream* stream = new AssetStreamAdaptor(asset, 152 AssetStreamAdaptor::kYes_OwnAsset, 153 AssetStreamAdaptor::kYes_HasMemoryBase); 154 SkTypeface* face = SkTypeface::CreateFromStream(stream); 155 // SkTypeFace::CreateFromStream calls ref() on the stream, so we 156 // need to unref it here or it won't be freed later on 157 stream->unref(); 158 return createFromSkTypeface(face); 159} 160 161TypefaceImpl* TypefaceImpl_createFromFamilies(const jlong* families, size_t size) { 162 std::vector<FontFamily *>familyVec; 163 for (size_t i = 0; i < size; i++) { 164 FontFamily* family = reinterpret_cast<FontFamily*>(families[i]); 165 familyVec.push_back(family); 166 } 167 TypefaceImpl* result = new TypefaceImpl; 168 result->fFontCollection = new FontCollection(familyVec); 169 if (size == 0) { 170 ALOGW("createFromFamilies creating empty collection"); 171 result->fStyle = FontStyle(); 172 } else { 173 const FontStyle defaultStyle; 174 FontFamily* firstFamily = reinterpret_cast<FontFamily*>(families[0]); 175 MinikinFont* mf = firstFamily->getClosestMatch(defaultStyle); 176 SkTypeface* skTypeface = reinterpret_cast<MinikinFontSkia*>(mf)->GetSkTypeface(); 177 // TODO: probably better to query more precise style from family, will be important 178 // when we open up API to access 100..900 weights 179 result->fStyle = styleFromSkiaStyle(skTypeface->style()); 180 } 181 return result; 182} 183 184void TypefaceImpl_unref(TypefaceImpl* face) { 185 if (face != NULL) { 186 face->fFontCollection->Unref(); 187 } 188 delete face; 189} 190 191int TypefaceImpl_getStyle(TypefaceImpl* face) { 192 FontStyle style = face->fStyle; 193 int result = style.getItalic() ? SkTypeface::kItalic : 0; 194 if (style.getWeight() >= kBoldThreshold) { 195 result |= SkTypeface::kBold; 196 } 197 return result; 198} 199 200void TypefaceImpl_setDefault(TypefaceImpl* face) { 201 gDefaultTypeface = face; 202} 203 204#else // USE_MINIKIN 205 206/* Just use SkTypeface instead. */ 207 208typedef SkTypeface TypefaceImpl; 209 210TypefaceImpl* TypefaceImpl_createFromTypeface(TypefaceImpl* src, SkTypeface::Style style) { 211 return SkTypeface::CreateFromTypeface(src, style); 212} 213 214TypefaceImpl* TypefaceImpl_createFromName(const char* name, SkTypeface::Style style) { 215 return SkTypeface::CreateFromName(name, style); 216} 217 218TypefaceImpl* TypefaceImpl_createFromFile(const char* filename) { 219 return SkTypeface::CreateFromFile(filename); 220} 221 222TypefaceImpl* TypefaceImpl_createFromAsset(Asset* asset) { 223 SkStream* stream = new AssetStreamAdaptor(asset, 224 AssetStreamAdaptor::kYes_OwnAsset, 225 AssetStreamAdaptor::kYes_HasMemoryBase); 226 SkTypeface* face = SkTypeface::CreateFromStream(stream); 227 // SkTypeFace::CreateFromStream calls ref() on the stream, so we 228 // need to unref it here or it won't be freed later on 229 stream->unref(); 230 231 return face; 232} 233 234TypefaceImpl* TypefaceImpl_createFromFamilies(const jlong* families, size_t size) { 235 // Should never be called in non-Minikin builds 236 return 0; 237} 238 239void TypefaceImpl_unref(TypefaceImpl* face) { 240 SkSafeUnref(face); 241} 242 243int TypefaceImpl_getStyle(TypefaceImpl* face) { 244 return face->style(); 245} 246 247void TypefaceImpl_setDefault(TypefaceImpl* face) { 248} 249 250#endif // USE_MINIKIN 251 252} 253