Files
openlayers/src/ol/parser/ogc/sldparser_v1.js
2013-11-04 14:26:05 +01:00

910 lines
32 KiB
JavaScript

goog.provide('ol.parser.ogc.SLD_v1');
goog.require('goog.asserts');
goog.require('goog.dom.xml');
goog.require('goog.object');
goog.require('ol.expr.Literal');
goog.require('ol.parser.XML');
goog.require('ol.parser.ogc.Filter_v1_0_0');
goog.require('ol.style.Fill');
goog.require('ol.style.Icon');
goog.require('ol.style.Rule');
goog.require('ol.style.Shape');
goog.require('ol.style.Stroke');
goog.require('ol.style.Style');
goog.require('ol.style.Text');
/**
* Read Styled Layer Descriptor (SLD).
*
* @constructor
* @extends {ol.parser.XML}
*/
ol.parser.ogc.SLD_v1 = function() {
this.defaultNamespaceURI = 'http://www.opengis.net/sld';
this.readers = {
'http://www.opengis.net/sld': {
'StyledLayerDescriptor': function(node, sld) {
sld.version = node.getAttribute('version');
this.readChildNodes(node, sld);
},
'Name': function(node, obj) {
obj.name = this.getChildValue(node);
},
'Title': function(node, obj) {
obj.title = this.getChildValue(node);
},
'Abstract': function(node, obj) {
obj.description = this.getChildValue(node);
},
'NamedLayer': function(node, sld) {
var layer = {
userStyles: [],
namedStyles: []
};
this.readChildNodes(node, layer);
sld.namedLayers[layer.name] = layer;
},
'NamedStyle': function(node, layer) {
layer.namedStyles.push(
this.getChildValue(node.firstChild)
);
},
'UserStyle': function(node, layer) {
var obj = {rules: []};
this.featureTypeCounter = -1;
this.readChildNodes(node, obj);
layer.userStyles.push(new ol.style.Style(obj));
},
'IsDefault': function(node, style) {
if (this.getChildValue(node) === '1') {
style.isDefault = true;
}
},
'FeatureTypeStyle': function(node, style) {
++this.featureTypeCounter;
var obj = {
rules: style.rules
};
this.readChildNodes(node, obj);
},
'Rule': function(node, obj) {
var config = {symbolizers: []};
this.readChildNodes(node, config);
var rule = new ol.style.Rule(config);
obj.rules.push(rule);
},
'ElseFilter': function(node, rule) {
rule.elseFilter = true;
},
'MinScaleDenominator': function(node, rule) {
rule.minResolution = this.getResolutionFromScaleDenominator_(
parseFloat(this.getChildValue(node)));
},
'MaxScaleDenominator': function(node, rule) {
rule.maxResolution = this.getResolutionFromScaleDenominator_(
parseFloat(this.getChildValue(node)));
},
'TextSymbolizer': function(node, rule) {
var config = {};
this.readChildNodes(node, config);
config.color = config.fill.fillColor;
delete config.fill;
config.zIndex = this.featureTypeCounter;
rule.symbolizers.push(
new ol.style.Text(/** @type {ol.style.TextOptions} */(config))
);
},
'LabelPlacement': function(node, symbolizer) {
this.readChildNodes(node, symbolizer);
},
'PointPlacement': function(node, symbolizer) {
var config = {};
this.readChildNodes(node, config);
config.labelRotation = config.rotation;
delete config.rotation;
var labelAlign,
x = symbolizer.labelAnchorPointX,
y = symbolizer.labelAnchorPointY;
if (x <= 1 / 3) {
labelAlign = 'l';
} else if (x > 1 / 3 && x < 2 / 3) {
labelAlign = 'c';
} else if (x >= 2 / 3) {
labelAlign = 'r';
}
if (y <= 1 / 3) {
labelAlign += 'b';
} else if (y > 1 / 3 && y < 2 / 3) {
labelAlign += 'm';
} else if (y >= 2 / 3) {
labelAlign += 't';
}
config.labelAlign = labelAlign;
goog.object.extend(symbolizer, config);
},
'AnchorPoint': function(node, symbolizer) {
this.readChildNodes(node, symbolizer);
},
'AnchorPointX': function(node, symbolizer) {
var ogcreaders = this.readers['http://www.opengis.net/ogc'];
var labelAnchorPointX = ogcreaders._expression.call(this, node);
// always string, could be empty string
if (labelAnchorPointX) {
symbolizer.labelAnchorPointX = labelAnchorPointX;
}
},
'AnchorPointY': function(node, symbolizer) {
var ogcreaders = this.readers['http://www.opengis.net/ogc'];
var labelAnchorPointY = ogcreaders._expression.call(this, node);
// always string, could be empty string
if (labelAnchorPointY) {
symbolizer.labelAnchorPointY = labelAnchorPointY;
}
},
'Displacement': function(node, symbolizer) {
this.readChildNodes(node, symbolizer);
},
'DisplacementX': function(node, symbolizer) {
var ogcreaders = this.readers['http://www.opengis.net/ogc'];
var labelXOffset = ogcreaders._expression.call(this, node);
// always string, could be empty string
if (labelXOffset) {
symbolizer.labelXOffset = labelXOffset;
}
},
'DisplacementY': function(node, symbolizer) {
var ogcreaders = this.readers['http://www.opengis.net/ogc'];
var labelYOffset = ogcreaders._expression.call(this, node);
// always string, could be empty string
if (labelYOffset) {
symbolizer.labelYOffset = labelYOffset;
}
},
'LinePlacement': function(node, symbolizer) {
this.readChildNodes(node, symbolizer);
},
'PerpendicularOffset': function(node, symbolizer) {
var ogcreaders = this.readers['http://www.opengis.net/ogc'];
var labelPerpendicularOffset = ogcreaders._expression.call(this, node);
// always string, could be empty string
if (labelPerpendicularOffset) {
symbolizer.labelPerpendicularOffset = labelPerpendicularOffset;
}
},
'Label': function(node, symbolizer) {
var ogcreaders = this.readers['http://www.opengis.net/ogc'];
var value = ogcreaders._expression.call(this, node);
if (value) {
symbolizer.text = value;
}
},
'Font': function(node, symbolizer) {
this.readChildNodes(node, symbolizer);
},
'Halo': function(node, symbolizer) {
var obj = {};
this.readChildNodes(node, obj);
symbolizer.stroke = new ol.style.Stroke({
color: goog.isDef(obj.fill.fillColor) ? obj.fill.fillColor :
ol.parser.ogc.SLD_v1.defaults_.haloColor,
width: goog.isDef(obj.haloRadius) ? obj.haloRadius * 2 :
ol.parser.ogc.SLD_v1.defaults_.haloRadius,
opacity: goog.isDef(obj.fill.fillOpacity) ? obj.fill.fillOpacity :
ol.parser.ogc.SLD_v1.defaults_.haloOpacity
});
},
'Radius': function(node, symbolizer) {
var ogcreaders = this.readers['http://www.opengis.net/ogc'];
var radius = ogcreaders._expression.call(this, node);
goog.asserts.assertInstanceof(radius, ol.expr.Literal,
'radius expected to be an ol.expr.Literal');
if (goog.isDef(radius)) {
symbolizer.haloRadius = radius.getValue();
}
},
'RasterSymbolizer': function(node, rule) {
var config = {};
this.readChildNodes(node, config);
config.zIndex = this.featureTypeCounter;
/* TODO
rule.symbolizers.push(
new OpenLayers.Symbolizer.Raster(config)
);
*/
},
'Geometry': function(node, obj) {
obj.geometry = {};
this.readChildNodes(node, obj.geometry);
},
'ColorMap': function(node, symbolizer) {
symbolizer.colorMap = [];
this.readChildNodes(node, symbolizer.colorMap);
},
'ColorMapEntry': function(node, colorMap) {
var q = node.getAttribute('quantity');
var o = node.getAttribute('opacity');
colorMap.push({
color: node.getAttribute('color'),
quantity: q !== null ? parseFloat(q) : undefined,
label: node.getAttribute('label') || undefined,
opacity: o !== null ? parseFloat(o) : undefined
});
},
'LineSymbolizer': function(node, rule) {
var config = {};
this.readChildNodes(node, config);
config.zIndex = this.featureTypeCounter;
rule.symbolizers.push(
new ol.style.Stroke(config)
);
},
'PolygonSymbolizer': function(node, rule) {
var config = {};
this.readChildNodes(node, config);
config.zIndex = this.featureTypeCounter;
if (goog.isDef(config.fill)) {
var fill = {
color: config.fill.fillColor.getValue(),
opacity: goog.isDef(config.fill.fillOpacity) ?
config.fill.fillOpacity :
ol.parser.ogc.SLD_v1.defaults_.fillOpacity
};
rule.symbolizers.push(
new ol.style.Fill(fill)
);
delete config.fill;
}
if (goog.isDef(config.stroke)) {
var stroke = {
color: config.stroke.strokeColor.getValue(),
opacity: goog.isDef(config.stroke.strokeOpacity) ?
config.stroke.strokeOpacity :
ol.parser.ogc.SLD_v1.defaults_.strokeOpacity,
width: goog.isDef(config.stroke.strokeWidth) ?
config.stroke.strokeWidth :
ol.parser.ogc.SLD_v1.defaults_.strokeWidth
};
rule.symbolizers.push(
new ol.style.Stroke(stroke)
);
delete config.stroke;
}
},
'PointSymbolizer': function(node, rule) {
var config = {};
this.readChildNodes(node, config);
config.zIndex = this.featureTypeCounter;
if (config.fill) {
config.fill = new ol.style.Fill(config.fill);
}
if (config.stroke) {
config.stroke = new ol.style.Stroke(config.stroke);
}
// TODO shape or icon?
rule.symbolizers.push(
new ol.style.Shape(config)
);
},
'Stroke': function(node, symbolizer) {
var stroke = {};
this.readChildNodes(node, stroke);
symbolizer.stroke = stroke;
},
'Fill': function(node, symbolizer) {
var fill = {};
this.readChildNodes(node, fill);
symbolizer.fill = fill;
},
'CssParameter': function(node, symbolizer) {
var cssProperty = node.getAttribute('name');
var symProperty = ol.parser.ogc.SLD_v1.cssMap_[cssProperty];
// for labels, fill should map to fontColor and fill-opacity
// to fontOpacity
if (symbolizer.label) {
if (cssProperty === 'fill') {
symProperty = 'fontColor';
} else if (cssProperty === 'fill-opacity') {
symProperty = 'fontOpacity';
}
}
if (symProperty) {
// Limited support for parsing of OGC expressions
var ogcreaders = this.readers['http://www.opengis.net/ogc'];
var value = ogcreaders._expression.call(this, node);
// always string, could be an empty string
if (value) {
symbolizer[symProperty] = value;
}
}
},
'Graphic': function(node, symbolizer) {
symbolizer.graphic = true;
var graphic = {};
// painter's order not respected here, clobber previous with next
this.readChildNodes(node, graphic);
// directly properties with names that match symbolizer properties
var properties = [
'stroke', 'strokeColor', 'strokeWidth', 'strokeOpacity',
'strokeLinecap', 'fill', 'fillColor', 'fillOpacity',
'graphicName', 'rotation', 'graphicFormat'
];
var prop, value;
for (var i = 0, ii = properties.length; i < ii; ++i) {
prop = properties[i];
value = graphic[prop];
if (goog.isDef(value)) {
symbolizer[prop] = value;
}
}
// set other generic properties with specific graphic property names
if (goog.isDef(graphic.opacity)) {
symbolizer.graphicOpacity = graphic.opacity;
}
if (goog.isDef(graphic.size)) {
var pointRadius = graphic.size / 2;
if (isNaN(pointRadius)) {
// likely a property name
symbolizer.graphicWidth = graphic.size;
} else {
symbolizer.pointRadius = graphic.size / 2;
}
}
if (goog.isDef(graphic.href)) {
symbolizer.externalGraphic = graphic.href;
}
if (goog.isDef(graphic.rotation)) {
symbolizer.rotation = graphic.rotation;
}
},
'ExternalGraphic': function(node, graphic) {
this.readChildNodes(node, graphic);
},
'Mark': function(node, graphic) {
this.readChildNodes(node, graphic);
},
'WellKnownName': function(node, graphic) {
graphic.graphicName = this.getChildValue(node);
},
'Opacity': function(node, obj) {
var ogcreaders = this.readers['http://www.opengis.net/ogc'];
var opacity = ogcreaders._expression.call(this, node);
// always string, could be empty string
if (opacity) {
obj.opacity = opacity;
}
},
'Size': function(node, obj) {
var ogcreaders = this.readers['http://www.opengis.net/ogc'];
var size = ogcreaders._expression.call(this, node);
// always string, could be empty string
if (size) {
obj.size = size;
}
},
'Rotation': function(node, obj) {
var ogcreaders = this.readers['http://www.opengis.net/ogc'];
var rotation = ogcreaders._expression.call(this, node);
// always string, could be empty string
if (rotation) {
obj.rotation = rotation;
}
},
'OnlineResource': function(node, obj) {
obj.href = this.getAttributeNS(
node, 'http://www.w3.org/1999/xlink', 'href'
);
},
'Format': function(node, graphic) {
graphic.graphicFormat = this.getChildValue(node);
}
}
};
this.writers = {
'http://www.opengis.net/sld': {
'StyledLayerDescriptor': function(sld) {
var node = this.createElementNS('sld:StyledLayerDescriptor');
node.setAttribute('version', this.version);
if (goog.isDef(sld.name)) {
this.writeNode('Name', sld.name, null, node);
}
if (goog.isDef(sld.title)) {
this.writeNode('Title', sld.title, null, node);
}
if (goog.isDef(sld.description)) {
this.writeNode('Abstract', sld.description, null, node);
}
goog.object.forEach(sld.namedLayers, function(layer) {
this.writeNode('NamedLayer', layer, null, node);
}, this);
return node;
},
'Name': function(name) {
var node = this.createElementNS('sld:Name');
node.appendChild(this.createTextNode(name));
return node;
},
'Title': function(title) {
var node = this.createElementNS('sld:Title');
node.appendChild(this.createTextNode(title));
return node;
},
'Abstract': function(description) {
var node = this.createElementNS('sld:Abstract');
node.appendChild(this.createTextNode(description));
return node;
},
'NamedLayer': function(layer) {
var node = this.createElementNS('sld:NamedLayer');
this.writeNode('Name', layer.name, null, node);
var i, ii;
if (layer.namedStyles) {
for (i = 0, ii = layer.namedStyles.length; i < ii; ++i) {
this.writeNode('NamedStyle', layer.namedStyles[i], null, node);
}
}
if (layer.userStyles) {
for (i = 0, ii = layer.userStyles.length; i < ii; ++i) {
this.writeNode('UserStyle', layer.userStyles[i], null, node);
}
}
return node;
},
'NamedStyle': function(name) {
var node = this.createElementNS('sld:NamedStyle');
this.writeNode('Name', name, null, node);
return node;
},
'UserStyle': function(style) {
var node = this.createElementNS('sld:UserStyle');
if (style.name) {
this.writeNode('Name', style.name, null, node);
}
if (style.title) {
this.writeNode('Title', style.title, null, node);
}
if (style.description) {
this.writeNode('Abstract', style.description, null, node);
}
if (style.isDefault) {
this.writeNode('IsDefault', style.isDefault, null, node);
}
if (style.rules) {
// group style objects by symbolizer zIndex
var rulesByZ = {
0: []
};
var zValues = [0];
var rule, ruleMap, symbolizer, zIndex, clone;
for (var i = 0, ii = style.rules.length; i < ii; ++i) {
rule = style.rules[i];
var symbolizers = rule.getSymbolizers();
if (symbolizers) {
ruleMap = {};
for (var j = 0, jj = symbolizers.length; j < jj; ++j) {
symbolizer = symbolizers[j];
zIndex = symbolizer.zIndex;
if (!(zIndex in ruleMap)) {
// TODO check if clone works?
clone = goog.object.clone(rule);
clone.setSymbolizers([]);
ruleMap[zIndex] = clone;
}
// TODO check if clone works
ruleMap[zIndex].getSymbolizers().push(
goog.object.clone(symbolizer));
}
for (zIndex in ruleMap) {
if (!(zIndex in rulesByZ)) {
zValues.push(zIndex);
rulesByZ[zIndex] = [];
}
rulesByZ[zIndex].push(ruleMap[zIndex]);
}
} else {
// no symbolizers in rule
rulesByZ[0].push(goog.object.clone(rule));
}
}
// write one FeatureTypeStyle per zIndex
zValues.sort();
var rules;
for (var i = 0, ii = zValues.length; i < ii; ++i) {
rules = rulesByZ[zValues[i]];
if (rules.length > 0) {
clone = goog.object.clone(style);
clone.setRules(rulesByZ[zValues[i]]);
this.writeNode('FeatureTypeStyle', clone, null, node);
}
}
} else {
this.writeNode('FeatureTypeStyle', style, null, node);
}
return node;
},
'IsDefault': function(bool) {
var node = this.createElementNS('sld:IsDefault');
node.appendChild(this.createTextNode((bool) ? '1' : '0'));
return node;
},
'FeatureTypeStyle': function(style) {
var node = this.createElementNS('sld:FeatureTypeStyle');
// OpenLayers currently stores no Name, Title, Abstract,
// FeatureTypeName, or SemanticTypeIdentifier information
// related to FeatureTypeStyle
// add in rules
var rules = style.getRules();
for (var i = 0, ii = rules.length; i < ii; ++i) {
this.writeNode('Rule', rules[i], null, node);
}
return node;
},
'Rule': function(rule) {
var node = this.createElementNS('sld:Rule');
var filter = rule.getFilter();
if (!goog.isNull(rule.getName())) {
this.writeNode('Name', rule.getName(), null, node);
}
if (!goog.isNull(rule.getTitle())) {
this.writeNode('Title', rule.title, null, node);
}
if (rule.elseFilter) {
this.writeNode('ElseFilter', null, null, node);
} else if (filter) {
this.writeNode('Filter', filter, 'http://www.opengis.net/ogc', node);
}
var minResolution = rule.getMinResolution();
if (minResolution > 0) {
this.writeNode('MinScaleDenominator',
this.getScaleDenominatorFromResolution_(minResolution),
null, node);
}
var maxResolution = rule.getMaxResolution();
if (maxResolution < Infinity) {
this.writeNode('MaxScaleDenominator',
this.getScaleDenominatorFromResolution_(maxResolution),
null, node);
}
var type, symbolizer, symbolizers = rule.getSymbolizers();
if (symbolizers) {
for (var i = 0, ii = symbolizers.length; i < ii; ++i) {
symbolizer = symbolizers[i];
// TODO other types of symbolizers
if (symbolizer instanceof ol.style.Text) {
type = 'Text';
} else if (symbolizer instanceof ol.style.Stroke) {
type = 'Line';
} else if (symbolizer instanceof ol.style.Fill) {
type = 'Polygon';
} else if (symbolizer instanceof ol.style.Shape ||
symbolizer instanceof ol.style.Icon) {
type = 'Point';
}
if (goog.isDef(type)) {
this.writeNode(type + 'Symbolizer', symbolizer, null, node);
}
}
}
return node;
},
'PointSymbolizer': function(symbolizer) {
var node = this.createElementNS('sld:PointSymbolizer');
this.writeNode('Graphic', symbolizer, null, node);
return node;
},
'Mark': function(symbolizer) {
var node = this.createElementNS('sld:Mark');
this.writeNode('WellKnownName', symbolizer.getType(), null, node);
var fill = symbolizer.getFill();
if (!goog.isNull(fill)) {
this.writeNode('Fill', fill, null, node);
}
var stroke = symbolizer.getStroke();
if (!goog.isNull(stroke)) {
this.writeNode('Stroke', stroke, null, node);
}
return node;
},
'WellKnownName': function(name) {
var node = this.createElementNS('sld:WellKnownName');
node.appendChild(this.createTextNode(name));
return node;
},
'Graphic': function(symbolizer) {
var node = this.createElementNS('sld:Graphic');
var size;
if (symbolizer instanceof ol.style.Icon) {
this.writeNode('ExternalGraphic', symbolizer, null, node);
var opacity = symbolizer.getOpacity();
goog.asserts.assertInstanceof(opacity, ol.expr.Literal,
'Only ol.expr.Literal supported for graphicOpacity');
this.writeNode('Opacity', opacity.getValue(), null, node);
size = symbolizer.getWidth();
} else if (symbolizer instanceof ol.style.Shape) {
this.writeNode('Mark', symbolizer, null, node);
size = symbolizer.getSize();
}
goog.asserts.assertInstanceof(size, ol.expr.Literal,
'Only ol.expr.Literal supported for in Size');
this.writeNode('Size', size.getValue(), null, node);
if (symbolizer instanceof ol.style.Icon) {
var rotation = symbolizer.getRotation();
goog.asserts.assertInstanceof(rotation, ol.expr.Literal,
'Only ol.expr.Literal supported for rotation');
this.writeNode('Rotation', rotation.getValue(), null, node);
}
return node;
},
'PolygonSymbolizer': function(symbolizer) {
var node = this.createElementNS('sld:PolygonSymbolizer');
this.writeNode('Fill', symbolizer, null, node);
return node;
},
'Fill': function(symbolizer) {
var node = this.createElementNS('sld:Fill');
var fillColor = symbolizer.getColor();
var msg = 'Only ol.expr.Literal supported for Fill properties';
goog.asserts.assertInstanceof(fillColor, ol.expr.Literal, msg);
this.writeNode('CssParameter', {
value: fillColor.getValue(),
key: 'fillColor'
}, null, node);
var fillOpacity = symbolizer.getOpacity();
goog.asserts.assertInstanceof(fillOpacity, ol.expr.Literal, msg);
this.writeNode('CssParameter', {
value: fillOpacity.getValue(),
key: 'fillOpacity'
}, null, node);
return node;
},
'TextSymbolizer': function(symbolizer) {
var node = this.createElementNS('sld:TextSymbolizer');
var text = symbolizer.getText();
// TODO in SLD optional, but in ol3 required?
this.writeNode('Label', text, null, node);
// TODO in SLD optional, but in ol3 required?
this.writeNode('Font', symbolizer, null, node);
// TODO map align to labelAnchorPoint etc.
var stroke = symbolizer.getStroke();
if (!goog.isNull(stroke)) {
this.writeNode('Halo', stroke, null, node);
}
var color = symbolizer.getColor();
goog.asserts.assertInstanceof(color, ol.expr.Literal,
'font color should be ol.expr.Literal');
this.writeNode('Fill', symbolizer, null, node);
return node;
},
'Halo': function(symbolizer) {
var node = this.createElementNS('sld:Halo');
goog.asserts.assertInstanceof(symbolizer.getWidth(), ol.expr.Literal,
'Only ol.expr.Literal supported for haloRadius');
this.writeNode('Radius', symbolizer.getWidth().getValue() / 2, null,
node);
this.writeNode('Fill', symbolizer, null, node);
return node;
},
'Radius': function(value) {
var node = this.createElementNS('sld:Radius');
node.appendChild(this.createTextNode(value));
return node;
},
'LineSymbolizer': function(symbolizer) {
var node = this.createElementNS('sld:LineSymbolizer');
this.writeNode('Stroke', symbolizer, null, node);
return node;
},
'Stroke': function(symbolizer) {
var node = this.createElementNS('sld:Stroke');
var strokeColor = symbolizer.getColor();
var msg = 'SLD writing of stroke properties only supported ' +
'for ol.expr.Literal';
goog.asserts.assertInstanceof(strokeColor, ol.expr.Literal, msg);
this.writeNode('CssParameter', {
value: strokeColor.getValue(),
key: 'strokeColor'
}, null, node);
var strokeOpacity = symbolizer.getOpacity();
goog.asserts.assertInstanceof(strokeOpacity, ol.expr.Literal, msg);
this.writeNode('CssParameter', {
value: strokeOpacity.getValue(),
key: 'strokeOpacity'
}, null, node);
var strokeWidth = symbolizer.getWidth();
goog.asserts.assertInstanceof(strokeWidth, ol.expr.Literal, msg);
this.writeNode('CssParameter', {
value: strokeWidth.getValue(),
key: 'strokeWidth'
}, null, node);
// TODO strokeDashstyle and strokeLinecap
return node;
},
'CssParameter': function(obj) {
// not handling ogc:expressions for now
var name = ol.parser.ogc.SLD_v1.getCssProperty_(obj.key);
if (goog.isDef(name) && obj.value !==
ol.parser.ogc.SLD_v1.defaults_[obj.key]) {
var node = this.createElementNS('sld:CssParameter');
node.setAttribute('name', name);
node.appendChild(this.createTextNode(obj.value));
return node;
}
},
'Label': function(label) {
var node = this.createElementNS('sld:Label');
this.filter_.writeOgcExpression(label, node);
return node;
},
'Font': function(symbolizer) {
var node = this.createElementNS('sld:Font');
this.writeNode('CssParameter', {
key: 'fontFamily',
value: symbolizer.getFontFamily().getValue()
}, null, node);
this.writeNode('CssParameter', {
key: 'fontSize',
value: symbolizer.getFontSize().getValue()
}, null, node);
// TODO fontWeight and fontStyle
return node;
},
'MinScaleDenominator': function(scale) {
var node = this.createElementNS('sld:MinScaleDenominator');
node.appendChild(this.createTextNode(scale));
return node;
},
'MaxScaleDenominator': function(scale) {
var node = this.createElementNS('sld:MaxScaleDenominator');
node.appendChild(this.createTextNode(scale));
return node;
},
'Size': function(value) {
var node = this.createElementNS('sld:Size');
this.filter_.writeOgcExpression(value, node);
return node;
}
}
};
this.filter_ = new ol.parser.ogc.Filter_v1_0_0();
for (var uri in this.filter_.readers) {
for (var key in this.filter_.readers[uri]) {
if (!goog.isDef(this.readers[uri])) {
this.readers[uri] = {};
}
this.readers[uri][key] = goog.bind(this.filter_.readers[uri][key],
this.filter_);
}
}
for (var uri in this.filter_.writers) {
for (var key in this.filter_.writers[uri]) {
if (!goog.isDef(this.writers[uri])) {
this.writers[uri] = {};
}
this.writers[uri][key] = goog.bind(this.filter_.writers[uri][key],
this.filter_);
}
}
goog.base(this);
};
goog.inherits(ol.parser.ogc.SLD_v1, ol.parser.XML);
/**
* @private
*/
ol.parser.ogc.SLD_v1.cssMap_ = {
'stroke': 'strokeColor',
'stroke-opacity': 'strokeOpacity',
'stroke-width': 'strokeWidth',
'stroke-linecap': 'strokeLinecap',
'stroke-dasharray': 'strokeDashstyle',
'fill': 'fillColor',
'fill-opacity': 'fillOpacity',
'font-family': 'fontFamily',
'font-size': 'fontSize',
'font-weight': 'fontWeight',
'font-style': 'fontStyle'
};
/**
* @private
*/
ol.parser.ogc.SLD_v1.defaults_ = {
fillOpacity: 1,
strokeOpacity: 1,
strokeWidth: 1,
haloColor: '#FFFFFF',
haloOpacity: 1,
haloRadius: 1
};
/**
* @private
* @param {string} sym Symbolizer property.
* @return {string|undefined} The css property that matches the symbolizer
* property.
*/
ol.parser.ogc.SLD_v1.getCssProperty_ = function(sym) {
return goog.object.findKey(ol.parser.ogc.SLD_v1.cssMap_,
function(value, key, obj) {
return (sym === value);
}
);
};
/**
* @private
* @param {number} scaleDenominator The scale denominator to convert to
* resolution.
* @return {number} resolution.
*/
ol.parser.ogc.SLD_v1.prototype.getResolutionFromScaleDenominator_ =
function(scaleDenominator) {
var dpi = 25.4 / 0.28;
var mpu = ol.METERS_PER_UNIT[this.units];
return 1 / ((1 / scaleDenominator) * (mpu * 39.37) * dpi);
};
/**
* @private
* @param {number} resolution The resolution to convert to scale denominator.
* @return {number} scale denominator.
*/
ol.parser.ogc.SLD_v1.prototype.getScaleDenominatorFromResolution_ =
function(resolution) {
var dpi = 25.4 / 0.28;
var mpu = ol.METERS_PER_UNIT[this.units];
return resolution * mpu * 39.37 * dpi;
};
/**
* @param {string|Document|Element} data Data to read.
* @param {ol.parser.SLDReadOptions=} opt_options Read options.
* @return {Object} An object representing the document.
*/
ol.parser.ogc.SLD_v1.prototype.read = function(data, opt_options) {
var units = 'm';
if (goog.isDef(opt_options) && goog.isDef(opt_options.units)) {
units = opt_options.units;
}
this.units = units;
if (goog.isString(data)) {
data = goog.dom.xml.loadXml(data);
}
if (data && data.nodeType == 9) {
data = data.documentElement;
}
var obj = {namedLayers: {}};
this.readNode(data, obj);
delete this.units;
return obj;
};
/**
* @param {Object} style The style to write out.
* @param {ol.parser.SLDWriteOptions=} opt_options Write options.
* @return {string} The serialized SLD.
*/
ol.parser.ogc.SLD_v1.prototype.write = function(style, opt_options) {
var units = 'm';
if (goog.isDef(opt_options) && goog.isDef(opt_options.units)) {
units = opt_options.units;
}
this.units = units;
var root = this.writeNode('StyledLayerDescriptor', style);
this.setAttributeNS(
root, 'http://www.w3.org/2001/XMLSchema-instance',
'xsi:schemaLocation', this.schemaLocation);
var result = this.serialize(root);
delete this.units;
return result;
};