diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 7a270d3..29fbac4 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -60,6 +60,8 @@ set(SOURCES src/Commands/Quit.h src/Commands/Screenshot.cpp src/Commands/Screenshot.h + src/Commands/ScreenshotBase64.cpp + src/Commands/ScreenshotBase64.h src/Commands/SetProperty.cpp src/Commands/SetProperty.h src/Commands/Wait.cpp diff --git a/lib/include/Spix/TestServer.h b/lib/include/Spix/TestServer.h index 69d648a..92ccce2 100644 --- a/lib/include/Spix/TestServer.h +++ b/lib/include/Spix/TestServer.h @@ -66,6 +66,7 @@ class SPIX_EXPORT TestServer { std::vector getErrors(); void takeScreenshot(ItemPath targetItem, std::string filePath); + std::string takeScreenshotAsBase64(ItemPath targetItem); void quit(); protected: diff --git a/lib/src/AnyRpcServer.cpp b/lib/src/AnyRpcServer.cpp index 0c2957a..fb6c3c5 100644 --- a/lib/src/AnyRpcServer.cpp +++ b/lib/src/AnyRpcServer.cpp @@ -117,6 +117,10 @@ AnyRpcServer::AnyRpcServer(int anyrpcPort) return takeScreenshot(std::move(targetItem), std::move(filePath)); }); + utils::AddFunctionToAnyRpc(methodManager, "takeScreenshotAsBase64", + "Take a screenshot of the object and send as base64 string | takeScreenshotAsBase64(string pathToTargetedItem)", + [this](std::string targetItem) { return takeScreenshotAsBase64(std::move(targetItem)); }); + utils::AddFunctionToAnyRpc(methodManager, "quit", "Close the app | quit()", [this] { quit(); }); utils::AddFunctionToAnyRpc(methodManager, "command", diff --git a/lib/src/Commands/ScreenshotBase64.cpp b/lib/src/Commands/ScreenshotBase64.cpp new file mode 100644 index 0000000..fa126da --- /dev/null +++ b/lib/src/Commands/ScreenshotBase64.cpp @@ -0,0 +1,26 @@ +/*** + * Copyright (C) Falko Axmann. All rights reserved. + * Licensed under the MIT license. + * See LICENSE.txt file in the project root for full license information. + ****/ + +#include "ScreenshotBase64.h" + +#include +namespace spix { +namespace cmd { + +ScreenshotAsBase64::ScreenshotAsBase64(ItemPath targetItemPath, std::promise promise) +: m_itemPath {std::move(targetItemPath)} +, m_promise(std::move(promise)) +{ +} + +void ScreenshotAsBase64::execute(CommandEnvironment& env) +{ + auto value = env.scene().takeScreenshotAsBase64(m_itemPath); + m_promise.set_value(value); +} + +} // namespace cmd +} // namespace spix diff --git a/lib/src/Commands/ScreenshotBase64.h b/lib/src/Commands/ScreenshotBase64.h new file mode 100644 index 0000000..477bf17 --- /dev/null +++ b/lib/src/Commands/ScreenshotBase64.h @@ -0,0 +1,23 @@ +#pragma once + +#include "Command.h" +#include + +#include + +namespace spix { +namespace cmd { + +class ScreenshotAsBase64 : public Command { +public: + ScreenshotAsBase64(ItemPath targetItemPath, std::promise promise); + + void execute(CommandEnvironment& env) override; + +private: + ItemPath m_itemPath; + std::promise m_promise; +}; + +} // namespace cmd +} // namespace spix diff --git a/lib/src/Scene/Mock/MockScene.cpp b/lib/src/Scene/Mock/MockScene.cpp index c9a2d87..586eac9 100644 --- a/lib/src/Scene/Mock/MockScene.cpp +++ b/lib/src/Scene/Mock/MockScene.cpp @@ -28,6 +28,11 @@ void MockScene::takeScreenshot(const ItemPath&, const std::string&) { } +std::string MockScene::takeScreenshotAsBase64(const ItemPath&) +{ + return "Base64 String"; +} + void MockScene::addItemAtPath(MockItem item, const ItemPath& path) { m_items.emplace(std::make_pair(path.string(), std::move(item))); diff --git a/lib/src/Scene/Mock/MockScene.h b/lib/src/Scene/Mock/MockScene.h index 17a9bdb..8a9b757 100644 --- a/lib/src/Scene/Mock/MockScene.h +++ b/lib/src/Scene/Mock/MockScene.h @@ -25,7 +25,7 @@ class SPIX_EXPORT MockScene : public Scene { // Tasks void takeScreenshot(const ItemPath& targetItem, const std::string& filePath) override; - + std::string takeScreenshotAsBase64(const ItemPath& targetItem); // Mock stuff void addItemAtPath(MockItem item, const ItemPath& path); MockEvents& mockEvents(); diff --git a/lib/src/Scene/Qt/QtScene.cpp b/lib/src/Scene/Qt/QtScene.cpp index 75aa5b0..d320e7d 100644 --- a/lib/src/Scene/Qt/QtScene.cpp +++ b/lib/src/Scene/Qt/QtScene.cpp @@ -10,6 +10,8 @@ #include #include +#include +#include #include #include #include @@ -139,4 +141,32 @@ void QtScene::takeScreenshot(const ItemPath& targetItem, const std::string& file image.save(QString::fromStdString(filePath)); } +std::string QtScene::takeScreenshotAsBase64(const ItemPath& targetItem) +{ + auto item = getQQuickItemAtPath(targetItem); + if (!item) { + return ""; + } + + // take screenshot of the full window + auto windowImage = item->window()->grabWindow(); + + // get the rect of the item in window space in pixels, account for the device pixel ratio + QRectF imageCropRectItemSpace {0, 0, item->width(), item->height()}; + auto imageCropRectF = item->mapRectToScene(imageCropRectItemSpace); + QRect imageCropRect(imageCropRectF.x() * windowImage.devicePixelRatio(), + imageCropRectF.y() * windowImage.devicePixelRatio(), imageCropRectF.width() * windowImage.devicePixelRatio(), + imageCropRectF.height() * windowImage.devicePixelRatio()); + + // crop the window image to the item rect + auto image = windowImage.copy(imageCropRect); + QByteArray byteArray; + QBuffer buffer(&byteArray); + buffer.open(QIODevice::WriteOnly); + image.save(&buffer, "PNG"); + buffer.close(); + + return byteArray.toBase64().toStdString(); +} + } // namespace spix diff --git a/lib/src/Scene/Qt/QtScene.h b/lib/src/Scene/Qt/QtScene.h index c166af3..1897845 100644 --- a/lib/src/Scene/Qt/QtScene.h +++ b/lib/src/Scene/Qt/QtScene.h @@ -6,6 +6,7 @@ #pragma once +#include #include #include @@ -28,6 +29,7 @@ class QtScene : public Scene { // Tasks void takeScreenshot(const ItemPath& targetItem, const std::string& filePath) override; + std::string takeScreenshotAsBase64(const ItemPath& targetItem); private: QtEvents m_events; diff --git a/lib/src/Scene/Scene.h b/lib/src/Scene/Scene.h index a5f4bc2..91e53cc 100644 --- a/lib/src/Scene/Scene.h +++ b/lib/src/Scene/Scene.h @@ -37,6 +37,7 @@ class Scene { // Tasks virtual void takeScreenshot(const ItemPath& targetItem, const std::string& filePath) = 0; + virtual std::string takeScreenshotAsBase64(const ItemPath& targetItem) = 0; }; } // namespace spix diff --git a/lib/src/TestServer.cpp b/lib/src/TestServer.cpp index bfe9068..157cc71 100644 --- a/lib/src/TestServer.cpp +++ b/lib/src/TestServer.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -177,6 +178,16 @@ void TestServer::takeScreenshot(ItemPath targetItem, std::string filePath) m_cmdExec->enqueueCommand(targetItem, std::move(filePath)); } +std::string TestServer::takeScreenshotAsBase64(ItemPath targetItem) +{ + std::promise promise; + auto result = promise.get_future(); + auto cmd = std::make_unique(targetItem, std::move(promise)); + m_cmdExec->enqueueCommand(std::move(cmd)); + + return result.get(); +} + void TestServer::quit() { m_cmdExec->enqueueCommand();