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.vajng...@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.vajng...@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()
_______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits