From ed622035274e65476e57aea10f9cf327347c9bbf Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Thu, 25 Feb 2016 18:04:39 +0100 Subject: [PATCH 1/4] Merge pull request #4921 from ahocevar/unlisten-earlier-and-bind-to-target Unlisten before calling listener and bind to target by default --- src/ol/events.js | 5 +++-- test/spec/ol/events.test.js | 33 +++++++++++++++++++++------------ 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/ol/events.js b/src/ol/events.js index c07373bd30..2035441864 100644 --- a/src/ol/events.js +++ b/src/ol/events.js @@ -107,11 +107,12 @@ ol.events.ListenerObjType; */ ol.events.bindListener_ = function(listenerObj) { var boundListener = function(evt) { - var rv = listenerObj.listener.call(listenerObj.bindTo, evt); + var listener = listenerObj.listener; + var bindTo = listenerObj.bindTo || listenerObj.target; if (listenerObj.callOnce) { ol.events.unlistenByKey(listenerObj); } - return rv; + return listener.call(bindTo, evt); } listenerObj.boundListener = boundListener; return boundListener; diff --git a/test/spec/ol/events.test.js b/test/spec/ol/events.test.js index 6592bdcb3d..6a9f79dd4c 100644 --- a/test/spec/ol/events.test.js +++ b/test/spec/ol/events.test.js @@ -24,23 +24,32 @@ describe('ol.events', function() { boundListener(); expect(listenerObj.listener.thisValues[0]).to.equal(listenerObj.bindTo); }); - it('binds a self-unregistering listener when callOnce is true', function() { - var bindTo = {id: 1}; - var listener = sinon.spy(); - target.removeEventListener = function() {}; + it('binds to the target when bindTo is not provided', function() { var listenerObj = { - type: 'foo', - target: target, - listener: listener, - bindTo: bindTo, - callOnce: true + listener: sinon.spy(), + target: {id: 1} }; var boundListener = ol.events.bindListener_(listenerObj); expect(listenerObj.boundListener).to.equal(boundListener); - var spy = sinon.spy(ol.events, 'unlistenByKey'); boundListener(); - expect(listener.thisValues[0]).to.equal(bindTo); - expect(spy.firstCall.args[0]).to.eql(listenerObj); + expect(listenerObj.listener.thisValues[0]).to.equal(listenerObj.target); + }); + it('binds a self-unregistering listener when callOnce is true', function() { + var bindTo = {id: 1}; + var listenerObj = { + type: 'foo', + target: target, + bindTo: bindTo, + callOnce: true + }; + var unlistenSpy = sinon.spy(ol.events, 'unlistenByKey'); + listenerObj.listener = function() { + expect(this).to.equal(bindTo); + expect(unlistenSpy.firstCall.args[0]).to.eql(listenerObj); + } + var boundListener = ol.events.bindListener_(listenerObj); + expect(listenerObj.boundListener).to.equal(boundListener); + boundListener(); ol.events.unlistenByKey.restore(); }); }); From 4b586df2b56a4826d5cbb9b3b5e0f59a485d8617 Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Tue, 1 Mar 2016 09:43:24 +0100 Subject: [PATCH 2/4] Merge pull request #4939 from ahocevar/clip-opacity Fix rendering of opaque layers with opacity != 1 --- .../canvas/canvastilelayerrenderer.js | 96 +++++++++---------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/src/ol/renderer/canvas/canvastilelayerrenderer.js b/src/ol/renderer/canvas/canvastilelayerrenderer.js index 0d3bdd4df1..14c7910ab3 100644 --- a/src/ol/renderer/canvas/canvastilelayerrenderer.js +++ b/src/ol/renderer/canvas/canvastilelayerrenderer.js @@ -9,6 +9,7 @@ goog.require('ol.array'); goog.require('ol.dom'); goog.require('ol.extent'); goog.require('ol.layer.Tile'); +goog.require('ol.object'); goog.require('ol.render.EventType'); goog.require('ol.renderer.canvas.Layer'); goog.require('ol.source.Tile'); @@ -25,9 +26,9 @@ ol.renderer.canvas.TileLayer = function(tileLayer) { /** * @private - * @type {Object.>} + * @type {!Object.>} */ - this.clipExtents_ = null; + this.clipTileCoords_ = {}; /** * @private @@ -68,7 +69,6 @@ ol.renderer.canvas.TileLayer.prototype.composeFrame = function( goog.asserts.assertInstanceof(source, ol.source.Tile, 'source is an ol.source.Tile'); var tileGutter = source.getGutter(projection); - var opaque = source.getOpaque(projection); var transform = this.getTransform(frameState, 0); @@ -95,60 +95,60 @@ ol.renderer.canvas.TileLayer.prototype.composeFrame = function( var tileGrid = source.getTileGridForProjection(projection); var tilesToDraw = this.renderedTiles_; - var clipExtents, clipExtent, currentZ, i, ii, j, jj, insertPoint; - var origin, tile, tileExtent, tileHeight, tileOffsetX, tileOffsetY; - var tilePixelSize, tileWidth; + var clipExtent, clipH, clipLeft, clipOrigin, clipTileCoord, clipTileCoords; + var clipTop, clipW, currentZ, h, i, ii, j, jj, left, origin, tile, tileExtent; + var tilePixelSize, top, w; for (i = 0, ii = tilesToDraw.length; i < ii; ++i) { tile = tilesToDraw[i]; tileExtent = tileGrid.getTileCoordExtent( tile.getTileCoord(), this.tmpExtent_); - clipExtents = !opaque && this.clipExtents_[tile.tileCoord.toString()]; - if (clipExtents) { + currentZ = tile.getTileCoord()[0]; + // Calculate all insert points by tile widths from a common origin to avoid + // gaps caused by rounding + origin = ol.extent.getBottomLeft(tileGrid.getTileCoordExtent( + tileGrid.getTileCoordForCoordAndZ(center, currentZ))); + w = Math.round(ol.extent.getWidth(tileExtent) * pixelScale); + h = Math.round(ol.extent.getHeight(tileExtent) * pixelScale); + left = Math.round((tileExtent[0] - origin[0]) * pixelScale / w) * w + + offsetX + Math.round((origin[0] - center[0]) * pixelScale); + top = Math.round((origin[1] - tileExtent[3]) * pixelScale / h) * h + + offsetY + Math.round((center[1] - origin[1]) * pixelScale); + clipTileCoords = this.clipTileCoords_[tile.tileCoord.toString()]; + if (clipTileCoords) { // Create a clip mask for regions in this low resolution tile that will be // filled by a higher resolution tile renderContext.save(); renderContext.beginPath(); - renderContext.moveTo((tileExtent[0] - center[0]) * pixelScale + offsetX, - (center[1] - tileExtent[1]) * pixelScale + offsetY); - renderContext.lineTo((tileExtent[2] - center[0]) * pixelScale + offsetX, - (center[1] - tileExtent[1]) * pixelScale + offsetY); - renderContext.lineTo((tileExtent[2] - center[0]) * pixelScale + offsetX, - (center[1] - tileExtent[3]) * pixelScale + offsetY); - renderContext.lineTo((tileExtent[0] - center[0]) * pixelScale + offsetX, - (center[1] - tileExtent[3]) * pixelScale + offsetY); + // counter-clockwise (outer ring) for current tile + renderContext.moveTo(left + w, top); + renderContext.lineTo(left, top); + renderContext.lineTo(left, top + h); + renderContext.lineTo(left + w, top + h); renderContext.closePath(); - for (j = 0, jj = clipExtents.length; j < jj; ++j) { - clipExtent = clipExtents[j]; - renderContext.moveTo((clipExtent[0] - center[0]) * pixelScale + offsetX, - (center[1] - clipExtent[1]) * pixelScale + offsetY); - renderContext.lineTo((clipExtent[0] - center[0]) * pixelScale + offsetX, - (center[1] - clipExtent[3]) * pixelScale + offsetY); - renderContext.lineTo((clipExtent[2] - center[0]) * pixelScale + offsetX, - (center[1] - clipExtent[3]) * pixelScale + offsetY); - renderContext.lineTo((clipExtent[2] - center[0]) * pixelScale + offsetX, - (center[1] - clipExtent[1]) * pixelScale + offsetY); + // clockwise (inner rings) for lower resolution tiles + for (j = 0, jj = clipTileCoords.length; j < jj; ++j) { + clipTileCoord = clipTileCoords[j]; + clipExtent = tileGrid.getTileCoordExtent(clipTileCoord); + clipOrigin = ol.extent.getBottomLeft(tileGrid.getTileCoordExtent( + tileGrid.getTileCoordForCoordAndZ(center, clipTileCoord[0]))); + clipW = Math.round(ol.extent.getWidth(clipExtent) * pixelScale); + clipH = Math.round(ol.extent.getHeight(clipExtent) * pixelScale); + clipLeft = Math.round((clipExtent[0] - clipOrigin[0]) * pixelScale / clipW) * clipW + + offsetX + Math.round((clipOrigin[0] - center[0]) * pixelScale); + clipTop = Math.round((clipOrigin[1] - clipExtent[3]) * pixelScale / clipH) * clipH + + offsetY + Math.round((center[1] - clipOrigin[1]) * pixelScale); + renderContext.moveTo(clipLeft, clipTop + clipH); + renderContext.lineTo(clipLeft, clipTop); + renderContext.lineTo(clipLeft + clipW, clipTop); + renderContext.lineTo(clipLeft + clipW, clipTop + clipH); renderContext.closePath(); } renderContext.clip(); } - currentZ = tile.getTileCoord()[0]; tilePixelSize = source.getTilePixelSize(currentZ, pixelRatio, projection); - insertPoint = ol.extent.getTopLeft(tileExtent); - tileWidth = Math.round(ol.extent.getWidth(tileExtent) * pixelScale); - tileHeight = Math.round(ol.extent.getHeight(tileExtent) * pixelScale); - // Calculate all insert points from a common origin and tile widths to avoid - // gaps caused by rounding - origin = ol.extent.getBottomLeft(tileGrid.getTileCoordExtent( - tileGrid.getTileCoordForCoordAndZ(center, currentZ))); - tileOffsetX = offsetX + Math.round((origin[0] - center[0]) * pixelScale); - tileOffsetY = offsetY + Math.round((center[1] - origin[1]) * pixelScale); renderContext.drawImage(tile.getImage(), tileGutter, tileGutter, - tilePixelSize[0], tilePixelSize[1], - Math.round((insertPoint[0] - origin[0]) * pixelScale / tileWidth) * - tileWidth + tileOffsetX, - Math.round((origin[1] - insertPoint[1]) * pixelScale / tileHeight) * - tileHeight + tileOffsetY, tileWidth, tileHeight); - if (clipExtents) { + tilePixelSize[0], tilePixelSize[1], left, top, w, h); + if (clipTileCoords) { renderContext.restore(); } } @@ -266,8 +266,9 @@ ol.renderer.canvas.TileLayer.prototype.prepareFrame = function( } } this.renderedTiles_ = renderables; - if (!tileSource.getOpaque(projection)) { - var clipExtents = {}; + ol.object.clear(this.clipTileCoords_); + if (!(tileSource.getOpaque(projection) && layerState.opacity == 1)) { + var clipTileCoords = this.clipTileCoords_; var tileCoord; for (i = renderables.length - 1; i >= 0; --i) { tileCoord = renderables[i].getTileCoord(); @@ -280,10 +281,10 @@ ol.renderer.canvas.TileLayer.prototype.prepareFrame = function( tile = tiles[key]; if (tileRange.contains(tile.getTileCoord()) && tile.getState() == ol.TileState.LOADED) { - if (!(key in clipExtents)) { - clipExtents[key] = []; + if (!(key in clipTileCoords)) { + clipTileCoords[key] = []; } - clipExtents[key].push(tileGrid.getTileCoordExtent(tileCoord)); + clipTileCoords[key].push(tileCoord); return true; } } @@ -291,7 +292,6 @@ ol.renderer.canvas.TileLayer.prototype.prepareFrame = function( return false; }, this, tmpTileRange, tmpExtent); } - this.clipExtents_ = clipExtents; } this.updateUsedTiles(frameState.usedTiles, tileSource, z, tileRange); From 7478e82b9aa551ffedca7985eade3d8871176f00 Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Tue, 1 Mar 2016 10:10:06 +0100 Subject: [PATCH 3/4] Changelog for v3.14.1 --- changelog/v3.14.1.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 changelog/v3.14.1.md diff --git a/changelog/v3.14.1.md b/changelog/v3.14.1.md new file mode 100644 index 0000000000..bee79c34ea --- /dev/null +++ b/changelog/v3.14.1.md @@ -0,0 +1,10 @@ +# v3.14.1 + +## Summary + +The v3.14.1 release is a patch release that addresses a few regressions in the v3.14.0 release. See the [v3.14.0 release notes](https://github.com/openlayers/ol3/releases/tag/v3.14.0) for details on upgrading from v3.13.x. + +## Fixes + +* [#4939](https://github.com/openlayers/ol3/pull/4939) - Fix rendering of opaque layers with opacity != 1 ([@ahocevar](https://github.com/ahocevar)) + * [#4921](https://github.com/openlayers/ol3/pull/4921) - Unlisten before calling listener and bind to target by default ([@ahocevar](https://github.com/ahocevar)) From b4c4a81afb69f6c8fa72ed0fdb8b78ea15020695 Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Tue, 1 Mar 2016 10:10:41 +0100 Subject: [PATCH 4/4] Update package version to 3.14.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2f511bd1c0..58daf8a907 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "openlayers", - "version": "3.14.0", + "version": "3.14.1", "description": "Build tools and sources for developing OpenLayers based mapping applications", "keywords": [ "map",