Encapsulate the SDF loop

Change-Id: Ib7c6bcc0ccb39224c1d6be3df4f342bd7e58d69e
Reviewed-on: https://skia-review.googlesource.com/148220
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Herb Derby <herb@google.com>
diff --git a/src/core/SkGlyphRun.cpp b/src/core/SkGlyphRun.cpp
index dce1faa..ca5bac3 100644
--- a/src/core/SkGlyphRun.cpp
+++ b/src/core/SkGlyphRun.cpp
@@ -828,11 +828,11 @@
     return glyph.fWidth >= 256 || glyph.fHeight >= 256;
 }
 
-template <typename PerGlyph1, typename PerPath1>
-void SkGlyphRunListDrawer::drawGlyphRunAsGlyphWithPathFallback(
+template <typename PerGlyphT, typename PerPathT>
+void SkGlyphRunListDrawer::drawGlyphRunAsBMPWithPathFallback(
         SkGlyphCache* cache, const SkGlyphRun& glyphRun,
         SkPoint origin, const SkMatrix& deviceMatrix,
-        PerGlyph1 perGlyph, PerPath1 perPath) {
+        PerGlyphT perGlyph, PerPathT perPath) {
     auto eachGlyph =
             [cache, perGlyph{std::move(perGlyph)}, perPath{std::move(perPath)}]
                     (const SkGlyph& glyph, SkPoint pt, SkPoint mappedPt) {
@@ -852,6 +852,63 @@
     this->forEachMappedDrawableGlyph(glyphRun, origin, deviceMatrix, cache, eachGlyph);
 }
 
+static SkRect rect_to_draw(
+        const SkGlyph& glyph, SkPoint origin, SkScalar textScale, GrGlyph::MaskStyle maskStyle) {
+
+    SkScalar dx = SkIntToScalar(glyph.fLeft);
+    SkScalar dy = SkIntToScalar(glyph.fTop);
+    SkScalar width = SkIntToScalar(glyph.fWidth);
+    SkScalar height = SkIntToScalar(glyph.fHeight);
+
+    if (maskStyle == GrGlyph::kDistance_MaskStyle) {
+        dx += SK_DistanceFieldInset;
+        dy += SK_DistanceFieldInset;
+        width -= 2 * SK_DistanceFieldInset;
+        height -= 2 * SK_DistanceFieldInset;
+    }
+
+    dx *= textScale;
+    dy *= textScale;
+    width *= textScale;
+    height *= textScale;
+
+    return SkRect::MakeXYWH(origin.x() + dx, origin.y() + dy, width, height);
+}
+
+template <typename PerSDFT, typename PerPathT, typename PerFallbackT>
+void SkGlyphRunListDrawer::drawGlyphRunAsSDFWithFallback(
+        SkGlyphCache* cache, const SkGlyphRun& glyphRun,
+        SkPoint origin, SkScalar textRatio,
+        PerSDFT perSDF, PerPathT perPath, PerFallbackT perFallback) {
+
+    const SkPoint* positionCursor = glyphRun.positions().data();
+    for (auto glyphID : glyphRun.shuntGlyphsIDs()) {
+        const SkGlyph& glyph = cache->getGlyphIDMetrics(glyphID);
+        SkPoint glyphPos = origin + *positionCursor++;
+        if (glyph.fWidth > 0) {
+            if (glyph.fMaskFormat == SkMask::kSDF_Format) {
+
+                if (glyph_too_big_for_atlas(glyph)) {
+                    SkRect glyphRect =
+                            rect_to_draw(glyph, glyphPos, textRatio,
+                                         GrGlyph::kDistance_MaskStyle);
+                    if (!glyphRect.isEmpty()) {
+                        const SkPath* glyphPath = cache->findPath(glyph);
+                        if (glyphPath != nullptr) {
+                            perPath(glyphPath, glyph, glyphPos);
+                        }
+                    }
+                } else {
+                    perSDF(glyph, glyphPos);
+                }
+
+            } else {
+                perFallback(glyph, glyphPos);
+            }
+        }
+    }
+}
+
 GrColor generate_filtered_color(const SkPaint& paint, const GrColorSpaceInfo& colorSpaceInfo) {
     GrColor4f filteredColor = SkColorToUnpremulGrColor4f(paint.getColor(), colorSpaceInfo);
     if (paint.getColorFilter() != nullptr) {
@@ -954,29 +1011,6 @@
                      clip, viewMatrix, origin.x(), origin.y());
 }
 
-static SkRect rect_to_draw(
-        const SkGlyph& glyph, SkPoint origin, SkScalar textScale, GrGlyph::MaskStyle maskStyle) {
-
-    SkScalar dx = SkIntToScalar(glyph.fLeft);
-    SkScalar dy = SkIntToScalar(glyph.fTop);
-    SkScalar width = SkIntToScalar(glyph.fWidth);
-    SkScalar height = SkIntToScalar(glyph.fHeight);
-
-    if (maskStyle == GrGlyph::kDistance_MaskStyle) {
-        dx += SK_DistanceFieldInset;
-        dy += SK_DistanceFieldInset;
-        width -= 2 * SK_DistanceFieldInset;
-        height -= 2 * SK_DistanceFieldInset;
-    }
-
-    dx *= textScale;
-    dy *= textScale;
-    width *= textScale;
-    height *= textScale;
-
-    return SkRect::MakeXYWH(origin.x() + dx, origin.y() + dy, width, height);
-}
-
 void GrTextContext::AppendGlyph(GrTextBlob* blob, int runIndex,
                                 GrGlyphCache* grGlyphCache,
                                 sk_sp<GrTextStrike>* strike,
@@ -1049,43 +1083,39 @@
             sk_sp<GrTextStrike> currStrike;
 
             {
+
                 auto cache = cacheBlob->setupCache(
                         runIndex, props, flags, distanceFieldPaint, nullptr);
 
-                const SkPoint* positionCursor = glyphRun.positions().data();
-                for (auto glyphID : glyphRun.shuntGlyphsIDs()) {
-                    const SkGlyph& glyph = cache->getGlyphIDMetrics(glyphID);
-                    SkPoint glyphPos = origin + *positionCursor++;
-                    if (glyph.fWidth > 0) {
-                        if (glyph.fMaskFormat == SkMask::kSDF_Format) {
+                auto perSDF =
+                        [cacheBlob, runIndex, glyphCache, &currStrike,
+                         filteredColor, cache{cache.get()}, textRatio]
+                        (const SkGlyph& glyph, SkPoint position) {
+                            SkScalar sx = position.fX,
+                                     sy = position.fY;
+                        AppendGlyph(cacheBlob, runIndex, glyphCache, &currStrike,
+                                    glyph, GrGlyph::kDistance_MaskStyle, sx, sy,
+                                    filteredColor,
+                                    cache, textRatio, true);
+                };
 
-                            SkScalar sx = glyphPos.fX,
-                                    sy = glyphPos.fY;
+                auto perPath =
+                        [cacheBlob, runIndex, textRatio]
+                        (const SkPath* path, const SkGlyph& glyph, SkPoint position) {
+                            SkScalar sx = position.fX,
+                                     sy = position.fY;
+                            cacheBlob->appendPathGlyph(
+                                    runIndex, *path, sx, sy, textRatio, false);
+                };
 
-                            if (glyph_too_big_for_atlas(glyph)) {
-                                SkRect glyphRect =
-                                        rect_to_draw(glyph, glyphPos, textRatio,
-                                                     GrGlyph::kDistance_MaskStyle);
-                                if (!glyphRect.isEmpty()) {
-                                    const SkPath* glyphPath = cache->findPath(glyph);
-                                    if (glyphPath != nullptr) {
-                                        cacheBlob->appendPathGlyph(
-                                                runIndex, *glyphPath, sx, sy, textRatio, false);
-                                    }
-                                }
-                            } else {
-                                AppendGlyph(cacheBlob, runIndex, glyphCache, &currStrike,
-                                            glyph, GrGlyph::kDistance_MaskStyle, sx, sy,
-                                            filteredColor,
-                                            cache.get(), textRatio, true);
-                            }
+                auto perFallback =
+                        [&fallbackTextHelper]
+                        (const SkGlyph& glyph, SkPoint position) {
+                    fallbackTextHelper.appendGlyph(glyph, glyph.getGlyphID(), position);
+                };
 
-                        } else {
-                            // can't append non-SDF glyph to SDF batch, send to fallback
-                            fallbackTextHelper.appendGlyph(glyph, glyphID, glyphPos);
-                        }
-                    }
-                }
+                glyphDrawer->drawGlyphRunAsSDFWithFallback(
+                        cache.get(), glyphRun, origin, textRatio, perSDF, perPath, perFallback);
             }
 
             fallbackTextHelper.drawGlyphs(
@@ -1156,7 +1186,7 @@
                                 runIndex, *path, sx, sy, SK_Scalar1, true);
                     };
 
-            glyphDrawer->drawGlyphRunAsGlyphWithPathFallback(
+            glyphDrawer->drawGlyphRunAsBMPWithPathFallback(
                     cache.get(), glyphRun, origin, viewMatrix, perGlyph, perPath);
         }
         runIndex += 1;
diff --git a/src/core/SkGlyphRun.h b/src/core/SkGlyphRun.h
index b9039f7..b90c83e 100644
--- a/src/core/SkGlyphRun.h
+++ b/src/core/SkGlyphRun.h
@@ -133,11 +133,17 @@
 
     //using PerGlyph = std::function<void(const SkGlyph&, SkPoint)>;
     template <typename PerGlyphT, typename PerPathT>
-    void drawGlyphRunAsGlyphWithPathFallback(
+    void drawGlyphRunAsBMPWithPathFallback(
             SkGlyphCache* cache, const SkGlyphRun& glyphRun,
             SkPoint origin, const SkMatrix& deviceMatrix,
             PerGlyphT perGlyph, PerPathT perPath);
 
+    template <typename PerSDFT, typename PerPathT, typename PerFallbackT>
+    void drawGlyphRunAsSDFWithFallback(
+            SkGlyphCache* cache, const SkGlyphRun& glyphRun,
+            SkPoint origin, SkScalar textRatio,
+            PerSDFT perSDF, PerPathT perPath, PerFallbackT perFallback);
+
 private:
     static bool ShouldDrawAsPath(const SkPaint& paint, const SkMatrix& matrix);
     bool ensureBitmapBuffers(size_t runSize);