[Libreoffice-commits] online.git: 2 commits - loleaflet/src loolwsd/MasterProcessSession.cpp

Tomaž Vajngerl tomaz.vajngerl at collabora.com
Wed Jan 20 14:21:08 PST 2016


 loleaflet/src/control/Parts.js        |    2 
 loleaflet/src/layer/tile/GridLayer.js |  133 ++++++++++++++++++++++++++++++++++
 loolwsd/MasterProcessSession.cpp      |  113 ++++++++++++++++++++++++++++
 3 files changed, 244 insertions(+), 4 deletions(-)

New commits:
commit 424a5aee42d0ad8d8b14c22134b971606220a632
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.com>
Date:   Wed Jan 20 23:09:41 2016 +0100

    loleaflet: specific tile update function when changing parts
    
    _updateOnChangePart includes duplicated and changed _update and
    _addTile functions. Deduplication will be done later..

diff --git a/loleaflet/src/control/Parts.js b/loleaflet/src/control/Parts.js
index 8e2d5c3..189f2d5 100644
--- a/loleaflet/src/control/Parts.js
+++ b/loleaflet/src/control/Parts.js
@@ -32,7 +32,7 @@ L.Map.include({
 		});
 		this._socket.sendMessage('setclientpart part=' + docLayer._selectedPart);
 		docLayer._clearSelections();
-		docLayer._update();
+		docLayer._updateOnChangePart();
 		docLayer._pruneTiles();
 		docLayer._prevSelectedPartNeedsUpdate = true;
 		if (docLayer._invalidatePreview) {
diff --git a/loleaflet/src/layer/tile/GridLayer.js b/loleaflet/src/layer/tile/GridLayer.js
index 8e3be8f..60ed36a 100644
--- a/loleaflet/src/layer/tile/GridLayer.js
+++ b/loleaflet/src/layer/tile/GridLayer.js
@@ -558,6 +558,139 @@ L.GridLayer = L.Layer.extend({
 		}
 	},
 
+	_updateOnChangePart: function () {
+		var map = this._map;
+		if (!map || this._documentInfo === '') {
+			return;
+		}
+
+		var center = map.getCenter();
+		var zoom = Math.round(map.getZoom());
+
+		var pixelBounds = map.getPixelBounds(center, zoom),
+			tileRange = this._pxBoundsToTileRange(pixelBounds),
+			queue = [];
+
+		for (var key in this._tiles) {
+			if (this._keyToTileCoords(key).z !== zoom ||
+					this._keyToTileCoords(key).part !== this._selectedPart) {
+				this._tiles[key].current = false;
+			}
+		}
+
+		// if there is no exiting tile in the current view
+		var newView = true;
+		// create a queue of coordinates to load tiles from
+		for (var j = tileRange.min.y; j <= tileRange.max.y; j++) {
+			for (var i = tileRange.min.x; i <= tileRange.max.x; i++) {
+				var coords = new L.Point(i, j);
+				coords.z = zoom;
+				coords.part = this._selectedPart;
+
+				if (!this._isValidTile(coords)) { continue; }
+
+				key = this._tileCoordsToKey(coords);
+				var tile = this._tiles[key];
+				if (tile) {
+					tile.current = true;
+					newView = false;
+				} else {
+					queue.push(coords);
+				}
+			}
+		}
+
+		if (queue.length !== 0) {
+			if (newView) {
+				// we know that a new set of tiles that cover the whole view has been requested
+				// so we're able to cancel the previous requests that are being processed
+				this._map._socket.sendMessage('canceltiles');
+				for (key in this._tiles) {
+					var tile = this._tiles[key];
+					if (!tile.loaded) {
+						L.DomUtil.remove(tile.el);
+						delete this._tiles[key];
+					}
+				}
+				this._emptyTilesCount = 0;
+			}
+
+			// if its the first batch of tiles to load
+			if (this._noTilesToLoad()) {
+				this.fire('loading');
+			}
+
+			// create DOM fragment to append tiles in one batch
+			var fragment = document.createDocumentFragment();
+			var tilePositionsX = '';
+			var tilePositionsY = '';
+
+			for (i = 0; i < queue.length; i++) {
+				var coords = queue[i];
+				var tilePos = this._getTilePos(coords),
+				key = this._tileCoordsToKey(coords);
+
+				if (coords.part === this._selectedPart) {
+					var tile = this.createTile(this._wrapCoords(coords), L.bind(this._tileReady, this, coords));
+
+					this._initTile(tile);
+
+					// if createTile is defined with a second argument ("done" callback),
+					// we know that tile is async and will be ready later; otherwise
+					if (this.createTile.length < 2) {
+						// mark tile as ready, but delay one frame for opacity animation to happen
+						setTimeout(L.bind(this._tileReady, this, coords, null, tile), 0);
+					}
+
+					// we prefer top/left over translate3d so that we don't create a HW-accelerated layer from each tile
+					// which is slow, and it also fixes gaps between tiles in Safari
+					L.DomUtil.setPosition(tile, tilePos, true);
+
+					// save tile in cache
+					this._tiles[key] = {
+						el: tile,
+						coords: coords,
+						current: true
+					};
+
+					fragment.appendChild(tile);
+
+					this.fire('tileloadstart', {
+						tile: tile,
+						coords: coords
+					});
+				}
+				if (!this._tileCache[key]) {
+					var twips = this._coordsToTwips(coords);
+					if (tilePositionsX !== '')
+						tilePositionsX += ',';
+					tilePositionsX += twips.x;
+					if (tilePositionsY !== '')
+						tilePositionsY += ',';
+					tilePositionsY += twips.y;
+				}
+				else {
+					tile.src = this._tileCache[key];
+				}
+			}
+
+			if (tilePositionsX !== '' && tilePositionsY !== '') {
+				var message = 'tilecombine ' +
+					'part=' + this._selectedPart + ' ' +
+					'width=' + this._tileSize + ' ' +
+					'height=' + this._tileSize + ' ' +
+					'tileposx=' + tilePositionsX + ' ' +
+					'tileposy=' + tilePositionsY + ' ' +
+					'tilewidth=' + this._tileWidthTwips + ' ' +
+					'tileheight=' + this._tileHeightTwips;
+
+				this._map._socket.sendMessage(message, "");
+			}
+
+			this._level.el.appendChild(fragment);
+		}
+	},
+
 	_isValidTile: function (coords) {
 		if (coords.x < 0 || coords.y < 0) {
 			return false;
commit 21121e2f55e95310fe436ce51f86f9897924b09e
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.com>
Date:   Wed Jan 20 23:04:41 2016 +0100

    Support returning cached tiles for "tilecombine"

diff --git a/loolwsd/MasterProcessSession.cpp b/loolwsd/MasterProcessSession.cpp
index d3b3fd9..d41820d 100644
--- a/loolwsd/MasterProcessSession.cpp
+++ b/loolwsd/MasterProcessSession.cpp
@@ -20,6 +20,7 @@
 #include "LOOLWSD.hpp"
 #include "MasterProcessSession.hpp"
 #include "Util.hpp"
+#include "Rectangle.hpp"
 
 using namespace LOOLProtocol;
 
@@ -575,12 +576,118 @@ void MasterProcessSession::sendTile(const char *buffer, int length, StringTokeni
     forwardToPeer(buffer, length);
 }
 
-void MasterProcessSession::sendCombinedTiles(const char *buffer, int length, StringTokenizer& /*tokens*/)
+
+void MasterProcessSession::sendCombinedTiles(const char* /*buffer*/, int /*length*/, StringTokenizer& tokens)
 {
-    // This is for invalidation - we should not have cached tiles
+    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::string forwardTileX;
+    std::string forwardTileY;
+
+    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;
+        }
+
+        std::unique_ptr<std::fstream> cachedTile = _tileCache->lookupTile(part, pixelWidth, pixelHeight, x, y, tileWidth, tileHeight);
+
+        if (cachedTile && cachedTile->is_open())
+        {
+            std::string response = "tile: part=" + std::to_string(part) +
+                               " width=" + std::to_string(pixelWidth) +
+                               " height=" + std::to_string(pixelHeight) +
+                               " tileposx=" + std::to_string(x) +
+                               " tileposy=" + std::to_string(y) +
+                               " tilewidth=" + std::to_string(tileWidth) +
+                               " tileheight=" + std::to_string(tileHeight) + "\n";
+
+            std::vector<char> output;
+            output.reserve(4 * pixelWidth * pixelHeight);
+            output.resize(response.size());
+            std::memcpy(output.data(), response.data(), response.size());
+            cachedTile->seekg(0, std::ios_base::end);
+            size_t pos = output.size();
+            std::streamsize size = cachedTile->tellg();
+            output.resize(pos + size);
+            cachedTile->seekg(0, std::ios_base::beg);
+            cachedTile->read(output.data() + pos, size);
+            cachedTile->close();
+
+            sendBinaryFrame(output.data(), output.size());
+        }
+        else
+        {
+            if (!forwardTileX.empty())
+                forwardTileX += ",";
+            forwardTileX += std::to_string(x);
+
+            if (!forwardTileY.empty())
+                forwardTileY += ",";
+            forwardTileY += std::to_string(y);
+        }
+    }
+
+    if (forwardTileX.empty() && forwardTileY.empty())
+        return;
+
     if (_peer.expired())
         dispatchChild();
-    forwardToPeer(buffer, length);
+
+    std::string forward = "tilecombine part=" + std::to_string(part) +
+                               " width=" + std::to_string(pixelWidth) +
+                               " height=" + std::to_string(pixelHeight) +
+                               " tileposx=" + forwardTileX +
+                               " tileposy=" + forwardTileY +
+                               " tilewidth=" + std::to_string(tileWidth) +
+                               " tileheight=" + std::to_string(tileHeight);
+
+    forwardToPeer(forward.c_str(), forward.size());
 }
 
 void MasterProcessSession::dispatchChild()


More information about the Libreoffice-commits mailing list