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