Move scaler context fallback to GDI

The GDI Typeface is the only one that can fail to make a
scaler context. Move all the logic to the GDI specific code.

Change-Id: I50a0a58529bb44625068244e6ae27e54bccd9f67
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/269913
Commit-Queue: Herb Derby <herb@google.com>
Reviewed-by: Herb Derby <herb@google.com>
Reviewed-by: Ben Wagner <bungeman@google.com>
diff --git a/include/core/SkTypeface.h b/include/core/SkTypeface.h
index 64a6898..3ace52f 100644
--- a/include/core/SkTypeface.h
+++ b/include/core/SkTypeface.h
@@ -320,13 +320,11 @@
     std::unique_ptr<SkFontData> makeFontData() const;
 
     /**
-     *  Return a scalercontext for the given descriptor. If this fails, then
-     *  if allowFailure is true, this returns NULL, else it returns a
+     *  Return a scalercontext for the given descriptor. It may return a
      *  dummy scalercontext that will not crash, but will draw nothing.
      */
     std::unique_ptr<SkScalerContext> createScalerContext(const SkScalerContextEffects&,
-                                                         const SkDescriptor*,
-                                                         bool allowFailure = false) const;
+                                                         const SkDescriptor*) const;
 
     /**
      *  Return a rectangle (scaled to 1-pt) that represents the union of the bounds of all
@@ -361,6 +359,7 @@
     /** Sets the font style. If used, must be called in the constructor. */
     void setFontStyle(SkFontStyle style) { fStyle = style; }
 
+    // Must return a valid scaler context. It can not return nullptr.
     virtual SkScalerContext* onCreateScalerContext(const SkScalerContextEffects&,
                                                    const SkDescriptor*) const = 0;
     virtual void onFilterRec(SkScalerContextRec*) const = 0;
diff --git a/src/core/SkRemoteGlyphCache.cpp b/src/core/SkRemoteGlyphCache.cpp
index 2d2b6d1..46f09b1 100644
--- a/src/core/SkRemoteGlyphCache.cpp
+++ b/src/core/SkRemoteGlyphCache.cpp
@@ -952,7 +952,7 @@
             // glyphs here anyway, and the desc is still correct since it includes the serialized
             // effects.
             SkScalerContextEffects effects;
-            auto scaler = SkStrikeCache::CreateScalerContext(*client_desc, effects, *tf);
+            auto scaler = tf->createScalerContext(effects, client_desc);
             strike = fStrikeCache->createStrikeExclusive(
                     *client_desc, std::move(scaler), &fontMetrics,
                     std::make_unique<DiscardableStrikePinner>(
diff --git a/src/core/SkScalerContext.cpp b/src/core/SkScalerContext.cpp
index 930692b..987ebb5 100644
--- a/src/core/SkScalerContext.cpp
+++ b/src/core/SkScalerContext.cpp
@@ -863,53 +863,13 @@
             SkColorSetRGB(SkColorGetR(c), SkColorGetG(c), SkColorGetB(c)));
 }
 
-///////////////////////////////////////////////////////////////////////////////
-
-class SkScalerContext_Empty : public SkScalerContext {
-public:
-    SkScalerContext_Empty(sk_sp<SkTypeface> typeface, const SkScalerContextEffects& effects,
-                          const SkDescriptor* desc)
-        : SkScalerContext(std::move(typeface), effects, desc) {}
-
-protected:
-    unsigned generateGlyphCount() override {
-        return 0;
-    }
-    bool generateAdvance(SkGlyph* glyph) override {
-        glyph->zeroMetrics();
-        return true;
-    }
-    void generateMetrics(SkGlyph* glyph) override {
-        glyph->fMaskFormat = fRec.fMaskFormat;
-        glyph->zeroMetrics();
-    }
-    void generateImage(const SkGlyph& glyph) override {}
-    bool generatePath(SkGlyphID glyph, SkPath* path) override {
-        path->reset();
-        return false;
-    }
-    void generateFontMetrics(SkFontMetrics* metrics) override {
-        if (metrics) {
-            sk_bzero(metrics, sizeof(*metrics));
-        }
-    }
-};
-
 extern SkScalerContext* SkCreateColorScalerContext(const SkDescriptor* desc);
 
 std::unique_ptr<SkScalerContext> SkTypeface::createScalerContext(
-    const SkScalerContextEffects& effects, const SkDescriptor* desc, bool allowFailure) const
-{
-    std::unique_ptr<SkScalerContext> c(this->onCreateScalerContext(effects, desc));
-    if (!c && !allowFailure) {
-        c = std::make_unique<SkScalerContext_Empty>(sk_ref_sp(const_cast<SkTypeface*>(this)),
-                                                      effects, desc);
-    }
-
-    // !allowFailure implies c != nullptr
-    SkASSERT(c || allowFailure);
-
-    return c;
+        const SkScalerContextEffects& effects, const SkDescriptor* desc) const {
+    auto answer = std::unique_ptr<SkScalerContext>{this->onCreateScalerContext(effects, desc)};
+    SkASSERT(answer != nullptr);
+    return answer;
 }
 
 /*
@@ -1198,6 +1158,42 @@
     return size >= calculate_size_and_flatten(rec, effects, &buf);
 }
 
+SkScalerContext* SkScalerContext::MakeEmptyContext(
+        sk_sp<SkTypeface> typeface, const SkScalerContextEffects& effects,
+        const SkDescriptor* desc) {
+    class SkScalerContext_Empty : public SkScalerContext {
+    public:
+        SkScalerContext_Empty(sk_sp<SkTypeface> typeface, const SkScalerContextEffects& effects,
+                              const SkDescriptor* desc)
+                : SkScalerContext(std::move(typeface), effects, desc) {}
+
+    protected:
+        unsigned generateGlyphCount() override {
+            return 0;
+        }
+        bool generateAdvance(SkGlyph* glyph) override {
+            glyph->zeroMetrics();
+            return true;
+        }
+        void generateMetrics(SkGlyph* glyph) override {
+            glyph->fMaskFormat = fRec.fMaskFormat;
+            glyph->zeroMetrics();
+        }
+        void generateImage(const SkGlyph& glyph) override {}
+        bool generatePath(SkGlyphID glyph, SkPath* path) override {
+            path->reset();
+            return false;
+        }
+        void generateFontMetrics(SkFontMetrics* metrics) override {
+            if (metrics) {
+                sk_bzero(metrics, sizeof(*metrics));
+            }
+        }
+    };
+
+    return new SkScalerContext_Empty{std::move(typeface), effects, desc};
+}
+
 
 
 
diff --git a/src/core/SkScalerContext.h b/src/core/SkScalerContext.h
index fc4f941..735ea19 100644
--- a/src/core/SkScalerContext.h
+++ b/src/core/SkScalerContext.h
@@ -323,6 +323,10 @@
     static SkDescriptor*  MakeDescriptorForPaths(SkFontID fontID,
                                                  SkAutoDescriptor* ad);
 
+    static SkScalerContext* MakeEmptyContext(
+            sk_sp<SkTypeface> typeface, const SkScalerContextEffects& effects,
+            const SkDescriptor* desc);
+
     static SkDescriptor* AutoDescriptorGivenRecAndEffects(
         const SkScalerContextRec& rec,
         const SkScalerContextEffects& effects,
diff --git a/src/core/SkStrikeCache.cpp b/src/core/SkStrikeCache.cpp
index f90caa2..98733f7 100644
--- a/src/core/SkStrikeCache.cpp
+++ b/src/core/SkStrikeCache.cpp
@@ -140,23 +140,6 @@
     }
 }
 
-std::unique_ptr<SkScalerContext> SkStrikeCache::CreateScalerContext(
-        const SkDescriptor& desc,
-        const SkScalerContextEffects& effects,
-        const SkTypeface& typeface) {
-    auto scaler = typeface.createScalerContext(effects, &desc, true /* can fail */);
-
-    // Check if we can create a scaler-context before creating the glyphcache.
-    // If not, we may have exhausted OS/font resources, so try purging the
-    // cache once and try again
-    // pass true the first time, to notice if the scalercontext failed,
-    if (scaler == nullptr) {
-        PurgeAll();
-        scaler = typeface.createScalerContext(effects, &desc, false /* must succeed */);
-    }
-    return scaler;
-}
-
 SkExclusiveStrikePtr SkStrikeCache::findOrCreateStrikeExclusive(
         const SkDescriptor& desc, const SkScalerContextEffects& effects, const SkTypeface& typeface)
 {
@@ -168,7 +151,7 @@
                                        const SkTypeface& typeface) -> Node* {
     Node* node = this->findAndDetachStrike(desc);
     if (node == nullptr) {
-        auto scaler = CreateScalerContext(desc, effects, typeface);
+        auto scaler = typeface.createScalerContext(effects, &desc);
         node = this->createStrike(desc, std::move(scaler));
     }
     return node;
diff --git a/src/core/SkStrikeCache.h b/src/core/SkStrikeCache.h
index db5ee6b..89035bd 100644
--- a/src/core/SkStrikeCache.h
+++ b/src/core/SkStrikeCache.h
@@ -86,9 +86,6 @@
                                                   const SkScalerContextEffects& effects,
                                                   const SkTypeface& typeface) override;
 
-    static std::unique_ptr<SkScalerContext> CreateScalerContext(
-            const SkDescriptor&, const SkScalerContextEffects&, const SkTypeface&);
-
     static void PurgeAll();
     static void ValidateGlyphCacheDataSize();
     static void Dump();
diff --git a/src/core/SkTypeface.cpp b/src/core/SkTypeface.cpp
index 69e5de6..2cfa6b7 100644
--- a/src/core/SkTypeface.cpp
+++ b/src/core/SkTypeface.cpp
@@ -14,6 +14,7 @@
 #include "src/core/SkAdvancedTypefaceMetrics.h"
 #include "src/core/SkEndian.h"
 #include "src/core/SkFontDescriptor.h"
+#include "src/core/SkScalerContext.h"
 #include "src/core/SkSurfacePriv.h"
 #include "src/core/SkTypefaceCache.h"
 #include "src/sfnt/SkOTTable_OS_2.h"
@@ -47,9 +48,10 @@
     sk_sp<SkTypeface> onMakeClone(const SkFontArguments& args) const override {
         return sk_ref_sp(this);
     }
-    SkScalerContext* onCreateScalerContext(const SkScalerContextEffects&,
-                                           const SkDescriptor*) const override {
-        return nullptr;
+    SkScalerContext* onCreateScalerContext(const SkScalerContextEffects& effects,
+                                           const SkDescriptor* desc) const override {
+        return SkScalerContext::MakeEmptyContext(
+                sk_ref_sp(const_cast<SkEmptyTypeface*>(this)), effects, desc);
     }
     void onFilterRec(SkScalerContextRec*) const override { }
     std::unique_ptr<SkAdvancedTypefaceMetrics> onGetAdvancedMetrics() const override {
@@ -401,10 +403,7 @@
     SkScalerContextEffects noeffects;
     SkScalerContext::AutoDescriptorGivenRecAndEffects(rec, noeffects, &ad);
 
-    std::unique_ptr<SkScalerContext> ctx = this->createScalerContext(noeffects, ad.getDesc(), true);
-    if (!ctx) {
-        return false;
-    }
+    std::unique_ptr<SkScalerContext> ctx = this->createScalerContext(noeffects, ad.getDesc());
 
     SkFontMetrics fm;
     ctx->getFontMetrics(&fm);
diff --git a/src/ports/SkFontHost_FreeType.cpp b/src/ports/SkFontHost_FreeType.cpp
index ef240c7..e18b286 100644
--- a/src/ports/SkFontHost_FreeType.cpp
+++ b/src/ports/SkFontHost_FreeType.cpp
@@ -701,7 +701,8 @@
     auto c = std::make_unique<SkScalerContext_FreeType>(
             sk_ref_sp(const_cast<SkTypeface_FreeType*>(this)), effects, desc);
     if (!c->success()) {
-        return nullptr;
+        return SkScalerContext::MakeEmptyContext(
+                sk_ref_sp(const_cast<SkTypeface_FreeType*>(this)), effects, desc);
     }
     return c.release();
 }
diff --git a/src/ports/SkFontHost_win.cpp b/src/ports/SkFontHost_win.cpp
index 1fa12c9..bc0f07f 100644
--- a/src/ports/SkFontHost_win.cpp
+++ b/src/ports/SkFontHost_win.cpp
@@ -26,6 +26,7 @@
 #include "src/core/SkGlyph.h"
 #include "src/core/SkLeanWindows.h"
 #include "src/core/SkMaskGamma.h"
+#include "src/core/SkStrikeCache.h"
 #include "src/core/SkTypefaceCache.h"
 #include "src/core/SkUtils.h"
 #include "src/sfnt/SkOTTable_OS_2.h"
@@ -2028,7 +2029,14 @@
     auto ctx = std::make_unique<SkScalerContext_GDI>(
             sk_ref_sp(const_cast<LogFontTypeface*>(this)), effects, desc);
     if (!ctx->isValid()) {
-        return nullptr;
+        ctx.reset();
+        SkStrikeCache::PurgeAll();
+        ctx = std::make_unique<SkScalerContext_GDI>(
+            sk_ref_sp(const_cast<LogFontTypeface*>(this)), effects, desc);
+        if (!ctx->isValid()) {
+            return SkScalerContext::MakeEmptyContext(
+                    sk_ref_sp(const_cast<LogFontTypeface*>(this)), effects, desc);
+        }
     }
     return ctx.release();
 }
diff --git a/tests/FontMgrTest.cpp b/tests/FontMgrTest.cpp
index f63920b..ffeb05e 100644
--- a/tests/FontMgrTest.cpp
+++ b/tests/FontMgrTest.cpp
@@ -11,6 +11,7 @@
 #include "include/core/SkStream.h"
 #include "include/core/SkTypeface.h"
 #include "src/core/SkAdvancedTypefaceMetrics.h"
+#include "src/core/SkScalerContext.h"
 #include "tests/Test.h"
 #include "tools/flags/CommandLineFlags.h"
 
@@ -127,9 +128,10 @@
         sk_sp<SkTypeface> onMakeClone(const SkFontArguments& args) const override {
             return sk_ref_sp(this);
         }
-        SkScalerContext* onCreateScalerContext(const SkScalerContextEffects&,
-                                               const SkDescriptor*) const override {
-            return nullptr;
+        SkScalerContext* onCreateScalerContext(const SkScalerContextEffects& effects,
+                                               const SkDescriptor* desc) const override {
+            return SkScalerContext::MakeEmptyContext(
+                    sk_ref_sp(const_cast<TestTypeface*>(this)), effects, desc);
         }
         void onFilterRec(SkScalerContextRec*) const override { }
         std::unique_ptr<SkAdvancedTypefaceMetrics> onGetAdvancedMetrics() const override {
diff --git a/tests/SkRemoteGlyphCacheTest.cpp b/tests/SkRemoteGlyphCacheTest.cpp
index c3b21c2..64a6823 100644
--- a/tests/SkRemoteGlyphCacheTest.cpp
+++ b/tests/SkRemoteGlyphCacheTest.cpp
@@ -857,7 +857,7 @@
                 SkMatrix::I(), &rec, &effects);
         auto desc = SkScalerContext::AutoDescriptorGivenRecAndEffects(rec, effects, &ad);
 
-        auto context = serverTf->createScalerContext(effects, desc, false);
+        auto context = serverTf->createScalerContext(effects, desc);
         SkGlyph glyph{lostGlyphID};
         context->getMetrics(&glyph);
         realMask = glyph.maskFormat();
diff --git a/tools/fonts/TestEmptyTypeface.h b/tools/fonts/TestEmptyTypeface.h
index 3d61762..a340ffe 100644
--- a/tools/fonts/TestEmptyTypeface.h
+++ b/tools/fonts/TestEmptyTypeface.h
@@ -11,6 +11,7 @@
 #include "include/core/SkStream.h"
 #include "include/core/SkTypeface.h"
 #include "src/core/SkAdvancedTypefaceMetrics.h"
+#include "src/core/SkScalerContext.h"
 
 class TestEmptyTypeface : public SkTypeface {
 public:
@@ -23,9 +24,11 @@
     sk_sp<SkTypeface>              onMakeClone(const SkFontArguments& args) const override {
         return sk_ref_sp(this);
     }
-    SkScalerContext* onCreateScalerContext(const SkScalerContextEffects&,
-                                           const SkDescriptor*) const override {
-        return nullptr;
+    SkScalerContext* onCreateScalerContext(const SkScalerContextEffects& effects,
+                                           const SkDescriptor* desc) const override {
+        return SkScalerContext::MakeEmptyContext(
+                sk_ref_sp(const_cast<TestEmptyTypeface*>(this)), effects, desc);
+
     }
     void                                       onFilterRec(SkScalerContextRec*) const override {}
     std::unique_ptr<SkAdvancedTypefaceMetrics> onGetAdvancedMetrics() const override {