aboutsummaryrefslogtreecommitdiffhomepage
path: root/tests/RecorderTest.cpp
blob: d81bf059ef34e38659910c52538df15c658651de (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
/*
 * Copyright 2014 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "Test.h"

#include "SkPictureRecorder.h"
#include "SkRecord.h"
#include "SkRecorder.h"
#include "SkRecords.h"
#include "SkShader.h"
#include "SkSurface.h"

#define COUNT(T) + 1
static const int kRecordTypes = SK_RECORD_TYPES(COUNT);
#undef COUNT

// Tallies the types of commands it sees into a histogram.
class Tally {
public:
    Tally() { sk_bzero(&fHistogram, sizeof(fHistogram)); }

    template <typename T>
    void operator()(const T&) { ++fHistogram[T::kType]; }

    template <typename T>
    int count() const { return fHistogram[T::kType]; }

    void apply(const SkRecord& record) {
        for (unsigned i = 0; i < record.count(); i++) {
            record.visit<void>(i, *this);
        }
    }

private:
    int fHistogram[kRecordTypes];
};

DEF_TEST(Recorder, r) {
    SkRecord record;
    SkRecorder recorder(&record, 1920, 1080);

    recorder.drawRect(SkRect::MakeWH(10, 10), SkPaint());

    Tally tally;
    tally.apply(record);
    REPORTER_ASSERT(r, 1 == tally.count<SkRecords::DrawRect>());
}

// All of Skia will work fine without support for comment groups, but
// Chrome's inspector can break.  This serves as a simple regression test.
DEF_TEST(Recorder_CommentGroups, r) {
    SkRecord record;
    SkRecorder recorder(&record, 1920, 1080);

    recorder.beginCommentGroup("test");
        recorder.addComment("foo", "bar");
        recorder.addComment("baz", "quux");
    recorder.endCommentGroup();

    Tally tally;
    tally.apply(record);

    REPORTER_ASSERT(r, 1 == tally.count<SkRecords::BeginCommentGroup>());
    REPORTER_ASSERT(r, 2 == tally.count<SkRecords::AddComment>());
    REPORTER_ASSERT(r, 1 == tally.count<SkRecords::EndCommentGroup>());
}

// DrawData is similar to comment groups.  It doesn't affect drawing, but
// it's a pass-through we provide to the client.  Again, a simple reg. test.
DEF_TEST(Recorder_DrawData, r) {
    SkRecord record;
    SkRecorder recorder(&record, 100, 100);

    const char* data = "This sure is some data, eh?";
    recorder.drawData(data, strlen(data));

    Tally tally;
    tally.apply(record);
    REPORTER_ASSERT(r, 1 == tally.count<SkRecords::DrawData>());
}

// Regression test for leaking refs held by optional arguments.
DEF_TEST(Recorder_RefLeaking, r) {
    // We use SaveLayer to test:
    //   - its SkRect argument is optional and SkRect is POD.  Just testing that that works.
    //   - its SkPaint argument is optional and SkPaint is not POD.  The bug was here.

    SkRect bounds = SkRect::MakeWH(320, 240);
    SkPaint paint;
    paint.setShader(SkShader::CreateEmptyShader())->unref();

    REPORTER_ASSERT(r, paint.getShader()->unique());
    {
        SkRecord record;
        SkRecorder recorder(&record, 1920, 1080);
        recorder.saveLayer(&bounds, &paint);
        REPORTER_ASSERT(r, !paint.getShader()->unique());
    }
    REPORTER_ASSERT(r, paint.getShader()->unique());
}

DEF_TEST(Recorder_RefPictures, r) {
    SkAutoTUnref<SkPicture> pic;

    {
        SkPictureRecorder pr;
        SkCanvas* canvas = pr.beginRecording(100, 100);
        canvas->drawColor(SK_ColorRED);
        pic.reset(pr.endRecording());
    }
    REPORTER_ASSERT(r, pic->unique());

    {
        SkRecord record;
        SkRecorder recorder(&record, 100, 100);
        recorder.drawPicture(pic);
        // the recorder should now also be an owner
        REPORTER_ASSERT(r, !pic->unique());
    }
    // the recorder destructor should have released us (back to unique)
    REPORTER_ASSERT(r, pic->unique());
}

DEF_TEST(Recorder_IsDrawingToLayer, r) {
    SkRecord record;
    SkRecorder recorder(&record, 100, 100);

    // We'll save, saveLayer, save, and saveLayer, then restore them all,
    // checking that isDrawingToLayer() is correct at each step.

    REPORTER_ASSERT(r, !recorder.isDrawingToLayer());
    recorder.save();
        REPORTER_ASSERT(r, !recorder.isDrawingToLayer());
        recorder.saveLayer(NULL, NULL);
            REPORTER_ASSERT(r, recorder.isDrawingToLayer());
            recorder.save();
                REPORTER_ASSERT(r, recorder.isDrawingToLayer());
                recorder.saveLayer(NULL, NULL);
                    REPORTER_ASSERT(r, recorder.isDrawingToLayer());
                recorder.restore();
                REPORTER_ASSERT(r, recorder.isDrawingToLayer());
            recorder.restore();
            REPORTER_ASSERT(r, recorder.isDrawingToLayer());
        recorder.restore();
        REPORTER_ASSERT(r, !recorder.isDrawingToLayer());
    recorder.restore();
    REPORTER_ASSERT(r, !recorder.isDrawingToLayer());
}

DEF_TEST(Recorder_drawImage_takeReference, reporter) {

    SkAutoTUnref<SkImage> image;
    {
        SkAutoTUnref<SkSurface> surface(SkSurface::NewRasterPMColor(100, 100));
        surface->getCanvas()->clear(SK_ColorGREEN);
        image.reset(surface->newImageSnapshot());
    }
    {
        SkRecord record;
        SkRecorder recorder(&record, 100, 100);

        // DrawImage is supposed to take a reference
        recorder.drawImage(image.get(), 0, 0);
        REPORTER_ASSERT(reporter, !image->unique());

        Tally tally;
        tally.apply(record);

        REPORTER_ASSERT(reporter, 1 == tally.count<SkRecords::DrawImage>());
    }
    REPORTER_ASSERT(reporter, image->unique());

    {
        SkRecord record;
        SkRecorder recorder(&record, 100, 100);

        // DrawImageRect is supposed to take a reference
        recorder.drawImageRect(image.get(), 0, SkRect::MakeWH(100, 100));
        REPORTER_ASSERT(reporter, !image->unique());

        Tally tally;
        tally.apply(record);

        REPORTER_ASSERT(reporter, 1 == tally.count<SkRecords::DrawImageRect>());
    }
    REPORTER_ASSERT(reporter, image->unique());
}