[Libreoffice-commits] online.git: 9 commits - loleaflet/src loolwsd/ChildProcessSession.cpp loolwsd/ChildProcessSession.hpp loolwsd/LOKitClient.cpp loolwsd/loolmap.c loolwsd/LOOLProtocol.cpp loolwsd/LOOLProtocol.hpp loolwsd/LOOLSession.hpp loolwsd/loolwsd.spec.in loolwsd/Makefile.am loolwsd/MasterProcessSession.cpp loolwsd/MasterProcessSession.hpp loolwsd/Rectangle.hpp loolwsd/Util.cpp loolwsd/Util.hpp

Andras Timar andras.timar at collabora.com
Thu Jan 14 05:01:54 PST 2016


 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 <andras.timar at collabora.com>
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 <andras.timar at collabora.com>
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 <andras.timar at collabora.com>
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 <tomaz.vajngerl at collabora.com>
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 <tomaz.vajngerl at collabora.com>
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 <tomaz.vajngerl at collabora.com>
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 <tomaz.vajngerl at collabora.com>
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 <andras.timar at collabora.com>
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 <tomaz.vajngerl at collabora.com>
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);


More information about the Libreoffice-commits mailing list