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 "SkBitmap.h"
9#include "SkCanvas.h"
10#include "SkBBoxHierarchy.h"
11#include "SkPaint.h"
12#include "SkPicture.h"
13#include "SkPictureRecorder.h"
14#include "SkRectPriv.h"
15
16#include "Test.h"
17
18class PictureBBHTestBase {
19public:
20    PictureBBHTestBase(int playbackWidth, int playbackHeight,
21        int recordWidth, int recordHeight) {
22
23        fResultBitmap.allocN32Pixels(playbackWidth, playbackHeight);
24        fPictureWidth = recordWidth;
25        fPictureHeight = recordHeight;
26    }
27
28    virtual ~PictureBBHTestBase() { }
29
30    virtual void doTest(SkCanvas& playbackCanvas, SkCanvas& recordingCanvas) = 0;
31
32    void run(skiatest::Reporter* reporter) {
33        // No BBH
34        this->run(nullptr, reporter);
35
36        // With an R-Tree
37        SkRTreeFactory RTreeFactory;
38        this->run(&RTreeFactory, reporter);
39    }
40
41private:
42    void run(SkBBHFactory* factory, skiatest::Reporter* reporter) {
43        SkCanvas playbackCanvas(fResultBitmap);
44        playbackCanvas.clear(SK_ColorGREEN);
45        SkPictureRecorder recorder;
46        SkCanvas* recordCanvas = recorder.beginRecording(SkIntToScalar(fPictureWidth),
47                                                         SkIntToScalar(fPictureHeight),
48                                                         factory);
49        this->doTest(playbackCanvas, *recordCanvas);
50        sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());
51        playbackCanvas.drawPicture(picture);
52        REPORTER_ASSERT(reporter, SK_ColorGREEN == fResultBitmap.getColor(0, 0));
53    }
54
55    SkBitmap fResultBitmap;
56    int fPictureWidth, fPictureHeight;
57};
58
59// Test to verify the playback of an empty picture
60//
61class DrawEmptyPictureBBHTest : public PictureBBHTestBase {
62public:
63    DrawEmptyPictureBBHTest()
64        : PictureBBHTestBase(2, 2, 1, 1) {}
65    ~DrawEmptyPictureBBHTest() override {}
66
67    void doTest(SkCanvas&, SkCanvas&) override {}
68};
69
70// Test to verify the playback of a picture into a canvas that has
71// an empty clip.
72//
73class EmptyClipPictureBBHTest : public PictureBBHTestBase {
74public:
75    EmptyClipPictureBBHTest()
76        : PictureBBHTestBase(2, 2, 3, 3) {}
77
78    void doTest(SkCanvas& playbackCanvas, SkCanvas& recordingCanvas) override {
79        // intersect with out of bounds rect -> empty clip.
80        playbackCanvas.clipRect(SkRect::MakeXYWH(10, 10, 1, 1));
81        SkPaint paint;
82        recordingCanvas.drawRect(SkRect::MakeWH(3, 3), paint);
83    }
84
85    ~EmptyClipPictureBBHTest() override {}
86};
87
88DEF_TEST(PictureBBH, reporter) {
89
90    DrawEmptyPictureBBHTest emptyPictureTest;
91    emptyPictureTest.run(reporter);
92
93    EmptyClipPictureBBHTest emptyClipPictureTest;
94    emptyClipPictureTest.run(reporter);
95}
96
97DEF_TEST(RTreeMakeLargest, r) {
98    // A call to insert() with 2 or more rects and a bounds of SkRect::MakeLargest()
99    // used to fall into an infinite loop.
100
101    SkRTreeFactory factory;
102    std::unique_ptr<SkBBoxHierarchy> bbh{ factory(SkRectPriv::MakeLargest()) };
103
104    SkRect rects[] = { {0,0, 10,10}, {5,5,15,15} };
105    bbh->insert(rects, SK_ARRAY_COUNT(rects));
106    REPORTER_ASSERT(r, bbh->getRootBound() == SkRect::MakeWH(15,15));
107}
108