Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 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 #include "SkDataTable.h" | 8 #include "SkDataTable.h" |
| 9 #include "SkFontDescriptor.h" | 9 #include "SkFontDescriptor.h" |
| 10 #include "SkFontHost_FreeType_common.h" | 10 #include "SkFontHost_FreeType_common.h" |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 99 template<typename T, void (*P)(T*)> void FcTDestroy(T* t) { | 99 template<typename T, void (*P)(T*)> void FcTDestroy(T* t) { |
| 100 FCLocker::AssertHeld(); | 100 FCLocker::AssertHeld(); |
| 101 P(t); | 101 P(t); |
| 102 } | 102 } |
| 103 template <typename T, void (*P)(T*)> class SkAutoFc | 103 template <typename T, void (*P)(T*)> class SkAutoFc |
| 104 : public SkAutoTCallVProc<T, FcTDestroy<T, P> > { | 104 : public SkAutoTCallVProc<T, FcTDestroy<T, P> > { |
| 105 public: | 105 public: |
| 106 SkAutoFc(T* obj) : SkAutoTCallVProc<T, FcTDestroy<T, P> >(obj) {} | 106 SkAutoFc(T* obj) : SkAutoTCallVProc<T, FcTDestroy<T, P> >(obj) {} |
| 107 }; | 107 }; |
| 108 | 108 |
| 109 typedef SkAutoFc<FcCharSet, FcCharSetDestroy> SkAutoFcCharSet; | |
| 109 typedef SkAutoFc<FcConfig, FcConfigDestroy> SkAutoFcConfig; | 110 typedef SkAutoFc<FcConfig, FcConfigDestroy> SkAutoFcConfig; |
| 110 typedef SkAutoFc<FcFontSet, FcFontSetDestroy> SkAutoFcFontSet; | 111 typedef SkAutoFc<FcFontSet, FcFontSetDestroy> SkAutoFcFontSet; |
| 111 typedef SkAutoFc<FcLangSet, FcLangSetDestroy> SkAutoFcLangSet; | 112 typedef SkAutoFc<FcLangSet, FcLangSetDestroy> SkAutoFcLangSet; |
| 112 typedef SkAutoFc<FcObjectSet, FcObjectSetDestroy> SkAutoFcObjectSet; | 113 typedef SkAutoFc<FcObjectSet, FcObjectSetDestroy> SkAutoFcObjectSet; |
| 113 typedef SkAutoFc<FcPattern, FcPatternDestroy> SkAutoFcPattern; | 114 typedef SkAutoFc<FcPattern, FcPatternDestroy> SkAutoFcPattern; |
| 114 | 115 |
| 115 static int get_int(FcPattern* pattern, const char object[], int missing) { | 116 static int get_int(FcPattern* pattern, const char object[], int missing) { |
| 116 int value; | 117 int value; |
| 117 if (FcPatternGetInteger(pattern, object, 0, &value) != FcResultMatch) { | 118 if (FcPatternGetInteger(pattern, object, 0, &value) != FcResultMatch) { |
| 118 return missing; | 119 return missing; |
| (...skipping 524 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 643 continue; | 644 continue; |
| 644 } | 645 } |
| 645 if (0 == FcStrCmpIgnoreCase(patternString, fontString)) { | 646 if (0 == FcStrCmpIgnoreCase(patternString, fontString)) { |
| 646 return true; | 647 return true; |
| 647 } | 648 } |
| 648 } | 649 } |
| 649 } | 650 } |
| 650 return false; | 651 return false; |
| 651 } | 652 } |
| 652 | 653 |
| 653 static bool ValidPattern(FcPattern* pattern) { | 654 static bool FontAccessible(FcPattern* font) { |
| 654 // FontConfig can return fonts which are unreadable. | 655 // FontConfig can return fonts which are unreadable. |
| 655 const char* filename = get_string(pattern, FC_FILE, NULL); | 656 const char* filename = get_string(font, FC_FILE, NULL); |
| 656 if (NULL == filename) { | 657 if (NULL == filename) { |
| 657 return false; | 658 return false; |
| 658 } | 659 } |
| 659 return sk_exists(filename, kRead_SkFILE_Flag); | 660 return sk_exists(filename, kRead_SkFILE_Flag); |
| 660 } | 661 } |
| 661 | 662 |
| 662 static bool FontMatches(FcPattern* font, FcPattern* pattern) { | 663 static bool FontFamilyNameMatches(FcPattern* font, FcPattern* pattern) { |
| 663 return ValidPattern(font) && AnyMatching(font, pattern, FC_FAMILY); | 664 return AnyMatching(font, pattern, FC_FAMILY); |
| 665 } | |
| 666 | |
| 667 static bool FontContainsCharacter(FcPattern* font, uint32_t character) { | |
| 668 FcResult result; | |
| 669 FcCharSet* matchCharSet; | |
| 670 for (int charSetId = 0; ; ++charSetId) { | |
| 671 result = FcPatternGetCharSet(font, FC_CHARSET, charSetId, &matchChar Set); | |
| 672 if (FcResultNoId == result) { | |
| 673 break; | |
| 674 } | |
| 675 if (FcResultMatch != result) { | |
|
mtklein
2014/08/28 21:32:23
// just a sanity check
bungeman-skia
2014/09/09 19:06:17
Acknowledged.
| |
| 676 continue; | |
| 677 } | |
| 678 if (FcCharSetHasChar(matchCharSet, character)) { | |
| 679 return true; | |
| 680 } | |
| 681 } | |
| 682 return false; | |
| 664 } | 683 } |
| 665 | 684 |
| 666 virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVER RIDE { | 685 virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVER RIDE { |
| 667 FCLocker lock; | 686 FCLocker lock; |
| 668 | 687 |
| 669 SkAutoFcPattern pattern(FcPatternCreate()); | 688 SkAutoFcPattern pattern(FcPatternCreate()); |
| 670 if (NULL == pattern) { | 689 if (NULL == pattern) { |
| 671 return NULL; | 690 return NULL; |
| 672 } | 691 } |
| 673 | 692 |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 691 // It should be possible to collapse these patterns by normalizing. | 710 // It should be possible to collapse these patterns by normalizing. |
| 692 static const FcSetName fcNameSet[] = { FcSetSystem, FcSetApplication }; | 711 static const FcSetName fcNameSet[] = { FcSetSystem, FcSetApplication }; |
| 693 for (int setIndex = 0; setIndex < (int)SK_ARRAY_COUNT(fcNameSet); ++setI ndex) { | 712 for (int setIndex = 0; setIndex < (int)SK_ARRAY_COUNT(fcNameSet); ++setI ndex) { |
| 694 // Return value of FcConfigGetFonts must not be destroyed. | 713 // Return value of FcConfigGetFonts must not be destroyed. |
| 695 FcFontSet* allFonts(FcConfigGetFonts(fFC, fcNameSet[setIndex])); | 714 FcFontSet* allFonts(FcConfigGetFonts(fFC, fcNameSet[setIndex])); |
| 696 if (NULL == allFonts) { | 715 if (NULL == allFonts) { |
| 697 continue; | 716 continue; |
| 698 } | 717 } |
| 699 | 718 |
| 700 for (int fontIndex = 0; fontIndex < allFonts->nfont; ++fontIndex) { | 719 for (int fontIndex = 0; fontIndex < allFonts->nfont; ++fontIndex) { |
| 701 if (FontMatches(allFonts->fonts[fontIndex], matchPattern)) { | 720 FcPattern* font = allFonts->fonts[fontIndex]; |
| 702 FcFontSetAdd(matches, | 721 if (FontAccessible(font) && FontFamilyNameMatches(font, matchPat tern)) { |
| 703 FcFontRenderPrepare(fFC, pattern, allFonts->fon ts[fontIndex])); | 722 FcFontSetAdd(matches, FcFontRenderPrepare(fFC, pattern, font )); |
| 704 } | 723 } |
| 705 } | 724 } |
| 706 } | 725 } |
| 707 | 726 |
| 708 return SkNEW_ARGS(StyleSet, (this, matches.detach())); | 727 return SkNEW_ARGS(StyleSet, (this, matches.detach())); |
| 709 } | 728 } |
| 710 | 729 |
| 711 virtual SkTypeface* onMatchFamilyStyle(const char familyName[], | 730 virtual SkTypeface* onMatchFamilyStyle(const char familyName[], |
| 712 const SkFontStyle& style) const SK_OV ERRIDE | 731 const SkFontStyle& style) const SK_OV ERRIDE |
| 713 { | 732 { |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 735 SkAutoFcPattern strongPattern(NULL); | 754 SkAutoFcPattern strongPattern(NULL); |
| 736 if (familyName) { | 755 if (familyName) { |
| 737 strongPattern.reset(FcPatternDuplicate(pattern)); | 756 strongPattern.reset(FcPatternDuplicate(pattern)); |
| 738 remove_weak(strongPattern, FC_FAMILY); | 757 remove_weak(strongPattern, FC_FAMILY); |
| 739 matchPattern = strongPattern; | 758 matchPattern = strongPattern; |
| 740 } else { | 759 } else { |
| 741 matchPattern = pattern; | 760 matchPattern = pattern; |
| 742 } | 761 } |
| 743 | 762 |
| 744 FcResult result; | 763 FcResult result; |
| 745 SkAutoFcPattern match(FcFontMatch(fFC, pattern, &result)); | 764 SkAutoFcPattern font(FcFontMatch(fFC, pattern, &result)); |
| 746 if (NULL == match || !FontMatches(match, matchPattern)) { | 765 if (NULL == font || !FontAccessible(font) || !FontFamilyNameMatches(font , matchPattern)) { |
| 747 return NULL; | 766 return NULL; |
| 748 } | 767 } |
| 749 | 768 |
| 750 return createTypefaceFromFcPattern(match); | 769 return createTypefaceFromFcPattern(font); |
| 770 } | |
| 771 | |
| 772 virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], | |
| 773 const SkFontStyle& style, | |
| 774 const char bpc47[], | |
|
mtklein
2014/08/28 21:32:23
/* may be NULL*/ ?
bungeman-skia
2014/09/09 19:06:17
This sort of comment needs to be over in SkFontMgr
| |
| 775 uint32_t character) const SK _OVERRIDE | |
| 776 { | |
| 777 FCLocker lock; | |
| 778 | |
| 779 SkAutoFcPattern pattern(FcPatternCreate()); | |
| 780 if (NULL == pattern) { | |
|
mtklein
2014/08/28 21:32:23
add SkASSERT(pattern) ?
bungeman-skia
2014/09/09 19:06:17
Done.
| |
| 781 return NULL; | |
| 782 } | |
| 783 | |
| 784 FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName); | |
| 785 fcpattern_from_skfontstyle(style, pattern); | |
| 786 | |
| 787 SkAutoFcCharSet charSet(FcCharSetCreate()); | |
|
mtklein
2014/08/28 21:32:23
No null check?
bungeman-skia
2014/09/09 19:06:17
Done.
| |
| 788 FcCharSetAddChar(charSet, character); | |
| 789 FcPatternAddCharSet(pattern, FC_CHARSET, charSet); | |
| 790 | |
| 791 if (bpc47) { | |
| 792 SkAutoFcLangSet langSet(FcLangSetCreate()); | |
|
mtklein
2014/08/28 21:32:23
...
bungeman-skia
2014/09/09 19:06:17
Done.
| |
| 793 FcLangSetAdd(langSet, (const FcChar8*)bpc47); | |
| 794 FcPatternAddLangSet(pattern, FC_LANG, langSet); | |
| 795 } | |
| 796 | |
| 797 FcConfigSubstitute(fFC, pattern, FcMatchPattern); | |
| 798 FcDefaultSubstitute(pattern); | |
| 799 | |
| 800 FcResult result; | |
| 801 SkAutoFcPattern font(FcFontMatch(fFC, pattern, &result)); | |
| 802 if (NULL == font || !FontAccessible(font) || !FontContainsCharacter(font , character)) { | |
| 803 return NULL; | |
| 804 } | |
| 805 | |
| 806 return createTypefaceFromFcPattern(font); | |
| 751 } | 807 } |
| 752 | 808 |
| 753 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* typeface, | 809 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* typeface, |
| 754 const SkFontStyle& style) const SK_OVER RIDE | 810 const SkFontStyle& style) const SK_OVER RIDE |
| 755 { | 811 { |
| 756 //TODO: should the SkTypeface_fontconfig know its family? | 812 //TODO: should the SkTypeface_fontconfig know its family? |
| 757 const SkTypeface_fontconfig* fcTypeface = | 813 const SkTypeface_fontconfig* fcTypeface = |
| 758 static_cast<const SkTypeface_fontconfig*>(typeface); | 814 static_cast<const SkTypeface_fontconfig*>(typeface); |
| 759 return this->matchFamilyStyle(get_string(fcTypeface->fPattern, FC_FAMILY ), style); | 815 return this->matchFamilyStyle(get_string(fcTypeface->fPattern, FC_FAMILY ), style); |
| 760 } | 816 } |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 800 return typeface.detach(); | 856 return typeface.detach(); |
| 801 } | 857 } |
| 802 | 858 |
| 803 return this->matchFamilyStyle(NULL, style); | 859 return this->matchFamilyStyle(NULL, style); |
| 804 } | 860 } |
| 805 }; | 861 }; |
| 806 | 862 |
| 807 SkFontMgr* SkFontMgr::Factory() { | 863 SkFontMgr* SkFontMgr::Factory() { |
| 808 return SkNEW(SkFontMgr_fontconfig); | 864 return SkNEW(SkFontMgr_fontconfig); |
| 809 } | 865 } |
| OLD | NEW |