diff --git a/src/ol/render/canvas/replay.js b/src/ol/render/canvas/replay.js index 3f75f77292..74502b7317 100644 --- a/src/ol/render/canvas/replay.js +++ b/src/ol/render/canvas/replay.js @@ -89,7 +89,7 @@ ol.render.canvas.Replay = function(tolerance, maxExtent, resolution, overlaps) { /** * @private - * @type {ol.Transform} + * @type {!ol.Transform} */ this.renderedTransform_ = ol.transform.create(); @@ -103,17 +103,17 @@ ol.render.canvas.Replay = function(tolerance, maxExtent, resolution, overlaps) { * @private * @type {Array.} */ - this.pixelCoordinates_ = []; + this.pixelCoordinates_ = null; /** * @private - * @type {ol.Transform} + * @type {!ol.Transform} */ this.tmpLocalTransform_ = ol.transform.create(); /** * @private - * @type {ol.Transform} + * @type {!ol.Transform} */ this.resetTransform_ = ol.transform.create(); }; @@ -229,9 +229,12 @@ ol.render.canvas.Replay.prototype.replay_ = function( instructions, featureCallback, opt_hitExtent) { /** @type {Array.} */ var pixelCoordinates; - if (ol.array.equals(transform, this.renderedTransform_)) { + if (this.pixelCoordinates_ && ol.array.equals(transform, this.renderedTransform_)) { pixelCoordinates = this.pixelCoordinates_; } else { + if (!this.pixelCoordinates_) { + this.pixelCoordinates_ = []; + } pixelCoordinates = ol.geom.flat.transform.transform2D( this.coordinates, 0, this.coordinates.length, 2, transform, this.pixelCoordinates_); @@ -427,6 +430,8 @@ ol.render.canvas.Replay.prototype.replay_ = function( this.fill_(context, viewRotation); } ++i; + prevX = NaN; + prevY = NaN; break; case ol.render.canvas.Instruction.MOVE_TO_LINE_TO: d = /** @type {number} */ (instruction[1]); diff --git a/src/ol/typedefs.js b/src/ol/typedefs.js index 6985f6a158..659afd2a8a 100644 --- a/src/ol/typedefs.js +++ b/src/ol/typedefs.js @@ -360,7 +360,7 @@ ol.MapOptionsInternal; /** * An array representing an affine 2d transformation for use with * {@link ol.transform} functions. The array has 6 elements. - * @typedef {Array.} + * @typedef {!Array.} */ ol.Transform; diff --git a/test/spec/ol/renderer/canvas/replay.test.js b/test/spec/ol/renderer/canvas/replay.test.js index 55fedd61de..3aa3b2b883 100644 --- a/test/spec/ol/renderer/canvas/replay.test.js +++ b/test/spec/ol/renderer/canvas/replay.test.js @@ -16,18 +16,24 @@ describe('ol.render.canvas.ReplayGroup', function() { describe('#replay', function() { - var context, replay, fillCount, strokeCount, beginPathCount; - var feature1, feature2, feature3, style1, style2, transform; + var context, replay, fillCount, transform; + var strokeCount, beginPathCount, moveToCount, lineToCount; + var feature0, feature1, feature2, feature3, style0, style1, style2; beforeEach(function() { transform = ol.transform.create(); replay = new ol.render.canvas.ReplayGroup(1, [-180, -90, 180, 90], 1, false); + feature0 = new ol.Feature(new ol.geom.Polygon( + [[[-90, 0], [-45, 45], [0, 0], [1, 1], [0, -45], [-90, 0]]])); feature1 = new ol.Feature(new ol.geom.Polygon( [[[-90, -45], [-90, 0], [0, 0], [0, -45], [-90, -45]]])); feature2 = new ol.Feature(new ol.geom.Polygon( [[[90, 45], [90, 0], [0, 0], [0, 45], [90, 45]]])); feature3 = new ol.Feature(new ol.geom.Polygon( [[[-90, -45], [-90, 45], [90, 45], [90, -45], [-90, -45]]])); + style0 = new ol.style.Style({ + fill: new ol.style.Fill({color: 'black'}) + }); style1 = new ol.style.Style({ fill: new ol.style.Fill({color: 'black'}), stroke: new ol.style.Stroke({color: 'white', width: 1}) @@ -40,6 +46,8 @@ describe('ol.render.canvas.ReplayGroup', function() { fillCount = 0; strokeCount = 0; beginPathCount = 0; + moveToCount = 0; + lineToCount = 0; context = { fill: function() { fillCount++; @@ -51,18 +59,42 @@ describe('ol.render.canvas.ReplayGroup', function() { beginPathCount++; }, clip: function() { + // remove beginPath, moveTo and lineTo counts for clipping beginPathCount--; + moveToCount--; + lineToCount -= 3; + }, + moveTo: function() { + moveToCount++; + }, + lineTo: function() { + lineToCount++; }, - save: function() {}, - moveTo: function() {}, - lineTo: function() {}, closePath: function() {}, setLineDash: function() {}, + save: function() {}, restore: function() {} }; }); + it('omits lineTo for repeated coordinates', function() { + ol.renderer.vector.renderFeature(replay, feature0, style0, 1); + replay.replay(context, 1, transform, 0, {}); + expect(lineToCount).to.be(4); + lineToCount = 0; + ol.transform.scale(transform, 0.25, 0.25); + replay.replay(context, 1, transform, 0, {}); + expect(lineToCount).to.be(3); + }); + + it('does not omit moveTo for repeated coordinates', function() { + ol.renderer.vector.renderFeature(replay, feature0, style0, 1); + ol.renderer.vector.renderFeature(replay, feature1, style0, 1); + replay.replay(context, 1, transform, 0, {}); + expect(moveToCount).to.be(2); + }); + it('batches fill and stroke instructions for same style', function() { ol.renderer.vector.renderFeature(replay, feature1, style1, 1); ol.renderer.vector.renderFeature(replay, feature2, style1, 1);