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
16 namespace {
17
18 class Dumper {
19 public:
Dumper(SkCanvas * canvas,int count,bool timeWithCommand)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>
operator ()(const T & command)33 void operator()(const T& command) {
34 auto start = SkTime::GetNSecs();
35 fDraw(command);
36 this->print(command, SkTime::GetNSecs() - start);
37 }
38
operator ()(const SkRecords::NoOp &)39 void operator()(const SkRecords::NoOp&) {
40 // Move on without printing anything.
41 }
42
43 template <typename T>
print(const T & command,double ns)44 void print(const T& command, double ns) {
45 this->printNameAndTime(command, ns);
46 }
47
print(const SkRecords::Restore & command,double ns)48 void print(const SkRecords::Restore& command, double ns) {
49 --fIndent;
50 this->printNameAndTime(command, ns);
51 }
52
print(const SkRecords::Save & command,double ns)53 void print(const SkRecords::Save& command, double ns) {
54 this->printNameAndTime(command, ns);
55 ++fIndent;
56 }
57
print(const SkRecords::SaveLayer & command,double ns)58 void print(const SkRecords::SaveLayer& command, double ns) {
59 this->printNameAndTime(command, ns);
60 ++fIndent;
61 }
62
print(const SkRecords::DrawPicture & command,double ns)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
print(const SkRecords::DrawAnnotation & command,double ns)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
97 private:
98 template <typename T>
printNameAndTime(const T & command,double ns)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>
NameOf(const 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
NameOf(const SkRecords::SaveLayer &)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
DumpRecord(const SkRecord & record,SkCanvas * canvas,bool timeWithCommand)136 void 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