1c4b21e6c03a6cdb03e116b9f510eb10cf8daedb1commit-bot@chromium.org/*
2c4b21e6c03a6cdb03e116b9f510eb10cf8daedb1commit-bot@chromium.org * Copyright 2014 Google Inc.
3c4b21e6c03a6cdb03e116b9f510eb10cf8daedb1commit-bot@chromium.org *
4c4b21e6c03a6cdb03e116b9f510eb10cf8daedb1commit-bot@chromium.org * Use of this source code is governed by a BSD-style license that can be
5c4b21e6c03a6cdb03e116b9f510eb10cf8daedb1commit-bot@chromium.org * found in the LICENSE file.
6c4b21e6c03a6cdb03e116b9f510eb10cf8daedb1commit-bot@chromium.org */
7c4b21e6c03a6cdb03e116b9f510eb10cf8daedb1commit-bot@chromium.org
8d9ce2be6b24b1c89d13c2edb63c3462b0f5c6aa3commit-bot@chromium.org#include "Test.h"
90a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org#include "RecordTestUtils.h"
10d9ce2be6b24b1c89d13c2edb63c3462b0f5c6aa3commit-bot@chromium.org
11d9ce2be6b24b1c89d13c2edb63c3462b0f5c6aa3commit-bot@chromium.org#include "SkDebugCanvas.h"
12271a030f5d0d3c59715fbeffb31c761279f3f8caMike Klein#include "SkDropShadowImageFilter.h"
1365151754b9fdb6a968d7307764c20655d1b680a0piotaixr#include "SkImagePriv.h"
14d9ce2be6b24b1c89d13c2edb63c3462b0f5c6aa3commit-bot@chromium.org#include "SkRecord.h"
15d9ce2be6b24b1c89d13c2edb63c3462b0f5c6aa3commit-bot@chromium.org#include "SkRecordDraw.h"
16271a030f5d0d3c59715fbeffb31c761279f3f8caMike Klein#include "SkRecordOpts.h"
17d9ce2be6b24b1c89d13c2edb63c3462b0f5c6aa3commit-bot@chromium.org#include "SkRecorder.h"
18d9ce2be6b24b1c89d13c2edb63c3462b0f5c6aa3commit-bot@chromium.org#include "SkRecords.h"
1965151754b9fdb6a968d7307764c20655d1b680a0piotaixr#include "SkSurface.h"
20d9ce2be6b24b1c89d13c2edb63c3462b0f5c6aa3commit-bot@chromium.org
21d9ce2be6b24b1c89d13c2edb63c3462b0f5c6aa3commit-bot@chromium.orgstatic const int W = 1920, H = 1080;
22d9ce2be6b24b1c89d13c2edb63c3462b0f5c6aa3commit-bot@chromium.org
23783fe16b8ed1cd1cff34eacc33296874a32f293brobertphillipsclass JustOneDraw : public SkPicture::AbortCallback {
24c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Kleinpublic:
25c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    JustOneDraw() : fCalls(0) {}
26c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein
2736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    bool abort() override { return fCalls++ > 0; }
28c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Kleinprivate:
29c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    int fCalls;
30c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein};
31c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein
322ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedDEF_TEST(RecordDraw_LazySaves, r) {
332ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    // Record two commands.
342ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    SkRecord record;
352ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    SkRecorder recorder(&record, W, H);
362ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed
372ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    REPORTER_ASSERT(r, 0 == record.count());
382ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    recorder.save();
392ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    REPORTER_ASSERT(r, 0 == record.count());    // the save was not recorded (yet)
402ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    recorder.drawColor(SK_ColorRED);
412ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    REPORTER_ASSERT(r, 1 == record.count());
422ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    recorder.scale(2, 2);
432ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    REPORTER_ASSERT(r, 3 == record.count());    // now we see the save
442ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    recorder.restore();
452ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    REPORTER_ASSERT(r, 4 == record.count());
462ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed
472ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    assert_type<SkRecords::DrawPaint>(r, record, 0);
482ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    assert_type<SkRecords::Save>     (r, record, 1);
49e9d2052e4931eeade49042a855b9c1f5ab7c84c5mtklein    assert_type<SkRecords::Concat>   (r, record, 2);
502ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    assert_type<SkRecords::Restore>  (r, record, 3);
512ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed
522ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    recorder.save();
532ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    recorder.save();
542ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    recorder.restore();
552ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    recorder.restore();
562ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    REPORTER_ASSERT(r, 4 == record.count());
572ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed}
582ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed
59c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike KleinDEF_TEST(RecordDraw_Abort, r) {
60c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    // Record two commands.
61c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    SkRecord record;
62c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    SkRecorder recorder(&record, W, H);
63c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    recorder.drawRect(SkRect::MakeWH(200, 300), SkPaint());
64c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    recorder.clipRect(SkRect::MakeWH(100, 200));
65c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein
66c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    SkRecord rerecord;
67c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    SkRecorder canvas(&rerecord, W, H);
68c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein
69c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    JustOneDraw callback;
7096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    SkRecordDraw(record, &canvas, nullptr, nullptr, 0, nullptr/*bbh*/, &callback);
71c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein
722ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    REPORTER_ASSERT(r, 1 == count_instances_of_type<SkRecords::DrawRect>(rerecord));
732ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    REPORTER_ASSERT(r, 0 == count_instances_of_type<SkRecords::ClipRect>(rerecord));
74c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein}
75c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein
76c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike KleinDEF_TEST(RecordDraw_Unbalanced, r) {
77c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    SkRecord record;
78c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    SkRecorder recorder(&record, W, H);
79c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    recorder.save();  // We won't balance this, but SkRecordDraw will for us.
802ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    recorder.scale(2, 2);
81c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein
82c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    SkRecord rerecord;
83c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    SkRecorder canvas(&rerecord, W, H);
8496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    SkRecordDraw(record, &canvas, nullptr, nullptr, 0, nullptr/*bbh*/, nullptr/*callback*/);
85c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein
862ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    int save_count = count_instances_of_type<SkRecords::Save>(rerecord);
872ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    int restore_count = count_instances_of_type<SkRecords::Save>(rerecord);
882ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    REPORTER_ASSERT(r, save_count == restore_count);
89c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein}
90c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein
910a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.orgDEF_TEST(RecordDraw_SetMatrixClobber, r) {
920a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org    // Set up an SkRecord that just scales by 2x,3x.
930a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org    SkRecord scaleRecord;
94a095041f5148dd1e71f38d0546335ed94199104bcommit-bot@chromium.org    SkRecorder scaleCanvas(&scaleRecord, W, H);
950a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org    SkMatrix scale;
960a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org    scale.setScale(2, 3);
970a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org    scaleCanvas.setMatrix(scale);
980a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org
990a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org    // Set up an SkRecord with an initial +20, +20 translate.
1000a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org    SkRecord translateRecord;
101a095041f5148dd1e71f38d0546335ed94199104bcommit-bot@chromium.org    SkRecorder translateCanvas(&translateRecord, W, H);
1020a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org    SkMatrix translate;
1030a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org    translate.setTranslate(20, 20);
1040a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org    translateCanvas.setMatrix(translate);
1050a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org
10696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    SkRecordDraw(scaleRecord, &translateCanvas, nullptr, nullptr, 0, nullptr/*bbh*/, nullptr/*callback*/);
107c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    REPORTER_ASSERT(r, 4 == translateRecord.count());
108c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    assert_type<SkRecords::SetMatrix>(r, translateRecord, 0);
109c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    assert_type<SkRecords::Save>     (r, translateRecord, 1);
110c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    assert_type<SkRecords::SetMatrix>(r, translateRecord, 2);
111c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    assert_type<SkRecords::Restore>  (r, translateRecord, 3);
1120a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org
1130a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org    // When we look at translateRecord now, it should have its first +20,+20 translate,
1140a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org    // then a 2x,3x scale that's been concatted with that +20,+20 translate.
1150a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org    const SkRecords::SetMatrix* setMatrix;
1160a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org    setMatrix = assert_type<SkRecords::SetMatrix>(r, translateRecord, 0);
1170a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org    REPORTER_ASSERT(r, setMatrix->matrix == translate);
1180a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org
119c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    setMatrix = assert_type<SkRecords::SetMatrix>(r, translateRecord, 2);
1200a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org    SkMatrix expected = scale;
1210a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org    expected.postConcat(translate);
1220a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org    REPORTER_ASSERT(r, setMatrix->matrix == expected);
1230a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org}
124a723b576aed31a6eb2bdda6388e6bd779d04c6b0mtklein
125937c9c7eb4e06d4d3bc495e129c7b8103a5d6c0fmtklein// Like a==b, with a little slop recognizing that float equality can be weird.
126937c9c7eb4e06d4d3bc495e129c7b8103a5d6c0fmtkleinstatic bool sloppy_rect_eq(SkRect a, SkRect b) {
127937c9c7eb4e06d4d3bc495e129c7b8103a5d6c0fmtklein    SkRect inset(a), outset(a);
128937c9c7eb4e06d4d3bc495e129c7b8103a5d6c0fmtklein    inset.inset(1, 1);
129937c9c7eb4e06d4d3bc495e129c7b8103a5d6c0fmtklein    outset.outset(1, 1);
130937c9c7eb4e06d4d3bc495e129c7b8103a5d6c0fmtklein    return outset.contains(b) && !inset.contains(b);
131937c9c7eb4e06d4d3bc495e129c7b8103a5d6c0fmtklein}
132937c9c7eb4e06d4d3bc495e129c7b8103a5d6c0fmtklein
13340732b34a1bf94eb44ee4b2327eece8d97735f11mtkleinDEF_TEST(RecordDraw_BasicBounds, r) {
134a723b576aed31a6eb2bdda6388e6bd779d04c6b0mtklein    SkRecord record;
135a723b576aed31a6eb2bdda6388e6bd779d04c6b0mtklein    SkRecorder recorder(&record, W, H);
136a723b576aed31a6eb2bdda6388e6bd779d04c6b0mtklein    recorder.save();
137a723b576aed31a6eb2bdda6388e6bd779d04c6b0mtklein        recorder.clipRect(SkRect::MakeWH(400, 500));
138a723b576aed31a6eb2bdda6388e6bd779d04c6b0mtklein        recorder.scale(2, 2);
139a723b576aed31a6eb2bdda6388e6bd779d04c6b0mtklein        recorder.drawRect(SkRect::MakeWH(320, 240), SkPaint());
140a723b576aed31a6eb2bdda6388e6bd779d04c6b0mtklein    recorder.restore();
141a723b576aed31a6eb2bdda6388e6bd779d04c6b0mtklein
14240732b34a1bf94eb44ee4b2327eece8d97735f11mtklein    SkAutoTMalloc<SkRect> bounds(record.count());
14340732b34a1bf94eb44ee4b2327eece8d97735f11mtklein    SkRecordFillBounds(SkRect::MakeWH(SkIntToScalar(W), SkIntToScalar(H)), record, bounds);
144a723b576aed31a6eb2bdda6388e6bd779d04c6b0mtklein
14540732b34a1bf94eb44ee4b2327eece8d97735f11mtklein    for (int i = 0; i < record.count(); i++) {
14640732b34a1bf94eb44ee4b2327eece8d97735f11mtklein        REPORTER_ASSERT(r, sloppy_rect_eq(SkRect::MakeWH(400, 480), bounds[i]));
147a723b576aed31a6eb2bdda6388e6bd779d04c6b0mtklein    }
148a723b576aed31a6eb2bdda6388e6bd779d04c6b0mtklein}
14900f30bdc9e34b013da54b4406f36556c5be8d041mtklein
150937c9c7eb4e06d4d3bc495e129c7b8103a5d6c0fmtklein// A regression test for crbug.com/409110.
151937c9c7eb4e06d4d3bc495e129c7b8103a5d6c0fmtkleinDEF_TEST(RecordDraw_TextBounds, r) {
152937c9c7eb4e06d4d3bc495e129c7b8103a5d6c0fmtklein    SkRecord record;
153937c9c7eb4e06d4d3bc495e129c7b8103a5d6c0fmtklein    SkRecorder recorder(&record, W, H);
154937c9c7eb4e06d4d3bc495e129c7b8103a5d6c0fmtklein
155937c9c7eb4e06d4d3bc495e129c7b8103a5d6c0fmtklein    // Two Chinese characters in UTF-8.
156937c9c7eb4e06d4d3bc495e129c7b8103a5d6c0fmtklein    const char text[] = { '\xe6', '\xbc', '\xa2', '\xe5', '\xad', '\x97' };
157937c9c7eb4e06d4d3bc495e129c7b8103a5d6c0fmtklein    const size_t bytes = SK_ARRAY_COUNT(text);
158937c9c7eb4e06d4d3bc495e129c7b8103a5d6c0fmtklein
159937c9c7eb4e06d4d3bc495e129c7b8103a5d6c0fmtklein    const SkScalar xpos[] = { 10, 20 };
160937c9c7eb4e06d4d3bc495e129c7b8103a5d6c0fmtklein    recorder.drawPosTextH(text, bytes, xpos, 30, SkPaint());
161937c9c7eb4e06d4d3bc495e129c7b8103a5d6c0fmtklein
162937c9c7eb4e06d4d3bc495e129c7b8103a5d6c0fmtklein    const SkPoint pos[] = { {40, 50}, {60, 70} };
163937c9c7eb4e06d4d3bc495e129c7b8103a5d6c0fmtklein    recorder.drawPosText(text, bytes, pos, SkPaint());
164937c9c7eb4e06d4d3bc495e129c7b8103a5d6c0fmtklein
16540732b34a1bf94eb44ee4b2327eece8d97735f11mtklein    SkAutoTMalloc<SkRect> bounds(record.count());
16640732b34a1bf94eb44ee4b2327eece8d97735f11mtklein    SkRecordFillBounds(SkRect::MakeWH(SkIntToScalar(W), SkIntToScalar(H)), record, bounds);
167937c9c7eb4e06d4d3bc495e129c7b8103a5d6c0fmtklein
1689a5380dd358a9c559a41beef7cb368cd7f0ca51fmtklein    // We can make these next assertions confidently because SkRecordFillBounds
1699a5380dd358a9c559a41beef7cb368cd7f0ca51fmtklein    // builds its bounds by overestimating font metrics in a platform-independent way.
1709a5380dd358a9c559a41beef7cb368cd7f0ca51fmtklein    // If that changes, these tests will need to be more flexible.
17140732b34a1bf94eb44ee4b2327eece8d97735f11mtklein    REPORTER_ASSERT(r, sloppy_rect_eq(bounds[0], SkRect::MakeLTRB(0,  0, 140, 60)));
17240732b34a1bf94eb44ee4b2327eece8d97735f11mtklein    REPORTER_ASSERT(r, sloppy_rect_eq(bounds[1], SkRect::MakeLTRB(0, 20, 180, 100)));
173937c9c7eb4e06d4d3bc495e129c7b8103a5d6c0fmtklein}
174937c9c7eb4e06d4d3bc495e129c7b8103a5d6c0fmtklein
17500f30bdc9e34b013da54b4406f36556c5be8d041mtklein// Base test to ensure start/stop range is respected
17600f30bdc9e34b013da54b4406f36556c5be8d041mtkleinDEF_TEST(RecordDraw_PartialStartStop, r) {
17700f30bdc9e34b013da54b4406f36556c5be8d041mtklein    static const int kWidth = 10, kHeight = 10;
17800f30bdc9e34b013da54b4406f36556c5be8d041mtklein
17900f30bdc9e34b013da54b4406f36556c5be8d041mtklein    SkRect r1 = { 0, 0, kWidth,   kHeight };
18000f30bdc9e34b013da54b4406f36556c5be8d041mtklein    SkRect r2 = { 0, 0, kWidth,   kHeight/2 };
18100f30bdc9e34b013da54b4406f36556c5be8d041mtklein    SkRect r3 = { 0, 0, kWidth/2, kHeight };
18200f30bdc9e34b013da54b4406f36556c5be8d041mtklein    SkPaint p;
18300f30bdc9e34b013da54b4406f36556c5be8d041mtklein
18400f30bdc9e34b013da54b4406f36556c5be8d041mtklein    SkRecord record;
18500f30bdc9e34b013da54b4406f36556c5be8d041mtklein    SkRecorder recorder(&record, kWidth, kHeight);
18600f30bdc9e34b013da54b4406f36556c5be8d041mtklein    recorder.drawRect(r1, p);
18700f30bdc9e34b013da54b4406f36556c5be8d041mtklein    recorder.drawRect(r2, p);
18800f30bdc9e34b013da54b4406f36556c5be8d041mtklein    recorder.drawRect(r3, p);
18900f30bdc9e34b013da54b4406f36556c5be8d041mtklein
19000f30bdc9e34b013da54b4406f36556c5be8d041mtklein    SkRecord rerecord;
19100f30bdc9e34b013da54b4406f36556c5be8d041mtklein    SkRecorder canvas(&rerecord, kWidth, kHeight);
19296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    SkRecordPartialDraw(record, &canvas, nullptr, 0, 1, 2, SkMatrix::I()); // replay just drawRect of r2
19300f30bdc9e34b013da54b4406f36556c5be8d041mtklein
1942ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    REPORTER_ASSERT(r, 1 == count_instances_of_type<SkRecords::DrawRect>(rerecord));
1952ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    int index = find_first_instances_of_type<SkRecords::DrawRect>(rerecord);
1962ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    const SkRecords::DrawRect* drawRect = assert_type<SkRecords::DrawRect>(r, rerecord, index);
19700f30bdc9e34b013da54b4406f36556c5be8d041mtklein    REPORTER_ASSERT(r, drawRect->rect == r2);
19800f30bdc9e34b013da54b4406f36556c5be8d041mtklein}
19900f30bdc9e34b013da54b4406f36556c5be8d041mtklein
2006950de6c4166fabb35e6c756fc009e0cf1c47819halcanary// A regression test for crbug.com/415468 and https://bug.skia.org/2957 .
2018e393bf70ea2aab9ca31f52c15b518436c7b6055mtklein//
2028e393bf70ea2aab9ca31f52c15b518436c7b6055mtklein// This also now serves as a regression test for crbug.com/418417.  We used to adjust the
2038e393bf70ea2aab9ca31f52c15b518436c7b6055mtklein// bounds for the saveLayer, clip, and restore to be greater than the bounds of the picture.
2048e393bf70ea2aab9ca31f52c15b518436c7b6055mtklein// (We were applying the saveLayer paint to the bounds after restore, which makes no sense.)
205271a030f5d0d3c59715fbeffb31c761279f3f8caMike KleinDEF_TEST(RecordDraw_SaveLayerAffectsClipBounds, r) {
206271a030f5d0d3c59715fbeffb31c761279f3f8caMike Klein    SkRecord record;
207271a030f5d0d3c59715fbeffb31c761279f3f8caMike Klein    SkRecorder recorder(&record, 50, 50);
208271a030f5d0d3c59715fbeffb31c761279f3f8caMike Klein
209271a030f5d0d3c59715fbeffb31c761279f3f8caMike Klein    // We draw a rectangle with a long drop shadow.  We used to not update the clip
210271a030f5d0d3c59715fbeffb31c761279f3f8caMike Klein    // bounds based on SaveLayer paints, so the drop shadow could be cut off.
211271a030f5d0d3c59715fbeffb31c761279f3f8caMike Klein    SkPaint paint;
212c416912da4840af0c49bd8cdcf00044ed39500f6robertphillips    paint.setImageFilter(SkDropShadowImageFilter::Make(
213c416912da4840af0c49bd8cdcf00044ed39500f6robertphillips                                 20, 0, 0, 0, SK_ColorBLACK,
214c416912da4840af0c49bd8cdcf00044ed39500f6robertphillips                                 SkDropShadowImageFilter::kDrawShadowAndForeground_ShadowMode,
215c416912da4840af0c49bd8cdcf00044ed39500f6robertphillips                                 nullptr));
216271a030f5d0d3c59715fbeffb31c761279f3f8caMike Klein
21796fcdcc219d2a0d3579719b84b28bede76efba64halcanary    recorder.saveLayer(nullptr, &paint);
218271a030f5d0d3c59715fbeffb31c761279f3f8caMike Klein        recorder.clipRect(SkRect::MakeWH(20, 40));
219271a030f5d0d3c59715fbeffb31c761279f3f8caMike Klein        recorder.drawRect(SkRect::MakeWH(20, 40), SkPaint());
220271a030f5d0d3c59715fbeffb31c761279f3f8caMike Klein    recorder.restore();
221271a030f5d0d3c59715fbeffb31c761279f3f8caMike Klein
2228e393bf70ea2aab9ca31f52c15b518436c7b6055mtklein    // Under the original bug, the right edge value of the drawRect would be 20 less than asserted
2238e393bf70ea2aab9ca31f52c15b518436c7b6055mtklein    // here because we intersected it with a clip that had not been adjusted for the drop shadow.
2248e393bf70ea2aab9ca31f52c15b518436c7b6055mtklein    //
2258e393bf70ea2aab9ca31f52c15b518436c7b6055mtklein    // The second bug showed up as adjusting the picture bounds (0,0,50,50) by the drop shadow too.
2268e393bf70ea2aab9ca31f52c15b518436c7b6055mtklein    // The saveLayer, clipRect, and restore bounds were incorrectly (0,0,70,50).
22740732b34a1bf94eb44ee4b2327eece8d97735f11mtklein    SkAutoTMalloc<SkRect> bounds(record.count());
22840732b34a1bf94eb44ee4b2327eece8d97735f11mtklein    SkRecordFillBounds(SkRect::MakeWH(50, 50), record, bounds);
22940732b34a1bf94eb44ee4b2327eece8d97735f11mtklein    REPORTER_ASSERT(r, sloppy_rect_eq(bounds[0], SkRect::MakeLTRB(0, 0, 50, 50)));
23040732b34a1bf94eb44ee4b2327eece8d97735f11mtklein    REPORTER_ASSERT(r, sloppy_rect_eq(bounds[1], SkRect::MakeLTRB(0, 0, 50, 50)));
23140732b34a1bf94eb44ee4b2327eece8d97735f11mtklein    REPORTER_ASSERT(r, sloppy_rect_eq(bounds[2], SkRect::MakeLTRB(0, 0, 40, 40)));
23240732b34a1bf94eb44ee4b2327eece8d97735f11mtklein    REPORTER_ASSERT(r, sloppy_rect_eq(bounds[3], SkRect::MakeLTRB(0, 0, 50, 50)));
233271a030f5d0d3c59715fbeffb31c761279f3f8caMike Klein}
23465151754b9fdb6a968d7307764c20655d1b680a0piotaixr
2354d52afef5cf90a2fed3bb69db71675c6450ab397robertphillips// When a saveLayer provides an explicit bound and has a complex paint (e.g., one that
2364d52afef5cf90a2fed3bb69db71675c6450ab397robertphillips// affects transparent black), that bound should serve to shrink the area of the required
2374d52afef5cf90a2fed3bb69db71675c6450ab397robertphillips// backing store.
2384d52afef5cf90a2fed3bb69db71675c6450ab397robertphillipsDEF_TEST(RecordDraw_SaveLayerBoundsAffectsClipBounds, r) {
2394d52afef5cf90a2fed3bb69db71675c6450ab397robertphillips    SkRecord record;
2404d52afef5cf90a2fed3bb69db71675c6450ab397robertphillips    SkRecorder recorder(&record, 50, 50);
2414d52afef5cf90a2fed3bb69db71675c6450ab397robertphillips
2424d52afef5cf90a2fed3bb69db71675c6450ab397robertphillips    SkPaint p;
243374772bd61951f01bf84fe17bf53d8867681c9aereed    p.setBlendMode(SkBlendMode::kSrc);
2444d52afef5cf90a2fed3bb69db71675c6450ab397robertphillips
24540732b34a1bf94eb44ee4b2327eece8d97735f11mtklein    SkRect layerBounds = SkRect::MakeLTRB(10, 10, 40, 40);
24640732b34a1bf94eb44ee4b2327eece8d97735f11mtklein    recorder.saveLayer(&layerBounds, &p);
2474d52afef5cf90a2fed3bb69db71675c6450ab397robertphillips    recorder.drawRect(SkRect::MakeLTRB(20, 20, 30, 30), SkPaint());
2484d52afef5cf90a2fed3bb69db71675c6450ab397robertphillips    recorder.restore();
2494d52afef5cf90a2fed3bb69db71675c6450ab397robertphillips
25040732b34a1bf94eb44ee4b2327eece8d97735f11mtklein    SkAutoTMalloc<SkRect> bounds(record.count());
25140732b34a1bf94eb44ee4b2327eece8d97735f11mtklein    SkRecordFillBounds(SkRect::MakeWH(50, 50), record, bounds);
252d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    if (!SkCanvas::Internal_Private_GetIgnoreSaveLayerBounds()) {
25340732b34a1bf94eb44ee4b2327eece8d97735f11mtklein        REPORTER_ASSERT(r, sloppy_rect_eq(bounds[0], SkRect::MakeLTRB(10, 10, 40, 40)));
25440732b34a1bf94eb44ee4b2327eece8d97735f11mtklein        REPORTER_ASSERT(r, sloppy_rect_eq(bounds[1], SkRect::MakeLTRB(20, 20, 30, 30)));
25540732b34a1bf94eb44ee4b2327eece8d97735f11mtklein        REPORTER_ASSERT(r, sloppy_rect_eq(bounds[2], SkRect::MakeLTRB(10, 10, 40, 40)));
256d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    }
2574d52afef5cf90a2fed3bb69db71675c6450ab397robertphillips}
2584d52afef5cf90a2fed3bb69db71675c6450ab397robertphillips
25965151754b9fdb6a968d7307764c20655d1b680a0piotaixrDEF_TEST(RecordDraw_drawImage, r){
26065151754b9fdb6a968d7307764c20655d1b680a0piotaixr    class SkCanvasMock : public SkCanvas {
26165151754b9fdb6a968d7307764c20655d1b680a0piotaixr    public:
262ad8aa1dcf36d64ddf849b914281713b901a01f49mtklein        SkCanvasMock(int width, int height) : SkCanvas(width, height) {
26365151754b9fdb6a968d7307764c20655d1b680a0piotaixr            this->resetTestValues();
26465151754b9fdb6a968d7307764c20655d1b680a0piotaixr        }
26565151754b9fdb6a968d7307764c20655d1b680a0piotaixr
26641af966ab338e95eee81ab618ab28195075338f7reed        void onDrawImage(const SkImage* image, SkScalar left, SkScalar top,
26736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein                         const SkPaint* paint) override {
26865151754b9fdb6a968d7307764c20655d1b680a0piotaixr            fDrawImageCalled = true;
26965151754b9fdb6a968d7307764c20655d1b680a0piotaixr        }
27065151754b9fdb6a968d7307764c20655d1b680a0piotaixr
27141af966ab338e95eee81ab618ab28195075338f7reed        void onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
272562fe4767cc73e08a4e039362bc0336aea66ecfbreed                             const SkPaint* paint, SrcRectConstraint) override {
27365151754b9fdb6a968d7307764c20655d1b680a0piotaixr            fDrawImageRectCalled = true;
27465151754b9fdb6a968d7307764c20655d1b680a0piotaixr        }
27565151754b9fdb6a968d7307764c20655d1b680a0piotaixr
27665151754b9fdb6a968d7307764c20655d1b680a0piotaixr        void resetTestValues() {
27765151754b9fdb6a968d7307764c20655d1b680a0piotaixr            fDrawImageCalled = fDrawImageRectCalled = false;
27865151754b9fdb6a968d7307764c20655d1b680a0piotaixr        }
27965151754b9fdb6a968d7307764c20655d1b680a0piotaixr
28065151754b9fdb6a968d7307764c20655d1b680a0piotaixr        bool fDrawImageCalled;
28165151754b9fdb6a968d7307764c20655d1b680a0piotaixr        bool fDrawImageRectCalled;
28265151754b9fdb6a968d7307764c20655d1b680a0piotaixr    };
28365151754b9fdb6a968d7307764c20655d1b680a0piotaixr
284e8f3062a36d3682f4019309a32b5b84dc9eddf8creed    auto surface(SkSurface::MakeRasterN32Premul(10, 10));
28565151754b9fdb6a968d7307764c20655d1b680a0piotaixr    surface->getCanvas()->clear(SK_ColorGREEN);
2869ce9d6772df650ceb0511f275e1a83dffa78ff72reed    sk_sp<SkImage> image(surface->makeImageSnapshot());
28765151754b9fdb6a968d7307764c20655d1b680a0piotaixr
28865151754b9fdb6a968d7307764c20655d1b680a0piotaixr    SkCanvasMock canvas(10, 10);
28965151754b9fdb6a968d7307764c20655d1b680a0piotaixr
29065151754b9fdb6a968d7307764c20655d1b680a0piotaixr    {
29165151754b9fdb6a968d7307764c20655d1b680a0piotaixr        SkRecord record;
29265151754b9fdb6a968d7307764c20655d1b680a0piotaixr        SkRecorder recorder(&record, 10, 10);
29365151754b9fdb6a968d7307764c20655d1b680a0piotaixr        recorder.drawImage(image, 0, 0);
29496fcdcc219d2a0d3579719b84b28bede76efba64halcanary        SkRecordDraw(record, &canvas, nullptr, nullptr, 0, nullptr, 0);
29565151754b9fdb6a968d7307764c20655d1b680a0piotaixr    }
29665151754b9fdb6a968d7307764c20655d1b680a0piotaixr    REPORTER_ASSERT(r, canvas.fDrawImageCalled);
29765151754b9fdb6a968d7307764c20655d1b680a0piotaixr    canvas.resetTestValues();
29865151754b9fdb6a968d7307764c20655d1b680a0piotaixr
29965151754b9fdb6a968d7307764c20655d1b680a0piotaixr    {
30065151754b9fdb6a968d7307764c20655d1b680a0piotaixr        SkRecord record;
30165151754b9fdb6a968d7307764c20655d1b680a0piotaixr        SkRecorder recorder(&record, 10, 10);
302e47829b6b1eeb6b0c97ccb3df3016d197046824creed        recorder.drawImageRect(image, SkRect::MakeWH(10, 10), nullptr);
30396fcdcc219d2a0d3579719b84b28bede76efba64halcanary        SkRecordDraw(record, &canvas, nullptr, nullptr, 0, nullptr, 0);
30465151754b9fdb6a968d7307764c20655d1b680a0piotaixr    }
30565151754b9fdb6a968d7307764c20655d1b680a0piotaixr    REPORTER_ASSERT(r, canvas.fDrawImageRectCalled);
30665151754b9fdb6a968d7307764c20655d1b680a0piotaixr
30765151754b9fdb6a968d7307764c20655d1b680a0piotaixr}
308