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 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 Loading... |
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 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) { |
| 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 Loading... |
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 } |
OLD | NEW |