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 |