diff options
-rwxr-xr-x | bin/build-style.js | 12 | ||||
-rwxr-xr-x | bin/convert-style.js | 98 | ||||
-rw-r--r-- | bin/style.js | 11 | ||||
-rw-r--r-- | include/llmr/map/transform.hpp | 2 | ||||
-rw-r--r-- | include/llmr/style/class_description.hpp | 18 | ||||
-rw-r--r-- | include/llmr/style/properties.hpp | 69 | ||||
-rw-r--r-- | include/llmr/style/style.hpp | 14 | ||||
-rw-r--r-- | proto/style.proto | 44 | ||||
-rw-r--r-- | resources/style.pbf | bin | 947 -> 936 bytes | |||
-rw-r--r-- | src/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/map/map.cpp | 3 | ||||
-rw-r--r-- | src/map/transform.cpp | 4 | ||||
-rw-r--r-- | src/renderer/painter.cpp | 16 | ||||
-rw-r--r-- | src/resources/style.cpp | 60 | ||||
-rw-r--r-- | src/style/properties.cpp | 25 | ||||
-rw-r--r-- | src/style/style.cpp | 138 |
16 files changed, 405 insertions, 110 deletions
diff --git a/bin/build-style.js b/bin/build-style.js index 227c164a28..26445ab26c 100755 --- a/bin/build-style.js +++ b/bin/build-style.js @@ -30,8 +30,16 @@ code += '\n'; code += 'using namespace llmr;\n'; code += '\n'; code += 'const unsigned char resources::' + name + '[] = {\n'; -code += ' ' + Array.prototype.join.call(data, ', ') + '\n'; -code += '};\n'; + + +for (var i = 0; i < data.length; i += 16) { + if (i > 0) { + code += ',\n'; + } + var part = data.slice(i, i + 16); + code += ' ' + Array.prototype.join.call(part, ', '); +} +code += '\n};\n'; code += 'const unsigned long resources::' + name + '_size = sizeof(resources::' + name + ');\n'; fs.writeFileSync('src/resources/' + name + '.cpp', code); diff --git a/bin/convert-style.js b/bin/convert-style.js index 78cc17d5a5..be38458eab 100755 --- a/bin/convert-style.js +++ b/bin/convert-style.js @@ -27,6 +27,13 @@ var join_type = { bevel: 2 }; +// enum +var property_type = { + 'null': 1, + constant: 2, + stops: 3 +}; + function createValue(value) { var pbf = new Protobuf(); @@ -83,45 +90,91 @@ function createStructure(structure) { return pbf; } -function createWidth(width) { +// 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 /* value */, values); + +// return pbf; +// } + +function createProperty(type, values) { 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 /* value */, values); + pbf.writeTaggedVarint(1 /* function */, property_type[type]); + pbf.writePackedFloats(2 /* value */, values.map(function(value) { return +value; })); return pbf; } -function createLayer(layer, name) { +function createFillClass(layer, name) { var pbf = new Protobuf(); pbf.writeTaggedString(1 /* layer_name */, name); + if ('antialias' in layer) { + pbf.writeMessage(4 /* antialias */, createProperty('constant', [layer.antialias])); + } + 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)); + pbf.writeTaggedUInt32(5 /* fill_color */, parseInt(color[1] + 'ff', 16)); } } - if ('antialias' in layer) { - pbf.writeTaggedBoolean(3 /* antialias */, layer.antialias); + if ('opacity' in layer) { + if (typeof layer.opacity == 'number') { + pbf.writeMessage(7 /* opacity */, createProperty('constant', [layer.opacity])); + } + } + + return pbf; +} + +function createLineClass(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(3 /* color */, parseInt(color[1] + 'ff', 16)); + } } if ('width' in layer) { - pbf.writeMessage(4 /* width */, createWidth(layer.width)); + var values = []; + var width = layer.width; + var type = 'constant'; + if (Array.isArray(width)) { + type = 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.writeMessage(4 /* width */, createProperty(type, values)); } return pbf; @@ -132,7 +185,10 @@ function createClass(klass) { var pbf = new Protobuf(); pbf.writeTaggedString(1 /* name */, klass.name); for (var name in klass.layers) { - pbf.writeMessage(2 /* layer */, createLayer(klass.layers[name], name)); + switch (klass.layers[name].type) { + case 'fill': pbf.writeMessage(2 /* fill */, createFillClass(klass.layers[name], name)); break; + case 'line': pbf.writeMessage(3 /* line */, createLineClass(klass.layers[name], name)); break; + } } return pbf; } diff --git a/bin/style.js b/bin/style.js index d218e125c1..d9f9f36614 100644 --- a/bin/style.js +++ b/bin/style.js @@ -75,21 +75,27 @@ module.exports = { "name": "default", "layers": { "background": { + "type": "background", "color": "#FFFFFF" }, "park": { + "type": "fill", "color": "#c8df9f", "antialias": true }, "wood": { + "type": "fill", "color": "#33AA66", - "antialias": true + "antialias": true, + "opacity": 0.1 }, "water": { + "type": "fill", "color": "#73b6e6", "antialias": true }, "road_limited": { + "type": "line", "color": "#BBBBBB", "width": [ "stops", @@ -98,6 +104,7 @@ module.exports = { ] }, "road_regular": { + "type": "line", "color": "#999999", "width": [ "stops", @@ -108,6 +115,7 @@ module.exports = { ], }, "road_large": { + "type": "line", "color": "#666666", "width": [ "stops", @@ -119,6 +127,7 @@ module.exports = { ], }, "alcohol": { + "type": "marker", "image": "alcohol-shop" } } diff --git a/include/llmr/map/transform.hpp b/include/llmr/map/transform.hpp index 78c06e2a18..b6578b0926 100644 --- a/include/llmr/map/transform.hpp +++ b/include/llmr/map/transform.hpp @@ -39,7 +39,7 @@ public: // Getters void matrixFor(float matrix[16], const vec3<int32_t>& id) const; - int32_t getZoom() const; + float getZoom() const; double getScale() const; double getAngle() const; void getLonLat(double& lon, double& lat) const; diff --git a/include/llmr/style/class_description.hpp b/include/llmr/style/class_description.hpp index a63dc8d041..3130f8d78f 100644 --- a/include/llmr/style/class_description.hpp +++ b/include/llmr/style/class_description.hpp @@ -8,24 +8,12 @@ namespace llmr { - -class WidthDescription { -public: - std::string scaling; - std::vector<float> value; -}; - - -class LayerStyleDescription { +class ClassDescription { public: - Color color = {{ 0, 0, 0, 0 }}; - bool antialias = false; - WidthDescription width; + std::map<std::string, FillClass> fill; + std::map<std::string, StrokeClass> stroke; }; -typedef std::map<std::string, LayerStyleDescription> ClassDescription; - -std::ostream& operator<<(std::ostream&, const ClassDescription& layer); } diff --git a/include/llmr/style/properties.hpp b/include/llmr/style/properties.hpp index 8eb0969c71..71b3b3aa95 100644 --- a/include/llmr/style/properties.hpp +++ b/include/llmr/style/properties.hpp @@ -2,12 +2,13 @@ #define LLMR_STYLE_PROPERTIES #include <array> +#include <vector> namespace llmr { typedef std::array<float, 4> Color; -enum Winding { +enum class Winding { EvenOdd = 1, NonZero = 2 }; @@ -22,19 +23,71 @@ enum Winding { // }; +enum class Property { + Null = 1, + Constant = 2, + Stops = 3 +}; + +namespace functions { + +float null(float z, const std::vector<float>&); +bool null(float z, const std::vector<bool>&); + +float constant(float z, const std::vector<float>& values); +bool constant(float z, const std::vector<bool>& values); + +} + + +template <typename T> +struct FunctionProperty { + typedef T (*fn)(float z, const std::vector<T>& values); + + fn function; + std::vector<T> values; + + inline FunctionProperty() : function(&functions::null) {} + inline FunctionProperty(T value) : function(&functions::constant), values(1, value) {} + inline T operator()(float z) const { return function(z, values); } +}; + + +// StrokeClass is the information we parse from the stylesheet +struct StrokeClass { + FunctionProperty<bool> hidden; + FunctionProperty<float> width; + FunctionProperty<float> offset; + Color color = {{ 0, 0, 0, 1 }}; +}; + +// StrokeProperties is the one we resolve this to. struct StrokeProperties { - bool enabled = false; - Color line_color = {{ 0, 0, 0, 1 }}; - float line_width = 1; + bool hidden = false; + float width = 0; + float offset = 0; + Color color = {{ 0, 0, 0, 1 }}; +}; + + + + +struct FillClass { + FunctionProperty<bool> hidden; + Winding winding = Winding::NonZero; + FunctionProperty<bool> antialias = true; + Color fill_color = {{ 0, 0, 0, 1 }}; + Color stroke_color = {{ 0, 0, 0, std::numeric_limits<float>::infinity() }}; + FunctionProperty<float> opacity = 1; }; struct FillProperties { - bool enabled = false; - Winding winding = NonZero; - bool antialiasing = true; + bool hidden = false; + Winding winding = Winding::NonZero; + bool antialias = true; Color fill_color = {{ 0, 0, 0, 1 }}; Color stroke_color = {{ 0, 0, 0, 1 }}; - float stroke_width = 1; + float opacity = 1.0; }; } diff --git a/include/llmr/style/style.hpp b/include/llmr/style/style.hpp index ee99ff2243..a690a31e56 100644 --- a/include/llmr/style/style.hpp +++ b/include/llmr/style/style.hpp @@ -21,14 +21,16 @@ public: void reset(); void load(const uint8_t *const data, uint32_t bytes); - void cascade(); + void cascade(float z); private: - static std::pair<std::string, BucketDescription> loadBucket(pbf data); - static LayerDescription loadLayer(pbf data); - static std::pair<std::string, ClassDescription> loadClass(pbf data); - static std::pair<std::string, LayerStyleDescription> loadLayerStyle(pbf data); - static WidthDescription loadWidth(pbf data); + static std::pair<std::string, BucketDescription> parseBucket(pbf data); + static LayerDescription parseLayer(pbf data); + static std::pair<std::string, ClassDescription> parseClass(pbf data); + static std::pair<std::string, FillClass> parseFillClass(pbf data); + static std::pair<std::string, StrokeClass> parseStrokeClass(pbf data); + template <typename T> static FunctionProperty<T> parseProperty(pbf data); + static Color parseColor(pbf& data); public: // This is static information parsed from the stylesheet. diff --git a/proto/style.proto b/proto/style.proto index d5f1c6c9f5..5a977d799c 100644 --- a/proto/style.proto +++ b/proto/style.proto @@ -2,6 +2,8 @@ enum bucket_type { fill = 1; line = 2; point = 3; + + background = 15; } enum cap_type { @@ -13,6 +15,17 @@ enum join_type { bevel = 2; } +enum winding_type { + evenodd = 1; + nonzero = 2; +} + +enum property_type { + null = 1; + constant = 2; + stops = 3; +} + message value { // Exactly one of these values may be present in a valid message optional string string_value = 1; @@ -49,21 +62,38 @@ message layer { repeated layer child_layer = 3; } -message width { - optional string scaling = 1; +message property { + required property_type function = 1; repeated float value = 2 [ packed = true ]; } -message layer_style { +message fill_style { + required string layer_name = 1; + optional property hidden = 2; + optional winding_type winding = 3 [ default = nonzero ]; + optional property antialias = 4; + optional fixed32 fill_color = 5 [ default = 0x000000FF ]; // rgba (=> rgb << 8 | 0xFF for opaque!) + optional fixed32 stroke_color = 6; // if none is specified, no stroke will be painted + optional property opacity = 7; // values from 0..1 + // TODO: translate x/y +} + +message stroke_style { required string layer_name = 1; - optional fixed32 color = 2; // rgba (=> rgb << 8 | 0xFF for opaque!) - optional bool antialias = 3; - optional width width = 4; + optional property hidden = 2; + optional fixed32 color = 3 [ default = 0x000000FF ]; // rgba (=> rgb << 8 | 0xFF for opaque!) + optional property width = 4; + optional property offset = 5; + // line join + line cap are already defined in the + // TODO: dasharray + // TODO: image/icon + // TODO: translate x/y } message class { required string name = 1; - repeated layer_style layer = 2; + repeated fill_style fill = 2; + repeated stroke_style stroke = 3; } // root level object diff --git a/resources/style.pbf b/resources/style.pbf Binary files differindex a916d4ed69..90b496b70b 100644 --- a/resources/style.pbf +++ b/resources/style.pbf diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6a6e7e4a9b..14a3e88125 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -17,6 +17,7 @@ SET(llmr_SOURCES style/value.cpp style/bucket_description.cpp style/layer_description.cpp + style/properties.cpp util/animation.cpp util/mat4.cpp ) diff --git a/src/map/map.cpp b/src/map/map.cpp index 31c4f1d81f..2b008c2ccf 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -39,6 +39,7 @@ void Map::loadSettings() { transform.setAngle(settings.angle); transform.setScale(settings.scale); transform.setLonLat(settings.longitude, settings.latitude); + style.cascade(transform.getZoom()); update(); } @@ -60,6 +61,7 @@ void Map::moveBy(double dx, double dy) { void Map::scaleBy(double ds, double cx, double cy) { transform.scaleBy(ds, cx, cy); + style.cascade(transform.getZoom()); update(); transform.getLonLat(settings.longitude, settings.latitude); @@ -87,6 +89,7 @@ void Map::resetPosition() { transform.setAngle(0); transform.setLonLat(0, 0); transform.setZoom(0); + style.cascade(transform.getZoom()); update(); transform.getLonLat(settings.longitude, settings.latitude); diff --git a/src/map/transform.cpp b/src/map/transform.cpp index cf0139cb3b..7f8d9939d1 100644 --- a/src/map/transform.cpp +++ b/src/map/transform.cpp @@ -164,8 +164,8 @@ void Transform::matrixFor(float matrix[16], const vec3<int32_t>& id) const { mat4::translate(matrix, matrix, 0, 0, -1); } -int32_t Transform::getZoom() const { - return floor(log(scale) / M_LN2); +float Transform::getZoom() const { + return log(scale) / M_LN2; } double Transform::getScale() const { diff --git a/src/renderer/painter.cpp b/src/renderer/painter.cpp index 139e434820..84e8f95946 100644 --- a/src/renderer/painter.cpp +++ b/src/renderer/painter.cpp @@ -204,7 +204,13 @@ void Painter::renderLayers(const std::shared_ptr<Tile>& tile, const std::vector< void Painter::renderFill(FillBucket& bucket, const std::string& layer_name) { const FillProperties& properties = style.computed.fills[layer_name]; - if (!properties.enabled) return; + if (properties.hidden) return; + + Color fill_color = properties.fill_color; + fill_color[0] *= properties.opacity; + fill_color[1] *= properties.opacity; + fill_color[2] *= properties.opacity; + fill_color[3] *= properties.opacity; // Draw the stencil mask. { @@ -219,7 +225,7 @@ void Painter::renderFill(FillBucket& bucket, const std::string& layer_name) { // orientation, while all holes (see below) are in CW orientation. glStencilFunc(GL_NOTEQUAL, 0x80, 0x80); - if (properties.winding == EvenOdd) { + if (properties.winding == Winding::EvenOdd) { // When we draw an even/odd winding fill, we just invert all the bits. glStencilOp(GL_INVERT, GL_KEEP, GL_KEEP); } else { @@ -252,7 +258,7 @@ void Painter::renderFill(FillBucket& bucket, const std::string& layer_name) { // Because we're drawing top-to-bottom, and we update the stencil mask // below, we have to draw the outline first (!) - if (properties.antialiasing) { + if (properties.antialias) { switchShader(outlineShader); glUniformMatrix4fv(outlineShader->u_matrix, 1, GL_FALSE, matrix); glLineWidth(2); @@ -270,7 +276,7 @@ void Painter::renderFill(FillBucket& bucket, const std::string& layer_name) { // the current shape, some pixels from the outline stroke overlapped // the (non-antialiased) fill. glStencilFunc(GL_EQUAL, 0x80, 0xBF); - glUniform4fv(outlineShader->u_color, 1, properties.fill_color.data()); + glUniform4fv(outlineShader->u_color, 1, fill_color.data()); } // Draw the entire line @@ -307,7 +313,7 @@ void Painter::renderFill(FillBucket& bucket, const std::string& layer_name) { // Draw filling rectangle. switchShader(fillShader); glUniformMatrix4fv(fillShader->u_matrix, 1, GL_FALSE, matrix); - glUniform4fv(fillShader->u_color, 1, properties.fill_color.data()); + glUniform4fv(fillShader->u_color, 1, fill_color.data()); } // Only draw regions that we marked diff --git a/src/resources/style.cpp b/src/resources/style.cpp index 69c0b10655..57bad8636f 100644 --- a/src/resources/style.cpp +++ b/src/resources/style.cpp @@ -4,6 +4,64 @@ using namespace llmr; const unsigned char resources::style[] = { - 10, 25, 10, 5, 119, 97, 116, 101, 114, 16, 1, 26, 7, 115, 116, 114, 101, 101, 116, 115, 34, 5, 119, 97, 116, 101, 114, 10, 60, 10, 10, 114, 111, 97, 100, 95, 108, 97, 114, 103, 101, 16, 2, 26, 7, 115, 116, 114, 101, 101, 116, 115, 34, 4, 114, 111, 97, 100, 42, 5, 99, 108, 97, 115, 115, 50, 10, 10, 8, 109, 111, 116, 111, 114, 119, 97, 121, 50, 6, 10, 4, 109, 97, 105, 110, 56, 1, 64, 2, 10, 52, 10, 12, 114, 111, 97, 100, 95, 114, 101, 103, 117, 108, 97, 114, 16, 2, 26, 7, 115, 116, 114, 101, 101, 116, 115, 34, 4, 114, 111, 97, 100, 42, 5, 99, 108, 97, 115, 115, 50, 8, 10, 6, 115, 116, 114, 101, 101, 116, 56, 1, 64, 2, 10, 60, 10, 12, 114, 111, 97, 100, 95, 108, 105, 109, 105, 116, 101, 100, 16, 2, 26, 7, 115, 116, 114, 101, 101, 116, 115, 34, 4, 114, 111, 97, 100, 42, 5, 99, 108, 97, 115, 115, 50, 16, 10, 14, 115, 116, 114, 101, 101, 116, 95, 108, 105, 109, 105, 116, 101, 100, 56, 1, 64, 2, 10, 41, 10, 4, 112, 97, 114, 107, 16, 1, 26, 7, 115, 116, 114, 101, 101, 116, 115, 34, 7, 108, 97, 110, 100, 117, 115, 101, 42, 5, 99, 108, 97, 115, 115, 50, 6, 10, 4, 112, 97, 114, 107, 10, 41, 10, 4, 119, 111, 111, 100, 16, 1, 26, 7, 115, 116, 114, 101, 101, 116, 115, 34, 7, 108, 97, 110, 100, 117, 115, 101, 42, 5, 99, 108, 97, 115, 115, 50, 6, 10, 4, 119, 111, 111, 100, 10, 45, 10, 6, 115, 99, 104, 111, 111, 108, 16, 1, 26, 7, 115, 116, 114, 101, 101, 116, 115, 34, 7, 108, 97, 110, 100, 117, 115, 101, 42, 5, 99, 108, 97, 115, 115, 50, 8, 10, 6, 115, 99, 104, 111, 111, 108, 10, 49, 10, 8, 99, 101, 109, 101, 116, 101, 114, 121, 16, 1, 26, 7, 115, 116, 114, 101, 101, 116, 115, 34, 7, 108, 97, 110, 100, 117, 115, 101, 42, 5, 99, 108, 97, 115, 115, 50, 10, 10, 8, 99, 101, 109, 101, 116, 101, 114, 121, 10, 53, 10, 10, 105, 110, 100, 117, 115, 116, 114, 105, 97, 108, 16, 1, 26, 7, 115, 116, 114, 101, 101, 116, 115, 34, 7, 108, 97, 110, 100, 117, 115, 101, 42, 5, 99, 108, 97, 115, 115, 50, 12, 10, 10, 105, 110, 100, 117, 115, 116, 114, 105, 97, 108, 10, 31, 10, 8, 98, 117, 105, 108, 100, 105, 110, 103, 16, 1, 26, 7, 115, 116, 114, 101, 101, 116, 115, 34, 8, 98, 117, 105, 108, 100, 105, 110, 103, 10, 48, 10, 7, 97, 108, 99, 111, 104, 111, 108, 16, 3, 26, 7, 115, 116, 114, 101, 101, 116, 115, 34, 9, 112, 111, 105, 95, 108, 97, 98, 101, 108, 42, 4, 116, 121, 112, 101, 50, 9, 10, 7, 65, 108, 99, 111, 104, 111, 108, 18, 12, 10, 4, 112, 97, 114, 107, 18, 4, 112, 97, 114, 107, 18, 12, 10, 4, 119, 111, 111, 100, 18, 4, 119, 111, 111, 100, 18, 14, 10, 5, 119, 97, 116, 101, 114, 18, 5, 119, 97, 116, 101, 114, 18, 28, 10, 12, 114, 111, 97, 100, 95, 108, 105, 109, 105, 116, 101, 100, 18, 12, 114, 111, 97, 100, 95, 108, 105, 109, 105, 116, 101, 100, 18, 28, 10, 12, 114, 111, 97, 100, 95, 114, 101, 103, 117, 108, 97, 114, 18, 12, 114, 111, 97, 100, 95, 114, 101, 103, 117, 108, 97, 114, 18, 24, 10, 10, 114, 111, 97, 100, 95, 108, 97, 114, 103, 101, 18, 10, 114, 111, 97, 100, 95, 108, 97, 114, 103, 101, 18, 18, 10, 7, 97, 108, 99, 111, 104, 111, 108, 18, 7, 97, 108, 99, 111, 104, 111, 108, 26, 139, 2, 10, 7, 100, 101, 102, 97, 117, 108, 116, 18, 17, 10, 10, 98, 97, 99, 107, 103, 114, 111, 117, 110, 100, 21, 255, 255, 255, 255, 18, 13, 10, 4, 112, 97, 114, 107, 21, 255, 159, 223, 200, 24, 1, 18, 13, 10, 4, 119, 111, 111, 100, 21, 255, 102, 170, 51, 24, 1, 18, 14, 10, 5, 119, 97, 116, 101, 114, 21, 255, 230, 182, 115, 24, 1, 18, 46, 10, 12, 114, 111, 97, 100, 95, 108, 105, 109, 105, 116, 101, 100, 21, 255, 187, 187, 187, 34, 25, 10, 5, 115, 116, 111, 112, 115, 18, 16, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, 160, 65, 0, 0, 128, 63, 18, 62, 10, 12, 114, 111, 97, 100, 95, 114, 101, 103, 117, 108, 97, 114, 21, 255, 153, 153, 153, 34, 41, 10, 5, 115, 116, 111, 112, 115, 18, 32, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 80, 65, 0, 0, 0, 63, 0, 0, 128, 65, 0, 0, 0, 64, 0, 0, 160, 65, 0, 0, 0, 66, 18, 68, 10, 10, 114, 111, 97, 100, 95, 108, 97, 114, 103, 101, 21, 255, 102, 102, 102, 34, 49, 10, 5, 115, 116, 111, 112, 115, 18, 40, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 48, 65, 0, 0, 0, 63, 0, 0, 80, 65, 0, 0, 128, 63, 0, 0, 128, 65, 0, 0, 128, 64, 0, 0, 160, 65, 0, 0, 128, 66, 18, 9, 10, 7, 97, 108, 99, 111, 104, 111, 108 + 10, 25, 10, 5, 119, 97, 116, 101, 114, 16, 1, 26, 7, 115, 116, 114, + 101, 101, 116, 115, 34, 5, 119, 97, 116, 101, 114, 10, 60, 10, 10, 114, + 111, 97, 100, 95, 108, 97, 114, 103, 101, 16, 2, 26, 7, 115, 116, 114, + 101, 101, 116, 115, 34, 4, 114, 111, 97, 100, 42, 5, 99, 108, 97, 115, + 115, 50, 10, 10, 8, 109, 111, 116, 111, 114, 119, 97, 121, 50, 6, 10, + 4, 109, 97, 105, 110, 56, 1, 64, 2, 10, 52, 10, 12, 114, 111, 97, + 100, 95, 114, 101, 103, 117, 108, 97, 114, 16, 2, 26, 7, 115, 116, 114, + 101, 101, 116, 115, 34, 4, 114, 111, 97, 100, 42, 5, 99, 108, 97, 115, + 115, 50, 8, 10, 6, 115, 116, 114, 101, 101, 116, 56, 1, 64, 2, 10, + 60, 10, 12, 114, 111, 97, 100, 95, 108, 105, 109, 105, 116, 101, 100, 16, + 2, 26, 7, 115, 116, 114, 101, 101, 116, 115, 34, 4, 114, 111, 97, 100, + 42, 5, 99, 108, 97, 115, 115, 50, 16, 10, 14, 115, 116, 114, 101, 101, + 116, 95, 108, 105, 109, 105, 116, 101, 100, 56, 1, 64, 2, 10, 41, 10, + 4, 112, 97, 114, 107, 16, 1, 26, 7, 115, 116, 114, 101, 101, 116, 115, + 34, 7, 108, 97, 110, 100, 117, 115, 101, 42, 5, 99, 108, 97, 115, 115, + 50, 6, 10, 4, 112, 97, 114, 107, 10, 41, 10, 4, 119, 111, 111, 100, + 16, 1, 26, 7, 115, 116, 114, 101, 101, 116, 115, 34, 7, 108, 97, 110, + 100, 117, 115, 101, 42, 5, 99, 108, 97, 115, 115, 50, 6, 10, 4, 119, + 111, 111, 100, 10, 45, 10, 6, 115, 99, 104, 111, 111, 108, 16, 1, 26, + 7, 115, 116, 114, 101, 101, 116, 115, 34, 7, 108, 97, 110, 100, 117, 115, + 101, 42, 5, 99, 108, 97, 115, 115, 50, 8, 10, 6, 115, 99, 104, 111, + 111, 108, 10, 49, 10, 8, 99, 101, 109, 101, 116, 101, 114, 121, 16, 1, + 26, 7, 115, 116, 114, 101, 101, 116, 115, 34, 7, 108, 97, 110, 100, 117, + 115, 101, 42, 5, 99, 108, 97, 115, 115, 50, 10, 10, 8, 99, 101, 109, + 101, 116, 101, 114, 121, 10, 53, 10, 10, 105, 110, 100, 117, 115, 116, 114, + 105, 97, 108, 16, 1, 26, 7, 115, 116, 114, 101, 101, 116, 115, 34, 7, + 108, 97, 110, 100, 117, 115, 101, 42, 5, 99, 108, 97, 115, 115, 50, 12, + 10, 10, 105, 110, 100, 117, 115, 116, 114, 105, 97, 108, 10, 31, 10, 8, + 98, 117, 105, 108, 100, 105, 110, 103, 16, 1, 26, 7, 115, 116, 114, 101, + 101, 116, 115, 34, 8, 98, 117, 105, 108, 100, 105, 110, 103, 10, 48, 10, + 7, 97, 108, 99, 111, 104, 111, 108, 16, 3, 26, 7, 115, 116, 114, 101, + 101, 116, 115, 34, 9, 112, 111, 105, 95, 108, 97, 98, 101, 108, 42, 4, + 116, 121, 112, 101, 50, 9, 10, 7, 65, 108, 99, 111, 104, 111, 108, 18, + 12, 10, 4, 112, 97, 114, 107, 18, 4, 112, 97, 114, 107, 18, 12, 10, + 4, 119, 111, 111, 100, 18, 4, 119, 111, 111, 100, 18, 14, 10, 5, 119, + 97, 116, 101, 114, 18, 5, 119, 97, 116, 101, 114, 18, 28, 10, 12, 114, + 111, 97, 100, 95, 108, 105, 109, 105, 116, 101, 100, 18, 12, 114, 111, 97, + 100, 95, 108, 105, 109, 105, 116, 101, 100, 18, 28, 10, 12, 114, 111, 97, + 100, 95, 114, 101, 103, 117, 108, 97, 114, 18, 12, 114, 111, 97, 100, 95, + 114, 101, 103, 117, 108, 97, 114, 18, 24, 10, 10, 114, 111, 97, 100, 95, + 108, 97, 114, 103, 101, 18, 10, 114, 111, 97, 100, 95, 108, 97, 114, 103, + 101, 18, 18, 10, 7, 97, 108, 99, 111, 104, 111, 108, 18, 7, 97, 108, + 99, 111, 104, 111, 108, 26, 128, 2, 10, 7, 100, 101, 102, 97, 117, 108, + 116, 18, 21, 10, 4, 112, 97, 114, 107, 34, 8, 8, 2, 18, 4, 0, + 0, 128, 63, 45, 255, 159, 223, 200, 18, 31, 10, 4, 119, 111, 111, 100, + 34, 8, 8, 2, 18, 4, 0, 0, 128, 63, 45, 255, 102, 170, 51, 58, + 8, 8, 2, 18, 4, 205, 204, 204, 61, 18, 22, 10, 5, 119, 97, 116, + 101, 114, 34, 8, 8, 2, 18, 4, 0, 0, 128, 63, 45, 255, 230, 182, + 115, 26, 41, 10, 12, 114, 111, 97, 100, 95, 108, 105, 109, 105, 116, 101, + 100, 29, 255, 187, 187, 187, 34, 20, 8, 3, 18, 16, 0, 0, 0, 0, + 0, 0, 128, 63, 0, 0, 160, 65, 0, 0, 128, 63, 26, 57, 10, 12, + 114, 111, 97, 100, 95, 114, 101, 103, 117, 108, 97, 114, 29, 255, 153, 153, + 153, 34, 36, 8, 3, 18, 32, 0, 0, 0, 0, 0, 0, 0, 63, 0, + 0, 80, 65, 0, 0, 0, 63, 0, 0, 128, 65, 0, 0, 0, 64, 0, + 0, 160, 65, 0, 0, 0, 66, 26, 63, 10, 10, 114, 111, 97, 100, 95, + 108, 97, 114, 103, 101, 29, 255, 102, 102, 102, 34, 44, 8, 3, 18, 40, + 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 48, 65, 0, 0, 0, 63, + 0, 0, 80, 65, 0, 0, 128, 63, 0, 0, 128, 65, 0, 0, 128, 64, + 0, 0, 160, 65, 0, 0, 128, 66 }; const unsigned long resources::style_size = sizeof(resources::style); diff --git a/src/style/properties.cpp b/src/style/properties.cpp new file mode 100644 index 0000000000..0ea3fbfeef --- /dev/null +++ b/src/style/properties.cpp @@ -0,0 +1,25 @@ +#include <llmr/style/properties.hpp> + + +#include <cassert> + +using namespace llmr; + + +float functions::null(float z, const std::vector<float>&) { + return 0; +} + +bool functions::null(float z, const std::vector<bool>&) { + return false; +} + +float functions::constant(float z, const std::vector<float>& values) { + assert(values.size() == 1); + return values.front(); +} + +bool functions::constant(float z, const std::vector<bool>& values) { + assert(values.size() == 1); + return values.front(); +}
\ No newline at end of file diff --git a/src/style/style.cpp b/src/style/style.cpp index 0acce7c35b..dc60d93a88 100644 --- a/src/style/style.cpp +++ b/src/style/style.cpp @@ -18,20 +18,18 @@ void Style::load(const uint8_t *const data, uint32_t bytes) { while (style.next()) { if (style.tag == 1) { // bucket - buckets.insert(loadBucket(style.message())); + buckets.insert(parseBucket(style.message())); } else if (style.tag == 2) { // structure - layers.push_back(loadLayer(style.message())); + layers.push_back(parseLayer(style.message())); } else if (style.tag == 3) { // class - classes.insert(loadClass(style.message())); + classes.insert(parseClass(style.message())); } else { style.skip(); } } - - cascade(); } -std::pair<std::string, BucketDescription> Style::loadBucket(pbf data) { +std::pair<std::string, BucketDescription> Style::parseBucket(pbf data) { BucketDescription bucket; std::string name; @@ -64,7 +62,7 @@ std::pair<std::string, BucketDescription> Style::loadBucket(pbf data) { return { name, bucket }; } -LayerDescription Style::loadLayer(pbf data) { +LayerDescription Style::parseLayer(pbf data) { LayerDescription layer; while (data.next()) { @@ -73,7 +71,7 @@ LayerDescription Style::loadLayer(pbf data) { } else if (data.tag == 2) { // bucket_name layer.bucket_name = data.string(); } else if (data.tag == 3) { // child_layer - layer.child_layer.emplace_back(loadLayer(data.message())); + layer.child_layer.emplace_back(parseLayer(data.message())); } else { data.skip(); } @@ -83,15 +81,17 @@ LayerDescription Style::loadLayer(pbf data) { } -std::pair<std::string, ClassDescription> Style::loadClass(pbf data) { +std::pair<std::string, ClassDescription> Style::parseClass(pbf data) { ClassDescription klass; std::string name; while (data.next()) { if (data.tag == 1) { // name name = data.string(); - } else if (data.tag == 2) { // layer_style - klass.insert(loadLayerStyle(data.message())); + } else if (data.tag == 2) { // fill_style + klass.fill.insert(parseFillClass(data.message())); + } else if (data.tag == 3) { // stroke_style + klass.stroke.insert(parseStrokeClass(data.message())); } else { data.skip(); } @@ -100,55 +100,96 @@ std::pair<std::string, ClassDescription> Style::loadClass(pbf data) { return { name, klass }; } -std::pair<std::string, LayerStyleDescription> Style::loadLayerStyle(pbf data) { - LayerStyleDescription layerStyle; +std::pair<std::string, FillClass> Style::parseFillClass(pbf data) { + FillClass fill; + std::string name; + + while (data.next()) { + if (data.tag == 1) { // name + name = data.string(); + } else if (data.tag == 2) { // hidden + fill.hidden = parseProperty<bool>(data.message()); + } else if (data.tag == 3) { // winding + fill.winding = (Winding)data.varint(); + } else if (data.tag == 4) { // antialias + fill.antialias = parseProperty<bool>(data.message()); + } else if (data.tag == 5) { // fill_color + fill.fill_color = parseColor(data); + if (fill.stroke_color[3] == std::numeric_limits<float>::infinity()) { + fill.stroke_color = fill.fill_color; + } + } else if (data.tag == 6) { // stroke_color + fill.stroke_color = parseColor(data); + } else if (data.tag == 7) { // opacity + fill.opacity = parseProperty<float>(data.message()); + } else { + data.skip(); + } + } + + return { name, fill }; +} + + +std::pair<std::string, StrokeClass> Style::parseStrokeClass(pbf data) { + StrokeClass stroke; std::string name; while (data.next()) { if (data.tag == 1) { // name name = data.string(); - } else if (data.tag == 2) { // color - uint32_t rgba = data.fixed<uint32_t, 4>(); - layerStyle.color = {{ - (float)((rgba >> 24) & 0xFF) / 0xFF, - (float)((rgba >> 16) & 0xFF) / 0xFF, - (float)((rgba >> 8) & 0xFF) / 0xFF, - (float)((rgba >> 0) & 0xFF) / 0xFF - }}; - } else if (data.tag == 3) { // antialias - layerStyle.antialias = data.boolean(); + } else if (data.tag == 2) { // hidden + stroke.hidden = parseProperty<bool>(data.message()); + } else if (data.tag == 3) { // color + stroke.color = parseColor(data); } else if (data.tag == 4) { // width - layerStyle.width = loadWidth(data.message()); + stroke.width = parseProperty<float>(data.message()); + } else if (data.tag == 5) { // opacity + stroke.offset = parseProperty<float>(data.message()); } else { data.skip(); } } - return { name, layerStyle }; + return { name, stroke }; } -WidthDescription Style::loadWidth(pbf data) { - WidthDescription width; + +Color Style::parseColor(pbf& data) { + uint32_t rgba = data.fixed<uint32_t, 4>(); + return {{ + (float)((rgba >> 24) & 0xFF) / 0xFF, + (float)((rgba >> 16) & 0xFF) / 0xFF, + (float)((rgba >> 8) & 0xFF) / 0xFF, + (float)((rgba >> 0) & 0xFF) / 0xFF + }}; +} + +template <typename T> FunctionProperty<T> Style::parseProperty(pbf data) { + FunctionProperty<T> property; while (data.next()) { - if (data.tag == 1) { // scaling - width.scaling = data.string(); + if (data.tag == 1) { // function + switch((Property)data.varint()) { + case Property::Null: property.function = &functions::null; break; + case Property::Constant: property.function = &functions::constant; break; + default: property.function = &functions::null; break; + } } else if (data.tag == 2) { // value // read a packed float32 pbf floats = data.message(); while (floats) { - width.value.push_back(floats.float32()); + property.values.push_back(floats.float32()); } } else { data.skip(); } } - return width; + return property; } - -void Style::cascade() { +void Style::cascade(float z) { reset(); // Recalculate style @@ -160,15 +201,30 @@ void Style::cascade() { // Not enabled if (appliedClasses.find(class_name) == appliedClasses.end()) continue; - for (const auto& layer_pair : sheetClass) { - const std::string& layer_name = layer_pair.first; - const LayerStyleDescription& layer = layer_pair.second; + // Cascade fill classes + for (const auto& fill_pair : sheetClass.fill) { + const std::string& layer_name = fill_pair.first; + const llmr::FillClass& layer = fill_pair.second; + + llmr::FillProperties& fill = computed.fills[layer_name]; + fill.hidden = layer.hidden(z); + fill.winding = layer.winding; + fill.antialias = layer.antialias(z); + fill.fill_color = layer.fill_color; + fill.stroke_color = layer.stroke_color; + fill.opacity = layer.opacity(z); + } + + // Cascade line classes + for (const auto& stroke_pair : sheetClass.stroke) { + const std::string& layer_name = stroke_pair.first; + const llmr::StrokeClass& layer = stroke_pair.second; - // Find out what type this layer style is. - computed.fills[layer_name].enabled = true; - computed.fills[layer_name].antialiasing = layer.antialias; - computed.fills[layer_name].fill_color = layer.color; - computed.fills[layer_name].stroke_color = layer.color; + llmr::StrokeProperties& stroke = computed.strokes[layer_name]; + stroke.hidden = layer.hidden(z); + stroke.width = layer.width(z); + stroke.offset = layer.offset(z); + stroke.color = layer.color; } } } |