From 1538ebaf220ebc25243f2f71eb26c91cdf10548a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Mon, 27 Jan 2014 17:21:48 +0100 Subject: cascade styles --- src/style/properties.cpp | 25 +++++++++ src/style/style.cpp | 138 +++++++++++++++++++++++++++++++++-------------- 2 files changed, 122 insertions(+), 41 deletions(-) create mode 100644 src/style/properties.cpp (limited to 'src/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 + + +#include + +using namespace llmr; + + +float functions::null(float z, const std::vector&) { + return 0; +} + +bool functions::null(float z, const std::vector&) { + return false; +} + +float functions::constant(float z, const std::vector& values) { + assert(values.size() == 1); + return values.front(); +} + +bool functions::constant(float z, const std::vector& 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 Style::loadBucket(pbf data) { +std::pair Style::parseBucket(pbf data) { BucketDescription bucket; std::string name; @@ -64,7 +62,7 @@ std::pair 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 Style::loadClass(pbf data) { +std::pair 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 Style::loadClass(pbf data) { return { name, klass }; } -std::pair Style::loadLayerStyle(pbf data) { - LayerStyleDescription layerStyle; +std::pair 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(data.message()); + } else if (data.tag == 3) { // winding + fill.winding = (Winding)data.varint(); + } else if (data.tag == 4) { // antialias + fill.antialias = parseProperty(data.message()); + } else if (data.tag == 5) { // fill_color + fill.fill_color = parseColor(data); + if (fill.stroke_color[3] == std::numeric_limits::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(data.message()); + } else { + data.skip(); + } + } + + return { name, fill }; +} + + +std::pair 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(); - 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(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(data.message()); + } else if (data.tag == 5) { // opacity + stroke.offset = parseProperty(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(); + return {{ + (float)((rgba >> 24) & 0xFF) / 0xFF, + (float)((rgba >> 16) & 0xFF) / 0xFF, + (float)((rgba >> 8) & 0xFF) / 0xFF, + (float)((rgba >> 0) & 0xFF) / 0xFF + }}; +} + +template FunctionProperty Style::parseProperty(pbf data) { + FunctionProperty 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; } } } -- cgit v1.2.1