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 "SkPictureRecorder.h" 11 #include "SkRecord.h" 12 #include "SkRecorder.h" 13 #include "SkRecords.h" 14 #include "SkShader.h" 15 #include "SkSurface.h" 16 17 #define COUNT(T) + 1 18 static const int kRecordTypes = SK_RECORD_TYPES(COUNT); 19 #undef COUNT 20 21 // Tallies the types of commands it sees into a histogram. 22 class Tally { 23 public: 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 (unsigned i = 0; i < record.count(); i++) { 34 record.visit<void>(i, *this); 35 } 36 } 37 38 private: 39 int fHistogram[kRecordTypes]; 40 }; 41 42 DEF_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 // All of Skia will work fine without support for comment groups, but 54 // Chrome's inspector can break. This serves as a simple regression test. 55 DEF_TEST(Recorder_CommentGroups, r) { 56 SkRecord record; 57 SkRecorder recorder(&record, 1920, 1080); 58 59 recorder.beginCommentGroup("test"); 60 recorder.addComment("foo", "bar"); 61 recorder.addComment("baz", "quux"); 62 recorder.endCommentGroup(); 63 64 Tally tally; 65 tally.apply(record); 66 67 REPORTER_ASSERT(r, 1 == tally.count<SkRecords::BeginCommentGroup>()); 68 REPORTER_ASSERT(r, 2 == tally.count<SkRecords::AddComment>()); 69 REPORTER_ASSERT(r, 1 == tally.count<SkRecords::EndCommentGroup>()); 70 } 71 72 // Regression test for leaking refs held by optional arguments. 73 DEF_TEST(Recorder_RefLeaking, r) { 74 // We use SaveLayer to test: 75 // - its SkRect argument is optional and SkRect is POD. Just testing that that works. 76 // - its SkPaint argument is optional and SkPaint is not POD. The bug was here. 77 78 SkRect bounds = SkRect::MakeWH(320, 240); 79 SkPaint paint; 80 paint.setShader(SkShader::CreateEmptyShader())->unref(); 81 82 REPORTER_ASSERT(r, paint.getShader()->unique()); 83 { 84 SkRecord record; 85 SkRecorder recorder(&record, 1920, 1080); 86 recorder.saveLayer(&bounds, &paint); 87 REPORTER_ASSERT(r, !paint.getShader()->unique()); 88 } 89 REPORTER_ASSERT(r, paint.getShader()->unique()); 90 } 91 92 DEF_TEST(Recorder_drawImage_takeReference, reporter) { 93 94 SkAutoTUnref<SkImage> image; 95 { 96 SkAutoTUnref<SkSurface> surface(SkSurface::NewRasterN32Premul(100, 100)); 97 surface->getCanvas()->clear(SK_ColorGREEN); 98 image.reset(surface->newImageSnapshot()); 99 } 100 { 101 SkRecord record; 102 SkRecorder recorder(&record, 100, 100); 103 104 // DrawImage is supposed to take a reference 105 recorder.drawImage(image.get(), 0, 0); 106 REPORTER_ASSERT(reporter, !image->unique()); 107 108 Tally tally; 109 tally.apply(record); 110 111 REPORTER_ASSERT(reporter, 1 == tally.count<SkRecords::DrawImage>()); 112 } 113 REPORTER_ASSERT(reporter, image->unique()); 114 115 { 116 SkRecord record; 117 SkRecorder recorder(&record, 100, 100); 118 119 // DrawImageRect is supposed to take a reference 120 recorder.drawImageRect(image.get(), 0, SkRect::MakeWH(100, 100)); 121 REPORTER_ASSERT(reporter, !image->unique()); 122 123 Tally tally; 124 tally.apply(record); 125 126 REPORTER_ASSERT(reporter, 1 == tally.count<SkRecords::DrawImageRect>()); 127 } 128 REPORTER_ASSERT(reporter, image->unique()); 129 } 130