Move the empty glyph checks into the common code

This is part of a larger movement to remove unneeded
cache API chatter.

Change-Id: Id8e9c72a5cebe31a7efe51a947a1d4c68384609a
Reviewed-on: https://skia-review.googlesource.com/c/172947
Reviewed-by: Mike Klein <mtklein@google.com>
Commit-Queue: Herb Derby <herb@google.com>
diff --git a/src/core/SkGlyphCache.cpp b/src/core/SkGlyphCache.cpp
index 9bd8d0f..0d4e37d 100644
--- a/src/core/SkGlyphCache.cpp
+++ b/src/core/SkGlyphCache.cpp
@@ -479,6 +479,14 @@
     SkDebugf("%s\n", msg.c_str());
 }
 
+bool SkGlyphCache::hasImage(const SkGlyph& glyph) {
+    return !glyph.isEmpty() && this->findImage(glyph) != nullptr;
+}
+
+bool SkGlyphCache::hasPath(const SkGlyph& glyph) {
+    return !glyph.isEmpty() && this->findPath(glyph) != nullptr;
+}
+
 #ifdef SK_DEBUG
 void SkGlyphCache::forceValidate() const {
     size_t memoryUsed = sizeof(*this);
@@ -499,7 +507,6 @@
     forceValidate();
 #endif
 }
-
 #endif
 
 
diff --git a/src/core/SkGlyphCache.h b/src/core/SkGlyphCache.h
index 38aeb16..85294ec 100644
--- a/src/core/SkGlyphCache.h
+++ b/src/core/SkGlyphCache.h
@@ -139,6 +139,10 @@
 
     const SkGlyph& getGlyphMetrics(SkGlyphID glyphID, SkPoint position) override;
 
+    bool hasImage(const SkGlyph& glyph) override;
+
+    bool hasPath(const SkGlyph& glyph) override;
+
     /** Return the approx RAM usage for this cache. */
     size_t getMemoryUsed() const { return fMemoryUsed; }
 
diff --git a/src/core/SkGlyphRunPainter.cpp b/src/core/SkGlyphRunPainter.cpp
index 19c3c83..a3f20e8 100644
--- a/src/core/SkGlyphRunPainter.cpp
+++ b/src/core/SkGlyphRunPainter.cpp
@@ -354,11 +354,11 @@
     }
 }
 
-template <typename PerGlyphT, typename PerPathT>
+template <typename PerEmptyT, typename PerGlyphT, typename PerPathT>
 void SkGlyphRunListPainter::drawGlyphRunAsBMPWithPathFallback(
         SkGlyphCacheInterface* cache, const SkGlyphRun& glyphRun,
         SkPoint origin, const SkMatrix& deviceMatrix,
-        PerGlyphT&& perGlyph, PerPathT&& perPath) {
+        PerEmptyT&& perEmpty, PerGlyphT&& perGlyph, PerPathT&& perPath) {
 
     SkMatrix mapping = deviceMatrix;
     mapping.preTranslate(origin.x(), origin.y());
@@ -373,10 +373,20 @@
         auto mappedPt = *mappedPtCursor++;
         if (SkScalarsAreFinite(mappedPt.x(), mappedPt.y())) {
             const SkGlyph& glyph = cache->getGlyphMetrics(glyphID, mappedPt);
-            if (SkGlyphCacheCommon::GlyphTooBigForAtlas(glyph)) {
-                perPath(glyph, mappedPt);
+            if (glyph.isEmpty()) {
+                perEmpty(glyph, mappedPt);
+            } else if (!SkGlyphCacheCommon::GlyphTooBigForAtlas(glyph)) {
+                if (cache->hasImage(glyph)) {
+                    perGlyph(glyph, mappedPt);
+                } else {
+                    perEmpty(glyph, mappedPt);
+                }
             } else {
-                perGlyph(glyph, mappedPt);
+                if (cache->hasPath(glyph)) {
+                    perPath(glyph, mappedPt);
+                } else {
+                    perEmpty(glyph, mappedPt);
+                }
             }
         }
     }
@@ -770,35 +780,30 @@
 
             sk_sp<GrTextStrike> currStrike = glyphCache->getStrike(cache.get());
 
+            auto perEmpty = [](const SkGlyph&, SkPoint) {};
+
             auto perGlyph =
                 [this, run, &currStrike, filteredColor, cache{cache.get()}]
                 (const SkGlyph& glyph, SkPoint mappedPt) {
-                    if (!glyph.isEmpty()) {
-                        const void* glyphImage = cache->findImage(glyph);
-                        if (glyphImage != nullptr) {
-                            SkPoint pt{SkScalarFloorToScalar(mappedPt.fX),
-                                       SkScalarFloorToScalar(mappedPt.fY)};
-                            run->appendGlyph(this, currStrike,
-                                             glyph, GrGlyph::kCoverage_MaskStyle, pt,
-                                             filteredColor, cache, SK_Scalar1, false);
-                        }
-                    }
+                    SkPoint pt{SkScalarFloorToScalar(mappedPt.fX),
+                               SkScalarFloorToScalar(mappedPt.fY)};
+                    run->appendGlyph(this, currStrike,
+                                     glyph, GrGlyph::kCoverage_MaskStyle, pt,
+                                     filteredColor, cache, SK_Scalar1, false);
                 };
 
             auto perPath =
                 [run, cache{cache.get()}]
                 (const SkGlyph& glyph, SkPoint position) {
                     const SkPath* glyphPath = cache->findPath(glyph);
-                    if (glyphPath != nullptr) {
-                        SkPoint pt{SkScalarFloorToScalar(position.fX),
-                                   SkScalarFloorToScalar(position.fY)};
-                        run->appendPathGlyph(*glyphPath, pt, SK_Scalar1, true);
-                    }
+                    SkPoint pt{SkScalarFloorToScalar(position.fX),
+                               SkScalarFloorToScalar(position.fY)};
+                    run->appendPathGlyph(*glyphPath, pt, SK_Scalar1, true);
                 };
 
             glyphPainter->drawGlyphRunAsBMPWithPathFallback(
                     cache.get(), glyphRun, origin, viewMatrix,
-                    std::move(perGlyph), std::move(perPath));
+                    std::move(perEmpty), std::move(perGlyph), std::move(perPath));
         }
     }
 }
@@ -881,6 +886,10 @@
             SkScalerContextFlags::kFakeGammaAndBoostContrast, &effects);
     SkASSERT(glyphCacheState);
 
+    auto perEmpty = [glyphCacheState] (const SkGlyph& glyph, SkPoint mappedPt) {
+        glyphCacheState->addGlyph(glyph.getPackedID(), false);
+    };
+
     auto perGlyph = [glyphCacheState] (const SkGlyph& glyph, SkPoint mappedPt) {
         glyphCacheState->addGlyph(glyph.getPackedID(), false);
     };
@@ -894,7 +903,8 @@
     };
 
     fPainter.drawGlyphRunAsBMPWithPathFallback(
-            glyphCacheState, glyphRun, origin, runMatrix, perGlyph, perPath);
+            glyphCacheState, glyphRun, origin, runMatrix,
+            std::move(perEmpty), std::move(perGlyph), std::move(perPath));
 }
 
 struct ARGBHelper {
diff --git a/src/core/SkGlyphRunPainter.h b/src/core/SkGlyphRunPainter.h
index c41262b..8b1f1b4 100644
--- a/src/core/SkGlyphRunPainter.h
+++ b/src/core/SkGlyphRunPainter.h
@@ -24,6 +24,8 @@
     virtual ~SkGlyphCacheInterface() = default;
     virtual SkVector rounding() const = 0;
     virtual const SkGlyph& getGlyphMetrics(SkGlyphID glyphID, SkPoint position) = 0;
+    virtual bool hasImage(const SkGlyph& glyph) = 0;
+    virtual bool hasPath(const SkGlyph& glyph) = 0;
 };
 
 class SkGlyphCacheCommon {
@@ -70,11 +72,11 @@
             const SkGlyphRunList& glyphRunList, const SkMatrix& deviceMatrix,
             const BitmapDevicePainter* bitmapDevice);
 
-    template <typename PerGlyphT, typename PerPathT>
+    template <typename PerEmptyT, typename PerGlyphT, typename PerPathT>
     void drawGlyphRunAsBMPWithPathFallback(
             SkGlyphCacheInterface* cache, const SkGlyphRun& glyphRun,
             SkPoint origin, const SkMatrix& deviceMatrix,
-            PerGlyphT&& perGlyph, PerPathT&& perPath);
+            PerEmptyT&& perEmpty, PerGlyphT&& perGlyph, PerPathT&& perPath);
 
     enum NeedsTransform : bool { kTransformDone = false, kDoTransform = true };
 
diff --git a/src/core/SkRemoteGlyphCache.cpp b/src/core/SkRemoteGlyphCache.cpp
index aae01de..2a399dd 100644
--- a/src/core/SkRemoteGlyphCache.cpp
+++ b/src/core/SkRemoteGlyphCache.cpp
@@ -532,6 +532,15 @@
     return this->findGlyph(packedGlyphID);
 }
 
+bool SkStrikeServer::SkGlyphCacheState::hasImage(const SkGlyph& glyph) {
+    // If a glyph has width and height, it must have an image available to it.
+    return !glyph.isEmpty();
+}
+
+bool SkStrikeServer::SkGlyphCacheState::hasPath(const SkGlyph& glyph) {
+    return const_cast<SkGlyph&>(glyph).addPath(fContext.get(), &fAlloc) != nullptr;
+}
+
 void SkStrikeServer::SkGlyphCacheState::writeGlyphPath(const SkPackedGlyphID& glyphID,
                                                        Serializer* serializer) const {
     SkPath path;
diff --git a/src/core/SkRemoteGlyphCacheImpl.h b/src/core/SkRemoteGlyphCacheImpl.h
index 5bad3d1..3b50e83 100644
--- a/src/core/SkRemoteGlyphCacheImpl.h
+++ b/src/core/SkRemoteGlyphCacheImpl.h
@@ -44,6 +44,10 @@
 
     const SkGlyph& getGlyphMetrics(SkGlyphID glyphID, SkPoint position) override;
 
+    bool hasImage(const SkGlyph& glyph) override;
+
+    bool hasPath(const SkGlyph& glyph) override;
+
 private:
     bool hasPendingGlyphs() const {
         return !fPendingGlyphImages.empty() || !fPendingGlyphPaths.empty();
@@ -83,6 +87,8 @@
     // FallbackTextHelper cases require glyph metrics when analyzing a glyph run, in which case
     // we cache them here.
     SkTHashMap<SkPackedGlyphID, SkGlyph> fGlyphMap;
+
+    SkArenaAlloc fAlloc{256};
 };
 
 class SkTextBlobCacheDiffCanvas::TrackLayerDevice : public SkNoPixelsDevice {
diff --git a/src/core/SkStrikeCache.cpp b/src/core/SkStrikeCache.cpp
index 943ddb0..8206d94 100644
--- a/src/core/SkStrikeCache.cpp
+++ b/src/core/SkStrikeCache.cpp
@@ -38,6 +38,14 @@
         return fCache.getGlyphMetrics(glyphID, position);
     }
 
+    bool hasImage(const SkGlyph& glyph) override {
+        return fCache.hasImage(glyph);
+    }
+
+    bool hasPath(const SkGlyph& glyph) override {
+        return fCache.hasPath(glyph);
+    }
+
     SkStrikeCache* const            fStrikeCache;
     Node*                           fNext{nullptr};
     Node*                           fPrev{nullptr};