1b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik/*
2b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * Copyright (C) 2015 The Android Open Source Project
3b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik *
4b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * Licensed under the Apache License, Version 2.0 (the "License");
5b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * you may not use this file except in compliance with the License.
6b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * You may obtain a copy of the License at
7b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik *
8b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik *      http://www.apache.org/licenses/LICENSE-2.0
9b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik *
10b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * Unless required by applicable law or agreed to in writing, software
11b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * distributed under the License is distributed on an "AS IS" BASIS,
12b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * See the License for the specific language governing permissions and
14b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * limitations under the License.
15b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik */
16b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
17b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <gtest/gtest.h>
18b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
19aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik#include <DeferredLayerUpdater.h>
20b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <RecordedOp.h>
21b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <RecordingCanvas.h>
22dccca44ffda4836b56a21da95a046c9708ffd49csergeyv#include <hwui/Paint.h>
23dccca44ffda4836b56a21da95a046c9708ffd49csergeyv#include <minikin/Layout.h>
248160f20b0aca8c6595d4b385d673f59b6bcd16a4Chris Craik#include <tests/common/TestUtils.h>
251713c7773cea83a9c1ba7e08c73434df33ca6f4bChris Craik#include <utils/Color.h>
26b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
27734f146c1ebf43816d5a3c8e82c726ab09489cb9Chris Craik#include <SkGradientShader.h>
28734f146c1ebf43816d5a3c8e82c726ab09489cb9Chris Craik#include <SkShader.h>
29734f146c1ebf43816d5a3c8e82c726ab09489cb9Chris Craik
30b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craiknamespace android {
31b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craiknamespace uirenderer {
32b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
33b36af87f8275f4b982906f88193ec27600f2746aChris Craikstatic void playbackOps(const DisplayList& displayList,
346fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        std::function<void(const RecordedOp&)> opReceiver) {
35161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik    for (auto& chunk : displayList.getChunks()) {
36b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        for (size_t opIndex = chunk.beginOpIndex; opIndex < chunk.endOpIndex; opIndex++) {
37b36af87f8275f4b982906f88193ec27600f2746aChris Craik            RecordedOp* op = displayList.getOps()[opIndex];
386fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik            opReceiver(*op);
39b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        }
40b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
41b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
42b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
43aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craikstatic void validateSingleOp(std::unique_ptr<DisplayList>& dl,
44aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik        std::function<void(const RecordedOp& op)> opValidator) {
45aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik    ASSERT_EQ(1u, dl->getOps().size()) << "Must be exactly one op";
46aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik    opValidator(*(dl->getOps()[0]));
47aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik}
48aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik
49b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris CraikTEST(RecordingCanvas, emptyPlayback) {
50b36af87f8275f4b982906f88193ec27600f2746aChris Craik    auto dl = TestUtils::createDisplayList<RecordingCanvas>(100, 200, [](RecordingCanvas& canvas) {
51eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.save(SaveFlags::MatrixClip);
52b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        canvas.restore();
53b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    });
54818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik    playbackOps(*dl, [](const RecordedOp& op) { ADD_FAILURE(); });
55b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
56b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
57e4db79de127cfe961195f52907af8451026eaa20Chris CraikTEST(RecordingCanvas, clipRect) {
58e4db79de127cfe961195f52907af8451026eaa20Chris Craik    auto dl = TestUtils::createDisplayList<RecordingCanvas>(100, 100, [](RecordingCanvas& canvas) {
59eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.save(SaveFlags::MatrixClip);
60e4db79de127cfe961195f52907af8451026eaa20Chris Craik        canvas.clipRect(0, 0, 100, 100, SkRegion::kIntersect_Op);
61e4db79de127cfe961195f52907af8451026eaa20Chris Craik        canvas.drawRect(0, 0, 50, 50, SkPaint());
62e4db79de127cfe961195f52907af8451026eaa20Chris Craik        canvas.drawRect(50, 50, 100, 100, SkPaint());
63e4db79de127cfe961195f52907af8451026eaa20Chris Craik        canvas.restore();
64e4db79de127cfe961195f52907af8451026eaa20Chris Craik    });
65e4db79de127cfe961195f52907af8451026eaa20Chris Craik
66e4db79de127cfe961195f52907af8451026eaa20Chris Craik    ASSERT_EQ(2u, dl->getOps().size()) << "Must be exactly two ops";
67e4db79de127cfe961195f52907af8451026eaa20Chris Craik    EXPECT_CLIP_RECT(Rect(100, 100), dl->getOps()[0]->localClip);
68e4db79de127cfe961195f52907af8451026eaa20Chris Craik    EXPECT_CLIP_RECT(Rect(100, 100), dl->getOps()[1]->localClip);
69e4db79de127cfe961195f52907af8451026eaa20Chris Craik    EXPECT_EQ(dl->getOps()[0]->localClip, dl->getOps()[1]->localClip)
70e4db79de127cfe961195f52907af8451026eaa20Chris Craik            << "Clip should be serialized once";
71e4db79de127cfe961195f52907af8451026eaa20Chris Craik}
72e4db79de127cfe961195f52907af8451026eaa20Chris Craik
73261725fdb2962271c222a049fcdf57bbdc8363c7Chris CraikTEST(RecordingCanvas, emptyClipRect) {
74261725fdb2962271c222a049fcdf57bbdc8363c7Chris Craik    auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
75261725fdb2962271c222a049fcdf57bbdc8363c7Chris Craik        canvas.save(SaveFlags::MatrixClip);
76261725fdb2962271c222a049fcdf57bbdc8363c7Chris Craik        canvas.clipRect(0, 0, 100, 100, SkRegion::kIntersect_Op);
77261725fdb2962271c222a049fcdf57bbdc8363c7Chris Craik        canvas.clipRect(100, 100, 200, 200, SkRegion::kIntersect_Op);
78261725fdb2962271c222a049fcdf57bbdc8363c7Chris Craik        canvas.drawRect(0, 0, 50, 50, SkPaint()); // rejected at record time
79261725fdb2962271c222a049fcdf57bbdc8363c7Chris Craik        canvas.restore();
80261725fdb2962271c222a049fcdf57bbdc8363c7Chris Craik    });
81261725fdb2962271c222a049fcdf57bbdc8363c7Chris Craik    ASSERT_EQ(0u, dl->getOps().size()) << "Must be zero ops. Rect should be rejected.";
82261725fdb2962271c222a049fcdf57bbdc8363c7Chris Craik}
83261725fdb2962271c222a049fcdf57bbdc8363c7Chris Craik
84caa24184735a607e87077c73262a42acdea7b8fbChris CraikTEST(RecordingCanvas, drawArc) {
85caa24184735a607e87077c73262a42acdea7b8fbChris Craik    auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
86caa24184735a607e87077c73262a42acdea7b8fbChris Craik        canvas.drawArc(0, 0, 200, 200, 0, 180, true, SkPaint());
87caa24184735a607e87077c73262a42acdea7b8fbChris Craik        canvas.drawArc(0, 0, 100, 100, 0, 360, true, SkPaint());
88caa24184735a607e87077c73262a42acdea7b8fbChris Craik    });
89caa24184735a607e87077c73262a42acdea7b8fbChris Craik
90caa24184735a607e87077c73262a42acdea7b8fbChris Craik    auto&& ops = dl->getOps();
91caa24184735a607e87077c73262a42acdea7b8fbChris Craik    ASSERT_EQ(2u, ops.size()) << "Must be exactly two ops";
92caa24184735a607e87077c73262a42acdea7b8fbChris Craik    EXPECT_EQ(RecordedOpId::ArcOp, ops[0]->opId);
93caa24184735a607e87077c73262a42acdea7b8fbChris Craik    EXPECT_EQ(Rect(200, 200), ops[0]->unmappedBounds);
94caa24184735a607e87077c73262a42acdea7b8fbChris Craik
95caa24184735a607e87077c73262a42acdea7b8fbChris Craik    EXPECT_EQ(RecordedOpId::OvalOp, ops[1]->opId)
96caa24184735a607e87077c73262a42acdea7b8fbChris Craik            << "Circular arcs should be converted to ovals";
97caa24184735a607e87077c73262a42acdea7b8fbChris Craik    EXPECT_EQ(Rect(100, 100), ops[1]->unmappedBounds);
98caa24184735a607e87077c73262a42acdea7b8fbChris Craik}
99caa24184735a607e87077c73262a42acdea7b8fbChris Craik
100a1717271caac5e8ea3808c331d4141ac01a42134Chris CraikTEST(RecordingCanvas, drawLines) {
101a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    auto dl = TestUtils::createDisplayList<RecordingCanvas>(100, 200, [](RecordingCanvas& canvas) {
102a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        SkPaint paint;
103386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik        paint.setStrokeWidth(20); // doesn't affect recorded bounds - would be resolved at bake time
104a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        float points[] = { 0, 0, 20, 10, 30, 40, 90 }; // NB: only 1 valid line
105a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        canvas.drawLines(&points[0], 7, paint);
106a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    });
107a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik
108a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    ASSERT_EQ(1u, dl->getOps().size()) << "Must be exactly one op";
109a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    auto op = dl->getOps()[0];
110a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    ASSERT_EQ(RecordedOpId::LinesOp, op->opId);
111a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    EXPECT_EQ(4, ((LinesOp*)op)->floatCount)
112a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik            << "float count must be rounded down to closest multiple of 4";
1135430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik    EXPECT_EQ(Rect(20, 10), op->unmappedBounds)
114386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik            << "unmapped bounds must be size of line, and not outset for stroke width";
115a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik}
116a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik
117a1717271caac5e8ea3808c331d4141ac01a42134Chris CraikTEST(RecordingCanvas, drawRect) {
118b36af87f8275f4b982906f88193ec27600f2746aChris Craik    auto dl = TestUtils::createDisplayList<RecordingCanvas>(100, 200, [](RecordingCanvas& canvas) {
119b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        canvas.drawRect(10, 20, 90, 180, SkPaint());
120b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    });
121b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
122a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    ASSERT_EQ(1u, dl->getOps().size()) << "Must be exactly one op";
123a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    auto op = *(dl->getOps()[0]);
124a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    ASSERT_EQ(RecordedOpId::RectOp, op.opId);
125e4db79de127cfe961195f52907af8451026eaa20Chris Craik    EXPECT_EQ(nullptr, op.localClip);
126a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    EXPECT_EQ(Rect(10, 20, 90, 180), op.unmappedBounds);
127a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik}
128a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik
1292dbb4c46ee648c64bb977b6839374d73b5a605d9Chris CraikTEST(RecordingCanvas, drawRoundRect) {
1302dbb4c46ee648c64bb977b6839374d73b5a605d9Chris Craik    // Round case - stays rounded
1312dbb4c46ee648c64bb977b6839374d73b5a605d9Chris Craik    auto dl = TestUtils::createDisplayList<RecordingCanvas>(100, 200, [](RecordingCanvas& canvas) {
1322dbb4c46ee648c64bb977b6839374d73b5a605d9Chris Craik        canvas.drawRoundRect(0, 0, 100, 100, 10, 10, SkPaint());
1332dbb4c46ee648c64bb977b6839374d73b5a605d9Chris Craik    });
1342dbb4c46ee648c64bb977b6839374d73b5a605d9Chris Craik    ASSERT_EQ(1u, dl->getOps().size()) << "Must be exactly one op";
1352dbb4c46ee648c64bb977b6839374d73b5a605d9Chris Craik    ASSERT_EQ(RecordedOpId::RoundRectOp, dl->getOps()[0]->opId);
1362dbb4c46ee648c64bb977b6839374d73b5a605d9Chris Craik
1372dbb4c46ee648c64bb977b6839374d73b5a605d9Chris Craik    // Non-rounded case - turned into drawRect
1382dbb4c46ee648c64bb977b6839374d73b5a605d9Chris Craik    dl = TestUtils::createDisplayList<RecordingCanvas>(100, 200, [](RecordingCanvas& canvas) {
1392dbb4c46ee648c64bb977b6839374d73b5a605d9Chris Craik        canvas.drawRoundRect(0, 0, 100, 100, 0, -1, SkPaint());
1402dbb4c46ee648c64bb977b6839374d73b5a605d9Chris Craik    });
1412dbb4c46ee648c64bb977b6839374d73b5a605d9Chris Craik    ASSERT_EQ(1u, dl->getOps().size()) << "Must be exactly one op";
1422dbb4c46ee648c64bb977b6839374d73b5a605d9Chris Craik    ASSERT_EQ(RecordedOpId::RectOp, dl->getOps()[0]->opId)
1432dbb4c46ee648c64bb977b6839374d73b5a605d9Chris Craik        << "Non-rounded rects should be converted";
1442dbb4c46ee648c64bb977b6839374d73b5a605d9Chris Craik}
1452dbb4c46ee648c64bb977b6839374d73b5a605d9Chris Craik
146dccca44ffda4836b56a21da95a046c9708ffd49csergeyvTEST(RecordingCanvas, drawGlyphs) {
147a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
148a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        SkPaint paint;
149a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        paint.setAntiAlias(true);
150a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        paint.setTextSize(20);
15142a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
152dccca44ffda4836b56a21da95a046c9708ffd49csergeyv        TestUtils::drawUtf8ToCanvas(&canvas, "test text", paint, 25, 25);
153a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    });
154a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik
155b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    int count = 0;
156b36af87f8275f4b982906f88193ec27600f2746aChris Craik    playbackOps(*dl, [&count](const RecordedOp& op) {
157b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        count++;
158a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        ASSERT_EQ(RecordedOpId::TextOp, op.opId);
159e4db79de127cfe961195f52907af8451026eaa20Chris Craik        EXPECT_EQ(nullptr, op.localClip);
160a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        EXPECT_TRUE(op.localMatrix.isIdentity());
161a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        EXPECT_TRUE(op.unmappedBounds.contains(25, 15, 50, 25))
162a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik                << "Op expected to be 25+ pixels wide, 10+ pixels tall";
163b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    });
164a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik    ASSERT_EQ(1, count);
165b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
166b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
167dccca44ffda4836b56a21da95a046c9708ffd49csergeyvTEST(RecordingCanvas, drawGlyphs_strikeThruAndUnderline) {
168a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
169a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        SkPaint paint;
170a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        paint.setAntiAlias(true);
171a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        paint.setTextSize(20);
17242a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
173a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        for (int i = 0; i < 2; i++) {
174a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik            for (int j = 0; j < 2; j++) {
175a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik                paint.setUnderlineText(i != 0);
176a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik                paint.setStrikeThruText(j != 0);
177dccca44ffda4836b56a21da95a046c9708ffd49csergeyv                TestUtils::drawUtf8ToCanvas(&canvas, "test text", paint, 25, 25);
178a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik            }
179a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        }
180a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    });
181a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik
182a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    auto ops = dl->getOps();
183a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    ASSERT_EQ(8u, ops.size());
184a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik
185a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    int index = 0;
186a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    EXPECT_EQ(RecordedOpId::TextOp, ops[index++]->opId); // no underline or strikethrough
187a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik
188a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    EXPECT_EQ(RecordedOpId::TextOp, ops[index++]->opId);
189a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    EXPECT_EQ(RecordedOpId::RectOp, ops[index++]->opId); // strikethrough only
190a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik
191a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    EXPECT_EQ(RecordedOpId::TextOp, ops[index++]->opId);
192a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    EXPECT_EQ(RecordedOpId::RectOp, ops[index++]->opId); // underline only
193a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik
194a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    EXPECT_EQ(RecordedOpId::TextOp, ops[index++]->opId);
195a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    EXPECT_EQ(RecordedOpId::RectOp, ops[index++]->opId); // underline
196a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    EXPECT_EQ(RecordedOpId::RectOp, ops[index++]->opId); // strikethrough
197a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik}
198a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik
199dccca44ffda4836b56a21da95a046c9708ffd49csergeyvTEST(RecordingCanvas, drawGlyphs_forceAlignLeft) {
200a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
201a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        SkPaint paint;
202a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        paint.setAntiAlias(true);
203a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        paint.setTextSize(20);
20442a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
205a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        paint.setTextAlign(SkPaint::kLeft_Align);
206dccca44ffda4836b56a21da95a046c9708ffd49csergeyv        TestUtils::drawUtf8ToCanvas(&canvas, "test text", paint, 25, 25);
207a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        paint.setTextAlign(SkPaint::kCenter_Align);
208dccca44ffda4836b56a21da95a046c9708ffd49csergeyv        TestUtils::drawUtf8ToCanvas(&canvas, "test text", paint, 25, 25);
209a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        paint.setTextAlign(SkPaint::kRight_Align);
210dccca44ffda4836b56a21da95a046c9708ffd49csergeyv        TestUtils::drawUtf8ToCanvas(&canvas, "test text", paint, 25, 25);
211a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    });
212a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik
213a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    int count = 0;
21442a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik    float lastX = FLT_MAX;
21542a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik    playbackOps(*dl, [&count, &lastX](const RecordedOp& op) {
216a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        count++;
217a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        ASSERT_EQ(RecordedOpId::TextOp, op.opId);
218a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        EXPECT_EQ(SkPaint::kLeft_Align, op.paint->getTextAlign())
219a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik                << "recorded drawText commands must force kLeft_Align on their paint";
22042a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik
22142a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        // verify TestUtils alignment offsetting (TODO: move asserts to Canvas base class)
22242a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        EXPECT_GT(lastX, ((const TextOp&)op).x)
22342a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik                << "x coordinate should reduce across each of the draw commands, from alignment";
22442a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        lastX = ((const TextOp&)op).x;
225a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    });
226a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    ASSERT_EQ(3, count);
227a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik}
228a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik
2291713c7773cea83a9c1ba7e08c73434df33ca6f4bChris CraikTEST(RecordingCanvas, drawColor) {
2301713c7773cea83a9c1ba7e08c73434df33ca6f4bChris Craik    auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
2311713c7773cea83a9c1ba7e08c73434df33ca6f4bChris Craik        canvas.drawColor(Color::Black, SkXfermode::kSrcOver_Mode);
2321713c7773cea83a9c1ba7e08c73434df33ca6f4bChris Craik    });
2331713c7773cea83a9c1ba7e08c73434df33ca6f4bChris Craik
2341713c7773cea83a9c1ba7e08c73434df33ca6f4bChris Craik    ASSERT_EQ(1u, dl->getOps().size()) << "Must be exactly one op";
2351713c7773cea83a9c1ba7e08c73434df33ca6f4bChris Craik    auto op = *(dl->getOps()[0]);
236a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik    EXPECT_EQ(RecordedOpId::ColorOp, op.opId);
2371713c7773cea83a9c1ba7e08c73434df33ca6f4bChris Craik    EXPECT_EQ(nullptr, op.localClip);
238a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik    EXPECT_TRUE(op.unmappedBounds.isEmpty()) << "Expect undefined recorded bounds";
2391713c7773cea83a9c1ba7e08c73434df33ca6f4bChris Craik}
2401713c7773cea83a9c1ba7e08c73434df33ca6f4bChris Craik
241b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris CraikTEST(RecordingCanvas, backgroundAndImage) {
242b36af87f8275f4b982906f88193ec27600f2746aChris Craik    auto dl = TestUtils::createDisplayList<RecordingCanvas>(100, 200, [](RecordingCanvas& canvas) {
243b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        SkBitmap bitmap;
244b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        bitmap.setInfo(SkImageInfo::MakeUnknown(25, 25));
245b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        SkPaint paint;
246b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        paint.setColor(SK_ColorBLUE);
247b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
248eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.save(SaveFlags::MatrixClip);
249b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        {
250b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            // a background!
251eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita            canvas.save(SaveFlags::MatrixClip);
252b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            canvas.drawRect(0, 0, 100, 200, paint);
253b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            canvas.restore();
254b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        }
255b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        {
256b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            // an image!
257eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita            canvas.save(SaveFlags::MatrixClip);
258b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            canvas.translate(25, 25);
259b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            canvas.scale(2, 2);
260b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            canvas.drawBitmap(bitmap, 0, 0, nullptr);
261b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            canvas.restore();
262b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        }
263b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        canvas.restore();
264b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    });
265b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
266b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    int count = 0;
267b36af87f8275f4b982906f88193ec27600f2746aChris Craik    playbackOps(*dl, [&count](const RecordedOp& op) {
268b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        if (count == 0) {
269b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            ASSERT_EQ(RecordedOpId::RectOp, op.opId);
270b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            ASSERT_NE(nullptr, op.paint);
271b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            EXPECT_EQ(SK_ColorBLUE, op.paint->getColor());
2725430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik            EXPECT_EQ(Rect(100, 200), op.unmappedBounds);
273e4db79de127cfe961195f52907af8451026eaa20Chris Craik            EXPECT_EQ(nullptr, op.localClip);
274b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
275b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            Matrix4 expectedMatrix;
276b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            expectedMatrix.loadIdentity();
277b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            EXPECT_MATRIX_APPROX_EQ(expectedMatrix, op.localMatrix);
278b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        } else {
279b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            ASSERT_EQ(RecordedOpId::BitmapOp, op.opId);
280b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            EXPECT_EQ(nullptr, op.paint);
2815430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik            EXPECT_EQ(Rect(25, 25), op.unmappedBounds);
282e4db79de127cfe961195f52907af8451026eaa20Chris Craik            EXPECT_EQ(nullptr, op.localClip);
283b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
284b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            Matrix4 expectedMatrix;
285b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            expectedMatrix.loadTranslate(25, 25, 0);
286b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            expectedMatrix.scale(2, 2, 1);
287b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            EXPECT_MATRIX_APPROX_EQ(expectedMatrix, op.localMatrix);
288b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        }
289b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        count++;
290b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    });
291a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik    ASSERT_EQ(2, count);
292b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
293b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
294aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris CraikRENDERTHREAD_TEST(RecordingCanvas, textureLayer) {
295aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik    auto layerUpdater = TestUtils::createTextureLayerUpdater(renderThread, 100, 100,
296aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik            SkMatrix::MakeTrans(5, 5));
297aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik
298aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik    auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200,
299aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik            [&layerUpdater](RecordingCanvas& canvas) {
300aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik        canvas.drawLayer(layerUpdater.get());
301aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik    });
302aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik
303aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik    validateSingleOp(dl, [] (const RecordedOp& op) {
304aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik        ASSERT_EQ(RecordedOpId::TextureLayerOp, op.opId);
305aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik        ASSERT_TRUE(op.localMatrix.isIdentity()) << "Op must not apply matrix at record time.";
306aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik    });
307aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik}
308aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik
309a1717271caac5e8ea3808c331d4141ac01a42134Chris CraikTEST(RecordingCanvas, saveLayer_simple) {
3106fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
311eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.saveLayerAlpha(10, 20, 190, 180, 128, SaveFlags::ClipToLayer);
3126fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        canvas.drawRect(10, 20, 190, 180, SkPaint());
3136fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        canvas.restore();
3146fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    });
3156fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    int count = 0;
3166fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    playbackOps(*dl, [&count](const RecordedOp& op) {
3176fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        Matrix4 expectedMatrix;
3186fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        switch(count++) {
3196fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        case 0:
3206fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik            EXPECT_EQ(RecordedOpId::BeginLayerOp, op.opId);
321a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik            EXPECT_EQ(Rect(10, 20, 190, 180), op.unmappedBounds);
322e4db79de127cfe961195f52907af8451026eaa20Chris Craik            EXPECT_EQ(nullptr, op.localClip);
323a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik            EXPECT_TRUE(op.localMatrix.isIdentity());
3246fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik            break;
3256fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        case 1:
3266fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik            EXPECT_EQ(RecordedOpId::RectOp, op.opId);
327e4db79de127cfe961195f52907af8451026eaa20Chris Craik            EXPECT_CLIP_RECT(Rect(180, 160), op.localClip);
3286fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik            EXPECT_EQ(Rect(10, 20, 190, 180), op.unmappedBounds);
3296fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik            expectedMatrix.loadTranslate(-10, -20, 0);
3306fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik            EXPECT_MATRIX_APPROX_EQ(expectedMatrix, op.localMatrix);
3316fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik            break;
3326fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        case 2:
3336fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik            EXPECT_EQ(RecordedOpId::EndLayerOp, op.opId);
334a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik            // Don't bother asserting recording state data - it's not used
3356fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik            break;
3366fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        default:
337818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik            ADD_FAILURE();
3386fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        }
3396fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    });
3406fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    EXPECT_EQ(3, count);
341b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
3426fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
343b87eadda1818034ce03d85f30388384d1ac65916Chris CraikTEST(RecordingCanvas, saveLayer_missingRestore) {
344b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
345eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.saveLayerAlpha(0, 0, 200, 200, 128, SaveFlags::ClipToLayer);
346b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        canvas.drawRect(0, 0, 200, 200, SkPaint());
347b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        // Note: restore omitted, shouldn't result in unmatched save
348b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    });
349b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    int count = 0;
350b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    playbackOps(*dl, [&count](const RecordedOp& op) {
351b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        if (count++ == 2) {
352b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(RecordedOpId::EndLayerOp, op.opId);
353b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        }
354b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    });
355b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    EXPECT_EQ(3, count) << "Missing a restore shouldn't result in an unmatched saveLayer";
356b87eadda1818034ce03d85f30388384d1ac65916Chris Craik}
357b87eadda1818034ce03d85f30388384d1ac65916Chris Craik
358b87eadda1818034ce03d85f30388384d1ac65916Chris CraikTEST(RecordingCanvas, saveLayer_simpleUnclipped) {
359b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
360eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.saveLayerAlpha(10, 20, 190, 180, 128, (SaveFlags::Flags)0); // unclipped
361b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        canvas.drawRect(10, 20, 190, 180, SkPaint());
362b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        canvas.restore();
363b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    });
364b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    int count = 0;
365b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    playbackOps(*dl, [&count](const RecordedOp& op) {
366b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        switch(count++) {
367b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        case 0:
368b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(RecordedOpId::BeginUnclippedLayerOp, op.opId);
369b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(Rect(10, 20, 190, 180), op.unmappedBounds);
370b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(nullptr, op.localClip);
371b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_TRUE(op.localMatrix.isIdentity());
372b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            break;
373b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        case 1:
374b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(RecordedOpId::RectOp, op.opId);
375b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(nullptr, op.localClip);
376b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(Rect(10, 20, 190, 180), op.unmappedBounds);
377b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_TRUE(op.localMatrix.isIdentity());
378b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            break;
379b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        case 2:
380b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(RecordedOpId::EndUnclippedLayerOp, op.opId);
381b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            // Don't bother asserting recording state data - it's not used
382b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            break;
383b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        default:
384b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            ADD_FAILURE();
385b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        }
386b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    });
387b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    EXPECT_EQ(3, count);
388b87eadda1818034ce03d85f30388384d1ac65916Chris Craik}
389b87eadda1818034ce03d85f30388384d1ac65916Chris Craik
390b87eadda1818034ce03d85f30388384d1ac65916Chris CraikTEST(RecordingCanvas, saveLayer_addClipFlag) {
391b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
392eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.save(SaveFlags::MatrixClip);
393b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        canvas.clipRect(10, 20, 190, 180, SkRegion::kIntersect_Op);
394eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.saveLayerAlpha(10, 20, 190, 180, 128, (SaveFlags::Flags)0); // unclipped
395b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        canvas.drawRect(10, 20, 190, 180, SkPaint());
396b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        canvas.restore();
397b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        canvas.restore();
398b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    });
399b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    int count = 0;
400b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    playbackOps(*dl, [&count](const RecordedOp& op) {
401b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        if (count++ == 0) {
402b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(RecordedOpId::BeginLayerOp, op.opId)
403b87eadda1818034ce03d85f30388384d1ac65916Chris Craik                    << "Clip + unclipped saveLayer should result in a clipped layer";
404b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        }
405b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    });
406b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    EXPECT_EQ(3, count);
407b87eadda1818034ce03d85f30388384d1ac65916Chris Craik}
408b87eadda1818034ce03d85f30388384d1ac65916Chris Craik
409a1717271caac5e8ea3808c331d4141ac01a42134Chris CraikTEST(RecordingCanvas, saveLayer_viewportCrop) {
4106fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
4116fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        // shouldn't matter, since saveLayer will clip to its bounds
4126fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        canvas.clipRect(-1000, -1000, 1000, 1000, SkRegion::kReplace_Op);
4136fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
414eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.saveLayerAlpha(100, 100, 300, 300, 128, SaveFlags::ClipToLayer);
4156fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        canvas.drawRect(0, 0, 400, 400, SkPaint());
4166fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        canvas.restore();
4176fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    });
4186fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    int count = 0;
4196fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    playbackOps(*dl, [&count](const RecordedOp& op) {
4206fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        if (count++ == 1) {
4216fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik            Matrix4 expectedMatrix;
4226fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik            EXPECT_EQ(RecordedOpId::RectOp, op.opId);
423e4db79de127cfe961195f52907af8451026eaa20Chris Craik            EXPECT_CLIP_RECT(Rect(100, 100), op.localClip) // Recorded clip rect should be
424e4db79de127cfe961195f52907af8451026eaa20Chris Craik            // intersection of viewport and saveLayer bounds, in layer space;
4255430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik            EXPECT_EQ(Rect(400, 400), op.unmappedBounds);
4266fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik            expectedMatrix.loadTranslate(-100, -100, 0);
4276fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik            EXPECT_MATRIX_APPROX_EQ(expectedMatrix, op.localMatrix);
4286fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        }
4296fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    });
4306fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    EXPECT_EQ(3, count);
431b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
4326fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
433a1717271caac5e8ea3808c331d4141ac01a42134Chris CraikTEST(RecordingCanvas, saveLayer_rotateUnclipped) {
4346fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
435eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.save(SaveFlags::MatrixClip);
4366fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        canvas.translate(100, 100);
4376fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        canvas.rotate(45);
4386fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        canvas.translate(-50, -50);
4396fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
440eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.saveLayerAlpha(0, 0, 100, 100, 128, SaveFlags::ClipToLayer);
4416fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        canvas.drawRect(0, 0, 100, 100, SkPaint());
4426fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        canvas.restore();
4436fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
4446fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        canvas.restore();
4456fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    });
4466fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    int count = 0;
4476fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    playbackOps(*dl, [&count](const RecordedOp& op) {
4486fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        if (count++ == 1) {
4496fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik            EXPECT_EQ(RecordedOpId::RectOp, op.opId);
450e4db79de127cfe961195f52907af8451026eaa20Chris Craik            EXPECT_CLIP_RECT(Rect(100, 100), op.localClip);
4515430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik            EXPECT_EQ(Rect(100, 100), op.unmappedBounds);
452a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik            EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), op.localMatrix)
453a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik                    << "Recorded op shouldn't see any canvas transform before the saveLayer";
4546fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        }
4556fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    });
4566fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    EXPECT_EQ(3, count);
4576fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik}
4586fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
459a1717271caac5e8ea3808c331d4141ac01a42134Chris CraikTEST(RecordingCanvas, saveLayer_rotateClipped) {
4606fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
461eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.save(SaveFlags::MatrixClip);
4626fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        canvas.translate(100, 100);
4636fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        canvas.rotate(45);
4646fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        canvas.translate(-200, -200);
4656fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
4666fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        // area of saveLayer will be clipped to parent viewport, so we ask for 400x400...
467eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.saveLayerAlpha(0, 0, 400, 400, 128, SaveFlags::ClipToLayer);
4686fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        canvas.drawRect(0, 0, 400, 400, SkPaint());
4696fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        canvas.restore();
4706fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
4716fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        canvas.restore();
4726fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    });
4736fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    int count = 0;
4746fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    playbackOps(*dl, [&count](const RecordedOp& op) {
4756fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        if (count++ == 1) {
4766fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik            Matrix4 expectedMatrix;
4776fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik            EXPECT_EQ(RecordedOpId::RectOp, op.opId);
4786fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
4796fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik            // ...and get about 58.6, 58.6, 341.4 341.4, because the bounds are clipped by
4806fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik            // the parent 200x200 viewport, but prior to rotation
481e4db79de127cfe961195f52907af8451026eaa20Chris Craik            ASSERT_NE(nullptr, op.localClip);
482e4db79de127cfe961195f52907af8451026eaa20Chris Craik            ASSERT_EQ(ClipMode::Rectangle, op.localClip->mode);
483e4db79de127cfe961195f52907af8451026eaa20Chris Craik            // NOTE: this check relies on saveLayer altering the clip post-viewport init. This
484e4db79de127cfe961195f52907af8451026eaa20Chris Craik            // causes the clip to be recorded by contained draw commands, though it's not necessary
485e4db79de127cfe961195f52907af8451026eaa20Chris Craik            // since the same clip will be computed at draw time. If such a change is made, this
486e4db79de127cfe961195f52907af8451026eaa20Chris Craik            // check could be done at record time by querying the clip, or the clip could be altered
487e4db79de127cfe961195f52907af8451026eaa20Chris Craik            // slightly so that it is serialized.
48869aeabe6184bbbe6e731656205ffbef78b7b0f3fChris Craik            EXPECT_EQ(Rect(59, 59, 341, 341), op.localClip->rect);
4895430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik            EXPECT_EQ(Rect(400, 400), op.unmappedBounds);
4906fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik            expectedMatrix.loadIdentity();
4916fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik            EXPECT_MATRIX_APPROX_EQ(expectedMatrix, op.localMatrix);
4926fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        }
4936fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    });
4946fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    EXPECT_EQ(3, count);
4956fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik}
4966fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
4971367d2550ebce40f45b16dc651bc3d8d22930801Chris CraikTEST(RecordingCanvas, drawRenderNode_rejection) {
4981367d2550ebce40f45b16dc651bc3d8d22930801Chris Craik    auto child = TestUtils::createNode(50, 50, 150, 150,
4991367d2550ebce40f45b16dc651bc3d8d22930801Chris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
5001367d2550ebce40f45b16dc651bc3d8d22930801Chris Craik        SkPaint paint;
5011367d2550ebce40f45b16dc651bc3d8d22930801Chris Craik        paint.setColor(SK_ColorWHITE);
5021367d2550ebce40f45b16dc651bc3d8d22930801Chris Craik        canvas.drawRect(0, 0, 100, 100, paint);
5031367d2550ebce40f45b16dc651bc3d8d22930801Chris Craik    });
5041367d2550ebce40f45b16dc651bc3d8d22930801Chris Craik
5051367d2550ebce40f45b16dc651bc3d8d22930801Chris Craik    auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [&child](RecordingCanvas& canvas) {
5061367d2550ebce40f45b16dc651bc3d8d22930801Chris Craik        canvas.clipRect(0, 0, 0, 0, SkRegion::kIntersect_Op); // empty clip, reject node
5071367d2550ebce40f45b16dc651bc3d8d22930801Chris Craik        canvas.drawRenderNode(child.get()); // shouldn't crash when rejecting node...
5081367d2550ebce40f45b16dc651bc3d8d22930801Chris Craik    });
5091367d2550ebce40f45b16dc651bc3d8d22930801Chris Craik    ASSERT_TRUE(dl->isEmpty());
5101367d2550ebce40f45b16dc651bc3d8d22930801Chris Craik}
5111367d2550ebce40f45b16dc651bc3d8d22930801Chris Craik
5128d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris CraikTEST(RecordingCanvas, drawRenderNode_projection) {
5138d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik    sp<RenderNode> background = TestUtils::createNode(50, 50, 150, 150,
5148d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
5158d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        SkPaint paint;
5168d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        paint.setColor(SK_ColorWHITE);
5178d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        canvas.drawRect(0, 0, 100, 100, paint);
5188d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik    });
5198d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik    {
5208d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        background->mutateStagingProperties().setProjectionReceiver(false);
5218d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik
5228d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        // NO RECEIVER PRESENT
5238d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200,
5248d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik                    [&background](RecordingCanvas& canvas) {
5258d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            canvas.drawRect(0, 0, 100, 100, SkPaint());
5268d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            canvas.drawRenderNode(background.get());
5278d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            canvas.drawRect(0, 0, 100, 100, SkPaint());
5288d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        });
5298d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        EXPECT_EQ(-1, dl->projectionReceiveIndex)
5308d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik                << "no projection receiver should have been observed";
5318d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik    }
5328d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik    {
5338d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        background->mutateStagingProperties().setProjectionReceiver(true);
5348d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik
5358d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        // RECEIVER PRESENT
5368d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200,
5378d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik                    [&background](RecordingCanvas& canvas) {
5388d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            canvas.drawRect(0, 0, 100, 100, SkPaint());
5398d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            canvas.drawRenderNode(background.get());
5408d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            canvas.drawRect(0, 0, 100, 100, SkPaint());
5418d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        });
5428d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik
5438d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        ASSERT_EQ(3u, dl->getOps().size()) << "Must be three ops";
5448d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        auto op = dl->getOps()[1];
5458d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        EXPECT_EQ(RecordedOpId::RenderNodeOp, op->opId);
5468d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        EXPECT_EQ(1, dl->projectionReceiveIndex)
5478d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik                << "correct projection receiver not identified";
5488d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik
5498d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        // verify the behavior works even though projection receiver hasn't been sync'd yet
5508d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        EXPECT_TRUE(background->stagingProperties().isProjectionReceiver());
5518d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        EXPECT_FALSE(background->properties().isProjectionReceiver());
5528d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik    }
5538d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik}
5548d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik
5557fc1b0349bc2ac8c880120dc5611f703faa7f06fChris CraikTEST(RecordingCanvas, firstClipWillReplace) {
5567fc1b0349bc2ac8c880120dc5611f703faa7f06fChris Craik    auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
5577fc1b0349bc2ac8c880120dc5611f703faa7f06fChris Craik        canvas.save(SaveFlags::MatrixClip);
5587fc1b0349bc2ac8c880120dc5611f703faa7f06fChris Craik        // since no explicit clip set on canvas, this should be the one observed on op:
5597fc1b0349bc2ac8c880120dc5611f703faa7f06fChris Craik        canvas.clipRect(-100, -100, 300, 300, SkRegion::kIntersect_Op);
5607fc1b0349bc2ac8c880120dc5611f703faa7f06fChris Craik
5617fc1b0349bc2ac8c880120dc5611f703faa7f06fChris Craik        SkPaint paint;
5627fc1b0349bc2ac8c880120dc5611f703faa7f06fChris Craik        paint.setColor(SK_ColorWHITE);
5637fc1b0349bc2ac8c880120dc5611f703faa7f06fChris Craik        canvas.drawRect(0, 0, 100, 100, paint);
5647fc1b0349bc2ac8c880120dc5611f703faa7f06fChris Craik
5657fc1b0349bc2ac8c880120dc5611f703faa7f06fChris Craik        canvas.restore();
5667fc1b0349bc2ac8c880120dc5611f703faa7f06fChris Craik    });
5677fc1b0349bc2ac8c880120dc5611f703faa7f06fChris Craik    ASSERT_EQ(1u, dl->getOps().size()) << "Must have one op";
5687fc1b0349bc2ac8c880120dc5611f703faa7f06fChris Craik    // first clip must be preserved, even if it extends beyond canvas bounds
5697fc1b0349bc2ac8c880120dc5611f703faa7f06fChris Craik    EXPECT_CLIP_RECT(Rect(-100, -100, 300, 300), dl->getOps()[0]->localClip);
5707fc1b0349bc2ac8c880120dc5611f703faa7f06fChris Craik}
5717fc1b0349bc2ac8c880120dc5611f703faa7f06fChris Craik
57204d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris CraikTEST(RecordingCanvas, replaceClipIntersectWithRoot) {
57304d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik    auto dl = TestUtils::createDisplayList<RecordingCanvas>(100, 100, [](RecordingCanvas& canvas) {
57404d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik        canvas.save(SaveFlags::MatrixClip);
57504d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik        canvas.clipRect(-10, -10, 110, 110, SkRegion::kReplace_Op);
57604d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik        canvas.drawColor(SK_ColorWHITE, SkXfermode::Mode::kSrcOver_Mode);
57704d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik        canvas.restore();
57804d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik    });
57904d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik    ASSERT_EQ(1u, dl->getOps().size()) << "Must have one op";
58004d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik    // first clip must be preserved, even if it extends beyond canvas bounds
58104d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik    EXPECT_CLIP_RECT(Rect(-10, -10, 110, 110), dl->getOps()[0]->localClip);
58204d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik    EXPECT_TRUE(dl->getOps()[0]->localClip->intersectWithRoot);
58304d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik}
58404d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik
585a1717271caac5e8ea3808c331d4141ac01a42134Chris CraikTEST(RecordingCanvas, insertReorderBarrier) {
586161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik    auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
587161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        canvas.drawRect(0, 0, 400, 400, SkPaint());
588161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        canvas.insertReorderBarrier(true);
589161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        canvas.insertReorderBarrier(false);
590161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        canvas.insertReorderBarrier(false);
591161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        canvas.insertReorderBarrier(true);
592161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        canvas.drawRect(0, 0, 400, 400, SkPaint());
593161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        canvas.insertReorderBarrier(false);
594161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik    });
595161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik
596161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik    auto chunks = dl->getChunks();
597161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik    EXPECT_EQ(0u, chunks[0].beginOpIndex);
598161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik    EXPECT_EQ(1u, chunks[0].endOpIndex);
599161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik    EXPECT_FALSE(chunks[0].reorderChildren);
600161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik
601161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik    EXPECT_EQ(1u, chunks[1].beginOpIndex);
602161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik    EXPECT_EQ(2u, chunks[1].endOpIndex);
603161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik    EXPECT_TRUE(chunks[1].reorderChildren);
604161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik}
605161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik
606d645640180c25c2711e99aa82ec629155f8e91baChris CraikTEST(RecordingCanvas, insertReorderBarrier_clip) {
607d645640180c25c2711e99aa82ec629155f8e91baChris Craik    auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
608d645640180c25c2711e99aa82ec629155f8e91baChris Craik        // first chunk: no recorded clip
609d645640180c25c2711e99aa82ec629155f8e91baChris Craik        canvas.insertReorderBarrier(true);
610d645640180c25c2711e99aa82ec629155f8e91baChris Craik        canvas.drawRect(0, 0, 400, 400, SkPaint());
611d645640180c25c2711e99aa82ec629155f8e91baChris Craik
612d645640180c25c2711e99aa82ec629155f8e91baChris Craik        // second chunk: no recorded clip, since inorder region
613d645640180c25c2711e99aa82ec629155f8e91baChris Craik        canvas.clipRect(0, 0, 200, 200, SkRegion::kIntersect_Op);
614d645640180c25c2711e99aa82ec629155f8e91baChris Craik        canvas.insertReorderBarrier(false);
615d645640180c25c2711e99aa82ec629155f8e91baChris Craik        canvas.drawRect(0, 0, 400, 400, SkPaint());
616d645640180c25c2711e99aa82ec629155f8e91baChris Craik
617d645640180c25c2711e99aa82ec629155f8e91baChris Craik        // third chunk: recorded clip
618d645640180c25c2711e99aa82ec629155f8e91baChris Craik        canvas.insertReorderBarrier(true);
619d645640180c25c2711e99aa82ec629155f8e91baChris Craik        canvas.drawRect(0, 0, 400, 400, SkPaint());
620d645640180c25c2711e99aa82ec629155f8e91baChris Craik    });
621d645640180c25c2711e99aa82ec629155f8e91baChris Craik
622d645640180c25c2711e99aa82ec629155f8e91baChris Craik    auto chunks = dl->getChunks();
623d645640180c25c2711e99aa82ec629155f8e91baChris Craik    ASSERT_EQ(3u, chunks.size());
624d645640180c25c2711e99aa82ec629155f8e91baChris Craik
625d645640180c25c2711e99aa82ec629155f8e91baChris Craik    EXPECT_TRUE(chunks[0].reorderChildren);
626d645640180c25c2711e99aa82ec629155f8e91baChris Craik    EXPECT_EQ(nullptr, chunks[0].reorderClip);
627d645640180c25c2711e99aa82ec629155f8e91baChris Craik
628d645640180c25c2711e99aa82ec629155f8e91baChris Craik    EXPECT_FALSE(chunks[1].reorderChildren);
629d645640180c25c2711e99aa82ec629155f8e91baChris Craik    EXPECT_EQ(nullptr, chunks[1].reorderClip);
630d645640180c25c2711e99aa82ec629155f8e91baChris Craik
631d645640180c25c2711e99aa82ec629155f8e91baChris Craik    EXPECT_TRUE(chunks[2].reorderChildren);
632d645640180c25c2711e99aa82ec629155f8e91baChris Craik    ASSERT_NE(nullptr, chunks[2].reorderClip);
633d645640180c25c2711e99aa82ec629155f8e91baChris Craik    EXPECT_EQ(Rect(200, 200), chunks[2].reorderClip->rect);
634d645640180c25c2711e99aa82ec629155f8e91baChris Craik}
635d645640180c25c2711e99aa82ec629155f8e91baChris Craik
63642a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris CraikTEST(RecordingCanvas, refPaint) {
63742a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik    SkPaint paint;
63842a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik
63942a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik    auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [&paint](RecordingCanvas& canvas) {
64042a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        paint.setColor(SK_ColorBLUE);
64179abbf22d4f672208327546661e694d837f564a9Derek Sollenberger        // first two should use same paint
64242a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        canvas.drawRect(0, 0, 200, 10, paint);
64342a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        SkPaint paintCopy(paint);
64442a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        canvas.drawRect(0, 10, 200, 20, paintCopy);
64542a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik
64642a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        // only here do we use different paint ptr
64742a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        paint.setColor(SK_ColorRED);
64842a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        canvas.drawRect(0, 20, 200, 30, paint);
64942a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik    });
65042a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik    auto ops = dl->getOps();
65179abbf22d4f672208327546661e694d837f564a9Derek Sollenberger    ASSERT_EQ(3u, ops.size());
65242a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik
65379abbf22d4f672208327546661e694d837f564a9Derek Sollenberger    // first two are the same
65442a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik    EXPECT_NE(nullptr, ops[0]->paint);
65542a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik    EXPECT_NE(&paint, ops[0]->paint);
65642a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik    EXPECT_EQ(ops[0]->paint, ops[1]->paint);
65742a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik
65842a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik    // last is different, but still copied / non-null
65979abbf22d4f672208327546661e694d837f564a9Derek Sollenberger    EXPECT_NE(nullptr, ops[2]->paint);
66079abbf22d4f672208327546661e694d837f564a9Derek Sollenberger    EXPECT_NE(ops[0]->paint, ops[2]->paint);
66179abbf22d4f672208327546661e694d837f564a9Derek Sollenberger    EXPECT_NE(&paint, ops[2]->paint);
66242a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik}
66342a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik
664bee6092dbef81ff724624c4dd630efa8657817f8Chris CraikTEST(RecordingCanvas, refBitmap) {
665bee6092dbef81ff724624c4dd630efa8657817f8Chris Craik    SkBitmap bitmap = TestUtils::createSkBitmap(100, 100);
666bee6092dbef81ff724624c4dd630efa8657817f8Chris Craik    auto dl = TestUtils::createDisplayList<RecordingCanvas>(100, 100, [&bitmap](RecordingCanvas& canvas) {
667bee6092dbef81ff724624c4dd630efa8657817f8Chris Craik        canvas.drawBitmap(bitmap, 0, 0, nullptr);
668bee6092dbef81ff724624c4dd630efa8657817f8Chris Craik    });
669bee6092dbef81ff724624c4dd630efa8657817f8Chris Craik    auto& bitmaps = dl->getBitmapResources();
670bee6092dbef81ff724624c4dd630efa8657817f8Chris Craik    EXPECT_EQ(1u, bitmaps.size());
671bee6092dbef81ff724624c4dd630efa8657817f8Chris Craik}
672bee6092dbef81ff724624c4dd630efa8657817f8Chris Craik
673734f146c1ebf43816d5a3c8e82c726ab09489cb9Chris CraikTEST(RecordingCanvas, refBitmapInShader_bitmapShader) {
674734f146c1ebf43816d5a3c8e82c726ab09489cb9Chris Craik    SkBitmap bitmap = TestUtils::createSkBitmap(100, 100);
675734f146c1ebf43816d5a3c8e82c726ab09489cb9Chris Craik    auto dl = TestUtils::createDisplayList<RecordingCanvas>(100, 100, [&bitmap](RecordingCanvas& canvas) {
676734f146c1ebf43816d5a3c8e82c726ab09489cb9Chris Craik        SkPaint paint;
677734f146c1ebf43816d5a3c8e82c726ab09489cb9Chris Craik        SkAutoTUnref<SkShader> shader(SkShader::CreateBitmapShader(bitmap,
678734f146c1ebf43816d5a3c8e82c726ab09489cb9Chris Craik                SkShader::TileMode::kClamp_TileMode,
679734f146c1ebf43816d5a3c8e82c726ab09489cb9Chris Craik                SkShader::TileMode::kClamp_TileMode));
680734f146c1ebf43816d5a3c8e82c726ab09489cb9Chris Craik        paint.setShader(shader);
681734f146c1ebf43816d5a3c8e82c726ab09489cb9Chris Craik        canvas.drawRoundRect(0, 0, 100, 100, 20.0f, 20.0f, paint);
682734f146c1ebf43816d5a3c8e82c726ab09489cb9Chris Craik    });
683734f146c1ebf43816d5a3c8e82c726ab09489cb9Chris Craik    auto& bitmaps = dl->getBitmapResources();
684734f146c1ebf43816d5a3c8e82c726ab09489cb9Chris Craik    EXPECT_EQ(1u, bitmaps.size());
685734f146c1ebf43816d5a3c8e82c726ab09489cb9Chris Craik}
686734f146c1ebf43816d5a3c8e82c726ab09489cb9Chris Craik
687734f146c1ebf43816d5a3c8e82c726ab09489cb9Chris CraikTEST(RecordingCanvas, refBitmapInShader_composeShader) {
688734f146c1ebf43816d5a3c8e82c726ab09489cb9Chris Craik    SkBitmap bitmap = TestUtils::createSkBitmap(100, 100);
689734f146c1ebf43816d5a3c8e82c726ab09489cb9Chris Craik    auto dl = TestUtils::createDisplayList<RecordingCanvas>(100, 100, [&bitmap](RecordingCanvas& canvas) {
690734f146c1ebf43816d5a3c8e82c726ab09489cb9Chris Craik        SkPaint paint;
691734f146c1ebf43816d5a3c8e82c726ab09489cb9Chris Craik        SkAutoTUnref<SkShader> shader1(SkShader::CreateBitmapShader(bitmap,
692734f146c1ebf43816d5a3c8e82c726ab09489cb9Chris Craik                SkShader::TileMode::kClamp_TileMode,
693734f146c1ebf43816d5a3c8e82c726ab09489cb9Chris Craik                SkShader::TileMode::kClamp_TileMode));
694734f146c1ebf43816d5a3c8e82c726ab09489cb9Chris Craik
695734f146c1ebf43816d5a3c8e82c726ab09489cb9Chris Craik        SkPoint center;
696734f146c1ebf43816d5a3c8e82c726ab09489cb9Chris Craik        center.set(50, 50);
697734f146c1ebf43816d5a3c8e82c726ab09489cb9Chris Craik        SkColor colors[2];
698734f146c1ebf43816d5a3c8e82c726ab09489cb9Chris Craik        colors[0] = Color::Black;
699734f146c1ebf43816d5a3c8e82c726ab09489cb9Chris Craik        colors[1] = Color::White;
700734f146c1ebf43816d5a3c8e82c726ab09489cb9Chris Craik        SkAutoTUnref<SkShader> shader2(SkGradientShader::CreateRadial(center, 50, colors, nullptr, 2,
701734f146c1ebf43816d5a3c8e82c726ab09489cb9Chris Craik                SkShader::TileMode::kRepeat_TileMode));
702734f146c1ebf43816d5a3c8e82c726ab09489cb9Chris Craik
703734f146c1ebf43816d5a3c8e82c726ab09489cb9Chris Craik        SkAutoTUnref<SkShader> composeShader(SkShader::CreateComposeShader(shader1, shader2,
704734f146c1ebf43816d5a3c8e82c726ab09489cb9Chris Craik                SkXfermode::Mode::kMultiply_Mode));
705734f146c1ebf43816d5a3c8e82c726ab09489cb9Chris Craik        paint.setShader(composeShader);
706734f146c1ebf43816d5a3c8e82c726ab09489cb9Chris Craik        canvas.drawRoundRect(0, 0, 100, 100, 20.0f, 20.0f, paint);
707734f146c1ebf43816d5a3c8e82c726ab09489cb9Chris Craik    });
708734f146c1ebf43816d5a3c8e82c726ab09489cb9Chris Craik    auto& bitmaps = dl->getBitmapResources();
709734f146c1ebf43816d5a3c8e82c726ab09489cb9Chris Craik    EXPECT_EQ(1u, bitmaps.size());
710734f146c1ebf43816d5a3c8e82c726ab09489cb9Chris Craik}
711734f146c1ebf43816d5a3c8e82c726ab09489cb9Chris Craik
712dccca44ffda4836b56a21da95a046c9708ffd49csergeyvTEST(RecordingCanvas, drawText) {
713dccca44ffda4836b56a21da95a046c9708ffd49csergeyv    auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
714dccca44ffda4836b56a21da95a046c9708ffd49csergeyv        Paint paint;
715dccca44ffda4836b56a21da95a046c9708ffd49csergeyv        paint.setAntiAlias(true);
716dccca44ffda4836b56a21da95a046c9708ffd49csergeyv        paint.setTextSize(20);
717dccca44ffda4836b56a21da95a046c9708ffd49csergeyv        paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
71879abbf22d4f672208327546661e694d837f564a9Derek Sollenberger        std::unique_ptr<uint16_t[]> dst = TestUtils::asciiToUtf16("HELLO");
719dccca44ffda4836b56a21da95a046c9708ffd49csergeyv        canvas.drawText(dst.get(), 0, 5, 5, 25, 25, kBidi_Force_LTR, paint, NULL);
720dccca44ffda4836b56a21da95a046c9708ffd49csergeyv    });
721dccca44ffda4836b56a21da95a046c9708ffd49csergeyv
722dccca44ffda4836b56a21da95a046c9708ffd49csergeyv    int count = 0;
723dccca44ffda4836b56a21da95a046c9708ffd49csergeyv    playbackOps(*dl, [&count](const RecordedOp& op) {
724dccca44ffda4836b56a21da95a046c9708ffd49csergeyv        count++;
725dccca44ffda4836b56a21da95a046c9708ffd49csergeyv        ASSERT_EQ(RecordedOpId::TextOp, op.opId);
726dccca44ffda4836b56a21da95a046c9708ffd49csergeyv        EXPECT_EQ(nullptr, op.localClip);
727dccca44ffda4836b56a21da95a046c9708ffd49csergeyv        EXPECT_TRUE(op.localMatrix.isIdentity());
728dccca44ffda4836b56a21da95a046c9708ffd49csergeyv        EXPECT_TRUE(op.unmappedBounds.getHeight() >= 10);
729dccca44ffda4836b56a21da95a046c9708ffd49csergeyv        EXPECT_TRUE(op.unmappedBounds.getWidth() >= 25);
730dccca44ffda4836b56a21da95a046c9708ffd49csergeyv    });
731dccca44ffda4836b56a21da95a046c9708ffd49csergeyv    ASSERT_EQ(1, count);
732dccca44ffda4836b56a21da95a046c9708ffd49csergeyv}
733dccca44ffda4836b56a21da95a046c9708ffd49csergeyv
734dccca44ffda4836b56a21da95a046c9708ffd49csergeyvTEST(RecordingCanvas, drawTextInHighContrast) {
735dccca44ffda4836b56a21da95a046c9708ffd49csergeyv    auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
736dccca44ffda4836b56a21da95a046c9708ffd49csergeyv        canvas.setHighContrastText(true);
737dccca44ffda4836b56a21da95a046c9708ffd49csergeyv        Paint paint;
738dccca44ffda4836b56a21da95a046c9708ffd49csergeyv        paint.setColor(SK_ColorWHITE);
739dccca44ffda4836b56a21da95a046c9708ffd49csergeyv        paint.setAntiAlias(true);
740dccca44ffda4836b56a21da95a046c9708ffd49csergeyv        paint.setTextSize(20);
741dccca44ffda4836b56a21da95a046c9708ffd49csergeyv        paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
74279abbf22d4f672208327546661e694d837f564a9Derek Sollenberger        std::unique_ptr<uint16_t[]> dst = TestUtils::asciiToUtf16("HELLO");
743dccca44ffda4836b56a21da95a046c9708ffd49csergeyv        canvas.drawText(dst.get(), 0, 5, 5, 25, 25, kBidi_Force_LTR, paint, NULL);
744dccca44ffda4836b56a21da95a046c9708ffd49csergeyv    });
745dccca44ffda4836b56a21da95a046c9708ffd49csergeyv
746dccca44ffda4836b56a21da95a046c9708ffd49csergeyv    int count = 0;
747dccca44ffda4836b56a21da95a046c9708ffd49csergeyv    playbackOps(*dl, [&count](const RecordedOp& op) {
748dccca44ffda4836b56a21da95a046c9708ffd49csergeyv        ASSERT_EQ(RecordedOpId::TextOp, op.opId);
749dccca44ffda4836b56a21da95a046c9708ffd49csergeyv        if (count++ == 0) {
750dccca44ffda4836b56a21da95a046c9708ffd49csergeyv            EXPECT_EQ(SK_ColorBLACK, op.paint->getColor());
751dccca44ffda4836b56a21da95a046c9708ffd49csergeyv            EXPECT_EQ(SkPaint::kStrokeAndFill_Style, op.paint->getStyle());
752dccca44ffda4836b56a21da95a046c9708ffd49csergeyv        } else {
753dccca44ffda4836b56a21da95a046c9708ffd49csergeyv            EXPECT_EQ(SK_ColorWHITE, op.paint->getColor());
754dccca44ffda4836b56a21da95a046c9708ffd49csergeyv            EXPECT_EQ(SkPaint::kFill_Style, op.paint->getStyle());
755dccca44ffda4836b56a21da95a046c9708ffd49csergeyv        }
756dccca44ffda4836b56a21da95a046c9708ffd49csergeyv
757dccca44ffda4836b56a21da95a046c9708ffd49csergeyv    });
758dccca44ffda4836b56a21da95a046c9708ffd49csergeyv    ASSERT_EQ(2, count);
759dccca44ffda4836b56a21da95a046c9708ffd49csergeyv}
760dccca44ffda4836b56a21da95a046c9708ffd49csergeyv
7616fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} // namespace uirenderer
7626fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} // namespace android
763