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

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

Powered by Google App Engine
This is Rietveld 408576698