loleaflet/src/layer/tile/CalcTileLayer.js | 40 ++++---- loleaflet/src/layer/tile/ImpressTileLayer.js | 40 ++++---- loleaflet/src/layer/tile/WriterTileLayer.js | 40 ++++---- loolwsd/ChildProcessSession.cpp | 135 ++++++++++++++++++++++++++- loolwsd/ChildProcessSession.hpp | 2 loolwsd/LOKitClient.cpp | 3 loolwsd/LOOLProtocol.cpp | 15 ++- loolwsd/LOOLProtocol.hpp | 2 loolwsd/LOOLSession.hpp | 2 loolwsd/Makefile.am | 2 loolwsd/MasterProcessSession.cpp | 13 ++ loolwsd/MasterProcessSession.hpp | 2 loolwsd/Rectangle.hpp | 81 ++++++++++++++++ loolwsd/Util.cpp | 25 +++-- loolwsd/Util.hpp | 6 + loolwsd/loolmap.c | 8 - loolwsd/loolwsd.spec.in | 3 17 files changed, 348 insertions(+), 71 deletions(-)
New commits: commit 3ec262e01b23d5f0bff716f12faacd7831170f2a Author: Andras Timar <[email protected]> Date: Thu Jan 14 13:45:33 2016 +0100 loolwsd: add loolbroker, loolkit and loolmap to rpm diff --git a/loolwsd/loolwsd.spec.in b/loolwsd/loolwsd.spec.in index a45eea4..9028a2b 100644 --- a/loolwsd/loolwsd.spec.in +++ b/loolwsd/loolwsd.spec.in @@ -56,6 +56,9 @@ echo "0 0 */1 * * root find /var/cache/loolwsd -name \"*.png\" -a -atime +10 -ex %files /usr/bin/loolwsd /usr/bin/loolwsd-systemplate-setup +/usr/bin/loolmap +/usr/bin/loolkit +/usr/bin/loolbroker %{_unitdir}/loolwsd.service /var/adm/fillup-templates/sysconfig.loolwsd /etc/cron.d/loolwsd.cron commit 7cf9cdd4c8cae3d6b5b2e0ffdf033c85629a6a7c Author: Andras Timar <[email protected]> Date: Thu Jan 14 13:43:54 2016 +0100 loolwsd: add QueueHandler.hpp to dist tarball diff --git a/loolwsd/Makefile.am b/loolwsd/Makefile.am index b07c4b7..0da19e6 100644 --- a/loolwsd/Makefile.am +++ b/loolwsd/Makefile.am @@ -29,7 +29,7 @@ loolmap_SOURCES = loolmap.c noinst_HEADERS = LOKitHelper.hpp LOOLProtocol.hpp LOOLSession.hpp MasterProcessSession.hpp ChildProcessSession.hpp \ LOOLWSD.hpp LoadTest.hpp MessageQueue.hpp TileCache.hpp Util.hpp Png.hpp Common.hpp Capabilities.hpp \ - Rectangle.hpp \ + Rectangle.hpp QueueHandler.hpp \ bundled/include/LibreOfficeKit/LibreOfficeKit.h bundled/include/LibreOfficeKit/LibreOfficeKitEnums.h \ bundled/include/LibreOfficeKit/LibreOfficeKitInit.h bundled/include/LibreOfficeKit/LibreOfficeKitTypes.h commit 207925266caa5bf447a35fbe0062423ecfe714b1 Author: Andras Timar <[email protected]> Date: Wed Jan 13 21:10:07 2016 +0100 loolwsd: add Rectangle.hpp to dist tarball (cherry picked from commit 69222ace7a67ca8adc9a21a988436aad92883b51) diff --git a/loolwsd/Makefile.am b/loolwsd/Makefile.am index d32bd3d..b07c4b7 100644 --- a/loolwsd/Makefile.am +++ b/loolwsd/Makefile.am @@ -29,7 +29,7 @@ loolmap_SOURCES = loolmap.c noinst_HEADERS = LOKitHelper.hpp LOOLProtocol.hpp LOOLSession.hpp MasterProcessSession.hpp ChildProcessSession.hpp \ LOOLWSD.hpp LoadTest.hpp MessageQueue.hpp TileCache.hpp Util.hpp Png.hpp Common.hpp Capabilities.hpp \ - QueueHandler.hpp \ + Rectangle.hpp \ bundled/include/LibreOfficeKit/LibreOfficeKit.h bundled/include/LibreOfficeKit/LibreOfficeKitEnums.h \ bundled/include/LibreOfficeKit/LibreOfficeKitInit.h bundled/include/LibreOfficeKit/LibreOfficeKitTypes.h commit c22842442bd769933d3c963864a54d95ef070429 Author: Tomaž Vajngerl <[email protected]> Date: Tue Jan 12 12:20:53 2016 +0100 Send tilecombine command when invalidating tiles (cherry picked from commit 2f58be7613f2bd663693b7022f7ca5e38f5c1f41) diff --git a/loleaflet/src/layer/tile/CalcTileLayer.js b/loleaflet/src/layer/tile/CalcTileLayer.js index 8ac137e..6ee5cb3 100644 --- a/loleaflet/src/layer/tile/CalcTileLayer.js +++ b/loleaflet/src/layer/tile/CalcTileLayer.js @@ -30,7 +30,10 @@ L.CalcTileLayer = L.TileLayer.extend({ var visibleTopLeft = this._latLngToTwips(this._map.getBounds().getNorthWest()); var visibleBottomRight = this._latLngToTwips(this._map.getBounds().getSouthEast()); var visibleArea = new L.Bounds(visibleTopLeft, visibleBottomRight); - var toRequest = []; + + var tilePositionsX = ""; + var tilePositionsY = ""; + var needsNewTiles = false; for (var key in this._tiles) { var coords = this._tiles[key].coords; @@ -45,15 +48,14 @@ L.CalcTileLayer = L.TileLayer.extend({ this._tiles[key]._invalidCount = 1; } if (visibleArea.intersects(bounds)) { - var msg = 'tile ' + - 'part=' + coords.part + ' ' + - 'width=' + this._tileSize + ' ' + - 'height=' + this._tileSize + ' ' + - 'tileposx=' + tileTopLeft.x + ' ' + - 'tileposy=' + tileTopLeft.y + ' ' + - 'tilewidth=' + this._tileWidthTwips + ' ' + - 'tileheight=' + this._tileHeightTwips; - toRequest.push({msg: msg, key: key, coords: coords}); + if (tilePositionsX !== "") + tilePositionsX += ','; + tilePositionsX += tileTopLeft.x; + + if (tilePositionsY !== "") + tilePositionsY += ','; + tilePositionsY += tileTopLeft.y; + needsNewTiles = true; } else { // tile outside of the visible area, just remove it @@ -63,12 +65,18 @@ L.CalcTileLayer = L.TileLayer.extend({ } } - // Sort tiles so that we request those closer to the cursor first - var cursorPos = this._map.project(this._visibleCursor.getNorthWest()); - cursorPos = cursorPos.divideBy(this._tileSize); - toRequest.sort(function(x, y) {return x.coords.distanceTo(cursorPos) - y.coords.distanceTo(cursorPos);}); - for (var i = 0; i < toRequest.length; i++) { - this._map._socket.sendMessage(toRequest[i].msg, toRequest[i].key); + if (needsNewTiles) + { + var message = 'tilecombine ' + + 'part=' + command.part + ' ' + + 'width=' + this._tileSize + ' ' + + 'height=' + this._tileSize + ' ' + + 'tileposx=' + tilePositionsX + ' ' + + 'tileposy=' + tilePositionsY + ' ' + + 'tilewidth=' + this._tileWidthTwips + ' ' + + 'tileheight=' + this._tileHeightTwips; + + this._map._socket.sendMessage(message, ""); } for (key in this._tileCache) { diff --git a/loleaflet/src/layer/tile/ImpressTileLayer.js b/loleaflet/src/layer/tile/ImpressTileLayer.js index 85cc275..3e76cbe 100644 --- a/loleaflet/src/layer/tile/ImpressTileLayer.js +++ b/loleaflet/src/layer/tile/ImpressTileLayer.js @@ -21,7 +21,10 @@ L.ImpressTileLayer = L.TileLayer.extend({ var visibleTopLeft = this._latLngToTwips(this._map.getBounds().getNorthWest()); var visibleBottomRight = this._latLngToTwips(this._map.getBounds().getSouthEast()); var visibleArea = new L.Bounds(visibleTopLeft, visibleBottomRight); - var toRequest = []; + + var tilePositionsX = ""; + var tilePositionsY = ""; + var needsNewTiles = false; for (var key in this._tiles) { var coords = this._tiles[key].coords; @@ -36,15 +39,14 @@ L.ImpressTileLayer = L.TileLayer.extend({ this._tiles[key]._invalidCount = 1; } if (visibleArea.intersects(bounds)) { - var msg = 'tile ' + - 'part=' + coords.part + ' ' + - 'width=' + this._tileSize + ' ' + - 'height=' + this._tileSize + ' ' + - 'tileposx=' + tileTopLeft.x + ' ' + - 'tileposy=' + tileTopLeft.y + ' ' + - 'tilewidth=' + this._tileWidthTwips + ' ' + - 'tileheight=' + this._tileHeightTwips; - toRequest.push({msg: msg, key: key, coords: coords}); + if (tilePositionsX !== "") + tilePositionsX += ','; + tilePositionsX += tileTopLeft.x; + + if (tilePositionsY !== "") + tilePositionsY += ','; + tilePositionsY += tileTopLeft.y; + needsNewTiles = true; } else { // tile outside of the visible area, just remove it @@ -54,12 +56,18 @@ L.ImpressTileLayer = L.TileLayer.extend({ } } - // Sort tiles so that we request those closer to the cursor first - var cursorPos = this._map.project(this._visibleCursor.getNorthWest()); - cursorPos = cursorPos.divideBy(this._tileSize); - toRequest.sort(function(x, y) {return x.coords.distanceTo(cursorPos) - y.coords.distanceTo(cursorPos);}); - for (var i = 0; i < toRequest.length; i++) { - this._map._socket.sendMessage(toRequest[i].msg, toRequest[i].key); + if (needsNewTiles) + { + var message = 'tilecombine ' + + 'part=' + command.part + ' ' + + 'width=' + this._tileSize + ' ' + + 'height=' + this._tileSize + ' ' + + 'tileposx=' + tilePositionsX + ' ' + + 'tileposy=' + tilePositionsY + ' ' + + 'tilewidth=' + this._tileWidthTwips + ' ' + + 'tileheight=' + this._tileHeightTwips; + + this._map._socket.sendMessage(message, ""); } for (key in this._tileCache) { diff --git a/loleaflet/src/layer/tile/WriterTileLayer.js b/loleaflet/src/layer/tile/WriterTileLayer.js index 7dca8ea..3c0ad8f 100644 --- a/loleaflet/src/layer/tile/WriterTileLayer.js +++ b/loleaflet/src/layer/tile/WriterTileLayer.js @@ -22,7 +22,10 @@ L.WriterTileLayer = L.TileLayer.extend({ var visibleTopLeft = this._latLngToTwips(this._map.getBounds().getNorthWest()); var visibleBottomRight = this._latLngToTwips(this._map.getBounds().getSouthEast()); var visibleArea = new L.Bounds(visibleTopLeft, visibleBottomRight); - var toRequest = []; + + var tilePositionsX = ""; + var tilePositionsY = ""; + var needsNewTiles = false; for (var key in this._tiles) { var coords = this._tiles[key].coords; @@ -37,15 +40,14 @@ L.WriterTileLayer = L.TileLayer.extend({ this._tiles[key]._invalidCount = 1; } if (visibleArea.intersects(bounds)) { - var msg = 'tile ' + - 'part=' + coords.part + ' ' + - 'width=' + this._tileSize + ' ' + - 'height=' + this._tileSize + ' ' + - 'tileposx=' + tileTopLeft.x + ' ' + - 'tileposy=' + tileTopLeft.y + ' ' + - 'tilewidth=' + this._tileWidthTwips + ' ' + - 'tileheight=' + this._tileHeightTwips; - toRequest.push({msg: msg, key: key, coords: coords}); + if (tilePositionsX !== "") + tilePositionsX += ','; + tilePositionsX += tileTopLeft.x; + + if (tilePositionsY !== "") + tilePositionsY += ','; + tilePositionsY += tileTopLeft.y; + needsNewTiles = true; } else { // tile outside of the visible area, just remove it @@ -55,12 +57,18 @@ L.WriterTileLayer = L.TileLayer.extend({ } } - // Sort tiles so that we request those closer to the cursor first - var cursorPos = this._map.project(this._visibleCursor.getNorthWest()); - cursorPos = cursorPos.divideBy(this._tileSize); - toRequest.sort(function(x, y) {return x.coords.distanceTo(cursorPos) - y.coords.distanceTo(cursorPos);}); - for (var i = 0; i < toRequest.length; i++) { - this._map._socket.sendMessage(toRequest[i].msg, toRequest[i].key); + if (needsNewTiles) + { + var message = 'tilecombine ' + + 'part=' + command.part + ' ' + + 'width=' + this._tileSize + ' ' + + 'height=' + this._tileSize + ' ' + + 'tileposx=' + tilePositionsX + ' ' + + 'tileposy=' + tilePositionsY + ' ' + + 'tilewidth=' + this._tileWidthTwips + ' ' + + 'tileheight=' + this._tileHeightTwips; + + this._map._socket.sendMessage(message, ""); } for (key in this._tileCache) { commit 721cbbcbb37009e845edb97f1cc472acea9d4869 Author: Tomaž Vajngerl <[email protected]> Date: Thu Jan 14 13:00:04 2016 +0100 Add "tilecombine" command to render more tiles in one call When invalidating we need to rerender more tiles at once. This change optimizes that with a new command which rerenders a larger area once and then separates the rendered buffer into more tiles. This generally decreases the invalidation time by 2-4 times and in some cases (when invalidating images in document) up to 9 times. diff --git a/loolwsd/ChildProcessSession.cpp b/loolwsd/ChildProcessSession.cpp index 25d1de9..2c10576 100644 --- a/loolwsd/ChildProcessSession.cpp +++ b/loolwsd/ChildProcessSession.cpp @@ -24,6 +24,7 @@ #include "LOKitHelper.hpp" #include "LOOLProtocol.hpp" #include "Util.hpp" +#include "Rectangle.hpp" using namespace LOOLProtocol; @@ -125,6 +126,10 @@ bool ChildProcessSession::_handleInput(const char *buffer, int length) { sendTile(buffer, length, tokens); } + else if (tokens[0] == "tilecombine") + { + sendCombinedTiles(buffer, length, tokens); + } else { // All other commands are such that they always require a LibreOfficeKitDocument session, @@ -423,6 +428,132 @@ void ChildProcessSession::sendTile(const char* /*buffer*/, int /*length*/, Strin sendBinaryFrame(output.data(), output.size()); } +void ChildProcessSession::sendCombinedTiles(const char* /*buffer*/, int /*length*/, StringTokenizer& tokens) +{ + int part, pixelWidth, pixelHeight, tileWidth, tileHeight; + std::string tilePositionsX, tilePositionsY; + + if (tokens.count() < 8 || + !getTokenInteger(tokens[1], "part", part) || + !getTokenInteger(tokens[2], "width", pixelWidth) || + !getTokenInteger(tokens[3], "height", pixelHeight) || + !getTokenString (tokens[4], "tileposx", tilePositionsX) || + !getTokenString (tokens[5], "tileposy", tilePositionsY) || + !getTokenInteger(tokens[6], "tilewidth", tileWidth) || + !getTokenInteger(tokens[7], "tileheight", tileHeight)) + { + sendTextFrame("error: cmd=tilecombine kind=syntax"); + return; + } + + if (part < 0 || pixelWidth <= 0 || pixelHeight <= 0 + || tileWidth <= 0 || tileHeight <= 0 + || tilePositionsX.empty() || tilePositionsY.empty()) + { + sendTextFrame("error: cmd=tilecombine kind=invalid"); + return; + } + + Util::Rectangle renderArea; + + StringTokenizer positionXtokens(tilePositionsX, ",", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM); + StringTokenizer positionYtokens(tilePositionsY, ",", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM); + + size_t numberOfPositions = positionYtokens.count(); + // check that number of positions for X and Y is the same + if (numberOfPositions != positionYtokens.count()) + { + sendTextFrame("error: cmd=tilecombine kind=invalid"); + return; + } + + std::vector<Util::Rectangle> tiles; + tiles.reserve(numberOfPositions); + + for (size_t i = 0; i < numberOfPositions; i++) + { + int x, y; + + if (!stringToInteger(positionXtokens[i], x)) + { + sendTextFrame("error: cmd=tilecombine kind=syntax"); + return; + } + if (!stringToInteger(positionYtokens[i], y)) + { + sendTextFrame("error: cmd=tilecombine kind=syntax"); + return; + } + + Util::Rectangle rectangle(x, y, tileWidth, tileHeight); + + if (tiles.empty()) + { + renderArea = rectangle; + } + else + { + renderArea.extend(rectangle); + } + + tiles.push_back(rectangle); + } + + if (_docType != "text" && part != _loKitDocument->pClass->getPart(_loKitDocument)) + { + _loKitDocument->pClass->setPart(_loKitDocument, part); + } + + LibreOfficeKitTileMode mode = static_cast<LibreOfficeKitTileMode>(_loKitDocument->pClass->getTileMode(_loKitDocument)); + + int tilesByX = renderArea.getWidth() / tileWidth; + int tilesByY = renderArea.getHeight() / tileHeight; + + int pixmapWidth = tilesByX * pixelWidth; + int pixmapHeight = tilesByY * pixelHeight; + + const size_t pixmapSize = 4 * pixmapWidth * pixmapHeight; + + std::vector<unsigned char> pixmap(pixmapSize, 0); + + Poco::Timestamp timestamp; + _loKitDocument->pClass->paintTile(_loKitDocument, pixmap.data(), pixmapWidth, pixmapHeight, + renderArea.getLeft(), renderArea.getTop(), + renderArea.getWidth(), renderArea.getHeight()); + + Log::debug() << "paintTile (Multiple) called, tile at [" << renderArea.getLeft() << ", " << renderArea.getTop() << "]" + << " (" << renderArea.getWidth() << ", " << renderArea.getHeight() << ") rendered in " + << double(timestamp.elapsed())/1000 << "ms" << Log::end; + + for (Util::Rectangle& tileRect : tiles) + { + std::string response = "tile: part=" + std::to_string(part) + + " width=" + std::to_string(pixelWidth) + + " height=" + std::to_string(pixelHeight) + + " tileposx=" + std::to_string(tileRect.getLeft()) + + " tileposy=" + std::to_string(tileRect.getTop()) + + " tilewidth=" + std::to_string(tileWidth) + + " tileheight=" + std::to_string(tileHeight) + "\n"; + + std::vector<char> output; + output.reserve(pixelWidth * pixelHeight * 4 + response.size()); + output.resize(response.size()); + + std::copy(response.begin(), response.end(), output.begin()); + + int positionX = (tileRect.getLeft() - renderArea.getLeft()) / tileWidth; + int positionY = (tileRect.getTop() - renderArea.getTop()) / tileHeight; + + if (!Util::encodeSubBufferToPNG(pixmap.data(), positionX * pixelWidth, positionY * pixelHeight, pixelWidth, pixelHeight, pixmapWidth, pixmapHeight, output, mode)) + { + sendTextFrame("error: cmd=tile kind=failure"); + return; + } + + sendBinaryFrame(output.data(), output.size()); + } +} + bool ChildProcessSession::clientZoom(const char* /*buffer*/, int /*length*/, StringTokenizer& tokens) { int tilePixelWidth, tilePixelHeight, tileTwipWidth, tileTwipHeight; diff --git a/loolwsd/ChildProcessSession.hpp b/loolwsd/ChildProcessSession.hpp index 062e4cf..12d7d02 100644 --- a/loolwsd/ChildProcessSession.hpp +++ b/loolwsd/ChildProcessSession.hpp @@ -59,6 +59,8 @@ public: virtual void sendTile(const char *buffer, int length, Poco::StringTokenizer& tokens) override; + virtual void sendCombinedTiles(const char *buffer, int length, Poco::StringTokenizer& tokens) override; + virtual void sendFontRendering(const char *buffer, int length, Poco::StringTokenizer& tokens) override; bool clientZoom(const char *buffer, int length, Poco::StringTokenizer& tokens); diff --git a/loolwsd/LOOLSession.hpp b/loolwsd/LOOLSession.hpp index a5f3678..c03de93 100644 --- a/loolwsd/LOOLSession.hpp +++ b/loolwsd/LOOLSession.hpp @@ -75,6 +75,8 @@ protected: virtual void sendTile(const char *buffer, int length, Poco::StringTokenizer& tokens) = 0; + virtual void sendCombinedTiles(const char *buffer, int length, Poco::StringTokenizer& tokens) = 0; + virtual void sendFontRendering(const char *buffer, int length, Poco::StringTokenizer& tokens) = 0; // Fields common to sessions in master and jailed processes: diff --git a/loolwsd/MasterProcessSession.cpp b/loolwsd/MasterProcessSession.cpp index e427328..32a3098 100644 --- a/loolwsd/MasterProcessSession.cpp +++ b/loolwsd/MasterProcessSession.cpp @@ -289,6 +289,7 @@ bool MasterProcessSession::_handleInput(const char *buffer, int length) tokens[0] != "setpage" && tokens[0] != "status" && tokens[0] != "tile" && + tokens[0] != "tilecombine" && tokens[0] != "uno") { sendTextFrame("error: cmd=" + tokens[0] + " kind=unknown"); @@ -328,6 +329,10 @@ bool MasterProcessSession::_handleInput(const char *buffer, int length) { sendTile(buffer, length, tokens); } + else if (tokens[0] == "tilecombine") + { + sendCombinedTiles(buffer, length, tokens); + } else { // All other commands are such that they always require a @@ -570,6 +575,14 @@ void MasterProcessSession::sendTile(const char *buffer, int length, StringTokeni forwardToPeer(buffer, length); } +void MasterProcessSession::sendCombinedTiles(const char *buffer, int length, StringTokenizer& /*tokens*/) +{ + // This is for invalidation - we should not have cached tiles + if (_peer.expired()) + dispatchChild(); + forwardToPeer(buffer, length); +} + void MasterProcessSession::dispatchChild() { short nRequest = 3; diff --git a/loolwsd/MasterProcessSession.hpp b/loolwsd/MasterProcessSession.hpp index 380def8..42ed9e9 100644 --- a/loolwsd/MasterProcessSession.hpp +++ b/loolwsd/MasterProcessSession.hpp @@ -47,6 +47,8 @@ public: virtual void sendTile(const char *buffer, int length, Poco::StringTokenizer& tokens) override; + virtual void sendCombinedTiles(const char *buffer, int length, Poco::StringTokenizer& tokens) override; + virtual void sendFontRendering(const char *buffer, int length, Poco::StringTokenizer& tokens) override; void dispatchChild(); commit 9af47a69d3073936b6bf563f707c894d0cb5a00b Author: Tomaž Vajngerl <[email protected]> Date: Tue Jan 12 12:11:49 2016 +0100 add simple Rectangle struct implementation (cherry picked from commit 5c25dd61cb6a27da47c6e3776024cd7d622082b8) diff --git a/loolwsd/Rectangle.hpp b/loolwsd/Rectangle.hpp new file mode 100644 index 0000000..bac02b4 --- /dev/null +++ b/loolwsd/Rectangle.hpp @@ -0,0 +1,81 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_RECTANGLE_HPP +#define INCLUDED_RECTANGLE_HPP + +#include <limits> + +namespace Util +{ + +struct Rectangle +{ + int _x1; + int _y1; + int _x2; + int _y2; + + Rectangle() + : _x1(std::numeric_limits<int>::max()) + , _y1(std::numeric_limits<int>::max()) + , _x2(std::numeric_limits<int>::min()) + , _y2(std::numeric_limits<int>::min()) + {} + + Rectangle(int x, int y, int width, int height) + : _x1(x) + , _y1(y) + , _x2(x + width) + , _y2(y + height) + {} + + void extend(Rectangle& rectangle) + { + if (rectangle._x1 < _x1) + _x1 = rectangle._x1; + if (rectangle._x2 > _x2) + _x2 = rectangle._x2; + if (rectangle._y1 < _y1) + _y1 = rectangle._y1; + if (rectangle._y2 > _y2) + _y2 = rectangle._y2; + } + + int getLeft() + { + return _x1; + } + + int getTop() + { + return _y1; + } + + int getWidth() + { + return _x2 - _x1; + } + + int getHeight() + { + return _y2 - _y1; + } + + bool isValid() + { + return _x1 <= _x2 && _y1 <= _y2; + } +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ commit 8ee650346998a4863aac1c60d01c8927087ba303 Author: Tomaž Vajngerl <[email protected]> Date: Tue Jan 12 12:07:13 2016 +0100 add function to convert string to integer (cherry picked from commit f7acce6f20bf362b741542d66e2879c1638bab7c) diff --git a/loolwsd/LOOLProtocol.cpp b/loolwsd/LOOLProtocol.cpp index 0d358c2..20c5d8e 100644 --- a/loolwsd/LOOLProtocol.cpp +++ b/loolwsd/LOOLProtocol.cpp @@ -40,10 +40,23 @@ namespace LOOLProtocol if (secondTokens.count() > 1) patch = secondTokens[1]; } - return std::make_tuple(major, minor, patch); } + bool stringToInteger(const std::string& input, int& value) + { + try + { + value = std::stoi(input); + } + catch (std::invalid_argument&) + { + return false; + } + + return true; + } + bool getTokenInteger(const std::string& token, const std::string& name, int& value) { size_t nextIdx; diff --git a/loolwsd/LOOLProtocol.hpp b/loolwsd/LOOLProtocol.hpp index 1478713..26a8f4b 100644 --- a/loolwsd/LOOLProtocol.hpp +++ b/loolwsd/LOOLProtocol.hpp @@ -78,6 +78,8 @@ namespace LOOLProtocol // Negative numbers for error. std::tuple<signed, signed, std::string> ParseVersion(const std::string& version); + bool stringToInteger(const std::string& input, int& value); + bool getTokenInteger(const std::string& token, const std::string& name, int& value); bool getTokenString(const std::string& token, const std::string& name, std::string& value); bool getTokenKeyword(const std::string& token, const std::string& name, const std::map<std::string, int>& map, int& value); commit 26d30c88dea37960673324e7c6ab684b4905223a Author: Andras Timar <[email protected]> Date: Thu Jan 14 12:40:59 2016 +0100 loolwsd: -Werror,-Wunused-variable diff --git a/loolwsd/loolmap.c b/loolwsd/loolmap.c index 922a6c3..3a863ae 100644 --- a/loolwsd/loolmap.c +++ b/loolwsd/loolmap.c @@ -69,10 +69,6 @@ static void total_smaps(unsigned proc_id, const char *file, const char *cmdline) FILE *file_pointer; char buffer[BUFFER_SIZE]; - unsigned long long private_dirty = 0ull; - unsigned long long private_clean = 0ull; - unsigned long long shared_dirty = 0ull; - unsigned long long shared_clean = 0ull; unsigned long long total_private_dirty = 0ull; unsigned long long total_private_clean = 0ull; unsigned long long total_shared_dirty = 0ull; @@ -91,25 +87,21 @@ static void total_smaps(unsigned proc_id, const char *file, const char *cmdline) { if (strncmp("Shared_Dirty", smap_key, 12) == 0) { - shared_dirty = smap_value; total_shared_dirty += smap_value; continue; } if (strncmp("Shared_Clean", smap_key, 12) == 0) { - shared_clean = smap_value; total_shared_clean += smap_value; continue; } if (strncmp("Private_Dirty", smap_key, 13) == 0) { - private_dirty = smap_value; total_private_dirty += smap_value; continue; } if (strncmp("Private_Clean", smap_key, 13) == 0) { - private_clean = smap_value; total_private_clean += smap_value; continue; } commit 9071f7c9bc8125bc3ba15afa14f731beb904d183 Author: Tomaž Vajngerl <[email protected]> Date: Tue Jan 12 12:00:42 2016 +0100 encode PNG from buffer at arbitrary buffer position This commit add 2 methods to encode a buffer to PNG: the "old" method which encodes the whole buffer to a PNG, and a new method to encode a part of a buffer (sub image) to PNG. The first method is only added for convenience. diff --git a/loolwsd/ChildProcessSession.cpp b/loolwsd/ChildProcessSession.cpp index c84650d..25d1de9 100644 --- a/loolwsd/ChildProcessSession.cpp +++ b/loolwsd/ChildProcessSession.cpp @@ -293,7 +293,7 @@ void ChildProcessSession::sendFontRendering(const char* /*buffer*/, int /*length if (pixmap != nullptr) { - if (!Util::encodePNGAndAppendToBuffer(pixmap, width, height, output, LOK_TILEMODE_RGBA)) + if (!Util::encodeBufferToPNG(pixmap, width, height, output, LOK_TILEMODE_RGBA)) { sendTextFrame("error: cmd=renderfont kind=failure"); delete[] pixmap; @@ -414,7 +414,7 @@ void ChildProcessSession::sendTile(const char* /*buffer*/, int /*length*/, Strin << "] rendered in " << (timestamp.elapsed()/1000.) << " ms" << Log::end; LibreOfficeKitTileMode mode = static_cast<LibreOfficeKitTileMode>(_loKitDocument->pClass->getTileMode(_loKitDocument)); - if (!Util::encodePNGAndAppendToBuffer(pixmap.data(), width, height, output, mode)) + if (!Util::encodeBufferToPNG(pixmap.data(), width, height, output, mode)) { sendTextFrame("error: cmd=tile kind=failure"); return; diff --git a/loolwsd/LOKitClient.cpp b/loolwsd/LOKitClient.cpp index b6db978..b03c2fd 100644 --- a/loolwsd/LOKitClient.cpp +++ b/loolwsd/LOKitClient.cpp @@ -167,7 +167,8 @@ protected: std::vector<char> png; LibreOfficeKitTileMode mode = static_cast<LibreOfficeKitTileMode>(loKitDocument->pClass->getTileMode(loKitDocument)); - Util::encodePNGAndAppendToBuffer(pixmap.data(), canvasWidth, canvasHeight, png, mode); + + Util::encodeBufferToPNG(pixmap.data(), canvasWidth, canvasHeight, png, mode); TemporaryFile pngFile; std::ofstream pngStream(pngFile.path(), std::ios::binary); diff --git a/loolwsd/Util.cpp b/loolwsd/Util.cpp index addef5b..ed8757d 100644 --- a/loolwsd/Util.cpp +++ b/loolwsd/Util.cpp @@ -226,8 +226,18 @@ namespace Util return false; } - bool encodePNGAndAppendToBuffer(unsigned char *pixmap, int width, int height, std::vector<char>& output, LibreOfficeKitTileMode mode) + bool encodeBufferToPNG(unsigned char *pixmap, int width, int height, std::vector<char>& output, LibreOfficeKitTileMode mode) { + + return encodeSubBufferToPNG(pixmap, 0, 0, width, height, width, height, output, mode); + } + + bool encodeSubBufferToPNG(unsigned char *pixmap, int startX, int startY, int width, int height, + int bufferWidth, int bufferHeight, std::vector<char>& output, LibreOfficeKitTileMode mode) + { + if (bufferWidth < width || bufferHeight < height) + return false; + png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); png_infop info_ptr = png_create_info_struct(png_ptr); @@ -245,19 +255,16 @@ namespace Util png_write_info(png_ptr, info_ptr); - switch (mode) + if (mode == LOK_TILEMODE_BGRA) { - case LOK_TILEMODE_RGBA: - break; - case LOK_TILEMODE_BGRA: png_set_write_user_transform_fn (png_ptr, unpremultiply_data); - break; - default: - assert(false); } for (int y = 0; y < height; ++y) - png_write_row(png_ptr, pixmap + y * width * 4); + { + size_t position = ((startY + y) * bufferWidth * 4) + (startX * 4); + png_write_row(png_ptr, pixmap + position); + } png_write_end(png_ptr, info_ptr); diff --git a/loolwsd/Util.hpp b/loolwsd/Util.hpp index 04aed30..702fe98 100644 --- a/loolwsd/Util.hpp +++ b/loolwsd/Util.hpp @@ -50,7 +50,11 @@ namespace Util // Sadly, older libpng headers don't use const for the pixmap pointer parameter to // png_write_row(), so can't use const here for pixmap. - bool encodePNGAndAppendToBuffer(unsigned char *pixmap, int width, int height, std::vector<char>& output, LibreOfficeKitTileMode mode); + bool encodeBufferToPNG(unsigned char* pixmap, int width, int height, + std::vector<char>& output, LibreOfficeKitTileMode mode); + bool encodeSubBufferToPNG(unsigned char* pixmap, int startX, int startY, int width, int height, + int bufferWidth, int bufferHeight, + std::vector<char>& output, LibreOfficeKitTileMode mode); // Call WebSocket::shutdown() ignoring Poco::IOException void shutdownWebSocket(Poco::Net::WebSocket& ws);
_______________________________________________ Libreoffice-commits mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
