aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools/dump_record.cpp
blob: 86911555257dd60f0181a2ae4de42b906f4e0d08 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/*
 * Copyright 2014 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include <stdio.h>

#include "LazyDecodeBitmap.h"
#include "SkCommandLineFlags.h"
#include "SkGraphics.h"
#include "SkOSFile.h"
#include "SkPicture.h"
#include "SkRecord.h"
#include "SkRecordOpts.h"
#include "SkRecorder.h"
#include "SkStream.h"

DEFINE_string2(skps, r, "", ".SKPs to dump.");
DEFINE_string(match, "", "The usual filters on file names to dump.");
DEFINE_bool2(optimize, O, false, "Run SkRecordOptimize before dumping.");

class Dumper {
public:
    Dumper() : fIndent(0) {}

    template <typename T>
    void operator()(const T& command) {
        this->printIndentedName(command);
    }

    void operator()(const SkRecords::Restore& command) {
        --fIndent;
        this->printIndentedName(command);
    }

    void operator()(const SkRecords::Save& command) {
        this->printIndentedName(command);
        ++fIndent;
    }

    void operator()(const SkRecords::SaveLayer& command) {
        this->printIndentedName(command);
        ++fIndent;
    }

private:
    template <typename T>
    void printIndentedName(const T& command) {
        for (int i = 0; i < fIndent; i++) {
            putchar('\t');
        }
        puts(NameOf(command));
    }

    template <typename T>
    static const char* NameOf(const T&) {
    #define CASE(U) case SkRecords::U##_Type: return #U;
        switch(T::kType) { SK_RECORD_TYPES(CASE); }
    #undef CASE
        SkDEBUGFAIL("Unknown T");
        return "Unknown T";
    }

    static const char* NameOf(const SkRecords::SaveLayer&) {
        return "\x1b[31;1mSaveLayer\x1b[0m";  // Bold red.
    }

    int fIndent;
};


static void dump(const char* name, const SkRecord& record) {
    Dumper dumper;

    unsigned count = record.count();
    int digits = 0;
    while (count > 0) {
        count /= 10;
        digits++;
    }

    printf("%s %s\n", FLAGS_optimize ? "optimized" : "not-optimized", name);
    for (unsigned i = 0; i < record.count(); i++) {
        printf("%*d ", digits, i);
        record.visit(i, dumper);
    }
}

int tool_main(int argc, char** argv);
int tool_main(int argc, char** argv) {
    SkCommandLineFlags::Parse(argc, argv);
    SkAutoGraphics ag;

    for (int i = 0; i < FLAGS_skps.count(); i++) {
        if (SkCommandLineFlags::ShouldSkip(FLAGS_match, FLAGS_skps[i])) {
            continue;
        }

        SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(FLAGS_skps[i]));
        if (!stream) {
            SkDebugf("Could not read %s.\n", FLAGS_skps[i]);
            exit(1);
        }
        SkAutoTUnref<SkPicture> src(
                SkPicture::CreateFromStream(stream, sk_tools::LazyDecodeBitmap));
        if (!src) {
            SkDebugf("Could not read %s as an SkPicture.\n", FLAGS_skps[i]);
            exit(1);
        }

        SkRecord record;
        SkRecorder canvas(SkRecorder::kWriteOnly_Mode, &record, src->width(), src->height());
        src->draw(&canvas);

        if (FLAGS_optimize) {
            SkRecordOptimize(&record);
        }

        dump(FLAGS_skps[i], record);
    }

    return 0;
}

#if !defined SK_BUILD_FOR_IOS
int main(int argc, char * const argv[]) {
    return tool_main(argc, (char**) argv);
}
#endif