TypefaceImpl.cpp revision b9c58ab617c257dbece105167b21e94faad67320
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#include "SkStream.h" 24#include "SkTypeface.h" 25 26#ifdef USE_MINIKIN 27#include <vector> 28#include <minikin/FontCollection.h> 29#include <minikin/FontFamily.h> 30#include <minikin/Layout.h> 31#include "MinikinSkia.h" 32#endif 33 34#include "TypefaceImpl.h" 35#include "Utils.h" 36 37namespace android { 38 39#ifdef USE_MINIKIN 40 41// Any weight greater than or equal to this is considered "bold" for 42// legacy API. 43static const int kBoldThreshold = 6; 44 45static FontStyle styleFromSkiaStyle(SkTypeface::Style skiaStyle) { 46 int weight = (skiaStyle & SkTypeface::kBold) != 0 ? 7 : 4; 47 bool italic = (skiaStyle & SkTypeface::kItalic) != 0; 48 return FontStyle(weight, italic); 49} 50 51TypefaceImpl* gDefaultTypeface; 52pthread_once_t gDefaultTypefaceOnce = PTHREAD_ONCE_INIT; 53 54// TODO: this currently builds a font collection from hardcoded paths. 55// It will get replaced by an implementation that parses the XML files. 56static FontCollection *makeFontCollection() { 57 std::vector<FontFamily *>typefaces; 58 const char *fns[] = { 59 "/system/fonts/Roboto-Regular.ttf", 60 "/system/fonts/Roboto-Italic.ttf", 61 "/system/fonts/Roboto-BoldItalic.ttf", 62 "/system/fonts/Roboto-Light.ttf", 63 "/system/fonts/Roboto-Thin.ttf", 64 "/system/fonts/Roboto-Bold.ttf", 65 "/system/fonts/Roboto-ThinItalic.ttf", 66 "/system/fonts/Roboto-LightItalic.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 SkTypeface *skFace = SkTypeface::CreateFromFile(fn); 73 MinikinFont *font = new MinikinFontSkia(skFace); 74 family->addFont(font); 75 } 76 typefaces.push_back(family); 77 78 family = new FontFamily(); 79 const char *fn = "/system/fonts/NotoSansDevanagari-Regular.ttf"; 80 SkTypeface *skFace = SkTypeface::CreateFromFile(fn); 81 MinikinFont *font = new MinikinFontSkia(skFace); 82 family->addFont(font); 83 typefaces.push_back(family); 84 85 return new FontCollection(typefaces); 86} 87 88static void getDefaultTypefaceOnce() { 89 Layout::init(); 90 gDefaultTypeface = new TypefaceImpl; 91 gDefaultTypeface->fFontCollection = makeFontCollection(); 92 gDefaultTypeface->fStyle = FontStyle(); 93} 94 95TypefaceImpl* TypefaceImpl_resolveDefault(TypefaceImpl* src) { 96 if (src == NULL) { 97 pthread_once(&gDefaultTypefaceOnce, getDefaultTypefaceOnce); 98 return gDefaultTypeface; 99 } else { 100 return src; 101 } 102} 103 104TypefaceImpl* TypefaceImpl_createFromTypeface(TypefaceImpl* src, SkTypeface::Style style) { 105 TypefaceImpl* resolvedFace = TypefaceImpl_resolveDefault(src); 106 TypefaceImpl* result = new TypefaceImpl; 107 if (result != 0) { 108 result->fFontCollection = resolvedFace->fFontCollection; 109 result->fStyle = styleFromSkiaStyle(style); 110 } 111 return result; 112} 113 114static TypefaceImpl* createFromSkTypeface(SkTypeface* typeface) { 115 MinikinFont* minikinFont = new MinikinFontSkia(typeface); 116 std::vector<FontFamily *> typefaces; 117 FontFamily* family = new FontFamily(); 118 family->addFont(minikinFont); 119 typefaces.push_back(family); 120 TypefaceImpl* result = new TypefaceImpl; 121 result->fFontCollection = new FontCollection(typefaces); 122 result->fStyle = FontStyle(); // TODO: improve 123 return result; 124} 125 126TypefaceImpl* TypefaceImpl_createFromName(const char* name, SkTypeface::Style style) { 127 // TODO: should create a font collection with all styles corresponding to 128 // the name 129 SkTypeface* face = SkTypeface::CreateFromName(name, style); 130 return createFromSkTypeface(face); 131} 132 133TypefaceImpl* TypefaceImpl_createFromFile(const char* filename) { 134 SkTypeface* face = SkTypeface::CreateFromFile(filename); 135 return createFromSkTypeface(face); 136} 137 138TypefaceImpl* TypefaceImpl_createFromAsset(Asset* asset) { 139 SkStream* stream = new AssetStreamAdaptor(asset, 140 AssetStreamAdaptor::kYes_OwnAsset, 141 AssetStreamAdaptor::kYes_HasMemoryBase); 142 SkTypeface* face = SkTypeface::CreateFromStream(stream); 143 // SkTypeFace::CreateFromStream calls ref() on the stream, so we 144 // need to unref it here or it won't be freed later on 145 stream->unref(); 146 return createFromSkTypeface(face); 147} 148 149void TypefaceImpl_unref(TypefaceImpl* face) { 150 delete face; 151} 152 153int TypefaceImpl_getStyle(TypefaceImpl* face) { 154 FontStyle style = face->fStyle; 155 int result = style.getItalic() ? SkTypeface::kItalic : 0; 156 if (style.getWeight() >= kBoldThreshold) { 157 result |= SkTypeface::kBold; 158 } 159 return result; 160} 161 162#else // USE_MINIKIN 163 164/* Just use SkTypeface instead. */ 165 166typedef SkTypeface TypefaceImpl; 167 168TypefaceImpl* TypefaceImpl_createFromTypeface(TypefaceImpl* src, SkTypeface::Style style) { 169 return SkTypeface::CreateFromTypeface(src, style); 170} 171 172TypefaceImpl* TypefaceImpl_createFromName(const char* name, SkTypeface::Style style) { 173 return SkTypeface::CreateFromName(name, style); 174} 175 176TypefaceImpl* TypefaceImpl_createFromFile(const char* filename) { 177 return SkTypeface::CreateFromFile(filename); 178} 179 180TypefaceImpl* TypefaceImpl_createFromAsset(Asset* asset) { 181 SkStream* stream = new AssetStreamAdaptor(asset, 182 AssetStreamAdaptor::kYes_OwnAsset, 183 AssetStreamAdaptor::kYes_HasMemoryBase); 184 SkTypeface* face = SkTypeface::CreateFromStream(stream); 185 // SkTypeFace::CreateFromStream calls ref() on the stream, so we 186 // need to unref it here or it won't be freed later on 187 stream->unref(); 188 189 return face; 190} 191 192void TypefaceImpl_unref(TypefaceImpl* face) { 193 SkSafeUnref(face); 194} 195 196int TypefaceImpl_getStyle(TypefaceImpl* face) { 197 return face->style(); 198} 199 200#endif // USE_MINIKIN 201 202} 203