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 <stdio.h> 9 10#include "SkRecord.h" 11#include "SkRecordDraw.h" 12 13#include "DumpRecord.h" 14#include "SkTime.h" 15 16namespace { 17 18class Dumper { 19public: 20 explicit Dumper(SkCanvas* canvas, int count, bool timeWithCommand) 21 : fDigits(0) 22 , fIndent(0) 23 , fIndex(0) 24 , fDraw(canvas, nullptr, nullptr, 0, nullptr) 25 , fTimeWithCommand(timeWithCommand) { 26 while (count > 0) { 27 count /= 10; 28 fDigits++; 29 } 30 } 31 32 template <typename T> 33 void operator()(const T& command) { 34 auto start = SkTime::GetNSecs(); 35 fDraw(command); 36 this->print(command, SkTime::GetNSecs() - start); 37 } 38 39 void operator()(const SkRecords::NoOp&) { 40 // Move on without printing anything. 41 } 42 43 template <typename T> 44 void print(const T& command, double ns) { 45 this->printNameAndTime(command, ns); 46 } 47 48 void print(const SkRecords::Restore& command, double ns) { 49 --fIndent; 50 this->printNameAndTime(command, ns); 51 } 52 53 void print(const SkRecords::Save& command, double ns) { 54 this->printNameAndTime(command, ns); 55 ++fIndent; 56 } 57 58 void print(const SkRecords::SaveLayer& command, double ns) { 59 this->printNameAndTime(command, ns); 60 ++fIndent; 61 } 62 63 void print(const SkRecords::DrawPicture& command, double ns) { 64 this->printNameAndTime(command, ns); 65 66 if (auto bp = command.picture->asSkBigPicture()) { 67 ++fIndent; 68 69 const SkRecord& record = *bp->record(); 70 for (int i = 0; i < record.count(); i++) { 71 record.visit(i, *this); 72 } 73 74 --fIndent; 75 } 76 } 77 78#if 1 79 void print(const SkRecords::DrawAnnotation& command, double ns) { 80 int us = (int)(ns * 1e-3); 81 if (!fTimeWithCommand) { 82 printf("%6dus ", us); 83 } 84 printf("%*d ", fDigits, fIndex++); 85 for (int i = 0; i < fIndent; i++) { 86 printf(" "); 87 } 88 if (fTimeWithCommand) { 89 printf("%6dus ", us); 90 } 91 printf("DrawAnnotation [%g %g %g %g] %s\n", 92 command.rect.left(), command.rect.top(), command.rect.right(), command.rect.bottom(), 93 command.key.c_str()); 94 } 95#endif 96 97private: 98 template <typename T> 99 void printNameAndTime(const T& command, double ns) { 100 int us = (int)(ns * 1e-3); 101 if (!fTimeWithCommand) { 102 printf("%6dus ", us); 103 } 104 printf("%*d ", fDigits, fIndex++); 105 for (int i = 0; i < fIndent; i++) { 106 printf(" "); 107 } 108 if (fTimeWithCommand) { 109 printf("%6dus ", us); 110 } 111 puts(NameOf(command)); 112 } 113 114 template <typename T> 115 static const char* NameOf(const T&) { 116 #define CASE(U) case SkRecords::U##_Type: return #U; 117 switch(T::kType) { SK_RECORD_TYPES(CASE); } 118 #undef CASE 119 SkDEBUGFAIL("Unknown T"); 120 return "Unknown T"; 121 } 122 123 static const char* NameOf(const SkRecords::SaveLayer&) { 124 return "\x1b[31;1mSaveLayer\x1b[0m"; // Bold red. 125 } 126 127 int fDigits; 128 int fIndent; 129 int fIndex; 130 SkRecords::Draw fDraw; 131 const bool fTimeWithCommand; 132}; 133 134} // namespace 135 136void DumpRecord(const SkRecord& record, 137 SkCanvas* canvas, 138 bool timeWithCommand) { 139 Dumper dumper(canvas, record.count(), timeWithCommand); 140 for (int i = 0; i < record.count(); i++) { 141 record.visit(i, dumper); 142 } 143} 144