Index: src/ports/SkFontMgr_fontconfig.cpp |
diff --git a/src/ports/SkFontMgr_fontconfig.cpp b/src/ports/SkFontMgr_fontconfig.cpp |
index 8dec85f6d570881ea434ae7d4ee9ce1864141253..782fb268ccc7e18b2c320b45f3365c3895bb305a 100644 |
--- a/src/ports/SkFontMgr_fontconfig.cpp |
+++ b/src/ports/SkFontMgr_fontconfig.cpp |
@@ -96,21 +96,26 @@ struct FCLocker { |
} // namespace |
-template<typename T, void (*P)(T*)> void FcTDestroy(T* t) { |
+template<typename T, void (*D)(T*)> void FcTDestroy(T* t) { |
FCLocker::AssertHeld(); |
- P(t); |
+ D(t); |
} |
-template <typename T, void (*P)(T*)> class SkAutoFc |
- : public SkAutoTCallVProc<T, FcTDestroy<T, P> > { |
+template <typename T, T* (*C)(), void (*D)(T*)> class SkAutoFc |
+ : public SkAutoTCallVProc<T, FcTDestroy<T, D> > { |
public: |
- SkAutoFc(T* obj) : SkAutoTCallVProc<T, FcTDestroy<T, P> >(obj) {} |
+ SkAutoFc() : SkAutoTCallVProc<T, FcTDestroy<T, D> >(C()) { |
+ T* obj = this->operator T*(); |
+ SK_ALWAYSBREAK(NULL != obj); |
+ } |
+ explicit SkAutoFc(T* obj) : SkAutoTCallVProc<T, FcTDestroy<T, D> >(obj) {} |
}; |
-typedef SkAutoFc<FcConfig, FcConfigDestroy> SkAutoFcConfig; |
-typedef SkAutoFc<FcFontSet, FcFontSetDestroy> SkAutoFcFontSet; |
-typedef SkAutoFc<FcLangSet, FcLangSetDestroy> SkAutoFcLangSet; |
-typedef SkAutoFc<FcObjectSet, FcObjectSetDestroy> SkAutoFcObjectSet; |
-typedef SkAutoFc<FcPattern, FcPatternDestroy> SkAutoFcPattern; |
+typedef SkAutoFc<FcCharSet, FcCharSetCreate, FcCharSetDestroy> SkAutoFcCharSet; |
+typedef SkAutoFc<FcConfig, FcConfigCreate, FcConfigDestroy> SkAutoFcConfig; |
+typedef SkAutoFc<FcFontSet, FcFontSetCreate, FcFontSetDestroy> SkAutoFcFontSet; |
+typedef SkAutoFc<FcLangSet, FcLangSetCreate, FcLangSetDestroy> SkAutoFcLangSet; |
+typedef SkAutoFc<FcObjectSet, FcObjectSetCreate, FcObjectSetDestroy> SkAutoFcObjectSet; |
+typedef SkAutoFc<FcPattern, FcPatternCreate, FcPatternDestroy> SkAutoFcPattern; |
static int get_int(FcPattern* pattern, const char object[], int missing) { |
int value; |
@@ -170,16 +175,16 @@ static SkWeakReturn is_weak(FcPattern* pattern, const char object[], int id) { |
// Create a font set with two patterns. |
// 1. the same 'object' as minimal and a lang object with only 'nomatchlang'. |
// 2. a different 'object' from minimal and a lang object with only 'matchlang'. |
- SkAutoFcFontSet fontSet(FcFontSetCreate()); |
+ SkAutoFcFontSet fontSet; |
- SkAutoFcLangSet strongLangSet(FcLangSetCreate()); |
+ SkAutoFcLangSet strongLangSet; |
FcLangSetAdd(strongLangSet, (const FcChar8*)"nomatchlang"); |
SkAutoFcPattern strong(FcPatternDuplicate(minimal)); |
FcPatternAddLangSet(strong, FC_LANG, strongLangSet); |
- SkAutoFcLangSet weakLangSet(FcLangSetCreate()); |
+ SkAutoFcLangSet weakLangSet; |
FcLangSetAdd(weakLangSet, (const FcChar8*)"matchlang"); |
- SkAutoFcPattern weak(FcPatternCreate()); |
+ SkAutoFcPattern weak; |
FcPatternAddString(weak, object, (const FcChar8*)"nomatchstring"); |
FcPatternAddLangSet(weak, FC_LANG, weakLangSet); |
@@ -195,7 +200,7 @@ static SkWeakReturn is_weak(FcPattern* pattern, const char object[], int id) { |
// Note that this config is only used for FcFontRenderPrepare, which we don't even want. |
// However, there appears to be no way to match/sort without it. |
- SkAutoFcConfig config(FcConfigCreate()); |
+ SkAutoFcConfig config; |
FcFontSet* fontSets[1] = { fontSet }; |
SkAutoFcPattern match(FcFontSetMatch(config, fontSets, SK_ARRAY_COUNT(fontSets), |
minimal, &result)); |
@@ -488,11 +493,7 @@ class SkFontMgr_fontconfig : public SkFontMgr { |
virtual SkTypeface* matchStyle(const SkFontStyle& style) SK_OVERRIDE { |
FCLocker lock; |
- SkAutoFcPattern pattern(FcPatternCreate()); |
- if (NULL == pattern) { |
- return NULL; |
- } |
- |
+ SkAutoFcPattern pattern; |
fcpattern_from_skfontstyle(style, pattern); |
FcConfigSubstitute(fFontMgr->fFC, pattern, FcMatchPattern); |
FcDefaultSubstitute(pattern); |
@@ -650,27 +651,41 @@ protected: |
return false; |
} |
- static bool ValidPattern(FcPattern* pattern) { |
+ static bool FontAccessible(FcPattern* font) { |
// FontConfig can return fonts which are unreadable. |
- const char* filename = get_string(pattern, FC_FILE, NULL); |
+ const char* filename = get_string(font, FC_FILE, NULL); |
if (NULL == filename) { |
return false; |
} |
return sk_exists(filename, kRead_SkFILE_Flag); |
} |
- static bool FontMatches(FcPattern* font, FcPattern* pattern) { |
- return ValidPattern(font) && AnyMatching(font, pattern, FC_FAMILY); |
+ static bool FontFamilyNameMatches(FcPattern* font, FcPattern* pattern) { |
+ return AnyMatching(font, pattern, FC_FAMILY); |
+ } |
+ |
+ static bool FontContainsCharacter(FcPattern* font, uint32_t character) { |
+ FcResult result; |
+ FcCharSet* matchCharSet; |
+ for (int charSetId = 0; ; ++charSetId) { |
+ result = FcPatternGetCharSet(font, FC_CHARSET, charSetId, &matchCharSet); |
+ if (FcResultNoId == result) { |
+ break; |
+ } |
+ if (FcResultMatch != result) { |
+ continue; |
+ } |
+ if (FcCharSetHasChar(matchCharSet, character)) { |
+ return true; |
+ } |
+ } |
+ return false; |
} |
virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVERRIDE { |
FCLocker lock; |
- SkAutoFcPattern pattern(FcPatternCreate()); |
- if (NULL == pattern) { |
- return NULL; |
- } |
- |
+ SkAutoFcPattern pattern; |
FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName); |
FcConfigSubstitute(fFC, pattern, FcMatchPattern); |
FcDefaultSubstitute(pattern); |
@@ -685,7 +700,7 @@ protected: |
matchPattern = pattern; |
} |
- SkAutoFcFontSet matches(FcFontSetCreate()); |
+ SkAutoFcFontSet matches; |
// TODO: Some families have 'duplicates' due to symbolic links. |
// The patterns are exactly the same except for the FC_FILE. |
// It should be possible to collapse these patterns by normalizing. |
@@ -698,9 +713,9 @@ protected: |
} |
for (int fontIndex = 0; fontIndex < allFonts->nfont; ++fontIndex) { |
- if (FontMatches(allFonts->fonts[fontIndex], matchPattern)) { |
- FcFontSetAdd(matches, |
- FcFontRenderPrepare(fFC, pattern, allFonts->fonts[fontIndex])); |
+ FcPattern* font = allFonts->fonts[fontIndex]; |
+ if (FontAccessible(font) && FontFamilyNameMatches(font, matchPattern)) { |
+ FcFontSetAdd(matches, FcFontRenderPrepare(fFC, pattern, font)); |
} |
} |
} |
@@ -713,11 +728,7 @@ protected: |
{ |
FCLocker lock; |
- SkAutoFcPattern pattern(FcPatternCreate()); |
- if (NULL == pattern) { |
- return NULL; |
- } |
- |
+ SkAutoFcPattern pattern; |
FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName); |
fcpattern_from_skfontstyle(style, pattern); |
FcConfigSubstitute(fFC, pattern, FcMatchPattern); |
@@ -742,12 +753,45 @@ protected: |
} |
FcResult result; |
- SkAutoFcPattern match(FcFontMatch(fFC, pattern, &result)); |
- if (NULL == match || !FontMatches(match, matchPattern)) { |
+ SkAutoFcPattern font(FcFontMatch(fFC, pattern, &result)); |
+ if (NULL == font || !FontAccessible(font) || !FontFamilyNameMatches(font, matchPattern)) { |
+ return NULL; |
+ } |
+ |
+ return createTypefaceFromFcPattern(font); |
+ } |
+ |
+ virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], |
+ const SkFontStyle& style, |
+ const char bpc47[], |
+ uint32_t character) const SK_OVERRIDE |
+ { |
+ FCLocker lock; |
+ |
+ SkAutoFcPattern pattern; |
+ FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName); |
+ fcpattern_from_skfontstyle(style, pattern); |
+ |
+ SkAutoFcCharSet charSet; |
+ FcCharSetAddChar(charSet, character); |
+ FcPatternAddCharSet(pattern, FC_CHARSET, charSet); |
+ |
+ if (bpc47) { |
+ SkAutoFcLangSet langSet; |
+ FcLangSetAdd(langSet, (const FcChar8*)bpc47); |
+ FcPatternAddLangSet(pattern, FC_LANG, langSet); |
+ } |
+ |
+ FcConfigSubstitute(fFC, pattern, FcMatchPattern); |
+ FcDefaultSubstitute(pattern); |
+ |
+ FcResult result; |
+ SkAutoFcPattern font(FcFontMatch(fFC, pattern, &result)); |
+ if (NULL == font || !FontAccessible(font) || !FontContainsCharacter(font, character)) { |
return NULL; |
} |
- return createTypefaceFromFcPattern(match); |
+ return createTypefaceFromFcPattern(font); |
} |
virtual SkTypeface* onMatchFaceStyle(const SkTypeface* typeface, |