blob: f6d3a6ed3d8e88c7993414f256f7aad2b21b4b11 [file] [log] [blame]
Raph Leviena0336302013-05-22 16:16:59 -07001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/**
18 * This is the implementation of the Typeface object. Historically, it has
19 * just been SkTypeface, but we are migrating to Minikin. For the time
20 * being, that choice is hidden under the USE_MINIKIN compile-time flag.
21 */
22
23#include "SkStream.h"
24#include "SkTypeface.h"
25
26#ifdef USE_MINIKIN
27#include <vector>
28#include <minikin/FontCollection.h>
29#include <minikin/FontFamily.h>
30#include <minikin/Layout.h>
31#include "MinikinSkia.h"
32#endif
33
34#include "TypefaceImpl.h"
Leon Scroggins IIIb9c58ab2013-12-03 15:10:04 -050035#include "Utils.h"
Raph Leviena0336302013-05-22 16:16:59 -070036
37namespace android {
38
Raph Leviena0336302013-05-22 16:16:59 -070039#ifdef USE_MINIKIN
40
41// Any weight greater than or equal to this is considered "bold" for
42// legacy API.
43static const int kBoldThreshold = 6;
44
45static FontStyle styleFromSkiaStyle(SkTypeface::Style skiaStyle) {
46 int weight = (skiaStyle & SkTypeface::kBold) != 0 ? 7 : 4;
47 bool italic = (skiaStyle & SkTypeface::kItalic) != 0;
48 return FontStyle(weight, italic);
49}
50
51TypefaceImpl* gDefaultTypeface;
52pthread_once_t gDefaultTypefaceOnce = PTHREAD_ONCE_INIT;
53
54// TODO: this currently builds a font collection from hardcoded paths.
55// It will get replaced by an implementation that parses the XML files.
56static FontCollection *makeFontCollection() {
57 std::vector<FontFamily *>typefaces;
58 const char *fns[] = {
59 "/system/fonts/Roboto-Regular.ttf",
60 "/system/fonts/Roboto-Italic.ttf",
61 "/system/fonts/Roboto-BoldItalic.ttf",
62 "/system/fonts/Roboto-Light.ttf",
63 "/system/fonts/Roboto-Thin.ttf",
64 "/system/fonts/Roboto-Bold.ttf",
65 "/system/fonts/Roboto-ThinItalic.ttf",
66 "/system/fonts/Roboto-LightItalic.ttf"
67 };
68
69 FontFamily *family = new FontFamily();
70 for (size_t i = 0; i < sizeof(fns)/sizeof(fns[0]); i++) {
71 const char *fn = fns[i];
72 SkTypeface *skFace = SkTypeface::CreateFromFile(fn);
73 MinikinFont *font = new MinikinFontSkia(skFace);
74 family->addFont(font);
75 }
76 typefaces.push_back(family);
77
78 family = new FontFamily();
79 const char *fn = "/system/fonts/NotoSansDevanagari-Regular.ttf";
80 SkTypeface *skFace = SkTypeface::CreateFromFile(fn);
81 MinikinFont *font = new MinikinFontSkia(skFace);
82 family->addFont(font);
83 typefaces.push_back(family);
84
85 return new FontCollection(typefaces);
86}
87
88static void getDefaultTypefaceOnce() {
89 Layout::init();
90 gDefaultTypeface = new TypefaceImpl;
91 gDefaultTypeface->fFontCollection = makeFontCollection();
92 gDefaultTypeface->fStyle = FontStyle();
93}
94
95TypefaceImpl* TypefaceImpl_resolveDefault(TypefaceImpl* src) {
96 if (src == NULL) {
97 pthread_once(&gDefaultTypefaceOnce, getDefaultTypefaceOnce);
98 return gDefaultTypeface;
99 } else {
100 return src;
101 }
102}
103
104TypefaceImpl* TypefaceImpl_createFromTypeface(TypefaceImpl* src, SkTypeface::Style style) {
105 TypefaceImpl* resolvedFace = TypefaceImpl_resolveDefault(src);
106 TypefaceImpl* result = new TypefaceImpl;
107 if (result != 0) {
108 result->fFontCollection = resolvedFace->fFontCollection;
109 result->fStyle = styleFromSkiaStyle(style);
110 }
111 return result;
112}
113
114static TypefaceImpl* createFromSkTypeface(SkTypeface* typeface) {
115 MinikinFont* minikinFont = new MinikinFontSkia(typeface);
116 std::vector<FontFamily *> typefaces;
117 FontFamily* family = new FontFamily();
118 family->addFont(minikinFont);
119 typefaces.push_back(family);
120 TypefaceImpl* result = new TypefaceImpl;
121 result->fFontCollection = new FontCollection(typefaces);
122 result->fStyle = FontStyle(); // TODO: improve
123 return result;
124}
125
126TypefaceImpl* TypefaceImpl_createFromName(const char* name, SkTypeface::Style style) {
127 // TODO: should create a font collection with all styles corresponding to
128 // the name
129 SkTypeface* face = SkTypeface::CreateFromName(name, style);
130 return createFromSkTypeface(face);
131}
132
133TypefaceImpl* TypefaceImpl_createFromFile(const char* filename) {
134 SkTypeface* face = SkTypeface::CreateFromFile(filename);
135 return createFromSkTypeface(face);
136}
137
138TypefaceImpl* TypefaceImpl_createFromAsset(Asset* asset) {
Leon Scroggins IIIb9c58ab2013-12-03 15:10:04 -0500139 SkStream* stream = new AssetStreamAdaptor(asset,
140 AssetStreamAdaptor::kYes_OwnAsset,
141 AssetStreamAdaptor::kYes_HasMemoryBase);
Raph Leviena0336302013-05-22 16:16:59 -0700142 SkTypeface* face = SkTypeface::CreateFromStream(stream);
143 // SkTypeFace::CreateFromStream calls ref() on the stream, so we
144 // need to unref it here or it won't be freed later on
145 stream->unref();
146 return createFromSkTypeface(face);
147}
148
149void TypefaceImpl_unref(TypefaceImpl* face) {
150 delete face;
151}
152
153int TypefaceImpl_getStyle(TypefaceImpl* face) {
154 FontStyle style = face->fStyle;
155 int result = style.getItalic() ? SkTypeface::kItalic : 0;
156 if (style.getWeight() >= kBoldThreshold) {
157 result |= SkTypeface::kBold;
158 }
159 return result;
160}
161
162#else // USE_MINIKIN
163
164/* Just use SkTypeface instead. */
165
166typedef SkTypeface TypefaceImpl;
167
168TypefaceImpl* TypefaceImpl_createFromTypeface(TypefaceImpl* src, SkTypeface::Style style) {
169 return SkTypeface::CreateFromTypeface(src, style);
170}
171
172TypefaceImpl* TypefaceImpl_createFromName(const char* name, SkTypeface::Style style) {
173 return SkTypeface::CreateFromName(name, style);
174}
175
176TypefaceImpl* TypefaceImpl_createFromFile(const char* filename) {
177 return SkTypeface::CreateFromFile(filename);
178}
179
180TypefaceImpl* TypefaceImpl_createFromAsset(Asset* asset) {
Leon Scroggins IIIb9c58ab2013-12-03 15:10:04 -0500181 SkStream* stream = new AssetStreamAdaptor(asset,
182 AssetStreamAdaptor::kYes_OwnAsset,
183 AssetStreamAdaptor::kYes_HasMemoryBase);
Raph Leviena0336302013-05-22 16:16:59 -0700184 SkTypeface* face = SkTypeface::CreateFromStream(stream);
185 // SkTypeFace::CreateFromStream calls ref() on the stream, so we
186 // need to unref it here or it won't be freed later on
187 stream->unref();
188
189 return face;
190}
191
192void TypefaceImpl_unref(TypefaceImpl* face) {
193 SkSafeUnref(face);
194}
195
196int TypefaceImpl_getStyle(TypefaceImpl* face) {
197 return face->style();
198}
199
200#endif // USE_MINIKIN
201
202}