RecordDrawTest.cpp revision 4d52afef5cf90a2fed3bb69db71675c6450ab397
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"
12c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein#include "SkDrawPictureCallback.h"
13271a030f5d0d3c59715fbeffb31c761279f3f8caMike Klein#include "SkDropShadowImageFilter.h"
1465151754b9fdb6a968d7307764c20655d1b680a0piotaixr#include "SkImagePriv.h"
15d9ce2be6b24b1c89d13c2edb63c3462b0f5c6aa3commit-bot@chromium.org#include "SkRecord.h"
16d9ce2be6b24b1c89d13c2edb63c3462b0f5c6aa3commit-bot@chromium.org#include "SkRecordDraw.h"
17271a030f5d0d3c59715fbeffb31c761279f3f8caMike Klein#include "SkRecordOpts.h"
18d9ce2be6b24b1c89d13c2edb63c3462b0f5c6aa3commit-bot@chromium.org#include "SkRecorder.h"
19d9ce2be6b24b1c89d13c2edb63c3462b0f5c6aa3commit-bot@chromium.org#include "SkRecords.h"
2065151754b9fdb6a968d7307764c20655d1b680a0piotaixr#include "SkSurface.h"
21d9ce2be6b24b1c89d13c2edb63c3462b0f5c6aa3commit-bot@chromium.org
22d9ce2be6b24b1c89d13c2edb63c3462b0f5c6aa3commit-bot@chromium.orgstatic const int W = 1920, H = 1080;
23d9ce2be6b24b1c89d13c2edb63c3462b0f5c6aa3commit-bot@chromium.org
24c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Kleinclass JustOneDraw : public SkDrawPictureCallback {
25c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Kleinpublic:
26c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    JustOneDraw() : fCalls(0) {}
27c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein
28c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    virtual bool abortDrawing() SK_OVERRIDE { return fCalls++ > 0; }
29c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Kleinprivate:
30c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    int fCalls;
31c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein};
32c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein
33c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike KleinDEF_TEST(RecordDraw_Abort, r) {
34c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    // Record two commands.
35c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    SkRecord record;
36c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    SkRecorder recorder(&record, W, H);
37c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    recorder.drawRect(SkRect::MakeWH(200, 300), SkPaint());
38c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    recorder.clipRect(SkRect::MakeWH(100, 200));
39c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein
40c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    SkRecord rerecord;
41c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    SkRecorder canvas(&rerecord, W, H);
42c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein
43c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    JustOneDraw callback;
445ad6ee1b2ce54f8e59b9f5a337c688a98a4b0f2amtklein    SkRecordDraw(record, &canvas, NULL/*bbh*/, &callback);
45c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein
46c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    REPORTER_ASSERT(r, 3 == rerecord.count());
47c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    assert_type<SkRecords::Save>    (r, rerecord, 0);
48c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    assert_type<SkRecords::DrawRect>(r, rerecord, 1);
49c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    assert_type<SkRecords::Restore> (r, rerecord, 2);
50c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein}
51c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein
52c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike KleinDEF_TEST(RecordDraw_Unbalanced, r) {
53c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    SkRecord record;
54c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    SkRecorder recorder(&record, W, H);
55c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    recorder.save();  // We won't balance this, but SkRecordDraw will for us.
56c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein
57c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    SkRecord rerecord;
58c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    SkRecorder canvas(&rerecord, W, H);
595ad6ee1b2ce54f8e59b9f5a337c688a98a4b0f2amtklein    SkRecordDraw(record, &canvas, NULL/*bbh*/, NULL/*callback*/);
60c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein
61c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    REPORTER_ASSERT(r, 4 == rerecord.count());
62c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    assert_type<SkRecords::Save>    (r, rerecord, 0);
63c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    assert_type<SkRecords::Save>    (r, rerecord, 1);
64c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    assert_type<SkRecords::Restore> (r, rerecord, 2);
65c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    assert_type<SkRecords::Restore> (r, rerecord, 3);
66c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein}
67c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein
680a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.orgDEF_TEST(RecordDraw_SetMatrixClobber, r) {
690a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org    // Set up an SkRecord that just scales by 2x,3x.
700a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org    SkRecord scaleRecord;
71a095041f5148dd1e71f38d0546335ed94199104bcommit-bot@chromium.org    SkRecorder scaleCanvas(&scaleRecord, W, H);
720a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org    SkMatrix scale;
730a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org    scale.setScale(2, 3);
740a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org    scaleCanvas.setMatrix(scale);
750a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org
760a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org    // Set up an SkRecord with an initial +20, +20 translate.
770a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org    SkRecord translateRecord;
78a095041f5148dd1e71f38d0546335ed94199104bcommit-bot@chromium.org    SkRecorder translateCanvas(&translateRecord, W, H);
790a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org    SkMatrix translate;
800a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org    translate.setTranslate(20, 20);
810a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org    translateCanvas.setMatrix(translate);
820a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org
835ad6ee1b2ce54f8e59b9f5a337c688a98a4b0f2amtklein    SkRecordDraw(scaleRecord, &translateCanvas, NULL/*bbh*/, NULL/*callback*/);
84c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    REPORTER_ASSERT(r, 4 == translateRecord.count());
85c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    assert_type<SkRecords::SetMatrix>(r, translateRecord, 0);
86c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    assert_type<SkRecords::Save>     (r, translateRecord, 1);
87c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    assert_type<SkRecords::SetMatrix>(r, translateRecord, 2);
88c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    assert_type<SkRecords::Restore>  (r, translateRecord, 3);
890a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org
900a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org    // When we look at translateRecord now, it should have its first +20,+20 translate,
910a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org    // then a 2x,3x scale that's been concatted with that +20,+20 translate.
920a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org    const SkRecords::SetMatrix* setMatrix;
930a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org    setMatrix = assert_type<SkRecords::SetMatrix>(r, translateRecord, 0);
940a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org    REPORTER_ASSERT(r, setMatrix->matrix == translate);
950a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org
96c11530ea73b2a2fcb431df0f5c1887d08ac9113cMike Klein    setMatrix = assert_type<SkRecords::SetMatrix>(r, translateRecord, 2);
970a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org    SkMatrix expected = scale;
980a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org    expected.postConcat(translate);
990a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org    REPORTER_ASSERT(r, setMatrix->matrix == expected);
1000a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org}
101a723b576aed31a6eb2bdda6388e6bd779d04c6b0mtklein
102a723b576aed31a6eb2bdda6388e6bd779d04c6b0mtkleinstruct TestBBH : public SkBBoxHierarchy {
1034477c3c0e6eb064772aefe8737425cd1c2ce557fmtklein    virtual void insert(SkAutoTMalloc<SkRect>* boundsArray, int N) SK_OVERRIDE {
1044477c3c0e6eb064772aefe8737425cd1c2ce557fmtklein        fEntries.setCount(N);
1054477c3c0e6eb064772aefe8737425cd1c2ce557fmtklein        for (int i = 0; i < N; i++) {
1064477c3c0e6eb064772aefe8737425cd1c2ce557fmtklein            Entry e = { (unsigned)i, (*boundsArray)[i] };
1074477c3c0e6eb064772aefe8737425cd1c2ce557fmtklein            fEntries[i] = e;
1084477c3c0e6eb064772aefe8737425cd1c2ce557fmtklein        }
109a723b576aed31a6eb2bdda6388e6bd779d04c6b0mtklein    }
110a723b576aed31a6eb2bdda6388e6bd779d04c6b0mtklein
1116bd41969a0f2283a7a7320bb0025551353c241ecmtklein    virtual void search(const SkRect& query, SkTDArray<unsigned>* results) const SK_OVERRIDE {}
112a723b576aed31a6eb2bdda6388e6bd779d04c6b0mtklein
113a723b576aed31a6eb2bdda6388e6bd779d04c6b0mtklein    struct Entry {
1146bd41969a0f2283a7a7320bb0025551353c241ecmtklein        unsigned opIndex;
115533eb782edaa0b6fece6166d3001edf72ec39f11mtklein        SkRect bounds;
116a723b576aed31a6eb2bdda6388e6bd779d04c6b0mtklein    };
1176bd41969a0f2283a7a7320bb0025551353c241ecmtklein    SkTDArray<Entry> fEntries;
118a723b576aed31a6eb2bdda6388e6bd779d04c6b0mtklein};
119a723b576aed31a6eb2bdda6388e6bd779d04c6b0mtklein
120937c9c7eb4e06d4d3bc495e129c7b8103a5d6c0fmtklein// Like a==b, with a little slop recognizing that float equality can be weird.
121937c9c7eb4e06d4d3bc495e129c7b8103a5d6c0fmtkleinstatic bool sloppy_rect_eq(SkRect a, SkRect b) {
122937c9c7eb4e06d4d3bc495e129c7b8103a5d6c0fmtklein    SkRect inset(a), outset(a);
123937c9c7eb4e06d4d3bc495e129c7b8103a5d6c0fmtklein    inset.inset(1, 1);
124937c9c7eb4e06d4d3bc495e129c7b8103a5d6c0fmtklein    outset.outset(1, 1);
125937c9c7eb4e06d4d3bc495e129c7b8103a5d6c0fmtklein    return outset.contains(b) && !inset.contains(b);
126937c9c7eb4e06d4d3bc495e129c7b8103a5d6c0fmtklein}
127937c9c7eb4e06d4d3bc495e129c7b8103a5d6c0fmtklein
128a723b576aed31a6eb2bdda6388e6bd779d04c6b0mtklein// This test is not meant to make total sense yet.  It's testing the status quo
129a723b576aed31a6eb2bdda6388e6bd779d04c6b0mtklein// of SkRecordFillBounds(), which itself doesn't make total sense yet.
130a723b576aed31a6eb2bdda6388e6bd779d04c6b0mtkleinDEF_TEST(RecordDraw_BBH, r) {
131a723b576aed31a6eb2bdda6388e6bd779d04c6b0mtklein    SkRecord record;
132a723b576aed31a6eb2bdda6388e6bd779d04c6b0mtklein    SkRecorder recorder(&record, W, H);
133a723b576aed31a6eb2bdda6388e6bd779d04c6b0mtklein    recorder.save();
134a723b576aed31a6eb2bdda6388e6bd779d04c6b0mtklein        recorder.clipRect(SkRect::MakeWH(400, 500));
135a723b576aed31a6eb2bdda6388e6bd779d04c6b0mtklein        recorder.scale(2, 2);
136a723b576aed31a6eb2bdda6388e6bd779d04c6b0mtklein        recorder.drawRect(SkRect::MakeWH(320, 240), SkPaint());
137a723b576aed31a6eb2bdda6388e6bd779d04c6b0mtklein    recorder.restore();
138a723b576aed31a6eb2bdda6388e6bd779d04c6b0mtklein
139937c9c7eb4e06d4d3bc495e129c7b8103a5d6c0fmtklein    TestBBH bbh;
1404d52afef5cf90a2fed3bb69db71675c6450ab397robertphillips    SkRecordFillBounds(SkRect::MakeWH(SkIntToScalar(W), SkIntToScalar(H)), record, &bbh);
141a723b576aed31a6eb2bdda6388e6bd779d04c6b0mtklein
1426bd41969a0f2283a7a7320bb0025551353c241ecmtklein    REPORTER_ASSERT(r, bbh.fEntries.count() == 5);
1436bd41969a0f2283a7a7320bb0025551353c241ecmtklein    for (int i = 0; i < bbh.fEntries.count(); i++) {
1446bd41969a0f2283a7a7320bb0025551353c241ecmtklein        REPORTER_ASSERT(r, bbh.fEntries[i].opIndex == (unsigned)i);
145a723b576aed31a6eb2bdda6388e6bd779d04c6b0mtklein
1466bd41969a0f2283a7a7320bb0025551353c241ecmtklein        REPORTER_ASSERT(r, sloppy_rect_eq(SkRect::MakeWH(400, 480), bbh.fEntries[i].bounds));
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
165937c9c7eb4e06d4d3bc495e129c7b8103a5d6c0fmtklein    TestBBH bbh;
1664d52afef5cf90a2fed3bb69db71675c6450ab397robertphillips    SkRecordFillBounds(SkRect::MakeWH(SkIntToScalar(W), SkIntToScalar(H)), record, &bbh);
1676bd41969a0f2283a7a7320bb0025551353c241ecmtklein    REPORTER_ASSERT(r, bbh.fEntries.count() == 2);
168937c9c7eb4e06d4d3bc495e129c7b8103a5d6c0fmtklein
169ed167acb7b494bf0aece05ac8a68b560782b027cmtklein    // We can make these next assertions confidently because SkRecordFillBounds
170ed167acb7b494bf0aece05ac8a68b560782b027cmtklein    // builds its bounds by overestimating font metrics in a platform-independent way.
171ed167acb7b494bf0aece05ac8a68b560782b027cmtklein    // If that changes, these tests will need to be more flexible.
1724d52afef5cf90a2fed3bb69db71675c6450ab397robertphillips    REPORTER_ASSERT(r, sloppy_rect_eq(bbh.fEntries[0].bounds, SkRect::MakeLTRB(0,  0, 140, 60)));
1734d52afef5cf90a2fed3bb69db71675c6450ab397robertphillips    REPORTER_ASSERT(r, sloppy_rect_eq(bbh.fEntries[1].bounds, SkRect::MakeLTRB(0, 20, 180, 100)));
174937c9c7eb4e06d4d3bc495e129c7b8103a5d6c0fmtklein}
175937c9c7eb4e06d4d3bc495e129c7b8103a5d6c0fmtklein
17600f30bdc9e34b013da54b4406f36556c5be8d041mtklein// Base test to ensure start/stop range is respected
17700f30bdc9e34b013da54b4406f36556c5be8d041mtkleinDEF_TEST(RecordDraw_PartialStartStop, r) {
17800f30bdc9e34b013da54b4406f36556c5be8d041mtklein    static const int kWidth = 10, kHeight = 10;
17900f30bdc9e34b013da54b4406f36556c5be8d041mtklein
18000f30bdc9e34b013da54b4406f36556c5be8d041mtklein    SkRect r1 = { 0, 0, kWidth,   kHeight };
18100f30bdc9e34b013da54b4406f36556c5be8d041mtklein    SkRect r2 = { 0, 0, kWidth,   kHeight/2 };
18200f30bdc9e34b013da54b4406f36556c5be8d041mtklein    SkRect r3 = { 0, 0, kWidth/2, kHeight };
18300f30bdc9e34b013da54b4406f36556c5be8d041mtklein    SkPaint p;
18400f30bdc9e34b013da54b4406f36556c5be8d041mtklein
18500f30bdc9e34b013da54b4406f36556c5be8d041mtklein    SkRecord record;
18600f30bdc9e34b013da54b4406f36556c5be8d041mtklein    SkRecorder recorder(&record, kWidth, kHeight);
18700f30bdc9e34b013da54b4406f36556c5be8d041mtklein    recorder.drawRect(r1, p);
18800f30bdc9e34b013da54b4406f36556c5be8d041mtklein    recorder.drawRect(r2, p);
18900f30bdc9e34b013da54b4406f36556c5be8d041mtklein    recorder.drawRect(r3, p);
19000f30bdc9e34b013da54b4406f36556c5be8d041mtklein
19100f30bdc9e34b013da54b4406f36556c5be8d041mtklein    SkRecord rerecord;
19200f30bdc9e34b013da54b4406f36556c5be8d041mtklein    SkRecorder canvas(&rerecord, kWidth, kHeight);
1934815fe5a0a497b676677fb4e4a0f05c511855490robertphillips    SkRecordPartialDraw(record, &canvas, r1, 1, 2, SkMatrix::I()); // replay just drawRect of r2
19400f30bdc9e34b013da54b4406f36556c5be8d041mtklein
19500f30bdc9e34b013da54b4406f36556c5be8d041mtklein    REPORTER_ASSERT(r, 3 == rerecord.count());
19600f30bdc9e34b013da54b4406f36556c5be8d041mtklein    assert_type<SkRecords::Save>     (r, rerecord, 0);
19700f30bdc9e34b013da54b4406f36556c5be8d041mtklein    assert_type<SkRecords::DrawRect> (r, rerecord, 1);
19800f30bdc9e34b013da54b4406f36556c5be8d041mtklein    assert_type<SkRecords::Restore>  (r, rerecord, 2);
19900f30bdc9e34b013da54b4406f36556c5be8d041mtklein
20000f30bdc9e34b013da54b4406f36556c5be8d041mtklein    const SkRecords::DrawRect* drawRect = assert_type<SkRecords::DrawRect>(r, rerecord, 1);
20100f30bdc9e34b013da54b4406f36556c5be8d041mtklein    REPORTER_ASSERT(r, drawRect->rect == r2);
20200f30bdc9e34b013da54b4406f36556c5be8d041mtklein}
20300f30bdc9e34b013da54b4406f36556c5be8d041mtklein
20400f30bdc9e34b013da54b4406f36556c5be8d041mtklein// Check that clears are converted to drawRects
20500f30bdc9e34b013da54b4406f36556c5be8d041mtkleinDEF_TEST(RecordDraw_PartialClear, r) {
20600f30bdc9e34b013da54b4406f36556c5be8d041mtklein    static const int kWidth = 10, kHeight = 10;
20700f30bdc9e34b013da54b4406f36556c5be8d041mtklein
20800f30bdc9e34b013da54b4406f36556c5be8d041mtklein    SkRect rect = { 0, 0, kWidth, kHeight };
20900f30bdc9e34b013da54b4406f36556c5be8d041mtklein
21000f30bdc9e34b013da54b4406f36556c5be8d041mtklein    SkRecord record;
21100f30bdc9e34b013da54b4406f36556c5be8d041mtklein    SkRecorder recorder(&record, kWidth, kHeight);
21200f30bdc9e34b013da54b4406f36556c5be8d041mtklein    recorder.clear(SK_ColorRED);
21300f30bdc9e34b013da54b4406f36556c5be8d041mtklein
21400f30bdc9e34b013da54b4406f36556c5be8d041mtklein    SkRecord rerecord;
21500f30bdc9e34b013da54b4406f36556c5be8d041mtklein    SkRecorder canvas(&rerecord, kWidth, kHeight);
2164815fe5a0a497b676677fb4e4a0f05c511855490robertphillips    SkRecordPartialDraw(record, &canvas, rect, 0, 1, SkMatrix::I()); // replay just the clear
21700f30bdc9e34b013da54b4406f36556c5be8d041mtklein
21800f30bdc9e34b013da54b4406f36556c5be8d041mtklein    REPORTER_ASSERT(r, 3 == rerecord.count());
21900f30bdc9e34b013da54b4406f36556c5be8d041mtklein    assert_type<SkRecords::Save>    (r, rerecord, 0);
22000f30bdc9e34b013da54b4406f36556c5be8d041mtklein    assert_type<SkRecords::DrawRect>(r, rerecord, 1);
22100f30bdc9e34b013da54b4406f36556c5be8d041mtklein    assert_type<SkRecords::Restore> (r, rerecord, 2);
22200f30bdc9e34b013da54b4406f36556c5be8d041mtklein
22300f30bdc9e34b013da54b4406f36556c5be8d041mtklein    const SkRecords::DrawRect* drawRect = assert_type<SkRecords::DrawRect>(r, rerecord, 1);
22400f30bdc9e34b013da54b4406f36556c5be8d041mtklein    REPORTER_ASSERT(r, drawRect->rect == rect);
22500f30bdc9e34b013da54b4406f36556c5be8d041mtklein    REPORTER_ASSERT(r, drawRect->paint.getColor() == SK_ColorRED);
22600f30bdc9e34b013da54b4406f36556c5be8d041mtklein}
227271a030f5d0d3c59715fbeffb31c761279f3f8caMike Klein
228271a030f5d0d3c59715fbeffb31c761279f3f8caMike Klein// A regression test for crbug.com/415468 and skbug.com/2957.
2298e393bf70ea2aab9ca31f52c15b518436c7b6055mtklein//
2308e393bf70ea2aab9ca31f52c15b518436c7b6055mtklein// This also now serves as a regression test for crbug.com/418417.  We used to adjust the
2318e393bf70ea2aab9ca31f52c15b518436c7b6055mtklein// bounds for the saveLayer, clip, and restore to be greater than the bounds of the picture.
2328e393bf70ea2aab9ca31f52c15b518436c7b6055mtklein// (We were applying the saveLayer paint to the bounds after restore, which makes no sense.)
233271a030f5d0d3c59715fbeffb31c761279f3f8caMike KleinDEF_TEST(RecordDraw_SaveLayerAffectsClipBounds, r) {
234271a030f5d0d3c59715fbeffb31c761279f3f8caMike Klein    SkRecord record;
235271a030f5d0d3c59715fbeffb31c761279f3f8caMike Klein    SkRecorder recorder(&record, 50, 50);
236271a030f5d0d3c59715fbeffb31c761279f3f8caMike Klein
237271a030f5d0d3c59715fbeffb31c761279f3f8caMike Klein    // We draw a rectangle with a long drop shadow.  We used to not update the clip
238271a030f5d0d3c59715fbeffb31c761279f3f8caMike Klein    // bounds based on SaveLayer paints, so the drop shadow could be cut off.
239271a030f5d0d3c59715fbeffb31c761279f3f8caMike Klein    SkPaint paint;
240234f036b3e731e06e616c5291157d3bb4fbfdee2sugoi    paint.setImageFilter(SkDropShadowImageFilter::Create(20, 0, 0, 0, SK_ColorBLACK,
241234f036b3e731e06e616c5291157d3bb4fbfdee2sugoi                         SkDropShadowImageFilter::kDrawShadowAndForeground_ShadowMode))->unref();
242271a030f5d0d3c59715fbeffb31c761279f3f8caMike Klein
243271a030f5d0d3c59715fbeffb31c761279f3f8caMike Klein    recorder.saveLayer(NULL, &paint);
244271a030f5d0d3c59715fbeffb31c761279f3f8caMike Klein        recorder.clipRect(SkRect::MakeWH(20, 40));
245271a030f5d0d3c59715fbeffb31c761279f3f8caMike Klein        recorder.drawRect(SkRect::MakeWH(20, 40), SkPaint());
246271a030f5d0d3c59715fbeffb31c761279f3f8caMike Klein    recorder.restore();
247271a030f5d0d3c59715fbeffb31c761279f3f8caMike Klein
2488e393bf70ea2aab9ca31f52c15b518436c7b6055mtklein    // Under the original bug, the right edge value of the drawRect would be 20 less than asserted
2498e393bf70ea2aab9ca31f52c15b518436c7b6055mtklein    // here because we intersected it with a clip that had not been adjusted for the drop shadow.
2508e393bf70ea2aab9ca31f52c15b518436c7b6055mtklein    //
2518e393bf70ea2aab9ca31f52c15b518436c7b6055mtklein    // The second bug showed up as adjusting the picture bounds (0,0,50,50) by the drop shadow too.
2528e393bf70ea2aab9ca31f52c15b518436c7b6055mtklein    // The saveLayer, clipRect, and restore bounds were incorrectly (0,0,70,50).
253271a030f5d0d3c59715fbeffb31c761279f3f8caMike Klein    TestBBH bbh;
2544d52afef5cf90a2fed3bb69db71675c6450ab397robertphillips    SkRecordFillBounds(SkRect::MakeWH(50, 50), record, &bbh);
2556bd41969a0f2283a7a7320bb0025551353c241ecmtklein    REPORTER_ASSERT(r, bbh.fEntries.count() == 4);
2566bd41969a0f2283a7a7320bb0025551353c241ecmtklein    REPORTER_ASSERT(r, sloppy_rect_eq(bbh.fEntries[0].bounds, SkRect::MakeLTRB(0, 0, 50, 50)));
2576bd41969a0f2283a7a7320bb0025551353c241ecmtklein    REPORTER_ASSERT(r, sloppy_rect_eq(bbh.fEntries[1].bounds, SkRect::MakeLTRB(0, 0, 50, 50)));
2586bd41969a0f2283a7a7320bb0025551353c241ecmtklein    REPORTER_ASSERT(r, sloppy_rect_eq(bbh.fEntries[2].bounds, SkRect::MakeLTRB(0, 0, 40, 40)));
2596bd41969a0f2283a7a7320bb0025551353c241ecmtklein    REPORTER_ASSERT(r, sloppy_rect_eq(bbh.fEntries[3].bounds, SkRect::MakeLTRB(0, 0, 50, 50)));
260271a030f5d0d3c59715fbeffb31c761279f3f8caMike Klein}
26165151754b9fdb6a968d7307764c20655d1b680a0piotaixr
2624d52afef5cf90a2fed3bb69db71675c6450ab397robertphillips// When a saveLayer provides an explicit bound and has a complex paint (e.g., one that
2634d52afef5cf90a2fed3bb69db71675c6450ab397robertphillips// affects transparent black), that bound should serve to shrink the area of the required
2644d52afef5cf90a2fed3bb69db71675c6450ab397robertphillips// backing store.
2654d52afef5cf90a2fed3bb69db71675c6450ab397robertphillipsDEF_TEST(RecordDraw_SaveLayerBoundsAffectsClipBounds, r) {
2664d52afef5cf90a2fed3bb69db71675c6450ab397robertphillips    SkRecord record;
2674d52afef5cf90a2fed3bb69db71675c6450ab397robertphillips    SkRecorder recorder(&record, 50, 50);
2684d52afef5cf90a2fed3bb69db71675c6450ab397robertphillips
2694d52afef5cf90a2fed3bb69db71675c6450ab397robertphillips    SkPaint p;
2704d52afef5cf90a2fed3bb69db71675c6450ab397robertphillips    p.setXfermodeMode(SkXfermode::kSrc_Mode);
2714d52afef5cf90a2fed3bb69db71675c6450ab397robertphillips
2724d52afef5cf90a2fed3bb69db71675c6450ab397robertphillips    SkRect bounds = SkRect::MakeLTRB(10, 10, 40, 40);
2734d52afef5cf90a2fed3bb69db71675c6450ab397robertphillips    recorder.saveLayer(&bounds, &p);
2744d52afef5cf90a2fed3bb69db71675c6450ab397robertphillips    recorder.drawRect(SkRect::MakeLTRB(20, 20, 30, 30), SkPaint());
2754d52afef5cf90a2fed3bb69db71675c6450ab397robertphillips    recorder.restore();
2764d52afef5cf90a2fed3bb69db71675c6450ab397robertphillips
2774d52afef5cf90a2fed3bb69db71675c6450ab397robertphillips    TestBBH bbh;
2784d52afef5cf90a2fed3bb69db71675c6450ab397robertphillips    SkRecordFillBounds(SkRect::MakeWH(50, 50), record, &bbh);
2794d52afef5cf90a2fed3bb69db71675c6450ab397robertphillips    REPORTER_ASSERT(r, bbh.fEntries.count() == 3);
2804d52afef5cf90a2fed3bb69db71675c6450ab397robertphillips    REPORTER_ASSERT(r, sloppy_rect_eq(bbh.fEntries[0].bounds, SkRect::MakeLTRB(10, 10, 40, 40)));
2814d52afef5cf90a2fed3bb69db71675c6450ab397robertphillips    REPORTER_ASSERT(r, sloppy_rect_eq(bbh.fEntries[1].bounds, SkRect::MakeLTRB(20, 20, 30, 30)));
2824d52afef5cf90a2fed3bb69db71675c6450ab397robertphillips    REPORTER_ASSERT(r, sloppy_rect_eq(bbh.fEntries[2].bounds, SkRect::MakeLTRB(10, 10, 40, 40)));
2834d52afef5cf90a2fed3bb69db71675c6450ab397robertphillips}
2844d52afef5cf90a2fed3bb69db71675c6450ab397robertphillips
28565151754b9fdb6a968d7307764c20655d1b680a0piotaixrDEF_TEST(RecordDraw_drawImage, r){
28665151754b9fdb6a968d7307764c20655d1b680a0piotaixr    class SkCanvasMock : public SkCanvas {
28765151754b9fdb6a968d7307764c20655d1b680a0piotaixr    public:
28865151754b9fdb6a968d7307764c20655d1b680a0piotaixr        SkCanvasMock(int width, int height) : INHERITED(width, height) {
28965151754b9fdb6a968d7307764c20655d1b680a0piotaixr            this->resetTestValues();
29065151754b9fdb6a968d7307764c20655d1b680a0piotaixr        }
29165151754b9fdb6a968d7307764c20655d1b680a0piotaixr        virtual ~SkCanvasMock() {}
29265151754b9fdb6a968d7307764c20655d1b680a0piotaixr        virtual void drawImage(const SkImage* image, SkScalar left, SkScalar top,
29365151754b9fdb6a968d7307764c20655d1b680a0piotaixr                               const SkPaint* paint = NULL) SK_OVERRIDE {
29465151754b9fdb6a968d7307764c20655d1b680a0piotaixr
29565151754b9fdb6a968d7307764c20655d1b680a0piotaixr            fDrawImageCalled = true;
29665151754b9fdb6a968d7307764c20655d1b680a0piotaixr        }
29765151754b9fdb6a968d7307764c20655d1b680a0piotaixr
29865151754b9fdb6a968d7307764c20655d1b680a0piotaixr        virtual void drawImageRect(const SkImage* image, const SkRect* src,
29965151754b9fdb6a968d7307764c20655d1b680a0piotaixr                                   const SkRect& dst,
30065151754b9fdb6a968d7307764c20655d1b680a0piotaixr                                   const SkPaint* paint = NULL) SK_OVERRIDE {
30165151754b9fdb6a968d7307764c20655d1b680a0piotaixr            fDrawImageRectCalled = true;
30265151754b9fdb6a968d7307764c20655d1b680a0piotaixr        }
30365151754b9fdb6a968d7307764c20655d1b680a0piotaixr
30465151754b9fdb6a968d7307764c20655d1b680a0piotaixr        void resetTestValues() {
30565151754b9fdb6a968d7307764c20655d1b680a0piotaixr            fDrawImageCalled = fDrawImageRectCalled = false;
30665151754b9fdb6a968d7307764c20655d1b680a0piotaixr        }
30765151754b9fdb6a968d7307764c20655d1b680a0piotaixr
30865151754b9fdb6a968d7307764c20655d1b680a0piotaixr        bool fDrawImageCalled;
30965151754b9fdb6a968d7307764c20655d1b680a0piotaixr        bool fDrawImageRectCalled;
31065151754b9fdb6a968d7307764c20655d1b680a0piotaixr    private:
31165151754b9fdb6a968d7307764c20655d1b680a0piotaixr        typedef SkCanvas INHERITED;
31265151754b9fdb6a968d7307764c20655d1b680a0piotaixr    };
31365151754b9fdb6a968d7307764c20655d1b680a0piotaixr
31465151754b9fdb6a968d7307764c20655d1b680a0piotaixr    SkAutoTUnref<SkSurface> surface(SkSurface::NewRasterPMColor(10, 10));
31565151754b9fdb6a968d7307764c20655d1b680a0piotaixr    surface->getCanvas()->clear(SK_ColorGREEN);
31665151754b9fdb6a968d7307764c20655d1b680a0piotaixr    SkAutoTUnref<SkImage> image(surface->newImageSnapshot());
31765151754b9fdb6a968d7307764c20655d1b680a0piotaixr
31865151754b9fdb6a968d7307764c20655d1b680a0piotaixr    SkCanvasMock canvas(10, 10);
31965151754b9fdb6a968d7307764c20655d1b680a0piotaixr
32065151754b9fdb6a968d7307764c20655d1b680a0piotaixr    {
32165151754b9fdb6a968d7307764c20655d1b680a0piotaixr        SkRecord record;
32265151754b9fdb6a968d7307764c20655d1b680a0piotaixr        SkRecorder recorder(&record, 10, 10);
32365151754b9fdb6a968d7307764c20655d1b680a0piotaixr        recorder.drawImage(image, 0, 0);
32465151754b9fdb6a968d7307764c20655d1b680a0piotaixr        SkRecordDraw(record, &canvas, 0, 0);
32565151754b9fdb6a968d7307764c20655d1b680a0piotaixr    }
32665151754b9fdb6a968d7307764c20655d1b680a0piotaixr    REPORTER_ASSERT(r, canvas.fDrawImageCalled);
32765151754b9fdb6a968d7307764c20655d1b680a0piotaixr    canvas.resetTestValues();
32865151754b9fdb6a968d7307764c20655d1b680a0piotaixr
32965151754b9fdb6a968d7307764c20655d1b680a0piotaixr    {
33065151754b9fdb6a968d7307764c20655d1b680a0piotaixr        SkRecord record;
33165151754b9fdb6a968d7307764c20655d1b680a0piotaixr        SkRecorder recorder(&record, 10, 10);
33265151754b9fdb6a968d7307764c20655d1b680a0piotaixr        recorder.drawImageRect(image, 0, SkRect::MakeWH(10, 10));
33365151754b9fdb6a968d7307764c20655d1b680a0piotaixr        SkRecordDraw(record, &canvas, 0, 0);
33465151754b9fdb6a968d7307764c20655d1b680a0piotaixr    }
33565151754b9fdb6a968d7307764c20655d1b680a0piotaixr    REPORTER_ASSERT(r, canvas.fDrawImageRectCalled);
33665151754b9fdb6a968d7307764c20655d1b680a0piotaixr
33765151754b9fdb6a968d7307764c20655d1b680a0piotaixr}
338