Clip text geometrically when possible.

Currently when we clip text we can't batch the clipped text with non-clipped text.
By modifying the quads and texCoords we can produce the same effect, and allow batching.
Includes some minor text code cleanup.

Bug: skia:6990
Change-Id: Ibfd4bc2fdc2d7680071e2abddd4d77fc3017e3d3
Reviewed-on: https://skia-review.googlesource.com/60780
Commit-Queue: Jim Van Verth <jvanverth@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/text/GrAtlasTextBlob.cpp b/src/gpu/text/GrAtlasTextBlob.cpp
index 5d27b3e..339ae6d 100644
--- a/src/gpu/text/GrAtlasTextBlob.cpp
+++ b/src/gpu/text/GrAtlasTextBlob.cpp
@@ -7,6 +7,7 @@
 
 #include "GrAtlasTextBlob.h"
 #include "GrBlurUtils.h"
+#include "GrClip.h"
 #include "GrContext.h"
 #include "GrRenderTargetContext.h"
 #include "GrTextUtils.h"
@@ -258,8 +259,9 @@
 
 inline std::unique_ptr<GrDrawOp> GrAtlasTextBlob::makeOp(
         const Run::SubRunInfo& info, int glyphCount, int run, int subRun,
-        const SkMatrix& viewMatrix, SkScalar x, SkScalar y, const GrTextUtils::Paint& paint,
-        const SkSurfaceProps& props, const GrDistanceFieldAdjustTable* distanceAdjustTable,
+        const SkMatrix& viewMatrix, SkScalar x, SkScalar y, const SkIRect& clipRect,
+        const GrTextUtils::Paint& paint, const SkSurfaceProps& props,
+        const GrDistanceFieldAdjustTable* distanceAdjustTable,
         GrAtlasGlyphCache* cache, GrRenderTargetContext* renderTargetContext) {
     GrMaskFormat format = info.maskFormat();
 
@@ -279,6 +281,7 @@
     }
     GrAtlasTextOp::Geometry& geometry = op->geometry();
     geometry.fViewMatrix = viewMatrix;
+    geometry.fClipRect = clipRect;
     geometry.fBlob = SkRef(this);
     geometry.fRun = run;
     geometry.fSubRun = subRun;
@@ -302,10 +305,33 @@
         if (0 == glyphCount) {
             continue;
         }
-        auto op = this->makeOp(info, glyphCount, run, subRun, viewMatrix, x, y, std::move(paint),
-                               props, distanceAdjustTable, cache, rtc);
+
+        SkRect rtBounds = SkRect::MakeWH(rtc->width(), rtc->height());
+        SkRRect clipRRect;
+        GrAA aa;
+        // we can clip geometrically if we're not using SDFs,
+        // and we have an axis-aligned rectangular non-AA clip
+        bool skipClip = false;
+        SkIRect clipRect = SkIRect::MakeEmpty();
+        if (!info.drawAsDistanceFields() && 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
+            SkRect subRunBounds;
+            this->computeSubRunBounds(&subRunBounds, run, subRun, viewMatrix, x, y);
+            if (!clipRRect.getBounds().contains(subRunBounds)) {
+                clipRRect.getBounds().round(&clipRect);
+            }
+        }
+
+        auto op = this->makeOp(info, glyphCount, run, subRun, viewMatrix, x, y, clipRect,
+                               std::move(paint), props, distanceAdjustTable, cache, rtc);
         if (op) {
-            rtc->addDrawOp(clip, std::move(op));
+            if (skipClip) {
+                rtc->addDrawOp(GrNoClip(), std::move(op));
+            } else {
+                rtc->addDrawOp(clip, std::move(op));
+            }
         }
     }
 }
@@ -427,8 +453,9 @@
         const GrDistanceFieldAdjustTable* distanceAdjustTable, GrAtlasGlyphCache* cache,
         GrRenderTargetContext* rtc) {
     const GrAtlasTextBlob::Run::SubRunInfo& info = fRuns[run].fSubRunInfo[subRun];
-    return this->makeOp(info, glyphCount, run, subRun, viewMatrix, x, y, paint, props,
-                        distanceAdjustTable, cache, rtc);
+    SkIRect emptyRect = SkIRect::MakeEmpty();
+    return this->makeOp(info, glyphCount, run, subRun, viewMatrix, x, y, emptyRect,
+                        paint, props, distanceAdjustTable, cache, rtc);
 }
 
 void GrAtlasTextBlob::AssertEqual(const GrAtlasTextBlob& l, const GrAtlasTextBlob& r) {