diff --git a/src/ol/renderer/canvas/ImageLayer.js b/src/ol/renderer/canvas/ImageLayer.js index 266d36bed5..435d55a6a0 100644 --- a/src/ol/renderer/canvas/ImageLayer.js +++ b/src/ol/renderer/canvas/ImageLayer.js @@ -187,10 +187,10 @@ class CanvasImageLayerRenderer extends CanvasLayerRenderer { const opacity = layerState.opacity; let previousAlpha; if (opacity !== 1) { - previousAlpha = this.context.globalAlpha; - this.context.globalAlpha = opacity; + previousAlpha = context.globalAlpha; + context.globalAlpha = opacity; } - this.context.drawImage( + context.drawImage( img, 0, 0, @@ -202,7 +202,7 @@ class CanvasImageLayerRenderer extends CanvasLayerRenderer { Math.round(dh) ); if (opacity !== 1) { - this.context.globalAlpha = previousAlpha; + context.globalAlpha = previousAlpha; } } this.postRender(context, frameState); diff --git a/test/browser/spec/ol/renderer/canvas/imagelayer.test.js b/test/browser/spec/ol/renderer/canvas/imagelayer.test.js index 4b2c092c0b..71b34aa9f3 100644 --- a/test/browser/spec/ol/renderer/canvas/imagelayer.test.js +++ b/test/browser/spec/ol/renderer/canvas/imagelayer.test.js @@ -1,3 +1,4 @@ +import CanvasImageLayerRenderer from '../../../../../../src/ol/renderer/canvas/ImageLayer.js'; import Feature from '../../../../../../src/ol/Feature.js'; import ImageLayer from '../../../../../../src/ol/layer/Image.js'; import Map from '../../../../../../src/ol/Map.js'; @@ -348,4 +349,90 @@ describe('ol.renderer.canvas.ImageLayer', function () { }); }); }); + describe('renderFrame', function () { + const projection = new Projection({ + code: 'custom-image', + units: 'pixels', + extent: [0, 0, 256, 256], + }); + let renderer, layer; + function createLayerFrameState(extent) { + layer = new ImageLayer({ + source: new Static({ + url: 'spec/ol/data/osm-0-0-0.png', + imageExtent: projection.getExtent(), + projection: projection, + }), + extent: extent, + }); + layer.getSource().image_.load(); + renderer = layer.getRenderer(); + renderer.renderWorlds = sinon.spy(); + renderer.clipUnrotated = sinon.spy(); + renderer.useContainer = function () { + CanvasImageLayerRenderer.prototype.useContainer.apply(this, arguments); + this.context = sinon.spy(this.context); + }; + return { + pixelRatio: 1, + time: 1000000000000, + viewState: { + center: [0, 0], + projection: projection, + resolution: 1, + rotation: 0, + }, + animate: false, + coordinateToPixelTransform: [1, 0, 0, 1, 0, 0], + extent: [0, 0, 100, 100], + index: 0, + layerStatesArray: [layer.getLayerState()], + layerIndex: 0, + pixelToCoordinateTransform: [1, 0, 0, 1, 0, 0], + size: [100, 100], + viewHints: [], + }; + } + it('does not render if layer extent does not intersect view extent', function (done) { + const frameState = createLayerFrameState([200, 200, 300, 300]); + layer.getSource().on('imageloadend', function () { + try { + expect(renderer.prepareFrame(frameState)).to.be(false); + done(); + } catch (e) { + done(e); + } + }); + }); + it('renders if layer extent partially intersects view extent', function (done) { + const frameState = createLayerFrameState([50, 50, 150, 150]); + layer.getSource().on('imageloadend', function () { + if (renderer.prepareFrame(frameState)) { + renderer.renderFrame(frameState, null); + } + try { + expect(renderer.clipUnrotated.callCount).to.be(1); + expect(renderer.context.drawImage.callCount).to.be(1); + done(); + } catch (e) { + done(e); + } + }); + }); + it('renders without clipping when layer extent covers view', function (done) { + const frameState = createLayerFrameState([0, 0, 100, 100]); + layer.getSource().on('imageloadend', function () { + if (renderer.prepareFrame(frameState)) { + renderer.renderFrame(frameState, null); + } + try { + expect(renderer.clipUnrotated.callCount).to.be(0); + expect(renderer.context.drawImage.callCount).to.be(1); + done(); + } catch (e) { + done(e); + } + }); + }); + }); }); diff --git a/test/browser/spec/ol/renderer/canvas/vectorlayer.test.js b/test/browser/spec/ol/renderer/canvas/vectorlayer.test.js index 37a548cc9e..3100001f82 100644 --- a/test/browser/spec/ol/renderer/canvas/vectorlayer.test.js +++ b/test/browser/spec/ol/renderer/canvas/vectorlayer.test.js @@ -699,4 +699,62 @@ describe('ol.renderer.canvas.VectorLayer', function () { } }); }); + describe('renderFrame', function () { + const projection = getProjection('EPSG:3857'); + let renderer; + function createLayerFrameState(extent) { + const layer = new VectorLayer({ + source: new VectorSource({ + features: [new Feature(new Point(getCenter(extent)))], + }), + extent: extent, + }); + renderer = layer.getRenderer(); + renderer.renderWorlds = sinon.spy(); + renderer.clipUnrotated = sinon.spy(); + return { + pixelRatio: 1, + time: 1000000000000, + viewState: { + center: [0, 0], + projection: projection, + resolution: 1, + rotation: 0, + }, + animate: false, + coordinateToPixelTransform: [1, 0, 0, 1, 0, 0], + extent: [-50, -50, 50, 50], + index: 0, + layerStatesArray: [layer.getLayerState()], + layerIndex: 0, + pixelToCoordinateTransform: [1, 0, 0, 1, 0, 0], + size: [100, 100], + viewHints: [], + }; + } + it('does not render if layer extent does not intersect view extent', function () { + const frameState = createLayerFrameState([100, 100, 200, 200]); + if (renderer.prepareFrame(frameState)) { + renderer.renderFrame(frameState, null); + } + expect(renderer.renderWorlds.callCount).to.be(0); + expect(renderer.clipUnrotated.callCount).to.be(0); + }); + it('renders if layer extent partially intersects view extent', function () { + const frameState = createLayerFrameState([0, 0, 100, 100]); + if (renderer.prepareFrame(frameState)) { + renderer.renderFrame(frameState, null); + } + expect(renderer.renderWorlds.callCount).to.be(1); + expect(renderer.clipUnrotated.callCount).to.be(1); + }); + it('renders withoutt clipping when layer extent covers view', function () { + const frameState = createLayerFrameState([-200, -200, 200, 200]); + if (renderer.prepareFrame(frameState)) { + renderer.renderFrame(frameState, null); + } + expect(renderer.renderWorlds.callCount).to.be(1); + expect(renderer.clipUnrotated.callCount).to.be(0); + }); + }); });