summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt2
-rw-r--r--cmake/core-files.cmake3
-rw-r--r--cmake/test-files.cmake2
-rw-r--r--include/mbgl/style/layer.hpp2
-rw-r--r--include/mbgl/util/color.hpp1
-rw-r--r--package.json2
-rw-r--r--src/mbgl/annotation/style_sourced_annotation_impl.cpp4
-rw-r--r--src/mbgl/layout/symbol_layout.cpp7
-rw-r--r--src/mbgl/layout/symbol_layout.hpp5
-rw-r--r--src/mbgl/style/conversion/stringify.hpp256
-rw-r--r--src/mbgl/style/group_by_layout.cpp51
-rw-r--r--src/mbgl/style/group_by_layout.hpp14
-rw-r--r--src/mbgl/style/layer_impl.cpp6
-rw-r--r--src/mbgl/style/layer_impl.hpp13
-rw-r--r--src/mbgl/style/layers/background_layer.cpp5
-rw-r--r--src/mbgl/style/layers/background_layer_impl.hpp1
-rw-r--r--src/mbgl/style/layers/circle_layer.cpp5
-rw-r--r--src/mbgl/style/layers/circle_layer_impl.cpp3
-rw-r--r--src/mbgl/style/layers/circle_layer_impl.hpp1
-rw-r--r--src/mbgl/style/layers/custom_layer_impl.cpp3
-rw-r--r--src/mbgl/style/layers/custom_layer_impl.hpp1
-rw-r--r--src/mbgl/style/layers/fill_extrusion_layer.cpp5
-rw-r--r--src/mbgl/style/layers/fill_extrusion_layer_impl.hpp1
-rw-r--r--src/mbgl/style/layers/fill_layer.cpp5
-rw-r--r--src/mbgl/style/layers/fill_layer_impl.cpp3
-rw-r--r--src/mbgl/style/layers/fill_layer_impl.hpp1
-rw-r--r--src/mbgl/style/layers/layer.cpp.ejs11
-rw-r--r--src/mbgl/style/layers/layer_properties.hpp.ejs1
-rw-r--r--src/mbgl/style/layers/line_layer.cpp6
-rw-r--r--src/mbgl/style/layers/line_layer_impl.cpp3
-rw-r--r--src/mbgl/style/layers/line_layer_impl.hpp1
-rw-r--r--src/mbgl/style/layers/line_layer_properties.hpp4
-rw-r--r--src/mbgl/style/layers/raster_layer.cpp5
-rw-r--r--src/mbgl/style/layers/raster_layer_impl.hpp1
-rw-r--r--src/mbgl/style/layers/symbol_layer.cpp6
-rw-r--r--src/mbgl/style/layers/symbol_layer_impl.cpp6
-rw-r--r--src/mbgl/style/layers/symbol_layer_impl.hpp4
-rw-r--r--src/mbgl/style/layers/symbol_layer_properties.hpp34
-rw-r--r--src/mbgl/tile/geometry_tile.cpp2
-rw-r--r--src/mbgl/tile/geometry_tile.hpp6
-rw-r--r--src/mbgl/tile/geometry_tile_worker.cpp71
-rw-r--r--src/mbgl/util/color.cpp9
-rw-r--r--test/style/conversion/stringify.test.cpp98
-rw-r--r--test/style/group_by_layout.test.cpp44
44 files changed, 645 insertions, 69 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a9f52ba9de..41df0f2a12 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -60,6 +60,8 @@ mason_use(pixelmatch VERSION 0.10.0 HEADER_ONLY)
mason_use(geojson VERSION 0.4.0 HEADER_ONLY)
mason_use(polylabel VERSION 1.0.2 HEADER_ONLY)
+add_definitions(-DRAPIDJSON_HAS_STDSTRING=1)
+
if(WITH_COVERAGE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} --coverage")
diff --git a/cmake/core-files.cmake b/cmake/core-files.cmake
index 3255da66f2..6c44117cd8 100644
--- a/cmake/core-files.cmake
+++ b/cmake/core-files.cmake
@@ -221,6 +221,8 @@ set(MBGL_CORE_FILES
src/mbgl/style/cross_faded_property_evaluator.cpp
src/mbgl/style/cross_faded_property_evaluator.hpp
src/mbgl/style/function.cpp
+ src/mbgl/style/group_by_layout.cpp
+ src/mbgl/style/group_by_layout.hpp
src/mbgl/style/layer.cpp
src/mbgl/style/layer_impl.cpp
src/mbgl/style/layer_impl.hpp
@@ -260,6 +262,7 @@ set(MBGL_CORE_FILES
include/mbgl/style/conversion/property_value.hpp
include/mbgl/style/conversion/source.hpp
include/mbgl/style/conversion/tileset.hpp
+ src/mbgl/style/conversion/stringify.hpp
# style/layers
include/mbgl/style/layers/background_layer.hpp
diff --git a/cmake/test-files.cmake b/cmake/test-files.cmake
index 7d8dc82756..e05b956b1e 100644
--- a/cmake/test-files.cmake
+++ b/cmake/test-files.cmake
@@ -73,10 +73,12 @@ set(MBGL_TEST_FILES
# style/conversion
test/style/conversion/geojson_options.test.cpp
+ test/style/conversion/stringify.test.cpp
# style
test/style/filter.test.cpp
test/style/functions.test.cpp
+ test/style/group_by_layout.test.cpp
test/style/source.test.cpp
test/style/style.test.cpp
test/style/style_layer.test.cpp
diff --git a/include/mbgl/style/layer.hpp b/include/mbgl/style/layer.hpp
index dc02cb09b2..5936422c74 100644
--- a/include/mbgl/style/layer.hpp
+++ b/include/mbgl/style/layer.hpp
@@ -116,6 +116,8 @@ public:
// Private implementation
const std::unique_ptr<Impl> baseImpl;
+
+ friend std::string layoutKey(const Layer&);
};
} // namespace style
diff --git a/include/mbgl/util/color.hpp b/include/mbgl/util/color.hpp
index 18e4747069..300d7fae82 100644
--- a/include/mbgl/util/color.hpp
+++ b/include/mbgl/util/color.hpp
@@ -36,6 +36,7 @@ public:
static Color blue() { return { 0.0f, 0.0f, 1.0f, 1.0f }; };
static optional<Color> parse(const std::string&);
+ std::string stringify() const;
};
inline bool operator==(const Color& colorA, const Color& colorB) {
diff --git a/package.json b/package.json
index 4633b4bc4d..9eff43e1d7 100644
--- a/package.json
+++ b/package.json
@@ -23,7 +23,7 @@
"express": "^4.11.1",
"lodash": "^4.16.4",
"mapbox-gl-style-spec": "mapbox/mapbox-gl-style-spec#49e8b407bdbbe6f7c92dbcb56d3d51f425fc2653",
- "mapbox-gl-test-suite": "mapbox/mapbox-gl-test-suite#2bdca923fc4190156b5a22af71be29442451db54",
+ "mapbox-gl-test-suite": "mapbox/mapbox-gl-test-suite#7bf5725a2dfe848463db85ff2c85a0f9551d18bf",
"mkdirp": "^0.5.1",
"node-cmake": "^1.2.1",
"pixelmatch": "^4.0.2",
diff --git a/src/mbgl/annotation/style_sourced_annotation_impl.cpp b/src/mbgl/annotation/style_sourced_annotation_impl.cpp
index d3212da12d..cb664cf15d 100644
--- a/src/mbgl/annotation/style_sourced_annotation_impl.cpp
+++ b/src/mbgl/annotation/style_sourced_annotation_impl.cpp
@@ -24,12 +24,12 @@ void StyleSourcedAnnotationImpl::updateStyle(Style& style) const {
return;
if (sourceLayer->is<LineLayer>()) {
- std::unique_ptr<Layer> layer = sourceLayer->baseImpl->copy(layerID, "", AnnotationManager::SourceID);
+ std::unique_ptr<Layer> layer = sourceLayer->baseImpl->copy(layerID, AnnotationManager::SourceID);
layer->as<LineLayer>()->setSourceLayer(layerID);
layer->as<LineLayer>()->setVisibility(VisibilityType::Visible);
style.addLayer(std::move(layer), sourceLayer->getID());
} else if (sourceLayer->is<FillLayer>()) {
- std::unique_ptr<Layer> layer = sourceLayer->baseImpl->copy(layerID, "", AnnotationManager::SourceID);
+ std::unique_ptr<Layer> layer = sourceLayer->baseImpl->copy(layerID, AnnotationManager::SourceID);
layer->as<FillLayer>()->setSourceLayer(layerID);
layer->as<FillLayer>()->setVisibility(VisibilityType::Visible);
style.addLayer(std::move(layer), sourceLayer->getID());
diff --git a/src/mbgl/layout/symbol_layout.cpp b/src/mbgl/layout/symbol_layout.cpp
index 351858f6f8..85e0b19609 100644
--- a/src/mbgl/layout/symbol_layout.cpp
+++ b/src/mbgl/layout/symbol_layout.cpp
@@ -3,6 +3,7 @@
#include <mbgl/layout/clip_lines.hpp>
#include <mbgl/renderer/symbol_bucket.hpp>
#include <mbgl/style/filter_evaluator.hpp>
+#include <mbgl/style/layer.hpp>
#include <mbgl/sprite/sprite_atlas.hpp>
#include <mbgl/text/glyph_atlas.hpp>
#include <mbgl/text/get_anchors.hpp>
@@ -26,7 +27,7 @@ namespace mbgl {
using namespace style;
-SymbolLayout::SymbolLayout(std::string bucketName_,
+SymbolLayout::SymbolLayout(std::vector<std::unique_ptr<Layer>> layers_,
std::string sourceLayerName_,
uint32_t overscaling_,
float zoom_,
@@ -36,7 +37,7 @@ SymbolLayout::SymbolLayout(std::string bucketName_,
style::SymbolLayoutProperties::Evaluated layout_,
float textMaxSize_,
SpriteAtlas& spriteAtlas_)
- : bucketName(std::move(bucketName_)),
+ : layers(std::move(layers_)),
sourceLayerName(std::move(sourceLayerName_)),
overscaling(overscaling_),
zoom(zoom_),
@@ -253,7 +254,7 @@ void SymbolLayout::addFeature(const SymbolFeature& feature,
? SymbolPlacementType::Point
: layout.get<SymbolPlacement>();
const float textRepeatDistance = symbolSpacing / 2;
- IndexedSubfeature indexedFeature = {feature.index, sourceLayerName, bucketName, symbolInstances.size()};
+ IndexedSubfeature indexedFeature = {feature.index, sourceLayerName, layers.at(0)->getID(), symbolInstances.size()};
auto addSymbolInstance = [&] (const GeometryCoordinates& line, Anchor& anchor) {
// https://github.com/mapbox/vector-tile-spec/tree/master/2.1#41-layers
diff --git a/src/mbgl/layout/symbol_layout.hpp b/src/mbgl/layout/symbol_layout.hpp
index 18fb9ff4bc..63c0a8859d 100644
--- a/src/mbgl/layout/symbol_layout.hpp
+++ b/src/mbgl/layout/symbol_layout.hpp
@@ -21,13 +21,14 @@ class SymbolBucket;
namespace style {
class Filter;
+class Layer;
} // namespace style
struct Anchor;
class SymbolLayout {
public:
- SymbolLayout(std::string bucketName_,
+ SymbolLayout(std::vector<std::unique_ptr<style::Layer>>,
std::string sourceLayerName_,
uint32_t overscaling,
float zoom,
@@ -55,7 +56,7 @@ public:
State state = Pending;
- const std::string bucketName;
+ const std::vector<std::unique_ptr<style::Layer>> layers;
const std::string sourceLayerName;
private:
diff --git a/src/mbgl/style/conversion/stringify.hpp b/src/mbgl/style/conversion/stringify.hpp
new file mode 100644
index 0000000000..d06b2f2814
--- /dev/null
+++ b/src/mbgl/style/conversion/stringify.hpp
@@ -0,0 +1,256 @@
+#pragma once
+
+#include <mbgl/style/filter.hpp>
+#include <mbgl/style/property_value.hpp>
+#include <mbgl/style/layout_property.hpp>
+#include <mbgl/util/enum.hpp>
+#include <mbgl/util/color.hpp>
+#include <mbgl/util/feature.hpp>
+#include <mbgl/util/ignore.hpp>
+#include <mbgl/util/rapidjson.hpp>
+
+#include <array>
+#include <vector>
+#include <unordered_map>
+
+namespace mbgl {
+namespace style {
+namespace conversion {
+
+template <class Writer>
+void stringify(Writer& writer, NullValue) {
+ writer.Null();
+}
+
+template <class Writer>
+void stringify(Writer& writer, bool v) {
+ writer.Bool(v);
+}
+
+template <class Writer>
+void stringify(Writer& writer, uint64_t v) {
+ writer.Uint64(v);
+}
+
+template <class Writer>
+void stringify(Writer& writer, int64_t v) {
+ writer.Int64(v);
+}
+
+template <class Writer>
+void stringify(Writer& writer, double v) {
+ writer.Double(v);
+}
+
+template <class Writer>
+void stringify(Writer& writer, const std::string& v) {
+ writer.String(v);
+}
+
+template <class Writer, class T, class Enable = std::enable_if_t<std::is_enum<T>::value>>
+void stringify(Writer& writer, const T& v) {
+ writer.String(Enum<T>::toString(v));
+}
+
+template <class Writer>
+void stringify(Writer& writer, const Color& v) {
+ writer.String(v.stringify());
+}
+
+template <class Writer>
+void stringify(Writer& writer, const std::array<float, 2>& v) {
+ writer.StartArray();
+ writer.Double(v[0]);
+ writer.Double(v[1]);
+ writer.EndArray();
+}
+
+template <class Writer>
+void stringify(Writer& writer, const std::array<float, 4>& v) {
+ writer.StartArray();
+ writer.Double(v[0]);
+ writer.Double(v[1]);
+ writer.Double(v[2]);
+ writer.Double(v[3]);
+ writer.EndArray();
+}
+
+template <class Writer>
+void stringify(Writer&, const Value&);
+
+template <class Writer, class T>
+void stringify(Writer& writer, const std::vector<T>& v) {
+ writer.StartArray();
+ for (const auto& e : v) {
+ stringify(writer, e);
+ }
+ writer.EndArray();
+}
+
+template <class Writer, class T>
+void stringify(Writer& writer, const std::unordered_map<std::string, T>& m) {
+ writer.StartObject();
+ for (const auto& p : m) {
+ writer.Key(p.first.data(), static_cast<unsigned>(p.first.size()));
+ stringify(writer, p.second);
+ }
+ writer.EndObject();
+}
+
+template <class Writer>
+void stringify(Writer& writer, const Value& v) {
+ Value::visit(v, [&] (const auto& v_) { stringify(writer, v_); });
+}
+
+template <class Writer>
+class StringifyFilter {
+public:
+ Writer& writer;
+
+ void operator()(const NullFilter&) {
+ writer.Null();
+ }
+
+ void operator()(const EqualsFilter& f) {
+ stringifyBinaryFilter(f, "==");
+ }
+
+ void operator()(const NotEqualsFilter& f) {
+ stringifyBinaryFilter(f, "!=");
+ }
+
+ void operator()(const LessThanFilter& f) {
+ stringifyBinaryFilter(f, "<");
+ }
+
+ void operator()(const LessThanEqualsFilter& f) {
+ stringifyBinaryFilter(f, "<=");
+ }
+
+ void operator()(const GreaterThanFilter& f) {
+ stringifyBinaryFilter(f, ">");
+ }
+
+ void operator()(const GreaterThanEqualsFilter& f) {
+ stringifyBinaryFilter(f, ">=");
+ }
+
+ void operator()(const InFilter& f) {
+ stringifySetFilter(f, "in");
+ }
+
+ void operator()(const NotInFilter& f) {
+ stringifySetFilter(f, "!in");
+ }
+
+ void operator()(const AllFilter& f) {
+ stringifyCompoundFilter(f, "all");
+ }
+
+ void operator()(const AnyFilter& f) {
+ stringifyCompoundFilter(f, "any");
+ }
+
+ void operator()(const NoneFilter& f) {
+ stringifyCompoundFilter(f, "none");
+ }
+
+ void operator()(const HasFilter& f) {
+ stringifyUnaryFilter(f, "has");
+ }
+
+ void operator()(const NotHasFilter& f) {
+ stringifyUnaryFilter(f, "!has");
+ }
+
+private:
+ template <class F>
+ void stringifyBinaryFilter(const F& f, const char * op) {
+ writer.StartArray();
+ writer.String(op);
+ writer.String(f.key);
+ stringify(writer, f.value);
+ writer.EndArray();
+ }
+
+ template <class F>
+ void stringifySetFilter(const F& f, const char * op) {
+ writer.StartArray();
+ writer.String(op);
+ writer.String(f.key);
+ for (const auto& value : f.values) {
+ stringify(writer, value);
+ }
+ writer.EndArray();
+ }
+
+ template <class F>
+ void stringifyCompoundFilter(const F& f, const char * op) {
+ writer.StartArray();
+ writer.String(op);
+ for (const auto& filter : f.filters) {
+ Filter::visit(filter, *this);
+ }
+ writer.EndArray();
+ }
+
+ template <class F>
+ void stringifyUnaryFilter(const F& f, const char * op) {
+ writer.StartArray();
+ writer.String(op);
+ writer.String(f.key);
+ writer.EndArray();
+ }
+};
+
+template <class Writer>
+void stringify(Writer& writer, const Filter& f) {
+ Filter::visit(f, StringifyFilter<Writer> { writer });
+}
+
+template <class Writer>
+void stringify(Writer& writer, const Undefined&) {
+ assert(false); // Should be omitted entirely instead.
+ writer.Null();
+}
+
+template <class Writer, class T>
+void stringify(Writer& writer, const Function<T>& f) {
+ writer.StartObject();
+ writer.Key("base");
+ writer.Double(f.getBase());
+ writer.Key("stops");
+ writer.StartArray();
+ for (const auto& stop : f.getStops()) {
+ writer.StartArray();
+ writer.Double(stop.first);
+ stringify(writer, stop.second);
+ writer.EndArray();
+ }
+ writer.EndArray();
+ writer.EndObject();
+}
+
+template <class Writer, class T>
+void stringify(Writer& writer, const PropertyValue<T>& v) {
+ v.evaluate([&] (const auto& v_) { stringify(writer, v_); });
+}
+
+template <class Property, class Writer, class T>
+void stringify(Writer& writer, const PropertyValue<T>& value) {
+ if (value) {
+ writer.Key(Property::key);
+ stringify(writer, value);
+ }
+}
+
+template <class Writer, class... Ps>
+void stringify(Writer& writer, const LayoutProperties<Ps...>& ps) {
+ writer.StartObject();
+ util::ignore({ (stringify<Ps>(writer, ps.unevaluated.template get<Ps>()), 0)... });
+ writer.EndObject();
+}
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/group_by_layout.cpp b/src/mbgl/style/group_by_layout.cpp
new file mode 100644
index 0000000000..52d33827ef
--- /dev/null
+++ b/src/mbgl/style/group_by_layout.cpp
@@ -0,0 +1,51 @@
+#include <mbgl/style/group_by_layout.hpp>
+#include <mbgl/style/layer.hpp>
+#include <mbgl/style/layer_impl.hpp>
+#include <mbgl/style/conversion/stringify.hpp>
+#include <mbgl/util/rapidjson.hpp>
+
+#include <rapidjson/writer.h>
+#include <rapidjson/stringbuffer.h>
+
+#include <unordered_map>
+
+namespace mbgl {
+namespace style {
+
+std::string layoutKey(const Layer& layer) {
+ using namespace conversion;
+
+ rapidjson::StringBuffer s;
+ rapidjson::Writer<rapidjson::StringBuffer> writer(s);
+
+ writer.StartArray();
+ writer.Uint(static_cast<uint32_t>(layer.type));
+ writer.String(layer.baseImpl->source);
+ writer.String(layer.baseImpl->sourceLayer);
+ writer.Double(layer.baseImpl->minZoom);
+ writer.Double(layer.baseImpl->maxZoom);
+ writer.Uint(static_cast<uint32_t>(layer.baseImpl->visibility));
+ stringify(writer, layer.baseImpl->filter);
+ layer.baseImpl->stringifyLayout(writer);
+ writer.EndArray();
+
+ return s.GetString();
+}
+
+std::vector<std::vector<std::unique_ptr<Layer>>> groupByLayout(std::vector<std::unique_ptr<Layer>> layers) {
+ std::unordered_map<std::string, std::vector<std::unique_ptr<Layer>>> map;
+ for (auto& layer : layers) {
+ auto& vector = map[layoutKey(*layer)];
+ vector.push_back(std::move(layer));
+ }
+
+ std::vector<std::vector<std::unique_ptr<Layer>>> result;
+ for (auto& pair : map) {
+ result.push_back(std::move(pair.second));
+ }
+
+ return result;
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/group_by_layout.hpp b/src/mbgl/style/group_by_layout.hpp
new file mode 100644
index 0000000000..dd7b5d118a
--- /dev/null
+++ b/src/mbgl/style/group_by_layout.hpp
@@ -0,0 +1,14 @@
+#pragma once
+
+#include <vector>
+#include <memory>
+
+namespace mbgl {
+namespace style {
+
+class Layer;
+
+std::vector<std::vector<std::unique_ptr<Layer>>> groupByLayout(std::vector<std::unique_ptr<Layer>>);
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layer_impl.cpp b/src/mbgl/style/layer_impl.cpp
index 7a0195c55c..5840318724 100644
--- a/src/mbgl/style/layer_impl.cpp
+++ b/src/mbgl/style/layer_impl.cpp
@@ -4,19 +4,13 @@ namespace mbgl {
namespace style {
std::unique_ptr<Layer> Layer::Impl::copy(const std::string& id_,
- const std::string& ref_,
const std::string& source_) const {
std::unique_ptr<Layer> result = clone();
result->baseImpl->id = id_;
- result->baseImpl->ref = ref_;
result->baseImpl->source = source_;
return result;
}
-const std::string& Layer::Impl::bucketName() const {
- return ref.empty() ? id : ref;
-}
-
bool Layer::Impl::hasRenderPass(RenderPass pass) const {
return bool(passes & pass);
}
diff --git a/src/mbgl/style/layer_impl.hpp b/src/mbgl/style/layer_impl.hpp
index 7e2c55c2e6..0fea70c10b 100644
--- a/src/mbgl/style/layer_impl.hpp
+++ b/src/mbgl/style/layer_impl.hpp
@@ -8,6 +8,9 @@
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/tile/geometry_tile_data.hpp>
+#include <rapidjson/writer.h>
+#include <rapidjson/stringbuffer.h>
+
#include <memory>
#include <string>
#include <limits>
@@ -37,20 +40,19 @@ class Layer::Impl {
public:
virtual ~Impl() = default;
- // Create a new layer with the specified `id`, `ref`, and `sourceID`. All other properties
+ // Create a new layer with the specified `id` and `sourceID`. All other properties
// are copied from this layer.
std::unique_ptr<Layer> copy(const std::string& id,
- const std::string& ref,
const std::string& sourceID) const;
// Create an identical copy of this layer.
virtual std::unique_ptr<Layer> clone() const = 0;
- // Create a layer, copying all properties except id, ref, and paint properties from this layer.
+ // Create a layer, copying all properties except id and paint properties from this layer.
virtual std::unique_ptr<Layer> cloneRef(const std::string& id) const = 0;
- // If the layer has a ref, the ref. Otherwise, the id.
- const std::string& bucketName() const;
+ // Utility function for automatic layer grouping.
+ virtual void stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const = 0;
// Partially evaluate paint properties based on a set of classes.
virtual void cascade(const CascadeParameters&) = 0;
@@ -78,7 +80,6 @@ public:
public:
std::string id;
- std::string ref;
std::string source;
std::string sourceLayer;
Filter filter;
diff --git a/src/mbgl/style/layers/background_layer.cpp b/src/mbgl/style/layers/background_layer.cpp
index a54115d1a7..a75038bfa0 100644
--- a/src/mbgl/style/layers/background_layer.cpp
+++ b/src/mbgl/style/layers/background_layer.cpp
@@ -2,6 +2,7 @@
#include <mbgl/style/layers/background_layer.hpp>
#include <mbgl/style/layers/background_layer_impl.hpp>
+#include <mbgl/style/conversion/stringify.hpp>
namespace mbgl {
namespace style {
@@ -26,11 +27,13 @@ std::unique_ptr<Layer> BackgroundLayer::Impl::clone() const {
std::unique_ptr<Layer> BackgroundLayer::Impl::cloneRef(const std::string& id_) const {
auto result = std::make_unique<BackgroundLayer>(*this);
result->impl->id = id_;
- result->impl->ref = this->id;
result->impl->paint = BackgroundPaintProperties();
return std::move(result);
}
+void BackgroundLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const {
+}
+
// Layout properties
diff --git a/src/mbgl/style/layers/background_layer_impl.hpp b/src/mbgl/style/layers/background_layer_impl.hpp
index d3d50e21cd..4629217e6d 100644
--- a/src/mbgl/style/layers/background_layer_impl.hpp
+++ b/src/mbgl/style/layers/background_layer_impl.hpp
@@ -11,6 +11,7 @@ class BackgroundLayer::Impl : public Layer::Impl {
public:
std::unique_ptr<Layer> clone() const override;
std::unique_ptr<Layer> cloneRef(const std::string& id) const override;
+ void stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const override;
void cascade(const CascadeParameters&) override;
bool evaluate(const PropertyEvaluationParameters&) override;
diff --git a/src/mbgl/style/layers/circle_layer.cpp b/src/mbgl/style/layers/circle_layer.cpp
index e3a506e895..389ab93403 100644
--- a/src/mbgl/style/layers/circle_layer.cpp
+++ b/src/mbgl/style/layers/circle_layer.cpp
@@ -2,6 +2,7 @@
#include <mbgl/style/layers/circle_layer.hpp>
#include <mbgl/style/layers/circle_layer_impl.hpp>
+#include <mbgl/style/conversion/stringify.hpp>
namespace mbgl {
namespace style {
@@ -27,11 +28,13 @@ std::unique_ptr<Layer> CircleLayer::Impl::clone() const {
std::unique_ptr<Layer> CircleLayer::Impl::cloneRef(const std::string& id_) const {
auto result = std::make_unique<CircleLayer>(*this);
result->impl->id = id_;
- result->impl->ref = this->id;
result->impl->paint = CirclePaintProperties();
return std::move(result);
}
+void CircleLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const {
+}
+
// Source
const std::string& CircleLayer::getSourceID() const {
diff --git a/src/mbgl/style/layers/circle_layer_impl.cpp b/src/mbgl/style/layers/circle_layer_impl.cpp
index 614f637b3b..136522e41c 100644
--- a/src/mbgl/style/layers/circle_layer_impl.cpp
+++ b/src/mbgl/style/layers/circle_layer_impl.cpp
@@ -24,11 +24,10 @@ bool CircleLayer::Impl::evaluate(const PropertyEvaluationParameters& parameters)
std::unique_ptr<Bucket> CircleLayer::Impl::createBucket(BucketParameters& parameters, const GeometryTileLayer& layer) const {
auto bucket = std::make_unique<CircleBucket>(parameters.mode);
- auto& name = bucketName();
parameters.eachFilteredFeature(filter, layer, [&] (const auto& feature, std::size_t index, const std::string& layerName) {
auto geometries = feature.getGeometries();
bucket->addGeometry(geometries);
- parameters.featureIndex.insert(geometries, index, layerName, name);
+ parameters.featureIndex.insert(geometries, index, layerName, id);
});
return std::move(bucket);
diff --git a/src/mbgl/style/layers/circle_layer_impl.hpp b/src/mbgl/style/layers/circle_layer_impl.hpp
index f0db58be24..744a56898c 100644
--- a/src/mbgl/style/layers/circle_layer_impl.hpp
+++ b/src/mbgl/style/layers/circle_layer_impl.hpp
@@ -11,6 +11,7 @@ class CircleLayer::Impl : public Layer::Impl {
public:
std::unique_ptr<Layer> clone() const override;
std::unique_ptr<Layer> cloneRef(const std::string& id) const override;
+ void stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const override;
void cascade(const CascadeParameters&) override;
bool evaluate(const PropertyEvaluationParameters&) override;
diff --git a/src/mbgl/style/layers/custom_layer_impl.cpp b/src/mbgl/style/layers/custom_layer_impl.cpp
index baf55205c4..cecd60a296 100644
--- a/src/mbgl/style/layers/custom_layer_impl.cpp
+++ b/src/mbgl/style/layers/custom_layer_impl.cpp
@@ -34,6 +34,9 @@ std::unique_ptr<Layer> CustomLayer::Impl::cloneRef(const std::string&) const {
return std::make_unique<CustomLayer>(*this);
}
+void CustomLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const {
+}
+
void CustomLayer::Impl::initialize() {
assert(initializeFn);
initializeFn(context);
diff --git a/src/mbgl/style/layers/custom_layer_impl.hpp b/src/mbgl/style/layers/custom_layer_impl.hpp
index 3e365faacf..71fb46d0d9 100644
--- a/src/mbgl/style/layers/custom_layer_impl.hpp
+++ b/src/mbgl/style/layers/custom_layer_impl.hpp
@@ -27,6 +27,7 @@ public:
private:
std::unique_ptr<Layer> clone() const override;
std::unique_ptr<Layer> cloneRef(const std::string& id) const override;
+ void stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const override;
void cascade(const CascadeParameters&) final {}
bool evaluate(const PropertyEvaluationParameters&) final;
diff --git a/src/mbgl/style/layers/fill_extrusion_layer.cpp b/src/mbgl/style/layers/fill_extrusion_layer.cpp
index 64efb1dd6a..34f0267d16 100644
--- a/src/mbgl/style/layers/fill_extrusion_layer.cpp
+++ b/src/mbgl/style/layers/fill_extrusion_layer.cpp
@@ -2,6 +2,7 @@
#include <mbgl/style/layers/fill_extrusion_layer.hpp>
#include <mbgl/style/layers/fill_extrusion_layer_impl.hpp>
+#include <mbgl/style/conversion/stringify.hpp>
namespace mbgl {
namespace style {
@@ -27,11 +28,13 @@ std::unique_ptr<Layer> FillExtrusionLayer::Impl::clone() const {
std::unique_ptr<Layer> FillExtrusionLayer::Impl::cloneRef(const std::string& id_) const {
auto result = std::make_unique<FillExtrusionLayer>(*this);
result->impl->id = id_;
- result->impl->ref = this->id;
result->impl->paint = FillExtrusionPaintProperties();
return std::move(result);
}
+void FillExtrusionLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const {
+}
+
// Source
const std::string& FillExtrusionLayer::getSourceID() const {
diff --git a/src/mbgl/style/layers/fill_extrusion_layer_impl.hpp b/src/mbgl/style/layers/fill_extrusion_layer_impl.hpp
index 52b9d327f2..3dd8bb270a 100644
--- a/src/mbgl/style/layers/fill_extrusion_layer_impl.hpp
+++ b/src/mbgl/style/layers/fill_extrusion_layer_impl.hpp
@@ -11,6 +11,7 @@ class FillExtrusionLayer::Impl : public Layer::Impl {
public:
std::unique_ptr<Layer> clone() const override;
std::unique_ptr<Layer> cloneRef(const std::string& id) const override;
+ void stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const override;
void cascade(const CascadeParameters&) override;
bool evaluate(const PropertyEvaluationParameters&) override;
diff --git a/src/mbgl/style/layers/fill_layer.cpp b/src/mbgl/style/layers/fill_layer.cpp
index 3bea9b56b0..b8fa8cad8b 100644
--- a/src/mbgl/style/layers/fill_layer.cpp
+++ b/src/mbgl/style/layers/fill_layer.cpp
@@ -2,6 +2,7 @@
#include <mbgl/style/layers/fill_layer.hpp>
#include <mbgl/style/layers/fill_layer_impl.hpp>
+#include <mbgl/style/conversion/stringify.hpp>
namespace mbgl {
namespace style {
@@ -27,11 +28,13 @@ std::unique_ptr<Layer> FillLayer::Impl::clone() const {
std::unique_ptr<Layer> FillLayer::Impl::cloneRef(const std::string& id_) const {
auto result = std::make_unique<FillLayer>(*this);
result->impl->id = id_;
- result->impl->ref = this->id;
result->impl->paint = FillPaintProperties();
return std::move(result);
}
+void FillLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const {
+}
+
// Source
const std::string& FillLayer::getSourceID() const {
diff --git a/src/mbgl/style/layers/fill_layer_impl.cpp b/src/mbgl/style/layers/fill_layer_impl.cpp
index 59d6a22432..51636820f0 100644
--- a/src/mbgl/style/layers/fill_layer_impl.cpp
+++ b/src/mbgl/style/layers/fill_layer_impl.cpp
@@ -33,11 +33,10 @@ bool FillLayer::Impl::evaluate(const PropertyEvaluationParameters& parameters) {
std::unique_ptr<Bucket> FillLayer::Impl::createBucket(BucketParameters& parameters, const GeometryTileLayer& layer) const {
auto bucket = std::make_unique<FillBucket>();
- auto& name = bucketName();
parameters.eachFilteredFeature(filter, layer, [&] (const auto& feature, std::size_t index, const std::string& layerName) {
auto geometries = feature.getGeometries();
bucket->addGeometry(geometries);
- parameters.featureIndex.insert(geometries, index, layerName, name);
+ parameters.featureIndex.insert(geometries, index, layerName, id);
});
return std::move(bucket);
diff --git a/src/mbgl/style/layers/fill_layer_impl.hpp b/src/mbgl/style/layers/fill_layer_impl.hpp
index bebea4ffab..28e2fa7edc 100644
--- a/src/mbgl/style/layers/fill_layer_impl.hpp
+++ b/src/mbgl/style/layers/fill_layer_impl.hpp
@@ -11,6 +11,7 @@ class FillLayer::Impl : public Layer::Impl {
public:
std::unique_ptr<Layer> clone() const override;
std::unique_ptr<Layer> cloneRef(const std::string& id) const override;
+ void stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const override;
void cascade(const CascadeParameters&) override;
bool evaluate(const PropertyEvaluationParameters&) override;
diff --git a/src/mbgl/style/layers/layer.cpp.ejs b/src/mbgl/style/layers/layer.cpp.ejs
index 5fe78519ec..e730e3a29b 100644
--- a/src/mbgl/style/layers/layer.cpp.ejs
+++ b/src/mbgl/style/layers/layer.cpp.ejs
@@ -7,6 +7,7 @@
#include <mbgl/style/layers/<%- type.replace('-', '_') %>_layer.hpp>
#include <mbgl/style/layers/<%- type.replace('-', '_') %>_layer_impl.hpp>
+#include <mbgl/style/conversion/stringify.hpp>
namespace mbgl {
namespace style {
@@ -40,11 +41,19 @@ std::unique_ptr<Layer> <%- camelize(type) %>Layer::Impl::clone() const {
std::unique_ptr<Layer> <%- camelize(type) %>Layer::Impl::cloneRef(const std::string& id_) const {
auto result = std::make_unique<<%- camelize(type) %>Layer>(*this);
result->impl->id = id_;
- result->impl->ref = this->id;
result->impl->paint = <%- camelize(type) %>PaintProperties();
return std::move(result);
}
+<% if (layoutProperties.length) { -%>
+void <%- camelize(type) %>Layer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>& writer) const {
+ conversion::stringify(writer, layout);
+}
+<% } else { -%>
+void <%- camelize(type) %>Layer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const {
+}
+<% } -%>
+
<% if (type !== 'background') { -%>
// Source
diff --git a/src/mbgl/style/layers/layer_properties.hpp.ejs b/src/mbgl/style/layers/layer_properties.hpp.ejs
index f490a636f9..d18ad44efd 100644
--- a/src/mbgl/style/layers/layer_properties.hpp.ejs
+++ b/src/mbgl/style/layers/layer_properties.hpp.ejs
@@ -16,6 +16,7 @@ namespace style {
<% for (const property of layoutProperties) { -%>
struct <%- camelize(property.name) %> : LayoutProperty<<%- propertyType(property) %>> {
+ static constexpr const char * key = "<%- property.name %>";
static <%- propertyType(property) %> defaultValue() { return <%- defaultValue(property) %>; }
};
diff --git a/src/mbgl/style/layers/line_layer.cpp b/src/mbgl/style/layers/line_layer.cpp
index 8c38ef5694..7f6c148cd1 100644
--- a/src/mbgl/style/layers/line_layer.cpp
+++ b/src/mbgl/style/layers/line_layer.cpp
@@ -2,6 +2,7 @@
#include <mbgl/style/layers/line_layer.hpp>
#include <mbgl/style/layers/line_layer_impl.hpp>
+#include <mbgl/style/conversion/stringify.hpp>
namespace mbgl {
namespace style {
@@ -27,11 +28,14 @@ std::unique_ptr<Layer> LineLayer::Impl::clone() const {
std::unique_ptr<Layer> LineLayer::Impl::cloneRef(const std::string& id_) const {
auto result = std::make_unique<LineLayer>(*this);
result->impl->id = id_;
- result->impl->ref = this->id;
result->impl->paint = LinePaintProperties();
return std::move(result);
}
+void LineLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>& writer) const {
+ conversion::stringify(writer, layout);
+}
+
// Source
const std::string& LineLayer::getSourceID() const {
diff --git a/src/mbgl/style/layers/line_layer_impl.cpp b/src/mbgl/style/layers/line_layer_impl.cpp
index 24b2b097b1..477579a43c 100644
--- a/src/mbgl/style/layers/line_layer_impl.cpp
+++ b/src/mbgl/style/layers/line_layer_impl.cpp
@@ -31,11 +31,10 @@ std::unique_ptr<Bucket> LineLayer::Impl::createBucket(BucketParameters& paramete
bucket->layout = layout.evaluate(PropertyEvaluationParameters(parameters.tileID.overscaledZ));
- auto& name = bucketName();
parameters.eachFilteredFeature(filter, layer, [&] (const auto& feature, std::size_t index, const std::string& layerName) {
auto geometries = feature.getGeometries();
bucket->addGeometry(geometries);
- parameters.featureIndex.insert(geometries, index, layerName, name);
+ parameters.featureIndex.insert(geometries, index, layerName, id);
});
return std::move(bucket);
diff --git a/src/mbgl/style/layers/line_layer_impl.hpp b/src/mbgl/style/layers/line_layer_impl.hpp
index 8c8c7d053b..1955c019af 100644
--- a/src/mbgl/style/layers/line_layer_impl.hpp
+++ b/src/mbgl/style/layers/line_layer_impl.hpp
@@ -11,6 +11,7 @@ class LineLayer::Impl : public Layer::Impl {
public:
std::unique_ptr<Layer> clone() const override;
std::unique_ptr<Layer> cloneRef(const std::string& id) const override;
+ void stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const override;
void cascade(const CascadeParameters&) override;
bool evaluate(const PropertyEvaluationParameters&) override;
diff --git a/src/mbgl/style/layers/line_layer_properties.hpp b/src/mbgl/style/layers/line_layer_properties.hpp
index 07458cd634..2ea7f6b125 100644
--- a/src/mbgl/style/layers/line_layer_properties.hpp
+++ b/src/mbgl/style/layers/line_layer_properties.hpp
@@ -10,18 +10,22 @@ namespace mbgl {
namespace style {
struct LineCap : LayoutProperty<LineCapType> {
+ static constexpr const char * key = "line-cap";
static LineCapType defaultValue() { return LineCapType::Butt; }
};
struct LineJoin : LayoutProperty<LineJoinType> {
+ static constexpr const char * key = "line-join";
static LineJoinType defaultValue() { return LineJoinType::Miter; }
};
struct LineMiterLimit : LayoutProperty<float> {
+ static constexpr const char * key = "line-miter-limit";
static float defaultValue() { return 2; }
};
struct LineRoundLimit : LayoutProperty<float> {
+ static constexpr const char * key = "line-round-limit";
static float defaultValue() { return 1; }
};
diff --git a/src/mbgl/style/layers/raster_layer.cpp b/src/mbgl/style/layers/raster_layer.cpp
index 21d72a0fdc..0fda27f0dc 100644
--- a/src/mbgl/style/layers/raster_layer.cpp
+++ b/src/mbgl/style/layers/raster_layer.cpp
@@ -2,6 +2,7 @@
#include <mbgl/style/layers/raster_layer.hpp>
#include <mbgl/style/layers/raster_layer_impl.hpp>
+#include <mbgl/style/conversion/stringify.hpp>
namespace mbgl {
namespace style {
@@ -27,11 +28,13 @@ std::unique_ptr<Layer> RasterLayer::Impl::clone() const {
std::unique_ptr<Layer> RasterLayer::Impl::cloneRef(const std::string& id_) const {
auto result = std::make_unique<RasterLayer>(*this);
result->impl->id = id_;
- result->impl->ref = this->id;
result->impl->paint = RasterPaintProperties();
return std::move(result);
}
+void RasterLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const {
+}
+
// Source
const std::string& RasterLayer::getSourceID() const {
diff --git a/src/mbgl/style/layers/raster_layer_impl.hpp b/src/mbgl/style/layers/raster_layer_impl.hpp
index b7c926f623..8e69c21ca8 100644
--- a/src/mbgl/style/layers/raster_layer_impl.hpp
+++ b/src/mbgl/style/layers/raster_layer_impl.hpp
@@ -11,6 +11,7 @@ class RasterLayer::Impl : public Layer::Impl {
public:
std::unique_ptr<Layer> clone() const override;
std::unique_ptr<Layer> cloneRef(const std::string& id) const override;
+ void stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const override;
void cascade(const CascadeParameters&) override;
bool evaluate(const PropertyEvaluationParameters&) override;
diff --git a/src/mbgl/style/layers/symbol_layer.cpp b/src/mbgl/style/layers/symbol_layer.cpp
index 61f360ff64..c9014e7ee7 100644
--- a/src/mbgl/style/layers/symbol_layer.cpp
+++ b/src/mbgl/style/layers/symbol_layer.cpp
@@ -2,6 +2,7 @@
#include <mbgl/style/layers/symbol_layer.hpp>
#include <mbgl/style/layers/symbol_layer_impl.hpp>
+#include <mbgl/style/conversion/stringify.hpp>
namespace mbgl {
namespace style {
@@ -27,11 +28,14 @@ std::unique_ptr<Layer> SymbolLayer::Impl::clone() const {
std::unique_ptr<Layer> SymbolLayer::Impl::cloneRef(const std::string& id_) const {
auto result = std::make_unique<SymbolLayer>(*this);
result->impl->id = id_;
- result->impl->ref = this->id;
result->impl->paint = SymbolPaintProperties();
return std::move(result);
}
+void SymbolLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>& writer) const {
+ conversion::stringify(writer, layout);
+}
+
// Source
const std::string& SymbolLayer::getSourceID() const {
diff --git a/src/mbgl/style/layers/symbol_layer_impl.cpp b/src/mbgl/style/layers/symbol_layer_impl.cpp
index 64968f51e4..8fb85513cf 100644
--- a/src/mbgl/style/layers/symbol_layer_impl.cpp
+++ b/src/mbgl/style/layers/symbol_layer_impl.cpp
@@ -29,7 +29,9 @@ std::unique_ptr<Bucket> SymbolLayer::Impl::createBucket(BucketParameters&, const
return nullptr;
}
-std::unique_ptr<SymbolLayout> SymbolLayer::Impl::createLayout(BucketParameters& parameters, const GeometryTileLayer& layer) const {
+std::unique_ptr<SymbolLayout> SymbolLayer::Impl::createLayout(BucketParameters& parameters,
+ const GeometryTileLayer& layer,
+ std::vector<std::unique_ptr<Layer>> group) const {
PropertyEvaluationParameters p(parameters.tileID.overscaledZ);
SymbolLayoutProperties::Evaluated evaluated = layout.evaluate(p);
@@ -59,7 +61,7 @@ std::unique_ptr<SymbolLayout> SymbolLayer::Impl::createLayout(BucketParameters&
evaluated.get<IconSize>() = layout.evaluate<IconSize>(PropertyEvaluationParameters(p.z + 1));
evaluated.get<TextSize>() = layout.evaluate<TextSize>(PropertyEvaluationParameters(p.z + 1));
- return std::make_unique<SymbolLayout>(id,
+ return std::make_unique<SymbolLayout>(std::move(group),
layer.getName(),
parameters.tileID.overscaleFactor(),
parameters.tileID.overscaledZ,
diff --git a/src/mbgl/style/layers/symbol_layer_impl.hpp b/src/mbgl/style/layers/symbol_layer_impl.hpp
index 4377630491..0d9a7c07e3 100644
--- a/src/mbgl/style/layers/symbol_layer_impl.hpp
+++ b/src/mbgl/style/layers/symbol_layer_impl.hpp
@@ -45,12 +45,14 @@ class SymbolLayer::Impl : public Layer::Impl {
public:
std::unique_ptr<Layer> clone() const override;
std::unique_ptr<Layer> cloneRef(const std::string& id) const override;
+ void stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const override;
void cascade(const CascadeParameters&) override;
bool evaluate(const PropertyEvaluationParameters&) override;
std::unique_ptr<Bucket> createBucket(BucketParameters&, const GeometryTileLayer&) const override;
- std::unique_ptr<SymbolLayout> createLayout(BucketParameters&, const GeometryTileLayer&) const;
+ std::unique_ptr<SymbolLayout> createLayout(BucketParameters&, const GeometryTileLayer&,
+ std::vector<std::unique_ptr<Layer>>) const;
SymbolPropertyValues iconPropertyValues(const SymbolLayoutProperties::Evaluated&) const;
SymbolPropertyValues textPropertyValues(const SymbolLayoutProperties::Evaluated&) const;
diff --git a/src/mbgl/style/layers/symbol_layer_properties.hpp b/src/mbgl/style/layers/symbol_layer_properties.hpp
index 8b72c4347a..f5fd6ce3df 100644
--- a/src/mbgl/style/layers/symbol_layer_properties.hpp
+++ b/src/mbgl/style/layers/symbol_layer_properties.hpp
@@ -10,138 +10,172 @@ namespace mbgl {
namespace style {
struct SymbolPlacement : LayoutProperty<SymbolPlacementType> {
+ static constexpr const char * key = "symbol-placement";
static SymbolPlacementType defaultValue() { return SymbolPlacementType::Point; }
};
struct SymbolSpacing : LayoutProperty<float> {
+ static constexpr const char * key = "symbol-spacing";
static float defaultValue() { return 250; }
};
struct SymbolAvoidEdges : LayoutProperty<bool> {
+ static constexpr const char * key = "symbol-avoid-edges";
static bool defaultValue() { return false; }
};
struct IconAllowOverlap : LayoutProperty<bool> {
+ static constexpr const char * key = "icon-allow-overlap";
static bool defaultValue() { return false; }
};
struct IconIgnorePlacement : LayoutProperty<bool> {
+ static constexpr const char * key = "icon-ignore-placement";
static bool defaultValue() { return false; }
};
struct IconOptional : LayoutProperty<bool> {
+ static constexpr const char * key = "icon-optional";
static bool defaultValue() { return false; }
};
struct IconRotationAlignment : LayoutProperty<AlignmentType> {
+ static constexpr const char * key = "icon-rotation-alignment";
static AlignmentType defaultValue() { return AlignmentType::Auto; }
};
struct IconSize : LayoutProperty<float> {
+ static constexpr const char * key = "icon-size";
static float defaultValue() { return 1; }
};
struct IconTextFit : LayoutProperty<IconTextFitType> {
+ static constexpr const char * key = "icon-text-fit";
static IconTextFitType defaultValue() { return IconTextFitType::None; }
};
struct IconTextFitPadding : LayoutProperty<std::array<float, 4>> {
+ static constexpr const char * key = "icon-text-fit-padding";
static std::array<float, 4> defaultValue() { return {{ 0, 0, 0, 0 }}; }
};
struct IconImage : LayoutProperty<std::string> {
+ static constexpr const char * key = "icon-image";
static std::string defaultValue() { return ""; }
};
struct IconRotate : LayoutProperty<float> {
+ static constexpr const char * key = "icon-rotate";
static float defaultValue() { return 0; }
};
struct IconPadding : LayoutProperty<float> {
+ static constexpr const char * key = "icon-padding";
static float defaultValue() { return 2; }
};
struct IconKeepUpright : LayoutProperty<bool> {
+ static constexpr const char * key = "icon-keep-upright";
static bool defaultValue() { return false; }
};
struct IconOffset : LayoutProperty<std::array<float, 2>> {
+ static constexpr const char * key = "icon-offset";
static std::array<float, 2> defaultValue() { return {{ 0, 0 }}; }
};
struct TextPitchAlignment : LayoutProperty<AlignmentType> {
+ static constexpr const char * key = "text-pitch-alignment";
static AlignmentType defaultValue() { return AlignmentType::Auto; }
};
struct TextRotationAlignment : LayoutProperty<AlignmentType> {
+ static constexpr const char * key = "text-rotation-alignment";
static AlignmentType defaultValue() { return AlignmentType::Auto; }
};
struct TextField : LayoutProperty<std::string> {
+ static constexpr const char * key = "text-field";
static std::string defaultValue() { return ""; }
};
struct TextFont : LayoutProperty<std::vector<std::string>> {
+ static constexpr const char * key = "text-font";
static std::vector<std::string> defaultValue() { return { "Open Sans Regular", "Arial Unicode MS Regular" }; }
};
struct TextSize : LayoutProperty<float> {
+ static constexpr const char * key = "text-size";
static float defaultValue() { return 16; }
};
struct TextMaxWidth : LayoutProperty<float> {
+ static constexpr const char * key = "text-max-width";
static float defaultValue() { return 10; }
};
struct TextLineHeight : LayoutProperty<float> {
+ static constexpr const char * key = "text-line-height";
static float defaultValue() { return 1.2; }
};
struct TextLetterSpacing : LayoutProperty<float> {
+ static constexpr const char * key = "text-letter-spacing";
static float defaultValue() { return 0; }
};
struct TextJustify : LayoutProperty<TextJustifyType> {
+ static constexpr const char * key = "text-justify";
static TextJustifyType defaultValue() { return TextJustifyType::Center; }
};
struct TextAnchor : LayoutProperty<TextAnchorType> {
+ static constexpr const char * key = "text-anchor";
static TextAnchorType defaultValue() { return TextAnchorType::Center; }
};
struct TextMaxAngle : LayoutProperty<float> {
+ static constexpr const char * key = "text-max-angle";
static float defaultValue() { return 45; }
};
struct TextRotate : LayoutProperty<float> {
+ static constexpr const char * key = "text-rotate";
static float defaultValue() { return 0; }
};
struct TextPadding : LayoutProperty<float> {
+ static constexpr const char * key = "text-padding";
static float defaultValue() { return 2; }
};
struct TextKeepUpright : LayoutProperty<bool> {
+ static constexpr const char * key = "text-keep-upright";
static bool defaultValue() { return true; }
};
struct TextTransform : LayoutProperty<TextTransformType> {
+ static constexpr const char * key = "text-transform";
static TextTransformType defaultValue() { return TextTransformType::None; }
};
struct TextOffset : LayoutProperty<std::array<float, 2>> {
+ static constexpr const char * key = "text-offset";
static std::array<float, 2> defaultValue() { return {{ 0, 0 }}; }
};
struct TextAllowOverlap : LayoutProperty<bool> {
+ static constexpr const char * key = "text-allow-overlap";
static bool defaultValue() { return false; }
};
struct TextIgnorePlacement : LayoutProperty<bool> {
+ static constexpr const char * key = "text-ignore-placement";
static bool defaultValue() { return false; }
};
struct TextOptional : LayoutProperty<bool> {
+ static constexpr const char * key = "text-optional";
static bool defaultValue() { return false; }
};
diff --git a/src/mbgl/tile/geometry_tile.cpp b/src/mbgl/tile/geometry_tile.cpp
index 10c0e1b244..2a0047fecf 100644
--- a/src/mbgl/tile/geometry_tile.cpp
+++ b/src/mbgl/tile/geometry_tile.cpp
@@ -128,7 +128,7 @@ void GeometryTile::onError(std::exception_ptr err) {
}
Bucket* GeometryTile::getBucket(const Layer& layer) {
- const auto it = buckets.find(layer.baseImpl->bucketName());
+ const auto it = buckets.find(layer.baseImpl->id);
if (it == buckets.end()) {
return nullptr;
}
diff --git a/src/mbgl/tile/geometry_tile.hpp b/src/mbgl/tile/geometry_tile.hpp
index 86243e8a09..993f7b018e 100644
--- a/src/mbgl/tile/geometry_tile.hpp
+++ b/src/mbgl/tile/geometry_tile.hpp
@@ -50,7 +50,7 @@ public:
class LayoutResult {
public:
- std::unordered_map<std::string, std::unique_ptr<Bucket>> buckets;
+ std::unordered_map<std::string, std::shared_ptr<Bucket>> buckets;
std::unique_ptr<FeatureIndex> featureIndex;
std::unique_ptr<GeometryTileData> tileData;
uint64_t correlationID;
@@ -59,7 +59,7 @@ public:
class PlacementResult {
public:
- std::unordered_map<std::string, std::unique_ptr<Bucket>> buckets;
+ std::unordered_map<std::string, std::shared_ptr<Bucket>> buckets;
std::unique_ptr<CollisionTile> collisionTile;
uint64_t correlationID;
};
@@ -80,7 +80,7 @@ private:
uint64_t correlationID = 0;
optional<PlacementConfig> requestedConfig;
- std::unordered_map<std::string, std::unique_ptr<Bucket>> buckets;
+ std::unordered_map<std::string, std::shared_ptr<Bucket>> buckets;
std::unique_ptr<FeatureIndex> featureIndex;
std::unique_ptr<const GeometryTileData> data;
};
diff --git a/src/mbgl/tile/geometry_tile_worker.cpp b/src/mbgl/tile/geometry_tile_worker.cpp
index beebebd262..169339f13f 100644
--- a/src/mbgl/tile/geometry_tile_worker.cpp
+++ b/src/mbgl/tile/geometry_tile_worker.cpp
@@ -5,6 +5,7 @@
#include <mbgl/text/glyph_atlas.hpp>
#include <mbgl/layout/symbol_layout.hpp>
#include <mbgl/style/bucket_parameters.hpp>
+#include <mbgl/style/group_by_layout.hpp>
#include <mbgl/style/layers/symbol_layer.hpp>
#include <mbgl/style/layers/symbol_layer_impl.hpp>
#include <mbgl/renderer/symbol_bucket.hpp>
@@ -201,51 +202,61 @@ void GeometryTileWorker::redoLayout() {
return;
}
- // We're doing a fresh parse of the tile, because the underlying data or style has changed.
- symbolLayouts.clear();
+ std::vector<std::string> symbolOrder;
+ for (auto it = layers->rbegin(); it != layers->rend(); it++) {
+ if ((*it)->is<SymbolLayer>()) {
+ symbolOrder.push_back((*it)->getID());
+ }
+ }
- // We're storing a set of bucket names we've parsed to avoid parsing a bucket twice that is
- // referenced from more than one layer
- std::unordered_set<std::string> parsed;
- std::unordered_map<std::string, std::unique_ptr<Bucket>> buckets;
+ std::unordered_map<std::string, std::unique_ptr<SymbolLayout>> symbolLayoutMap;
+ std::unordered_map<std::string, std::shared_ptr<Bucket>> buckets;
auto featureIndex = std::make_unique<FeatureIndex>();
BucketParameters parameters { id, obsolete, *featureIndex, mode };
- for (auto i = layers->rbegin(); i != layers->rend(); i++) {
+ std::vector<std::vector<std::unique_ptr<Layer>>> groups = groupByLayout(std::move(*layers));
+ for (auto& group : groups) {
if (obsolete) {
return;
}
- const Layer* layer = i->get();
- const std::string& bucketName = layer->baseImpl->bucketName();
-
- featureIndex->addBucketLayerName(bucketName, layer->baseImpl->id);
-
- if (parsed.find(bucketName) != parsed.end()) {
- continue;
- }
-
- parsed.emplace(bucketName);
-
if (!*data) {
continue; // Tile has no data.
}
- auto geometryLayer = (*data)->getLayer(layer->baseImpl->sourceLayer);
+ const Layer& leader = *group.at(0);
+
+ auto geometryLayer = (*data)->getLayer(leader.baseImpl->sourceLayer);
if (!geometryLayer) {
continue;
}
- if (layer->is<SymbolLayer>()) {
- symbolLayouts.push_back(layer->as<SymbolLayer>()->impl->createLayout(parameters, *geometryLayer));
+ for (const auto& layer : group) {
+ featureIndex->addBucketLayerName(leader.getID(), layer->getID());
+ }
+
+ if (leader.is<SymbolLayer>()) {
+ symbolLayoutMap.emplace(leader.getID(),
+ leader.as<SymbolLayer>()->impl->createLayout(parameters, *geometryLayer, std::move(group)));
} else {
- std::unique_ptr<Bucket> bucket = layer->baseImpl->createBucket(parameters, *geometryLayer);
- if (bucket->hasData()) {
- buckets.emplace(layer->baseImpl->bucketName(), std::move(bucket));
+ std::shared_ptr<Bucket> bucket = leader.baseImpl->createBucket(parameters, *geometryLayer);
+ if (!bucket->hasData()) {
+ continue;
+ }
+ for (const auto& layer : group) {
+ buckets.emplace(layer->getID(), bucket);
}
}
}
+ symbolLayouts.clear();
+ for (const auto& symbolLayerID : symbolOrder) {
+ auto it = symbolLayoutMap.find(symbolLayerID);
+ if (it != symbolLayoutMap.end()) {
+ symbolLayouts.push_back(std::move(it->second));
+ }
+ }
+
parent.invoke(&GeometryTile::onLayout, GeometryTile::LayoutResult {
std::move(buckets),
std::move(featureIndex),
@@ -297,7 +308,7 @@ void GeometryTileWorker::attemptPlacement() {
}
auto collisionTile = std::make_unique<CollisionTile>(*placementConfig);
- std::unordered_map<std::string, std::unique_ptr<Bucket>> buckets;
+ std::unordered_map<std::string, std::shared_ptr<Bucket>> buckets;
for (auto& symbolLayout : symbolLayouts) {
if (obsolete) {
@@ -305,9 +316,13 @@ void GeometryTileWorker::attemptPlacement() {
}
symbolLayout->state = SymbolLayout::Placed;
- if (symbolLayout->hasSymbolInstances()) {
- buckets.emplace(symbolLayout->bucketName,
- symbolLayout->place(*collisionTile));
+ if (!symbolLayout->hasSymbolInstances()) {
+ continue;
+ }
+
+ std::shared_ptr<Bucket> bucket = symbolLayout->place(*collisionTile);
+ for (const auto& layer : symbolLayout->layers) {
+ buckets.emplace(layer->getID(), bucket);
}
}
diff --git a/src/mbgl/util/color.cpp b/src/mbgl/util/color.cpp
index eea897d3ab..d5751b405f 100644
--- a/src/mbgl/util/color.cpp
+++ b/src/mbgl/util/color.cpp
@@ -1,4 +1,5 @@
#include <mbgl/util/color.hpp>
+#include <mbgl/util/string.hpp>
#include <csscolorparser/csscolorparser.hpp>
@@ -17,4 +18,12 @@ optional<Color> Color::parse(const std::string& s) {
}};
}
+std::string Color::stringify() const {
+ return "rgba(" +
+ util::toString(r * 255) + "," +
+ util::toString(g * 255) + "," +
+ util::toString(b * 255) + "," +
+ util::toString(a) + ")";
+}
+
} // namespace mbgl
diff --git a/test/style/conversion/stringify.test.cpp b/test/style/conversion/stringify.test.cpp
new file mode 100644
index 0000000000..be5d65d4ce
--- /dev/null
+++ b/test/style/conversion/stringify.test.cpp
@@ -0,0 +1,98 @@
+#include <mbgl/test/util.hpp>
+
+#include <mbgl/style/conversion/stringify.hpp>
+#include <mbgl/style/types.hpp>
+#include <mbgl/style/layers/symbol_layer_properties.hpp>
+#include <mbgl/util/rapidjson.hpp>
+
+#include <rapidjson/writer.h>
+#include <rapidjson/stringbuffer.h>
+
+using namespace mbgl;
+using namespace mbgl::style;
+using namespace mbgl::style::conversion;
+
+template <class T>
+std::string stringify(const T& t) {
+ rapidjson::StringBuffer s;
+ rapidjson::Writer<rapidjson::StringBuffer> writer(s);
+ stringify(writer, t);
+ return s.GetString();
+}
+
+TEST(Stringify, NullValue) {
+ ASSERT_EQ(stringify(NullValue()), "null");
+}
+
+TEST(Stringify, Boolean) {
+ ASSERT_EQ(stringify(true), "true");
+ ASSERT_EQ(stringify(false), "false");
+}
+
+TEST(Stringify, Uint64) {
+ ASSERT_EQ(stringify(uint64_t(0)), "0");
+ ASSERT_EQ(stringify(uint64_t(1)), "1");
+}
+
+TEST(Stringify, Int64) {
+ ASSERT_EQ(stringify(int64_t(0)), "0");
+ ASSERT_EQ(stringify(int64_t(-1)), "-1");
+}
+
+TEST(Stringify, Double) {
+ ASSERT_EQ(stringify(0.0), "0.0");
+ ASSERT_EQ(stringify(10.1234), "10.1234");
+}
+
+TEST(Stringify, String) {
+ ASSERT_EQ(stringify(std::string("test")), "\"test\"");
+}
+
+TEST(Stringify, Enum) {
+ ASSERT_EQ(stringify(VisibilityType::Visible), "\"visible\"");
+}
+
+TEST(Stringify, Color) {
+ ASSERT_EQ(stringify(Color::blue()), "\"rgba(0,0,255,1)\"");
+}
+
+TEST(Stringify, Array) {
+ ASSERT_EQ(stringify(std::array<float, 2> {{ 1, 2 }}), "[1.0,2.0]");
+}
+
+TEST(Stringify, Vector) {
+ ASSERT_EQ(stringify(std::vector<float> {{ 1, 2 }}), "[1.0,2.0]");
+}
+
+TEST(Stringify, Map) {
+ ASSERT_EQ(stringify(std::unordered_map<std::string, float> {{ "a", 1 }}), "{\"a\":1.0}");
+}
+
+TEST(Stringify, Value) {
+ ASSERT_EQ(stringify(Value(true)), "true");
+ ASSERT_EQ(stringify(Value(uint64_t(0))), "0");
+ ASSERT_EQ(stringify(Value(1.2)), "1.2");
+}
+
+TEST(Stringify, Filter) {
+ ASSERT_EQ(stringify(NullFilter()), "null");
+ ASSERT_EQ(stringify(EqualsFilter { "a", 1.0 }), "[\"==\",\"a\",1.0]");
+}
+
+TEST(Stringify, Function) {
+ ASSERT_EQ(stringify(Function<float>({{0, 1}}, 2)), "{\"base\":2.0,\"stops\":[[0.0,1.0]]}");
+}
+
+TEST(Stringify, PropertyValue) {
+ ASSERT_EQ(stringify(PropertyValue<float>(1)), "1.0");
+ ASSERT_EQ(stringify(PropertyValue<float>(Function<float>({{0, 1}}, 2))), "{\"base\":2.0,\"stops\":[[0.0,1.0]]}");
+}
+
+TEST(Stringify, Layout) {
+ ASSERT_EQ(stringify(SymbolLayoutProperties()), "{}");
+
+ SymbolLayoutProperties layout;
+ layout.unevaluated.get<SymbolAvoidEdges>() = true;
+ layout.unevaluated.get<IconPadding>() = 2.0;
+ ASSERT_EQ(stringify(layout), "{\"symbol-avoid-edges\":true,\"icon-padding\":2.0}");
+}
diff --git a/test/style/group_by_layout.test.cpp b/test/style/group_by_layout.test.cpp
new file mode 100644
index 0000000000..d74916cdc9
--- /dev/null
+++ b/test/style/group_by_layout.test.cpp
@@ -0,0 +1,44 @@
+#include <mbgl/test/util.hpp>
+
+#include <mbgl/style/group_by_layout.hpp>
+#include <mbgl/style/layers/background_layer.hpp>
+#include <mbgl/style/layers/circle_layer.hpp>
+#include <mbgl/style/layers/line_layer.hpp>
+
+using namespace mbgl;
+using namespace mbgl::style;
+
+TEST(GroupByLayout, Related) {
+ std::vector<std::unique_ptr<Layer>> layers;
+ layers.push_back(std::make_unique<LineLayer>("a", "source"));
+ layers.push_back(std::make_unique<LineLayer>("b", "source"));
+ auto result = groupByLayout(std::move(layers));
+ ASSERT_EQ(1u, result.size());
+ ASSERT_EQ(2u, result[0].size());
+}
+
+TEST(GroupByLayout, UnrelatedType) {
+ std::vector<std::unique_ptr<Layer>> layers;
+ layers.push_back(std::make_unique<BackgroundLayer>("background"));
+ layers.push_back(std::make_unique<CircleLayer>("circle", "source"));
+ auto result = groupByLayout(std::move(layers));
+ ASSERT_EQ(2u, result.size());
+}
+
+TEST(GroupByLayout, UnrelatedFilter) {
+ std::vector<std::unique_ptr<Layer>> layers;
+ layers.push_back(std::make_unique<LineLayer>("a", "source"));
+ layers.push_back(std::make_unique<LineLayer>("b", "source"));
+ layers[0]->as<LineLayer>()->setFilter(EqualsFilter());
+ auto result = groupByLayout(std::move(layers));
+ ASSERT_EQ(2u, result.size());
+}
+
+TEST(GroupByLayout, UnrelatedLayout) {
+ std::vector<std::unique_ptr<Layer>> layers;
+ layers.push_back(std::make_unique<LineLayer>("a", "source"));
+ layers.push_back(std::make_unique<LineLayer>("b", "source"));
+ layers[0]->as<LineLayer>()->setLineCap(LineCapType::Square);
+ auto result = groupByLayout(std::move(layers));
+ ASSERT_EQ(2u, result.size());
+}