Add gn plumbing for mdbviz tool

Change-Id: I06e6b63c2742da069f48ff5d7defafc63a485af7
Reviewed-on: https://skia-review.googlesource.com/41842
Reviewed-by: Mike Klein <mtklein@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/BUILD.gn b/BUILD.gn
index 845feef..e4384d7 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -43,6 +43,7 @@
   skia_enable_tools = is_skia_dev_build
   skia_enable_vulkan_debug_layers = is_skia_dev_build && is_debug
   skia_vulkan_sdk = getenv("VULKAN_SDK")
+  skia_qt_path = getenv("QT_PATH")
   skia_compile_processors = false
 
   skia_jumper_clang = ""
@@ -1666,6 +1667,68 @@
     }
   }
 
+  if (skia_qt_path != "" && (is_win || is_linux || is_mac)) {
+    action_foreach("generate_mocs") {
+      script = "gn/call.py"
+      sources = [
+        "tools/mdbviz/MainWindow.h",
+      ]
+      outputs = [
+        "$target_gen_dir/mdbviz/{{source_name_part}}_moc.cpp",
+      ]
+      args = [
+        "$skia_qt_path" + "/bin/moc",
+        "{{source}}",
+        "-o",
+        "gen/mdbviz/{{source_name_part}}_moc.cpp",
+      ]
+    }
+    action_foreach("generate_resources") {
+      script = "gn/call.py"
+      sources = [
+        "tools/mdbviz/resources.qrc",
+      ]
+      outputs = [
+        "$target_gen_dir/mdbviz/{{source_name_part}}_res.cpp",
+      ]
+      args = [
+        "$skia_qt_path" + "/bin/rcc",
+        "{{source}}",
+        "-o",
+        "gen/mdbviz/{{source_name_part}}_res.cpp",
+      ]
+    }
+    test_app("mdbviz") {
+      if (is_win) {
+        # on Windows we need to disable some exception handling warnings due to the Qt headers
+        cflags = [ "/Wv:18" ]  # 18 -> VS2013, 19 -> VS2015, 1910 -> VS2017
+      }
+      sources = [
+        "tools/mdbviz/MainWindow.cpp",
+        "tools/mdbviz/main.cpp",
+
+        # generated files
+        "$target_gen_dir/mdbviz/MainWindow_moc.cpp",
+        "$target_gen_dir/mdbviz/resources_res.cpp",
+      ]
+      lib_dirs = [ "$skia_qt_path/lib" ]
+      libs = [
+        "Qt5Core.lib",
+        "Qt5Gui.lib",
+        "Qt5Widgets.lib",
+      ]
+      include_dirs = [
+        "$skia_qt_path/include",
+        "$skia_qt_path/include/QtWidgets",
+      ]
+      deps = [
+        ":generate_mocs",
+        ":generate_resources",
+        ":skia",
+      ]
+    }
+  }
+
   if (is_android && defined(ndk) && ndk != "") {
     copy("gdbserver") {
       sources = [
diff --git a/gn/call.py b/gn/call.py
new file mode 100644
index 0000000..edda821
--- /dev/null
+++ b/gn/call.py
@@ -0,0 +1,12 @@
+#!/usr/bin/env python
+#
+# Copyright 2017 Google Inc.
+#
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import subprocess
+import sys
+
+subprocess.check_call(sys.argv[1:])
+
diff --git a/tools/mdbviz/images/open.png b/tools/mdbviz/images/open.png
new file mode 100644
index 0000000..6043f4b
--- /dev/null
+++ b/tools/mdbviz/images/open.png
Binary files differ
diff --git a/tools/mdbviz/main.cpp b/tools/mdbviz/main.cpp
new file mode 100644
index 0000000..42abc2a
--- /dev/null
+++ b/tools/mdbviz/main.cpp
@@ -0,0 +1,30 @@
+/*
+ * 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 <QtWidgets>
+
+#include "mainwindow.h"
+
+int main(int argc, char *argv[])
+{
+    QApplication app(argc, argv);
+    QCoreApplication::setOrganizationName("Google");
+    QCoreApplication::setApplicationName("MDB Viz");
+    QCoreApplication::setApplicationVersion("0.0");
+
+    QCommandLineParser parser;
+    parser.setApplicationDescription(QCoreApplication::applicationName());
+    parser.addVersionOption();
+    parser.process(app);
+
+    MainWindow mainWin;
+    mainWin.show();
+
+    return app.exec();
+}
+
+
diff --git a/tools/mdbviz/mainwindow.cpp b/tools/mdbviz/mainwindow.cpp
new file mode 100644
index 0000000..c77bfd6
--- /dev/null
+++ b/tools/mdbviz/mainwindow.cpp
@@ -0,0 +1,119 @@
+/*
+ * 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 <QtWidgets>
+
+#include "MainWindow.h"
+
+#include "SkBitmap.h"
+#include "SkCanvas.h"
+#include "SkPicture.h"
+#include "SkStream.h"
+
+MainWindow::MainWindow()
+        : fImageLabel(new QLabel) {
+    this->setCentralWidget(fImageLabel);
+
+    this->createActions();
+    this->createStatusBar();
+    this->readSettings();
+    this->setUnifiedTitleAndToolBarOnMac(true);
+}
+
+void MainWindow::openFile() {
+    QString fileName = QFileDialog::getOpenFileName(this);
+    if (!fileName.isEmpty()) {
+        this->loadFile(fileName);
+    }
+}
+
+void MainWindow::loadFile(const QString &fileName) {
+    QFile file(fileName);
+    if (!file.open(QFile::ReadOnly | QFile::Text)) {
+        QMessageBox::warning(this, tr("MDB Viz"),
+                             tr("Cannot read file %1:\n%2.")
+                             .arg(QDir::toNativeSeparators(fileName), file.errorString()));
+        return;
+    }
+
+    QTextStream in(&file);
+#ifndef QT_NO_CURSOR
+    QApplication::setOverrideCursor(Qt::WaitCursor);
+#endif
+
+    std::string str = file.fileName().toLocal8Bit().constData();
+
+    std::unique_ptr<SkStream> stream = SkStream::MakeFromFile(str.c_str());
+    if (!stream) {
+        this->statusBar()->showMessage(tr("Couldn't read file"));
+        return;
+    }
+    sk_sp<SkPicture> pic(SkPicture::MakeFromStream(stream.get()));
+    if (!pic) {
+        this->statusBar()->showMessage(tr("Couldn't decode picture"));
+        return;
+    }
+
+    SkBitmap bm;
+
+    SkImageInfo ii = SkImageInfo::MakeN32Premul(1024, 1024);
+    bm.allocPixels(ii, 0);
+
+    SkCanvas canvas(bm);
+
+    canvas.drawPicture(pic);
+
+    fImage = QImage((uchar*)bm.getPixels(), bm.width(), bm.height(), QImage::Format_RGBA8888);
+    fImageLabel->setPixmap(QPixmap::fromImage(fImage));
+
+#ifndef QT_NO_CURSOR
+    QApplication::restoreOverrideCursor();
+#endif
+}
+
+void MainWindow::createActions() {
+
+    QMenu *fileMenu = this->menuBar()->addMenu(tr("&File"));
+    QToolBar *fileToolBar = this->addToolBar(tr("File"));
+
+    const QIcon openIcon = QIcon::fromTheme("document-open", QIcon(":/images/open.png"));
+    QAction *openAct = new QAction(openIcon, tr("&Open..."), this);
+    openAct->setShortcuts(QKeySequence::Open);
+    openAct->setStatusTip(tr("Open an existing file"));
+    connect(openAct, &QAction::triggered, this, &MainWindow::openFile);
+    fileMenu->addAction(openAct);
+    fileToolBar->addAction(openAct);
+
+    fileMenu->addSeparator();
+
+    const QIcon exitIcon = QIcon::fromTheme("application-exit");
+    QAction *exitAct = fileMenu->addAction(exitIcon, tr("E&xit"), this, &QWidget::close);
+    exitAct->setShortcuts(QKeySequence::Quit);
+    exitAct->setStatusTip(tr("Exit the application"));
+}
+
+void MainWindow::createStatusBar() {
+    this->statusBar()->showMessage(tr("Ready"));
+}
+
+void MainWindow::readSettings() {
+    QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName());
+    const QByteArray geometry = settings.value("geometry", QByteArray()).toByteArray();
+    if (geometry.isEmpty()) {
+        const QRect availableGeometry = QApplication::desktop()->availableGeometry(this);
+        resize(availableGeometry.width() / 3, availableGeometry.height() / 2);
+        move((availableGeometry.width() - width()) / 2,
+             (availableGeometry.height() - height()) / 2);
+    } else {
+        this->restoreGeometry(geometry);
+    }
+}
+
+void MainWindow::writeSettings() {
+    QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName());
+    settings.setValue("geometry", this->saveGeometry());
+}
diff --git a/tools/mdbviz/mainwindow.h b/tools/mdbviz/mainwindow.h
new file mode 100644
index 0000000..9aa9fcf
--- /dev/null
+++ b/tools/mdbviz/mainwindow.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef MainWindow_DEFINED
+#define MainWindow_DEFINED
+
+#include <QMainWindow>
+
+class QLabel;
+
+class MainWindow : public QMainWindow {
+    Q_OBJECT
+
+public:
+    MainWindow();
+
+private slots:
+    void openFile();
+
+private:
+    void loadFile(const QString &fileName);
+
+    void createActions();
+    void createStatusBar();
+    void readSettings();
+    void writeSettings();
+
+    QImage  fImage;
+    QLabel* fImageLabel;
+};
+
+#endif
diff --git a/tools/mdbviz/resources.qrc b/tools/mdbviz/resources.qrc
new file mode 100644
index 0000000..0d8713f
--- /dev/null
+++ b/tools/mdbviz/resources.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">

+<qresource>

+  <file>images/open.png</file>

+</qresource>

+</RCC>
\ No newline at end of file