diff --git a/src/ol/layer/vectorlayer.js b/src/ol/layer/vectorlayer.js index 06c4a82e30..bb773113ef 100644 --- a/src/ol/layer/vectorlayer.js +++ b/src/ol/layer/vectorlayer.js @@ -384,50 +384,45 @@ ol.layer.Vector.prototype.groupFeaturesBySymbolizerLiteral = var uniqueLiterals = {}, featuresBySymbolizer = [], style = this.style_, - i, j, l, feature, geom, type, symbolizers, literals, numLiterals, literal, + i, j, l, feature, symbolizers, literals, numLiterals, literal, uniqueLiteral, key, item; for (i in features) { feature = features[i]; - geom = feature.getGeometry(); - if (geom) { - type = geom.getType(); - // feature level symbolizers take precedence - symbolizers = feature.getSymbolizers(); - if (!goog.isNull(symbolizers)) { - literals = ol.style.Style.createLiterals( - symbolizers, type, feature); + // feature level symbolizers take precedence + symbolizers = feature.getSymbolizers(); + if (!goog.isNull(symbolizers)) { + literals = ol.style.Style.createLiterals(symbolizers, feature); + } else { + if (!goog.isNull(style)) { + // layer style second + literals = style.apply(feature); } else { - if (!goog.isNull(style)) { - // layer style second - literals = style.apply(feature); - } else { - literals = ol.style.Style.applyDefaultStyle(feature); + literals = ol.style.Style.applyDefaultStyle(feature); + } + } + numLiterals = literals.length; + for (j = 0; j < numLiterals; ++j) { + literal = literals[j]; + for (l in uniqueLiterals) { + uniqueLiteral = featuresBySymbolizer[uniqueLiterals[l]][1]; + if (literal.equals(uniqueLiteral)) { + literal = uniqueLiteral; + break; } } - numLiterals = literals.length; - for (j = 0; j < numLiterals; ++j) { - literal = literals[j]; - for (l in uniqueLiterals) { - uniqueLiteral = featuresBySymbolizer[uniqueLiterals[l]][1]; - if (literal.equals(uniqueLiteral)) { - literal = uniqueLiteral; - break; - } - } - key = goog.getUid(literal); - if (!goog.object.containsKey(uniqueLiterals, key)) { - uniqueLiterals[key] = featuresBySymbolizer.length; - featuresBySymbolizer.push([ - /** @type {Array.} */ ([]), - /** @type {ol.style.Literal} */ (literal), - /** @type {Array} */ ([]) - ]); - } - item = featuresBySymbolizer[uniqueLiterals[key]]; - item[0].push(feature); - if (literal instanceof ol.style.TextLiteral) { - item[2].push(literals[j].text); - } + key = goog.getUid(literal); + if (!goog.object.containsKey(uniqueLiterals, key)) { + uniqueLiterals[key] = featuresBySymbolizer.length; + featuresBySymbolizer.push([ + /** @type {Array.} */ ([]), + /** @type {ol.style.Literal} */ (literal), + /** @type {Array} */ ([]) + ]); + } + item = featuresBySymbolizer[uniqueLiterals[key]]; + item[0].push(feature); + if (literal instanceof ol.style.TextLiteral) { + item[2].push(literals[j].text); } } } diff --git a/src/ol/style/fillsymbolizer.js b/src/ol/style/fillsymbolizer.js index 9b734a76d8..55e7491557 100644 --- a/src/ol/style/fillsymbolizer.js +++ b/src/ol/style/fillsymbolizer.js @@ -45,17 +45,25 @@ goog.inherits(ol.style.Fill, ol.style.Symbolizer); * @inheritDoc * @return {ol.style.PolygonLiteral} Literal shape symbolizer. */ -ol.style.Fill.prototype.createLiteral = function(type, opt_feature) { +ol.style.Fill.prototype.createLiteral = function(featureOrType) { + var feature, type; + if (featureOrType instanceof ol.Feature) { + feature = featureOrType; + var geometry = feature.getGeometry(); + type = geometry ? geometry.getType() : null; + } else { + type = featureOrType; + } var literal = null; if (type === ol.geom.GeometryType.POLYGON || type === ol.geom.GeometryType.MULTIPOLYGON) { - var color = ol.expr.evaluateFeature(this.color_, opt_feature); + var color = ol.expr.evaluateFeature(this.color_, feature); goog.asserts.assertString( color, 'color must be a string'); - var opacity = ol.expr.evaluateFeature(this.opacity_, opt_feature); + var opacity = ol.expr.evaluateFeature(this.opacity_, feature); goog.asserts.assertNumber( opacity, 'color must be a number'); diff --git a/src/ol/style/iconsymbolizer.js b/src/ol/style/iconsymbolizer.js index e5036091ea..a2cf9671ed 100644 --- a/src/ol/style/iconsymbolizer.js +++ b/src/ol/style/iconsymbolizer.js @@ -71,37 +71,52 @@ ol.style.Icon = function(options) { * @inheritDoc * @return {ol.style.IconLiteral} Literal shape symbolizer. */ -ol.style.Icon.prototype.createLiteral = function(type, opt_feature) { - - var url = ol.expr.evaluateFeature(this.url_, opt_feature); - goog.asserts.assertString(url, 'url must be a string'); - goog.asserts.assert(url != '#', 'url must not be "#"'); - - var width; - if (!goog.isNull(this.width_)) { - width = ol.expr.evaluateFeature(this.width_, opt_feature); - goog.asserts.assertNumber(width, 'width must be a number'); +ol.style.Icon.prototype.createLiteral = function(featureOrType) { + var feature, type; + if (featureOrType instanceof ol.Feature) { + feature = featureOrType; + var geometry = feature.getGeometry(); + type = geometry ? geometry.getType() : null; + } else { + type = featureOrType; } - var height; - if (!goog.isNull(this.height_)) { - height = ol.expr.evaluateFeature(this.height_, opt_feature); - goog.asserts.assertNumber(height, 'height must be a number'); + var literal = null; + if (type === ol.geom.GeometryType.POINT || + type === ol.geom.GeometryType.MULTIPOINT) { + + var url = ol.expr.evaluateFeature(this.url_, feature); + goog.asserts.assertString(url, 'url must be a string'); + goog.asserts.assert(url != '#', 'url must not be "#"'); + + var width; + if (!goog.isNull(this.width_)) { + width = ol.expr.evaluateFeature(this.width_, feature); + goog.asserts.assertNumber(width, 'width must be a number'); + } + + var height; + if (!goog.isNull(this.height_)) { + height = ol.expr.evaluateFeature(this.height_, feature); + goog.asserts.assertNumber(height, 'height must be a number'); + } + + var opacity = ol.expr.evaluateFeature(this.opacity_, feature); + goog.asserts.assertNumber(opacity, 'opacity must be a number'); + + var rotation = ol.expr.evaluateFeature(this.rotation_, feature); + goog.asserts.assertNumber(rotation, 'rotation must be a number'); + + literal = new ol.style.IconLiteral({ + url: url, + width: width, + height: height, + opacity: opacity, + rotation: rotation + }); } - var opacity = ol.expr.evaluateFeature(this.opacity_, opt_feature); - goog.asserts.assertNumber(opacity, 'opacity must be a number'); - - var rotation = ol.expr.evaluateFeature(this.rotation_, opt_feature); - goog.asserts.assertNumber(rotation, 'rotation must be a number'); - - return new ol.style.IconLiteral({ - url: url, - width: width, - height: height, - opacity: opacity, - rotation: rotation - }); + return literal; }; diff --git a/src/ol/style/shapesymbolizer.js b/src/ol/style/shapesymbolizer.js index 0cbfabb2fa..bbf4806cee 100644 --- a/src/ol/style/shapesymbolizer.js +++ b/src/ol/style/shapesymbolizer.js @@ -60,34 +60,42 @@ ol.style.Shape = function(options) { * @inheritDoc * @return {ol.style.ShapeLiteral} Literal shape symbolizer. */ -ol.style.Shape.prototype.createLiteral = function(type, opt_feature) { - var literal = null; +ol.style.Shape.prototype.createLiteral = function(featureOrType) { + var feature, type; + if (featureOrType instanceof ol.Feature) { + feature = featureOrType; + var geometry = feature.getGeometry(); + type = geometry ? geometry.getType() : null; + } else { + type = featureOrType; + } + var literal = null; if (type === ol.geom.GeometryType.POINT || type === ol.geom.GeometryType.MULTIPOINT) { - var size = ol.expr.evaluateFeature(this.size_, opt_feature); + var size = ol.expr.evaluateFeature(this.size_, feature); goog.asserts.assertNumber(size, 'size must be a number'); var fillColor, fillOpacity; if (!goog.isNull(this.fill_)) { - fillColor = ol.expr.evaluateFeature(this.fill_.getColor(), opt_feature); + fillColor = ol.expr.evaluateFeature(this.fill_.getColor(), feature); goog.asserts.assertString( fillColor, 'fillColor must be a string'); - fillOpacity = ol.expr.evaluateFeature(this.fill_.getOpacity(), opt_feature); + fillOpacity = ol.expr.evaluateFeature(this.fill_.getOpacity(), feature); goog.asserts.assertNumber( fillOpacity, 'fillOpacity must be a number'); } var strokeColor, strokeOpacity, strokeWidth; if (!goog.isNull(this.stroke_)) { - strokeColor = ol.expr.evaluateFeature(this.stroke_.getColor(), opt_feature); + strokeColor = ol.expr.evaluateFeature(this.stroke_.getColor(), feature); goog.asserts.assertString( strokeColor, 'strokeColor must be a string'); strokeOpacity = ol.expr.evaluateFeature(this.stroke_.getOpacity(), - opt_feature); + feature); goog.asserts.assertNumber( strokeOpacity, 'strokeOpacity must be a number'); - strokeWidth = ol.expr.evaluateFeature(this.stroke_.getWidth(), opt_feature); + strokeWidth = ol.expr.evaluateFeature(this.stroke_.getWidth(), feature); goog.asserts.assertNumber( strokeWidth, 'strokeWidth must be a number'); } diff --git a/src/ol/style/strokesymbolizer.js b/src/ol/style/strokesymbolizer.js index 189bf1d1ee..4520b83dbf 100644 --- a/src/ol/style/strokesymbolizer.js +++ b/src/ol/style/strokesymbolizer.js @@ -56,17 +56,26 @@ goog.inherits(ol.style.Stroke, ol.style.Symbolizer); * @inheritDoc * @return {ol.style.LineLiteral|ol.style.PolygonLiteral} Symbolizer literal. */ -ol.style.Stroke.prototype.createLiteral = function(type, opt_feature) { +ol.style.Stroke.prototype.createLiteral = function(featureOrType) { + var feature, type; + if (featureOrType instanceof ol.Feature) { + feature = featureOrType; + var geometry = feature.getGeometry(); + type = geometry ? geometry.getType() : null; + } else { + type = featureOrType; + } + var color = ol.expr.evaluateFeature( - this.color_, opt_feature); + this.color_, feature); goog.asserts.assertString(color, 'color must be a string'); var opacity = ol.expr.evaluateFeature( - this.opacity_, opt_feature); + this.opacity_, feature); goog.asserts.assertNumber(opacity, 'opacity must be a number'); var width = ol.expr.evaluateFeature( - this.width_, opt_feature); + this.width_, feature); goog.asserts.assertNumber(width, 'width must be a number'); var literal = null; @@ -85,6 +94,7 @@ ol.style.Stroke.prototype.createLiteral = function(type, opt_feature) { strokeWidth: width }); } + return literal; }; diff --git a/src/ol/style/style.js b/src/ol/style/style.js index ed92d99d0b..8401fafc56 100644 --- a/src/ol/style/style.js +++ b/src/ol/style/style.js @@ -35,22 +35,17 @@ ol.style.Style = function(options) { ol.style.Style.prototype.apply = function(feature) { var rules = this.rules_, literals = [], - geometry = feature.getGeometry(), rule, symbolizers; - var type = geometry ? geometry.getType() : null; - if (!goog.isNull(type)) { - for (var i = 0, ii = rules.length; i < ii; ++i) { - rule = rules[i]; - if (rule.applies(feature)) { - symbolizers = rule.getSymbolizers(); - for (var j = 0, jj = symbolizers.length; j < jj; ++j) { - literals.push(symbolizers[j].createLiteral(type, feature)); - } + for (var i = 0, ii = rules.length; i < ii; ++i) { + rule = rules[i]; + if (rule.applies(feature)) { + symbolizers = rule.getSymbolizers(); + for (var j = 0, jj = symbolizers.length; j < jj; ++j) { + literals.push(symbolizers[j].createLiteral(feature)); } } - literals = ol.style.Style.reduceLiterals_(literals); } - return literals; + return ol.style.Style.reduceLiterals_(literals); }; @@ -87,15 +82,15 @@ ol.style.Style.defaults = new ol.style.Style({ /** * Given an array of symbolizers, generate an array of literals. * @param {Array.} symbolizers List of symbolizers. - * @param {ol.geom.GeometryType} type Geometry type. - * @param {ol.Feature=} opt_feature Optional feature. + * @param {ol.Feature|ol.geom.GeometryType} featureOrType Feature or geometry + * type. * @return {Array.} Array of literals. */ -ol.style.Style.createLiterals = function(symbolizers, type, opt_feature) { +ol.style.Style.createLiterals = function(symbolizers, featureOrType) { var length = symbolizers.length; var literals = new Array(length); for (var i = 0; i < length; ++i) { - literals[i] = symbolizers[i].createLiteral(type, opt_feature); + literals[i] = symbolizers[i].createLiteral(featureOrType); } return ol.style.Style.reduceLiterals_(literals); } diff --git a/src/ol/style/symbolizer.js b/src/ol/style/symbolizer.js index f96cf4f083..e32a3a9c58 100644 --- a/src/ol/style/symbolizer.js +++ b/src/ol/style/symbolizer.js @@ -12,8 +12,10 @@ ol.style.Symbolizer = function() {}; /** - * @param {ol.geom.GeometryType} type Geometry type. - * @param {ol.Feature=} opt_feature Feature for evaluating expressions. + * Create a literal from the symbolizer given a complete feature or a geometry + * type. + * @param {ol.geom.GeometryType|ol.Feature} featureOrType Feature for evaluating + * expressions or a geometry type. * @return {ol.style.Literal} Literal symbolizer. */ ol.style.Symbolizer.prototype.createLiteral = goog.abstractMethod; diff --git a/src/ol/style/textsymbolizer.js b/src/ol/style/textsymbolizer.js index 1919488920..1f1961687b 100644 --- a/src/ol/style/textsymbolizer.js +++ b/src/ol/style/textsymbolizer.js @@ -67,21 +67,29 @@ goog.inherits(ol.style.Text, ol.style.Symbolizer); * @inheritDoc * @return {ol.style.TextLiteral} Literal text symbolizer. */ -ol.style.Text.prototype.createLiteral = function(type, opt_feature) { +ol.style.Text.prototype.createLiteral = function(featureOrType) { + var feature, type; + if (featureOrType instanceof ol.Feature) { + feature = featureOrType; + var geometry = feature.getGeometry(); + type = geometry ? geometry.getType() : null; + } else { + type = featureOrType; + } - var color = ol.expr.evaluateFeature(this.color_, opt_feature); + var color = ol.expr.evaluateFeature(this.color_, feature); goog.asserts.assertString(color, 'color must be a string'); - var fontFamily = ol.expr.evaluateFeature(this.fontFamily_, opt_feature); + var fontFamily = ol.expr.evaluateFeature(this.fontFamily_, feature); goog.asserts.assertString(fontFamily, 'fontFamily must be a string'); - var fontSize = ol.expr.evaluateFeature(this.fontSize_, opt_feature); + var fontSize = ol.expr.evaluateFeature(this.fontSize_, feature); goog.asserts.assertNumber(fontSize, 'fontSize must be a number'); - var text = ol.expr.evaluateFeature(this.text_, opt_feature); + var text = ol.expr.evaluateFeature(this.text_, feature); goog.asserts.assertString(text, 'text must be a string'); - var opacity = ol.expr.evaluateFeature(this.opacity_, opt_feature); + var opacity = ol.expr.evaluateFeature(this.opacity_, feature); goog.asserts.assertNumber(opacity, 'opacity must be a number'); return new ol.style.TextLiteral({ diff --git a/test/spec/ol/style/fillsymbolizer.test.js b/test/spec/ol/style/fillsymbolizer.test.js index 69aed88656..14797ced49 100644 --- a/test/spec/ol/style/fillsymbolizer.test.js +++ b/test/spec/ol/style/fillsymbolizer.test.js @@ -31,11 +31,12 @@ describe('ol.style.Fill', function() { var feature = new ol.Feature({ value: 42, - fillAttr: '#ff0000' + fillAttr: '#ff0000', + geometry: new ol.geom.Polygon( + [[[0, 0], [1, 0], [1, 1], [0, 1], [0, 0]]]) }); - var literal = symbolizer.createLiteral(ol.geom.GeometryType.POLYGON, - feature); + var literal = symbolizer.createLiteral(feature); expect(literal).to.be.a(ol.style.PolygonLiteral); expect(literal.fillOpacity).to.be(42 / 100); expect(literal.fillColor).to.be('#ff0000'); @@ -158,5 +159,6 @@ goog.require('ol.Feature'); goog.require('ol.expr'); goog.require('ol.expr.Literal'); goog.require('ol.geom.GeometryType'); +goog.require('ol.geom.Polygon'); goog.require('ol.style.Fill'); goog.require('ol.style.PolygonLiteral'); diff --git a/test/spec/ol/style/iconsymbolizer.test.js b/test/spec/ol/style/iconsymbolizer.test.js index 342f27b871..8433a29435 100644 --- a/test/spec/ol/style/iconsymbolizer.test.js +++ b/test/spec/ol/style/iconsymbolizer.test.js @@ -48,8 +48,7 @@ describe('ol.style.Icon', function() { geometry: new ol.geom.Point([1, 2]) }); - var literal = symbolizer.createLiteral(ol.geom.GeometryType.POINT, - feature); + var literal = symbolizer.createLiteral(feature); expect(literal).to.be.a(ol.style.IconLiteral); expect(literal.height).to.be(42); expect(literal.width).to.be(.42); diff --git a/test/spec/ol/style/shapesymbolizer.test.js b/test/spec/ol/style/shapesymbolizer.test.js index a0a4c82bec..ceb7cd8be3 100644 --- a/test/spec/ol/style/shapesymbolizer.test.js +++ b/test/spec/ol/style/shapesymbolizer.test.js @@ -43,8 +43,7 @@ describe('ol.style.Shape', function() { geometry: new ol.geom.Point([1, 2]) }); - var literal = symbolizer.createLiteral(ol.geom.GeometryType.POINT, - feature); + var literal = symbolizer.createLiteral(feature); expect(literal).to.be.a(ol.style.ShapeLiteral); expect(literal.size).to.be(42); expect(literal.fillOpacity).to.be(0.4); diff --git a/test/spec/ol/style/strokesymbolizer.test.js b/test/spec/ol/style/strokesymbolizer.test.js index 51caa562c3..2dd1c44b8c 100644 --- a/test/spec/ol/style/strokesymbolizer.test.js +++ b/test/spec/ol/style/strokesymbolizer.test.js @@ -32,11 +32,11 @@ describe('ol.style.Stroke', function() { var feature = new ol.Feature({ value: 42, - widthAttr: 1.5 + widthAttr: 1.5, + geometry: new ol.geom.LineString([[1, 2], [3, 4]]) }); - var literal = symbolizer.createLiteral(ol.geom.GeometryType.LINESTRING, - feature); + var literal = symbolizer.createLiteral(feature); expect(literal).to.be.a(ol.style.LineLiteral); expect(literal.strokeOpacity).to.be(42 / 100); expect(literal.strokeWidth).to.be(1.5); diff --git a/test/spec/ol/style/textsymbolizer.test.js b/test/spec/ol/style/textsymbolizer.test.js index a55c4bb94c..85a4113fb9 100644 --- a/test/spec/ol/style/textsymbolizer.test.js +++ b/test/spec/ol/style/textsymbolizer.test.js @@ -47,8 +47,7 @@ describe('ol.style.Text', function() { opacityAttr: 0.4 }); - var literal = symbolizer.createLiteral(ol.geom.GeometryType.POINT, - feature); + var literal = symbolizer.createLiteral(feature); expect(literal).to.be.a(ol.style.TextLiteral); expect(literal.color).to.be('#ff0000'); expect(literal.fontFamily).to.be('Dingbats');