Make SkClipStack::Iter use SkClipStack::Element.

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

git-svn-id: http://skia.googlecode.com/svn/trunk@6661 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp
index fdaa067..64ead1a 100644
--- a/src/gpu/GrClipMaskManager.cpp
+++ b/src/gpu/GrClipMaskManager.cpp
@@ -24,6 +24,7 @@
 #define GR_AA_CLIP 1
 #define GR_SW_CLIP 1
 
+typedef SkClipStack::Element Element;
 ////////////////////////////////////////////////////////////////////////////////
 
 namespace GrReducedClip {
@@ -38,11 +39,11 @@
 take a rect in case the caller knows a bound on what is to be drawn through this clip.
 */
 void GrReduceClipStack(const SkClipStack& stack,
-                       SkTDArray<SkClipStack::Iter::Clip>* resultClips,
+                       ElementList* result,
                        SkRect* resultBounds,
                        bool* resultsAreBounded,
                        InitialState* initialState) {
-    resultClips->reset();
+    result->reset();
 
     if (stack.isWideOpen()) {
         *initialState = kAllIn_InitialState;
@@ -56,15 +57,10 @@
     if (iior) {
         *resultsAreBounded = true;
         *initialState = kAllOut_InitialState;
-        SkClipStack::Iter::Clip* clip = resultClips->append();
-        // append doesn't call the default cons.
-        *clip = SkClipStack::Iter::Clip();
-
-        // iior should only be true if aa/non-aa status matches.
         SkClipStack::Iter iter(stack, SkClipStack::Iter::kTop_IterStart);
-        clip->fDoAA = iter.prev()->fDoAA;
-        clip->fOp = SkRegion::kReplace_Op;
-        clip->fRect = resultBounds;
+        // iior should only be true if aa/non-aa status matches among all elements.
+        bool doAA = iter.prev()->isAA();
+        SkNEW_INSERT_AT_LLIST_TAIL(result, Element, (*resultBounds, SkRegion::kReplace_Op, doAA));
         return;
     }
 
@@ -85,16 +81,16 @@
 
     SkClipStack::Iter iter(stack, SkClipStack::Iter::kTop_IterStart);
     while ((kUnknown_InitialState == *initialState)) {
-        const SkClipStack::Iter::Clip* clip = iter.prev();
-        if (NULL == clip) {
+        const Element* element = iter.prev();
+        if (NULL == element) {
             *initialState = kAllIn_InitialState;
             break;
         }
-        if (SkClipStack::kEmptyGenID == clip->fGenID) {
+        if (SkClipStack::kEmptyGenID == element->getGenID()) {
             *initialState = kAllOut_InitialState;
             break;
         }
-        if (SkClipStack::kWideOpenGenID == clip->fGenID) {
+        if (SkClipStack::kWideOpenGenID == element->getGenID()) {
             *initialState = kAllIn_InitialState;
             break;
         }
@@ -102,23 +98,23 @@
         bool skippable = false;
         bool isFlip = false; // does this op just flip the in/out state of every point in the bounds
 
-        switch (clip->fOp) {
+        switch (element->getOp()) {
             case SkRegion::kDifference_Op:
                 if (*resultsAreBounded) {
                     // 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 (clip->isInverseFilled()) {
-                        if (clip->contains(*resultBounds)) {
+                    if (element->isInverseFilled()) {
+                        if (element->contains(*resultBounds)) {
                             skippable = true;
-                        } else if (!SkRect::Intersects(clip->getBounds(), *resultBounds)) {
+                        } else if (!SkRect::Intersects(element->getBounds(), *resultBounds)) {
                             *initialState = kAllOut_InitialState;
                             skippable = true;
                         }
                     } else {
-                        if (clip->contains(*resultBounds)) {
+                        if (element->contains(*resultBounds)) {
                             *initialState = kAllOut_InitialState;
                             skippable = true;
-                        } else if (!SkRect::Intersects(clip->getBounds(), *resultBounds)) {
+                        } else if (!SkRect::Intersects(element->getBounds(), *resultBounds)) {
                             skippable = true;
                         }
                     }
@@ -132,17 +128,17 @@
                     // 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 (clip->isInverseFilled()) {
-                        if (clip->contains(*resultBounds)) {
+                    if (element->isInverseFilled()) {
+                        if (element->contains(*resultBounds)) {
                             *initialState = kAllOut_InitialState;
                             skippable = true;
-                        } else if (!SkRect::Intersects(clip->getBounds(), *resultBounds)) {
+                        } else if (!SkRect::Intersects(element->getBounds(), *resultBounds)) {
                             skippable = true;
                         }
                     } else {
-                        if (clip->contains(*resultBounds)) {
+                        if (element->contains(*resultBounds)) {
                             skippable = true;
-                        } else if (!SkRect::Intersects(clip->getBounds(), *resultBounds)) {
+                        } else if (!SkRect::Intersects(element->getBounds(), *resultBounds)) {
                             *initialState = kAllOut_InitialState;
                             skippable = true;
                         }
@@ -157,18 +153,18 @@
                     // 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 (clip->isInverseFilled()) {
-                        if (clip->contains(*resultBounds)) {
+                    if (element->isInverseFilled()) {
+                        if (element->contains(*resultBounds)) {
                             skippable = true;
-                        } else if (!SkRect::Intersects(clip->getBounds(), *resultBounds)) {
+                        } else if (!SkRect::Intersects(element->getBounds(), *resultBounds)) {
                             *initialState = kAllIn_InitialState;
                             skippable = true;
                         }
                     } else {
-                        if (clip->contains(*resultBounds)) {
+                        if (element->contains(*resultBounds)) {
                             *initialState = kAllIn_InitialState;
                             skippable = true;
-                        } else if (!SkRect::Intersects(clip->getBounds(), *resultBounds)) {
+                        } else if (!SkRect::Intersects(element->getBounds(), *resultBounds)) {
                             skippable = true;
                         }
                     }
@@ -183,16 +179,16 @@
                     // 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 (clip->isInverseFilled()) {
-                        if (clip->contains(*resultBounds)) {
+                    if (element->isInverseFilled()) {
+                        if (element->contains(*resultBounds)) {
                             skippable = true;
-                        } else if (!SkRect::Intersects(clip->getBounds(), *resultBounds)) {
+                        } else if (!SkRect::Intersects(element->getBounds(), *resultBounds)) {
                             isFlip = true;
                         }
                     } else {
-                        if (clip->contains(*resultBounds)) {
+                        if (element->contains(*resultBounds)) {
                             isFlip = true;
-                        } else if (!SkRect::Intersects(clip->getBounds(), *resultBounds)) {
+                        } else if (!SkRect::Intersects(element->getBounds(), *resultBounds)) {
                             skippable = true;
                         }
                     }
@@ -207,17 +203,17 @@
                 // the bounds then we know after this element is applied that the bounds will be
                 // all outside the current clip.B
                 if (*resultsAreBounded) {
-                    if (clip->isInverseFilled()) {
-                        if (clip->contains(*resultBounds)) {
+                    if (element->isInverseFilled()) {
+                        if (element->contains(*resultBounds)) {
                             *initialState = kAllOut_InitialState;
                             skippable = true;
-                        } else if (!SkRect::Intersects(clip->getBounds(), *resultBounds)) {
+                        } else if (!SkRect::Intersects(element->getBounds(), *resultBounds)) {
                             isFlip = true;
                         }
                     } else {
-                        if (clip->contains(*resultBounds)) {
+                        if (element->contains(*resultBounds)) {
                             isFlip = true;
-                        } else if (!SkRect::Intersects(clip->getBounds(), *resultBounds)) {
+                        } else if (!SkRect::Intersects(element->getBounds(), *resultBounds)) {
                             *initialState = kAllOut_InitialState;
                             skippable = true;
                         }
@@ -233,19 +229,19 @@
                 // or completely outside the bounds. In this latter case it can be skipped by
                 // setting the correct value for initialState.
                 if (*resultsAreBounded) {
-                    if (clip->isInverseFilled()) {
-                        if (clip->contains(*resultBounds)) {
+                    if (element->isInverseFilled()) {
+                        if (element->contains(*resultBounds)) {
                             *initialState = kAllOut_InitialState;
                             skippable = true;
-                        } else if (!SkRect::Intersects(clip->getBounds(), *resultBounds)) {
+                        } else if (!SkRect::Intersects(element->getBounds(), *resultBounds)) {
                             *initialState = kAllIn_InitialState;
                             skippable = true;
                         }
                     } else {
-                        if (clip->contains(*resultBounds)) {
+                        if (element->contains(*resultBounds)) {
                             *initialState = kAllIn_InitialState;
                             skippable = true;
-                        } else if (!SkRect::Intersects(clip->getBounds(), *resultBounds)) {
+                        } else if (!SkRect::Intersects(element->getBounds(), *resultBounds)) {
                             *initialState = kAllOut_InitialState;
                             skippable = true;
                         }
@@ -261,32 +257,28 @@
                 break;
         }
         if (!skippable) {
-            SkClipStack::Iter::Clip* newClip = resultClips->prepend();
             // if it is a flip, change it to a bounds-filling rect
             if (isFlip) {
-                SkASSERT(SkRegion::kXOR_Op == clip->fOp ||
-                         SkRegion::kReverseDifference_Op == clip->fOp);
-                newClip->fPath = NULL;
-                newClip->fRect = resultBounds;
-                // assuming this is faster to perform on GPU with stenciling than xor.
-                newClip->fOp = SkRegion::kReverseDifference_Op;
-                newClip->fDoAA = false;
-                newClip->fGenID = SkClipStack::kInvalidGenID;
+                SkASSERT(SkRegion::kXOR_Op == element->getOp() ||
+                         SkRegion::kReverseDifference_Op == element->getOp());
+                SkNEW_INSERT_AT_LLIST_HEAD(result,
+                                           Element,
+                                           (*resultBounds, SkRegion::kReverseDifference_Op, false));
             } else {
-                *newClip = *clip;
+                result->addToHead(*element);
             }
         }
     }
 
     if ((kAllOut_InitialState == *initialState && !embiggens) ||
         (kAllIn_InitialState == *initialState && !emsmallens)) {
-        resultClips->reset();
+        result->reset();
     } else {
         int clipsToSkip = 0;
-        while (1) {
-            SkClipStack::Iter::Clip* clip = &(*resultClips)[clipsToSkip];
+        Element* element = result->headIter().get();
+        while (NULL != element) {            
             bool skippable = false;
-            switch (clip->fOp) {
+            switch (element->getOp()) {
                 case SkRegion::kDifference_Op:
                     // subtracting from the empty set yields the empty set.
                     skippable = kAllOut_InitialState == *initialState;
@@ -301,13 +293,13 @@
                         skippable = true;
                     } else {
                         // unioning the empty set with a shape is the shape.
-                        clip->fOp = SkRegion::kReplace_Op;
+                        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.
-                        clip->fOp = SkRegion::kReplace_Op;
+                        element->setOp(SkRegion::kReplace_Op);
                     }
                     break;
                 case SkRegion::kReverseDifference_Op:
@@ -317,15 +309,15 @@
                         *initialState = kAllOut_InitialState;
                     } else {
                         // this picks up flips inserted in the backwards pass.
-                        if (*resultsAreBounded && NULL != clip->fRect) {
-                            skippable = clip->isInverseFilled() ?
-                                !SkRect::Intersects(clip->getBounds(), *resultBounds) :
-                                clip->contains(*resultBounds);
+                        if (*resultsAreBounded) {
+                            skippable = element->isInverseFilled() ?
+                                !SkRect::Intersects(element->getBounds(), *resultBounds) :
+                                element->contains(*resultBounds);
                         }
                         if (skippable) {
                             *initialState = kAllIn_InitialState;
                         } else {
-                            clip->fOp = SkRegion::kReplace_Op;
+                            element->setOp(SkRegion::kReplace_Op);
                         }
                     }
                     break;
@@ -341,13 +333,10 @@
             if (!skippable) {
                 break;
             } else {
-                ++clipsToSkip;
-                if (clipsToSkip == resultClips->count()) {
-                    break;
-                }
+                result->popHead();
+                element = result->headIter().get();
             }
         }
-        resultClips->remove(0, clipsToSkip);
     }
 }
 } // namespace GrReducedClip
@@ -413,12 +402,12 @@
     SkClipStack::Iter iter;
     iter.reset(clipIn, SkClipStack::Iter::kBottom_IterStart);
 
-    const SkClipStack::Iter::Clip* clip = NULL;
-    for (clip = iter.skipToTopmost(SkRegion::kReplace_Op);
-         NULL != clip;
-         clip = iter.next()) {
+    const Element* element = NULL;
+    for (element = iter.skipToTopmost(SkRegion::kReplace_Op);
+         NULL != element;
+         element = iter.next()) {
 
-        if (clip->fDoAA) {
+        if (element->isAA()) {
             return true;
         }
     }
@@ -441,19 +430,19 @@
     bool useSW = false;
 
     SkClipStack::Iter iter(clipIn, SkClipStack::Iter::kBottom_IterStart);
-    const SkClipStack::Iter::Clip* clip = NULL;
+    const Element* element = NULL;
 
-    for (clip = iter.skipToTopmost(SkRegion::kReplace_Op);
-         NULL != clip;
-         clip = iter.next()) {
+    for (element = iter.skipToTopmost(SkRegion::kReplace_Op);
+         NULL != element;
+         element = iter.next()) {
 
         // rects can always be drawn directly w/o using the software path
         // so only paths need to be checked
-        if (NULL != clip->fPath &&
+        if (Element::kPath_Type == element->getType() &&
             path_needs_SW_renderer(this->getContext(), fGpu,
-                                   *clip->fPath,
-                                   get_path_fill(*clip->fPath),
-                                   clip->fDoAA)) {
+                                   element->getPath(),
+                                   get_path_fill(element->getPath()),
+                                   element->isAA())) {
             useSW = true;
         }
     }
@@ -598,7 +587,7 @@
 // determines how many elements at the head of the clip can be skipped and
 // whether the initial clear should be to the inside- or outside-the-clip value,
 // and what op should be used to draw the first element that isn't skipped.
-const SkClipStack::Iter::Clip* process_initial_clip_elements(
+const SkClipStack::Element* process_initial_clip_elements(
                                   SkClipStack::Iter* iter,
                                   const GrIRect& devBounds,
                                   bool* clearToInside,
@@ -615,12 +604,12 @@
     bool done = false;
     *clearToInside = true;
 
-    const SkClipStack::Iter::Clip* clip = NULL;
+    const SkClipStack::Element* element = NULL;
 
-    for (clip = iter->skipToTopmost(SkRegion::kReplace_Op);
-         NULL != clip && !done;
-         clip = iter->next()) {
-        switch (clip->fOp) {
+    for (element = iter->skipToTopmost(SkRegion::kReplace_Op);
+         NULL != element && !done;
+         element = iter->next()) {
+        switch (element->getOp()) {
             case SkRegion::kReplace_Op:
                 // replace ignores everything previous
                 *firstOp = SkRegion::kReplace_Op;
@@ -630,8 +619,8 @@
             case SkRegion::kIntersect_Op:
                 // if this element contains the entire bounds then we
                 // can skip it.
-                if (NULL != clip->fRect &&
-                    contains(*clip->fRect, devBounds, clipData.fOrigin)) {
+                if (Element::kRect_Type == element->getType() &&
+                    contains(element->getRect(), devBounds, clipData.fOrigin)) {
                     break;
                 }
                 // if everything is initially clearToInside then intersect is
@@ -674,7 +663,7 @@
                 break;
             case SkRegion::kReverseDifference_Op:
                 // if all pixels are clearToInside then reverse difference
-                // produces empty set. Otherise it is same as replace
+                // produces empty set. Otherwise it is same as replace
                 if (*clearToInside) {
                     *clearToInside = false;
                 } else {
@@ -692,7 +681,7 @@
             break;
         }
     }
-    return clip;
+    return element;
 }
 
 }
@@ -786,27 +775,31 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 bool GrClipMaskManager::drawClipShape(GrTexture* target,
-                                      const SkClipStack::Iter::Clip* clip,
+                                      const SkClipStack::Element* element,
                                       const GrIRect& resultBounds) {
     GrDrawState* drawState = fGpu->drawState();
     GrAssert(NULL != drawState);
 
     drawState->setRenderTarget(target->asRenderTarget());
 
-    if (NULL != clip->fRect) {
-        if (clip->fDoAA) {
-            getContext()->getAARectRenderer()->fillAARect(fGpu, fGpu,
-                                                          *clip->fRect,
-                                                          true);
-        } else {
-            fGpu->drawSimpleRect(*clip->fRect, NULL);
-        }
-    } else if (NULL != clip->fPath) {
-        return draw_path(this->getContext(), fGpu,
-                         *clip->fPath,
-                         get_path_fill(*clip->fPath),
-                         clip->fDoAA,
-                         resultBounds);
+    switch (element->getType()) {
+        case Element::kRect_Type:
+            if (element->isAA()) {
+                getContext()->getAARectRenderer()->fillAARect(fGpu, fGpu, element->getRect(), true);
+            } else {
+                fGpu->drawSimpleRect(element->getRect(), NULL);
+            }
+            return true;
+        case Element::kPath_Type:
+            return draw_path(this->getContext(), fGpu,
+                             element->getPath(),
+                             get_path_fill(element->getPath()),
+                             element->isAA(),
+                             resultBounds);
+        default:
+            // something is wrong if we're trying to draw an empty element.
+            GrCrash("Unexpected element type");
+            return false;
     }
     return true;
 }
@@ -951,11 +944,11 @@
 
     SkClipStack::Iter iter(*clipDataIn.fClipStack,
                            SkClipStack::Iter::kBottom_IterStart);
-    const SkClipStack::Iter::Clip* clip = process_initial_clip_elements(&iter,
-                                                              *devResultBounds,
-                                                              &clearToInside,
-                                                              &firstOp,
-                                                              clipDataIn);
+    const Element* element = process_initial_clip_elements(&iter,
+                                                           *devResultBounds,
+                                                           &clearToInside,
+                                                           &firstOp,
+                                                           clipDataIn);
     // 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(&maskResultBounds,
@@ -966,9 +959,9 @@
     GrAutoScratchTexture temp;
     bool first = true;
     // walk through each clip element and perform its set op
-    for ( ; NULL != clip; clip = iter.next()) {
+    for ( ; NULL != element; element = iter.next()) {
 
-        SkRegion::Op op = clip->fOp;
+        SkRegion::Op op = element->getOp();
         if (first) {
             first = false;
             op = firstOp;
@@ -981,13 +974,13 @@
             }
 
             setup_boolean_blendcoeffs(drawState, op);
-            this->drawClipShape(accum, clip, *devResultBounds);
+            this->drawClipShape(accum, element, *devResultBounds);
 
         } else if (SkRegion::kReverseDifference_Op == op ||
                    SkRegion::kIntersect_Op == op) {
             // there is no point in intersecting a screen filling rectangle.
-            if (SkRegion::kIntersect_Op == op && NULL != clip->fRect &&
-                contains(*clip->fRect, *devResultBounds, clipDataIn.fOrigin)) {
+            if (SkRegion::kIntersect_Op == op && Element::kRect_Type == element->getType() &&
+                contains(element->getRect(), *devResultBounds, clipDataIn.fOrigin)) {
                 continue;
             }
 
@@ -1001,7 +994,7 @@
             // mask buffer can be substantially larger than the actually clip stack element. We
             // touch the minimum number of pixels necessary and use decal mode to combine it with
             // the accumulator
-            GrRect elementMaskBounds = clip->getBounds();
+            GrRect elementMaskBounds = element->getBounds();
             elementMaskBounds.offset(clipToMaskOffset);
             GrIRect elementMaskIBounds;
             elementMaskBounds.roundOut(&elementMaskIBounds);
@@ -1010,7 +1003,7 @@
             fGpu->clear(&elementMaskIBounds, 0x00000000, temp.texture()->asRenderTarget());
 
             setup_boolean_blendcoeffs(drawState, SkRegion::kReplace_Op);
-            this->drawClipShape(temp.texture(), clip, elementMaskIBounds);
+            this->drawClipShape(temp.texture(), element, elementMaskIBounds);
 
             // Now draw into the accumulator using the real operation
             // and the temp buffer as a texture
@@ -1019,7 +1012,7 @@
             // all the remaining ops can just be directly draw into
             // the accumulation buffer
             setup_boolean_blendcoeffs(drawState, op);
-            this->drawClipShape(accum, clip, *devResultBounds);
+            this->drawClipShape(accum, element, *devResultBounds);
         }
         accumClearedToZero = false;
     }
@@ -1096,25 +1089,25 @@
 
         SkClipStack::Iter iter(*oldClipData->fClipStack,
                                SkClipStack::Iter::kBottom_IterStart);
-        const SkClipStack::Iter::Clip* clip = process_initial_clip_elements(&iter,
-                                                  devRTRect,
-                                                  &clearToInside,
-                                                  &firstOp,
-                                                  clipDataIn);
+        const Element* element = process_initial_clip_elements(&iter,
+                                                               devRTRect,
+                                                               &clearToInside,
+                                                               &firstOp,
+                                                               clipDataIn);
 
         fGpu->clearStencilClip(devClipBounds, clearToInside);
         bool first = true;
 
         // walk through each clip element and perform its set op
         // with the existing clip.
-        for ( ; NULL != clip; clip = iter.next()) {
+        for ( ; NULL != element; element = iter.next()) {
             GrPathFill fill;
             bool fillInverted = false;
             // enabled at bottom of loop
             drawState->disableState(GrGpu::kModifyStencilClip_StateBit);
             // if the target is MSAA then we want MSAA enabled when the clip is soft
             if (rt->isMultisampled()) {
-                drawState->setState(GrDrawState::kHWAntialias_StateBit, clip->fDoAA);
+                drawState->setState(GrDrawState::kHWAntialias_StateBit, element->isAA());
             }
 
             // Can the clip element be drawn directly to the stencil buffer
@@ -1122,7 +1115,7 @@
             // resolve in/out status?
             bool canRenderDirectToStencil = false;
 
-            SkRegion::Op op = clip->fOp;
+            SkRegion::Op op = element->getOp();
             if (first) {
                 first = false;
                 op = firstOp;
@@ -1130,22 +1123,22 @@
 
             GrPathRenderer* pr = NULL;
             const SkPath* clipPath = NULL;
-            if (NULL != clip->fRect) {
+            if (Element::kRect_Type == element->getType()) {
                 canRenderDirectToStencil = true;
                 fill = kEvenOdd_GrPathFill;
                 fillInverted = false;
                 // there is no point in intersecting a screen filling
                 // rectangle.
                 if (SkRegion::kIntersect_Op == op &&
-                    contains(*clip->fRect, devRTRect, oldClipData->fOrigin)) {
+                    contains(element->getRect(), devRTRect, oldClipData->fOrigin)) {
                     continue;
                 }
             } else {
-                GrAssert(NULL != clip->fPath);
-                fill = get_path_fill(*clip->fPath);
+                GrAssert(Element::kPath_Type == element->getType());
+                clipPath = &element->getPath();
+                fill = get_path_fill(*clipPath);
                 fillInverted = GrIsFillInverted(fill);
                 fill = GrNonInvertedFill(fill);
-                clipPath = clip->fPath;
                 pr = this->getContext()->getPathRenderer(*clipPath, fill, fGpu, false, true);
                 if (NULL == pr) {
                     fGpu->setClip(oldClipData);
@@ -1180,10 +1173,11 @@
                     0x0000,
                     0xffff);
                 SET_RANDOM_COLOR
-                if (NULL != clip->fRect) {
+                if (Element::kRect_Type == element->getType()) {
                     *drawState->stencil() = gDrawToStencil;
-                    fGpu->drawSimpleRect(*clip->fRect, NULL);
+                    fGpu->drawSimpleRect(element->getRect(), NULL);
                 } else {
+                    GrAssert(Element::kPath_Type == element->getType());
                     if (canRenderDirectToStencil) {
                         *drawState->stencil() = gDrawToStencil;
                         pr->drawPath(*clipPath, fill, fGpu, false);
@@ -1199,10 +1193,11 @@
             for (int p = 0; p < passes; ++p) {
                 *drawState->stencil() = stencilSettings[p];
                 if (canDrawDirectToClip) {
-                    if (NULL != clip->fRect) {
+                    if (Element::kRect_Type == element->getType()) {
                         SET_RANDOM_COLOR
-                        fGpu->drawSimpleRect(*clip->fRect, NULL);
+                        fGpu->drawSimpleRect(element->getRect(), NULL);
                     } else {
+                        GrAssert(Element::kPath_Type == element->getType());
                         SET_RANDOM_COLOR
                         pr->drawPath(*clipPath, fill, fGpu, false);
                     }
@@ -1464,18 +1459,18 @@
 
     SkClipStack::Iter iter(*clipDataIn.fClipStack,
                            SkClipStack::Iter::kBottom_IterStart);
-    const SkClipStack::Iter::Clip* clip = process_initial_clip_elements(&iter,
-                                              *devResultBounds,
-                                              &clearToInside,
-                                              &firstOp,
-                                              clipDataIn);
+    const Element* element = process_initial_clip_elements(&iter,
+                                                           *devResultBounds,
+                                                           &clearToInside,
+                                                           &firstOp,
+                                                           clipDataIn);
 
     helper.clear(clearToInside ? 0xFF : 0x00);
 
     bool first = true;
-    for ( ; NULL != clip; clip = iter.next()) {
+    for ( ; NULL != element; element = iter.next()) {
 
-        SkRegion::Op op = clip->fOp;
+        SkRegion::Op op = element->getOp();
         if (first) {
             first = false;
             op = firstOp;
@@ -1499,20 +1494,20 @@
                 helper.draw(temp, SkRegion::kXOR_Op, false, 0xFF);
             }
 
-            if (NULL != clip->fRect) {
-
+            if (Element::kRect_Type == element->getType()) {
                 // convert the rect to a path so we can invert the fill
                 SkPath temp;
-                temp.addRect(*clip->fRect);
+                temp.addRect(element->getRect());
 
                 helper.draw(temp, SkRegion::kReplace_Op,
-                            kInverseEvenOdd_GrPathFill, clip->fDoAA,
+                            kInverseEvenOdd_GrPathFill, element->isAA(),
                             0x00);
-            } else if (NULL != clip->fPath) {
-                helper.draw(*clip->fPath,
+            } else {
+                GrAssert(Element::kPath_Type == element->getType());
+                helper.draw(element->getPath(),
                             SkRegion::kReplace_Op,
-                            invert_fill(get_path_fill(*clip->fPath)),
-                            clip->fDoAA,
+                            invert_fill(get_path_fill(element->getPath())),
+                            element->isAA(),
                             0x00);
             }
 
@@ -1521,17 +1516,14 @@
 
         // The other ops (union, xor, diff) only affect pixels inside
         // the geometry so they can just be drawn normally
-        if (NULL != clip->fRect) {
-
-            helper.draw(*clip->fRect,
+        if (Element::kRect_Type == element->getType()) {
+            helper.draw(element->getRect(), op, element->isAA(), 0xFF);
+        } else {
+            GrAssert(Element::kPath_Type == element->getType());
+            helper.draw(element->getPath(),
                         op,
-                        clip->fDoAA, 0xFF);
-
-        } else if (NULL != clip->fPath) {
-            helper.draw(*clip->fPath,
-                        op,
-                        get_path_fill(*clip->fPath),
-                        clip->fDoAA, 0xFF);
+                        get_path_fill(element->getPath()),
+                        element->isAA(), 0xFF);
         }
     }