1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2014 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "tests/Test.h"
9cb93a386Sopenharmony_ci
10cb93a386Sopenharmony_ci#include "include/core/SkPictureRecorder.h"
11cb93a386Sopenharmony_ci#include "include/core/SkShader.h"
12cb93a386Sopenharmony_ci#include "include/core/SkSurface.h"
13cb93a386Sopenharmony_ci#include "src/core/SkRecord.h"
14cb93a386Sopenharmony_ci#include "src/core/SkRecorder.h"
15cb93a386Sopenharmony_ci#include "src/core/SkRecords.h"
16cb93a386Sopenharmony_ci
17cb93a386Sopenharmony_ci#define COUNT(T) + 1
18cb93a386Sopenharmony_cistatic const int kRecordTypes = SK_RECORD_TYPES(COUNT);
19cb93a386Sopenharmony_ci#undef COUNT
20cb93a386Sopenharmony_ci
21cb93a386Sopenharmony_ci// Tallies the types of commands it sees into a histogram.
22cb93a386Sopenharmony_ciclass Tally {
23cb93a386Sopenharmony_cipublic:
24cb93a386Sopenharmony_ci    Tally() { sk_bzero(&fHistogram, sizeof(fHistogram)); }
25cb93a386Sopenharmony_ci
26cb93a386Sopenharmony_ci    template <typename T>
27cb93a386Sopenharmony_ci    void operator()(const T&) { ++fHistogram[T::kType]; }
28cb93a386Sopenharmony_ci
29cb93a386Sopenharmony_ci    template <typename T>
30cb93a386Sopenharmony_ci    int count() const { return fHistogram[T::kType]; }
31cb93a386Sopenharmony_ci
32cb93a386Sopenharmony_ci    void apply(const SkRecord& record) {
33cb93a386Sopenharmony_ci        for (int i = 0; i < record.count(); i++) {
34cb93a386Sopenharmony_ci            record.visit(i, *this);
35cb93a386Sopenharmony_ci        }
36cb93a386Sopenharmony_ci    }
37cb93a386Sopenharmony_ci
38cb93a386Sopenharmony_ciprivate:
39cb93a386Sopenharmony_ci    int fHistogram[kRecordTypes];
40cb93a386Sopenharmony_ci};
41cb93a386Sopenharmony_ci
42cb93a386Sopenharmony_ciDEF_TEST(Recorder, r) {
43cb93a386Sopenharmony_ci    SkRecord record;
44cb93a386Sopenharmony_ci    SkRecorder recorder(&record, 1920, 1080);
45cb93a386Sopenharmony_ci
46cb93a386Sopenharmony_ci    recorder.drawRect(SkRect::MakeWH(10, 10), SkPaint());
47cb93a386Sopenharmony_ci
48cb93a386Sopenharmony_ci    Tally tally;
49cb93a386Sopenharmony_ci    tally.apply(record);
50cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, 1 == tally.count<SkRecords::DrawRect>());
51cb93a386Sopenharmony_ci}
52cb93a386Sopenharmony_ci
53cb93a386Sopenharmony_ci// Regression test for leaking refs held by optional arguments.
54cb93a386Sopenharmony_ciDEF_TEST(Recorder_RefLeaking, r) {
55cb93a386Sopenharmony_ci    // We use SaveLayer to test:
56cb93a386Sopenharmony_ci    //   - its SkRect argument is optional and SkRect is POD.  Just testing that that works.
57cb93a386Sopenharmony_ci    //   - its SkPaint argument is optional and SkPaint is not POD.  The bug was here.
58cb93a386Sopenharmony_ci
59cb93a386Sopenharmony_ci    SkRect bounds = SkRect::MakeWH(320, 240);
60cb93a386Sopenharmony_ci    SkPaint paint;
61cb93a386Sopenharmony_ci    paint.setShader(SkShaders::Empty());
62cb93a386Sopenharmony_ci
63cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, paint.getShader()->unique());
64cb93a386Sopenharmony_ci    {
65cb93a386Sopenharmony_ci        SkRecord record;
66cb93a386Sopenharmony_ci        SkRecorder recorder(&record, 1920, 1080);
67cb93a386Sopenharmony_ci        recorder.saveLayer(&bounds, &paint);
68cb93a386Sopenharmony_ci        REPORTER_ASSERT(r, !paint.getShader()->unique());
69cb93a386Sopenharmony_ci    }
70cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, paint.getShader()->unique());
71cb93a386Sopenharmony_ci}
72cb93a386Sopenharmony_ci
73cb93a386Sopenharmony_ciDEF_TEST(Recorder_drawImage_takeReference, reporter) {
74cb93a386Sopenharmony_ci
75cb93a386Sopenharmony_ci    sk_sp<SkImage> image;
76cb93a386Sopenharmony_ci    {
77cb93a386Sopenharmony_ci        auto surface(SkSurface::MakeRasterN32Premul(100, 100));
78cb93a386Sopenharmony_ci        surface->getCanvas()->clear(SK_ColorGREEN);
79cb93a386Sopenharmony_ci        image = surface->makeImageSnapshot();
80cb93a386Sopenharmony_ci    }
81cb93a386Sopenharmony_ci
82cb93a386Sopenharmony_ci    {
83cb93a386Sopenharmony_ci        SkRecord record;
84cb93a386Sopenharmony_ci        SkRecorder recorder(&record, 100, 100);
85cb93a386Sopenharmony_ci
86cb93a386Sopenharmony_ci        // DrawImage is supposed to take a reference
87cb93a386Sopenharmony_ci        recorder.drawImage(image.get(), 0, 0, SkSamplingOptions());
88cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, !image->unique());
89cb93a386Sopenharmony_ci
90cb93a386Sopenharmony_ci        Tally tally;
91cb93a386Sopenharmony_ci        tally.apply(record);
92cb93a386Sopenharmony_ci
93cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, 1 == tally.count<SkRecords::DrawImage>());
94cb93a386Sopenharmony_ci    }
95cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, image->unique());
96cb93a386Sopenharmony_ci
97cb93a386Sopenharmony_ci    {
98cb93a386Sopenharmony_ci        SkRecord record;
99cb93a386Sopenharmony_ci        SkRecorder recorder(&record, 100, 100);
100cb93a386Sopenharmony_ci
101cb93a386Sopenharmony_ci        // DrawImageRect is supposed to take a reference
102cb93a386Sopenharmony_ci        recorder.drawImageRect(image.get(), SkRect::MakeWH(100, 100), SkRect::MakeWH(100, 100),
103cb93a386Sopenharmony_ci                               SkSamplingOptions(), nullptr, SkCanvas::kFast_SrcRectConstraint);
104cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, !image->unique());
105cb93a386Sopenharmony_ci
106cb93a386Sopenharmony_ci        Tally tally;
107cb93a386Sopenharmony_ci        tally.apply(record);
108cb93a386Sopenharmony_ci
109cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, 1 == tally.count<SkRecords::DrawImageRect>());
110cb93a386Sopenharmony_ci    }
111cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, image->unique());
112cb93a386Sopenharmony_ci}
113cb93a386Sopenharmony_ci
114cb93a386Sopenharmony_ci// skbug.com/10997
115cb93a386Sopenharmony_ciDEF_TEST(Recorder_boundsOverflow, reporter) {
116cb93a386Sopenharmony_ci    SkRect bigBounds = {SK_ScalarMin, SK_ScalarMin, SK_ScalarMax, SK_ScalarMax};
117cb93a386Sopenharmony_ci
118cb93a386Sopenharmony_ci    SkRecord record;
119cb93a386Sopenharmony_ci    SkRecorder recorder(&record, bigBounds);
120cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, recorder.imageInfo().width() > 0 &&
121cb93a386Sopenharmony_ci                              recorder.imageInfo().height() > 0);
122cb93a386Sopenharmony_ci}
123