Make the clip reducer operate on int rects. Remove redundant Gr from func 
name.

R=robertphillips@google.com
Review URL: https://codereview.appspot.com/6890045

git-svn-id: http://skia.googlecode.com/svn/trunk@6688 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/GrReducedClip.cpp b/src/gpu/GrReducedClip.cpp
index 8ee28dd..4745792 100644
--- a/src/gpu/GrReducedClip.cpp
+++ b/src/gpu/GrReducedClip.cpp
@@ -13,6 +13,13 @@
 
 namespace GrReducedClip {
 
+// helper function
+void reduced_stack_walker(const SkClipStack& stack,
+                          const SkRect& queryBounds,
+                          ElementList* result,
+                          InitialState* initialState,
+                          bool* requiresAA);
+
 /*
 There are plenty of optimizations that could be added here. For example we could consider
 checking for cases where an inverse path can be changed to a regular fill with a different op.
@@ -22,10 +29,12 @@
 based on later intersect operations, and perhaps remove intersect-rects. We could optionally
 take a rect in case the caller knows a bound on what is to be drawn through this clip.
 */
-void GrReduceClipStack(const SkClipStack& stack,
-                       const SkRect& queryBounds,
-                       ElementList* result,
-                       InitialState* initialState) {
+void ReduceClipStack(const SkClipStack& stack,
+                     const SkIRect& queryBounds,
+                     ElementList* result,
+                     InitialState* initialState,
+                     SkIRect* tighterBounds,
+                     bool* requiresAA) {
     result->reset();
 
     if (stack.isWideOpen()) {
@@ -33,39 +42,98 @@
         return;
     }
 
+
+    // We initially look at whether the bounds alone is sufficient. We also use the stack bounds to
+    // attempt to compute the tighterBounds.
+
     SkClipStack::BoundsType stackBoundsType;
     SkRect stackBounds;
     bool iior;
     stack.getBounds(&stackBounds, &stackBoundsType, &iior);
 
+    const SkIRect* bounds = &queryBounds;
+
+    SkRect scalarQueryBounds = SkRect::MakeFromIRect(queryBounds);
+
     if (iior) {
         SkASSERT(SkClipStack::kNormal_BoundsType == stackBoundsType);
         SkRect isectRect;
-        if (stackBounds.contains(queryBounds)) {
+        if (stackBounds.contains(scalarQueryBounds)) {
             *initialState = kAllIn_InitialState;
-        } else if (isectRect.intersect(stackBounds, queryBounds)) {
-            // iior should only be true if aa/non-aa status matches among all elements.
-            SkClipStack::Iter iter(stack, SkClipStack::Iter::kTop_IterStart);
-            bool doAA = iter.prev()->isAA();
-            SkNEW_INSERT_AT_LLIST_HEAD(result, Element, (isectRect, SkRegion::kReplace_Op, doAA));
+            if (NULL != tighterBounds) {
+                *tighterBounds = queryBounds;
+            }
+            if (NULL != requiresAA) {
+               *requiresAA = false;
+            }
+        } else if (isectRect.intersect(stackBounds, scalarQueryBounds)) {
+            if (NULL != tighterBounds) {
+                isectRect.roundOut(tighterBounds);
+                SkRect scalarTighterBounds = SkRect::MakeFromIRect(*tighterBounds);
+                if (scalarTighterBounds == isectRect) {
+                    // the round-out didn't add any area outside the clip rect.
+                    *requiresAA = false;
+                    *initialState = kAllIn_InitialState;
+                    return;
+                }
+                *initialState = kAllOut_InitialState;
+                // iior should only be true if aa/non-aa status matches among all elements.
+                SkClipStack::Iter iter(stack, SkClipStack::Iter::kTop_IterStart);
+                bool doAA = iter.prev()->isAA();
+                SkNEW_INSERT_AT_LLIST_HEAD(result, Element, (isectRect, SkRegion::kReplace_Op, doAA));
+                if (NULL != requiresAA) {
+                    *requiresAA = doAA;
+                }
+            }
         } else {
             *initialState = kAllOut_InitialState;
+             if (NULL != requiresAA) {
+                *requiresAA = false;
+             }
         }
         return;
     } else {
         if (SkClipStack::kNormal_BoundsType == stackBoundsType) {
-            if (!SkRect::Intersects(stackBounds, queryBounds)) {
+            if (!SkRect::Intersects(stackBounds, scalarQueryBounds)) {
                 *initialState = kAllOut_InitialState;
+                if (NULL != requiresAA) {
+                   *requiresAA = false;
+                }
                 return;
             }
+            if (NULL != tighterBounds) {
+                SkIRect stackIBounds;
+                stackBounds.roundOut(&stackIBounds);
+                tighterBounds->intersect(queryBounds, stackIBounds);
+                bounds = tighterBounds;
+            }
         } else {
-            if (stackBounds.contains(queryBounds)) {
+            if (stackBounds.contains(scalarQueryBounds)) {
                 *initialState = kAllOut_InitialState;
+                if (NULL != requiresAA) {
+                   *requiresAA = false;
+                }
                 return;
             }
+            if (NULL != tighterBounds) {
+                *tighterBounds = queryBounds;
+            }
         }
     }
 
+    SkRect scalarBounds = SkRect::MakeFromIRect(*bounds);
+    
+    // Now that we have determined the bounds to use and filtered out the trivial cases, call the
+    // helper that actually walks the stack.
+    reduced_stack_walker(stack, scalarBounds, result, initialState, requiresAA);
+}
+
+void reduced_stack_walker(const SkClipStack& stack,
+                          const SkRect& queryBounds,
+                          ElementList* result,
+                          InitialState* initialState,
+                          bool* requiresAA) {
+
     // walk backwards until we get to:
     //  a) the beginning
     //  b) an operation that is known to make the bounds all inside/outside
@@ -80,6 +148,7 @@
     bool emsmallens = false;
 
     SkClipStack::Iter iter(stack, SkClipStack::Iter::kTop_IterStart);
+    int numAAElements = 0;
     while ((kUnknown_InitialState == *initialState)) {
         const Element* element = iter.prev();
         if (NULL == element) {
@@ -254,6 +323,9 @@
                                            (queryBounds, SkRegion::kReverseDifference_Op, false));
             } else {
                 result->addToHead(*element);
+                if (element->isAA()) {
+                    ++numAAElements;
+                }
             }
         }
     }
@@ -262,7 +334,6 @@
         (kAllIn_InitialState == *initialState && !emsmallens)) {
         result->reset();
     } else {
-        int clipsToSkip = 0;
         Element* element = result->headIter().get();
         while (NULL != element) {
             bool skippable = false;
@@ -308,7 +379,6 @@
                     }
                     break;
                 case SkRegion::kReplace_Op:
-                    SkASSERT(!clipsToSkip); // replace should always be the first op
                     skippable = false; // we would have skipped it in the backwards walk if we
                                        // could've.
                     break;
@@ -319,10 +389,16 @@
             if (!skippable) {
                 break;
             } else {
+                if (element->isAA()) {
+                    --numAAElements;
+                }
                 result->popHead();
                 element = result->headIter().get();
             }
         }
     }
+    if (NULL != requiresAA) {
+        *requiresAA = numAAElements > 0;
+    }
 }
 } // namespace GrReducedClip