• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2017 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 <memory>
9 
10 #include "tools/mdbviz/Model.h"
11 
12 #include "include/core/SkBitmap.h"
13 #include "include/core/SkCanvas.h"
14 #include "include/core/SkPicture.h"
15 #include "include/core/SkStream.h"
16 #include "tools/debugger/DebugCanvas.h"
17 
Model()18 Model::Model() : fCurOp(0) {
19     SkImageInfo ii = SkImageInfo::MakeN32Premul(1024, 1024);
20     fBM.allocPixels(ii, 0);
21 }
22 
~Model()23 Model::~Model() {
24     this->resetOpsTask();
25 }
26 
load(const char * filename)27 Model::ErrorCode Model::load(const char* filename) {
28     std::unique_ptr<SkStream> stream = SkStream::MakeFromFile(filename);
29     if (!stream) {
30         return ErrorCode::kCouldntOpenFile;
31     }
32     sk_sp<SkPicture> pic(SkPicture::MakeFromStream(stream.get()));
33     if (!pic) {
34         return ErrorCode::kCouldntDecodeSKP;
35     }
36 
37     {
38         std::unique_ptr<DebugCanvas> temp(
39                 new DebugCanvas(SkScalarCeilToInt(pic->cullRect().width()),
40                                 SkScalarCeilToInt(pic->cullRect().height())));
41 
42         temp->setPicture(pic.get());
43         pic->playback(temp.get());
44         temp->setPicture(nullptr);
45         this->resetOpsTask();
46         temp->detachCommands(&fOps);
47     }
48 
49     this->setCurOp(fOps.count()-1);
50 
51     return ErrorCode::kOK;
52 }
53 
ErrorString(ErrorCode err)54 const char* Model::ErrorString(ErrorCode err) {
55     static const char* kStrings[] = {
56         "OK",
57         "Couldn't read file",
58         "Couldn't decode picture"
59     };
60 
61     return kStrings[(int)err];
62 }
63 
getOpName(int index) const64 const char* Model::getOpName(int index) const {
65     return DrawCommand::GetCommandString(fOps[index]->getType());
66 }
67 
isHierarchyPush(int index) const68 bool Model::isHierarchyPush(int index) const {
69     DrawCommand::OpType type = fOps[index]->getType();
70 
71     return DrawCommand::kSave_OpType == type || DrawCommand::kSaveLayer_OpType == type ||
72            DrawCommand::kBeginDrawPicture_OpType == type;
73 }
74 
isHierarchyPop(int index) const75 bool Model::isHierarchyPop(int index) const {
76     DrawCommand::OpType type = fOps[index]->getType();
77 
78     return DrawCommand::kRestore_OpType == type || DrawCommand::kEndDrawPicture_OpType == type;
79 }
80 
setCurOp(int curOp)81 void Model::setCurOp(int curOp) {
82     SkASSERT(curOp < fOps.count());
83 
84     if (curOp == fCurOp) {
85         return; // the render state is already up to date
86     }
87 
88     fCurOp = curOp;
89     this->drawTo(fCurOp);
90 }
91 
drawTo(int index)92 void Model::drawTo(int index) {
93     SkASSERT(index < fOps.count());
94 
95     SkCanvas canvas(fBM);
96 
97     int saveCount = canvas.save();
98 
99     for (int i = 0; i <= index; ++i) {
100         if (fOps[i]->isVisible()) {
101             fOps[i]->execute(&canvas);
102         }
103     }
104 
105     canvas.restoreToCount(saveCount);
106 }
107 
resetOpsTask()108 void Model::resetOpsTask() {
109     for (int i = 0; i < fOps.count(); ++i) {
110         delete fOps[i];
111     }
112     fOps.reset();
113     fCurOp = 0;
114 }
115