aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools/mdbviz/Model.cpp
blob: c2929568f44bd9492ea62c32d2ed6f3f29b3d3cd (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
/*
 * Copyright 2017 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include <memory>

#include "Model.h"

#include "SkBitmap.h"
#include "SkCanvas.h"
#include "SkDebugCanvas.h"
#include "SkPicture.h"
#include "SkStream.h"

Model::Model() : fCurOp(0) {
    SkImageInfo ii = SkImageInfo::MakeN32Premul(1024, 1024);
    fBM.allocPixels(ii, 0);
}

Model::~Model() {
    this->resetOpList();
}

Model::ErrorCode Model::load(const char* filename) {
    std::unique_ptr<SkStream> stream = SkStream::MakeFromFile(filename);
    if (!stream) {
        return ErrorCode::kCouldntOpenFile;
    }
    sk_sp<SkPicture> pic(SkPicture::MakeFromStream(stream.get()));
    if (!pic) {
        return ErrorCode::kCouldntDecodeSKP;
    }

    {
        std::unique_ptr<SkDebugCanvas> temp(new SkDebugCanvas(
                                                    SkScalarCeilToInt(pic->cullRect().width()),
                                                    SkScalarCeilToInt(pic->cullRect().height())));

        temp->setPicture(pic.get());
        pic->playback(temp.get());
        temp->setPicture(nullptr);
        this->resetOpList();
        temp->detachCommands(&fOps);
    }

    this->setCurOp(fOps.count()-1);

    return ErrorCode::kOK;
}

const char* Model::ErrorString(ErrorCode err) {
    static const char* kStrings[] = {
        "OK",
        "Couldn't read file",
        "Couldn't decode picture"
    };

    return kStrings[(int)err];
}

const char* Model::getOpName(int index) const {
    return SkDrawCommand::GetCommandString(fOps[index]->getType());
}

bool Model::isHierarchyPush(int index) const {
    SkDrawCommand::OpType type = fOps[index]->getType();

    return SkDrawCommand::kSave_OpType == type ||
           SkDrawCommand::kSaveLayer_OpType == type ||
           SkDrawCommand::kBeginDrawPicture_OpType == type;
}

bool Model::isHierarchyPop(int index) const {
    SkDrawCommand::OpType type = fOps[index]->getType();

    return SkDrawCommand::kRestore_OpType == type ||
           SkDrawCommand::kEndDrawPicture_OpType == type;
}

void Model::setCurOp(int curOp) {
    SkASSERT(curOp < fOps.count());

    if (curOp == fCurOp) {
        return; // the render state is already up to date
    }

    fCurOp = curOp;
    this->drawTo(fCurOp);
}

void Model::drawTo(int index) {
    SkASSERT(index < fOps.count());

    SkCanvas canvas(fBM);

    int saveCount = canvas.save();

    for (int i = 0; i <= index; ++i) {
        if (fOps[i]->isVisible()) {
            fOps[i]->execute(&canvas);
        }
    }

    canvas.restoreToCount(saveCount);
}

void Model::resetOpList() {
    for (int i = 0; i < fOps.count(); ++i) {
        delete fOps[i];
    }
    fOps.reset();
    fCurOp = 0;
}