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