From 81d0bc21d513e0f8393c66bb3c0c269ecba0225e Mon Sep 17 00:00:00 2001 From: Guillaume Beraudo Date: Fri, 16 Nov 2018 12:36:50 +0100 Subject: [PATCH] Pass instructions to executor constructor --- src/ol/render/canvas/Executor.js | 30 +++-------- src/ol/render/canvas/ExecutorGroup.js | 25 +++++++-- src/ol/renderer/canvas/VectorLayer.js | 4 +- src/ol/renderer/canvas/VectorTileLayer.js | 3 +- test/spec/ol/render/canvas/textreplay.test.js | 3 +- test/spec/ol/renderer/canvas/replay.test.js | 54 +++++++++---------- 6 files changed, 57 insertions(+), 62 deletions(-) diff --git a/src/ol/render/canvas/Executor.js b/src/ol/render/canvas/Executor.js index 970486dc2e..a2d5e470f6 100644 --- a/src/ol/render/canvas/Executor.js +++ b/src/ol/render/canvas/Executor.js @@ -55,9 +55,9 @@ class CanvasExecutor { * @param {number} pixelRatio Pixel ratio. * @param {boolean} overlaps The replay can have overlapping geometries. * @param {?} declutterTree Declutter tree. + * @param {SerializableInstructions} instructions The serializable instructions */ - constructor(tolerance, maxExtent, resolution, pixelRatio, overlaps, declutterTree) { - + constructor(tolerance, maxExtent, resolution, pixelRatio, overlaps, declutterTree, instructions) { /** * @type {?} */ @@ -129,13 +129,13 @@ class CanvasExecutor { * @protected * @type {Array<*>} */ - this.instructions = []; + this.instructions = instructions.instructions; /** * @protected * @type {Array} */ - this.coordinates = []; + this.coordinates = instructions.coordinates; /** * @private @@ -153,7 +153,7 @@ class CanvasExecutor { * @protected * @type {Array<*>} */ - this.hitDetectionInstructions = []; + this.hitDetectionInstructions = instructions.hitDetectionInstructions; /** * @private @@ -176,17 +176,17 @@ class CanvasExecutor { /** * @type {!Object} */ - this.fillStates = {}; + this.fillStates = instructions.fillStates || {}; /** * @type {!Object} */ - this.strokeStates = {}; + this.strokeStates = instructions.strokeStates || {}; /** * @type {!Object} */ - this.textStates = {}; + this.textStates = instructions.textStates || {}; // Adaptations @@ -267,20 +267,6 @@ class CanvasExecutor { return labelCache.get(key); } - /** - * Recreate replays and populate them using the provided instructions. - * @param {SerializableInstructions} instructions The serializable instructions - */ - replaceInstructions(instructions) { - this.instructions = instructions.instructions; - this.hitDetectionInstructions = instructions.hitDetectionInstructions; - this.coordinates = instructions.coordinates; - // Workaround for decluttered text creation / rendering being coupled - this.textStates = instructions.textStates; - this.fillStates = instructions.fillStates; - this.strokeStates = instructions.strokeStates; - } - /** * @param {CanvasRenderingContext2D} context Context. * @param {import("../../coordinate.js").Coordinate} p1 1st point of the background box. diff --git a/src/ol/render/canvas/ExecutorGroup.js b/src/ol/render/canvas/ExecutorGroup.js index 962a3e3081..c9a0331032 100644 --- a/src/ol/render/canvas/ExecutorGroup.js +++ b/src/ol/render/canvas/ExecutorGroup.js @@ -22,6 +22,8 @@ class ExecutorGroup extends BaseExecutorGroup { * @param {number} pixelRatio Pixel ratio. * @param {boolean} overlaps The executor group can have overlapping geometries. * @param {?} declutterTree Declutter tree for declutter processing in postrender. + * @param {!Object>} allInstructions + * The serializable instructions. * @param {number=} opt_renderBuffer Optional rendering buffer. */ constructor( @@ -31,6 +33,7 @@ class ExecutorGroup extends BaseExecutorGroup { pixelRatio, overlaps, declutterTree, + allInstructions, opt_renderBuffer ) { super(); @@ -100,6 +103,8 @@ class ExecutorGroup extends BaseExecutorGroup { * @type {import("../../transform.js").Transform} */ this.hitDetectionTransform_ = createTransform(); + + this.createExectutors_(allInstructions); } /** @@ -118,16 +123,20 @@ class ExecutorGroup extends BaseExecutorGroup { /** * Create executors and populate them using the provided instructions. + * @private * @param {!Object>} allInstructions The serializable instructions */ - replaceInstructions(allInstructions) { - this.executorsByZIndex_ = {}; + createExectutors_(allInstructions) { for (const zIndex in allInstructions) { + let executors = this.executorsByZIndex_[zIndex]; + if (executors === undefined) { + this.executorsByZIndex_[zIndex] = executors = {}; + } const instructionByZindex = allInstructions[zIndex]; for (const replayType in instructionByZindex) { const instructions = instructionByZindex[replayType]; - const executor = this.getExecutor(zIndex, replayType); - executor.replaceInstructions(instructions); + executors[replayType] = new CanvasExecutor(this.tolerance_, this.maxExtent_, + this.resolution_, this.pixelRatio_, this.overlaps_, this.declutterTree_, instructions); } } } @@ -301,8 +310,14 @@ class ExecutorGroup extends BaseExecutorGroup { } let executor = executors[replayType]; if (executor === undefined) { + // FIXME: it should not be possible to ask for an executor that does not exist executor = new CanvasExecutor(this.tolerance_, this.maxExtent_, - this.resolution_, this.pixelRatio_, this.overlaps_, this.declutterTree_); + this.resolution_, this.pixelRatio_, this.overlaps_, { + instructions: [], + hitDetectionInstructions: [], + coordinates: [] + }, + this.declutterTree_); executors[replayType] = executor; } return executor; diff --git a/src/ol/renderer/canvas/VectorLayer.js b/src/ol/renderer/canvas/VectorLayer.js index 76a2f205ec..295dcd31c5 100644 --- a/src/ol/renderer/canvas/VectorLayer.js +++ b/src/ol/renderer/canvas/VectorLayer.js @@ -485,8 +485,8 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer { const replayGroupInstructions = replayGroup.finish(); const renderingExecutorGroup = new InstructionsGroupExecutor( getRenderTolerance(resolution, pixelRatio), extent, resolution, - pixelRatio, vectorSource.getOverlaps(), this.declutterTree_, vectorLayer.getRenderBuffer()); - renderingExecutorGroup.replaceInstructions(replayGroupInstructions); + pixelRatio, vectorSource.getOverlaps(), this.declutterTree_, + replayGroupInstructions, vectorLayer.getRenderBuffer()); this.renderedResolution_ = resolution; this.renderedRevision_ = vectorLayerRevision; diff --git a/src/ol/renderer/canvas/VectorTileLayer.js b/src/ol/renderer/canvas/VectorTileLayer.js index 4bd30cc533..62850f0974 100644 --- a/src/ol/renderer/canvas/VectorTileLayer.js +++ b/src/ol/renderer/canvas/VectorTileLayer.js @@ -229,8 +229,7 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer { } const replayGroupInstructions = builderGroup.finish(); const renderingReplayGroup = new CanvasExecutorGroup(0, sharedExtent, resolution, - pixelRatio, source.getOverlaps(), this.declutterTree_, layer.getRenderBuffer()); - renderingReplayGroup.replaceInstructions(replayGroupInstructions); + pixelRatio, source.getOverlaps(), this.declutterTree_, replayGroupInstructions, layer.getRenderBuffer()); sourceTile.setExecutorGroup(layer, tile.tileCoord.toString(), renderingReplayGroup); } builderState.renderedRevision = revision; diff --git a/test/spec/ol/render/canvas/textreplay.test.js b/test/spec/ol/render/canvas/textreplay.test.js index 1b879be727..590ab22cbe 100644 --- a/test/spec/ol/render/canvas/textreplay.test.js +++ b/test/spec/ol/render/canvas/textreplay.test.js @@ -28,10 +28,9 @@ function createContext() { function executeInstructions(builder, expectedDrawTextImageCalls, expectedReplayImageCalls) { const transform = createTransform(); const context = createContext(); - const executor = new InstructionExecutor(1, [-180, -90, 180, 90], 0.02, 1, null); + const executor = new InstructionExecutor(1, [-180, -90, 180, 90], 0.02, 1, false, null, builder.finish()); sinon.spy(executor, 'drawTextImageWithPointPlacement_'); const replayImageStub = sinon.stub(executor, 'replayImage_'); - executor.replaceInstructions(builder.finish()); executor.execute(context, transform); expect(executor.drawTextImageWithPointPlacement_.callCount).to.be(expectedDrawTextImageCalls); expect(replayImageStub.callCount).to.be(expectedReplayImageCalls); diff --git a/test/spec/ol/renderer/canvas/replay.test.js b/test/spec/ol/renderer/canvas/replay.test.js index 44a11ec865..3bfb3881fe 100644 --- a/test/spec/ol/renderer/canvas/replay.test.js +++ b/test/spec/ol/renderer/canvas/replay.test.js @@ -22,15 +22,26 @@ describe('ol.render.canvas.ReplayGroup', function() { describe('#replay', function() { - let context, builder, executor, fillCount, transform; + let context, builder, fillCount, transform; let strokeCount, beginPathCount, moveToCount, lineToCount; let feature0, feature1, feature2, feature3; let fill0, fill1, style1, style2; + /** + * @param {CanvasInstructionsGroupBuilder} builder The builder to get instructions from. + * @param {Object=} skippedUids The ids to skip. + * @param {number=} pixelRatio The pixel ratio. + * @param {boolean=} overlaps Whether there is overlaps. + */ + function execute(builder, skippedUids, pixelRatio, overlaps) { + const executor = new CanvasInstructionsGroupExecutor(1, [-180, -90, 180, 90], 1, + pixelRatio || 1, !!overlaps, null, builder.finish()); + executor.execute(context, transform, 0, skippedUids || {}); + } + beforeEach(function() { transform = createTransform(); builder = new CanvasInstructionsGroupBuilder(1, [-180, -90, 180, 90], 1, 1, false); - executor = new CanvasInstructionsGroupExecutor(1, [-180, -90, 180, 90], 1, 1, false); feature0 = new Feature(new Polygon( [[[-90, 0], [-45, 45], [0, 0], [1, 1], [0, -45], [-90, 0]]])); feature1 = new Feature(new Polygon( @@ -91,21 +102,18 @@ describe('ol.render.canvas.ReplayGroup', function() { it('omits lineTo for repeated coordinates', function() { renderFeature(builder, feature0, fill0, 1); - executor.replaceInstructions(builder.finish()); - executor.execute(context, transform, 0, {}); + execute(builder); expect(lineToCount).to.be(4); lineToCount = 0; scaleTransform(transform, 0.25, 0.25); - executor.replaceInstructions(builder.finish()); - executor.execute(context, transform, 0, {}); + execute(builder); expect(lineToCount).to.be(3); }); it('does not omit moveTo for repeated coordinates', function() { renderFeature(builder, feature0, fill0, 1); renderFeature(builder, feature1, fill1, 1); - executor.replaceInstructions(builder.finish()); - executor.execute(context, transform, 0, {}); + execute(builder); expect(moveToCount).to.be(2); }); @@ -113,8 +121,7 @@ describe('ol.render.canvas.ReplayGroup', function() { renderFeature(builder, feature1, style1, 1); renderFeature(builder, feature2, style1, 1); renderFeature(builder, feature3, style1, 1); - executor.replaceInstructions(builder.finish()); - executor.execute(context, transform, 0, {}); + execute(builder); expect(fillCount).to.be(1); expect(strokeCount).to.be(1); expect(beginPathCount).to.be(1); @@ -124,8 +131,7 @@ describe('ol.render.canvas.ReplayGroup', function() { renderFeature(builder, feature1, style1, 1); renderFeature(builder, feature2, style1, 1); renderFeature(builder, feature3, style2, 1); - executor.replaceInstructions(builder.finish()); - executor.execute(context, transform, 0, {}); + execute(builder); expect(fillCount).to.be(2); expect(strokeCount).to.be(2); expect(beginPathCount).to.be(2); @@ -135,8 +141,7 @@ describe('ol.render.canvas.ReplayGroup', function() { renderFeature(builder, feature1, style1, 1); renderFeature(builder, feature2, style2, 1); renderFeature(builder, feature3, style1, 1); - executor.replaceInstructions(builder.finish()); - executor.execute(context, transform, 0, {}); + execute(builder); expect(fillCount).to.be(3); expect(strokeCount).to.be(3); expect(beginPathCount).to.be(3); @@ -148,8 +153,7 @@ describe('ol.render.canvas.ReplayGroup', function() { renderFeature(builder, feature3, style2, 1); const skippedUids = {}; skippedUids[getUid(feature1)] = true; - executor.replaceInstructions(builder.finish()); - executor.execute(context, transform, 0, skippedUids); + execute(builder, skippedUids); expect(fillCount).to.be(1); expect(strokeCount).to.be(1); expect(beginPathCount).to.be(1); @@ -161,8 +165,7 @@ describe('ol.render.canvas.ReplayGroup', function() { renderFeature(builder, feature3, style2, 1); const skippedUids = {}; skippedUids[getUid(feature3)] = true; - executor.replaceInstructions(builder.finish()); - executor.execute(context, transform, 0, skippedUids); + execute(builder, skippedUids); expect(fillCount).to.be(1); expect(strokeCount).to.be(1); expect(beginPathCount).to.be(1); @@ -175,8 +178,7 @@ describe('ol.render.canvas.ReplayGroup', function() { const skippedUids = {}; skippedUids[getUid(feature1)] = true; skippedUids[getUid(feature2)] = true; - executor.replaceInstructions(builder.finish()); - executor.execute(context, transform, 0, skippedUids); + execute(builder, skippedUids); expect(fillCount).to.be(1); expect(strokeCount).to.be(1); expect(beginPathCount).to.be(1); @@ -184,12 +186,10 @@ describe('ol.render.canvas.ReplayGroup', function() { it('does not batch when overlaps is set to true', function() { builder = new CanvasInstructionsGroupBuilder(1, [-180, -90, 180, 90], 1, 1, true); - executor = new CanvasInstructionsGroupExecutor(1, [-180, -90, 180, 90], 1, 1, true); renderFeature(builder, feature1, style1, 1); renderFeature(builder, feature2, style1, 1); renderFeature(builder, feature3, style1, 1); - executor.replaceInstructions(builder.finish()); - executor.execute(context, transform, 0, {}); + execute(builder, {}, 1, true); expect(fillCount).to.be(3); expect(strokeCount).to.be(3); expect(beginPathCount).to.be(3); @@ -198,7 +198,6 @@ describe('ol.render.canvas.ReplayGroup', function() { it('applies the pixelRatio to the linedash array and offset', function() { // replay with a pixelRatio of 2 builder = new CanvasInstructionsGroupBuilder(1, [-180, -90, 180, 90], 1, 2, true); - executor = new CanvasInstructionsGroupExecutor(1, [-180, -90, 180, 90], 1, 2, true); let lineDash, lineDashCount = 0, lineDashOffset, lineDashOffsetCount = 0; @@ -217,8 +216,7 @@ describe('ol.render.canvas.ReplayGroup', function() { renderFeature(builder, feature1, style2, 1); renderFeature(builder, feature2, style2, 1); - executor.replaceInstructions(builder.finish()); - executor.execute(context, transform, 0, {}); + execute(builder, {}, 2, true); expect(lineDashCount).to.be(1); expect(style2.getStroke().getLineDash()).to.eql([3, 6]); @@ -257,7 +255,6 @@ describe('ol.render.canvas.ReplayGroup', function() { const geometrycollection = new Feature(new GeometryCollection( [point.getGeometry(), linestring.getGeometry(), polygon.getGeometry()])); builder = new CanvasInstructionsGroupBuilder(1, [-180, -90, 180, 90], 1, 1, true); - executor = new CanvasInstructionsGroupExecutor(1, [-180, -90, 180, 90], 1, 1, true); renderFeature(builder, point, style, 1); renderFeature(builder, multipoint, style, 1); renderFeature(builder, linestring, style, 1); @@ -266,8 +263,7 @@ describe('ol.render.canvas.ReplayGroup', function() { renderFeature(builder, multipolygon, style, 1); renderFeature(builder, geometrycollection, style, 1); scaleTransform(transform, 0.1, 0.1); - executor.replaceInstructions(builder.finish()); - executor.execute(context, transform, 0, {}); + execute(builder, {}, 1, true); expect(calls.length).to.be(9); expect(calls[0].geometry).to.be(point.getGeometry()); expect(calls[0].feature).to.be(point);