/* * 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 #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 stream = SkStream::MakeFromFile(filename); if (!stream) { return ErrorCode::kCouldntOpenFile; } sk_sp pic(SkPicture::MakeFromStream(stream.get())); if (!pic) { return ErrorCode::kCouldntDecodeSKP; } { std::unique_ptr 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; }