Cleanup: Turn GrReducedClip into a class with a static function.

Clean up namespace usage.

Similar to what was done in
https://skia.googlesource.com/skia/+/a5414c4a8efc3119ee20fcee96c0bf68a04909c7

BUG=None
TEST=None
R=bsalomon@google.com

Review URL: https://codereview.chromium.org/653393003
diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp
index 1d05565..414bbab 100644
--- a/src/gpu/GrClipMaskManager.cpp
+++ b/src/gpu/GrClipMaskManager.cpp
@@ -28,8 +28,6 @@
 
 typedef SkClipStack::Element Element;
 
-using namespace GrReducedClip;
-
 ////////////////////////////////////////////////////////////////////////////////
 namespace {
 // set up the draw state to enable the aa clipping mask. Besides setting up the
@@ -85,14 +83,14 @@
  * will be used on any element. If so, it returns true to indicate that the
  * entire clip should be rendered in SW and then uploaded en masse to the gpu.
  */
-bool GrClipMaskManager::useSWOnlyPath(const ElementList& elements) {
+bool GrClipMaskManager::useSWOnlyPath(const GrReducedClip::ElementList& elements) {
 
     // TODO: generalize this function so that when
     // a clip gets complex enough it can just be done in SW regardless
     // of whether it would invoke the GrSoftwarePathRenderer.
     SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
 
-    for (ElementList::Iter iter(elements.headIter()); iter.get(); iter.next()) {
+    for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.get(); iter.next()) {
         const Element* element = iter.get();
         // rects can always be drawn directly w/o using the software path
         // Skip rrects once we're drawing them directly.
@@ -107,7 +105,7 @@
     return false;
 }
 
-bool GrClipMaskManager::installClipEffects(const ElementList& elements,
+bool GrClipMaskManager::installClipEffects(const GrReducedClip::ElementList& elements,
                                            GrDrawState::AutoRestoreEffects* are,
                                            const SkVector& clipToRTOffset,
                                            const SkRect* drawBounds) {
@@ -121,7 +119,7 @@
 
     are->set(drawState);
     GrRenderTarget* rt = drawState->getRenderTarget();
-    ElementList::Iter iter(elements);
+    GrReducedClip::ElementList::Iter iter(elements);
 
     bool setARE = false;
     bool failed = false;
@@ -217,9 +215,9 @@
                                       const SkRect* devBounds) {
     fCurrClipMaskType = kNone_ClipMaskType;
 
-    ElementList elements(16);
+    GrReducedClip::ElementList elements(16);
     int32_t genID;
-    InitialState initialState;
+    GrReducedClip::InitialState initialState;
     SkIRect clipSpaceIBounds;
     bool requiresAA;
 
@@ -234,15 +232,15 @@
     if (!ignoreClip) {
         SkIRect clipSpaceRTIBounds = SkIRect::MakeWH(rt->width(), rt->height());
         clipSpaceRTIBounds.offset(clipDataIn->fOrigin);
-        ReduceClipStack(*clipDataIn->fClipStack,
-                        clipSpaceRTIBounds,
-                        &elements,
-                        &genID,
-                        &initialState,
-                        &clipSpaceIBounds,
-                        &requiresAA);
+        GrReducedClip::ReduceClipStack(*clipDataIn->fClipStack,
+                                       clipSpaceRTIBounds,
+                                       &elements,
+                                       &genID,
+                                       &initialState,
+                                       &clipSpaceIBounds,
+                                       &requiresAA);
         if (elements.isEmpty()) {
-            if (kAllIn_InitialState == initialState) {
+            if (GrReducedClip::kAllIn_InitialState == initialState) {
                 ignoreClip = clipSpaceIBounds == clipSpaceRTIBounds;
             } else {
                 return false;
@@ -534,8 +532,8 @@
 ////////////////////////////////////////////////////////////////////////////////
 // Create a 8-bit clip mask in alpha
 GrTexture* GrClipMaskManager::createAlphaClipMask(int32_t elementsGenID,
-                                                  InitialState initialState,
-                                                  const ElementList& elements,
+                                                  GrReducedClip::InitialState initialState,
+                                                  const GrReducedClip::ElementList& elements,
                                                   const SkIRect& clipSpaceIBounds) {
     SkASSERT(kNone_ClipMaskType == fCurrClipMaskType);
 
@@ -575,7 +573,7 @@
     // The scratch texture that we are drawing into can be substantially larger than the mask. Only
     // clear the part that we care about.
     fGpu->clear(&maskSpaceIBounds,
-                kAllIn_InitialState == initialState ? 0xffffffff : 0x00000000,
+                GrReducedClip::kAllIn_InitialState == initialState ? 0xffffffff : 0x00000000,
                 true,
                 result->asRenderTarget());
 
@@ -588,7 +586,7 @@
 
     SkAutoTUnref<GrTexture> temp;
     // walk through each clip element and perform its set op
-    for (ElementList::Iter iter = elements.headIter(); iter.get(); iter.next()) {
+    for (GrReducedClip::ElementList::Iter iter = elements.headIter(); iter.get(); iter.next()) {
         const Element* element = iter.get();
         SkRegion::Op op = element->getOp();
         bool invert = element->isInverseFilled();
@@ -688,8 +686,8 @@
 // Create a 1-bit clip mask in the stencil buffer. 'devClipBounds' are in device
 // (as opposed to canvas) coordinates
 bool GrClipMaskManager::createStencilClipMask(int32_t elementsGenID,
-                                              InitialState initialState,
-                                              const ElementList& elements,
+                                              GrReducedClip::InitialState initialState,
+                                              const GrReducedClip::ElementList& elements,
                                               const SkIRect& clipSpaceIBounds,
                                               const SkIPoint& clipSpaceToStencilOffset) {
 
@@ -737,11 +735,12 @@
         SkASSERT((clipBit <= 16) && "Ganesh only handles 16b or smaller stencil buffers");
         clipBit = (1 << (clipBit-1));
 
-        fGpu->clearStencilClip(rt, stencilSpaceIBounds, kAllIn_InitialState == initialState);
+        fGpu->clearStencilClip(rt, stencilSpaceIBounds,
+                               GrReducedClip::kAllIn_InitialState == initialState);
 
         // walk through each clip element and perform its set op
         // with the existing clip.
-        for (ElementList::Iter iter(elements.headIter()); iter.get(); iter.next()) {
+        for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.get(); iter.next()) {
             const Element* element = iter.get();
             bool fillInverted = false;
             // enabled at bottom of loop
@@ -1058,11 +1057,11 @@
                         SkIntToScalar(-clipSpaceIBounds.fTop));
     helper.init(maskSpaceIBounds, &matrix, false);
 
-    helper.clear(kAllIn_InitialState == initialState ? 0xFF : 0x00);
+    helper.clear(GrReducedClip::kAllIn_InitialState == initialState ? 0xFF : 0x00);
 
     SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
 
-    for (ElementList::Iter iter(elements.headIter()) ; iter.get(); iter.next()) {
+    for (GrReducedClip::ElementList::Iter iter(elements.headIter()) ; iter.get(); iter.next()) {
 
         const Element* element = iter.get();
         SkRegion::Op op = element->getOp();
diff --git a/src/gpu/GrReducedClip.cpp b/src/gpu/GrReducedClip.cpp
index 2083af9..3040b46 100644
--- a/src/gpu/GrReducedClip.cpp
+++ b/src/gpu/GrReducedClip.cpp
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2012 Google Inc.
  *
@@ -9,17 +8,314 @@
 #include "GrReducedClip.h"
 
 typedef SkClipStack::Element Element;
-////////////////////////////////////////////////////////////////////////////////
 
-namespace GrReducedClip {
+static void reduced_stack_walker(const SkClipStack& stack,
+                                 const SkRect& queryBounds,
+                                 GrReducedClip::ElementList* result,
+                                 int32_t* resultGenID,
+                                 GrReducedClip::InitialState* initialState,
+                                 bool* requiresAA) {
 
-// helper function
-void reduced_stack_walker(const SkClipStack& stack,
-                          const SkRect& queryBounds,
-                          ElementList* result,
-                          int32_t* resultGenID,
-                          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
+    //  c) a replace operation
+
+    static const GrReducedClip::InitialState kUnknown_InitialState =
+        static_cast<GrReducedClip::InitialState>(-1);
+    *initialState = kUnknown_InitialState;
+
+    // During our backwards walk, track whether we've seen ops that either grow or shrink the clip.
+    // TODO: track these per saved clip so that we can consider them on the forward pass.
+    bool embiggens = false;
+    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) {
+            *initialState = GrReducedClip::kAllIn_InitialState;
+            break;
+        }
+        if (SkClipStack::kEmptyGenID == element->getGenID()) {
+            *initialState = GrReducedClip::kAllOut_InitialState;
+            break;
+        }
+        if (SkClipStack::kWideOpenGenID == element->getGenID()) {
+            *initialState = GrReducedClip::kAllIn_InitialState;
+            break;
+        }
+
+        bool skippable = false;
+        bool isFlip = false; // does this op just flip the in/out state of every point in the bounds
+
+        switch (element->getOp()) {
+            case SkRegion::kDifference_Op:
+                // check if the shape subtracted either contains the entire bounds (and makes
+                // the clip empty) or is outside the bounds and therefore can be skipped.
+                if (element->isInverseFilled()) {
+                    if (element->contains(queryBounds)) {
+                        skippable = true;
+                    } else if (!SkRect::Intersects(element->getBounds(), queryBounds)) {
+                        *initialState = GrReducedClip::kAllOut_InitialState;
+                        skippable = true;
+                    }
+                } else {
+                    if (element->contains(queryBounds)) {
+                        *initialState = GrReducedClip::kAllOut_InitialState;
+                        skippable = true;
+                    } else if (!SkRect::Intersects(element->getBounds(), queryBounds)) {
+                        skippable = true;
+                    }
+                }
+                if (!skippable) {
+                    emsmallens = true;
+                }
+                break;
+            case SkRegion::kIntersect_Op:
+                // check if the shape intersected contains the entire bounds and therefore can
+                // be skipped or it is outside the entire bounds and therefore makes the clip
+                // empty.
+                if (element->isInverseFilled()) {
+                    if (element->contains(queryBounds)) {
+                        *initialState = GrReducedClip::kAllOut_InitialState;
+                        skippable = true;
+                    } else if (!SkRect::Intersects(element->getBounds(), queryBounds)) {
+                        skippable = true;
+                    }
+                } else {
+                    if (element->contains(queryBounds)) {
+                        skippable = true;
+                    } else if (!SkRect::Intersects(element->getBounds(), queryBounds)) {
+                        *initialState = GrReducedClip::kAllOut_InitialState;
+                        skippable = true;
+                    }
+                }
+                if (!skippable) {
+                    emsmallens = true;
+                }
+                break;
+            case SkRegion::kUnion_Op:
+                // If the union-ed shape contains the entire bounds then after this element
+                // the bounds is entirely inside the clip. If the union-ed shape is outside the
+                // bounds then this op can be skipped.
+                if (element->isInverseFilled()) {
+                    if (element->contains(queryBounds)) {
+                        skippable = true;
+                    } else if (!SkRect::Intersects(element->getBounds(), queryBounds)) {
+                        *initialState = GrReducedClip::kAllIn_InitialState;
+                        skippable = true;
+                    }
+                } else {
+                    if (element->contains(queryBounds)) {
+                        *initialState = GrReducedClip::kAllIn_InitialState;
+                        skippable = true;
+                    } else if (!SkRect::Intersects(element->getBounds(), queryBounds)) {
+                        skippable = true;
+                    }
+                }
+                if (!skippable) {
+                    embiggens = true;
+                }
+                break;
+            case SkRegion::kXOR_Op:
+                // If the bounds is entirely inside the shape being xor-ed then the effect is
+                // to flip the inside/outside state of every point in the bounds. We may be
+                // able to take advantage of this in the forward pass. If the xor-ed shape
+                // doesn't intersect the bounds then it can be skipped.
+                if (element->isInverseFilled()) {
+                    if (element->contains(queryBounds)) {
+                        skippable = true;
+                    } else if (!SkRect::Intersects(element->getBounds(), queryBounds)) {
+                        isFlip = true;
+                    }
+                } else {
+                    if (element->contains(queryBounds)) {
+                        isFlip = true;
+                    } else if (!SkRect::Intersects(element->getBounds(), queryBounds)) {
+                        skippable = true;
+                    }
+                }
+                if (!skippable) {
+                    emsmallens = embiggens = true;
+                }
+                break;
+            case SkRegion::kReverseDifference_Op:
+                // When the bounds is entirely within the rev-diff shape then this behaves like xor
+                // and reverses every point inside the bounds. If the shape is completely outside
+                // the bounds then we know after this element is applied that the bounds will be
+                // all outside the current clip.B
+                if (element->isInverseFilled()) {
+                    if (element->contains(queryBounds)) {
+                        *initialState = GrReducedClip::kAllOut_InitialState;
+                        skippable = true;
+                    } else if (!SkRect::Intersects(element->getBounds(), queryBounds)) {
+                        isFlip = true;
+                    }
+                } else {
+                    if (element->contains(queryBounds)) {
+                        isFlip = true;
+                    } else if (!SkRect::Intersects(element->getBounds(), queryBounds)) {
+                        *initialState = GrReducedClip::kAllOut_InitialState;
+                        skippable = true;
+                    }
+                }
+                if (!skippable) {
+                    emsmallens = embiggens = true;
+                }
+                break;
+            case SkRegion::kReplace_Op:
+                // Replace will always terminate our walk. We will either begin the forward walk
+                // at the replace op or detect here than the shape is either completely inside
+                // or completely outside the bounds. In this latter case it can be skipped by
+                // setting the correct value for initialState.
+                if (element->isInverseFilled()) {
+                    if (element->contains(queryBounds)) {
+                        *initialState = GrReducedClip::kAllOut_InitialState;
+                        skippable = true;
+                    } else if (!SkRect::Intersects(element->getBounds(), queryBounds)) {
+                        *initialState = GrReducedClip::kAllIn_InitialState;
+                        skippable = true;
+                    }
+                } else {
+                    if (element->contains(queryBounds)) {
+                        *initialState = GrReducedClip::kAllIn_InitialState;
+                        skippable = true;
+                    } else if (!SkRect::Intersects(element->getBounds(), queryBounds)) {
+                        *initialState = GrReducedClip::kAllOut_InitialState;
+                        skippable = true;
+                    }
+                }
+                if (!skippable) {
+                    *initialState = GrReducedClip::kAllOut_InitialState;
+                    embiggens = emsmallens = true;
+                }
+                break;
+            default:
+                SkDEBUGFAIL("Unexpected op.");
+                break;
+        }
+        if (!skippable) {
+            if (0 == result->count()) {
+                // This will be the last element. Record the stricter genID.
+                *resultGenID = element->getGenID();
+            }
+
+            // if it is a flip, change it to a bounds-filling rect
+            if (isFlip) {
+                SkASSERT(SkRegion::kXOR_Op == element->getOp() ||
+                         SkRegion::kReverseDifference_Op == element->getOp());
+                SkNEW_INSERT_AT_LLIST_HEAD(result,
+                                           Element,
+                                           (queryBounds, SkRegion::kReverseDifference_Op, false));
+            } else {
+                Element* newElement = result->addToHead(*element);
+                if (newElement->isAA()) {
+                    ++numAAElements;
+                }
+                // Intersecting an inverse shape is the same as differencing the non-inverse shape.
+                // Replacing with an inverse shape is the same as setting initialState=kAllIn and
+                // differencing the non-inverse shape.
+                bool isReplace = SkRegion::kReplace_Op == newElement->getOp();
+                if (newElement->isInverseFilled() &&
+                    (SkRegion::kIntersect_Op == newElement->getOp() || isReplace)) {
+                    newElement->invertShapeFillType();
+                    newElement->setOp(SkRegion::kDifference_Op);
+                    if (isReplace) {
+                        SkASSERT(GrReducedClip::kAllOut_InitialState == *initialState);
+                        *initialState = GrReducedClip::kAllIn_InitialState;
+                    }
+                }
+            }
+        }
+    }
+
+    if ((GrReducedClip::kAllOut_InitialState == *initialState && !embiggens) ||
+        (GrReducedClip::kAllIn_InitialState == *initialState && !emsmallens)) {
+        result->reset();
+    } else {
+        Element* element = result->headIter().get();
+        while (element) {
+            bool skippable = false;
+            switch (element->getOp()) {
+                case SkRegion::kDifference_Op:
+                    // subtracting from the empty set yields the empty set.
+                    skippable = GrReducedClip::kAllOut_InitialState == *initialState;
+                    break;
+                case SkRegion::kIntersect_Op:
+                    // intersecting with the empty set yields the empty set
+                    if (GrReducedClip::kAllOut_InitialState == *initialState) {
+                        skippable = true;
+                    } else {
+                        // We can clear to zero and then simply draw the clip element.
+                        *initialState = GrReducedClip::kAllOut_InitialState;
+                        element->setOp(SkRegion::kReplace_Op);
+                    }
+                    break;
+                case SkRegion::kUnion_Op:
+                    if (GrReducedClip::kAllIn_InitialState == *initialState) {
+                        // unioning the infinite plane with anything is a no-op.
+                        skippable = true;
+                    } else {
+                        // unioning the empty set with a shape is the shape.
+                        element->setOp(SkRegion::kReplace_Op);
+                    }
+                    break;
+                case SkRegion::kXOR_Op:
+                    if (GrReducedClip::kAllOut_InitialState == *initialState) {
+                        // xor could be changed to diff in the kAllIn case, not sure it's a win.
+                        element->setOp(SkRegion::kReplace_Op);
+                    }
+                    break;
+                case SkRegion::kReverseDifference_Op:
+                    if (GrReducedClip::kAllIn_InitialState == *initialState) {
+                        // subtracting the whole plane will yield the empty set.
+                        skippable = true;
+                        *initialState = GrReducedClip::kAllOut_InitialState;
+                    } else {
+                        // this picks up flips inserted in the backwards pass.
+                        skippable = element->isInverseFilled() ?
+                            !SkRect::Intersects(element->getBounds(), queryBounds) :
+                            element->contains(queryBounds);
+                        if (skippable) {
+                            *initialState = GrReducedClip::kAllIn_InitialState;
+                        } else {
+                            element->setOp(SkRegion::kReplace_Op);
+                        }
+                    }
+                    break;
+                case SkRegion::kReplace_Op:
+                    skippable = false; // we would have skipped it in the backwards walk if we
+                                       // could've.
+                    break;
+                default:
+                    SkDEBUGFAIL("Unexpected op.");
+                    break;
+            }
+            if (!skippable) {
+                break;
+            } else {
+                if (element->isAA()) {
+                    --numAAElements;
+                }
+                result->popHead();
+                element = result->headIter().get();
+            }
+        }
+    }
+    if (requiresAA) {
+        *requiresAA = numAAElements > 0;
+    }
+
+    if (0 == result->count()) {
+        if (*initialState == GrReducedClip::kAllIn_InitialState) {
+            *resultGenID = SkClipStack::kWideOpenGenID;
+        } else {
+            *resultGenID = SkClipStack::kEmptyGenID;
+        }
+    }
+}
 
 /*
 There are plenty of optimizations that could be added here. Maybe flips could be folded into
@@ -28,13 +324,13 @@
 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 ReduceClipStack(const SkClipStack& stack,
-                     const SkIRect& queryBounds,
-                     ElementList* result,
-                     int32_t* resultGenID,
-                     InitialState* initialState,
-                     SkIRect* tighterBounds,
-                     bool* requiresAA) {
+void GrReducedClip::ReduceClipStack(const SkClipStack& stack,
+                                    const SkIRect& queryBounds,
+                                    ElementList* result,
+                                    int32_t* resultGenID,
+                                    InitialState* initialState,
+                                    SkIRect* tighterBounds,
+                                    bool* requiresAA) {
     result->reset();
 
     // The clip established by the element list might be cached based on the last
@@ -64,7 +360,7 @@
         SkASSERT(SkClipStack::kNormal_BoundsType == stackBoundsType);
         SkRect isectRect;
         if (stackBounds.contains(scalarQueryBounds)) {
-            *initialState = kAllIn_InitialState;
+            *initialState = GrReducedClip::kAllIn_InitialState;
             if (tighterBounds) {
                 *tighterBounds = queryBounds;
             }
@@ -82,7 +378,7 @@
                     if (requiresAA) {
                         *requiresAA = false;
                     }
-                    *initialState = kAllIn_InitialState;
+                    *initialState = GrReducedClip::kAllIn_InitialState;
                     return;
                 }
             }
@@ -140,311 +436,3 @@
     // element.
     SkASSERT(SkClipStack::kInvalidGenID != *resultGenID);
 }
-
-void reduced_stack_walker(const SkClipStack& stack,
-                          const SkRect& queryBounds,
-                          ElementList* result,
-                          int32_t* resultGenID,
-                          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
-    //  c) a replace operation
-
-    static const InitialState kUnknown_InitialState = static_cast<InitialState>(-1);
-    *initialState = kUnknown_InitialState;
-
-    // During our backwards walk, track whether we've seen ops that either grow or shrink the clip.
-    // TODO: track these per saved clip so that we can consider them on the forward pass.
-    bool embiggens = false;
-    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) {
-            *initialState = kAllIn_InitialState;
-            break;
-        }
-        if (SkClipStack::kEmptyGenID == element->getGenID()) {
-            *initialState = kAllOut_InitialState;
-            break;
-        }
-        if (SkClipStack::kWideOpenGenID == element->getGenID()) {
-            *initialState = kAllIn_InitialState;
-            break;
-        }
-
-        bool skippable = false;
-        bool isFlip = false; // does this op just flip the in/out state of every point in the bounds
-
-        switch (element->getOp()) {
-            case SkRegion::kDifference_Op:
-                // check if the shape subtracted either contains the entire bounds (and makes
-                // the clip empty) or is outside the bounds and therefore can be skipped.
-                if (element->isInverseFilled()) {
-                    if (element->contains(queryBounds)) {
-                        skippable = true;
-                    } else if (!SkRect::Intersects(element->getBounds(), queryBounds)) {
-                        *initialState = kAllOut_InitialState;
-                        skippable = true;
-                    }
-                } else {
-                    if (element->contains(queryBounds)) {
-                        *initialState = kAllOut_InitialState;
-                        skippable = true;
-                    } else if (!SkRect::Intersects(element->getBounds(), queryBounds)) {
-                        skippable = true;
-                    }
-                }
-                if (!skippable) {
-                    emsmallens = true;
-                }
-                break;
-            case SkRegion::kIntersect_Op:
-                // check if the shape intersected contains the entire bounds and therefore can
-                // be skipped or it is outside the entire bounds and therefore makes the clip
-                // empty.
-                if (element->isInverseFilled()) {
-                    if (element->contains(queryBounds)) {
-                        *initialState = kAllOut_InitialState;
-                        skippable = true;
-                    } else if (!SkRect::Intersects(element->getBounds(), queryBounds)) {
-                        skippable = true;
-                    }
-                } else {
-                    if (element->contains(queryBounds)) {
-                        skippable = true;
-                    } else if (!SkRect::Intersects(element->getBounds(), queryBounds)) {
-                        *initialState = kAllOut_InitialState;
-                        skippable = true;
-                    }
-                }
-                if (!skippable) {
-                    emsmallens = true;
-                }
-                break;
-            case SkRegion::kUnion_Op:
-                // If the union-ed shape contains the entire bounds then after this element
-                // the bounds is entirely inside the clip. If the union-ed shape is outside the
-                // bounds then this op can be skipped.
-                if (element->isInverseFilled()) {
-                    if (element->contains(queryBounds)) {
-                        skippable = true;
-                    } else if (!SkRect::Intersects(element->getBounds(), queryBounds)) {
-                        *initialState = kAllIn_InitialState;
-                        skippable = true;
-                    }
-                } else {
-                    if (element->contains(queryBounds)) {
-                        *initialState = kAllIn_InitialState;
-                        skippable = true;
-                    } else if (!SkRect::Intersects(element->getBounds(), queryBounds)) {
-                        skippable = true;
-                    }
-                }
-                if (!skippable) {
-                    embiggens = true;
-                }
-                break;
-            case SkRegion::kXOR_Op:
-                // If the bounds is entirely inside the shape being xor-ed then the effect is
-                // to flip the inside/outside state of every point in the bounds. We may be
-                // able to take advantage of this in the forward pass. If the xor-ed shape
-                // doesn't intersect the bounds then it can be skipped.
-                if (element->isInverseFilled()) {
-                    if (element->contains(queryBounds)) {
-                        skippable = true;
-                    } else if (!SkRect::Intersects(element->getBounds(), queryBounds)) {
-                        isFlip = true;
-                    }
-                } else {
-                    if (element->contains(queryBounds)) {
-                        isFlip = true;
-                    } else if (!SkRect::Intersects(element->getBounds(), queryBounds)) {
-                        skippable = true;
-                    }
-                }
-                if (!skippable) {
-                    emsmallens = embiggens = true;
-                }
-                break;
-            case SkRegion::kReverseDifference_Op:
-                // When the bounds is entirely within the rev-diff shape then this behaves like xor
-                // and reverses every point inside the bounds. If the shape is completely outside
-                // the bounds then we know after this element is applied that the bounds will be
-                // all outside the current clip.B
-                if (element->isInverseFilled()) {
-                    if (element->contains(queryBounds)) {
-                        *initialState = kAllOut_InitialState;
-                        skippable = true;
-                    } else if (!SkRect::Intersects(element->getBounds(), queryBounds)) {
-                        isFlip = true;
-                    }
-                } else {
-                    if (element->contains(queryBounds)) {
-                        isFlip = true;
-                    } else if (!SkRect::Intersects(element->getBounds(), queryBounds)) {
-                        *initialState = kAllOut_InitialState;
-                        skippable = true;
-                    }
-                }
-                if (!skippable) {
-                    emsmallens = embiggens = true;
-                }
-                break;
-            case SkRegion::kReplace_Op:
-                // Replace will always terminate our walk. We will either begin the forward walk
-                // at the replace op or detect here than the shape is either completely inside
-                // or completely outside the bounds. In this latter case it can be skipped by
-                // setting the correct value for initialState.
-                if (element->isInverseFilled()) {
-                    if (element->contains(queryBounds)) {
-                        *initialState = kAllOut_InitialState;
-                        skippable = true;
-                    } else if (!SkRect::Intersects(element->getBounds(), queryBounds)) {
-                        *initialState = kAllIn_InitialState;
-                        skippable = true;
-                    }
-                } else {
-                    if (element->contains(queryBounds)) {
-                        *initialState = kAllIn_InitialState;
-                        skippable = true;
-                    } else if (!SkRect::Intersects(element->getBounds(), queryBounds)) {
-                        *initialState = kAllOut_InitialState;
-                        skippable = true;
-                    }
-                }
-                if (!skippable) {
-                    *initialState = kAllOut_InitialState;
-                    embiggens = emsmallens = true;
-                }
-                break;
-            default:
-                SkDEBUGFAIL("Unexpected op.");
-                break;
-        }
-        if (!skippable) {
-            if (0 == result->count()) {
-                // This will be the last element. Record the stricter genID.
-                *resultGenID = element->getGenID();
-            }
-
-            // if it is a flip, change it to a bounds-filling rect
-            if (isFlip) {
-                SkASSERT(SkRegion::kXOR_Op == element->getOp() ||
-                         SkRegion::kReverseDifference_Op == element->getOp());
-                SkNEW_INSERT_AT_LLIST_HEAD(result,
-                                           Element,
-                                           (queryBounds, SkRegion::kReverseDifference_Op, false));
-            } else {
-                Element* newElement = result->addToHead(*element);
-                if (newElement->isAA()) {
-                    ++numAAElements;
-                }
-                // Intersecting an inverse shape is the same as differencing the non-inverse shape.
-                // Replacing with an inverse shape is the same as setting initialState=kAllIn and
-                // differencing the non-inverse shape.
-                bool isReplace = SkRegion::kReplace_Op == newElement->getOp();
-                if (newElement->isInverseFilled() &&
-                    (SkRegion::kIntersect_Op == newElement->getOp() || isReplace)) {
-                    newElement->invertShapeFillType();
-                    newElement->setOp(SkRegion::kDifference_Op);
-                    if (isReplace) {
-                        SkASSERT(kAllOut_InitialState == *initialState);
-                        *initialState = kAllIn_InitialState;
-                    }
-                }
-            }
-        }
-    }
-
-    if ((kAllOut_InitialState == *initialState && !embiggens) ||
-        (kAllIn_InitialState == *initialState && !emsmallens)) {
-        result->reset();
-    } else {
-        Element* element = result->headIter().get();
-        while (element) {
-            bool skippable = false;
-            switch (element->getOp()) {
-                case SkRegion::kDifference_Op:
-                    // subtracting from the empty set yields the empty set.
-                    skippable = kAllOut_InitialState == *initialState;
-                    break;
-                case SkRegion::kIntersect_Op:
-                    // intersecting with the empty set yields the empty set
-                    if (kAllOut_InitialState == *initialState) {
-                        skippable = true;
-                    } else {
-                        // We can clear to zero and then simply draw the clip element.
-                        *initialState = kAllOut_InitialState;
-                        element->setOp(SkRegion::kReplace_Op);
-                    }
-                    break;
-                case SkRegion::kUnion_Op:
-                    if (kAllIn_InitialState == *initialState) {
-                        // unioning the infinite plane with anything is a no-op.
-                        skippable = true;
-                    } else {
-                        // unioning the empty set with a shape is the shape.
-                        element->setOp(SkRegion::kReplace_Op);
-                    }
-                    break;
-                case SkRegion::kXOR_Op:
-                    if (kAllOut_InitialState == *initialState) {
-                        // xor could be changed to diff in the kAllIn case, not sure it's a win.
-                        element->setOp(SkRegion::kReplace_Op);
-                    }
-                    break;
-                case SkRegion::kReverseDifference_Op:
-                    if (kAllIn_InitialState == *initialState) {
-                        // subtracting the whole plane will yield the empty set.
-                        skippable = true;
-                        *initialState = kAllOut_InitialState;
-                    } else {
-                        // this picks up flips inserted in the backwards pass.
-                        skippable = element->isInverseFilled() ?
-                            !SkRect::Intersects(element->getBounds(), queryBounds) :
-                            element->contains(queryBounds);
-                        if (skippable) {
-                            *initialState = kAllIn_InitialState;
-                        } else {
-                            element->setOp(SkRegion::kReplace_Op);
-                        }
-                    }
-                    break;
-                case SkRegion::kReplace_Op:
-                    skippable = false; // we would have skipped it in the backwards walk if we
-                                       // could've.
-                    break;
-                default:
-                    SkDEBUGFAIL("Unexpected op.");
-                    break;
-            }
-            if (!skippable) {
-                break;
-            } else {
-                if (element->isAA()) {
-                    --numAAElements;
-                }
-                result->popHead();
-                element = result->headIter().get();
-            }
-        }
-    }
-    if (requiresAA) {
-        *requiresAA = numAAElements > 0;
-    }
-
-    if (0 == result->count()) {
-        if (*initialState == kAllIn_InitialState) {
-            *resultGenID = SkClipStack::kWideOpenGenID;
-        } else {
-            *resultGenID = SkClipStack::kEmptyGenID;
-        }
-    }
-}
-} // namespace GrReducedClip
diff --git a/src/gpu/GrReducedClip.h b/src/gpu/GrReducedClip.h
index e3a28cc..21899c7 100644
--- a/src/gpu/GrReducedClip.h
+++ b/src/gpu/GrReducedClip.h
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2012 Google Inc.
  *
@@ -12,37 +11,39 @@
 #include "SkClipStack.h"
 #include "SkTLList.h"
 
-namespace GrReducedClip {
+class SK_API GrReducedClip {
+public:
+    typedef SkTLList<SkClipStack::Element> ElementList;
 
-typedef SkTLList<SkClipStack::Element> ElementList;
+    enum InitialState {
+        kAllIn_InitialState,
+        kAllOut_InitialState,
+    };
 
-enum InitialState {
-    kAllIn_InitialState,
-    kAllOut_InitialState,
+    /**
+     * This function takes a clip stack and a query rectangle and it produces a
+     * reduced set of SkClipStack::Elements that are equivalent to applying the
+     * full stack to the rectangle. The clip stack generation id that represents
+     * the list of elements is returned in resultGenID. The initial state of the
+     * query rectangle before the first clip element is applied is returned via
+     * initialState. Optionally, the caller can request a tighter bounds on the
+     * clip be returned via tighterBounds. If not NULL, tighterBounds will
+     * always be contained by queryBounds after return. If tighterBounds is
+     * specified then it is assumed that the caller will implicitly clip against
+     * it. If the caller specifies non-NULL for requiresAA then it will indicate
+     * whether anti-aliasing is required to process any of the elements in the
+     * result.
+     *
+     * This may become a member function of SkClipStack when its interface is
+     * determined to be stable.
+     */
+    static void ReduceClipStack(const SkClipStack& stack,
+                                const SkIRect& queryBounds,
+                                ElementList* result,
+                                int32_t* resultGenID,
+                                InitialState* initialState,
+                                SkIRect* tighterBounds = NULL,
+                                bool* requiresAA = NULL);
 };
 
-/**
- * This function takes a clip stack and a query rectangle and it produces a reduced set of
- * SkClipStack::Elements that are equivalent to applying the full stack to the rectangle. The clip
- * stack generation id that represents the list of elements is returned in resultGenID. The
- * initial state of the query rectangle before the first clip element is applied is returned via
- * initialState. Optionally, the caller can request a tighter bounds on the clip be returned via
- * tighterBounds. If not NULL, tighterBounds will always be contained by queryBounds after return.
- * If tighterBounds is specified then it is assumed that the caller will implicitly clip against it.
- * If the caller specifies non-NULL for requiresAA then it will indicate whether anti-aliasing is
- * required to process any of the elements in the result.
- *
- * This may become a member function of SkClipStack when its interface is determined to be stable.
- * Marked SK_API so that SkLua can call this in a shared library build.
- */
-SK_API void ReduceClipStack(const SkClipStack& stack,
-                            const SkIRect& queryBounds,
-                            ElementList* result,
-                            int32_t* resultGenID,
-                            InitialState* initialState,
-                            SkIRect* tighterBounds = NULL,
-                            bool* requiresAA = NULL);
-
-} // namespace GrReducedClip
-
 #endif