Change getMetrics to the final API prepareForDrawing

Change the name, and add the atlas limit parameter.

Change-Id: Ic718d06d483667d7a341b74c280bc3fd016289ff
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/207314
Reviewed-by: Ben Wagner <bungeman@google.com>
Commit-Queue: Herb Derby <herb@google.com>
diff --git a/src/core/SkGlyphRunPainter.cpp b/src/core/SkGlyphRunPainter.cpp
index 5a6da46..a0dd674 100644
--- a/src/core/SkGlyphRunPainter.cpp
+++ b/src/core/SkGlyphRunPainter.cpp
@@ -306,10 +306,13 @@
                 fStrikeCache->findOrCreateScopedStrike(
                         *ad.getDesc(), effects, *runFont.getTypefaceOrDefault());
 
-        SkSpan<const SkGlyphPos> glyphPosSpan = strike->glyphMetrics(fARGBGlyphsIDs.data(),
-                                                                     fARGBPositions.data(),
-                                                                     fARGBGlyphsIDs.size(),
-                                                                     fGlyphPos);
+        SkSpan<const SkGlyphPos> glyphPosSpan = strike->prepareForDrawing(
+                fARGBGlyphsIDs.data(),
+                fARGBPositions.data(),
+                fARGBGlyphsIDs.size(),
+                SkStrikeCommon::kSkSideTooBigForAtlas,
+                fGlyphPos);
+
         if (process) {
             process->processDeviceFallback(glyphPosSpan, strike.get());
         }
@@ -552,13 +555,21 @@
             mapping.postTranslate(rounding.x(), rounding.y());
             mapping.mapPoints(fPositions, glyphRun.positions().data(), glyphRun.runSize());
 
-            SkSpan<const SkGlyphPos> glyphPosSpan = strike->glyphMetrics(
-                    glyphRun.glyphsIDs().data(), fPositions, glyphRun.runSize(), fGlyphPos);
+            // Lookup all the glyphs from the cache.
+            SkSpan<const SkGlyphPos> glyphPosSpan = strike->prepareForDrawing(
+                    glyphRun.glyphsIDs().data(),
+                    fPositions,
+                    glyphRun.runSize(),
+                    SkStrikeCommon::kSkSideTooBigForAtlas,
+                    fGlyphPos);
 
+            // Sort glyphs into the three bins: mask (fGlyphPos), path (fPaths), and fallback.
             size_t glyphsWithMaskCount = 0;
             for (const SkGlyphPos& glyphPos : glyphPosSpan) {
                 const SkGlyph& glyph = *glyphPos.glyph;
                 const SkPoint position = glyphPos.position;
+
+                // Able to position glyph?
                 if (!SkScalarsAreFinite(position.x(), position.y())) {
                     continue;
                 }
diff --git a/src/core/SkRemoteGlyphCache.cpp b/src/core/SkRemoteGlyphCache.cpp
index 5abb37c..8b4cdac 100644
--- a/src/core/SkRemoteGlyphCache.cpp
+++ b/src/core/SkRemoteGlyphCache.cpp
@@ -609,10 +609,14 @@
 
 
 // This version of glyphMetrics only adds entries to result if their data need to be sent to the
-// GPU process.
-SkSpan<const SkGlyphPos> SkStrikeServer::SkGlyphCacheState::glyphMetrics(
-        const SkGlyphID glyphIDs[], const SkPoint positions[], size_t n, SkGlyphPos result[]) {
-
+// GPU process. As a result, empty glyphs will be sent so that the GPU code can lookup the glyph
+// and detect that it is empty.
+SkSpan<const SkGlyphPos> SkStrikeServer::SkGlyphCacheState::prepareForDrawing(
+        const SkGlyphID glyphIDs[],
+        const SkPoint positions[],
+        size_t n,
+        int maxDimension,
+        SkGlyphPos results[]) {
     size_t glyphsToSendCount = 0;
     for (size_t i = 0; i < n; i++) {
         SkPoint glyphPos = positions[i];
@@ -633,15 +637,40 @@
             this->ensureScalerContext();
             fContext->getMetrics(glyphPtr);
 
-            result[glyphsToSendCount++] = {i, glyphPtr, glyphPos};
+            if (glyphPtr->maxDimension() <= maxDimension) {
+
+                // The mask/SDF will fit in the cache.
+                // TODO: no need to do this once code base converted over to bulk.
+                results[glyphsToSendCount++] = {i, glyphPtr, glyphPos};
+            } else if (glyphPtr->fMaskFormat != SkMask::kARGB32_Format) {
+
+                // The glyph is too big for the atlas, but it is not color, so it is handled with a
+                // path.
+                if (glyphPtr->fPathData == nullptr) {
+
+                    // Never checked for a path before. Add the path now.
+                    auto path = const_cast<SkGlyph&>(*glyphPtr).addPath(fContext.get(), &fAlloc);
+                    if (path != nullptr) {
+
+                        // A path was added make sure to send it to the GPU.
+                        fCachedGlyphPaths.add(glyphPtr->getPackedID());
+                        fPendingGlyphPaths.push_back(glyphPtr->getPackedID());
+                    }
+                }
+            } else {
+
+                // This will be handled by the fallback strike.
+                SkASSERT(glyphPtr->maxDimension() > maxDimension
+                         && glyphPtr->fMaskFormat == SkMask::kARGB32_Format);
+            }
 
             // Make sure to send the glyph to the GPU because we always send the image for a glyph.
             fCachedGlyphImages.add(packedGlyphID);
             fPendingGlyphImages.push_back(packedGlyphID);
         }
-    }
 
-    return SkSpan<const SkGlyphPos>{result, glyphsToSendCount};
+    }
+    return SkSpan<const SkGlyphPos>(results, glyphsToSendCount);
 }
 
 // SkStrikeClient -----------------------------------------
diff --git a/src/core/SkRemoteGlyphCacheImpl.h b/src/core/SkRemoteGlyphCacheImpl.h
index c7f5acf..1d7c9ba 100644
--- a/src/core/SkRemoteGlyphCacheImpl.h
+++ b/src/core/SkRemoteGlyphCacheImpl.h
@@ -43,8 +43,11 @@
 
     const SkGlyph& getGlyphMetrics(SkGlyphID glyphID, SkPoint position) override;
 
-    SkSpan<const SkGlyphPos> glyphMetrics(
-            const SkGlyphID[], const SkPoint[], size_t n, SkGlyphPos result[]) override;
+    SkSpan<const SkGlyphPos> prepareForDrawing(const SkGlyphID glyphIDs[],
+                                               const SkPoint positions[],
+                                               size_t n,
+                                               int maxDimension,
+                                               SkGlyphPos results[]) override;
 
     bool decideCouldDrawFromPath(const SkGlyph& glyph) override;
 
diff --git a/src/core/SkStrike.cpp b/src/core/SkStrike.cpp
index 236d721..20bb221 100644
--- a/src/core/SkStrike.cpp
+++ b/src/core/SkStrike.cpp
@@ -233,17 +233,34 @@
 
 // N.B. This glyphMetrics call culls all the glyphs which will not display based on a non-finite
 // position or that there are no mask pixels.
-SkSpan<const SkGlyphPos> SkStrike::glyphMetrics(const SkGlyphID glyphIDs[],
-                                                const SkPoint positions[],
-                                                size_t n,
-                                                SkGlyphPos result[]) {
+SkSpan<const SkGlyphPos> SkStrike::prepareForDrawing(const SkGlyphID glyphIDs[],
+                                                     const SkPoint positions[],
+                                                     size_t n,
+                                                     int maxDimension,
+                                                     SkGlyphPos result[]) {
     size_t drawableGlyphCount = 0;
     for (size_t i = 0; i < n; i++) {
-        SkPoint glyphPos = positions[i];
-        if (SkScalarsAreFinite(glyphPos.x(), glyphPos.y())) {
-            const SkGlyph& glyph = this->getGlyphMetrics(glyphIDs[i], glyphPos);
+        SkPoint position = positions[i];
+        if (SkScalarsAreFinite(position.x(), position.y())) {
+            // This assumes that the strike has no sub-pixel positioning for glyphs that are
+            // transformed from source space to device space.
+            const SkGlyph& glyph = this->getGlyphMetrics(glyphIDs[i], position);
             if (!glyph.isEmpty()) {
-                result[drawableGlyphCount++] = {i, &glyph, glyphPos};
+                result[drawableGlyphCount++] = {i, &glyph, position};
+                if (glyph.maxDimension() <= maxDimension) {
+
+                    // Glyph fits in the atlas, good to go.
+                    this->findImage(glyph);
+                } else if (glyph.fMaskFormat != SkMask::kARGB32_Format) {
+
+                    // The out of atlas glyph is not color so we can draw it using paths.
+                    this->findPath(glyph);
+                } else {
+
+                    // This will be handled by the fallback strike.
+                    SkASSERT(glyph.maxDimension() > maxDimension
+                             && glyph.fMaskFormat == SkMask::kARGB32_Format);
+                }
             }
         }
     }
diff --git a/src/core/SkStrike.h b/src/core/SkStrike.h
index 1f17b14..76b2fae 100644
--- a/src/core/SkStrike.h
+++ b/src/core/SkStrike.h
@@ -136,8 +136,11 @@
                             this->getScalerContext()->getEffects()};
     }
 
-    SkSpan<const SkGlyphPos> glyphMetrics(
-            const SkGlyphID[], const SkPoint[], size_t n, SkGlyphPos result[]) override;
+    SkSpan<const SkGlyphPos> prepareForDrawing(const SkGlyphID glyphIDs[],
+                                               const SkPoint positions[],
+                                               size_t n,
+                                               int maxDimension,
+                                               SkGlyphPos results[]) override;
 
     void onAboutToExitScope() override;
 
diff --git a/src/core/SkStrikeCache.cpp b/src/core/SkStrikeCache.cpp
index f5da322..02ff8af 100644
--- a/src/core/SkStrikeCache.cpp
+++ b/src/core/SkStrikeCache.cpp
@@ -36,12 +36,14 @@
         return fStrike.getGlyphMetrics(glyphID, position);
     }
 
-    SkSpan<const SkGlyphPos> glyphMetrics(
-            const SkGlyphID id[], const SkPoint point[], size_t n, SkGlyphPos result[]) override {
-        return fStrike.glyphMetrics(id, point, n, result);
+    SkSpan<const SkGlyphPos> prepareForDrawing(const SkGlyphID glyphIDs[],
+                                               const SkPoint positions[],
+                                               size_t n,
+                                               int maxDimension,
+                                               SkGlyphPos results[]) override {
+        return fStrike.prepareForDrawing(glyphIDs, positions, n, maxDimension, results);
     }
 
-
     bool decideCouldDrawFromPath(const SkGlyph& glyph) override {
         return fStrike.decideCouldDrawFromPath(glyph);
     }
diff --git a/src/core/SkStrikeInterface.h b/src/core/SkStrikeInterface.h
index 0353b0a..9c52c36 100644
--- a/src/core/SkStrikeInterface.h
+++ b/src/core/SkStrikeInterface.h
@@ -70,9 +70,17 @@
     virtual const SkDescriptor& getDescriptor() const = 0;
     virtual SkStrikeSpec strikeSpec() const = 0;
 
-    // glyphMetrics writes its results to result, but only returns a subspan of result.
-    virtual SkSpan<const SkGlyphPos> glyphMetrics(
-            const SkGlyphID[], const SkPoint[], size_t n, SkGlyphPos result[]) = 0;
+    // prepareForDrawing takes glyphIDs, and position, and returns a list of SkGlyphs and
+    // positions where all the data to draw the glyph has been created. The maxDimension
+    // parameter determines if the mask/SDF version will be created, or an alternate drawing
+    // format should be used. For path-only drawing set maxDimension to 0, and for bitmap-device
+    // drawing (where there is no upper limit to the glyph in the cache) use INT_MAX.
+    virtual SkSpan<const SkGlyphPos> prepareForDrawing(const SkGlyphID glyphIDs[],
+                                                       const SkPoint positions[],
+                                                       size_t n,
+                                                       int maxDimension,
+                                                       SkGlyphPos results[]) = 0;
+
     virtual const SkGlyph& getGlyphMetrics(SkGlyphID glyphID, SkPoint position) = 0;
     virtual bool decideCouldDrawFromPath(const SkGlyph& glyph) = 0;
     virtual void onAboutToExitScope() = 0;