[Libreoffice-commits] online.git: Branch 'feature/calc-canvas' - 44 commits - android/app android/lib common/Common.hpp common/JailUtil.cpp common/JailUtil.hpp discovery.xml ios/CollaboraOnlineWebViewKeyboardManager ios/Mobile ios/Mobile.xcodeproj kit/ForKit.cpp kit/Kit.cpp loleaflet/css loleaflet/html loleaflet/images loleaflet/l10n loleaflet/po loleaflet/src loolwsd-systemplate-setup Makefile.am wsd/ClientSession.cpp wsd/DocumentBroker.cpp wsd/DocumentBroker.hpp wsd/lint-discovery.py wsd/LOOLWSD.cpp

Jan Holesovsky (via logerrit) logerrit at kemper.freedesktop.org
Fri Aug 28 15:08:58 UTC 2020


Rebased ref, commits from common ancestor:
commit 395ce779cfa589f1293f94e56ccd792285a718a9
Author:     Jan Holesovsky <kendy at collabora.com>
AuthorDate: Wed Aug 26 15:15:55 2020 +0200
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Fri Aug 28 17:04:56 2020 +0200

    calc canvas: Keep the document zoom separate from the browser zoom.
    
    With this, if you increase or decrease the browser zoom, the document
    zoom still stays the same.
    
    Before this, when you had eg. 100% document zoom and 150% browser zoom
    and try to zoom out, it actually zooms in instead, because the browser's
    zoom is added to the mix; and it displays the wrong value in the
    dropdown.  Even worse, to get the 100% again, you have to choose 80% so
    that the correction for the browser zoom is added, resulting in the
    100%.
    
    We should keep both the document and browser zoom separately.  The
    questions is then whether to combine them later for the actual document
    rendering; I believe we should not, but even if we should, we cannot do
    it directly in the setZoom() method, but instead closer to the painting
    itself.
    
    Change-Id: Ib7f3d2ae8b4e6e6086f14e933b215c32326c6be6

diff --git a/loleaflet/src/map/Map.js b/loleaflet/src/map/Map.js
index 8c3271b95..84a286eb6 100644
--- a/loleaflet/src/map/Map.js
+++ b/loleaflet/src/map/Map.js
@@ -461,19 +461,6 @@ L.Map = L.Evented.extend({
 		return Math.round(relzoom) + this.options.zoom;
 	},
 
-	// Compute the nearest zoom level corresponding to the effective zoom-scale (ie, with dpiscale included).
-	findNearestProductZoom: function (zoom) {
-		var clientZoomScale = this.zoomToFactor(zoom);
-
-		var dpiScale = this._docLayer ? this._docLayer.canvasDPIScale() : L.getDpiScaleFactor(true /* useExactDPR */);
-
-		var zoomScale = clientZoomScale * dpiScale;
-		var nearestZoom = this.factorToZoom(zoomScale);
-		nearestZoom = this._limitZoom(nearestZoom);
-
-		return nearestZoom;
-	},
-
 	setZoom: function (zoom, options) {
 
 		if (this._docLayer instanceof L.CanvasTileLayer) {
@@ -481,8 +468,6 @@ L.Map = L.Evented.extend({
 				zoom = this._clientZoom || this.options.zoom;
 			else
 				this._clientZoom = zoom;
-
-			zoom = this.findNearestProductZoom(zoom);
 		}
 
 		if (!this._loaded) {
commit c89cad739fc041ef40083d73f8b07cb030b78bc6
Author:     Dennis Francis <dennis.francis at collabora.com>
AuthorDate: Tue Aug 25 12:01:51 2020 +0530
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Fri Aug 28 17:04:56 2020 +0200

    specialize twips/core-pixels/css-pixels conversion methods
    
    Change-Id: Ifb0a67b938fdd34a06bb7e75832498d566247010

diff --git a/loleaflet/src/layer/tile/CalcTileLayer.js b/loleaflet/src/layer/tile/CalcTileLayer.js
index 2c6f74a77..403f2e27e 100644
--- a/loleaflet/src/layer/tile/CalcTileLayer.js
+++ b/loleaflet/src/layer/tile/CalcTileLayer.js
@@ -499,17 +499,16 @@ L.CalcTileLayer = BaseTileLayer.extend({
 			return;
 		}
 
-		var newWidthPx = newDocWidth / this._tileWidthTwips * this._tileSize;
-		var newHeightPx = newDocHeight / this._tileHeightTwips * this._tileSize;
+		var newSizePx = this._twipsToCorePixels(new L.Point(newDocWidth, newDocHeight));
 
 		var topLeft = this._map.unproject(new L.Point(0, 0));
-		var bottomRight = this._map.unproject(new L.Point(newWidthPx, newHeightPx));
+		var bottomRight = this._map.unproject(newSizePx);
 		this._map.setMaxBounds(new L.LatLngBounds(topLeft, bottomRight));
 
-		this._docPixelSize = {x: newWidthPx, y: newHeightPx};
+		this._docPixelSize = newSizePx.clone();
 		this._docWidthTwips = newDocWidth;
 		this._docHeightTwips = newDocHeight;
-		this._map.fire('docsize', {x: newWidthPx, y: newHeightPx});
+		this._map.fire('docsize', newSizePx.clone());
 	},
 
 	_onUpdateCurrentHeader: function() {
@@ -563,8 +562,9 @@ L.CalcTileLayer = BaseTileLayer.extend({
 			this._selectedPart = command.selectedPart;
 			this._viewId = parseInt(command.viewid);
 			var mapSize = this._map.getSize();
-			var width = this._docWidthTwips / this._tileWidthTwips * this._tileSize;
-			var height = this._docHeightTwips / this._tileHeightTwips * this._tileSize;
+			var sizePx = this._twipsToPixels(new L.Point(this._docWidthTwips, this._docHeightTwips));
+			var width = sizePx.x;
+			var height = sizePx.y;
 			if (width < mapSize.x || height < mapSize.y) {
 				width = Math.max(width, mapSize.x);
 				height = Math.max(height, mapSize.y);
diff --git a/loleaflet/src/layer/tile/CanvasTileLayer.js b/loleaflet/src/layer/tile/CanvasTileLayer.js
index 88e271431..35f23437a 100644
--- a/loleaflet/src/layer/tile/CanvasTileLayer.js
+++ b/loleaflet/src/layer/tile/CanvasTileLayer.js
@@ -158,16 +158,17 @@ L.CanvasTilePainter = L.Class.extend({
 		var tileBounds = new L.Bounds(tileTopLeft, tileTopLeft.add(ctx.tileSize));
 
 		for (var i = 0; i < ctx.paneBoundsList.length; ++i) {
-			var paneBounds = ctx.paneBoundsList[i];
+			var paneBounds = this._layer._cssBoundsToCore(ctx.paneBoundsList[i]);
+			var viewBounds = this._layer._cssBoundsToCore(ctx.viewBounds);
 
 			if (!paneBounds.intersects(tileBounds))
 				continue;
 
 			var topLeft = paneBounds.getTopLeft();
 			if (topLeft.x)
-				topLeft.x = ctx.viewBounds.min.x;
+				topLeft.x = viewBounds.min.x;
 			if (topLeft.y)
-				topLeft.y = ctx.viewBounds.min.y;
+				topLeft.y = viewBounds.min.y;
 
 			this._canvasCtx.save();
 			this._canvasCtx.scale(1, 1);
@@ -194,7 +195,7 @@ L.CanvasTilePainter = L.Class.extend({
 		if (!splitPanesContext) {
 			return;
 		}
-		var splitPos = splitPanesContext.getSplitPos();
+		var splitPos = this._layer._cssPixelsToCore(splitPanesContext.getSplitPos());
 		this._canvasCtx.save();
 		this._canvasCtx.scale(1, 1);
 		this._canvasCtx.strokeStyle = 'red';
@@ -497,8 +498,75 @@ L.CanvasTileLayer = L.TileLayer.extend({
 
 	_pxBoundsToTileRange: function (bounds) {
 		return new L.Bounds(
-			bounds.min.divideBy(this._tileSize).floor(),
-			bounds.max.divideBy(this._tileSize).floor());
+			this._cssPixelsToCore(bounds.min)._divideBy(this._tileSize)._floor(),
+			this._cssPixelsToCore(bounds.max)._divideBy(this._tileSize)._floor());
+	},
+
+	_getCoreZoomFactor: function () {
+		return new L.Point(
+			this._tileSize * 15.0 / this._tileWidthTwips,
+			this._tileSize * 15.0 / this._tileHeightTwips);
+	},
+
+	_corePixelsToCss: function (corePixels) {
+		var dpiScale = this.canvasDPIScale();
+		return corePixels.divideBy(dpiScale);
+	},
+
+	_cssPixelsToCore: function (cssPixels) {
+		var dpiScale = this.canvasDPIScale();
+		return cssPixels.multiplyBy(dpiScale);
+	},
+
+	_cssBoundsToCore: function (bounds) {
+		return new L.Bounds(
+			this._cssPixelsToCore(bounds.min),
+			this._cssPixelsToCore(bounds.max)
+		);
+	},
+
+	_twipsToCorePixels: function (twips) {
+		return new L.Point(
+			twips.x / this._tileWidthTwips * this._tileSize,
+			twips.y / this._tileHeightTwips * this._tileSize);
+	},
+
+	_corePixelsToTwips: function (corePixels) {
+		return new L.Point(
+			corePixels.x / this._tileSize * this._tileWidthTwips,
+			corePixels.y / this._tileSize * this._tileHeightTwips);
+	},
+
+	_twipsToCssPixels: function (twips) {
+		var dpiScale = this.canvasDPIScale();
+		return new L.Point(
+			twips.x / this._tileWidthTwips * this._tileSize / dpiScale,
+			twips.y / this._tileHeightTwips * this._tileSize / dpiScale);
+	},
+
+	_cssPixelsToTwips: function (pixels) {
+		var dpiScale = this.canvasDPIScale();
+		return new L.Point(
+			pixels.x * dpiScale / this._tileSize * this._tileWidthTwips,
+			pixels.y * dpiScale / this._tileSize * this._tileHeightTwips);
+	},
+
+	_twipsToLatLng: function (twips, zoom) {
+		var pixels = this._twipsToCssPixels(twips);
+		return this._map.unproject(pixels, zoom);
+	},
+
+	_latLngToTwips: function (latLng, zoom) {
+		var pixels = this._map.project(latLng, zoom);
+		return this._cssPixelsToTwips(pixels);
+	},
+
+	_twipsToPixels: function (twips) { // css pixels
+		return this._twipsToCssPixels(twips);
+	},
+
+	_pixelsToTwips: function (pixels) { // css pixels
+		return this._cssPixelsToTwips(pixels);
 	},
 
 	_twipsToCoords: function (twips) {
@@ -524,6 +592,48 @@ L.CanvasTileLayer = L.TileLayer.extend({
 		return true;
 	},
 
+	_updateMaxBounds: function (sizeChanged, extraSize, options, zoom) {
+		if (this._docWidthTwips === undefined || this._docHeightTwips === undefined) {
+			return;
+		}
+		if (!zoom) {
+			zoom = this._map.getZoom();
+		}
+
+		var dpiScale = this.canvasDPIScale();
+		var docPixelLimits = new L.Point(this._docWidthTwips / this.options.tileWidthTwips,
+			this._docHeightTwips / this.options.tileHeightTwips);
+		// docPixelLimits should be in csspx.
+		docPixelLimits = docPixelLimits.multiplyBy(this._tileSize / dpiScale);
+		var scale = this._map.getZoomScale(zoom, 10);
+		var topLeft = new L.Point(0, 0);
+		topLeft = this._map.unproject(topLeft.multiplyBy(scale));
+		var bottomRight = new L.Point(docPixelLimits.x, docPixelLimits.y);
+		bottomRight = bottomRight.multiplyBy(scale);
+		if (extraSize) {
+			// extraSize is unscaled.
+			bottomRight = bottomRight.add(extraSize);
+		}
+		bottomRight = this._map.unproject(bottomRight);
+
+		if (this._documentInfo === '' || sizeChanged) {
+			// we just got the first status so we need to center the document
+			this._map.setMaxBounds(new L.LatLngBounds(topLeft, bottomRight), options);
+			this._map.setDocBounds(new L.LatLngBounds(topLeft, this._map.unproject(docPixelLimits.multiplyBy(scale))));
+		}
+
+		var scrollPixelLimits = new L.Point(this._docWidthTwips / this._tileWidthTwips,
+			this._docHeightTwips / this._tileHeightTwips);
+		scrollPixelLimits = scrollPixelLimits.multiplyBy(this._tileSize / dpiScale);
+		if (extraSize) {
+			// extraSize is unscaled.
+			scrollPixelLimits = scrollPixelLimits.add(extraSize);
+		}
+		this._docPixelSize = {x: scrollPixelLimits.x, y: scrollPixelLimits.y};
+		this._map.fire('docsize', {x: scrollPixelLimits.x, y: scrollPixelLimits.y, extraSize: extraSize});
+	},
+
+
 	_update: function (center, zoom) {
 		var map = this._map;
 		if (!map || this._documentInfo === '') {
@@ -1048,6 +1158,8 @@ L.CanvasTileLayer = L.TileLayer.extend({
 
 		var nwPoint = new L.Point(coords.x, coords.y);
 		var sePoint = nwPoint.add([tileSize, tileSize]);
+		nwPoint = this._corePixelsToCss(nwPoint);
+		sePoint = this._corePixelsToCss(sePoint);
 
 		var nw = map.wrapLatLng(map.unproject(nwPoint, coords.z));
 		var se = map.wrapLatLng(map.unproject(sePoint, coords.z));
commit 286a89dc3a7d2f002d7d45c601c966c1b5aa1eb1
Author:     Dennis Francis <dennis.francis at collabora.com>
AuthorDate: Tue Aug 25 11:55:25 2020 +0530
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Fri Aug 28 17:04:56 2020 +0200

    detect change in dpi and update zoom
    
    Change-Id: I034727a8fe8495445350648fea2422c56fda1875

diff --git a/loleaflet/src/layer/tile/CanvasTileLayer.js b/loleaflet/src/layer/tile/CanvasTileLayer.js
index 2a28a3e9e..88e271431 100644
--- a/loleaflet/src/layer/tile/CanvasTileLayer.js
+++ b/loleaflet/src/layer/tile/CanvasTileLayer.js
@@ -210,6 +210,14 @@ L.CanvasTilePainter = L.Class.extend({
 
 	update: function () {
 
+		var newDpiScale = L.getDpiScaleFactor(true /* useExactDPR */);
+		var scaleChanged = this._dpiScale != newDpiScale;
+
+		if (scaleChanged) {
+			this._dpiScale = L.getDpiScaleFactor(true /* useExactDPR */);
+			this._map.setZoom();
+		}
+
 		var splitPanesContext = this._layer.getSplitPanesContext();
 		var zoom = Math.round(this._map.getZoom());
 		var pixelBounds = this._map.getPixelBounds();
@@ -218,11 +226,9 @@ L.CanvasTilePainter = L.Class.extend({
 		var part = this._layer._selectedPart;
 		var newSplitPos = splitPanesContext ?
 		    splitPanesContext.getSplitPos(): this._splitPos;
-		var newDpiScale = L.getDpiScaleFactor(true /* useExactDPR */);
 
 		var zoomChanged = (zoom !== this._lastZoom);
 		var partChanged = (part !== this._lastPart);
-		var scaleChanged = this._dpiScale != newDpiScale;
 
 		var mapSizeChanged = !newMapSize.equals(this._lastMapSize);
 		// To avoid flicker, only resize the canvas element if width or height of the map increases.
@@ -246,11 +252,6 @@ L.CanvasTilePainter = L.Class.extend({
 		if (skipUpdate)
 			return;
 
-		if (scaleChanged) {
-			this._dpiScale = L.getDpiScaleFactor(true /* useExactDPR */);
-			console.log('DEBUG: scaleChanged : this._dpiScale = ' + this._dpiScale);
-		}
-
 		if (resizeCanvas || scaleChanged) {
 			this._setCanvasSize(newSize.x, newSize.y);
 			this._lastSize = newSize;
@@ -384,12 +385,8 @@ L.CanvasTileLayer = L.TileLayer.extend({
 		this._tileHeightPx = this.options.tileSize;
 		this._tilePixelScale = 1;
 
-		// FIXME: workaround for correcting initial zoom with dpiscale included.
-		// The one set during Map constructor is does not include dpiscale because
-		// there we don't have enough info to specialize for calc-canvas
-		map.setZoom(map.getZoom());
-
 		L.TileLayer.prototype.onAdd.call(this, map);
+		map.setZoom();
 	},
 
 	onRemove: function (map) {
diff --git a/loleaflet/src/map/Map.js b/loleaflet/src/map/Map.js
index 0592c801d..8c3271b95 100644
--- a/loleaflet/src/map/Map.js
+++ b/loleaflet/src/map/Map.js
@@ -476,8 +476,14 @@ L.Map = L.Evented.extend({
 
 	setZoom: function (zoom, options) {
 
-		if (this._docLayer instanceof L.CanvasTileLayer)
+		if (this._docLayer instanceof L.CanvasTileLayer) {
+			if (!zoom)
+				zoom = this._clientZoom || this.options.zoom;
+			else
+				this._clientZoom = zoom;
+
 			zoom = this.findNearestProductZoom(zoom);
+		}
 
 		if (!this._loaded) {
 			this._zoom = this._limitZoom(zoom);
commit d5fe86c7e0cb7b64128540319b3074a46258f825
Author:     Dennis Francis <dennis.francis at collabora.com>
AuthorDate: Tue Aug 25 11:36:03 2020 +0530
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Fri Aug 28 17:04:56 2020 +0200

    use the main canvas dpiScale everywhere
    
    Change-Id: I2bea44a000552ce8f2fee2b0ebb5a4d162d3576f

diff --git a/loleaflet/src/control/Control.ColumnHeader.js b/loleaflet/src/control/Control.ColumnHeader.js
index 53ae8b9f2..df70e6cb7 100644
--- a/loleaflet/src/control/Control.ColumnHeader.js
+++ b/loleaflet/src/control/Control.ColumnHeader.js
@@ -39,7 +39,7 @@ L.Control.ColumnHeader = L.Control.Header.extend({
 		this._setCanvasHeight();
 		this._canvasBaseHeight = this._canvasHeight;
 
-		var scale = L.getDpiScaleFactor();
+		var scale = this.canvasDPIScale();
 		this._canvasContext.scale(scale, scale);
 
 		this._headerHeight = this._canvasHeight;
@@ -224,8 +224,7 @@ L.Control.ColumnHeader = L.Control.Header.extend({
 			return;
 
 		ctx.save();
-		var useExactDPR = this._map && (this._map._docLayer instanceof L.CanvasTileLayer);
-		var scale = L.getDpiScaleFactor(useExactDPR);
+		var scale = this.canvasDPIScale();
 		ctx.scale(scale, scale);
 		// background gradient
 		var selectionBackgroundGradient = null;
@@ -291,7 +290,7 @@ L.Control.ColumnHeader = L.Control.Header.extend({
 		var height = group.endPos - group.startPos;
 
 		ctx.save();
-		var scale = L.getDpiScaleFactor();
+		var scale = this.canvasDPIScale();
 		ctx.scale(scale, scale);
 
 		// clip mask
@@ -340,7 +339,7 @@ L.Control.ColumnHeader = L.Control.Header.extend({
 		var ctx = this._cornerCanvasContext;
 		var ctrlHeadSize = this._groupHeadSize;
 		var levelSpacing = this._levelSpacing;
-		var scale = L.getDpiScaleFactor();
+		var scale = this.canvasDPIScale();
 
 		var startOrt = levelSpacing + (ctrlHeadSize + levelSpacing) * level;
 		var startPar = this._cornerCanvas.width / scale - (ctrlHeadSize + (L.Control.Header.rowHeaderWidth - ctrlHeadSize) / 2);
@@ -533,7 +532,7 @@ L.Control.ColumnHeader = L.Control.Header.extend({
 			return;
 		}
 
-		var scale = L.getDpiScaleFactor();
+		var scale = this.canvasDPIScale();
 		var rowOutlineWidth = this._cornerCanvas.width / scale - L.Control.Header.rowHeaderWidth - this._borderWidth;
 		if (pos.x <= rowOutlineWidth) {
 			// empty rectangle on the left select all
diff --git a/loleaflet/src/control/Control.Header.js b/loleaflet/src/control/Control.Header.js
index 757cfd5c8..89fc78fe0 100644
--- a/loleaflet/src/control/Control.Header.js
+++ b/loleaflet/src/control/Control.Header.js
@@ -578,8 +578,13 @@ L.Control.Header = L.Control.extend({
 		return Math.round(this._getParallelPos(this.converter(point)));
 	},
 
+	canvasDPIScale: function () {
+		var docLayer = this._map && this._map._docLayer;
+		var scale = docLayer && docLayer.canvasDPIScale ? docLayer.canvasDPIScale() : L.getDpiScaleFactor();
+		return scale;
+	},
+
 	_setCanvasSizeImpl: function (container, canvas, property, value, isCorner) {
-		var useExactDPR = this._map && (this._map._docLayer instanceof L.CanvasTileLayer);
 		if (!value) {
 			value = parseInt(L.DomUtil.getStyle(container, property));
 		}
@@ -587,15 +592,15 @@ L.Control.Header = L.Control.extend({
 			L.DomUtil.setStyle(container, property, value + 'px');
 		}
 
-		var scale = L.getDpiScaleFactor(useExactDPR);
+		var scale = this.canvasDPIScale();
 		if (property === 'width') {
-			canvas.width = value * scale;
+			canvas.width = Math.floor(value * scale);
 			if (!isCorner)
 				this._canvasWidth = value;
 //			console.log('Header._setCanvasSizeImpl: _canvasWidth' + this._canvasWidth);
 		}
 		else if (property === 'height') {
-			canvas.height = value * scale;
+			canvas.height = Math.floor(value * scale);
 			if (!isCorner)
 				this._canvasHeight = value;
 //			console.log('Header._setCanvasSizeImpl: _canvasHeight' + this._canvasHeight);
@@ -718,7 +723,7 @@ L.Control.Header = L.Control.extend({
 			return;
 
 		ctx.save();
-		var scale = L.getDpiScaleFactor();
+		var scale = this.canvasDPIScale();
 		ctx.scale(scale, scale);
 
 		ctx.fillStyle = this._borderColor;
diff --git a/loleaflet/src/control/Control.RowHeader.js b/loleaflet/src/control/Control.RowHeader.js
index 32974d9e9..2f42023be 100644
--- a/loleaflet/src/control/Control.RowHeader.js
+++ b/loleaflet/src/control/Control.RowHeader.js
@@ -39,7 +39,7 @@ L.Control.RowHeader = L.Control.Header.extend({
 		this._setCanvasWidth();
 		this._setCanvasHeight();
 
-		var scale = L.getDpiScaleFactor();
+		var scale = this.canvasDPIScale();
 		this._canvasContext.scale(scale, scale);
 		this._headerWidth = this._canvasWidth;
 		L.Control.Header.rowHeaderWidth = this._canvasWidth;
@@ -217,8 +217,7 @@ L.Control.RowHeader = L.Control.Header.extend({
 			return;
 
 		ctx.save();
-		var useExactDPR = this._map && (this._map._docLayer instanceof L.CanvasTileLayer);
-		var scale = L.getDpiScaleFactor(useExactDPR);
+		var scale = this.canvasDPIScale();
 		ctx.scale(scale, scale);
 		// background gradient
 		var selectionBackgroundGradient = null;
@@ -280,7 +279,7 @@ L.Control.RowHeader = L.Control.Header.extend({
 		var height = group.endPos - group.startPos;
 
 		ctx.save();
-		var scale = L.getDpiScaleFactor();
+		var scale = this.canvasDPIScale();
 		ctx.scale(scale, scale);
 
 		// clip mask
@@ -329,7 +328,7 @@ L.Control.RowHeader = L.Control.Header.extend({
 		var ctx = this._cornerCanvasContext;
 		var ctrlHeadSize = this._groupHeadSize;
 		var levelSpacing = this._levelSpacing;
-		var scale = L.getDpiScaleFactor();
+		var scale = this.canvasDPIScale();
 
 		var startOrt = levelSpacing + (ctrlHeadSize + levelSpacing) * level;
 		var startPar = this._cornerCanvas.height / scale - (ctrlHeadSize + (L.Control.Header.colHeaderHeight - ctrlHeadSize) / 2);
diff --git a/loleaflet/src/layer/tile/CalcTileLayer.js b/loleaflet/src/layer/tile/CalcTileLayer.js
index 70303c4c0..2c6f74a77 100644
--- a/loleaflet/src/layer/tile/CalcTileLayer.js
+++ b/loleaflet/src/layer/tile/CalcTileLayer.js
@@ -79,7 +79,6 @@ L.CalcTileLayer = BaseTileLayer.extend({
 	},
 
 	onAdd: function (map) {
-		this._useExactDPR = this._hasCanvasRenderer = (this instanceof L.CanvasTileLayer);
 		map.addControl(L.control.tabs());
 		map.addControl(L.control.columnHeader());
 		map.addControl(L.control.rowHeader());
@@ -473,7 +472,7 @@ L.CalcTileLayer = BaseTileLayer.extend({
 		this._sendClientZoom();
 		if (this.sheetGeometry) {
 			this.sheetGeometry.setTileGeometryData(this._tileWidthTwips, this._tileHeightTwips,
-				this._tileSize, this._hasCanvasRenderer ? L.getDpiScaleFactor(true /* useExactDPR */) : this._tilePixelScale);
+				this._tileSize, this.hasCanvasRenderer() ? this.canvasDPIScale() : this._tilePixelScale);
 		}
 		this._restrictDocumentSize();
 		this._replayPrintTwipsMsgs();
@@ -739,7 +738,7 @@ L.CalcTileLayer = BaseTileLayer.extend({
 	_handleSheetGeometryDataMsg: function (jsonMsgObj) {
 		if (!this.sheetGeometry) {
 			this._sheetGeomFirstWait = false;
-			var dpiScale = this._hasCanvasRenderer ? L.getDpiScaleFactor(true /* useExactDPR */) : this._tilePixelScale;
+			var dpiScale = this.hasCanvasRenderer() ? this.canvasDPIScale() : this._tilePixelScale;
 			this.sheetGeometry = new L.SheetGeometry(jsonMsgObj,
 				this._tileWidthTwips, this._tileHeightTwips,
 				this._tileSize, dpiScale, this._selectedPart);
diff --git a/loleaflet/src/layer/tile/CanvasTileLayer.js b/loleaflet/src/layer/tile/CanvasTileLayer.js
index f8b739a2a..2a28a3e9e 100644
--- a/loleaflet/src/layer/tile/CanvasTileLayer.js
+++ b/loleaflet/src/layer/tile/CanvasTileLayer.js
@@ -111,6 +111,10 @@ L.CanvasTilePainter = L.Class.extend({
 		this._syncTileContainerSize();
 	},
 
+	canvasDPIScale: function () {
+		return parseInt(this._canvas.width) / this._width;
+	},
+
 	_syncTileContainerSize: function () {
 		var tileContainer = this._layer._container;
 		if (tileContainer) {
@@ -481,6 +485,10 @@ L.CanvasTileLayer = L.TileLayer.extend({
 			coords.part);
 	},
 
+	canvasDPIScale: function () {
+		return this._painter.canvasDPIScale();
+	},
+
 	_pxBoundsToTileRanges: function (bounds) {
 		if (!this._splitPanesContext) {
 			return [this._pxBoundsToTileRange(bounds)];
@@ -1210,6 +1218,10 @@ L.CanvasTileLayer = L.TileLayer.extend({
 		return !!(this._ySplitter);
 	},
 
+	hasCanvasRenderer: function () {
+		return true;
+	},
+
 });
 
 L.TilesPreFetcher = L.Class.extend({
diff --git a/loleaflet/src/layer/tile/GridLayer.js b/loleaflet/src/layer/tile/GridLayer.js
index 5d3ce69db..4ad07d8fa 100644
--- a/loleaflet/src/layer/tile/GridLayer.js
+++ b/loleaflet/src/layer/tile/GridLayer.js
@@ -1352,6 +1352,10 @@ L.GridLayer = L.Layer.extend({
 		return docPosPixY;
 	},
 
+	hasCanvasRenderer: function () {
+		return false;
+	},
+
 	hasSplitPanesSupport: function () {
 		return false;
 	},
diff --git a/loleaflet/src/map/Map.js b/loleaflet/src/map/Map.js
index 946896e0c..0592c801d 100644
--- a/loleaflet/src/map/Map.js
+++ b/loleaflet/src/map/Map.js
@@ -452,12 +452,23 @@ L.Map = L.Evented.extend({
 		this._progressBar.end(this);
 	},
 
+	zoomToFactor: function (zoom) {
+		return Math.pow(1.2, (zoom - this.options.zoom));
+	},
+
+	factorToZoom: function (zoomFactor) {
+		var relzoom = Math.log(zoomFactor) / Math.log(1.2);
+		return Math.round(relzoom) + this.options.zoom;
+	},
+
 	// Compute the nearest zoom level corresponding to the effective zoom-scale (ie, with dpiscale included).
 	findNearestProductZoom: function (zoom) {
-		var clientZoomScale = Math.pow(1.2, (zoom - this.options.zoom));
+		var clientZoomScale = this.zoomToFactor(zoom);
+
+		var dpiScale = this._docLayer ? this._docLayer.canvasDPIScale() : L.getDpiScaleFactor(true /* useExactDPR */);
 
-		var zoomScale = clientZoomScale * L.getCanvasScaleFactor();
-		var nearestZoom = Math.round((Math.log(zoomScale) / Math.log(1.2)) + this.options.zoom);
+		var zoomScale = clientZoomScale * dpiScale;
+		var nearestZoom = this.factorToZoom(zoomScale);
 		nearestZoom = this._limitZoom(nearestZoom);
 
 		return nearestZoom;
commit 9abba48fdd9d11974c0a666f3f467f1470e7dee2
Author:     Dennis Francis <dennis.francis at collabora.com>
AuthorDate: Mon Aug 24 22:34:27 2020 +0530
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Fri Aug 28 17:04:56 2020 +0200

    sheetGeometry: use exact dpiScale when canvas is used
    
    Also use the term core-pixels instead of 'device pixels' which is more
    appropriate.
    
    Change-Id: I18952393f17e0391167e0219b829be47723c5c47

diff --git a/loleaflet/src/layer/tile/CalcTileLayer.js b/loleaflet/src/layer/tile/CalcTileLayer.js
index be567fa14..70303c4c0 100644
--- a/loleaflet/src/layer/tile/CalcTileLayer.js
+++ b/loleaflet/src/layer/tile/CalcTileLayer.js
@@ -79,6 +79,7 @@ L.CalcTileLayer = BaseTileLayer.extend({
 	},
 
 	onAdd: function (map) {
+		this._useExactDPR = this._hasCanvasRenderer = (this instanceof L.CanvasTileLayer);
 		map.addControl(L.control.tabs());
 		map.addControl(L.control.columnHeader());
 		map.addControl(L.control.rowHeader());
@@ -472,7 +473,7 @@ L.CalcTileLayer = BaseTileLayer.extend({
 		this._sendClientZoom();
 		if (this.sheetGeometry) {
 			this.sheetGeometry.setTileGeometryData(this._tileWidthTwips, this._tileHeightTwips,
-				this._tileSize, this._tilePixelScale);
+				this._tileSize, this._hasCanvasRenderer ? L.getDpiScaleFactor(true /* useExactDPR */) : this._tilePixelScale);
 		}
 		this._restrictDocumentSize();
 		this._replayPrintTwipsMsgs();
@@ -738,9 +739,10 @@ L.CalcTileLayer = BaseTileLayer.extend({
 	_handleSheetGeometryDataMsg: function (jsonMsgObj) {
 		if (!this.sheetGeometry) {
 			this._sheetGeomFirstWait = false;
+			var dpiScale = this._hasCanvasRenderer ? L.getDpiScaleFactor(true /* useExactDPR */) : this._tilePixelScale;
 			this.sheetGeometry = new L.SheetGeometry(jsonMsgObj,
 				this._tileWidthTwips, this._tileHeightTwips,
-				this._tileSize, this._tilePixelScale, this._selectedPart);
+				this._tileSize, dpiScale, this._selectedPart);
 		}
 		else {
 			this.sheetGeometry.update(jsonMsgObj, /* checkCompleteness */ false, this._selectedPart);
@@ -1220,12 +1222,12 @@ L.SheetGeometry = L.Class.extend({
 	// all flags (ie 'columns', 'rows', 'sizes', 'hidden', 'filtered',
 	// 'groups') enabled.
 	initialize: function (sheetGeomJSON, tileWidthTwips, tileHeightTwips,
-		tileSizeCSSPixels, dpiScale, part) {
+		tileSizePixels, dpiScale, part) {
 
 		if (typeof sheetGeomJSON !== 'object' ||
 			typeof tileWidthTwips !== 'number' ||
 			typeof tileHeightTwips !== 'number' ||
-			typeof tileSizeCSSPixels !== 'number' ||
+			typeof tileSizePixels !== 'number' ||
 			typeof dpiScale !== 'number' ||
 			typeof part !== 'number') {
 			console.error('Incorrect constructor argument types or missing required arguments');
@@ -1238,7 +1240,7 @@ L.SheetGeometry = L.Class.extend({
 		this._unoCommand = '.uno:SheetGeometryData';
 
 		// Set various unit conversion info early on because on update() call below, these info are needed.
-		this.setTileGeometryData(tileWidthTwips, tileHeightTwips, tileSizeCSSPixels,
+		this.setTileGeometryData(tileWidthTwips, tileHeightTwips, tileSizePixels,
 			dpiScale, false /* update position info ?*/);
 
 		this.update(sheetGeomJSON, /* checkCompleteness */ true, part);
@@ -1282,10 +1284,10 @@ L.SheetGeometry = L.Class.extend({
 		return this._part;
 	},
 
-	setTileGeometryData: function (tileWidthTwips, tileHeightTwips, tileSizeCSSPixels,
+	setTileGeometryData: function (tileWidthTwips, tileHeightTwips, tileSizePixels,
 		dpiScale, updatePositions) {
-		this._columns.setTileGeometryData(tileWidthTwips, tileSizeCSSPixels, dpiScale, updatePositions);
-		this._rows.setTileGeometryData(tileHeightTwips, tileSizeCSSPixels, dpiScale, updatePositions);
+		this._columns.setTileGeometryData(tileWidthTwips, tileSizePixels, dpiScale, updatePositions);
+		this._rows.setTileGeometryData(tileHeightTwips, tileSizePixels, dpiScale, updatePositions);
 	},
 
 	setViewArea: function (topLeftTwipsPoint, sizeTwips) {
@@ -1426,7 +1428,7 @@ L.SheetGeometry = L.Class.extend({
 	},
 
 	// Returns full sheet size as L.Point in the given unit.
-	// unit must be one of 'csspixels', 'devpixels', 'tiletwips', 'printtwips'
+	// unit must be one of 'csspixels', 'corepixels', 'tiletwips', 'printtwips'
 	getSize: function (unit) {
 		return new L.Point(this._columns.getSize(unit),
 			this._rows.getSize(unit));
@@ -1434,8 +1436,8 @@ L.SheetGeometry = L.Class.extend({
 
 	// Returns the CSS pixel position/size of the requested cell at a specified zoom.
 	getCellRect: function (columnIndex, rowIndex, zoomScale) {
-		var horizPosSize = this._columns.getElementData(columnIndex, false /* devicePixels */, zoomScale);
-		var vertPosSize  = this._rows.getElementData(rowIndex, false /* devicePixels */, zoomScale);
+		var horizPosSize = this._columns.getElementData(columnIndex, false /* corePixels */, zoomScale);
+		var vertPosSize  = this._rows.getElementData(rowIndex, false /* corePixels */, zoomScale);
 
 		var topLeft = new L.Point(horizPosSize.startpos, vertPosSize.startpos);
 		var size = new L.Point(horizPosSize.size, vertPosSize.size);
@@ -1452,13 +1454,13 @@ L.SheetGeometry = L.Class.extend({
 	},
 
 	// Returns the start position of the column containing posX in the specified unit.
-	// unit must be one of 'csspixels', 'devpixels', 'tiletwips', 'printtwips'
+	// unit must be one of 'csspixels', 'corepixels', 'tiletwips', 'printtwips'
 	getSnapDocPosX: function (posX, unit) {
 		return this._columns.getSnapPos(posX, unit);
 	},
 
 	// Returns the start position of the row containing posY in the specified unit.
-	// unit must be one of 'csspixels', 'devpixels', 'tiletwips', 'printtwips'
+	// unit must be one of 'csspixels', 'corepixels', 'tiletwips', 'printtwips'
 	getSnapDocPosY: function (posY, unit) {
 		return this._rows.getSnapPos(posY, unit);
 	},
@@ -1590,7 +1592,7 @@ L.SheetDimension = L.Class.extend({
 		this._maxIndex = maxIndex;
 	},
 
-	setTileGeometryData: function (tileSizeTwips, tileSizeCSSPixels, dpiScale, updatePositions) {
+	setTileGeometryData: function (tileSizeTwips, tileSizePixels, dpiScale, updatePositions) {
 
 		if (updatePositions === undefined) {
 			updatePositions = true;
@@ -1598,17 +1600,22 @@ L.SheetDimension = L.Class.extend({
 
 		// Avoid position re-computations if no change in Zoom/dpiScale.
 		if (this._tileSizeTwips === tileSizeTwips &&
-			this._tileSizeCSSPixels === tileSizeCSSPixels &&
+			this._tileSizePixels === tileSizePixels &&
 			this._dpiScale === dpiScale) {
 			return;
 		}
 
 		this._tileSizeTwips = tileSizeTwips;
-		this._tileSizeCSSPixels = tileSizeCSSPixels;
+		this._tileSizePixels = tileSizePixels;
 		this._dpiScale = dpiScale;
 
-		this._twipsPerCSSPixel = tileSizeTwips / tileSizeCSSPixels;
-		this._devPixelsPerCssPixel = dpiScale;
+		// number of core-pixels in the tile is the same as the number of device pixels used to render the tile.
+		// (Note that when not using L.CanvasTileLayer, we do not use the exact window.devicePixelRatio
+		// for dpiScale hence the usage of the term device-pixels is not accurate.)
+		this._coreZoomFactor = this._tileSizePixels * 15.0 / this._tileSizeTwips;
+		this._twipsPerCorePixel = this._tileSizeTwips / this._tileSizePixels;
+
+		this._corePixelsPerCssPixel = this._dpiScale;
 
 		if (updatePositions) {
 			// We need to compute positions data for every zoom change.
@@ -1625,7 +1632,7 @@ L.SheetDimension = L.Class.extend({
 
 	_updatePositions: function() {
 
-		var posDevPx = 0; // position in device pixels.
+		var posCorePx = 0; // position in core pixels.
 		var posPrintTwips = 0;
 		var dimensionObj = this;
 		this._visibleSizes.addCustomDataForEachSpan(function (
@@ -1633,17 +1640,17 @@ L.SheetDimension = L.Class.extend({
 			size, /* size in twips of one element in the span */
 			spanLength /* #elements in the span */) {
 
-			// Important: rounding needs to be done in device pixels exactly like the core.
-			var sizeDevPxOne = Math.floor(size / dimensionObj._twipsPerCSSPixel * dimensionObj._devPixelsPerCssPixel);
-			posDevPx += (sizeDevPxOne * spanLength);
-			var posCssPx = posDevPx / dimensionObj._devPixelsPerCssPixel;
-			// position in device-pixel aligned twips.
-			var posTileTwips = Math.floor(posCssPx * dimensionObj._twipsPerCSSPixel);
+			// Important: rounding needs to be done in core pixels to match core.
+			var sizeCorePxOne = Math.floor(size / dimensionObj._twipsPerCorePixel);
+			posCorePx += (sizeCorePxOne * spanLength);
+			var posCssPx = posCorePx / dimensionObj._corePixelsPerCssPixel;
+			// position in core-pixel aligned twips.
+			var posTileTwips = Math.floor(posCorePx * dimensionObj._twipsPerCorePixel);
 			posPrintTwips += (size * spanLength);
 
 			var customData = {
-				sizedev: sizeDevPxOne,
-				posdevpx: posDevPx,
+				sizecore: sizeCorePxOne,
+				poscorepx: posCorePx,
 				poscsspx: posCssPx,
 				postiletwips: posTileTwips,
 				posprinttwips: posPrintTwips
@@ -1654,23 +1661,29 @@ L.SheetDimension = L.Class.extend({
 	},
 
 	// returns the element pos/size in css pixels by default.
-	getElementData: function (index, useDevicePixels, zoomScale) {
+	getElementData: function (index, useCorePixels, zoomScale) {
 		if (zoomScale !== undefined) {
 			var startpos = 0;
 			var size = 0;
 			this._visibleSizes.forEachSpanInRange(0, index, function (spanData) {
 				var count = spanData.end - spanData.start + 1;
-				var sizeOneCSSPx = Math.floor(spanData.size * zoomScale / 15.0);
+				var sizeOneCorePx = Math.floor(spanData.size * zoomScale / 15.0);
 				if (index > spanData.end) {
-					startpos += (sizeOneCSSPx * count);
+					startpos += (sizeOneCorePx * count);
 				}
 				else if (index >= spanData.start && index <= spanData.end) {
 					// final span
-					startpos += (sizeOneCSSPx * (index - spanData.start));
-					size = sizeOneCSSPx;
+					startpos += (sizeOneCorePx * (index - spanData.start));
+					size = sizeOneCorePx;
 				}
 			});
 
+			if (!useCorePixels) {
+				// startpos and size are now in core pixels, so convert to css pixels.
+				startpos = Math.floor(startpos / this._corePixelsPerCssPixel);
+				size = Math.floor(size / this._corePixelsPerCssPixel);
+			}
+
 			return {
 				startpos: startpos,
 				size: size
@@ -1682,7 +1695,7 @@ L.SheetDimension = L.Class.extend({
 			return undefined;
 		}
 
-		return this._getElementDataFromSpanByIndex(index, span, useDevicePixels);
+		return this._getElementDataFromSpanByIndex(index, span, useCorePixels);
 	},
 
 	getElementDataAny: function (index, unitName) {
@@ -1695,9 +1708,9 @@ L.SheetDimension = L.Class.extend({
 	},
 
 	// returns element pos/size in css pixels by default.
-	_getElementDataFromSpanByIndex: function (index, span, useDevicePixels) {
+	_getElementDataFromSpanByIndex: function (index, span, useCorePixels) {
 		return this._getElementDataAnyFromSpanByIndex(index, span,
-				useDevicePixels ? 'devpixels' : 'csspixels');
+				useCorePixels ? 'corepixels' : 'csspixels');
 	},
 
 	// returns element pos/size in the requested unit.
@@ -1707,20 +1720,20 @@ L.SheetDimension = L.Class.extend({
 			return undefined;
 		}
 
-		if (unitName !== 'csspixels' && unitName !== 'devpixels' &&
+		if (unitName !== 'csspixels' && unitName !== 'corepixels' &&
 				unitName !== 'tiletwips' && unitName !== 'printtwips') {
 			console.error('unsupported unitName: ' + unitName);
 			return undefined;
 		}
 
 		var numSizes = span.end - index + 1;
-		var inPixels = (unitName === 'csspixels' || unitName === 'devpixels');
+		var inPixels = (unitName === 'csspixels' || unitName === 'corepixels');
 		if (inPixels) {
-			var useDevicePixels = (unitName === 'devpixels');
-			var pixelScale = useDevicePixels ? 1 : this._devPixelsPerCssPixel;
+			var useCorePixels = (unitName === 'corepixels');
+			var pixelScale = useCorePixels ? 1 : this._corePixelsPerCssPixel;
 			return {
-				startpos: (span.data.posdevpx - span.data.sizedev * numSizes) / pixelScale,
-				size: span.data.sizedev / pixelScale
+				startpos: (span.data.poscorepx - span.data.sizecore * numSizes) / pixelScale,
+				size: span.data.sizecore / pixelScale
 			};
 		}
 
@@ -1732,12 +1745,12 @@ L.SheetDimension = L.Class.extend({
 		}
 
 		// unitName is 'tiletwips'
-		// It is very important to calculate this from device pixel units to mirror the core calculations.
-		var twipsPerDevPixels = this._twipsPerCSSPixel / this._devPixelsPerCssPixel;
+		// It is very important to calculate this from core pixel units to mirror the core calculations.
+		var twipsPerCorePixel = this._twipsPerCorePixel;
 		return {
 			startpos: Math.floor(
-				(span.data.posdevpx - span.data.sizedev * numSizes) * twipsPerDevPixels),
-			size: Math.floor(span.data.sizedev * twipsPerDevPixels)
+				(span.data.poscorepx - span.data.sizecore * numSizes) * twipsPerCorePixel),
+			size: Math.floor(span.data.sizecore * twipsPerCorePixel)
 		};
 	},
 
@@ -1766,8 +1779,7 @@ L.SheetDimension = L.Class.extend({
 			return result;
 		}
 		var elementCount = span.end - span.start + 1;
-		var posStart = ((span.data.posdevpx - span.data.sizedev * elementCount) /
-			this._devPixelsPerCssPixel * this._twipsPerCSSPixel);
+		var posStart = ((span.data.poscorepx - span.data.sizecore * elementCount) * this._twipsPerCorePixel);
 		var posEnd = span.data.postiletwips;
 		var sizeOne = (posEnd - posStart) / elementCount;
 
@@ -1834,8 +1846,8 @@ L.SheetDimension = L.Class.extend({
 		this._outlines.forEachGroupInRange(this._viewStartIndex, this._viewEndIndex,
 			function (levelIdx, groupIdx, start, end, hidden) {
 
-				var startElementData = dimensionObj.getElementData(start, true /* device pixels */);
-				var endElementData = dimensionObj.getElementData(end, true /* device pixels */);
+				var startElementData = dimensionObj.getElementData(start, true /* core pixels */);
+				var endElementData = dimensionObj.getElementData(end, true /* core pixels */);
 				groupsData.push({
 					level: (levelIdx + 1).toString(),
 					index: groupIdx.toString(),
@@ -1897,9 +1909,9 @@ L.SheetDimension = L.Class.extend({
 		var startData = this._getElementDataAnyFromSpanByIndex(startElement.index, startElement.span, 'tiletwips');
 		if (posStartPT === posEndPT) {
 			// range is hidden, send a minimal sized tile-twips range.
-			// Set the size = twips equivalent of 1 device pixel,
+			// Set the size = twips equivalent of 1 core pixel,
 			// to imitate what core does when it sends cursor/ranges in tile-twips coordinates.
-			var rangeSize = Math.floor(this._twipsPerCSSPixel / this._devPixelsPerCssPixel);
+			var rangeSize = Math.floor(this._twipsPerCorePixel);
 			return {
 				startpos: startData.startpos,
 				endpos: startData.startpos + rangeSize
@@ -1932,7 +1944,7 @@ L.SheetDimension = L.Class.extend({
 	isUnitSupported: function (unitName) {
 		return (
 			unitName === 'csspixels' ||
-			unitName === 'devpixels' ||
+			unitName === 'corepixels' ||
 			unitName === 'tiletwips' ||
 			unitName === 'printtwips'
 		);
@@ -1944,12 +1956,12 @@ L.SheetDimension = L.Class.extend({
 
 		var origUnit = unit;
 
-		if (unit === 'devpixels') {
-			pos = (pos * this._twipsPerCSSPixel) / this._devPixelsPerCssPixel;
+		if (unit === 'corepixels') {
+			pos = pos * this._twipsPerCorePixel;
 			unit = 'tiletwips';
 		}
 		else if (unit === 'csspixels') {
-			pos = pos * this._twipsPerCSSPixel;
+			pos = pos * this._corePixelsPerCssPixel * this._twipsPerCorePixel;
 			unit = 'tiletwips';
 		}
 
@@ -1965,12 +1977,12 @@ L.SheetDimension = L.Class.extend({
 		console.assert(typeof pos === 'number', 'pos is not a number');
 		console.assert(this.isUnitSupported(unit), 'unit: ' + unit + ' is not supported');
 
-		if (unit === 'devpixels') {
-			pos = (pos * this._twipsPerCSSPixel) / this._devPixelsPerCssPixel;
+		if (unit === 'corepixels') {
+			pos = pos * this._twipsPerCorePixel;
 			unit = 'tiletwips';
 		}
 		else if (unit === 'csspixels') {
-			pos = pos * this._twipsPerCSSPixel;
+			pos = pos * this._corePixelsPerCssPixel * this._twipsPerCorePixel;
 			unit = 'tiletwips';
 		}
 
commit 25806ecce1d2691701e6c90e8d966ce4cdcab242
Author:     Dennis Francis <dennis.francis at collabora.com>
AuthorDate: Mon Aug 24 22:31:16 2020 +0530
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Fri Aug 28 17:04:56 2020 +0200

    header canvases should resize with map-resize
    
    This is now safe as we update their contents on resize.
    
    Change-Id: Ie8b33e03e9b67de0f5c4d0e4822154032c171a70

diff --git a/loleaflet/css/spreadsheet.css b/loleaflet/css/spreadsheet.css
index c0c6b95e0..abf6cad98 100644
--- a/loleaflet/css/spreadsheet.css
+++ b/loleaflet/css/spreadsheet.css
@@ -130,6 +130,7 @@
 .spreadsheet-header-columns {
 	display: inline-block;
 	white-space: nowrap;
+	width: 100%;
 	height: 100%;
 	border-spacing: 0px !important;
 	position: relative;
@@ -172,6 +173,7 @@
 
 .spreadsheet-header-rows {
 	width: 100%;
+	height: 100%;
 	border-spacing: 0px !important;
 	position: relative;
 	margin: 0px;
commit c0bb916855dad49e469a95c03cc76d962eec5fc6
Author:     Dennis Francis <dennis.francis at collabora.com>
AuthorDate: Mon Aug 24 22:12:18 2020 +0530
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Fri Aug 28 17:04:56 2020 +0200

    setup the header canvases in the same way as the tile-canvas
    
    All drawings to it needs to in css pixels for now, because the
    mouse/touch handlers need positions in css pixels and the HeaderInfo
    datastructure has everything in css pixels.
    
    Moving the headers to the main-canvas needs more work but this change
    will help in doing that.
    
    Change-Id: I6a19e62a67b2b42975a51bb695db300ce493ba01

diff --git a/loleaflet/src/control/Control.ColumnHeader.js b/loleaflet/src/control/Control.ColumnHeader.js
index cbd73c919..53ae8b9f2 100644
--- a/loleaflet/src/control/Control.ColumnHeader.js
+++ b/loleaflet/src/control/Control.ColumnHeader.js
@@ -224,7 +224,8 @@ L.Control.ColumnHeader = L.Control.Header.extend({
 			return;
 
 		ctx.save();
-		var scale = L.getDpiScaleFactor();
+		var useExactDPR = this._map && (this._map._docLayer instanceof L.CanvasTileLayer);
+		var scale = L.getDpiScaleFactor(useExactDPR);
 		ctx.scale(scale, scale);
 		// background gradient
 		var selectionBackgroundGradient = null;
diff --git a/loleaflet/src/control/Control.Header.js b/loleaflet/src/control/Control.Header.js
index bb0d4433f..757cfd5c8 100644
--- a/loleaflet/src/control/Control.Header.js
+++ b/loleaflet/src/control/Control.Header.js
@@ -579,6 +579,7 @@ L.Control.Header = L.Control.extend({
 	},
 
 	_setCanvasSizeImpl: function (container, canvas, property, value, isCorner) {
+		var useExactDPR = this._map && (this._map._docLayer instanceof L.CanvasTileLayer);
 		if (!value) {
 			value = parseInt(L.DomUtil.getStyle(container, property));
 		}
@@ -586,7 +587,7 @@ L.Control.Header = L.Control.extend({
 			L.DomUtil.setStyle(container, property, value + 'px');
 		}
 
-		var scale = L.getDpiScaleFactor();
+		var scale = L.getDpiScaleFactor(useExactDPR);
 		if (property === 'width') {
 			canvas.width = value * scale;
 			if (!isCorner)
diff --git a/loleaflet/src/control/Control.RowHeader.js b/loleaflet/src/control/Control.RowHeader.js
index e39162ff2..32974d9e9 100644
--- a/loleaflet/src/control/Control.RowHeader.js
+++ b/loleaflet/src/control/Control.RowHeader.js
@@ -217,7 +217,8 @@ L.Control.RowHeader = L.Control.Header.extend({
 			return;
 
 		ctx.save();
-		var scale = L.getDpiScaleFactor();
+		var useExactDPR = this._map && (this._map._docLayer instanceof L.CanvasTileLayer);
+		var scale = L.getDpiScaleFactor(useExactDPR);
 		ctx.scale(scale, scale);
 		// background gradient
 		var selectionBackgroundGradient = null;
commit 129b73c4ed71133c10b2cd23d8e38e6279e47a84
Author:     Dennis Francis <dennis.francis at collabora.com>
AuthorDate: Mon Aug 24 16:49:47 2020 +0530
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Fri Aug 28 17:04:56 2020 +0200

    compute nearest zoomlevel with devpixelratio included
    
    and use this for every setZoom call.
    
    Change-Id: I37f0d7503e4087f062576bc03b13bd8155c3c994

diff --git a/loleaflet/src/layer/tile/CanvasTileLayer.js b/loleaflet/src/layer/tile/CanvasTileLayer.js
index ba74b2c4c..f8b739a2a 100644
--- a/loleaflet/src/layer/tile/CanvasTileLayer.js
+++ b/loleaflet/src/layer/tile/CanvasTileLayer.js
@@ -380,6 +380,11 @@ L.CanvasTileLayer = L.TileLayer.extend({
 		this._tileHeightPx = this.options.tileSize;
 		this._tilePixelScale = 1;
 
+		// FIXME: workaround for correcting initial zoom with dpiscale included.
+		// The one set during Map constructor is does not include dpiscale because
+		// there we don't have enough info to specialize for calc-canvas
+		map.setZoom(map.getZoom());
+
 		L.TileLayer.prototype.onAdd.call(this, map);
 	},
 
diff --git a/loleaflet/src/map/Map.js b/loleaflet/src/map/Map.js
index 6f5677a26..946896e0c 100644
--- a/loleaflet/src/map/Map.js
+++ b/loleaflet/src/map/Map.js
@@ -452,7 +452,22 @@ L.Map = L.Evented.extend({
 		this._progressBar.end(this);
 	},
 
+	// Compute the nearest zoom level corresponding to the effective zoom-scale (ie, with dpiscale included).
+	findNearestProductZoom: function (zoom) {
+		var clientZoomScale = Math.pow(1.2, (zoom - this.options.zoom));
+
+		var zoomScale = clientZoomScale * L.getCanvasScaleFactor();
+		var nearestZoom = Math.round((Math.log(zoomScale) / Math.log(1.2)) + this.options.zoom);
+		nearestZoom = this._limitZoom(nearestZoom);
+
+		return nearestZoom;
+	},
+
 	setZoom: function (zoom, options) {
+
+		if (this._docLayer instanceof L.CanvasTileLayer)
+			zoom = this.findNearestProductZoom(zoom);
+
 		if (!this._loaded) {
 			this._zoom = this._limitZoom(zoom);
 			return this;
commit 4272b418bfb66d15865e38b637dc3e3c7246458a
Author:     Dennis Francis <dennis.francis at collabora.com>
AuthorDate: Mon Aug 24 15:50:44 2020 +0530
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Fri Aug 28 17:04:56 2020 +0200

    calc-canvas: make tile size fixed (256) for every device
    
    Change-Id: I4e00b8b43f73f001a8bcfc77931f5fa22982642e

diff --git a/loleaflet/src/layer/tile/CalcTileLayer.js b/loleaflet/src/layer/tile/CalcTileLayer.js
index 534c307ab..be567fa14 100644
--- a/loleaflet/src/layer/tile/CalcTileLayer.js
+++ b/loleaflet/src/layer/tile/CalcTileLayer.js
@@ -4,7 +4,8 @@
  */
 
 /* global */
-L.CalcTileLayer = (L.Browser.mobile ? L.TileLayer : L.CanvasTileLayer).extend({
+var BaseTileLayer = L.Browser.mobile ? L.TileLayer : L.CanvasTileLayer;
+L.CalcTileLayer = BaseTileLayer.extend({
 	options: {
 		// TODO: sync these automatically from SAL_LOK_OPTIONS
 		sheetGeometryDataEnabled: true,
@@ -81,7 +82,7 @@ L.CalcTileLayer = (L.Browser.mobile ? L.TileLayer : L.CanvasTileLayer).extend({
 		map.addControl(L.control.tabs());
 		map.addControl(L.control.columnHeader());
 		map.addControl(L.control.rowHeader());
-		L.TileLayer.prototype.onAdd.call(this, map);
+		BaseTileLayer.prototype.onAdd.call(this, map);
 
 		map.on('resize', function () {
 			if (this.isCursorVisible()) {
diff --git a/loleaflet/src/layer/tile/CanvasTileLayer.js b/loleaflet/src/layer/tile/CanvasTileLayer.js
index 70f6c8a36..ba74b2c4c 100644
--- a/loleaflet/src/layer/tile/CanvasTileLayer.js
+++ b/loleaflet/src/layer/tile/CanvasTileLayer.js
@@ -373,6 +373,16 @@ L.CanvasTileLayer = L.TileLayer.extend({
 		return false;
 	},
 
+	onAdd: function (map) {
+
+		// Override L.TileLayer._tilePixelScale to 1 (independent of the device).
+		this._tileWidthPx = this.options.tileSize;
+		this._tileHeightPx = this.options.tileSize;
+		this._tilePixelScale = 1;
+
+		L.TileLayer.prototype.onAdd.call(this, map);
+	},
+
 	onRemove: function (map) {
 		this._painter.dispose();
 		L.TileLayer.prototype.onRemove.call(this, map);
commit 5e788202002f7bb035d72a285f2cbc97da814063
Author:     Dennis Francis <dennis.francis at collabora.com>
AuthorDate: Mon Aug 24 15:34:30 2020 +0530
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Fri Aug 28 17:04:56 2020 +0200

    use window.devicePixelRatio without rounding
    
    at least for the canvas tile layer.
    
    Change-Id: Ia830cad1fe0aaac6df03288cc1ee9e0371ef6f47

diff --git a/loleaflet/src/core/Util.js b/loleaflet/src/core/Util.js
index 596dfa756..e5f461cab 100644
--- a/loleaflet/src/core/Util.js
+++ b/loleaflet/src/core/Util.js
@@ -159,8 +159,11 @@ L.Util = {
 	// minimal image URI, set to an image when disposing to flush memory
 	emptyImageUrl: 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=',
 
-	getDpiScaleFactor: function() {
-		var dpiScale = window.devicePixelRatio ? Math.ceil(window.devicePixelRatio) : 1;
+	getDpiScaleFactor: function(useExactDPR) {
+		var dpiScale = window.devicePixelRatio ? window.devicePixelRatio : 1;
+		if (!useExactDPR)
+			dpiScale = Math.ceil(dpiScale);
+
 		if (dpiScale == 1 && L.Browser.retina) {
 			dpiScale = 2;
 		}
diff --git a/loleaflet/src/layer/tile/CanvasTileLayer.js b/loleaflet/src/layer/tile/CanvasTileLayer.js
index d189ecf6a..70f6c8a36 100644
--- a/loleaflet/src/layer/tile/CanvasTileLayer.js
+++ b/loleaflet/src/layer/tile/CanvasTileLayer.js
@@ -44,7 +44,7 @@ L.CanvasTilePainter = L.Class.extend({
 		this._layer = layer;
 		this._canvas = this._layer._canvas;
 
-		var dpiScale = L.getDpiScaleFactor();
+		var dpiScale = L.getDpiScaleFactor(true /* useExactDPR */);
 		this._dpiScale = dpiScale;
 
 		this._map = this._layer._map;
@@ -214,7 +214,7 @@ L.CanvasTilePainter = L.Class.extend({
 		var part = this._layer._selectedPart;
 		var newSplitPos = splitPanesContext ?
 		    splitPanesContext.getSplitPos(): this._splitPos;
-		var newDpiScale = L.getDpiScaleFactor();
+		var newDpiScale = L.getDpiScaleFactor(true /* useExactDPR */);
 
 		var zoomChanged = (zoom !== this._lastZoom);
 		var partChanged = (part !== this._lastPart);
@@ -242,8 +242,10 @@ L.CanvasTilePainter = L.Class.extend({
 		if (skipUpdate)
 			return;
 
-		if (scaleChanged)
-			this._dpiScale = L.getDpiScaleFactor();
+		if (scaleChanged) {
+			this._dpiScale = L.getDpiScaleFactor(true /* useExactDPR */);
+			console.log('DEBUG: scaleChanged : this._dpiScale = ' + this._dpiScale);
+		}
 
 		if (resizeCanvas || scaleChanged) {
 			this._setCanvasSize(newSize.x, newSize.y);
commit ef8589212d2c4e1388684a63283ed10554e3f51c
Author:     Michael Meeks <michael.meeks at collabora.com>
AuthorDate: Fri Aug 21 20:43:47 2020 +0100
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Fri Aug 28 17:04:56 2020 +0200

    Don't merge - grim hack try to get 1:1 pixels in canvas.
    
    Change-Id: I8ff3f157112295e0c6ef6743de3c878329b98adb

diff --git a/loleaflet/src/layer/tile/CanvasTileLayer.js b/loleaflet/src/layer/tile/CanvasTileLayer.js
index 9f3b6e02f..d189ecf6a 100644
--- a/loleaflet/src/layer/tile/CanvasTileLayer.js
+++ b/loleaflet/src/layer/tile/CanvasTileLayer.js
@@ -40,22 +40,15 @@ L.CanvasTilePainter = L.Class.extend({
 		debug: true,
 	},
 
-	initialize: function (layer, enableImageSmoothing) {
+	initialize: function (layer) {
 		this._layer = layer;
 		this._canvas = this._layer._canvas;
 
 		var dpiScale = L.getDpiScaleFactor();
-		if (dpiScale === 1 || dpiScale === 2) {
-			enableImageSmoothing = (enableImageSmoothing === true);
-		}
-		else {
-			enableImageSmoothing = (enableImageSmoothing === undefined || enableImageSmoothing);
-		}
-
 		this._dpiScale = dpiScale;
 
 		this._map = this._layer._map;
-		this._setupCanvas(enableImageSmoothing);
+		this._setupCanvas();
 
 		this._topLeft = undefined;
 		this._lastZoom = undefined;
@@ -95,15 +88,11 @@ L.CanvasTilePainter = L.Class.extend({
 		this.stopUpdates();
 	},
 
-	setImageSmoothing: function (enable) {
-		this._canvasCtx.imageSmoothingEnabled = enable;
-		this._canvasCtx.msImageSmoothingEnabled = enable;
-	},
-
-	_setupCanvas: function (enableImageSmoothing) {
+	_setupCanvas: function () {
 		console.assert(this._canvas, 'no canvas element');
 		this._canvasCtx = this._canvas.getContext('2d', { alpha: false });
-		this.setImageSmoothing(enableImageSmoothing);
+		this._canvasCtx.imageSmoothingEnabled = false;
+		this._canvasCtx.msImageSmoothingEnabled = false;
 		var mapSize = this._map.getPixelBounds().getSize();
 		this._lastSize = mapSize;
 		this._lastMapSize = mapSize;
@@ -132,7 +121,7 @@ L.CanvasTilePainter = L.Class.extend({
 
 	clear: function () {
 		this._canvasCtx.save();
-		this._canvasCtx.scale(this._dpiScale, this._dpiScale);
+		this._canvasCtx.scale(1, 1);
 		if (this.options.debug)
 			this._canvasCtx.fillStyle = 'red';
 		else
@@ -177,7 +166,7 @@ L.CanvasTilePainter = L.Class.extend({
 				topLeft.y = ctx.viewBounds.min.y;
 
 			this._canvasCtx.save();
-			this._canvasCtx.scale(this._dpiScale, this._dpiScale);
+			this._canvasCtx.scale(1, 1);
 			this._canvasCtx.translate(-topLeft.x, -topLeft.y);
 
 			// create a clip for the pane/view.
@@ -186,12 +175,11 @@ L.CanvasTilePainter = L.Class.extend({
 			this._canvasCtx.rect(paneBounds.min.x, paneBounds.min.y, paneSize.x + 1, paneSize.y + 1);
 			this._canvasCtx.clip();
 
-			if (this._dpiScale !== 1) {
-				// FIXME: avoid this scaling when possible (dpiScale = 2).
-				this._canvasCtx.drawImage(tile.el, tile.coords.x, tile.coords.y, ctx.tileSize.x, ctx.tileSize.y);
-			}
-			else {
-				this._canvasCtx.drawImage(tile.el, tile.coords.x, tile.coords.y);
+			this._canvasCtx.drawImage(tile.el, tile.coords.x, tile.coords.y);
+			if (this.options.debug)
+			{
+				this._canvasCtx.strokeStyle = 'red';
+				this._canvasCtx.strokeRect(tile.coords.x, tile.coords.y, 256, 256);
 			}
 			this._canvasCtx.restore();
 		}
@@ -204,7 +192,7 @@ L.CanvasTilePainter = L.Class.extend({
 		}
 		var splitPos = splitPanesContext.getSplitPos();
 		this._canvasCtx.save();
-		this._canvasCtx.scale(this._dpiScale, this._dpiScale);
+		this._canvasCtx.scale(1, 1);
 		this._canvasCtx.strokeStyle = 'red';
 		this._canvasCtx.strokeRect(0, 0, splitPos.x, splitPos.y);
 		this._canvasCtx.restore();
@@ -249,6 +237,8 @@ L.CanvasTilePainter = L.Class.extend({
 			!splitPosChanged &&
 			!scaleChanged);
 
+		console.debug('Tile size: ' + this._layer._getTileSize());
+
 		if (skipUpdate)
 			return;
 
@@ -296,8 +286,8 @@ L.CanvasTilePainter = L.Class.extend({
 			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.TileCoordData(
-						i * ctx.tileSize,
-						j * ctx.tileSize,
+						i * ctx.tileSize.x,
+						j * ctx.tileSize.y,
 						zoom,
 						part);
 
commit f83db8cb91494843e9f140f7057f205cbee43c2e
Author:     Michael Meeks <michael.meeks at collabora.com>
AuthorDate: Fri Aug 21 16:40:29 2020 +0100
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Fri Aug 28 17:04:56 2020 +0200

    calc tiles: more debug helpers
    
    Change-Id: I24370b2a35fdfeca360cbaeb296cd2dd3a11e768

diff --git a/loleaflet/src/layer/tile/CanvasTileLayer.js b/loleaflet/src/layer/tile/CanvasTileLayer.js
index 5829239fa..9f3b6e02f 100644
--- a/loleaflet/src/layer/tile/CanvasTileLayer.js
+++ b/loleaflet/src/layer/tile/CanvasTileLayer.js
@@ -37,7 +37,7 @@ L.TileCoordData.parseKey = function (keyString) {
 L.CanvasTilePainter = L.Class.extend({
 
 	options: {
-		debug: false,
+		debug: true,
 	},
 
 	initialize: function (layer, enableImageSmoothing) {
@@ -133,7 +133,10 @@ L.CanvasTilePainter = L.Class.extend({
 	clear: function () {
 		this._canvasCtx.save();
 		this._canvasCtx.scale(this._dpiScale, this._dpiScale);
-		this._canvasCtx.fillStyle = 'white';
+		if (this.options.debug)
+			this._canvasCtx.fillStyle = 'red';
+		else
+			this._canvasCtx.fillStyle = 'white';
 		this._canvasCtx.fillRect(0, 0, this._width, this._height);
 		this._canvasCtx.restore();
 	},
@@ -277,6 +280,10 @@ L.CanvasTilePainter = L.Class.extend({
 	},
 
 	_paintWholeCanvas: function () {
+
+		if (this.options.debug)
+			this.clear();
+
 		var zoom = this._lastZoom || Math.round(this._map.getZoom());
 		var part = this._lastPart || this._layer._selectedPart;
 
commit f2b77441cbd001f5b7815033a63eb9330b961c6a
Author:     Michael Meeks <michael.meeks at collabora.com>
AuthorDate: Fri Aug 21 15:54:50 2020 +0100
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Fri Aug 28 17:04:56 2020 +0200

    calc tiles: share code for building bounds and panes.
    
    Avoid duplication between tileReady and paint.
    
    Change-Id: Ic3d1c22a1dbeffe1abfffd35ea0d7fbcfd5c1ccc

diff --git a/loleaflet/src/layer/tile/CanvasTileLayer.js b/loleaflet/src/layer/tile/CanvasTileLayer.js
index 5881803c8..5829239fa 100644
--- a/loleaflet/src/layer/tile/CanvasTileLayer.js
+++ b/loleaflet/src/layer/tile/CanvasTileLayer.js
@@ -63,8 +63,6 @@ L.CanvasTilePainter = L.Class.extend({
 		var splitPanesContext = this._layer.getSplitPanesContext();
 		this._splitPos = splitPanesContext ?
 			splitPanesContext.getSplitPos() : new L.Point(0, 0);
-
-		this._tileSizeCSSPx = undefined;
 		this._updatesRunning = false;
 	},
 
@@ -140,38 +138,40 @@ L.CanvasTilePainter = L.Class.extend({
 		this._canvasCtx.restore();
 	},
 
-	paint: function (tile, viewBounds, paneBoundsList) {
+	// Details of tile areas to render
+	_paintContext: function() {
+		var tileSize = new L.Point(this._layer._getTileSize(), this._layer._getTileSize());
 
-		if (this._tileSizeCSSPx === undefined) {
-			this._tileSizeCSSPx = this._layer._getTileSize();
-		}
+		var viewBounds = this._map.getPixelBounds();
+		var splitPanesContext = this._layer.getSplitPanesContext();
+		var paneBoundsList = splitPanesContext ?
+		    splitPanesContext.getPxBoundList(viewBounds) :
+		    [viewBounds];
+
+		return { tileSize: tileSize,
+			 viewBounds: viewBounds,
+			 paneBoundsList: paneBoundsList };
+	},
+
+	paint: function (tile, ctx) {
+
+		if (!ctx)
+			ctx = this._paintContext();
 
 		var tileTopLeft = tile.coords.getPos();
-		var tileSize = new L.Point(this._tileSizeCSSPx, this._tileSizeCSSPx);
-		var tileBounds = new L.Bounds(tileTopLeft, tileTopLeft.add(tileSize));
+		var tileBounds = new L.Bounds(tileTopLeft, tileTopLeft.add(ctx.tileSize));
 
-		viewBounds = viewBounds || this._map.getPixelBounds();
-		var splitPanesContext = this._layer.getSplitPanesContext();
-		paneBoundsList = paneBoundsList || (
-			splitPanesContext ?
-			splitPanesContext.getPxBoundList(viewBounds) :
-			[viewBounds]
-		);
+		for (var i = 0; i < ctx.paneBoundsList.length; ++i) {
+			var paneBounds = ctx.paneBoundsList[i];
 
-		for (var i = 0; i < paneBoundsList.length; ++i) {
-			var paneBounds = paneBoundsList[i];
-			if (!paneBounds.intersects(tileBounds)) {
+			if (!paneBounds.intersects(tileBounds))
 				continue;
-			}
 
 			var topLeft = paneBounds.getTopLeft();
-			if (topLeft.x) {
-				topLeft.x = viewBounds.min.x;
-			}
-
-			if (topLeft.y) {
-				topLeft.y = viewBounds.min.y;
-			}
+			if (topLeft.x)
+				topLeft.x = ctx.viewBounds.min.x;
+			if (topLeft.y)
+				topLeft.y = ctx.viewBounds.min.y;
 
 			this._canvasCtx.save();
 			this._canvasCtx.scale(this._dpiScale, this._dpiScale);
@@ -185,7 +185,7 @@ L.CanvasTilePainter = L.Class.extend({
 
 			if (this._dpiScale !== 1) {
 				// FIXME: avoid this scaling when possible (dpiScale = 2).
-				this._canvasCtx.drawImage(tile.el, tile.coords.x, tile.coords.y, this._tileSizeCSSPx, this._tileSizeCSSPx);
+				this._canvasCtx.drawImage(tile.el, tile.coords.x, tile.coords.y, ctx.tileSize.x, ctx.tileSize.y);
 			}
 			else {
 				this._canvasCtx.drawImage(tile.el, tile.coords.x, tile.coords.y);
@@ -280,24 +280,17 @@ L.CanvasTilePainter = L.Class.extend({
 		var zoom = this._lastZoom || Math.round(this._map.getZoom());
 		var part = this._lastPart || this._layer._selectedPart;
 
-		var viewSize = new L.Point(this._width, this._height);
-		var viewBounds = new L.Bounds(this._topLeft, this._topLeft.add(viewSize));
-
-		var splitPanesContext = this._layer.getSplitPanesContext();
 		// Calculate all this here intead of doing it per tile.
-		var paneBoundsList = splitPanesContext ?
-			splitPanesContext.getPxBoundList(viewBounds) : [viewBounds];
-		var tileRanges = paneBoundsList.map(this._layer._pxBoundsToTileRange, this._layer);
-
-		var tileSize = this._tileSizeCSSPx || this._layer._getTileSize();
+		var ctx = this._paintContext();
+		var tileRanges = ctx.paneBoundsList.map(this._layer._pxBoundsToTileRange, this._layer);
 
 		for (var rangeIdx = 0; rangeIdx < tileRanges.length; ++rangeIdx) {
 			var tileRange = tileRanges[rangeIdx];
 			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.TileCoordData(
-						i * tileSize,
-						j * tileSize,
+						i * ctx.tileSize,
+						j * ctx.tileSize,
 						zoom,
 						part);
 
@@ -305,7 +298,7 @@ L.CanvasTilePainter = L.Class.extend({
 					var tile = this._layer._tiles[key];
 					var invalid = tile && tile._invalidCount && tile._invalidCount > 0;
 					if (tile && tile.loaded && !invalid) {
-						this.paint(tile, viewBounds, paneBoundsList);
+						this.paint(tile, ctx);
 					}
 				}
 			}
commit 43288cbcb5b934ea69b310771d63220b7d425826
Author:     Michael Meeks <michael.meeks at collabora.com>
AuthorDate: Fri Aug 21 15:47:58 2020 +0100
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Fri Aug 28 17:04:56 2020 +0200

    calc tiles: remove partial re-rendering for now.
    
    Drops _shiftAndPaint and _paintRects, blits are fast.
    
    Change-Id: I64779f1037784f4efbe74cdf564b5f09e13b3316

diff --git a/loleaflet/src/layer/tile/CanvasTileLayer.js b/loleaflet/src/layer/tile/CanvasTileLayer.js
index f6c29d57a..5881803c8 100644
--- a/loleaflet/src/layer/tile/CanvasTileLayer.js
+++ b/loleaflet/src/layer/tile/CanvasTileLayer.js
@@ -236,7 +236,6 @@ L.CanvasTilePainter = L.Class.extend({
 		var resizeCanvas = !newSize.equals(this._lastSize);
 
 		var topLeftChanged = this._topLeft === undefined || !newTopLeft.equals(this._topLeft);
-
 		var splitPosChanged = !newSplitPos.equals(this._splitPos);
 
 		var skipUpdate = (
@@ -247,9 +246,9 @@ L.CanvasTilePainter = L.Class.extend({
 			!splitPosChanged &&
 			!scaleChanged);
 
-		if (skipUpdate) {
+		if (skipUpdate)
 			return;
-		}
+
 		if (scaleChanged)
 			this._dpiScale = L.getDpiScaleFactor();
 
@@ -261,130 +260,20 @@ L.CanvasTilePainter = L.Class.extend({
 			this.clear();
 		}
 
-		if (mapSizeChanged) {
+		if (mapSizeChanged)
 			this._lastMapSize = newMapSize;
-		}
 
-		if (splitPosChanged) {
+		if (splitPosChanged)
 			this._splitPos = newSplitPos;
-		}
-
-		// TODO: fix _shiftAndPaint for high DPI.
-		var shiftPaintDisabled = true;
-		var fullRepaintNeeded = zoomChanged || partChanged || resizeCanvas ||
-		    shiftPaintDisabled || scaleChanged;
 
 		this._lastZoom = zoom;
 		this._lastPart = part;
 
-		if (fullRepaintNeeded) {
-
-			this._topLeft = newTopLeft;
-			this._paintWholeCanvas();
-
-			if (this.options.debug) {
-				this._drawSplits();
-			}
-
-			return;
-		}
-
-		this._shiftAndPaint(newTopLeft);
-	},
-
-	_shiftAndPaint: function (newTopLeft) {
-
-		console.assert(!this._layer.getSplitPanesContext(), '_shiftAndPaint is broken for split-panes.');
-		var offset = new L.Point(this._width - 1, this._height - 1);
-
-		var dx = newTopLeft.x - this._topLeft.x;
-		var dy = newTopLeft.y - this._topLeft.y;
-		if (!dx && !dy) {
-			return;
-		}
-
-		// Determine the area that needs to be painted as max. two disjoint rectangles.
-		var rectsToPaint = [];
-		this._inMove = true;
-		var oldTopLeft = this._topLeft;
-		var oldBottomRight = oldTopLeft.add(offset);
-		var newBottomRight = newTopLeft.add(offset);
-
-		if (Math.abs(dx) < this._width && Math.abs(dy) < this._height) {
-
-			this._canvasCtx.save();
-			this._canvasCtx.scale(this._dpiScale, this._dpiScale);
-			this._canvasCtx.globalCompositeOperation = 'copy';
-			this._canvasCtx.drawImage(this._canvas, -dx, -dy);
-			this._canvasCtx.globalCompositeOperation = 'source-over';
-			this._canvasCtx.restore();
-
-			var xstart = newTopLeft.x, xend = newBottomRight.x;
-			var ystart = newTopLeft.y, yend = newBottomRight.y;
-			if (dx) {
-				xstart = dx > 0 ? oldBottomRight.x + 1 : newTopLeft.x;
-				xend   = xstart + Math.abs(dx) - 1;
-			}
-
-			if (dy) {
-				ystart = dy > 0 ? oldBottomRight.y + 1 : newTopLeft.y;
-				yend   = ystart + Math.abs(dy) - 1;
-			}
-
-			// rectangle including the x-range that needs painting with full y-range.
-			// This will take care of simultaneous non-zero dx and dy.
-			if (dx) {
-				rectsToPaint.push(new L.Bounds(
-					new L.Point(xstart, newTopLeft.y),
-					new L.Point(xend,   newBottomRight.y)
-				));
-			}
-
-			// rectangle excluding the x-range that needs painting + needed y-range.
-			if (dy) {
-				rectsToPaint.push(new L.Bounds(
-					new L.Point(dx > 0 ? newTopLeft.x : (dx ? xend + 1 : newTopLeft.x), ystart),
-					new L.Point(dx > 0 ? xstart - 1   : newBottomRight.x,               yend)
-				));
-			}
-
-		}
-		else {
-			rectsToPaint.push(new L.Bounds(newTopLeft, newBottomRight));
-		}
-
 		this._topLeft = newTopLeft;
+		this._paintWholeCanvas();
 
-		this._paintRects(rectsToPaint, newTopLeft);
-	},
-
-	_paintRects: function (rects, topLeft) {
-		for (var i = 0; i < rects.length; ++i) {
-			this._paintRect(rects[i], topLeft);
-		}
-	},
-
-	_paintRect: function (rect) {
-		var zoom = this._lastZoom || Math.round(this._map.getZoom());
-		var part = this._lastPart || this._layer._selectedPart;
-		var tileRange = this._layer._pxBoundsToTileRange(rect);
-		var tileSize = this._tileSizeCSSPx || this._layer._getTileSize();
-		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.TileCoordData(
-					i * tileSize,
-					j * tileSize,
-					zoom,
-					part);
-
-				var key = coords.key();
-				var tile = this._layer._tiles[key];
-				var invalid = tile && tile._invalidCount && tile._invalidCount > 0;
-				if (tile && tile.loaded && !invalid) {
-					this.paint(tile);
-				}
-			}
-		}
+		if (this.options.debug)
+			this._drawSplits();
 	},
 
 	_paintWholeCanvas: function () {
commit 1bcf147083de59cc2732e4f9ce056cbb8f2f2434
Author:     Tor Lillqvist <tml at collabora.com>
AuthorDate: Fri Aug 28 14:05:13 2020 +0300
Commit:     Tor Lillqvist <tml at collabora.com>
CommitDate: Fri Aug 28 13:36:11 2020 +0200

    Surely it is called loolwsd and not lowsd?
    
    Change-Id: Ie2d8a26fa55de484b6d04e12202ca449d005f7a7
    Reviewed-on: https://gerrit.libreoffice.org/c/online/+/101539
    Tested-by: Jenkins
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>
    Reviewed-by: Tor Lillqvist <tml at collabora.com>

diff --git a/loleaflet/src/layer/BackgroundColor.js b/loleaflet/src/layer/BackgroundColor.js
index 31a96ef17..3029657c8 100644
--- a/loleaflet/src/layer/BackgroundColor.js
+++ b/loleaflet/src/layer/BackgroundColor.js
@@ -43,7 +43,7 @@ L.BackgroundColor = L.Layer.extend({
 
 /*
  * A L.BackgroundColor that automatically resets its color
- * based on 'statechange' messages from lowsd.
+ * based on 'statechange' messages from loolwsd.
  */
 L.CalcBackground = L.BackgroundColor.extend({
 	onAdd: function(map) {
diff --git a/loleaflet/src/layer/marker/TextInput.js b/loleaflet/src/layer/marker/TextInput.js
index 24af6a272..bae93c25e 100644
--- a/loleaflet/src/layer/marker/TextInput.js
+++ b/loleaflet/src/layer/marker/TextInput.js
@@ -660,10 +660,10 @@ L.TextInput = L.Layer.extend({
 			this._emptyArea();
 	},
 
-	// Sends the given (UTF-8) string of text to lowsd, as IME (text composition)
+	// Sends the given (UTF-8) string of text to loolwsd, as IME (text composition)
 	// messages
 	_sendText: function _sendText(text) {
-		this._fancyLog('send-text-to-lowsd', text);
+		this._fancyLog('send-text-to-loolwsd', text);
 
 		// MSIE/Edge cannot compare a string to "\n" for whatever reason,
 		// so compare charcode as well
@@ -792,7 +792,7 @@ L.TextInput = L.Layer.extend({
 	_removeTextContent: function _removeTextContent(before, after) {
 		console.log('Remove ' + before + ' before, and ' + after + ' after');
 
-		/// TODO: rename the event to 'removetextcontent' as soon as lowsd supports it
+		/// TODO: rename the event to 'removetextcontent' as soon as loolwsd supports it
 		/// TODO: Ask Marco about it
 		this._map._socket.sendMessage(
 			'removetextcontext id=' +
@@ -805,7 +805,7 @@ L.TextInput = L.Layer.extend({
 	// Tiny helper - encapsulates sending a 'textinput' websocket message.
 	// sends a pair of "input" for a composition update paird with an "end"
 	_sendCompositionEvent: function _sendCompositionEvent(text) {
-		console.log('sending to lowsd: ', text);
+		console.log('sending to loolwsd: ', text);
 
 		// We want to trigger auto-correction, but not if we may
 		// have to delete a count of characters in the future,
diff --git a/loleaflet/src/layer/tile/TileLayer.js b/loleaflet/src/layer/tile/TileLayer.js
index 71340ad89..e7558562c 100644
--- a/loleaflet/src/layer/tile/TileLayer.js
+++ b/loleaflet/src/layer/tile/TileLayer.js
@@ -796,7 +796,7 @@ L.TileLayer = L.GridLayer.extend({
 
 	_onCellAddressMsg: function (textMsg) {
 		// When the user moves the focus to a different cell, a 'cellformula'
-		// message is received from lowsd, *then* a 'celladdress' message.
+		// message is received from loolwsd, *then* a 'celladdress' message.
 		var address = textMsg.substring(13);
 		if (this._map._clip && !this._map['wopi'].DisableCopy) {
 			this._map._clip.setTextSelectionText(this._lastFormula);
@@ -805,10 +805,10 @@ L.TileLayer = L.GridLayer.extend({
 	},
 
 	_onCellFormulaMsg: function (textMsg) {
-		// When a 'cellformula' message from lowsd is received,
+		// When a 'cellformula' message from loolwsd is received,
 		// store the text contents of the cell, but don't push
 		// them to the clipboard container (yet).
-		// This is done because lowsd will send several 'cellformula'
+		// This is done because loolwsd will send several 'cellformula'
 		// messages during text composition, and resetting the contents
 		// of the clipboard container mid-composition will easily break it.
 		var formula = textMsg.substring(13);
@@ -2166,14 +2166,14 @@ L.TileLayer = L.GridLayer.extend({
 		}
 	},
 
-	// Given a character code and a UNO keycode, send a "key" message to lowsd.
+	// Given a character code and a UNO keycode, send a "key" message to loolwsd.
 	//
 	// "type" is either "input" for key presses (akin to the DOM "keypress"
 	// / "beforeinput" events) and "up" for key releases (akin to the DOM
 	// "keyup" event).
 	//
 	// PageUp/PageDown are handled as special cases for spreadsheets - in
-	// addition of sending messages to lowsd, they move the cell cursor around.
+	// addition of sending messages to loolwsd, they move the cell cursor around.
 	postKeyboardEvent: function(type, charCode, unoKeyCode) {
 		var winId = this._map.getWinId();
 		if (
diff --git a/loleaflet/src/map/handler/Map.Keyboard.js b/loleaflet/src/map/handler/Map.Keyboard.js
index 405b73995..852ab07fb 100644
--- a/loleaflet/src/map/handler/Map.Keyboard.js
+++ b/loleaflet/src/map/handler/Map.Keyboard.js
@@ -243,7 +243,7 @@ L.Map.Keyboard = L.Handler.extend({
 	},
 
 	// _handleKeyEvent - checks if the given keyboard event shall trigger
-	// a message to lowsd, and calls the given keyEventFn(type, charcode, keycode)
+	// a message to loolwsd, and calls the given keyEventFn(type, charcode, keycode)
 	// callback if so.
 	// Called from private _onKeyDown
 	_handleKeyEvent: function (ev, keyEventFn) {
@@ -391,7 +391,7 @@ L.Map.Keyboard = L.Handler.extend({
 	},
 
 	// Given a DOM keyboard event that happened while the Control key was depressed,
-	// triggers the appropriate action or lowsd message.
+	// triggers the appropriate action or loolwsd message.
 	_handleCtrlCommand: function (e) {
 		// Control
 		if (e.keyCode == 17)
commit 2422cc373895c0d3ee23ef3728b474f2ff6e4d9e
Author:     Weblate <noreply at documentfoundation.org>
AuthorDate: Sat Aug 22 06:28:57 2020 +0200
Commit:     Andras Timar <andras.timar at collabora.com>
CommitDate: Fri Aug 28 12:07:37 2020 +0200

    update translations
    
    LibreOffice Online/android-lib (Portuguese (Brazil))
    Currently translated at 100.0% (13 of 13 strings)
    
    Change-Id: I0933cc28a6570b91b65a0f761dc883546c9ed0ae
    
    update translations
    
    LibreOffice Online/loleaflet-ui (Portuguese (Brazil))
    Currently translated at 100.0% (344 of 344 strings)
    
    Change-Id: I504ea0faf6e68b7b5d8d44512fe8bb93d52c2723
    
    update translations
    
    LibreOffice Online/loleaflet-ui (German)
    Currently translated at 100.0% (344 of 344 strings)
    
    Change-Id: I62651c9a4ec680370b1e2e0db4bdac1f53679507
    
    update translations
    
    LibreOffice Online/loleaflet-help (Spanish)
    Currently translated at 100.0% (416 of 416 strings)
    
    Change-Id: I7d9f1eca068faaf4fbe730dc4f7a4f6009fd389d
    
    update translations
    
    LibreOffice Online/android-app (Korean)
    Currently translated at 19.6% (20 of 102 strings)
    
    Change-Id: I0d462951fe7a928931002feedbbd019db3cd5a1f
    
    update translations
    
    LibreOffice Online/android-app (Korean)
    Currently translated at 19.6% (20 of 102 strings)
    
    Change-Id: I2229085507efd42a0c6e0f7232e4cb044bf1340e
    
    update translations
    
    LibreOffice Online/android-app (Korean)
    Currently translated at 19.6% (20 of 102 strings)
    
    Change-Id: I9cb8da6624db1374ec5b60745a5a1d228ebd7463
    
    update translations
    
    LibreOffice Online/android-app (Danish)
    Currently translated at 0.9% (1 of 102 strings)
    
    Change-Id: I1172754fcf8b77e7a8bfd5a5c27debde97a2ff2b
    Reviewed-on: https://gerrit.libreoffice.org/c/online/+/100928
    Tested-by: Jenkins
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>
    Reviewed-by: Andras Timar <andras.timar at collabora.com>

diff --git a/android/app/src/main/res/values-da/strings.xml b/android/app/src/main/res/values-da/strings.xml
index a6b3daec9..7801c538f 100644
--- a/android/app/src/main/res/values-da/strings.xml
+++ b/android/app/src/main/res/values-da/strings.xml
@@ -1,2 +1,4 @@
 <?xml version="1.0" encoding="utf-8"?>
-<resources></resources>
\ No newline at end of file
+<resources>
+    <string name="app_name_settings">Indstillinger</string>
+</resources>
\ No newline at end of file
diff --git a/android/app/src/main/res/values-ko/strings.xml b/android/app/src/main/res/values-ko/strings.xml
index a2f1dea3f..7320b53f5 100644
--- a/android/app/src/main/res/values-ko/strings.xml
+++ b/android/app/src/main/res/values-ko/strings.xml
@@ -4,4 +4,23 @@
     <string name="app_description">$APP_NAME 은 현대적이며, 사용하기 쉬운 오픈소스 제품군이다. 이 제품군은 워드 프로세서, 스프레드시트, 프레젠테이션 등등이 포함되어 있습니다.</string>
     <string name="app_version">버전: %1$s, 빌드 ID: %2$s</string>
     <string name="app_name_settings">설정</string>
+    <string name="file_creation_failed">파일 생성 실패</string>
+    <string name="file_exists_warning">동일한 이름을 가진 파일이 이미 존재하며, 덮어 씁니다.</string>
+    <string name="temp_file_saving_disabled">이 파일은 읽기 전용이며, 저장이 비활성화됩니다.</string>
+    <string name="no_items">항목 없음</string>
+    <string name="no_recent_items">도구 모음의 폴더 아이콘을 사용하여 파일을 여십시오.</string>
+    <string name="app_version_and_hash">버전 : %1$s
+\n온라인 git-hash : %2$s
+\n핵심 git-hash : %3$s</string>
+    <string name="pref_file_explorer_title">파일 관리자 레이아웃</string>
+    <string name="pref_viewmode_summary">파일을 그리드 또는 리스트로 봅니다.</string>
+    <string name="pref_sort_summary">파일을 불러올 방법을 선택 하십시오 : A-Z, 크기 또는 날짜</string>
+    <string name="pref_show_hidden_files_summary">숨겨진 파일/폴더 표시 가능</string>
+    <string name="pref_show_hidden_files">숨겨진 파일/폴더</string>
+    <string name="pref_category_explorer">파일 관리자 설정</string>
+    <string name="grid_view">그리드</string>
+    <string name="failed_to_load_file">로드할 파일을 결정하지 못하였습니다</string>
+    <string name="storage_permission_required">저장 권한이 필요합니다</string>
+    <string name="pref_category_editor">편집기 설정</string>
+    <string name="list_view">목록</string>
 </resources>
\ No newline at end of file
diff --git a/android/lib/src/main/res/values-pt-rBR/strings.xml b/android/lib/src/main/res/values-pt-rBR/strings.xml
index 98b088211..c5dcc247c 100644
--- a/android/lib/src/main/res/values-pt-rBR/strings.xml
+++ b/android/lib/src/main/res/values-pt-rBR/strings.xml
@@ -14,4 +14,5 @@
     <string name="rate_our_app_title">Obrigado por usar %1$s!</string>
     <string name="later">Mais tarde</string>
     <string name="exiting">Saindo...</string>
+    <string name="file_chromeos_read_only">Este arquivo não pode ser salvo neste local, abrindo-o em só leitura. Mova-o para os arquivos de Play para poder ler e gravar o arquivo.</string>
 </resources>
\ No newline at end of file
diff --git a/loleaflet/po/help-es.po b/loleaflet/po/help-es.po
index a9f8f6313..d0c811fb8 100644
--- a/loleaflet/po/help-es.po
+++ b/loleaflet/po/help-es.po
@@ -3,7 +3,7 @@ msgstr ""
 "Project-Id-Version: \n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2020-03-31 22:32+0200\n"
-"PO-Revision-Date: 2020-03-22 00:15+0000\n"
+"PO-Revision-Date: 2020-08-19 17:35+0000\n"
 "Last-Translator: Adolfo Jayme Barrientos <fito at libreoffice.org>\n"
 "Language-Team: Spanish <https://weblate.documentfoundation.org/projects/libo_online/loleaflet-help/es/>\n"
 "Language: es\n"
@@ -11,7 +11,7 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 3.10.3\n"
+"X-Generator: Weblate 4.1.1\n"
 "X-Pootle-Path: /es/libo_online/loleaflet-help-es.po\n"
 "X-Pootle-Revision: 3713610\n"
 
@@ -1503,7 +1503,7 @@ msgstr "¿Cómo salir del <span class=\"productname\">%productName</span> sin gu
 
 #: html/loleaflet-help.html%2Bdiv.p:457-5
 msgid "<span class=\"productname\">%productName</span> saves the document in the background regularly, you can't just close without saving it. To abandon your changes, you must either undo them, or use the <span class=\"ui\">Revision History </span> in the <span class=\"ui\">File</span> menu."
-msgstr "<span class=\"productname\">%productName</span> guarda el documento regularmente; no puede cerrarlo sin que se guarde. Para abandonar sus modificaciones, puede deshacer o utilizar el historial de revisiones en el menú <span class=\"ui\">Archivo</span>."
+msgstr "<span class=\"productname\">%productName</span> guarda el documento regularmente; no puede cerrarlo sin que se guarde. Para abandonar sus modificaciones, puede deshacer o utilizar el <span class=\"ui\">Historial de revisiones</span> en el menú <span class=\"ui\">Archivo</span>."
 
 #: html/loleaflet-help.html%2Bdiv.h4:458-5
 msgid "Can <span class=\"productname\">%productName</span> open a password-protected document?"
diff --git a/loleaflet/po/ui-de.po b/loleaflet/po/ui-de.po
index 4fdacd21f..0952bf6cd 100644
--- a/loleaflet/po/ui-de.po
+++ b/loleaflet/po/ui-de.po
@@ -7,7 +7,7 @@ msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2020-08-04 15:38+0200\n"
-"PO-Revision-Date: 2020-07-25 19:23+0000\n"
+"PO-Revision-Date: 2020-08-21 14:17+0000\n"
 "Last-Translator: Christian Kühl <kuehl.christian at googlemail.com>\n"
 "Language-Team: German <https://weblate.documentfoundation.org/projects/libo_online/loleaflet-ui/de/>\n"
 "Language: de\n"
@@ -626,10 +626,8 @@ msgid "Last modification"
 msgstr "Letzte Bearbeitung"
 
 #: src/control/Control.Menubar.js:257
-#, fuzzy
-#| msgid "Comment"
 msgid "Save Comments"
-msgstr "Kommentar"
+msgstr "Kommentare speichern"
 
 #: src/control/Control.Menubar.js:263 src/control/Control.Menubar.js:549
 #: src/control/Control.NotebookbarImpress.js:269
@@ -658,7 +656,7 @@ msgstr "Vollbild Präsentation"
 
 #: src/control/Control.Menubar.js:354
 msgid "Present current slide"
-msgstr ""
+msgstr "Aktuelle Folie präsentieren"
 
 #: src/control/Control.Menubar.js:381 src/control/Control.Menubar.js:597
 #: src/control/Control.NotebookbarCalc.js:211
@@ -728,19 +726,19 @@ msgstr "Suchleiste ausblenden"
 
 #: src/control/Control.SheetsBar.js:28
 msgid "Scroll to the first sheet"
-msgstr ""
+msgstr "Zur ersten Tabelle rollen"
 
 #: src/control/Control.SheetsBar.js:29
 msgid "Scroll left"
-msgstr ""
+msgstr "Nach links rollen"
 
 #: src/control/Control.SheetsBar.js:30
 msgid "Scroll right"
-msgstr ""
+msgstr "Nach rechts rollen"
 
 #: src/control/Control.SheetsBar.js:31
 msgid "Scroll to the last sheet"
-msgstr ""
+msgstr "Zur letzten Tabelle rollen"
 
 #: src/control/Control.SheetsBar.js:32
 msgid "Insert sheet"
@@ -905,7 +903,7 @@ msgstr "Aktuell"
 #: src/control/Control.NotebookbarBuilder.js:614
 #: src/control/Control.NotebookbarBuilder.js:630
 msgid "Menu"
-msgstr ""
+msgstr "Menü"
 
 #: src/control/Control.Notebookbar.js:133
 #: src/control/Control.NotebookbarImpress.js:32
@@ -921,7 +919,7 @@ msgstr "Wiederherstellen"
 #: src/control/Control.NotebookbarCalc.js:12
 #: src/control/Control.NotebookbarImpress.js:86
 msgid "~File"
-msgstr ""
+msgstr "~Datei"
 
 #: src/control/Control.NotebookbarWriter.js:17
 #: src/control/Control.NotebookbarCalc.js:17
@@ -956,73 +954,61 @@ msgstr "~Tabelle"
 
 #: src/control/Control.NotebookbarWriter.js:49
 msgid "~Draw"
-msgstr ""
+msgstr "~Zeichnen"
 
 #: src/control/Control.NotebookbarWriter.js:55
 #: src/control/Control.NotebookbarCalc.js:43
 #: src/control/Control.NotebookbarImpress.js:119
 msgid "~Help"
-msgstr ""
+msgstr "~Hilfe"
 
 #: src/control/Control.NotebookbarCalc.js:28
 msgid "~Sheet"
-msgstr ""
+msgstr "~Tabelle"
 
 #: src/control/Control.NotebookbarCalc.js:33
 msgid "~Data"
-msgstr ""
+msgstr "~Daten"
 
 #: src/control/Control.NotebookbarCalc.js:1900
-#, fuzzy
-#| msgid "Insert table"
 msgid "Insert Rows Above"
-msgstr "Tabelle einfügen"
+msgstr "Zeilen oberhalb einfügen"
 
 #: src/control/Control.NotebookbarCalc.js:1913
-#, fuzzy
-#| msgid "Insert sheet"
 msgid "Insert Rows Below"
-msgstr "Tabelle einfügen"
+msgstr "Zeilen unterhalb einfügen"
 
 #: src/control/Control.NotebookbarCalc.js:1935
-#, fuzzy
-#| msgid "Insert sheet before this"
 msgid "Insert Columns Before"
-msgstr "Tabelle vor dieser einfügen"
+msgstr "Spalten davor einfügen"
 
 #: src/control/Control.NotebookbarCalc.js:1948
-#, fuzzy
-#| msgid "Insert sheet after this"
 msgid "Insert Columns After"
-msgstr "Tabelle nach dieser einfügen"
+msgstr "Spalten danach einfügen"
 
 #: src/control/Control.NotebookbarCalc.js:1970
 msgid "Insert Row Break"
-msgstr ""
+msgstr "Zeilenumbruch einfügen"
 
 #: src/control/Control.NotebookbarCalc.js:1983
 msgid "Insert Column Break"
-msgstr ""
+msgstr "Spaltenumbruch einfügen"
 
 #: src/control/Control.NotebookbarCalc.js:2005
-#, fuzzy
-#| msgid "Delete"
 msgid "Delete Rows"
-msgstr "Löschen"
+msgstr "Zeilen löschen"
 
 #: src/control/Control.NotebookbarCalc.js:2018
-#, fuzzy
-#| msgid "Columns"
 msgid "Delete Columns"
-msgstr "Spalten"
+msgstr "Spalten löschen"
 
 #: src/control/Control.NotebookbarCalc.js:2040
 msgid "Remove Row Break"
-msgstr ""
+msgstr "Zeilenumbruch entfernen"
 
 #: src/control/Control.NotebookbarCalc.js:2053
 msgid "Remove Column Break"
-msgstr ""
+msgstr "Spaltenumbruch entfernen"
 
 #: src/control/Control.NotebookbarImpress.js:27
 msgid "Start Presentation"
@@ -1249,10 +1235,8 @@ msgid "Idle document - please click to reload and resume editing"
 msgstr "Leeres Dokument - zum Neuladen und Fortsetzen der Bearbeitung klicken Sie bitte"
 
 #: src/core/Socket.js:403
-#, fuzzy
-#| msgid "Idle document - please click to reload and resume editing"
 msgid "Idle document - please tap to reload and resume editing"
-msgstr "Leeres Dokument - zum Neuladen und Fortsetzen der Bearbeitung klicken Sie bitte"
+msgstr "Inaktives Dokument – zum Neuladen und Fortsetzen der Bearbeitung bitte tippen"
 
 #: src/core/Socket.js:411
 msgid "Server is shutting down for maintenance (auto-saving)"
diff --git a/loleaflet/po/ui-pt_BR.po b/loleaflet/po/ui-pt_BR.po
index d5bce3bd3..458591b72 100644
--- a/loleaflet/po/ui-pt_BR.po
+++ b/loleaflet/po/ui-pt_BR.po
@@ -7,8 +7,8 @@ msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2020-08-04 15:38+0200\n"
-"PO-Revision-Date: 2020-08-07 08:29+0000\n"
-"Last-Translator: Felipe Viggiano <felipeviggiano at gmail.com>\n"
+"PO-Revision-Date: 2020-08-22 04:28+0000\n"
+"Last-Translator: Olivier Hallot <olivier.hallot at libreoffice.org>\n"
 "Language-Team: Portuguese (Brazil) <https://weblate.documentfoundation.org/projects/libo_online/loleaflet-ui/pt_BR/>\n"
 "Language: pt_BR\n"
 "MIME-Version: 1.0\n"
@@ -656,7 +656,7 @@ msgstr "Apresentação em tela cheia"
 
 #: src/control/Control.Menubar.js:354
 msgid "Present current slide"
-msgstr ""
+msgstr "Apresentar slide atual"
 
 #: src/control/Control.Menubar.js:381 src/control/Control.Menubar.js:597
 #: src/control/Control.NotebookbarCalc.js:211
@@ -726,7 +726,7 @@ msgstr "Ocultar a barra de pesquisa"
 
 #: src/control/Control.SheetsBar.js:28
 msgid "Scroll to the first sheet"
-msgstr ""
+msgstr "Ir para a primeira planilha"
 
 #: src/control/Control.SheetsBar.js:29
 msgid "Scroll left"
@@ -738,7 +738,7 @@ msgstr "Rolar para a direita"
 
 #: src/control/Control.SheetsBar.js:31
 msgid "Scroll to the last sheet"
-msgstr ""
+msgstr "Ir para a última planilha"
 
 #: src/control/Control.SheetsBar.js:32
 msgid "Insert sheet"
@@ -1020,7 +1020,7 @@ msgstr "Não foi possível bloquear o documento e está aberto em modo somente l
 
 #: src/control/Permission.js:47 src/control/Permission.js:65
 msgid "Server returned this reason:"
-msgstr ""
+msgstr "O servidor retornou esta razão:"
 
 #: src/control/Permission.js:63
 msgid "The document could not be locked."
commit 939ab8444042e2c486190a3815f1043a3686a7dd
Author:     Andras Timar <andras.timar at collabora.com>
AuthorDate: Fri Aug 28 08:37:55 2020 +0200
Commit:     Andras Timar <andras.timar at collabora.com>
CommitDate: Fri Aug 28 10:46:05 2020 +0200

    Revert "Disable insert comment on spreadsheet for mobile"
    
    This reverts commit 0cc4977abdbb0225c8c1a5f59b5bc00891463775.
    Reason for revert: after Pranam's fixes viewing/hiding/modifying comments
    work as expected, therefore we can have this option back.
    
    Change-Id: I299f33552ae26d29ea2078c286bc5c785ebdb7a9
    Reviewed-on: https://gerrit.libreoffice.org/c/online/+/101517
    Tested-by: Jenkins
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>
    Reviewed-by: Andras Timar <andras.timar at collabora.com>

diff --git a/loleaflet/src/control/Control.Menubar.js b/loleaflet/src/control/Control.Menubar.js
index 5ea9a8500..074ec743a 100644
--- a/loleaflet/src/control/Control.Menubar.js
+++ b/loleaflet/src/control/Control.Menubar.js
@@ -698,6 +698,7 @@ L.Control.Menubar = L.Control.extend({
 					{name: _('Local Image...'), id: 'insertgraphic', type: 'action'},
 					{name: _UNO('.uno:InsertGraphic', 'spreadsheet'), id: 'insertgraphicremote', type: 'action'},
 					{uno: '.uno:InsertObjectChart'},
+					{name: _UNO('.uno:InsertAnnotation', 'spreadsheet'), id: 'insertcomment', type: 'action'},
 					{type: 'separator'},
 					{name: _UNO('.uno:HyperlinkDialog'), id: 'inserthyperlink', type: 'action'},
 					{name: _UNO('.uno:ShapesMenu'), id: 'insertshape', type: 'action'},
commit 5181e6d51d392488e38b6e85d713248a42864509
Author:     Pranam Lashkari <lpranam at collabora.com>
AuthorDate: Fri Aug 28 02:03:29 2020 +0530
Commit:     Andras Timar <andras.timar at collabora.com>
CommitDate: Fri Aug 28 10:31:04 2020 +0200

    leaflet: use vex dialog to modify comments in calc mobile
    
    Change-Id: I7c76c3cb9b5438f010752933db45f30899068d4c
    Reviewed-on: https://gerrit.libreoffice.org/c/online/+/101507
    Tested-by: Jenkins
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>
    Reviewed-by: Andras Timar <andras.timar at collabora.com>

diff --git a/loleaflet/src/layer/tile/CalcTileLayer.js b/loleaflet/src/layer/tile/CalcTileLayer.js
index c5072f233..534c307ab 100644
--- a/loleaflet/src/layer/tile/CalcTileLayer.js
+++ b/loleaflet/src/layer/tile/CalcTileLayer.js
@@ -93,8 +93,13 @@ L.CalcTileLayer = (L.Browser.mobile ? L.TileLayer : L.CanvasTileLayer).extend({
 	},
 
 	onAnnotationModify: function (annotation) {
-		annotation.edit();
-		annotation.focus();
+		if (window.mode.isMobile() || window.mode.isTablet()) {
+			var that = this;
+			this.newAnnotationVex(annotation, function(annotation) { that._onAnnotationSave(annotation); }, /* isMod */ true);
+		} else {
+			annotation.edit();
+			annotation.focus();
+		}
 	},
 
 	onAnnotationRemove: function (id) {
commit d3780ad1416fd9eed013e8e766545c8dc7fce8e5
Author:     Pranam Lashkari <lpranam at collabora.com>
AuthorDate: Wed Aug 26 04:06:24 2020 +0530
Commit:     Andras Timar <andras.timar at collabora.com>
CommitDate: Fri Aug 28 10:30:08 2020 +0200

    leaflet: fixed show/hide comment in context menu
    
    Change-Id: Ia18c92832c0dd0de5a09b6e434b4afe4ca9afb26
    Reviewed-on: https://gerrit.libreoffice.org/c/online/+/101375
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>
    Tested-by: Jenkins
    Reviewed-by: Andras Timar <andras.timar at collabora.com>

diff --git a/loleaflet/src/control/Control.ContextMenu.js b/loleaflet/src/control/Control.ContextMenu.js
index db34a5600..3f0a4c035 100644
--- a/loleaflet/src/control/Control.ContextMenu.js
+++ b/loleaflet/src/control/Control.ContextMenu.js
@@ -78,7 +78,6 @@ L.Control.ContextMenu = L.Control.extend({
 			'SpellingAndGrammarDialog', 'FontDialog', 'FontDialogForParagraph',
 			// spreadsheet
 			'FormatCellDialog',
-			'ShowNote', 'HideNote', 'DeleteNote',
 		]
 	},
 
diff --git a/loleaflet/src/control/Control.JSDialogBuilder.js b/loleaflet/src/control/Control.JSDialogBuilder.js
index ca72b9be7..ab9056aef 100644
--- a/loleaflet/src/control/Control.JSDialogBuilder.js
+++ b/loleaflet/src/control/Control.JSDialogBuilder.js
@@ -2163,6 +2163,10 @@ L.Control.JSDialogBuilder = L.Control.extend({
 					     data.command.startsWith('.uno:InsertPageFooter')) &&
 					    data.checked && data.checked === true) {
 						return;
+					} else if (data.command === '.uno:ShowNote') {
+						builder.map._docLayer.showAnnotationFromCurrentCell();
+					} else if (data.command === '.uno:HideNote') {
+						builder.map._docLayer.hideAnnotationFromCurrentCell();
 					}
 					builder.map.sendUnoCommand(data.command);
 				}
diff --git a/loleaflet/src/layer/tile/CalcTileLayer.js b/loleaflet/src/layer/tile/CalcTileLayer.js
index 35eae4c14..c5072f233 100644
--- a/loleaflet/src/layer/tile/CalcTileLayer.js
+++ b/loleaflet/src/layer/tile/CalcTileLayer.js
@@ -130,7 +130,7 @@ L.CalcTileLayer = (L.Browser.mobile ? L.TileLayer : L.CanvasTileLayer).extend({
 		var annotations = this._annotations[this._selectedPart];
 		for (var key in annotations) {
 			var annotation = annotations[key]._annotation;
-			if (this._cellCursor.contains(annotation._data.cellPos)) {
+			if (this._cellCursor.intersects(annotation._data.cellPos)) {
 				this._map.addLayer(annotation);
 				annotation.show();
 			}
commit 8895a48d1f430260bc79ae1c65b447c7f70b1894
Author:     gokaysatir <gokaysatir at collabora.com>
AuthorDate: Wed Aug 19 13:16:52 2020 +0300
Commit:     Andras Timar <andras.timar at collabora.com>
CommitDate: Thu Aug 27 20:48:21 2020 +0200

    loleaflet: Insert shape window last row visibility.
    
    Last row wasn't fully visible on Calculator mobile view.
    
    Change-Id: Ia326fddc3510eabbca9b3d9b4bd90bf30f95f785
    Reviewed-on: https://gerrit.libreoffice.org/c/online/+/100982
    Tested-by: Jenkins
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>
    Reviewed-by: Andras Timar <andras.timar at collabora.com>

diff --git a/loleaflet/css/device-mobile.css b/loleaflet/css/device-mobile.css
index f78dd8fb8..38a7658f4 100644
--- a/loleaflet/css/device-mobile.css
+++ b/loleaflet/css/device-mobile.css
@@ -411,7 +411,7 @@ button.vex-dialog-button-secondary.vex-dialog-button.vex-last {
 /* Related to toolbar.css */
 .insertshape-grid {
 	box-sizing: content-box;
-	position: absolute;
+	position: static;
 	padding: 2px 0px 2px 0px;
 	display: inline-block;
 	width: 100%;
diff --git a/loleaflet/css/mobilewizard.css b/loleaflet/css/mobilewizard.css
index ae530a7f3..efb84291e 100644
--- a/loleaflet/css/mobilewizard.css
+++ b/loleaflet/css/mobilewizard.css
@@ -194,7 +194,6 @@ p.mobile-wizard.ui-combobox-text.selected {
 	top: 111px;
 	bottom: 0px;
 	width: 100%;
-	padding-bottom: 50px;
 }
 #mobile-wizard.funcwizard div#mobile-wizard-content.hideHelpBG {
 	background: none !important;
@@ -265,7 +264,8 @@ p.mobile-wizard.ui-combobox-text.selected {
 		bottom: 0px;
 		z-index: 1000;
 		background-color: white;
-		box-shadow: 0px -2px 4px 1px #00000030
+		box-shadow: 0px -2px 4px 1px #00000030;
+		overflow-y: scroll;
 }
 
 #mobile-wizard-content *{
@@ -279,6 +279,7 @@ p.mobile-wizard.ui-combobox-text.selected {
 	height: 48px;
 	color: #636363;
 	border-bottom: 1px solid #dddddd !important;
+	position: sticky;
 }
 
 .ui-content.mobile-wizard {
diff --git a/loleaflet/css/toolbar.css b/loleaflet/css/toolbar.css
index 3be4c97e6..986290d35 100644
--- a/loleaflet/css/toolbar.css
+++ b/loleaflet/css/toolbar.css
@@ -852,8 +852,7 @@ button.leaflet-control-search-next
 }
 
 .insertshape-grid .row:last-child {
-		box-sizing: content-box;
-		margin-bottom: 43px;
+	margin-bottom: 70px;
 }
 
 .insertshape-grid .col {
@@ -866,10 +865,11 @@ button.leaflet-control-search-next
 .insertshape-grid .row-header {
 		height: 30px;
 		text-align: center;
-		padding: 5px;
-		padding-top: 10px;
+		padding: 7px;
 		clear: both;
 		background-color: rgba(128, 128, 128, 0.1);
+		position: static;
+		line-height: 30px;
 }
 
 .insertshape-grid .col:hover {
commit 05dba7ad86e4bc5ddde3fcfb3faca2c4458c676b
Author:     Mike Kaganski <mike.kaganski at collabora.com>
AuthorDate: Tue Jul 28 17:52:14 2020 +0300
Commit:     Mike Kaganski <mike.kaganski at collabora.com>
CommitDate: Thu Aug 27 11:29:12 2020 +0200

    Restructure discovery to have less apps
    
    The apps are not meant to represent MIME types of respective
    single file extensions; rather, they represent application/module
    that handles several extensions. So this groups extensions under
    modules (writer/calc/...). This is required for some WOPI hosts
    that whitelist discovery data on per-app base.
    
    The old list of MIME-type-based apps is kept for compatibility
    with existing integrations, until they are fixed to use new-style
    discovery. Extensions are removed from legacy part, to avoid
    duplicating actions.
    
    This also hardcodes content types, to avoid repeated parsing of
    discovery.xml.
    
    lint-discovery.py is updated to process new-style information
    (ignores legacy part).
    
    Change-Id: Ib8d3518f00510cd0788314d8a9da9a286a52e0ba
    Reviewed-on: https://gerrit.libreoffice.org/c/online/+/99637
    Tested-by: Jenkins
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>
    Reviewed-by: Mike Kaganski <mike.kaganski at collabora.com>

diff --git a/discovery.xml b/discovery.xml
index b0ea602d4..22b284621 100644
--- a/discovery.xml
+++ b/discovery.xml
@@ -1,314 +1,451 @@
 <?xml version="1.0" encoding="utf-8"?>
 <wopi-discovery>
     <net-zone name="external-http">
-        <app name="image/svg+xml">
+
+        <!-- Writer documents -->
+        <app name="writer">
+            <action name="view" default="true" ext="sxw"/>
+            <action name="edit" default="true" ext="odt"/>
+            <action name="edit" default="true" ext="fodt"/>
+            <!-- Text template documents -->
+            <action name="view" default="true" ext="stw"/>
+            <action name="edit" default="true" ext="ott"/>
+            <!-- MS Word -->
+            <action name="edit" default="true" ext="doc"/>
+            <action name="edit" default="true" ext="dot"/>
+            <!-- OOXML wordprocessing -->
+            <action name="edit" default="true" ext="docx"/>
+            <action name="edit" default="true" ext="docm"/>
+            <action name="view" default="true" ext="dotx"/>
+            <action name="view" default="true" ext="dotm"/>
+            <!-- Others -->
+            <action name="view" default="true" ext="wpd"/>
+            <action name="view" default="true" ext="pdb"/>
+            <action name="view" default="true" ext="hwp"/>
+            <action name="view" default="true" ext="wps"/>
+            <action name="view" default="true" ext="wri"/>
+            <action name="view" default="true" ext="lrf"/>
+            <action name="view" default="true" ext="mw"/>
+            <action name="edit" default="true" ext="rtf"/>
+            <action name="edit" default="true" ext="txt"/>
+            <action name="view" default="true" ext="fb2"/>
+            <action name="view" default="true" ext="cwk"/>
+            <action name="view" default="true" ext="pages"/>
+            <action name="view" default="true" ext="abw"/>
+            <action name="view" default="true" ext="602"/>
+        </app>
+
+        <app name="writer-global">
+            <!-- Text master documents -->
+            <action name="view" default="true" ext="sxg"/>
+            <action name="edit" default="true" ext="odm"/>
+            <!-- Writer master document templates -->
+            <action name="edit" default="true" ext="otm"/>
+        </app>
+
+        <app name="writer-web">
+            <action name="edit" default="true" ext="oth"/>
+        </app>
+
+        <!-- Calc documents -->
+        <app name="calc">
+            <action name="view" default="true" ext="sxc"/>
+            <action name="edit" default="true" ext="ods"/>
+            <action name="edit" default="true" ext="fods"/>
+            <!-- Spreadsheet template documents -->
+            <action name="view" default="true" ext="stc"/>
+            <action name="edit" default="true" ext="ots"/>
+            <!-- MS Excel -->
+            <action name="edit" default="true" ext="xls"/>
+            <action name="edit" default="true" ext="xla"/>
+            <!-- OOXML spreadsheet -->
+            <action name="view" default="true" ext="xltx"/>
+            <action name="view" default="true" ext="xltm"/>
+            <action name="edit" default="true" ext="xlsx"/>
+            <action name="edit" default="true" ext="xlsb"/>
+            <action name="edit" default="true" ext="xlsm"/>
+            <!-- Others -->
+            <action name="edit" default="true" ext="dif"/>
+            <action name="edit" default="true" ext="slk"/>
+            <action name="edit" default="true" ext="csv"/>
+            <action name="edit" default="true" ext="dbf"/>
+            <action name="view" default="true" ext="wk1"/>
+            <action name="view" default="true" ext="gnumeric"/>
+            <action name="view" default="true" ext="numbers"/>
+        </app>
+
+        <!-- Impress documents -->
+        <app name="impress">
+            <action name="view" default="true" ext="sxi"/>
+            <action name="edit" default="true" ext="odp"/>
+            <action name="edit" default="true" ext="fodp"/>
+            <!-- Presentation template documents -->
+            <action name="view" default="true" ext="sti"/>
+            <action name="edit" default="true" ext="otp"/>
+            <!-- MS PowerPoint -->
+            <action name="edit" default="true" ext="ppt"/>
+            <action name="edit" default="true" ext="pot"/>
+            <!-- OOXML presentation -->
+            <action name="edit" default="true" ext="pptx"/>
+            <action name="edit" default="true" ext="pptm"/>
+            <action name="edit" default="true" ext="potx"/>
+            <action name="edit" default="true" ext="potm"/>
+            <action name="edit" default="true" ext="ppsx"/>
+            <!-- Others -->
+            <action name="view" default="true" ext="cgm"/>
+            <action name="view" default="true" ext="key"/>
+        </app>
+
+        <!-- Draw documents -->
+        <app name="draw">
+            <action name="view" default="true" ext="sxd"/>
+            <action name="view" default="true" ext="odg"/>
+            <action name="view" default="true" ext="fodg"/>
+            <!-- Drawing template documents -->
+            <action name="view" default="true" ext="std"/>
+            <action name="edit" default="true" ext="otg"/>
+            <!-- Others -->
             <action name="view" ext="svg"/>
+            <action name="view" default="true" ext="dxf"/>
+            <action name="view" default="true" ext="emf"/>

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list