Add bilerp support to scaled emojis

Bug: skia:7562
Change-Id: Ibdf8e71050e909de87ca2beb3fb2b57327011364
Reviewed-on: https://skia-review.googlesource.com/111820
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Jim Van Verth <jvanverth@google.com>
diff --git a/src/gpu/text/GrAtlasTextBlob.cpp b/src/gpu/text/GrAtlasTextBlob.cpp
index 8470370..bd3d768 100644
--- a/src/gpu/text/GrAtlasTextBlob.cpp
+++ b/src/gpu/text/GrAtlasTextBlob.cpp
@@ -152,6 +152,7 @@
     subRun->appendVertices(vertexStride);
     fGlyphs[subRun->glyphEndIndex()] = glyph;
     subRun->glyphAppended();
+    subRun->setHasScaledGlyphs(SK_Scalar1 != scale);
 }
 
 void GrAtlasTextBlob::appendPathGlyph(int runIndex, const SkPath& path, SkScalar x, SkScalar y,
@@ -264,8 +265,8 @@
                 target->colorSpaceInfo().isGammaCorrect(), paint.luminanceColor(),
                 info.hasUseLCDText(), useBGR, info.isAntiAliased());
     } else {
-        op = GrAtlasTextOp::MakeBitmap(std::move(grPaint), format,
-                                       glyphCount, restrictedAtlasManager);
+        op = GrAtlasTextOp::MakeBitmap(std::move(grPaint), format, glyphCount,
+                                       info.hasScaledGlyphs(), restrictedAtlasManager);
     }
     GrAtlasTextOp::Geometry& geometry = op->geometry();
     geometry.fViewMatrix = viewMatrix;
@@ -355,9 +356,10 @@
             SkRect rtBounds = SkRect::MakeWH(target->width(), target->height());
             SkRRect clipRRect;
             GrAA aa;
-            // We can clip geometrically if we're not using SDFs,
+            // We can clip geometrically if we're not using SDFs or scaled glyphs,
             // and we have an axis-aligned rectangular non-AA clip
-            if (!info.drawAsDistanceFields() && clip.isRRect(rtBounds, &clipRRect, &aa) &&
+            if (!info.drawAsDistanceFields() && !info.hasScaledGlyphs() &&
+                clip.isRRect(rtBounds, &clipRRect, &aa) &&
                 clipRRect.isRect() && GrAA::kNo == aa) {
                 skipClip = true;
                 // We only need to do clipping work if the subrun isn't contained by the clip
diff --git a/src/gpu/text/GrAtlasTextBlob.h b/src/gpu/text/GrAtlasTextBlob.h
index 52771c7..b4a11a4 100644
--- a/src/gpu/text/GrAtlasTextBlob.h
+++ b/src/gpu/text/GrAtlasTextBlob.h
@@ -435,13 +435,19 @@
                 fFlags  = hasW ? (fFlags | kHasWCoord_Flag) : fFlags & ~kHasWCoord_Flag;
             }
             bool hasWCoord() const { return SkToBool(fFlags & kHasWCoord_Flag); }
+            void setHasScaledGlyphs(bool hasScaledGlyphs) {
+                fFlags  = hasScaledGlyphs ? (fFlags | kHasScaledGlyphs_Flag)
+                                          : fFlags & ~kHasScaledGlyphs_Flag;
+            }
+            bool hasScaledGlyphs() const { return SkToBool(fFlags & kHasScaledGlyphs_Flag); }
 
         private:
             enum Flag {
-                kDrawAsSDF_Flag = 0x1,
-                kUseLCDText_Flag = 0x2,
-                kAntiAliased_Flag = 0x4,
-                kHasWCoord_Flag = 0x8
+                kDrawAsSDF_Flag = 0x01,
+                kUseLCDText_Flag = 0x02,
+                kAntiAliased_Flag = 0x04,
+                kHasWCoord_Flag = 0x08,
+                kHasScaledGlyphs_Flag = 0x10
             };
 
             GrDrawOpAtlas::BulkUseTokenUpdater fBulkUseToken;
diff --git a/src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp b/src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp
index f574d6f..296df22 100644
--- a/src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp
+++ b/src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp
@@ -280,7 +280,8 @@
             if (!fFullAtlasManager->hasGlyph(glyph) &&
                 !strike->addGlyphToAtlas(fResourceProvider, fUploadTarget, fGlyphCache,
                                          fFullAtlasManager, glyph,
-                                         fLazyCache->get(), fSubRun->maskFormat())) {
+                                         fLazyCache->get(), fSubRun->maskFormat(),
+                                         fSubRun->hasScaledGlyphs())) {
                 fBrokenRun = glyphIdx > 0;
                 result.fFinished = false;
                 return result;
diff --git a/src/gpu/text/GrAtlasTextContext.cpp b/src/gpu/text/GrAtlasTextContext.cpp
index 5ac683e..4a10e10 100644
--- a/src/gpu/text/GrAtlasTextContext.cpp
+++ b/src/gpu/text/GrAtlasTextContext.cpp
@@ -856,6 +856,7 @@
         SkScalar scaledGlyphSize = maxDim * fMaxScale;
         if (!fViewMatrix.hasPerspective() && scaledGlyphSize > fMaxTextSize) {
             fUseScaledFallback = true;
+            fMaxTextSize -= 2;    // Subtract 2 to account for the bilerp pad around the glyph
         }
     }
 
diff --git a/src/gpu/text/GrGlyphCache.cpp b/src/gpu/text/GrGlyphCache.cpp
index 7d89907..2372af8 100644
--- a/src/gpu/text/GrGlyphCache.cpp
+++ b/src/gpu/text/GrGlyphCache.cpp
@@ -298,35 +298,57 @@
                                    GrAtlasManager* fullAtlasManager,
                                    GrGlyph* glyph,
                                    SkGlyphCache* cache,
-                                   GrMaskFormat expectedMaskFormat) {
+                                   GrMaskFormat expectedMaskFormat,
+                                   bool isScaledGlyph) {
     SkASSERT(glyph);
     SkASSERT(cache);
     SkASSERT(fCache.find(glyph->fPackedID));
 
     int bytesPerPixel = GrMaskFormatBytesPerPixel(expectedMaskFormat);
+    int width = glyph->width();
+    int height = glyph->height();
+    int rowBytes = width * bytesPerPixel;
 
     size_t size = glyph->fBounds.area() * bytesPerPixel;
+    bool isSDFGlyph = GrGlyph::kDistance_MaskStyle == GrGlyph::UnpackMaskStyle(glyph->fPackedID);
+    bool addPad = isScaledGlyph && !isSDFGlyph;
+    if (addPad) {
+        width += 2;
+        rowBytes += 2*bytesPerPixel;
+        size += 2 * rowBytes;
+        height += 2;
+        size += 2 * (height + 2) * bytesPerPixel;
+    }
     SkAutoSMalloc<1024> storage(size);
 
     const SkGlyph& skGlyph = GrToSkGlyph(cache, glyph->fPackedID);
-    if (GrGlyph::kDistance_MaskStyle == GrGlyph::UnpackMaskStyle(glyph->fPackedID)) {
-        if (!get_packed_glyph_df_image(cache, skGlyph, glyph->width(), glyph->height(),
+    if (isSDFGlyph) {
+        if (!get_packed_glyph_df_image(cache, skGlyph, width, height,
                                        storage.get())) {
             return false;
         }
     } else {
+        void* dataPtr = storage.get();
+        if (addPad) {
+            sk_bzero(dataPtr, size);
+            dataPtr = (char*)(dataPtr) + rowBytes + bytesPerPixel;
+        }
         if (!get_packed_glyph_image(cache, skGlyph, glyph->width(), glyph->height(),
-                                    glyph->width() * bytesPerPixel, expectedMaskFormat,
-                                    storage.get())) {
+                                    rowBytes, expectedMaskFormat,
+                                    dataPtr)) {
             return false;
         }
     }
 
     bool success = fullAtlasManager->addToAtlas(resourceProvider, glyphCache, this,
                                                 &glyph->fID, target, expectedMaskFormat,
-                                                glyph->width(), glyph->height(),
+                                                width, height,
                                                 storage.get(), &glyph->fAtlasLocation);
     if (success) {
+        if (addPad) {
+            glyph->fAtlasLocation.fX += 1;
+            glyph->fAtlasLocation.fY += 1;
+        }
         SkASSERT(GrDrawOpAtlas::kInvalidAtlasID != glyph->fID);
         fAtlasedGlyphs++;
     }
diff --git a/src/gpu/text/GrGlyphCache.h b/src/gpu/text/GrGlyphCache.h
index 8279814..7e6056e 100644
--- a/src/gpu/text/GrGlyphCache.h
+++ b/src/gpu/text/GrGlyphCache.h
@@ -65,7 +65,7 @@
     // get the actual glyph image itself when we get the glyph metrics.
     bool addGlyphToAtlas(GrResourceProvider*, GrDeferredUploadTarget*, GrGlyphCache*,
                          GrAtlasManager*, GrGlyph*,
-                         SkGlyphCache*, GrMaskFormat expectedMaskFormat);
+                         SkGlyphCache*, GrMaskFormat expectedMaskFormat, bool isScaledGlyph);
 
     // testing
     int countGlyphs() const { return fCache.count(); }