TypefaceImpl.cpp revision 1a73f732f91e97c9c66b808c245ddda36a10e987
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; 56pthread_once_t gDefaultTypefaceOnce = PTHREAD_ONCE_INIT; 57 58// TODO: this currently builds a font collection from hardcoded paths. 59// It will get replaced by an implementation that parses the XML files. 60static FontCollection *makeFontCollection() { 61 std::vector<FontFamily *>typefaces; 62 const char *fns[] = { 63 "/system/fonts/Roboto-Regular.ttf", 64 "/system/fonts/Roboto-Italic.ttf", 65 "/system/fonts/Roboto-BoldItalic.ttf", 66 "/system/fonts/Roboto-Light.ttf", 67 "/system/fonts/Roboto-Thin.ttf", 68 "/system/fonts/Roboto-Bold.ttf", 69 "/system/fonts/Roboto-ThinItalic.ttf", 70 "/system/fonts/Roboto-LightItalic.ttf" 71 }; 72 73 FontFamily *family = new FontFamily(); 74 for (size_t i = 0; i < sizeof(fns)/sizeof(fns[0]); i++) { 75 const char *fn = fns[i]; 76 SkTypeface *skFace = SkTypeface::CreateFromFile(fn); 77 MinikinFont *font = new MinikinFontSkia(skFace); 78 family->addFont(font); 79 } 80 typefaces.push_back(family); 81 82 family = new FontFamily(); 83 const char *fn = "/system/fonts/NotoSansDevanagari-Regular.ttf"; 84 SkTypeface *skFace = SkTypeface::CreateFromFile(fn); 85 MinikinFont *font = new MinikinFontSkia(skFace); 86 family->addFont(font); 87 typefaces.push_back(family); 88 89 return new FontCollection(typefaces); 90} 91 92static void getDefaultTypefaceOnce() { 93 Layout::init(); 94 gDefaultTypeface = new TypefaceImpl; 95 gDefaultTypeface->fFontCollection = makeFontCollection(); 96 gDefaultTypeface->fStyle = FontStyle(); 97} 98 99TypefaceImpl* TypefaceImpl_resolveDefault(TypefaceImpl* src) { 100 if (src == NULL) { 101 pthread_once(&gDefaultTypefaceOnce, getDefaultTypefaceOnce); 102 return gDefaultTypeface; 103 } else { 104 return src; 105 } 106} 107 108TypefaceImpl* TypefaceImpl_createFromTypeface(TypefaceImpl* src, SkTypeface::Style style) { 109 TypefaceImpl* resolvedFace = TypefaceImpl_resolveDefault(src); 110 TypefaceImpl* result = new TypefaceImpl; 111 if (result != 0) { 112 result->fFontCollection = resolvedFace->fFontCollection; 113 result->fStyle = styleFromSkiaStyle(style); 114 } 115 return result; 116} 117 118static TypefaceImpl* createFromSkTypeface(SkTypeface* typeface) { 119 MinikinFont* minikinFont = new MinikinFontSkia(typeface); 120 std::vector<FontFamily *> typefaces; 121 FontFamily* family = new FontFamily(); 122 family->addFont(minikinFont); 123 typefaces.push_back(family); 124 TypefaceImpl* result = new TypefaceImpl; 125 result->fFontCollection = new FontCollection(typefaces); 126 result->fStyle = FontStyle(); // TODO: improve 127 return result; 128} 129 130TypefaceImpl* TypefaceImpl_createFromName(const char* name, SkTypeface::Style style) { 131 // TODO: should create a font collection with all styles corresponding to 132 // the name 133 SkTypeface* face = SkTypeface::CreateFromName(name, style); 134 return createFromSkTypeface(face); 135} 136 137TypefaceImpl* TypefaceImpl_createFromFile(const char* filename) { 138 SkTypeface* face = SkTypeface::CreateFromFile(filename); 139 return createFromSkTypeface(face); 140} 141 142TypefaceImpl* TypefaceImpl_createFromAsset(Asset* asset) { 143 SkStream* stream = new AssetStreamAdaptor(asset, 144 AssetStreamAdaptor::kYes_OwnAsset, 145 AssetStreamAdaptor::kYes_HasMemoryBase); 146 SkTypeface* face = SkTypeface::CreateFromStream(stream); 147 // SkTypeFace::CreateFromStream calls ref() on the stream, so we 148 // need to unref it here or it won't be freed later on 149 stream->unref(); 150 return createFromSkTypeface(face); 151} 152 153TypefaceImpl* TypefaceImpl_createFromFamilies(const jlong* families, size_t size) { 154 ALOGD("createFromFamilies size=%d", size); 155 std::vector<FontFamily *>familyVec; 156 for (size_t i = 0; i < size; i++) { 157 FontFamily* family = reinterpret_cast<FontFamily*>(families[i]); 158 familyVec.push_back(family); 159 } 160 TypefaceImpl* result = new TypefaceImpl; 161 result->fFontCollection = new FontCollection(familyVec); 162 result->fStyle = FontStyle(); // TODO: improve 163 return result; 164} 165 166void TypefaceImpl_unref(TypefaceImpl* face) { 167 delete face; 168} 169 170int TypefaceImpl_getStyle(TypefaceImpl* face) { 171 FontStyle style = face->fStyle; 172 int result = style.getItalic() ? SkTypeface::kItalic : 0; 173 if (style.getWeight() >= kBoldThreshold) { 174 result |= SkTypeface::kBold; 175 } 176 return result; 177} 178 179#else // USE_MINIKIN 180 181/* Just use SkTypeface instead. */ 182 183typedef SkTypeface TypefaceImpl; 184 185TypefaceImpl* TypefaceImpl_createFromTypeface(TypefaceImpl* src, SkTypeface::Style style) { 186 return SkTypeface::CreateFromTypeface(src, style); 187} 188 189TypefaceImpl* TypefaceImpl_createFromName(const char* name, SkTypeface::Style style) { 190 return SkTypeface::CreateFromName(name, style); 191} 192 193TypefaceImpl* TypefaceImpl_createFromFile(const char* filename) { 194 return SkTypeface::CreateFromFile(filename); 195} 196 197TypefaceImpl* TypefaceImpl_createFromAsset(Asset* asset) { 198 SkStream* stream = new AssetStreamAdaptor(asset, 199 AssetStreamAdaptor::kYes_OwnAsset, 200 AssetStreamAdaptor::kYes_HasMemoryBase); 201 SkTypeface* face = SkTypeface::CreateFromStream(stream); 202 // SkTypeFace::CreateFromStream calls ref() on the stream, so we 203 // need to unref it here or it won't be freed later on 204 stream->unref(); 205 206 return face; 207} 208 209TypefaceImpl* TypefaceImpl_createFromFamilies(const jlong* families, size_t size) { 210 // Should never be called in non-Minikin builds 211 return 0; 212} 213 214void TypefaceImpl_unref(TypefaceImpl* face) { 215 SkSafeUnref(face); 216} 217 218int TypefaceImpl_getStyle(TypefaceImpl* face) { 219 return face->style(); 220} 221 222#endif // USE_MINIKIN 223 224} 225