Fix quickReject's handling of AA ramp geometry

By having quickReject round out the window-space geometry bounds, we
prevent the AA perimeter (which falls outside the local bounds passed
in) from drawing outside the clip.

Change-Id: I8ee36be9039a9c47906815ee2f0dbaa5eb910b82
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index bc00ce8..24cd5cb 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -1414,6 +1414,10 @@
         if (!state.mBounds.isEmpty()) {
             currentMatrix.mapRect(state.mBounds);
             Rect clippedBounds(state.mBounds);
+            // NOTE: if we ever want to use this clipping info to drive whether the scissor
+            // is used, it should more closely duplicate the quickReject logic (in how it uses
+            // snapToPixelBoundaries)
+
             if(!clippedBounds.intersect(currentClip)) {
                 // quick rejected
                 return true;
@@ -1608,14 +1612,21 @@
 }
 
 bool OpenGLRenderer::quickRejectNoScissor(float left, float top, float right, float bottom,
-        bool* clipRequired) {
+        bool snapOut, bool* clipRequired) {
     if (mSnapshot->isIgnored() || bottom <= top || right <= left) {
         return true;
     }
 
     Rect r(left, top, right, bottom);
     currentTransform().mapRect(r);
-    r.snapToPixelBoundaries();
+
+    if (snapOut) {
+        // snapOut is generally used to account for 1 pixel ramp (in window coordinates)
+        // outside of the provided rect boundaries in tessellated AA geometry
+        r.snapOutToPixelBoundaries();
+    } else {
+        r.snapToPixelBoundaries();
+    }
 
     Rect clipRect(*mSnapshot->clipRect);
     clipRect.snapToPixelBoundaries();
@@ -1628,17 +1639,21 @@
 
 bool OpenGLRenderer::quickRejectPreStroke(float left, float top, float right, float bottom,
         SkPaint* paint) {
+    // AA geometry will likely have a ramp around it (not accounted for in local bounds). Snap out
+    // the final mapped rect to ensure correct clipping behavior for the ramp.
+    bool snapOut = paint->isAntiAlias();
+
     if (paint->getStyle() != SkPaint::kFill_Style) {
         float outset = paint->getStrokeWidth() * 0.5f;
-        return quickReject(left - outset, top - outset, right + outset, bottom + outset);
+        return quickReject(left - outset, top - outset, right + outset, bottom + outset, snapOut);
     } else {
-        return quickReject(left, top, right, bottom);
+        return quickReject(left, top, right, bottom, snapOut);
     }
 }
 
-bool OpenGLRenderer::quickReject(float left, float top, float right, float bottom) {
+bool OpenGLRenderer::quickReject(float left, float top, float right, float bottom, bool snapOut) {
     bool clipRequired = false;
-    if (quickRejectNoScissor(left, top, right, bottom, &clipRequired)) {
+    if (quickRejectNoScissor(left, top, right, bottom, snapOut, &clipRequired)) {
         return true;
     }
 
@@ -3115,7 +3130,7 @@
 
     bool clipRequired = false;
     const bool rejected = quickRejectNoScissor(x, y,
-            x + layer->layer.getWidth(), y + layer->layer.getHeight(), &clipRequired);
+            x + layer->layer.getWidth(), y + layer->layer.getHeight(), false, &clipRequired);
 
     if (rejected) {
         if (transform && !transform->isIdentity()) {