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 16 #define COUNT(T) + 1 17 static const int kRecordTypes = SK_RECORD_TYPES(COUNT); 18 #undef COUNT 19 20 // Tallies the types of commands it sees into a histogram. 21 class Tally { 22 public: 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 37 private: 38 int fHistogram[kRecordTypes]; 39 }; 40 41 DEF_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 // All of Skia will work fine without support for comment groups, but 53 // Chrome's inspector can break. This serves as a simple regression test. 54 DEF_TEST(Recorder_CommentGroups, r) { 55 SkRecord record; 56 SkRecorder recorder(&record, 1920, 1080); 57 58 recorder.beginCommentGroup("test"); 59 recorder.addComment("foo", "bar"); 60 recorder.addComment("baz", "quux"); 61 recorder.endCommentGroup(); 62 63 Tally tally; 64 tally.apply(record); 65 66 REPORTER_ASSERT(r, 1 == tally.count<SkRecords::BeginCommentGroup>()); 67 REPORTER_ASSERT(r, 2 == tally.count<SkRecords::AddComment>()); 68 REPORTER_ASSERT(r, 1 == tally.count<SkRecords::EndCommentGroup>()); 69 } 70 71 // DrawData is similar to comment groups. It doesn't affect drawing, but 72 // it's a pass-through we provide to the client. Again, a simple reg. test. 73 DEF_TEST(Recorder_DrawData, r) { 74 SkRecord record; 75 SkRecorder recorder(&record, 100, 100); 76 77 const char* data = "This sure is some data, eh?"; 78 recorder.drawData(data, strlen(data)); 79 80 Tally tally; 81 tally.apply(record); 82 REPORTER_ASSERT(r, 1 == tally.count<SkRecords::DrawData>()); 83 } 84 85 // Regression test for leaking refs held by optional arguments. 86 DEF_TEST(Recorder_RefLeaking, r) { 87 // We use SaveLayer to test: 88 // - its SkRect argument is optional and SkRect is POD. Just testing that that works. 89 // - its SkPaint argument is optional and SkPaint is not POD. The bug was here. 90 91 SkRect bounds = SkRect::MakeWH(320, 240); 92 SkPaint paint; 93 paint.setShader(SkShader::CreateEmptyShader())->unref(); 94 95 REPORTER_ASSERT(r, paint.getShader()->unique()); 96 { 97 SkRecord record; 98 SkRecorder recorder(&record, 1920, 1080); 99 recorder.saveLayer(&bounds, &paint); 100 REPORTER_ASSERT(r, !paint.getShader()->unique()); 101 } 102 REPORTER_ASSERT(r, paint.getShader()->unique()); 103 } 104 105 DEF_TEST(Recorder_RefPictures, r) { 106 SkAutoTUnref<SkPicture> pic; 107 108 { 109 SkPictureRecorder pr; 110 SkCanvas* canvas = pr.beginRecording(100, 100); 111 canvas->drawColor(SK_ColorRED); 112 pic.reset(pr.endRecording()); 113 } 114 REPORTER_ASSERT(r, pic->unique()); 115 116 { 117 SkRecord record; 118 SkRecorder recorder(&record, 100, 100); 119 recorder.drawPicture(pic); 120 // the recorder should now also be an owner 121 REPORTER_ASSERT(r, !pic->unique()); 122 } 123 // the recorder destructor should have released us (back to unique) 124 REPORTER_ASSERT(r, pic->unique()); 125 } 126 127 DEF_TEST(Recorder_IsDrawingToLayer, r) { 128 SkRecord record; 129 SkRecorder recorder(&record, 100, 100); 130 131 // We'll save, saveLayer, save, and saveLayer, then restore them all, 132 // checking that isDrawingToLayer() is correct at each step. 133 134 REPORTER_ASSERT(r, !recorder.isDrawingToLayer()); 135 recorder.save(); 136 REPORTER_ASSERT(r, !recorder.isDrawingToLayer()); 137 recorder.saveLayer(NULL, NULL); 138 REPORTER_ASSERT(r, recorder.isDrawingToLayer()); 139 recorder.save(); 140 REPORTER_ASSERT(r, recorder.isDrawingToLayer()); 141 recorder.saveLayer(NULL, NULL); 142 REPORTER_ASSERT(r, recorder.isDrawingToLayer()); 143 recorder.restore(); 144 REPORTER_ASSERT(r, recorder.isDrawingToLayer()); 145 recorder.restore(); 146 REPORTER_ASSERT(r, recorder.isDrawingToLayer()); 147 recorder.restore(); 148 REPORTER_ASSERT(r, !recorder.isDrawingToLayer()); 149 recorder.restore(); 150 REPORTER_ASSERT(r, !recorder.isDrawingToLayer()); 151 } 152 153