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