Typeface.cpp revision dccca44ffda4836b56a21da95a046c9708ffd49c
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 23dccca44ffda4836b56a21da95a046c9708ffd49csergeyv#include "TypefaceImpl.h" 241a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien 25dccca44ffda4836b56a21da95a046c9708ffd49csergeyv#include "MinikinSkia.h" 26a033630e805c407080221e20b236b6054f324670Raph Levien#include "SkTypeface.h" 27dccca44ffda4836b56a21da95a046c9708ffd49csergeyv#include "SkPaint.h" 28a033630e805c407080221e20b236b6054f324670Raph Levien 29a033630e805c407080221e20b236b6054f324670Raph Levien#include <minikin/FontCollection.h> 30a033630e805c407080221e20b236b6054f324670Raph Levien#include <minikin/FontFamily.h> 31a033630e805c407080221e20b236b6054f324670Raph Levien#include <minikin/Layout.h> 32dccca44ffda4836b56a21da95a046c9708ffd49csergeyv#include <utils/Log.h> 33a033630e805c407080221e20b236b6054f324670Raph Levien 34a033630e805c407080221e20b236b6054f324670Raph Leviennamespace android { 35a033630e805c407080221e20b236b6054f324670Raph Levien 36117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien// Resolve the 1..9 weight based on base weight and bold flag 37117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levienstatic void resolveStyle(TypefaceImpl* typeface) { 38117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien int weight = typeface->fBaseWeight / 100; 39117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien if (typeface->fSkiaStyle & SkTypeface::kBold) { 40117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien weight += 3; 41117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien } 42117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien if (weight > 9) { 43117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien weight = 9; 44117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien } 45117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien bool italic = (typeface->fSkiaStyle & SkTypeface::kItalic) != 0; 46117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien typeface->fStyle = FontStyle(weight, italic); 47a033630e805c407080221e20b236b6054f324670Raph Levien} 48a033630e805c407080221e20b236b6054f324670Raph Levien 499a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph LevienTypefaceImpl* gDefaultTypeface = NULL; 50a033630e805c407080221e20b236b6054f324670Raph Levienpthread_once_t gDefaultTypefaceOnce = PTHREAD_ONCE_INIT; 51a033630e805c407080221e20b236b6054f324670Raph Levien 529a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien// This installs a default typeface (from a hardcoded path) that allows 539a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien// layouts to work (not crash on null pointer) before the default 549a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien// typeface is set. 559a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien// TODO: investigate why layouts are being created before Typeface.java 569a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien// class initialization. 57a033630e805c407080221e20b236b6054f324670Raph Levienstatic FontCollection *makeFontCollection() { 58a033630e805c407080221e20b236b6054f324670Raph Levien std::vector<FontFamily *>typefaces; 59a033630e805c407080221e20b236b6054f324670Raph Levien const char *fns[] = { 60a033630e805c407080221e20b236b6054f324670Raph Levien "/system/fonts/Roboto-Regular.ttf", 61a033630e805c407080221e20b236b6054f324670Raph Levien }; 62a033630e805c407080221e20b236b6054f324670Raph Levien 63a033630e805c407080221e20b236b6054f324670Raph Levien FontFamily *family = new FontFamily(); 64a033630e805c407080221e20b236b6054f324670Raph Levien for (size_t i = 0; i < sizeof(fns)/sizeof(fns[0]); i++) { 65a033630e805c407080221e20b236b6054f324670Raph Levien const char *fn = fns[i]; 669a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien ALOGD("makeFontCollection adding %s", fn); 67a033630e805c407080221e20b236b6054f324670Raph Levien SkTypeface *skFace = SkTypeface::CreateFromFile(fn); 689a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien if (skFace != NULL) { 699a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien MinikinFont *font = new MinikinFontSkia(skFace); 709a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien family->addFont(font); 7115cf4757dc0099301662f8a26da561434cc07cfaRaph Levien font->Unref(); 729a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien } else { 739a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien ALOGE("failed to create font %s", fn); 749a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien } 75a033630e805c407080221e20b236b6054f324670Raph Levien } 76a033630e805c407080221e20b236b6054f324670Raph Levien typefaces.push_back(family); 77a033630e805c407080221e20b236b6054f324670Raph Levien 7815cf4757dc0099301662f8a26da561434cc07cfaRaph Levien FontCollection *result = new FontCollection(typefaces); 7915cf4757dc0099301662f8a26da561434cc07cfaRaph Levien family->Unref(); 8015cf4757dc0099301662f8a26da561434cc07cfaRaph Levien return result; 81a033630e805c407080221e20b236b6054f324670Raph Levien} 82a033630e805c407080221e20b236b6054f324670Raph Levien 83a033630e805c407080221e20b236b6054f324670Raph Levienstatic void getDefaultTypefaceOnce() { 84a033630e805c407080221e20b236b6054f324670Raph Levien Layout::init(); 859a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien if (gDefaultTypeface == NULL) { 869a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien // We expect the client to set a default typeface, but provide a 879a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien // default so we can make progress before that happens. 889a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien gDefaultTypeface = new TypefaceImpl; 899a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien gDefaultTypeface->fFontCollection = makeFontCollection(); 90117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien gDefaultTypeface->fSkiaStyle = SkTypeface::kNormal; 91117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien gDefaultTypeface->fBaseWeight = 400; 92117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien resolveStyle(gDefaultTypeface); 939a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien } 94a033630e805c407080221e20b236b6054f324670Raph Levien} 95a033630e805c407080221e20b236b6054f324670Raph Levien 96a033630e805c407080221e20b236b6054f324670Raph LevienTypefaceImpl* TypefaceImpl_resolveDefault(TypefaceImpl* src) { 97a033630e805c407080221e20b236b6054f324670Raph Levien if (src == NULL) { 98a033630e805c407080221e20b236b6054f324670Raph Levien pthread_once(&gDefaultTypefaceOnce, getDefaultTypefaceOnce); 99a033630e805c407080221e20b236b6054f324670Raph Levien return gDefaultTypeface; 100a033630e805c407080221e20b236b6054f324670Raph Levien } else { 101a033630e805c407080221e20b236b6054f324670Raph Levien return src; 102a033630e805c407080221e20b236b6054f324670Raph Levien } 103a033630e805c407080221e20b236b6054f324670Raph Levien} 104a033630e805c407080221e20b236b6054f324670Raph Levien 105a033630e805c407080221e20b236b6054f324670Raph LevienTypefaceImpl* TypefaceImpl_createFromTypeface(TypefaceImpl* src, SkTypeface::Style style) { 106a033630e805c407080221e20b236b6054f324670Raph Levien TypefaceImpl* resolvedFace = TypefaceImpl_resolveDefault(src); 107a033630e805c407080221e20b236b6054f324670Raph Levien TypefaceImpl* result = new TypefaceImpl; 108a033630e805c407080221e20b236b6054f324670Raph Levien if (result != 0) { 109a033630e805c407080221e20b236b6054f324670Raph Levien result->fFontCollection = resolvedFace->fFontCollection; 11015cf4757dc0099301662f8a26da561434cc07cfaRaph Levien result->fFontCollection->Ref(); 111117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien result->fSkiaStyle = style; 112117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien result->fBaseWeight = resolvedFace->fBaseWeight; 113117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien resolveStyle(result); 114a033630e805c407080221e20b236b6054f324670Raph Levien } 115a033630e805c407080221e20b236b6054f324670Raph Levien return result; 116a033630e805c407080221e20b236b6054f324670Raph Levien} 117a033630e805c407080221e20b236b6054f324670Raph Levien 118117cbebe810613d4a6de034f02652cdbbfef4cdeRaph LevienTypefaceImpl* TypefaceImpl_createWeightAlias(TypefaceImpl* src, int weight) { 119117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien TypefaceImpl* resolvedFace = TypefaceImpl_resolveDefault(src); 120a033630e805c407080221e20b236b6054f324670Raph Levien TypefaceImpl* result = new TypefaceImpl; 121117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien if (result != 0) { 122117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien result->fFontCollection = resolvedFace->fFontCollection; 123117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien result->fFontCollection->Ref(); 124117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien result->fSkiaStyle = resolvedFace->fSkiaStyle; 125117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien result->fBaseWeight = weight; 126117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien resolveStyle(result); 127117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien } 128a033630e805c407080221e20b236b6054f324670Raph Levien return result; 129a033630e805c407080221e20b236b6054f324670Raph Levien} 130a033630e805c407080221e20b236b6054f324670Raph Levien 131dccca44ffda4836b56a21da95a046c9708ffd49csergeyvTypefaceImpl* TypefaceImpl_createFromFamilies(const std::vector<FontFamily*>& families) { 1321a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien TypefaceImpl* result = new TypefaceImpl; 133dccca44ffda4836b56a21da95a046c9708ffd49csergeyv result->fFontCollection = new FontCollection(families); 134dccca44ffda4836b56a21da95a046c9708ffd49csergeyv if (families.empty()) { 1351633caef58ebd0bc3b0c5da15dde2fb425b77c43Raph Levien ALOGW("createFromFamilies creating empty collection"); 136117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien result->fSkiaStyle = SkTypeface::kNormal; 1371633caef58ebd0bc3b0c5da15dde2fb425b77c43Raph Levien } else { 1381633caef58ebd0bc3b0c5da15dde2fb425b77c43Raph Levien const FontStyle defaultStyle; 1391633caef58ebd0bc3b0c5da15dde2fb425b77c43Raph Levien FontFamily* firstFamily = reinterpret_cast<FontFamily*>(families[0]); 1401fc0fa87d42ce9268ece76b85b9edc834593e53aRaph Levien MinikinFont* mf = firstFamily->getClosestMatch(defaultStyle).font; 14127bb05f2dccf1ac2ca55515aa0f4a99cd9c548a7Raph Levien if (mf != NULL) { 14227bb05f2dccf1ac2ca55515aa0f4a99cd9c548a7Raph Levien SkTypeface* skTypeface = reinterpret_cast<MinikinFontSkia*>(mf)->GetSkTypeface(); 14327bb05f2dccf1ac2ca55515aa0f4a99cd9c548a7Raph Levien // TODO: probably better to query more precise style from family, will be important 14427bb05f2dccf1ac2ca55515aa0f4a99cd9c548a7Raph Levien // when we open up API to access 100..900 weights 145117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien result->fSkiaStyle = skTypeface->style(); 14627bb05f2dccf1ac2ca55515aa0f4a99cd9c548a7Raph Levien } else { 147117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien result->fSkiaStyle = SkTypeface::kNormal; 14827bb05f2dccf1ac2ca55515aa0f4a99cd9c548a7Raph Levien } 1491633caef58ebd0bc3b0c5da15dde2fb425b77c43Raph Levien } 150117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien result->fBaseWeight = 400; 151117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien resolveStyle(result); 1521a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien return result; 1531a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien} 1541a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien 155a033630e805c407080221e20b236b6054f324670Raph Levienvoid TypefaceImpl_unref(TypefaceImpl* face) { 156a0cba0fde3e39723052a50e1f09e3b254da6c175Raph Levien if (face != NULL) { 157a0cba0fde3e39723052a50e1f09e3b254da6c175Raph Levien face->fFontCollection->Unref(); 158a0cba0fde3e39723052a50e1f09e3b254da6c175Raph Levien } 159a033630e805c407080221e20b236b6054f324670Raph Levien delete face; 160a033630e805c407080221e20b236b6054f324670Raph Levien} 161a033630e805c407080221e20b236b6054f324670Raph Levien 162a033630e805c407080221e20b236b6054f324670Raph Levienint TypefaceImpl_getStyle(TypefaceImpl* face) { 163117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien return face->fSkiaStyle; 164a033630e805c407080221e20b236b6054f324670Raph Levien} 165a033630e805c407080221e20b236b6054f324670Raph Levien 1669a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levienvoid TypefaceImpl_setDefault(TypefaceImpl* face) { 1679a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien gDefaultTypeface = face; 1689a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien} 1699a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien 170a033630e805c407080221e20b236b6054f324670Raph Levien} 171