TypefaceImpl.cpp revision b9c58ab617c257dbece105167b21e94faad67320
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
23a033630e805c407080221e20b236b6054f324670Raph Levien#include "SkStream.h"
24a033630e805c407080221e20b236b6054f324670Raph Levien#include "SkTypeface.h"
25a033630e805c407080221e20b236b6054f324670Raph Levien
26a033630e805c407080221e20b236b6054f324670Raph Levien#ifdef USE_MINIKIN
27a033630e805c407080221e20b236b6054f324670Raph Levien#include <vector>
28a033630e805c407080221e20b236b6054f324670Raph Levien#include <minikin/FontCollection.h>
29a033630e805c407080221e20b236b6054f324670Raph Levien#include <minikin/FontFamily.h>
30a033630e805c407080221e20b236b6054f324670Raph Levien#include <minikin/Layout.h>
31a033630e805c407080221e20b236b6054f324670Raph Levien#include "MinikinSkia.h"
32a033630e805c407080221e20b236b6054f324670Raph Levien#endif
33a033630e805c407080221e20b236b6054f324670Raph Levien
34a033630e805c407080221e20b236b6054f324670Raph Levien#include "TypefaceImpl.h"
35b9c58ab617c257dbece105167b21e94faad67320Leon Scroggins III#include "Utils.h"
36a033630e805c407080221e20b236b6054f324670Raph Levien
37a033630e805c407080221e20b236b6054f324670Raph Leviennamespace android {
38a033630e805c407080221e20b236b6054f324670Raph Levien
39a033630e805c407080221e20b236b6054f324670Raph Levien#ifdef USE_MINIKIN
40a033630e805c407080221e20b236b6054f324670Raph Levien
41a033630e805c407080221e20b236b6054f324670Raph Levien// Any weight greater than or equal to this is considered "bold" for
42a033630e805c407080221e20b236b6054f324670Raph Levien// legacy API.
43a033630e805c407080221e20b236b6054f324670Raph Levienstatic const int kBoldThreshold = 6;
44a033630e805c407080221e20b236b6054f324670Raph Levien
45a033630e805c407080221e20b236b6054f324670Raph Levienstatic FontStyle styleFromSkiaStyle(SkTypeface::Style skiaStyle) {
46a033630e805c407080221e20b236b6054f324670Raph Levien    int weight = (skiaStyle & SkTypeface::kBold) != 0 ? 7 : 4;
47a033630e805c407080221e20b236b6054f324670Raph Levien    bool italic = (skiaStyle & SkTypeface::kItalic) != 0;
48a033630e805c407080221e20b236b6054f324670Raph Levien    return FontStyle(weight, italic);
49a033630e805c407080221e20b236b6054f324670Raph Levien}
50a033630e805c407080221e20b236b6054f324670Raph Levien
51a033630e805c407080221e20b236b6054f324670Raph LevienTypefaceImpl* gDefaultTypeface;
52a033630e805c407080221e20b236b6054f324670Raph Levienpthread_once_t gDefaultTypefaceOnce = PTHREAD_ONCE_INIT;
53a033630e805c407080221e20b236b6054f324670Raph Levien
54a033630e805c407080221e20b236b6054f324670Raph Levien// TODO: this currently builds a font collection from hardcoded paths.
55a033630e805c407080221e20b236b6054f324670Raph Levien// It will get replaced by an implementation that parses the XML files.
56a033630e805c407080221e20b236b6054f324670Raph Levienstatic FontCollection *makeFontCollection() {
57a033630e805c407080221e20b236b6054f324670Raph Levien    std::vector<FontFamily *>typefaces;
58a033630e805c407080221e20b236b6054f324670Raph Levien    const char *fns[] = {
59a033630e805c407080221e20b236b6054f324670Raph Levien        "/system/fonts/Roboto-Regular.ttf",
60a033630e805c407080221e20b236b6054f324670Raph Levien        "/system/fonts/Roboto-Italic.ttf",
61a033630e805c407080221e20b236b6054f324670Raph Levien        "/system/fonts/Roboto-BoldItalic.ttf",
62a033630e805c407080221e20b236b6054f324670Raph Levien        "/system/fonts/Roboto-Light.ttf",
63a033630e805c407080221e20b236b6054f324670Raph Levien        "/system/fonts/Roboto-Thin.ttf",
64a033630e805c407080221e20b236b6054f324670Raph Levien        "/system/fonts/Roboto-Bold.ttf",
65a033630e805c407080221e20b236b6054f324670Raph Levien        "/system/fonts/Roboto-ThinItalic.ttf",
66a033630e805c407080221e20b236b6054f324670Raph Levien        "/system/fonts/Roboto-LightItalic.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];
72a033630e805c407080221e20b236b6054f324670Raph Levien        SkTypeface *skFace = SkTypeface::CreateFromFile(fn);
73a033630e805c407080221e20b236b6054f324670Raph Levien        MinikinFont *font = new MinikinFontSkia(skFace);
74a033630e805c407080221e20b236b6054f324670Raph Levien        family->addFont(font);
75a033630e805c407080221e20b236b6054f324670Raph Levien    }
76a033630e805c407080221e20b236b6054f324670Raph Levien    typefaces.push_back(family);
77a033630e805c407080221e20b236b6054f324670Raph Levien
78a033630e805c407080221e20b236b6054f324670Raph Levien    family = new FontFamily();
79a033630e805c407080221e20b236b6054f324670Raph Levien    const char *fn = "/system/fonts/NotoSansDevanagari-Regular.ttf";
80a033630e805c407080221e20b236b6054f324670Raph Levien    SkTypeface *skFace = SkTypeface::CreateFromFile(fn);
81a033630e805c407080221e20b236b6054f324670Raph Levien    MinikinFont *font = new MinikinFontSkia(skFace);
82a033630e805c407080221e20b236b6054f324670Raph Levien    family->addFont(font);
83a033630e805c407080221e20b236b6054f324670Raph Levien    typefaces.push_back(family);
84a033630e805c407080221e20b236b6054f324670Raph Levien
85a033630e805c407080221e20b236b6054f324670Raph Levien    return new FontCollection(typefaces);
86a033630e805c407080221e20b236b6054f324670Raph Levien}
87a033630e805c407080221e20b236b6054f324670Raph Levien
88a033630e805c407080221e20b236b6054f324670Raph Levienstatic void getDefaultTypefaceOnce() {
89a033630e805c407080221e20b236b6054f324670Raph Levien    Layout::init();
90a033630e805c407080221e20b236b6054f324670Raph Levien    gDefaultTypeface = new TypefaceImpl;
91a033630e805c407080221e20b236b6054f324670Raph Levien    gDefaultTypeface->fFontCollection = makeFontCollection();
92a033630e805c407080221e20b236b6054f324670Raph Levien    gDefaultTypeface->fStyle = FontStyle();
93a033630e805c407080221e20b236b6054f324670Raph Levien}
94a033630e805c407080221e20b236b6054f324670Raph Levien
95a033630e805c407080221e20b236b6054f324670Raph LevienTypefaceImpl* TypefaceImpl_resolveDefault(TypefaceImpl* src) {
96a033630e805c407080221e20b236b6054f324670Raph Levien    if (src == NULL) {
97a033630e805c407080221e20b236b6054f324670Raph Levien        pthread_once(&gDefaultTypefaceOnce, getDefaultTypefaceOnce);
98a033630e805c407080221e20b236b6054f324670Raph Levien        return gDefaultTypeface;
99a033630e805c407080221e20b236b6054f324670Raph Levien    } else {
100a033630e805c407080221e20b236b6054f324670Raph Levien        return src;
101a033630e805c407080221e20b236b6054f324670Raph Levien    }
102a033630e805c407080221e20b236b6054f324670Raph Levien}
103a033630e805c407080221e20b236b6054f324670Raph Levien
104a033630e805c407080221e20b236b6054f324670Raph LevienTypefaceImpl* TypefaceImpl_createFromTypeface(TypefaceImpl* src, SkTypeface::Style style) {
105a033630e805c407080221e20b236b6054f324670Raph Levien    TypefaceImpl* resolvedFace = TypefaceImpl_resolveDefault(src);
106a033630e805c407080221e20b236b6054f324670Raph Levien    TypefaceImpl* result = new TypefaceImpl;
107a033630e805c407080221e20b236b6054f324670Raph Levien    if (result != 0) {
108a033630e805c407080221e20b236b6054f324670Raph Levien        result->fFontCollection = resolvedFace->fFontCollection;
109a033630e805c407080221e20b236b6054f324670Raph Levien        result->fStyle = styleFromSkiaStyle(style);
110a033630e805c407080221e20b236b6054f324670Raph Levien    }
111a033630e805c407080221e20b236b6054f324670Raph Levien    return result;
112a033630e805c407080221e20b236b6054f324670Raph Levien}
113a033630e805c407080221e20b236b6054f324670Raph Levien
114a033630e805c407080221e20b236b6054f324670Raph Levienstatic TypefaceImpl* createFromSkTypeface(SkTypeface* typeface) {
115a033630e805c407080221e20b236b6054f324670Raph Levien    MinikinFont* minikinFont = new MinikinFontSkia(typeface);
116a033630e805c407080221e20b236b6054f324670Raph Levien    std::vector<FontFamily *> typefaces;
117a033630e805c407080221e20b236b6054f324670Raph Levien    FontFamily* family = new FontFamily();
118a033630e805c407080221e20b236b6054f324670Raph Levien    family->addFont(minikinFont);
119a033630e805c407080221e20b236b6054f324670Raph Levien    typefaces.push_back(family);
120a033630e805c407080221e20b236b6054f324670Raph Levien    TypefaceImpl* result = new TypefaceImpl;
121a033630e805c407080221e20b236b6054f324670Raph Levien    result->fFontCollection = new FontCollection(typefaces);
122a033630e805c407080221e20b236b6054f324670Raph Levien    result->fStyle = FontStyle();  // TODO: improve
123a033630e805c407080221e20b236b6054f324670Raph Levien    return result;
124a033630e805c407080221e20b236b6054f324670Raph Levien}
125a033630e805c407080221e20b236b6054f324670Raph Levien
126a033630e805c407080221e20b236b6054f324670Raph LevienTypefaceImpl* TypefaceImpl_createFromName(const char* name, SkTypeface::Style style) {
127a033630e805c407080221e20b236b6054f324670Raph Levien    // TODO: should create a font collection with all styles corresponding to
128a033630e805c407080221e20b236b6054f324670Raph Levien    // the name
129a033630e805c407080221e20b236b6054f324670Raph Levien    SkTypeface* face = SkTypeface::CreateFromName(name, style);
130a033630e805c407080221e20b236b6054f324670Raph Levien    return createFromSkTypeface(face);
131a033630e805c407080221e20b236b6054f324670Raph Levien}
132a033630e805c407080221e20b236b6054f324670Raph Levien
133a033630e805c407080221e20b236b6054f324670Raph LevienTypefaceImpl* TypefaceImpl_createFromFile(const char* filename) {
134a033630e805c407080221e20b236b6054f324670Raph Levien    SkTypeface* face = SkTypeface::CreateFromFile(filename);
135a033630e805c407080221e20b236b6054f324670Raph Levien    return createFromSkTypeface(face);
136a033630e805c407080221e20b236b6054f324670Raph Levien}
137a033630e805c407080221e20b236b6054f324670Raph Levien
138a033630e805c407080221e20b236b6054f324670Raph LevienTypefaceImpl* TypefaceImpl_createFromAsset(Asset* asset) {
139b9c58ab617c257dbece105167b21e94faad67320Leon Scroggins III    SkStream* stream = new AssetStreamAdaptor(asset,
140b9c58ab617c257dbece105167b21e94faad67320Leon Scroggins III                                              AssetStreamAdaptor::kYes_OwnAsset,
141b9c58ab617c257dbece105167b21e94faad67320Leon Scroggins III                                              AssetStreamAdaptor::kYes_HasMemoryBase);
142a033630e805c407080221e20b236b6054f324670Raph Levien    SkTypeface* face = SkTypeface::CreateFromStream(stream);
143a033630e805c407080221e20b236b6054f324670Raph Levien    // SkTypeFace::CreateFromStream calls ref() on the stream, so we
144a033630e805c407080221e20b236b6054f324670Raph Levien    // need to unref it here or it won't be freed later on
145a033630e805c407080221e20b236b6054f324670Raph Levien    stream->unref();
146a033630e805c407080221e20b236b6054f324670Raph Levien    return createFromSkTypeface(face);
147a033630e805c407080221e20b236b6054f324670Raph Levien}
148a033630e805c407080221e20b236b6054f324670Raph Levien
149a033630e805c407080221e20b236b6054f324670Raph Levienvoid TypefaceImpl_unref(TypefaceImpl* face) {
150a033630e805c407080221e20b236b6054f324670Raph Levien    delete face;
151a033630e805c407080221e20b236b6054f324670Raph Levien}
152a033630e805c407080221e20b236b6054f324670Raph Levien
153a033630e805c407080221e20b236b6054f324670Raph Levienint TypefaceImpl_getStyle(TypefaceImpl* face) {
154a033630e805c407080221e20b236b6054f324670Raph Levien    FontStyle style = face->fStyle;
155a033630e805c407080221e20b236b6054f324670Raph Levien    int result = style.getItalic() ? SkTypeface::kItalic : 0;
156a033630e805c407080221e20b236b6054f324670Raph Levien    if (style.getWeight() >= kBoldThreshold) {
157a033630e805c407080221e20b236b6054f324670Raph Levien        result |= SkTypeface::kBold;
158a033630e805c407080221e20b236b6054f324670Raph Levien    }
159a033630e805c407080221e20b236b6054f324670Raph Levien    return result;
160a033630e805c407080221e20b236b6054f324670Raph Levien}
161a033630e805c407080221e20b236b6054f324670Raph Levien
162a033630e805c407080221e20b236b6054f324670Raph Levien#else  // USE_MINIKIN
163a033630e805c407080221e20b236b6054f324670Raph Levien
164a033630e805c407080221e20b236b6054f324670Raph Levien/* Just use SkTypeface instead. */
165a033630e805c407080221e20b236b6054f324670Raph Levien
166a033630e805c407080221e20b236b6054f324670Raph Levientypedef SkTypeface TypefaceImpl;
167a033630e805c407080221e20b236b6054f324670Raph Levien
168a033630e805c407080221e20b236b6054f324670Raph LevienTypefaceImpl* TypefaceImpl_createFromTypeface(TypefaceImpl* src, SkTypeface::Style style) {
169a033630e805c407080221e20b236b6054f324670Raph Levien    return SkTypeface::CreateFromTypeface(src, style);
170a033630e805c407080221e20b236b6054f324670Raph Levien}
171a033630e805c407080221e20b236b6054f324670Raph Levien
172a033630e805c407080221e20b236b6054f324670Raph LevienTypefaceImpl* TypefaceImpl_createFromName(const char* name, SkTypeface::Style style) {
173a033630e805c407080221e20b236b6054f324670Raph Levien    return SkTypeface::CreateFromName(name, style);
174a033630e805c407080221e20b236b6054f324670Raph Levien}
175a033630e805c407080221e20b236b6054f324670Raph Levien
176a033630e805c407080221e20b236b6054f324670Raph LevienTypefaceImpl* TypefaceImpl_createFromFile(const char* filename) {
177a033630e805c407080221e20b236b6054f324670Raph Levien    return SkTypeface::CreateFromFile(filename);
178a033630e805c407080221e20b236b6054f324670Raph Levien}
179a033630e805c407080221e20b236b6054f324670Raph Levien
180a033630e805c407080221e20b236b6054f324670Raph LevienTypefaceImpl* TypefaceImpl_createFromAsset(Asset* asset) {
181b9c58ab617c257dbece105167b21e94faad67320Leon Scroggins III    SkStream* stream = new AssetStreamAdaptor(asset,
182b9c58ab617c257dbece105167b21e94faad67320Leon Scroggins III                                              AssetStreamAdaptor::kYes_OwnAsset,
183b9c58ab617c257dbece105167b21e94faad67320Leon Scroggins III                                              AssetStreamAdaptor::kYes_HasMemoryBase);
184a033630e805c407080221e20b236b6054f324670Raph Levien    SkTypeface* face = SkTypeface::CreateFromStream(stream);
185a033630e805c407080221e20b236b6054f324670Raph Levien    // SkTypeFace::CreateFromStream calls ref() on the stream, so we
186a033630e805c407080221e20b236b6054f324670Raph Levien    // need to unref it here or it won't be freed later on
187a033630e805c407080221e20b236b6054f324670Raph Levien    stream->unref();
188a033630e805c407080221e20b236b6054f324670Raph Levien
189a033630e805c407080221e20b236b6054f324670Raph Levien    return face;
190a033630e805c407080221e20b236b6054f324670Raph Levien}
191a033630e805c407080221e20b236b6054f324670Raph Levien
192a033630e805c407080221e20b236b6054f324670Raph Levienvoid TypefaceImpl_unref(TypefaceImpl* face) {
193a033630e805c407080221e20b236b6054f324670Raph Levien    SkSafeUnref(face);
194a033630e805c407080221e20b236b6054f324670Raph Levien}
195a033630e805c407080221e20b236b6054f324670Raph Levien
196a033630e805c407080221e20b236b6054f324670Raph Levienint TypefaceImpl_getStyle(TypefaceImpl* face) {
197a033630e805c407080221e20b236b6054f324670Raph Levien    return face->style();
198a033630e805c407080221e20b236b6054f324670Raph Levien}
199a033630e805c407080221e20b236b6054f324670Raph Levien
200a033630e805c407080221e20b236b6054f324670Raph Levien#endif  // USE_MINIKIN
201a033630e805c407080221e20b236b6054f324670Raph Levien
202a033630e805c407080221e20b236b6054f324670Raph Levien}
203