Pass instructions to executor constructor

This commit is contained in:
Guillaume Beraudo
2018-11-16 12:36:50 +01:00
parent ce44a9a3e4
commit 81d0bc21d5
6 changed files with 57 additions and 62 deletions
+8 -22
View File
@@ -55,9 +55,9 @@ class CanvasExecutor {
* @param {number} pixelRatio Pixel ratio. * @param {number} pixelRatio Pixel ratio.
* @param {boolean} overlaps The replay can have overlapping geometries. * @param {boolean} overlaps The replay can have overlapping geometries.
* @param {?} declutterTree Declutter tree. * @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 {?} * @type {?}
*/ */
@@ -129,13 +129,13 @@ class CanvasExecutor {
* @protected * @protected
* @type {Array<*>} * @type {Array<*>}
*/ */
this.instructions = []; this.instructions = instructions.instructions;
/** /**
* @protected * @protected
* @type {Array<number>} * @type {Array<number>}
*/ */
this.coordinates = []; this.coordinates = instructions.coordinates;
/** /**
* @private * @private
@@ -153,7 +153,7 @@ class CanvasExecutor {
* @protected * @protected
* @type {Array<*>} * @type {Array<*>}
*/ */
this.hitDetectionInstructions = []; this.hitDetectionInstructions = instructions.hitDetectionInstructions;
/** /**
* @private * @private
@@ -176,17 +176,17 @@ class CanvasExecutor {
/** /**
* @type {!Object<string, import("../canvas.js").FillState>} * @type {!Object<string, import("../canvas.js").FillState>}
*/ */
this.fillStates = {}; this.fillStates = instructions.fillStates || {};
/** /**
* @type {!Object<string, import("../canvas.js").StrokeState>} * @type {!Object<string, import("../canvas.js").StrokeState>}
*/ */
this.strokeStates = {}; this.strokeStates = instructions.strokeStates || {};
/** /**
* @type {!Object<string, import("../canvas.js").TextState>} * @type {!Object<string, import("../canvas.js").TextState>}
*/ */
this.textStates = {}; this.textStates = instructions.textStates || {};
// Adaptations // Adaptations
@@ -267,20 +267,6 @@ class CanvasExecutor {
return labelCache.get(key); 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 {CanvasRenderingContext2D} context Context.
* @param {import("../../coordinate.js").Coordinate} p1 1st point of the background box. * @param {import("../../coordinate.js").Coordinate} p1 1st point of the background box.
+20 -5
View File
@@ -22,6 +22,8 @@ class ExecutorGroup extends BaseExecutorGroup {
* @param {number} pixelRatio Pixel ratio. * @param {number} pixelRatio Pixel ratio.
* @param {boolean} overlaps The executor group can have overlapping geometries. * @param {boolean} overlaps The executor group can have overlapping geometries.
* @param {?} declutterTree Declutter tree for declutter processing in postrender. * @param {?} declutterTree Declutter tree for declutter processing in postrender.
* @param {!Object<string, !Object<ReplayType, import("./Builder.js").SerializableInstructions>>} allInstructions
* The serializable instructions.
* @param {number=} opt_renderBuffer Optional rendering buffer. * @param {number=} opt_renderBuffer Optional rendering buffer.
*/ */
constructor( constructor(
@@ -31,6 +33,7 @@ class ExecutorGroup extends BaseExecutorGroup {
pixelRatio, pixelRatio,
overlaps, overlaps,
declutterTree, declutterTree,
allInstructions,
opt_renderBuffer opt_renderBuffer
) { ) {
super(); super();
@@ -100,6 +103,8 @@ class ExecutorGroup extends BaseExecutorGroup {
* @type {import("../../transform.js").Transform} * @type {import("../../transform.js").Transform}
*/ */
this.hitDetectionTransform_ = createTransform(); this.hitDetectionTransform_ = createTransform();
this.createExectutors_(allInstructions);
} }
/** /**
@@ -118,16 +123,20 @@ class ExecutorGroup extends BaseExecutorGroup {
/** /**
* Create executors and populate them using the provided instructions. * Create executors and populate them using the provided instructions.
* @private
* @param {!Object<string, !Object<ReplayType, import("./Builder.js").SerializableInstructions>>} allInstructions The serializable instructions * @param {!Object<string, !Object<ReplayType, import("./Builder.js").SerializableInstructions>>} allInstructions The serializable instructions
*/ */
replaceInstructions(allInstructions) { createExectutors_(allInstructions) {
this.executorsByZIndex_ = {};
for (const zIndex in allInstructions) { for (const zIndex in allInstructions) {
let executors = this.executorsByZIndex_[zIndex];
if (executors === undefined) {
this.executorsByZIndex_[zIndex] = executors = {};
}
const instructionByZindex = allInstructions[zIndex]; const instructionByZindex = allInstructions[zIndex];
for (const replayType in instructionByZindex) { for (const replayType in instructionByZindex) {
const instructions = instructionByZindex[replayType]; const instructions = instructionByZindex[replayType];
const executor = this.getExecutor(zIndex, replayType); executors[replayType] = new CanvasExecutor(this.tolerance_, this.maxExtent_,
executor.replaceInstructions(instructions); this.resolution_, this.pixelRatio_, this.overlaps_, this.declutterTree_, instructions);
} }
} }
} }
@@ -301,8 +310,14 @@ class ExecutorGroup extends BaseExecutorGroup {
} }
let executor = executors[replayType]; let executor = executors[replayType];
if (executor === undefined) { 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_, 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; executors[replayType] = executor;
} }
return executor; return executor;
+2 -2
View File
@@ -485,8 +485,8 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer {
const replayGroupInstructions = replayGroup.finish(); const replayGroupInstructions = replayGroup.finish();
const renderingExecutorGroup = new InstructionsGroupExecutor( const renderingExecutorGroup = new InstructionsGroupExecutor(
getRenderTolerance(resolution, pixelRatio), extent, resolution, getRenderTolerance(resolution, pixelRatio), extent, resolution,
pixelRatio, vectorSource.getOverlaps(), this.declutterTree_, vectorLayer.getRenderBuffer()); pixelRatio, vectorSource.getOverlaps(), this.declutterTree_,
renderingExecutorGroup.replaceInstructions(replayGroupInstructions); replayGroupInstructions, vectorLayer.getRenderBuffer());
this.renderedResolution_ = resolution; this.renderedResolution_ = resolution;
this.renderedRevision_ = vectorLayerRevision; this.renderedRevision_ = vectorLayerRevision;
+1 -2
View File
@@ -229,8 +229,7 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
} }
const replayGroupInstructions = builderGroup.finish(); const replayGroupInstructions = builderGroup.finish();
const renderingReplayGroup = new CanvasExecutorGroup(0, sharedExtent, resolution, const renderingReplayGroup = new CanvasExecutorGroup(0, sharedExtent, resolution,
pixelRatio, source.getOverlaps(), this.declutterTree_, layer.getRenderBuffer()); pixelRatio, source.getOverlaps(), this.declutterTree_, replayGroupInstructions, layer.getRenderBuffer());
renderingReplayGroup.replaceInstructions(replayGroupInstructions);
sourceTile.setExecutorGroup(layer, tile.tileCoord.toString(), renderingReplayGroup); sourceTile.setExecutorGroup(layer, tile.tileCoord.toString(), renderingReplayGroup);
} }
builderState.renderedRevision = revision; builderState.renderedRevision = revision;
@@ -28,10 +28,9 @@ function createContext() {
function executeInstructions(builder, expectedDrawTextImageCalls, expectedReplayImageCalls) { function executeInstructions(builder, expectedDrawTextImageCalls, expectedReplayImageCalls) {
const transform = createTransform(); const transform = createTransform();
const context = createContext(); 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_'); sinon.spy(executor, 'drawTextImageWithPointPlacement_');
const replayImageStub = sinon.stub(executor, 'replayImage_'); const replayImageStub = sinon.stub(executor, 'replayImage_');
executor.replaceInstructions(builder.finish());
executor.execute(context, transform); executor.execute(context, transform);
expect(executor.drawTextImageWithPointPlacement_.callCount).to.be(expectedDrawTextImageCalls); expect(executor.drawTextImageWithPointPlacement_.callCount).to.be(expectedDrawTextImageCalls);
expect(replayImageStub.callCount).to.be(expectedReplayImageCalls); expect(replayImageStub.callCount).to.be(expectedReplayImageCalls);
+25 -29
View File
@@ -22,15 +22,26 @@ describe('ol.render.canvas.ReplayGroup', function() {
describe('#replay', function() { describe('#replay', function() {
let context, builder, executor, fillCount, transform; let context, builder, fillCount, transform;
let strokeCount, beginPathCount, moveToCount, lineToCount; let strokeCount, beginPathCount, moveToCount, lineToCount;
let feature0, feature1, feature2, feature3; let feature0, feature1, feature2, feature3;
let fill0, fill1, style1, style2; 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() { beforeEach(function() {
transform = createTransform(); transform = createTransform();
builder = new CanvasInstructionsGroupBuilder(1, [-180, -90, 180, 90], 1, 1, false); 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( feature0 = new Feature(new Polygon(
[[[-90, 0], [-45, 45], [0, 0], [1, 1], [0, -45], [-90, 0]]])); [[[-90, 0], [-45, 45], [0, 0], [1, 1], [0, -45], [-90, 0]]]));
feature1 = new Feature(new Polygon( feature1 = new Feature(new Polygon(
@@ -91,21 +102,18 @@ describe('ol.render.canvas.ReplayGroup', function() {
it('omits lineTo for repeated coordinates', function() { it('omits lineTo for repeated coordinates', function() {
renderFeature(builder, feature0, fill0, 1); renderFeature(builder, feature0, fill0, 1);
executor.replaceInstructions(builder.finish()); execute(builder);
executor.execute(context, transform, 0, {});
expect(lineToCount).to.be(4); expect(lineToCount).to.be(4);
lineToCount = 0; lineToCount = 0;
scaleTransform(transform, 0.25, 0.25); scaleTransform(transform, 0.25, 0.25);
executor.replaceInstructions(builder.finish()); execute(builder);
executor.execute(context, transform, 0, {});
expect(lineToCount).to.be(3); expect(lineToCount).to.be(3);
}); });
it('does not omit moveTo for repeated coordinates', function() { it('does not omit moveTo for repeated coordinates', function() {
renderFeature(builder, feature0, fill0, 1); renderFeature(builder, feature0, fill0, 1);
renderFeature(builder, feature1, fill1, 1); renderFeature(builder, feature1, fill1, 1);
executor.replaceInstructions(builder.finish()); execute(builder);
executor.execute(context, transform, 0, {});
expect(moveToCount).to.be(2); expect(moveToCount).to.be(2);
}); });
@@ -113,8 +121,7 @@ describe('ol.render.canvas.ReplayGroup', function() {
renderFeature(builder, feature1, style1, 1); renderFeature(builder, feature1, style1, 1);
renderFeature(builder, feature2, style1, 1); renderFeature(builder, feature2, style1, 1);
renderFeature(builder, feature3, style1, 1); renderFeature(builder, feature3, style1, 1);
executor.replaceInstructions(builder.finish()); execute(builder);
executor.execute(context, transform, 0, {});
expect(fillCount).to.be(1); expect(fillCount).to.be(1);
expect(strokeCount).to.be(1); expect(strokeCount).to.be(1);
expect(beginPathCount).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, feature1, style1, 1);
renderFeature(builder, feature2, style1, 1); renderFeature(builder, feature2, style1, 1);
renderFeature(builder, feature3, style2, 1); renderFeature(builder, feature3, style2, 1);
executor.replaceInstructions(builder.finish()); execute(builder);
executor.execute(context, transform, 0, {});
expect(fillCount).to.be(2); expect(fillCount).to.be(2);
expect(strokeCount).to.be(2); expect(strokeCount).to.be(2);
expect(beginPathCount).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, feature1, style1, 1);
renderFeature(builder, feature2, style2, 1); renderFeature(builder, feature2, style2, 1);
renderFeature(builder, feature3, style1, 1); renderFeature(builder, feature3, style1, 1);
executor.replaceInstructions(builder.finish()); execute(builder);
executor.execute(context, transform, 0, {});
expect(fillCount).to.be(3); expect(fillCount).to.be(3);
expect(strokeCount).to.be(3); expect(strokeCount).to.be(3);
expect(beginPathCount).to.be(3); expect(beginPathCount).to.be(3);
@@ -148,8 +153,7 @@ describe('ol.render.canvas.ReplayGroup', function() {
renderFeature(builder, feature3, style2, 1); renderFeature(builder, feature3, style2, 1);
const skippedUids = {}; const skippedUids = {};
skippedUids[getUid(feature1)] = true; skippedUids[getUid(feature1)] = true;
executor.replaceInstructions(builder.finish()); execute(builder, skippedUids);
executor.execute(context, transform, 0, skippedUids);
expect(fillCount).to.be(1); expect(fillCount).to.be(1);
expect(strokeCount).to.be(1); expect(strokeCount).to.be(1);
expect(beginPathCount).to.be(1); expect(beginPathCount).to.be(1);
@@ -161,8 +165,7 @@ describe('ol.render.canvas.ReplayGroup', function() {
renderFeature(builder, feature3, style2, 1); renderFeature(builder, feature3, style2, 1);
const skippedUids = {}; const skippedUids = {};
skippedUids[getUid(feature3)] = true; skippedUids[getUid(feature3)] = true;
executor.replaceInstructions(builder.finish()); execute(builder, skippedUids);
executor.execute(context, transform, 0, skippedUids);
expect(fillCount).to.be(1); expect(fillCount).to.be(1);
expect(strokeCount).to.be(1); expect(strokeCount).to.be(1);
expect(beginPathCount).to.be(1); expect(beginPathCount).to.be(1);
@@ -175,8 +178,7 @@ describe('ol.render.canvas.ReplayGroup', function() {
const skippedUids = {}; const skippedUids = {};
skippedUids[getUid(feature1)] = true; skippedUids[getUid(feature1)] = true;
skippedUids[getUid(feature2)] = true; skippedUids[getUid(feature2)] = true;
executor.replaceInstructions(builder.finish()); execute(builder, skippedUids);
executor.execute(context, transform, 0, skippedUids);
expect(fillCount).to.be(1); expect(fillCount).to.be(1);
expect(strokeCount).to.be(1); expect(strokeCount).to.be(1);
expect(beginPathCount).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() { it('does not batch when overlaps is set to true', function() {
builder = new CanvasInstructionsGroupBuilder(1, [-180, -90, 180, 90], 1, 1, true); 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, feature1, style1, 1);
renderFeature(builder, feature2, style1, 1); renderFeature(builder, feature2, style1, 1);
renderFeature(builder, feature3, style1, 1); renderFeature(builder, feature3, style1, 1);
executor.replaceInstructions(builder.finish()); execute(builder, {}, 1, true);
executor.execute(context, transform, 0, {});
expect(fillCount).to.be(3); expect(fillCount).to.be(3);
expect(strokeCount).to.be(3); expect(strokeCount).to.be(3);
expect(beginPathCount).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() { it('applies the pixelRatio to the linedash array and offset', function() {
// replay with a pixelRatio of 2 // replay with a pixelRatio of 2
builder = new CanvasInstructionsGroupBuilder(1, [-180, -90, 180, 90], 1, 2, true); 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, let lineDash, lineDashCount = 0,
lineDashOffset, lineDashOffsetCount = 0; lineDashOffset, lineDashOffsetCount = 0;
@@ -217,8 +216,7 @@ describe('ol.render.canvas.ReplayGroup', function() {
renderFeature(builder, feature1, style2, 1); renderFeature(builder, feature1, style2, 1);
renderFeature(builder, feature2, style2, 1); renderFeature(builder, feature2, style2, 1);
executor.replaceInstructions(builder.finish()); execute(builder, {}, 2, true);
executor.execute(context, transform, 0, {});
expect(lineDashCount).to.be(1); expect(lineDashCount).to.be(1);
expect(style2.getStroke().getLineDash()).to.eql([3, 6]); expect(style2.getStroke().getLineDash()).to.eql([3, 6]);
@@ -257,7 +255,6 @@ describe('ol.render.canvas.ReplayGroup', function() {
const geometrycollection = new Feature(new GeometryCollection( const geometrycollection = new Feature(new GeometryCollection(
[point.getGeometry(), linestring.getGeometry(), polygon.getGeometry()])); [point.getGeometry(), linestring.getGeometry(), polygon.getGeometry()]));
builder = new CanvasInstructionsGroupBuilder(1, [-180, -90, 180, 90], 1, 1, true); 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, point, style, 1);
renderFeature(builder, multipoint, style, 1); renderFeature(builder, multipoint, style, 1);
renderFeature(builder, linestring, style, 1); renderFeature(builder, linestring, style, 1);
@@ -266,8 +263,7 @@ describe('ol.render.canvas.ReplayGroup', function() {
renderFeature(builder, multipolygon, style, 1); renderFeature(builder, multipolygon, style, 1);
renderFeature(builder, geometrycollection, style, 1); renderFeature(builder, geometrycollection, style, 1);
scaleTransform(transform, 0.1, 0.1); scaleTransform(transform, 0.1, 0.1);
executor.replaceInstructions(builder.finish()); execute(builder, {}, 1, true);
executor.execute(context, transform, 0, {});
expect(calls.length).to.be(9); expect(calls.length).to.be(9);
expect(calls[0].geometry).to.be(point.getGeometry()); expect(calls[0].geometry).to.be(point.getGeometry());
expect(calls[0].feature).to.be(point); expect(calls[0].feature).to.be(point);