Use RoundRect clipping for circle reveal animation

bug:16630975

Also, remove inverse clipping feature from reveal animator.

Change-Id: I770a4eb48cd123b0ca0f39d16a0f3eefd1be3653
diff --git a/core/java/android/animation/RevealAnimator.java b/core/java/android/animation/RevealAnimator.java
index 53d92e6..e363a77 100644
--- a/core/java/android/animation/RevealAnimator.java
+++ b/core/java/android/animation/RevealAnimator.java
@@ -30,7 +30,6 @@
 
     private View mClipView;
     private int mX, mY;
-    private boolean mInverseClip;
     private float mStartRadius, mEndRadius;
     private float mDelta;
     private boolean mMayRunAsync;
@@ -41,14 +40,13 @@
     private RenderNodeAnimator mRtAnimator;
 
     public RevealAnimator(View clipView, int x, int y,
-            float startRadius, float endRadius, boolean inverseClip) {
+            float startRadius, float endRadius) {
         mClipView = clipView;
         mStartRadius = startRadius;
         mEndRadius = endRadius;
         mDelta = endRadius - startRadius;
         mX = x;
         mY = y;
-        mInverseClip = inverseClip;
         super.setValues(PropertyValuesHolder.ofFloat("radius", startRadius, endRadius));
     }
 
@@ -57,12 +55,12 @@
         super.animateValue(fraction);
         fraction = getAnimatedFraction();
         float radius = mStartRadius + (mDelta * fraction);
-        mClipView.setRevealClip(true, mInverseClip, mX, mY, radius);
+        mClipView.setRevealClip(true, mX, mY, radius);
     }
 
     @Override
     protected void endAnimation(AnimationHandler handler) {
-        mClipView.setRevealClip(false, false, 0, 0, 0);
+        mClipView.setRevealClip(false, 0, 0, 0);
         super.endAnimation(handler);
     }
 
@@ -92,7 +90,7 @@
             mRtAnimator = null;
         }
         if (canRunAsync()) {
-            mRtAnimator = new RenderNodeAnimator(mX, mY, mInverseClip, mStartRadius, mEndRadius);
+            mRtAnimator = new RenderNodeAnimator(mX, mY, mStartRadius, mEndRadius);
             mRtAnimator.setDuration(getDuration());
             mRtAnimator.setInterpolator(getInterpolator());
             mRtAnimator.setTarget(mClipView);
diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java
index 2d54acb..e9ec565 100644
--- a/core/java/android/view/RenderNode.java
+++ b/core/java/android/view/RenderNode.java
@@ -378,9 +378,9 @@
     /**
      * Controls the RenderNode's circular reveal clip.
      */
-    public boolean setRevealClip(boolean shouldClip, boolean inverseClip,
+    public boolean setRevealClip(boolean shouldClip,
             float x, float y, float radius) {
-        return nSetRevealClip(mNativeRenderNode, shouldClip, inverseClip, x, y, radius);
+        return nSetRevealClip(mNativeRenderNode, shouldClip, x, y, radius);
     }
 
     /**
@@ -855,7 +855,7 @@
     private static native boolean nSetOutlineNone(long renderNode);
     private static native boolean nSetClipToOutline(long renderNode, boolean clipToOutline);
     private static native boolean nSetRevealClip(long renderNode,
-            boolean shouldClip, boolean inverseClip, float x, float y, float radius);
+            boolean shouldClip, float x, float y, float radius);
     private static native boolean nSetAlpha(long renderNode, float alpha);
     private static native boolean nSetHasOverlappingRendering(long renderNode,
             boolean hasOverlappingRendering);
diff --git a/core/java/android/view/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java
index 2a06336..c7f16e0 100644
--- a/core/java/android/view/RenderNodeAnimator.java
+++ b/core/java/android/view/RenderNodeAnimator.java
@@ -125,10 +125,9 @@
                 property.getNativeContainer(), paintField, finalValue));
     }
 
-    public RenderNodeAnimator(int x, int y, boolean inverseClip,
-            float startRadius, float endRadius) {
-        init(nCreateRevealAnimator(new WeakReference<>(this),
-                x, y, inverseClip, startRadius, endRadius));
+    public RenderNodeAnimator(int x, int y, float startRadius, float endRadius) {
+        init(nCreateRevealAnimator(new WeakReference<RenderNodeAnimator>(this),
+                x, y, startRadius, endRadius));
     }
 
     private void init(long ptr) {
@@ -333,7 +332,7 @@
     private static native long nCreateCanvasPropertyPaintAnimator(WeakReference<RenderNodeAnimator> weakThis,
             long canvasProperty, int paintField, float finalValue);
     private static native long nCreateRevealAnimator(WeakReference<RenderNodeAnimator> weakThis,
-            int x, int y, boolean inverseClip, float startRadius, float endRadius);
+            int x, int y, float startRadius, float endRadius);
 
     private static native void nSetStartValue(long nativePtr, float startValue);
     private static native void nSetDuration(long nativePtr, long duration);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 16a161b..7e16c7d 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -10845,14 +10845,9 @@
         invalidateViewProperty(false, false);
     }
 
-    /**
-     * Private API to be used for reveal animation
-     *
-     * @hide
-     */
-    public void setRevealClip(boolean shouldClip, boolean inverseClip,
-            float x, float y, float radius) {
-        mRenderNode.setRevealClip(shouldClip, inverseClip, x, y, radius);
+    /** @hide */
+    public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
+        mRenderNode.setRevealClip(shouldClip, x, y, radius);
         invalidateViewProperty(false, false);
     }
 
diff --git a/core/java/android/view/ViewAnimationUtils.java b/core/java/android/view/ViewAnimationUtils.java
index 0a53b91..ea3efb1 100644
--- a/core/java/android/view/ViewAnimationUtils.java
+++ b/core/java/android/view/ViewAnimationUtils.java
@@ -38,6 +38,6 @@
      */
     public static final Animator createCircularReveal(View view,
             int centerX,  int centerY, float startRadius, float endRadius) {
-        return new RevealAnimator(view, centerX, centerY, startRadius, endRadius, false);
+        return new RevealAnimator(view, centerX, centerY, startRadius, endRadius);
     }
 }
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index 3b6f0eb..ff54fb9 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -181,11 +181,11 @@
 }
 
 static jboolean android_view_RenderNode_setRevealClip(JNIEnv* env,
-        jobject clazz, jlong renderNodePtr, jboolean shouldClip, jboolean inverseClip,
+        jobject clazz, jlong renderNodePtr, jboolean shouldClip,
         jfloat x, jfloat y, jfloat radius) {
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
     renderNode->mutateStagingProperties().mutableRevealClip().set(
-            shouldClip, inverseClip, x, y, radius);
+            shouldClip, x, y, radius);
     renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
     return true;
 }
@@ -485,7 +485,7 @@
     { "nSetOutlineEmpty",      "(J)Z",   (void*) android_view_RenderNode_setOutlineEmpty },
     { "nSetOutlineNone",       "(J)Z",   (void*) android_view_RenderNode_setOutlineNone },
     { "nSetClipToOutline",     "(JZ)Z",  (void*) android_view_RenderNode_setClipToOutline },
-    { "nSetRevealClip",        "(JZZFFF)Z", (void*) android_view_RenderNode_setRevealClip },
+    { "nSetRevealClip",        "(JZFFF)Z", (void*) android_view_RenderNode_setRevealClip },
 
     { "nSetAlpha",             "(JF)Z",  (void*) android_view_RenderNode_setAlpha },
     { "nSetHasOverlappingRendering", "(JZ)Z",
diff --git a/core/jni/android_view_RenderNodeAnimator.cpp b/core/jni/android_view_RenderNodeAnimator.cpp
index 7c0c6ef..767534f 100644
--- a/core/jni/android_view_RenderNodeAnimator.cpp
+++ b/core/jni/android_view_RenderNodeAnimator.cpp
@@ -117,9 +117,8 @@
 }
 
 static jlong createRevealAnimator(JNIEnv* env, jobject clazz, jobject weakThis,
-        jint centerX, jint centerY, jboolean inverseClip, jfloat startRadius, jfloat endRadius) {
-    BaseRenderNodeAnimator* animator = new RevealAnimator(centerX, centerY, inverseClip,
-            startRadius, endRadius);
+        jint centerX, jint centerY, jfloat startRadius, jfloat endRadius) {
+    BaseRenderNodeAnimator* animator = new RevealAnimator(centerX, centerY, startRadius, endRadius);
     animator->setListener(new AnimationListenerBridge(env, weakThis));
     return reinterpret_cast<jlong>( animator );
 }
@@ -180,7 +179,7 @@
     { "nCreateAnimator", "(Ljava/lang/ref/WeakReference;IF)J", (void*) createAnimator },
     { "nCreateCanvasPropertyFloatAnimator", "(Ljava/lang/ref/WeakReference;JF)J", (void*) createCanvasPropertyFloatAnimator },
     { "nCreateCanvasPropertyPaintAnimator", "(Ljava/lang/ref/WeakReference;JIF)J", (void*) createCanvasPropertyPaintAnimator },
-    { "nCreateRevealAnimator", "(Ljava/lang/ref/WeakReference;IIZFF)J", (void*) createRevealAnimator },
+    { "nCreateRevealAnimator", "(Ljava/lang/ref/WeakReference;IIFF)J", (void*) createRevealAnimator },
     { "nSetStartValue", "(JF)V", (void*) setStartValue },
     { "nSetDuration", "(JJ)V", (void*) setDuration },
     { "nGetDuration", "(J)J", (void*) getDuration },
diff --git a/libs/hwui/Animator.cpp b/libs/hwui/Animator.cpp
index 24ed6cd..dd2e2fd 100644
--- a/libs/hwui/Animator.cpp
+++ b/libs/hwui/Animator.cpp
@@ -288,21 +288,20 @@
     LOG_ALWAYS_FATAL("Unknown field %d", (int) mField);
 }
 
-RevealAnimator::RevealAnimator(int centerX, int centerY, bool inverseClip,
+RevealAnimator::RevealAnimator(int centerX, int centerY,
         float startValue, float finalValue)
         : BaseRenderNodeAnimator(finalValue)
         , mCenterX(centerX)
-        , mCenterY(centerY)
-        , mInverseClip(inverseClip) {
+        , mCenterY(centerY) {
     setStartValue(startValue);
 }
 
 float RevealAnimator::getValue(RenderNode* target) const {
-    return target->properties().getRevealClip().radius();
+    return target->properties().getRevealClip().getRadius();
 }
 
 void RevealAnimator::setValue(RenderNode* target, float value) {
-    target->animatorProperties().mutableRevealClip().set(true, mInverseClip,
+    target->animatorProperties().mutableRevealClip().set(true,
             mCenterX, mCenterY, value);
 }
 
diff --git a/libs/hwui/Animator.h b/libs/hwui/Animator.h
index 9a080a7..b0dcf2d 100644
--- a/libs/hwui/Animator.h
+++ b/libs/hwui/Animator.h
@@ -171,7 +171,7 @@
 
 class RevealAnimator : public BaseRenderNodeAnimator {
 public:
-    ANDROID_API RevealAnimator(int centerX, int centerY, bool inverseClip,
+    ANDROID_API RevealAnimator(int centerX, int centerY,
             float startValue, float finalValue);
 protected:
     virtual float getValue(RenderNode* target) const;
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 9f66904..777a35a 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -1535,10 +1535,9 @@
 class DrawShadowOp : public DrawOp {
 public:
     DrawShadowOp(const mat4& transformXY, const mat4& transformZ,
-            float casterAlpha, bool casterUnclipped,
-            const SkPath* casterOutline, const SkPath* revealClip)
+            float casterAlpha, const SkPath* casterOutline, const SkPath* revealClip)
             : DrawOp(NULL), mTransformXY(transformXY), mTransformZ(transformZ),
-            mCasterAlpha(casterAlpha), mCasterUnclipped(casterUnclipped) {
+            mCasterAlpha(casterAlpha) {
         mOutline = *casterOutline;
         if (revealClip) {
             // intersect the outline with the convex reveal clip
@@ -1572,12 +1571,11 @@
     virtual const char* name() { return "DrawShadow"; }
 
 private:
-    bool isCasterOpaque() { return mCasterAlpha >= 1.0f && mCasterUnclipped; }
+    bool isCasterOpaque() { return mCasterAlpha >= 1.0f; }
 
     const mat4 mTransformXY;
     const mat4 mTransformZ;
     const float mCasterAlpha;
-    const bool mCasterUnclipped;
     SkPath mOutline;
 };
 
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index de777f0..5e6ae3f 100755
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -1742,12 +1742,12 @@
     if (mDescription.hasRoundRectClip) {
         // TODO: avoid doing this repeatedly, stashing state pointer in program
         const RoundRectClipState* state = mSnapshot->roundRectClipState;
-        const Rect& innerRect = state->outlineInnerRect;
+        const Rect& innerRect = state->innerRect;
         glUniform4f(mCaches.currentProgram->getUniform("roundRectInnerRectLTRB"),
-                innerRect.left,  innerRect.top,
-                innerRect.right,  innerRect.bottom);
+                innerRect.left, innerRect.top,
+                innerRect.right, innerRect.bottom);
         glUniform1f(mCaches.currentProgram->getUniform("roundRectRadius"),
-                state->outlineRadius);
+                state->radius);
         glUniformMatrix4fv(mCaches.currentProgram->getUniform("roundRectInvTransform"),
                 1, GL_FALSE, &state->matrix.data[0]);
     }
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 1df2055..0662ca2 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -384,11 +384,15 @@
         handler(op, PROPERTY_SAVECOUNT, properties().getClipToBounds());
     }
 
-    if (CC_UNLIKELY(properties().hasClippingPath())) {
-        ClipPathOp* op = new (handler.allocator()) ClipPathOp(
-                properties().getClippingPath(), properties().getClippingPathOp());
-        handler(op, PROPERTY_SAVECOUNT, properties().getClipToBounds());
+    // TODO: support both reveal clip and outline clip simultaneously
+    if (mProperties.getRevealClip().willClip()) {
+        Rect bounds;
+        mProperties.getRevealClip().getBounds(&bounds);
+        renderer.setClippingRoundRect(handler.allocator(), bounds, mProperties.getRevealClip().getRadius());
+    } else if (mProperties.getOutline().willClip()) {
+        renderer.setClippingOutline(handler.allocator(), &(mProperties.getOutline()));
     }
+
 }
 
 /**
@@ -600,23 +604,11 @@
     applyViewPropertyTransforms(shadowMatrixZ, true);
 
     const SkPath* outlinePath = properties().getOutline().getPath();
-    const RevealClip& revealClip = properties().getRevealClip();
-    const SkPath* revealClipPath = revealClip.hasConvexClip()
-            ?  revealClip.getPath() : NULL; // only pass the reveal clip's path if it's convex
-
+    const SkPath* revealClipPath = properties().getRevealClip().getPath();
     if (revealClipPath && revealClipPath->isEmpty()) return;
 
-    /**
-     * The drawing area of the caster is always the same as the its perimeter (which
-     * the shadow system uses) *except* in the inverse clip case. Inform the shadow
-     * system that the caster's drawing area (as opposed to its perimeter) has been
-     * clipped, so that it knows the caster can't be opaque.
-     */
-    bool casterUnclipped = !revealClip.willClip() || revealClip.hasConvexClip();
-
     DisplayListOp* shadowOp  = new (handler.allocator()) DrawShadowOp(
-            shadowMatrixXY, shadowMatrixZ,
-            properties().getAlpha(), casterUnclipped,
+            shadowMatrixXY, shadowMatrixZ, properties().getAlpha(),
             outlinePath, revealClipPath);
     handler(shadowOp, PROPERTY_SAVECOUNT, properties().getClipToBounds());
 }
@@ -828,10 +820,6 @@
     bool quickRejected = properties().getClipToBounds()
             && renderer.quickRejectConservative(0, 0, properties().getWidth(), properties().getHeight());
     if (!quickRejected) {
-        if (mProperties.getOutline().willClip()) {
-            renderer.setClippingOutline(alloc, &(mProperties.getOutline()));
-        }
-
         if (drawLayer) {
             handler(new (alloc) DrawLayerOp(mLayer, 0, 0),
                     renderer.getSaveCount() - 1, properties().getClipToBounds());
diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h
index f50e514..9898bde 100644
--- a/libs/hwui/RenderProperties.h
+++ b/libs/hwui/RenderProperties.h
@@ -546,19 +546,6 @@
 
     void updateMatrix();
 
-    bool hasClippingPath() const {
-        return mPrimitiveFields.mRevealClip.willClip();
-    }
-
-    const SkPath* getClippingPath() const {
-        return mPrimitiveFields.mRevealClip.getPath();
-    }
-
-    SkRegion::Op getClippingPathOp() const {
-        return mPrimitiveFields.mRevealClip.isInverseClip()
-                ? SkRegion::kDifference_Op : SkRegion::kIntersect_Op;
-    }
-
     Outline& mutableOutline() {
         return mPrimitiveFields.mOutline;
     }
diff --git a/libs/hwui/RevealClip.h b/libs/hwui/RevealClip.h
index 07404cb..a9600f1 100644
--- a/libs/hwui/RevealClip.h
+++ b/libs/hwui/RevealClip.h
@@ -27,14 +27,12 @@
 public:
     RevealClip()
             : mShouldClip(false)
-            , mInverseClip(false)
             , mX(0)
             , mY(0)
             , mRadius(0) {}
 
-    void set(bool shouldClip, bool inverseClip, float x, float y, float radius) {
+    void set(bool shouldClip, float x, float y, float radius) {
         mShouldClip = shouldClip;
-        mInverseClip = inverseClip;
         mX = x;
         mY = y;
         mRadius = radius;
@@ -45,21 +43,15 @@
         }
     }
 
-    bool hasConvexClip() const {
-        return mShouldClip && !mInverseClip;
-    }
-
-    bool isInverseClip() const {
-        return mInverseClip;
-    }
-
     bool willClip() const {
         return mShouldClip;
     }
 
-    float radius() const {
-        return mRadius;
+    void getBounds(Rect* outBounds) const {
+        outBounds->set(mX - mRadius, mY - mRadius,
+                mX + mRadius, mY + mRadius);
     }
+    float getRadius() const { return mRadius; }
 
     const SkPath* getPath() const {
         if (!mShouldClip) return NULL;
@@ -69,7 +61,6 @@
 
 private:
     bool mShouldClip;
-    bool mInverseClip;
     float mX;
     float mY;
     float mRadius;
diff --git a/libs/hwui/Snapshot.cpp b/libs/hwui/Snapshot.cpp
index 80f7eca..6f19275 100644
--- a/libs/hwui/Snapshot.cpp
+++ b/libs/hwui/Snapshot.cpp
@@ -20,8 +20,6 @@
 
 #include <SkCanvas.h>
 
-#include "utils/MathUtils.h"
-
 namespace android {
 namespace uirenderer {
 
@@ -207,23 +205,22 @@
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-// Clipping outline
+// Clipping round rect
 ///////////////////////////////////////////////////////////////////////////////
 
-void Snapshot::setClippingOutline(LinearAllocator& allocator, const Outline* outline) {
-    Rect bounds;
-    float radius;
-    if (!outline->getAsRoundRect(&bounds, &radius)) return; // only RR supported
-
-    if (!MathUtils::isPositive(radius)) return; // leave clipping up to rect clipping
+void Snapshot::setClippingRoundRect(LinearAllocator& allocator, const Rect& bounds, float radius) {
+    if (bounds.isEmpty()) {
+        clipRect->setEmpty();
+        return;
+    }
 
     RoundRectClipState* state = new (allocator) RoundRectClipState;
 
     // store the inverse drawing matrix
-    Matrix4 outlineDrawingMatrix;
-    outlineDrawingMatrix.load(getOrthoMatrix());
-    outlineDrawingMatrix.multiply(*transform);
-    state->matrix.loadInverse(outlineDrawingMatrix);
+    Matrix4 roundRectDrawingMatrix;
+    roundRectDrawingMatrix.load(getOrthoMatrix());
+    roundRectDrawingMatrix.multiply(*transform);
+    state->matrix.loadInverse(roundRectDrawingMatrix);
 
     // compute area under rounded corners - only draws overlapping these rects need to be clipped
     for (int i = 0 ; i < 4; i++) {
@@ -241,9 +238,9 @@
     }
 
     // store RR area
-    bounds.inset(radius);
-    state->outlineInnerRect = bounds;
-    state->outlineRadius = radius;
+    state->innerRect = bounds;
+    state->innerRect.inset(radius);
+    state->radius = radius;
 
     // store as immutable so, for this frame, pointer uniquely identifies this bundle of shader info
     roundRectClipState = state;
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
index 5426e89..98e2440 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -57,8 +57,8 @@
 
     Matrix4 matrix;
     Rect dangerRects[4];
-    Rect outlineInnerRect;
-    float outlineRadius;
+    Rect innerRect;
+    float radius;
 };
 
 /**
@@ -164,7 +164,7 @@
     /**
      * Sets (and replaces) the current clipping outline
      */
-    void setClippingOutline(LinearAllocator& allocator, const Outline* outline);
+    void setClippingRoundRect(LinearAllocator& allocator, const Rect& bounds, float radius);
 
     /**
      * Indicates whether this snapshot should be ignored. A snapshot
diff --git a/libs/hwui/StatefulBaseRenderer.cpp b/libs/hwui/StatefulBaseRenderer.cpp
index 473005c..dc41157 100644
--- a/libs/hwui/StatefulBaseRenderer.cpp
+++ b/libs/hwui/StatefulBaseRenderer.cpp
@@ -20,6 +20,8 @@
 
 #include "StatefulBaseRenderer.h"
 
+#include "utils/MathUtils.h"
+
 namespace android {
 namespace uirenderer {
 
@@ -189,9 +191,24 @@
 }
 
 void StatefulBaseRenderer::setClippingOutline(LinearAllocator& allocator, const Outline* outline) {
-    mSnapshot->setClippingOutline(allocator, outline);
+    Rect bounds;
+    float radius;
+    if (!outline->getAsRoundRect(&bounds, &radius)) return; // only RR supported
+
+    if (!MathUtils::isPositive(radius)) {
+        // TODO: consider storing this rect separately, so that this can't be replaced with clip ops
+        clipRect(bounds.left, bounds.top, bounds.right, bounds.bottom, SkRegion::kIntersect_Op);
+        return;
+    }
+    setClippingRoundRect(allocator, bounds, radius);
 }
 
+void StatefulBaseRenderer::setClippingRoundRect(LinearAllocator& allocator,
+        const Rect& rect, float radius) {
+    mSnapshot->setClippingRoundRect(allocator, rect, radius);
+}
+
+
 ///////////////////////////////////////////////////////////////////////////////
 // Quick Rejection
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/StatefulBaseRenderer.h b/libs/hwui/StatefulBaseRenderer.h
index 25cc832..6d83b4c 100644
--- a/libs/hwui/StatefulBaseRenderer.h
+++ b/libs/hwui/StatefulBaseRenderer.h
@@ -96,6 +96,8 @@
      * The clipping outline is independent from the regular clip.
      */
     void setClippingOutline(LinearAllocator& allocator, const Outline* outline);
+    void setClippingRoundRect(LinearAllocator& allocator,
+            const Rect& rect, float radius);
 
 protected:
     const Rect& getRenderTargetClipBounds() const { return mSnapshot->getRenderTargetClip(); }