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

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

Issue 1184923002: Refactor SkFontHost_linux into SkFontMgr_custom. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Don't export embedded. Created 5 years, 6 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 2006 The Android Open Source Project
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 "SkFontHost_FreeType_common.h"
9 #include "SkFontDescriptor.h"
10 #include "SkFontMgr.h"
11 #include "SkDescriptor.h"
12 #include "SkOSFile.h"
13 #include "SkPaint.h"
14 #include "SkRTConf.h"
15 #include "SkString.h"
16 #include "SkStream.h"
17 #include "SkThread.h"
18 #include "SkTSearch.h"
19 #include "SkTypefaceCache.h"
20 #include "SkTArray.h"
21
22 #include <limits>
23
24 /** The base SkTypeface implementation for the custom font manager. */
25 class SkTypeface_Custom : public SkTypeface_FreeType {
26 public:
27 SkTypeface_Custom(const SkFontStyle& style, bool isFixedPitch,
28 bool sysFont, const SkString familyName, int index)
29 : INHERITED(style, SkTypefaceCache::NewFontID(), isFixedPitch)
30 , fIsSysFont(sysFont), fFamilyName(familyName), fIndex(index)
31 { }
32
33 bool isSysFont() const { return fIsSysFont; }
34
35 protected:
36 void onGetFamilyName(SkString* familyName) const override {
37 *familyName = fFamilyName;
38 }
39
40 void onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const overri de {
41 desc->setFamilyName(fFamilyName.c_str());
42 *isLocal = !this->isSysFont();
43 }
44
45 int getIndex() const { return fIndex; }
46
47 private:
48 const bool fIsSysFont;
49 const SkString fFamilyName;
50 const int fIndex;
51
52 typedef SkTypeface_FreeType INHERITED;
53 };
54
55 /** The empty SkTypeface implementation for the custom font manager.
56 * Used as the last resort fallback typeface.
57 */
58 class SkTypeface_Empty : public SkTypeface_Custom {
59 public:
60 SkTypeface_Empty() : INHERITED(SkFontStyle(), false, true, SkString(), 0) {}
61
62 protected:
63 SkStreamAsset* onOpenStream(int*) const override { return NULL; }
64
65 private:
66 typedef SkTypeface_Custom INHERITED;
67 };
68
69 /** The stream SkTypeface implementation for the custom font manager. */
70 class SkTypeface_Stream : public SkTypeface_Custom {
71 public:
72 SkTypeface_Stream(const SkFontStyle& style, bool isFixedPitch, bool sysFont,
73 const SkString familyName, SkStreamAsset* stream, int inde x)
74 : INHERITED(style, isFixedPitch, sysFont, familyName, index)
75 , fStream(stream)
76 { }
77
78 protected:
79 SkStreamAsset* onOpenStream(int* ttcIndex) const override {
80 *ttcIndex = this->getIndex();
81 return fStream->duplicate();
82 }
83
84 private:
85 const SkAutoTDelete<const SkStreamAsset> fStream;
86
87 typedef SkTypeface_Custom INHERITED;
88 };
89
90 // This configuration option is useful if we need to open and hold handles to
91 // all found system font data (e.g., for skfiddle, where the application can't
92 // access the filesystem to read fonts on demand)
93
94 SK_CONF_DECLARE(bool, c_CustomTypefaceRetain, "fonts.customFont.retainAllData", false,
95 "Retain the open stream for each found font on the system.");
96
97 /** The file SkTypeface implementation for the custom font manager. */
98 class SkTypeface_File : public SkTypeface_Custom {
99 public:
100 SkTypeface_File(const SkFontStyle& style, bool isFixedPitch, bool sysFont,
101 const SkString familyName, const char path[], int index)
102 : INHERITED(style, isFixedPitch, sysFont, familyName, index)
103 , fPath(path)
104 , fStream(c_CustomTypefaceRetain ? SkStream::NewFromFile(fPath.c_str()) : NULL)
105 { }
106
107 protected:
108 SkStreamAsset* onOpenStream(int* ttcIndex) const override {
109 *ttcIndex = this->getIndex();
110 if (fStream.get()) {
111 return fStream->duplicate();
112 } else {
113 return SkStream::NewFromFile(fPath.c_str());
114 }
115 }
116
117 private:
118 SkString fPath;
119 const SkAutoTDelete<SkStreamAsset> fStream;
120
121 typedef SkTypeface_Custom INHERITED;
122 };
123
124 ///////////////////////////////////////////////////////////////////////////////
125
126 /**
127 * SkFontStyleSet_Custom
128 *
129 * This class is used by SkFontMgr_Custom to hold SkTypeface_Custom families.
130 */
131 class SkFontStyleSet_Custom : public SkFontStyleSet {
132 public:
133 explicit SkFontStyleSet_Custom(const SkString familyName) : fFamilyName(fami lyName) { }
134
135 /** Should only be called during the inital build phase. */
136 void appendTypeface(SkTypeface_Custom* typeface) {
137 fStyles.push_back().reset(typeface);
138 }
139
140 int count() override {
141 return fStyles.count();
142 }
143
144 void getStyle(int index, SkFontStyle* style, SkString* name) override {
145 SkASSERT(index < fStyles.count());
146 bool bold = fStyles[index]->isBold();
147 bool italic = fStyles[index]->isItalic();
148 *style = SkFontStyle(bold ? SkFontStyle::kBold_Weight : SkFontStyle::kNo rmal_Weight,
149 SkFontStyle::kNormal_Width,
150 italic ? SkFontStyle::kItalic_Slant : SkFontStyle:: kUpright_Slant);
151 name->reset();
152 }
153
154 SkTypeface* createTypeface(int index) override {
155 SkASSERT(index < fStyles.count());
156 return SkRef(fStyles[index].get());
157 }
158
159 static int match_score(const SkFontStyle& pattern, const SkFontStyle& candid ate) {
160 int score = 0;
161 score += (pattern.width() - candidate.width()) * 100;
162 score += (pattern.isItalic() == candidate.isItalic()) ? 0 : 1000;
163 score += pattern.weight() - candidate.weight();
164 return score;
165 }
166
167 SkTypeface* matchStyle(const SkFontStyle& pattern) override {
168 if (0 == fStyles.count()) {
169 return NULL;
170 }
171
172 SkTypeface_Custom* closest = fStyles[0];
173 int minScore = std::numeric_limits<int>::max();
174 for (int i = 0; i < fStyles.count(); ++i) {
175 bool bold = fStyles[i]->isBold();
176 bool italic = fStyles[i]->isItalic();
177 SkFontStyle style = SkFontStyle(bold ? SkFontStyle::kBold_Weight
178 : SkFontStyle::kNormal_Weight,
179 SkFontStyle::kNormal_Width,
180 italic ? SkFontStyle::kItalic_Slant
181 : SkFontStyle::kUpright_Slant );
182
183 int score = match_score(pattern, style);
184 if (score < minScore) {
185 closest = fStyles[i];
186 minScore = score;
187 }
188 }
189 return SkRef(closest);
190 }
191
192 SkString getFamilyName() { return fFamilyName; }
193
194 private:
195 SkTArray<SkAutoTUnref<SkTypeface_Custom>, true> fStyles;
196 SkString fFamilyName;
197
198 friend class SkFontMgr_Custom;
199 };
200
201 /**
202 * SkFontMgr_Custom
203 *
204 * This class is essentially a collection of SkFontStyleSet_Custom,
205 * one SkFontStyleSet_Custom for each family. This class may be modified
206 * to load fonts from any source by changing the initialization.
207 */
208 class SkFontMgr_Custom : public SkFontMgr {
209 public:
210 typedef SkTArray<SkAutoTUnref<SkFontStyleSet_Custom>, true> Families;
211 class SystemFontLoader {
212 public:
213 virtual ~SystemFontLoader() { }
214 virtual void loadSystemFonts(const SkTypeface_FreeType::Scanner&, Famili es*) const = 0;
215 };
216 explicit SkFontMgr_Custom(const SystemFontLoader& loader) {
217 loader.loadSystemFonts(fScanner, &fFamilies);
218
219 // Try to pick a default font.
220 static const char* defaultNames[] = {
221 "Arial", "Verdana", "Times New Roman", "Droid Sans", NULL
222 };
223 for (size_t i = 0; i < SK_ARRAY_COUNT(defaultNames); ++i) {
224 SkFontStyleSet_Custom* set = this->onMatchFamily(defaultNames[i]);
225 if (NULL == set) {
226 continue;
227 }
228
229 SkTypeface* tf = set->matchStyle(SkFontStyle(SkFontStyle::kNormal_We ight,
230 SkFontStyle::kNormal_Wi dth,
231 SkFontStyle::kUpright_S lant));
232 if (NULL == tf) {
233 continue;
234 }
235
236 fDefaultFamily = set;
237 break;
238 }
239 if (NULL == fDefaultFamily) {
240 fDefaultFamily = fFamilies[0];
241 }
242 }
243
244 protected:
245 int onCountFamilies() const override {
246 return fFamilies.count();
247 }
248
249 void onGetFamilyName(int index, SkString* familyName) const override {
250 SkASSERT(index < fFamilies.count());
251 familyName->set(fFamilies[index]->getFamilyName());
252 }
253
254 SkFontStyleSet_Custom* onCreateStyleSet(int index) const override {
255 SkASSERT(index < fFamilies.count());
256 return SkRef(fFamilies[index].get());
257 }
258
259 SkFontStyleSet_Custom* onMatchFamily(const char familyName[]) const override {
260 for (int i = 0; i < fFamilies.count(); ++i) {
261 if (fFamilies[i]->getFamilyName().equals(familyName)) {
262 return SkRef(fFamilies[i].get());
263 }
264 }
265 return NULL;
266 }
267
268 SkTypeface* onMatchFamilyStyle(const char familyName[],
269 const SkFontStyle& fontStyle) const override
270 {
271 SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName));
272 return sset->matchStyle(fontStyle);
273 }
274
275 SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], const SkFon tStyle&,
276 const char* bcp47[], int bcp47Count,
277 SkUnichar character) const override
278 {
279 return NULL;
280 }
281
282 SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember,
283 const SkFontStyle& fontStyle) const override
284 {
285 for (int i = 0; i < fFamilies.count(); ++i) {
286 for (int j = 0; j < fFamilies[i]->fStyles.count(); ++j) {
287 if (fFamilies[i]->fStyles[j] == familyMember) {
288 return fFamilies[i]->matchStyle(fontStyle);
289 }
290 }
291 }
292 return NULL;
293 }
294
295 SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const override {
296 return this->createFromStream(new SkMemoryStream(data), ttcIndex);
297 }
298
299 SkTypeface* onCreateFromStream(SkStreamAsset* bareStream, int ttcIndex) cons t override {
300 SkAutoTDelete<SkStreamAsset> stream(bareStream);
301 if (NULL == stream || stream->getLength() <= 0) {
302 return NULL;
303 }
304
305 bool isFixedPitch;
306 SkFontStyle style;
307 SkString name;
308 if (fScanner.scanFont(stream, ttcIndex, &name, &style, &isFixedPitch, NU LL)) {
309 return SkNEW_ARGS(SkTypeface_Stream, (style, isFixedPitch, false, na me,
310 stream.detach(), ttcIndex));
311 } else {
312 return NULL;
313 }
314 }
315
316 SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const override {
317 SkAutoTDelete<SkStreamAsset> stream(SkStream::NewFromFile(path));
318 return stream.get() ? this->createFromStream(stream.detach(), ttcIndex) : NULL;
319 }
320
321 SkTypeface* onLegacyCreateTypeface(const char familyName[], unsigned styleBi ts) const override {
322 SkTypeface::Style oldStyle = (SkTypeface::Style)styleBits;
323 SkFontStyle style = SkFontStyle(oldStyle & SkTypeface::kBold
324 ? SkFontStyle::kBold_Weight
325 : SkFontStyle::kNormal_Weight,
326 SkFontStyle::kNormal_Width,
327 oldStyle & SkTypeface::kItalic
328 ? SkFontStyle::kItalic_Slant
329 : SkFontStyle::kUpright_Slant);
330 SkTypeface* tf = NULL;
331
332 if (familyName) {
333 tf = this->onMatchFamilyStyle(familyName, style);
334 }
335
336 if (NULL == tf) {
337 tf = fDefaultFamily->matchStyle(style);
338 }
339
340 return SkSafeRef(tf);
341 }
342
343 private:
344 Families fFamilies;
345 SkFontStyleSet_Custom* fDefaultFamily;
346 SkTypeface_FreeType::Scanner fScanner;
347 };
348
349 ///////////////////////////////////////////////////////////////////////////////
350
351 class DirectorySystemFontLoader : public SkFontMgr_Custom::SystemFontLoader {
352 public:
353 DirectorySystemFontLoader(const char* dir) : fBaseDirectory(dir) { }
354
355 void loadSystemFonts(const SkTypeface_FreeType::Scanner& scanner,
356 SkFontMgr_Custom::Families* families) const override
357 {
358 load_directory_fonts(scanner, fBaseDirectory, ".ttf", families);
359 load_directory_fonts(scanner, fBaseDirectory, ".ttc", families);
360 load_directory_fonts(scanner, fBaseDirectory, ".otf", families);
361 load_directory_fonts(scanner, fBaseDirectory, ".pfb", families);
362
363 if (families->empty()) {
364 SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString() );
365 families->push_back().reset(family);
366 family->appendTypeface(SkNEW(SkTypeface_Empty));
367 }
368 }
369
370 private:
371 static SkFontStyleSet_Custom* find_family(SkFontMgr_Custom::Families& famili es,
372 const char familyName[])
373 {
374 for (int i = 0; i < families.count(); ++i) {
375 if (families[i]->getFamilyName().equals(familyName)) {
376 return families[i].get();
377 }
378 }
379 return NULL;
380 }
381
382 static void load_directory_fonts(const SkTypeface_FreeType::Scanner& scanner ,
383 const SkString& directory, const char* suff ix,
384 SkFontMgr_Custom::Families* families)
385 {
386 SkOSFile::Iter iter(directory.c_str(), suffix);
387 SkString name;
388
389 while (iter.next(&name, false)) {
390 SkString filename(SkOSPath::Join(directory.c_str(), name.c_str()));
391 SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(filename.c_str( )));
392 if (!stream.get()) {
393 SkDebugf("---- failed to open <%s>\n", filename.c_str());
394 continue;
395 }
396
397 int numFaces;
398 if (!scanner.recognizedFont(stream, &numFaces)) {
399 SkDebugf("---- failed to open <%s> as a font\n", filename.c_str( ));
400 continue;
401 }
402
403 for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex) {
404 bool isFixedPitch;
405 SkString realname;
406 SkFontStyle style = SkFontStyle(); // avoid uninitialized warnin g
407 if (!scanner.scanFont(stream, faceIndex, &realname, &style, &isF ixedPitch, NULL)) {
408 SkDebugf("---- failed to open <%s> <%d> as a font\n",
409 filename.c_str(), faceIndex);
410 continue;
411 }
412
413 SkTypeface_Custom* tf = SkNEW_ARGS(SkTypeface_File, (
414 style,
415 isFixedPitch,
416 true, // system-font (canno t delete)
417 realname,
418 filename.c_str(),
419 faceIndex));
420
421 SkFontStyleSet_Custom* addTo = find_family(*families, realname.c _str());
422 if (NULL == addTo) {
423 addTo = new SkFontStyleSet_Custom(realname);
424 families->push_back().reset(addTo);
425 }
426 addTo->appendTypeface(tf);
427 }
428 }
429
430 SkOSFile::Iter dirIter(directory.c_str());
431 while (dirIter.next(&name, true)) {
432 if (name.startsWith(".")) {
433 continue;
434 }
435 SkString dirname(SkOSPath::Join(directory.c_str(), name.c_str()));
436 load_directory_fonts(scanner, dirname, suffix, families);
437 }
438 }
439
440 SkString fBaseDirectory;
441 };
442
443 struct SkEmbeddedResource { const uint8_t* data; size_t size; };
444 struct SkEmbeddedResourceHeader { const SkEmbeddedResource* entries; int count; };
445
446 class EmbeddedSystemFontLoader : public SkFontMgr_Custom::SystemFontLoader {
447 public:
448 EmbeddedSystemFontLoader(const SkEmbeddedResourceHeader* header) : fHeader(h eader) { }
449
450 void loadSystemFonts(const SkTypeface_FreeType::Scanner& scanner,
451 SkFontMgr_Custom::Families* families) const override
452 {
453 for (int i = 0; i < fHeader->count; ++i) {
454 const SkEmbeddedResource& fontEntry = fHeader->entries[i];
455 load_embedded_font(scanner, fontEntry.data, fontEntry.size, i, famil ies);
456 }
457
458 if (families->empty()) {
459 SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString() );
460 families->push_back().reset(family);
461 family->appendTypeface(SkNEW(SkTypeface_Empty));
462 }
463 }
464
465 private:
466 static SkFontStyleSet_Custom* find_family(SkFontMgr_Custom::Families& famili es,
467 const char familyName[])
468 {
469 for (int i = 0; i < families.count(); ++i) {
470 if (families[i]->getFamilyName().equals(familyName)) {
471 return families[i].get();
472 }
473 }
474 return NULL;
475 }
476
477 static void load_embedded_font(const SkTypeface_FreeType::Scanner& scanner,
478 const uint8_t* data, size_t size, int index,
479 SkFontMgr_Custom::Families* families)
480 {
481 SkAutoTDelete<SkMemoryStream> stream(new SkMemoryStream(data, size, fals e));
482
483 int numFaces;
484 if (!scanner.recognizedFont(stream, &numFaces)) {
485 SkDebugf("---- failed to open <%d> as a font\n", index);
486 return;
487 }
488
489 for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex) {
490 bool isFixedPitch;
491 SkString realname;
492 SkFontStyle style = SkFontStyle(); // avoid uninitialized warning
493 if (!scanner.scanFont(stream, faceIndex, &realname, &style, &isFixed Pitch, NULL)) {
494 SkDebugf("---- failed to open <%d> <%d> as a font\n", index, fac eIndex);
495 return;
496 }
497
498 SkTypeface_Custom* tf = SkNEW_ARGS(SkTypeface_Stream, (
499 style,
500 isFixedPitch,
501 true, // system-font (cannot de lete)
502 realname,
503 stream.detach(),
504 faceIndex));
505
506 SkFontStyleSet_Custom* addTo = find_family(*families, realname.c_str ());
507 if (NULL == addTo) {
508 addTo = new SkFontStyleSet_Custom(realname);
509 families->push_back().reset(addTo);
510 }
511 addTo->appendTypeface(tf);
512 }
513 }
514
515 const SkEmbeddedResourceHeader* fHeader;
516 };
517
518 #ifdef SK_EMBEDDED_FONTS
519
520 extern "C" const SkEmbeddedResourceHeader SK_EMBEDDED_FONTS;
521 SkFontMgr* SkFontMgr::Factory() {
522 return new SkFontMgr_Custom(EmbeddedSystemFontLoader(&SK_EMBEDDED_FONTS));
523 }
524
525 #else
526
527 #ifndef SK_FONT_FILE_PREFIX
528 # define SK_FONT_FILE_PREFIX "/usr/share/fonts/"
529 #endif
530 SkFontMgr* SkFontMgr::Factory() {
531 return new SkFontMgr_Custom(DirectorySystemFontLoader(SK_FONT_FILE_PREFIX));
532 }
533
534 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698