diff --git a/lib/carto/renderer.js b/lib/carto/renderer.js index 98370d0..6af4be7 100644 --- a/lib/carto/renderer.js +++ b/lib/carto/renderer.js @@ -60,13 +60,15 @@ carto.Renderer.prototype.render = function render(m, callback) { }); var rules = inheritRules(matching, env); var sorted = sortStyles(rules, env); + _(sorted).each(function(rule) { var style = new tree.Style(l.name, rule.attachment, rule); if (style) { l.styles.push(style.name); + var xml = style.toXML(env); // env.effects can be modified by this call - output.push(style.toXML(env)); + output.push(xml); } }); if (l.styles.length) { @@ -170,7 +172,8 @@ function addRules(current, definition, existing) { k++; } } - } else if (updatedFilters === null) { + } else if (updatedFilters === null && + current[k].zoom === definition.zoom) { // Filters can be added, but they don't change the // filters. This means we don't have to split the // definition. @@ -213,6 +216,7 @@ function inheritRules(definitions, env) { byAttachment[attachment].push(current[k]); } } + // console.log(JSON.stringify(result, null, 4)); if (env.benchmark) console.warn('Inheritance time: ' + ((new Date() - inheritTime)) + 'ms'); diff --git a/lib/carto/tree/definition.js b/lib/carto/tree/definition.js index bfe4fd0..446d678 100644 --- a/lib/carto/tree/definition.js +++ b/lib/carto/tree/definition.js @@ -65,13 +65,13 @@ tree.Definition.prototype.appliesTo = function(id, classes) { }; tree.Definition.prototype.symbolizersToXML = function(env, symbolizers, zoom) { - var xml = ' \n'; + var xml = ' \n', key; xml += tree.Zoom.toXML(zoom).join(''); xml += this.filters.toXML(env); // Sort symbolizers by the index of their first property definition var sym_order = [], indexes = []; - for (var key in symbolizers) { + for (key in symbolizers) { indexes = []; for (var prop in symbolizers[key]) { indexes.push(symbolizers[key][prop].index); @@ -87,6 +87,10 @@ tree.Definition.prototype.symbolizersToXML = function(env, symbolizers, zoom) { return v[0]; }); + function capitalize(str) { + return str[1].toUpperCase(); + } + for (var i = 0; i < sym_order.length; i++) { var attributes = symbolizers[sym_order[i]]; var symbolizer = sym_order[i].split('/').pop(); @@ -106,13 +110,11 @@ tree.Definition.prototype.symbolizersToXML = function(env, symbolizers, zoom) { } var name = symbolizer.charAt(0).toUpperCase() + - symbolizer.slice(1).replace(/\-./, function(str) { - return str[1].toUpperCase(); - }) + 'Symbolizer'; + symbolizer.slice(1).replace(/\-./, capitalize) + 'Symbolizer'; var selfclosing = true, tagcontent; xml += ' <' + name + ' '; - for (var key in attributes) { + for (key in attributes) { if (symbolizer === 'map') env.error({ message: 'Map properties are not permitted in other rules', index: attributes[key].index, @@ -140,6 +142,8 @@ tree.Definition.prototype.symbolizersToXML = function(env, symbolizers, zoom) { return xml; }; +// Take a zoom range of zooms and 'i', the index of a rule in this.rules, +// and finds all applicable symbolizers tree.Definition.prototype.collectSymbolizers = function(zooms, i) { var symbolizers = {}, child; diff --git a/lib/carto/tree/filterset.js b/lib/carto/tree/filterset.js index 10d9383..0da1c01 100644 --- a/lib/carto/tree/filterset.js +++ b/lib/carto/tree/filterset.js @@ -46,6 +46,8 @@ Object.defineProperty(tree.Filterset.prototype, 'cloneWith', { var additions; for (var id in other) { var status = this.addable(other[id]); + // status is true, false or null. if it's null we don't fail this + // clone nor do we add the filter. if (status === false) { return false; } @@ -58,7 +60,9 @@ Object.defineProperty(tree.Filterset.prototype, 'cloneWith', { // Adding the other filters doesn't make this filterset invalid, but it // doesn't add anything to it either. - if (!additions) return null; + if (!additions) { + return null; + } // We can successfully add all filters. Now clone the filterset and add the // new rules. @@ -66,7 +70,7 @@ Object.defineProperty(tree.Filterset.prototype, 'cloneWith', { // We can add the rules that are already present without going through the // add function as a Filterset is always in it's simplest canonical form. - for (var id in this) { + for (id in this) { clone[id] = this[id]; } @@ -79,20 +83,21 @@ Object.defineProperty(tree.Filterset.prototype, 'cloneWith', { } }); -/** - * Returns true when the new filter can be added, false otherwise. - */ +// Returns true when the new filter can be added, false otherwise. +// It can also return null, and on the other side we test for === true or +// false Object.defineProperty(tree.Filterset.prototype, 'addable', { enumerable: false, value: function(filter) { - var key = filter.key, value = filter.val; + var key = filter.key, + value = filter.val; switch (filter.op) { case '=': if (key + '=' in this) return (this[key + '='].val != value) ? false : null; if (key + '!=' + value in this) return false; - if (key + '>' in this && this[key + '>'].val >= value) return false; - if (key + '<' in this && this[key + '<'].val <= value) return false; + if (key + '>' in this && this[key + '>'].val >= value) return false; + if (key + '<' in this && this[key + '<'].val <= value) return false; if (key + '>=' in this && this[key + '>='].val > value) return false; if (key + '<=' in this && this[key + '<='].val < value) return false; return true; @@ -103,8 +108,8 @@ Object.defineProperty(tree.Filterset.prototype, 'addable', { case '!=': if (key + '=' in this) return (this[key + '='].val == value) ? false : null; if (key + '!=' + value in this) return null; - if (key + '>' in this && this[key + '>'].val >= value) return null; - if (key + '<' in this && this[key + '<'].val <= value) return null; + if (key + '>' in this && this[key + '>'].val >= value) return null; + if (key + '<' in this && this[key + '<'].val <= value) return null; if (key + '>=' in this && this[key + '>='].val > value) return null; if (key + '<=' in this && this[key + '<='].val < value) return null; return true; @@ -150,11 +155,11 @@ Object.defineProperty(tree.Filterset.prototype, 'addable', { Object.defineProperty(tree.Filterset.prototype, 'add', { enumerable: false, value: function(filter) { - var key = filter.key; + var key = filter.key, id; switch (filter.op) { case '=': - for (var id in this) { + for (id in this) { if (this[id].key == key) { delete this[id]; } @@ -174,7 +179,7 @@ Object.defineProperty(tree.Filterset.prototype, 'add', { // If there are other filters that are also > // but are less than this one, they don't matter, so // remove them. - for (var id in this) { + for (id in this) { if (this[id].key == key && this[id].val <= filter.val) { delete this[id]; } @@ -183,7 +188,7 @@ Object.defineProperty(tree.Filterset.prototype, 'add', { break; case '>=': - for (var id in this) { + for (id in this) { if (this[id].key == key && this[id].val < filter.val) { delete this[id]; } @@ -199,7 +204,7 @@ Object.defineProperty(tree.Filterset.prototype, 'add', { break; case '<': - for (var id in this) { + for (id in this) { if (this[id].key == key && this[id].val >= filter.val) { delete this[id]; } @@ -208,7 +213,7 @@ Object.defineProperty(tree.Filterset.prototype, 'add', { break; case '<=': - for (var id in this) { + for (id in this) { if (this[id].key == key && this[id].val > filter.val) { delete this[id]; } diff --git a/test/rendering/sharedclass.mml b/test/rendering/sharedclass.mml index e73b1bd..cb223de 100644 --- a/test/rendering/sharedclass.mml +++ b/test/rendering/sharedclass.mml @@ -17,7 +17,7 @@ }, { "Datasource": { - "file": "http://tilemill-data.s3.amazonaws.com/natural-earth-10m-1.3.0/urban_areas.zip", + "file": "http://tilemill-data.s3.amazonaws.com/world_borders_merc.zip", "type": "shape" }, "srs": "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over",