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