From f5abaf0f54f91ca81160b5c61354a06bac3833bb Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Mon, 2 Jan 2017 17:02:33 -0800 Subject: [PATCH 1/3] [node] Fix array/object distinction Only affects tests. --- platform/node/src/node_conversion.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/node/src/node_conversion.hpp b/platform/node/src/node_conversion.hpp index 6ebc846d118..22daedef6a5 100644 --- a/platform/node/src/node_conversion.hpp +++ b/platform/node/src/node_conversion.hpp @@ -36,7 +36,7 @@ inline v8::Local arrayMember(v8::Local value, std::size_t inline bool isObject(v8::Local value) { Nan::HandleScope scope; - return value->IsObject(); + return value->IsObject() && !value->IsArray(); } inline optional> objectMember(v8::Local value, const char * name) { From d12a5f9ad3ca8d59f75725dc3a390c5cdbe1abef Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Mon, 19 Dec 2016 17:10:51 -0800 Subject: [PATCH 2/3] [core] Use PropertyMap typedef --- include/mbgl/style/filter_evaluator.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/mbgl/style/filter_evaluator.hpp b/include/mbgl/style/filter_evaluator.hpp index cf9877da268..659f554bbab 100644 --- a/include/mbgl/style/filter_evaluator.hpp +++ b/include/mbgl/style/filter_evaluator.hpp @@ -173,8 +173,8 @@ class FilterEvaluator { return false; } - bool operator()(const std::unordered_map&, - const std::unordered_map&) const { + bool operator()(const PropertyMap&, + const PropertyMap&) const { // Should be unreachable; nested values are not currently allowed by the style specification. assert(false); return false; From 99c1a0ecbdadb54df32baddb1b0b88df71533c4b Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Mon, 19 Dec 2016 17:10:51 -0800 Subject: [PATCH 3/3] [core] Get rid of user-specified refs --- CMakeLists.txt | 2 + cmake/core-files.cmake | 3 + cmake/test-files.cmake | 2 + include/mbgl/style/layer.hpp | 2 + include/mbgl/util/color.hpp | 1 + package.json | 2 +- .../style_sourced_annotation_impl.cpp | 4 +- src/mbgl/layout/symbol_layout.cpp | 7 +- src/mbgl/layout/symbol_layout.hpp | 5 +- src/mbgl/style/conversion/stringify.hpp | 256 ++++++++++++++++++ src/mbgl/style/group_by_layout.cpp | 51 ++++ src/mbgl/style/group_by_layout.hpp | 14 + src/mbgl/style/layer_impl.cpp | 6 - src/mbgl/style/layer_impl.hpp | 13 +- src/mbgl/style/layers/background_layer.cpp | 5 +- .../style/layers/background_layer_impl.hpp | 1 + src/mbgl/style/layers/circle_layer.cpp | 5 +- src/mbgl/style/layers/circle_layer_impl.cpp | 3 +- src/mbgl/style/layers/circle_layer_impl.hpp | 1 + src/mbgl/style/layers/custom_layer_impl.cpp | 3 + src/mbgl/style/layers/custom_layer_impl.hpp | 1 + .../style/layers/fill_extrusion_layer.cpp | 5 +- .../layers/fill_extrusion_layer_impl.hpp | 1 + src/mbgl/style/layers/fill_layer.cpp | 5 +- src/mbgl/style/layers/fill_layer_impl.cpp | 3 +- src/mbgl/style/layers/fill_layer_impl.hpp | 1 + src/mbgl/style/layers/layer.cpp.ejs | 11 +- .../style/layers/layer_properties.hpp.ejs | 1 + src/mbgl/style/layers/line_layer.cpp | 6 +- src/mbgl/style/layers/line_layer_impl.cpp | 3 +- src/mbgl/style/layers/line_layer_impl.hpp | 1 + .../style/layers/line_layer_properties.hpp | 4 + src/mbgl/style/layers/raster_layer.cpp | 5 +- src/mbgl/style/layers/raster_layer_impl.hpp | 1 + src/mbgl/style/layers/symbol_layer.cpp | 6 +- src/mbgl/style/layers/symbol_layer_impl.cpp | 6 +- src/mbgl/style/layers/symbol_layer_impl.hpp | 4 +- .../style/layers/symbol_layer_properties.hpp | 34 +++ src/mbgl/tile/geometry_tile.cpp | 2 +- src/mbgl/tile/geometry_tile.hpp | 6 +- src/mbgl/tile/geometry_tile_worker.cpp | 71 +++-- src/mbgl/util/color.cpp | 9 + test/style/conversion/stringify.test.cpp | 98 +++++++ test/style/group_by_layout.test.cpp | 44 +++ 44 files changed, 645 insertions(+), 69 deletions(-) create mode 100644 src/mbgl/style/conversion/stringify.hpp create mode 100644 src/mbgl/style/group_by_layout.cpp create mode 100644 src/mbgl/style/group_by_layout.hpp create mode 100644 test/style/conversion/stringify.test.cpp create mode 100644 test/style/group_by_layout.test.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index a9f52ba9dea..41df0f2a126 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 3255da66f28..6c44117cd8e 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 7d8dc82756e..e05b956b1ec 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 dc02cb09b2e..5936422c740 100644 --- a/include/mbgl/style/layer.hpp +++ b/include/mbgl/style/layer.hpp @@ -116,6 +116,8 @@ class Layer : public mbgl::util::noncopyable { // Private implementation const std::unique_ptr baseImpl; + + friend std::string layoutKey(const Layer&); }; } // namespace style diff --git a/include/mbgl/util/color.hpp b/include/mbgl/util/color.hpp index 178d0dc7586..7ac63e345e1 100644 --- a/include/mbgl/util/color.hpp +++ b/include/mbgl/util/color.hpp @@ -36,6 +36,7 @@ class Color { static constexpr Color blue() { return { 0.0f, 0.0f, 1.0f, 1.0f }; }; static optional parse(const std::string&); + std::string stringify() const; }; constexpr bool operator==(const Color& colorA, const Color& colorB) { diff --git a/package.json b/package.json index 4633b4bc4d5..9eff43e1d75 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 d3212da12d8..cb664cf15d0 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()) { - std::unique_ptr layer = sourceLayer->baseImpl->copy(layerID, "", AnnotationManager::SourceID); + std::unique_ptr layer = sourceLayer->baseImpl->copy(layerID, AnnotationManager::SourceID); layer->as()->setSourceLayer(layerID); layer->as()->setVisibility(VisibilityType::Visible); style.addLayer(std::move(layer), sourceLayer->getID()); } else if (sourceLayer->is()) { - std::unique_ptr layer = sourceLayer->baseImpl->copy(layerID, "", AnnotationManager::SourceID); + std::unique_ptr layer = sourceLayer->baseImpl->copy(layerID, AnnotationManager::SourceID); layer->as()->setSourceLayer(layerID); layer->as()->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 351858f6f85..85e0b196096 100644 --- a/src/mbgl/layout/symbol_layout.cpp +++ b/src/mbgl/layout/symbol_layout.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -26,7 +27,7 @@ namespace mbgl { using namespace style; -SymbolLayout::SymbolLayout(std::string bucketName_, +SymbolLayout::SymbolLayout(std::vector> 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(); 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 18fb9ff4bc0..63c0a8859d9 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::string sourceLayerName_, uint32_t overscaling, float zoom, @@ -55,7 +56,7 @@ class SymbolLayout { State state = Pending; - const std::string bucketName; + const std::vector> 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 00000000000..d06b2f2814d --- /dev/null +++ b/src/mbgl/style/conversion/stringify.hpp @@ -0,0 +1,256 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace mbgl { +namespace style { +namespace conversion { + +template +void stringify(Writer& writer, NullValue) { + writer.Null(); +} + +template +void stringify(Writer& writer, bool v) { + writer.Bool(v); +} + +template +void stringify(Writer& writer, uint64_t v) { + writer.Uint64(v); +} + +template +void stringify(Writer& writer, int64_t v) { + writer.Int64(v); +} + +template +void stringify(Writer& writer, double v) { + writer.Double(v); +} + +template +void stringify(Writer& writer, const std::string& v) { + writer.String(v); +} + +template ::value>> +void stringify(Writer& writer, const T& v) { + writer.String(Enum::toString(v)); +} + +template +void stringify(Writer& writer, const Color& v) { + writer.String(v.stringify()); +} + +template +void stringify(Writer& writer, const std::array& v) { + writer.StartArray(); + writer.Double(v[0]); + writer.Double(v[1]); + writer.EndArray(); +} + +template +void stringify(Writer& writer, const std::array& v) { + writer.StartArray(); + writer.Double(v[0]); + writer.Double(v[1]); + writer.Double(v[2]); + writer.Double(v[3]); + writer.EndArray(); +} + +template +void stringify(Writer&, const Value&); + +template +void stringify(Writer& writer, const std::vector& v) { + writer.StartArray(); + for (const auto& e : v) { + stringify(writer, e); + } + writer.EndArray(); +} + +template +void stringify(Writer& writer, const std::unordered_map& m) { + writer.StartObject(); + for (const auto& p : m) { + writer.Key(p.first.data(), static_cast(p.first.size())); + stringify(writer, p.second); + } + writer.EndObject(); +} + +template +void stringify(Writer& writer, const Value& v) { + Value::visit(v, [&] (const auto& v_) { stringify(writer, v_); }); +} + +template +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 + void stringifyBinaryFilter(const F& f, const char * op) { + writer.StartArray(); + writer.String(op); + writer.String(f.key); + stringify(writer, f.value); + writer.EndArray(); + } + + template + 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 + 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 + void stringifyUnaryFilter(const F& f, const char * op) { + writer.StartArray(); + writer.String(op); + writer.String(f.key); + writer.EndArray(); + } +}; + +template +void stringify(Writer& writer, const Filter& f) { + Filter::visit(f, StringifyFilter { writer }); +} + +template +void stringify(Writer& writer, const Undefined&) { + assert(false); // Should be omitted entirely instead. + writer.Null(); +} + +template +void stringify(Writer& writer, const Function& 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 +void stringify(Writer& writer, const PropertyValue& v) { + v.evaluate([&] (const auto& v_) { stringify(writer, v_); }); +} + +template +void stringify(Writer& writer, const PropertyValue& value) { + if (value) { + writer.Key(Property::key); + stringify(writer, value); + } +} + +template +void stringify(Writer& writer, const LayoutProperties& ps) { + writer.StartObject(); + util::ignore({ (stringify(writer, ps.unevaluated.template get()), 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 00000000000..52d33827ef9 --- /dev/null +++ b/src/mbgl/style/group_by_layout.cpp @@ -0,0 +1,51 @@ +#include +#include +#include +#include +#include + +#include +#include + +#include + +namespace mbgl { +namespace style { + +std::string layoutKey(const Layer& layer) { + using namespace conversion; + + rapidjson::StringBuffer s; + rapidjson::Writer writer(s); + + writer.StartArray(); + writer.Uint(static_cast(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(layer.baseImpl->visibility)); + stringify(writer, layer.baseImpl->filter); + layer.baseImpl->stringifyLayout(writer); + writer.EndArray(); + + return s.GetString(); +} + +std::vector>> groupByLayout(std::vector> layers) { + std::unordered_map>> map; + for (auto& layer : layers) { + auto& vector = map[layoutKey(*layer)]; + vector.push_back(std::move(layer)); + } + + std::vector>> 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 00000000000..dd7b5d118a2 --- /dev/null +++ b/src/mbgl/style/group_by_layout.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include +#include + +namespace mbgl { +namespace style { + +class Layer; + +std::vector>> groupByLayout(std::vector>); + +} // namespace style +} // namespace mbgl diff --git a/src/mbgl/style/layer_impl.cpp b/src/mbgl/style/layer_impl.cpp index 7a0195c55c0..58403187243 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::Impl::copy(const std::string& id_, - const std::string& ref_, const std::string& source_) const { std::unique_ptr 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 7e2c55c2e68..0fea70c10b9 100644 --- a/src/mbgl/style/layer_impl.hpp +++ b/src/mbgl/style/layer_impl.hpp @@ -8,6 +8,9 @@ #include #include +#include +#include + #include #include #include @@ -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 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 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 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&) const = 0; // Partially evaluate paint properties based on a set of classes. virtual void cascade(const CascadeParameters&) = 0; @@ -78,7 +80,6 @@ class Layer::Impl { 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 a54115d1a7a..a75038bfa0b 100644 --- a/src/mbgl/style/layers/background_layer.cpp +++ b/src/mbgl/style/layers/background_layer.cpp @@ -2,6 +2,7 @@ #include #include +#include namespace mbgl { namespace style { @@ -26,11 +27,13 @@ std::unique_ptr BackgroundLayer::Impl::clone() const { std::unique_ptr BackgroundLayer::Impl::cloneRef(const std::string& id_) const { auto result = std::make_unique(*this); result->impl->id = id_; - result->impl->ref = this->id; result->impl->paint = BackgroundPaintProperties(); return std::move(result); } +void BackgroundLayer::Impl::stringifyLayout(rapidjson::Writer&) const { +} + // Layout properties diff --git a/src/mbgl/style/layers/background_layer_impl.hpp b/src/mbgl/style/layers/background_layer_impl.hpp index d3d50e21cd6..4629217e6d3 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 clone() const override; std::unique_ptr cloneRef(const std::string& id) const override; + void stringifyLayout(rapidjson::Writer&) 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 e3a506e8956..389ab934032 100644 --- a/src/mbgl/style/layers/circle_layer.cpp +++ b/src/mbgl/style/layers/circle_layer.cpp @@ -2,6 +2,7 @@ #include #include +#include namespace mbgl { namespace style { @@ -27,11 +28,13 @@ std::unique_ptr CircleLayer::Impl::clone() const { std::unique_ptr CircleLayer::Impl::cloneRef(const std::string& id_) const { auto result = std::make_unique(*this); result->impl->id = id_; - result->impl->ref = this->id; result->impl->paint = CirclePaintProperties(); return std::move(result); } +void CircleLayer::Impl::stringifyLayout(rapidjson::Writer&) 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 614f637b3b1..136522e41c4 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 CircleLayer::Impl::createBucket(BucketParameters& parameters, const GeometryTileLayer& layer) const { auto bucket = std::make_unique(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 f0db58be24e..744a56898ce 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 clone() const override; std::unique_ptr cloneRef(const std::string& id) const override; + void stringifyLayout(rapidjson::Writer&) 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 baf55205c4a..cecd60a296d 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 CustomLayer::Impl::cloneRef(const std::string&) const { return std::make_unique(*this); } +void CustomLayer::Impl::stringifyLayout(rapidjson::Writer&) 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 3e365faacff..71fb46d0d91 100644 --- a/src/mbgl/style/layers/custom_layer_impl.hpp +++ b/src/mbgl/style/layers/custom_layer_impl.hpp @@ -27,6 +27,7 @@ class CustomLayer::Impl : public Layer::Impl { private: std::unique_ptr clone() const override; std::unique_ptr cloneRef(const std::string& id) const override; + void stringifyLayout(rapidjson::Writer&) 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 64efb1dd6ae..34f0267d166 100644 --- a/src/mbgl/style/layers/fill_extrusion_layer.cpp +++ b/src/mbgl/style/layers/fill_extrusion_layer.cpp @@ -2,6 +2,7 @@ #include #include +#include namespace mbgl { namespace style { @@ -27,11 +28,13 @@ std::unique_ptr FillExtrusionLayer::Impl::clone() const { std::unique_ptr FillExtrusionLayer::Impl::cloneRef(const std::string& id_) const { auto result = std::make_unique(*this); result->impl->id = id_; - result->impl->ref = this->id; result->impl->paint = FillExtrusionPaintProperties(); return std::move(result); } +void FillExtrusionLayer::Impl::stringifyLayout(rapidjson::Writer&) 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 52b9d327f27..3dd8bb270a4 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 clone() const override; std::unique_ptr cloneRef(const std::string& id) const override; + void stringifyLayout(rapidjson::Writer&) 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 3bea9b56b09..b8fa8cad8b7 100644 --- a/src/mbgl/style/layers/fill_layer.cpp +++ b/src/mbgl/style/layers/fill_layer.cpp @@ -2,6 +2,7 @@ #include #include +#include namespace mbgl { namespace style { @@ -27,11 +28,13 @@ std::unique_ptr FillLayer::Impl::clone() const { std::unique_ptr FillLayer::Impl::cloneRef(const std::string& id_) const { auto result = std::make_unique(*this); result->impl->id = id_; - result->impl->ref = this->id; result->impl->paint = FillPaintProperties(); return std::move(result); } +void FillLayer::Impl::stringifyLayout(rapidjson::Writer&) 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 59d6a22432c..51636820f02 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 FillLayer::Impl::createBucket(BucketParameters& parameters, const GeometryTileLayer& layer) const { auto bucket = std::make_unique(); - 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 bebea4ffab0..28e2fa7edc8 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 clone() const override; std::unique_ptr cloneRef(const std::string& id) const override; + void stringifyLayout(rapidjson::Writer&) 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 5fe78519ec4..e730e3a29b9 100644 --- a/src/mbgl/style/layers/layer.cpp.ejs +++ b/src/mbgl/style/layers/layer.cpp.ejs @@ -7,6 +7,7 @@ #include _layer.hpp> #include _layer_impl.hpp> +#include namespace mbgl { namespace style { @@ -40,11 +41,19 @@ std::unique_ptr <%- camelize(type) %>Layer::Impl::clone() const { std::unique_ptr <%- 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& writer) const { + conversion::stringify(writer, layout); +} +<% } else { -%> +void <%- camelize(type) %>Layer::Impl::stringifyLayout(rapidjson::Writer&) 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 f490a636f9f..d18ad44efd8 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 8c38ef5694d..7f6c148cd19 100644 --- a/src/mbgl/style/layers/line_layer.cpp +++ b/src/mbgl/style/layers/line_layer.cpp @@ -2,6 +2,7 @@ #include #include +#include namespace mbgl { namespace style { @@ -27,11 +28,14 @@ std::unique_ptr LineLayer::Impl::clone() const { std::unique_ptr LineLayer::Impl::cloneRef(const std::string& id_) const { auto result = std::make_unique(*this); result->impl->id = id_; - result->impl->ref = this->id; result->impl->paint = LinePaintProperties(); return std::move(result); } +void LineLayer::Impl::stringifyLayout(rapidjson::Writer& 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 24b2b097b15..477579a43c1 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 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 8c8c7d053b9..1955c019af2 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 clone() const override; std::unique_ptr cloneRef(const std::string& id) const override; + void stringifyLayout(rapidjson::Writer&) 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 07458cd6344..2ea7f6b125d 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 { + static constexpr const char * key = "line-cap"; static LineCapType defaultValue() { return LineCapType::Butt; } }; struct LineJoin : LayoutProperty { + static constexpr const char * key = "line-join"; static LineJoinType defaultValue() { return LineJoinType::Miter; } }; struct LineMiterLimit : LayoutProperty { + static constexpr const char * key = "line-miter-limit"; static float defaultValue() { return 2; } }; struct LineRoundLimit : LayoutProperty { + 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 21d72a0fdc0..0fda27f0dc3 100644 --- a/src/mbgl/style/layers/raster_layer.cpp +++ b/src/mbgl/style/layers/raster_layer.cpp @@ -2,6 +2,7 @@ #include #include +#include namespace mbgl { namespace style { @@ -27,11 +28,13 @@ std::unique_ptr RasterLayer::Impl::clone() const { std::unique_ptr RasterLayer::Impl::cloneRef(const std::string& id_) const { auto result = std::make_unique(*this); result->impl->id = id_; - result->impl->ref = this->id; result->impl->paint = RasterPaintProperties(); return std::move(result); } +void RasterLayer::Impl::stringifyLayout(rapidjson::Writer&) 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 b7c926f6239..8e69c21ca8d 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 clone() const override; std::unique_ptr cloneRef(const std::string& id) const override; + void stringifyLayout(rapidjson::Writer&) 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 61f360ff644..c9014e7ee73 100644 --- a/src/mbgl/style/layers/symbol_layer.cpp +++ b/src/mbgl/style/layers/symbol_layer.cpp @@ -2,6 +2,7 @@ #include #include +#include namespace mbgl { namespace style { @@ -27,11 +28,14 @@ std::unique_ptr SymbolLayer::Impl::clone() const { std::unique_ptr SymbolLayer::Impl::cloneRef(const std::string& id_) const { auto result = std::make_unique(*this); result->impl->id = id_; - result->impl->ref = this->id; result->impl->paint = SymbolPaintProperties(); return std::move(result); } +void SymbolLayer::Impl::stringifyLayout(rapidjson::Writer& 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 64968f51e40..8fb85513cf0 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 SymbolLayer::Impl::createBucket(BucketParameters&, const return nullptr; } -std::unique_ptr SymbolLayer::Impl::createLayout(BucketParameters& parameters, const GeometryTileLayer& layer) const { +std::unique_ptr SymbolLayer::Impl::createLayout(BucketParameters& parameters, + const GeometryTileLayer& layer, + std::vector> group) const { PropertyEvaluationParameters p(parameters.tileID.overscaledZ); SymbolLayoutProperties::Evaluated evaluated = layout.evaluate(p); @@ -59,7 +61,7 @@ std::unique_ptr SymbolLayer::Impl::createLayout(BucketParameters& evaluated.get() = layout.evaluate(PropertyEvaluationParameters(p.z + 1)); evaluated.get() = layout.evaluate(PropertyEvaluationParameters(p.z + 1)); - return std::make_unique(id, + return std::make_unique(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 43776304913..0d9a7c07e39 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 clone() const override; std::unique_ptr cloneRef(const std::string& id) const override; + void stringifyLayout(rapidjson::Writer&) const override; void cascade(const CascadeParameters&) override; bool evaluate(const PropertyEvaluationParameters&) override; std::unique_ptr createBucket(BucketParameters&, const GeometryTileLayer&) const override; - std::unique_ptr createLayout(BucketParameters&, const GeometryTileLayer&) const; + std::unique_ptr createLayout(BucketParameters&, const GeometryTileLayer&, + std::vector>) 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 8b72c4347a9..f5fd6ce3df3 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 { + static constexpr const char * key = "symbol-placement"; static SymbolPlacementType defaultValue() { return SymbolPlacementType::Point; } }; struct SymbolSpacing : LayoutProperty { + static constexpr const char * key = "symbol-spacing"; static float defaultValue() { return 250; } }; struct SymbolAvoidEdges : LayoutProperty { + static constexpr const char * key = "symbol-avoid-edges"; static bool defaultValue() { return false; } }; struct IconAllowOverlap : LayoutProperty { + static constexpr const char * key = "icon-allow-overlap"; static bool defaultValue() { return false; } }; struct IconIgnorePlacement : LayoutProperty { + static constexpr const char * key = "icon-ignore-placement"; static bool defaultValue() { return false; } }; struct IconOptional : LayoutProperty { + static constexpr const char * key = "icon-optional"; static bool defaultValue() { return false; } }; struct IconRotationAlignment : LayoutProperty { + static constexpr const char * key = "icon-rotation-alignment"; static AlignmentType defaultValue() { return AlignmentType::Auto; } }; struct IconSize : LayoutProperty { + static constexpr const char * key = "icon-size"; static float defaultValue() { return 1; } }; struct IconTextFit : LayoutProperty { + static constexpr const char * key = "icon-text-fit"; static IconTextFitType defaultValue() { return IconTextFitType::None; } }; struct IconTextFitPadding : LayoutProperty> { + static constexpr const char * key = "icon-text-fit-padding"; static std::array defaultValue() { return {{ 0, 0, 0, 0 }}; } }; struct IconImage : LayoutProperty { + static constexpr const char * key = "icon-image"; static std::string defaultValue() { return ""; } }; struct IconRotate : LayoutProperty { + static constexpr const char * key = "icon-rotate"; static float defaultValue() { return 0; } }; struct IconPadding : LayoutProperty { + static constexpr const char * key = "icon-padding"; static float defaultValue() { return 2; } }; struct IconKeepUpright : LayoutProperty { + static constexpr const char * key = "icon-keep-upright"; static bool defaultValue() { return false; } }; struct IconOffset : LayoutProperty> { + static constexpr const char * key = "icon-offset"; static std::array defaultValue() { return {{ 0, 0 }}; } }; struct TextPitchAlignment : LayoutProperty { + static constexpr const char * key = "text-pitch-alignment"; static AlignmentType defaultValue() { return AlignmentType::Auto; } }; struct TextRotationAlignment : LayoutProperty { + static constexpr const char * key = "text-rotation-alignment"; static AlignmentType defaultValue() { return AlignmentType::Auto; } }; struct TextField : LayoutProperty { + static constexpr const char * key = "text-field"; static std::string defaultValue() { return ""; } }; struct TextFont : LayoutProperty> { + static constexpr const char * key = "text-font"; static std::vector defaultValue() { return { "Open Sans Regular", "Arial Unicode MS Regular" }; } }; struct TextSize : LayoutProperty { + static constexpr const char * key = "text-size"; static float defaultValue() { return 16; } }; struct TextMaxWidth : LayoutProperty { + static constexpr const char * key = "text-max-width"; static float defaultValue() { return 10; } }; struct TextLineHeight : LayoutProperty { + static constexpr const char * key = "text-line-height"; static float defaultValue() { return 1.2; } }; struct TextLetterSpacing : LayoutProperty { + static constexpr const char * key = "text-letter-spacing"; static float defaultValue() { return 0; } }; struct TextJustify : LayoutProperty { + static constexpr const char * key = "text-justify"; static TextJustifyType defaultValue() { return TextJustifyType::Center; } }; struct TextAnchor : LayoutProperty { + static constexpr const char * key = "text-anchor"; static TextAnchorType defaultValue() { return TextAnchorType::Center; } }; struct TextMaxAngle : LayoutProperty { + static constexpr const char * key = "text-max-angle"; static float defaultValue() { return 45; } }; struct TextRotate : LayoutProperty { + static constexpr const char * key = "text-rotate"; static float defaultValue() { return 0; } }; struct TextPadding : LayoutProperty { + static constexpr const char * key = "text-padding"; static float defaultValue() { return 2; } }; struct TextKeepUpright : LayoutProperty { + static constexpr const char * key = "text-keep-upright"; static bool defaultValue() { return true; } }; struct TextTransform : LayoutProperty { + static constexpr const char * key = "text-transform"; static TextTransformType defaultValue() { return TextTransformType::None; } }; struct TextOffset : LayoutProperty> { + static constexpr const char * key = "text-offset"; static std::array defaultValue() { return {{ 0, 0 }}; } }; struct TextAllowOverlap : LayoutProperty { + static constexpr const char * key = "text-allow-overlap"; static bool defaultValue() { return false; } }; struct TextIgnorePlacement : LayoutProperty { + static constexpr const char * key = "text-ignore-placement"; static bool defaultValue() { return false; } }; struct TextOptional : LayoutProperty { + 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 10c0e1b244e..2a0047fecfc 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 86243e8a094..993f7b018ea 100644 --- a/src/mbgl/tile/geometry_tile.hpp +++ b/src/mbgl/tile/geometry_tile.hpp @@ -50,7 +50,7 @@ class GeometryTile : public Tile { class LayoutResult { public: - std::unordered_map> buckets; + std::unordered_map> buckets; std::unique_ptr featureIndex; std::unique_ptr tileData; uint64_t correlationID; @@ -59,7 +59,7 @@ class GeometryTile : public Tile { class PlacementResult { public: - std::unordered_map> buckets; + std::unordered_map> buckets; std::unique_ptr collisionTile; uint64_t correlationID; }; @@ -80,7 +80,7 @@ class GeometryTile : public Tile { uint64_t correlationID = 0; optional requestedConfig; - std::unordered_map> buckets; + std::unordered_map> buckets; std::unique_ptr featureIndex; std::unique_ptr data; }; diff --git a/src/mbgl/tile/geometry_tile_worker.cpp b/src/mbgl/tile/geometry_tile_worker.cpp index beebebd262d..169339f13fc 100644 --- a/src/mbgl/tile/geometry_tile_worker.cpp +++ b/src/mbgl/tile/geometry_tile_worker.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -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 symbolOrder; + for (auto it = layers->rbegin(); it != layers->rend(); it++) { + if ((*it)->is()) { + 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 parsed; - std::unordered_map> buckets; + std::unordered_map> symbolLayoutMap; + std::unordered_map> buckets; auto featureIndex = std::make_unique(); BucketParameters parameters { id, obsolete, *featureIndex, mode }; - for (auto i = layers->rbegin(); i != layers->rend(); i++) { + std::vector>> 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()) { - symbolLayouts.push_back(layer->as()->impl->createLayout(parameters, *geometryLayer)); + for (const auto& layer : group) { + featureIndex->addBucketLayerName(leader.getID(), layer->getID()); + } + + if (leader.is()) { + symbolLayoutMap.emplace(leader.getID(), + leader.as()->impl->createLayout(parameters, *geometryLayer, std::move(group))); } else { - std::unique_ptr bucket = layer->baseImpl->createBucket(parameters, *geometryLayer); - if (bucket->hasData()) { - buckets.emplace(layer->baseImpl->bucketName(), std::move(bucket)); + std::shared_ptr 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(*placementConfig); - std::unordered_map> buckets; + std::unordered_map> 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 = 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 eea897d3abb..d5751b405fe 100644 --- a/src/mbgl/util/color.cpp +++ b/src/mbgl/util/color.cpp @@ -1,4 +1,5 @@ #include +#include #include @@ -17,4 +18,12 @@ optional 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 00000000000..be5d65d4ce6 --- /dev/null +++ b/test/style/conversion/stringify.test.cpp @@ -0,0 +1,98 @@ +#include + +#include +#include +#include +#include + +#include +#include + +using namespace mbgl; +using namespace mbgl::style; +using namespace mbgl::style::conversion; + +template +std::string stringify(const T& t) { + rapidjson::StringBuffer s; + rapidjson::Writer 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 {{ 1, 2 }}), "[1.0,2.0]"); +} + +TEST(Stringify, Vector) { + ASSERT_EQ(stringify(std::vector {{ 1, 2 }}), "[1.0,2.0]"); +} + +TEST(Stringify, Map) { + ASSERT_EQ(stringify(std::unordered_map {{ "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({{0, 1}}, 2)), "{\"base\":2.0,\"stops\":[[0.0,1.0]]}"); +} + +TEST(Stringify, PropertyValue) { + ASSERT_EQ(stringify(PropertyValue(1)), "1.0"); + ASSERT_EQ(stringify(PropertyValue(Function({{0, 1}}, 2))), "{\"base\":2.0,\"stops\":[[0.0,1.0]]}"); +} + +TEST(Stringify, Layout) { + ASSERT_EQ(stringify(SymbolLayoutProperties()), "{}"); + + SymbolLayoutProperties layout; + layout.unevaluated.get() = true; + layout.unevaluated.get() = 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 00000000000..d74916cdc9a --- /dev/null +++ b/test/style/group_by_layout.test.cpp @@ -0,0 +1,44 @@ +#include + +#include +#include +#include +#include + +using namespace mbgl; +using namespace mbgl::style; + +TEST(GroupByLayout, Related) { + std::vector> layers; + layers.push_back(std::make_unique("a", "source")); + layers.push_back(std::make_unique("b", "source")); + auto result = groupByLayout(std::move(layers)); + ASSERT_EQ(1u, result.size()); + ASSERT_EQ(2u, result[0].size()); +} + +TEST(GroupByLayout, UnrelatedType) { + std::vector> layers; + layers.push_back(std::make_unique("background")); + layers.push_back(std::make_unique("circle", "source")); + auto result = groupByLayout(std::move(layers)); + ASSERT_EQ(2u, result.size()); +} + +TEST(GroupByLayout, UnrelatedFilter) { + std::vector> layers; + layers.push_back(std::make_unique("a", "source")); + layers.push_back(std::make_unique("b", "source")); + layers[0]->as()->setFilter(EqualsFilter()); + auto result = groupByLayout(std::move(layers)); + ASSERT_EQ(2u, result.size()); +} + +TEST(GroupByLayout, UnrelatedLayout) { + std::vector> layers; + layers.push_back(std::make_unique("a", "source")); + layers.push_back(std::make_unique("b", "source")); + layers[0]->as()->setLineCap(LineCapType::Square); + auto result = groupByLayout(std::move(layers)); + ASSERT_EQ(2u, result.size()); +}