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#include <vector> 31a033630e805c407080221e20b236b6054f324670Raph Levien#include <minikin/FontCollection.h> 32a033630e805c407080221e20b236b6054f324670Raph Levien#include <minikin/FontFamily.h> 33a033630e805c407080221e20b236b6054f324670Raph Levien#include <minikin/Layout.h> 34e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien#include "SkPaint.h" 35a033630e805c407080221e20b236b6054f324670Raph Levien#include "MinikinSkia.h" 36a033630e805c407080221e20b236b6054f324670Raph Levien 37a033630e805c407080221e20b236b6054f324670Raph Levien#include "TypefaceImpl.h" 38b9c58ab617c257dbece105167b21e94faad67320Leon Scroggins III#include "Utils.h" 39a033630e805c407080221e20b236b6054f324670Raph Levien 40a033630e805c407080221e20b236b6054f324670Raph Leviennamespace android { 41a033630e805c407080221e20b236b6054f324670Raph Levien 42117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien// Resolve the 1..9 weight based on base weight and bold flag 43117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levienstatic void resolveStyle(TypefaceImpl* typeface) { 44117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien int weight = typeface->fBaseWeight / 100; 45117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien if (typeface->fSkiaStyle & SkTypeface::kBold) { 46117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien weight += 3; 47117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien } 48117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien if (weight > 9) { 49117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien weight = 9; 50117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien } 51117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien bool italic = (typeface->fSkiaStyle & SkTypeface::kItalic) != 0; 52117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien typeface->fStyle = 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); 7715cf4757dc0099301662f8a26da561434cc07cfaRaph Levien font->Unref(); 789a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien } else { 799a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien ALOGE("failed to create font %s", fn); 809a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien } 81a033630e805c407080221e20b236b6054f324670Raph Levien } 82a033630e805c407080221e20b236b6054f324670Raph Levien typefaces.push_back(family); 83a033630e805c407080221e20b236b6054f324670Raph Levien 8415cf4757dc0099301662f8a26da561434cc07cfaRaph Levien FontCollection *result = new FontCollection(typefaces); 8515cf4757dc0099301662f8a26da561434cc07cfaRaph Levien family->Unref(); 8615cf4757dc0099301662f8a26da561434cc07cfaRaph Levien return result; 87a033630e805c407080221e20b236b6054f324670Raph Levien} 88a033630e805c407080221e20b236b6054f324670Raph Levien 89a033630e805c407080221e20b236b6054f324670Raph Levienstatic void getDefaultTypefaceOnce() { 90a033630e805c407080221e20b236b6054f324670Raph Levien Layout::init(); 919a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien if (gDefaultTypeface == NULL) { 929a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien // We expect the client to set a default typeface, but provide a 939a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien // default so we can make progress before that happens. 949a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien gDefaultTypeface = new TypefaceImpl; 959a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien gDefaultTypeface->fFontCollection = makeFontCollection(); 96117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien gDefaultTypeface->fSkiaStyle = SkTypeface::kNormal; 97117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien gDefaultTypeface->fBaseWeight = 400; 98117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien resolveStyle(gDefaultTypeface); 999a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien } 100a033630e805c407080221e20b236b6054f324670Raph Levien} 101a033630e805c407080221e20b236b6054f324670Raph Levien 102a033630e805c407080221e20b236b6054f324670Raph LevienTypefaceImpl* TypefaceImpl_resolveDefault(TypefaceImpl* src) { 103a033630e805c407080221e20b236b6054f324670Raph Levien if (src == NULL) { 104a033630e805c407080221e20b236b6054f324670Raph Levien pthread_once(&gDefaultTypefaceOnce, getDefaultTypefaceOnce); 105a033630e805c407080221e20b236b6054f324670Raph Levien return gDefaultTypeface; 106a033630e805c407080221e20b236b6054f324670Raph Levien } else { 107a033630e805c407080221e20b236b6054f324670Raph Levien return src; 108a033630e805c407080221e20b236b6054f324670Raph Levien } 109a033630e805c407080221e20b236b6054f324670Raph Levien} 110a033630e805c407080221e20b236b6054f324670Raph Levien 111a033630e805c407080221e20b236b6054f324670Raph LevienTypefaceImpl* TypefaceImpl_createFromTypeface(TypefaceImpl* src, SkTypeface::Style style) { 112a033630e805c407080221e20b236b6054f324670Raph Levien TypefaceImpl* resolvedFace = TypefaceImpl_resolveDefault(src); 113a033630e805c407080221e20b236b6054f324670Raph Levien TypefaceImpl* result = new TypefaceImpl; 114a033630e805c407080221e20b236b6054f324670Raph Levien if (result != 0) { 115a033630e805c407080221e20b236b6054f324670Raph Levien result->fFontCollection = resolvedFace->fFontCollection; 11615cf4757dc0099301662f8a26da561434cc07cfaRaph Levien result->fFontCollection->Ref(); 117117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien result->fSkiaStyle = style; 118117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien result->fBaseWeight = resolvedFace->fBaseWeight; 119117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien resolveStyle(result); 120a033630e805c407080221e20b236b6054f324670Raph Levien } 121a033630e805c407080221e20b236b6054f324670Raph Levien return result; 122a033630e805c407080221e20b236b6054f324670Raph Levien} 123a033630e805c407080221e20b236b6054f324670Raph Levien 124117cbebe810613d4a6de034f02652cdbbfef4cdeRaph LevienTypefaceImpl* TypefaceImpl_createWeightAlias(TypefaceImpl* src, int weight) { 125117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien TypefaceImpl* resolvedFace = TypefaceImpl_resolveDefault(src); 126a033630e805c407080221e20b236b6054f324670Raph Levien TypefaceImpl* result = new TypefaceImpl; 127117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien if (result != 0) { 128117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien result->fFontCollection = resolvedFace->fFontCollection; 129117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien result->fFontCollection->Ref(); 130117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien result->fSkiaStyle = resolvedFace->fSkiaStyle; 131117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien result->fBaseWeight = weight; 132117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien resolveStyle(result); 133117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien } 134a033630e805c407080221e20b236b6054f324670Raph Levien return result; 135a033630e805c407080221e20b236b6054f324670Raph Levien} 136a033630e805c407080221e20b236b6054f324670Raph Levien 1371a73f732f91e97c9c66b808c245ddda36a10e987Raph LevienTypefaceImpl* TypefaceImpl_createFromFamilies(const jlong* families, size_t size) { 1381a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien std::vector<FontFamily *>familyVec; 1391a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien for (size_t i = 0; i < size; i++) { 1401a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien FontFamily* family = reinterpret_cast<FontFamily*>(families[i]); 1411a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien familyVec.push_back(family); 1421a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien } 1431a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien TypefaceImpl* result = new TypefaceImpl; 1441a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien result->fFontCollection = new FontCollection(familyVec); 1451633caef58ebd0bc3b0c5da15dde2fb425b77c43Raph Levien if (size == 0) { 1461633caef58ebd0bc3b0c5da15dde2fb425b77c43Raph Levien ALOGW("createFromFamilies creating empty collection"); 147117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien result->fSkiaStyle = SkTypeface::kNormal; 1481633caef58ebd0bc3b0c5da15dde2fb425b77c43Raph Levien } else { 1491633caef58ebd0bc3b0c5da15dde2fb425b77c43Raph Levien const FontStyle defaultStyle; 1501633caef58ebd0bc3b0c5da15dde2fb425b77c43Raph Levien FontFamily* firstFamily = reinterpret_cast<FontFamily*>(families[0]); 1511fc0fa87d42ce9268ece76b85b9edc834593e53aRaph Levien MinikinFont* mf = firstFamily->getClosestMatch(defaultStyle).font; 15227bb05f2dccf1ac2ca55515aa0f4a99cd9c548a7Raph Levien if (mf != NULL) { 15327bb05f2dccf1ac2ca55515aa0f4a99cd9c548a7Raph Levien SkTypeface* skTypeface = reinterpret_cast<MinikinFontSkia*>(mf)->GetSkTypeface(); 15427bb05f2dccf1ac2ca55515aa0f4a99cd9c548a7Raph Levien // TODO: probably better to query more precise style from family, will be important 15527bb05f2dccf1ac2ca55515aa0f4a99cd9c548a7Raph Levien // when we open up API to access 100..900 weights 156117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien result->fSkiaStyle = skTypeface->style(); 15727bb05f2dccf1ac2ca55515aa0f4a99cd9c548a7Raph Levien } else { 158117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien result->fSkiaStyle = SkTypeface::kNormal; 15927bb05f2dccf1ac2ca55515aa0f4a99cd9c548a7Raph Levien } 1601633caef58ebd0bc3b0c5da15dde2fb425b77c43Raph Levien } 161117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien result->fBaseWeight = 400; 162117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien resolveStyle(result); 1631a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien return result; 1641a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien} 1651a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien 166a033630e805c407080221e20b236b6054f324670Raph Levienvoid TypefaceImpl_unref(TypefaceImpl* face) { 167a0cba0fde3e39723052a50e1f09e3b254da6c175Raph Levien if (face != NULL) { 168a0cba0fde3e39723052a50e1f09e3b254da6c175Raph Levien face->fFontCollection->Unref(); 169a0cba0fde3e39723052a50e1f09e3b254da6c175Raph Levien } 170a033630e805c407080221e20b236b6054f324670Raph Levien delete face; 171a033630e805c407080221e20b236b6054f324670Raph Levien} 172a033630e805c407080221e20b236b6054f324670Raph Levien 173a033630e805c407080221e20b236b6054f324670Raph Levienint TypefaceImpl_getStyle(TypefaceImpl* face) { 174117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien return face->fSkiaStyle; 175a033630e805c407080221e20b236b6054f324670Raph Levien} 176a033630e805c407080221e20b236b6054f324670Raph Levien 1779a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levienvoid TypefaceImpl_setDefault(TypefaceImpl* face) { 1789a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien gDefaultTypeface = face; 1799a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien} 1809a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien 181a033630e805c407080221e20b236b6054f324670Raph Levien} 182