Add SkiaCanvas::captureCanvasState()

Test: Verified bug is fixed.  Wrote unit test.

Bug: 37268771

Change-Id: I9deb7db353cd2129ad245e7f65419670463bb717
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index c902a73..ece0b47 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -23,6 +23,7 @@
 #include "hwui/MinikinUtils.h"
 #include "pipeline/skia/AnimatedDrawables.h"
 
+#include <SkCanvasStateUtils.h>
 #include <SkColorSpaceXformCanvas.h>
 #include <SkDrawable.h>
 #include <SkDeque.h>
@@ -411,6 +412,30 @@
 }
 
 // ----------------------------------------------------------------------------
+// Canvas state operations: Capture
+// ----------------------------------------------------------------------------
+
+SkCanvasState* SkiaCanvas::captureCanvasState() const {
+    SkCanvas* canvas = mCanvas;
+    if (mCanvasOwned) {
+        // Important to use the underlying SkCanvas, not the wrapper.
+        canvas = mCanvasOwned.get();
+    }
+
+    // Workarounds for http://crbug.com/271096: SW draw only supports
+    // translate & scale transforms, and a simple rectangular clip.
+    // (This also avoids significant wasted time in calling
+    // SkCanvasStateUtils::CaptureCanvasState when the clip is complex).
+    if (!canvas->isClipRect() ||
+        (canvas->getTotalMatrix().getType() &
+                  ~(SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask))) {
+      return nullptr;
+    }
+
+    return SkCanvasStateUtils::CaptureCanvasState(canvas);
+}
+
+// ----------------------------------------------------------------------------
 // Canvas draw operations
 // ----------------------------------------------------------------------------