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

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

Issue 489733005: Add font fallback support to SkFontMgr_fontconfig. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Add suppressions for rebaseline. Created 6 years, 3 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
« no previous file with comments | « expectations/gm/ignored-tests.txt ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
89 if (FcGetVersion() < 21091) { 89 if (FcGetVersion() < 21091) {
90 gFCMutex.assertHeld(); 90 gFCMutex.assertHeld();
91 } else { 91 } else {
92 SkASSERT(true == *THREAD_FC_LOCKED); 92 SkASSERT(true == *THREAD_FC_LOCKED);
93 } 93 }
94 ) } 94 ) }
95 }; 95 };
96 96
97 } // namespace 97 } // namespace
98 98
99 template<typename T, void (*P)(T*)> void FcTDestroy(T* t) { 99 template<typename T, void (*D)(T*)> void FcTDestroy(T* t) {
100 FCLocker::AssertHeld(); 100 FCLocker::AssertHeld();
101 P(t); 101 D(t);
102 } 102 }
103 template <typename T, void (*P)(T*)> class SkAutoFc 103 template <typename T, T* (*C)(), void (*D)(T*)> class SkAutoFc
104 : public SkAutoTCallVProc<T, FcTDestroy<T, P> > { 104 : public SkAutoTCallVProc<T, FcTDestroy<T, D> > {
105 public: 105 public:
106 SkAutoFc(T* obj) : SkAutoTCallVProc<T, FcTDestroy<T, P> >(obj) {} 106 SkAutoFc() : SkAutoTCallVProc<T, FcTDestroy<T, D> >(C()) {
107 T* obj = this->operator T*();
108 SK_ALWAYSBREAK(NULL != obj);
109 }
110 explicit SkAutoFc(T* obj) : SkAutoTCallVProc<T, FcTDestroy<T, D> >(obj) {}
107 }; 111 };
108 112
109 typedef SkAutoFc<FcConfig, FcConfigDestroy> SkAutoFcConfig; 113 typedef SkAutoFc<FcCharSet, FcCharSetCreate, FcCharSetDestroy> SkAutoFcCharSet;
110 typedef SkAutoFc<FcFontSet, FcFontSetDestroy> SkAutoFcFontSet; 114 typedef SkAutoFc<FcConfig, FcConfigCreate, FcConfigDestroy> SkAutoFcConfig;
111 typedef SkAutoFc<FcLangSet, FcLangSetDestroy> SkAutoFcLangSet; 115 typedef SkAutoFc<FcFontSet, FcFontSetCreate, FcFontSetDestroy> SkAutoFcFontSet;
112 typedef SkAutoFc<FcObjectSet, FcObjectSetDestroy> SkAutoFcObjectSet; 116 typedef SkAutoFc<FcLangSet, FcLangSetCreate, FcLangSetDestroy> SkAutoFcLangSet;
113 typedef SkAutoFc<FcPattern, FcPatternDestroy> SkAutoFcPattern; 117 typedef SkAutoFc<FcObjectSet, FcObjectSetCreate, FcObjectSetDestroy> SkAutoFcObj ectSet;
118 typedef SkAutoFc<FcPattern, FcPatternCreate, FcPatternDestroy> SkAutoFcPattern;
114 119
115 static int get_int(FcPattern* pattern, const char object[], int missing) { 120 static int get_int(FcPattern* pattern, const char object[], int missing) {
116 int value; 121 int value;
117 if (FcPatternGetInteger(pattern, object, 0, &value) != FcResultMatch) { 122 if (FcPatternGetInteger(pattern, object, 0, &value) != FcResultMatch) {
118 return missing; 123 return missing;
119 } 124 }
120 return value; 125 return value;
121 } 126 }
122 127
123 static const char* get_string(FcPattern* pattern, const char object[], const cha r* missing = "") { 128 static const char* get_string(FcPattern* pattern, const char object[], const cha r* missing = "") {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
163 if (result != FcResultMatch) { 168 if (result != FcResultMatch) {
164 return kNoId_WeakReturn; 169 return kNoId_WeakReturn;
165 } 170 }
166 while (hasId) { 171 while (hasId) {
167 hasId = FcPatternRemove(minimal, object, 1); 172 hasId = FcPatternRemove(minimal, object, 1);
168 } 173 }
169 174
170 // Create a font set with two patterns. 175 // Create a font set with two patterns.
171 // 1. the same 'object' as minimal and a lang object with only 'nomatchlang' . 176 // 1. the same 'object' as minimal and a lang object with only 'nomatchlang' .
172 // 2. a different 'object' from minimal and a lang object with only 'matchla ng'. 177 // 2. a different 'object' from minimal and a lang object with only 'matchla ng'.
173 SkAutoFcFontSet fontSet(FcFontSetCreate()); 178 SkAutoFcFontSet fontSet;
174 179
175 SkAutoFcLangSet strongLangSet(FcLangSetCreate()); 180 SkAutoFcLangSet strongLangSet;
176 FcLangSetAdd(strongLangSet, (const FcChar8*)"nomatchlang"); 181 FcLangSetAdd(strongLangSet, (const FcChar8*)"nomatchlang");
177 SkAutoFcPattern strong(FcPatternDuplicate(minimal)); 182 SkAutoFcPattern strong(FcPatternDuplicate(minimal));
178 FcPatternAddLangSet(strong, FC_LANG, strongLangSet); 183 FcPatternAddLangSet(strong, FC_LANG, strongLangSet);
179 184
180 SkAutoFcLangSet weakLangSet(FcLangSetCreate()); 185 SkAutoFcLangSet weakLangSet;
181 FcLangSetAdd(weakLangSet, (const FcChar8*)"matchlang"); 186 FcLangSetAdd(weakLangSet, (const FcChar8*)"matchlang");
182 SkAutoFcPattern weak(FcPatternCreate()); 187 SkAutoFcPattern weak;
183 FcPatternAddString(weak, object, (const FcChar8*)"nomatchstring"); 188 FcPatternAddString(weak, object, (const FcChar8*)"nomatchstring");
184 FcPatternAddLangSet(weak, FC_LANG, weakLangSet); 189 FcPatternAddLangSet(weak, FC_LANG, weakLangSet);
185 190
186 FcFontSetAdd(fontSet, strong.detach()); 191 FcFontSetAdd(fontSet, strong.detach());
187 FcFontSetAdd(fontSet, weak.detach()); 192 FcFontSetAdd(fontSet, weak.detach());
188 193
189 // Add 'matchlang' to the copy of the pattern. 194 // Add 'matchlang' to the copy of the pattern.
190 FcPatternAddLangSet(minimal, FC_LANG, weakLangSet); 195 FcPatternAddLangSet(minimal, FC_LANG, weakLangSet);
191 196
192 // Run a match against the copy of the pattern. 197 // Run a match against the copy of the pattern.
193 // If the 'id' was weak, then we should match the pattern with 'matchlang'. 198 // If the 'id' was weak, then we should match the pattern with 'matchlang'.
194 // If the 'id' was strong, then we should match the pattern with 'nomatchlan g'. 199 // If the 'id' was strong, then we should match the pattern with 'nomatchlan g'.
195 200
196 // Note that this config is only used for FcFontRenderPrepare, which we don' t even want. 201 // Note that this config is only used for FcFontRenderPrepare, which we don' t even want.
197 // However, there appears to be no way to match/sort without it. 202 // However, there appears to be no way to match/sort without it.
198 SkAutoFcConfig config(FcConfigCreate()); 203 SkAutoFcConfig config;
199 FcFontSet* fontSets[1] = { fontSet }; 204 FcFontSet* fontSets[1] = { fontSet };
200 SkAutoFcPattern match(FcFontSetMatch(config, fontSets, SK_ARRAY_COUNT(fontSe ts), 205 SkAutoFcPattern match(FcFontSetMatch(config, fontSets, SK_ARRAY_COUNT(fontSe ts),
201 minimal, &result)); 206 minimal, &result));
202 207
203 FcLangSet* matchLangSet; 208 FcLangSet* matchLangSet;
204 FcPatternGetLangSet(match, FC_LANG, 0, &matchLangSet); 209 FcPatternGetLangSet(match, FC_LANG, 0, &matchLangSet);
205 return FcLangEqual == FcLangSetHasLang(matchLangSet, (const FcChar8*)"matchl ang") 210 return FcLangEqual == FcLangSetHasLang(matchLangSet, (const FcChar8*)"matchl ang")
206 ? kIsWeak_WeakReturn : kIsStrong_WeakReturn; 211 ? kIsWeak_WeakReturn : kIsStrong_WeakReturn;
207 } 212 }
208 213
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after
481 virtual SkTypeface* createTypeface(int index) SK_OVERRIDE { 486 virtual SkTypeface* createTypeface(int index) SK_OVERRIDE {
482 FCLocker lock; 487 FCLocker lock;
483 488
484 FcPattern* match = fFontSet->fonts[index]; 489 FcPattern* match = fFontSet->fonts[index];
485 return fFontMgr->createTypefaceFromFcPattern(match); 490 return fFontMgr->createTypefaceFromFcPattern(match);
486 } 491 }
487 492
488 virtual SkTypeface* matchStyle(const SkFontStyle& style) SK_OVERRIDE { 493 virtual SkTypeface* matchStyle(const SkFontStyle& style) SK_OVERRIDE {
489 FCLocker lock; 494 FCLocker lock;
490 495
491 SkAutoFcPattern pattern(FcPatternCreate()); 496 SkAutoFcPattern pattern;
492 if (NULL == pattern) {
493 return NULL;
494 }
495
496 fcpattern_from_skfontstyle(style, pattern); 497 fcpattern_from_skfontstyle(style, pattern);
497 FcConfigSubstitute(fFontMgr->fFC, pattern, FcMatchPattern); 498 FcConfigSubstitute(fFontMgr->fFC, pattern, FcMatchPattern);
498 FcDefaultSubstitute(pattern); 499 FcDefaultSubstitute(pattern);
499 500
500 FcResult result; 501 FcResult result;
501 FcFontSet* fontSets[1] = { fFontSet }; 502 FcFontSet* fontSets[1] = { fFontSet };
502 SkAutoFcPattern match(FcFontSetMatch(fFontMgr->fFC, 503 SkAutoFcPattern match(FcFontSetMatch(fFontMgr->fFC,
503 fontSets, SK_ARRAY_COUNT(fontSe ts), 504 fontSets, SK_ARRAY_COUNT(fontSe ts),
504 pattern, &result)); 505 pattern, &result));
505 if (NULL == match) { 506 if (NULL == match) {
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
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) {
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;
670 if (NULL == pattern) {
671 return NULL;
672 }
673
674 FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName); 689 FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName);
675 FcConfigSubstitute(fFC, pattern, FcMatchPattern); 690 FcConfigSubstitute(fFC, pattern, FcMatchPattern);
676 FcDefaultSubstitute(pattern); 691 FcDefaultSubstitute(pattern);
677 692
678 FcPattern* matchPattern; 693 FcPattern* matchPattern;
679 SkAutoFcPattern strongPattern(NULL); 694 SkAutoFcPattern strongPattern(NULL);
680 if (familyName) { 695 if (familyName) {
681 strongPattern.reset(FcPatternDuplicate(pattern)); 696 strongPattern.reset(FcPatternDuplicate(pattern));
682 remove_weak(strongPattern, FC_FAMILY); 697 remove_weak(strongPattern, FC_FAMILY);
683 matchPattern = strongPattern; 698 matchPattern = strongPattern;
684 } else { 699 } else {
685 matchPattern = pattern; 700 matchPattern = pattern;
686 } 701 }
687 702
688 SkAutoFcFontSet matches(FcFontSetCreate()); 703 SkAutoFcFontSet matches;
689 // TODO: Some families have 'duplicates' due to symbolic links. 704 // TODO: Some families have 'duplicates' due to symbolic links.
690 // The patterns are exactly the same except for the FC_FILE. 705 // The patterns are exactly the same except for the FC_FILE.
691 // It should be possible to collapse these patterns by normalizing. 706 // It should be possible to collapse these patterns by normalizing.
692 static const FcSetName fcNameSet[] = { FcSetSystem, FcSetApplication }; 707 static const FcSetName fcNameSet[] = { FcSetSystem, FcSetApplication };
693 for (int setIndex = 0; setIndex < (int)SK_ARRAY_COUNT(fcNameSet); ++setI ndex) { 708 for (int setIndex = 0; setIndex < (int)SK_ARRAY_COUNT(fcNameSet); ++setI ndex) {
694 // Return value of FcConfigGetFonts must not be destroyed. 709 // Return value of FcConfigGetFonts must not be destroyed.
695 FcFontSet* allFonts(FcConfigGetFonts(fFC, fcNameSet[setIndex])); 710 FcFontSet* allFonts(FcConfigGetFonts(fFC, fcNameSet[setIndex]));
696 if (NULL == allFonts) { 711 if (NULL == allFonts) {
697 continue; 712 continue;
698 } 713 }
699 714
700 for (int fontIndex = 0; fontIndex < allFonts->nfont; ++fontIndex) { 715 for (int fontIndex = 0; fontIndex < allFonts->nfont; ++fontIndex) {
701 if (FontMatches(allFonts->fonts[fontIndex], matchPattern)) { 716 FcPattern* font = allFonts->fonts[fontIndex];
702 FcFontSetAdd(matches, 717 if (FontAccessible(font) && FontFamilyNameMatches(font, matchPat tern)) {
703 FcFontRenderPrepare(fFC, pattern, allFonts->fon ts[fontIndex])); 718 FcFontSetAdd(matches, FcFontRenderPrepare(fFC, pattern, font ));
704 } 719 }
705 } 720 }
706 } 721 }
707 722
708 return SkNEW_ARGS(StyleSet, (this, matches.detach())); 723 return SkNEW_ARGS(StyleSet, (this, matches.detach()));
709 } 724 }
710 725
711 virtual SkTypeface* onMatchFamilyStyle(const char familyName[], 726 virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
712 const SkFontStyle& style) const SK_OV ERRIDE 727 const SkFontStyle& style) const SK_OV ERRIDE
713 { 728 {
714 FCLocker lock; 729 FCLocker lock;
715 730
716 SkAutoFcPattern pattern(FcPatternCreate()); 731 SkAutoFcPattern pattern;
717 if (NULL == pattern) {
718 return NULL;
719 }
720
721 FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName); 732 FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName);
722 fcpattern_from_skfontstyle(style, pattern); 733 fcpattern_from_skfontstyle(style, pattern);
723 FcConfigSubstitute(fFC, pattern, FcMatchPattern); 734 FcConfigSubstitute(fFC, pattern, FcMatchPattern);
724 FcDefaultSubstitute(pattern); 735 FcDefaultSubstitute(pattern);
725 736
726 // We really want to match strong (prefered) and same (acceptable) only here. 737 // We really want to match strong (prefered) and same (acceptable) only here.
727 // If a family name was specified, assume that any weak matches after th e last strong match 738 // If a family name was specified, assume that any weak matches after th e last strong match
728 // are weak (default) and ignore them. 739 // are weak (default) and ignore them.
729 // The reason for is that after substitution the pattern for 'sans-serif ' looks like 740 // The reason for is that after substitution the pattern for 'sans-serif ' looks like
730 // "wwwwwwwwwwwwwwswww" where there are many weak but preferred names, f ollowed by defaults. 741 // "wwwwwwwwwwwwwwswww" where there are many weak but preferred names, f ollowed by defaults.
731 // So it is possible to have weakly matching but preferred names. 742 // So it is possible to have weakly matching but preferred names.
732 // In aliases, bindings are weak by default, so this is easy and common. 743 // In aliases, bindings are weak by default, so this is easy and common.
733 // If no family name was specified, we'll probably only get weak matches , but that's ok. 744 // If no family name was specified, we'll probably only get weak matches , but that's ok.
734 FcPattern* matchPattern; 745 FcPattern* matchPattern;
735 SkAutoFcPattern strongPattern(NULL); 746 SkAutoFcPattern strongPattern(NULL);
736 if (familyName) { 747 if (familyName) {
737 strongPattern.reset(FcPatternDuplicate(pattern)); 748 strongPattern.reset(FcPatternDuplicate(pattern));
738 remove_weak(strongPattern, FC_FAMILY); 749 remove_weak(strongPattern, FC_FAMILY);
739 matchPattern = strongPattern; 750 matchPattern = strongPattern;
740 } else { 751 } else {
741 matchPattern = pattern; 752 matchPattern = pattern;
742 } 753 }
743 754
744 FcResult result; 755 FcResult result;
745 SkAutoFcPattern match(FcFontMatch(fFC, pattern, &result)); 756 SkAutoFcPattern font(FcFontMatch(fFC, pattern, &result));
746 if (NULL == match || !FontMatches(match, matchPattern)) { 757 if (NULL == font || !FontAccessible(font) || !FontFamilyNameMatches(font , matchPattern)) {
747 return NULL; 758 return NULL;
748 } 759 }
749 760
750 return createTypefaceFromFcPattern(match); 761 return createTypefaceFromFcPattern(font);
762 }
763
764 virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
765 const SkFontStyle& style,
766 const char bpc47[],
767 uint32_t character) const SK _OVERRIDE
768 {
769 FCLocker lock;
770
771 SkAutoFcPattern pattern;
772 FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName);
773 fcpattern_from_skfontstyle(style, pattern);
774
775 SkAutoFcCharSet charSet;
776 FcCharSetAddChar(charSet, character);
777 FcPatternAddCharSet(pattern, FC_CHARSET, charSet);
778
779 if (bpc47) {
780 SkAutoFcLangSet langSet;
781 FcLangSetAdd(langSet, (const FcChar8*)bpc47);
782 FcPatternAddLangSet(pattern, FC_LANG, langSet);
783 }
784
785 FcConfigSubstitute(fFC, pattern, FcMatchPattern);
786 FcDefaultSubstitute(pattern);
787
788 FcResult result;
789 SkAutoFcPattern font(FcFontMatch(fFC, pattern, &result));
790 if (NULL == font || !FontAccessible(font) || !FontContainsCharacter(font , character)) {
791 return NULL;
792 }
793
794 return createTypefaceFromFcPattern(font);
751 } 795 }
752 796
753 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* typeface, 797 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* typeface,
754 const SkFontStyle& style) const SK_OVER RIDE 798 const SkFontStyle& style) const SK_OVER RIDE
755 { 799 {
756 //TODO: should the SkTypeface_fontconfig know its family? 800 //TODO: should the SkTypeface_fontconfig know its family?
757 const SkTypeface_fontconfig* fcTypeface = 801 const SkTypeface_fontconfig* fcTypeface =
758 static_cast<const SkTypeface_fontconfig*>(typeface); 802 static_cast<const SkTypeface_fontconfig*>(typeface);
759 return this->matchFamilyStyle(get_string(fcTypeface->fPattern, FC_FAMILY ), style); 803 return this->matchFamilyStyle(get_string(fcTypeface->fPattern, FC_FAMILY ), style);
760 } 804 }
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
800 return typeface.detach(); 844 return typeface.detach();
801 } 845 }
802 846
803 return this->matchFamilyStyle(NULL, style); 847 return this->matchFamilyStyle(NULL, style);
804 } 848 }
805 }; 849 };
806 850
807 SkFontMgr* SkFontMgr::Factory() { 851 SkFontMgr* SkFontMgr::Factory() {
808 return SkNEW(SkFontMgr_fontconfig); 852 return SkNEW(SkFontMgr_fontconfig);
809 } 853 }
OLDNEW
« no previous file with comments | « expectations/gm/ignored-tests.txt ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698