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