Typeface.cpp revision 9a5b61ccc83303ceeec2059f58c1977af9faa9e3
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 231a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien#define LOG_TAG "TypefaceImpl" 241a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien 251a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien#include "jni.h" // for jlong, remove when being passed proper type 261a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien 27a033630e805c407080221e20b236b6054f324670Raph Levien#include "SkStream.h" 28a033630e805c407080221e20b236b6054f324670Raph Levien#include "SkTypeface.h" 29a033630e805c407080221e20b236b6054f324670Raph Levien 30a033630e805c407080221e20b236b6054f324670Raph Levien#ifdef USE_MINIKIN 31a033630e805c407080221e20b236b6054f324670Raph Levien#include <vector> 32a033630e805c407080221e20b236b6054f324670Raph Levien#include <minikin/FontCollection.h> 33a033630e805c407080221e20b236b6054f324670Raph Levien#include <minikin/FontFamily.h> 34a033630e805c407080221e20b236b6054f324670Raph Levien#include <minikin/Layout.h> 35a033630e805c407080221e20b236b6054f324670Raph Levien#include "MinikinSkia.h" 36a033630e805c407080221e20b236b6054f324670Raph Levien#endif 37a033630e805c407080221e20b236b6054f324670Raph Levien 38a033630e805c407080221e20b236b6054f324670Raph Levien#include "TypefaceImpl.h" 39b9c58ab617c257dbece105167b21e94faad67320Leon Scroggins III#include "Utils.h" 40a033630e805c407080221e20b236b6054f324670Raph Levien 41a033630e805c407080221e20b236b6054f324670Raph Leviennamespace android { 42a033630e805c407080221e20b236b6054f324670Raph Levien 43a033630e805c407080221e20b236b6054f324670Raph Levien#ifdef USE_MINIKIN 44a033630e805c407080221e20b236b6054f324670Raph Levien 45a033630e805c407080221e20b236b6054f324670Raph Levien// Any weight greater than or equal to this is considered "bold" for 46a033630e805c407080221e20b236b6054f324670Raph Levien// legacy API. 47a033630e805c407080221e20b236b6054f324670Raph Levienstatic const int kBoldThreshold = 6; 48a033630e805c407080221e20b236b6054f324670Raph Levien 49a033630e805c407080221e20b236b6054f324670Raph Levienstatic FontStyle styleFromSkiaStyle(SkTypeface::Style skiaStyle) { 50a033630e805c407080221e20b236b6054f324670Raph Levien int weight = (skiaStyle & SkTypeface::kBold) != 0 ? 7 : 4; 51a033630e805c407080221e20b236b6054f324670Raph Levien bool italic = (skiaStyle & SkTypeface::kItalic) != 0; 52a033630e805c407080221e20b236b6054f324670Raph Levien return FontStyle(weight, italic); 53a033630e805c407080221e20b236b6054f324670Raph Levien} 54a033630e805c407080221e20b236b6054f324670Raph Levien 559a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph LevienTypefaceImpl* gDefaultTypeface = NULL; 56a033630e805c407080221e20b236b6054f324670Raph Levienpthread_once_t gDefaultTypefaceOnce = PTHREAD_ONCE_INIT; 57a033630e805c407080221e20b236b6054f324670Raph Levien 589a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien// This installs a default typeface (from a hardcoded path) that allows 599a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien// layouts to work (not crash on null pointer) before the default 609a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien// typeface is set. 619a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien// TODO: investigate why layouts are being created before Typeface.java 629a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien// class initialization. 63a033630e805c407080221e20b236b6054f324670Raph Levienstatic FontCollection *makeFontCollection() { 64a033630e805c407080221e20b236b6054f324670Raph Levien std::vector<FontFamily *>typefaces; 65a033630e805c407080221e20b236b6054f324670Raph Levien const char *fns[] = { 66a033630e805c407080221e20b236b6054f324670Raph Levien "/system/fonts/Roboto-Regular.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]; 729a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien ALOGD("makeFontCollection adding %s", fn); 73a033630e805c407080221e20b236b6054f324670Raph Levien SkTypeface *skFace = SkTypeface::CreateFromFile(fn); 749a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien if (skFace != NULL) { 759a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien MinikinFont *font = new MinikinFontSkia(skFace); 769a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien family->addFont(font); 779a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien } else { 789a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien ALOGE("failed to create font %s", fn); 799a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien } 80a033630e805c407080221e20b236b6054f324670Raph Levien } 81a033630e805c407080221e20b236b6054f324670Raph Levien typefaces.push_back(family); 82a033630e805c407080221e20b236b6054f324670Raph Levien 83a033630e805c407080221e20b236b6054f324670Raph Levien return new FontCollection(typefaces); 84a033630e805c407080221e20b236b6054f324670Raph Levien} 85a033630e805c407080221e20b236b6054f324670Raph Levien 86a033630e805c407080221e20b236b6054f324670Raph Levienstatic void getDefaultTypefaceOnce() { 87a033630e805c407080221e20b236b6054f324670Raph Levien Layout::init(); 889a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien if (gDefaultTypeface == NULL) { 899a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien // We expect the client to set a default typeface, but provide a 909a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien // default so we can make progress before that happens. 919a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien gDefaultTypeface = new TypefaceImpl; 929a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien gDefaultTypeface->fFontCollection = makeFontCollection(); 939a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien gDefaultTypeface->fStyle = FontStyle(); 949a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien } 95a033630e805c407080221e20b236b6054f324670Raph Levien} 96a033630e805c407080221e20b236b6054f324670Raph Levien 97a033630e805c407080221e20b236b6054f324670Raph LevienTypefaceImpl* TypefaceImpl_resolveDefault(TypefaceImpl* src) { 98a033630e805c407080221e20b236b6054f324670Raph Levien if (src == NULL) { 99a033630e805c407080221e20b236b6054f324670Raph Levien pthread_once(&gDefaultTypefaceOnce, getDefaultTypefaceOnce); 100a033630e805c407080221e20b236b6054f324670Raph Levien return gDefaultTypeface; 101a033630e805c407080221e20b236b6054f324670Raph Levien } else { 102a033630e805c407080221e20b236b6054f324670Raph Levien return src; 103a033630e805c407080221e20b236b6054f324670Raph Levien } 104a033630e805c407080221e20b236b6054f324670Raph Levien} 105a033630e805c407080221e20b236b6054f324670Raph Levien 106a033630e805c407080221e20b236b6054f324670Raph LevienTypefaceImpl* TypefaceImpl_createFromTypeface(TypefaceImpl* src, SkTypeface::Style style) { 107a033630e805c407080221e20b236b6054f324670Raph Levien TypefaceImpl* resolvedFace = TypefaceImpl_resolveDefault(src); 108a033630e805c407080221e20b236b6054f324670Raph Levien TypefaceImpl* result = new TypefaceImpl; 109a033630e805c407080221e20b236b6054f324670Raph Levien if (result != 0) { 110a033630e805c407080221e20b236b6054f324670Raph Levien result->fFontCollection = resolvedFace->fFontCollection; 111a033630e805c407080221e20b236b6054f324670Raph Levien result->fStyle = styleFromSkiaStyle(style); 112a033630e805c407080221e20b236b6054f324670Raph Levien } 113a033630e805c407080221e20b236b6054f324670Raph Levien return result; 114a033630e805c407080221e20b236b6054f324670Raph Levien} 115a033630e805c407080221e20b236b6054f324670Raph Levien 116a033630e805c407080221e20b236b6054f324670Raph Levienstatic TypefaceImpl* createFromSkTypeface(SkTypeface* typeface) { 1179a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien if (typeface == NULL) { 1189a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien return NULL; 1199a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien } 120a033630e805c407080221e20b236b6054f324670Raph Levien MinikinFont* minikinFont = new MinikinFontSkia(typeface); 121a033630e805c407080221e20b236b6054f324670Raph Levien std::vector<FontFamily *> typefaces; 122a033630e805c407080221e20b236b6054f324670Raph Levien FontFamily* family = new FontFamily(); 123a033630e805c407080221e20b236b6054f324670Raph Levien family->addFont(minikinFont); 124a033630e805c407080221e20b236b6054f324670Raph Levien typefaces.push_back(family); 125a033630e805c407080221e20b236b6054f324670Raph Levien TypefaceImpl* result = new TypefaceImpl; 126a033630e805c407080221e20b236b6054f324670Raph Levien result->fFontCollection = new FontCollection(typefaces); 127a033630e805c407080221e20b236b6054f324670Raph Levien result->fStyle = FontStyle(); // TODO: improve 128a033630e805c407080221e20b236b6054f324670Raph Levien return result; 129a033630e805c407080221e20b236b6054f324670Raph Levien} 130a033630e805c407080221e20b236b6054f324670Raph Levien 131a033630e805c407080221e20b236b6054f324670Raph LevienTypefaceImpl* TypefaceImpl_createFromName(const char* name, SkTypeface::Style style) { 132a033630e805c407080221e20b236b6054f324670Raph Levien // TODO: should create a font collection with all styles corresponding to 133a033630e805c407080221e20b236b6054f324670Raph Levien // the name 134a033630e805c407080221e20b236b6054f324670Raph Levien SkTypeface* face = SkTypeface::CreateFromName(name, style); 135a033630e805c407080221e20b236b6054f324670Raph Levien return createFromSkTypeface(face); 136a033630e805c407080221e20b236b6054f324670Raph Levien} 137a033630e805c407080221e20b236b6054f324670Raph Levien 138a033630e805c407080221e20b236b6054f324670Raph LevienTypefaceImpl* TypefaceImpl_createFromFile(const char* filename) { 139a033630e805c407080221e20b236b6054f324670Raph Levien SkTypeface* face = SkTypeface::CreateFromFile(filename); 140a033630e805c407080221e20b236b6054f324670Raph Levien return createFromSkTypeface(face); 141a033630e805c407080221e20b236b6054f324670Raph Levien} 142a033630e805c407080221e20b236b6054f324670Raph Levien 143a033630e805c407080221e20b236b6054f324670Raph LevienTypefaceImpl* TypefaceImpl_createFromAsset(Asset* asset) { 144b9c58ab617c257dbece105167b21e94faad67320Leon Scroggins III SkStream* stream = new AssetStreamAdaptor(asset, 145b9c58ab617c257dbece105167b21e94faad67320Leon Scroggins III AssetStreamAdaptor::kYes_OwnAsset, 146b9c58ab617c257dbece105167b21e94faad67320Leon Scroggins III AssetStreamAdaptor::kYes_HasMemoryBase); 147a033630e805c407080221e20b236b6054f324670Raph Levien SkTypeface* face = SkTypeface::CreateFromStream(stream); 148a033630e805c407080221e20b236b6054f324670Raph Levien // SkTypeFace::CreateFromStream calls ref() on the stream, so we 149a033630e805c407080221e20b236b6054f324670Raph Levien // need to unref it here or it won't be freed later on 150a033630e805c407080221e20b236b6054f324670Raph Levien stream->unref(); 151a033630e805c407080221e20b236b6054f324670Raph Levien return createFromSkTypeface(face); 152a033630e805c407080221e20b236b6054f324670Raph Levien} 153a033630e805c407080221e20b236b6054f324670Raph Levien 1541a73f732f91e97c9c66b808c245ddda36a10e987Raph LevienTypefaceImpl* TypefaceImpl_createFromFamilies(const jlong* families, size_t size) { 1551a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien ALOGD("createFromFamilies size=%d", size); 1561a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien std::vector<FontFamily *>familyVec; 1571a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien for (size_t i = 0; i < size; i++) { 1581a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien FontFamily* family = reinterpret_cast<FontFamily*>(families[i]); 1591a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien familyVec.push_back(family); 1601a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien } 1611a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien TypefaceImpl* result = new TypefaceImpl; 1621a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien result->fFontCollection = new FontCollection(familyVec); 1631a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien result->fStyle = FontStyle(); // TODO: improve 1641a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien return result; 1651a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien} 1661a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien 167a033630e805c407080221e20b236b6054f324670Raph Levienvoid TypefaceImpl_unref(TypefaceImpl* face) { 168a033630e805c407080221e20b236b6054f324670Raph Levien delete face; 169a033630e805c407080221e20b236b6054f324670Raph Levien} 170a033630e805c407080221e20b236b6054f324670Raph Levien 171a033630e805c407080221e20b236b6054f324670Raph Levienint TypefaceImpl_getStyle(TypefaceImpl* face) { 172a033630e805c407080221e20b236b6054f324670Raph Levien FontStyle style = face->fStyle; 173a033630e805c407080221e20b236b6054f324670Raph Levien int result = style.getItalic() ? SkTypeface::kItalic : 0; 174a033630e805c407080221e20b236b6054f324670Raph Levien if (style.getWeight() >= kBoldThreshold) { 175a033630e805c407080221e20b236b6054f324670Raph Levien result |= SkTypeface::kBold; 176a033630e805c407080221e20b236b6054f324670Raph Levien } 177a033630e805c407080221e20b236b6054f324670Raph Levien return result; 178a033630e805c407080221e20b236b6054f324670Raph Levien} 179a033630e805c407080221e20b236b6054f324670Raph Levien 1809a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levienvoid TypefaceImpl_setDefault(TypefaceImpl* face) { 1819a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien gDefaultTypeface = face; 1829a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien} 1839a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien 184a033630e805c407080221e20b236b6054f324670Raph Levien#else // USE_MINIKIN 185a033630e805c407080221e20b236b6054f324670Raph Levien 186a033630e805c407080221e20b236b6054f324670Raph Levien/* Just use SkTypeface instead. */ 187a033630e805c407080221e20b236b6054f324670Raph Levien 188a033630e805c407080221e20b236b6054f324670Raph Levientypedef SkTypeface TypefaceImpl; 189a033630e805c407080221e20b236b6054f324670Raph Levien 190a033630e805c407080221e20b236b6054f324670Raph LevienTypefaceImpl* TypefaceImpl_createFromTypeface(TypefaceImpl* src, SkTypeface::Style style) { 191a033630e805c407080221e20b236b6054f324670Raph Levien return SkTypeface::CreateFromTypeface(src, style); 192a033630e805c407080221e20b236b6054f324670Raph Levien} 193a033630e805c407080221e20b236b6054f324670Raph Levien 194a033630e805c407080221e20b236b6054f324670Raph LevienTypefaceImpl* TypefaceImpl_createFromName(const char* name, SkTypeface::Style style) { 195a033630e805c407080221e20b236b6054f324670Raph Levien return SkTypeface::CreateFromName(name, style); 196a033630e805c407080221e20b236b6054f324670Raph Levien} 197a033630e805c407080221e20b236b6054f324670Raph Levien 198a033630e805c407080221e20b236b6054f324670Raph LevienTypefaceImpl* TypefaceImpl_createFromFile(const char* filename) { 199a033630e805c407080221e20b236b6054f324670Raph Levien return SkTypeface::CreateFromFile(filename); 200a033630e805c407080221e20b236b6054f324670Raph Levien} 201a033630e805c407080221e20b236b6054f324670Raph Levien 202a033630e805c407080221e20b236b6054f324670Raph LevienTypefaceImpl* TypefaceImpl_createFromAsset(Asset* asset) { 203b9c58ab617c257dbece105167b21e94faad67320Leon Scroggins III SkStream* stream = new AssetStreamAdaptor(asset, 204b9c58ab617c257dbece105167b21e94faad67320Leon Scroggins III AssetStreamAdaptor::kYes_OwnAsset, 205b9c58ab617c257dbece105167b21e94faad67320Leon Scroggins III AssetStreamAdaptor::kYes_HasMemoryBase); 206a033630e805c407080221e20b236b6054f324670Raph Levien SkTypeface* face = SkTypeface::CreateFromStream(stream); 207a033630e805c407080221e20b236b6054f324670Raph Levien // SkTypeFace::CreateFromStream calls ref() on the stream, so we 208a033630e805c407080221e20b236b6054f324670Raph Levien // need to unref it here or it won't be freed later on 209a033630e805c407080221e20b236b6054f324670Raph Levien stream->unref(); 210a033630e805c407080221e20b236b6054f324670Raph Levien 211a033630e805c407080221e20b236b6054f324670Raph Levien return face; 212a033630e805c407080221e20b236b6054f324670Raph Levien} 213a033630e805c407080221e20b236b6054f324670Raph Levien 2141a73f732f91e97c9c66b808c245ddda36a10e987Raph LevienTypefaceImpl* TypefaceImpl_createFromFamilies(const jlong* families, size_t size) { 2151a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien // Should never be called in non-Minikin builds 2161a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien return 0; 2171a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien} 2181a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien 219a033630e805c407080221e20b236b6054f324670Raph Levienvoid TypefaceImpl_unref(TypefaceImpl* face) { 220a033630e805c407080221e20b236b6054f324670Raph Levien SkSafeUnref(face); 221a033630e805c407080221e20b236b6054f324670Raph Levien} 222a033630e805c407080221e20b236b6054f324670Raph Levien 223a033630e805c407080221e20b236b6054f324670Raph Levienint TypefaceImpl_getStyle(TypefaceImpl* face) { 224a033630e805c407080221e20b236b6054f324670Raph Levien return face->style(); 225a033630e805c407080221e20b236b6054f324670Raph Levien} 226a033630e805c407080221e20b236b6054f324670Raph Levien 2279a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levienvoid TypefaceImpl_setDefault(TypefaceImpl* face) { 2289a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien} 2299a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien 230a033630e805c407080221e20b236b6054f324670Raph Levien#endif // USE_MINIKIN 231a033630e805c407080221e20b236b6054f324670Raph Levien 232a033630e805c407080221e20b236b6054f324670Raph Levien} 233