TypefaceImpl.cpp revision 1a73f732f91e97c9c66b808c245ddda36a10e987
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
55a033630e805c407080221e20b236b6054f324670Raph LevienTypefaceImpl* gDefaultTypeface;
56a033630e805c407080221e20b236b6054f324670Raph Levienpthread_once_t gDefaultTypefaceOnce = PTHREAD_ONCE_INIT;
57a033630e805c407080221e20b236b6054f324670Raph Levien
58a033630e805c407080221e20b236b6054f324670Raph Levien// TODO: this currently builds a font collection from hardcoded paths.
59a033630e805c407080221e20b236b6054f324670Raph Levien// It will get replaced by an implementation that parses the XML files.
60a033630e805c407080221e20b236b6054f324670Raph Levienstatic FontCollection *makeFontCollection() {
61a033630e805c407080221e20b236b6054f324670Raph Levien    std::vector<FontFamily *>typefaces;
62a033630e805c407080221e20b236b6054f324670Raph Levien    const char *fns[] = {
63a033630e805c407080221e20b236b6054f324670Raph Levien        "/system/fonts/Roboto-Regular.ttf",
64a033630e805c407080221e20b236b6054f324670Raph Levien        "/system/fonts/Roboto-Italic.ttf",
65a033630e805c407080221e20b236b6054f324670Raph Levien        "/system/fonts/Roboto-BoldItalic.ttf",
66a033630e805c407080221e20b236b6054f324670Raph Levien        "/system/fonts/Roboto-Light.ttf",
67a033630e805c407080221e20b236b6054f324670Raph Levien        "/system/fonts/Roboto-Thin.ttf",
68a033630e805c407080221e20b236b6054f324670Raph Levien        "/system/fonts/Roboto-Bold.ttf",
69a033630e805c407080221e20b236b6054f324670Raph Levien        "/system/fonts/Roboto-ThinItalic.ttf",
70a033630e805c407080221e20b236b6054f324670Raph Levien        "/system/fonts/Roboto-LightItalic.ttf"
71a033630e805c407080221e20b236b6054f324670Raph Levien    };
72a033630e805c407080221e20b236b6054f324670Raph Levien
73a033630e805c407080221e20b236b6054f324670Raph Levien    FontFamily *family = new FontFamily();
74a033630e805c407080221e20b236b6054f324670Raph Levien    for (size_t i = 0; i < sizeof(fns)/sizeof(fns[0]); i++) {
75a033630e805c407080221e20b236b6054f324670Raph Levien        const char *fn = fns[i];
76a033630e805c407080221e20b236b6054f324670Raph Levien        SkTypeface *skFace = SkTypeface::CreateFromFile(fn);
77a033630e805c407080221e20b236b6054f324670Raph Levien        MinikinFont *font = new MinikinFontSkia(skFace);
78a033630e805c407080221e20b236b6054f324670Raph Levien        family->addFont(font);
79a033630e805c407080221e20b236b6054f324670Raph Levien    }
80a033630e805c407080221e20b236b6054f324670Raph Levien    typefaces.push_back(family);
81a033630e805c407080221e20b236b6054f324670Raph Levien
82a033630e805c407080221e20b236b6054f324670Raph Levien    family = new FontFamily();
83a033630e805c407080221e20b236b6054f324670Raph Levien    const char *fn = "/system/fonts/NotoSansDevanagari-Regular.ttf";
84a033630e805c407080221e20b236b6054f324670Raph Levien    SkTypeface *skFace = SkTypeface::CreateFromFile(fn);
85a033630e805c407080221e20b236b6054f324670Raph Levien    MinikinFont *font = new MinikinFontSkia(skFace);
86a033630e805c407080221e20b236b6054f324670Raph Levien    family->addFont(font);
87a033630e805c407080221e20b236b6054f324670Raph Levien    typefaces.push_back(family);
88a033630e805c407080221e20b236b6054f324670Raph Levien
89a033630e805c407080221e20b236b6054f324670Raph Levien    return new FontCollection(typefaces);
90a033630e805c407080221e20b236b6054f324670Raph Levien}
91a033630e805c407080221e20b236b6054f324670Raph Levien
92a033630e805c407080221e20b236b6054f324670Raph Levienstatic void getDefaultTypefaceOnce() {
93a033630e805c407080221e20b236b6054f324670Raph Levien    Layout::init();
94a033630e805c407080221e20b236b6054f324670Raph Levien    gDefaultTypeface = new TypefaceImpl;
95a033630e805c407080221e20b236b6054f324670Raph Levien    gDefaultTypeface->fFontCollection = makeFontCollection();
96a033630e805c407080221e20b236b6054f324670Raph Levien    gDefaultTypeface->fStyle = FontStyle();
97a033630e805c407080221e20b236b6054f324670Raph Levien}
98a033630e805c407080221e20b236b6054f324670Raph Levien
99a033630e805c407080221e20b236b6054f324670Raph LevienTypefaceImpl* TypefaceImpl_resolveDefault(TypefaceImpl* src) {
100a033630e805c407080221e20b236b6054f324670Raph Levien    if (src == NULL) {
101a033630e805c407080221e20b236b6054f324670Raph Levien        pthread_once(&gDefaultTypefaceOnce, getDefaultTypefaceOnce);
102a033630e805c407080221e20b236b6054f324670Raph Levien        return gDefaultTypeface;
103a033630e805c407080221e20b236b6054f324670Raph Levien    } else {
104a033630e805c407080221e20b236b6054f324670Raph Levien        return src;
105a033630e805c407080221e20b236b6054f324670Raph Levien    }
106a033630e805c407080221e20b236b6054f324670Raph Levien}
107a033630e805c407080221e20b236b6054f324670Raph Levien
108a033630e805c407080221e20b236b6054f324670Raph LevienTypefaceImpl* TypefaceImpl_createFromTypeface(TypefaceImpl* src, SkTypeface::Style style) {
109a033630e805c407080221e20b236b6054f324670Raph Levien    TypefaceImpl* resolvedFace = TypefaceImpl_resolveDefault(src);
110a033630e805c407080221e20b236b6054f324670Raph Levien    TypefaceImpl* result = new TypefaceImpl;
111a033630e805c407080221e20b236b6054f324670Raph Levien    if (result != 0) {
112a033630e805c407080221e20b236b6054f324670Raph Levien        result->fFontCollection = resolvedFace->fFontCollection;
113a033630e805c407080221e20b236b6054f324670Raph Levien        result->fStyle = styleFromSkiaStyle(style);
114a033630e805c407080221e20b236b6054f324670Raph Levien    }
115a033630e805c407080221e20b236b6054f324670Raph Levien    return result;
116a033630e805c407080221e20b236b6054f324670Raph Levien}
117a033630e805c407080221e20b236b6054f324670Raph Levien
118a033630e805c407080221e20b236b6054f324670Raph Levienstatic TypefaceImpl* createFromSkTypeface(SkTypeface* typeface) {
119a033630e805c407080221e20b236b6054f324670Raph Levien    MinikinFont* minikinFont = new MinikinFontSkia(typeface);
120a033630e805c407080221e20b236b6054f324670Raph Levien    std::vector<FontFamily *> typefaces;
121a033630e805c407080221e20b236b6054f324670Raph Levien    FontFamily* family = new FontFamily();
122a033630e805c407080221e20b236b6054f324670Raph Levien    family->addFont(minikinFont);
123a033630e805c407080221e20b236b6054f324670Raph Levien    typefaces.push_back(family);
124a033630e805c407080221e20b236b6054f324670Raph Levien    TypefaceImpl* result = new TypefaceImpl;
125a033630e805c407080221e20b236b6054f324670Raph Levien    result->fFontCollection = new FontCollection(typefaces);
126a033630e805c407080221e20b236b6054f324670Raph Levien    result->fStyle = FontStyle();  // TODO: improve
127a033630e805c407080221e20b236b6054f324670Raph Levien    return result;
128a033630e805c407080221e20b236b6054f324670Raph Levien}
129a033630e805c407080221e20b236b6054f324670Raph Levien
130a033630e805c407080221e20b236b6054f324670Raph LevienTypefaceImpl* TypefaceImpl_createFromName(const char* name, SkTypeface::Style style) {
131a033630e805c407080221e20b236b6054f324670Raph Levien    // TODO: should create a font collection with all styles corresponding to
132a033630e805c407080221e20b236b6054f324670Raph Levien    // the name
133a033630e805c407080221e20b236b6054f324670Raph Levien    SkTypeface* face = SkTypeface::CreateFromName(name, style);
134a033630e805c407080221e20b236b6054f324670Raph Levien    return createFromSkTypeface(face);
135a033630e805c407080221e20b236b6054f324670Raph Levien}
136a033630e805c407080221e20b236b6054f324670Raph Levien
137a033630e805c407080221e20b236b6054f324670Raph LevienTypefaceImpl* TypefaceImpl_createFromFile(const char* filename) {
138a033630e805c407080221e20b236b6054f324670Raph Levien    SkTypeface* face = SkTypeface::CreateFromFile(filename);
139a033630e805c407080221e20b236b6054f324670Raph Levien    return createFromSkTypeface(face);
140a033630e805c407080221e20b236b6054f324670Raph Levien}
141a033630e805c407080221e20b236b6054f324670Raph Levien
142a033630e805c407080221e20b236b6054f324670Raph LevienTypefaceImpl* TypefaceImpl_createFromAsset(Asset* asset) {
143b9c58ab617c257dbece105167b21e94faad67320Leon Scroggins III    SkStream* stream = new AssetStreamAdaptor(asset,
144b9c58ab617c257dbece105167b21e94faad67320Leon Scroggins III                                              AssetStreamAdaptor::kYes_OwnAsset,
145b9c58ab617c257dbece105167b21e94faad67320Leon Scroggins III                                              AssetStreamAdaptor::kYes_HasMemoryBase);
146a033630e805c407080221e20b236b6054f324670Raph Levien    SkTypeface* face = SkTypeface::CreateFromStream(stream);
147a033630e805c407080221e20b236b6054f324670Raph Levien    // SkTypeFace::CreateFromStream calls ref() on the stream, so we
148a033630e805c407080221e20b236b6054f324670Raph Levien    // need to unref it here or it won't be freed later on
149a033630e805c407080221e20b236b6054f324670Raph Levien    stream->unref();
150a033630e805c407080221e20b236b6054f324670Raph Levien    return createFromSkTypeface(face);
151a033630e805c407080221e20b236b6054f324670Raph Levien}
152a033630e805c407080221e20b236b6054f324670Raph Levien
1531a73f732f91e97c9c66b808c245ddda36a10e987Raph LevienTypefaceImpl* TypefaceImpl_createFromFamilies(const jlong* families, size_t size) {
1541a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien    ALOGD("createFromFamilies size=%d", size);
1551a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien    std::vector<FontFamily *>familyVec;
1561a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien    for (size_t i = 0; i < size; i++) {
1571a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien        FontFamily* family = reinterpret_cast<FontFamily*>(families[i]);
1581a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien        familyVec.push_back(family);
1591a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien    }
1601a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien    TypefaceImpl* result = new TypefaceImpl;
1611a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien    result->fFontCollection = new FontCollection(familyVec);
1621a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien    result->fStyle = FontStyle();  // TODO: improve
1631a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien    return result;
1641a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien}
1651a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien
166a033630e805c407080221e20b236b6054f324670Raph Levienvoid TypefaceImpl_unref(TypefaceImpl* face) {
167a033630e805c407080221e20b236b6054f324670Raph Levien    delete face;
168a033630e805c407080221e20b236b6054f324670Raph Levien}
169a033630e805c407080221e20b236b6054f324670Raph Levien
170a033630e805c407080221e20b236b6054f324670Raph Levienint TypefaceImpl_getStyle(TypefaceImpl* face) {
171a033630e805c407080221e20b236b6054f324670Raph Levien    FontStyle style = face->fStyle;
172a033630e805c407080221e20b236b6054f324670Raph Levien    int result = style.getItalic() ? SkTypeface::kItalic : 0;
173a033630e805c407080221e20b236b6054f324670Raph Levien    if (style.getWeight() >= kBoldThreshold) {
174a033630e805c407080221e20b236b6054f324670Raph Levien        result |= SkTypeface::kBold;
175a033630e805c407080221e20b236b6054f324670Raph Levien    }
176a033630e805c407080221e20b236b6054f324670Raph Levien    return result;
177a033630e805c407080221e20b236b6054f324670Raph Levien}
178a033630e805c407080221e20b236b6054f324670Raph Levien
179a033630e805c407080221e20b236b6054f324670Raph Levien#else  // USE_MINIKIN
180a033630e805c407080221e20b236b6054f324670Raph Levien
181a033630e805c407080221e20b236b6054f324670Raph Levien/* Just use SkTypeface instead. */
182a033630e805c407080221e20b236b6054f324670Raph Levien
183a033630e805c407080221e20b236b6054f324670Raph Levientypedef SkTypeface TypefaceImpl;
184a033630e805c407080221e20b236b6054f324670Raph Levien
185a033630e805c407080221e20b236b6054f324670Raph LevienTypefaceImpl* TypefaceImpl_createFromTypeface(TypefaceImpl* src, SkTypeface::Style style) {
186a033630e805c407080221e20b236b6054f324670Raph Levien    return SkTypeface::CreateFromTypeface(src, style);
187a033630e805c407080221e20b236b6054f324670Raph Levien}
188a033630e805c407080221e20b236b6054f324670Raph Levien
189a033630e805c407080221e20b236b6054f324670Raph LevienTypefaceImpl* TypefaceImpl_createFromName(const char* name, SkTypeface::Style style) {
190a033630e805c407080221e20b236b6054f324670Raph Levien    return SkTypeface::CreateFromName(name, style);
191a033630e805c407080221e20b236b6054f324670Raph Levien}
192a033630e805c407080221e20b236b6054f324670Raph Levien
193a033630e805c407080221e20b236b6054f324670Raph LevienTypefaceImpl* TypefaceImpl_createFromFile(const char* filename) {
194a033630e805c407080221e20b236b6054f324670Raph Levien    return SkTypeface::CreateFromFile(filename);
195a033630e805c407080221e20b236b6054f324670Raph Levien}
196a033630e805c407080221e20b236b6054f324670Raph Levien
197a033630e805c407080221e20b236b6054f324670Raph LevienTypefaceImpl* TypefaceImpl_createFromAsset(Asset* asset) {
198b9c58ab617c257dbece105167b21e94faad67320Leon Scroggins III    SkStream* stream = new AssetStreamAdaptor(asset,
199b9c58ab617c257dbece105167b21e94faad67320Leon Scroggins III                                              AssetStreamAdaptor::kYes_OwnAsset,
200b9c58ab617c257dbece105167b21e94faad67320Leon Scroggins III                                              AssetStreamAdaptor::kYes_HasMemoryBase);
201a033630e805c407080221e20b236b6054f324670Raph Levien    SkTypeface* face = SkTypeface::CreateFromStream(stream);
202a033630e805c407080221e20b236b6054f324670Raph Levien    // SkTypeFace::CreateFromStream calls ref() on the stream, so we
203a033630e805c407080221e20b236b6054f324670Raph Levien    // need to unref it here or it won't be freed later on
204a033630e805c407080221e20b236b6054f324670Raph Levien    stream->unref();
205a033630e805c407080221e20b236b6054f324670Raph Levien
206a033630e805c407080221e20b236b6054f324670Raph Levien    return face;
207a033630e805c407080221e20b236b6054f324670Raph Levien}
208a033630e805c407080221e20b236b6054f324670Raph Levien
2091a73f732f91e97c9c66b808c245ddda36a10e987Raph LevienTypefaceImpl* TypefaceImpl_createFromFamilies(const jlong* families, size_t size) {
2101a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien    // Should never be called in non-Minikin builds
2111a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien    return 0;
2121a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien}
2131a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien
214a033630e805c407080221e20b236b6054f324670Raph Levienvoid TypefaceImpl_unref(TypefaceImpl* face) {
215a033630e805c407080221e20b236b6054f324670Raph Levien    SkSafeUnref(face);
216a033630e805c407080221e20b236b6054f324670Raph Levien}
217a033630e805c407080221e20b236b6054f324670Raph Levien
218a033630e805c407080221e20b236b6054f324670Raph Levienint TypefaceImpl_getStyle(TypefaceImpl* face) {
219a033630e805c407080221e20b236b6054f324670Raph Levien    return face->style();
220a033630e805c407080221e20b236b6054f324670Raph Levien}
221a033630e805c407080221e20b236b6054f324670Raph Levien
222a033630e805c407080221e20b236b6054f324670Raph Levien#endif  // USE_MINIKIN
223a033630e805c407080221e20b236b6054f324670Raph Levien
224a033630e805c407080221e20b236b6054f324670Raph Levien}
225