Add more canvas ops 5

Added:
--DrawImage
--DrawImageRect
--DrawImageNine
--DrawPicture
--DrawImageLattice

Test: Added tests to CanvasOpTests
Change-Id: I9997d9fadd8738aa5fef4288dbcf92864da9fe74
diff --git a/libs/hwui/tests/unit/CanvasOpTests.cpp b/libs/hwui/tests/unit/CanvasOpTests.cpp
index 60c8628..50d3cb1 100644
--- a/libs/hwui/tests/unit/CanvasOpTests.cpp
+++ b/libs/hwui/tests/unit/CanvasOpTests.cpp
@@ -22,7 +22,9 @@
 
 #include <tests/common/CallCountingCanvas.h>
 
+#include "SkPictureRecorder.h"
 #include "SkColor.h"
+#include "SkLatticeIter.h"
 #include "pipeline/skia/AnimatedDrawables.h"
 
 using namespace android;
@@ -184,7 +186,7 @@
 TEST(CanvasOp, simpleDrawPaint) {
     CanvasOpBuffer buffer;
     EXPECT_EQ(buffer.size(), 0);
-    buffer.push(CanvasOp<Op::DrawColor> {
+    buffer.push<Op::DrawColor> ({
         .color = SkColor4f{1, 1, 1, 1},
         .mode = SkBlendMode::kSrcIn
     });
@@ -199,7 +201,7 @@
 TEST(CanvasOp, simpleDrawPoint) {
     CanvasOpBuffer buffer;
     EXPECT_EQ(buffer.size(), 0);
-    buffer.push(CanvasOp<Op::DrawPoint> {
+    buffer.push<Op::DrawPoint> ({
         .x = 12,
         .y = 42,
         .paint = SkPaint{}
@@ -215,7 +217,7 @@
 TEST(CanvasOp, simpleDrawLine) {
     CanvasOpBuffer buffer;
     EXPECT_EQ(buffer.size(), 0);
-    buffer.push(CanvasOp<Op::DrawLine> {
+    buffer.push<Op::DrawLine> ({
         .startX = 16,
         .startY = 28,
         .endX = 12,
@@ -233,7 +235,7 @@
 TEST(CanvasOp, simpleDrawRect) {
     CanvasOpBuffer buffer;
     EXPECT_EQ(buffer.size(), 0);
-    buffer.push(CanvasOp<Op::DrawRect> {
+    buffer.push<Op::DrawRect> ({
         .paint = SkPaint{},
         .rect = SkRect::MakeEmpty()
     });
@@ -250,7 +252,7 @@
     EXPECT_EQ(buffer.size(), 0);
     SkRegion region;
     region.setRect(SkIRect::MakeWH(12, 50));
-    buffer.push(CanvasOp<Op::DrawRegion> {
+    buffer.push<Op::DrawRegion> ({
         .paint = SkPaint{},
         .region = region
     });
@@ -272,7 +274,7 @@
     clip.setRect(SkIRect::MakeWH(100, 100));
     SkRegion region;
     region.setPath(path, clip);
-    buffer.push(CanvasOp<Op::DrawRegion> {
+    buffer.push<Op::DrawRegion> ({
         .paint = SkPaint{},
         .region = region
     });
@@ -287,7 +289,7 @@
 TEST(CanvasOp, simpleDrawRoundRect) {
     CanvasOpBuffer buffer;
     EXPECT_EQ(buffer.size(), 0);
-    buffer.push(CanvasOp<Op::DrawRoundRect> {
+    buffer.push<Op::DrawRoundRect> ({
         .paint = SkPaint{},
         .rect = SkRect::MakeEmpty(),
         .rx = 10,
@@ -326,7 +328,7 @@
     innerPts[3].set(10, 10);
     innerRRect.setRectRadii(inner, innerPts.get());
 
-    buffer.push(CanvasOp<Op::DrawDoubleRoundRect> {
+    buffer.push<Op::DrawDoubleRoundRect> ({
         .outer = outerRRect,
         .inner = innerRRect,
         .paint = SkPaint{}
@@ -342,7 +344,7 @@
 TEST(CanvasOp, simpleDrawCircle) {
     CanvasOpBuffer buffer;
     EXPECT_EQ(buffer.size(), 0);
-    buffer.push(CanvasOp<Op::DrawCircle> {
+    buffer.push<Op::DrawCircle>({
         .cx = 5,
         .cy = 7,
         .radius = 10,
@@ -359,7 +361,7 @@
 TEST(CanvasOp, simpleDrawOval) {
     CanvasOpBuffer buffer;
     EXPECT_EQ(buffer.size(), 0);
-    buffer.push(CanvasOp<Op::DrawOval> {
+    buffer.push<Op::DrawOval> ({
         .oval = SkRect::MakeEmpty(),
         .paint = SkPaint{}
     });
@@ -374,7 +376,7 @@
 TEST(CanvasOp, simpleDrawArc) {
     CanvasOpBuffer buffer;
     EXPECT_EQ(buffer.size(), 0);
-    buffer.push(CanvasOp<Op::DrawArc> {
+    buffer.push<Op::DrawArc>({
         .oval = SkRect::MakeWH(100, 100),
         .startAngle = 120,
         .sweepAngle = 70,
@@ -394,7 +396,7 @@
     EXPECT_EQ(buffer.size(), 0);
     SkPath path;
     path.addCircle(50, 50, 30);
-    buffer.push(CanvasOp<Op::DrawPath> {
+    buffer.push<Op::DrawPath> ({
         .path = path,
         .paint = SkPaint{}
     });
@@ -419,7 +421,7 @@
     auto propertyPaint =
             sp<uirenderer::CanvasPropertyPaint>(new uirenderer::CanvasPropertyPaint(SkPaint{}));
 
-    buffer.push(CanvasOp<Op::DrawRoundRectProperty> {
+    buffer.push<Op::DrawRoundRectProperty> ({
         .left = left,
         .top = top,
         .right = right,
@@ -446,7 +448,7 @@
     auto propertyPaint =
             sp<uirenderer::CanvasPropertyPaint>(new uirenderer::CanvasPropertyPaint(SkPaint{}));
 
-    buffer.push(CanvasOp<Op::DrawCircleProperty> {
+    buffer.push<Op::DrawCircleProperty> ({
         .x = x,
         .y = y,
         .radius = radius,
@@ -468,7 +470,7 @@
     SkColor colors[3] = {SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN};
     sk_sp<SkVertices> vertices = SkVertices::MakeCopy(SkVertices::kTriangles_VertexMode, 3, pts,
             nullptr, colors);
-    buffer.push(CanvasOp<Op::DrawVertices> {
+    buffer.push<Op::DrawVertices> ({
         .vertices = vertices,
         .mode = SkBlendMode::kSrcOver,
         .paint = SkPaint{}
@@ -481,6 +483,110 @@
     EXPECT_EQ(1, canvas.sumTotalDrawCalls());
 }
 
+TEST(CanvasOp, simpleDrawImage) {
+    CanvasOpBuffer buffer;
+    EXPECT_EQ(buffer.size(), 0);
+
+    SkImageInfo info =SkImageInfo::Make(5, 1,
+        kGray_8_SkColorType, kOpaque_SkAlphaType);
+    sk_sp<Bitmap> bitmap = Bitmap::allocateHeapBitmap(info);
+    buffer.push<Op::DrawImage> ({
+            bitmap,
+            7,
+            19,
+            SkPaint{}
+        }
+    );
+
+    CallCountingCanvas canvas;
+    EXPECT_EQ(0, canvas.sumTotalDrawCalls());
+    rasterizeCanvasBuffer(buffer, &canvas);
+    EXPECT_EQ(1, canvas.drawImageCount);
+    EXPECT_EQ(1, canvas.sumTotalDrawCalls());
+}
+
+TEST(CanvasOp, simpleDrawImageRect) {
+    CanvasOpBuffer buffer;
+    EXPECT_EQ(buffer.size(), 0);
+
+    SkImageInfo info = SkImageInfo::Make(5, 1,
+        kGray_8_SkColorType, kOpaque_SkAlphaType);
+
+    sk_sp<Bitmap> bitmap = Bitmap::allocateHeapBitmap(info);
+    buffer.push<Op::DrawImageRect> ({
+          bitmap, SkRect::MakeWH(100, 100),
+          SkRect::MakeLTRB(120, 110, 220, 210),
+          SkPaint{}
+        }
+    );
+
+    CallCountingCanvas canvas;
+    EXPECT_EQ(0, canvas.sumTotalDrawCalls());
+    rasterizeCanvasBuffer(buffer, &canvas);
+    EXPECT_EQ(1, canvas.drawImageRectCount);
+    EXPECT_EQ(1, canvas.sumTotalDrawCalls());
+}
+
+TEST(CanvasOp, simpleDrawImageLattice) {
+    CanvasOpBuffer buffer;
+    EXPECT_EQ(buffer.size(), 0);
+
+    SkBitmap skBitmap;
+    skBitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
+
+    const int xDivs[] = { 20, 50 };
+    const int yDivs[] = { 10, 40 };
+    SkCanvas::Lattice::RectType fillTypes[3][3];
+    memset(fillTypes, 0, sizeof(fillTypes));
+    fillTypes[1][1] = SkCanvas::Lattice::kTransparent;
+    SkColor colors[9];
+    SkCanvas::Lattice lattice = { xDivs, yDivs, fillTypes[0], 2,
+         2, nullptr, colors };
+    sk_sp<Bitmap> bitmap = Bitmap::allocateHeapBitmap(&skBitmap);
+    buffer.push<Op::DrawImageLattice>(
+        {
+            bitmap,
+            SkRect::MakeWH(5, 1),
+            lattice,
+            SkPaint{}
+        }
+    );
+
+    CallCountingCanvas canvas;
+    EXPECT_EQ(0, canvas.sumTotalDrawCalls());
+    rasterizeCanvasBuffer(buffer, &canvas);
+    EXPECT_EQ(1, canvas.drawImageLatticeCount);
+    EXPECT_EQ(1, canvas.sumTotalDrawCalls());
+}
+
+TEST(CanvasOp, simpleDrawPicture) {
+    CanvasOpBuffer buffer;
+    EXPECT_EQ(buffer.size(), 0);
+
+    SkPictureRecorder recorder;
+    SkCanvas* pictureCanvas = recorder.beginRecording({64, 64, 192, 192});
+    SkPaint paint;
+    pictureCanvas->drawRect(SkRect::MakeWH(200, 200), paint);
+    paint.setColor(SK_ColorWHITE);
+    pictureCanvas->drawRect(SkRect::MakeLTRB(20, 20, 180, 180), paint);
+    sk_sp<SkPicture> picture = recorder.finishRecordingAsPicture();
+    buffer.push<Op::DrawPicture> ({
+        .picture = picture
+    });
+
+    CallCountingCanvas canvas;
+    EXPECT_EQ(0, canvas.sumTotalDrawCalls());
+    rasterizeCanvasBuffer(buffer, &canvas);
+    // Note because we are explicitly issuing 2 drawRect calls
+    // in the picture recorder above, when it is played back into
+    // CallCountingCanvas we will see 2 calls to drawRect instead of 1
+    // call to drawPicture.
+    // This is because SkiaCanvas::drawPicture uses picture.playback(canvas)
+    // instead of canvas->drawPicture.
+    EXPECT_EQ(2, canvas.drawRectCount);
+    EXPECT_EQ(2, canvas.sumTotalDrawCalls());
+}
+
 TEST(CanvasOp, immediateRendering) {
     auto canvas = std::make_shared<CallCountingCanvas>();