Rewrite zoom filters as objects, support variables in zoom definitions.
This commit is contained in:
parent
3c4baaf8cb
commit
04cf9013a8
@ -598,7 +598,7 @@ carto.Parser = function Parser(env) {
|
||||
var a, attachment;
|
||||
var e, elements = [];
|
||||
var f, filters = new tree.Filterset();
|
||||
var z, zoom = tree.Zoom.all;
|
||||
var z, zooms = [];
|
||||
var segments = 0, conditions = 0;
|
||||
|
||||
while (
|
||||
@ -611,7 +611,7 @@ carto.Parser = function Parser(env) {
|
||||
if (e) {
|
||||
elements.push(e);
|
||||
} else if (z) {
|
||||
zoom &= z;
|
||||
zooms.push(z);
|
||||
conditions++;
|
||||
} else if (f) {
|
||||
filters.add(f);
|
||||
@ -630,7 +630,7 @@ carto.Parser = function Parser(env) {
|
||||
}
|
||||
|
||||
if (segments) {
|
||||
return new tree.Selector(filters, zoom, elements, attachment, conditions, memo);
|
||||
return new tree.Selector(filters, zooms, elements, attachment, conditions, memo);
|
||||
}
|
||||
},
|
||||
|
||||
@ -653,9 +653,8 @@ carto.Parser = function Parser(env) {
|
||||
var op, val;
|
||||
if ($(/^\[zoom/g) &&
|
||||
(op = $(this.entities.comparison)) &&
|
||||
(val = $(/^\d+/)) &&
|
||||
$(']')) {
|
||||
return tree.Zoom(op, val, memo);
|
||||
(val = $(this.entities.variable) || $(this.entities.dimension)) && $(']')) {
|
||||
return new tree.Zoom(op, val, memo);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -81,7 +81,7 @@ function symbolizerList(sym_order) {
|
||||
}
|
||||
|
||||
tree.Definition.prototype.symbolizersToXML = function(env, symbolizers, zoom) {
|
||||
var xml = ' <Rule>\n' + tree.Zoom.toXML(zoom).join('') +
|
||||
var xml = ' <Rule>\n' + zoom.toXML(env).join('') +
|
||||
this.filters.toXML(env);
|
||||
var key;
|
||||
|
||||
@ -183,8 +183,8 @@ tree.Definition.prototype.toXML = function(env, existing) {
|
||||
var filter = this.filters.toString();
|
||||
if (!(filter in existing)) existing[filter] = tree.Zoom.all;
|
||||
|
||||
var available = tree.Zoom.all, xml = '', zoom, symbolizers;
|
||||
var zooms = { available: tree.Zoom.all };
|
||||
var available = tree.Zoom.all, xml = '', zoom, symbolizers,
|
||||
zooms = { available: tree.Zoom.all };
|
||||
for (var i = 0; i < this.rules.length && available; i++) {
|
||||
zooms.rule = this.rules[i].zoom;
|
||||
if (!(existing[filter] & zooms.rule)) continue;
|
||||
@ -192,7 +192,7 @@ tree.Definition.prototype.toXML = function(env, existing) {
|
||||
while (zooms.current = zooms.rule & available) {
|
||||
if (symbolizers = this.collectSymbolizers(zooms, i)) {
|
||||
if (!(existing[filter] & zooms.current)) continue;
|
||||
xml += this.symbolizersToXML(env, symbolizers, existing[filter] & zooms.current);
|
||||
xml += this.symbolizersToXML(env, symbolizers, (new tree.Zoom()).setZoom(existing[filter] & zooms.current));
|
||||
existing[filter] &= ~zooms.current;
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,6 @@ tree.Filter = function Filter(key, op, val, index, filename) {
|
||||
this.id = this.key + this.op + this.val;
|
||||
};
|
||||
|
||||
|
||||
// xmlsafe, numeric, suffix
|
||||
var ops = {
|
||||
'<': [' < ', 'numeric'],
|
||||
|
@ -19,8 +19,7 @@ tree.Filterset.prototype.toXML = function(env) {
|
||||
tree.Filterset.prototype.toString = function() {
|
||||
var arr = [];
|
||||
for (var id in this.filters) arr.push(this.filters[id].id);
|
||||
arr.sort();
|
||||
return arr.join('\t');
|
||||
return arr.sort().join('\t');
|
||||
};
|
||||
|
||||
tree.Filterset.prototype.eval = function(env) {
|
||||
@ -40,7 +39,7 @@ tree.Filterset.prototype.clone = function() {
|
||||
|
||||
// Note: other has to be a tree.Filterset.
|
||||
tree.Filterset.prototype.cloneWith = function(other) {
|
||||
var additions;
|
||||
var additions = [];
|
||||
for (var id in other.filters) {
|
||||
var status = this.addable(other.filters[id]);
|
||||
// status is true, false or null. if it's null we don't fail this
|
||||
@ -50,14 +49,13 @@ tree.Filterset.prototype.cloneWith = function(other) {
|
||||
}
|
||||
if (status === true) {
|
||||
// Adding the filter will override another value.
|
||||
if (!additions) additions = [];
|
||||
additions.push(other.filters[id]);
|
||||
}
|
||||
}
|
||||
|
||||
// Adding the other filters doesn't make this filterset invalid, but it
|
||||
// doesn't add anything to it either.
|
||||
if (!additions) {
|
||||
if (!additions.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -88,7 +86,14 @@ tree.Filterset.prototype.addable = function(filter) {
|
||||
|
||||
switch (filter.op) {
|
||||
case '=':
|
||||
if (key + '=' in this.filters) return (this.filters[key + '='].val != value) ? false : null;
|
||||
// if there is already foo= and we're adding foo=
|
||||
if (key + '=' in this.filters) {
|
||||
if (this.filters[key + '='].val != value) {
|
||||
return false;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (key + '!=' + value in this.filters) return false;
|
||||
if (key + '>' in this.filters && this.filters[key + '>'].val >= value) return false;
|
||||
if (key + '<' in this.filters && this.filters[key + '<'].val <= value) return false;
|
||||
|
@ -77,11 +77,23 @@ tree.Ruleset.prototype = {
|
||||
});
|
||||
return this._lookups[key] = rules;
|
||||
},
|
||||
// Zooms can use variables. This replaces tree.Zoom objects on selectors
|
||||
// with simple bit-arrays that we can compare easily.
|
||||
evalZooms: function(env) {
|
||||
for (var i = 0; i < this.selectors.length; i++) {
|
||||
var zval = tree.Zoom.all;
|
||||
for (var z = 0; z < this.selectors[i].zoom.length; z++) {
|
||||
zval = zval & this.selectors[i].zoom[z].eval(env).zoom;
|
||||
}
|
||||
this.selectors[i].zoom = zval;
|
||||
}
|
||||
},
|
||||
flatten: function(result, parents, env) {
|
||||
var selectors = [], i, j;
|
||||
if (this.selectors.length === 0) {
|
||||
env.frames = env.frames.concat(this.rules);
|
||||
}
|
||||
this.evalZooms(env);
|
||||
for (i = 0; i < this.selectors.length; i++) {
|
||||
var child = this.selectors[i];
|
||||
|
||||
|
@ -14,14 +14,13 @@ tree.Variable.prototype = {
|
||||
eval: function(env) {
|
||||
var variable,
|
||||
v,
|
||||
that = this,
|
||||
name = this.name;
|
||||
|
||||
if (this._css) return this._css;
|
||||
|
||||
var thisframe = env.frames.filter(function(f) {
|
||||
return f.name == that.name;
|
||||
});
|
||||
return f.name == this.name;
|
||||
}.bind(this));
|
||||
if (thisframe.length) {
|
||||
return thisframe[0].value.eval(env);
|
||||
} else {
|
||||
|
@ -4,7 +4,22 @@ var tree = require('../tree');
|
||||
// and stores them as bit-sequences so that they can be combined,
|
||||
// inverted, and compared quickly.
|
||||
tree.Zoom = function(op, value, index) {
|
||||
value = parseInt(value, 10);
|
||||
this.op = op;
|
||||
this.value = value;
|
||||
this.index = index;
|
||||
};
|
||||
|
||||
tree.Zoom.prototype.setZoom = function(zoom) {
|
||||
this.zoom = zoom;
|
||||
return this;
|
||||
};
|
||||
|
||||
tree.Zoom.prototype.eval = function(env) {
|
||||
var start = 0,
|
||||
end = Infinity,
|
||||
value = parseInt(this.value.eval(env).toString(), 10),
|
||||
zoom = 0;
|
||||
|
||||
if (value > tree.Zoom.maxZoom || value < 0) {
|
||||
throw {
|
||||
message: 'Only zoom levels between 0 and ' +
|
||||
@ -13,13 +28,10 @@ tree.Zoom = function(op, value, index) {
|
||||
};
|
||||
}
|
||||
|
||||
var start = 0,
|
||||
end = Infinity,
|
||||
zoom = 0;
|
||||
|
||||
switch (op) {
|
||||
switch (this.op) {
|
||||
case '=':
|
||||
return 1 << value;
|
||||
this.zoom = 1 << value;
|
||||
return this;
|
||||
case '>':
|
||||
start = value + 1;
|
||||
break;
|
||||
@ -38,7 +50,12 @@ tree.Zoom = function(op, value, index) {
|
||||
zoom |= (1 << i);
|
||||
}
|
||||
}
|
||||
return zoom;
|
||||
this.zoom = zoom;
|
||||
return this;
|
||||
};
|
||||
|
||||
tree.Zoom.prototype.toString = function() {
|
||||
return this.zoom;
|
||||
};
|
||||
|
||||
// Covers all zoomlevels from 0 to 22
|
||||
@ -74,12 +91,12 @@ tree.Zoom.ranges = {
|
||||
};
|
||||
|
||||
// Only works for single range zooms. `[XXX....XXXXX.........]` is invalid.
|
||||
tree.Zoom.toXML = function(zoom) {
|
||||
tree.Zoom.prototype.toXML = function() {
|
||||
var conditions = [];
|
||||
if (zoom != tree.Zoom.all) {
|
||||
if (this.zoom != tree.Zoom.all) {
|
||||
var start = null, end = null;
|
||||
for (var i = 0; i <= tree.Zoom.maxZoom; i++) {
|
||||
if (zoom & (1 << i)) {
|
||||
if (this.zoom & (1 << i)) {
|
||||
if (start === null) start = i;
|
||||
end = i;
|
||||
}
|
||||
@ -92,11 +109,10 @@ tree.Zoom.toXML = function(zoom) {
|
||||
return conditions;
|
||||
};
|
||||
|
||||
|
||||
tree.Zoom.toString = function(zoom) {
|
||||
tree.Zoom.prototype.toString = function() {
|
||||
var str = '';
|
||||
for (var i = 0; i <= tree.Zoom.maxZoom; i++) {
|
||||
str += (zoom & (1 << i)) ? 'X' : '.';
|
||||
str += (this.zoom & (1 << i)) ? 'X' : '.';
|
||||
}
|
||||
return str;
|
||||
};
|
||||
|
@ -1,5 +1,5 @@
|
||||
#world {
|
||||
[zoom>9] { marker-height: 4; }
|
||||
[zoom=9] { marker-height: 4; }
|
||||
[zoom>6][zoom<10] { marker-height: 3; }
|
||||
[zoom>3][zoom<7] { marker-height: 2; }
|
||||
[zoom<4] { marker-height: 1; }
|
||||
|
Loading…
Reference in New Issue
Block a user