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