TypefaceImpl.cpp revision b9c58ab617c257dbece105167b21e94faad67320
1a033630e805c407080221e20b236b6054f324670Raph Levien/* 2a033630e805c407080221e20b236b6054f324670Raph Levien * Copyright (C) 2013 The Android Open Source Project 3a033630e805c407080221e20b236b6054f324670Raph Levien * 4a033630e805c407080221e20b236b6054f324670Raph Levien * Licensed under the Apache License, Version 2.0 (the "License"); 5a033630e805c407080221e20b236b6054f324670Raph Levien * you may not use this file except in compliance with the License. 6a033630e805c407080221e20b236b6054f324670Raph Levien * You may obtain a copy of the License at 7a033630e805c407080221e20b236b6054f324670Raph Levien * 8a033630e805c407080221e20b236b6054f324670Raph Levien * http://www.apache.org/licenses/LICENSE-2.0 9a033630e805c407080221e20b236b6054f324670Raph Levien * 10a033630e805c407080221e20b236b6054f324670Raph Levien * Unless required by applicable law or agreed to in writing, software 11a033630e805c407080221e20b236b6054f324670Raph Levien * distributed under the License is distributed on an "AS IS" BASIS, 12a033630e805c407080221e20b236b6054f324670Raph Levien * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a033630e805c407080221e20b236b6054f324670Raph Levien * See the License for the specific language governing permissions and 14a033630e805c407080221e20b236b6054f324670Raph Levien * limitations under the License. 15a033630e805c407080221e20b236b6054f324670Raph Levien */ 16a033630e805c407080221e20b236b6054f324670Raph Levien 17a033630e805c407080221e20b236b6054f324670Raph Levien/** 18a033630e805c407080221e20b236b6054f324670Raph Levien * This is the implementation of the Typeface object. Historically, it has 19a033630e805c407080221e20b236b6054f324670Raph Levien * just been SkTypeface, but we are migrating to Minikin. For the time 20a033630e805c407080221e20b236b6054f324670Raph Levien * being, that choice is hidden under the USE_MINIKIN compile-time flag. 21a033630e805c407080221e20b236b6054f324670Raph Levien */ 22a033630e805c407080221e20b236b6054f324670Raph Levien 23a033630e805c407080221e20b236b6054f324670Raph Levien#include "SkStream.h" 24a033630e805c407080221e20b236b6054f324670Raph Levien#include "SkTypeface.h" 25a033630e805c407080221e20b236b6054f324670Raph Levien 26a033630e805c407080221e20b236b6054f324670Raph Levien#ifdef USE_MINIKIN 27a033630e805c407080221e20b236b6054f324670Raph Levien#include <vector> 28a033630e805c407080221e20b236b6054f324670Raph Levien#include <minikin/FontCollection.h> 29a033630e805c407080221e20b236b6054f324670Raph Levien#include <minikin/FontFamily.h> 30a033630e805c407080221e20b236b6054f324670Raph Levien#include <minikin/Layout.h> 31a033630e805c407080221e20b236b6054f324670Raph Levien#include "MinikinSkia.h" 32a033630e805c407080221e20b236b6054f324670Raph Levien#endif 33a033630e805c407080221e20b236b6054f324670Raph Levien 34a033630e805c407080221e20b236b6054f324670Raph Levien#include "TypefaceImpl.h" 35b9c58ab617c257dbece105167b21e94faad67320Leon Scroggins III#include "Utils.h" 36a033630e805c407080221e20b236b6054f324670Raph Levien 37a033630e805c407080221e20b236b6054f324670Raph Leviennamespace android { 38a033630e805c407080221e20b236b6054f324670Raph Levien 39a033630e805c407080221e20b236b6054f324670Raph Levien#ifdef USE_MINIKIN 40a033630e805c407080221e20b236b6054f324670Raph Levien 41a033630e805c407080221e20b236b6054f324670Raph Levien// Any weight greater than or equal to this is considered "bold" for 42a033630e805c407080221e20b236b6054f324670Raph Levien// legacy API. 43a033630e805c407080221e20b236b6054f324670Raph Levienstatic const int kBoldThreshold = 6; 44a033630e805c407080221e20b236b6054f324670Raph Levien 45a033630e805c407080221e20b236b6054f324670Raph Levienstatic FontStyle styleFromSkiaStyle(SkTypeface::Style skiaStyle) { 46a033630e805c407080221e20b236b6054f324670Raph Levien int weight = (skiaStyle & SkTypeface::kBold) != 0 ? 7 : 4; 47a033630e805c407080221e20b236b6054f324670Raph Levien bool italic = (skiaStyle & SkTypeface::kItalic) != 0; 48a033630e805c407080221e20b236b6054f324670Raph Levien return FontStyle(weight, italic); 49a033630e805c407080221e20b236b6054f324670Raph Levien} 50a033630e805c407080221e20b236b6054f324670Raph Levien 51a033630e805c407080221e20b236b6054f324670Raph LevienTypefaceImpl* gDefaultTypeface; 52a033630e805c407080221e20b236b6054f324670Raph Levienpthread_once_t gDefaultTypefaceOnce = PTHREAD_ONCE_INIT; 53a033630e805c407080221e20b236b6054f324670Raph Levien 54a033630e805c407080221e20b236b6054f324670Raph Levien// TODO: this currently builds a font collection from hardcoded paths. 55a033630e805c407080221e20b236b6054f324670Raph Levien// It will get replaced by an implementation that parses the XML files. 56a033630e805c407080221e20b236b6054f324670Raph Levienstatic FontCollection *makeFontCollection() { 57a033630e805c407080221e20b236b6054f324670Raph Levien std::vector<FontFamily *>typefaces; 58a033630e805c407080221e20b236b6054f324670Raph Levien const char *fns[] = { 59a033630e805c407080221e20b236b6054f324670Raph Levien "/system/fonts/Roboto-Regular.ttf", 60a033630e805c407080221e20b236b6054f324670Raph Levien "/system/fonts/Roboto-Italic.ttf", 61a033630e805c407080221e20b236b6054f324670Raph Levien "/system/fonts/Roboto-BoldItalic.ttf", 62a033630e805c407080221e20b236b6054f324670Raph Levien "/system/fonts/Roboto-Light.ttf", 63a033630e805c407080221e20b236b6054f324670Raph Levien "/system/fonts/Roboto-Thin.ttf", 64a033630e805c407080221e20b236b6054f324670Raph Levien "/system/fonts/Roboto-Bold.ttf", 65a033630e805c407080221e20b236b6054f324670Raph Levien "/system/fonts/Roboto-ThinItalic.ttf", 66a033630e805c407080221e20b236b6054f324670Raph Levien "/system/fonts/Roboto-LightItalic.ttf" 67a033630e805c407080221e20b236b6054f324670Raph Levien }; 68a033630e805c407080221e20b236b6054f324670Raph Levien 69a033630e805c407080221e20b236b6054f324670Raph Levien FontFamily *family = new FontFamily(); 70a033630e805c407080221e20b236b6054f324670Raph Levien for (size_t i = 0; i < sizeof(fns)/sizeof(fns[0]); i++) { 71a033630e805c407080221e20b236b6054f324670Raph Levien const char *fn = fns[i]; 72a033630e805c407080221e20b236b6054f324670Raph Levien SkTypeface *skFace = SkTypeface::CreateFromFile(fn); 73a033630e805c407080221e20b236b6054f324670Raph Levien MinikinFont *font = new MinikinFontSkia(skFace); 74a033630e805c407080221e20b236b6054f324670Raph Levien family->addFont(font); 75a033630e805c407080221e20b236b6054f324670Raph Levien } 76a033630e805c407080221e20b236b6054f324670Raph Levien typefaces.push_back(family); 77a033630e805c407080221e20b236b6054f324670Raph Levien 78a033630e805c407080221e20b236b6054f324670Raph Levien family = new FontFamily(); 79a033630e805c407080221e20b236b6054f324670Raph Levien const char *fn = "/system/fonts/NotoSansDevanagari-Regular.ttf"; 80a033630e805c407080221e20b236b6054f324670Raph Levien SkTypeface *skFace = SkTypeface::CreateFromFile(fn); 81a033630e805c407080221e20b236b6054f324670Raph Levien MinikinFont *font = new MinikinFontSkia(skFace); 82a033630e805c407080221e20b236b6054f324670Raph Levien family->addFont(font); 83a033630e805c407080221e20b236b6054f324670Raph Levien typefaces.push_back(family); 84a033630e805c407080221e20b236b6054f324670Raph Levien 85a033630e805c407080221e20b236b6054f324670Raph Levien return new FontCollection(typefaces); 86a033630e805c407080221e20b236b6054f324670Raph Levien} 87a033630e805c407080221e20b236b6054f324670Raph Levien 88a033630e805c407080221e20b236b6054f324670Raph Levienstatic void getDefaultTypefaceOnce() { 89a033630e805c407080221e20b236b6054f324670Raph Levien Layout::init(); 90a033630e805c407080221e20b236b6054f324670Raph Levien gDefaultTypeface = new TypefaceImpl; 91a033630e805c407080221e20b236b6054f324670Raph Levien gDefaultTypeface->fFontCollection = makeFontCollection(); 92a033630e805c407080221e20b236b6054f324670Raph Levien gDefaultTypeface->fStyle = FontStyle(); 93a033630e805c407080221e20b236b6054f324670Raph Levien} 94a033630e805c407080221e20b236b6054f324670Raph Levien 95a033630e805c407080221e20b236b6054f324670Raph LevienTypefaceImpl* TypefaceImpl_resolveDefault(TypefaceImpl* src) { 96a033630e805c407080221e20b236b6054f324670Raph Levien if (src == NULL) { 97a033630e805c407080221e20b236b6054f324670Raph Levien pthread_once(&gDefaultTypefaceOnce, getDefaultTypefaceOnce); 98a033630e805c407080221e20b236b6054f324670Raph Levien return gDefaultTypeface; 99a033630e805c407080221e20b236b6054f324670Raph Levien } else { 100a033630e805c407080221e20b236b6054f324670Raph Levien return src; 101a033630e805c407080221e20b236b6054f324670Raph Levien } 102a033630e805c407080221e20b236b6054f324670Raph Levien} 103a033630e805c407080221e20b236b6054f324670Raph Levien 104a033630e805c407080221e20b236b6054f324670Raph LevienTypefaceImpl* TypefaceImpl_createFromTypeface(TypefaceImpl* src, SkTypeface::Style style) { 105a033630e805c407080221e20b236b6054f324670Raph Levien TypefaceImpl* resolvedFace = TypefaceImpl_resolveDefault(src); 106a033630e805c407080221e20b236b6054f324670Raph Levien TypefaceImpl* result = new TypefaceImpl; 107a033630e805c407080221e20b236b6054f324670Raph Levien if (result != 0) { 108a033630e805c407080221e20b236b6054f324670Raph Levien result->fFontCollection = resolvedFace->fFontCollection; 109a033630e805c407080221e20b236b6054f324670Raph Levien result->fStyle = styleFromSkiaStyle(style); 110a033630e805c407080221e20b236b6054f324670Raph Levien } 111a033630e805c407080221e20b236b6054f324670Raph Levien return result; 112a033630e805c407080221e20b236b6054f324670Raph Levien} 113a033630e805c407080221e20b236b6054f324670Raph Levien 114a033630e805c407080221e20b236b6054f324670Raph Levienstatic TypefaceImpl* createFromSkTypeface(SkTypeface* typeface) { 115a033630e805c407080221e20b236b6054f324670Raph Levien MinikinFont* minikinFont = new MinikinFontSkia(typeface); 116a033630e805c407080221e20b236b6054f324670Raph Levien std::vector<FontFamily *> typefaces; 117a033630e805c407080221e20b236b6054f324670Raph Levien FontFamily* family = new FontFamily(); 118a033630e805c407080221e20b236b6054f324670Raph Levien family->addFont(minikinFont); 119a033630e805c407080221e20b236b6054f324670Raph Levien typefaces.push_back(family); 120a033630e805c407080221e20b236b6054f324670Raph Levien TypefaceImpl* result = new TypefaceImpl; 121a033630e805c407080221e20b236b6054f324670Raph Levien result->fFontCollection = new FontCollection(typefaces); 122a033630e805c407080221e20b236b6054f324670Raph Levien result->fStyle = FontStyle(); // TODO: improve 123a033630e805c407080221e20b236b6054f324670Raph Levien return result; 124a033630e805c407080221e20b236b6054f324670Raph Levien} 125a033630e805c407080221e20b236b6054f324670Raph Levien 126a033630e805c407080221e20b236b6054f324670Raph LevienTypefaceImpl* TypefaceImpl_createFromName(const char* name, SkTypeface::Style style) { 127a033630e805c407080221e20b236b6054f324670Raph Levien // TODO: should create a font collection with all styles corresponding to 128a033630e805c407080221e20b236b6054f324670Raph Levien // the name 129a033630e805c407080221e20b236b6054f324670Raph Levien SkTypeface* face = SkTypeface::CreateFromName(name, style); 130a033630e805c407080221e20b236b6054f324670Raph Levien return createFromSkTypeface(face); 131a033630e805c407080221e20b236b6054f324670Raph Levien} 132a033630e805c407080221e20b236b6054f324670Raph Levien 133a033630e805c407080221e20b236b6054f324670Raph LevienTypefaceImpl* TypefaceImpl_createFromFile(const char* filename) { 134a033630e805c407080221e20b236b6054f324670Raph Levien SkTypeface* face = SkTypeface::CreateFromFile(filename); 135a033630e805c407080221e20b236b6054f324670Raph Levien return createFromSkTypeface(face); 136a033630e805c407080221e20b236b6054f324670Raph Levien} 137a033630e805c407080221e20b236b6054f324670Raph Levien 138a033630e805c407080221e20b236b6054f324670Raph LevienTypefaceImpl* TypefaceImpl_createFromAsset(Asset* asset) { 139b9c58ab617c257dbece105167b21e94faad67320Leon Scroggins III SkStream* stream = new AssetStreamAdaptor(asset, 140b9c58ab617c257dbece105167b21e94faad67320Leon Scroggins III AssetStreamAdaptor::kYes_OwnAsset, 141b9c58ab617c257dbece105167b21e94faad67320Leon Scroggins III AssetStreamAdaptor::kYes_HasMemoryBase); 142a033630e805c407080221e20b236b6054f324670Raph Levien SkTypeface* face = SkTypeface::CreateFromStream(stream); 143a033630e805c407080221e20b236b6054f324670Raph Levien // SkTypeFace::CreateFromStream calls ref() on the stream, so we 144a033630e805c407080221e20b236b6054f324670Raph Levien // need to unref it here or it won't be freed later on 145a033630e805c407080221e20b236b6054f324670Raph Levien stream->unref(); 146a033630e805c407080221e20b236b6054f324670Raph Levien return createFromSkTypeface(face); 147a033630e805c407080221e20b236b6054f324670Raph Levien} 148a033630e805c407080221e20b236b6054f324670Raph Levien 149a033630e805c407080221e20b236b6054f324670Raph Levienvoid TypefaceImpl_unref(TypefaceImpl* face) { 150a033630e805c407080221e20b236b6054f324670Raph Levien delete face; 151a033630e805c407080221e20b236b6054f324670Raph Levien} 152a033630e805c407080221e20b236b6054f324670Raph Levien 153a033630e805c407080221e20b236b6054f324670Raph Levienint TypefaceImpl_getStyle(TypefaceImpl* face) { 154a033630e805c407080221e20b236b6054f324670Raph Levien FontStyle style = face->fStyle; 155a033630e805c407080221e20b236b6054f324670Raph Levien int result = style.getItalic() ? SkTypeface::kItalic : 0; 156a033630e805c407080221e20b236b6054f324670Raph Levien if (style.getWeight() >= kBoldThreshold) { 157a033630e805c407080221e20b236b6054f324670Raph Levien result |= SkTypeface::kBold; 158a033630e805c407080221e20b236b6054f324670Raph Levien } 159a033630e805c407080221e20b236b6054f324670Raph Levien return result; 160a033630e805c407080221e20b236b6054f324670Raph Levien} 161a033630e805c407080221e20b236b6054f324670Raph Levien 162a033630e805c407080221e20b236b6054f324670Raph Levien#else // USE_MINIKIN 163a033630e805c407080221e20b236b6054f324670Raph Levien 164a033630e805c407080221e20b236b6054f324670Raph Levien/* Just use SkTypeface instead. */ 165a033630e805c407080221e20b236b6054f324670Raph Levien 166a033630e805c407080221e20b236b6054f324670Raph Levientypedef SkTypeface TypefaceImpl; 167a033630e805c407080221e20b236b6054f324670Raph Levien 168a033630e805c407080221e20b236b6054f324670Raph LevienTypefaceImpl* TypefaceImpl_createFromTypeface(TypefaceImpl* src, SkTypeface::Style style) { 169a033630e805c407080221e20b236b6054f324670Raph Levien return SkTypeface::CreateFromTypeface(src, style); 170a033630e805c407080221e20b236b6054f324670Raph Levien} 171a033630e805c407080221e20b236b6054f324670Raph Levien 172a033630e805c407080221e20b236b6054f324670Raph LevienTypefaceImpl* TypefaceImpl_createFromName(const char* name, SkTypeface::Style style) { 173a033630e805c407080221e20b236b6054f324670Raph Levien return SkTypeface::CreateFromName(name, style); 174a033630e805c407080221e20b236b6054f324670Raph Levien} 175a033630e805c407080221e20b236b6054f324670Raph Levien 176a033630e805c407080221e20b236b6054f324670Raph LevienTypefaceImpl* TypefaceImpl_createFromFile(const char* filename) { 177a033630e805c407080221e20b236b6054f324670Raph Levien return SkTypeface::CreateFromFile(filename); 178a033630e805c407080221e20b236b6054f324670Raph Levien} 179a033630e805c407080221e20b236b6054f324670Raph Levien 180a033630e805c407080221e20b236b6054f324670Raph LevienTypefaceImpl* TypefaceImpl_createFromAsset(Asset* asset) { 181b9c58ab617c257dbece105167b21e94faad67320Leon Scroggins III SkStream* stream = new AssetStreamAdaptor(asset, 182b9c58ab617c257dbece105167b21e94faad67320Leon Scroggins III AssetStreamAdaptor::kYes_OwnAsset, 183b9c58ab617c257dbece105167b21e94faad67320Leon Scroggins III AssetStreamAdaptor::kYes_HasMemoryBase); 184a033630e805c407080221e20b236b6054f324670Raph Levien SkTypeface* face = SkTypeface::CreateFromStream(stream); 185a033630e805c407080221e20b236b6054f324670Raph Levien // SkTypeFace::CreateFromStream calls ref() on the stream, so we 186a033630e805c407080221e20b236b6054f324670Raph Levien // need to unref it here or it won't be freed later on 187a033630e805c407080221e20b236b6054f324670Raph Levien stream->unref(); 188a033630e805c407080221e20b236b6054f324670Raph Levien 189a033630e805c407080221e20b236b6054f324670Raph Levien return face; 190a033630e805c407080221e20b236b6054f324670Raph Levien} 191a033630e805c407080221e20b236b6054f324670Raph Levien 192a033630e805c407080221e20b236b6054f324670Raph Levienvoid TypefaceImpl_unref(TypefaceImpl* face) { 193a033630e805c407080221e20b236b6054f324670Raph Levien SkSafeUnref(face); 194a033630e805c407080221e20b236b6054f324670Raph Levien} 195a033630e805c407080221e20b236b6054f324670Raph Levien 196a033630e805c407080221e20b236b6054f324670Raph Levienint TypefaceImpl_getStyle(TypefaceImpl* face) { 197a033630e805c407080221e20b236b6054f324670Raph Levien return face->style(); 198a033630e805c407080221e20b236b6054f324670Raph Levien} 199a033630e805c407080221e20b236b6054f324670Raph Levien 200a033630e805c407080221e20b236b6054f324670Raph Levien#endif // USE_MINIKIN 201a033630e805c407080221e20b236b6054f324670Raph Levien 202a033630e805c407080221e20b236b6054f324670Raph Levien} 203