Skip to content
This repository was archived by the owner on Jan 12, 2024. It is now read-only.

Support Layout and Format nodes in text and shield symbolizers #358

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions lib/carto/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,10 @@ var carto = {

[ 'call', 'color', 'comment', 'definition', 'dimension',
'element', 'expression', 'filterset', 'filter', 'field',
'keyword', 'layer', 'literal', 'operation', 'quoted', 'imagefilter',
'reference', 'rule', 'ruleset', 'selector', 'style', 'url', 'value',
'variable', 'zoom', 'invalid', 'fontset'
'keyword', 'layer', 'literal', 'operation', 'pseudo',
'quoted', 'imagefilter', 'reference', 'rendernode',
'rule', 'ruleset', 'selector', 'style', 'subset', 'url',
'value', 'variable', 'zoom', 'invalid', 'fontset'
].forEach(function(n) {
require('./tree/' + n);
});
Expand Down
34 changes: 31 additions & 3 deletions lib/carto/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ carto.Parser = function Parser(env) {
primary: function() {
var node, root = [];

while ((node = $(this.rule) || $(this.ruleset) ||
while ((node = $(this.rule) || $(this.ruleset) || $(this.subset) ||
$(this.comment)) ||
$(/^[\s\n]+/) || (node = $(this.invalid))) {
if (node) root.push(node);
Expand Down Expand Up @@ -602,6 +602,34 @@ carto.Parser = function Parser(env) {
}
},

pseudo: function() {
var s = $(/^::([\w\-]+)(?:\(([0-9]+)\))?/);
if (s) return new tree.Pseudo(s[1], s[2]);
},

subset: function() {
var symbolizer,
p, pseudoelements = [];

save();

symbolizer = $(/^[\w\-]+(?:\/[\w\-]+)*/);
while (p = $(this.pseudo)) {
pseudoelements.push(p);
}
if (pseudoelements.length > 0 && $('{')) {
var node, rules = [], subsets = [];

while ((node = $(this.rule) || $(this.subset) || $(this.comment)) || $(/^[\s\n]+/)) {
rules.push(node);
}
if ($('}')) {
return new tree.Subset(symbolizer, pseudoelements, rules);
}
}
restore();
},

// The `block` rule is used by `ruleset`
// It's a wrapper around the `primary` rule, with added `{}`.
block: function() {
Expand All @@ -614,7 +642,7 @@ carto.Parser = function Parser(env) {

// div, .class, body > p {...}
ruleset: function() {
var selectors = [], s, f, l, rules, filters = [];
var selectors = [], s, sub, rules, filters = [];
save();

while (s = $(this.selector)) {
Expand All @@ -627,7 +655,7 @@ carto.Parser = function Parser(env) {
while ($(this.comment)) {}
}

if (selectors.length > 0 && (rules = $(this.block))) {
if ((selectors.length > 0 || sub) && (rules = $(this.block))) {
if (selectors.length === 1 &&
selectors[0].elements.length &&
selectors[0].elements[0].value === 'Map') {
Expand Down
1 change: 1 addition & 0 deletions lib/carto/renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ carto.Renderer.prototype.render = function render(m) {
function addRules(current, definition, byFilter, env) {
var newFilters = definition.filters,
newRules = definition.rules,
newSubdef = definition.subdefinitions,
updatedFilters, clone, previous;

// The current definition might have been split up into
Expand Down
69 changes: 12 additions & 57 deletions lib/carto/tree/definition.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ tree.Definition.prototype.clone = function(filters) {
var clone = Object.create(tree.Definition.prototype);
clone.rules = this.rules.slice();
clone.ruleIndex = _.clone(this.ruleIndex);
clone.subdefinitions = _.clone(this.subdefinitions);
clone.filters = filters ? filters : this.filters.clone();
clone.attachment = this.attachment;
return clone;
Expand Down Expand Up @@ -70,12 +71,6 @@ tree.Definition.prototype.appliesTo = function(id, classes) {
return true;
};

function symbolizerName(symbolizer) {
function capitalize(str) { return str[1].toUpperCase(); }
return symbolizer.charAt(0).toUpperCase() +
symbolizer.slice(1).replace(/\-./, capitalize) + 'Symbolizer';
}

// Get a simple list of the symbolizers, in order
function symbolizerList(sym_order) {
return sym_order.sort(function(a, b) { return a[1] - b[1]; })
Expand All @@ -89,8 +84,8 @@ tree.Definition.prototype.symbolizersToXML = function(env, symbolizers, zoom) {
var sym_order = [], indexes = [];
for (var key in symbolizers) {
indexes = [];
for (var prop in symbolizers[key]) {
indexes.push(symbolizers[key][prop].index);
for (var prop in symbolizers[key].attributes) {
indexes.push(symbolizers[key].attributes[prop].index);
}
var min_idx = Math.min.apply(Math, indexes);
sym_order.push([key, min_idx]);
Expand All @@ -100,55 +95,16 @@ tree.Definition.prototype.symbolizersToXML = function(env, symbolizers, zoom) {
var sym_count = 0;

for (var i = 0; i < sym_order.length; i++) {
var attributes = symbolizers[sym_order[i]];
var symbolizer = sym_order[i].split('/').pop();
var symbolizer = symbolizers[sym_order[i]];

// Skip the magical * symbolizer which is used for universal properties
// which are bubbled up to Style elements intead of Symbolizer elements.
if (symbolizer === '*') continue;
if (symbolizer.name === '*') continue;
sym_count++;

var fail = tree.Reference.requiredProperties(symbolizer, attributes);
if (fail) {
var rule = attributes[Object.keys(attributes).shift()];
env.error({
message: fail,
index: rule.index,
filename: rule.filename
});
}

var name = symbolizerName(symbolizer);

var selfclosing = true, tagcontent;
xml += ' <' + name + ' ';
for (var j in attributes) {
if (symbolizer === 'map') env.error({
message: 'Map properties are not permitted in other rules',
index: attributes[j].index,
filename: attributes[j].filename
});
var x = tree.Reference.selector(attributes[j].name);
if (x && x.serialization && x.serialization === 'content') {
selfclosing = false;
tagcontent = attributes[j].ev(env).toXML(env, true);
} else if (x && x.serialization && x.serialization === 'tag') {
selfclosing = false;
tagcontent = attributes[j].ev(env).toXML(env, true);
} else {
xml += attributes[j].ev(env).toXML(env) + ' ';
}
}
if (selfclosing) {
xml += '/>\n';
} else if (typeof tagcontent !== "undefined") {
if (tagcontent.indexOf('<') != -1) {
xml += '>' + tagcontent + '</' + name + '>\n';
} else {
xml += '><![CDATA[' + tagcontent + ']]></' + name + '>\n';
}
}
xml += symbolizer.toXML(env);
}

if (!sym_count || !xml) return '';
return ' <Rule>\n' + xml + ' </Rule>\n';
};
Expand All @@ -161,14 +117,13 @@ tree.Definition.prototype.collectSymbolizers = function(zooms, i) {
for (var j = i; j < this.rules.length; j++) {
child = this.rules[j];
var key = child.instance + '/' + child.symbolizer;
if (zooms.current & child.zoom &&
(!(key in symbolizers) ||
(!(child.name in symbolizers[key])))) {
zooms.current &= child.zoom;
if (zooms.current & child.zoom) {
if (!(key in symbolizers)) {
symbolizers[key] = {};
symbolizers[key] = new tree.SymbolizerNode(child.symbolizer);
}
if (symbolizers[key].addAttribute(child)) {
zooms.current &= child.zoom;
}
symbolizers[key][child.name] = child;
}
}

Expand Down
8 changes: 8 additions & 0 deletions lib/carto/tree/pseudo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
(function(tree) {

tree.Pseudo = function Pseudo(name, index) {
this.name = name;
this.index = index || 0;
};

})(require('../tree'));
Loading