add protobuf encoding of style
This commit is contained in:
140
bin/convert-style.js
Executable file
140
bin/convert-style.js
Executable file
@@ -0,0 +1,140 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
var style = require('./style.js');
|
||||
var Protobuf = require('./protobuf.js');
|
||||
|
||||
var fs = require('fs');
|
||||
|
||||
var pbf = new Protobuf();
|
||||
|
||||
// enum
|
||||
var bucket_type = {
|
||||
fill: 1,
|
||||
line: 2,
|
||||
point: 3
|
||||
};
|
||||
|
||||
// enum
|
||||
var cap_type = {
|
||||
round: 1,
|
||||
}
|
||||
|
||||
// enum
|
||||
var join_type = {
|
||||
butt: 1,
|
||||
bevel: 2
|
||||
}
|
||||
|
||||
function createBucket(bucket, name) {
|
||||
var pbf = new Protobuf();
|
||||
pbf.writeTaggedString(1 /* name */, name);
|
||||
pbf.writeTaggedVarint(2 /* type */, bucket_type[bucket.type]);
|
||||
|
||||
pbf.writeTaggedString(3 /* source_name */, bucket.datasource);
|
||||
pbf.writeTaggedString(4 /* source_layer */, bucket.layer);
|
||||
if (bucket.field) {
|
||||
pbf.writeTaggedString(5 /* source_field */, bucket.field);
|
||||
var values = Array.isArray(bucket.value) ? bucket.value : [bucket.value];
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
pbf.writeTaggedString(6 /* source_values */, values[i]);
|
||||
}
|
||||
}
|
||||
if (bucket.cap) {
|
||||
pbf.writeTaggedVarint(7 /* cap */, cap_type[bucket.cap]);
|
||||
}
|
||||
if (bucket.join) {
|
||||
pbf.writeTaggedVarint(8 /* join */, join_type[bucket.join]);
|
||||
}
|
||||
|
||||
// TODO: font stuff
|
||||
|
||||
return pbf;
|
||||
}
|
||||
|
||||
function createStructure(structure) {
|
||||
var pbf = new Protobuf();
|
||||
pbf.writeTaggedString(1 /* name */, structure.name);
|
||||
if (structure.bucket) {
|
||||
pbf.writeTaggedString(2 /* bucket_name */, structure.bucket);
|
||||
} else if (structure.layers) {
|
||||
for (var i = 0; i < structure.layers.length; i++) {
|
||||
pbf.writeMessage(3 /* child_layers */, createStructure(structure.layers[i]));
|
||||
}
|
||||
}
|
||||
return pbf;
|
||||
}
|
||||
|
||||
function createWidth(width) {
|
||||
var pbf = new Protobuf();
|
||||
var values = [];
|
||||
if (Array.isArray(width)) {
|
||||
pbf.writeTaggedString(1 /* scaling */, width[0]);
|
||||
for (var i = 1; i < width.length; i++) {
|
||||
if (width[0] === 'stops') {
|
||||
values.push(width[i].z, width[i].val);
|
||||
} else {
|
||||
values.push(width[i]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
values.push(width);
|
||||
}
|
||||
pbf.writePackedFloats(2 /* values */, values);
|
||||
|
||||
return pbf;
|
||||
}
|
||||
|
||||
function createLayer(layer, name) {
|
||||
var pbf = new Protobuf();
|
||||
pbf.writeTaggedString(1 /* layer_name */, name);
|
||||
|
||||
if ('color' in layer) {
|
||||
var color = layer.color.match(/^#([0-9a-f]{6})$/i);
|
||||
if (!color) {
|
||||
console.warn('invalid color');
|
||||
} else {
|
||||
pbf.writeTaggedUInt32(2 /* color */, parseInt(color[1] + 'ff', 16));
|
||||
}
|
||||
}
|
||||
|
||||
if ('antialias' in layer) {
|
||||
pbf.writeTaggedBoolean(3 /* antialias */, layer.antialias);
|
||||
}
|
||||
|
||||
if ('width' in layer) {
|
||||
pbf.writeMessage(4 /* width */, createWidth(layer.width));
|
||||
}
|
||||
|
||||
return pbf;
|
||||
}
|
||||
|
||||
|
||||
function createClass(klass) {
|
||||
var pbf = new Protobuf();
|
||||
pbf.writeTaggedString(1 /* name */, klass.name);
|
||||
for (var name in klass.layers) {
|
||||
pbf.writeMessage(2 /* layers */, createLayer(klass.layers[name], name));
|
||||
}
|
||||
return pbf;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
for (var name in style.buckets) {
|
||||
var bucket = style.buckets[name];
|
||||
pbf.writeMessage(1 /* buckets */, createBucket(bucket, name));
|
||||
}
|
||||
|
||||
for (var i = 0; i < style.structure.length; i++) {
|
||||
var structure = style.structure[i];
|
||||
pbf.writeMessage(2 /* structure */, createStructure(structure));
|
||||
}
|
||||
|
||||
for (var i = 0; i < style.classes.length; i++) {
|
||||
var klass = style.classes[i];
|
||||
pbf.writeMessage(3 /* classes */, createClass(klass));
|
||||
}
|
||||
|
||||
process.stdout.write(pbf.finish());
|
||||
312
bin/protobuf.js
Normal file
312
bin/protobuf.js
Normal file
@@ -0,0 +1,312 @@
|
||||
module.exports = Protobuf;
|
||||
function Protobuf(buf, pos) {
|
||||
if (Buffer.isBuffer(buf)) {
|
||||
this.buf = buf;
|
||||
} else {
|
||||
this.buf = new Buffer(buf || 128);
|
||||
}
|
||||
this.pos = pos || 0;
|
||||
this.length = this.buf.length;
|
||||
}
|
||||
|
||||
// === READING =================================================================
|
||||
|
||||
Protobuf.prototype.readUInt32 = function() {
|
||||
var val = this.readUInt32LE(this.pos);
|
||||
this.pos += 4;
|
||||
return val;
|
||||
};
|
||||
|
||||
Protobuf.prototype.readUInt64 = function() {
|
||||
var val = this.readUInt64LE(this.pos);
|
||||
this.pos += 4;
|
||||
return val;
|
||||
};
|
||||
|
||||
Protobuf.prototype.readVarint = function() {
|
||||
// TODO: bounds checking
|
||||
var pos = this.pos;
|
||||
if (this.buf[pos] <= 0x7f) {
|
||||
this.pos++;
|
||||
return this.buf[pos];
|
||||
} else if (this.buf[pos + 1] <= 0x7f) {
|
||||
this.pos += 2;
|
||||
return (this.buf[pos] & 0x7f) | (this.buf[pos + 1] << 7);
|
||||
} else if (this.buf[pos + 2] <= 0x7f) {
|
||||
this.pos += 3;
|
||||
return (this.buf[pos] & 0x7f) | (this.buf[pos + 1] & 0x7f) << 7 | (this.buf[pos + 2]) << 14;
|
||||
} else if (this.buf[pos + 3] <= 0x7f) {
|
||||
this.pos += 4;
|
||||
return (this.buf[pos] & 0x7f) | (this.buf[pos + 1] & 0x7f) << 7 | (this.buf[pos + 2] & 0x7f) << 14 | (this.buf[pos + 3]) << 21;
|
||||
} else if (this.buf[pos + 4] <= 0x7f) {
|
||||
this.pos += 5;
|
||||
return ((this.buf[pos] & 0x7f) | (this.buf[pos + 1] & 0x7f) << 7 | (this.buf[pos + 2] & 0x7f) << 14 | (this.buf[pos + 3]) << 21) + (this.buf[pos + 4] * 268435456);
|
||||
} else {
|
||||
throw new Error("TODO: Handle 6+ byte varints");
|
||||
}
|
||||
};
|
||||
|
||||
Protobuf.prototype.readSVarint = function() {
|
||||
var num = this.readVarint();
|
||||
if (num > 2147483647) throw new Error('TODO: Handle numbers >= 2^30');
|
||||
// zigzag encoding
|
||||
return ((num >> 1) ^ -(num & 1));
|
||||
};
|
||||
|
||||
Protobuf.prototype.readString = function() {
|
||||
var bytes = this.readVarint();
|
||||
// Node.js
|
||||
var str = this.buf.toString('utf8', this.pos, this.pos + bytes);
|
||||
// Client side JS code:
|
||||
// // TODO: bounds checking
|
||||
// var chr = String.fromCharCode;
|
||||
// var b = this.buf;
|
||||
// var p = this.pos;
|
||||
// var end = this.pos;
|
||||
// var str = '';
|
||||
// while (p < end) {
|
||||
// if (b[p] <= 0x7F) str += chr(b[p++]);
|
||||
// else if (b[p] <= 0xBF) throw new Error('Invalid UTF-8 codepoint: ' + b[p]);
|
||||
// else if (b[p] <= 0xDF) str += chr((b[p++] & 0x1F) << 6 | (b[p++] & 0x3F));
|
||||
// else if (b[p] <= 0xEF) str += chr((b[p++] & 0x1F) << 12 | (b[p++] & 0x3F) << 6 | (b[p++] & 0x3F));
|
||||
// else if (b[p] <= 0xF7) p += 4; // We can't handle these codepoints in JS, so skip.
|
||||
// else if (b[p] <= 0xFB) p += 5;
|
||||
// else if (b[p] <= 0xFD) p += 6;
|
||||
// else throw new Error('Invalid UTF-8 codepoint: ' + b[p]);
|
||||
// }
|
||||
this.pos += bytes;
|
||||
return str;
|
||||
};
|
||||
|
||||
Protobuf.prototype.readPacked = function(type) {
|
||||
// TODO: bounds checking
|
||||
var bytes = this.readVarint();
|
||||
var end = this.pos + bytes;
|
||||
var array = [];
|
||||
while (this.pos < end) {
|
||||
array.push(this['read' + type]());
|
||||
}
|
||||
return array;
|
||||
};
|
||||
|
||||
Protobuf.prototype.skip = function(val) {
|
||||
// TODO: bounds checking
|
||||
var type = val & 0x7;
|
||||
switch (type) {
|
||||
/* varint */ case 0: while (this.buf[this.pos++] > 0x7f); break;
|
||||
/* 64 bit */ case 1: this.pos += 8; break;
|
||||
/* length */ case 2: var bytes = this.readVarint(); this.pos += bytes; break;
|
||||
/* 32 bit */ case 5: this.pos += 4; break;
|
||||
default: throw new Error('Unimplemented type: ' + type);
|
||||
}
|
||||
};
|
||||
|
||||
// Generic read function
|
||||
Protobuf.prototype.read = function(spec, end) {
|
||||
var ref, tag;
|
||||
var obj = {};
|
||||
for (tag in spec) {
|
||||
ref = spec[tag];
|
||||
if ('default' in ref) {
|
||||
obj[ref.name] = ref['default'];
|
||||
}
|
||||
|
||||
if ('repeated' in ref) {
|
||||
obj[ref.name] = [];
|
||||
}
|
||||
}
|
||||
|
||||
var begin = this.pos;
|
||||
if (typeof end == 'undefined') {
|
||||
var bytes = this.readVarint();
|
||||
end = this.pos + bytes;
|
||||
}
|
||||
|
||||
while (this.pos < end) {
|
||||
var val = this.readVarint();
|
||||
tag = val >> 3;
|
||||
ref = spec[tag];
|
||||
if (ref) {
|
||||
if (ref.packed) {
|
||||
obj[ref.name] = this.readPacked(ref.type);
|
||||
}
|
||||
else if (ref.repeated) {
|
||||
if (!obj[ref.name]) obj[ref.name] = [];
|
||||
obj[ref.name].push(this['read' + ref.type]());
|
||||
} else {
|
||||
obj[ref.name] = this['read' + ref.type]();
|
||||
}
|
||||
} else {
|
||||
this.skip(val);
|
||||
}
|
||||
}
|
||||
|
||||
if (this._debug) {
|
||||
obj._begin = begin;
|
||||
obj._end = end;
|
||||
obj._bytes = obj._end - obj._begin;
|
||||
}
|
||||
|
||||
for (tag in spec) {
|
||||
ref = spec[tag];
|
||||
if (!(ref.name in obj) && ('required' in ref)) {
|
||||
throw new Error('Field ' + ref.name + ' is required');
|
||||
}
|
||||
}
|
||||
|
||||
return obj;
|
||||
};
|
||||
|
||||
// === WRITING =================================================================
|
||||
|
||||
Protobuf.Varint = 0;
|
||||
Protobuf.Int64 = 1;
|
||||
Protobuf.Message = 2;
|
||||
Protobuf.String = 2;
|
||||
Protobuf.Packed = 2;
|
||||
Protobuf.Int32 = 5;
|
||||
|
||||
Protobuf.prototype.writeTag = function(tag, type) {
|
||||
this.writeVarint((tag << 3) | type);
|
||||
};
|
||||
|
||||
Protobuf.prototype.writeUInt32 = function(val) {
|
||||
while (this.length < this.pos + 4) this.realloc();
|
||||
this.buf.writeUInt32LE(val, this.pos);
|
||||
this.pos += 4;
|
||||
};
|
||||
|
||||
Protobuf.prototype.writeTaggedUInt32 = function(tag, val) {
|
||||
this.writeTag(tag, Protobuf.Int32);
|
||||
this.writeUInt32(val);
|
||||
};
|
||||
|
||||
Protobuf.prototype.writeVarint = function(val) {
|
||||
val = Number(val);
|
||||
if (isNaN(val)) {
|
||||
val = 0;
|
||||
}
|
||||
|
||||
if (val <= 0x7f) {
|
||||
while (this.length < this.pos + 1) this.realloc();
|
||||
this.buf[this.pos++] = val;
|
||||
} else if (val <= 0x3fff) {
|
||||
while (this.length < this.pos + 2) this.realloc();
|
||||
this.buf[this.pos++] = 0x80 | ((val >>> 0) & 0x7f);
|
||||
this.buf[this.pos++] = 0x00 | ((val >>> 7) & 0x7f);
|
||||
} else if (val <= 0x1ffffff) {
|
||||
while (this.length < this.pos + 3) this.realloc();
|
||||
this.buf[this.pos++] = 0x80 | ((val >>> 0) & 0x7f);
|
||||
this.buf[this.pos++] = 0x80 | ((val >>> 7) & 0x7f);
|
||||
this.buf[this.pos++] = 0x00 | ((val >>> 14) & 0x7f);
|
||||
} else if (val <= 0xfffffff) {
|
||||
while (this.length < this.pos + 4) this.realloc();
|
||||
this.buf[this.pos++] = 0x80 | ((val >>> 0) & 0x7f);
|
||||
this.buf[this.pos++] = 0x80 | ((val >>> 7) & 0x7f);
|
||||
this.buf[this.pos++] = 0x80 | ((val >>> 14) & 0x7f);
|
||||
this.buf[this.pos++] = 0x00 | ((val >>> 21) & 0x7f);
|
||||
} else {
|
||||
throw new Error("TODO: Handle 5+ byte varints (" + val + ")");
|
||||
}
|
||||
};
|
||||
|
||||
Protobuf.prototype.writeTaggedVarint = function(tag, val) {
|
||||
this.writeTag(tag, Protobuf.Varint);
|
||||
this.writeVarint(val);
|
||||
};
|
||||
|
||||
Protobuf.prototype.writeBoolean = function(val) {
|
||||
this.writeVarint(Boolean(val));
|
||||
};
|
||||
|
||||
Protobuf.prototype.writeTaggedBoolean = function(tag, val) {
|
||||
this.writeTaggedVarint(tag, Boolean(val));
|
||||
};
|
||||
|
||||
Protobuf.prototype.writeString = function(str) {
|
||||
str = String(str);
|
||||
var bytes = Buffer.byteLength(str);
|
||||
this.writeVarint(bytes);
|
||||
while (this.length < this.pos + bytes) this.realloc();
|
||||
this.buf.write(str, this.pos);
|
||||
this.pos += bytes;
|
||||
};
|
||||
|
||||
Protobuf.prototype.writeTaggedString = function(tag, str) {
|
||||
this.writeTag(tag, Protobuf.String);
|
||||
this.writeString(str);
|
||||
};
|
||||
|
||||
Protobuf.prototype.writeFloat = function(val) {
|
||||
while (this.length < this.pos + 4) this.realloc();
|
||||
this.buf.writeFloatLE(val, this.pos);
|
||||
this.pos += 4;
|
||||
};
|
||||
|
||||
Protobuf.prototype.writeTaggedFloat = function(tag, val) {
|
||||
this.writeTag(tag, Protobuf.Int32);
|
||||
this.writeFloat(val);
|
||||
};
|
||||
|
||||
Protobuf.prototype.writeDouble = function(val) {
|
||||
while (this.length < this.pos + 8) this.realloc();
|
||||
this.buf.writeDoubleLE(val, this.pos);
|
||||
this.pos += 8;
|
||||
};
|
||||
|
||||
Protobuf.prototype.writeTaggedDouble = function(tag, val) {
|
||||
this.writeTag(tag, Protobuf.Int64);
|
||||
this.writeDouble(val);
|
||||
};
|
||||
|
||||
Protobuf.prototype.writeBuffer = function(buffer) {
|
||||
var bytes = buffer.length;
|
||||
this.writeVarint(bytes);
|
||||
while (this.length < this.pos + bytes) this.realloc();
|
||||
buffer.copy(this.buf, this.pos);
|
||||
this.pos += bytes;
|
||||
};
|
||||
|
||||
Protobuf.prototype.writeMessage = function(tag, protobuf) {
|
||||
var buffer = protobuf.finish();
|
||||
this.writeTag(tag, Protobuf.Message);
|
||||
this.writeBuffer(buffer);
|
||||
};
|
||||
|
||||
Protobuf.prototype.writeRepeated = function(type, tag, items) {
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
this['write' + type](tag, items[i]);
|
||||
}
|
||||
};
|
||||
|
||||
Protobuf.prototype.writePacked = function(type, tag, items) {
|
||||
if (!items.length) return;
|
||||
|
||||
var message = new Protobuf();
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
message['write' + type](items[i]);
|
||||
}
|
||||
var data = message.finish();
|
||||
|
||||
this.writeTag(tag, Protobuf.Packed);
|
||||
this.writeBuffer(data);
|
||||
};
|
||||
|
||||
Protobuf.prototype.writePackedVarints = function(tag, items) {
|
||||
this.writePacked('Varint', tag, items);
|
||||
};
|
||||
|
||||
Protobuf.prototype.writePackedFloats = function(tag, items) {
|
||||
this.writePacked('Float', tag, items);
|
||||
};
|
||||
|
||||
Protobuf.prototype.realloc = function() {
|
||||
var buf = new Buffer(this.buf.length * 2);
|
||||
this.buf.copy(buf);
|
||||
this.buf = buf;
|
||||
this.length = this.buf.length;
|
||||
};
|
||||
|
||||
Protobuf.prototype.finish = function() {
|
||||
return this.buf.slice(0, this.pos);
|
||||
};
|
||||
127
bin/style.js
Normal file
127
bin/style.js
Normal file
@@ -0,0 +1,127 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
"buckets": {
|
||||
"water": {
|
||||
"datasource": "streets",
|
||||
"layer": "water",
|
||||
"type": "fill"
|
||||
},
|
||||
"road_large": {
|
||||
"datasource": "streets",
|
||||
"layer": "road", "field": "class", "value": ["motorway", "main"],
|
||||
"type": "line", "cap": "round", "join": "bevel"
|
||||
},
|
||||
"road_regular": {
|
||||
"datasource": "streets",
|
||||
"layer": "road", "field": "class", "value": "street",
|
||||
"type": "line", "cap": "round", "join": "bevel"
|
||||
},
|
||||
"road_limited": {
|
||||
"datasource": "streets",
|
||||
"layer": "road", "field": "class", "value": "street_limited",
|
||||
"type": "line", "cap": "round", "join": "bevel"
|
||||
},
|
||||
"park": {
|
||||
"datasource": "streets",
|
||||
"layer": "landuse", "field": "class", "value": "park",
|
||||
"type": "fill"
|
||||
},
|
||||
"wood": {
|
||||
"datasource": "streets",
|
||||
"layer": "landuse", "field": "class", "value": "wood",
|
||||
"type": "fill"
|
||||
},
|
||||
"school": {
|
||||
"datasource": "streets",
|
||||
"layer": "landuse", "field": "class", "value": "school",
|
||||
"type": "fill"
|
||||
},
|
||||
"cemetery": {
|
||||
"datasource": "streets",
|
||||
"layer": "landuse", "field": "class", "value": "cemetery",
|
||||
"type": "fill"
|
||||
},
|
||||
"industrial": {
|
||||
"datasource": "streets",
|
||||
"layer": "landuse", "field": "class", "value": "industrial",
|
||||
"type": "fill"
|
||||
},
|
||||
"building": {
|
||||
"datasource": "streets",
|
||||
"layer": "building",
|
||||
"type": "fill"
|
||||
},
|
||||
"alcohol": {
|
||||
"datasource": "streets",
|
||||
"layer": "poi_label",
|
||||
"field": "type",
|
||||
"value": ["Alcohol"],
|
||||
"type": "point"
|
||||
}
|
||||
},
|
||||
"sprite": "img/maki-sprite",
|
||||
"structure": [
|
||||
{ "name": "park", "bucket": "park" },
|
||||
{ "name": "wood", "bucket": "wood" },
|
||||
{ "name": "water", "bucket": "water" },
|
||||
{ "name": "road_limited", "bucket": "road_limited" },
|
||||
{ "name": "road_regular", "bucket": "road_regular" },
|
||||
{ "name": "road_large", "bucket": "road_large" },
|
||||
{ "name": "alcohol", "bucket": "alcohol" }
|
||||
],
|
||||
"classes": [
|
||||
{
|
||||
"name": "default",
|
||||
"layers": {
|
||||
"background": {
|
||||
"color": "#FFFFFF"
|
||||
},
|
||||
"park": {
|
||||
"color": "#c8df9f",
|
||||
"antialias": true
|
||||
},
|
||||
"wood": {
|
||||
"color": "#33AA66",
|
||||
"antialias": true
|
||||
},
|
||||
"water": {
|
||||
"color": "#73b6e6",
|
||||
"antialias": true
|
||||
},
|
||||
"road_limited": {
|
||||
"color": "#BBBBBB",
|
||||
"width": [
|
||||
"stops",
|
||||
{ z: 0, val: 1 },
|
||||
{ z: 20, val: 1 }
|
||||
]
|
||||
},
|
||||
"road_regular": {
|
||||
"color": "#999999",
|
||||
"width": [
|
||||
"stops",
|
||||
{ z: 0, val: 0.5 },
|
||||
{ z: 13, val: 0.5 },
|
||||
{ z: 16, val: 2 },
|
||||
{ z: 20, val: 32 }
|
||||
],
|
||||
},
|
||||
"road_large": {
|
||||
"color": "#666666",
|
||||
"width": [
|
||||
"stops",
|
||||
{ z: 0, val: 0.5 },
|
||||
{ z: 11, val: 0.5 },
|
||||
{ z: 13, val: 1 },
|
||||
{ z: 16, val: 4 },
|
||||
{ z: 20, val: 64 }
|
||||
],
|
||||
},
|
||||
"alcohol": {
|
||||
"image": "alcohol-shop"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
61
proto/style.proto
Normal file
61
proto/style.proto
Normal file
@@ -0,0 +1,61 @@
|
||||
enum bucket_type {
|
||||
fill = 1;
|
||||
line = 2;
|
||||
point = 3;
|
||||
}
|
||||
|
||||
enum cap_type {
|
||||
round = 1;
|
||||
}
|
||||
|
||||
enum join_type {
|
||||
butt = 1;
|
||||
bevel = 2;
|
||||
}
|
||||
|
||||
message bucket {
|
||||
required string name = 1;
|
||||
required bucket_type type = 2;
|
||||
|
||||
// Specify what data to pull into this bucket
|
||||
required string source_name = 3;
|
||||
required string source_layer = 4;
|
||||
optional string source_field = 5;
|
||||
repeated string source_values = 6;
|
||||
|
||||
// Specifies how the geometry for this bucket should be created
|
||||
optional cap_type cap = 7;
|
||||
optional join_type join = 8;
|
||||
optional string font = 9;
|
||||
optional float fontSize = 10;
|
||||
}
|
||||
|
||||
message structure {
|
||||
required string name = 1;
|
||||
optional string bucket_name = 2;
|
||||
repeated structure child_layers = 3;
|
||||
}
|
||||
|
||||
message width {
|
||||
optional string scaling = 1;
|
||||
repeated float values = 2 [ packed = true ];
|
||||
}
|
||||
|
||||
message layer {
|
||||
required string layer_name = 1;
|
||||
optional fixed32 color = 2; // rgba (=> rgb << 8 | 0xFF for opaque!)
|
||||
optional bool antialias = 3;
|
||||
optional width width = 4;
|
||||
}
|
||||
|
||||
message class {
|
||||
required string name = 1;
|
||||
repeated layer layers = 2;
|
||||
}
|
||||
|
||||
// root level object
|
||||
message style {
|
||||
repeated bucket buckets = 1;
|
||||
repeated structure structure = 2;
|
||||
repeated class classes = 3;
|
||||
}
|
||||
Reference in New Issue
Block a user