OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2009 Google Inc. | 2 * Copyright 2009-2015 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 /* migrated from chrome/src/skia/ext/SkFontHost_fontconfig_direct.cpp */ | 8 /* migrated from chrome/src/skia/ext/SkFontHost_fontconfig_direct.cpp */ |
9 | 9 |
10 #include "SkBuffer.h" | 10 #include "SkBuffer.h" |
11 #include "SkDataTable.h" | 11 #include "SkDataTable.h" |
12 #include "SkFontConfigInterface.h" | 12 #include "SkFontConfigInterface_direct.h" |
13 #include "SkFontStyle.h" | 13 #include "SkFontStyle.h" |
14 #include "SkMutex.h" | 14 #include "SkMutex.h" |
15 #include "SkStream.h" | 15 #include "SkStream.h" |
16 #include "SkString.h" | 16 #include "SkString.h" |
17 #include "SkTArray.h" | 17 #include "SkTArray.h" |
18 #include "SkTDArray.h" | 18 #include "SkTDArray.h" |
19 #include "SkTemplates.h" | 19 #include "SkTemplates.h" |
20 #include "SkTypeface.h" | 20 #include "SkTypeface.h" |
21 #include "SkTypes.h" | 21 #include "SkTypes.h" |
22 | 22 |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
100 SkASSERT(iden0 != iden1); | 100 SkASSERT(iden0 != iden1); |
101 | 101 |
102 make_iden(&iden1); | 102 make_iden(&iden1); |
103 SkASSERT(iden0 == iden1); | 103 SkASSERT(iden0 == iden1); |
104 | 104 |
105 test_writeToMemory(iden0, 0); | 105 test_writeToMemory(iden0, 0); |
106 test_writeToMemory(iden0, 0); | 106 test_writeToMemory(iden0, 0); |
107 } | 107 } |
108 #endif | 108 #endif |
109 | 109 |
110 class SkFontConfigInterfaceDirect : public SkFontConfigInterface { | |
111 public: | |
112 SkFontConfigInterfaceDirect(); | |
113 virtual ~SkFontConfigInterfaceDirect(); | |
114 | |
115 virtual bool matchFamilyName(const char familyName[], | |
116 SkTypeface::Style requested, | |
117 FontIdentity* outFontIdentifier, | |
118 SkString* outFamilyName, | |
119 SkTypeface::Style* outStyle) override; | |
120 SkStreamAsset* openStream(const FontIdentity&) override; | |
121 | |
122 // new APIs | |
123 SkDataTable* getFamilyNames() override; | |
124 virtual bool matchFamilySet(const char inFamilyName[], | |
125 SkString* outFamilyName, | |
126 SkTArray<FontIdentity>*) override; | |
127 | |
128 private: | |
129 SkMutex mutex_; | |
130 }; | |
131 | |
132 SkFontConfigInterface* SkFontConfigInterface::GetSingletonDirectInterface(SkBase
Mutex* mutex) { | |
133 SkAutoMutexAcquire ac(mutex); | |
134 static SkFontConfigInterfaceDirect* singleton = nullptr; | |
135 if (singleton == nullptr) { | |
136 singleton = new SkFontConfigInterfaceDirect; | |
137 } | |
138 return singleton; | |
139 } | |
140 | |
141 /////////////////////////////////////////////////////////////////////////////// | 110 /////////////////////////////////////////////////////////////////////////////// |
142 | 111 |
143 // Returns the string from the pattern, or nullptr | 112 // Returns the string from the pattern, or nullptr |
144 static const char* get_name(FcPattern* pattern, const char field[], | 113 static const char* get_name(FcPattern* pattern, const char field[], |
145 int index = 0) { | 114 int index = 0) { |
146 const char* name; | 115 const char* name; |
147 if (FcPatternGetString(pattern, field, index, | 116 if (FcPatternGetString(pattern, field, index, |
148 (FcChar8**)&name) != FcResultMatch) { | 117 (FcChar8**)&name) != FcResultMatch) { |
149 name = nullptr; | 118 name = nullptr; |
150 } | 119 } |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
327 // basic font names like "Sans", "Serif" or "Monospace". This function | 296 // basic font names like "Sans", "Serif" or "Monospace". This function |
328 // tells you whether a given request is for such a fallback. | 297 // tells you whether a given request is for such a fallback. |
329 bool IsFallbackFontAllowed(const SkString& family) { | 298 bool IsFallbackFontAllowed(const SkString& family) { |
330 const char* family_cstr = family.c_str(); | 299 const char* family_cstr = family.c_str(); |
331 return family.isEmpty() || | 300 return family.isEmpty() || |
332 strcasecmp(family_cstr, "sans") == 0 || | 301 strcasecmp(family_cstr, "sans") == 0 || |
333 strcasecmp(family_cstr, "serif") == 0 || | 302 strcasecmp(family_cstr, "serif") == 0 || |
334 strcasecmp(family_cstr, "monospace") == 0; | 303 strcasecmp(family_cstr, "monospace") == 0; |
335 } | 304 } |
336 | 305 |
337 static bool valid_pattern(FcPattern* pattern) { | 306 // Retrieves |is_bold|, |is_italic| and |font_family| properties from |font|. |
| 307 SkTypeface::Style GetFontStyle(FcPattern* font) { |
| 308 int resulting_bold; |
| 309 if (FcPatternGetInteger(font, FC_WEIGHT, 0, &resulting_bold)) |
| 310 resulting_bold = FC_WEIGHT_NORMAL; |
| 311 |
| 312 int resulting_italic; |
| 313 if (FcPatternGetInteger(font, FC_SLANT, 0, &resulting_italic)) |
| 314 resulting_italic = FC_SLANT_ROMAN; |
| 315 |
| 316 // If we ask for an italic font, fontconfig might take a roman font and set |
| 317 // the undocumented property FC_MATRIX to a skew matrix. It'll then say |
| 318 // that the font is italic or oblique. So, if we see a matrix, we don't |
| 319 // believe that it's italic. |
| 320 FcValue matrix; |
| 321 const bool have_matrix = FcPatternGet(font, FC_MATRIX, 0, &matrix) == 0; |
| 322 |
| 323 // If we ask for an italic font, fontconfig might take a roman font and set |
| 324 // FC_EMBOLDEN. |
| 325 FcValue embolden; |
| 326 const bool have_embolden = FcPatternGet(font, FC_EMBOLDEN, 0, &embolden) ==
0; |
| 327 |
| 328 int styleBits = 0; |
| 329 if (resulting_bold > FC_WEIGHT_MEDIUM && !have_embolden) { |
| 330 styleBits |= SkTypeface::kBold; |
| 331 } |
| 332 if (resulting_italic > FC_SLANT_ROMAN && !have_matrix) { |
| 333 styleBits |= SkTypeface::kItalic; |
| 334 } |
| 335 |
| 336 return (SkTypeface::Style)styleBits; |
| 337 } |
| 338 |
| 339 } // anonymous namespace |
| 340 |
| 341 /////////////////////////////////////////////////////////////////////////////// |
| 342 |
| 343 #define kMaxFontFamilyLength 2048 |
| 344 |
| 345 SkFontConfigInterfaceDirect::SkFontConfigInterfaceDirect() { |
| 346 SkAutoMutexAcquire ac(mutex_); |
| 347 |
| 348 FcInit(); |
| 349 |
| 350 SkDEBUGCODE(fontconfiginterface_unittest();) |
| 351 } |
| 352 |
| 353 SkFontConfigInterfaceDirect::~SkFontConfigInterfaceDirect() { |
| 354 } |
| 355 |
| 356 bool SkFontConfigInterfaceDirect::isAccessible(const char* filename) { |
| 357 if (access(filename, R_OK) != 0) { |
| 358 return false; |
| 359 } |
| 360 return true; |
| 361 } |
| 362 |
| 363 bool SkFontConfigInterfaceDirect::isValidPattern(FcPattern* pattern) { |
338 #ifdef SK_FONT_CONFIG_ONLY_ALLOW_SCALABLE_FONTS | 364 #ifdef SK_FONT_CONFIG_ONLY_ALLOW_SCALABLE_FONTS |
339 FcBool is_scalable; | 365 FcBool is_scalable; |
340 if (FcPatternGetBool(pattern, FC_SCALABLE, 0, &is_scalable) != FcResultMatch | 366 if (FcPatternGetBool(pattern, FC_SCALABLE, 0, &is_scalable) != FcResultMatch |
341 || !is_scalable) { | 367 || !is_scalable) { |
342 return false; | 368 return false; |
343 } | 369 } |
344 #endif | 370 #endif |
345 | 371 |
346 // fontconfig can also return fonts which are unreadable | 372 // fontconfig can also return fonts which are unreadable |
347 const char* c_filename = get_name(pattern, FC_FILE); | 373 const char* c_filename = get_name(pattern, FC_FILE); |
348 if (!c_filename) { | 374 if (!c_filename) { |
349 return false; | 375 return false; |
350 } | 376 } |
351 if (access(c_filename, R_OK) != 0) { | 377 return this->isAccessible(c_filename); |
352 return false; | |
353 } | |
354 return true; | |
355 } | 378 } |
356 | 379 |
357 // Find matching font from |font_set| for the given font family. | 380 // Find matching font from |font_set| for the given font family. |
358 FcPattern* MatchFont(FcFontSet* font_set, | 381 FcPattern* SkFontConfigInterfaceDirect::MatchFont(FcFontSet* font_set, |
359 const char* post_config_family, | 382 const char* post_config_family
, |
360 const SkString& family) { | 383 const SkString& family) { |
361 // Older versions of fontconfig have a bug where they cannot select | 384 // Older versions of fontconfig have a bug where they cannot select |
362 // only scalable fonts so we have to manually filter the results. | 385 // only scalable fonts so we have to manually filter the results. |
363 FcPattern* match = nullptr; | 386 FcPattern* match = nullptr; |
364 for (int i = 0; i < font_set->nfont; ++i) { | 387 for (int i = 0; i < font_set->nfont; ++i) { |
365 FcPattern* current = font_set->fonts[i]; | 388 FcPattern* current = font_set->fonts[i]; |
366 if (valid_pattern(current)) { | 389 if (this->isValidPattern(current)) { |
367 match = current; | 390 match = current; |
368 break; | 391 break; |
369 } | 392 } |
370 } | 393 } |
371 | 394 |
372 if (match && !IsFallbackFontAllowed(family)) { | 395 if (match && !IsFallbackFontAllowed(family)) { |
373 bool acceptable_substitute = false; | 396 bool acceptable_substitute = false; |
374 for (int id = 0; id < 255; ++id) { | 397 for (int id = 0; id < 255; ++id) { |
375 const char* post_match_family = get_name(match, FC_FAMILY, id); | 398 const char* post_match_family = get_name(match, FC_FAMILY, id); |
376 if (!post_match_family) | 399 if (!post_match_family) |
(...skipping 10 matching lines...) Expand all Loading... |
387 if (acceptable_substitute) | 410 if (acceptable_substitute) |
388 break; | 411 break; |
389 } | 412 } |
390 if (!acceptable_substitute) | 413 if (!acceptable_substitute) |
391 return nullptr; | 414 return nullptr; |
392 } | 415 } |
393 | 416 |
394 return match; | 417 return match; |
395 } | 418 } |
396 | 419 |
397 // Retrieves |is_bold|, |is_italic| and |font_family| properties from |font|. | |
398 SkTypeface::Style GetFontStyle(FcPattern* font) { | |
399 int resulting_bold; | |
400 if (FcPatternGetInteger(font, FC_WEIGHT, 0, &resulting_bold)) | |
401 resulting_bold = FC_WEIGHT_NORMAL; | |
402 | |
403 int resulting_italic; | |
404 if (FcPatternGetInteger(font, FC_SLANT, 0, &resulting_italic)) | |
405 resulting_italic = FC_SLANT_ROMAN; | |
406 | |
407 // If we ask for an italic font, fontconfig might take a roman font and set | |
408 // the undocumented property FC_MATRIX to a skew matrix. It'll then say | |
409 // that the font is italic or oblique. So, if we see a matrix, we don't | |
410 // believe that it's italic. | |
411 FcValue matrix; | |
412 const bool have_matrix = FcPatternGet(font, FC_MATRIX, 0, &matrix) == 0; | |
413 | |
414 // If we ask for an italic font, fontconfig might take a roman font and set | |
415 // FC_EMBOLDEN. | |
416 FcValue embolden; | |
417 const bool have_embolden = FcPatternGet(font, FC_EMBOLDEN, 0, &embolden) ==
0; | |
418 | |
419 int styleBits = 0; | |
420 if (resulting_bold > FC_WEIGHT_MEDIUM && !have_embolden) { | |
421 styleBits |= SkTypeface::kBold; | |
422 } | |
423 if (resulting_italic > FC_SLANT_ROMAN && !have_matrix) { | |
424 styleBits |= SkTypeface::kItalic; | |
425 } | |
426 | |
427 return (SkTypeface::Style)styleBits; | |
428 } | |
429 | |
430 } // anonymous namespace | |
431 | |
432 /////////////////////////////////////////////////////////////////////////////// | |
433 | |
434 #define kMaxFontFamilyLength 2048 | |
435 | |
436 SkFontConfigInterfaceDirect::SkFontConfigInterfaceDirect() { | |
437 SkAutoMutexAcquire ac(mutex_); | |
438 | |
439 FcInit(); | |
440 | |
441 SkDEBUGCODE(fontconfiginterface_unittest();) | |
442 } | |
443 | |
444 SkFontConfigInterfaceDirect::~SkFontConfigInterfaceDirect() { | |
445 } | |
446 | |
447 bool SkFontConfigInterfaceDirect::matchFamilyName(const char familyName[], | 420 bool SkFontConfigInterfaceDirect::matchFamilyName(const char familyName[], |
448 SkTypeface::Style style, | 421 SkTypeface::Style style, |
449 FontIdentity* outIdentity, | 422 FontIdentity* outIdentity, |
450 SkString* outFamilyName, | 423 SkString* outFamilyName, |
451 SkTypeface::Style* outStyle) { | 424 SkTypeface::Style* outStyle) { |
452 SkString familyStr(familyName ? familyName : ""); | 425 SkString familyStr(familyName ? familyName : ""); |
453 if (familyStr.size() > kMaxFontFamilyLength) { | 426 if (familyStr.size() > kMaxFontFamilyLength) { |
454 return false; | 427 return false; |
455 } | 428 } |
456 | 429 |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
507 post_config_family = ""; | 480 post_config_family = ""; |
508 } | 481 } |
509 | 482 |
510 FcResult result; | 483 FcResult result; |
511 FcFontSet* font_set = FcFontSort(0, pattern, 0, 0, &result); | 484 FcFontSet* font_set = FcFontSort(0, pattern, 0, 0, &result); |
512 if (!font_set) { | 485 if (!font_set) { |
513 FcPatternDestroy(pattern); | 486 FcPatternDestroy(pattern); |
514 return false; | 487 return false; |
515 } | 488 } |
516 | 489 |
517 FcPattern* match = MatchFont(font_set, post_config_family, familyStr); | 490 FcPattern* match = this->MatchFont(font_set, post_config_family, familyStr); |
518 if (!match) { | 491 if (!match) { |
519 FcPatternDestroy(pattern); | 492 FcPatternDestroy(pattern); |
520 FcFontSetDestroy(font_set); | 493 FcFontSetDestroy(font_set); |
521 return false; | 494 return false; |
522 } | 495 } |
523 | 496 |
524 FcPatternDestroy(pattern); | 497 FcPatternDestroy(pattern); |
525 | 498 |
526 // From here out we just extract our results from 'match' | 499 // From here out we just extract our results from 'match' |
527 | 500 |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
664 | 637 |
665 const char* post_config_family = get_name(pattern, FC_FAMILY); | 638 const char* post_config_family = get_name(pattern, FC_FAMILY); |
666 | 639 |
667 FcResult result; | 640 FcResult result; |
668 FcFontSet* font_set = FcFontSort(0, pattern, 0, 0, &result); | 641 FcFontSet* font_set = FcFontSort(0, pattern, 0, 0, &result); |
669 if (!font_set) { | 642 if (!font_set) { |
670 FcPatternDestroy(pattern); | 643 FcPatternDestroy(pattern); |
671 return false; | 644 return false; |
672 } | 645 } |
673 | 646 |
674 FcPattern* match = MatchFont(font_set, post_config_family, familyStr); | 647 FcPattern* match = this->MatchFont(font_set, post_config_family, familyStr); |
675 if (!match) { | 648 if (!match) { |
676 FcPatternDestroy(pattern); | 649 FcPatternDestroy(pattern); |
677 FcFontSetDestroy(font_set); | 650 FcFontSetDestroy(font_set); |
678 return false; | 651 return false; |
679 } | 652 } |
680 | 653 |
681 FcPatternDestroy(pattern); | 654 FcPatternDestroy(pattern); |
682 | 655 |
683 // From here out we just extract our results from 'match' | 656 // From here out we just extract our results from 'match' |
684 | 657 |
(...skipping 24 matching lines...) Expand all Loading... |
709 outFamilyName->set((const char*)post_config_family); | 682 outFamilyName->set((const char*)post_config_family); |
710 } | 683 } |
711 if (outStyle) { | 684 if (outStyle) { |
712 *outStyle = GetFontStyle(match); | 685 *outStyle = GetFontStyle(match); |
713 } | 686 } |
714 return true; | 687 return true; |
715 | 688 |
716 //////////////////// | 689 //////////////////// |
717 | 690 |
718 int count; | 691 int count; |
719 FcPattern** match = MatchFont(font_set, post_config_family, &count); | 692 FcPattern** match = this->MatchFont(font_set, post_config_family, &count
); |
720 if (!match) { | 693 if (!match) { |
721 FcPatternDestroy(pattern); | 694 FcPatternDestroy(pattern); |
722 FcFontSetDestroy(font_set); | 695 FcFontSetDestroy(font_set); |
723 return nullptr; | 696 return nullptr; |
724 } | 697 } |
725 | 698 |
726 FcPatternDestroy(pattern); | 699 FcPatternDestroy(pattern); |
727 | 700 |
728 SkTDArray<FcPattern*> trimmedMatches; | 701 SkTDArray<FcPattern*> trimmedMatches; |
729 for (int i = 0; i < count; ++i) { | 702 for (int i = 0; i < count; ++i) { |
730 const char* justName = find_just_name(get_name(match[i], FC_FILE)); | 703 const char* justName = find_just_name(get_name(match[i], FC_FILE)); |
731 if (!is_lower(*justName)) { | 704 if (!is_lower(*justName)) { |
732 *trimmedMatches.append() = match[i]; | 705 *trimmedMatches.append() = match[i]; |
733 } | 706 } |
734 } | 707 } |
735 | 708 |
736 SkFontStyleSet_FC* sset = new SkFontStyleSet_FC
(trimmedMatches.begin(),
trimmedMatches.count()); | 709 SkFontStyleSet_FC* sset = new SkFontStyleSet_FC
(trimmedMatches.begin(),
trimmedMatches.count()); |
737 #endif | 710 #endif |
738 return false; | 711 return false; |
739 } | 712 } |
OLD | NEW |