Clipping performance improvements

Create a ClipArea class to handle tracking clip regions. This class can
select the most efficient implementation depending on the types of
clipping presented.

ClipArea re-used the rectangle and region-based clipping
implementations as well as adding a "list of rotated rectangles"
approach that is more efficient for rotated views with children.

Change-Id: I2133761a2462ebc0852b394220e265974b3086f0
diff --git a/libs/hwui/CanvasState.cpp b/libs/hwui/CanvasState.cpp
index 9d2ccf1..85f860d 100644
--- a/libs/hwui/CanvasState.cpp
+++ b/libs/hwui/CanvasState.cpp
@@ -155,47 +155,18 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 bool CanvasState::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {
-    if (CC_LIKELY(currentTransform()->rectToRect())) {
-        mDirtyClip |= mSnapshot->clip(left, top, right, bottom, op);
-        return !mSnapshot->clipRect->isEmpty();
-    }
-
-    SkPath path;
-    path.addRect(left, top, right, bottom);
-
-    return CanvasState::clipPath(&path, op);
+    mDirtyClip |= mSnapshot->clip(left, top, right, bottom, op);
+    return !mSnapshot->clipIsEmpty();
 }
 
 bool CanvasState::clipPath(const SkPath* path, SkRegion::Op op) {
-    SkMatrix transform;
-    currentTransform()->copyTo(transform);
-
-    SkPath transformed;
-    path->transform(transform, &transformed);
-
-    SkRegion clip;
-    if (!mSnapshot->previous->clipRegion->isEmpty()) {
-        clip.setRegion(*mSnapshot->previous->clipRegion);
-    } else {
-        if (mSnapshot->previous == firstSnapshot()) {
-            clip.setRect(0, 0, getWidth(), getHeight());
-        } else {
-            Rect* bounds = mSnapshot->previous->clipRect;
-            clip.setRect(bounds->left, bounds->top, bounds->right, bounds->bottom);
-        }
-    }
-
-    SkRegion region;
-    region.setPath(transformed, clip);
-
-    // region is the transformed input path, masked by the previous clip
-    mDirtyClip |= mSnapshot->clipRegionTransformed(region, op);
-    return !mSnapshot->clipRect->isEmpty();
+    mDirtyClip |= mSnapshot->clipPath(*path, op);
+    return !mSnapshot->clipIsEmpty();
 }
 
 bool CanvasState::clipRegion(const SkRegion* region, SkRegion::Op op) {
     mDirtyClip |= mSnapshot->clipRegionTransformed(*region, op);
-    return !mSnapshot->clipRect->isEmpty();
+    return !mSnapshot->clipIsEmpty();
 }
 
 void CanvasState::setClippingOutline(LinearAllocator& allocator, const Outline* outline) {
@@ -245,7 +216,7 @@
     currentTransform()->mapRect(r);
     r.snapGeometryToPixelBoundaries(snapOut);
 
-    Rect clipRect(*currentClipRect());
+    Rect clipRect(currentClipRect());
     clipRect.snapToPixelBoundaries();
 
     if (!clipRect.intersects(r)) return true;
@@ -273,7 +244,7 @@
     currentTransform()->mapRect(r);
     r.roundOut(); // rounded out to be conservative
 
-    Rect clipRect(*currentClipRect());
+    Rect clipRect(currentClipRect());
     clipRect.snapToPixelBoundaries();
 
     if (!clipRect.intersects(r)) return true;