This commit is contained in:
Tom MacWright 2012-06-28 13:58:04 -04:00
commit 255b0219b6
34 changed files with 533 additions and 70 deletions

View File

@ -1,5 +1,14 @@
## Changelog
## 0.9.0
* Adds the modulus operator `%` as an option
* Adds a new field-type like `[FIELD]` instead of "[FIELD"
### 0.8.0
* Supports function syntax for transforms, optionally with variables and arguments.
### 0.7.0
* Support an `opacity` property on any style that is a style-level property

View File

@ -2,7 +2,7 @@
var path = require('path'),
fs = require('fs'),
sys = require('sys'),
util = require('util'),
carto = require('carto');
var args = process.argv.slice(1);
@ -17,7 +17,7 @@ args = args.filter(function (arg) {
switch (arg) {
case 'v':
case 'version':
sys.puts("carto " + carto.version.join('.') + " (Carto map stylesheet compiler)");
util.puts("carto " + carto.version.join('.') + " (Carto map stylesheet compiler)");
process.exit(0);
break;
case 'b':
@ -46,7 +46,7 @@ if (input && input[0] != '/') {
}
if (!input) {
sys.puts("carto: no input files");
util.puts("carto: no input files");
process.exit(1);
}
@ -57,14 +57,14 @@ if (options.benchmark) {
try {
var data = fs.readFileSync(input, 'utf-8');
} catch(err) {
sys.puts("carto: " + err.message.replace(/^[A-Z]+, /, ''));
util.puts("carto: " + err.message.replace(/^[A-Z]+, /, ''));
process.exit(1);
}
try {
data = JSON.parse(data);
} catch(err) {
sys.puts("carto: " + err.message.replace(/^[A-Z]+, /, ''));
util.puts("carto: " + err.message.replace(/^[A-Z]+, /, ''));
process.exit(1);
}
@ -98,7 +98,7 @@ function compile(err, data) {
process.exit(1);
} else {
if (!options.benchmark) {
sys.puts(output);
util.puts(output);
} else {
var duration = (+new Date) - start;
console.log('TOTAL: ' + (duration) + 'ms');
@ -107,9 +107,9 @@ function compile(err, data) {
});
} catch (e) {
if (e.stack) {
sys.error(e.stack);
util.error(e.stack);
} else {
sys.error(e);
util.error(e);
}
}
};

View File

@ -94,6 +94,13 @@ tree.functions = {
return hsla(hsl);
},
replace: function (entity, a, b) {
if (entity.is === 'field') {
return entity.toString + '.replace(' + a.toString() + ', ' + b.toString() + ')';
} else {
return entity.replace(a, b);
}
},
//
// Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein
// http://sass-lang.com
@ -126,7 +133,7 @@ tree.functions = {
.replace(/%[da]/, args[i].toString());
}
str = str.replace(/%%/g, '%');
return new tree.Quoted('"' + str + '"', str);
return new tree.Quoted(str);
}
};

View File

@ -50,9 +50,9 @@ var carto = {
}
};
[ 'anonymous', 'call', 'color', 'comment', 'definition', 'dimension',
'directive', 'element', 'expression', 'filterset', 'filter',
'keyword', 'layer', 'operation', 'quoted', 'imagefilter',
[ 'call', 'color', 'comment', 'definition', 'dimension',
'directive', 'element', 'expression', 'filterset', 'filter', 'field',
'keyword', 'layer', 'literal', 'operation', 'quoted', 'imagefilter',
'reference', 'rule', 'ruleset', 'selector', 'style', 'url', 'value',
'variable', 'zoom', 'invalid', 'fontset'
].forEach(function(n) {

View File

@ -419,10 +419,24 @@ carto.Parser = function Parser(env) {
if (input.charAt(i) !== '"' && input.charAt(i) !== "'") return;
var str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/);
if (str) {
return new tree.Quoted(str[0], str[1] || str[2]);
return new tree.Quoted(str[1] || str[2]);
}
},
// A reference to a Mapnik field, like
//
// [NAME]
//
// Behind the scenes, this has the same representation, but Carto
// needs to be careful to warn when unsupported operations are used.
field: function() {
if (! $('[')) return;
var field_name = $(/(^[a-zA-Z0-9\-_]+)/);
if (! $(']')) return;
if (field_name) return new tree.Field(field_name[1]);
},
// This is a comparison operator
comparison: function() {
var str = $(/^=~|=|!=|<=|>=|<|>/);
if (str) {
@ -449,7 +463,7 @@ carto.Parser = function Parser(env) {
call: function() {
var name, args;
if (! (name = /^([\w-]+|%)\(/.exec(chunks[j]))) return;
if (! (name = /^([\w\-]+|%)\(/.exec(chunks[j]))) return;
name = name[1].toLowerCase();
@ -467,13 +481,15 @@ carto.Parser = function Parser(env) {
return new tree.Call(name, args, i);
}
},
arguments: function() {
// Arguments are comma-separated expressions
'arguments': function() {
var args = [], arg;
while (arg = $(this.expression)) {
args.push(arg);
if (! $(',')) { break; }
}
return args;
},
literal: function() {
@ -497,7 +513,7 @@ carto.Parser = function Parser(env) {
return new tree.Invalid(value, memo, 'Missing closing ) in URL.');
} else {
return new tree.URL((value.value || value instanceof tree.Variable) ?
value : new tree.Anonymous(value), imports.paths);
value : new tree.Quoted(value), imports.paths);
}
},
@ -553,7 +569,9 @@ carto.Parser = function Parser(env) {
variable: function() {
var name;
if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1]; }
if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) {
return name[1];
}
},
//
@ -561,8 +579,12 @@ carto.Parser = function Parser(env) {
// and can be found inside a rule's value.
//
entity: function() {
return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) ||
$(this.entities.call) || $(this.entities.keyword);
return $(this.entities.literal) ||
$(this.entities.field) ||
$(this.entities.variable) ||
$(this.entities.url) ||
$(this.entities.call) ||
$(this.entities.keyword);
},
//
@ -743,6 +765,7 @@ carto.Parser = function Parser(env) {
return new tree.Value(expressions);
}
},
// A sub-expression, contained by parenthensis
sub: function() {
var e;
@ -750,10 +773,12 @@ carto.Parser = function Parser(env) {
return e;
}
},
// This is a misnomer because it actually handles multiplication
// and division.
multiplication: function() {
var m, a, op, operation;
if (m = $(this.operand)) {
while ((op = ($('/') || $('*'))) && (a = $(this.operand))) {
while ((op = ($('/') || $('*') || $('%'))) && (a = $(this.operand))) {
operation = new tree.Operation(op, [operation || m, a], memo);
}
return operation || m;
@ -773,9 +798,7 @@ carto.Parser = function Parser(env) {
// An operand is anything that can be part of an operation,
// such as a Color, or a Variable
operand: function() {
return $(this.sub) || $(this.entities.dimension) ||
$(this.entities.color) || $(this.entities.variable) ||
$(this.entities.call);
return $(this.sub) || $(this.entity);
},
// Expressions either represent mathematical operations,

View File

@ -1,8 +1,5 @@
(function(tree) {
//
// A function call node.
//
tree.Call = function Call(name, args, index) {
this.name = name;
this.args = args;
@ -50,9 +47,37 @@ tree.Call.prototype = {
value: 'undefined'
};
}
} else { // 2.
return new tree.Anonymous(this.name +
'(' + args.map(function(a) { return a.toString(); }).join(', ') + ')');
} else {
var fn = tree.Reference.mapnikFunction(this.name);
if (!fn) {
env.error({
message: 'unknown function ' + this.name,
index: this.index,
type: 'runtime',
filename: this.filename
});
return {
is: 'undefined',
value: 'undefined'
};
}
if (fn[1] !== args.length) {
env.error({
message: 'function ' + this.name + ' takes ' +
fn[1] + ' arguments and was given ' + args.length,
index: this.index,
type: 'runtime',
filename: this.filename
});
return {
is: 'undefined',
value: 'undefined'
};
} else {
// Save the evaluated versions of arguments
this.args = args;
return this;
}
}
},
toString: function(env) {

View File

@ -4,6 +4,7 @@ tree.Comment = function Comment(value, silent) {
this.value = value;
this.silent = !!silent;
};
tree.Comment.prototype = {
toString: function(env) {
return '<!--' + this.value + '-->';

View File

@ -25,7 +25,7 @@ tree.Dimension.prototype = {
return new tree.Color([this.value, this.value, this.value]);
},
toString: function() {
return this.value;
return this.value.toString();
},
// In an operation between two Dimensions,

17
lib/carto/tree/field.js Normal file
View File

@ -0,0 +1,17 @@
(function(tree) {
tree.Field = function Field(content) {
this.value = content || '';
this.is = 'field';
};
tree.Field.prototype = {
toString: function() {
return '[' + this.value + ']';
},
'eval': function() {
return this;
}
};
})(require('../tree'));

20
lib/carto/tree/literal.js Normal file
View File

@ -0,0 +1,20 @@
// A literal is a literal string for Mapnik - the
// result of the combination of a `tree.Field` with any
// other type.
(function(tree) {
tree.Literal = function Field(content) {
this.value = content || '';
this.is = 'field';
};
tree.Literal.prototype = {
toString: function() {
return this.value;
},
'eval': function() {
return this;
}
};
})(require('../tree'));

View File

@ -1,11 +1,12 @@
(function(tree) {
tree.Operation = function Operation(op, operands, index) {
this.op = op.trim();
this.operands = operands;
this.index = index;
this.is = 'operation';
};
tree.Operation.prototype.eval = function(env) {
var a = this.operands[0].eval(env),
b = this.operands[1].eval(env),
@ -30,9 +31,11 @@ tree.Operation.prototype.eval = function(env) {
}
}
if (a instanceof tree.Quoted || b instanceof tree.Quoted) {
// Only concatenate plain strings, because this is easily
// pre-processed
if (a instanceof tree.Quoted && b instanceof tree.Quoted && this.op !== '+') {
env.error({
message: 'One cannot add, subtract, divide, or multiply strings.',
message: "Can't subtract, divide, or multiply strings.",
index: this.index,
type: 'runtime',
filename: this.filename
@ -43,6 +46,25 @@ tree.Operation.prototype.eval = function(env) {
};
}
// Fields, literals, dimensions, and quoted strings can be combined.
if (a instanceof tree.Field || b instanceof tree.Field ||
a instanceof tree.Literal || b instanceof tree.Literal) {
if (a.is === 'color' || b.is === 'color') {
env.error({
message: "Can't subtract, divide, or multiply colors in expressions.",
index: this.index,
type: 'runtime',
filename: this.filename
});
return {
is: 'undefined',
value: 'undefined'
};
} else {
return new tree.Literal(a.eval(env).toString(true) + this.op + b.eval(env).toString(true));
}
}
return a.operate(this.op, b);
};
@ -51,6 +73,7 @@ tree.operate = function(op, a, b) {
case '+': return a + b;
case '-': return a - b;
case '*': return a * b;
case '%': return a % b;
case '/': return a / b;
}
};

View File

@ -1,17 +1,23 @@
(function(tree) {
tree.Quoted = function Quoted(str, content) {
tree.Quoted = function Quoted(content) {
this.value = content || '';
this.quote = str.charAt(0);
this.is = 'string';
};
tree.Quoted.prototype = {
toString: function(quotes) {
var xmlvalue = this.value.replace(/\'/g, '&apos;');
return (quotes === true) ? "'" + xmlvalue + "'" : this.value;
},
'eval': function() {
return this;
},
operate: function(op, other) {
return new tree.Quoted(true,
tree.operate(op, this.toString(), other.toString(this.contains_field)));
}
};

View File

@ -1,3 +1,9 @@
/*
* Carto pulls in a reference from the `mapnik-reference`
* module. This file builds indexes from that file for its various
* options, and provides validation methods for property: value
* combinations.
*/
(function(tree) {
var _ = require('underscore');
@ -59,6 +65,24 @@ tree.Reference.symbolizer = function(selector) {
}
};
/*
* For transform properties and image-filters,
* mapnik has its own functions.
*/
tree.Reference.mapnikFunction = function(name) {
var functions = [];
for (var i in tree.Reference.data.symbolizers) {
for (var j in tree.Reference.data.symbolizers[i]) {
if (tree.Reference.data.symbolizers[i][j].type === 'functions') {
functions = functions.concat(tree.Reference.data.symbolizers[i][j].functions);
}
}
}
return _.find(functions, function(f) {
return f[0] === name;
});
};
tree.Reference.requiredPropertyList = function(symbolizer_name) {
if (this.required_prop_list_cache[symbolizer_name]) {
return this.required_prop_list_cache[symbolizer_name];
@ -101,28 +125,30 @@ tree.Reference.isFont = function(selector) {
tree.Reference.validValue = function(env, selector, value) {
var i, j;
if (value[0]) {
return tree.Reference.selector(selector).type == value[0].is;
} else {
// TODO: handle in reusable way
if (!tree.Reference.selector(selector)) {
return false;
} else if (value.value[0].is == 'keyword') {
return tree.Reference
.selector(selector).type
.indexOf(value.value[0].value) !== -1;
} else if (value.value[0].is == 'undefined') {
// caught earlier in the chain - ignore here so that
// error is not overridden
return true;
} else if (tree.Reference.selector(selector).type == 'numbers') {
for (i in value.value) {
if (value.value[i].is !== 'float') {
return false;
}
// TODO: handle in reusable way
if (!tree.Reference.selector(selector)) {
return false;
} else if (value.value[0].is == 'keyword') {
return tree.Reference
.selector(selector).type
.indexOf(value.value[0].value) !== -1;
} else if (value.value[0].is == 'undefined') {
// caught earlier in the chain - ignore here so that
// error is not overridden
return true;
} else if (tree.Reference.selector(selector).type == 'numbers') {
for (i in value.value) {
if (value.value[i].is !== 'float') {
return false;
}
}
return true;
} else if (tree.Reference.selector(selector).type == 'functions') {
// For backwards compatibility, you can specify a string for `functions`-compatible
// values, though they will not be validated.
if (value.value[0].is === 'string') {
return true;
} else if (tree.Reference.selector(selector).type == 'functions') {
} else {
for (i in value.value) {
for (j in value.value[i].value) {
if (value.value[i].value[j].is !== 'call') {
@ -139,22 +165,24 @@ tree.Reference.validValue = function(env, selector, value) {
}
}
return true;
} else {
if (tree.Reference.selector(selector).validate) {
var valid = false;
for (i = 0; i < value.value.length; i++) {
if (tree.Reference.selector(selector).type == value.value[i].is &&
tree.Reference
._validateValue
[tree.Reference.selector(selector).validate]
(env, value.value[i].value)) {
return true;
}
}
} else if (tree.Reference.selector(selector).type == 'expression') {
return true;
} else {
if (tree.Reference.selector(selector).validate) {
var valid = false;
for (i = 0; i < value.value.length; i++) {
if (tree.Reference.selector(selector).type == value.value[i].is &&
tree.Reference
._validateValue
[tree.Reference.selector(selector).validate]
(env, value.value[i].value)) {
return true;
}
return valid;
} else {
return tree.Reference.selector(selector).type == value.value[0].is;
}
return valid;
} else {
return tree.Reference.selector(selector).type == value.value[0].is;
}
}
};

View File

@ -36,7 +36,7 @@
},
"dependencies": {
"underscore": "~1.3.3",
"mapnik-reference": "~2.1.0",
"mapnik-reference": "https://github.com/mapnik/mapnik-reference/tarball/transform-functions",
"xml2js": "~0.1.13"
},
"devDependencies": {

View File

@ -0,0 +1,23 @@
{
"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",
"Stylesheet": [
"building_height.mss"
],
"Layer": [{
"name": "world",
"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",
"Datasource": {
"file": "http://tilemill-data.s3.amazonaws.com/test_data/shape_demo.zip",
"type": "shape"
}
},
{
"class": "new",
"name": "countries",
"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",
"Datasource": {
"file": "http://tilemill-data.s3.amazonaws.com/test_data/shape_demo.zip",
"type": "shape"
}
}]
}

View File

@ -0,0 +1,4 @@
@n: 4;
#world {
building-height: 2 * 3 * [HEIGHT] + 2 + [NOTHEIGHT] + (@n * 2);
}

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Map[]>
<Map 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" maximum-extent="-20037508.34,-20037508.34,20037508.34,20037508.34">
<Style name="world" filter-mode="first" >
<Rule>
<BuildingSymbolizer height="6*[HEIGHT]+2+[NOTHEIGHT]+8" />
</Rule>
</Style>
<Layer name="world"
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">
<StyleName>world</StyleName>
<Datasource>
<Parameter name="file"><![CDATA[[absolute path]]]></Parameter>
<Parameter name="type"><![CDATA[shape]]></Parameter>
</Datasource>
</Layer>
</Map>

23
test/rendering/field.mml Normal file
View File

@ -0,0 +1,23 @@
{
"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",
"Stylesheet": [
"field.mss"
],
"Layer": [{
"name": "world",
"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",
"Datasource": {
"file": "http://tilemill-data.s3.amazonaws.com/test_data/shape_demo.zip",
"type": "shape"
}
},
{
"class": "new",
"name": "countries",
"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",
"Datasource": {
"file": "http://tilemill-data.s3.amazonaws.com/test_data/shape_demo.zip",
"type": "shape"
}
}]
}

6
test/rendering/field.mss Normal file
View File

@ -0,0 +1,6 @@
#world {
text-name: "hello " + [NAME] + " hello";
text-size: 11;
text-face-name: "Georgia Regular", "Arial Italic";
}

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Map[]>
<Map 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" maximum-extent="-20037508.34,-20037508.34,20037508.34,20037508.34">
<FontSet name="fontset-0">
<Font face-name="Georgia Regular"/>
<Font face-name="Arial Italic"/>
</FontSet>
<Style name="world" filter-mode="first" >
<Rule>
<TextSymbolizer size="11" fontset-name="fontset-0" ><![CDATA['hello '+[NAME]+' hello']]></TextSymbolizer>
</Rule>
</Style>
<Layer name="world"
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">
<StyleName>world</StyleName>
<Datasource>
<Parameter name="file"><![CDATA[[absolute path]]]></Parameter>
<Parameter name="type"><![CDATA[shape]]></Parameter>
</Datasource>
</Layer>
</Map>

View File

@ -0,0 +1,23 @@
{
"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",
"Stylesheet": [
"field_advanced.mss"
],
"Layer": [{
"name": "world",
"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",
"Datasource": {
"file": "http://tilemill-data.s3.amazonaws.com/test_data/shape_demo.zip",
"type": "shape"
}
},
{
"class": "new",
"name": "countries",
"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",
"Datasource": {
"file": "http://tilemill-data.s3.amazonaws.com/test_data/shape_demo.zip",
"type": "shape"
}
}]
}

View File

@ -0,0 +1,6 @@
#world {
text-name: "hello " + [NAME] + " hello" + 2;
text-size: 11;
text-face-name: "Georgia Regular", "Arial Italic";
}

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Map[]>
<Map 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" maximum-extent="-20037508.34,-20037508.34,20037508.34,20037508.34">
<FontSet name="fontset-0">
<Font face-name="Georgia Regular"/>
<Font face-name="Arial Italic"/>
</FontSet>
<Style name="world" filter-mode="first" >
<Rule>
<TextSymbolizer size="11" fontset-name="fontset-0" ><![CDATA['hello '+[NAME]+' hello'+2]]></TextSymbolizer>
</Rule>
</Style>
<Layer name="world"
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">
<StyleName>world</StyleName>
<Datasource>
<Parameter name="file"><![CDATA[[absolute path]]]></Parameter>
<Parameter name="type"><![CDATA[shape]]></Parameter>
</Datasource>
</Layer>
</Map>

View File

@ -0,0 +1,23 @@
{
"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",
"Stylesheet": [
"modulus.mss"
],
"Layer": [{
"name": "world",
"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",
"Datasource": {
"file": "http://tilemill-data.s3.amazonaws.com/test_data/shape_demo.zip",
"type": "shape"
}
},
{
"class": "new",
"name": "countries",
"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",
"Datasource": {
"file": "http://tilemill-data.s3.amazonaws.com/test_data/shape_demo.zip",
"type": "shape"
}
}]
}

View File

@ -0,0 +1,6 @@
#world {
text-name: "hello ";
text-size: 11 % 2;
text-face-name: "Georgia Regular", "Arial Italic";
}

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Map[]>
<Map 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" maximum-extent="-20037508.34,-20037508.34,20037508.34,20037508.34">
<FontSet name="fontset-0">
<Font face-name="Georgia Regular"/>
<Font face-name="Arial Italic"/>
</FontSet>
<Style name="world" filter-mode="first" >
<Rule>
<TextSymbolizer size="1" fontset-name="fontset-0" ><![CDATA[hello ]]></TextSymbolizer>
</Rule>
</Style>
<Layer name="world"
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">
<StyleName>world</StyleName>
<Datasource>
<Parameter name="file"><![CDATA[[absolute path]]]></Parameter>
<Parameter name="type"><![CDATA[shape]]></Parameter>
</Datasource>
</Layer>
</Map>

View File

@ -0,0 +1,5 @@
@trans: 2;
#world {
point-file: url(foo.png);
point-transform: translate(@trans * 2, @trans);
}

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Map[]>
<Map 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" maximum-extent="-20037508.34,-20037508.34,20037508.34,20037508.34">
<Style name="world" filter-mode="first" >
<Rule>
<PointSymbolizer file="foo.png" image-transform="translate(4,2)" />
</Rule>
</Style>
<Layer name="world"
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">
<StyleName>world</StyleName>
<Datasource>
<Parameter name="file"><![CDATA[[absolute path]]]></Parameter>
<Parameter name="type"><![CDATA[shape]]></Parameter>
</Datasource>
</Layer>
</Map>

View File

@ -0,0 +1,14 @@
{
"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",
"Stylesheet": [
"transforms_backwards.mss"
],
"Layer": [{
"name": "world",
"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",
"Datasource": {
"file": "http://tilemill-data.s3.amazonaws.com/test_data/shape_demo.zip",
"type": "shape"
}
}]
}

View File

@ -0,0 +1,4 @@
#world {
point-file: url(foo.png);
point-transform: "translate(2, 2)";
}

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Map[]>
<Map 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" maximum-extent="-20037508.34,-20037508.34,20037508.34,20037508.34">
<Style name="world" filter-mode="first" >
<Rule>
<PointSymbolizer file="foo.png" image-transform="translate(2, 2)" />
</Rule>
</Style>
<Layer name="world"
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">
<StyleName>world</StyleName>
<Datasource>
<Parameter name="file"><![CDATA[[absolute path]]]></Parameter>
<Parameter name="type"><![CDATA[shape]]></Parameter>
</Datasource>
</Layer>
</Map>

View File

@ -0,0 +1,14 @@
{
"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",
"Stylesheet": [
"transforms_field.mss"
],
"Layer": [{
"name": "world",
"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",
"Datasource": {
"file": "http://tilemill-data.s3.amazonaws.com/test_data/shape_demo.zip",
"type": "shape"
}
}]
}

View File

@ -0,0 +1,4 @@
#world {
point-file:url(foo.png);
point-transform: scale(2 * 5 * [POP2005], [POP2005]);
}

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Map[]>
<Map 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" maximum-extent="-20037508.34,-20037508.34,20037508.34,20037508.34">
<Style name="world" filter-mode="first" >
<Rule>
<PointSymbolizer file="foo.png" image-transform="scale(10*[POP2005],[POP2005])" />
</Rule>
</Style>
<Layer name="world"
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">
<StyleName>world</StyleName>
<Datasource>
<Parameter name="file"><![CDATA[[absolute path]]]></Parameter>
<Parameter name="type"><![CDATA[shape]]></Parameter>
</Datasource>
</Layer>
</Map>