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