aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/GrAuditTrail.cpp
blob: 6ff04d114460fdec628aaaa4984af1ff70ab670f (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
/*
 * Copyright 2016 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "GrAuditTrail.h"

void GrAuditTrail::JsonifyTArray(SkString* json, const char* name, const FrameArray& array) {
    if (array.count()) {
        json->appendf("\"%s\": [", name);
        for (int i = 0; i < array.count(); i++) {
            json->append(array[i]->toJson());
            if (i < array.count() - 1) {
                json->append(",");
            }
        }
        json->append("]");
    }
}

// This will pretty print a very small subset of json
// The parsing rules are straightforward, aside from the fact that we do not want an extra newline
// before ',' and after '}', so we have a comma exception rule.
class PrettyPrintJson {
public:
    SkString prettify(const SkString& json) {
        fPrettyJson.reset();
        fTabCount = 0;
        fFreshLine = false;
        fCommaException = false;
        for (size_t i = 0; i < json.size(); i++) {
            if ('[' == json[i] || '{' == json[i]) {
                this->newline();
                this->appendChar(json[i]);
                fTabCount++;
                this->newline();
            } else if (']' == json[i] || '}' == json[i]) {
                fTabCount--;
                this->newline();
                this->appendChar(json[i]);
                fCommaException = true;
            } else if (',' == json[i]) {
                this->appendChar(json[i]);
                this->newline();
            } else {
                this->appendChar(json[i]);
            }
        }
        return fPrettyJson;
    }
private:
    void appendChar(char appendee) {
        if (fCommaException && ',' != appendee) {
            this->newline();
        }
        this->tab();
        fPrettyJson += appendee;
        fFreshLine = false;
        fCommaException = false;
    }

    void tab() {
        if (fFreshLine) {
            for (int i = 0; i < fTabCount; i++) {
                fPrettyJson += '\t';
            }
        }
    }

    void newline() {
        if (!fFreshLine) {
            fFreshLine = true;
            fPrettyJson += '\n';
        }
    }

    SkString fPrettyJson;
    int fTabCount;
    bool fFreshLine;
    bool fCommaException;
};

static SkString pretty_print_json(SkString json) {
    class PrettyPrintJson prettyPrintJson;
    return prettyPrintJson.prettify(json);
}

SkString GrAuditTrail::toJson() const {
    SkString json;
    json.append("{");
    JsonifyTArray(&json, "Stacks", fFrames);
    json.append("}");

    // TODO if this becomes a performance issue we should make pretty print configurable
    return pretty_print_json(json);
}

SkString GrAuditTrail::Frame::toJson() const {
    SkString json;
    json.append("{");
    json.appendf("\"Name\": \"%s\",", fName);
    JsonifyTArray(&json, "Frames", fChildren);
    json.append("}");
    return json;
}

SkString GrAuditTrail::Batch::toJson() const {
    SkString json;
    json.append("{");
    json.appendf("\"Name\": \"%s\",", fName);
    json.append("\"Bounds\": {");
    json.appendf("\"Left\": %f,", fBounds.fLeft);
    json.appendf("\"Right\": %f,", fBounds.fRight);
    json.appendf("\"Top\": %f,", fBounds.fTop);
    json.appendf("\"Bottom\": %f", fBounds.fBottom);
    json.append("}");
    json.append("}");
    return json;
}