add a SkFontMgr to DM that returns portable fonts

Controlled by --[no]nativeFonts, and still defaults to native fonts.

Change-Id: Ib2879e69fadb63ddb5a17a7e4ae227941893b8cf
Reviewed-on: https://skia-review.googlesource.com/67806
Reviewed-by: Ben Wagner <bungeman@google.com>
Commit-Queue: Mike Klein <mtklein@chromium.org>
diff --git a/BUILD.gn b/BUILD.gn
index 3cf2352..e7744c9 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -1340,6 +1340,7 @@
     test_app("dm") {
       sources = [
         "dm/DM.cpp",
+        "dm/DMFontMgr.cpp",
         "dm/DMGpuTestProcs.cpp",
         "dm/DMJsonWriter.cpp",
         "dm/DMSrcSink.cpp",
diff --git a/dm/DM.cpp b/dm/DM.cpp
index cb5332d..b751393 100644
--- a/dm/DM.cpp
+++ b/dm/DM.cpp
@@ -5,6 +5,7 @@
  * found in the LICENSE file.
  */
 
+#include "DMFontMgr.h"
 #include "DMJsonWriter.h"
 #include "DMSrcSink.h"
 #include "ProcStats.h"
@@ -101,6 +102,9 @@
 
 DEFINE_string(dont_write, "", "File extensions to skip writing to --writePath.");  // See skia:6821
 
+DEFINE_bool(nativeFonts, true, "If true, use native font manager and rendering. "
+                               "If false, fonts will draw as portably as possible.");
+
 using namespace DM;
 using sk_gpu_test::GrContextFactory;
 using sk_gpu_test::GLTestContext;
@@ -1307,9 +1311,18 @@
 
 extern sk_sp<SkTypeface> (*gCreateTypefaceDelegate)(const char [], SkFontStyle );
 
+extern sk_sp<SkFontMgr> (*gSkFontMgr_DefaultFactory)();
+
+
 int main(int argc, char** argv) {
     SkCommandLineFlags::Parse(argc, argv);
 
+    if (!FLAGS_nativeFonts) {
+        gSkFontMgr_DefaultFactory = []() -> sk_sp<SkFontMgr> {
+            return sk_make_sp<DM::FontMgr>();
+        };
+    }
+
     initializeEventTracingForTools();
 
 #if !defined(GOOGLE3) && defined(SK_BUILD_FOR_IOS)
diff --git a/dm/DMFontMgr.cpp b/dm/DMFontMgr.cpp
new file mode 100644
index 0000000..51ee612
--- /dev/null
+++ b/dm/DMFontMgr.cpp
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "DMFontMgr.h"
+#include "SkFontDescriptor.h"
+#include "sk_tool_utils.h"
+
+namespace DM {
+
+    static constexpr const char* kFamilyNames[] = {
+        "Toy Liberation Sans",
+        "Toy Liberation Serif",
+        "Toy Liberation Mono",
+    };
+
+    FontStyleSet::FontStyleSet(int familyIndex) : fFamilyName(kFamilyNames[familyIndex]) {}
+
+    // Each font family has 4 styles: Normal, Bold, Italic, BoldItalic.
+    int FontStyleSet::count() { return 4; }
+    void FontStyleSet::getStyle(int index, SkFontStyle* style, SkString* name) {
+        switch (index) {
+            default:
+            case  0: if (style) { *style = SkFontStyle::Normal(); }
+                     if (name)  { *name = "Normal"; }
+                     break;
+            case  1: if (style) { *style = SkFontStyle::Bold(); }
+                     if (name)  { *name = "Bold"; }
+                     break;
+            case  2: if (style) { *style = SkFontStyle::Italic(); }
+                     if (name)  { *name = "Italic"; }
+                     break;
+            case  3: if (style) { *style = SkFontStyle::BoldItalic(); }
+                     if (name)  { *name = "BoldItalic"; }
+                     break;
+        }
+    }
+
+    SkTypeface* FontStyleSet::matchStyle(const SkFontStyle& style) {
+        return this->matchStyleCSS3(style);
+    }
+
+    SkTypeface* FontStyleSet::createTypeface(int index) {
+        SkFontStyle style;
+        this->getStyle(index, &style, nullptr);
+
+        return sk_tool_utils::create_portable_typeface(fFamilyName, style).release();
+    }
+
+    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
+
+    int FontMgr::onCountFamilies() const { return SK_ARRAY_COUNT(kFamilyNames); }
+
+    void FontMgr::onGetFamilyName(int index, SkString* familyName) const {
+        *familyName = kFamilyNames[index];
+    }
+
+    SkFontStyleSet* FontMgr::onCreateStyleSet(int index) const {
+        return new FontStyleSet(index);
+    }
+
+    SkFontStyleSet* FontMgr::onMatchFamily(const char familyName[]) const {
+        if (familyName) {
+            if (strstr(familyName,  "ans")) { return this->createStyleSet(0); }
+            if (strstr(familyName, "erif")) { return this->createStyleSet(1); }
+            if (strstr(familyName,  "ono")) { return this->createStyleSet(2); }
+        }
+        return this->createStyleSet(0);
+    }
+
+    SkTypeface* FontMgr::onMatchFamilyStyle(const char familyName[],
+                                            const SkFontStyle& style) const {
+        sk_sp<SkFontStyleSet> styleSet(this->matchFamily(familyName));
+        return styleSet->matchStyle(style);
+    }
+
+    SkTypeface* FontMgr::onMatchFamilyStyleCharacter(const char familyName[],
+                                                     const SkFontStyle& style,
+                                                     const char* bcp47[],
+                                                     int bcp47Count,
+                                                     SkUnichar character) const {
+        (void)bcp47;
+        (void)bcp47Count;
+        (void)character;
+        return this->matchFamilyStyle(familyName, style);
+    }
+
+    SkTypeface* FontMgr::onMatchFaceStyle(const SkTypeface* tf,
+                                          const SkFontStyle& style) const {
+        SkString familyName;
+        tf->getFamilyName(&familyName);
+        return this->matchFamilyStyle(familyName.c_str(), style);
+    }
+
+    sk_sp<SkTypeface> FontMgr::onMakeFromData(sk_sp<SkData>, int ttcIndex) const {
+        return sk_sp<SkTypeface>(this->matchFamilyStyle("Sans", SkFontStyle::Normal()));
+    }
+
+    sk_sp<SkTypeface> FontMgr::onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset>,
+                                                     int ttcIndex) const {
+        return sk_sp<SkTypeface>(this->matchFamilyStyle("Sans", SkFontStyle::Normal()));
+    }
+
+    sk_sp<SkTypeface> FontMgr::onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset>,
+                                                    const SkFontArguments&) const {
+        return sk_sp<SkTypeface>(this->matchFamilyStyle("Sans", SkFontStyle::Normal()));
+    }
+
+    sk_sp<SkTypeface> FontMgr::onMakeFromFontData(std::unique_ptr<SkFontData>) const {
+        return sk_sp<SkTypeface>(this->matchFamilyStyle("Sans", SkFontStyle::Normal()));
+    }
+
+    sk_sp<SkTypeface> FontMgr::onMakeFromFile(const char path[], int ttcIndex) const {
+        return sk_sp<SkTypeface>(this->matchFamilyStyle("Sans", SkFontStyle::Normal()));
+    }
+
+    sk_sp<SkTypeface> FontMgr::onLegacyMakeTypeface(const char familyName[],
+                                                    SkFontStyle style) const {
+        return sk_sp<SkTypeface>(this->matchFamilyStyle(familyName, style));
+    }
+
+} // namespace DM
diff --git a/dm/DMFontMgr.h b/dm/DMFontMgr.h
new file mode 100644
index 0000000..b2eb0ac
--- /dev/null
+++ b/dm/DMFontMgr.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef DMFontMgr_DEFINED
+#define DMFontMgr_DEFINED
+
+#include "SkFontMgr.h"
+
+// An SkFontMgr that always uses sk_tool_utils::create_portable_typeface().
+
+namespace DM {
+
+    // Returned by DM::FontMgr below.
+    class FontStyleSet final : public SkFontStyleSet {
+    public:
+        explicit FontStyleSet(int familyIndex);
+
+        int count() override;
+        void getStyle(int index, SkFontStyle* style, SkString* name) override;
+        SkTypeface* createTypeface(int index) override;
+        SkTypeface* matchStyle(const SkFontStyle& pattern) override;
+
+    private:
+        const char* fFamilyName;
+    };
+
+    struct FontMgr final : public SkFontMgr {
+
+        int onCountFamilies() const override;
+        void onGetFamilyName(int index, SkString* familyName) const override;
+
+        SkFontStyleSet* onCreateStyleSet(int index) const override;
+        SkFontStyleSet* onMatchFamily(const char familyName[]) const override;
+
+        SkTypeface* onMatchFamilyStyle(const char familyName[],
+                                       const SkFontStyle&) const override;
+        SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
+                                                const SkFontStyle&,
+                                                const char* bcp47[], int bcp47Count,
+                                                SkUnichar character) const override;
+        SkTypeface* onMatchFaceStyle(const SkTypeface*,
+                                     const SkFontStyle&) const override;
+
+        sk_sp<SkTypeface> onMakeFromData(sk_sp<SkData>, int ttcIndex) const override;
+        sk_sp<SkTypeface> onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset>,
+                                                int ttcIndex) const override;
+        sk_sp<SkTypeface> onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset>,
+                                               const SkFontArguments&) const override;
+        sk_sp<SkTypeface> onMakeFromFontData(std::unique_ptr<SkFontData>) const override;
+        sk_sp<SkTypeface> onMakeFromFile(const char path[], int ttcIndex) const override;
+
+        sk_sp<SkTypeface> onLegacyMakeTypeface(const char familyName[], SkFontStyle) const override;
+    };
+
+}  // namespace DM
+
+#endif//DMFontMgr_DEFINED
diff --git a/src/core/SkFontMgr.cpp b/src/core/SkFontMgr.cpp
index 33eb230..4e64de1 100644
--- a/src/core/SkFontMgr.cpp
+++ b/src/core/SkFontMgr.cpp
@@ -172,12 +172,16 @@
     return this->makeFromStream(data->detachStream(), data->getIndex());
 }
 
+// A global function pointer that's not declared, but can be overriden at startup by test tools.
+sk_sp<SkFontMgr> (*gSkFontMgr_DefaultFactory)() = nullptr;
+
 sk_sp<SkFontMgr> SkFontMgr::RefDefault() {
     static SkOnce once;
     static sk_sp<SkFontMgr> singleton;
 
     once([]{
-        sk_sp<SkFontMgr> fm = SkFontMgr::Factory();
+        sk_sp<SkFontMgr> fm = gSkFontMgr_DefaultFactory ? gSkFontMgr_DefaultFactory()
+                                                        : SkFontMgr::Factory();
         singleton = fm ? std::move(fm) : sk_make_sp<SkEmptyFontMgr>();
     });
     return singleton;