1/*
2 * Copyright 2014 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "Test.h"
9
10#include "SkRecord.h"
11#include "SkRecorder.h"
12#include "SkRecords.h"
13
14#include "SkEmptyShader.h"
15
16#define COUNT(T) + 1
17static const int kRecordTypes = SK_RECORD_TYPES(COUNT);
18#undef COUNT
19
20// Tallies the types of commands it sees into a histogram.
21class Tally {
22public:
23    Tally() { sk_bzero(&fHistogram, sizeof(fHistogram)); }
24
25    template <typename T>
26    void operator()(const T&) { ++fHistogram[T::kType]; }
27
28    template <typename T>
29    int count() const { return fHistogram[T::kType]; }
30
31    void apply(const SkRecord& record) {
32        for (unsigned i = 0; i < record.count(); i++) {
33            record.visit<void>(i, *this);
34        }
35    }
36
37private:
38    int fHistogram[kRecordTypes];
39};
40
41DEF_TEST(Recorder, r) {
42    SkRecord record;
43    SkRecorder recorder(&record, 1920, 1080);
44
45    recorder.drawRect(SkRect::MakeWH(10, 10), SkPaint());
46
47    Tally tally;
48    tally.apply(record);
49    REPORTER_ASSERT(r, 1 == tally.count<SkRecords::DrawRect>());
50}
51
52// Regression test for leaking refs held by optional arguments.
53DEF_TEST(Recorder_RefLeaking, r) {
54    // We use SaveLayer to test:
55    //   - its SkRect argument is optional and SkRect is POD.  Just testing that that works.
56    //   - its SkPaint argument is optional and SkPaint is not POD.  The bug was here.
57
58    SkRect bounds = SkRect::MakeWH(320, 240);
59    SkPaint paint;
60    paint.setShader(SkNEW(SkEmptyShader))->unref();
61
62    REPORTER_ASSERT(r, paint.getShader()->unique());
63    {
64        SkRecord record;
65        SkRecorder recorder(&record, 1920, 1080);
66        recorder.saveLayer(&bounds, &paint);
67        REPORTER_ASSERT(r, !paint.getShader()->unique());
68    }
69    REPORTER_ASSERT(r, paint.getShader()->unique());
70}
71