From 4dce59fe9545e7b4ac4af5157efac101d4d7b4d0 Mon Sep 17 00:00:00 2001 From: ahocevar Date: Wed, 2 Apr 2014 16:44:39 +0200 Subject: [PATCH 1/4] Add method for testing whether the canvas size is valid This is a way to detect whether a canvas exceeds the maximum dimensions if these are limited on the target device. See https://developer.apple.com/library/ios/documentation/AppleApplications/Reference/SafariWebContent/CreatingContentforSafarioniPhone/CreatingContentforSafarioniPhone.html for limitations on iOS devices. --- src/ol/renderer/canvas/canvaslayerrenderer.js | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/ol/renderer/canvas/canvaslayerrenderer.js b/src/ol/renderer/canvas/canvaslayerrenderer.js index 9022170cd6..b6ae6b6119 100644 --- a/src/ol/renderer/canvas/canvaslayerrenderer.js +++ b/src/ol/renderer/canvas/canvaslayerrenderer.js @@ -1,5 +1,6 @@ goog.provide('ol.renderer.canvas.Layer'); +goog.require('goog.array'); goog.require('goog.vec.Mat4'); goog.require('ol.layer.Layer'); goog.require('ol.render.Event'); @@ -20,6 +21,12 @@ ol.renderer.canvas.Layer = function(mapRenderer, layer) { goog.base(this, mapRenderer, layer); + /** + * @private + * @type {ImageData} + */ + this.testImageData_ = null; + /** * @private * @type {!goog.vec.Mat4.Number} @@ -163,3 +170,30 @@ ol.renderer.canvas.Layer.prototype.getTransform = function(frameState) { -view2DState.rotation, -view2DState.center[0], -view2DState.center[1]); }; + + +/** + * @param {CanvasRenderingContext2D} context Context. + * @param {ol.Size} size Size. + * @return {boolean} True when the canvas with the current size does not exceed + * the maximum dimensions. + * @protected + */ +ol.renderer.canvas.Layer.prototype.testCanvasSize = function(context, size) { + var x = size[0] - 1; + var y = size[1] - 1; + var originalImageData = context.getImageData(x, y, 1, 1); + if (goog.isNull(this.testImageData_)) { + this.testImageData_ = context.createImageData(1, 1); + var data = this.testImageData_.data; + data[0] = 42; + data[1] = 84; + data[2] = 126; + data[3] = 255; + } + context.putImageData(this.testImageData_, x, y); + var result = context.getImageData(x, y, 1, 1); + var good = goog.array.equals(this.testImageData_.data, result.data); + context.putImageData(originalImageData, x, y); + return good; +}; From 58b5fef3da33b20eb1262dca3906db4969ad272e Mon Sep 17 00:00:00 2001 From: ahocevar Date: Wed, 2 Apr 2014 16:44:57 +0200 Subject: [PATCH 2/4] Allow to make canvas smaller when it is too big For performance reason, we only make the canvas bigger, but not smaller. With this change, we also make it smaller, but only when we know that its current size exceeds the maximum dimensions. --- src/ol/renderer/canvas/canvastilelayerrenderer.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/ol/renderer/canvas/canvastilelayerrenderer.js b/src/ol/renderer/canvas/canvastilelayerrenderer.js index 724af798d0..626d39ec8e 100644 --- a/src/ol/renderer/canvas/canvastilelayerrenderer.js +++ b/src/ol/renderer/canvas/canvastilelayerrenderer.js @@ -44,6 +44,12 @@ ol.renderer.canvas.TileLayer = function(mapRenderer, tileLayer) { */ this.canvasSize_ = null; + /** + * @private + * @type {boolean} + */ + this.canvasTooBig_; + /** * @private * @type {CanvasRenderingContext2D} @@ -203,17 +209,21 @@ ol.renderer.canvas.TileLayer.prototype.prepareFrame = this.canvas_ = context.canvas; this.canvasSize_ = [canvasWidth, canvasHeight]; this.context_ = context; + this.canvasTooBig_ = !this.testCanvasSize(context, this.canvasSize_); } else { goog.asserts.assert(!goog.isNull(this.canvasSize_)); goog.asserts.assert(!goog.isNull(this.context_)); canvas = this.canvas_; context = this.context_; if (this.canvasSize_[0] < canvasWidth || - this.canvasSize_[1] < canvasHeight) { - // Canvas is too small, make it bigger + this.canvasSize_[1] < canvasHeight || + (this.canvasTooBig_ && (this.canvasSize_[0] > canvasWidth || + this.canvasSize_[1] > canvasHeight))) { + // Canvas is too small or too big, resize it canvas.width = canvasWidth; canvas.height = canvasHeight; this.canvasSize_ = [canvasWidth, canvasHeight]; + this.canvasTooBig_ = !this.testCanvasSize(context, this.canvasSize_); this.renderedCanvasTileRange_ = null; } else { canvasWidth = this.canvasSize_[0]; From 54ba06ae3b7c03c99e1e24f2689333ec916e5922 Mon Sep 17 00:00:00 2001 From: ahocevar Date: Thu, 3 Apr 2014 11:18:12 +0200 Subject: [PATCH 3/4] Initialize canvasTooBig_ member --- src/ol/renderer/canvas/canvastilelayerrenderer.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/ol/renderer/canvas/canvastilelayerrenderer.js b/src/ol/renderer/canvas/canvastilelayerrenderer.js index 626d39ec8e..89b5e93f63 100644 --- a/src/ol/renderer/canvas/canvastilelayerrenderer.js +++ b/src/ol/renderer/canvas/canvastilelayerrenderer.js @@ -48,7 +48,7 @@ ol.renderer.canvas.TileLayer = function(mapRenderer, tileLayer) { * @private * @type {boolean} */ - this.canvasTooBig_; + this.canvasTooBig_ = false; /** * @private @@ -209,7 +209,8 @@ ol.renderer.canvas.TileLayer.prototype.prepareFrame = this.canvas_ = context.canvas; this.canvasSize_ = [canvasWidth, canvasHeight]; this.context_ = context; - this.canvasTooBig_ = !this.testCanvasSize(context, this.canvasSize_); + this.canvasTooBig_ = + !ol.renderer.canvas.Layer.testCanvasSize(context, this.canvasSize_); } else { goog.asserts.assert(!goog.isNull(this.canvasSize_)); goog.asserts.assert(!goog.isNull(this.context_)); @@ -223,7 +224,8 @@ ol.renderer.canvas.TileLayer.prototype.prepareFrame = canvas.width = canvasWidth; canvas.height = canvasHeight; this.canvasSize_ = [canvasWidth, canvasHeight]; - this.canvasTooBig_ = !this.testCanvasSize(context, this.canvasSize_); + this.canvasTooBig_ = + !ol.renderer.canvas.Layer.testCanvasSize(context, this.canvasSize_); this.renderedCanvasTileRange_ = null; } else { canvasWidth = this.canvasSize_[0]; From ea58f38275e58d6edc5fe15417b2dde7f25e88c7 Mon Sep 17 00:00:00 2001 From: ahocevar Date: Thu, 3 Apr 2014 11:18:26 +0200 Subject: [PATCH 4/4] Make testCanvasSize a static function --- src/ol/renderer/canvas/canvaslayerrenderer.js | 51 ++++++++++--------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/src/ol/renderer/canvas/canvaslayerrenderer.js b/src/ol/renderer/canvas/canvaslayerrenderer.js index b6ae6b6119..8ce6f7cc4b 100644 --- a/src/ol/renderer/canvas/canvaslayerrenderer.js +++ b/src/ol/renderer/canvas/canvaslayerrenderer.js @@ -21,12 +21,6 @@ ol.renderer.canvas.Layer = function(mapRenderer, layer) { goog.base(this, mapRenderer, layer); - /** - * @private - * @type {ImageData} - */ - this.testImageData_ = null; - /** * @private * @type {!goog.vec.Mat4.Number} @@ -177,23 +171,30 @@ ol.renderer.canvas.Layer.prototype.getTransform = function(frameState) { * @param {ol.Size} size Size. * @return {boolean} True when the canvas with the current size does not exceed * the maximum dimensions. - * @protected */ -ol.renderer.canvas.Layer.prototype.testCanvasSize = function(context, size) { - var x = size[0] - 1; - var y = size[1] - 1; - var originalImageData = context.getImageData(x, y, 1, 1); - if (goog.isNull(this.testImageData_)) { - this.testImageData_ = context.createImageData(1, 1); - var data = this.testImageData_.data; - data[0] = 42; - data[1] = 84; - data[2] = 126; - data[3] = 255; - } - context.putImageData(this.testImageData_, x, y); - var result = context.getImageData(x, y, 1, 1); - var good = goog.array.equals(this.testImageData_.data, result.data); - context.putImageData(originalImageData, x, y); - return good; -}; +ol.renderer.canvas.Layer.testCanvasSize = (function() { + + /** + * @type {ImageData} + */ + var testImageData = null; + + return function(context, size) { + var x = size[0] - 1; + var y = size[1] - 1; + var originalImageData = context.getImageData(x, y, 1, 1); + if (goog.isNull(testImageData)) { + testImageData = context.createImageData(1, 1); + var data = testImageData.data; + data[0] = 42; + data[1] = 84; + data[2] = 126; + data[3] = 255; + } + context.putImageData(testImageData, x, y); + var result = context.getImageData(x, y, 1, 1); + var good = goog.array.equals(testImageData.data, result.data); + context.putImageData(originalImageData, x, y); + return good; + }; +})();