From f6670a63746fcec41e9227b819a7519b4a2db16f Mon Sep 17 00:00:00 2001
From: howard-stearns <howard.stearns@gmail.com>
Date: Thu, 18 Aug 2016 16:29:42 -0700
Subject: [PATCH] new optional aspect-ratio argument to snapshot chain
 (javascript through c++ display plugin). When non-zero, it pulls out the
 largest piece from the center that maintains that ratio.  Snapshot button
 uses 1.91.

---
 interface/src/Application.cpp                   |  4 ++--
 interface/src/Application.h                     |  2 +-
 .../src/scripting/WindowScriptingInterface.cpp  |  6 +++---
 .../src/scripting/WindowScriptingInterface.h    |  2 +-
 .../src/display-plugins/NullDisplayPlugin.cpp   |  2 +-
 .../src/display-plugins/NullDisplayPlugin.h     |  2 +-
 .../src/display-plugins/OpenGLDisplayPlugin.cpp | 17 ++++++++++++++---
 .../src/display-plugins/OpenGLDisplayPlugin.h   |  2 +-
 libraries/plugins/src/plugins/DisplayPlugin.h   |  2 +-
 scripts/system/snapshot.js                      |  2 +-
 10 files changed, 26 insertions(+), 15 deletions(-)

diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index 340597f18a..59ec1c0641 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -5130,13 +5130,13 @@ void Application::toggleLogDialog() {
     }
 }
 
-void Application::takeSnapshot(bool notify) {
+void Application::takeSnapshot(bool notify, float aspectRatio) {
     QMediaPlayer* player = new QMediaPlayer();
     QFileInfo inf = QFileInfo(PathUtils::resourcesPath() + "sounds/snap.wav");
     player->setMedia(QUrl::fromLocalFile(inf.absoluteFilePath()));
     player->play();
 
-    QString path = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getScreenshot());
+    QString path = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getScreenshot(aspectRatio));
 
     emit DependencyManager::get<WindowScriptingInterface>()->snapshotTaken(path, notify);
 }
diff --git a/interface/src/Application.h b/interface/src/Application.h
index 9fcce66f55..667969abf1 100644
--- a/interface/src/Application.h
+++ b/interface/src/Application.h
@@ -250,7 +250,7 @@ public:
     float getAvatarSimrate() const { return _avatarSimCounter.rate(); }
     float getAverageSimsPerSecond() const { return _simCounter.rate(); }
     
-    void takeSnapshot(bool notify);
+    void takeSnapshot(bool notify, float aspectRatio = 0.0f);
     void shareSnapshot(const QString& filename);
 
     model::SkyboxPointer getDefaultSkybox() const { return _defaultSkybox; }
diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp
index f843673c07..f68f6d212a 100644
--- a/interface/src/scripting/WindowScriptingInterface.cpp
+++ b/interface/src/scripting/WindowScriptingInterface.cpp
@@ -204,10 +204,10 @@ void WindowScriptingInterface::copyToClipboard(const QString& text) {
     QApplication::clipboard()->setText(text);
 }
 
-void WindowScriptingInterface::takeSnapshot(bool notify) {
+void WindowScriptingInterface::takeSnapshot(bool notify, float aspectRatio) {
     // only evil-doers call takeSnapshot from a random thread
-    qApp->postLambdaEvent([notify] {
-        qApp->takeSnapshot(notify);
+    qApp->postLambdaEvent([notify, aspectRatio] {
+        qApp->takeSnapshot(notify, aspectRatio);
     });
 }
 
diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h
index 15dc1a8004..ca82753598 100644
--- a/interface/src/scripting/WindowScriptingInterface.h
+++ b/interface/src/scripting/WindowScriptingInterface.h
@@ -55,7 +55,7 @@ public slots:
     QScriptValue save(const QString& title = "", const QString& directory = "",  const QString& nameFilter = "");
     void showAssetServer(const QString& upload = "");
     void copyToClipboard(const QString& text);
-    void takeSnapshot(bool notify);
+    void takeSnapshot(bool notify = true, float aspectRatio = 0.0f);
     void shareSnapshot(const QString& path);
 
 signals:
diff --git a/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp
index 5ee05fa2e3..a4777b087b 100644
--- a/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp
+++ b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp
@@ -31,6 +31,6 @@ void NullDisplayPlugin::submitFrame(const gpu::FramePointer& frame) {
     }
 }
 
-QImage NullDisplayPlugin::getScreenshot() const {
+QImage NullDisplayPlugin::getScreenshot(float aspectRatio) const {
     return QImage();
 }
diff --git a/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h
index 198c89ae78..1852ed53ee 100644
--- a/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h
+++ b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h
@@ -18,7 +18,7 @@ public:
     glm::uvec2 getRecommendedRenderSize() const override;
     bool hasFocus() const override;
     void submitFrame(const gpu::FramePointer& newFrame) override;
-    QImage getScreenshot() const override;
+    QImage getScreenshot(float aspectRatio = 0.0f) const override;
 private:
     static const QString NAME;
 };
diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp
index 905042cb79..7334191b75 100644
--- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp
+++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp
@@ -659,15 +659,26 @@ void OpenGLDisplayPlugin::withMainThreadContext(std::function<void()> f) const {
     _container->makeRenderingContextCurrent();
 }
 
-QImage OpenGLDisplayPlugin::getScreenshot() const {
+QImage OpenGLDisplayPlugin::getScreenshot(float aspectRatio) const {
     auto size = _compositeFramebuffer->getSize();
     if (isHmd()) {
         size.x /= 2;
     }
+    auto bestSize = size;
+    uvec2 corner(0);
+    if (aspectRatio != 0.0f) { // Pick out the largest piece of the center that produces the requested width/height aspectRatio
+        if (((size.y * aspectRatio) + 0.5f) < size.x) {
+            bestSize.x = round(size.y * aspectRatio);
+        } else {
+            bestSize.y = round(size.x / aspectRatio);
+        }
+        corner.x = round((size.x - bestSize.x) / 2.0f);
+        corner.y = round((size.y - bestSize.y) / 2.0f);
+    }
     auto glBackend = const_cast<OpenGLDisplayPlugin&>(*this).getGLBackend();
-    QImage screenshot(size.x, size.y, QImage::Format_ARGB32);
+    QImage screenshot(bestSize.x, bestSize.y, QImage::Format_ARGB32);
     withMainThreadContext([&] {
-        glBackend->downloadFramebuffer(_compositeFramebuffer, ivec4(uvec2(0), size), screenshot);
+        glBackend->downloadFramebuffer(_compositeFramebuffer, ivec4(corner, bestSize), screenshot);
     });
     return screenshot.mirrored(false, true);
 }
diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h
index 48f9a78eda..51b33c9bcd 100644
--- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h
+++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h
@@ -54,7 +54,7 @@ public:
         return getSurfaceSize();
     }
 
-    QImage getScreenshot() const override;
+    QImage getScreenshot(float aspectRatio = 0.0f) const override;
 
     float presentRate() const override;
 
diff --git a/libraries/plugins/src/plugins/DisplayPlugin.h b/libraries/plugins/src/plugins/DisplayPlugin.h
index 49c341cdcb..288cee3223 100644
--- a/libraries/plugins/src/plugins/DisplayPlugin.h
+++ b/libraries/plugins/src/plugins/DisplayPlugin.h
@@ -172,7 +172,7 @@ public:
     }
 
     // Fetch the most recently displayed image as a QImage
-    virtual QImage getScreenshot() const = 0;
+    virtual QImage getScreenshot(float aspectRatio = 0.0f) const = 0;
 
     // will query the underlying hmd api to compute the most recent head pose
     virtual bool beginFrameRender(uint32_t frameIndex) { return true; }
diff --git a/scripts/system/snapshot.js b/scripts/system/snapshot.js
index 92b16d31bc..5c893fad4a 100644
--- a/scripts/system/snapshot.js
+++ b/scripts/system/snapshot.js
@@ -116,7 +116,7 @@ function onClicked() {
 
     // take snapshot (with no notification)
     Script.setTimeout(function () {
-        Window.takeSnapshot(false);
+        Window.takeSnapshot(false, 1.91);
     }, SNAPSHOT_DELAY);
 }