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