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<void>(i, *this);
72             }
73 
74             --fIndent;
75         }
76     }
77 
78 private:
79     template <typename T>
printNameAndTime(const T & command,double ns)80     void printNameAndTime(const T& 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         puts(NameOf(command));
93     }
94 
95     template <typename T>
NameOf(const T &)96     static const char* NameOf(const T&) {
97     #define CASE(U) case SkRecords::U##_Type: return #U;
98         switch(T::kType) { SK_RECORD_TYPES(CASE); }
99     #undef CASE
100         SkDEBUGFAIL("Unknown T");
101         return "Unknown T";
102     }
103 
NameOf(const SkRecords::SaveLayer &)104     static const char* NameOf(const SkRecords::SaveLayer&) {
105         return "\x1b[31;1mSaveLayer\x1b[0m";  // Bold red.
106     }
107 
108     int fDigits;
109     int fIndent;
110     int fIndex;
111     SkRecords::Draw fDraw;
112     const bool fTimeWithCommand;
113 };
114 
115 }  // namespace
116 
DumpRecord(const SkRecord & record,SkCanvas * canvas,bool timeWithCommand)117 void DumpRecord(const SkRecord& record,
118                   SkCanvas* canvas,
119                   bool timeWithCommand) {
120     Dumper dumper(canvas, record.count(), timeWithCommand);
121     for (int i = 0; i < record.count(); i++) {
122         record.visit<void>(i, dumper);
123     }
124 }
125