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 "RecordTestUtils.h" 9 #include "SkBitmap.h" 10 #include "SkImageInfo.h" 11 #include "SkRecord.h" 12 #include "SkRecords.h" 13 #include "SkShader.h" 14 #include "Test.h" 15 16 #include <new> 17 18 // Sums the area of any DrawRect command it sees. 19 class AreaSummer { 20 public: 21 AreaSummer() : fArea(0) {} 22 23 template <typename T> void operator()(const T&) { } 24 25 void operator()(const SkRecords::DrawRect& draw) { 26 fArea += (int)(draw.rect.width() * draw.rect.height()); 27 } 28 29 int area() const { return fArea; } 30 31 void apply(const SkRecord& record) { 32 for (int i = 0; i < record.count(); i++) { 33 record.visit(i, *this); 34 } 35 } 36 37 private: 38 int fArea; 39 }; 40 41 // Scales out the bottom-right corner of any DrawRect command it sees by 2x. 42 struct Stretch { 43 template <typename T> void operator()(T*) {} 44 void operator()(SkRecords::DrawRect* draw) { 45 draw->rect.fRight *= 2; 46 draw->rect.fBottom *= 2; 47 } 48 49 void apply(SkRecord* record) { 50 for (int i = 0; i < record->count(); i++) { 51 record->mutate(i, *this); 52 } 53 } 54 }; 55 56 #define APPEND(record, type, ...) new (record.append<type>()) type{__VA_ARGS__} 57 58 // Basic tests for the low-level SkRecord code. 59 DEF_TEST(Record, r) { 60 SkRecord record; 61 62 // Add a simple DrawRect command. 63 SkRect rect = SkRect::MakeWH(10, 10); 64 SkPaint paint; 65 APPEND(record, SkRecords::DrawRect, paint, rect); 66 67 // Its area should be 100. 68 AreaSummer summer; 69 summer.apply(record); 70 REPORTER_ASSERT(r, summer.area() == 100); 71 72 // Scale 2x. 73 Stretch stretch; 74 stretch.apply(&record); 75 76 // Now its area should be 100 + 400. 77 summer.apply(record); 78 REPORTER_ASSERT(r, summer.area() == 500); 79 } 80 81 DEF_TEST(Record_defrag, r) { 82 SkRecord record; 83 APPEND(record, SkRecords::Save); 84 APPEND(record, SkRecords::ClipRect); 85 APPEND(record, SkRecords::NoOp); 86 APPEND(record, SkRecords::DrawRect); 87 APPEND(record, SkRecords::NoOp); 88 APPEND(record, SkRecords::NoOp); 89 APPEND(record, SkRecords::Restore); 90 REPORTER_ASSERT(r, record.count() == 7); 91 92 record.defrag(); 93 REPORTER_ASSERT(r, record.count() == 4); 94 assert_type<SkRecords::Save >(r, record, 0); 95 assert_type<SkRecords::ClipRect>(r, record, 1); 96 assert_type<SkRecords::DrawRect>(r, record, 2); 97 assert_type<SkRecords::Restore >(r, record, 3); 98 } 99 100 #undef APPEND 101 102 template <typename T> 103 static bool is_aligned(const T* p) { 104 return (((uintptr_t)p) & (sizeof(T) - 1)) == 0; 105 } 106 107 DEF_TEST(Record_Alignment, r) { 108 SkRecord record; 109 REPORTER_ASSERT(r, is_aligned(record.alloc<uint8_t>())); 110 REPORTER_ASSERT(r, is_aligned(record.alloc<uint16_t>())); 111 REPORTER_ASSERT(r, is_aligned(record.alloc<uint32_t>())); 112 REPORTER_ASSERT(r, is_aligned(record.alloc<void*>())); 113 114 // It's not clear if we care that 8-byte values are aligned on 32-bit machines. 115 if (sizeof(void*) == 8) { 116 REPORTER_ASSERT(r, is_aligned(record.alloc<double>())); 117 REPORTER_ASSERT(r, is_aligned(record.alloc<uint64_t>())); 118 } 119 } 120