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