From b52a4b084ecb56899eff7bcb128f25dcb272aced Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Thu, 9 Jan 2014 00:17:46 +0100 Subject: [PATCH 01/14] Remove pointless test --- test/spec/ol/source/imagewmssource.test.js | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/test/spec/ol/source/imagewmssource.test.js b/test/spec/ol/source/imagewmssource.test.js index 33f8f4089b..06895b9684 100644 --- a/test/spec/ol/source/imagewmssource.test.js +++ b/test/spec/ol/source/imagewmssource.test.js @@ -1,26 +1,9 @@ goog.provide('ol.test.source.ImageWMS'); + describe('ol.source.ImageWMS', function() { - describe('constructor', function() { - - it('creates a source', function() { - var source = new ol.source.ImageWMS({ - url: 'http://demo.opengeo.org/geoserver/wms', - params: {'LAYERS': 'topp:states'}, - extent: [-13884991, 2870341, -7455066, 6338219] - }); - - expect(source).to.be.a(ol.source.ImageWMS); - expect(source).to.be.a(ol.source.Source); - }); - - }); - }); -goog.require('goog.Uri'); -goog.require('ol.Map'); goog.require('ol.source.ImageWMS'); -goog.require('ol.source.Source'); From 079cd585e60a4e11740e4a21626a2886e7388dbb Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Thu, 9 Jan 2014 01:27:54 +0100 Subject: [PATCH 02/14] Add ol.source.ImageWMS tests --- test/spec/ol/source/imagewmssource.test.js | 136 +++++++++++++++++++++ 1 file changed, 136 insertions(+) diff --git a/test/spec/ol/source/imagewmssource.test.js b/test/spec/ol/source/imagewmssource.test.js index 06895b9684..18aa4848b8 100644 --- a/test/spec/ol/source/imagewmssource.test.js +++ b/test/spec/ol/source/imagewmssource.test.js @@ -3,7 +3,143 @@ goog.provide('ol.test.source.ImageWMS'); describe('ol.source.ImageWMS', function() { + describe('#getImage', function() { + + var extent, pixelRatio, options, projection, resolution; + beforeEach(function() { + extent = [10, 20, 30, 40]; + pixelRatio = 1; + projection = ol.proj.get('EPSG:4326'); + resolution = 0.1; + options = { + params: { + 'LAYERS': 'layer' + }, + ratio: 1, + url: 'http://example.com/wms' + }; + }); + + it('returns the expected image URL', function() { + var source = new ol.source.ImageWMS(options); + var image = source.getImage(extent, resolution, pixelRatio, projection); + var uri = new goog.Uri(image.src_); + expect(uri.getScheme()).to.be('http'); + expect(uri.getDomain()).to.be('example.com'); + expect(uri.getPath()).to.be('/wms'); + var queryData = uri.getQueryData(); + expect(queryData.get('BBOX')).to.be('20,10,40,30'); + expect(queryData.get('CRS')).to.be('EPSG:4326'); + expect(queryData.get('FORMAT')).to.be('image/png'); + expect(queryData.get('HEIGHT')).to.be('200'); + expect(queryData.get('LAYERS')).to.be('layer'); + expect(queryData.get('REQUEST')).to.be('GetMap'); + expect(queryData.get('SERVICE')).to.be('WMS'); + expect(queryData.get('SRS')).to.be(undefined); + expect(queryData.get('STYLES')).to.be(''); + expect(queryData.get('TRANSPARENT')).to.be('true'); + expect(queryData.get('VERSION')).to.be('1.3.0'); + expect(queryData.get('WIDTH')).to.be('200'); + expect(uri.getFragment()).to.be.empty(); + }); + + it('sets the SRS query value instead of CRS if version < 1.3', function() { + options.params.VERSION = '1.2'; + var source = new ol.source.ImageWMS(options); + var image = source.getImage(extent, resolution, pixelRatio, projection); + var uri = new goog.Uri(image.src_); + var queryData = uri.getQueryData(); + expect(queryData.get('CRS')).to.be(undefined); + expect(queryData.get('SRS')).to.be('EPSG:4326'); + }); + + it('allows various parameters to be overridden', function() { + options.params.FORMAT = 'image/jpeg'; + options.params.TRANSPARENT = false; + var source = new ol.source.ImageWMS(options); + var image = source.getImage(extent, resolution, pixelRatio, projection); + var uri = new goog.Uri(image.src_); + var queryData = uri.getQueryData(); + expect(queryData.get('FORMAT')).to.be('image/jpeg'); + expect(queryData.get('TRANSPARENT')).to.be('false'); + }); + + it('does not add a STYLES= option if one is specified', function() { + options.params.STYLES = 'foo'; + var source = new ol.source.ImageWMS(options); + var image = source.getImage(extent, resolution, pixelRatio, projection); + var uri = new goog.Uri(image.src_); + var queryData = uri.getQueryData(); + expect(queryData.get('STYLES')).to.be('foo'); + }); + + it('changes the BBOX order for EN axis orientations', function() { + var source = new ol.source.ImageWMS(options); + projection = ol.proj.get('CRS:84'); + var image = source.getImage(extent, resolution, pixelRatio, projection); + var uri = new goog.Uri(image.src_); + var queryData = uri.getQueryData(); + expect(queryData.get('BBOX')).to.be('10,20,30,40'); + }); + + it('uses EN BBOX order if version < 1.3', function() { + options.params.VERSION = '1.1.0'; + var source = new ol.source.ImageWMS(options); + var image = + source.getImage(extent, resolution, pixelRatio, projection); + var uri = new goog.Uri(image.src_); + var queryData = uri.getQueryData(); + expect(queryData.get('BBOX')).to.be('10,20,30,40'); + }); + + it('sets MAP_RESOLUTION when the server is MapServer', function() { + options.serverType = ol.source.wms.ServerType.MAPSERVER; + var source = new ol.source.ImageWMS(options); + pixelRatio = 2; + var image = source.getImage(extent, resolution, pixelRatio, projection); + var uri = new goog.Uri(image.src_); + var queryData = uri.getQueryData(); + expect(queryData.get('MAP_RESOLUTION')).to.be('180'); + }); + + it('sets FORMAT_OPTIONS when the server is GeoServer', function() { + options.serverType = ol.source.wms.ServerType.GEOSERVER; + var source = new ol.source.ImageWMS(options); + pixelRatio = 2; + var image = source.getImage(extent, resolution, pixelRatio, projection); + var uri = new goog.Uri(image.src_); + var queryData = uri.getQueryData(); + expect(queryData.get('FORMAT_OPTIONS')).to.be('dpi:180'); + }); + + it('rounds FORMAT_OPTIONS to an integer when the server is GeoServer', + function() { + options.serverType = ol.source.wms.ServerType.GEOSERVER; + var source = new ol.source.ImageWMS(options); + pixelRatio = 1.325; + var image = + source.getImage(extent, resolution, pixelRatio, projection); + var uri = new goog.Uri(image.src_); + var queryData = uri.getQueryData(); + expect(queryData.get('FORMAT_OPTIONS')).to.be('dpi:119'); + }); + + it('sets DPI when the server is QGIS', function() { + options.serverType = ol.source.wms.ServerType.QGIS; + var source = new ol.source.ImageWMS(options); + pixelRatio = 2; + var image = source.getImage(extent, resolution, pixelRatio, projection); + var uri = new goog.Uri(image.src_); + var queryData = uri.getQueryData(); + expect(queryData.get('DPI')).to.be('180'); + }); + + }); + }); +goog.require('goog.Uri'); goog.require('ol.source.ImageWMS'); +goog.require('ol.proj'); +goog.require('ol.source.wms.ServerType'); From 8d18f25296a718e01e4d96e47591cb592ee4fa07 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Thu, 9 Jan 2014 10:50:51 +0100 Subject: [PATCH 03/14] Add ol.source.TileWMS tests --- test/spec/ol/source/tilewmssource.test.js | 113 ++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 test/spec/ol/source/tilewmssource.test.js diff --git a/test/spec/ol/source/tilewmssource.test.js b/test/spec/ol/source/tilewmssource.test.js new file mode 100644 index 0000000000..f27cee5b97 --- /dev/null +++ b/test/spec/ol/source/tilewmssource.test.js @@ -0,0 +1,113 @@ +goog.provide('ol.test.source.TileWMS'); + + +describe('ol.source.TileWMS', function() { + + var options; + beforeEach(function() { + options = { + params: { + 'LAYERS': 'layer' + }, + url: 'http://example.com/wms' + }; + }); + + describe('#getTile', function() { + + it('returns a tile with the expected URL', function() { + var source = new ol.source.TileWMS(options); + var tile = source.getTile(3, 2, 1, ol.proj.get('EPSG:3857')); + expect(tile).to.be.an(ol.ImageTile); + var uri = new goog.Uri(tile.src_); + expect(uri.getScheme()).to.be('http'); + expect(uri.getDomain()).to.be('example.com'); + expect(uri.getPath()).to.be('/wms'); + var queryData = uri.getQueryData(); + expect(queryData.get('BBOX')).to.be( + '-10018754.171394622,-15028131.257091932,' + + '-5009377.085697311,-10018754.17139462'); + expect(queryData.get('CRS')).to.be('EPSG:3857'); + expect(queryData.get('FORMAT')).to.be('image/png'); + expect(queryData.get('HEIGHT')).to.be('256'); + expect(queryData.get('LAYERS')).to.be('layer'); + expect(queryData.get('REQUEST')).to.be('GetMap'); + expect(queryData.get('SERVICE')).to.be('WMS'); + expect(queryData.get('SRS')).to.be(undefined); + expect(queryData.get('STYLES')).to.be(''); + expect(queryData.get('TRANSPARENT')).to.be('true'); + expect(queryData.get('VERSION')).to.be('1.3.0'); + expect(queryData.get('WIDTH')).to.be('256'); + expect(uri.getFragment()).to.be.empty(); + }); + + it('returns a larger tile when a gutter is specified', function() { + options.gutter = 16; + var source = new ol.source.TileWMS(options); + var tile = source.getTile(3, 2, 1, ol.proj.get('EPSG:3857')); + expect(tile).to.be.an(ol.ImageTile); + var uri = new goog.Uri(tile.src_); + var queryData = uri.getQueryData(); + expect(queryData.get('BBOX')).to.be( + '-10331840.239250705,-15341217.324948015,' + + '-4696291.017841229,-9705668.103538537'); + expect(queryData.get('HEIGHT')).to.be('288'); + expect(queryData.get('WIDTH')).to.be('288'); + }); + + it('sets the SRS query value instead of CRS if version < 1.3', function() { + options.params.VERSION = '1.2'; + var source = new ol.source.TileWMS(options); + var tile = source.getTile(3, 2, 1, ol.proj.get('EPSG:4326')); + var uri = new goog.Uri(tile.src_); + var queryData = uri.getQueryData(); + expect(queryData.get('CRS')).to.be(undefined); + expect(queryData.get('SRS')).to.be('EPSG:4326'); + }); + + it('allows various parameters to be overridden', function() { + options.params.FORMAT = 'image/jpeg'; + options.params.TRANSPARENT = false; + var source = new ol.source.TileWMS(options); + var tile = source.getTile(3, 2, 1, ol.proj.get('EPSG:4326')); + var uri = new goog.Uri(tile.src_); + var queryData = uri.getQueryData(); + expect(queryData.get('FORMAT')).to.be('image/jpeg'); + expect(queryData.get('TRANSPARENT')).to.be('false'); + }); + + it('does not add a STYLES= option if one is specified', function() { + options.params.STYLES = 'foo'; + var source = new ol.source.TileWMS(options); + var tile = source.getTile(3, 2, 1, ol.proj.get('EPSG:4326')); + var uri = new goog.Uri(tile.src_); + var queryData = uri.getQueryData(); + expect(queryData.get('STYLES')).to.be('foo'); + }); + + it('changes the BBOX order for EN axis orientations', function() { + var source = new ol.source.TileWMS(options); + var tile = source.getTile(3, 2, 1, ol.proj.get('EPSG:4326')); + var uri = new goog.Uri(tile.src_); + var queryData = uri.getQueryData(); + expect(queryData.get('BBOX')).to.be('-45,-90,0,-45'); + }); + + it('uses EN BBOX order if version < 1.3', function() { + options.params.VERSION = '1.1.0'; + var source = new ol.source.TileWMS(options); + var tile = source.getTile(3, 2, 1, ol.proj.get('CRS:84')); + var uri = new goog.Uri(tile.src_); + var queryData = uri.getQueryData(); + expect(queryData.get('BBOX')).to.be('-90,-45,-45,0'); + }); + + }); + +}); + + +goog.require('goog.Uri'); +goog.require('ol.ImageTile'); +goog.require('ol.source.TileWMS'); +goog.require('ol.proj'); From 95f1871ac40fd1aa31cb1a9ce862c2389910d2e6 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Wed, 8 Jan 2014 21:14:44 +0100 Subject: [PATCH 04/14] Make ol.source.ImageSource crossOrigin property protected --- src/ol/source/imagesource.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ol/source/imagesource.js b/src/ol/source/imagesource.js index 2fbcb87bb1..3bcf40e698 100644 --- a/src/ol/source/imagesource.js +++ b/src/ol/source/imagesource.js @@ -52,10 +52,10 @@ ol.source.Image = function(options) { ol.ImageUrlFunction.nullImageUrlFunction; /** - * @private + * @protected * @type {?string} */ - this.crossOrigin_ = + this.crossOrigin = goog.isDef(options.crossOrigin) ? options.crossOrigin : null; /** @@ -89,7 +89,7 @@ ol.source.Image.prototype.createImage = var imageUrl = this.imageUrlFunction(extent, size, projection); if (goog.isDef(imageUrl)) { image = new ol.Image( - extent, resolution, pixelRatio, imageUrl, this.crossOrigin_, + extent, resolution, pixelRatio, imageUrl, this.crossOrigin, this.getAttributions()); } return image; From e9d84017867d3016425291cad0fbe49022f9c4b3 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Wed, 8 Jan 2014 21:19:52 +0100 Subject: [PATCH 05/14] Refactor ol.source.ImageWMS URL logic * Always request images of integer WIDTH and HEIGHT * Match BBOX to requested size * Handle integer-only DPIs in GeoServer --- src/ol/source/imagewmssource.js | 130 +++++++++++++++++++++++++------- 1 file changed, 103 insertions(+), 27 deletions(-) diff --git a/src/ol/source/imagewmssource.js b/src/ol/source/imagewmssource.js index 89b228408c..72b591e09a 100644 --- a/src/ol/source/imagewmssource.js +++ b/src/ol/source/imagewmssource.js @@ -1,43 +1,48 @@ +// FIXME factor out v13 calculation + goog.provide('ol.source.ImageWMS'); goog.require('goog.asserts'); goog.require('goog.object'); +goog.require('goog.string'); +goog.require('goog.uri.utils'); goog.require('ol.Image'); -goog.require('ol.ImageUrlFunction'); goog.require('ol.extent'); goog.require('ol.source.Image'); -goog.require('ol.source.wms'); +goog.require('ol.source.wms.ServerType'); /** * @constructor * @extends {ol.source.Image} - * @param {olx.source.ImageWMSOptions} options Options. + * @param {olx.source.ImageWMSOptions=} opt_options Options. * @todo stability experimental */ -ol.source.ImageWMS = function(options) { +ol.source.ImageWMS = function(opt_options) { - /** - * @private - * @type {Object} - */ - this.params_ = options.params; - - var imageUrlFunction = goog.isDef(options.url) ? - ol.ImageUrlFunction.createFromParamsFunction( - options.url, this.params_, ol.source.wms.getUrl) : - ol.ImageUrlFunction.nullImageUrlFunction; + var options = goog.isDef(opt_options) ? opt_options : {}; goog.base(this, { attributions: options.attributions, crossOrigin: options.crossOrigin, extent: options.extent, projection: options.projection, - resolutions: options.resolutions, - imageUrlFunction: imageUrlFunction + resolutions: options.resolutions }); + /** + * @private + * @type {string|undefined} + */ + this.url_ = options.url; + + /** + * @private + * @type {Object} + */ + this.params_ = options.params; + /** * @private * @type {ol.source.wms.ServerType|undefined} @@ -81,8 +86,16 @@ ol.source.ImageWMS.prototype.getParams = function() { */ ol.source.ImageWMS.prototype.getImage = function(extent, resolution, pixelRatio, projection) { + + if (!goog.isDef(this.url_)) { + return null; + } + resolution = this.findNearestResolution(resolution); - pixelRatio = this.hidpi_ ? pixelRatio : 1; + + if (pixelRatio != 1 && (!this.hidpi_ || !goog.isDef(this.serverType_))) { + pixelRatio = 1; + } var image = this.image_; if (!goog.isNull(image) && @@ -92,20 +105,83 @@ ol.source.ImageWMS.prototype.getImage = return image; } - extent = extent.slice(); - ol.extent.scaleFromCenter(extent, this.ratio_); - var width = (extent[2] - extent[0]) / resolution; - var height = (extent[3] - extent[1]) / resolution; - var size = [width * pixelRatio, height * pixelRatio]; + var params = { + 'SERVICE': 'WMS', + 'VERSION': '1.3.0', + 'REQUEST': 'GetMap', + 'FORMAT': 'image/png', + 'TRANSPARENT': true + }; + goog.object.extend(params, this.params_); - if (goog.isDef(this.serverType_) && pixelRatio > 1) { - var param = ol.source.wms.getDpiParam(this.serverType_, pixelRatio); - goog.object.extend(this.params_, param); + var v13 = goog.string.compareVersions( + goog.object.get(params, 'VERSION'), '1.3') >= 0; + + params[v13 ? 'CRS' : 'SRS'] = projection.getCode(); + + if (!('STYLES' in this.params_)) { + goog.object.set(params, 'STYLES', new String('')); } - this.image_ = this.createImage( - extent, resolution, pixelRatio, size, projection); + if (pixelRatio != 1) { + switch (this.serverType_) { + case ol.source.wms.ServerType.GEOSERVER: + var dpi = (90 * pixelRatio + 0.5) | 0; + goog.object.set(params, 'FORMAT_OPTIONS', 'dpi:' + dpi); + break; + case ol.source.wms.ServerType.MAPSERVER: + goog.object.set(params, 'MAP_RESOLUTION', 90 * pixelRatio); + break; + case ol.source.wms.ServerType.QGIS: + goog.object.set(params, 'DPI', 90 * pixelRatio); + break; + default: + goog.asserts.fail(); + break; + } + } + + extent = extent.slice(); + var centerX = (extent[0] + extent[2]) / 2; + var centerY = (extent[1] + extent[3]) / 2; + if (this.ratio_ != 1) { + var halfWidth = this.ratio_ * (extent[2] - extent[0]) / 2; + var halfHeight = this.ratio_ * (extent[3] - extent[1]) / 2; + extent[0] = centerX - halfWidth; + extent[1] = centerY - halfHeight; + extent[2] = centerX + halfWidth; + extent[3] = centerY + halfHeight; + } + + var imageResolution = resolution / pixelRatio; + + // Compute an integer width and height. + var width = Math.ceil((extent[2] - extent[0]) / imageResolution); + goog.object.set(params, 'WIDTH', width); + var height = Math.ceil((extent[3] - extent[1]) / imageResolution); + goog.object.set(params, 'HEIGHT', height); + + // Modify the extent to match the integer width and height. + extent[0] = centerX - imageResolution * width / 2; + extent[2] = centerX + imageResolution * width / 2; + extent[1] = centerY - imageResolution * height / 2; + extent[3] = centerY + imageResolution * height / 2; + + var axisOrientation = projection.getAxisOrientation(); + var bbox; + if (v13 && axisOrientation.substr(0, 2) == 'ne') { + bbox = [extent[1], extent[0], extent[3], extent[2]]; + } else { + bbox = extent; + } + goog.object.set(params, 'BBOX', bbox.join(',')); + + var url = goog.uri.utils.appendParamsFromMap(this.url_, params); + + this.image_ = new ol.Image(extent, resolution, pixelRatio, url, + this.crossOrigin, this.getAttributions()); return this.image_; + }; From 1bf678bef2f279610b1f0edbcfc99dd7e539c64b Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Wed, 8 Jan 2014 21:22:18 +0100 Subject: [PATCH 06/14] Remove unused ol.source.wms.getDpiParam function --- src/ol/source/wmssource.js | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/src/ol/source/wmssource.js b/src/ol/source/wmssource.js index 6dde4c7663..8c13882557 100644 --- a/src/ol/source/wmssource.js +++ b/src/ol/source/wmssource.js @@ -51,23 +51,3 @@ ol.source.wms.getUrl = function(baseUrl, params, extent, size, projection) { return goog.uri.utils.appendParamsFromMap(baseUrl, baseParams); }; - - -/** - * @param {ol.source.wms.ServerType} serverType Server name. - * @param {number} pixelRatio Pixel ratio. - * @return {Object.} - */ -ol.source.wms.getDpiParam = function(serverType, pixelRatio) { - var param = {}; - if (serverType == ol.source.wms.ServerType.MAPSERVER) { - param['MAP_RESOLUTION'] = 90 * pixelRatio; - } else if (serverType == ol.source.wms.ServerType.GEOSERVER) { - param['FORMAT_OPTIONS'] = 'dpi:' + 90 * pixelRatio; - } else if (serverType == ol.source.wms.ServerType.QGIS) { - param['DPI'] = 90 * pixelRatio; - } else { - goog.asserts.fail(); - } - return param; -}; From bcf38b1b21fc388498680b296604a5a1128919e3 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Wed, 8 Jan 2014 22:04:25 +0100 Subject: [PATCH 07/14] Add ol.source.ImageWMS#setUrl --- src/ol/source/imagewmssource.exports | 1 + src/ol/source/imagewmssource.js | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/src/ol/source/imagewmssource.exports b/src/ol/source/imagewmssource.exports index afd33970c9..acb2495587 100644 --- a/src/ol/source/imagewmssource.exports +++ b/src/ol/source/imagewmssource.exports @@ -1,3 +1,4 @@ @exportSymbol ol.source.ImageWMS @exportProperty ol.source.ImageWMS.prototype.getParams +@exportProperty ol.source.ImageWMS.prototype.setUrl @exportProperty ol.source.ImageWMS.prototype.updateParams diff --git a/src/ol/source/imagewmssource.js b/src/ol/source/imagewmssource.js index 72b591e09a..6fd03abeb6 100644 --- a/src/ol/source/imagewmssource.js +++ b/src/ol/source/imagewmssource.js @@ -185,6 +185,18 @@ ol.source.ImageWMS.prototype.getImage = }; +/** + * @param {string|undefined} url URL. + */ +ol.source.ImageWMS.prototype.setUrl = function(url) { + if (url != this.url_) { + this.url_ = url; + this.image_ = null; + this.dispatchChangeEvent(); + } +}; + + /** * Update the user-provided params. * @param {Object} params Params. From 784f3500f29063aec02d755124e5f6012ae7b9c3 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Wed, 8 Jan 2014 23:07:10 +0100 Subject: [PATCH 08/14] Make ol.extent.buffer return an extent instead of mutating --- src/ol/extent.js | 26 +++++++++++++++++++------- src/ol/tileurlfunction.js | 2 +- test/spec/ol/extent.test.js | 3 +-- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/ol/extent.js b/src/ol/extent.js index 762d26a3d0..58046e2930 100644 --- a/src/ol/extent.js +++ b/src/ol/extent.js @@ -51,15 +51,27 @@ ol.extent.boundingExtentXYs_ = function(xs, ys, opt_extent) { /** - * Increase an extent by the provided value. - * @param {ol.Extent} extent The extent to buffer. + * Return extent increased by the provided value. + * @param {ol.Extent} extent Extent. * @param {number} value The amount by wich the extent should be buffered. + * @param {ol.Extent=} opt_extent Extent. + * @return {ol.Extent} Extent. */ -ol.extent.buffer = function(extent, value) { - extent[0] -= value; - extent[1] -= value; - extent[2] += value; - extent[3] += value; +ol.extent.buffer = function(extent, value, opt_extent) { + if (goog.isDef(opt_extent)) { + opt_extent[0] = extent[0] - value; + opt_extent[1] = extent[1] - value; + opt_extent[2] = extent[2] + value; + opt_extent[3] = extent[3] + value; + return opt_extent; + } else { + return [ + extent[0] - value, + extent[1] - value, + extent[2] + value, + extent[3] + value + ]; + } }; diff --git a/src/ol/tileurlfunction.js b/src/ol/tileurlfunction.js index d193383766..2e0c7a8d0b 100644 --- a/src/ol/tileurlfunction.js +++ b/src/ol/tileurlfunction.js @@ -114,7 +114,7 @@ ol.TileUrlFunction.createFromParamsFunction = tmpSize[0] = tileSize[0] + (2 * gutter); tmpSize[1] = tileSize[1] + (2 * gutter); var extent = tileGrid.getTileCoordExtent(tileCoord, tmpExtent); - ol.extent.buffer(extent, tileResolution * gutter); + ol.extent.buffer(extent, tileResolution * gutter, extent); return paramsFunction.call(this, baseUrl, params, extent, tmpSize, projection); } diff --git a/test/spec/ol/extent.test.js b/test/spec/ol/extent.test.js index 182491d9a6..7cfe5a541b 100644 --- a/test/spec/ol/extent.test.js +++ b/test/spec/ol/extent.test.js @@ -7,8 +7,7 @@ describe('ol.extent', function() { it('buffers an extent by some value', function() { var extent = [-10, -20, 10, 20]; - ol.extent.buffer(extent, 15); - expect(extent).to.eql([-25, -35, 25, 35]); + expect(ol.extent.buffer(extent, 15)).to.eql([-25, -35, 25, 35]); }); }); From 86f23aa615744f1adfd0cba3f948c9bae68a1e38 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Wed, 8 Jan 2014 23:12:43 +0100 Subject: [PATCH 09/14] Add ol.source.wms.DEFAULT_VERSION --- src/ol/source/imagewmssource.js | 3 ++- src/ol/source/wmssource.js | 8 +++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/ol/source/imagewmssource.js b/src/ol/source/imagewmssource.js index 6fd03abeb6..27883c4a8f 100644 --- a/src/ol/source/imagewmssource.js +++ b/src/ol/source/imagewmssource.js @@ -9,6 +9,7 @@ goog.require('goog.uri.utils'); goog.require('ol.Image'); goog.require('ol.extent'); goog.require('ol.source.Image'); +goog.require('ol.source.wms'); goog.require('ol.source.wms.ServerType'); @@ -107,7 +108,7 @@ ol.source.ImageWMS.prototype.getImage = var params = { 'SERVICE': 'WMS', - 'VERSION': '1.3.0', + 'VERSION': ol.source.wms.DEFAULT_VERSION, 'REQUEST': 'GetMap', 'FORMAT': 'image/png', 'TRANSPARENT': true diff --git a/src/ol/source/wmssource.js b/src/ol/source/wmssource.js index 8c13882557..52bc75600d 100644 --- a/src/ol/source/wmssource.js +++ b/src/ol/source/wmssource.js @@ -6,6 +6,12 @@ goog.require('goog.object'); goog.require('goog.uri.utils'); +/** + * @define {string} WMS default version. + */ +ol.source.wms.DEFAULT_VERSION = '1.3.0'; + + /** * @enum {string} */ @@ -27,7 +33,7 @@ ol.source.wms.ServerType = { ol.source.wms.getUrl = function(baseUrl, params, extent, size, projection) { var baseParams = { 'SERVICE': 'WMS', - 'VERSION': '1.3.0', + 'VERSION': ol.source.wms.DEFAULT_VERSION, 'REQUEST': 'GetMap', 'FORMAT': 'image/png', 'TRANSPARENT': true, From 46d8b816612fb1eef8be1ed0bd8780ee3cf07863 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Wed, 8 Jan 2014 23:20:41 +0100 Subject: [PATCH 10/14] Factor out WMS version 1.3 check --- src/ol/source/imagewmssource.js | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/src/ol/source/imagewmssource.js b/src/ol/source/imagewmssource.js index 27883c4a8f..481ec4eb87 100644 --- a/src/ol/source/imagewmssource.js +++ b/src/ol/source/imagewmssource.js @@ -1,5 +1,3 @@ -// FIXME factor out v13 calculation - goog.provide('ol.source.ImageWMS'); goog.require('goog.asserts'); @@ -44,6 +42,13 @@ ol.source.ImageWMS = function(opt_options) { */ this.params_ = options.params; + /** + * @private + * @type {boolean} + */ + this.v13_ = true; + this.updateV13_(); + /** * @private * @type {ol.source.wms.ServerType|undefined} @@ -115,10 +120,7 @@ ol.source.ImageWMS.prototype.getImage = }; goog.object.extend(params, this.params_); - var v13 = goog.string.compareVersions( - goog.object.get(params, 'VERSION'), '1.3') >= 0; - - params[v13 ? 'CRS' : 'SRS'] = projection.getCode(); + params[this.v13_ ? 'CRS' : 'SRS'] = projection.getCode(); if (!('STYLES' in this.params_)) { goog.object.set(params, 'STYLES', new String('')); @@ -170,7 +172,7 @@ ol.source.ImageWMS.prototype.getImage = var axisOrientation = projection.getAxisOrientation(); var bbox; - if (v13 && axisOrientation.substr(0, 2) == 'ne') { + if (this.v13_ && axisOrientation.substr(0, 2) == 'ne') { bbox = [extent[1], extent[0], extent[3], extent[2]]; } else { bbox = extent; @@ -204,6 +206,17 @@ ol.source.ImageWMS.prototype.setUrl = function(url) { */ ol.source.ImageWMS.prototype.updateParams = function(params) { goog.object.extend(this.params_, params); + this.updateV13_(); this.image_ = null; this.dispatchChangeEvent(); }; + + +/** + * @private + */ +ol.source.ImageWMS.prototype.updateV13_ = function() { + var version = + goog.object.get(this.params_, 'VERSION', ol.source.wms.DEFAULT_VERSION); + this.v13_ = goog.string.compareVersions(version, '1.3') >= 0; +}; From c5a5acbf893b1f32dc8c64f0642ecc10aef4cbc0 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Wed, 8 Jan 2014 23:28:06 +0100 Subject: [PATCH 11/14] Refactor ol.source.TileWMS URL logic --- src/ol/source/tilewmssource.js | 192 ++++++++++++++++++++++----------- 1 file changed, 129 insertions(+), 63 deletions(-) diff --git a/src/ol/source/tilewmssource.js b/src/ol/source/tilewmssource.js index 6eed73c25c..dfae79c94d 100644 --- a/src/ol/source/tilewmssource.js +++ b/src/ol/source/tilewmssource.js @@ -1,10 +1,13 @@ // FIXME add minZoom support +// FIXME add date line wrap (tile coord transform) goog.provide('ol.source.TileWMS'); goog.require('goog.array'); goog.require('goog.math'); goog.require('goog.object'); +goog.require('goog.string'); +goog.require('goog.uri.utils'); goog.require('ol.TileCoord'); goog.require('ol.TileUrlFunction'); goog.require('ol.extent'); @@ -16,22 +19,40 @@ goog.require('ol.source.wms'); /** * @constructor * @extends {ol.source.TileImage} - * @param {olx.source.TileWMSOptions} options Tile WMS options. + * @param {olx.source.TileWMSOptions=} opt_options Tile WMS options. * @todo stability experimental */ -ol.source.TileWMS = function(options) { +ol.source.TileWMS = function(opt_options) { - var tileGrid; - if (goog.isDef(options.tileGrid)) { - tileGrid = options.tileGrid; - } + var options = goog.isDef(opt_options) ? opt_options : {}; + + var params = goog.isDef(options.params) ? options.params : {}; + + var transparent = goog.object.get(params, 'TRANSPARENT', true); + + goog.base(this, { + attributions: options.attributions, + crossOrigin: options.crossOrigin, + extent: options.extent, + logo: options.logo, + opaque: !transparent, + projection: options.projection, + tileGrid: options.tileGrid, + tileLoadFunction: options.tileLoadFunction, + tileUrlFunction: goog.bind(this.tileUrlFunction_, this) + }); - var tileUrlFunction = ol.TileUrlFunction.nullTileUrlFunction; var urls = options.urls; if (!goog.isDef(urls) && goog.isDef(options.url)) { urls = ol.TileUrlFunction.expandUrl(options.url); } + /** + * @private + * @type {Array.|undefined} + */ + this.urls_ = urls; + /** * @private * @type {number} @@ -42,7 +63,13 @@ ol.source.TileWMS = function(options) { * @private * @type {Object} */ - this.params_ = options.params; + this.params_ = params; + + /** + * @private + * @type {boolean} + */ + this.v13_ = true; /** * @private @@ -51,62 +78,13 @@ ol.source.TileWMS = function(options) { this.coordKeyPrefix_ = ''; this.resetCoordKeyPrefix_(); - if (goog.isDef(urls)) { - var tileUrlFunctions = goog.array.map( - urls, function(url) { - return ol.TileUrlFunction.createFromParamsFunction( - url, this.params_, this.gutter_, ol.source.wms.getUrl); - }, this); - tileUrlFunction = ol.TileUrlFunction.createFromTileUrlFunctions( - tileUrlFunctions); - } + /** + * @private + * @type {ol.Extent} + */ + this.tmpExtent_ = ol.extent.createEmpty(); - var transparent = goog.isDef(options.params['TRANSPARENT']) ? - options.params['TRANSPARENT'] : true; - var extent = options.extent; - - var tileCoordTransform = function(tileCoord, projection) { - var tileGrid = this.getTileGrid(); - if (goog.isNull(tileGrid)) { - tileGrid = ol.tilegrid.getForProjection(projection); - } - if (tileGrid.getResolutions().length <= tileCoord.z) { - return null; - } - var x = tileCoord.x; - var tileExtent = tileGrid.getTileCoordExtent(tileCoord); - var projectionExtent = projection.getExtent(); - extent = goog.isDef(extent) ? extent : projectionExtent; - - if (!goog.isNull(extent) && projection.isGlobal() && - extent[0] === projectionExtent[0] && - extent[2] === projectionExtent[2]) { - var numCols = Math.ceil( - (extent[2] - extent[0]) / - (tileExtent[2] - tileExtent[0])); - x = goog.math.modulo(x, numCols); - tileExtent = tileGrid.getTileCoordExtent( - new ol.TileCoord(tileCoord.z, x, tileCoord.y)); - } - if (!goog.isNull(extent) && (!ol.extent.intersects(tileExtent, extent) || - ol.extent.touches(tileExtent, extent))) { - return null; - } - return new ol.TileCoord(tileCoord.z, x, tileCoord.y); - }; - - goog.base(this, { - attributions: options.attributions, - crossOrigin: options.crossOrigin, - extent: extent, - logo: options.logo, - tileGrid: options.tileGrid, - opaque: !transparent, - projection: options.projection, - tileLoadFunction: options.tileLoadFunction, - tileUrlFunction: ol.TileUrlFunction.withTileCoordTransform( - tileCoordTransform, tileUrlFunction) - }); + this.updateV13_(); }; goog.inherits(ol.source.TileWMS, ol.source.TileImage); @@ -152,6 +130,83 @@ ol.source.TileWMS.prototype.resetCoordKeyPrefix_ = function() { }; +/** + * @param {ol.TileCoord} tileCoord Tile coordinate. + * @param {ol.proj.Projection} projection Projection. + * @private + * @return {string|undefined} Tile URL. + */ +ol.source.TileWMS.prototype.tileUrlFunction_ = function(tileCoord, projection) { + + var urls = this.urls_; + if (!goog.isDef(urls) || goog.array.isEmpty(urls)) { + return undefined; + } + + var tileGrid = this.getTileGrid(); + if (goog.isNull(tileGrid)) { + tileGrid = ol.tilegrid.getForProjection(projection); + } + + if (tileGrid.getResolutions().length <= tileCoord.z) { + return undefined; + } + + var tileExtent = tileGrid.getTileCoordExtent(tileCoord); + + var params = { + 'SERVICE': 'WMS', + 'VERSION': ol.source.wms.DEFAULT_VERSION, + 'REQUEST': 'GetMap', + 'FORMAT': 'image/png', + 'TRANSPARENT': true + }; + goog.object.extend(params, this.params_); + + var tileResolution = tileGrid.getResolution(tileCoord.z); + var tileSize = tileGrid.getTileSize(tileCoord.z); + var gutter = this.gutter_; + if (gutter === 0) { + goog.object.set(params, 'WIDTH', tileSize[0]); + goog.object.set(params, 'HEIGHT', tileSize[1]); + } else { + goog.object.set(params, 'WIDTH', tileSize[0] + 2 * gutter); + goog.object.set(params, 'HEIGHT', tileSize[1] + 2 * gutter); + tileExtent = + ol.extent.buffer(tileExtent, tileResolution * gutter, this.tmpExtent_); + } + + params[this.v13_ ? 'CRS' : 'SRS'] = projection.getCode(); + + if (!('STYLES' in this.params_)) { + goog.object.set(params, 'STYLES', new String('')); + } + + var axisOrientation = projection.getAxisOrientation(); + var bbox; + if (this.v13_ && axisOrientation.substr(0, 2) == 'ne') { + bbox = this.tmpExtent_; + bbox[0] = tileExtent[1]; + bbox[1] = tileExtent[0]; + bbox[2] = tileExtent[3]; + bbox[3] = tileExtent[2]; + } else { + bbox = tileExtent; + } + goog.object.set(params, 'BBOX', bbox.join(',')); + + var url; + if (urls.length == 1) { + url = urls[0]; + } else { + var index = goog.math.modulo(tileCoord.hash(), this.urls_.length); + url = urls[index]; + } + return goog.uri.utils.appendParamsFromMap(url, params); + +}; + + /** * Update the user-provided params. * @param {Object} params Params. @@ -160,5 +215,16 @@ ol.source.TileWMS.prototype.resetCoordKeyPrefix_ = function() { ol.source.TileWMS.prototype.updateParams = function(params) { goog.object.extend(this.params_, params); this.resetCoordKeyPrefix_(); + this.updateV13_(); this.dispatchChangeEvent(); }; + + +/** + * @private + */ +ol.source.TileWMS.prototype.updateV13_ = function() { + var version = + goog.object.get(this.params_, 'VERSION', ol.source.wms.DEFAULT_VERSION); + this.v13_ = goog.string.compareVersions(version, '1.3') >= 0; +}; From cee014ec9e21cb0e38e2f1ba3cd16c24b4712166 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Wed, 8 Jan 2014 23:28:36 +0100 Subject: [PATCH 12/14] Remove unused ol.source.wms.getUrl function --- src/ol/source/wmssource.js | 41 --------------------------- test/spec/ol/source/wmssource.test.js | 33 --------------------- 2 files changed, 74 deletions(-) delete mode 100644 test/spec/ol/source/wmssource.test.js diff --git a/src/ol/source/wmssource.js b/src/ol/source/wmssource.js index 52bc75600d..591cd2d951 100644 --- a/src/ol/source/wmssource.js +++ b/src/ol/source/wmssource.js @@ -1,10 +1,6 @@ goog.provide('ol.source.wms'); goog.provide('ol.source.wms.ServerType'); -goog.require('goog.asserts'); -goog.require('goog.object'); -goog.require('goog.uri.utils'); - /** * @define {string} WMS default version. @@ -20,40 +16,3 @@ ol.source.wms.ServerType = { MAPSERVER: 'mapserver', QGIS: 'qgis' }; - - -/** - * @param {string} baseUrl WMS base URL. - * @param {Object.} params Request parameters. - * @param {ol.Extent} extent Extent. - * @param {ol.Size} size Size. - * @param {ol.proj.Projection} projection Projection. - * @return {string} WMS GetMap request URL. - */ -ol.source.wms.getUrl = function(baseUrl, params, extent, size, projection) { - var baseParams = { - 'SERVICE': 'WMS', - 'VERSION': ol.source.wms.DEFAULT_VERSION, - 'REQUEST': 'GetMap', - 'FORMAT': 'image/png', - 'TRANSPARENT': true, - 'WIDTH': Math.round(size[0]), - 'HEIGHT': Math.round(size[1]) - }; - goog.object.extend(baseParams, params); - - //TODO: Provide our own appendParams function to avoid this empty string hack - var stylesParam = 'STYLES'; - baseParams[stylesParam] = params[stylesParam] || new String(''); - - var wms13 = baseParams['VERSION'] > '1.3'; - baseParams[wms13 ? 'CRS' : 'SRS'] = projection.getCode(); - - var axisOrientation = projection.getAxisOrientation(); - var bboxValues = (wms13 && axisOrientation.substr(0, 2) == 'ne') ? - [extent[1], extent[0], extent[3], extent[2]] : - [extent[0], extent[1], extent[2], extent[3]]; - baseParams['BBOX'] = bboxValues.join(','); - - return goog.uri.utils.appendParamsFromMap(baseUrl, baseParams); -}; diff --git a/test/spec/ol/source/wmssource.test.js b/test/spec/ol/source/wmssource.test.js deleted file mode 100644 index 665c4baf2f..0000000000 --- a/test/spec/ol/source/wmssource.test.js +++ /dev/null @@ -1,33 +0,0 @@ -goog.provide('ol.test.source.wms'); - -describe('ol.source.wms', function() { - - describe('ol.source.wms.getUrl', function() { - it('creates expected URL', function() { - var epsg3857 = ol.proj.get('EPSG:3857'); - var extent = [-20037508.342789244, -20037508.342789244, 0, 0]; - var expected = 'http://wms?SERVICE=WMS&VERSION=1.3.0&REQUEST=' + - 'GetMap&FORMAT=image%2Fpng&TRANSPARENT=true&WIDTH=256&HEIGHT=256&' + - 'foo=bar&STYLES=&CRS=EPSG%3A3857&BBOX=' + - '-20037508.342789244%2C-20037508.342789244%2C0%2C0'; - var url = ol.source.wms.getUrl('http://wms', {'foo': 'bar'}, - extent, [256, 256], epsg3857); - expect(url).to.eql(expected); - }); - it('creates expected URL respecting axis orientation', function() { - var epsg4326 = ol.proj.get('EPSG:4326'); - var extent = [-180, -90, 0, 90]; - var expected = 'http://wms?SERVICE=WMS&VERSION=1.3.0&REQUEST=' + - 'GetMap&FORMAT=image%2Fpng&TRANSPARENT=true&WIDTH=256&HEIGHT=256&' + - 'foo=bar&STYLES=&CRS=EPSG%3A4326&BBOX=-90%2C-180%2C90%2C0'; - var url = ol.source.wms.getUrl('http://wms', {'foo': 'bar'}, - extent, [256, 256], epsg4326); - expect(url).to.eql(expected); - }); - }); - -}); - - -goog.require('ol.proj'); -goog.require('ol.source.wms'); From 807bf757afb1bd0c0682c6196f6bd17f2eb78fd1 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Wed, 8 Jan 2014 23:37:32 +0100 Subject: [PATCH 13/14] Remove unused ol.TileUrlFunction.createFromParamsFunction --- src/ol/tileurlfunction.js | 41 ---------------------------- test/spec/ol/tileurlfunction.test.js | 19 ------------- 2 files changed, 60 deletions(-) diff --git a/src/ol/tileurlfunction.js b/src/ol/tileurlfunction.js index 2e0c7a8d0b..8b8e17620b 100644 --- a/src/ol/tileurlfunction.js +++ b/src/ol/tileurlfunction.js @@ -4,7 +4,6 @@ goog.provide('ol.TileUrlFunctionType'); goog.require('goog.array'); goog.require('goog.math'); goog.require('ol.TileCoord'); -goog.require('ol.extent'); /** @@ -82,46 +81,6 @@ ol.TileUrlFunction.createFromTileUrlFunctions = function(tileUrlFunctions) { }; -/** - * @param {string} baseUrl Base URL (may have query data). - * @param {Object.} params Params to encode in the URL. - * @param {number} gutter Gutter value. - * @param {function(this: ol.source.TileImage, string, Object., - * ol.Extent, ol.Size, ol.proj.Projection)} paramsFunction params function. - * @return {ol.TileUrlFunctionType} Tile URL function. - */ -ol.TileUrlFunction.createFromParamsFunction = - function(baseUrl, params, gutter, paramsFunction) { - var tmpExtent = ol.extent.createEmpty(); - var tmpSize = [0, 0]; - return ( - /** - * @this {ol.source.TileImage} - * @param {ol.TileCoord} tileCoord Tile Coordinate. - * @param {ol.proj.Projection} projection Projection. - * @return {string|undefined} Tile URL. - */ - function(tileCoord, projection) { - if (goog.isNull(tileCoord)) { - return undefined; - } else { - var tileGrid = this.getTileGrid(); - if (goog.isNull(tileGrid)) { - tileGrid = ol.tilegrid.getForProjection(projection); - } - var tileResolution = tileGrid.getResolution(tileCoord.z); - var tileSize = tileGrid.getTileSize(tileCoord.z); - tmpSize[0] = tileSize[0] + (2 * gutter); - tmpSize[1] = tileSize[1] + (2 * gutter); - var extent = tileGrid.getTileCoordExtent(tileCoord, tmpExtent); - ol.extent.buffer(extent, tileResolution * gutter, extent); - return paramsFunction.call(this, baseUrl, params, - extent, tmpSize, projection); - } - }); -}; - - /** * @this {ol.source.TileImage} * @param {ol.TileCoord} tileCoord Tile coordinate. diff --git a/test/spec/ol/tileurlfunction.test.js b/test/spec/ol/tileurlfunction.test.js index 6c0e5bcbdd..23b32e9628 100644 --- a/test/spec/ol/tileurlfunction.test.js +++ b/test/spec/ol/tileurlfunction.test.js @@ -78,26 +78,7 @@ describe('ol.TileUrlFunction', function() { }); }); - describe('createFromParamsFunction', function() { - var paramsFunction = function(url, params) { return arguments; }; - var projection = ol.proj.get('EPSG:3857'); - var fakeTileSource = {getTileGrid: function() {return null;}}; - var params = {foo: 'bar'}; - var tileUrlFunction = ol.TileUrlFunction.createFromParamsFunction( - 'url', params, 0, paramsFunction); - it('calls the passed function with the correct arguments', function() { - var args = tileUrlFunction.call(fakeTileSource, - new ol.TileCoord(0, 0, 0), projection); - expect(args[0]).to.eql('url'); - expect(args[1]).to.be(params); - expect(args[2]).to.eql(projection.getExtent()); - expect(args[3]).to.eql([256, 256]); - expect(args[4]).to.eql(projection); - }); - }); - }); goog.require('ol.TileCoord'); goog.require('ol.TileUrlFunction'); -goog.require('ol.proj'); From 04a0369d6872715c3a69c6d0462caef53287f800 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Wed, 8 Jan 2014 23:30:14 +0100 Subject: [PATCH 14/14] Correct ol.renderer.canvas.ImageLayer transform for HiDPI devices --- .../renderer/canvas/canvasimagelayerrenderer.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/ol/renderer/canvas/canvasimagelayerrenderer.js b/src/ol/renderer/canvas/canvasimagelayerrenderer.js index 69a41c6eb5..3c653df019 100644 --- a/src/ol/renderer/canvas/canvasimagelayerrenderer.js +++ b/src/ol/renderer/canvas/canvasimagelayerrenderer.js @@ -64,6 +64,7 @@ ol.renderer.canvas.ImageLayer.prototype.getImageTransform = function() { ol.renderer.canvas.ImageLayer.prototype.prepareFrame = function(frameState, layerState) { + var devicePixelRatio = frameState.devicePixelRatio; var view2DState = frameState.view2DState; var viewCenter = view2DState.center; var viewResolution = view2DState.resolution; @@ -79,7 +80,7 @@ ol.renderer.canvas.ImageLayer.prototype.prepareFrame = if (!hints[ol.ViewHint.ANIMATING] && !hints[ol.ViewHint.INTERACTING]) { image = imageSource.getImage(frameState.extent, viewResolution, - frameState.devicePixelRatio, view2DState.projection); + devicePixelRatio, view2DState.projection); if (!goog.isNull(image)) { var imageState = image.getState(); if (imageState == ol.ImageState.IDLE) { @@ -95,16 +96,17 @@ ol.renderer.canvas.ImageLayer.prototype.prepareFrame = if (!goog.isNull(this.image_)) { image = this.image_; var imageExtent = image.getExtent(); - var imageResolution = image.getResolution() / image.getPixelRatio(); - var devicePixelRatio = frameState.devicePixelRatio; + var imageResolution = image.getResolution(); + var imagePixelRatio = image.getPixelRatio(); + var scale = devicePixelRatio * imageResolution / + (viewResolution * imagePixelRatio); ol.vec.Mat4.makeTransform2D(this.imageTransform_, devicePixelRatio * frameState.size[0] / 2, devicePixelRatio * frameState.size[1] / 2, - devicePixelRatio * imageResolution / viewResolution, - devicePixelRatio * imageResolution / viewResolution, + scale, scale, viewRotation, - (imageExtent[0] - viewCenter[0]) / imageResolution, - (viewCenter[1] - imageExtent[3]) / imageResolution); + imagePixelRatio * (imageExtent[0] - viewCenter[0]) / imageResolution, + imagePixelRatio * (viewCenter[1] - imageExtent[3]) / imageResolution); this.updateAttributions(frameState.attributions, image.getAttributions()); this.updateLogos(frameState, imageSource); }