diff --git a/src/ol/render/canvas/canvasimmediate.js b/src/ol/render/canvas/canvasimmediate.js index 63ab55b1a6..f727058498 100644 --- a/src/ol/render/canvas/canvasimmediate.js +++ b/src/ol/render/canvas/canvasimmediate.js @@ -10,6 +10,7 @@ goog.require('ol.array'); goog.require('ol.color'); goog.require('ol.colorlike'); goog.require('ol.extent'); +goog.require('ol.geom.GeometryType'); goog.require('ol.geom.flat.transform'); goog.require('ol.has'); goog.require('ol.render.VectorContext'); @@ -475,6 +476,46 @@ ol.render.canvas.Immediate.prototype.setStyle = function(style) { }; +/** + * Render a geometry into the canvas. Call + * {@link ol.render.canvas.Immediate#setStyle} first to set the rendering style. + * + * @param {ol.geom.Geometry|ol.render.Feature} geometry The geometry to render. + * @api + */ +ol.render.canvas.Immediate.prototype.drawGeometry = function(geometry) { + var type = geometry.getType(); + switch (type) { + case ol.geom.GeometryType.POINT: + this.drawPointGeometry(/** @type {ol.geom.Point} */ (geometry)); + break; + case ol.geom.GeometryType.LINE_STRING: + this.drawLineStringGeometry(/** @type {ol.geom.LineString} */ (geometry)); + break; + case ol.geom.GeometryType.POLYGON: + this.drawPolygonGeometry(/** @type {ol.geom.Polygon} */ (geometry)); + break; + case ol.geom.GeometryType.MULTI_POINT: + this.drawMultiPointGeometry(/** @type {ol.geom.MultiPoint} */ (geometry)); + break; + case ol.geom.GeometryType.MULTI_LINE_STRING: + this.drawMultiLineStringGeometry(/** @type {ol.geom.MultiLineString} */ (geometry)); + break; + case ol.geom.GeometryType.MULTI_POLYGON: + this.drawMultiPolygonGeometry(/** @type {ol.geom.MultiPolygon} */ (geometry)); + break; + case ol.geom.GeometryType.GEOMETRY_COLLECTION: + this.drawGeometryCollectionGeometry(/** @type {ol.geom.GeometryCollection} */ (geometry), null); + break; + case ol.geom.GeometryType.CIRCLE: + this.drawCircleGeometry(/** @type {ol.geom.Circle} */ (geometry)); + break; + default: + goog.asserts.fail('Unsupported geometry type: ' + type); + } +}; + + /** * Render a feature into the canvas. In order to respect the zIndex of the * style this method draws asynchronously and thus *after* calls to @@ -500,11 +541,8 @@ ol.render.canvas.Immediate.prototype.drawFeature = function(feature, style) { render.setFillStrokeStyle(style.getFill(), style.getStroke()); render.setImageStyle(style.getImage()); render.setTextStyle(style.getText()); - var renderGeometry = - ol.render.canvas.Immediate.GEOMETRY_RENDERERS_[geometry.getType()]; - goog.asserts.assert(renderGeometry !== undefined, - 'renderGeometry should be defined'); - renderGeometry.call(render, geometry, null); + goog.asserts.assert(geometry); + render.drawGeometry(geometry); }); }; @@ -521,12 +559,7 @@ ol.render.canvas.Immediate.prototype.drawGeometryCollectionGeometry = function(g var geometries = geometryCollectionGeometry.getGeometriesArray(); var i, ii; for (i = 0, ii = geometries.length; i < ii; ++i) { - var geometry = geometries[i]; - var geometryRenderer = - ol.render.canvas.Immediate.GEOMETRY_RENDERERS_[geometry.getType()]; - goog.asserts.assert(geometryRenderer !== undefined, - 'geometryRenderer should be defined'); - geometryRenderer.call(this, geometry, feature); + this.drawGeometry(geometries[i]); } }; @@ -985,24 +1018,3 @@ ol.render.canvas.Immediate.prototype.setTextStyle = function(textStyle) { textScale : 1); } }; - - -/** - * @const - * @private - * @type {Object.} - */ -ol.render.canvas.Immediate.GEOMETRY_RENDERERS_ = { - 'Point': ol.render.canvas.Immediate.prototype.drawPointGeometry, - 'LineString': ol.render.canvas.Immediate.prototype.drawLineStringGeometry, - 'Polygon': ol.render.canvas.Immediate.prototype.drawPolygonGeometry, - 'MultiPoint': ol.render.canvas.Immediate.prototype.drawMultiPointGeometry, - 'MultiLineString': - ol.render.canvas.Immediate.prototype.drawMultiLineStringGeometry, - 'MultiPolygon': ol.render.canvas.Immediate.prototype.drawMultiPolygonGeometry, - 'GeometryCollection': - ol.render.canvas.Immediate.prototype.drawGeometryCollectionGeometry, - 'Circle': ol.render.canvas.Immediate.prototype.drawCircleGeometry -}; diff --git a/test/spec/ol/render/canvasimmediate.test.js b/test/spec/ol/render/canvasimmediate.test.js index ad64a26b31..27bc62cba9 100644 --- a/test/spec/ol/render/canvasimmediate.test.js +++ b/test/spec/ol/render/canvasimmediate.test.js @@ -2,6 +2,17 @@ goog.provide('ol.test.render.canvas.Immediate'); describe('ol.render.canvas.Immediate', function() { + function getMockContext() { + return { + setLineDash: sinon.spy(), + beginPath: sinon.spy(), + closePath: sinon.spy(), + stroke: sinon.spy(), + lineTo: sinon.spy(), + moveTo: sinon.spy() + }; + } + describe('constructor', function() { it('creates an instance', function() { var instance = new ol.render.canvas.Immediate(); @@ -52,6 +63,106 @@ describe('ol.render.canvas.Immediate', function() { }); }); + describe('#drawGeometry()', function() { + + var extent = [-10, -10, 10, 10]; + + it('calls drawPointGeometry() with a Point', function() { + var context = new ol.render.canvas.Immediate(getMockContext(), 1, extent); + sinon.spy(context, 'drawPointGeometry'); + + var geometry = new ol.geom.Point([1, 2]); + context.drawGeometry(geometry); + expect(context.drawPointGeometry.calledOnce).to.be(true); + expect(context.drawPointGeometry.firstCall.calledWithExactly(geometry)).to.be(true); + }); + + it('calls drawLineStringGeometry() with a LineString', function() { + var context = new ol.render.canvas.Immediate(getMockContext(), 1, extent); + sinon.spy(context, 'drawLineStringGeometry'); + + var geometry = new ol.geom.LineString([[1, 2], [3, 4]]); + context.drawGeometry(geometry); + expect(context.drawLineStringGeometry.calledOnce).to.be(true); + expect(context.drawLineStringGeometry.firstCall.calledWithExactly(geometry)).to.be(true); + }); + + it('calls drawPolygonGeometry() with a Polygon', function() { + var context = new ol.render.canvas.Immediate(getMockContext(), 1, extent); + sinon.spy(context, 'drawPolygonGeometry'); + + var geometry = new ol.geom.Polygon([[[1, 2], [3, 4], [5, 6], [1, 2]]]); + context.drawGeometry(geometry); + expect(context.drawPolygonGeometry.calledOnce).to.be(true); + expect(context.drawPolygonGeometry.firstCall.calledWithExactly(geometry)).to.be(true); + }); + + it('calls drawMultiPointGeometry() with a MultiPoint', function() { + var context = new ol.render.canvas.Immediate(getMockContext(), 1, extent); + sinon.spy(context, 'drawMultiPointGeometry'); + + var geometry = new ol.geom.MultiPoint([[1, 2], [3, 4]]); + context.drawGeometry(geometry); + expect(context.drawMultiPointGeometry.calledOnce).to.be(true); + expect(context.drawMultiPointGeometry.firstCall.calledWithExactly(geometry)).to.be(true); + }); + + it('calls drawMultiLineStringGeometry() with a MultiLineString', function() { + var context = new ol.render.canvas.Immediate(getMockContext(), 1, extent); + sinon.spy(context, 'drawMultiLineStringGeometry'); + + var geometry = new ol.geom.MultiLineString([[[1, 2], [3, 4]]]); + context.drawGeometry(geometry); + expect(context.drawMultiLineStringGeometry.calledOnce).to.be(true); + expect(context.drawMultiLineStringGeometry.firstCall.calledWithExactly(geometry)).to.be(true); + }); + + it('calls drawMultiPolygonGeometry() with a MultiPolygon', function() { + var context = new ol.render.canvas.Immediate(getMockContext(), 1, extent); + sinon.spy(context, 'drawMultiPolygonGeometry'); + + var geometry = new ol.geom.MultiPolygon([[[[1, 2], [3, 4], [5, 6], [1, 2]]]]); + context.drawGeometry(geometry); + expect(context.drawMultiPolygonGeometry.calledOnce).to.be(true); + expect(context.drawMultiPolygonGeometry.firstCall.calledWithExactly(geometry)).to.be(true); + }); + + it('calls drawGeometryCollectionGeometry() with a GeometryCollection', function() { + var context = new ol.render.canvas.Immediate(getMockContext(), 1, extent); + sinon.spy(context, 'drawGeometryCollectionGeometry'); + sinon.spy(context, 'drawPointGeometry'); + sinon.spy(context, 'drawLineStringGeometry'); + sinon.spy(context, 'drawPolygonGeometry'); + + var point = new ol.geom.Point([1, 2]); + var linestring = new ol.geom.LineString([[1, 2], [3, 4]]); + var polygon = new ol.geom.Polygon([[[1, 2], [3, 4], [5, 6], [1, 2]]]); + + var geometry = new ol.geom.GeometryCollection([point, linestring, polygon]); + context.drawGeometry(geometry); + + expect(context.drawGeometryCollectionGeometry.calledOnce).to.be(true); + expect(context.drawPointGeometry.calledOnce).to.be(true); + expect(context.drawPointGeometry.firstCall.calledWithExactly(point)).to.be(true); + expect(context.drawLineStringGeometry.calledOnce).to.be(true); + expect(context.drawLineStringGeometry.firstCall.calledWithExactly(linestring)).to.be(true); + expect(context.drawPolygonGeometry.calledOnce).to.be(true); + expect(context.drawPolygonGeometry.firstCall.calledWithExactly(polygon)).to.be(true); + }); + + it('calls drawCircle() with a Circle', function() { + var context = new ol.render.canvas.Immediate(getMockContext(), 1, extent); + sinon.spy(context, 'drawCircleGeometry'); + + var geometry = new ol.geom.Circle([0, 0]); + context.drawGeometry(geometry); + + expect(context.drawCircleGeometry.calledOnce).to.be(true); + expect(context.drawCircleGeometry.firstCall.calledWithExactly(geometry)).to.be(true); + }); + + }); + describe('#drawMultiPolygonGeometry', function() { it('creates the correct canvas instructions for 3D geometries', function() { var log = { @@ -144,7 +255,14 @@ describe('ol.render.canvas.Immediate', function() { }); }); +goog.require('ol.geom.Circle'); +goog.require('ol.geom.GeometryCollection'); +goog.require('ol.geom.LineString'); +goog.require('ol.geom.MultiLineString'); +goog.require('ol.geom.MultiPoint'); goog.require('ol.geom.MultiPolygon'); +goog.require('ol.geom.Point'); +goog.require('ol.geom.Polygon'); goog.require('ol.render.VectorContext'); goog.require('ol.render.canvas.Immediate'); goog.require('ol.style.Circle');