Fix string matching TODO in SkFontMgr_fontconfig

FontConfig may report many names for a given font pattern (since a font
may have many names) and the match pattern may itself have many names.
We wish to know if any font pattern name matches any match
pattern name. Previously this was done with brute force, limiting the
number of names that could reasonably be compared. Instead sort the
lists of names and then compare the sorted lists.

Change-Id: I22e80f0f7ae941d234cad43799c6fb76bee0f841
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/783386
Commit-Queue: Ben Wagner <bungeman@google.com>
Reviewed-by: John Stiles <johnstiles@google.com>
diff --git a/src/ports/BUILD.bazel b/src/ports/BUILD.bazel
index 7106b03..afc27e9 100644
--- a/src/ports/BUILD.bazel
+++ b/src/ports/BUILD.bazel
@@ -84,7 +84,7 @@
             "//bazel/common_config_settings:custom_directory_fontmgr": [":fontmgr_custom_directory"],
             "//bazel/common_config_settings:custom_embedded_fontmgr": [":fontmgr_custom_embedded"],
             "//bazel/common_config_settings:custom_empty_fontmgr": [":fontmgr_custom_empty"],
-            "//bazel/common_config_settings:fontconfig_fontmgr": [":fontmgr_fontconfig"],
+            "//bazel/common_config_settings:fontconfig_fontmgr": [":legacy_fontmgr_fontconfig"],
             "//bazel/common_config_settings:fci_fontmgr": [":fontmgr_fci"],
         },
     ),
diff --git a/src/ports/SkFontMgr_fontconfig.cpp b/src/ports/SkFontMgr_fontconfig.cpp
index 389b6a4..12b1e95 100644
--- a/src/ports/SkFontMgr_fontconfig.cpp
+++ b/src/ports/SkFontMgr_fontconfig.cpp
@@ -6,31 +6,43 @@
  */
 
 #include "include/core/SkDataTable.h"
+#include "include/core/SkFontArguments.h"
 #include "include/core/SkFontMgr.h"
 #include "include/core/SkFontStyle.h"
+#include "include/core/SkMatrix.h"
 #include "include/core/SkRefCnt.h"
+#include "include/core/SkScalar.h"
 #include "include/core/SkStream.h"
 #include "include/core/SkString.h"
 #include "include/core/SkTypeface.h"
 #include "include/core/SkTypes.h"
-#include "include/private/base/SkFixed.h"
-#include "include/private/base/SkMath.h"
+#include "include/private/base/SkDebug.h"
 #include "include/private/base/SkMutex.h"
+#include "include/private/base/SkTArray.h"
 #include "include/private/base/SkTDArray.h"
 #include "include/private/base/SkTemplates.h"
+#include "include/private/base/SkThreadAnnotations.h"
+#include "src/base/SkTSort.h"
 #include "src/core/SkAdvancedTypefaceMetrics.h"
 #include "src/core/SkFontDescriptor.h"
 #include "src/core/SkOSFile.h"
+#include "src/core/SkScalerContext.h"
 #include "src/core/SkTypefaceCache.h"
 #include "src/ports/SkFontHost_FreeType_common.h"
 
 #include <fontconfig/fontconfig.h>
-#include <string.h>
 
-using namespace skia_private;
+#include <string.h>
+#include <array>
+#include <cstddef>
+#include <cstdint>
+#include <memory>
+#include <utility>
 
 class SkData;
 
+using namespace skia_private;
+
 // FC_POSTSCRIPT_NAME was added with b561ff20 which ended up in 2.10.92
 // Ubuntu 14.04 is on 2.11.0
 // Debian 8 and 9 are on 2.11
@@ -702,32 +714,43 @@
     /** True if any string object value in the font is the same
      *         as a string object value in the pattern.
      */
-    static bool AnyMatching(FcPattern* font, FcPattern* pattern, const char* object) {
-        FcChar8* fontString;
-        FcChar8* patternString;
-        FcResult result;
-        // Set an arbitrary limit on the number of pattern object values to consider.
-        // TODO: re-write this to avoid N*M
-        static const int maxId = 16;
-        for (int patternId = 0; patternId < maxId; ++patternId) {
-            result = FcPatternGetString(pattern, object, patternId, &patternString);
-            if (FcResultNoId == result) {
-                break;
-            }
-            if (FcResultMatch != result) {
-                continue;
-            }
-            for (int fontId = 0; fontId < maxId; ++fontId) {
-                result = FcPatternGetString(font, object, fontId, &fontString);
-                if (FcResultNoId == result) {
+    static bool AnyStringMatching(FcPattern* font, FcPattern* pattern, const char* object) {
+        auto getStrings = [](FcPattern* p, const char* object, STArray<32, FcChar8*>& strings) {
+            // Set an arbitrary (but high) limit on the number of pattern object values to consider.
+            static constexpr const int maxId = 65536;
+            for (int patternId = 0; patternId < maxId; ++patternId) {
+                FcChar8* patternString;
+                FcResult result = FcPatternGetString(p, object, patternId, &patternString);
+                if (result == FcResultNoId) {
                     break;
                 }
-                if (FcResultMatch != result) {
-                    continue;
+                if (result == FcResultMatch) {
+                    strings.push_back(patternString);
                 }
-                if (0 == FcStrCmpIgnoreCase(patternString, fontString)) {
-                    return true;
-                }
+            }
+        };
+        auto compareStrings = [](FcChar8* a, FcChar8* b) -> bool {
+            return FcStrCmpIgnoreCase(a, b) < 0;
+        };
+
+        STArray<32, FcChar8*> fontStrings;
+        STArray<32, FcChar8*> patternStrings;
+        getStrings(font, object, fontStrings);
+        getStrings(pattern, object, patternStrings);
+
+        SkTQSort(fontStrings.begin(), fontStrings.end(), compareStrings);
+        SkTQSort(patternStrings.begin(), patternStrings.end(), compareStrings);
+
+        FcChar8** fontString = fontStrings.begin();
+        FcChar8** patternString = patternStrings.begin();
+        while (fontString != fontStrings.end() && patternString != patternStrings.end()) {
+            int cmp = FcStrCmpIgnoreCase(*fontString, *patternString);
+            if (cmp < 0) {
+                ++fontString;
+            } else if (cmp > 0) {
+                ++patternString;
+            } else {
+                return true;
             }
         }
         return false;
@@ -761,7 +784,7 @@
     }
 
     static bool FontFamilyNameMatches(FcPattern* font, FcPattern* pattern) {
-        return AnyMatching(font, pattern, FC_FAMILY);
+        return AnyStringMatching(font, pattern, FC_FAMILY);
     }
 
     static bool FontContainsCharacter(FcPattern* font, uint32_t character) {
diff --git a/toolchain/linux_trampolines/clang_trampoline_linux.sh b/toolchain/linux_trampolines/clang_trampoline_linux.sh
index aacac9c..0cd7c71 100755
--- a/toolchain/linux_trampolines/clang_trampoline_linux.sh
+++ b/toolchain/linux_trampolines/clang_trampoline_linux.sh
@@ -38,6 +38,7 @@
   "src/gpu/ganesh/surface/"
   "src/image/"
   "src/pathops/"
+  "src/ports/SkFontMgr_fontconfig"
   "src/shaders/"
   "src/sksl/"
   "src/svg/"