[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