Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(41)

Side by Side Diff: src/ports/SkFontMgr_android.cpp

Issue 414483002: SkFontMgr for Android. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Rebase and add index. Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/ports/SkFontConfigParser_android.cpp ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright 2014 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "SkFontConfigParser_android.h"
9 #include "SkFontDescriptor.h"
10 #include "SkFontHost_FreeType_common.h"
11 #include "SkFontMgr.h"
12 #include "SkFontStyle.h"
13 #include "SkStream.h"
14 #include "SkTDArray.h"
15 #include "SkTSearch.h"
16 #include "SkTypeface.h"
17 #include "SkTypefaceCache.h"
18
19 #include <limits>
20 #include <stdlib.h>
21
22 #ifndef SK_FONT_FILE_PREFIX
23 # define SK_FONT_FILE_PREFIX "/fonts/"
24 #endif
25
26 #ifndef SK_DEBUG_FONTS
27 #define SK_DEBUG_FONTS 0
28 #endif
29
30 #if SK_DEBUG_FONTS
31 # define DEBUG_FONT(args) SkDebugf args
32 #else
33 # define DEBUG_FONT(args)
34 #endif
35
36 class SkTypeface_Android : public SkTypeface_FreeType {
37 public:
38 SkTypeface_Android(int index,
39 Style style,
40 bool isFixedPitch,
41 const SkString familyName)
42 : INHERITED(style, SkTypefaceCache::NewFontID(), isFixedPitch)
43 , fIndex(index)
44 , fFamilyName(familyName)
45 { }
46
47 const SkString& name() const { return fFamilyName; }
48
49 protected:
50 int fIndex;
51 SkString fFamilyName;
52
53 private:
54 typedef SkTypeface_FreeType INHERITED;
55 };
56
57 class SkTypeface_AndroidSystem : public SkTypeface_Android {
58 public:
59 SkTypeface_AndroidSystem(const SkString pathName,
60 int index,
61 Style style,
62 bool isFixedPitch,
63 const SkString familyName)
64 : INHERITED(index, style, isFixedPitch, familyName)
65 , fPathName(pathName)
66 { }
67
68 virtual void onGetFontDescriptor(SkFontDescriptor* desc,
69 bool* serialize) const SK_OVERRIDE
70 {
71 SkASSERT(desc);
72 SkASSERT(serialize);
73 desc->setFamilyName(fFamilyName.c_str());
74 desc->setFontFileName(fPathName.c_str());
75 *serialize = false;
76 }
77 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE {
78 *ttcIndex = fIndex;
79 return SkStream::NewFromFile(fPathName.c_str());
80 }
81
82 private:
83 SkString fPathName;
84
85 typedef SkTypeface_Android INHERITED;
86 };
87
88 class SkTypeface_AndroidStream : public SkTypeface_Android {
89 public:
90 SkTypeface_AndroidStream(SkStream* stream,
91 int index,
92 Style style,
93 bool isFixedPitch,
94 const SkString familyName)
95 : INHERITED(index, style, isFixedPitch, familyName)
96 , fStream(stream)
97 { }
98
99 virtual void onGetFontDescriptor(SkFontDescriptor* desc,
100 bool* serialize) const SK_OVERRIDE {
101 SkASSERT(desc);
102 SkASSERT(serialize);
103 desc->setFamilyName(fFamilyName.c_str());
104 desc->setFontFileName(NULL);
105 *serialize = true;
106 }
107
108 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE {
109 *ttcIndex = fIndex;
110 return fStream->duplicate();
111 }
112
113 private:
114 SkAutoTUnref<SkStream> fStream;
115
116 typedef SkTypeface_Android INHERITED;
117 };
118
119 void get_path_for_sys_fonts(SkString* full, const SkString& name) {
120 full->set(getenv("ANDROID_ROOT"));
121 full->append(SK_FONT_FILE_PREFIX);
122 full->append(name);
123 }
124
125 class SkFontStyleSet_Android : public SkFontStyleSet {
126 public:
127 explicit SkFontStyleSet_Android(FontFamily* family) : fFontFamily(family) {
128 // TODO? make this lazy
129 for (int i = 0; i < family->fFontFiles.count(); ++i) {
130 const SkString& fileName = family->fFontFiles[i].fFileName;
131
132 SkString pathName;
133 get_path_for_sys_fonts(&pathName, fileName);
134
135 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(pathName.c_str() ));
136 if (!stream.get()) {
137 DEBUG_FONT(("---- SystemFonts[%d] file=%s (NOT EXIST)", i, filen ame.c_str()));
138 continue;
139 }
140
141 SkString fontName;
142 SkTypeface::Style style;
143 bool isFixedWidth;
144 if (!SkTypeface_FreeType::ScanFont(stream.get(), family->fFontFiles[ i].fIndex,
145 &fontName, &style, &isFixedWidth) )
146 {
147 DEBUG_FONT(("---- SystemFonts[%d] file=%s (INVALID)", i, filenam e.c_str()));
148 continue;
149 }
150
151 fStyles.push_back().reset(SkNEW_ARGS(SkTypeface_AndroidSystem,
152 (pathName, 0,
153 style, isFixedWidth, fontName) ));
154 }
155 }
156
157 virtual int count() SK_OVERRIDE {
158 return fStyles.count();
159 }
160 virtual void getStyle(int index, SkFontStyle* style, SkString* name) SK_OVER RIDE {
161 if (index < 0 || fStyles.count() <= index) {
162 return;
163 }
164 if (style) {
165 *style = this->style(index);
166 }
167 if (name) {
168 name->reset();
169 }
170 }
171 virtual SkTypeface* createTypeface(int index) SK_OVERRIDE {
172 if (index < 0 || fStyles.count() <= index) {
173 return NULL;
174 }
175 return SkRef(fStyles[index].get());
176 }
177
178 /** Find the typeface in this style set that most closely matches the given pattern.
179 * TODO: consider replacing with SkStyleSet_Indirect::matchStyle();
180 * this simpler version using match_score() passes all our tests.
181 */
182 virtual SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE {
183 if (0 == fStyles.count()) {
184 return NULL;
185 }
186 SkTypeface* closest = fStyles[0];
187 int minScore = std::numeric_limits<int>::max();
188 for (int i = 0; i < fStyles.count(); ++i) {
189 SkFontStyle style = this->style(i);
190 int score = match_score(pattern, style);
191 if (score < minScore) {
192 closest = fStyles[i];
193 minScore = score;
194 }
195 }
196 return SkRef(closest);
197 }
198
199 private:
200 SkFontStyle style(int index) {
201 return SkFontStyle(this->weight(index), SkFontStyle::kNormal_Width,
202 this->slant(index));
203 }
204 SkFontStyle::Weight weight(int index) {
205 if (fStyles[index]->isBold()) return SkFontStyle::kBold_Weight;
206 return SkFontStyle::kNormal_Weight;
207 }
208 SkFontStyle::Slant slant(int index) {
209 if (fStyles[index]->isItalic()) return SkFontStyle::kItalic_Slant;
210 return SkFontStyle::kUpright_Slant;
211 }
212 static int match_score(const SkFontStyle& pattern, const SkFontStyle& candid ate) {
213 int score = 0;
214 score += abs((pattern.width() - candidate.width()) * 100);
215 score += abs((pattern.isItalic() == candidate.isItalic()) ? 0 : 1000);
216 score += abs(pattern.weight() - candidate.weight());
217 return score;
218 }
219
220
221 FontFamily* fFontFamily;
222 SkTArray<SkAutoTUnref<SkTypeface>, true> fStyles;
223
224 friend struct NameToFamily;
225 friend class SkFontMgr_Android;
226
227 typedef SkFontStyleSet INHERITED;
228 };
229
230 /** On Android a single family can have many names, but our API assumes unique n ames.
231 * Map names to the back end so that all names for a given family refer to the same
232 * (non-replicated) set of typefaces.
233 * SkTDict<> doesn't let us do index-based lookup, so we write our own mapping.
234 */
235 struct NameToFamily {
236 SkString name;
237 SkFontStyleSet_Android* styleSet;
238 };
239
240 class SkFontMgr_Android : public SkFontMgr {
241 public:
242 SkFontMgr_Android() {
243 SkTDArray<FontFamily*> fontFamilies;
244 SkFontConfigParser::GetFontFamilies(fontFamilies);
245 this->buildNameToFamilyMap(fontFamilies);
246 this->findDefaultFont();
247 }
248
249 protected:
250 /** Returns not how many families we have, but how many unique names
251 * exist among the families.
252 */
253 virtual int onCountFamilies() const SK_OVERRIDE {
254 return fNameToFamilyMap.count();
255 }
256
257 virtual void onGetFamilyName(int index, SkString* familyName) const SK_OVERR IDE {
258 if (index < 0 || fNameToFamilyMap.count() <= index) {
259 familyName->reset();
260 return;
261 }
262 familyName->set(fNameToFamilyMap[index].name);
263 }
264
265 virtual SkFontStyleSet* onCreateStyleSet(int index) const SK_OVERRIDE {
266 if (index < 0 || fNameToFamilyMap.count() <= index) {
267 return NULL;
268 }
269 return SkRef(fNameToFamilyMap[index].styleSet);
270 }
271
272 virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVER RIDE {
273 if (!familyName) {
274 return NULL;
275 }
276 SkAutoAsciiToLC tolc(familyName);
277 for (int i = 0; i < fNameToFamilyMap.count(); ++i) {
278 if (fNameToFamilyMap[i].name.equals(tolc.lc())) {
279 return SkRef(fNameToFamilyMap[i].styleSet);
280 }
281 }
282 return NULL;
283 }
284
285 virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
286 const SkFontStyle& style) const SK_OV ERRIDE {
287 SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName));
288 return sset->matchStyle(style);
289 }
290
291 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* typeface,
292 const SkFontStyle& style) const SK_OVER RIDE {
293 for (int i = 0; i < fFontStyleSets.count(); ++i) {
294 for (int j = 0; j < fFontStyleSets[i]->fStyles.count(); ++j) {
295 if (fFontStyleSets[i]->fStyles[j] == typeface) {
296 return fFontStyleSets[i]->matchStyle(style);
297 }
298 }
299 }
300 return NULL;
301 }
302
303 virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const SK_OV ERRIDE {
304 SkAutoTUnref<SkStream> stream(new SkMemoryStream(data));
305 return this->createFromStream(stream, ttcIndex);
306 }
307
308 virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const SK_OVERRIDE {
309 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
310 return stream.get() ? this->createFromStream(stream, ttcIndex) : NULL;
311 }
312
313 virtual SkTypeface* onCreateFromStream(SkStream* s, int ttcIndex) const SK_O VERRIDE {
314 SkAutoTUnref<SkStream> stream(s);
315
316 bool isFixedPitch;
317 SkTypeface::Style style;
318 SkString name;
319 if (!SkTypeface_FreeType::ScanFont(stream, ttcIndex, &name, &style, &isF ixedPitch)) {
320 return NULL;
321 }
322 return SkNEW_ARGS(SkTypeface_AndroidStream, (stream.detach(), ttcIndex,
323 style, isFixedPitch, name)) ;
324 }
325
326
327 virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
328 unsigned styleBits) const SK_OVER RIDE {
329 SkTypeface::Style oldStyle = (SkTypeface::Style)styleBits;
330 SkFontStyle style = SkFontStyle(oldStyle & SkTypeface::kBold
331 ? SkFontStyle::kBold_Weight
332 : SkFontStyle::kNormal_Weight,
333 SkFontStyle::kNormal_Width,
334 oldStyle & SkTypeface::kItalic
335 ? SkFontStyle::kItalic_Slant
336 : SkFontStyle::kUpright_Slant);
337 SkTypeface* tf = NULL;
338
339 if (NULL != familyName) {
340 // On Android, we must return NULL when we can't find the requested
341 // named typeface so that the system/app can provide their own recov ery
342 // mechanism. On other platforms we'd provide a typeface from the
343 // default family instead.
344 tf = this->onMatchFamilyStyle(familyName, style);
345 } else {
346 tf = fDefaultFamily->matchStyle(style);
347 }
348
349 // TODO: double ref? qv matchStyle()
350 return SkSafeRef(tf);
351 }
352
353
354 private:
355
356 SkTArray<SkAutoTUnref<SkFontStyleSet_Android>, true> fFontStyleSets;
357 SkFontStyleSet* fDefaultFamily;
358 SkTypeface* fDefaultTypeface;
359
360 SkTDArray<NameToFamily> fNameToFamilyMap;
361
362 void buildNameToFamilyMap(SkTDArray<FontFamily*> families) {
363 for (int i = 0; i < families.count(); i++) {
364 fFontStyleSets.push_back().reset(
365 SkNEW_ARGS(SkFontStyleSet_Android, (families[i])));
366 for (int j = 0; j < families[i]->fNames.count(); j++) {
367 NameToFamily* nextEntry = fNameToFamilyMap.append();
368 SkNEW_PLACEMENT_ARGS(&nextEntry->name, SkString, (families[i]->f Names[j]));
369 nextEntry->styleSet = fFontStyleSets.back().get();
370 }
371 }
372 }
373
374 void findDefaultFont() {
375 SkASSERT(!fFontStyleSets.empty());
376
377 static const char* gDefaultNames[] = { "sans-serif" };
378 for (size_t i = 0; i < SK_ARRAY_COUNT(gDefaultNames); ++i) {
379 SkFontStyleSet* set = this->onMatchFamily(gDefaultNames[i]);
380 if (NULL == set) {
381 continue;
382 }
383 SkTypeface* tf = set->matchStyle(SkFontStyle());
384 if (NULL == tf) {
385 continue;
386 }
387 fDefaultFamily = set;
388 fDefaultTypeface = tf;
389 break;
390 }
391 if (NULL == fDefaultTypeface) {
392 fDefaultFamily = fFontStyleSets[0];
393 fDefaultTypeface = fDefaultFamily->createTypeface(0);
394 }
395 SkASSERT(fDefaultFamily);
396 SkASSERT(fDefaultTypeface);
397 }
398
399 typedef SkFontMgr INHERITED;
400 };
401
402 ///////////////////////////////////////////////////////////////////////////////
403
404 SkFontMgr* SkFontMgr::Factory() {
405 return SkNEW(SkFontMgr_Android);
406 }
OLDNEW
« no previous file with comments | « src/ports/SkFontConfigParser_android.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698