From deaf568e07f0b63c84c5909f14e2b7261b1653ae Mon Sep 17 00:00:00 2001 From: Robert Phillips Date: Wed, 6 Sep 2017 13:07:21 -0400 Subject: Solidify Model/View split Change-Id: Iecf034feaa009002b5f09c47052c915d22aec0e4 Reviewed-on: https://skia-review.googlesource.com/43040 Reviewed-by: Brian Osman Commit-Queue: Robert Phillips --- tools/mdbviz/Model.cpp | 100 ++++++++++++++++++++++++++++++++++++++++++++ tools/mdbviz/Model.h | 54 ++++++++++++++++++++++++ tools/mdbviz/mainwindow.cpp | 58 ++++++++++--------------- tools/mdbviz/mainwindow.h | 7 +++- 4 files changed, 180 insertions(+), 39 deletions(-) create mode 100644 tools/mdbviz/Model.cpp create mode 100644 tools/mdbviz/Model.h (limited to 'tools/mdbviz') diff --git a/tools/mdbviz/Model.cpp b/tools/mdbviz/Model.cpp new file mode 100644 index 0000000000..a3f8e1ae87 --- /dev/null +++ b/tools/mdbviz/Model.cpp @@ -0,0 +1,100 @@ +/* + * 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) { + return SkDrawCommand::GetCommandString(fOps[index]->getType()); +} + +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]; + } + fCurOp = 0; +} diff --git a/tools/mdbviz/Model.h b/tools/mdbviz/Model.h new file mode 100644 index 0000000000..773c148c3f --- /dev/null +++ b/tools/mdbviz/Model.h @@ -0,0 +1,54 @@ +/* + * 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 "SkBitmap.h" +#include "SkTDArray.h" + +class SkDrawCommand; + +// This class encapsulates the both the in-memory representation of the draw ops +// and the state of Skia/Ganesh's rendering. It should never have any Qt intrusions. +class Model { +public: + enum class ErrorCode { + kOK, + kCouldntOpenFile, + kCouldntDecodeSKP + }; + + Model(); + ~Model(); + + static const char* ErrorString(ErrorCode); + + // Replace the list of draw ops by reading the provided skp filename and + // reset the Skia draw state. It is up to the view portion to update itself + // after this call (i.e., rebuild the opList view). + ErrorCode load(const char* filename); + + // Update the rendering state to the provided op + void setCurOp(int curOp); + int curOp() const { return fCurOp; } + + int numOps() const { return fOps.count(); } + const char* getOpName(int index); + + // Get the bits visually representing the current rendering state + void* getPixels() const { return fBM.getPixels(); } + int width() const { return fBM.width(); } + int height() const { return fBM.height(); } + +protected: + // draw the ops up to (and including) the index-th op + void drawTo(int index); + void resetOpList(); + +private: + SkTDArray fOps; + int fCurOp; // The current op the rendering state is at + SkBitmap fBM; +}; diff --git a/tools/mdbviz/mainwindow.cpp b/tools/mdbviz/mainwindow.cpp index 5fb1e7e344..c09ad091fa 100644 --- a/tools/mdbviz/mainwindow.cpp +++ b/tools/mdbviz/mainwindow.cpp @@ -9,11 +9,6 @@ #include "MainWindow.h" -#include "SkBitmap.h" -#include "SkCanvas.h" -#include "SkPicture.h" -#include "SkStream.h" - MainWindow::MainWindow() { this->createActions(); this->createStatusBar(); @@ -35,16 +30,21 @@ void MainWindow::openFile() { void MainWindow::setupOpListWidget() { fOpListWidget->clear(); - for (int i = 0; i < fDebugCanvas->getSize(); i++) { + for (int i = 0; i < fModel.numOps(); i++) { QListWidgetItem *item = new QListWidgetItem(); - const SkDrawCommand* command = fDebugCanvas->getDrawCommandAt(i); - - SkString commandString = command->toString(); - item->setData(Qt::DisplayRole, commandString.c_str()); + item->setData(Qt::DisplayRole, fModel.getOpName(i)); fOpListWidget->addItem(item); } + + fOpListWidget->setCurrentRow(fModel.numOps()-1); +} + +void MainWindow::presentCurrentRenderState() { + fImage = QImage((uchar*)fModel.getPixels(), fModel.width(), fModel.height(), + QImage::Format_RGBA8888); + fImageLabel->setPixmap(QPixmap::fromImage(fImage)); } void MainWindow::loadFile(const QString &fileName) { @@ -63,37 +63,14 @@ void MainWindow::loadFile(const QString &fileName) { std::string str = file.fileName().toLocal8Bit().constData(); - std::unique_ptr stream = SkStream::MakeFromFile(str.c_str()); - if (!stream) { - this->statusBar()->showMessage(tr("Couldn't read file")); - return; - } - sk_sp pic(SkPicture::MakeFromStream(stream.get())); - if (!pic) { - this->statusBar()->showMessage(tr("Couldn't decode picture")); + Model::ErrorCode err = fModel.load(str.c_str()); + if (Model::ErrorCode::kOK != err) { + this->statusBar()->showMessage(Model::ErrorString(err)); return; } - fDebugCanvas.reset(new SkDebugCanvas(SkScalarCeilToInt(pic->cullRect().width()), - SkScalarCeilToInt(pic->cullRect().height()))); - - fDebugCanvas->setPicture(pic.get()); - pic->playback(fDebugCanvas.get()); - fDebugCanvas->setPicture(nullptr); - this->setupOpListWidget(); - - SkBitmap bm; - - SkImageInfo ii = SkImageInfo::MakeN32Premul(1024, 1024); - bm.allocPixels(ii, 0); - - SkCanvas canvas(bm); - - fDebugCanvas->draw(&canvas); - - fImage = QImage((uchar*)bm.getPixels(), bm.width(), bm.height(), QImage::Format_RGBA8888); - fImageLabel->setPixmap(QPixmap::fromImage(fImage)); + this->presentCurrentRenderState(); #ifndef QT_NO_CURSOR QApplication::restoreOverrideCursor(); @@ -138,6 +115,11 @@ void MainWindow::createActions() { aboutAct->setStatusTip(tr("Show the application's About box")); } +void MainWindow::onCurrentRowChanged(int currentRow) { + fModel.setCurOp(currentRow); + this->presentCurrentRenderState(); +} + void MainWindow::createStatusBar() { this->statusBar()->showMessage(tr("Ready")); } @@ -155,6 +137,8 @@ void MainWindow::createDockWindows() { this->addDockWidget(Qt::LeftDockWidgetArea, opListDock); fViewMenu->addAction(opListDock->toggleViewAction()); + + connect(fOpListWidget, SIGNAL(currentRowChanged(int)), this, SLOT(onCurrentRowChanged(int))); } // Main canvas Window diff --git a/tools/mdbviz/mainwindow.h b/tools/mdbviz/mainwindow.h index 80c86b0471..59e7b98c38 100644 --- a/tools/mdbviz/mainwindow.h +++ b/tools/mdbviz/mainwindow.h @@ -11,7 +11,7 @@ #include #include -#include "SkDebugCanvas.h" +#include "Model.h" class QLabel; class QListWidget; @@ -27,10 +27,13 @@ public: private slots: void openFile(); void about(); + void onCurrentRowChanged(int currentRow); private: void loadFile(const QString &fileName); void setupOpListWidget(); + void presentCurrentRenderState(); + void createActions(); void createStatusBar(); @@ -46,7 +49,7 @@ private: QMenu* fViewMenu; - std::unique_ptr fDebugCanvas; + Model fModel; }; #endif -- cgit v1.2.3