diff --git a/kit/ChildSession.cpp b/kit/ChildSession.cpp index c3be0c13f..116b59a85 100644 --- a/kit/ChildSession.cpp +++ b/kit/ChildSession.cpp @@ -499,6 +499,10 @@ bool ChildSession::_handleInput(const char *buffer, int length) { return getStatus(); } + else if (tokens.equals(0, "getslide")) + { + return renderSlide(tokens); + } else if (tokens.equals(0, "paintwindow")) { return renderWindow(tokens); @@ -2189,6 +2193,115 @@ uint64_t hashSubBuffer(unsigned char* pixmap, size_t startX, size_t startY, } } +bool ChildSession::renderNextSlideLayer(int width, int height, size_t pixmapDataSize, bool& done) +{ + std::vector pixmap(pixmapDataSize); + bool bIsBitmapLayer = false; + char* msg = nullptr; + done = getLOKitDocument()->renderNextSlideLayer(pixmap.data(), &bIsBitmapLayer, &msg); + std::string jsonMsg(msg); + free(msg); + + if (jsonMsg.empty()) + return true; + + if (!bIsBitmapLayer) + { + std::string response = "slidelayer: " + jsonMsg; + sendTextFrame(response); + return true; + } + + uint64_t pixmapHash = hashSubBuffer(pixmap.data(), 0, 0, width, height, width, height) + getViewId(); + if (size_t start = jsonMsg.find("%IMAGETYPE%"); start != std::string::npos) + jsonMsg.replace(start, 11, "png"); + if (size_t start = jsonMsg.find("%IMAGECHECKSUM%"); start != std::string::npos) + jsonMsg.replace(start, 15, std::to_string(pixmapHash)); + + std::string response = "slidelayer: " + jsonMsg; + + response += "\n"; + + std::vector output; + output.reserve(response.size() + pixmapDataSize); + output.resize(response.size()); + std::memcpy(output.data(), response.data(), response.size()); + + const auto tileMode = static_cast(getLOKitDocument()->getTileMode()); + + if (!Png::encodeSubBufferToPNG(pixmap.data(), 0, 0, width, height, width, height, output, tileMode)) + { + LOG_ERR("Failed to encode into PNG."); + return false; + } + + LOG_TRC("Sending response (" << output.size() << " bytes) for: " << std::string(output.data(), response.size() - 1)); + sendBinaryFrame(output.data(), output.size()); + + return true; +} + +bool ChildSession::renderSlide(const StringVector& tokens) +{ + int part = -1; + std::string partString; + if (tokens.size() > 1 && getTokenString(tokens[1], "part", partString)) + { + part = std::stoi(partString); + } + int suggestedWidth = -1; + std::string widthString; + if (tokens.size() > 2 && getTokenString(tokens[2], "width", widthString)) + { + suggestedWidth = std::stoi(widthString); + } + int suggestedHeight = -1; + std::string heightString; + if (tokens.size() > 3 && getTokenString(tokens[3], "height", heightString)) + { + suggestedHeight = std::stoi(heightString); + } + if (part < 0 || suggestedWidth < 0 || suggestedHeight < 0) + return false; + + bool renderBackground = true; + std::string renderBackgroundString; + if (tokens.size() > 4 && getTokenString(tokens[4], "renderBackground", renderBackgroundString)) + { + renderBackground = std::stoi(renderBackgroundString) > 0; + } + bool renderMasterPage = true; + std::string renderMasterPageString; + if (tokens.size() > 5 && getTokenString(tokens[5], "renderMasterPage", renderMasterPageString)) + { + renderMasterPage = std::stoi(renderMasterPageString) > 0; + } + + unsigned int bufferWidth = suggestedWidth; + unsigned int bufferHeight = suggestedHeight; + bool success = getLOKitDocument()->createSlideRenderer(part, + &bufferWidth, &bufferHeight, + renderBackground, renderMasterPage); + if (!success) + return false; + + const int width = bufferWidth; + const int height = bufferHeight; + const size_t pixmapDataSize = 4 * bufferWidth * bufferHeight; + bool done = false; + while (!done) + { + success = renderNextSlideLayer(width, height, pixmapDataSize, done); + if (!success) + break; + } + + getLOKitDocument()->postSlideshowCleanup(); + sendTextFrame("sliderenderingcomplete"); + + return success; +} + bool ChildSession::renderWindow(const StringVector& tokens) { const unsigned winId = (tokens.size() > 1 ? std::stoul(tokens[1]) : 0); diff --git a/kit/ChildSession.hpp b/kit/ChildSession.hpp index e4cf90e48..d49abfa3e 100644 --- a/kit/ChildSession.hpp +++ b/kit/ChildSession.hpp @@ -154,6 +154,8 @@ private: bool unoCommand(const StringVector& tokens); bool selectText(const StringVector& tokens, const LokEventTargetEnum target); bool selectGraphic(const StringVector& tokens); + bool renderNextSlideLayer(int width, int height, size_t pixmapDataSize, bool& done); + bool renderSlide(const StringVector& tokens); bool renderWindow(const StringVector& tokens); bool resizeWindow(const StringVector& tokens); bool resetSelection(const StringVector& tokens); diff --git a/kit/KitWebSocket.cpp b/kit/KitWebSocket.cpp index 66223d0f9..c6012d4e3 100644 --- a/kit/KitWebSocket.cpp +++ b/kit/KitWebSocket.cpp @@ -128,6 +128,7 @@ void KitWebSocketHandler::handleMessage(const std::vector& data) } } else if (tokens.equals(0, "tile") || tokens.equals(0, "tilecombine") || + tokens.equals(0, "getslide") || tokens.equals(0, "paintwindow") || tokens.equals(0, "resizewindow") || COOLProtocol::getFirstToken(tokens[0], '-') == "child") { diff --git a/wsd/ClientSession.cpp b/wsd/ClientSession.cpp index 3c60f4087..87a35978c 100644 --- a/wsd/ClientSession.cpp +++ b/wsd/ClientSession.cpp @@ -1192,6 +1192,7 @@ bool ClientSession::_handleInput(const char *buffer, int length) tokens.equals(0, "urp") || tokens.equals(0, "useractive") || tokens.equals(0, "userinactive") || + tokens.equals(0, "getslide") || tokens.equals(0, "paintwindow") || tokens.equals(0, "windowcommand") || tokens.equals(0, "asksignaturestatus") ||