Add font fallback support to SkFontMgr_fontconfig.

R=mtklein@google.com, djsollen@google.com

Author: bungeman@google.com

Review URL: https://codereview.chromium.org/489733005
diff --git a/expectations/gm/ignored-tests.txt b/expectations/gm/ignored-tests.txt
index 2a451a3..f1c74cc 100644
--- a/expectations/gm/ignored-tests.txt
+++ b/expectations/gm/ignored-tests.txt
@@ -35,3 +35,6 @@
 
 # jvanverth
 fontcache
+
+#bungeman
+fontmgr_iter
diff --git a/src/ports/SkFontMgr_fontconfig.cpp b/src/ports/SkFontMgr_fontconfig.cpp
index 8dec85f..782fb26 100644
--- a/src/ports/SkFontMgr_fontconfig.cpp
+++ b/src/ports/SkFontMgr_fontconfig.cpp
@@ -96,21 +96,26 @@
 
 } // 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 @@
     // 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 @@
 
     // 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 @@
         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 @@
         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 @@
             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 @@
             }
 
             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 @@
     {
         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 @@
         }
 
         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(match);
+        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(font);
     }
 
     virtual SkTypeface* onMatchFaceStyle(const SkTypeface* typeface,