Home | History | Annotate | Download | only in mdbviz
      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 "Model.h"
     11 
     12 #include "SkBitmap.h"
     13 #include "SkCanvas.h"
     14 #include "SkDebugCanvas.h"
     15 #include "SkPicture.h"
     16 #include "SkStream.h"
     17 
     18 Model::Model() : fCurOp(0) {
     19     SkImageInfo ii = SkImageInfo::MakeN32Premul(1024, 1024);
     20     fBM.allocPixels(ii, 0);
     21 }
     22 
     23 Model::~Model() {
     24     this->resetOpList();
     25 }
     26 
     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<SkDebugCanvas> temp(new SkDebugCanvas(
     39                                                     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->resetOpList();
     46         temp->detachCommands(&fOps);
     47     }
     48 
     49     this->setCurOp(fOps.count()-1);
     50 
     51     return ErrorCode::kOK;
     52 }
     53 
     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 
     64 const char* Model::getOpName(int index) const {
     65     return SkDrawCommand::GetCommandString(fOps[index]->getType());
     66 }
     67 
     68 bool Model::isHierarchyPush(int index) const {
     69     SkDrawCommand::OpType type = fOps[index]->getType();
     70 
     71     return SkDrawCommand::kSave_OpType == type ||
     72            SkDrawCommand::kSaveLayer_OpType == type ||
     73            SkDrawCommand::kBeginDrawPicture_OpType == type;
     74 }
     75 
     76 bool Model::isHierarchyPop(int index) const {
     77     SkDrawCommand::OpType type = fOps[index]->getType();
     78 
     79     return SkDrawCommand::kRestore_OpType == type ||
     80            SkDrawCommand::kEndDrawPicture_OpType == type;
     81 }
     82 
     83 void Model::setCurOp(int curOp) {
     84     SkASSERT(curOp < fOps.count());
     85 
     86     if (curOp == fCurOp) {
     87         return; // the render state is already up to date
     88     }
     89 
     90     fCurOp = curOp;
     91     this->drawTo(fCurOp);
     92 }
     93 
     94 void Model::drawTo(int index) {
     95     SkASSERT(index < fOps.count());
     96 
     97     SkCanvas canvas(fBM);
     98 
     99     int saveCount = canvas.save();
    100 
    101     for (int i = 0; i <= index; ++i) {
    102         if (fOps[i]->isVisible()) {
    103             fOps[i]->execute(&canvas);
    104         }
    105     }
    106 
    107     canvas.restoreToCount(saveCount);
    108 }
    109 
    110 void Model::resetOpList() {
    111     for (int i = 0; i < fOps.count(); ++i) {
    112         delete fOps[i];
    113     }
    114     fOps.reset();
    115     fCurOp = 0;
    116 }
    117