diff options
author | John Firebaugh <john.firebaugh@gmail.com> | 2017-04-25 18:20:26 -0700 |
---|---|---|
committer | John Firebaugh <john.firebaugh@gmail.com> | 2017-05-12 11:26:27 -0700 |
commit | c2a5894f2dbe9982830066ab9347b059e6e7d845 (patch) | |
tree | c09363c2025b80265de195969ee56cc64e567e70 | |
parent | d3f23b83d42de8ef23ea1dbd8abfc6276009531f (diff) | |
download | qtlocation-mapboxgl-c2a5894f2dbe9982830066ab9347b059e6e7d845.tar.gz |
[core] Immutable Impls
124 files changed, 2590 insertions, 1485 deletions
diff --git a/cmake/core-files.cmake b/cmake/core-files.cmake index 5383f0ed7b..f83a0413b9 100644 --- a/cmake/core-files.cmake +++ b/cmake/core-files.cmake @@ -224,6 +224,8 @@ set(MBGL_CORE_FILES src/mbgl/renderer/render_symbol_layer.hpp src/mbgl/renderer/render_tile.cpp src/mbgl/renderer/render_tile.hpp + src/mbgl/renderer/style_diff.cpp + src/mbgl/renderer/style_diff.hpp src/mbgl/renderer/symbol_bucket.cpp src/mbgl/renderer/symbol_bucket.hpp src/mbgl/renderer/tile_parameters.hpp @@ -341,8 +343,6 @@ set(MBGL_CORE_FILES src/mbgl/style/source_observer.hpp src/mbgl/style/style.cpp src/mbgl/style/style.hpp - src/mbgl/style/tile_source_impl.cpp - src/mbgl/style/tile_source_impl.hpp src/mbgl/style/types.cpp src/mbgl/style/update_batch.hpp @@ -510,6 +510,7 @@ set(MBGL_CORE_FILES include/mbgl/util/geometry.hpp include/mbgl/util/ignore.hpp include/mbgl/util/image.hpp + include/mbgl/util/immutable.hpp include/mbgl/util/indexed_tuple.hpp include/mbgl/util/interpolate.hpp include/mbgl/util/logging.hpp @@ -559,6 +560,7 @@ set(MBGL_CORE_FILES src/mbgl/util/io.cpp src/mbgl/util/io.hpp src/mbgl/util/logging.cpp + src/mbgl/util/longest_common_subsequence.hpp src/mbgl/util/mapbox.cpp src/mbgl/util/mapbox.hpp src/mbgl/util/mat2.cpp diff --git a/include/mbgl/style/layer.hpp b/include/mbgl/style/layer.hpp index 56f2c48fa7..10176879c5 100644 --- a/include/mbgl/style/layer.hpp +++ b/include/mbgl/style/layer.hpp @@ -2,6 +2,7 @@ #include <mbgl/util/noncopyable.hpp> #include <mbgl/util/any.hpp> +#include <mbgl/util/immutable.hpp> #include <mbgl/style/layer_type.hpp> #include <mbgl/style/types.hpp> @@ -19,6 +20,7 @@ class RasterLayer; class BackgroundLayer; class CustomLayer; class FillExtrusionLayer; +class LayerObserver; /** * The runtime representation of a [layer](https://www.mapbox.com/mapbox-gl-style-spec/#layers) from the Mapbox Style @@ -38,15 +40,6 @@ class FillExtrusionLayer; */ class Layer : public mbgl::util::noncopyable { public: - class Impl; - -protected: - - const LayerType type; - Layer(LayerType, std::unique_ptr<Impl>); - -public: - virtual ~Layer(); // Check whether this layer is of the given subtype. @@ -78,7 +71,7 @@ public: // template <class V> auto accept(V&& visitor) { - switch (type) { + switch (getType()) { case LayerType::Fill: return visitor(*as<FillLayer>()); case LayerType::Line: @@ -98,20 +91,30 @@ public: } } + LayerType getType() const; const std::string& getID() const; // Visibility VisibilityType getVisibility() const; - void setVisibility(VisibilityType); + virtual void setVisibility(VisibilityType) = 0; // Zoom range float getMinZoom() const; - void setMinZoom(float) const; float getMaxZoom() const; - void setMaxZoom(float) const; + virtual void setMinZoom(float) = 0; + virtual void setMaxZoom(float) = 0; // Private implementation - const std::unique_ptr<Impl> baseImpl; + class Impl; + Immutable<Impl> baseImpl; + + Layer(Immutable<Impl>); + + // 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; + + LayerObserver* observer = nullptr; + void setObserver(LayerObserver*); // For use in SDK bindings, which store a reference to a platform-native peer // object here, so that separately-obtained references to this object share diff --git a/include/mbgl/style/layers/background_layer.hpp b/include/mbgl/style/layers/background_layer.hpp index 6604a868f3..63708a449f 100644 --- a/include/mbgl/style/layers/background_layer.hpp +++ b/include/mbgl/style/layers/background_layer.hpp @@ -19,6 +19,13 @@ public: BackgroundLayer(const std::string& layerID); ~BackgroundLayer() final; + // Visibility + void setVisibility(VisibilityType) final; + + // Zoom range + void setMinZoom(float) final; + void setMaxZoom(float) final; + // Paint properties static PropertyValue<Color> getDefaultBackgroundColor(); @@ -42,15 +49,16 @@ public: // Private implementation class Impl; - Impl* const impl; + const Impl& impl() const; - BackgroundLayer(const Impl&); - BackgroundLayer(const BackgroundLayer&) = delete; + Mutable<Impl> mutableImpl() const; + BackgroundLayer(Immutable<Impl>); + std::unique_ptr<Layer> cloneRef(const std::string& id) const final; }; template <> inline bool Layer::is<BackgroundLayer>() const { - return type == LayerType::Background; + return getType() == LayerType::Background; } } // namespace style diff --git a/include/mbgl/style/layers/circle_layer.hpp b/include/mbgl/style/layers/circle_layer.hpp index 3a3723249f..f40c507e28 100644 --- a/include/mbgl/style/layers/circle_layer.hpp +++ b/include/mbgl/style/layers/circle_layer.hpp @@ -27,6 +27,13 @@ public: void setFilter(const Filter&); const Filter& getFilter() const; + // Visibility + void setVisibility(VisibilityType) final; + + // Zoom range + void setMinZoom(float) final; + void setMaxZoom(float) final; + // Paint properties static DataDrivenPropertyValue<float> getDefaultCircleRadius(); @@ -92,15 +99,16 @@ public: // Private implementation class Impl; - Impl* const impl; + const Impl& impl() const; - CircleLayer(const Impl&); - CircleLayer(const CircleLayer&) = delete; + Mutable<Impl> mutableImpl() const; + CircleLayer(Immutable<Impl>); + std::unique_ptr<Layer> cloneRef(const std::string& id) const final; }; template <> inline bool Layer::is<CircleLayer>() const { - return type == LayerType::Circle; + return getType() == LayerType::Circle; } } // namespace style diff --git a/include/mbgl/style/layers/custom_layer.hpp b/include/mbgl/style/layers/custom_layer.hpp index edc8d43f89..79a353b047 100644 --- a/include/mbgl/style/layers/custom_layer.hpp +++ b/include/mbgl/style/layers/custom_layer.hpp @@ -55,12 +55,21 @@ public: void* context); ~CustomLayer() final; + // Visibility + void setVisibility(VisibilityType) final; + + // Zoom range + void setMinZoom(float) final; + void setMaxZoom(float) final; + // Private implementation class Impl; - Impl* impl; + const Impl& impl() const; + + Mutable<Impl> mutableImpl() const; + std::unique_ptr<Layer> cloneRef(const std::string& id) const final; - CustomLayer(const Impl&); CustomLayer(const CustomLayer&) = delete; }; diff --git a/include/mbgl/style/layers/fill_extrusion_layer.hpp b/include/mbgl/style/layers/fill_extrusion_layer.hpp index 1f79f87fac..bc6890e82f 100644 --- a/include/mbgl/style/layers/fill_extrusion_layer.hpp +++ b/include/mbgl/style/layers/fill_extrusion_layer.hpp @@ -27,6 +27,13 @@ public: void setFilter(const Filter&); const Filter& getFilter() const; + // Visibility + void setVisibility(VisibilityType) final; + + // Zoom range + void setMinZoom(float) final; + void setMaxZoom(float) final; + // Paint properties static PropertyValue<float> getDefaultFillExtrusionOpacity(); @@ -74,15 +81,16 @@ public: // Private implementation class Impl; - Impl* const impl; + const Impl& impl() const; - FillExtrusionLayer(const Impl&); - FillExtrusionLayer(const FillExtrusionLayer&) = delete; + Mutable<Impl> mutableImpl() const; + FillExtrusionLayer(Immutable<Impl>); + std::unique_ptr<Layer> cloneRef(const std::string& id) const final; }; template <> inline bool Layer::is<FillExtrusionLayer>() const { - return type == LayerType::FillExtrusion; + return getType() == LayerType::FillExtrusion; } } // namespace style diff --git a/include/mbgl/style/layers/fill_layer.hpp b/include/mbgl/style/layers/fill_layer.hpp index 8371ff7a8f..3d08e75a1c 100644 --- a/include/mbgl/style/layers/fill_layer.hpp +++ b/include/mbgl/style/layers/fill_layer.hpp @@ -27,6 +27,13 @@ public: void setFilter(const Filter&); const Filter& getFilter() const; + // Visibility + void setVisibility(VisibilityType) final; + + // Zoom range + void setMinZoom(float) final; + void setMaxZoom(float) final; + // Paint properties static PropertyValue<bool> getDefaultFillAntialias(); @@ -74,15 +81,16 @@ public: // Private implementation class Impl; - Impl* const impl; + const Impl& impl() const; - FillLayer(const Impl&); - FillLayer(const FillLayer&) = delete; + Mutable<Impl> mutableImpl() const; + FillLayer(Immutable<Impl>); + std::unique_ptr<Layer> cloneRef(const std::string& id) const final; }; template <> inline bool Layer::is<FillLayer>() const { - return type == LayerType::Fill; + return getType() == LayerType::Fill; } } // namespace style diff --git a/include/mbgl/style/layers/layer.hpp.ejs b/include/mbgl/style/layers/layer.hpp.ejs index 59d7cd6415..033ae88956 100644 --- a/include/mbgl/style/layers/layer.hpp.ejs +++ b/include/mbgl/style/layers/layer.hpp.ejs @@ -44,6 +44,13 @@ public: <% } -%> <% } -%> + // Visibility + void setVisibility(VisibilityType) final; + + // Zoom range + void setMinZoom(float) final; + void setMaxZoom(float) final; + <% if (layoutProperties.length) { -%> // Layout properties @@ -67,15 +74,16 @@ public: // Private implementation class Impl; - Impl* const impl; + const Impl& impl() const; - <%- camelize(type) %>Layer(const Impl&); - <%- camelize(type) %>Layer(const <%- camelize(type) %>Layer&) = delete; + Mutable<Impl> mutableImpl() const; + <%- camelize(type) %>Layer(Immutable<Impl>); + std::unique_ptr<Layer> cloneRef(const std::string& id) const final; }; template <> inline bool Layer::is<<%- camelize(type) %>Layer>() const { - return type == LayerType::<%- camelize(type) %>; + return getType() == LayerType::<%- camelize(type) %>; } } // namespace style diff --git a/include/mbgl/style/layers/line_layer.hpp b/include/mbgl/style/layers/line_layer.hpp index a5f08e553c..6000839d1c 100644 --- a/include/mbgl/style/layers/line_layer.hpp +++ b/include/mbgl/style/layers/line_layer.hpp @@ -29,6 +29,13 @@ public: void setFilter(const Filter&); const Filter& getFilter() const; + // Visibility + void setVisibility(VisibilityType) final; + + // Zoom range + void setMinZoom(float) final; + void setMaxZoom(float) final; + // Layout properties static PropertyValue<LineCapType> getDefaultLineCap(); @@ -112,15 +119,16 @@ public: // Private implementation class Impl; - Impl* const impl; + const Impl& impl() const; - LineLayer(const Impl&); - LineLayer(const LineLayer&) = delete; + Mutable<Impl> mutableImpl() const; + LineLayer(Immutable<Impl>); + std::unique_ptr<Layer> cloneRef(const std::string& id) const final; }; template <> inline bool Layer::is<LineLayer>() const { - return type == LayerType::Line; + return getType() == LayerType::Line; } } // namespace style diff --git a/include/mbgl/style/layers/raster_layer.hpp b/include/mbgl/style/layers/raster_layer.hpp index c0351da5d0..ad9a68f1b0 100644 --- a/include/mbgl/style/layers/raster_layer.hpp +++ b/include/mbgl/style/layers/raster_layer.hpp @@ -22,6 +22,13 @@ public: // Source const std::string& getSourceID() const; + // Visibility + void setVisibility(VisibilityType) final; + + // Zoom range + void setMinZoom(float) final; + void setMaxZoom(float) final; + // Paint properties static PropertyValue<float> getDefaultRasterOpacity(); @@ -69,15 +76,16 @@ public: // Private implementation class Impl; - Impl* const impl; + const Impl& impl() const; - RasterLayer(const Impl&); - RasterLayer(const RasterLayer&) = delete; + Mutable<Impl> mutableImpl() const; + RasterLayer(Immutable<Impl>); + std::unique_ptr<Layer> cloneRef(const std::string& id) const final; }; template <> inline bool Layer::is<RasterLayer>() const { - return type == LayerType::Raster; + return getType() == LayerType::Raster; } } // namespace style diff --git a/include/mbgl/style/layers/symbol_layer.hpp b/include/mbgl/style/layers/symbol_layer.hpp index ea6bda55d7..e7df5a92ae 100644 --- a/include/mbgl/style/layers/symbol_layer.hpp +++ b/include/mbgl/style/layers/symbol_layer.hpp @@ -29,6 +29,13 @@ public: void setFilter(const Filter&); const Filter& getFilter() const; + // Visibility + void setVisibility(VisibilityType) final; + + // Zoom range + void setMinZoom(float) final; + void setMaxZoom(float) final; + // Layout properties static PropertyValue<SymbolPlacementType> getDefaultSymbolPlacement(); @@ -256,15 +263,16 @@ public: // Private implementation class Impl; - Impl* const impl; + const Impl& impl() const; - SymbolLayer(const Impl&); - SymbolLayer(const SymbolLayer&) = delete; + Mutable<Impl> mutableImpl() const; + SymbolLayer(Immutable<Impl>); + std::unique_ptr<Layer> cloneRef(const std::string& id) const final; }; template <> inline bool Layer::is<SymbolLayer>() const { - return type == LayerType::Symbol; + return getType() == LayerType::Symbol; } } // namespace style diff --git a/include/mbgl/style/light.hpp b/include/mbgl/style/light.hpp index 8212a58dcc..c82792b28d 100644 --- a/include/mbgl/style/light.hpp +++ b/include/mbgl/style/light.hpp @@ -1,20 +1,19 @@ // This file is generated. Do not edit. #pragma once + #include <mbgl/style/property_value.hpp> #include <mbgl/style/transition_options.hpp> #include <mbgl/style/types.hpp> - -#include <memory> +#include <mbgl/util/immutable.hpp> namespace mbgl { namespace style { +class LightObserver; + class Light { public: - - class Impl; - Light(); ~Light(); @@ -42,7 +41,12 @@ public: void setIntensityTransition(const TransitionOptions&); TransitionOptions getIntensityTransition() const; - std::shared_ptr<Impl> impl; + class Impl; + Immutable<Impl> impl; + Mutable<Impl> mutableImpl() const; + + LightObserver* observer = nullptr; + void setObserver(LightObserver*); }; } // namespace style diff --git a/include/mbgl/style/light.hpp.ejs b/include/mbgl/style/light.hpp.ejs index 601e0bd410..adc5b651e3 100644 --- a/include/mbgl/style/light.hpp.ejs +++ b/include/mbgl/style/light.hpp.ejs @@ -4,20 +4,19 @@ // This file is generated. Do not edit. #pragma once + #include <mbgl/style/property_value.hpp> #include <mbgl/style/transition_options.hpp> #include <mbgl/style/types.hpp> - -#include <memory> +#include <mbgl/util/immutable.hpp> namespace mbgl { namespace style { +class LightObserver; + class Light { public: - - class Impl; - Light(); ~Light(); @@ -29,7 +28,12 @@ public: TransitionOptions get<%- camelize(property.name) %>Transition() const; <% } -%> - std::shared_ptr<Impl> impl; + class Impl; + Immutable<Impl> impl; + Mutable<Impl> mutableImpl() const; + + LightObserver* observer = nullptr; + void setObserver(LightObserver*); }; } // namespace style diff --git a/include/mbgl/style/source.hpp b/include/mbgl/style/source.hpp index 4c82e472a6..d19dfd4e36 100644 --- a/include/mbgl/style/source.hpp +++ b/include/mbgl/style/source.hpp @@ -1,19 +1,25 @@ #pragma once -#include <mbgl/util/feature.hpp> #include <mbgl/util/noncopyable.hpp> #include <mbgl/util/optional.hpp> -#include <mbgl/util/range.hpp> #include <mbgl/util/any.hpp> +#include <mbgl/util/immutable.hpp> #include <mbgl/style/types.hpp> #include <memory> #include <string> -#include <vector> namespace mbgl { + +class FileSource; + namespace style { +class VectorSource; +class RasterSource; +class GeoJSONSource; +class SourceObserver; + /** * The runtime representation of a [source](https://www.mapbox.com/mapbox-gl-style-spec/#sources) from the Mapbox Style * Specification. @@ -49,21 +55,28 @@ public: return is<T>() ? reinterpret_cast<const T*>(this) : nullptr; } + SourceType getType() const; const std::string& getID() const; optional<std::string> getAttribution() const; // Private implementation class Impl; - const std::unique_ptr<Impl> baseImpl; + Immutable<Impl> baseImpl; + + Source(Immutable<Impl>); + + void setObserver(SourceObserver*); + SourceObserver* observer = nullptr; + + virtual void loadDescription(FileSource&) = 0; + void dumpDebugLogs() const; + + bool loaded = false; // For use in SDK bindings, which store a reference to a platform-native peer // object here, so that separately-obtained references to this object share // identical platform-native peers. any peer; - -protected: - const SourceType type; - Source(SourceType, std::unique_ptr<Impl>); }; } // namespace style diff --git a/include/mbgl/style/sources/geojson_source.hpp b/include/mbgl/style/sources/geojson_source.hpp index 5b39d7821b..2dcfec51aa 100644 --- a/include/mbgl/style/sources/geojson_source.hpp +++ b/include/mbgl/style/sources/geojson_source.hpp @@ -5,6 +5,9 @@ #include <mbgl/util/optional.hpp> namespace mbgl { + +class AsyncRequest; + namespace style { struct GeoJSONOptions { @@ -22,21 +25,26 @@ struct GeoJSONOptions { class GeoJSONSource : public Source { public: GeoJSONSource(const std::string& id, const GeoJSONOptions& = {}); + ~GeoJSONSource() final; void setURL(const std::string& url); void setGeoJSON(const GeoJSON&); optional<std::string> getURL() const; - // Private implementation - class Impl; - Impl* const impl; + const Impl& impl() const; + + void loadDescription(FileSource&) final; + +private: + optional<std::string> url; + std::unique_ptr<AsyncRequest> req; }; template <> inline bool Source::is<GeoJSONSource>() const { - return type == SourceType::GeoJSON; + return getType() == SourceType::GeoJSON; } } // namespace style diff --git a/include/mbgl/style/sources/raster_source.hpp b/include/mbgl/style/sources/raster_source.hpp index 395f25e51d..7f23a7ca4b 100644 --- a/include/mbgl/style/sources/raster_source.hpp +++ b/include/mbgl/style/sources/raster_source.hpp @@ -5,23 +5,34 @@ #include <mbgl/util/variant.hpp> namespace mbgl { + +class AsyncRequest; + namespace style { class RasterSource : public Source { public: RasterSource(std::string id, variant<std::string, Tileset> urlOrTileset, uint16_t tileSize); + ~RasterSource() final; + const variant<std::string, Tileset>& getURLOrTileset() const; optional<std::string> getURL() const; - // Private implementation + uint16_t getTileSize() const; class Impl; - Impl* const impl; + const Impl& impl() const; + + void loadDescription(FileSource&) final; + +private: + const variant<std::string, Tileset> urlOrTileset; + std::unique_ptr<AsyncRequest> req; }; template <> inline bool Source::is<RasterSource>() const { - return type == SourceType::Raster; + return getType() == SourceType::Raster; } } // namespace style diff --git a/include/mbgl/style/sources/vector_source.hpp b/include/mbgl/style/sources/vector_source.hpp index 8626ce160a..6f16974b40 100644 --- a/include/mbgl/style/sources/vector_source.hpp +++ b/include/mbgl/style/sources/vector_source.hpp @@ -5,23 +5,32 @@ #include <mbgl/util/variant.hpp> namespace mbgl { + +class AsyncRequest; + namespace style { class VectorSource : public Source { public: VectorSource(std::string id, variant<std::string, Tileset> urlOrTileset); + ~VectorSource() final; + const variant<std::string, Tileset>& getURLOrTileset() const; optional<std::string> getURL() const; - // Private implementation - class Impl; - Impl* const impl; + const Impl& impl() const; + + void loadDescription(FileSource&) final; + +private: + const variant<std::string, Tileset> urlOrTileset; + std::unique_ptr<AsyncRequest> req; }; template <> inline bool Source::is<VectorSource>() const { - return type == SourceType::Vector; + return getType() == SourceType::Vector; } } // namespace style diff --git a/include/mbgl/util/immutable.hpp b/include/mbgl/util/immutable.hpp new file mode 100644 index 0000000000..1d6ff4079a --- /dev/null +++ b/include/mbgl/util/immutable.hpp @@ -0,0 +1,127 @@ +#pragma once + +#include <memory> + +namespace mbgl { + +/** + * `Mutable<T>` is a non-nullable uniquely owning reference to a `T`. It can be efficiently converted + * to `Immutable<T>`. + * + * The lifecycle of `Mutable<T>` and `Immutable<T>` is as follows: + * + * 1. Create a `Mutable<T>` using `makeMutable(...)` + * 2. Mutate it freely + * 3. When you're ready to freeze its state and enable safe cross-thread sharing, move assign or + * move construct it to `Immutable<T>` + * + * The reason that `Mutable<T>` exists, rather than simply using a `std::unique_ptr<T>`, is to take advantage + * of the underlying single-allocation optimization provided by `std::make_shared`. + */ +template <class T> +class Mutable { +public: + Mutable(Mutable&&) = default; + Mutable& operator=(Mutable&&) = default; + + Mutable(const Mutable&) = delete; + Mutable& operator=(const Mutable&) = delete; + + T* get() { return ptr.get(); } + T* operator->() { return ptr.get(); } + T& operator*() { return *ptr; } + +private: + Mutable(std::shared_ptr<T>&& s) + : ptr(std::move(s)) {} + + std::shared_ptr<T> ptr; + + template <class S> friend class Immutable; + template <class S, class... Args> friend Mutable<S> makeMutable(Args&&...); +}; + +template <class T, class... Args> +Mutable<T> makeMutable(Args&&... args) { + return Mutable<T>(std::make_shared<T>(std::forward<Args>(args)...)); +} + +/** + * `Immutable<T>` is a non-nullable shared reference to a `const T`. Construction requires + * a transfer of unique ownership from a `Mutable<T>`; once constructed it has the same behavior + * as `std::shared_ptr<const T>` but with better indication of intent. + * + * Normally one should not share state between threads because it's difficult to verify the + * absence of read/write data races. `Immutable` provides a guarantee that no writes are + * possible, and instances therefore can be freely transferred and shared between threads. + */ +template <class T> +class Immutable { +public: + template <class S> + Immutable(Mutable<S>&& s) + : ptr(std::const_pointer_cast<const S>(std::move(s.ptr))) {} + + template <class S> + Immutable(Immutable<S>&& s) + : ptr(std::move(s.ptr)) {} + + template <class S> + Immutable(const Immutable<S>& s) + : ptr(s.ptr) {} + + template <class S> + Immutable& operator=(Mutable<S>&& s) { + ptr = std::const_pointer_cast<const S>(std::move(s.ptr)); + return *this; + } + + template <class S> + Immutable& operator=(Immutable<S>&& s) { + ptr = std::move(s.ptr); + return *this; + } + + template <class S> + Immutable& operator=(const Immutable<S>& s) { + ptr = s.ptr; + return *this; + } + + const T* get() const { return ptr.get(); } + const T* operator->() const { return ptr.get(); } + const T& operator*() const { return *ptr; } + + friend bool operator==(const Immutable<T>& lhs, const Immutable<T>& rhs) { + return lhs.ptr == rhs.ptr; + } + + friend bool operator!=(const Immutable<T>& lhs, const Immutable<T>& rhs) { + return lhs.ptr != rhs.ptr; + } + +private: + Immutable(std::shared_ptr<const T>&& s) + : ptr(std::move(s)) {} + + std::shared_ptr<const T> ptr; + + template <class S> friend class Immutable; + template <class S> friend class EnableImmutableFromThis; + template <class S, class U> friend Immutable<S> staticImmutableCast(const Immutable<U>&); +}; + +template <class T> +class EnableImmutableFromThis : public std::enable_shared_from_this<const T> { +public: + Immutable<T> immutableFromThis() const { + return Immutable<T>(this->shared_from_this()); + } +}; + +template <class S, class U> +Immutable<S> staticImmutableCast(const Immutable<U>& u) { + return Immutable<S>(std::static_pointer_cast<const S>(u.ptr)); +} + +} // namespace mbgl diff --git a/include/mbgl/util/tileset.hpp b/include/mbgl/util/tileset.hpp index 1f28a5039a..1256e9fe96 100644 --- a/include/mbgl/util/tileset.hpp +++ b/include/mbgl/util/tileset.hpp @@ -18,6 +18,11 @@ public: Scheme scheme = Scheme::XYZ; // TileJSON also includes center, zoom, and bounds, but they are not used by mbgl. + + friend bool operator==(const Tileset& lhs, const Tileset& rhs) { + return std::tie(lhs.tiles, lhs.zoomRange, lhs.attribution, lhs.scheme) + == std::tie(rhs.tiles, rhs.zoomRange, rhs.attribution, rhs.scheme); + } }; } // namespace mbgl diff --git a/mapbox-gl-js b/mapbox-gl-js -Subproject 8b085a211579d417ad8b3d58bc502c4ffbdfc2e +Subproject 94619177e52614564496c9e5bdd7751fc8ee426 diff --git a/platform/default/mbgl/storage/offline_download.cpp b/platform/default/mbgl/storage/offline_download.cpp index 5a487b3534..235baac12c 100644 --- a/platform/default/mbgl/storage/offline_download.cpp +++ b/platform/default/mbgl/storage/offline_download.cpp @@ -5,8 +5,9 @@ #include <mbgl/storage/response.hpp> #include <mbgl/storage/http_file_source.hpp> #include <mbgl/style/parser.hpp> -#include <mbgl/style/sources/geojson_source_impl.hpp> -#include <mbgl/style/tile_source_impl.hpp> +#include <mbgl/style/sources/vector_source.hpp> +#include <mbgl/style/sources/raster_source.hpp> +#include <mbgl/style/sources/geojson_source.hpp> #include <mbgl/style/conversion/json.hpp> #include <mbgl/style/conversion/tileset.hpp> #include <mbgl/text/glyph.hpp> @@ -19,6 +20,8 @@ namespace mbgl { +using namespace style; + OfflineDownload::OfflineDownload(int64_t id_, OfflineRegionDefinition&& definition_, OfflineDatabase& offlineDatabase_, @@ -71,15 +74,9 @@ OfflineRegionStatus OfflineDownload::getStatus() const { result.requiredResourceCountIsPrecise = true; for (const auto& source : parser.sources) { - SourceType type = source->baseImpl->type; - - switch (type) { - case SourceType::Vector: - case SourceType::Raster: { - auto* tileSource = static_cast<style::TileSourceImpl*>(source->baseImpl.get()); - const variant<std::string, Tileset>& urlOrTileset = tileSource->getURLOrTileset(); - const uint16_t tileSize = tileSource->getTileSize(); + SourceType type = source->getType(); + auto handleTiledSource = [&] (const variant<std::string, Tileset>& urlOrTileset, const uint16_t tileSize) { if (urlOrTileset.is<Tileset>()) { result.requiredResourceCount += definition.tileCover(type, tileSize, urlOrTileset.get<Tileset>().zoomRange).size(); @@ -98,11 +95,23 @@ OfflineRegionStatus OfflineDownload::getStatus() const { result.requiredResourceCountIsPrecise = false; } } + }; + + switch (type) { + case SourceType::Vector: { + const auto& vectorSource = *source->as<VectorSource>(); + handleTiledSource(vectorSource.getURLOrTileset(), util::tileSize); + break; + } + + case SourceType::Raster: { + const auto& rasterSource = *source->as<RasterSource>(); + handleTiledSource(rasterSource.getURLOrTileset(), rasterSource.getTileSize()); break; } case SourceType::GeoJSON: { - auto* geojsonSource = source->as<style::GeoJSONSource>(); + auto* geojsonSource = source->as<GeoJSONSource>(); if (geojsonSource->getURL()) { result.requiredResourceCount += 1; } @@ -137,16 +146,9 @@ void OfflineDownload::activateDownload() { parser.parse(*styleResponse.data); for (const auto& source : parser.sources) { - SourceType type = source->baseImpl->type; - - switch (type) { - case SourceType::Vector: - case SourceType::Raster: { - const style::TileSourceImpl* tileSource = - static_cast<style::TileSourceImpl*>(source->baseImpl.get()); - const variant<std::string, Tileset>& urlOrTileset = tileSource->getURLOrTileset(); - const uint16_t tileSize = tileSource->getTileSize(); + SourceType type = source->getType(); + auto handleTiledSource = [&] (const variant<std::string, Tileset>& urlOrTileset, const uint16_t tileSize) { if (urlOrTileset.is<Tileset>()) { queueTiles(type, tileSize, urlOrTileset.get<Tileset>()); } else { @@ -169,12 +171,23 @@ void OfflineDownload::activateDownload() { } }); } + }; + + switch (type) { + case SourceType::Vector: { + const auto& vectorSource = *source->as<VectorSource>(); + handleTiledSource(vectorSource.getURLOrTileset(), util::tileSize); + break; + } + + case SourceType::Raster: { + const auto& rasterSource = *source->as<RasterSource>(); + handleTiledSource(rasterSource.getURLOrTileset(), rasterSource.getTileSize()); break; } case SourceType::GeoJSON: { - auto* geojsonSource = - static_cast<style::GeoJSONSource::Impl*>(source->baseImpl.get()); + const auto* geojsonSource = static_cast<const GeoJSONSource*>(source.get()); if (geojsonSource->getURL()) { queueResource(Resource::source(*geojsonSource->getURL())); diff --git a/src/mbgl/annotation/annotation_source.cpp b/src/mbgl/annotation/annotation_source.cpp index 9956140179..b0b8bae6cc 100644 --- a/src/mbgl/annotation/annotation_source.cpp +++ b/src/mbgl/annotation/annotation_source.cpp @@ -7,19 +7,23 @@ namespace mbgl { using namespace style; AnnotationSource::AnnotationSource() - : Source(SourceType::Annotations, std::make_unique<Impl>(*this)) { + : Source(makeMutable<Impl>()) { } -AnnotationSource::Impl::Impl(Source& base_) - : Source::Impl(SourceType::Annotations, AnnotationManager::SourceID, base_) { +AnnotationSource::Impl::Impl() + : Source::Impl(SourceType::Annotations, AnnotationManager::SourceID) { } -void AnnotationSource::Impl::loadDescription(FileSource&) { +void AnnotationSource::loadDescription(FileSource&) { loaded = true; } +optional<std::string> AnnotationSource::Impl::getAttribution() const { + return {}; +} + std::unique_ptr<RenderSource> AnnotationSource::Impl::createRenderSource() const { - return std::make_unique<RenderAnnotationSource>(*this); + return std::make_unique<RenderAnnotationSource>(staticImmutableCast<AnnotationSource::Impl>(immutableFromThis())); } } // namespace mbgl diff --git a/src/mbgl/annotation/annotation_source.hpp b/src/mbgl/annotation/annotation_source.hpp index 46c9564443..56d91f5501 100644 --- a/src/mbgl/annotation/annotation_source.hpp +++ b/src/mbgl/annotation/annotation_source.hpp @@ -10,13 +10,19 @@ public: AnnotationSource(); class Impl; + const Impl& impl() const; + +private: + void loadDescription(FileSource&) final; + + Mutable<Impl> mutableImpl() const; }; class AnnotationSource::Impl : public style::Source::Impl { public: - Impl(Source&); + Impl(); - void loadDescription(FileSource&) final; + optional<std::string> getAttribution() const final; std::unique_ptr<RenderSource> createRenderSource() const final; }; diff --git a/src/mbgl/annotation/render_annotation_source.cpp b/src/mbgl/annotation/render_annotation_source.cpp index a62d2d51d3..718f7a16e6 100644 --- a/src/mbgl/annotation/render_annotation_source.cpp +++ b/src/mbgl/annotation/render_annotation_source.cpp @@ -9,11 +9,15 @@ namespace mbgl { using namespace style; -RenderAnnotationSource::RenderAnnotationSource(const AnnotationSource::Impl& impl_) +RenderAnnotationSource::RenderAnnotationSource(Immutable<AnnotationSource::Impl> impl_) : RenderSource(impl_) { tilePyramid.setObserver(this); } +const AnnotationSource::Impl& RenderAnnotationSource::impl() const { + return static_cast<const AnnotationSource::Impl&>(*baseImpl); +} + bool RenderAnnotationSource::isLoaded() const { return tilePyramid.isLoaded(); } diff --git a/src/mbgl/annotation/render_annotation_source.hpp b/src/mbgl/annotation/render_annotation_source.hpp index 9ae9340477..539e73b57e 100644 --- a/src/mbgl/annotation/render_annotation_source.hpp +++ b/src/mbgl/annotation/render_annotation_source.hpp @@ -8,7 +8,7 @@ namespace mbgl { class RenderAnnotationSource : public RenderSource { public: - RenderAnnotationSource(const AnnotationSource::Impl&); + RenderAnnotationSource(Immutable<AnnotationSource::Impl>); bool isLoaded() const final; @@ -47,6 +47,8 @@ public: void dumpDebugLogs() const final; private: + const AnnotationSource::Impl& impl() const; + TilePyramid tilePyramid; }; diff --git a/src/mbgl/geometry/feature_index.cpp b/src/mbgl/geometry/feature_index.cpp index 8251e4d03a..451943ff26 100644 --- a/src/mbgl/geometry/feature_index.cpp +++ b/src/mbgl/geometry/feature_index.cpp @@ -61,7 +61,7 @@ static int16_t getAdditionalQueryRadius(const RenderedQueryOptions& queryOptions // Determine the additional radius needed factoring in property functions float additionalRadius = 0; auto getQueryRadius = [&](const RenderLayer& layer) { - auto bucket = tile.getBucket(layer); + auto bucket = tile.getBucket(*layer.baseImpl); if (bucket) { additionalRadius = std::max(additionalRadius, bucket->getQueryRadius(layer) * pixelsToTileUnits); } diff --git a/src/mbgl/layout/symbol_layout.cpp b/src/mbgl/layout/symbol_layout.cpp index aa91eb1688..fe857fec7e 100644 --- a/src/mbgl/layout/symbol_layout.cpp +++ b/src/mbgl/layout/symbol_layout.cpp @@ -50,11 +50,11 @@ SymbolLayout::SymbolLayout(const BucketParameters& parameters, mode(parameters.mode), tileSize(util::tileSize * overscaling), tilePixelRatio(float(util::EXTENT) / tileSize), - textSize(layers.at(0)->as<RenderSymbolLayer>()->impl->layout.unevaluated.get<TextSize>()), - iconSize(layers.at(0)->as<RenderSymbolLayer>()->impl->layout.unevaluated.get<IconSize>()) + textSize(layers.at(0)->as<RenderSymbolLayer>()->impl().layout.unevaluated.get<TextSize>()), + iconSize(layers.at(0)->as<RenderSymbolLayer>()->impl().layout.unevaluated.get<IconSize>()) { - const SymbolLayer::Impl& leader = *layers.at(0)->as<RenderSymbolLayer>()->impl; + const SymbolLayer::Impl& leader = layers.at(0)->as<RenderSymbolLayer>()->impl(); layout = leader.layout.evaluate(PropertyEvaluationParameters(zoom)); diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index c7daf5ac09..4ef422a2de 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -402,7 +402,7 @@ void Map::Impl::loadStyleJSON(const std::string& json) { map.setPitch(map.getDefaultPitch()); } - onUpdate(Update::Classes | Update::AnnotationStyle); + onUpdate(Update::AnnotationStyle); } std::string Map::getStyleURL() const { @@ -919,7 +919,7 @@ void Map::addLayer(std::unique_ptr<Layer> layer, const optional<std::string>& be BackendScope guard(impl->backend); impl->style->addLayer(std::move(layer), before); - impl->onUpdate(Update::Classes); + impl->onUpdate(Update::Repaint); } std::unique_ptr<Layer> Map::removeLayer(const std::string& id) { diff --git a/src/mbgl/map/update.hpp b/src/mbgl/map/update.hpp index 5e87515eac..29f2583f7c 100644 --- a/src/mbgl/map/update.hpp +++ b/src/mbgl/map/update.hpp @@ -8,7 +8,6 @@ enum class Update { Nothing = 0, Repaint = 1 << 0, Classes = 1 << 2, - RecalculateStyle = 1 << 3, AnnotationStyle = 1 << 6, AnnotationData = 1 << 7 }; diff --git a/src/mbgl/renderer/group_by_layout.cpp b/src/mbgl/renderer/group_by_layout.cpp index df1eb7c7dd..3b02727ff8 100644 --- a/src/mbgl/renderer/group_by_layout.cpp +++ b/src/mbgl/renderer/group_by_layout.cpp @@ -19,13 +19,13 @@ std::string layoutKey(const RenderLayer& layer) { 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.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(); diff --git a/src/mbgl/renderer/painter.cpp b/src/mbgl/renderer/painter.cpp index eed3bfcd8b..51770b07b1 100644 --- a/src/mbgl/renderer/painter.cpp +++ b/src/mbgl/renderer/painter.cpp @@ -144,7 +144,7 @@ void Painter::render(const Style& style, const FrameData& frame_, View& view, Sp spriteAtlas = style.spriteAtlas.get(); lineAtlas = style.lineAtlas.get(); - evaluatedLight = style.getRenderLight()->getEvaluated(); + evaluatedLight = style.getRenderLight().getEvaluated(); RenderData renderData = style.getRenderData(frame.debugOptions, state.getAngle()); const std::vector<RenderItem>& order = renderData.order; @@ -180,7 +180,7 @@ void Painter::render(const Style& style, const FrameData& frame_, View& view, Sp for (const auto& item : order) { for (const auto& tileRef : item.tiles) { - const auto& bucket = tileRef.get().tile.getBucket(item.layer); + const auto& bucket = tileRef.get().tile.getBucket(*item.layer.baseImpl); if (bucket && bucket->needsUpload()) { bucket->upload(context); } @@ -309,7 +309,7 @@ void Painter::renderPass(PaintParameters& parameters, MBGL_DEBUG_GROUP(context, "background"); renderBackground(parameters, *layer.as<RenderBackgroundLayer>()); } else if (layer.is<RenderCustomLayer>()) { - MBGL_DEBUG_GROUP(context, layer.baseImpl.id + " - custom"); + MBGL_DEBUG_GROUP(context, layer.baseImpl->id + " - custom"); // Reset GL state to a known state so the CustomLayer always has a clean slate. context.vertexArrayObject = 0; @@ -317,7 +317,7 @@ void Painter::renderPass(PaintParameters& parameters, context.setStencilMode(gl::StencilMode::disabled()); context.setColorMode(colorModeForRenderPass()); - layer.as<RenderCustomLayer>()->impl->render(state); + layer.as<RenderCustomLayer>()->impl().render(state); // Reset the view back to our original one, just in case the CustomLayer changed // the viewport or Framebuffer. @@ -339,8 +339,8 @@ void Painter::renderPass(PaintParameters& parameters, for (auto& tileRef : item.tiles) { auto& tile = tileRef.get(); - MBGL_DEBUG_GROUP(context, layer.baseImpl.id + " - " + util::toString(tile.id)); - auto bucket = tile.tile.getBucket(layer); + MBGL_DEBUG_GROUP(context, layer.baseImpl->id + " - " + util::toString(tile.id)); + auto bucket = tile.tile.getBucket(*layer.baseImpl); bucket->render(*this, parameters, layer, tile); } @@ -366,8 +366,8 @@ void Painter::renderPass(PaintParameters& parameters, } else { for (auto& tileRef : item.tiles) { auto& tile = tileRef.get(); - MBGL_DEBUG_GROUP(context, layer.baseImpl.id + " - " + util::toString(tile.id)); - auto bucket = tile.tile.getBucket(layer); + MBGL_DEBUG_GROUP(context, layer.baseImpl->id + " - " + util::toString(tile.id)); + auto bucket = tile.tile.getBucket(*layer.baseImpl); bucket->render(*this, parameters, layer, tile); } } diff --git a/src/mbgl/renderer/render_background_layer.cpp b/src/mbgl/renderer/render_background_layer.cpp index 8069209c71..f2e9c0cbaf 100644 --- a/src/mbgl/renderer/render_background_layer.cpp +++ b/src/mbgl/renderer/render_background_layer.cpp @@ -4,9 +4,12 @@ namespace mbgl { -RenderBackgroundLayer::RenderBackgroundLayer(const style::BackgroundLayer::Impl& _impl) - : RenderLayer(style::LayerType::Background, _impl), - impl(&_impl) { +RenderBackgroundLayer::RenderBackgroundLayer(Immutable<style::BackgroundLayer::Impl> _impl) + : RenderLayer(style::LayerType::Background, _impl) { +} + +const style::BackgroundLayer::Impl& RenderBackgroundLayer::impl() const { + return static_cast<const style::BackgroundLayer::Impl&>(*baseImpl); } std::unique_ptr<RenderLayer> RenderBackgroundLayer::clone() const { @@ -20,7 +23,7 @@ std::unique_ptr<Bucket> RenderBackgroundLayer::createBucket(const BucketParamete } void RenderBackgroundLayer::cascade(const CascadeParameters ¶meters) { - unevaluated = impl->cascading.cascade(parameters, std::move(unevaluated)); + unevaluated = impl().cascading.cascade(parameters, std::move(unevaluated)); } void RenderBackgroundLayer::evaluate(const PropertyEvaluationParameters ¶meters) { diff --git a/src/mbgl/renderer/render_background_layer.hpp b/src/mbgl/renderer/render_background_layer.hpp index 9174664a70..6a98ff330c 100644 --- a/src/mbgl/renderer/render_background_layer.hpp +++ b/src/mbgl/renderer/render_background_layer.hpp @@ -8,8 +8,7 @@ namespace mbgl { class RenderBackgroundLayer: public RenderLayer { public: - - RenderBackgroundLayer(const style::BackgroundLayer::Impl&); + RenderBackgroundLayer(Immutable<style::BackgroundLayer::Impl>); ~RenderBackgroundLayer() final = default; std::unique_ptr<RenderLayer> clone() const override; @@ -24,7 +23,7 @@ public: style::BackgroundPaintProperties::Unevaluated unevaluated; style::BackgroundPaintProperties::Evaluated evaluated; - const style::BackgroundLayer::Impl* const impl; + const style::BackgroundLayer::Impl& impl() const; }; template <> diff --git a/src/mbgl/renderer/render_circle_layer.cpp b/src/mbgl/renderer/render_circle_layer.cpp index e9ed465187..fb179082c9 100644 --- a/src/mbgl/renderer/render_circle_layer.cpp +++ b/src/mbgl/renderer/render_circle_layer.cpp @@ -7,9 +7,12 @@ namespace mbgl { -RenderCircleLayer::RenderCircleLayer(const style::CircleLayer::Impl& _impl) - : RenderLayer(style::LayerType::Circle, _impl), - impl(&_impl) { +RenderCircleLayer::RenderCircleLayer(Immutable<style::CircleLayer::Impl> _impl) + : RenderLayer(style::LayerType::Circle, _impl) { +} + +const style::CircleLayer::Impl& RenderCircleLayer::impl() const { + return static_cast<const style::CircleLayer::Impl&>(*baseImpl); } std::unique_ptr<RenderLayer> RenderCircleLayer::clone() const { @@ -21,7 +24,7 @@ std::unique_ptr<Bucket> RenderCircleLayer::createBucket(const BucketParameters& } void RenderCircleLayer::cascade(const CascadeParameters& parameters) { - unevaluated = impl->cascading.cascade(parameters, std::move(unevaluated)); + unevaluated = impl().cascading.cascade(parameters, std::move(unevaluated)); } void RenderCircleLayer::evaluate(const PropertyEvaluationParameters& parameters) { diff --git a/src/mbgl/renderer/render_circle_layer.hpp b/src/mbgl/renderer/render_circle_layer.hpp index 60d600faca..7c411e80aa 100644 --- a/src/mbgl/renderer/render_circle_layer.hpp +++ b/src/mbgl/renderer/render_circle_layer.hpp @@ -8,8 +8,7 @@ namespace mbgl { class RenderCircleLayer: public RenderLayer { public: - - RenderCircleLayer(const style::CircleLayer::Impl&); + RenderCircleLayer(Immutable<style::CircleLayer::Impl>); ~RenderCircleLayer() final = default; std::unique_ptr<RenderLayer> clone() const override; @@ -31,7 +30,7 @@ public: style::CirclePaintProperties::Unevaluated unevaluated; style::CirclePaintProperties::Evaluated evaluated; - const style::CircleLayer::Impl* const impl; + const style::CircleLayer::Impl& impl() const; }; template <> diff --git a/src/mbgl/renderer/render_custom_layer.cpp b/src/mbgl/renderer/render_custom_layer.cpp index d89fa7bba2..0f22bc8780 100644 --- a/src/mbgl/renderer/render_custom_layer.cpp +++ b/src/mbgl/renderer/render_custom_layer.cpp @@ -4,9 +4,12 @@ namespace mbgl { -RenderCustomLayer::RenderCustomLayer(const style::CustomLayer::Impl& _impl) - : RenderLayer(style::LayerType::Custom, _impl), - impl(&_impl) { +RenderCustomLayer::RenderCustomLayer(Immutable<style::CustomLayer::Impl> _impl) + : RenderLayer(style::LayerType::Custom, _impl) { +} + +const style::CustomLayer::Impl& RenderCustomLayer::impl() const { + return static_cast<const style::CustomLayer::Impl&>(*baseImpl); } std::unique_ptr<RenderLayer> RenderCustomLayer::clone() const { diff --git a/src/mbgl/renderer/render_custom_layer.hpp b/src/mbgl/renderer/render_custom_layer.hpp index f6ef253481..9b16928a58 100644 --- a/src/mbgl/renderer/render_custom_layer.hpp +++ b/src/mbgl/renderer/render_custom_layer.hpp @@ -7,8 +7,7 @@ namespace mbgl { class RenderCustomLayer: public RenderLayer { public: - - RenderCustomLayer(const style::CustomLayer::Impl&); + RenderCustomLayer(Immutable<style::CustomLayer::Impl>); ~RenderCustomLayer() final = default; std::unique_ptr<RenderLayer> clone() const override; @@ -19,7 +18,7 @@ public: std::unique_ptr<Bucket> createBucket(const BucketParameters&, const std::vector<const RenderLayer*>&) const final; - const style::CustomLayer::Impl* const impl; + const style::CustomLayer::Impl& impl() const; }; template <> diff --git a/src/mbgl/renderer/render_fill_extrusion_layer.cpp b/src/mbgl/renderer/render_fill_extrusion_layer.cpp index f6ba164d8c..8dc6e93a9e 100644 --- a/src/mbgl/renderer/render_fill_extrusion_layer.cpp +++ b/src/mbgl/renderer/render_fill_extrusion_layer.cpp @@ -7,9 +7,12 @@ namespace mbgl { -RenderFillExtrusionLayer::RenderFillExtrusionLayer(const style::FillExtrusionLayer::Impl& _impl) - : RenderLayer(style::LayerType::FillExtrusion, _impl), - impl(&_impl) { +RenderFillExtrusionLayer::RenderFillExtrusionLayer(Immutable<style::FillExtrusionLayer::Impl> _impl) + : RenderLayer(style::LayerType::FillExtrusion, _impl) { +} + +const style::FillExtrusionLayer::Impl& RenderFillExtrusionLayer::impl() const { + return static_cast<const style::FillExtrusionLayer::Impl&>(*baseImpl); } std::unique_ptr<RenderLayer> RenderFillExtrusionLayer::clone() const { @@ -21,7 +24,7 @@ std::unique_ptr<Bucket> RenderFillExtrusionLayer::createBucket(const BucketParam } void RenderFillExtrusionLayer::cascade(const CascadeParameters& parameters) { - unevaluated = impl->cascading.cascade(parameters, std::move(unevaluated)); + unevaluated = impl().cascading.cascade(parameters, std::move(unevaluated)); } void RenderFillExtrusionLayer::evaluate(const PropertyEvaluationParameters& parameters) { diff --git a/src/mbgl/renderer/render_fill_extrusion_layer.hpp b/src/mbgl/renderer/render_fill_extrusion_layer.hpp index bd66d8e3b1..2bfbc296c1 100644 --- a/src/mbgl/renderer/render_fill_extrusion_layer.hpp +++ b/src/mbgl/renderer/render_fill_extrusion_layer.hpp @@ -8,8 +8,7 @@ namespace mbgl { class RenderFillExtrusionLayer: public RenderLayer { public: - - RenderFillExtrusionLayer(const style::FillExtrusionLayer::Impl&); + RenderFillExtrusionLayer(Immutable<style::FillExtrusionLayer::Impl>); ~RenderFillExtrusionLayer() final = default; std::unique_ptr<RenderLayer> clone() const override; @@ -31,7 +30,7 @@ public: style::FillExtrusionPaintProperties::Unevaluated unevaluated; style::FillExtrusionPaintProperties::Evaluated evaluated; - const style::FillExtrusionLayer::Impl* const impl; + const style::FillExtrusionLayer::Impl& impl() const; }; template <> diff --git a/src/mbgl/renderer/render_fill_layer.cpp b/src/mbgl/renderer/render_fill_layer.cpp index 340ec85803..0de22b3ca8 100644 --- a/src/mbgl/renderer/render_fill_layer.cpp +++ b/src/mbgl/renderer/render_fill_layer.cpp @@ -7,9 +7,12 @@ namespace mbgl { -RenderFillLayer::RenderFillLayer(const style::FillLayer::Impl& _impl) - : RenderLayer(style::LayerType::Fill, _impl), - impl(&_impl) { +RenderFillLayer::RenderFillLayer(Immutable<style::FillLayer::Impl> _impl) + : RenderLayer(style::LayerType::Fill, _impl) { +} + +const style::FillLayer::Impl& RenderFillLayer::impl() const { + return static_cast<const style::FillLayer::Impl&>(*baseImpl); } std::unique_ptr<RenderLayer> RenderFillLayer::clone() const { @@ -21,7 +24,7 @@ std::unique_ptr<Bucket> RenderFillLayer::createBucket(const BucketParameters& pa } void RenderFillLayer::cascade(const CascadeParameters& parameters) { - unevaluated = impl->cascading.cascade(parameters, std::move(unevaluated)); + unevaluated = impl().cascading.cascade(parameters, std::move(unevaluated)); } void RenderFillLayer::evaluate(const PropertyEvaluationParameters& parameters) { diff --git a/src/mbgl/renderer/render_fill_layer.hpp b/src/mbgl/renderer/render_fill_layer.hpp index 8080cf289b..7e23a61a00 100644 --- a/src/mbgl/renderer/render_fill_layer.hpp +++ b/src/mbgl/renderer/render_fill_layer.hpp @@ -8,8 +8,7 @@ namespace mbgl { class RenderFillLayer: public RenderLayer { public: - - RenderFillLayer(const style::FillLayer::Impl&); + RenderFillLayer(Immutable<style::FillLayer::Impl>); ~RenderFillLayer() final = default; std::unique_ptr<RenderLayer> clone() const override; @@ -31,7 +30,7 @@ public: style::FillPaintProperties::Unevaluated unevaluated; style::FillPaintProperties::Evaluated evaluated; - const style::FillLayer::Impl* const impl; + const style::FillLayer::Impl& impl() const; }; template <> diff --git a/src/mbgl/renderer/render_layer.cpp b/src/mbgl/renderer/render_layer.cpp index ed8864149b..2f30b2ce21 100644 --- a/src/mbgl/renderer/render_layer.cpp +++ b/src/mbgl/renderer/render_layer.cpp @@ -3,12 +3,17 @@ namespace mbgl { -RenderLayer::RenderLayer(style::LayerType type_, const style::Layer::Impl& baseImpl_) - : type(type_), baseImpl(baseImpl_) { +RenderLayer::RenderLayer(style::LayerType type_, Immutable<style::Layer::Impl> baseImpl_) + : type(type_), + baseImpl(baseImpl_) { +} + +void RenderLayer::setImpl(Immutable<style::Layer::Impl> impl) { + baseImpl = impl; } const std::string& RenderLayer::getID() const { - return baseImpl.id; + return baseImpl->id; } bool RenderLayer::hasRenderPass(RenderPass pass) const { @@ -17,9 +22,9 @@ bool RenderLayer::hasRenderPass(RenderPass pass) const { bool RenderLayer::needsRendering(float zoom) const { return passes != RenderPass::None - && baseImpl.visibility != style::VisibilityType::None - && baseImpl.minZoom <= zoom - && baseImpl.maxZoom >= zoom; + && baseImpl->visibility != style::VisibilityType::None + && baseImpl->minZoom <= zoom + && baseImpl->maxZoom >= zoom; } } // namespace mbgl
\ No newline at end of file diff --git a/src/mbgl/renderer/render_layer.hpp b/src/mbgl/renderer/render_layer.hpp index eea2ec1f61..a877405564 100644 --- a/src/mbgl/renderer/render_layer.hpp +++ b/src/mbgl/renderer/render_layer.hpp @@ -16,14 +16,12 @@ class CascadeParameters; class PropertyEvaluationParameters; class RenderLayer { - protected: - RenderLayer(style::LayerType, const style::Layer::Impl&); + RenderLayer(style::LayerType, Immutable<style::Layer::Impl>); const style::LayerType type; public: - virtual ~RenderLayer() = default; // Create an identical copy of this layer. @@ -73,11 +71,12 @@ public: virtual std::unique_ptr<Bucket> createBucket(const BucketParameters&, const std::vector<const RenderLayer*>&) const = 0; // Private implementation - const style::Layer::Impl& baseImpl; + Immutable<style::Layer::Impl> baseImpl; + void setImpl(Immutable<style::Layer::Impl>); friend std::string layoutKey(const RenderLayer&); -protected: +protected: // Stores what render passes this layer is currently enabled for. This depends on the // evaluated StyleProperties object and is updated accordingly. RenderPass passes = RenderPass::None; diff --git a/src/mbgl/renderer/render_light.cpp b/src/mbgl/renderer/render_light.cpp index 134e1829e0..1fc346fd26 100644 --- a/src/mbgl/renderer/render_light.cpp +++ b/src/mbgl/renderer/render_light.cpp @@ -2,17 +2,8 @@ namespace mbgl { -RenderLight::RenderLight(std::shared_ptr<const style::Light::Impl> impl_) - : impl(std::move(impl_)) { -} - -RenderLight::RenderLight(std::shared_ptr<const style::Light::Impl> impl_, const TransitioningLight transitioning_) - : impl(std::move(impl_)) - , transitioning(transitioning_) { -} - -std::unique_ptr<RenderLight> RenderLight::copy(std::shared_ptr<const style::Light::Impl> impl_) const { - return std::make_unique<RenderLight>(std::move(impl_), transitioning); +RenderLight::RenderLight(Immutable<style::Light::Impl> impl_) + : impl(std::move(impl_)) { } void RenderLight::transition(const CascadeParameters& parameters) { diff --git a/src/mbgl/renderer/render_light.hpp b/src/mbgl/renderer/render_light.hpp index 275f3ae8ba..ed8d8bf59c 100644 --- a/src/mbgl/renderer/render_light.hpp +++ b/src/mbgl/renderer/render_light.hpp @@ -74,14 +74,7 @@ using EvaluatedLight = Evaluated<style::LightProperties>; class RenderLight { public: - RenderLight(std::shared_ptr<const style::Light::Impl>); - - // Creates a copy intitalized with previous transitioning light - RenderLight(std::shared_ptr<const style::Light::Impl>, const TransitioningLight); - - // creates a copy initialized with previous transitioning - // values - std::unique_ptr<RenderLight> copy(std::shared_ptr<const style::Light::Impl>) const; + RenderLight(Immutable<style::Light::Impl>); void transition(const CascadeParameters&); void evaluate(const PropertyEvaluationParameters&); @@ -89,10 +82,9 @@ public: const EvaluatedLight& getEvaluated() const; - const std::shared_ptr<const style::Light::Impl> impl; + Immutable<style::Light::Impl> impl; private: - TransitioningLight transitioning; EvaluatedLight evaluated; }; diff --git a/src/mbgl/renderer/render_line_layer.cpp b/src/mbgl/renderer/render_line_layer.cpp index 06c2564516..6573118c3b 100644 --- a/src/mbgl/renderer/render_line_layer.cpp +++ b/src/mbgl/renderer/render_line_layer.cpp @@ -7,9 +7,12 @@ namespace mbgl { -RenderLineLayer::RenderLineLayer(const style::LineLayer::Impl& _impl) - : RenderLayer(style::LayerType::Line, _impl), - impl(&_impl) { +RenderLineLayer::RenderLineLayer(Immutable<style::LineLayer::Impl> _impl) + : RenderLayer(style::LayerType::Line, _impl) { +} + +const style::LineLayer::Impl& RenderLineLayer::impl() const { + return static_cast<const style::LineLayer::Impl&>(*baseImpl); } std::unique_ptr<RenderLayer> RenderLineLayer::clone() const { @@ -17,11 +20,11 @@ std::unique_ptr<RenderLayer> RenderLineLayer::clone() const { } std::unique_ptr<Bucket> RenderLineLayer::createBucket(const BucketParameters& parameters, const std::vector<const RenderLayer*>& layers) const { - return std::make_unique<LineBucket>(parameters, layers, impl->layout); + return std::make_unique<LineBucket>(parameters, layers, impl().layout); } void RenderLineLayer::cascade(const CascadeParameters& parameters) { - unevaluated = impl->cascading.cascade(parameters, std::move(unevaluated)); + unevaluated = impl().cascading.cascade(parameters, std::move(unevaluated)); } void RenderLineLayer::evaluate(const PropertyEvaluationParameters& parameters) { diff --git a/src/mbgl/renderer/render_line_layer.hpp b/src/mbgl/renderer/render_line_layer.hpp index 6d6fecc227..dce4d07f18 100644 --- a/src/mbgl/renderer/render_line_layer.hpp +++ b/src/mbgl/renderer/render_line_layer.hpp @@ -8,8 +8,7 @@ namespace mbgl { class RenderLineLayer: public RenderLayer { public: - - RenderLineLayer(const style::LineLayer::Impl&); + RenderLineLayer(Immutable<style::LineLayer::Impl>); ~RenderLineLayer() final = default; std::unique_ptr<RenderLayer> clone() const override; @@ -31,14 +30,13 @@ public: style::LinePaintProperties::Unevaluated unevaluated; style::LinePaintProperties::Evaluated evaluated; - const style::LineLayer::Impl* const impl; + const style::LineLayer::Impl& impl() const; // Special case float dashLineWidth = 1; private: float getLineWidth(const GeometryTileFeature&, const float) const; - }; template <> diff --git a/src/mbgl/renderer/render_raster_layer.cpp b/src/mbgl/renderer/render_raster_layer.cpp index 5e664e6f58..2e79a785bc 100644 --- a/src/mbgl/renderer/render_raster_layer.cpp +++ b/src/mbgl/renderer/render_raster_layer.cpp @@ -4,9 +4,12 @@ namespace mbgl { -RenderRasterLayer::RenderRasterLayer(const style::RasterLayer::Impl& _impl) - : RenderLayer(style::LayerType::Raster, _impl), - impl(&_impl) { +RenderRasterLayer::RenderRasterLayer(Immutable<style::RasterLayer::Impl> _impl) + : RenderLayer(style::LayerType::Raster, _impl) { +} + +const style::RasterLayer::Impl& RenderRasterLayer::impl() const { + return static_cast<const style::RasterLayer::Impl&>(*baseImpl); } std::unique_ptr<RenderLayer> RenderRasterLayer::clone() const { @@ -19,7 +22,7 @@ std::unique_ptr<Bucket> RenderRasterLayer::createBucket(const BucketParameters&, } void RenderRasterLayer::cascade(const CascadeParameters& parameters) { - unevaluated = impl->cascading.cascade(parameters, std::move(unevaluated)); + unevaluated = impl().cascading.cascade(parameters, std::move(unevaluated)); } void RenderRasterLayer::evaluate(const PropertyEvaluationParameters& parameters) { diff --git a/src/mbgl/renderer/render_raster_layer.hpp b/src/mbgl/renderer/render_raster_layer.hpp index 3ffeb8febf..f51d042d5f 100644 --- a/src/mbgl/renderer/render_raster_layer.hpp +++ b/src/mbgl/renderer/render_raster_layer.hpp @@ -8,8 +8,7 @@ namespace mbgl { class RenderRasterLayer: public RenderLayer { public: - - RenderRasterLayer(const style::RasterLayer::Impl&); + RenderRasterLayer(Immutable<style::RasterLayer::Impl>); ~RenderRasterLayer() final = default; std::unique_ptr<RenderLayer> clone() const override; @@ -24,7 +23,7 @@ public: style::RasterPaintProperties::Unevaluated unevaluated; style::RasterPaintProperties::Evaluated evaluated; - const style::RasterLayer::Impl* const impl; + const style::RasterLayer::Impl& impl() const; }; template <> diff --git a/src/mbgl/renderer/render_source.cpp b/src/mbgl/renderer/render_source.cpp index 22043f9f3c..9eca54795a 100644 --- a/src/mbgl/renderer/render_source.cpp +++ b/src/mbgl/renderer/render_source.cpp @@ -6,7 +6,7 @@ namespace mbgl { static RenderSourceObserver nullObserver; -RenderSource::RenderSource(const style::Source::Impl& impl) +RenderSource::RenderSource(Immutable<style::Source::Impl> impl) : baseImpl(impl), observer(&nullObserver) { } @@ -15,6 +15,10 @@ void RenderSource::setObserver(RenderSourceObserver* observer_) { observer = observer_; } +void RenderSource::setImpl(Immutable<style::Source::Impl> impl) { + baseImpl = impl; +} + void RenderSource::onTileChanged(Tile& tile) { observer->onTileChanged(*this, tile.id); } diff --git a/src/mbgl/renderer/render_source.hpp b/src/mbgl/renderer/render_source.hpp index e682e4cd1a..178ee92f93 100644 --- a/src/mbgl/renderer/render_source.hpp +++ b/src/mbgl/renderer/render_source.hpp @@ -29,7 +29,7 @@ class ClipIDGenerator; class RenderSource : protected TileObserver { public: - RenderSource(const style::Source::Impl&); + RenderSource(Immutable<style::Source::Impl>); ~RenderSource() override = default; virtual bool isLoaded() const = 0; @@ -71,7 +71,9 @@ public: void setObserver(RenderSourceObserver*); - const style::Source::Impl& baseImpl; + Immutable<style::Source::Impl> baseImpl; + void setImpl(Immutable<style::Source::Impl>); + bool enabled = false; protected: diff --git a/src/mbgl/renderer/render_symbol_layer.cpp b/src/mbgl/renderer/render_symbol_layer.cpp index 30d769e032..7ea6190cb1 100644 --- a/src/mbgl/renderer/render_symbol_layer.cpp +++ b/src/mbgl/renderer/render_symbol_layer.cpp @@ -8,9 +8,12 @@ namespace mbgl { -RenderSymbolLayer::RenderSymbolLayer(const style::SymbolLayer::Impl& _impl) - : RenderLayer(style::LayerType::Symbol, _impl), - impl(&_impl) { +RenderSymbolLayer::RenderSymbolLayer(Immutable<style::SymbolLayer::Impl> _impl) + : RenderLayer(style::LayerType::Symbol, _impl) { +} + +const style::SymbolLayer::Impl& RenderSymbolLayer::impl() const { + return static_cast<const style::SymbolLayer::Impl&>(*baseImpl); } std::unique_ptr<RenderLayer> RenderSymbolLayer::clone() const { @@ -35,7 +38,7 @@ std::unique_ptr<SymbolLayout> RenderSymbolLayer::createLayout(const BucketParame } void RenderSymbolLayer::cascade(const CascadeParameters& parameters) { - unevaluated = impl->cascading.cascade(parameters, std::move(unevaluated)); + unevaluated = impl().cascading.cascade(parameters, std::move(unevaluated)); } void RenderSymbolLayer::evaluate(const PropertyEvaluationParameters& parameters) { diff --git a/src/mbgl/renderer/render_symbol_layer.hpp b/src/mbgl/renderer/render_symbol_layer.hpp index 80ffd95a06..553deb8259 100644 --- a/src/mbgl/renderer/render_symbol_layer.hpp +++ b/src/mbgl/renderer/render_symbol_layer.hpp @@ -61,7 +61,7 @@ class GeometryTileLayer; class RenderSymbolLayer: public RenderLayer { public: - RenderSymbolLayer(const style::SymbolLayer::Impl&); + RenderSymbolLayer(Immutable<style::SymbolLayer::Impl>); ~RenderSymbolLayer() final = default; std::unique_ptr<RenderLayer> clone() const override; @@ -87,7 +87,7 @@ public: float iconSize = 1.0f; float textSize = 16.0f; - const style::SymbolLayer::Impl* const impl; + const style::SymbolLayer::Impl& impl() const; }; template <> diff --git a/src/mbgl/renderer/sources/render_geojson_source.cpp b/src/mbgl/renderer/sources/render_geojson_source.cpp index 2b1eeea73b..893f6a2ac6 100644 --- a/src/mbgl/renderer/sources/render_geojson_source.cpp +++ b/src/mbgl/renderer/sources/render_geojson_source.cpp @@ -9,12 +9,15 @@ namespace mbgl { using namespace style; -RenderGeoJSONSource::RenderGeoJSONSource(const style::GeoJSONSource::Impl& impl_) - : RenderSource(impl_), - impl(impl_) { +RenderGeoJSONSource::RenderGeoJSONSource(Immutable<style::GeoJSONSource::Impl> impl_) + : RenderSource(impl_) { tilePyramid.setObserver(this); } +const style::GeoJSONSource::Impl& RenderGeoJSONSource::impl() const { + return static_cast<const style::GeoJSONSource::Impl&>(*baseImpl); +} + bool RenderGeoJSONSource::isLoaded() const { return tilePyramid.isLoaded(); } @@ -37,7 +40,7 @@ std::map<UnwrappedTileID, RenderTile>& RenderGeoJSONSource::getRenderTiles() { } void RenderGeoJSONSource::updateTiles(const TileParameters& parameters) { - GeoJSONData* data_ = impl.getData(); + GeoJSONData* data_ = impl().getData(); if (!data_) { return; @@ -55,9 +58,9 @@ void RenderGeoJSONSource::updateTiles(const TileParameters& parameters) { tilePyramid.updateTiles(parameters, SourceType::GeoJSON, util::tileSize, - impl.getZoomRange(), + impl().getZoomRange(), [&] (const OverscaledTileID& tileID) { - return std::make_unique<GeoJSONTile>(tileID, impl.id, parameters, data->getTile(tileID.canonical)); + return std::make_unique<GeoJSONTile>(tileID, impl().id, parameters, data->getTile(tileID.canonical)); }); } diff --git a/src/mbgl/renderer/sources/render_geojson_source.hpp b/src/mbgl/renderer/sources/render_geojson_source.hpp index 262ab29276..0f9379b9b6 100644 --- a/src/mbgl/renderer/sources/render_geojson_source.hpp +++ b/src/mbgl/renderer/sources/render_geojson_source.hpp @@ -12,7 +12,7 @@ class GeoJSONData; class RenderGeoJSONSource : public RenderSource { public: - RenderGeoJSONSource(const style::GeoJSONSource::Impl&); + RenderGeoJSONSource(Immutable<style::GeoJSONSource::Impl>); bool isLoaded() const final; @@ -51,7 +51,8 @@ public: void dumpDebugLogs() const final; private: - const style::GeoJSONSource::Impl& impl; + const style::GeoJSONSource::Impl& impl() const; + TilePyramid tilePyramid; style::GeoJSONData* data; }; diff --git a/src/mbgl/renderer/sources/render_raster_source.cpp b/src/mbgl/renderer/sources/render_raster_source.cpp index c5a29eebf5..e2d641c4e4 100644 --- a/src/mbgl/renderer/sources/render_raster_source.cpp +++ b/src/mbgl/renderer/sources/render_raster_source.cpp @@ -6,12 +6,15 @@ namespace mbgl { using namespace style; -RenderRasterSource::RenderRasterSource(const style::RasterSource::Impl& impl_) - : RenderSource(impl_), - impl(impl_) { +RenderRasterSource::RenderRasterSource(Immutable<style::RasterSource::Impl> impl_) + : RenderSource(impl_) { tilePyramid.setObserver(this); } +const style::RasterSource::Impl& RenderRasterSource::impl() const { + return static_cast<const style::RasterSource::Impl&>(*baseImpl); +} + bool RenderRasterSource::isLoaded() const { return tilePyramid.isLoaded(); } @@ -33,7 +36,7 @@ std::map<UnwrappedTileID, RenderTile>& RenderRasterSource::getRenderTiles() { } void RenderRasterSource::updateTiles(const TileParameters& parameters) { - optional<Tileset> tileset = impl.getTileset(); + optional<Tileset> tileset = impl().getTileset(); if (!tileset) { return; @@ -46,7 +49,7 @@ void RenderRasterSource::updateTiles(const TileParameters& parameters) { tilePyramid.updateTiles(parameters, SourceType::Raster, - impl.getTileSize(), + impl().getTileSize(), tileset->zoomRange, [&] (const OverscaledTileID& tileID) { return std::make_unique<RasterTile>(tileID, parameters, *tileset); diff --git a/src/mbgl/renderer/sources/render_raster_source.hpp b/src/mbgl/renderer/sources/render_raster_source.hpp index 5690ba80ea..9bf4436bc7 100644 --- a/src/mbgl/renderer/sources/render_raster_source.hpp +++ b/src/mbgl/renderer/sources/render_raster_source.hpp @@ -8,7 +8,7 @@ namespace mbgl { class RenderRasterSource : public RenderSource { public: - RenderRasterSource(const style::RasterSource::Impl&); + RenderRasterSource(Immutable<style::RasterSource::Impl>); bool isLoaded() const final; @@ -47,7 +47,8 @@ public: void dumpDebugLogs() const final; private: - const style::RasterSource::Impl& impl; + const style::RasterSource::Impl& impl() const; + TilePyramid tilePyramid; optional<std::vector<std::string>> tileURLTemplates; }; diff --git a/src/mbgl/renderer/sources/render_vector_source.cpp b/src/mbgl/renderer/sources/render_vector_source.cpp index 0db4698a81..f88ca2beea 100644 --- a/src/mbgl/renderer/sources/render_vector_source.cpp +++ b/src/mbgl/renderer/sources/render_vector_source.cpp @@ -9,12 +9,15 @@ namespace mbgl { using namespace style; -RenderVectorSource::RenderVectorSource(const style::VectorSource::Impl& impl_) - : RenderSource(impl_), - impl(impl_) { +RenderVectorSource::RenderVectorSource(Immutable<style::VectorSource::Impl> impl_) + : RenderSource(impl_) { tilePyramid.setObserver(this); } +const style::VectorSource::Impl& RenderVectorSource::impl() const { + return static_cast<const style::VectorSource::Impl&>(*baseImpl); +} + bool RenderVectorSource::isLoaded() const { return tilePyramid.isLoaded(); } @@ -37,7 +40,7 @@ std::map<UnwrappedTileID, RenderTile>& RenderVectorSource::getRenderTiles() { } void RenderVectorSource::updateTiles(const TileParameters& parameters) { - optional<Tileset> tileset = impl.getTileset(); + optional<Tileset> tileset = impl().getTileset(); if (!tileset) { return; @@ -53,7 +56,7 @@ void RenderVectorSource::updateTiles(const TileParameters& parameters) { util::tileSize, tileset->zoomRange, [&] (const OverscaledTileID& tileID) { - return std::make_unique<VectorTile>(tileID, impl.id, parameters, *tileset); + return std::make_unique<VectorTile>(tileID, impl().id, parameters, *tileset); }); } diff --git a/src/mbgl/renderer/sources/render_vector_source.hpp b/src/mbgl/renderer/sources/render_vector_source.hpp index 36d75e0982..b3704a1274 100644 --- a/src/mbgl/renderer/sources/render_vector_source.hpp +++ b/src/mbgl/renderer/sources/render_vector_source.hpp @@ -8,7 +8,7 @@ namespace mbgl { class RenderVectorSource : public RenderSource { public: - RenderVectorSource(const style::VectorSource::Impl&); + RenderVectorSource(Immutable<style::VectorSource::Impl>); bool isLoaded() const final; @@ -47,7 +47,8 @@ public: void dumpDebugLogs() const final; private: - const style::VectorSource::Impl& impl; + const style::VectorSource::Impl& impl() const; + TilePyramid tilePyramid; optional<std::vector<std::string>> tileURLTemplates; }; diff --git a/src/mbgl/renderer/style_diff.cpp b/src/mbgl/renderer/style_diff.cpp new file mode 100644 index 0000000000..12000069ea --- /dev/null +++ b/src/mbgl/renderer/style_diff.cpp @@ -0,0 +1,56 @@ +#include <mbgl/renderer/style_diff.hpp> +#include <mbgl/style/layer_impl.hpp> +#include <mbgl/util/immutable.hpp> +#include <mbgl/util/variant.hpp> +#include <mbgl/util/longest_common_subsequence.hpp> + +namespace mbgl { + +template <class T> +StyleDifference<T> diff(const std::vector<T>& a, const std::vector<T>& b) { + std::vector<T> lcs; + + auto eq = [] (const T& lhs, const T& rhs) { + return std::tie(lhs->id, lhs->type) + == std::tie(rhs->id, rhs->type); + }; + + longest_common_subsequence(a.begin(), a.end(), b.begin(), b.end(), std::back_inserter(lcs), eq); + + auto aIt = a.begin(); + auto bIt = b.begin(); + auto lIt = lcs.begin(); + + StyleDifference<T> result; + + while (aIt != a.end() || bIt != b.end()) { + if (aIt != a.end() && (lIt == lcs.end() || !eq(*lIt, *aIt))) { + result.removed.emplace((*aIt)->id, *aIt); + aIt++; + } else if (bIt != b.end() && (lIt == lcs.end() || !eq(*lIt, *bIt))) { + result.added.emplace((*bIt)->id, *bIt); + bIt++; + } else { + if (aIt->get() != bIt->get()) { + result.changed.emplace((*bIt)->id, *bIt); + } + aIt++; + bIt++; + lIt++; + } + } + + return result; +} + +SourceDifference diffSources(const std::vector<ImmutableSource>& a, + const std::vector<ImmutableSource>& b) { + return diff(a, b); +} + +LayerDifference diffLayers(const std::vector<ImmutableLayer>& a, + const std::vector<ImmutableLayer>& b) { + return diff(a, b); +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/style_diff.hpp b/src/mbgl/renderer/style_diff.hpp new file mode 100644 index 0000000000..dc2ef95c6c --- /dev/null +++ b/src/mbgl/renderer/style_diff.hpp @@ -0,0 +1,30 @@ +#include <mbgl/style/source_impl.hpp> +#include <mbgl/style/layer_impl.hpp> +#include <mbgl/util/immutable.hpp> +#include <mbgl/util/variant.hpp> + +#include <unordered_map> + +namespace mbgl { + +template <class T> +class StyleDifference { +public: + std::unordered_map<std::string, T> added; + std::unordered_map<std::string, T> removed; + std::unordered_map<std::string, T> changed; +}; + +using ImmutableSource = Immutable<style::Source::Impl>; +using SourceDifference = StyleDifference<ImmutableSource>; + +SourceDifference diffSources(const std::vector<ImmutableSource>&, + const std::vector<ImmutableSource>&); + +using ImmutableLayer = Immutable<style::Layer::Impl>; +using LayerDifference = StyleDifference<ImmutableLayer>; + +LayerDifference diffLayers(const std::vector<ImmutableLayer>&, + const std::vector<ImmutableLayer>&); + +} // namespace mbgl diff --git a/src/mbgl/style/layer.cpp b/src/mbgl/style/layer.cpp index e2eba0e2e0..fe51dd09ca 100644 --- a/src/mbgl/style/layer.cpp +++ b/src/mbgl/style/layer.cpp @@ -1,16 +1,23 @@ #include <mbgl/style/layer.hpp> #include <mbgl/style/layer_impl.hpp> -#include <mbgl/style/layer_type.hpp> +#include <mbgl/style/layer_observer.hpp> namespace mbgl { namespace style { -Layer::Layer(LayerType type_, std::unique_ptr<Impl> baseImpl_) - : type(type_), baseImpl(std::move(baseImpl_)) { +static LayerObserver nullObserver; + +Layer::Layer(Immutable<Impl> impl) + : baseImpl(std::move(impl)), + observer(&nullObserver) { } Layer::~Layer() = default; +LayerType Layer::getType() const { + return baseImpl->type; +} + const std::string& Layer::getID() const { return baseImpl->id; } @@ -19,27 +26,16 @@ VisibilityType Layer::getVisibility() const { return baseImpl->visibility; } -void Layer::setVisibility(VisibilityType value) { - if (value == getVisibility()) - return; - baseImpl->visibility = value; - baseImpl->observer->onLayerVisibilityChanged(*this); -} - float Layer::getMinZoom() const { return baseImpl->minZoom; } -void Layer::setMinZoom(float minZoom) const { - baseImpl->minZoom = minZoom; -} - float Layer::getMaxZoom() const { return baseImpl->maxZoom; } -void Layer::setMaxZoom(float maxZoom) const { - baseImpl->maxZoom = maxZoom; +void Layer::setObserver(LayerObserver* observer_) { + observer = observer_ ? observer_ : &nullObserver; } } // namespace style diff --git a/src/mbgl/style/layer_impl.cpp b/src/mbgl/style/layer_impl.cpp index 725064a9a2..a9a3941f3e 100644 --- a/src/mbgl/style/layer_impl.cpp +++ b/src/mbgl/style/layer_impl.cpp @@ -3,8 +3,10 @@ namespace mbgl { namespace style { -void Layer::Impl::setObserver(LayerObserver* observer_) { - observer = observer_ ? observer_ : &nullObserver; +Layer::Impl::Impl(LayerType type_, std::string layerID, std::string sourceID) + : type(type_), + id(std::move(layerID)), + source(std::move(sourceID)) { } } // namespace style diff --git a/src/mbgl/style/layer_impl.hpp b/src/mbgl/style/layer_impl.hpp index 914203f804..fe7259a11a 100644 --- a/src/mbgl/style/layer_impl.hpp +++ b/src/mbgl/style/layer_impl.hpp @@ -3,13 +3,10 @@ #include <mbgl/style/layer.hpp> #include <mbgl/style/types.hpp> #include <mbgl/style/filter.hpp> -#include <mbgl/style/layer_observer.hpp> -#include <mbgl/util/noncopyable.hpp> #include <rapidjson/writer.h> #include <rapidjson/stringbuffer.h> -#include <memory> #include <string> #include <limits> @@ -30,24 +27,19 @@ namespace style { * Members that are public in `FooLayer::Impl` are part of the internal API for "foo" layers. * Members that are private in `FooLayer::Impl` are internal to "foo" layers. */ -class Layer::Impl { +class Layer::Impl : public EnableImmutableFromThis<Layer::Impl> { public: + Impl(LayerType, std::string layerID, std::string sourceID); virtual ~Impl() = default; - // Create an identical copy of this layer. - virtual std::unique_ptr<Layer> clone() const = 0; - - // 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; + Impl& operator=(const Impl&) = delete; // Utility function for automatic layer grouping. virtual void stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const = 0; virtual std::unique_ptr<RenderLayer> createRenderLayer() const = 0; - void setObserver(LayerObserver*); - -public: + const LayerType type; std::string id; std::string source; std::string sourceLayer; @@ -56,13 +48,8 @@ public: float maxZoom = std::numeric_limits<float>::infinity(); VisibilityType visibility = VisibilityType::Visible; - LayerObserver nullObserver; - LayerObserver* observer = &nullObserver; - protected: - Impl() = default; Impl(const Impl&) = default; - Impl& operator=(const Impl&) = delete; }; } // namespace style diff --git a/src/mbgl/style/layers/background_layer.cpp b/src/mbgl/style/layers/background_layer.cpp index b4ffea138b..3d29b9819c 100644 --- a/src/mbgl/style/layers/background_layer.cpp +++ b/src/mbgl/style/layers/background_layer.cpp @@ -3,38 +3,65 @@ #include <mbgl/style/layers/background_layer.hpp> #include <mbgl/style/layers/background_layer_impl.hpp> #include <mbgl/style/conversion/stringify.hpp> +#include <mbgl/style/layer_observer.hpp> namespace mbgl { namespace style { BackgroundLayer::BackgroundLayer(const std::string& layerID) - : Layer(LayerType::Background, std::make_unique<Impl>()) - , impl(static_cast<Impl*>(baseImpl.get())) { - impl->id = layerID; + : Layer(makeMutable<Impl>(LayerType::Background, layerID, std::string())) { } -BackgroundLayer::BackgroundLayer(const Impl& other) - : Layer(LayerType::Background, std::make_unique<Impl>(other)) - , impl(static_cast<Impl*>(baseImpl.get())) { +BackgroundLayer::BackgroundLayer(Immutable<Impl> impl_) + : Layer(std::move(impl_)) { } BackgroundLayer::~BackgroundLayer() = default; -std::unique_ptr<Layer> BackgroundLayer::Impl::clone() const { - return std::make_unique<BackgroundLayer>(*this); +const BackgroundLayer::Impl& BackgroundLayer::impl() const { + return static_cast<const Impl&>(*baseImpl); } -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->cascading = BackgroundPaintProperties::Cascading(); - return std::move(result); +Mutable<BackgroundLayer::Impl> BackgroundLayer::mutableImpl() const { + return makeMutable<Impl>(impl()); +} + +std::unique_ptr<Layer> BackgroundLayer::cloneRef(const std::string& id_) const { + auto impl_ = mutableImpl(); + impl_->id = id_; + impl_->cascading = BackgroundPaintProperties::Cascading(); + return std::make_unique<BackgroundLayer>(std::move(impl_)); } void BackgroundLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const { } +// Visibility + +void BackgroundLayer::setVisibility(VisibilityType value) { + if (value == getVisibility()) + return; + auto impl_ = mutableImpl(); + impl_->visibility = value; + baseImpl = std::move(impl_); + observer->onLayerVisibilityChanged(*this); +} + +// Zoom range + +void BackgroundLayer::setMinZoom(float minZoom) { + auto impl_ = mutableImpl(); + impl_->minZoom = minZoom; + baseImpl = std::move(impl_); +} + +void BackgroundLayer::setMaxZoom(float maxZoom) { + auto impl_ = mutableImpl(); + impl_->maxZoom = maxZoom; + baseImpl = std::move(impl_); +} + // Layout properties @@ -45,22 +72,26 @@ PropertyValue<Color> BackgroundLayer::getDefaultBackgroundColor() { } PropertyValue<Color> BackgroundLayer::getBackgroundColor(const optional<std::string>& klass) const { - return impl->cascading.template get<BackgroundColor>().get(klass); + return impl().cascading.template get<BackgroundColor>().get(klass); } void BackgroundLayer::setBackgroundColor(PropertyValue<Color> value, const optional<std::string>& klass) { if (value == getBackgroundColor(klass)) return; - impl->cascading.template get<BackgroundColor>().set(value, klass); - impl->observer->onLayerPaintPropertyChanged(*this); + auto impl_ = mutableImpl(); + impl_->cascading.template get<BackgroundColor>().set(value, klass); + baseImpl = std::move(impl_); + observer->onLayerPaintPropertyChanged(*this); } void BackgroundLayer::setBackgroundColorTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<BackgroundColor>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<BackgroundColor>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions BackgroundLayer::getBackgroundColorTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<BackgroundColor>().getTransition(klass); + return impl().cascading.template get<BackgroundColor>().getTransition(klass); } PropertyValue<std::string> BackgroundLayer::getDefaultBackgroundPattern() { @@ -68,22 +99,26 @@ PropertyValue<std::string> BackgroundLayer::getDefaultBackgroundPattern() { } PropertyValue<std::string> BackgroundLayer::getBackgroundPattern(const optional<std::string>& klass) const { - return impl->cascading.template get<BackgroundPattern>().get(klass); + return impl().cascading.template get<BackgroundPattern>().get(klass); } void BackgroundLayer::setBackgroundPattern(PropertyValue<std::string> value, const optional<std::string>& klass) { if (value == getBackgroundPattern(klass)) return; - impl->cascading.template get<BackgroundPattern>().set(value, klass); - impl->observer->onLayerPaintPropertyChanged(*this); + auto impl_ = mutableImpl(); + impl_->cascading.template get<BackgroundPattern>().set(value, klass); + baseImpl = std::move(impl_); + observer->onLayerPaintPropertyChanged(*this); } void BackgroundLayer::setBackgroundPatternTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<BackgroundPattern>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<BackgroundPattern>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions BackgroundLayer::getBackgroundPatternTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<BackgroundPattern>().getTransition(klass); + return impl().cascading.template get<BackgroundPattern>().getTransition(klass); } PropertyValue<float> BackgroundLayer::getDefaultBackgroundOpacity() { @@ -91,22 +126,26 @@ PropertyValue<float> BackgroundLayer::getDefaultBackgroundOpacity() { } PropertyValue<float> BackgroundLayer::getBackgroundOpacity(const optional<std::string>& klass) const { - return impl->cascading.template get<BackgroundOpacity>().get(klass); + return impl().cascading.template get<BackgroundOpacity>().get(klass); } void BackgroundLayer::setBackgroundOpacity(PropertyValue<float> value, const optional<std::string>& klass) { if (value == getBackgroundOpacity(klass)) return; - impl->cascading.template get<BackgroundOpacity>().set(value, klass); - impl->observer->onLayerPaintPropertyChanged(*this); + auto impl_ = mutableImpl(); + impl_->cascading.template get<BackgroundOpacity>().set(value, klass); + baseImpl = std::move(impl_); + observer->onLayerPaintPropertyChanged(*this); } void BackgroundLayer::setBackgroundOpacityTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<BackgroundOpacity>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<BackgroundOpacity>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions BackgroundLayer::getBackgroundOpacityTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<BackgroundOpacity>().getTransition(klass); + return impl().cascading.template get<BackgroundOpacity>().getTransition(klass); } } // namespace style diff --git a/src/mbgl/style/layers/background_layer_impl.cpp b/src/mbgl/style/layers/background_layer_impl.cpp index 6c4a4c26d9..07249ec5a4 100644 --- a/src/mbgl/style/layers/background_layer_impl.cpp +++ b/src/mbgl/style/layers/background_layer_impl.cpp @@ -5,7 +5,7 @@ namespace mbgl { namespace style { std::unique_ptr<RenderLayer> BackgroundLayer::Impl::createRenderLayer() const { - return std::make_unique<RenderBackgroundLayer>(*this); + return std::make_unique<RenderBackgroundLayer>(staticImmutableCast<BackgroundLayer::Impl>(immutableFromThis())); } } // namespace style diff --git a/src/mbgl/style/layers/background_layer_impl.hpp b/src/mbgl/style/layers/background_layer_impl.hpp index 85152da4ec..41eee7bdf3 100644 --- a/src/mbgl/style/layers/background_layer_impl.hpp +++ b/src/mbgl/style/layers/background_layer_impl.hpp @@ -9,8 +9,8 @@ namespace style { 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; + using Layer::Impl::Impl; + void stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const override; std::unique_ptr<RenderLayer> createRenderLayer() const override; diff --git a/src/mbgl/style/layers/circle_layer.cpp b/src/mbgl/style/layers/circle_layer.cpp index 8b3431a9a1..6fcfe445a5 100644 --- a/src/mbgl/style/layers/circle_layer.cpp +++ b/src/mbgl/style/layers/circle_layer.cpp @@ -3,33 +3,34 @@ #include <mbgl/style/layers/circle_layer.hpp> #include <mbgl/style/layers/circle_layer_impl.hpp> #include <mbgl/style/conversion/stringify.hpp> +#include <mbgl/style/layer_observer.hpp> namespace mbgl { namespace style { CircleLayer::CircleLayer(const std::string& layerID, const std::string& sourceID) - : Layer(LayerType::Circle, std::make_unique<Impl>()) - , impl(static_cast<Impl*>(baseImpl.get())) { - impl->id = layerID; - impl->source = sourceID; + : Layer(makeMutable<Impl>(LayerType::Circle, layerID, sourceID)) { } -CircleLayer::CircleLayer(const Impl& other) - : Layer(LayerType::Circle, std::make_unique<Impl>(other)) - , impl(static_cast<Impl*>(baseImpl.get())) { +CircleLayer::CircleLayer(Immutable<Impl> impl_) + : Layer(std::move(impl_)) { } CircleLayer::~CircleLayer() = default; -std::unique_ptr<Layer> CircleLayer::Impl::clone() const { - return std::make_unique<CircleLayer>(*this); +const CircleLayer::Impl& CircleLayer::impl() const { + return static_cast<const Impl&>(*baseImpl); } -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->cascading = CirclePaintProperties::Cascading(); - return std::move(result); +Mutable<CircleLayer::Impl> CircleLayer::mutableImpl() const { + return makeMutable<Impl>(impl()); +} + +std::unique_ptr<Layer> CircleLayer::cloneRef(const std::string& id_) const { + auto impl_ = mutableImpl(); + impl_->id = id_; + impl_->cascading = CirclePaintProperties::Cascading(); + return std::make_unique<CircleLayer>(std::move(impl_)); } void CircleLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const { @@ -38,26 +39,55 @@ void CircleLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffe // Source const std::string& CircleLayer::getSourceID() const { - return impl->source; + return impl().source; } void CircleLayer::setSourceLayer(const std::string& sourceLayer) { - impl->sourceLayer = sourceLayer; + auto impl_ = mutableImpl(); + impl_->sourceLayer = sourceLayer; + baseImpl = std::move(impl_); } const std::string& CircleLayer::getSourceLayer() const { - return impl->sourceLayer; + return impl().sourceLayer; } // Filter void CircleLayer::setFilter(const Filter& filter) { - impl->filter = filter; - impl->observer->onLayerFilterChanged(*this); + auto impl_ = mutableImpl(); + impl_->filter = filter; + baseImpl = std::move(impl_); + observer->onLayerFilterChanged(*this); } const Filter& CircleLayer::getFilter() const { - return impl->filter; + return impl().filter; +} + +// Visibility + +void CircleLayer::setVisibility(VisibilityType value) { + if (value == getVisibility()) + return; + auto impl_ = mutableImpl(); + impl_->visibility = value; + baseImpl = std::move(impl_); + observer->onLayerVisibilityChanged(*this); +} + +// Zoom range + +void CircleLayer::setMinZoom(float minZoom) { + auto impl_ = mutableImpl(); + impl_->minZoom = minZoom; + baseImpl = std::move(impl_); +} + +void CircleLayer::setMaxZoom(float maxZoom) { + auto impl_ = mutableImpl(); + impl_->maxZoom = maxZoom; + baseImpl = std::move(impl_); } // Layout properties @@ -70,26 +100,30 @@ DataDrivenPropertyValue<float> CircleLayer::getDefaultCircleRadius() { } DataDrivenPropertyValue<float> CircleLayer::getCircleRadius(const optional<std::string>& klass) const { - return impl->cascading.template get<CircleRadius>().get(klass); + return impl().cascading.template get<CircleRadius>().get(klass); } void CircleLayer::setCircleRadius(DataDrivenPropertyValue<float> value, const optional<std::string>& klass) { if (value == getCircleRadius(klass)) return; - impl->cascading.template get<CircleRadius>().set(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<CircleRadius>().set(value, klass); + baseImpl = std::move(impl_); if (value.isDataDriven()) { - impl->observer->onLayerDataDrivenPaintPropertyChanged(*this); + observer->onLayerDataDrivenPaintPropertyChanged(*this); } else { - impl->observer->onLayerPaintPropertyChanged(*this); + observer->onLayerPaintPropertyChanged(*this); } } void CircleLayer::setCircleRadiusTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<CircleRadius>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<CircleRadius>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions CircleLayer::getCircleRadiusTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<CircleRadius>().getTransition(klass); + return impl().cascading.template get<CircleRadius>().getTransition(klass); } DataDrivenPropertyValue<Color> CircleLayer::getDefaultCircleColor() { @@ -97,26 +131,30 @@ DataDrivenPropertyValue<Color> CircleLayer::getDefaultCircleColor() { } DataDrivenPropertyValue<Color> CircleLayer::getCircleColor(const optional<std::string>& klass) const { - return impl->cascading.template get<CircleColor>().get(klass); + return impl().cascading.template get<CircleColor>().get(klass); } void CircleLayer::setCircleColor(DataDrivenPropertyValue<Color> value, const optional<std::string>& klass) { if (value == getCircleColor(klass)) return; - impl->cascading.template get<CircleColor>().set(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<CircleColor>().set(value, klass); + baseImpl = std::move(impl_); if (value.isDataDriven()) { - impl->observer->onLayerDataDrivenPaintPropertyChanged(*this); + observer->onLayerDataDrivenPaintPropertyChanged(*this); } else { - impl->observer->onLayerPaintPropertyChanged(*this); + observer->onLayerPaintPropertyChanged(*this); } } void CircleLayer::setCircleColorTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<CircleColor>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<CircleColor>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions CircleLayer::getCircleColorTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<CircleColor>().getTransition(klass); + return impl().cascading.template get<CircleColor>().getTransition(klass); } DataDrivenPropertyValue<float> CircleLayer::getDefaultCircleBlur() { @@ -124,26 +162,30 @@ DataDrivenPropertyValue<float> CircleLayer::getDefaultCircleBlur() { } DataDrivenPropertyValue<float> CircleLayer::getCircleBlur(const optional<std::string>& klass) const { - return impl->cascading.template get<CircleBlur>().get(klass); + return impl().cascading.template get<CircleBlur>().get(klass); } void CircleLayer::setCircleBlur(DataDrivenPropertyValue<float> value, const optional<std::string>& klass) { if (value == getCircleBlur(klass)) return; - impl->cascading.template get<CircleBlur>().set(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<CircleBlur>().set(value, klass); + baseImpl = std::move(impl_); if (value.isDataDriven()) { - impl->observer->onLayerDataDrivenPaintPropertyChanged(*this); + observer->onLayerDataDrivenPaintPropertyChanged(*this); } else { - impl->observer->onLayerPaintPropertyChanged(*this); + observer->onLayerPaintPropertyChanged(*this); } } void CircleLayer::setCircleBlurTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<CircleBlur>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<CircleBlur>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions CircleLayer::getCircleBlurTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<CircleBlur>().getTransition(klass); + return impl().cascading.template get<CircleBlur>().getTransition(klass); } DataDrivenPropertyValue<float> CircleLayer::getDefaultCircleOpacity() { @@ -151,26 +193,30 @@ DataDrivenPropertyValue<float> CircleLayer::getDefaultCircleOpacity() { } DataDrivenPropertyValue<float> CircleLayer::getCircleOpacity(const optional<std::string>& klass) const { - return impl->cascading.template get<CircleOpacity>().get(klass); + return impl().cascading.template get<CircleOpacity>().get(klass); } void CircleLayer::setCircleOpacity(DataDrivenPropertyValue<float> value, const optional<std::string>& klass) { if (value == getCircleOpacity(klass)) return; - impl->cascading.template get<CircleOpacity>().set(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<CircleOpacity>().set(value, klass); + baseImpl = std::move(impl_); if (value.isDataDriven()) { - impl->observer->onLayerDataDrivenPaintPropertyChanged(*this); + observer->onLayerDataDrivenPaintPropertyChanged(*this); } else { - impl->observer->onLayerPaintPropertyChanged(*this); + observer->onLayerPaintPropertyChanged(*this); } } void CircleLayer::setCircleOpacityTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<CircleOpacity>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<CircleOpacity>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions CircleLayer::getCircleOpacityTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<CircleOpacity>().getTransition(klass); + return impl().cascading.template get<CircleOpacity>().getTransition(klass); } PropertyValue<std::array<float, 2>> CircleLayer::getDefaultCircleTranslate() { @@ -178,22 +224,26 @@ PropertyValue<std::array<float, 2>> CircleLayer::getDefaultCircleTranslate() { } PropertyValue<std::array<float, 2>> CircleLayer::getCircleTranslate(const optional<std::string>& klass) const { - return impl->cascading.template get<CircleTranslate>().get(klass); + return impl().cascading.template get<CircleTranslate>().get(klass); } void CircleLayer::setCircleTranslate(PropertyValue<std::array<float, 2>> value, const optional<std::string>& klass) { if (value == getCircleTranslate(klass)) return; - impl->cascading.template get<CircleTranslate>().set(value, klass); - impl->observer->onLayerPaintPropertyChanged(*this); + auto impl_ = mutableImpl(); + impl_->cascading.template get<CircleTranslate>().set(value, klass); + baseImpl = std::move(impl_); + observer->onLayerPaintPropertyChanged(*this); } void CircleLayer::setCircleTranslateTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<CircleTranslate>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<CircleTranslate>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions CircleLayer::getCircleTranslateTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<CircleTranslate>().getTransition(klass); + return impl().cascading.template get<CircleTranslate>().getTransition(klass); } PropertyValue<TranslateAnchorType> CircleLayer::getDefaultCircleTranslateAnchor() { @@ -201,22 +251,26 @@ PropertyValue<TranslateAnchorType> CircleLayer::getDefaultCircleTranslateAnchor( } PropertyValue<TranslateAnchorType> CircleLayer::getCircleTranslateAnchor(const optional<std::string>& klass) const { - return impl->cascading.template get<CircleTranslateAnchor>().get(klass); + return impl().cascading.template get<CircleTranslateAnchor>().get(klass); } void CircleLayer::setCircleTranslateAnchor(PropertyValue<TranslateAnchorType> value, const optional<std::string>& klass) { if (value == getCircleTranslateAnchor(klass)) return; - impl->cascading.template get<CircleTranslateAnchor>().set(value, klass); - impl->observer->onLayerPaintPropertyChanged(*this); + auto impl_ = mutableImpl(); + impl_->cascading.template get<CircleTranslateAnchor>().set(value, klass); + baseImpl = std::move(impl_); + observer->onLayerPaintPropertyChanged(*this); } void CircleLayer::setCircleTranslateAnchorTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<CircleTranslateAnchor>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<CircleTranslateAnchor>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions CircleLayer::getCircleTranslateAnchorTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<CircleTranslateAnchor>().getTransition(klass); + return impl().cascading.template get<CircleTranslateAnchor>().getTransition(klass); } PropertyValue<CirclePitchScaleType> CircleLayer::getDefaultCirclePitchScale() { @@ -224,22 +278,26 @@ PropertyValue<CirclePitchScaleType> CircleLayer::getDefaultCirclePitchScale() { } PropertyValue<CirclePitchScaleType> CircleLayer::getCirclePitchScale(const optional<std::string>& klass) const { - return impl->cascading.template get<CirclePitchScale>().get(klass); + return impl().cascading.template get<CirclePitchScale>().get(klass); } void CircleLayer::setCirclePitchScale(PropertyValue<CirclePitchScaleType> value, const optional<std::string>& klass) { if (value == getCirclePitchScale(klass)) return; - impl->cascading.template get<CirclePitchScale>().set(value, klass); - impl->observer->onLayerPaintPropertyChanged(*this); + auto impl_ = mutableImpl(); + impl_->cascading.template get<CirclePitchScale>().set(value, klass); + baseImpl = std::move(impl_); + observer->onLayerPaintPropertyChanged(*this); } void CircleLayer::setCirclePitchScaleTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<CirclePitchScale>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<CirclePitchScale>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions CircleLayer::getCirclePitchScaleTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<CirclePitchScale>().getTransition(klass); + return impl().cascading.template get<CirclePitchScale>().getTransition(klass); } DataDrivenPropertyValue<float> CircleLayer::getDefaultCircleStrokeWidth() { @@ -247,26 +305,30 @@ DataDrivenPropertyValue<float> CircleLayer::getDefaultCircleStrokeWidth() { } DataDrivenPropertyValue<float> CircleLayer::getCircleStrokeWidth(const optional<std::string>& klass) const { - return impl->cascading.template get<CircleStrokeWidth>().get(klass); + return impl().cascading.template get<CircleStrokeWidth>().get(klass); } void CircleLayer::setCircleStrokeWidth(DataDrivenPropertyValue<float> value, const optional<std::string>& klass) { if (value == getCircleStrokeWidth(klass)) return; - impl->cascading.template get<CircleStrokeWidth>().set(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<CircleStrokeWidth>().set(value, klass); + baseImpl = std::move(impl_); if (value.isDataDriven()) { - impl->observer->onLayerDataDrivenPaintPropertyChanged(*this); + observer->onLayerDataDrivenPaintPropertyChanged(*this); } else { - impl->observer->onLayerPaintPropertyChanged(*this); + observer->onLayerPaintPropertyChanged(*this); } } void CircleLayer::setCircleStrokeWidthTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<CircleStrokeWidth>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<CircleStrokeWidth>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions CircleLayer::getCircleStrokeWidthTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<CircleStrokeWidth>().getTransition(klass); + return impl().cascading.template get<CircleStrokeWidth>().getTransition(klass); } DataDrivenPropertyValue<Color> CircleLayer::getDefaultCircleStrokeColor() { @@ -274,26 +336,30 @@ DataDrivenPropertyValue<Color> CircleLayer::getDefaultCircleStrokeColor() { } DataDrivenPropertyValue<Color> CircleLayer::getCircleStrokeColor(const optional<std::string>& klass) const { - return impl->cascading.template get<CircleStrokeColor>().get(klass); + return impl().cascading.template get<CircleStrokeColor>().get(klass); } void CircleLayer::setCircleStrokeColor(DataDrivenPropertyValue<Color> value, const optional<std::string>& klass) { if (value == getCircleStrokeColor(klass)) return; - impl->cascading.template get<CircleStrokeColor>().set(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<CircleStrokeColor>().set(value, klass); + baseImpl = std::move(impl_); if (value.isDataDriven()) { - impl->observer->onLayerDataDrivenPaintPropertyChanged(*this); + observer->onLayerDataDrivenPaintPropertyChanged(*this); } else { - impl->observer->onLayerPaintPropertyChanged(*this); + observer->onLayerPaintPropertyChanged(*this); } } void CircleLayer::setCircleStrokeColorTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<CircleStrokeColor>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<CircleStrokeColor>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions CircleLayer::getCircleStrokeColorTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<CircleStrokeColor>().getTransition(klass); + return impl().cascading.template get<CircleStrokeColor>().getTransition(klass); } DataDrivenPropertyValue<float> CircleLayer::getDefaultCircleStrokeOpacity() { @@ -301,26 +367,30 @@ DataDrivenPropertyValue<float> CircleLayer::getDefaultCircleStrokeOpacity() { } DataDrivenPropertyValue<float> CircleLayer::getCircleStrokeOpacity(const optional<std::string>& klass) const { - return impl->cascading.template get<CircleStrokeOpacity>().get(klass); + return impl().cascading.template get<CircleStrokeOpacity>().get(klass); } void CircleLayer::setCircleStrokeOpacity(DataDrivenPropertyValue<float> value, const optional<std::string>& klass) { if (value == getCircleStrokeOpacity(klass)) return; - impl->cascading.template get<CircleStrokeOpacity>().set(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<CircleStrokeOpacity>().set(value, klass); + baseImpl = std::move(impl_); if (value.isDataDriven()) { - impl->observer->onLayerDataDrivenPaintPropertyChanged(*this); + observer->onLayerDataDrivenPaintPropertyChanged(*this); } else { - impl->observer->onLayerPaintPropertyChanged(*this); + observer->onLayerPaintPropertyChanged(*this); } } void CircleLayer::setCircleStrokeOpacityTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<CircleStrokeOpacity>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<CircleStrokeOpacity>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions CircleLayer::getCircleStrokeOpacityTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<CircleStrokeOpacity>().getTransition(klass); + return impl().cascading.template get<CircleStrokeOpacity>().getTransition(klass); } } // namespace style diff --git a/src/mbgl/style/layers/circle_layer_impl.cpp b/src/mbgl/style/layers/circle_layer_impl.cpp index 31b286f273..8df79507bf 100644 --- a/src/mbgl/style/layers/circle_layer_impl.cpp +++ b/src/mbgl/style/layers/circle_layer_impl.cpp @@ -5,7 +5,7 @@ namespace mbgl { namespace style { std::unique_ptr<RenderLayer> CircleLayer::Impl::createRenderLayer() const { - return std::make_unique<RenderCircleLayer>(*this); + return std::make_unique<RenderCircleLayer>(staticImmutableCast<CircleLayer::Impl>(immutableFromThis())); } } // namespace style diff --git a/src/mbgl/style/layers/circle_layer_impl.hpp b/src/mbgl/style/layers/circle_layer_impl.hpp index 886815f0d1..94fa24b811 100644 --- a/src/mbgl/style/layers/circle_layer_impl.hpp +++ b/src/mbgl/style/layers/circle_layer_impl.hpp @@ -9,8 +9,8 @@ namespace style { 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; + using Layer::Impl::Impl; + void stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const override; std::unique_ptr<RenderLayer> createRenderLayer() const override; diff --git a/src/mbgl/style/layers/custom_layer.cpp b/src/mbgl/style/layers/custom_layer.cpp index cda8a157f0..f7c349b3d8 100644 --- a/src/mbgl/style/layers/custom_layer.cpp +++ b/src/mbgl/style/layers/custom_layer.cpp @@ -1,6 +1,6 @@ #include <mbgl/style/layers/custom_layer.hpp> #include <mbgl/style/layers/custom_layer_impl.hpp> -#include <mbgl/util/logging.hpp> +#include <mbgl/style/layer_observer.hpp> namespace mbgl { namespace style { @@ -10,21 +10,52 @@ CustomLayer::CustomLayer(const std::string& layerID, CustomLayerRenderFunction render, CustomLayerDeinitializeFunction deinit, void* context) - : Layer(LayerType::Custom, std::make_unique<Impl>(layerID, init, render, deinit, context)) - , impl(static_cast<Impl*>(baseImpl.get())) { - Log::Info(Event::General, "New custom layer: %s", layerID.c_str()); + : Layer(makeMutable<Impl>(layerID, init, render, deinit, context)) { } -CustomLayer::CustomLayer(const Impl& other) - : Layer(LayerType::Custom, std::make_unique<Impl>(other)) - , impl(static_cast<Impl*>(baseImpl.get())) { +CustomLayer::~CustomLayer() = default; + +const CustomLayer::Impl& CustomLayer::impl() const { + return static_cast<const Impl&>(*baseImpl); } -CustomLayer::~CustomLayer() = default; +Mutable<CustomLayer::Impl> CustomLayer::mutableImpl() const { + return makeMutable<Impl>(impl()); +} + +std::unique_ptr<Layer> CustomLayer::cloneRef(const std::string&) const { + assert(false); + return nullptr; +} + +// Visibility + +void CustomLayer::setVisibility(VisibilityType value) { + if (value == getVisibility()) + return; + auto impl_ = mutableImpl(); + impl_->visibility = value; + baseImpl = std::move(impl_); + observer->onLayerVisibilityChanged(*this); +} + +// Zoom range + +void CustomLayer::setMinZoom(float minZoom) { + auto impl_ = mutableImpl(); + impl_->minZoom = minZoom; + baseImpl = std::move(impl_); +} + +void CustomLayer::setMaxZoom(float maxZoom) { + auto impl_ = mutableImpl(); + impl_->maxZoom = maxZoom; + baseImpl = std::move(impl_); +} template <> bool Layer::is<CustomLayer>() const { - return type == LayerType::Custom; + return getType() == LayerType::Custom; } } // namespace style diff --git a/src/mbgl/style/layers/custom_layer_impl.cpp b/src/mbgl/style/layers/custom_layer_impl.cpp index 1d3e9af8d6..e459b57171 100644 --- a/src/mbgl/style/layers/custom_layer_impl.cpp +++ b/src/mbgl/style/layers/custom_layer_impl.cpp @@ -2,52 +2,36 @@ #include <mbgl/renderer/render_custom_layer.hpp> #include <mbgl/map/transform_state.hpp> #include <mbgl/util/logging.hpp> + namespace mbgl { namespace style { std::unique_ptr<RenderLayer> CustomLayer::Impl::createRenderLayer() const { - return std::make_unique<RenderCustomLayer>(*this); + return std::make_unique<RenderCustomLayer>(staticImmutableCast<CustomLayer::Impl>(immutableFromThis())); } CustomLayer::Impl::Impl(const std::string& id_, CustomLayerInitializeFunction initializeFn_, CustomLayerRenderFunction renderFn_, CustomLayerDeinitializeFunction deinitializeFn_, - void* context_) { + void* context_) + : Layer::Impl(LayerType::Custom, id_, std::string()) { Log::Info(Event::General, "New custom layer Impl: %s", id_.c_str()); - id = id_; initializeFn = initializeFn_; renderFn = renderFn_; deinitializeFn = deinitializeFn_; context = context_; } -CustomLayer::Impl::Impl(const CustomLayer::Impl &other) - : Layer::Impl(other) { - id = other.id; - // Don't copy anything else. -} - -CustomLayer::Impl::~Impl() = default; - -std::unique_ptr<Layer> CustomLayer::Impl::clone() const { - return std::make_unique<CustomLayer>(*this); -} - -std::unique_ptr<Layer> CustomLayer::Impl::cloneRef(const std::string&) const { - assert(false); - return std::make_unique<CustomLayer>(*this); -} - void CustomLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const { } -void CustomLayer::Impl::initialize() { +void CustomLayer::Impl::initialize() const { assert(initializeFn); initializeFn(context); } -void CustomLayer::Impl::deinitialize() { +void CustomLayer::Impl::deinitialize() const { if (deinitializeFn) { deinitializeFn(context); } diff --git a/src/mbgl/style/layers/custom_layer_impl.hpp b/src/mbgl/style/layers/custom_layer_impl.hpp index e612d17f14..f921f47d59 100644 --- a/src/mbgl/style/layers/custom_layer_impl.hpp +++ b/src/mbgl/style/layers/custom_layer_impl.hpp @@ -17,16 +17,11 @@ public: CustomLayerDeinitializeFunction, void* context); - Impl(const Impl&); - ~Impl() final; - - void initialize(); - void deinitialize(); + void initialize() const; + void deinitialize() const; void render(const TransformState&) const; 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; std::unique_ptr<RenderLayer> createRenderLayer() const final; diff --git a/src/mbgl/style/layers/fill_extrusion_layer.cpp b/src/mbgl/style/layers/fill_extrusion_layer.cpp index 6f11d6052c..78a348f5c4 100644 --- a/src/mbgl/style/layers/fill_extrusion_layer.cpp +++ b/src/mbgl/style/layers/fill_extrusion_layer.cpp @@ -3,33 +3,34 @@ #include <mbgl/style/layers/fill_extrusion_layer.hpp> #include <mbgl/style/layers/fill_extrusion_layer_impl.hpp> #include <mbgl/style/conversion/stringify.hpp> +#include <mbgl/style/layer_observer.hpp> namespace mbgl { namespace style { FillExtrusionLayer::FillExtrusionLayer(const std::string& layerID, const std::string& sourceID) - : Layer(LayerType::FillExtrusion, std::make_unique<Impl>()) - , impl(static_cast<Impl*>(baseImpl.get())) { - impl->id = layerID; - impl->source = sourceID; + : Layer(makeMutable<Impl>(LayerType::FillExtrusion, layerID, sourceID)) { } -FillExtrusionLayer::FillExtrusionLayer(const Impl& other) - : Layer(LayerType::FillExtrusion, std::make_unique<Impl>(other)) - , impl(static_cast<Impl*>(baseImpl.get())) { +FillExtrusionLayer::FillExtrusionLayer(Immutable<Impl> impl_) + : Layer(std::move(impl_)) { } FillExtrusionLayer::~FillExtrusionLayer() = default; -std::unique_ptr<Layer> FillExtrusionLayer::Impl::clone() const { - return std::make_unique<FillExtrusionLayer>(*this); +const FillExtrusionLayer::Impl& FillExtrusionLayer::impl() const { + return static_cast<const Impl&>(*baseImpl); } -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->cascading = FillExtrusionPaintProperties::Cascading(); - return std::move(result); +Mutable<FillExtrusionLayer::Impl> FillExtrusionLayer::mutableImpl() const { + return makeMutable<Impl>(impl()); +} + +std::unique_ptr<Layer> FillExtrusionLayer::cloneRef(const std::string& id_) const { + auto impl_ = mutableImpl(); + impl_->id = id_; + impl_->cascading = FillExtrusionPaintProperties::Cascading(); + return std::make_unique<FillExtrusionLayer>(std::move(impl_)); } void FillExtrusionLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const { @@ -38,26 +39,55 @@ void FillExtrusionLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::Stri // Source const std::string& FillExtrusionLayer::getSourceID() const { - return impl->source; + return impl().source; } void FillExtrusionLayer::setSourceLayer(const std::string& sourceLayer) { - impl->sourceLayer = sourceLayer; + auto impl_ = mutableImpl(); + impl_->sourceLayer = sourceLayer; + baseImpl = std::move(impl_); } const std::string& FillExtrusionLayer::getSourceLayer() const { - return impl->sourceLayer; + return impl().sourceLayer; } // Filter void FillExtrusionLayer::setFilter(const Filter& filter) { - impl->filter = filter; - impl->observer->onLayerFilterChanged(*this); + auto impl_ = mutableImpl(); + impl_->filter = filter; + baseImpl = std::move(impl_); + observer->onLayerFilterChanged(*this); } const Filter& FillExtrusionLayer::getFilter() const { - return impl->filter; + return impl().filter; +} + +// Visibility + +void FillExtrusionLayer::setVisibility(VisibilityType value) { + if (value == getVisibility()) + return; + auto impl_ = mutableImpl(); + impl_->visibility = value; + baseImpl = std::move(impl_); + observer->onLayerVisibilityChanged(*this); +} + +// Zoom range + +void FillExtrusionLayer::setMinZoom(float minZoom) { + auto impl_ = mutableImpl(); + impl_->minZoom = minZoom; + baseImpl = std::move(impl_); +} + +void FillExtrusionLayer::setMaxZoom(float maxZoom) { + auto impl_ = mutableImpl(); + impl_->maxZoom = maxZoom; + baseImpl = std::move(impl_); } // Layout properties @@ -70,22 +100,26 @@ PropertyValue<float> FillExtrusionLayer::getDefaultFillExtrusionOpacity() { } PropertyValue<float> FillExtrusionLayer::getFillExtrusionOpacity(const optional<std::string>& klass) const { - return impl->cascading.template get<FillExtrusionOpacity>().get(klass); + return impl().cascading.template get<FillExtrusionOpacity>().get(klass); } void FillExtrusionLayer::setFillExtrusionOpacity(PropertyValue<float> value, const optional<std::string>& klass) { if (value == getFillExtrusionOpacity(klass)) return; - impl->cascading.template get<FillExtrusionOpacity>().set(value, klass); - impl->observer->onLayerPaintPropertyChanged(*this); + auto impl_ = mutableImpl(); + impl_->cascading.template get<FillExtrusionOpacity>().set(value, klass); + baseImpl = std::move(impl_); + observer->onLayerPaintPropertyChanged(*this); } void FillExtrusionLayer::setFillExtrusionOpacityTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<FillExtrusionOpacity>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<FillExtrusionOpacity>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions FillExtrusionLayer::getFillExtrusionOpacityTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<FillExtrusionOpacity>().getTransition(klass); + return impl().cascading.template get<FillExtrusionOpacity>().getTransition(klass); } DataDrivenPropertyValue<Color> FillExtrusionLayer::getDefaultFillExtrusionColor() { @@ -93,26 +127,30 @@ DataDrivenPropertyValue<Color> FillExtrusionLayer::getDefaultFillExtrusionColor( } DataDrivenPropertyValue<Color> FillExtrusionLayer::getFillExtrusionColor(const optional<std::string>& klass) const { - return impl->cascading.template get<FillExtrusionColor>().get(klass); + return impl().cascading.template get<FillExtrusionColor>().get(klass); } void FillExtrusionLayer::setFillExtrusionColor(DataDrivenPropertyValue<Color> value, const optional<std::string>& klass) { if (value == getFillExtrusionColor(klass)) return; - impl->cascading.template get<FillExtrusionColor>().set(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<FillExtrusionColor>().set(value, klass); + baseImpl = std::move(impl_); if (value.isDataDriven()) { - impl->observer->onLayerDataDrivenPaintPropertyChanged(*this); + observer->onLayerDataDrivenPaintPropertyChanged(*this); } else { - impl->observer->onLayerPaintPropertyChanged(*this); + observer->onLayerPaintPropertyChanged(*this); } } void FillExtrusionLayer::setFillExtrusionColorTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<FillExtrusionColor>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<FillExtrusionColor>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions FillExtrusionLayer::getFillExtrusionColorTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<FillExtrusionColor>().getTransition(klass); + return impl().cascading.template get<FillExtrusionColor>().getTransition(klass); } PropertyValue<std::array<float, 2>> FillExtrusionLayer::getDefaultFillExtrusionTranslate() { @@ -120,22 +158,26 @@ PropertyValue<std::array<float, 2>> FillExtrusionLayer::getDefaultFillExtrusionT } PropertyValue<std::array<float, 2>> FillExtrusionLayer::getFillExtrusionTranslate(const optional<std::string>& klass) const { - return impl->cascading.template get<FillExtrusionTranslate>().get(klass); + return impl().cascading.template get<FillExtrusionTranslate>().get(klass); } void FillExtrusionLayer::setFillExtrusionTranslate(PropertyValue<std::array<float, 2>> value, const optional<std::string>& klass) { if (value == getFillExtrusionTranslate(klass)) return; - impl->cascading.template get<FillExtrusionTranslate>().set(value, klass); - impl->observer->onLayerPaintPropertyChanged(*this); + auto impl_ = mutableImpl(); + impl_->cascading.template get<FillExtrusionTranslate>().set(value, klass); + baseImpl = std::move(impl_); + observer->onLayerPaintPropertyChanged(*this); } void FillExtrusionLayer::setFillExtrusionTranslateTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<FillExtrusionTranslate>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<FillExtrusionTranslate>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions FillExtrusionLayer::getFillExtrusionTranslateTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<FillExtrusionTranslate>().getTransition(klass); + return impl().cascading.template get<FillExtrusionTranslate>().getTransition(klass); } PropertyValue<TranslateAnchorType> FillExtrusionLayer::getDefaultFillExtrusionTranslateAnchor() { @@ -143,22 +185,26 @@ PropertyValue<TranslateAnchorType> FillExtrusionLayer::getDefaultFillExtrusionTr } PropertyValue<TranslateAnchorType> FillExtrusionLayer::getFillExtrusionTranslateAnchor(const optional<std::string>& klass) const { - return impl->cascading.template get<FillExtrusionTranslateAnchor>().get(klass); + return impl().cascading.template get<FillExtrusionTranslateAnchor>().get(klass); } void FillExtrusionLayer::setFillExtrusionTranslateAnchor(PropertyValue<TranslateAnchorType> value, const optional<std::string>& klass) { if (value == getFillExtrusionTranslateAnchor(klass)) return; - impl->cascading.template get<FillExtrusionTranslateAnchor>().set(value, klass); - impl->observer->onLayerPaintPropertyChanged(*this); + auto impl_ = mutableImpl(); + impl_->cascading.template get<FillExtrusionTranslateAnchor>().set(value, klass); + baseImpl = std::move(impl_); + observer->onLayerPaintPropertyChanged(*this); } void FillExtrusionLayer::setFillExtrusionTranslateAnchorTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<FillExtrusionTranslateAnchor>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<FillExtrusionTranslateAnchor>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions FillExtrusionLayer::getFillExtrusionTranslateAnchorTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<FillExtrusionTranslateAnchor>().getTransition(klass); + return impl().cascading.template get<FillExtrusionTranslateAnchor>().getTransition(klass); } PropertyValue<std::string> FillExtrusionLayer::getDefaultFillExtrusionPattern() { @@ -166,22 +212,26 @@ PropertyValue<std::string> FillExtrusionLayer::getDefaultFillExtrusionPattern() } PropertyValue<std::string> FillExtrusionLayer::getFillExtrusionPattern(const optional<std::string>& klass) const { - return impl->cascading.template get<FillExtrusionPattern>().get(klass); + return impl().cascading.template get<FillExtrusionPattern>().get(klass); } void FillExtrusionLayer::setFillExtrusionPattern(PropertyValue<std::string> value, const optional<std::string>& klass) { if (value == getFillExtrusionPattern(klass)) return; - impl->cascading.template get<FillExtrusionPattern>().set(value, klass); - impl->observer->onLayerPaintPropertyChanged(*this); + auto impl_ = mutableImpl(); + impl_->cascading.template get<FillExtrusionPattern>().set(value, klass); + baseImpl = std::move(impl_); + observer->onLayerPaintPropertyChanged(*this); } void FillExtrusionLayer::setFillExtrusionPatternTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<FillExtrusionPattern>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<FillExtrusionPattern>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions FillExtrusionLayer::getFillExtrusionPatternTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<FillExtrusionPattern>().getTransition(klass); + return impl().cascading.template get<FillExtrusionPattern>().getTransition(klass); } DataDrivenPropertyValue<float> FillExtrusionLayer::getDefaultFillExtrusionHeight() { @@ -189,26 +239,30 @@ DataDrivenPropertyValue<float> FillExtrusionLayer::getDefaultFillExtrusionHeight } DataDrivenPropertyValue<float> FillExtrusionLayer::getFillExtrusionHeight(const optional<std::string>& klass) const { - return impl->cascading.template get<FillExtrusionHeight>().get(klass); + return impl().cascading.template get<FillExtrusionHeight>().get(klass); } void FillExtrusionLayer::setFillExtrusionHeight(DataDrivenPropertyValue<float> value, const optional<std::string>& klass) { if (value == getFillExtrusionHeight(klass)) return; - impl->cascading.template get<FillExtrusionHeight>().set(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<FillExtrusionHeight>().set(value, klass); + baseImpl = std::move(impl_); if (value.isDataDriven()) { - impl->observer->onLayerDataDrivenPaintPropertyChanged(*this); + observer->onLayerDataDrivenPaintPropertyChanged(*this); } else { - impl->observer->onLayerPaintPropertyChanged(*this); + observer->onLayerPaintPropertyChanged(*this); } } void FillExtrusionLayer::setFillExtrusionHeightTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<FillExtrusionHeight>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<FillExtrusionHeight>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions FillExtrusionLayer::getFillExtrusionHeightTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<FillExtrusionHeight>().getTransition(klass); + return impl().cascading.template get<FillExtrusionHeight>().getTransition(klass); } DataDrivenPropertyValue<float> FillExtrusionLayer::getDefaultFillExtrusionBase() { @@ -216,26 +270,30 @@ DataDrivenPropertyValue<float> FillExtrusionLayer::getDefaultFillExtrusionBase() } DataDrivenPropertyValue<float> FillExtrusionLayer::getFillExtrusionBase(const optional<std::string>& klass) const { - return impl->cascading.template get<FillExtrusionBase>().get(klass); + return impl().cascading.template get<FillExtrusionBase>().get(klass); } void FillExtrusionLayer::setFillExtrusionBase(DataDrivenPropertyValue<float> value, const optional<std::string>& klass) { if (value == getFillExtrusionBase(klass)) return; - impl->cascading.template get<FillExtrusionBase>().set(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<FillExtrusionBase>().set(value, klass); + baseImpl = std::move(impl_); if (value.isDataDriven()) { - impl->observer->onLayerDataDrivenPaintPropertyChanged(*this); + observer->onLayerDataDrivenPaintPropertyChanged(*this); } else { - impl->observer->onLayerPaintPropertyChanged(*this); + observer->onLayerPaintPropertyChanged(*this); } } void FillExtrusionLayer::setFillExtrusionBaseTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<FillExtrusionBase>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<FillExtrusionBase>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions FillExtrusionLayer::getFillExtrusionBaseTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<FillExtrusionBase>().getTransition(klass); + return impl().cascading.template get<FillExtrusionBase>().getTransition(klass); } } // namespace style diff --git a/src/mbgl/style/layers/fill_extrusion_layer_impl.cpp b/src/mbgl/style/layers/fill_extrusion_layer_impl.cpp index 5340541221..9530e45b7f 100644 --- a/src/mbgl/style/layers/fill_extrusion_layer_impl.cpp +++ b/src/mbgl/style/layers/fill_extrusion_layer_impl.cpp @@ -5,7 +5,7 @@ namespace mbgl { namespace style { std::unique_ptr<RenderLayer> FillExtrusionLayer::Impl::createRenderLayer() const { - return std::make_unique<RenderFillExtrusionLayer>(*this); + return std::make_unique<RenderFillExtrusionLayer>(staticImmutableCast<FillExtrusionLayer::Impl>(immutableFromThis())); } } // namespace style diff --git a/src/mbgl/style/layers/fill_extrusion_layer_impl.hpp b/src/mbgl/style/layers/fill_extrusion_layer_impl.hpp index 2353bd99fe..167d28e973 100644 --- a/src/mbgl/style/layers/fill_extrusion_layer_impl.hpp +++ b/src/mbgl/style/layers/fill_extrusion_layer_impl.hpp @@ -9,8 +9,8 @@ namespace style { 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; + using Layer::Impl::Impl; + void stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const override; std::unique_ptr<RenderLayer> createRenderLayer() const override; diff --git a/src/mbgl/style/layers/fill_layer.cpp b/src/mbgl/style/layers/fill_layer.cpp index 9fd9d33af3..39f476c974 100644 --- a/src/mbgl/style/layers/fill_layer.cpp +++ b/src/mbgl/style/layers/fill_layer.cpp @@ -3,33 +3,34 @@ #include <mbgl/style/layers/fill_layer.hpp> #include <mbgl/style/layers/fill_layer_impl.hpp> #include <mbgl/style/conversion/stringify.hpp> +#include <mbgl/style/layer_observer.hpp> namespace mbgl { namespace style { FillLayer::FillLayer(const std::string& layerID, const std::string& sourceID) - : Layer(LayerType::Fill, std::make_unique<Impl>()) - , impl(static_cast<Impl*>(baseImpl.get())) { - impl->id = layerID; - impl->source = sourceID; + : Layer(makeMutable<Impl>(LayerType::Fill, layerID, sourceID)) { } -FillLayer::FillLayer(const Impl& other) - : Layer(LayerType::Fill, std::make_unique<Impl>(other)) - , impl(static_cast<Impl*>(baseImpl.get())) { +FillLayer::FillLayer(Immutable<Impl> impl_) + : Layer(std::move(impl_)) { } FillLayer::~FillLayer() = default; -std::unique_ptr<Layer> FillLayer::Impl::clone() const { - return std::make_unique<FillLayer>(*this); +const FillLayer::Impl& FillLayer::impl() const { + return static_cast<const Impl&>(*baseImpl); } -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->cascading = FillPaintProperties::Cascading(); - return std::move(result); +Mutable<FillLayer::Impl> FillLayer::mutableImpl() const { + return makeMutable<Impl>(impl()); +} + +std::unique_ptr<Layer> FillLayer::cloneRef(const std::string& id_) const { + auto impl_ = mutableImpl(); + impl_->id = id_; + impl_->cascading = FillPaintProperties::Cascading(); + return std::make_unique<FillLayer>(std::move(impl_)); } void FillLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const { @@ -38,26 +39,55 @@ void FillLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer> // Source const std::string& FillLayer::getSourceID() const { - return impl->source; + return impl().source; } void FillLayer::setSourceLayer(const std::string& sourceLayer) { - impl->sourceLayer = sourceLayer; + auto impl_ = mutableImpl(); + impl_->sourceLayer = sourceLayer; + baseImpl = std::move(impl_); } const std::string& FillLayer::getSourceLayer() const { - return impl->sourceLayer; + return impl().sourceLayer; } // Filter void FillLayer::setFilter(const Filter& filter) { - impl->filter = filter; - impl->observer->onLayerFilterChanged(*this); + auto impl_ = mutableImpl(); + impl_->filter = filter; + baseImpl = std::move(impl_); + observer->onLayerFilterChanged(*this); } const Filter& FillLayer::getFilter() const { - return impl->filter; + return impl().filter; +} + +// Visibility + +void FillLayer::setVisibility(VisibilityType value) { + if (value == getVisibility()) + return; + auto impl_ = mutableImpl(); + impl_->visibility = value; + baseImpl = std::move(impl_); + observer->onLayerVisibilityChanged(*this); +} + +// Zoom range + +void FillLayer::setMinZoom(float minZoom) { + auto impl_ = mutableImpl(); + impl_->minZoom = minZoom; + baseImpl = std::move(impl_); +} + +void FillLayer::setMaxZoom(float maxZoom) { + auto impl_ = mutableImpl(); + impl_->maxZoom = maxZoom; + baseImpl = std::move(impl_); } // Layout properties @@ -70,22 +100,26 @@ PropertyValue<bool> FillLayer::getDefaultFillAntialias() { } PropertyValue<bool> FillLayer::getFillAntialias(const optional<std::string>& klass) const { - return impl->cascading.template get<FillAntialias>().get(klass); + return impl().cascading.template get<FillAntialias>().get(klass); } void FillLayer::setFillAntialias(PropertyValue<bool> value, const optional<std::string>& klass) { if (value == getFillAntialias(klass)) return; - impl->cascading.template get<FillAntialias>().set(value, klass); - impl->observer->onLayerPaintPropertyChanged(*this); + auto impl_ = mutableImpl(); + impl_->cascading.template get<FillAntialias>().set(value, klass); + baseImpl = std::move(impl_); + observer->onLayerPaintPropertyChanged(*this); } void FillLayer::setFillAntialiasTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<FillAntialias>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<FillAntialias>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions FillLayer::getFillAntialiasTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<FillAntialias>().getTransition(klass); + return impl().cascading.template get<FillAntialias>().getTransition(klass); } DataDrivenPropertyValue<float> FillLayer::getDefaultFillOpacity() { @@ -93,26 +127,30 @@ DataDrivenPropertyValue<float> FillLayer::getDefaultFillOpacity() { } DataDrivenPropertyValue<float> FillLayer::getFillOpacity(const optional<std::string>& klass) const { - return impl->cascading.template get<FillOpacity>().get(klass); + return impl().cascading.template get<FillOpacity>().get(klass); } void FillLayer::setFillOpacity(DataDrivenPropertyValue<float> value, const optional<std::string>& klass) { if (value == getFillOpacity(klass)) return; - impl->cascading.template get<FillOpacity>().set(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<FillOpacity>().set(value, klass); + baseImpl = std::move(impl_); if (value.isDataDriven()) { - impl->observer->onLayerDataDrivenPaintPropertyChanged(*this); + observer->onLayerDataDrivenPaintPropertyChanged(*this); } else { - impl->observer->onLayerPaintPropertyChanged(*this); + observer->onLayerPaintPropertyChanged(*this); } } void FillLayer::setFillOpacityTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<FillOpacity>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<FillOpacity>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions FillLayer::getFillOpacityTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<FillOpacity>().getTransition(klass); + return impl().cascading.template get<FillOpacity>().getTransition(klass); } DataDrivenPropertyValue<Color> FillLayer::getDefaultFillColor() { @@ -120,26 +158,30 @@ DataDrivenPropertyValue<Color> FillLayer::getDefaultFillColor() { } DataDrivenPropertyValue<Color> FillLayer::getFillColor(const optional<std::string>& klass) const { - return impl->cascading.template get<FillColor>().get(klass); + return impl().cascading.template get<FillColor>().get(klass); } void FillLayer::setFillColor(DataDrivenPropertyValue<Color> value, const optional<std::string>& klass) { if (value == getFillColor(klass)) return; - impl->cascading.template get<FillColor>().set(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<FillColor>().set(value, klass); + baseImpl = std::move(impl_); if (value.isDataDriven()) { - impl->observer->onLayerDataDrivenPaintPropertyChanged(*this); + observer->onLayerDataDrivenPaintPropertyChanged(*this); } else { - impl->observer->onLayerPaintPropertyChanged(*this); + observer->onLayerPaintPropertyChanged(*this); } } void FillLayer::setFillColorTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<FillColor>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<FillColor>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions FillLayer::getFillColorTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<FillColor>().getTransition(klass); + return impl().cascading.template get<FillColor>().getTransition(klass); } DataDrivenPropertyValue<Color> FillLayer::getDefaultFillOutlineColor() { @@ -147,26 +189,30 @@ DataDrivenPropertyValue<Color> FillLayer::getDefaultFillOutlineColor() { } DataDrivenPropertyValue<Color> FillLayer::getFillOutlineColor(const optional<std::string>& klass) const { - return impl->cascading.template get<FillOutlineColor>().get(klass); + return impl().cascading.template get<FillOutlineColor>().get(klass); } void FillLayer::setFillOutlineColor(DataDrivenPropertyValue<Color> value, const optional<std::string>& klass) { if (value == getFillOutlineColor(klass)) return; - impl->cascading.template get<FillOutlineColor>().set(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<FillOutlineColor>().set(value, klass); + baseImpl = std::move(impl_); if (value.isDataDriven()) { - impl->observer->onLayerDataDrivenPaintPropertyChanged(*this); + observer->onLayerDataDrivenPaintPropertyChanged(*this); } else { - impl->observer->onLayerPaintPropertyChanged(*this); + observer->onLayerPaintPropertyChanged(*this); } } void FillLayer::setFillOutlineColorTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<FillOutlineColor>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<FillOutlineColor>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions FillLayer::getFillOutlineColorTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<FillOutlineColor>().getTransition(klass); + return impl().cascading.template get<FillOutlineColor>().getTransition(klass); } PropertyValue<std::array<float, 2>> FillLayer::getDefaultFillTranslate() { @@ -174,22 +220,26 @@ PropertyValue<std::array<float, 2>> FillLayer::getDefaultFillTranslate() { } PropertyValue<std::array<float, 2>> FillLayer::getFillTranslate(const optional<std::string>& klass) const { - return impl->cascading.template get<FillTranslate>().get(klass); + return impl().cascading.template get<FillTranslate>().get(klass); } void FillLayer::setFillTranslate(PropertyValue<std::array<float, 2>> value, const optional<std::string>& klass) { if (value == getFillTranslate(klass)) return; - impl->cascading.template get<FillTranslate>().set(value, klass); - impl->observer->onLayerPaintPropertyChanged(*this); + auto impl_ = mutableImpl(); + impl_->cascading.template get<FillTranslate>().set(value, klass); + baseImpl = std::move(impl_); + observer->onLayerPaintPropertyChanged(*this); } void FillLayer::setFillTranslateTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<FillTranslate>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<FillTranslate>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions FillLayer::getFillTranslateTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<FillTranslate>().getTransition(klass); + return impl().cascading.template get<FillTranslate>().getTransition(klass); } PropertyValue<TranslateAnchorType> FillLayer::getDefaultFillTranslateAnchor() { @@ -197,22 +247,26 @@ PropertyValue<TranslateAnchorType> FillLayer::getDefaultFillTranslateAnchor() { } PropertyValue<TranslateAnchorType> FillLayer::getFillTranslateAnchor(const optional<std::string>& klass) const { - return impl->cascading.template get<FillTranslateAnchor>().get(klass); + return impl().cascading.template get<FillTranslateAnchor>().get(klass); } void FillLayer::setFillTranslateAnchor(PropertyValue<TranslateAnchorType> value, const optional<std::string>& klass) { if (value == getFillTranslateAnchor(klass)) return; - impl->cascading.template get<FillTranslateAnchor>().set(value, klass); - impl->observer->onLayerPaintPropertyChanged(*this); + auto impl_ = mutableImpl(); + impl_->cascading.template get<FillTranslateAnchor>().set(value, klass); + baseImpl = std::move(impl_); + observer->onLayerPaintPropertyChanged(*this); } void FillLayer::setFillTranslateAnchorTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<FillTranslateAnchor>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<FillTranslateAnchor>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions FillLayer::getFillTranslateAnchorTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<FillTranslateAnchor>().getTransition(klass); + return impl().cascading.template get<FillTranslateAnchor>().getTransition(klass); } PropertyValue<std::string> FillLayer::getDefaultFillPattern() { @@ -220,22 +274,26 @@ PropertyValue<std::string> FillLayer::getDefaultFillPattern() { } PropertyValue<std::string> FillLayer::getFillPattern(const optional<std::string>& klass) const { - return impl->cascading.template get<FillPattern>().get(klass); + return impl().cascading.template get<FillPattern>().get(klass); } void FillLayer::setFillPattern(PropertyValue<std::string> value, const optional<std::string>& klass) { if (value == getFillPattern(klass)) return; - impl->cascading.template get<FillPattern>().set(value, klass); - impl->observer->onLayerPaintPropertyChanged(*this); + auto impl_ = mutableImpl(); + impl_->cascading.template get<FillPattern>().set(value, klass); + baseImpl = std::move(impl_); + observer->onLayerPaintPropertyChanged(*this); } void FillLayer::setFillPatternTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<FillPattern>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<FillPattern>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions FillLayer::getFillPatternTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<FillPattern>().getTransition(klass); + return impl().cascading.template get<FillPattern>().getTransition(klass); } } // namespace style diff --git a/src/mbgl/style/layers/fill_layer_impl.cpp b/src/mbgl/style/layers/fill_layer_impl.cpp index 6ec55a58e3..3bddedbdfb 100644 --- a/src/mbgl/style/layers/fill_layer_impl.cpp +++ b/src/mbgl/style/layers/fill_layer_impl.cpp @@ -5,7 +5,7 @@ namespace mbgl { namespace style { std::unique_ptr<RenderLayer> FillLayer::Impl::createRenderLayer() const { - return std::make_unique<RenderFillLayer>(*this); + return std::make_unique<RenderFillLayer>(staticImmutableCast<FillLayer::Impl>(immutableFromThis())); } } // namespace style diff --git a/src/mbgl/style/layers/fill_layer_impl.hpp b/src/mbgl/style/layers/fill_layer_impl.hpp index 215558962e..0e911c86cf 100644 --- a/src/mbgl/style/layers/fill_layer_impl.hpp +++ b/src/mbgl/style/layers/fill_layer_impl.hpp @@ -9,8 +9,8 @@ namespace style { 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; + using Layer::Impl::Impl; + void stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const override; std::unique_ptr<RenderLayer> createRenderLayer() const override; diff --git a/src/mbgl/style/layers/layer.cpp.ejs b/src/mbgl/style/layers/layer.cpp.ejs index 2f690c3158..31a4332400 100644 --- a/src/mbgl/style/layers/layer.cpp.ejs +++ b/src/mbgl/style/layers/layer.cpp.ejs @@ -8,41 +8,40 @@ #include <mbgl/style/layers/<%- type.replace('-', '_') %>_layer.hpp> #include <mbgl/style/layers/<%- type.replace('-', '_') %>_layer_impl.hpp> #include <mbgl/style/conversion/stringify.hpp> +#include <mbgl/style/layer_observer.hpp> namespace mbgl { namespace style { <% if (type === 'background') { -%> <%- camelize(type) %>Layer::<%- camelize(type) %>Layer(const std::string& layerID) - : Layer(LayerType::<%- camelize(type) %>, std::make_unique<Impl>()) - , impl(static_cast<Impl*>(baseImpl.get())) { - impl->id = layerID; + : Layer(makeMutable<Impl>(LayerType::<%- camelize(type) %>, layerID, std::string())) { } <% } else { -%> <%- camelize(type) %>Layer::<%- camelize(type) %>Layer(const std::string& layerID, const std::string& sourceID) - : Layer(LayerType::<%- camelize(type) %>, std::make_unique<Impl>()) - , impl(static_cast<Impl*>(baseImpl.get())) { - impl->id = layerID; - impl->source = sourceID; + : Layer(makeMutable<Impl>(LayerType::<%- camelize(type) %>, layerID, sourceID)) { } <% } -%> -<%- camelize(type) %>Layer::<%- camelize(type) %>Layer(const Impl& other) - : Layer(LayerType::<%- camelize(type) %>, std::make_unique<Impl>(other)) - , impl(static_cast<Impl*>(baseImpl.get())) { +<%- camelize(type) %>Layer::<%- camelize(type) %>Layer(Immutable<Impl> impl_) + : Layer(std::move(impl_)) { } <%- camelize(type) %>Layer::~<%- camelize(type) %>Layer() = default; -std::unique_ptr<Layer> <%- camelize(type) %>Layer::Impl::clone() const { - return std::make_unique<<%- camelize(type) %>Layer>(*this); +const <%- camelize(type) %>Layer::Impl& <%- camelize(type) %>Layer::impl() const { + return static_cast<const Impl&>(*baseImpl); } -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->cascading = <%- camelize(type) %>PaintProperties::Cascading(); - return std::move(result); +Mutable<<%- camelize(type) %>Layer::Impl> <%- camelize(type) %>Layer::mutableImpl() const { + return makeMutable<Impl>(impl()); +} + +std::unique_ptr<Layer> <%- camelize(type) %>Layer::cloneRef(const std::string& id_) const { + auto impl_ = mutableImpl(); + impl_->id = id_; + impl_->cascading = <%- camelize(type) %>PaintProperties::Cascading(); + return std::make_unique<<%- camelize(type) %>Layer>(std::move(impl_)); } <% if (layoutProperties.length) { -%> @@ -58,31 +57,60 @@ void <%- camelize(type) %>Layer::Impl::stringifyLayout(rapidjson::Writer<rapidjs // Source const std::string& <%- camelize(type) %>Layer::getSourceID() const { - return impl->source; + return impl().source; } <% if (type !== 'raster') { -%> void <%- camelize(type) %>Layer::setSourceLayer(const std::string& sourceLayer) { - impl->sourceLayer = sourceLayer; + auto impl_ = mutableImpl(); + impl_->sourceLayer = sourceLayer; + baseImpl = std::move(impl_); } const std::string& <%- camelize(type) %>Layer::getSourceLayer() const { - return impl->sourceLayer; + return impl().sourceLayer; } // Filter void <%- camelize(type) %>Layer::setFilter(const Filter& filter) { - impl->filter = filter; - impl->observer->onLayerFilterChanged(*this); + auto impl_ = mutableImpl(); + impl_->filter = filter; + baseImpl = std::move(impl_); + observer->onLayerFilterChanged(*this); } const Filter& <%- camelize(type) %>Layer::getFilter() const { - return impl->filter; + return impl().filter; } <% } -%> <% } -%> +// Visibility + +void <%- camelize(type) %>Layer::setVisibility(VisibilityType value) { + if (value == getVisibility()) + return; + auto impl_ = mutableImpl(); + impl_->visibility = value; + baseImpl = std::move(impl_); + observer->onLayerVisibilityChanged(*this); +} + +// Zoom range + +void <%- camelize(type) %>Layer::setMinZoom(float minZoom) { + auto impl_ = mutableImpl(); + impl_->minZoom = minZoom; + baseImpl = std::move(impl_); +} + +void <%- camelize(type) %>Layer::setMaxZoom(float maxZoom) { + auto impl_ = mutableImpl(); + impl_->maxZoom = maxZoom; + baseImpl = std::move(impl_); +} + // Layout properties <% for (const property of layoutProperties) { -%> @@ -91,14 +119,16 @@ const Filter& <%- camelize(type) %>Layer::getFilter() const { } <%- propertyValueType(property) %> <%- camelize(type) %>Layer::get<%- camelize(property.name) %>() const { - return impl->layout.unevaluated.get<<%- camelize(property.name) %>>(); + return impl().layout.unevaluated.get<<%- camelize(property.name) %>>(); } void <%- camelize(type) %>Layer::set<%- camelize(property.name) %>(<%- propertyValueType(property) %> value) { if (value == get<%- camelize(property.name) %>()) return; - impl->layout.unevaluated.get<<%- camelize(property.name) %>>() = value; - impl->observer->onLayerLayoutPropertyChanged(*this, "<%- property.name %>"); + auto impl_ = mutableImpl(); + impl_->layout.unevaluated.get<<%- camelize(property.name) %>>() = value; + baseImpl = std::move(impl_); + observer->onLayerLayoutPropertyChanged(*this, "<%- property.name %>"); } <% } -%> @@ -109,30 +139,34 @@ void <%- camelize(type) %>Layer::set<%- camelize(property.name) %>(<%- propertyV } <%- propertyValueType(property) %> <%- camelize(type) %>Layer::get<%- camelize(property.name) %>(const optional<std::string>& klass) const { - return impl->cascading.template get<<%- camelize(property.name) %>>().get(klass); + return impl().cascading.template get<<%- camelize(property.name) %>>().get(klass); } void <%- camelize(type) %>Layer::set<%- camelize(property.name) %>(<%- propertyValueType(property) %> value, const optional<std::string>& klass) { if (value == get<%- camelize(property.name) %>(klass)) return; - impl->cascading.template get<<%- camelize(property.name) %>>().set(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<<%- camelize(property.name) %>>().set(value, klass); + baseImpl = std::move(impl_); <% if (isDataDriven(property)) { -%> if (value.isDataDriven()) { - impl->observer->onLayerDataDrivenPaintPropertyChanged(*this); + observer->onLayerDataDrivenPaintPropertyChanged(*this); } else { - impl->observer->onLayerPaintPropertyChanged(*this); + observer->onLayerPaintPropertyChanged(*this); } <% } else { -%> - impl->observer->onLayerPaintPropertyChanged(*this); + observer->onLayerPaintPropertyChanged(*this); <% } -%> } void <%- camelize(type) %>Layer::set<%- camelize(property.name) %>Transition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<<%- camelize(property.name) %>>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<<%- camelize(property.name) %>>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions <%- camelize(type) %>Layer::get<%- camelize(property.name) %>Transition(const optional<std::string>& klass) const { - return impl->cascading.template get<<%- camelize(property.name) %>>().getTransition(klass); + return impl().cascading.template get<<%- camelize(property.name) %>>().getTransition(klass); } <% } -%> diff --git a/src/mbgl/style/layers/line_layer.cpp b/src/mbgl/style/layers/line_layer.cpp index 7f1575aad5..8b9085b48c 100644 --- a/src/mbgl/style/layers/line_layer.cpp +++ b/src/mbgl/style/layers/line_layer.cpp @@ -3,33 +3,34 @@ #include <mbgl/style/layers/line_layer.hpp> #include <mbgl/style/layers/line_layer_impl.hpp> #include <mbgl/style/conversion/stringify.hpp> +#include <mbgl/style/layer_observer.hpp> namespace mbgl { namespace style { LineLayer::LineLayer(const std::string& layerID, const std::string& sourceID) - : Layer(LayerType::Line, std::make_unique<Impl>()) - , impl(static_cast<Impl*>(baseImpl.get())) { - impl->id = layerID; - impl->source = sourceID; + : Layer(makeMutable<Impl>(LayerType::Line, layerID, sourceID)) { } -LineLayer::LineLayer(const Impl& other) - : Layer(LayerType::Line, std::make_unique<Impl>(other)) - , impl(static_cast<Impl*>(baseImpl.get())) { +LineLayer::LineLayer(Immutable<Impl> impl_) + : Layer(std::move(impl_)) { } LineLayer::~LineLayer() = default; -std::unique_ptr<Layer> LineLayer::Impl::clone() const { - return std::make_unique<LineLayer>(*this); +const LineLayer::Impl& LineLayer::impl() const { + return static_cast<const Impl&>(*baseImpl); } -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->cascading = LinePaintProperties::Cascading(); - return std::move(result); +Mutable<LineLayer::Impl> LineLayer::mutableImpl() const { + return makeMutable<Impl>(impl()); +} + +std::unique_ptr<Layer> LineLayer::cloneRef(const std::string& id_) const { + auto impl_ = mutableImpl(); + impl_->id = id_; + impl_->cascading = LinePaintProperties::Cascading(); + return std::make_unique<LineLayer>(std::move(impl_)); } void LineLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>& writer) const { @@ -39,26 +40,55 @@ void LineLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer> // Source const std::string& LineLayer::getSourceID() const { - return impl->source; + return impl().source; } void LineLayer::setSourceLayer(const std::string& sourceLayer) { - impl->sourceLayer = sourceLayer; + auto impl_ = mutableImpl(); + impl_->sourceLayer = sourceLayer; + baseImpl = std::move(impl_); } const std::string& LineLayer::getSourceLayer() const { - return impl->sourceLayer; + return impl().sourceLayer; } // Filter void LineLayer::setFilter(const Filter& filter) { - impl->filter = filter; - impl->observer->onLayerFilterChanged(*this); + auto impl_ = mutableImpl(); + impl_->filter = filter; + baseImpl = std::move(impl_); + observer->onLayerFilterChanged(*this); } const Filter& LineLayer::getFilter() const { - return impl->filter; + return impl().filter; +} + +// Visibility + +void LineLayer::setVisibility(VisibilityType value) { + if (value == getVisibility()) + return; + auto impl_ = mutableImpl(); + impl_->visibility = value; + baseImpl = std::move(impl_); + observer->onLayerVisibilityChanged(*this); +} + +// Zoom range + +void LineLayer::setMinZoom(float minZoom) { + auto impl_ = mutableImpl(); + impl_->minZoom = minZoom; + baseImpl = std::move(impl_); +} + +void LineLayer::setMaxZoom(float maxZoom) { + auto impl_ = mutableImpl(); + impl_->maxZoom = maxZoom; + baseImpl = std::move(impl_); } // Layout properties @@ -68,56 +98,64 @@ PropertyValue<LineCapType> LineLayer::getDefaultLineCap() { } PropertyValue<LineCapType> LineLayer::getLineCap() const { - return impl->layout.unevaluated.get<LineCap>(); + return impl().layout.unevaluated.get<LineCap>(); } void LineLayer::setLineCap(PropertyValue<LineCapType> value) { if (value == getLineCap()) return; - impl->layout.unevaluated.get<LineCap>() = value; - impl->observer->onLayerLayoutPropertyChanged(*this, "line-cap"); + auto impl_ = mutableImpl(); + impl_->layout.unevaluated.get<LineCap>() = value; + baseImpl = std::move(impl_); + observer->onLayerLayoutPropertyChanged(*this, "line-cap"); } PropertyValue<LineJoinType> LineLayer::getDefaultLineJoin() { return LineJoin::defaultValue(); } PropertyValue<LineJoinType> LineLayer::getLineJoin() const { - return impl->layout.unevaluated.get<LineJoin>(); + return impl().layout.unevaluated.get<LineJoin>(); } void LineLayer::setLineJoin(PropertyValue<LineJoinType> value) { if (value == getLineJoin()) return; - impl->layout.unevaluated.get<LineJoin>() = value; - impl->observer->onLayerLayoutPropertyChanged(*this, "line-join"); + auto impl_ = mutableImpl(); + impl_->layout.unevaluated.get<LineJoin>() = value; + baseImpl = std::move(impl_); + observer->onLayerLayoutPropertyChanged(*this, "line-join"); } PropertyValue<float> LineLayer::getDefaultLineMiterLimit() { return LineMiterLimit::defaultValue(); } PropertyValue<float> LineLayer::getLineMiterLimit() const { - return impl->layout.unevaluated.get<LineMiterLimit>(); + return impl().layout.unevaluated.get<LineMiterLimit>(); } void LineLayer::setLineMiterLimit(PropertyValue<float> value) { if (value == getLineMiterLimit()) return; - impl->layout.unevaluated.get<LineMiterLimit>() = value; - impl->observer->onLayerLayoutPropertyChanged(*this, "line-miter-limit"); + auto impl_ = mutableImpl(); + impl_->layout.unevaluated.get<LineMiterLimit>() = value; + baseImpl = std::move(impl_); + observer->onLayerLayoutPropertyChanged(*this, "line-miter-limit"); } PropertyValue<float> LineLayer::getDefaultLineRoundLimit() { return LineRoundLimit::defaultValue(); } PropertyValue<float> LineLayer::getLineRoundLimit() const { - return impl->layout.unevaluated.get<LineRoundLimit>(); + return impl().layout.unevaluated.get<LineRoundLimit>(); } void LineLayer::setLineRoundLimit(PropertyValue<float> value) { if (value == getLineRoundLimit()) return; - impl->layout.unevaluated.get<LineRoundLimit>() = value; - impl->observer->onLayerLayoutPropertyChanged(*this, "line-round-limit"); + auto impl_ = mutableImpl(); + impl_->layout.unevaluated.get<LineRoundLimit>() = value; + baseImpl = std::move(impl_); + observer->onLayerLayoutPropertyChanged(*this, "line-round-limit"); } // Paint properties @@ -127,26 +165,30 @@ DataDrivenPropertyValue<float> LineLayer::getDefaultLineOpacity() { } DataDrivenPropertyValue<float> LineLayer::getLineOpacity(const optional<std::string>& klass) const { - return impl->cascading.template get<LineOpacity>().get(klass); + return impl().cascading.template get<LineOpacity>().get(klass); } void LineLayer::setLineOpacity(DataDrivenPropertyValue<float> value, const optional<std::string>& klass) { if (value == getLineOpacity(klass)) return; - impl->cascading.template get<LineOpacity>().set(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<LineOpacity>().set(value, klass); + baseImpl = std::move(impl_); if (value.isDataDriven()) { - impl->observer->onLayerDataDrivenPaintPropertyChanged(*this); + observer->onLayerDataDrivenPaintPropertyChanged(*this); } else { - impl->observer->onLayerPaintPropertyChanged(*this); + observer->onLayerPaintPropertyChanged(*this); } } void LineLayer::setLineOpacityTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<LineOpacity>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<LineOpacity>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions LineLayer::getLineOpacityTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<LineOpacity>().getTransition(klass); + return impl().cascading.template get<LineOpacity>().getTransition(klass); } DataDrivenPropertyValue<Color> LineLayer::getDefaultLineColor() { @@ -154,26 +196,30 @@ DataDrivenPropertyValue<Color> LineLayer::getDefaultLineColor() { } DataDrivenPropertyValue<Color> LineLayer::getLineColor(const optional<std::string>& klass) const { - return impl->cascading.template get<LineColor>().get(klass); + return impl().cascading.template get<LineColor>().get(klass); } void LineLayer::setLineColor(DataDrivenPropertyValue<Color> value, const optional<std::string>& klass) { if (value == getLineColor(klass)) return; - impl->cascading.template get<LineColor>().set(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<LineColor>().set(value, klass); + baseImpl = std::move(impl_); if (value.isDataDriven()) { - impl->observer->onLayerDataDrivenPaintPropertyChanged(*this); + observer->onLayerDataDrivenPaintPropertyChanged(*this); } else { - impl->observer->onLayerPaintPropertyChanged(*this); + observer->onLayerPaintPropertyChanged(*this); } } void LineLayer::setLineColorTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<LineColor>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<LineColor>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions LineLayer::getLineColorTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<LineColor>().getTransition(klass); + return impl().cascading.template get<LineColor>().getTransition(klass); } PropertyValue<std::array<float, 2>> LineLayer::getDefaultLineTranslate() { @@ -181,22 +227,26 @@ PropertyValue<std::array<float, 2>> LineLayer::getDefaultLineTranslate() { } PropertyValue<std::array<float, 2>> LineLayer::getLineTranslate(const optional<std::string>& klass) const { - return impl->cascading.template get<LineTranslate>().get(klass); + return impl().cascading.template get<LineTranslate>().get(klass); } void LineLayer::setLineTranslate(PropertyValue<std::array<float, 2>> value, const optional<std::string>& klass) { if (value == getLineTranslate(klass)) return; - impl->cascading.template get<LineTranslate>().set(value, klass); - impl->observer->onLayerPaintPropertyChanged(*this); + auto impl_ = mutableImpl(); + impl_->cascading.template get<LineTranslate>().set(value, klass); + baseImpl = std::move(impl_); + observer->onLayerPaintPropertyChanged(*this); } void LineLayer::setLineTranslateTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<LineTranslate>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<LineTranslate>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions LineLayer::getLineTranslateTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<LineTranslate>().getTransition(klass); + return impl().cascading.template get<LineTranslate>().getTransition(klass); } PropertyValue<TranslateAnchorType> LineLayer::getDefaultLineTranslateAnchor() { @@ -204,22 +254,26 @@ PropertyValue<TranslateAnchorType> LineLayer::getDefaultLineTranslateAnchor() { } PropertyValue<TranslateAnchorType> LineLayer::getLineTranslateAnchor(const optional<std::string>& klass) const { - return impl->cascading.template get<LineTranslateAnchor>().get(klass); + return impl().cascading.template get<LineTranslateAnchor>().get(klass); } void LineLayer::setLineTranslateAnchor(PropertyValue<TranslateAnchorType> value, const optional<std::string>& klass) { if (value == getLineTranslateAnchor(klass)) return; - impl->cascading.template get<LineTranslateAnchor>().set(value, klass); - impl->observer->onLayerPaintPropertyChanged(*this); + auto impl_ = mutableImpl(); + impl_->cascading.template get<LineTranslateAnchor>().set(value, klass); + baseImpl = std::move(impl_); + observer->onLayerPaintPropertyChanged(*this); } void LineLayer::setLineTranslateAnchorTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<LineTranslateAnchor>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<LineTranslateAnchor>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions LineLayer::getLineTranslateAnchorTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<LineTranslateAnchor>().getTransition(klass); + return impl().cascading.template get<LineTranslateAnchor>().getTransition(klass); } PropertyValue<float> LineLayer::getDefaultLineWidth() { @@ -227,22 +281,26 @@ PropertyValue<float> LineLayer::getDefaultLineWidth() { } PropertyValue<float> LineLayer::getLineWidth(const optional<std::string>& klass) const { - return impl->cascading.template get<LineWidth>().get(klass); + return impl().cascading.template get<LineWidth>().get(klass); } void LineLayer::setLineWidth(PropertyValue<float> value, const optional<std::string>& klass) { if (value == getLineWidth(klass)) return; - impl->cascading.template get<LineWidth>().set(value, klass); - impl->observer->onLayerPaintPropertyChanged(*this); + auto impl_ = mutableImpl(); + impl_->cascading.template get<LineWidth>().set(value, klass); + baseImpl = std::move(impl_); + observer->onLayerPaintPropertyChanged(*this); } void LineLayer::setLineWidthTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<LineWidth>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<LineWidth>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions LineLayer::getLineWidthTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<LineWidth>().getTransition(klass); + return impl().cascading.template get<LineWidth>().getTransition(klass); } DataDrivenPropertyValue<float> LineLayer::getDefaultLineGapWidth() { @@ -250,26 +308,30 @@ DataDrivenPropertyValue<float> LineLayer::getDefaultLineGapWidth() { } DataDrivenPropertyValue<float> LineLayer::getLineGapWidth(const optional<std::string>& klass) const { - return impl->cascading.template get<LineGapWidth>().get(klass); + return impl().cascading.template get<LineGapWidth>().get(klass); } void LineLayer::setLineGapWidth(DataDrivenPropertyValue<float> value, const optional<std::string>& klass) { if (value == getLineGapWidth(klass)) return; - impl->cascading.template get<LineGapWidth>().set(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<LineGapWidth>().set(value, klass); + baseImpl = std::move(impl_); if (value.isDataDriven()) { - impl->observer->onLayerDataDrivenPaintPropertyChanged(*this); + observer->onLayerDataDrivenPaintPropertyChanged(*this); } else { - impl->observer->onLayerPaintPropertyChanged(*this); + observer->onLayerPaintPropertyChanged(*this); } } void LineLayer::setLineGapWidthTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<LineGapWidth>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<LineGapWidth>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions LineLayer::getLineGapWidthTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<LineGapWidth>().getTransition(klass); + return impl().cascading.template get<LineGapWidth>().getTransition(klass); } DataDrivenPropertyValue<float> LineLayer::getDefaultLineOffset() { @@ -277,26 +339,30 @@ DataDrivenPropertyValue<float> LineLayer::getDefaultLineOffset() { } DataDrivenPropertyValue<float> LineLayer::getLineOffset(const optional<std::string>& klass) const { - return impl->cascading.template get<LineOffset>().get(klass); + return impl().cascading.template get<LineOffset>().get(klass); } void LineLayer::setLineOffset(DataDrivenPropertyValue<float> value, const optional<std::string>& klass) { if (value == getLineOffset(klass)) return; - impl->cascading.template get<LineOffset>().set(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<LineOffset>().set(value, klass); + baseImpl = std::move(impl_); if (value.isDataDriven()) { - impl->observer->onLayerDataDrivenPaintPropertyChanged(*this); + observer->onLayerDataDrivenPaintPropertyChanged(*this); } else { - impl->observer->onLayerPaintPropertyChanged(*this); + observer->onLayerPaintPropertyChanged(*this); } } void LineLayer::setLineOffsetTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<LineOffset>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<LineOffset>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions LineLayer::getLineOffsetTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<LineOffset>().getTransition(klass); + return impl().cascading.template get<LineOffset>().getTransition(klass); } DataDrivenPropertyValue<float> LineLayer::getDefaultLineBlur() { @@ -304,26 +370,30 @@ DataDrivenPropertyValue<float> LineLayer::getDefaultLineBlur() { } DataDrivenPropertyValue<float> LineLayer::getLineBlur(const optional<std::string>& klass) const { - return impl->cascading.template get<LineBlur>().get(klass); + return impl().cascading.template get<LineBlur>().get(klass); } void LineLayer::setLineBlur(DataDrivenPropertyValue<float> value, const optional<std::string>& klass) { if (value == getLineBlur(klass)) return; - impl->cascading.template get<LineBlur>().set(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<LineBlur>().set(value, klass); + baseImpl = std::move(impl_); if (value.isDataDriven()) { - impl->observer->onLayerDataDrivenPaintPropertyChanged(*this); + observer->onLayerDataDrivenPaintPropertyChanged(*this); } else { - impl->observer->onLayerPaintPropertyChanged(*this); + observer->onLayerPaintPropertyChanged(*this); } } void LineLayer::setLineBlurTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<LineBlur>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<LineBlur>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions LineLayer::getLineBlurTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<LineBlur>().getTransition(klass); + return impl().cascading.template get<LineBlur>().getTransition(klass); } PropertyValue<std::vector<float>> LineLayer::getDefaultLineDasharray() { @@ -331,22 +401,26 @@ PropertyValue<std::vector<float>> LineLayer::getDefaultLineDasharray() { } PropertyValue<std::vector<float>> LineLayer::getLineDasharray(const optional<std::string>& klass) const { - return impl->cascading.template get<LineDasharray>().get(klass); + return impl().cascading.template get<LineDasharray>().get(klass); } void LineLayer::setLineDasharray(PropertyValue<std::vector<float>> value, const optional<std::string>& klass) { if (value == getLineDasharray(klass)) return; - impl->cascading.template get<LineDasharray>().set(value, klass); - impl->observer->onLayerPaintPropertyChanged(*this); + auto impl_ = mutableImpl(); + impl_->cascading.template get<LineDasharray>().set(value, klass); + baseImpl = std::move(impl_); + observer->onLayerPaintPropertyChanged(*this); } void LineLayer::setLineDasharrayTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<LineDasharray>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<LineDasharray>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions LineLayer::getLineDasharrayTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<LineDasharray>().getTransition(klass); + return impl().cascading.template get<LineDasharray>().getTransition(klass); } PropertyValue<std::string> LineLayer::getDefaultLinePattern() { @@ -354,22 +428,26 @@ PropertyValue<std::string> LineLayer::getDefaultLinePattern() { } PropertyValue<std::string> LineLayer::getLinePattern(const optional<std::string>& klass) const { - return impl->cascading.template get<LinePattern>().get(klass); + return impl().cascading.template get<LinePattern>().get(klass); } void LineLayer::setLinePattern(PropertyValue<std::string> value, const optional<std::string>& klass) { if (value == getLinePattern(klass)) return; - impl->cascading.template get<LinePattern>().set(value, klass); - impl->observer->onLayerPaintPropertyChanged(*this); + auto impl_ = mutableImpl(); + impl_->cascading.template get<LinePattern>().set(value, klass); + baseImpl = std::move(impl_); + observer->onLayerPaintPropertyChanged(*this); } void LineLayer::setLinePatternTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<LinePattern>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<LinePattern>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions LineLayer::getLinePatternTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<LinePattern>().getTransition(klass); + return impl().cascading.template get<LinePattern>().getTransition(klass); } } // namespace style diff --git a/src/mbgl/style/layers/line_layer_impl.cpp b/src/mbgl/style/layers/line_layer_impl.cpp index 973a77abf4..0158ba7a96 100644 --- a/src/mbgl/style/layers/line_layer_impl.cpp +++ b/src/mbgl/style/layers/line_layer_impl.cpp @@ -5,7 +5,7 @@ namespace mbgl { namespace style { std::unique_ptr<RenderLayer> LineLayer::Impl::createRenderLayer() const { - return std::make_unique<RenderLineLayer>(*this); + return std::make_unique<RenderLineLayer>(staticImmutableCast<LineLayer::Impl>(immutableFromThis())); } } // namespace style diff --git a/src/mbgl/style/layers/line_layer_impl.hpp b/src/mbgl/style/layers/line_layer_impl.hpp index 02c9c85f00..70d357c592 100644 --- a/src/mbgl/style/layers/line_layer_impl.hpp +++ b/src/mbgl/style/layers/line_layer_impl.hpp @@ -9,8 +9,8 @@ namespace style { 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; + using Layer::Impl::Impl; + void stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const override; std::unique_ptr<RenderLayer> createRenderLayer() const override; diff --git a/src/mbgl/style/layers/raster_layer.cpp b/src/mbgl/style/layers/raster_layer.cpp index b525f9eaa4..13c2d214ce 100644 --- a/src/mbgl/style/layers/raster_layer.cpp +++ b/src/mbgl/style/layers/raster_layer.cpp @@ -3,33 +3,34 @@ #include <mbgl/style/layers/raster_layer.hpp> #include <mbgl/style/layers/raster_layer_impl.hpp> #include <mbgl/style/conversion/stringify.hpp> +#include <mbgl/style/layer_observer.hpp> namespace mbgl { namespace style { RasterLayer::RasterLayer(const std::string& layerID, const std::string& sourceID) - : Layer(LayerType::Raster, std::make_unique<Impl>()) - , impl(static_cast<Impl*>(baseImpl.get())) { - impl->id = layerID; - impl->source = sourceID; + : Layer(makeMutable<Impl>(LayerType::Raster, layerID, sourceID)) { } -RasterLayer::RasterLayer(const Impl& other) - : Layer(LayerType::Raster, std::make_unique<Impl>(other)) - , impl(static_cast<Impl*>(baseImpl.get())) { +RasterLayer::RasterLayer(Immutable<Impl> impl_) + : Layer(std::move(impl_)) { } RasterLayer::~RasterLayer() = default; -std::unique_ptr<Layer> RasterLayer::Impl::clone() const { - return std::make_unique<RasterLayer>(*this); +const RasterLayer::Impl& RasterLayer::impl() const { + return static_cast<const Impl&>(*baseImpl); } -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->cascading = RasterPaintProperties::Cascading(); - return std::move(result); +Mutable<RasterLayer::Impl> RasterLayer::mutableImpl() const { + return makeMutable<Impl>(impl()); +} + +std::unique_ptr<Layer> RasterLayer::cloneRef(const std::string& id_) const { + auto impl_ = mutableImpl(); + impl_->id = id_; + impl_->cascading = RasterPaintProperties::Cascading(); + return std::make_unique<RasterLayer>(std::move(impl_)); } void RasterLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const { @@ -38,10 +39,35 @@ void RasterLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffe // Source const std::string& RasterLayer::getSourceID() const { - return impl->source; + return impl().source; } +// Visibility + +void RasterLayer::setVisibility(VisibilityType value) { + if (value == getVisibility()) + return; + auto impl_ = mutableImpl(); + impl_->visibility = value; + baseImpl = std::move(impl_); + observer->onLayerVisibilityChanged(*this); +} + +// Zoom range + +void RasterLayer::setMinZoom(float minZoom) { + auto impl_ = mutableImpl(); + impl_->minZoom = minZoom; + baseImpl = std::move(impl_); +} + +void RasterLayer::setMaxZoom(float maxZoom) { + auto impl_ = mutableImpl(); + impl_->maxZoom = maxZoom; + baseImpl = std::move(impl_); +} + // Layout properties @@ -52,22 +78,26 @@ PropertyValue<float> RasterLayer::getDefaultRasterOpacity() { } PropertyValue<float> RasterLayer::getRasterOpacity(const optional<std::string>& klass) const { - return impl->cascading.template get<RasterOpacity>().get(klass); + return impl().cascading.template get<RasterOpacity>().get(klass); } void RasterLayer::setRasterOpacity(PropertyValue<float> value, const optional<std::string>& klass) { if (value == getRasterOpacity(klass)) return; - impl->cascading.template get<RasterOpacity>().set(value, klass); - impl->observer->onLayerPaintPropertyChanged(*this); + auto impl_ = mutableImpl(); + impl_->cascading.template get<RasterOpacity>().set(value, klass); + baseImpl = std::move(impl_); + observer->onLayerPaintPropertyChanged(*this); } void RasterLayer::setRasterOpacityTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<RasterOpacity>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<RasterOpacity>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions RasterLayer::getRasterOpacityTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<RasterOpacity>().getTransition(klass); + return impl().cascading.template get<RasterOpacity>().getTransition(klass); } PropertyValue<float> RasterLayer::getDefaultRasterHueRotate() { @@ -75,22 +105,26 @@ PropertyValue<float> RasterLayer::getDefaultRasterHueRotate() { } PropertyValue<float> RasterLayer::getRasterHueRotate(const optional<std::string>& klass) const { - return impl->cascading.template get<RasterHueRotate>().get(klass); + return impl().cascading.template get<RasterHueRotate>().get(klass); } void RasterLayer::setRasterHueRotate(PropertyValue<float> value, const optional<std::string>& klass) { if (value == getRasterHueRotate(klass)) return; - impl->cascading.template get<RasterHueRotate>().set(value, klass); - impl->observer->onLayerPaintPropertyChanged(*this); + auto impl_ = mutableImpl(); + impl_->cascading.template get<RasterHueRotate>().set(value, klass); + baseImpl = std::move(impl_); + observer->onLayerPaintPropertyChanged(*this); } void RasterLayer::setRasterHueRotateTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<RasterHueRotate>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<RasterHueRotate>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions RasterLayer::getRasterHueRotateTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<RasterHueRotate>().getTransition(klass); + return impl().cascading.template get<RasterHueRotate>().getTransition(klass); } PropertyValue<float> RasterLayer::getDefaultRasterBrightnessMin() { @@ -98,22 +132,26 @@ PropertyValue<float> RasterLayer::getDefaultRasterBrightnessMin() { } PropertyValue<float> RasterLayer::getRasterBrightnessMin(const optional<std::string>& klass) const { - return impl->cascading.template get<RasterBrightnessMin>().get(klass); + return impl().cascading.template get<RasterBrightnessMin>().get(klass); } void RasterLayer::setRasterBrightnessMin(PropertyValue<float> value, const optional<std::string>& klass) { if (value == getRasterBrightnessMin(klass)) return; - impl->cascading.template get<RasterBrightnessMin>().set(value, klass); - impl->observer->onLayerPaintPropertyChanged(*this); + auto impl_ = mutableImpl(); + impl_->cascading.template get<RasterBrightnessMin>().set(value, klass); + baseImpl = std::move(impl_); + observer->onLayerPaintPropertyChanged(*this); } void RasterLayer::setRasterBrightnessMinTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<RasterBrightnessMin>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<RasterBrightnessMin>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions RasterLayer::getRasterBrightnessMinTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<RasterBrightnessMin>().getTransition(klass); + return impl().cascading.template get<RasterBrightnessMin>().getTransition(klass); } PropertyValue<float> RasterLayer::getDefaultRasterBrightnessMax() { @@ -121,22 +159,26 @@ PropertyValue<float> RasterLayer::getDefaultRasterBrightnessMax() { } PropertyValue<float> RasterLayer::getRasterBrightnessMax(const optional<std::string>& klass) const { - return impl->cascading.template get<RasterBrightnessMax>().get(klass); + return impl().cascading.template get<RasterBrightnessMax>().get(klass); } void RasterLayer::setRasterBrightnessMax(PropertyValue<float> value, const optional<std::string>& klass) { if (value == getRasterBrightnessMax(klass)) return; - impl->cascading.template get<RasterBrightnessMax>().set(value, klass); - impl->observer->onLayerPaintPropertyChanged(*this); + auto impl_ = mutableImpl(); + impl_->cascading.template get<RasterBrightnessMax>().set(value, klass); + baseImpl = std::move(impl_); + observer->onLayerPaintPropertyChanged(*this); } void RasterLayer::setRasterBrightnessMaxTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<RasterBrightnessMax>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<RasterBrightnessMax>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions RasterLayer::getRasterBrightnessMaxTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<RasterBrightnessMax>().getTransition(klass); + return impl().cascading.template get<RasterBrightnessMax>().getTransition(klass); } PropertyValue<float> RasterLayer::getDefaultRasterSaturation() { @@ -144,22 +186,26 @@ PropertyValue<float> RasterLayer::getDefaultRasterSaturation() { } PropertyValue<float> RasterLayer::getRasterSaturation(const optional<std::string>& klass) const { - return impl->cascading.template get<RasterSaturation>().get(klass); + return impl().cascading.template get<RasterSaturation>().get(klass); } void RasterLayer::setRasterSaturation(PropertyValue<float> value, const optional<std::string>& klass) { if (value == getRasterSaturation(klass)) return; - impl->cascading.template get<RasterSaturation>().set(value, klass); - impl->observer->onLayerPaintPropertyChanged(*this); + auto impl_ = mutableImpl(); + impl_->cascading.template get<RasterSaturation>().set(value, klass); + baseImpl = std::move(impl_); + observer->onLayerPaintPropertyChanged(*this); } void RasterLayer::setRasterSaturationTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<RasterSaturation>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<RasterSaturation>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions RasterLayer::getRasterSaturationTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<RasterSaturation>().getTransition(klass); + return impl().cascading.template get<RasterSaturation>().getTransition(klass); } PropertyValue<float> RasterLayer::getDefaultRasterContrast() { @@ -167,22 +213,26 @@ PropertyValue<float> RasterLayer::getDefaultRasterContrast() { } PropertyValue<float> RasterLayer::getRasterContrast(const optional<std::string>& klass) const { - return impl->cascading.template get<RasterContrast>().get(klass); + return impl().cascading.template get<RasterContrast>().get(klass); } void RasterLayer::setRasterContrast(PropertyValue<float> value, const optional<std::string>& klass) { if (value == getRasterContrast(klass)) return; - impl->cascading.template get<RasterContrast>().set(value, klass); - impl->observer->onLayerPaintPropertyChanged(*this); + auto impl_ = mutableImpl(); + impl_->cascading.template get<RasterContrast>().set(value, klass); + baseImpl = std::move(impl_); + observer->onLayerPaintPropertyChanged(*this); } void RasterLayer::setRasterContrastTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<RasterContrast>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<RasterContrast>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions RasterLayer::getRasterContrastTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<RasterContrast>().getTransition(klass); + return impl().cascading.template get<RasterContrast>().getTransition(klass); } PropertyValue<float> RasterLayer::getDefaultRasterFadeDuration() { @@ -190,22 +240,26 @@ PropertyValue<float> RasterLayer::getDefaultRasterFadeDuration() { } PropertyValue<float> RasterLayer::getRasterFadeDuration(const optional<std::string>& klass) const { - return impl->cascading.template get<RasterFadeDuration>().get(klass); + return impl().cascading.template get<RasterFadeDuration>().get(klass); } void RasterLayer::setRasterFadeDuration(PropertyValue<float> value, const optional<std::string>& klass) { if (value == getRasterFadeDuration(klass)) return; - impl->cascading.template get<RasterFadeDuration>().set(value, klass); - impl->observer->onLayerPaintPropertyChanged(*this); + auto impl_ = mutableImpl(); + impl_->cascading.template get<RasterFadeDuration>().set(value, klass); + baseImpl = std::move(impl_); + observer->onLayerPaintPropertyChanged(*this); } void RasterLayer::setRasterFadeDurationTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<RasterFadeDuration>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<RasterFadeDuration>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions RasterLayer::getRasterFadeDurationTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<RasterFadeDuration>().getTransition(klass); + return impl().cascading.template get<RasterFadeDuration>().getTransition(klass); } } // namespace style diff --git a/src/mbgl/style/layers/raster_layer_impl.cpp b/src/mbgl/style/layers/raster_layer_impl.cpp index fa9f80dac6..f7e908a5cf 100644 --- a/src/mbgl/style/layers/raster_layer_impl.cpp +++ b/src/mbgl/style/layers/raster_layer_impl.cpp @@ -5,7 +5,7 @@ namespace mbgl { namespace style { std::unique_ptr<RenderLayer> RasterLayer::Impl::createRenderLayer() const { - return std::make_unique<RenderRasterLayer>(*this); + return std::make_unique<RenderRasterLayer>(staticImmutableCast<RasterLayer::Impl>(immutableFromThis())); } } // namespace style diff --git a/src/mbgl/style/layers/raster_layer_impl.hpp b/src/mbgl/style/layers/raster_layer_impl.hpp index edf5f9111b..451619807a 100644 --- a/src/mbgl/style/layers/raster_layer_impl.hpp +++ b/src/mbgl/style/layers/raster_layer_impl.hpp @@ -9,8 +9,8 @@ namespace style { 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; + using Layer::Impl::Impl; + void stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const override; std::unique_ptr<RenderLayer> createRenderLayer() const override; diff --git a/src/mbgl/style/layers/symbol_layer.cpp b/src/mbgl/style/layers/symbol_layer.cpp index 273a9fd24e..5a062997c4 100644 --- a/src/mbgl/style/layers/symbol_layer.cpp +++ b/src/mbgl/style/layers/symbol_layer.cpp @@ -3,33 +3,34 @@ #include <mbgl/style/layers/symbol_layer.hpp> #include <mbgl/style/layers/symbol_layer_impl.hpp> #include <mbgl/style/conversion/stringify.hpp> +#include <mbgl/style/layer_observer.hpp> namespace mbgl { namespace style { SymbolLayer::SymbolLayer(const std::string& layerID, const std::string& sourceID) - : Layer(LayerType::Symbol, std::make_unique<Impl>()) - , impl(static_cast<Impl*>(baseImpl.get())) { - impl->id = layerID; - impl->source = sourceID; + : Layer(makeMutable<Impl>(LayerType::Symbol, layerID, sourceID)) { } -SymbolLayer::SymbolLayer(const Impl& other) - : Layer(LayerType::Symbol, std::make_unique<Impl>(other)) - , impl(static_cast<Impl*>(baseImpl.get())) { +SymbolLayer::SymbolLayer(Immutable<Impl> impl_) + : Layer(std::move(impl_)) { } SymbolLayer::~SymbolLayer() = default; -std::unique_ptr<Layer> SymbolLayer::Impl::clone() const { - return std::make_unique<SymbolLayer>(*this); +const SymbolLayer::Impl& SymbolLayer::impl() const { + return static_cast<const Impl&>(*baseImpl); } -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->cascading = SymbolPaintProperties::Cascading(); - return std::move(result); +Mutable<SymbolLayer::Impl> SymbolLayer::mutableImpl() const { + return makeMutable<Impl>(impl()); +} + +std::unique_ptr<Layer> SymbolLayer::cloneRef(const std::string& id_) const { + auto impl_ = mutableImpl(); + impl_->id = id_; + impl_->cascading = SymbolPaintProperties::Cascading(); + return std::make_unique<SymbolLayer>(std::move(impl_)); } void SymbolLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>& writer) const { @@ -39,26 +40,55 @@ void SymbolLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffe // Source const std::string& SymbolLayer::getSourceID() const { - return impl->source; + return impl().source; } void SymbolLayer::setSourceLayer(const std::string& sourceLayer) { - impl->sourceLayer = sourceLayer; + auto impl_ = mutableImpl(); + impl_->sourceLayer = sourceLayer; + baseImpl = std::move(impl_); } const std::string& SymbolLayer::getSourceLayer() const { - return impl->sourceLayer; + return impl().sourceLayer; } // Filter void SymbolLayer::setFilter(const Filter& filter) { - impl->filter = filter; - impl->observer->onLayerFilterChanged(*this); + auto impl_ = mutableImpl(); + impl_->filter = filter; + baseImpl = std::move(impl_); + observer->onLayerFilterChanged(*this); } const Filter& SymbolLayer::getFilter() const { - return impl->filter; + return impl().filter; +} + +// Visibility + +void SymbolLayer::setVisibility(VisibilityType value) { + if (value == getVisibility()) + return; + auto impl_ = mutableImpl(); + impl_->visibility = value; + baseImpl = std::move(impl_); + observer->onLayerVisibilityChanged(*this); +} + +// Zoom range + +void SymbolLayer::setMinZoom(float minZoom) { + auto impl_ = mutableImpl(); + impl_->minZoom = minZoom; + baseImpl = std::move(impl_); +} + +void SymbolLayer::setMaxZoom(float maxZoom) { + auto impl_ = mutableImpl(); + impl_->maxZoom = maxZoom; + baseImpl = std::move(impl_); } // Layout properties @@ -68,476 +98,544 @@ PropertyValue<SymbolPlacementType> SymbolLayer::getDefaultSymbolPlacement() { } PropertyValue<SymbolPlacementType> SymbolLayer::getSymbolPlacement() const { - return impl->layout.unevaluated.get<SymbolPlacement>(); + return impl().layout.unevaluated.get<SymbolPlacement>(); } void SymbolLayer::setSymbolPlacement(PropertyValue<SymbolPlacementType> value) { if (value == getSymbolPlacement()) return; - impl->layout.unevaluated.get<SymbolPlacement>() = value; - impl->observer->onLayerLayoutPropertyChanged(*this, "symbol-placement"); + auto impl_ = mutableImpl(); + impl_->layout.unevaluated.get<SymbolPlacement>() = value; + baseImpl = std::move(impl_); + observer->onLayerLayoutPropertyChanged(*this, "symbol-placement"); } PropertyValue<float> SymbolLayer::getDefaultSymbolSpacing() { return SymbolSpacing::defaultValue(); } PropertyValue<float> SymbolLayer::getSymbolSpacing() const { - return impl->layout.unevaluated.get<SymbolSpacing>(); + return impl().layout.unevaluated.get<SymbolSpacing>(); } void SymbolLayer::setSymbolSpacing(PropertyValue<float> value) { if (value == getSymbolSpacing()) return; - impl->layout.unevaluated.get<SymbolSpacing>() = value; - impl->observer->onLayerLayoutPropertyChanged(*this, "symbol-spacing"); + auto impl_ = mutableImpl(); + impl_->layout.unevaluated.get<SymbolSpacing>() = value; + baseImpl = std::move(impl_); + observer->onLayerLayoutPropertyChanged(*this, "symbol-spacing"); } PropertyValue<bool> SymbolLayer::getDefaultSymbolAvoidEdges() { return SymbolAvoidEdges::defaultValue(); } PropertyValue<bool> SymbolLayer::getSymbolAvoidEdges() const { - return impl->layout.unevaluated.get<SymbolAvoidEdges>(); + return impl().layout.unevaluated.get<SymbolAvoidEdges>(); } void SymbolLayer::setSymbolAvoidEdges(PropertyValue<bool> value) { if (value == getSymbolAvoidEdges()) return; - impl->layout.unevaluated.get<SymbolAvoidEdges>() = value; - impl->observer->onLayerLayoutPropertyChanged(*this, "symbol-avoid-edges"); + auto impl_ = mutableImpl(); + impl_->layout.unevaluated.get<SymbolAvoidEdges>() = value; + baseImpl = std::move(impl_); + observer->onLayerLayoutPropertyChanged(*this, "symbol-avoid-edges"); } PropertyValue<bool> SymbolLayer::getDefaultIconAllowOverlap() { return IconAllowOverlap::defaultValue(); } PropertyValue<bool> SymbolLayer::getIconAllowOverlap() const { - return impl->layout.unevaluated.get<IconAllowOverlap>(); + return impl().layout.unevaluated.get<IconAllowOverlap>(); } void SymbolLayer::setIconAllowOverlap(PropertyValue<bool> value) { if (value == getIconAllowOverlap()) return; - impl->layout.unevaluated.get<IconAllowOverlap>() = value; - impl->observer->onLayerLayoutPropertyChanged(*this, "icon-allow-overlap"); + auto impl_ = mutableImpl(); + impl_->layout.unevaluated.get<IconAllowOverlap>() = value; + baseImpl = std::move(impl_); + observer->onLayerLayoutPropertyChanged(*this, "icon-allow-overlap"); } PropertyValue<bool> SymbolLayer::getDefaultIconIgnorePlacement() { return IconIgnorePlacement::defaultValue(); } PropertyValue<bool> SymbolLayer::getIconIgnorePlacement() const { - return impl->layout.unevaluated.get<IconIgnorePlacement>(); + return impl().layout.unevaluated.get<IconIgnorePlacement>(); } void SymbolLayer::setIconIgnorePlacement(PropertyValue<bool> value) { if (value == getIconIgnorePlacement()) return; - impl->layout.unevaluated.get<IconIgnorePlacement>() = value; - impl->observer->onLayerLayoutPropertyChanged(*this, "icon-ignore-placement"); + auto impl_ = mutableImpl(); + impl_->layout.unevaluated.get<IconIgnorePlacement>() = value; + baseImpl = std::move(impl_); + observer->onLayerLayoutPropertyChanged(*this, "icon-ignore-placement"); } PropertyValue<bool> SymbolLayer::getDefaultIconOptional() { return IconOptional::defaultValue(); } PropertyValue<bool> SymbolLayer::getIconOptional() const { - return impl->layout.unevaluated.get<IconOptional>(); + return impl().layout.unevaluated.get<IconOptional>(); } void SymbolLayer::setIconOptional(PropertyValue<bool> value) { if (value == getIconOptional()) return; - impl->layout.unevaluated.get<IconOptional>() = value; - impl->observer->onLayerLayoutPropertyChanged(*this, "icon-optional"); + auto impl_ = mutableImpl(); + impl_->layout.unevaluated.get<IconOptional>() = value; + baseImpl = std::move(impl_); + observer->onLayerLayoutPropertyChanged(*this, "icon-optional"); } PropertyValue<AlignmentType> SymbolLayer::getDefaultIconRotationAlignment() { return IconRotationAlignment::defaultValue(); } PropertyValue<AlignmentType> SymbolLayer::getIconRotationAlignment() const { - return impl->layout.unevaluated.get<IconRotationAlignment>(); + return impl().layout.unevaluated.get<IconRotationAlignment>(); } void SymbolLayer::setIconRotationAlignment(PropertyValue<AlignmentType> value) { if (value == getIconRotationAlignment()) return; - impl->layout.unevaluated.get<IconRotationAlignment>() = value; - impl->observer->onLayerLayoutPropertyChanged(*this, "icon-rotation-alignment"); + auto impl_ = mutableImpl(); + impl_->layout.unevaluated.get<IconRotationAlignment>() = value; + baseImpl = std::move(impl_); + observer->onLayerLayoutPropertyChanged(*this, "icon-rotation-alignment"); } DataDrivenPropertyValue<float> SymbolLayer::getDefaultIconSize() { return IconSize::defaultValue(); } DataDrivenPropertyValue<float> SymbolLayer::getIconSize() const { - return impl->layout.unevaluated.get<IconSize>(); + return impl().layout.unevaluated.get<IconSize>(); } void SymbolLayer::setIconSize(DataDrivenPropertyValue<float> value) { if (value == getIconSize()) return; - impl->layout.unevaluated.get<IconSize>() = value; - impl->observer->onLayerLayoutPropertyChanged(*this, "icon-size"); + auto impl_ = mutableImpl(); + impl_->layout.unevaluated.get<IconSize>() = value; + baseImpl = std::move(impl_); + observer->onLayerLayoutPropertyChanged(*this, "icon-size"); } PropertyValue<IconTextFitType> SymbolLayer::getDefaultIconTextFit() { return IconTextFit::defaultValue(); } PropertyValue<IconTextFitType> SymbolLayer::getIconTextFit() const { - return impl->layout.unevaluated.get<IconTextFit>(); + return impl().layout.unevaluated.get<IconTextFit>(); } void SymbolLayer::setIconTextFit(PropertyValue<IconTextFitType> value) { if (value == getIconTextFit()) return; - impl->layout.unevaluated.get<IconTextFit>() = value; - impl->observer->onLayerLayoutPropertyChanged(*this, "icon-text-fit"); + auto impl_ = mutableImpl(); + impl_->layout.unevaluated.get<IconTextFit>() = value; + baseImpl = std::move(impl_); + observer->onLayerLayoutPropertyChanged(*this, "icon-text-fit"); } PropertyValue<std::array<float, 4>> SymbolLayer::getDefaultIconTextFitPadding() { return IconTextFitPadding::defaultValue(); } PropertyValue<std::array<float, 4>> SymbolLayer::getIconTextFitPadding() const { - return impl->layout.unevaluated.get<IconTextFitPadding>(); + return impl().layout.unevaluated.get<IconTextFitPadding>(); } void SymbolLayer::setIconTextFitPadding(PropertyValue<std::array<float, 4>> value) { if (value == getIconTextFitPadding()) return; - impl->layout.unevaluated.get<IconTextFitPadding>() = value; - impl->observer->onLayerLayoutPropertyChanged(*this, "icon-text-fit-padding"); + auto impl_ = mutableImpl(); + impl_->layout.unevaluated.get<IconTextFitPadding>() = value; + baseImpl = std::move(impl_); + observer->onLayerLayoutPropertyChanged(*this, "icon-text-fit-padding"); } DataDrivenPropertyValue<std::string> SymbolLayer::getDefaultIconImage() { return IconImage::defaultValue(); } DataDrivenPropertyValue<std::string> SymbolLayer::getIconImage() const { - return impl->layout.unevaluated.get<IconImage>(); + return impl().layout.unevaluated.get<IconImage>(); } void SymbolLayer::setIconImage(DataDrivenPropertyValue<std::string> value) { if (value == getIconImage()) return; - impl->layout.unevaluated.get<IconImage>() = value; - impl->observer->onLayerLayoutPropertyChanged(*this, "icon-image"); + auto impl_ = mutableImpl(); + impl_->layout.unevaluated.get<IconImage>() = value; + baseImpl = std::move(impl_); + observer->onLayerLayoutPropertyChanged(*this, "icon-image"); } DataDrivenPropertyValue<float> SymbolLayer::getDefaultIconRotate() { return IconRotate::defaultValue(); } DataDrivenPropertyValue<float> SymbolLayer::getIconRotate() const { - return impl->layout.unevaluated.get<IconRotate>(); + return impl().layout.unevaluated.get<IconRotate>(); } void SymbolLayer::setIconRotate(DataDrivenPropertyValue<float> value) { if (value == getIconRotate()) return; - impl->layout.unevaluated.get<IconRotate>() = value; - impl->observer->onLayerLayoutPropertyChanged(*this, "icon-rotate"); + auto impl_ = mutableImpl(); + impl_->layout.unevaluated.get<IconRotate>() = value; + baseImpl = std::move(impl_); + observer->onLayerLayoutPropertyChanged(*this, "icon-rotate"); } PropertyValue<float> SymbolLayer::getDefaultIconPadding() { return IconPadding::defaultValue(); } PropertyValue<float> SymbolLayer::getIconPadding() const { - return impl->layout.unevaluated.get<IconPadding>(); + return impl().layout.unevaluated.get<IconPadding>(); } void SymbolLayer::setIconPadding(PropertyValue<float> value) { if (value == getIconPadding()) return; - impl->layout.unevaluated.get<IconPadding>() = value; - impl->observer->onLayerLayoutPropertyChanged(*this, "icon-padding"); + auto impl_ = mutableImpl(); + impl_->layout.unevaluated.get<IconPadding>() = value; + baseImpl = std::move(impl_); + observer->onLayerLayoutPropertyChanged(*this, "icon-padding"); } PropertyValue<bool> SymbolLayer::getDefaultIconKeepUpright() { return IconKeepUpright::defaultValue(); } PropertyValue<bool> SymbolLayer::getIconKeepUpright() const { - return impl->layout.unevaluated.get<IconKeepUpright>(); + return impl().layout.unevaluated.get<IconKeepUpright>(); } void SymbolLayer::setIconKeepUpright(PropertyValue<bool> value) { if (value == getIconKeepUpright()) return; - impl->layout.unevaluated.get<IconKeepUpright>() = value; - impl->observer->onLayerLayoutPropertyChanged(*this, "icon-keep-upright"); + auto impl_ = mutableImpl(); + impl_->layout.unevaluated.get<IconKeepUpright>() = value; + baseImpl = std::move(impl_); + observer->onLayerLayoutPropertyChanged(*this, "icon-keep-upright"); } DataDrivenPropertyValue<std::array<float, 2>> SymbolLayer::getDefaultIconOffset() { return IconOffset::defaultValue(); } DataDrivenPropertyValue<std::array<float, 2>> SymbolLayer::getIconOffset() const { - return impl->layout.unevaluated.get<IconOffset>(); + return impl().layout.unevaluated.get<IconOffset>(); } void SymbolLayer::setIconOffset(DataDrivenPropertyValue<std::array<float, 2>> value) { if (value == getIconOffset()) return; - impl->layout.unevaluated.get<IconOffset>() = value; - impl->observer->onLayerLayoutPropertyChanged(*this, "icon-offset"); + auto impl_ = mutableImpl(); + impl_->layout.unevaluated.get<IconOffset>() = value; + baseImpl = std::move(impl_); + observer->onLayerLayoutPropertyChanged(*this, "icon-offset"); } PropertyValue<AlignmentType> SymbolLayer::getDefaultTextPitchAlignment() { return TextPitchAlignment::defaultValue(); } PropertyValue<AlignmentType> SymbolLayer::getTextPitchAlignment() const { - return impl->layout.unevaluated.get<TextPitchAlignment>(); + return impl().layout.unevaluated.get<TextPitchAlignment>(); } void SymbolLayer::setTextPitchAlignment(PropertyValue<AlignmentType> value) { if (value == getTextPitchAlignment()) return; - impl->layout.unevaluated.get<TextPitchAlignment>() = value; - impl->observer->onLayerLayoutPropertyChanged(*this, "text-pitch-alignment"); + auto impl_ = mutableImpl(); + impl_->layout.unevaluated.get<TextPitchAlignment>() = value; + baseImpl = std::move(impl_); + observer->onLayerLayoutPropertyChanged(*this, "text-pitch-alignment"); } PropertyValue<AlignmentType> SymbolLayer::getDefaultTextRotationAlignment() { return TextRotationAlignment::defaultValue(); } PropertyValue<AlignmentType> SymbolLayer::getTextRotationAlignment() const { - return impl->layout.unevaluated.get<TextRotationAlignment>(); + return impl().layout.unevaluated.get<TextRotationAlignment>(); } void SymbolLayer::setTextRotationAlignment(PropertyValue<AlignmentType> value) { if (value == getTextRotationAlignment()) return; - impl->layout.unevaluated.get<TextRotationAlignment>() = value; - impl->observer->onLayerLayoutPropertyChanged(*this, "text-rotation-alignment"); + auto impl_ = mutableImpl(); + impl_->layout.unevaluated.get<TextRotationAlignment>() = value; + baseImpl = std::move(impl_); + observer->onLayerLayoutPropertyChanged(*this, "text-rotation-alignment"); } DataDrivenPropertyValue<std::string> SymbolLayer::getDefaultTextField() { return TextField::defaultValue(); } DataDrivenPropertyValue<std::string> SymbolLayer::getTextField() const { - return impl->layout.unevaluated.get<TextField>(); + return impl().layout.unevaluated.get<TextField>(); } void SymbolLayer::setTextField(DataDrivenPropertyValue<std::string> value) { if (value == getTextField()) return; - impl->layout.unevaluated.get<TextField>() = value; - impl->observer->onLayerLayoutPropertyChanged(*this, "text-field"); + auto impl_ = mutableImpl(); + impl_->layout.unevaluated.get<TextField>() = value; + baseImpl = std::move(impl_); + observer->onLayerLayoutPropertyChanged(*this, "text-field"); } PropertyValue<std::vector<std::string>> SymbolLayer::getDefaultTextFont() { return TextFont::defaultValue(); } PropertyValue<std::vector<std::string>> SymbolLayer::getTextFont() const { - return impl->layout.unevaluated.get<TextFont>(); + return impl().layout.unevaluated.get<TextFont>(); } void SymbolLayer::setTextFont(PropertyValue<std::vector<std::string>> value) { if (value == getTextFont()) return; - impl->layout.unevaluated.get<TextFont>() = value; - impl->observer->onLayerLayoutPropertyChanged(*this, "text-font"); + auto impl_ = mutableImpl(); + impl_->layout.unevaluated.get<TextFont>() = value; + baseImpl = std::move(impl_); + observer->onLayerLayoutPropertyChanged(*this, "text-font"); } DataDrivenPropertyValue<float> SymbolLayer::getDefaultTextSize() { return TextSize::defaultValue(); } DataDrivenPropertyValue<float> SymbolLayer::getTextSize() const { - return impl->layout.unevaluated.get<TextSize>(); + return impl().layout.unevaluated.get<TextSize>(); } void SymbolLayer::setTextSize(DataDrivenPropertyValue<float> value) { if (value == getTextSize()) return; - impl->layout.unevaluated.get<TextSize>() = value; - impl->observer->onLayerLayoutPropertyChanged(*this, "text-size"); + auto impl_ = mutableImpl(); + impl_->layout.unevaluated.get<TextSize>() = value; + baseImpl = std::move(impl_); + observer->onLayerLayoutPropertyChanged(*this, "text-size"); } PropertyValue<float> SymbolLayer::getDefaultTextMaxWidth() { return TextMaxWidth::defaultValue(); } PropertyValue<float> SymbolLayer::getTextMaxWidth() const { - return impl->layout.unevaluated.get<TextMaxWidth>(); + return impl().layout.unevaluated.get<TextMaxWidth>(); } void SymbolLayer::setTextMaxWidth(PropertyValue<float> value) { if (value == getTextMaxWidth()) return; - impl->layout.unevaluated.get<TextMaxWidth>() = value; - impl->observer->onLayerLayoutPropertyChanged(*this, "text-max-width"); + auto impl_ = mutableImpl(); + impl_->layout.unevaluated.get<TextMaxWidth>() = value; + baseImpl = std::move(impl_); + observer->onLayerLayoutPropertyChanged(*this, "text-max-width"); } PropertyValue<float> SymbolLayer::getDefaultTextLineHeight() { return TextLineHeight::defaultValue(); } PropertyValue<float> SymbolLayer::getTextLineHeight() const { - return impl->layout.unevaluated.get<TextLineHeight>(); + return impl().layout.unevaluated.get<TextLineHeight>(); } void SymbolLayer::setTextLineHeight(PropertyValue<float> value) { if (value == getTextLineHeight()) return; - impl->layout.unevaluated.get<TextLineHeight>() = value; - impl->observer->onLayerLayoutPropertyChanged(*this, "text-line-height"); + auto impl_ = mutableImpl(); + impl_->layout.unevaluated.get<TextLineHeight>() = value; + baseImpl = std::move(impl_); + observer->onLayerLayoutPropertyChanged(*this, "text-line-height"); } PropertyValue<float> SymbolLayer::getDefaultTextLetterSpacing() { return TextLetterSpacing::defaultValue(); } PropertyValue<float> SymbolLayer::getTextLetterSpacing() const { - return impl->layout.unevaluated.get<TextLetterSpacing>(); + return impl().layout.unevaluated.get<TextLetterSpacing>(); } void SymbolLayer::setTextLetterSpacing(PropertyValue<float> value) { if (value == getTextLetterSpacing()) return; - impl->layout.unevaluated.get<TextLetterSpacing>() = value; - impl->observer->onLayerLayoutPropertyChanged(*this, "text-letter-spacing"); + auto impl_ = mutableImpl(); + impl_->layout.unevaluated.get<TextLetterSpacing>() = value; + baseImpl = std::move(impl_); + observer->onLayerLayoutPropertyChanged(*this, "text-letter-spacing"); } PropertyValue<TextJustifyType> SymbolLayer::getDefaultTextJustify() { return TextJustify::defaultValue(); } PropertyValue<TextJustifyType> SymbolLayer::getTextJustify() const { - return impl->layout.unevaluated.get<TextJustify>(); + return impl().layout.unevaluated.get<TextJustify>(); } void SymbolLayer::setTextJustify(PropertyValue<TextJustifyType> value) { if (value == getTextJustify()) return; - impl->layout.unevaluated.get<TextJustify>() = value; - impl->observer->onLayerLayoutPropertyChanged(*this, "text-justify"); + auto impl_ = mutableImpl(); + impl_->layout.unevaluated.get<TextJustify>() = value; + baseImpl = std::move(impl_); + observer->onLayerLayoutPropertyChanged(*this, "text-justify"); } PropertyValue<TextAnchorType> SymbolLayer::getDefaultTextAnchor() { return TextAnchor::defaultValue(); } PropertyValue<TextAnchorType> SymbolLayer::getTextAnchor() const { - return impl->layout.unevaluated.get<TextAnchor>(); + return impl().layout.unevaluated.get<TextAnchor>(); } void SymbolLayer::setTextAnchor(PropertyValue<TextAnchorType> value) { if (value == getTextAnchor()) return; - impl->layout.unevaluated.get<TextAnchor>() = value; - impl->observer->onLayerLayoutPropertyChanged(*this, "text-anchor"); + auto impl_ = mutableImpl(); + impl_->layout.unevaluated.get<TextAnchor>() = value; + baseImpl = std::move(impl_); + observer->onLayerLayoutPropertyChanged(*this, "text-anchor"); } PropertyValue<float> SymbolLayer::getDefaultTextMaxAngle() { return TextMaxAngle::defaultValue(); } PropertyValue<float> SymbolLayer::getTextMaxAngle() const { - return impl->layout.unevaluated.get<TextMaxAngle>(); + return impl().layout.unevaluated.get<TextMaxAngle>(); } void SymbolLayer::setTextMaxAngle(PropertyValue<float> value) { if (value == getTextMaxAngle()) return; - impl->layout.unevaluated.get<TextMaxAngle>() = value; - impl->observer->onLayerLayoutPropertyChanged(*this, "text-max-angle"); + auto impl_ = mutableImpl(); + impl_->layout.unevaluated.get<TextMaxAngle>() = value; + baseImpl = std::move(impl_); + observer->onLayerLayoutPropertyChanged(*this, "text-max-angle"); } DataDrivenPropertyValue<float> SymbolLayer::getDefaultTextRotate() { return TextRotate::defaultValue(); } DataDrivenPropertyValue<float> SymbolLayer::getTextRotate() const { - return impl->layout.unevaluated.get<TextRotate>(); + return impl().layout.unevaluated.get<TextRotate>(); } void SymbolLayer::setTextRotate(DataDrivenPropertyValue<float> value) { if (value == getTextRotate()) return; - impl->layout.unevaluated.get<TextRotate>() = value; - impl->observer->onLayerLayoutPropertyChanged(*this, "text-rotate"); + auto impl_ = mutableImpl(); + impl_->layout.unevaluated.get<TextRotate>() = value; + baseImpl = std::move(impl_); + observer->onLayerLayoutPropertyChanged(*this, "text-rotate"); } PropertyValue<float> SymbolLayer::getDefaultTextPadding() { return TextPadding::defaultValue(); } PropertyValue<float> SymbolLayer::getTextPadding() const { - return impl->layout.unevaluated.get<TextPadding>(); + return impl().layout.unevaluated.get<TextPadding>(); } void SymbolLayer::setTextPadding(PropertyValue<float> value) { if (value == getTextPadding()) return; - impl->layout.unevaluated.get<TextPadding>() = value; - impl->observer->onLayerLayoutPropertyChanged(*this, "text-padding"); + auto impl_ = mutableImpl(); + impl_->layout.unevaluated.get<TextPadding>() = value; + baseImpl = std::move(impl_); + observer->onLayerLayoutPropertyChanged(*this, "text-padding"); } PropertyValue<bool> SymbolLayer::getDefaultTextKeepUpright() { return TextKeepUpright::defaultValue(); } PropertyValue<bool> SymbolLayer::getTextKeepUpright() const { - return impl->layout.unevaluated.get<TextKeepUpright>(); + return impl().layout.unevaluated.get<TextKeepUpright>(); } void SymbolLayer::setTextKeepUpright(PropertyValue<bool> value) { if (value == getTextKeepUpright()) return; - impl->layout.unevaluated.get<TextKeepUpright>() = value; - impl->observer->onLayerLayoutPropertyChanged(*this, "text-keep-upright"); + auto impl_ = mutableImpl(); + impl_->layout.unevaluated.get<TextKeepUpright>() = value; + baseImpl = std::move(impl_); + observer->onLayerLayoutPropertyChanged(*this, "text-keep-upright"); } DataDrivenPropertyValue<TextTransformType> SymbolLayer::getDefaultTextTransform() { return TextTransform::defaultValue(); } DataDrivenPropertyValue<TextTransformType> SymbolLayer::getTextTransform() const { - return impl->layout.unevaluated.get<TextTransform>(); + return impl().layout.unevaluated.get<TextTransform>(); } void SymbolLayer::setTextTransform(DataDrivenPropertyValue<TextTransformType> value) { if (value == getTextTransform()) return; - impl->layout.unevaluated.get<TextTransform>() = value; - impl->observer->onLayerLayoutPropertyChanged(*this, "text-transform"); + auto impl_ = mutableImpl(); + impl_->layout.unevaluated.get<TextTransform>() = value; + baseImpl = std::move(impl_); + observer->onLayerLayoutPropertyChanged(*this, "text-transform"); } DataDrivenPropertyValue<std::array<float, 2>> SymbolLayer::getDefaultTextOffset() { return TextOffset::defaultValue(); } DataDrivenPropertyValue<std::array<float, 2>> SymbolLayer::getTextOffset() const { - return impl->layout.unevaluated.get<TextOffset>(); + return impl().layout.unevaluated.get<TextOffset>(); } void SymbolLayer::setTextOffset(DataDrivenPropertyValue<std::array<float, 2>> value) { if (value == getTextOffset()) return; - impl->layout.unevaluated.get<TextOffset>() = value; - impl->observer->onLayerLayoutPropertyChanged(*this, "text-offset"); + auto impl_ = mutableImpl(); + impl_->layout.unevaluated.get<TextOffset>() = value; + baseImpl = std::move(impl_); + observer->onLayerLayoutPropertyChanged(*this, "text-offset"); } PropertyValue<bool> SymbolLayer::getDefaultTextAllowOverlap() { return TextAllowOverlap::defaultValue(); } PropertyValue<bool> SymbolLayer::getTextAllowOverlap() const { - return impl->layout.unevaluated.get<TextAllowOverlap>(); + return impl().layout.unevaluated.get<TextAllowOverlap>(); } void SymbolLayer::setTextAllowOverlap(PropertyValue<bool> value) { if (value == getTextAllowOverlap()) return; - impl->layout.unevaluated.get<TextAllowOverlap>() = value; - impl->observer->onLayerLayoutPropertyChanged(*this, "text-allow-overlap"); + auto impl_ = mutableImpl(); + impl_->layout.unevaluated.get<TextAllowOverlap>() = value; + baseImpl = std::move(impl_); + observer->onLayerLayoutPropertyChanged(*this, "text-allow-overlap"); } PropertyValue<bool> SymbolLayer::getDefaultTextIgnorePlacement() { return TextIgnorePlacement::defaultValue(); } PropertyValue<bool> SymbolLayer::getTextIgnorePlacement() const { - return impl->layout.unevaluated.get<TextIgnorePlacement>(); + return impl().layout.unevaluated.get<TextIgnorePlacement>(); } void SymbolLayer::setTextIgnorePlacement(PropertyValue<bool> value) { if (value == getTextIgnorePlacement()) return; - impl->layout.unevaluated.get<TextIgnorePlacement>() = value; - impl->observer->onLayerLayoutPropertyChanged(*this, "text-ignore-placement"); + auto impl_ = mutableImpl(); + impl_->layout.unevaluated.get<TextIgnorePlacement>() = value; + baseImpl = std::move(impl_); + observer->onLayerLayoutPropertyChanged(*this, "text-ignore-placement"); } PropertyValue<bool> SymbolLayer::getDefaultTextOptional() { return TextOptional::defaultValue(); } PropertyValue<bool> SymbolLayer::getTextOptional() const { - return impl->layout.unevaluated.get<TextOptional>(); + return impl().layout.unevaluated.get<TextOptional>(); } void SymbolLayer::setTextOptional(PropertyValue<bool> value) { if (value == getTextOptional()) return; - impl->layout.unevaluated.get<TextOptional>() = value; - impl->observer->onLayerLayoutPropertyChanged(*this, "text-optional"); + auto impl_ = mutableImpl(); + impl_->layout.unevaluated.get<TextOptional>() = value; + baseImpl = std::move(impl_); + observer->onLayerLayoutPropertyChanged(*this, "text-optional"); } // Paint properties @@ -547,26 +645,30 @@ DataDrivenPropertyValue<float> SymbolLayer::getDefaultIconOpacity() { } DataDrivenPropertyValue<float> SymbolLayer::getIconOpacity(const optional<std::string>& klass) const { - return impl->cascading.template get<IconOpacity>().get(klass); + return impl().cascading.template get<IconOpacity>().get(klass); } void SymbolLayer::setIconOpacity(DataDrivenPropertyValue<float> value, const optional<std::string>& klass) { if (value == getIconOpacity(klass)) return; - impl->cascading.template get<IconOpacity>().set(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<IconOpacity>().set(value, klass); + baseImpl = std::move(impl_); if (value.isDataDriven()) { - impl->observer->onLayerDataDrivenPaintPropertyChanged(*this); + observer->onLayerDataDrivenPaintPropertyChanged(*this); } else { - impl->observer->onLayerPaintPropertyChanged(*this); + observer->onLayerPaintPropertyChanged(*this); } } void SymbolLayer::setIconOpacityTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<IconOpacity>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<IconOpacity>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions SymbolLayer::getIconOpacityTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<IconOpacity>().getTransition(klass); + return impl().cascading.template get<IconOpacity>().getTransition(klass); } DataDrivenPropertyValue<Color> SymbolLayer::getDefaultIconColor() { @@ -574,26 +676,30 @@ DataDrivenPropertyValue<Color> SymbolLayer::getDefaultIconColor() { } DataDrivenPropertyValue<Color> SymbolLayer::getIconColor(const optional<std::string>& klass) const { - return impl->cascading.template get<IconColor>().get(klass); + return impl().cascading.template get<IconColor>().get(klass); } void SymbolLayer::setIconColor(DataDrivenPropertyValue<Color> value, const optional<std::string>& klass) { if (value == getIconColor(klass)) return; - impl->cascading.template get<IconColor>().set(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<IconColor>().set(value, klass); + baseImpl = std::move(impl_); if (value.isDataDriven()) { - impl->observer->onLayerDataDrivenPaintPropertyChanged(*this); + observer->onLayerDataDrivenPaintPropertyChanged(*this); } else { - impl->observer->onLayerPaintPropertyChanged(*this); + observer->onLayerPaintPropertyChanged(*this); } } void SymbolLayer::setIconColorTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<IconColor>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<IconColor>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions SymbolLayer::getIconColorTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<IconColor>().getTransition(klass); + return impl().cascading.template get<IconColor>().getTransition(klass); } DataDrivenPropertyValue<Color> SymbolLayer::getDefaultIconHaloColor() { @@ -601,26 +707,30 @@ DataDrivenPropertyValue<Color> SymbolLayer::getDefaultIconHaloColor() { } DataDrivenPropertyValue<Color> SymbolLayer::getIconHaloColor(const optional<std::string>& klass) const { - return impl->cascading.template get<IconHaloColor>().get(klass); + return impl().cascading.template get<IconHaloColor>().get(klass); } void SymbolLayer::setIconHaloColor(DataDrivenPropertyValue<Color> value, const optional<std::string>& klass) { if (value == getIconHaloColor(klass)) return; - impl->cascading.template get<IconHaloColor>().set(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<IconHaloColor>().set(value, klass); + baseImpl = std::move(impl_); if (value.isDataDriven()) { - impl->observer->onLayerDataDrivenPaintPropertyChanged(*this); + observer->onLayerDataDrivenPaintPropertyChanged(*this); } else { - impl->observer->onLayerPaintPropertyChanged(*this); + observer->onLayerPaintPropertyChanged(*this); } } void SymbolLayer::setIconHaloColorTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<IconHaloColor>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<IconHaloColor>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions SymbolLayer::getIconHaloColorTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<IconHaloColor>().getTransition(klass); + return impl().cascading.template get<IconHaloColor>().getTransition(klass); } DataDrivenPropertyValue<float> SymbolLayer::getDefaultIconHaloWidth() { @@ -628,26 +738,30 @@ DataDrivenPropertyValue<float> SymbolLayer::getDefaultIconHaloWidth() { } DataDrivenPropertyValue<float> SymbolLayer::getIconHaloWidth(const optional<std::string>& klass) const { - return impl->cascading.template get<IconHaloWidth>().get(klass); + return impl().cascading.template get<IconHaloWidth>().get(klass); } void SymbolLayer::setIconHaloWidth(DataDrivenPropertyValue<float> value, const optional<std::string>& klass) { if (value == getIconHaloWidth(klass)) return; - impl->cascading.template get<IconHaloWidth>().set(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<IconHaloWidth>().set(value, klass); + baseImpl = std::move(impl_); if (value.isDataDriven()) { - impl->observer->onLayerDataDrivenPaintPropertyChanged(*this); + observer->onLayerDataDrivenPaintPropertyChanged(*this); } else { - impl->observer->onLayerPaintPropertyChanged(*this); + observer->onLayerPaintPropertyChanged(*this); } } void SymbolLayer::setIconHaloWidthTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<IconHaloWidth>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<IconHaloWidth>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions SymbolLayer::getIconHaloWidthTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<IconHaloWidth>().getTransition(klass); + return impl().cascading.template get<IconHaloWidth>().getTransition(klass); } DataDrivenPropertyValue<float> SymbolLayer::getDefaultIconHaloBlur() { @@ -655,26 +769,30 @@ DataDrivenPropertyValue<float> SymbolLayer::getDefaultIconHaloBlur() { } DataDrivenPropertyValue<float> SymbolLayer::getIconHaloBlur(const optional<std::string>& klass) const { - return impl->cascading.template get<IconHaloBlur>().get(klass); + return impl().cascading.template get<IconHaloBlur>().get(klass); } void SymbolLayer::setIconHaloBlur(DataDrivenPropertyValue<float> value, const optional<std::string>& klass) { if (value == getIconHaloBlur(klass)) return; - impl->cascading.template get<IconHaloBlur>().set(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<IconHaloBlur>().set(value, klass); + baseImpl = std::move(impl_); if (value.isDataDriven()) { - impl->observer->onLayerDataDrivenPaintPropertyChanged(*this); + observer->onLayerDataDrivenPaintPropertyChanged(*this); } else { - impl->observer->onLayerPaintPropertyChanged(*this); + observer->onLayerPaintPropertyChanged(*this); } } void SymbolLayer::setIconHaloBlurTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<IconHaloBlur>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<IconHaloBlur>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions SymbolLayer::getIconHaloBlurTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<IconHaloBlur>().getTransition(klass); + return impl().cascading.template get<IconHaloBlur>().getTransition(klass); } PropertyValue<std::array<float, 2>> SymbolLayer::getDefaultIconTranslate() { @@ -682,22 +800,26 @@ PropertyValue<std::array<float, 2>> SymbolLayer::getDefaultIconTranslate() { } PropertyValue<std::array<float, 2>> SymbolLayer::getIconTranslate(const optional<std::string>& klass) const { - return impl->cascading.template get<IconTranslate>().get(klass); + return impl().cascading.template get<IconTranslate>().get(klass); } void SymbolLayer::setIconTranslate(PropertyValue<std::array<float, 2>> value, const optional<std::string>& klass) { if (value == getIconTranslate(klass)) return; - impl->cascading.template get<IconTranslate>().set(value, klass); - impl->observer->onLayerPaintPropertyChanged(*this); + auto impl_ = mutableImpl(); + impl_->cascading.template get<IconTranslate>().set(value, klass); + baseImpl = std::move(impl_); + observer->onLayerPaintPropertyChanged(*this); } void SymbolLayer::setIconTranslateTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<IconTranslate>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<IconTranslate>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions SymbolLayer::getIconTranslateTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<IconTranslate>().getTransition(klass); + return impl().cascading.template get<IconTranslate>().getTransition(klass); } PropertyValue<TranslateAnchorType> SymbolLayer::getDefaultIconTranslateAnchor() { @@ -705,22 +827,26 @@ PropertyValue<TranslateAnchorType> SymbolLayer::getDefaultIconTranslateAnchor() } PropertyValue<TranslateAnchorType> SymbolLayer::getIconTranslateAnchor(const optional<std::string>& klass) const { - return impl->cascading.template get<IconTranslateAnchor>().get(klass); + return impl().cascading.template get<IconTranslateAnchor>().get(klass); } void SymbolLayer::setIconTranslateAnchor(PropertyValue<TranslateAnchorType> value, const optional<std::string>& klass) { if (value == getIconTranslateAnchor(klass)) return; - impl->cascading.template get<IconTranslateAnchor>().set(value, klass); - impl->observer->onLayerPaintPropertyChanged(*this); + auto impl_ = mutableImpl(); + impl_->cascading.template get<IconTranslateAnchor>().set(value, klass); + baseImpl = std::move(impl_); + observer->onLayerPaintPropertyChanged(*this); } void SymbolLayer::setIconTranslateAnchorTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<IconTranslateAnchor>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<IconTranslateAnchor>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions SymbolLayer::getIconTranslateAnchorTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<IconTranslateAnchor>().getTransition(klass); + return impl().cascading.template get<IconTranslateAnchor>().getTransition(klass); } DataDrivenPropertyValue<float> SymbolLayer::getDefaultTextOpacity() { @@ -728,26 +854,30 @@ DataDrivenPropertyValue<float> SymbolLayer::getDefaultTextOpacity() { } DataDrivenPropertyValue<float> SymbolLayer::getTextOpacity(const optional<std::string>& klass) const { - return impl->cascading.template get<TextOpacity>().get(klass); + return impl().cascading.template get<TextOpacity>().get(klass); } void SymbolLayer::setTextOpacity(DataDrivenPropertyValue<float> value, const optional<std::string>& klass) { if (value == getTextOpacity(klass)) return; - impl->cascading.template get<TextOpacity>().set(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<TextOpacity>().set(value, klass); + baseImpl = std::move(impl_); if (value.isDataDriven()) { - impl->observer->onLayerDataDrivenPaintPropertyChanged(*this); + observer->onLayerDataDrivenPaintPropertyChanged(*this); } else { - impl->observer->onLayerPaintPropertyChanged(*this); + observer->onLayerPaintPropertyChanged(*this); } } void SymbolLayer::setTextOpacityTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<TextOpacity>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<TextOpacity>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions SymbolLayer::getTextOpacityTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<TextOpacity>().getTransition(klass); + return impl().cascading.template get<TextOpacity>().getTransition(klass); } DataDrivenPropertyValue<Color> SymbolLayer::getDefaultTextColor() { @@ -755,26 +885,30 @@ DataDrivenPropertyValue<Color> SymbolLayer::getDefaultTextColor() { } DataDrivenPropertyValue<Color> SymbolLayer::getTextColor(const optional<std::string>& klass) const { - return impl->cascading.template get<TextColor>().get(klass); + return impl().cascading.template get<TextColor>().get(klass); } void SymbolLayer::setTextColor(DataDrivenPropertyValue<Color> value, const optional<std::string>& klass) { if (value == getTextColor(klass)) return; - impl->cascading.template get<TextColor>().set(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<TextColor>().set(value, klass); + baseImpl = std::move(impl_); if (value.isDataDriven()) { - impl->observer->onLayerDataDrivenPaintPropertyChanged(*this); + observer->onLayerDataDrivenPaintPropertyChanged(*this); } else { - impl->observer->onLayerPaintPropertyChanged(*this); + observer->onLayerPaintPropertyChanged(*this); } } void SymbolLayer::setTextColorTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<TextColor>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<TextColor>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions SymbolLayer::getTextColorTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<TextColor>().getTransition(klass); + return impl().cascading.template get<TextColor>().getTransition(klass); } DataDrivenPropertyValue<Color> SymbolLayer::getDefaultTextHaloColor() { @@ -782,26 +916,30 @@ DataDrivenPropertyValue<Color> SymbolLayer::getDefaultTextHaloColor() { } DataDrivenPropertyValue<Color> SymbolLayer::getTextHaloColor(const optional<std::string>& klass) const { - return impl->cascading.template get<TextHaloColor>().get(klass); + return impl().cascading.template get<TextHaloColor>().get(klass); } void SymbolLayer::setTextHaloColor(DataDrivenPropertyValue<Color> value, const optional<std::string>& klass) { if (value == getTextHaloColor(klass)) return; - impl->cascading.template get<TextHaloColor>().set(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<TextHaloColor>().set(value, klass); + baseImpl = std::move(impl_); if (value.isDataDriven()) { - impl->observer->onLayerDataDrivenPaintPropertyChanged(*this); + observer->onLayerDataDrivenPaintPropertyChanged(*this); } else { - impl->observer->onLayerPaintPropertyChanged(*this); + observer->onLayerPaintPropertyChanged(*this); } } void SymbolLayer::setTextHaloColorTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<TextHaloColor>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<TextHaloColor>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions SymbolLayer::getTextHaloColorTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<TextHaloColor>().getTransition(klass); + return impl().cascading.template get<TextHaloColor>().getTransition(klass); } DataDrivenPropertyValue<float> SymbolLayer::getDefaultTextHaloWidth() { @@ -809,26 +947,30 @@ DataDrivenPropertyValue<float> SymbolLayer::getDefaultTextHaloWidth() { } DataDrivenPropertyValue<float> SymbolLayer::getTextHaloWidth(const optional<std::string>& klass) const { - return impl->cascading.template get<TextHaloWidth>().get(klass); + return impl().cascading.template get<TextHaloWidth>().get(klass); } void SymbolLayer::setTextHaloWidth(DataDrivenPropertyValue<float> value, const optional<std::string>& klass) { if (value == getTextHaloWidth(klass)) return; - impl->cascading.template get<TextHaloWidth>().set(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<TextHaloWidth>().set(value, klass); + baseImpl = std::move(impl_); if (value.isDataDriven()) { - impl->observer->onLayerDataDrivenPaintPropertyChanged(*this); + observer->onLayerDataDrivenPaintPropertyChanged(*this); } else { - impl->observer->onLayerPaintPropertyChanged(*this); + observer->onLayerPaintPropertyChanged(*this); } } void SymbolLayer::setTextHaloWidthTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<TextHaloWidth>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<TextHaloWidth>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions SymbolLayer::getTextHaloWidthTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<TextHaloWidth>().getTransition(klass); + return impl().cascading.template get<TextHaloWidth>().getTransition(klass); } DataDrivenPropertyValue<float> SymbolLayer::getDefaultTextHaloBlur() { @@ -836,26 +978,30 @@ DataDrivenPropertyValue<float> SymbolLayer::getDefaultTextHaloBlur() { } DataDrivenPropertyValue<float> SymbolLayer::getTextHaloBlur(const optional<std::string>& klass) const { - return impl->cascading.template get<TextHaloBlur>().get(klass); + return impl().cascading.template get<TextHaloBlur>().get(klass); } void SymbolLayer::setTextHaloBlur(DataDrivenPropertyValue<float> value, const optional<std::string>& klass) { if (value == getTextHaloBlur(klass)) return; - impl->cascading.template get<TextHaloBlur>().set(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<TextHaloBlur>().set(value, klass); + baseImpl = std::move(impl_); if (value.isDataDriven()) { - impl->observer->onLayerDataDrivenPaintPropertyChanged(*this); + observer->onLayerDataDrivenPaintPropertyChanged(*this); } else { - impl->observer->onLayerPaintPropertyChanged(*this); + observer->onLayerPaintPropertyChanged(*this); } } void SymbolLayer::setTextHaloBlurTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<TextHaloBlur>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<TextHaloBlur>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions SymbolLayer::getTextHaloBlurTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<TextHaloBlur>().getTransition(klass); + return impl().cascading.template get<TextHaloBlur>().getTransition(klass); } PropertyValue<std::array<float, 2>> SymbolLayer::getDefaultTextTranslate() { @@ -863,22 +1009,26 @@ PropertyValue<std::array<float, 2>> SymbolLayer::getDefaultTextTranslate() { } PropertyValue<std::array<float, 2>> SymbolLayer::getTextTranslate(const optional<std::string>& klass) const { - return impl->cascading.template get<TextTranslate>().get(klass); + return impl().cascading.template get<TextTranslate>().get(klass); } void SymbolLayer::setTextTranslate(PropertyValue<std::array<float, 2>> value, const optional<std::string>& klass) { if (value == getTextTranslate(klass)) return; - impl->cascading.template get<TextTranslate>().set(value, klass); - impl->observer->onLayerPaintPropertyChanged(*this); + auto impl_ = mutableImpl(); + impl_->cascading.template get<TextTranslate>().set(value, klass); + baseImpl = std::move(impl_); + observer->onLayerPaintPropertyChanged(*this); } void SymbolLayer::setTextTranslateTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<TextTranslate>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<TextTranslate>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions SymbolLayer::getTextTranslateTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<TextTranslate>().getTransition(klass); + return impl().cascading.template get<TextTranslate>().getTransition(klass); } PropertyValue<TranslateAnchorType> SymbolLayer::getDefaultTextTranslateAnchor() { @@ -886,22 +1036,26 @@ PropertyValue<TranslateAnchorType> SymbolLayer::getDefaultTextTranslateAnchor() } PropertyValue<TranslateAnchorType> SymbolLayer::getTextTranslateAnchor(const optional<std::string>& klass) const { - return impl->cascading.template get<TextTranslateAnchor>().get(klass); + return impl().cascading.template get<TextTranslateAnchor>().get(klass); } void SymbolLayer::setTextTranslateAnchor(PropertyValue<TranslateAnchorType> value, const optional<std::string>& klass) { if (value == getTextTranslateAnchor(klass)) return; - impl->cascading.template get<TextTranslateAnchor>().set(value, klass); - impl->observer->onLayerPaintPropertyChanged(*this); + auto impl_ = mutableImpl(); + impl_->cascading.template get<TextTranslateAnchor>().set(value, klass); + baseImpl = std::move(impl_); + observer->onLayerPaintPropertyChanged(*this); } void SymbolLayer::setTextTranslateAnchorTransition(const TransitionOptions& value, const optional<std::string>& klass) { - impl->cascading.template get<TextTranslateAnchor>().setTransition(value, klass); + auto impl_ = mutableImpl(); + impl_->cascading.template get<TextTranslateAnchor>().setTransition(value, klass); + baseImpl = std::move(impl_); } TransitionOptions SymbolLayer::getTextTranslateAnchorTransition(const optional<std::string>& klass) const { - return impl->cascading.template get<TextTranslateAnchor>().getTransition(klass); + return impl().cascading.template get<TextTranslateAnchor>().getTransition(klass); } } // namespace style diff --git a/src/mbgl/style/layers/symbol_layer_impl.cpp b/src/mbgl/style/layers/symbol_layer_impl.cpp index c99dd8ad70..220a17fd36 100644 --- a/src/mbgl/style/layers/symbol_layer_impl.cpp +++ b/src/mbgl/style/layers/symbol_layer_impl.cpp @@ -5,7 +5,7 @@ namespace mbgl { namespace style { std::unique_ptr<RenderLayer> SymbolLayer::Impl::createRenderLayer() const { - return std::make_unique<RenderSymbolLayer>(*this); + return std::make_unique<RenderSymbolLayer>(staticImmutableCast<SymbolLayer::Impl>(immutableFromThis())); } } // namespace style diff --git a/src/mbgl/style/layers/symbol_layer_impl.hpp b/src/mbgl/style/layers/symbol_layer_impl.hpp index df145647a0..4937ee8721 100644 --- a/src/mbgl/style/layers/symbol_layer_impl.hpp +++ b/src/mbgl/style/layers/symbol_layer_impl.hpp @@ -6,13 +6,12 @@ #include <mbgl/style/layers/symbol_layer_properties.hpp> namespace mbgl { - namespace style { 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; + using Layer::Impl::Impl; + void stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const override; std::unique_ptr<RenderLayer> createRenderLayer() const override; diff --git a/src/mbgl/style/light.cpp b/src/mbgl/style/light.cpp index b54920713c..d2f91c73af 100644 --- a/src/mbgl/style/light.cpp +++ b/src/mbgl/style/light.cpp @@ -2,17 +2,29 @@ #include <mbgl/style/light.hpp> #include <mbgl/style/light_impl.hpp> +#include <mbgl/style/light_observer.hpp> #include <mbgl/style/light_properties.hpp> namespace mbgl { namespace style { +static LightObserver nullObserver; + Light::Light() - : impl(std::make_unique<Impl>()) { + : impl(makeMutable<Impl>()), + observer(&nullObserver) { } Light::~Light() = default; +void Light::setObserver(LightObserver* observer_) { + observer = observer_ ? observer_ : &nullObserver; +} + +Mutable<Light::Impl> Light::mutableImpl() const { + return makeMutable<Impl>(*impl); +} + LightAnchorType Light::getDefaultAnchor() { return LightAnchor::defaultValue(); } @@ -22,13 +34,17 @@ PropertyValue<LightAnchorType> Light::getAnchor() const { } void Light::setAnchor(PropertyValue<LightAnchorType> property) { - impl->properties.template get<LightAnchor>().value = property; - impl->observer->onLightChanged(*this); + auto impl_ = mutableImpl(); + impl_->properties.template get<LightAnchor>().value = property; + impl = std::move(impl_); + observer->onLightChanged(*this); } void Light::setAnchorTransition(const TransitionOptions& transition) { - impl->properties.template get<LightAnchor>().transition = transition; - impl->observer->onLightChanged(*this); + auto impl_ = mutableImpl(); + impl_->properties.template get<LightAnchor>().transition = transition; + impl = std::move(impl_); + observer->onLightChanged(*this); } TransitionOptions Light::getAnchorTransition() const { @@ -44,13 +60,17 @@ PropertyValue<Position> Light::getPosition() const { } void Light::setPosition(PropertyValue<Position> property) { - impl->properties.template get<LightPosition>().value = property; - impl->observer->onLightChanged(*this); + auto impl_ = mutableImpl(); + impl_->properties.template get<LightPosition>().value = property; + impl = std::move(impl_); + observer->onLightChanged(*this); } void Light::setPositionTransition(const TransitionOptions& transition) { - impl->properties.template get<LightPosition>().transition = transition; - impl->observer->onLightChanged(*this); + auto impl_ = mutableImpl(); + impl_->properties.template get<LightPosition>().transition = transition; + impl = std::move(impl_); + observer->onLightChanged(*this); } TransitionOptions Light::getPositionTransition() const { @@ -66,13 +86,17 @@ PropertyValue<Color> Light::getColor() const { } void Light::setColor(PropertyValue<Color> property) { - impl->properties.template get<LightColor>().value = property; - impl->observer->onLightChanged(*this); + auto impl_ = mutableImpl(); + impl_->properties.template get<LightColor>().value = property; + impl = std::move(impl_); + observer->onLightChanged(*this); } void Light::setColorTransition(const TransitionOptions& transition) { - impl->properties.template get<LightColor>().transition = transition; - impl->observer->onLightChanged(*this); + auto impl_ = mutableImpl(); + impl_->properties.template get<LightColor>().transition = transition; + impl = std::move(impl_); + observer->onLightChanged(*this); } TransitionOptions Light::getColorTransition() const { @@ -88,13 +112,17 @@ PropertyValue<float> Light::getIntensity() const { } void Light::setIntensity(PropertyValue<float> property) { - impl->properties.template get<LightIntensity>().value = property; - impl->observer->onLightChanged(*this); + auto impl_ = mutableImpl(); + impl_->properties.template get<LightIntensity>().value = property; + impl = std::move(impl_); + observer->onLightChanged(*this); } void Light::setIntensityTransition(const TransitionOptions& transition) { - impl->properties.template get<LightIntensity>().transition = transition; - impl->observer->onLightChanged(*this); + auto impl_ = mutableImpl(); + impl_->properties.template get<LightIntensity>().transition = transition; + impl = std::move(impl_); + observer->onLightChanged(*this); } TransitionOptions Light::getIntensityTransition() const { diff --git a/src/mbgl/style/light.cpp.ejs b/src/mbgl/style/light.cpp.ejs index c82c65c10c..454bad49d8 100644 --- a/src/mbgl/style/light.cpp.ejs +++ b/src/mbgl/style/light.cpp.ejs @@ -5,17 +5,29 @@ #include <mbgl/style/light.hpp> #include <mbgl/style/light_impl.hpp> +#include <mbgl/style/light_observer.hpp> #include <mbgl/style/light_properties.hpp> namespace mbgl { namespace style { +static LightObserver nullObserver; + Light::Light() - : impl(std::make_unique<Impl>()) { + : impl(makeMutable<Impl>()), + observer(&nullObserver) { } Light::~Light() = default; +void Light::setObserver(LightObserver* observer_) { + observer = observer_ ? observer_ : &nullObserver; +} + +Mutable<Light::Impl> Light::mutableImpl() const { + return makeMutable<Impl>(*impl); +} + <% for (const property of properties) { -%> <%- evaluatedType(property) %> Light::getDefault<%- camelize(property.name) %>() { return Light<%- camelize(property.name) %>::defaultValue(); @@ -26,13 +38,17 @@ Light::~Light() = default; } void Light::set<%- camelize(property.name) %>(<%- propertyValueType(property) %> property) { - impl->properties.template get<Light<%- camelize(property.name) %>>().value = property; - impl->observer->onLightChanged(*this); + auto impl_ = mutableImpl(); + impl_->properties.template get<Light<%- camelize(property.name) %>>().value = property; + impl = std::move(impl_); + observer->onLightChanged(*this); } void Light::set<%- camelize(property.name) %>Transition(const TransitionOptions& transition) { - impl->properties.template get<Light<%- camelize(property.name) %>>().transition = transition; - impl->observer->onLightChanged(*this); + auto impl_ = mutableImpl(); + impl_->properties.template get<Light<%- camelize(property.name) %>>().transition = transition; + impl = std::move(impl_); + observer->onLightChanged(*this); } TransitionOptions Light::get<%- camelize(property.name) %>Transition() const { diff --git a/src/mbgl/style/light_impl.cpp b/src/mbgl/style/light_impl.cpp index e0ab1176ed..619d115f02 100644 --- a/src/mbgl/style/light_impl.cpp +++ b/src/mbgl/style/light_impl.cpp @@ -3,9 +3,5 @@ namespace mbgl { namespace style { -void Light::Impl::setObserver(LightObserver* observer_) { - observer = observer_; -} - } // namespace style } // namespace mbgl diff --git a/src/mbgl/style/light_impl.hpp b/src/mbgl/style/light_impl.hpp index b4fd886742..d607cf00e5 100644 --- a/src/mbgl/style/light_impl.hpp +++ b/src/mbgl/style/light_impl.hpp @@ -1,18 +1,13 @@ #pragma once +#include <mbgl/style/light.hpp> #include <mbgl/style/light_properties.hpp> -#include <mbgl/style/light_observer.hpp> namespace mbgl { namespace style { class Light::Impl { public: - - LightObserver nullObserver; - LightObserver* observer = &nullObserver; - void setObserver(LightObserver*); - IndexedTuple<LightProperties, LightProperties> properties; }; diff --git a/src/mbgl/style/light_observer.hpp b/src/mbgl/style/light_observer.hpp index 751a84850d..45beb64928 100644 --- a/src/mbgl/style/light_observer.hpp +++ b/src/mbgl/style/light_observer.hpp @@ -1,10 +1,10 @@ #pragma once -#include <mbgl/style/light.hpp> - namespace mbgl { namespace style { +class Light; + class LightObserver { public: virtual ~LightObserver() = default; diff --git a/src/mbgl/style/parser.cpp b/src/mbgl/style/parser.cpp index fc3ccf410b..ea96bda502 100644 --- a/src/mbgl/style/parser.cpp +++ b/src/mbgl/style/parser.cpp @@ -236,7 +236,7 @@ void Parser::parseLayer(const std::string& id, const JSValue& value, std::unique return; } - layer = reference->baseImpl->cloneRef(id); + layer = reference->cloneRef(id); conversion::setPaintProperties(*layer, value); } else { conversion::Error error; diff --git a/src/mbgl/style/source.cpp b/src/mbgl/style/source.cpp index cfb268006b..4fcebc8377 100644 --- a/src/mbgl/style/source.cpp +++ b/src/mbgl/style/source.cpp @@ -1,15 +1,24 @@ #include <mbgl/style/source.hpp> #include <mbgl/style/source_impl.hpp> +#include <mbgl/style/source_observer.hpp> +#include <mbgl/util/logging.hpp> namespace mbgl { namespace style { -Source::Source(SourceType type_, std::unique_ptr<Impl> baseImpl_) - : baseImpl(std::move(baseImpl_)), type(type_) { +static SourceObserver nullObserver; + +Source::Source(Immutable<Impl> impl) + : baseImpl(std::move(impl)), + observer(&nullObserver) { } Source::~Source() = default; +SourceType Source::getType() const { + return baseImpl->type; +} + const std::string& Source::getID() const { return baseImpl->id; } @@ -18,5 +27,14 @@ optional<std::string> Source::getAttribution() const { return baseImpl->getAttribution(); } +void Source::setObserver(SourceObserver* observer_) { + observer = observer_ ? observer_ : &nullObserver; +} + +void Source::dumpDebugLogs() const { + Log::Info(Event::General, "Source::id: %s", getID().c_str()); + Log::Info(Event::General, "Source::loaded: %d", loaded); +} + } // namespace style } // namespace mbgl diff --git a/src/mbgl/style/source_impl.cpp b/src/mbgl/style/source_impl.cpp index 1e9405abbb..0683f847cb 100644 --- a/src/mbgl/style/source_impl.cpp +++ b/src/mbgl/style/source_impl.cpp @@ -1,26 +1,11 @@ #include <mbgl/style/source_impl.hpp> -#include <mbgl/style/source_observer.hpp> -#include <mbgl/util/logging.hpp> namespace mbgl { namespace style { -static SourceObserver nullObserver; - -Source::Impl::Impl(SourceType type_, std::string id_, Source& base_) +Source::Impl::Impl(SourceType type_, std::string id_) : type(type_), - id(std::move(id_)), - base(base_), - observer(&nullObserver) { -} - -void Source::Impl::dumpDebugLogs() const { - Log::Info(Event::General, "Source::id: %s", base.getID().c_str()); - Log::Info(Event::General, "Source::loaded: %d", loaded); -} - -void Source::Impl::setObserver(SourceObserver* observer_) { - observer = observer_ ? observer_ : &nullObserver; + id(std::move(id_)) { } } // namespace style diff --git a/src/mbgl/style/source_impl.hpp b/src/mbgl/style/source_impl.hpp index 2514ec5120..3620ec4e50 100644 --- a/src/mbgl/style/source_impl.hpp +++ b/src/mbgl/style/source_impl.hpp @@ -3,35 +3,30 @@ #include <mbgl/style/source.hpp> #include <mbgl/util/noncopyable.hpp> +#include <string> + namespace mbgl { -class FileSource; class RenderSource; namespace style { class SourceObserver; -class Source::Impl : private util::noncopyable { +class Source::Impl : public EnableImmutableFromThis<Source::Impl> { public: - Impl(SourceType, std::string id, Source&); virtual ~Impl() = default; - virtual void loadDescription(FileSource&) = 0; + virtual optional<std::string> getAttribution() const = 0; virtual std::unique_ptr<RenderSource> createRenderSource() const = 0; - virtual optional<std::string> getAttribution() const { return {}; }; - const SourceType type; const std::string id; - bool loaded = false; - Source& base; - - void setObserver(SourceObserver*); - SourceObserver* observer = nullptr; - - void dumpDebugLogs() const; +protected: + Impl(SourceType, std::string); + Impl(const Impl&) = default; + Impl& operator=(const Impl&) = delete; }; } // namespace style diff --git a/src/mbgl/style/sources/geojson_source.cpp b/src/mbgl/style/sources/geojson_source.cpp index 110c1cd63c..d04c8ffce4 100644 --- a/src/mbgl/style/sources/geojson_source.cpp +++ b/src/mbgl/style/sources/geojson_source.cpp @@ -1,25 +1,80 @@ #include <mbgl/style/sources/geojson_source.hpp> #include <mbgl/style/sources/geojson_source_impl.hpp> +#include <mbgl/style/source_observer.hpp> +#include <mbgl/style/conversion/json.hpp> +#include <mbgl/style/conversion/geojson.hpp> +#include <mbgl/storage/file_source.hpp> +#include <mbgl/util/logging.hpp> namespace mbgl { namespace style { GeoJSONSource::GeoJSONSource(const std::string& id, const GeoJSONOptions& options) - : Source(SourceType::GeoJSON, - std::make_unique<GeoJSONSource::Impl>(std::move(id), *this, options)), - impl(static_cast<Impl*>(baseImpl.get())) { + : Source(makeMutable<Impl>(std::move(id), options)) { } -void GeoJSONSource::setURL(const std::string& url) { - impl->setURL(url); +GeoJSONSource::~GeoJSONSource() = default; + +const GeoJSONSource::Impl& GeoJSONSource::impl() const { + return static_cast<const Impl&>(*baseImpl); +} + +void GeoJSONSource::setURL(const std::string& url_) { + url = std::move(url_); + + // Signal that the source description needs a reload + if (loaded || req) { + loaded = false; + req.reset(); + observer->onSourceDescriptionChanged(*this); + } } void GeoJSONSource::setGeoJSON(const mapbox::geojson::geojson& geoJSON) { - impl->setGeoJSON(geoJSON); + req.reset(); + baseImpl = makeMutable<Impl>(impl(), geoJSON); } optional<std::string> GeoJSONSource::getURL() const { - return impl->getURL(); + return url; +} + +void GeoJSONSource::loadDescription(FileSource& fileSource) { + if (!url) { + loaded = true; + return; + } + + if (req) { + return; + } + + req = fileSource.request(Resource::source(*url), [this](Response res) { + if (res.error) { + observer->onSourceError( + *this, std::make_exception_ptr(std::runtime_error(res.error->message))); + } else if (res.notModified) { + return; + } else if (res.noContent) { + observer->onSourceError( + *this, std::make_exception_ptr(std::runtime_error("unexpectedly empty GeoJSON"))); + } else { + conversion::Error error; + optional<GeoJSON> geoJSON = conversion::convertJSON<GeoJSON>(*res.data, error); + if (!geoJSON) { + Log::Error(Event::ParseStyle, "Failed to parse GeoJSON data: %s", + error.message.c_str()); + // Create an empty GeoJSON VT object to make sure we're not infinitely waiting for + // tiles to load. + baseImpl = makeMutable<Impl>(impl(), GeoJSON{ FeatureCollection{} }); + } else { + baseImpl = makeMutable<Impl>(impl(), *geoJSON); + } + + loaded = true; + observer->onSourceLoaded(*this); + } + }); } } // namespace style diff --git a/src/mbgl/style/sources/geojson_source_impl.cpp b/src/mbgl/style/sources/geojson_source_impl.cpp index 1a686ff9bc..17d05aaa5a 100644 --- a/src/mbgl/style/sources/geojson_source_impl.cpp +++ b/src/mbgl/style/sources/geojson_source_impl.cpp @@ -1,12 +1,6 @@ #include <mbgl/style/sources/geojson_source_impl.hpp> -#include <mbgl/style/conversion/json.hpp> -#include <mbgl/style/conversion/geojson.hpp> -#include <mbgl/style/source_observer.hpp> -#include <mbgl/tile/tile_id.hpp> -#include <mbgl/storage/file_source.hpp> #include <mbgl/renderer/sources/render_geojson_source.hpp> #include <mbgl/util/constants.cpp> -#include <mbgl/util/logging.hpp> #include <mapbox/geojsonvt.hpp> #include <supercluster.hpp> @@ -42,33 +36,14 @@ private: mapbox::supercluster::Supercluster impl; }; -GeoJSONSource::Impl::Impl(std::string id_, Source& base_, const GeoJSONOptions options_) - : Source::Impl(SourceType::GeoJSON, std::move(id_), base_), options(options_) { +GeoJSONSource::Impl::Impl(std::string id_, GeoJSONOptions options_) + : Source::Impl(SourceType::GeoJSON, std::move(id_)), + options(std::move(options_)) { } -GeoJSONSource::Impl::~Impl() = default; - -void GeoJSONSource::Impl::setURL(std::string url_) { - url = std::move(url_); - - // Signal that the source description needs a reload - if (loaded || req) { - loaded = false; - req.reset(); - observer->onSourceDescriptionChanged(base); - } -} - -optional<std::string> GeoJSONSource::Impl::getURL() const { - return url; -} - -void GeoJSONSource::Impl::setGeoJSON(const GeoJSON& geoJSON) { - req.reset(); - _setGeoJSON(geoJSON); -} - -void GeoJSONSource::Impl::_setGeoJSON(const GeoJSON& geoJSON) { +GeoJSONSource::Impl::Impl(const Impl& other, const GeoJSON& geoJSON) + : Source::Impl(other), + options(other.options) { double scale = util::EXTENT / util::tileSize; if (options.cluster @@ -90,47 +65,7 @@ void GeoJSONSource::Impl::_setGeoJSON(const GeoJSON& geoJSON) { } } -void GeoJSONSource::Impl::loadDescription(FileSource& fileSource) { - if (!url) { - loaded = true; - return; - } - - if (req) { - return; - } - - req = fileSource.request(Resource::source(*url), [this](Response res) { - if (res.error) { - observer->onSourceError( - base, std::make_exception_ptr(std::runtime_error(res.error->message))); - } else if (res.notModified) { - return; - } else if (res.noContent) { - observer->onSourceError( - base, std::make_exception_ptr(std::runtime_error("unexpectedly empty GeoJSON"))); - } else { - conversion::Error error; - optional<GeoJSON> geoJSON = conversion::convertJSON<GeoJSON>(*res.data, error); - if (!geoJSON) { - Log::Error(Event::ParseStyle, "Failed to parse GeoJSON data: %s", - error.message.c_str()); - // Create an empty GeoJSON VT object to make sure we're not infinitely waiting for - // tiles to load. - _setGeoJSON(GeoJSON{ FeatureCollection{} }); - } else { - _setGeoJSON(*geoJSON); - } - - loaded = true; - observer->onSourceLoaded(base); - } - }); -} - -std::unique_ptr<RenderSource> GeoJSONSource::Impl::createRenderSource() const { - return std::make_unique<RenderGeoJSONSource>(*this); -} +GeoJSONSource::Impl::~Impl() = default; Range<uint8_t> GeoJSONSource::Impl::getZoomRange() const { return { 0, options.maxzoom }; @@ -140,5 +75,13 @@ GeoJSONData* GeoJSONSource::Impl::getData() const { return data.get(); } +optional<std::string> GeoJSONSource::Impl::getAttribution() const { + return {}; +} + +std::unique_ptr<RenderSource> GeoJSONSource::Impl::createRenderSource() const { + return std::make_unique<RenderGeoJSONSource>(staticImmutableCast<GeoJSONSource::Impl>(immutableFromThis())); +} + } // namespace style } // namespace mbgl diff --git a/src/mbgl/style/sources/geojson_source_impl.hpp b/src/mbgl/style/sources/geojson_source_impl.hpp index e8b881d05e..65580700e7 100644 --- a/src/mbgl/style/sources/geojson_source_impl.hpp +++ b/src/mbgl/style/sources/geojson_source_impl.hpp @@ -2,7 +2,7 @@ #include <mbgl/style/source_impl.hpp> #include <mbgl/style/sources/geojson_source.hpp> -#include <mbgl/util/variant.hpp> +#include <mbgl/util/range.hpp> namespace mbgl { @@ -18,25 +18,18 @@ public: class GeoJSONSource::Impl : public Source::Impl { public: - Impl(std::string id, Source&, const GeoJSONOptions); + Impl(std::string id, GeoJSONOptions); + Impl(const GeoJSONSource::Impl&, const GeoJSON&); ~Impl() final; - void setURL(std::string); - optional<std::string> getURL() const; Range<uint8_t> getZoomRange() const; - - void setGeoJSON(const GeoJSON&); GeoJSONData* getData() const; - void loadDescription(FileSource&) final; + optional<std::string> getAttribution() const final; std::unique_ptr<RenderSource> createRenderSource() const final; private: - void _setGeoJSON(const GeoJSON&); - GeoJSONOptions options; - optional<std::string> url; - std::unique_ptr<AsyncRequest> req; std::unique_ptr<GeoJSONData> data; }; diff --git a/src/mbgl/style/sources/raster_source.cpp b/src/mbgl/style/sources/raster_source.cpp index 94fdbcef12..0a0412a4ed 100644 --- a/src/mbgl/style/sources/raster_source.cpp +++ b/src/mbgl/style/sources/raster_source.cpp @@ -1,21 +1,81 @@ #include <mbgl/style/sources/raster_source.hpp> #include <mbgl/style/sources/raster_source_impl.hpp> +#include <mbgl/style/source_observer.hpp> +#include <mbgl/style/conversion/json.hpp> +#include <mbgl/style/conversion/tileset.hpp> +#include <mbgl/storage/file_source.hpp> +#include <mbgl/util/mapbox.hpp> namespace mbgl { namespace style { -RasterSource::RasterSource(std::string id, variant<std::string, Tileset> urlOrTileset, uint16_t tileSize) - : Source(SourceType::Raster, std::make_unique<RasterSource::Impl>(std::move(id), *this, std::move(urlOrTileset), tileSize)), - impl(static_cast<Impl*>(baseImpl.get())) { +RasterSource::RasterSource(std::string id, variant<std::string, Tileset> urlOrTileset_, uint16_t tileSize) + : Source(makeMutable<Impl>(std::move(id), tileSize)), + urlOrTileset(std::move(urlOrTileset_)) { +} + +RasterSource::~RasterSource() = default; + +const RasterSource::Impl& RasterSource::impl() const { + return static_cast<const Impl&>(*baseImpl); +} + +const variant<std::string, Tileset>& RasterSource::getURLOrTileset() const { + return urlOrTileset; } optional<std::string> RasterSource::getURL() const { - auto urlOrTileset = impl->getURLOrTileset(); - if (urlOrTileset.is<std::string>()) { - return urlOrTileset.get<std::string>(); - } else { + if (urlOrTileset.is<Tileset>()) { return {}; } + + return urlOrTileset.get<std::string>(); +} + +uint16_t RasterSource::getTileSize() const { + return impl().getTileSize(); +} + +void RasterSource::loadDescription(FileSource& fileSource) { + if (urlOrTileset.is<Tileset>()) { + baseImpl = makeMutable<Impl>(impl(), urlOrTileset.get<Tileset>()); + loaded = true; + return; + } + + if (req) { + return; + } + + const std::string& url = urlOrTileset.get<std::string>(); + req = fileSource.request(Resource::source(url), [this, url](Response res) { + if (res.error) { + observer->onSourceError(*this, std::make_exception_ptr(std::runtime_error(res.error->message))); + } else if (res.notModified) { + return; + } else if (res.noContent) { + observer->onSourceError(*this, std::make_exception_ptr(std::runtime_error("unexpectedly empty TileJSON"))); + } else { + conversion::Error error; + optional<Tileset> tileset = conversion::convertJSON<Tileset>(*res.data, error); + if (!tileset) { + observer->onSourceError(*this, std::make_exception_ptr(std::runtime_error(error.message))); + return; + } + + util::mapbox::canonicalizeTileset(*tileset, url, getType(), getTileSize()); + bool changed = impl().getTileset() != *tileset; + + baseImpl = makeMutable<Impl>(impl(), *tileset); + loaded = true; + + observer->onSourceLoaded(*this); + + if (changed) { + observer->onSourceChanged(*this); + } + } + }); } } // namespace style diff --git a/src/mbgl/style/sources/raster_source_impl.cpp b/src/mbgl/style/sources/raster_source_impl.cpp index b85d221f2e..1d684524c7 100644 --- a/src/mbgl/style/sources/raster_source_impl.cpp +++ b/src/mbgl/style/sources/raster_source_impl.cpp @@ -4,14 +4,34 @@ namespace mbgl { namespace style { -RasterSource::Impl::Impl(std::string id_, Source& base_, - variant<std::string, Tileset> urlOrTileset_, - uint16_t tileSize_) - : TileSourceImpl(SourceType::Raster, std::move(id_), base_, std::move(urlOrTileset_), tileSize_) { +RasterSource::Impl::Impl(std::string id_, uint16_t tileSize_) + : Source::Impl(SourceType::Raster, std::move(id_)), + tileSize(tileSize_) { +} + +RasterSource::Impl::Impl(const Impl& other, Tileset tileset_) + : Source::Impl(other), + tileSize(other.tileSize), + tileset(std::move(tileset_)) { +} + +uint16_t RasterSource::Impl::getTileSize() const { + return tileSize; +} + +optional<Tileset> RasterSource::Impl::getTileset() const { + return tileset; +} + +optional<std::string> RasterSource::Impl::getAttribution() const { + if (!tileset) { + return {}; + } + return tileset->attribution; } std::unique_ptr<RenderSource> RasterSource::Impl::createRenderSource() const { - return std::make_unique<RenderRasterSource>(*this); + return std::make_unique<RenderRasterSource>(staticImmutableCast<RasterSource::Impl>(immutableFromThis())); } } // namespace style diff --git a/src/mbgl/style/sources/raster_source_impl.hpp b/src/mbgl/style/sources/raster_source_impl.hpp index 4bc76560f8..0a58953ab7 100644 --- a/src/mbgl/style/sources/raster_source_impl.hpp +++ b/src/mbgl/style/sources/raster_source_impl.hpp @@ -1,16 +1,25 @@ #pragma once #include <mbgl/style/sources/raster_source.hpp> -#include <mbgl/style/tile_source_impl.hpp> +#include <mbgl/style/source_impl.hpp> namespace mbgl { namespace style { -class RasterSource::Impl : public TileSourceImpl { +class RasterSource::Impl : public Source::Impl { public: - Impl(std::string id, Source&, variant<std::string, Tileset>, uint16_t tileSize); + Impl(std::string id, uint16_t tileSize); + Impl(const Impl&, Tileset); + optional<Tileset> getTileset() const; + uint16_t getTileSize() const; + + optional<std::string> getAttribution() const final; std::unique_ptr<RenderSource> createRenderSource() const final; + +private: + uint16_t tileSize; + optional<Tileset> tileset; }; } // namespace style diff --git a/src/mbgl/style/sources/vector_source.cpp b/src/mbgl/style/sources/vector_source.cpp index 4bcd3b8985..ccdd453c75 100644 --- a/src/mbgl/style/sources/vector_source.cpp +++ b/src/mbgl/style/sources/vector_source.cpp @@ -1,21 +1,78 @@ #include <mbgl/style/sources/vector_source.hpp> #include <mbgl/style/sources/vector_source_impl.hpp> +#include <mbgl/style/source_observer.hpp> +#include <mbgl/style/conversion/json.hpp> +#include <mbgl/style/conversion/tileset.hpp> +#include <mbgl/storage/file_source.hpp> +#include <mbgl/util/mapbox.hpp> +#include <mbgl/util/constants.hpp> namespace mbgl { namespace style { -VectorSource::VectorSource(std::string id, variant<std::string, Tileset> urlOrTileset) - : Source(SourceType::Vector, std::make_unique<VectorSource::Impl>(std::move(id), *this, std::move(urlOrTileset))), - impl(static_cast<Impl*>(baseImpl.get())) { +VectorSource::VectorSource(std::string id, variant<std::string, Tileset> urlOrTileset_) + : Source(makeMutable<Impl>(std::move(id))), + urlOrTileset(std::move(urlOrTileset_)) { +} + +VectorSource::~VectorSource() = default; + +const VectorSource::Impl& VectorSource::impl() const { + return static_cast<const Impl&>(*baseImpl); +} + +const variant<std::string, Tileset>& VectorSource::getURLOrTileset() const { + return urlOrTileset; } optional<std::string> VectorSource::getURL() const { - auto urlOrTileset = impl->getURLOrTileset(); - if (urlOrTileset.is<std::string>()) { - return urlOrTileset.get<std::string>(); - } else { + if (urlOrTileset.is<Tileset>()) { return {}; } + + return urlOrTileset.get<std::string>(); +} + +void VectorSource::loadDescription(FileSource& fileSource) { + if (urlOrTileset.is<Tileset>()) { + baseImpl = makeMutable<Impl>(impl(), urlOrTileset.get<Tileset>()); + loaded = true; + return; + } + + if (req) { + return; + } + + const std::string& url = urlOrTileset.get<std::string>(); + req = fileSource.request(Resource::source(url), [this, url](Response res) { + if (res.error) { + observer->onSourceError(*this, std::make_exception_ptr(std::runtime_error(res.error->message))); + } else if (res.notModified) { + return; + } else if (res.noContent) { + observer->onSourceError(*this, std::make_exception_ptr(std::runtime_error("unexpectedly empty TileJSON"))); + } else { + conversion::Error error; + optional<Tileset> tileset = conversion::convertJSON<Tileset>(*res.data, error); + if (!tileset) { + observer->onSourceError(*this, std::make_exception_ptr(std::runtime_error(error.message))); + return; + } + + util::mapbox::canonicalizeTileset(*tileset, url, getType(), util::tileSize); + bool changed = impl().getTileset() != *tileset; + + baseImpl = makeMutable<Impl>(impl(), *tileset); + loaded = true; + + observer->onSourceLoaded(*this); + + if (changed) { + observer->onSourceChanged(*this); + } + } + }); } } // namespace style diff --git a/src/mbgl/style/sources/vector_source_impl.cpp b/src/mbgl/style/sources/vector_source_impl.cpp index 158abf8575..aab62acf3f 100644 --- a/src/mbgl/style/sources/vector_source_impl.cpp +++ b/src/mbgl/style/sources/vector_source_impl.cpp @@ -1,16 +1,31 @@ #include <mbgl/style/sources/vector_source_impl.hpp> #include <mbgl/renderer/sources/render_vector_source.hpp> -#include <mbgl/util/constants.hpp> namespace mbgl { namespace style { -VectorSource::Impl::Impl(std::string id_, Source& base_, variant<std::string, Tileset> urlOrTileset_) - : TileSourceImpl(SourceType::Vector, std::move(id_), base_, std::move(urlOrTileset_), util::tileSize) { +VectorSource::Impl::Impl(std::string id_) + : Source::Impl(SourceType::Vector, std::move(id_)) { +} + +VectorSource::Impl::Impl(const Impl& other, Tileset tileset_) + : Source::Impl(other), + tileset(std::move(tileset_)) { +} + +optional<Tileset> VectorSource::Impl::getTileset() const { + return tileset; +} + +optional<std::string> VectorSource::Impl::getAttribution() const { + if (!tileset) { + return {}; + } + return tileset->attribution; } std::unique_ptr<RenderSource> VectorSource::Impl::createRenderSource() const { - return std::make_unique<RenderVectorSource>(*this); + return std::make_unique<RenderVectorSource>(staticImmutableCast<VectorSource::Impl>(immutableFromThis())); } } // namespace style diff --git a/src/mbgl/style/sources/vector_source_impl.hpp b/src/mbgl/style/sources/vector_source_impl.hpp index 844739948c..602d0e5bbb 100644 --- a/src/mbgl/style/sources/vector_source_impl.hpp +++ b/src/mbgl/style/sources/vector_source_impl.hpp @@ -1,16 +1,23 @@ #pragma once #include <mbgl/style/sources/vector_source.hpp> -#include <mbgl/style/tile_source_impl.hpp> +#include <mbgl/style/source_impl.hpp> namespace mbgl { namespace style { -class VectorSource::Impl : public TileSourceImpl { +class VectorSource::Impl : public Source::Impl { public: - Impl(std::string id, Source&, variant<std::string, Tileset>); + Impl(std::string id); + Impl(const Impl&, Tileset); + optional<Tileset> getTileset() const; + + optional<std::string> getAttribution() const final; std::unique_ptr<RenderSource> createRenderSource() const final; + +private: + optional<Tileset> tileset; }; } // namespace style diff --git a/src/mbgl/style/style.cpp b/src/mbgl/style/style.cpp index 9cd8cda1ec..2042bc1225 100644 --- a/src/mbgl/style/style.cpp +++ b/src/mbgl/style/style.cpp @@ -34,6 +34,7 @@ #include <mbgl/renderer/render_line_layer.hpp> #include <mbgl/renderer/render_raster_layer.hpp> #include <mbgl/renderer/render_symbol_layer.hpp> +#include <mbgl/renderer/style_diff.hpp> #include <mbgl/tile/tile.hpp> #include <mbgl/util/constants.hpp> #include <mbgl/util/exception.hpp> @@ -74,27 +75,19 @@ Style::Style(Scheduler& scheduler_, FileSource& fileSource_, float pixelRatio) spriteAtlas(std::make_unique<SpriteAtlas>(Size{ 1024, 1024 }, pixelRatio)), lineAtlas(std::make_unique<LineAtlas>(Size{ 256, 512 })), light(std::make_unique<Light>()), - renderLight(std::make_unique<RenderLight>(light->impl)), + renderLight(light->impl), observer(&nullObserver) { glyphAtlas->setObserver(this); spriteAtlas->setObserver(this); - light->impl->setObserver(this); + light->setObserver(this); } Style::~Style() { - for (const auto& source : sources) { - source->baseImpl->setObserver(nullptr); - } - for (const auto& layer : layers) { if (auto* customLayer = layer->as<CustomLayer>()) { - customLayer->impl->deinitialize(); + customLayer->impl().deinitialize(); } } - - glyphAtlas->setObserver(nullptr); - spriteAtlas->setObserver(nullptr); - light->impl->setObserver(nullptr); } bool Style::addClass(const std::string& className) { @@ -136,7 +129,6 @@ void Style::setJSON(const std::string& json) { sources.clear(); renderSources.clear(); layers.clear(); - renderLayers.clear(); classes.clear(); transitionOptions = {}; updateBatch = {}; @@ -186,12 +178,8 @@ void Style::addSource(std::unique_ptr<Source> source) { throw std::runtime_error(msg.c_str()); } - source->baseImpl->setObserver(this); - source->baseImpl->loadDescription(fileSource); - - std::unique_ptr<RenderSource> renderSource = source->baseImpl->createRenderSource(); - renderSource->setObserver(this); - renderSources.emplace_back(std::move(renderSource)); + source->setObserver(this); + source->loadDescription(fileSource); sources.emplace_back(std::move(source)); } @@ -205,12 +193,8 @@ std::unique_ptr<Source> Style::removeSource(const std::string& id) { return nullptr; } - util::erase_if(renderSources, [&](const auto& source) { - return source->baseImpl.id == id; - }); - auto source = std::move(*it); - source->baseImpl->setObserver(nullptr); + source->setObserver(nullptr); sources.erase(it); updateBatch.sourceIDs.erase(id); @@ -259,15 +243,13 @@ Layer* Style::addLayer(std::unique_ptr<Layer> layer, optional<std::string> befor } if (auto* customLayer = layer->as<CustomLayer>()) { - customLayer->impl->initialize(); + customLayer->impl().initialize(); } - layer->baseImpl->setObserver(this); + layer->setObserver(this); layer->accept(QueueSourceReloadVisitor { updateBatch }); - auto added = layers.emplace(before ? findLayer(*before) : layers.end(), std::move(layer))->get(); - renderLayers.emplace(before ? findRenderLayer(*before) : renderLayers.end(), added->baseImpl->createRenderLayer()); - return std::move(added); + return layers.emplace(before ? findLayer(*before) : layers.end(), std::move(layer))->get(); } std::unique_ptr<Layer> Style::removeLayer(const std::string& id) { @@ -281,20 +263,19 @@ std::unique_ptr<Layer> Style::removeLayer(const std::string& id) { auto layer = std::move(*it); if (auto* customLayer = layer->as<CustomLayer>()) { - customLayer->impl->deinitialize(); + customLayer->impl().deinitialize(); } - layer->baseImpl->setObserver(nullptr); + layer->setObserver(nullptr); layers.erase(it); - removeRenderLayer(id); return layer; } std::vector<const RenderLayer*> Style::getRenderLayers() const { std::vector<const RenderLayer*> result; result.reserve(renderLayers.size()); - for (const auto& layer : renderLayers) { - result.push_back(layer.get()); + for (const auto& entry : renderLayers) { + result.push_back(entry.second.get()); } return result; } @@ -302,41 +283,20 @@ std::vector<const RenderLayer*> Style::getRenderLayers() const { std::vector<RenderLayer*> Style::getRenderLayers() { std::vector<RenderLayer*> result; result.reserve(renderLayers.size()); - for (auto& layer : renderLayers) { - result.push_back(layer.get()); + for (auto& entry : renderLayers) { + result.push_back(entry.second.get()); } return result; } -std::vector<std::unique_ptr<RenderLayer>>::const_iterator Style::findRenderLayer(const std::string& id) const { - return std::find_if(renderLayers.begin(), renderLayers.end(), [&](const auto& layer) { - return layer->baseImpl.id == id; - }); -} - RenderLayer* Style::getRenderLayer(const std::string& id) const { - auto it = findRenderLayer(id); - return it != renderLayers.end() ? it->get() : nullptr; -} - -void Style::removeRenderLayer(const std::string& id) { - auto it = std::find_if(renderLayers.begin(), renderLayers.end(), [&](const auto& layer) { - return layer->baseImpl.id == id; - }); - - if (it != renderLayers.end()) { - renderLayers.erase(it); - } + auto it = renderLayers.find(id); + return it != renderLayers.end() ? it->second.get() : nullptr; } void Style::setLight(std::unique_ptr<Light> light_) { light = std::move(light_); - light->impl->setObserver(this); - - // Copy renderlight to preserve the initialised - // transitioning light properties - renderLight = renderLight->copy(light->impl); - + light->setObserver(this); onLightChanged(*light); } @@ -344,8 +304,8 @@ Light* Style::getLight() const { return light.get(); } -RenderLight* Style::getRenderLight() const { - return renderLight.get(); +const RenderLight& Style::getRenderLight() const { + return renderLight; } std::string Style::getName() const { @@ -369,7 +329,8 @@ double Style::getDefaultPitch() const { } void Style::update(const UpdateParameters& parameters) { - bool zoomChanged = zoomHistory.update(parameters.transformState.getZoom(), parameters.timePoint); + const bool zoomChanged = zoomHistory.update(parameters.transformState.getZoom(), parameters.timePoint); + const bool classesChanged = parameters.updateFlags & Update::Classes; std::vector<ClassID> classIDs; for (const auto& className : classes) { @@ -398,48 +359,111 @@ void Style::update(const UpdateParameters& parameters) { parameters.annotationManager, *this); - const bool cascade = parameters.updateFlags & Update::Classes; - const bool evaluate = cascade || zoomChanged || parameters.updateFlags & Update::RecalculateStyle; + // Update light. + const bool lightChanged = renderLight.impl != light->impl; - if (cascade) { - renderLight->transition(cascadeParameters); + if (lightChanged) { + renderLight.impl = light->impl; + renderLight.transition(cascadeParameters); } - if (evaluate || renderLight->hasTransition()) { - renderLight->evaluate(evaluationParameters); + if (lightChanged || zoomChanged || renderLight.hasTransition()) { + renderLight.evaluate(evaluationParameters); } - for (const auto& renderSource : renderSources) { - renderSource->enabled = false; + + std::vector<Immutable<Source::Impl>> newSourceImpls; + newSourceImpls.reserve(sources.size()); + for (const auto& source : sources) { + newSourceImpls.push_back(source->baseImpl); } - for (const auto& layer : renderLayers) { - if (cascade) { - layer->cascade(cascadeParameters); + const SourceDifference sourceDiff = diffSources(sourceImpls, newSourceImpls); + sourceImpls = std::move(newSourceImpls); + + // Remove render layers for removed sources. + for (const auto& entry : sourceDiff.removed) { + renderLayers.erase(entry.first); + } + + // Create render sources for newly added sources. + for (const auto& entry : sourceDiff.added) { + std::unique_ptr<RenderSource> renderSource = entry.second->createRenderSource(); + renderSource->setObserver(this); + renderSources.emplace(entry.first, std::move(renderSource)); + } + + // Update render sources for changed sources. + for (const auto& entry : sourceDiff.changed) { + renderSources.at(entry.first)->setImpl(entry.second); + } + + + std::vector<Immutable<Layer::Impl>> newLayerImpls; + newLayerImpls.reserve(layers.size()); + for (const auto& layer : layers) { + newLayerImpls.push_back(layer->baseImpl); + } + + const LayerDifference layerDiff = diffLayers(layerImpls, newLayerImpls); + layerImpls = std::move(newLayerImpls); + + // Remove render layers for removed layers. + for (const auto& entry : layerDiff.removed) { + renderLayers.erase(entry.first); + } + + // Create render layers for newly added layers. + for (const auto& entry : layerDiff.added) { + renderLayers.emplace(entry.first, entry.second->createRenderLayer()); + } + + // Update render layers for changed layers. + for (const auto& entry : layerDiff.changed) { + renderLayers.at(entry.first)->setImpl(entry.second); + } + + // Update layers for class and zoom changes. + for (const auto& entry : renderLayers) { + RenderLayer& layer = *entry.second; + const bool layerAdded = layerDiff.added.count(entry.first); + const bool layerChanged = layerDiff.changed.count(entry.first); + + if (classesChanged || layerAdded || layerChanged) { + layer.cascade(cascadeParameters); } - if (evaluate || layer->hasTransition()) { - layer->evaluate(evaluationParameters); + if (classesChanged || layerAdded || layerChanged || zoomChanged || layer.hasTransition()) { + layer.evaluate(evaluationParameters); } + } + + + // Update tiles for each source. + for (const auto& entry : renderSources) { + entry.second->enabled = false; + } - if (layer->needsRendering(zoomHistory.lastZoom)) { - if (RenderSource* renderSource = getRenderSource(layer->baseImpl.source)) { - renderSource->enabled = true; + for (const auto& entry : renderLayers) { + RenderLayer& layer = *entry.second; + if (layer.needsRendering(zoomHistory.lastZoom)) { + if (RenderSource* source = getRenderSource(layer.baseImpl->source)) { + source->enabled = true; } } } - for (const auto& renderSource : renderSources) { - bool updated = updateBatch.sourceIDs.count(renderSource->baseImpl.id); - if (renderSource->enabled) { + for (const auto& entry : renderSources) { + bool updated = updateBatch.sourceIDs.count(entry.first); + if (entry.second->enabled) { if (updated) { - renderSource->reloadTiles(); + entry.second->reloadTiles(); } - renderSource->updateTiles(tileParameters); + entry.second->updateTiles(tileParameters); } else if (updated) { - renderSource->invalidateTiles(); + entry.second->invalidateTiles(); } else { - renderSource->removeTiles(); + entry.second->removeTiles(); } } @@ -473,20 +497,17 @@ Source* Style::getSource(const std::string& id) const { } RenderSource* Style::getRenderSource(const std::string& id) const { - const auto it = std::find_if(renderSources.begin(), renderSources.end(), [&](const auto& source) { - return source->baseImpl.id == id; - }); - - return it != renderSources.end() ? it->get() : nullptr; + auto it = renderSources.find(id); + return it != renderSources.end() ? it->second.get() : nullptr; } bool Style::hasTransitions() const { - if (renderLight->hasTransition()) { + if (renderLight.hasTransition()) { return true; } - for (const auto& layer : renderLayers) { - if (layer->hasTransition()) { + for (const auto& entry : renderLayers) { + if (entry.second->hasTransition()) { return true; } } @@ -500,13 +521,13 @@ bool Style::isLoaded() const { } for (const auto& source: sources) { - if (!source->baseImpl->loaded) { + if (!source->loaded) { return false; } } - for (const auto& renderSource: renderSources) { - if (!renderSource->isLoaded()) { + for (const auto& entry: renderSources) { + if (!entry.second->isLoaded()) { return false; } } @@ -521,13 +542,16 @@ bool Style::isLoaded() const { RenderData Style::getRenderData(MapDebugOptions debugOptions, float angle) const { RenderData result; - for (const auto& renderSource: renderSources) { - if (renderSource->enabled) { - result.sources.insert(renderSource.get()); + for (const auto& entry : renderSources) { + if (entry.second->enabled) { + result.sources.insert(entry.second.get()); } } - for (const auto& layer : renderLayers) { + for (const auto& layerImpl : layerImpls) { + const RenderLayer* layer = getRenderLayer(layerImpl->id); + assert(layer); + if (!layer->needsRendering(zoomHistory.lastZoom)) { continue; } @@ -539,7 +563,7 @@ RenderData Style::getRenderData(MapDebugOptions debugOptions, float angle) const continue; } const BackgroundPaintProperties::Evaluated& paint = background->evaluated; - if (layer.get() == renderLayers[0].get() && paint.get<BackgroundPattern>().from.empty()) { + if (layerImpl.get() == layerImpls[0].get() && paint.get<BackgroundPattern>().from.empty()) { // This is a solid background. We can use glClear(). result.backgroundColor = paint.get<BackgroundColor>() * paint.get<BackgroundOpacity>(); } else { @@ -554,9 +578,9 @@ RenderData Style::getRenderData(MapDebugOptions debugOptions, float angle) const continue; } - RenderSource* source = getRenderSource(layer->baseImpl.source); + RenderSource* source = getRenderSource(layer->baseImpl->source); if (!source) { - Log::Warning(Event::Render, "can't find source for layer '%s'", layer->baseImpl.id.c_str()); + Log::Warning(Event::Render, "can't find source for layer '%s'", layer->baseImpl->id.c_str()); continue; } @@ -609,7 +633,7 @@ RenderData Style::getRenderData(MapDebugOptions debugOptions, float angle) const } } - auto bucket = tile.tile.getBucket(*layer); + auto bucket = tile.tile.getBucket(*layer->baseImpl); if (bucket) { sortedTilesForInsertion.emplace_back(tile); tile.used = true; @@ -641,8 +665,8 @@ std::vector<Feature> Style::queryRenderedFeatures(const ScreenLineString& geomet } } } else { - for (const auto& renderSource : renderSources) { - auto sourceResults = renderSource->queryRenderedFeatures(geometry, transformState, options); + for (const auto& entry : renderSources) { + auto sourceResults = entry.second->queryRenderedFeatures(geometry, transformState, options); std::move(sourceResults.begin(), sourceResults.end(), std::inserter(resultsByLayer, resultsByLayer.begin())); } } @@ -654,11 +678,12 @@ std::vector<Feature> Style::queryRenderedFeatures(const ScreenLineString& geomet } // Combine all results based on the style layer order. - for (const auto& layer : renderLayers) { + for (const auto& layerImpl : layerImpls) { + const RenderLayer* layer = getRenderLayer(layerImpl->id); if (!layer->needsRendering(zoomHistory.lastZoom)) { continue; } - auto it = resultsByLayer.find(layer->baseImpl.id); + auto it = resultsByLayer.find(layer->baseImpl->id); if (it != resultsByLayer.end()) { std::move(it->second.begin(), it->second.end(), std::back_inserter(result)); } @@ -668,14 +693,14 @@ std::vector<Feature> Style::queryRenderedFeatures(const ScreenLineString& geomet } void Style::setSourceTileCacheSize(size_t size) { - for (const auto& renderSource : renderSources) { - renderSource->setCacheSize(size); + for (const auto& entry : renderSources) { + entry.second->setCacheSize(size); } } void Style::onLowMemory() { - for (const auto& renderSource : renderSources) { - renderSource->onLowMemory(); + for (const auto& entry : renderSources) { + entry.second->onLowMemory(); } } @@ -714,8 +739,8 @@ void Style::onSourceError(Source& source, std::exception_ptr error) { void Style::onSourceDescriptionChanged(Source& source) { observer->onSourceDescriptionChanged(source); - if (!source.baseImpl->loaded) { - source.baseImpl->loadDescription(fileSource); + if (!source.loaded) { + source.loadDescription(fileSource); } } @@ -726,7 +751,7 @@ void Style::onTileChanged(RenderSource&, const OverscaledTileID&) { void Style::onTileError(RenderSource& source, const OverscaledTileID& tileID, std::exception_ptr error) { lastError = error; Log::Error(Event::Style, "Failed to load tile %s for source %s: %s", - util::toString(tileID).c_str(), source.baseImpl.id.c_str(), util::toString(error).c_str()); + util::toString(tileID).c_str(), source.baseImpl->id.c_str(), util::toString(error).c_str()); observer->onResourceError(error); } @@ -749,38 +774,34 @@ void Style::onLayerFilterChanged(Layer& layer) { void Style::onLayerVisibilityChanged(Layer& layer) { layer.accept(QueueSourceReloadVisitor { updateBatch }); - observer->onUpdate(Update::RecalculateStyle); + observer->onUpdate(Update::Repaint); } void Style::onLayerPaintPropertyChanged(Layer&) { - observer->onUpdate(Update::RecalculateStyle | Update::Classes); + observer->onUpdate(Update::Repaint); } void Style::onLayerDataDrivenPaintPropertyChanged(Layer& layer) { layer.accept(QueueSourceReloadVisitor { updateBatch }); - observer->onUpdate(Update::RecalculateStyle | Update::Classes); + observer->onUpdate(Update::Repaint); } -void Style::onLayerLayoutPropertyChanged(Layer& layer, const char * property) { +void Style::onLayerLayoutPropertyChanged(Layer& layer, const char *) { layer.accept(QueueSourceReloadVisitor { updateBatch }); - - // Recalculate the style for certain properties - observer->onUpdate((strcmp(property, "icon-size") == 0 || strcmp(property, "text-size") == 0) - ? Update::RecalculateStyle - : Update::Repaint); + observer->onUpdate(Update::Repaint); } void Style::onLightChanged(const Light&) { - observer->onUpdate(Update::Classes | Update::RecalculateStyle); + observer->onUpdate(Update::Repaint); } void Style::dumpDebugLogs() const { for (const auto& source : sources) { - source->baseImpl->dumpDebugLogs(); + source->dumpDebugLogs(); } - for (const auto& renderSource : renderSources) { - renderSource->dumpDebugLogs(); + for (const auto& entry : renderSources) { + entry.second->dumpDebugLogs(); } spriteAtlas->dumpDebugLogs(); diff --git a/src/mbgl/style/style.hpp b/src/mbgl/style/style.hpp index 7d235dc665..04d3a11d55 100644 --- a/src/mbgl/style/style.hpp +++ b/src/mbgl/style/style.hpp @@ -3,10 +3,11 @@ #include <mbgl/style/transition_options.hpp> #include <mbgl/style/observer.hpp> #include <mbgl/style/source_observer.hpp> -#include <mbgl/renderer/render_source_observer.hpp> #include <mbgl/style/layer_observer.hpp> #include <mbgl/style/light_observer.hpp> #include <mbgl/style/update_batch.hpp> +#include <mbgl/renderer/render_source.hpp> +#include <mbgl/renderer/render_source_observer.hpp> #include <mbgl/renderer/render_layer.hpp> #include <mbgl/renderer/render_light.hpp> #include <mbgl/text/glyph_atlas_observer.hpp> @@ -35,8 +36,6 @@ class RenderData; class TransformState; class RenderedQueryOptions; class Scheduler; -class RenderLayer; -class RenderSource; class UpdateParameters; namespace style { @@ -105,7 +104,7 @@ public: void setLight(std::unique_ptr<Light>); Light* getLight() const; - RenderLight* getRenderLight() const; + const RenderLight& getRenderLight() const; RenderData getRenderData(MapDebugOptions, float angle) const; @@ -128,15 +127,10 @@ public: private: std::vector<std::unique_ptr<Source>> sources; - std::vector<std::unique_ptr<RenderSource>> renderSources; - std::vector<std::unique_ptr<Layer>> layers; - std::vector<std::unique_ptr<RenderLayer>> renderLayers; std::vector<std::string> classes; TransitionOptions transitionOptions; - std::unique_ptr<Light> light; - std::unique_ptr<RenderLight> renderLight; // Defaults std::string name; @@ -145,8 +139,14 @@ private: double defaultBearing = 0; double defaultPitch = 0; + std::vector<Immutable<Source::Impl>> sourceImpls; + std::vector<Immutable<Layer::Impl>> layerImpls; + + std::unordered_map<std::string, std::unique_ptr<RenderSource>> renderSources; + std::unordered_map<std::string, std::unique_ptr<RenderLayer>> renderLayers; + RenderLight renderLight; + std::vector<std::unique_ptr<Layer>>::const_iterator findLayer(const std::string& layerID) const; - std::vector<std::unique_ptr<RenderLayer>>::const_iterator findRenderLayer(const std::string&) const; // GlyphStoreObserver implementation. void onGlyphsLoaded(const FontStack&, const GlyphRange&) override; @@ -182,8 +182,6 @@ private: UpdateBatch updateBatch; ZoomHistory zoomHistory; - void removeRenderLayer(const std::string& layerID); - public: bool loaded = false; }; diff --git a/src/mbgl/style/tile_source_impl.cpp b/src/mbgl/style/tile_source_impl.cpp deleted file mode 100644 index 4d47221da9..0000000000 --- a/src/mbgl/style/tile_source_impl.cpp +++ /dev/null @@ -1,78 +0,0 @@ -#include <mbgl/style/tile_source_impl.hpp> -#include <mbgl/style/source_observer.hpp> -#include <mbgl/style/conversion/json.hpp> -#include <mbgl/style/conversion/tileset.hpp> -#include <mbgl/util/mapbox.hpp> -#include <mbgl/storage/file_source.hpp> - -namespace mbgl { -namespace style { - -TileSourceImpl::TileSourceImpl(SourceType type_, std::string id_, Source& base_, - variant<std::string, Tileset> urlOrTileset_, - uint16_t tileSize_) - : Impl(type_, std::move(id_), base_), - urlOrTileset(std::move(urlOrTileset_)), - tileSize(tileSize_) { -} - -TileSourceImpl::~TileSourceImpl() = default; - -void TileSourceImpl::loadDescription(FileSource& fileSource) { - if (urlOrTileset.is<Tileset>()) { - tileset = urlOrTileset.get<Tileset>(); - loaded = true; - return; - } - - if (req) { - return; - } - - const auto& url = urlOrTileset.get<std::string>(); - req = fileSource.request(Resource::source(url), [this, url](Response res) { - if (res.error) { - observer->onSourceError(base, std::make_exception_ptr(std::runtime_error(res.error->message))); - } else if (res.notModified) { - return; - } else if (res.noContent) { - observer->onSourceError(base, std::make_exception_ptr(std::runtime_error("unexpectedly empty TileJSON"))); - } else { - conversion::Error error; - optional<Tileset> newTileset = conversion::convertJSON<Tileset>(*res.data, error); - if (!newTileset) { - observer->onSourceError(base, std::make_exception_ptr(std::runtime_error(error.message))); - return; - } - - util::mapbox::canonicalizeTileset(*newTileset, url, type, tileSize); - bool attributionChanged = tileset.attribution != (*newTileset).attribution; - - tileset = *newTileset; - loaded = true; - - observer->onSourceLoaded(base); - if (attributionChanged) { - observer->onSourceChanged(base); - } - } - }); -} - -optional<Tileset> TileSourceImpl::getTileset() const { - if (loaded) { - return tileset; - } - return {}; -} - -optional<std::string> TileSourceImpl::getAttribution() const { - if (loaded && !tileset.attribution.empty()) { - return tileset.attribution; - } else { - return {}; - } -} - -} // namespace style -} // namespace mbgl diff --git a/src/mbgl/style/tile_source_impl.hpp b/src/mbgl/style/tile_source_impl.hpp deleted file mode 100644 index 0e5a53add7..0000000000 --- a/src/mbgl/style/tile_source_impl.hpp +++ /dev/null @@ -1,47 +0,0 @@ -#pragma once - -#include <mbgl/style/source_impl.hpp> -#include <mbgl/util/tileset.hpp> -#include <mbgl/util/variant.hpp> -#include <mbgl/util/optional.hpp> - -namespace mbgl { - -class AsyncRequest; - -namespace style { - -/* - Shared implementation for VectorSource and RasterSource. Should eventually - be refactored to use composition rather than inheritance. -*/ -class TileSourceImpl : public Source::Impl { -public: - TileSourceImpl(SourceType, std::string id, Source&, - variant<std::string, Tileset> urlOrTileset, - uint16_t tileSize); - ~TileSourceImpl() override; - - void loadDescription(FileSource&) final; - - uint16_t getTileSize() const { - return tileSize; - } - - const variant<std::string, Tileset>& getURLOrTileset() const { - return urlOrTileset; - } - - optional<std::string> getAttribution() const override; - optional<Tileset> getTileset() const; - -protected: - const variant<std::string, Tileset> urlOrTileset; - const uint16_t tileSize; - - Tileset tileset; - std::unique_ptr<AsyncRequest> req; -}; - -} // namespace style -} // namespace mbgl diff --git a/src/mbgl/tile/geometry_tile.cpp b/src/mbgl/tile/geometry_tile.cpp index 5079a33340..b8dc86555b 100644 --- a/src/mbgl/tile/geometry_tile.cpp +++ b/src/mbgl/tile/geometry_tile.cpp @@ -93,10 +93,10 @@ void GeometryTile::redoLayout() { // state despite pending parse operations. pending = true; - std::vector<std::unique_ptr<Layer>> copy; + std::vector<Immutable<Layer::Impl>> impls; for (const Layer* layer : style.getLayers()) { - // Avoid cloning and including irrelevant layers. + // Skip irrelevant layers. if (layer->is<BackgroundLayer>() || layer->is<CustomLayer>() || layer->baseImpl->source != sourceID || @@ -106,11 +106,11 @@ void GeometryTile::redoLayout() { continue; } - copy.push_back(layer->baseImpl->clone()); + impls.push_back(layer->baseImpl); } ++correlationID; - worker.invoke(&GeometryTileWorker::setLayers, std::move(copy), correlationID); + worker.invoke(&GeometryTileWorker::setLayers, std::move(impls), correlationID); } void GeometryTile::onLayout(LayoutResult result) { @@ -160,9 +160,9 @@ void GeometryTile::getIcons(IconDependencies) { spriteAtlas.getIcons(*this); } -Bucket* GeometryTile::getBucket(const RenderLayer& layer) const { - const auto& buckets = layer.is<RenderSymbolLayer>() ? symbolBuckets : nonSymbolBuckets; - const auto it = buckets.find(layer.baseImpl.id); +Bucket* GeometryTile::getBucket(const Layer::Impl& layer) const { + const auto& buckets = layer.type == LayerType::Symbol ? symbolBuckets : nonSymbolBuckets; + const auto it = buckets.find(layer.id); if (it == buckets.end()) { return nullptr; } diff --git a/src/mbgl/tile/geometry_tile.hpp b/src/mbgl/tile/geometry_tile.hpp index 08965b6389..7d275fc72c 100644 --- a/src/mbgl/tile/geometry_tile.hpp +++ b/src/mbgl/tile/geometry_tile.hpp @@ -48,7 +48,7 @@ public: void getGlyphs(GlyphDependencies); void getIcons(IconDependencies); - Bucket* getBucket(const RenderLayer&) const override; + Bucket* getBucket(const style::Layer::Impl&) const override; void queryRenderedFeatures( std::unordered_map<std::string, std::vector<Feature>>& result, diff --git a/src/mbgl/tile/geometry_tile_worker.cpp b/src/mbgl/tile/geometry_tile_worker.cpp index 29bfe8d472..788534531d 100644 --- a/src/mbgl/tile/geometry_tile_worker.cpp +++ b/src/mbgl/tile/geometry_tile_worker.cpp @@ -91,7 +91,7 @@ void GeometryTileWorker::setData(std::unique_ptr<const GeometryTileData> data_, } } -void GeometryTileWorker::setLayers(std::vector<std::unique_ptr<Layer>> layers_, uint64_t correlationID_) { +void GeometryTileWorker::setLayers(std::vector<Immutable<Layer::Impl>> layers_, uint64_t correlationID_) { try { layers = std::move(layers_); correlationID = correlationID_; @@ -242,11 +242,11 @@ void GeometryTileWorker::requestNewIcons(const IconDependencies& iconDependencie } } -static std::vector<std::unique_ptr<RenderLayer>> toRenderLayers(const std::vector<std::unique_ptr<style::Layer>>& layers, float zoom) { +static std::vector<std::unique_ptr<RenderLayer>> toRenderLayers(const std::vector<Immutable<style::Layer::Impl>>& layers, float zoom) { std::vector<std::unique_ptr<RenderLayer>> renderLayers; renderLayers.reserve(layers.size()); for (auto& layer : layers) { - renderLayers.push_back(layer->baseImpl->createRenderLayer()); + renderLayers.push_back(layer->createRenderLayer()); renderLayers.back()->cascade(CascadeParameters { { ClassID::Default }, @@ -268,8 +268,8 @@ void GeometryTileWorker::redoLayout() { std::vector<std::string> symbolOrder; for (auto it = layers->rbegin(); it != layers->rend(); it++) { - if ((*it)->is<SymbolLayer>()) { - symbolOrder.push_back((*it)->getID()); + if ((*it)->type == LayerType::Symbol) { + symbolOrder.push_back((*it)->id); } } @@ -296,7 +296,7 @@ void GeometryTileWorker::redoLayout() { const RenderLayer& leader = *group.at(0); - auto geometryLayer = (*data)->getLayer(leader.baseImpl.sourceLayer); + auto geometryLayer = (*data)->getLayer(leader.baseImpl->sourceLayer); if (!geometryLayer) { continue; } @@ -312,8 +312,8 @@ void GeometryTileWorker::redoLayout() { symbolLayoutMap.emplace(leader.getID(), leader.as<RenderSymbolLayer>()->createLayout(parameters, group, *geometryLayer, glyphDependencies, iconDependencies)); } else { - const Filter& filter = leader.baseImpl.filter; - const std::string& sourceLayerID = leader.baseImpl.sourceLayer; + const Filter& filter = leader.baseImpl->filter; + const std::string& sourceLayerID = leader.baseImpl->sourceLayer; std::shared_ptr<Bucket> bucket = leader.createBucket(parameters, group); for (std::size_t i = 0; !obsolete && i < geometryLayer->featureCount(); i++) { diff --git a/src/mbgl/tile/geometry_tile_worker.hpp b/src/mbgl/tile/geometry_tile_worker.hpp index 1df1ef43c4..0d4cba04b3 100644 --- a/src/mbgl/tile/geometry_tile_worker.hpp +++ b/src/mbgl/tile/geometry_tile_worker.hpp @@ -7,6 +7,8 @@ #include <mbgl/text/placement_config.hpp> #include <mbgl/actor/actor_ref.hpp> #include <mbgl/util/optional.hpp> +#include <mbgl/util/immutable.hpp> +#include <mbgl/style/layer_impl.hpp> #include <atomic> #include <memory> @@ -32,7 +34,7 @@ public: const MapMode); ~GeometryTileWorker(); - void setLayers(std::vector<std::unique_ptr<style::Layer>>, uint64_t correlationID); + void setLayers(std::vector<Immutable<style::Layer::Impl>>, uint64_t correlationID); void setData(std::unique_ptr<const GeometryTileData>, uint64_t correlationID); void setPlacementConfig(PlacementConfig, uint64_t correlationID); @@ -71,7 +73,7 @@ private: uint64_t correlationID = 0; // Outer optional indicates whether we've received it or not. - optional<std::vector<std::unique_ptr<style::Layer>>> layers; + optional<std::vector<Immutable<style::Layer::Impl>>> layers; optional<std::unique_ptr<const GeometryTileData>> data; optional<PlacementConfig> placementConfig; diff --git a/src/mbgl/tile/raster_tile.cpp b/src/mbgl/tile/raster_tile.cpp index b1a901e565..796517b8fa 100644 --- a/src/mbgl/tile/raster_tile.cpp +++ b/src/mbgl/tile/raster_tile.cpp @@ -55,7 +55,7 @@ void RasterTile::onError(std::exception_ptr err) { observer->onTileError(*this, err); } -Bucket* RasterTile::getBucket(const RenderLayer&) const { +Bucket* RasterTile::getBucket(const style::Layer::Impl&) const { return bucket.get(); } diff --git a/src/mbgl/tile/raster_tile.hpp b/src/mbgl/tile/raster_tile.hpp index e047430485..b4804bdb7d 100644 --- a/src/mbgl/tile/raster_tile.hpp +++ b/src/mbgl/tile/raster_tile.hpp @@ -29,7 +29,7 @@ public: optional<Timestamp> expires_); void cancel() override; - Bucket* getBucket(const RenderLayer&) const override; + Bucket* getBucket(const style::Layer::Impl&) const override; void onParsed(std::unique_ptr<Bucket> result); void onError(std::exception_ptr); diff --git a/src/mbgl/tile/tile.hpp b/src/mbgl/tile/tile.hpp index 795fd62140..544717e2b8 100644 --- a/src/mbgl/tile/tile.hpp +++ b/src/mbgl/tile/tile.hpp @@ -9,6 +9,7 @@ #include <mbgl/renderer/bucket.hpp> #include <mbgl/tile/geometry_tile_data.hpp> #include <mbgl/storage/resource.hpp> +#include <mbgl/style/layer_impl.hpp> #include <string> #include <memory> @@ -23,10 +24,6 @@ class TileObserver; class PlacementConfig; class RenderedQueryOptions; class SourceQueryOptions; -class RenderLayer; - -namespace style { -} // namespace style class Tile : private util::noncopyable { public: @@ -47,7 +44,7 @@ public: // Mark this tile as no longer needed and cancel any pending work. virtual void cancel() = 0; - virtual Bucket* getBucket(const RenderLayer&) const = 0; + virtual Bucket* getBucket(const style::Layer::Impl&) const = 0; virtual void setPlacementConfig(const PlacementConfig&) {} virtual void redoLayout() {} diff --git a/src/mbgl/util/longest_common_subsequence.hpp b/src/mbgl/util/longest_common_subsequence.hpp new file mode 100644 index 0000000000..ac127c6356 --- /dev/null +++ b/src/mbgl/util/longest_common_subsequence.hpp @@ -0,0 +1,106 @@ +#pragma once + +#include <cstddef> +#include <functional> +#include <iterator> +#include <vector> + +namespace mbgl { + +/* + Computes the longest common subsequence (LCS) of sequences A and B, represented + by pairs of random access iterators. The result is output to the provided output + iterator. Equality of elements is determined by the provided comparator, defaulting + to ==. + + The algorithm used is the O(ND) time and space algorithm from: + + Myers, Eugene W. An O(ND) Difference Algorithm and Its Variations. Algorithmica + (1986) 1: 251. http://xmailserver.org/diff2.pdf + + For understanding this algorithm, http://simplygenius.net/Article/DiffTutorial1 is + also helpful. + + TODO: implement the O(N) space refinement presented in the paper. +*/ +template <class InIt, class OutIt, class Equal> +OutIt longest_common_subsequence(InIt a, InIt endA, + InIt b, InIt endB, + OutIt outIt, + Equal eq) { + const std::ptrdiff_t N = endA - a; + const std::ptrdiff_t M = endB - b; + const std::ptrdiff_t D = N + M; + + if (D == 0) { + return outIt; + } + + std::vector<std::vector<std::ptrdiff_t>> vs; + + // Self-executing lambda to allow `return` to break from inner loop, and avoid shadowing `v`. + [&] () { + std::vector<std::ptrdiff_t> v; + v.resize(2 * D + 1); + v[1] = 0; + + // Core of the algorithm: greedily find farthest-reaching D-paths for increasing + // values of D. Store the farthest-reaching endpoints found in each iteration for + // later reconstructing the LCS. + for (std::ptrdiff_t d = 0; d <= D; ++d) { + for (std::ptrdiff_t k = -d; k <= d; k += 2) { + std::ptrdiff_t x = (k == -d || (k != d && v.at(k - 1 + D) < v.at(k + 1 + D))) + ? v.at(k + 1 + D) // moving down + : v.at(k - 1 + D) + 1; // moving right + + std::ptrdiff_t y = x - k; + + while (x < N && y < M && eq(a[x], b[y])) { + x++; + y++; + } + + v[k + D] = x; + + if (x >= N && y >= M) { + vs.push_back(v); + return; + } + } + + vs.push_back(v); + } + }(); + + std::ptrdiff_t x = N; + std::ptrdiff_t y = M; + + using E = typename std::iterator_traits<InIt>::value_type; + std::vector<E> lcsReverse; + + // Reconstruct the LCS using the farthest-reaching endpoints stored above. + for (std::ptrdiff_t d = vs.size() - 1; x > 0 || y > 0; --d) { + const std::vector<std::ptrdiff_t>& v = vs.at(d); + const std::ptrdiff_t k = x - y; + const bool down = (k == -d || (k != d && v.at(k - 1 + D) < v.at(k + 1 + D))); + const std::ptrdiff_t kPrev = down ? k + 1 : k - 1; + + x = v.at(kPrev + D); + y = x - kPrev; + + for (std::ptrdiff_t c = v[k + D]; c != (down ? x : x + 1); --c) { + lcsReverse.push_back(a[c - 1]); + } + } + + return std::copy(lcsReverse.rbegin(), lcsReverse.rend(), outIt); +} + +template < typename InIt, typename OutIt > +OutIt longest_common_subsequence(InIt a, InIt endA, + InIt b, InIt endB, + OutIt outIt) { + return longest_common_subsequence(a, endA, b, endB, outIt, std::equal_to<>()); +} + +} diff --git a/test/style/conversion/layer.test.cpp b/test/style/conversion/layer.test.cpp index ae8d4058ab..8ca5ed7e2b 100644 --- a/test/style/conversion/layer.test.cpp +++ b/test/style/conversion/layer.test.cpp @@ -35,13 +35,13 @@ TEST(StyleConversion, LayerTransition) { } })JSON"); - ASSERT_EQ(400ms, *layer->as<BackgroundLayer>()->impl->cascading + ASSERT_EQ(400ms, *layer->as<BackgroundLayer>()->impl().cascading .get<BackgroundColor>().getTransition({}).duration); - ASSERT_EQ(500ms, *layer->as<BackgroundLayer>()->impl->cascading + ASSERT_EQ(500ms, *layer->as<BackgroundLayer>()->impl().cascading .get<BackgroundColor>().getTransition({}).delay); - ASSERT_EQ(100ms, *layer->as<BackgroundLayer>()->impl->cascading + ASSERT_EQ(100ms, *layer->as<BackgroundLayer>()->impl().cascading .get<BackgroundColor>().getTransition({"class"}).duration); - ASSERT_FALSE(bool(layer->as<BackgroundLayer>()->impl->cascading + ASSERT_FALSE(bool(layer->as<BackgroundLayer>()->impl().cascading .get<BackgroundColor>().getTransition({"class"}).delay)); } diff --git a/test/style/source.test.cpp b/test/style/source.test.cpp index 9c0d914543..ad28db7c19 100644 --- a/test/style/source.test.cpp +++ b/test/style/source.test.cpp @@ -95,8 +95,8 @@ TEST(Source, LoadingFail) { }; VectorSource source("source", "url"); - source.baseImpl->setObserver(&test.styleObserver); - source.baseImpl->loadDescription(test.fileSource); + source.setObserver(&test.styleObserver); + source.loadDescription(test.fileSource); test.run(); } @@ -118,8 +118,8 @@ TEST(Source, LoadingCorrupt) { }; VectorSource source("source", "url"); - source.baseImpl->setObserver(&test.styleObserver); - source.baseImpl->loadDescription(test.fileSource); + source.setObserver(&test.styleObserver); + source.loadDescription(test.fileSource); test.run(); } @@ -137,10 +137,10 @@ TEST(Source, RasterTileEmpty) { tileset.tiles = { "tiles" }; RasterSource source("source", tileset, 512); - source.baseImpl->loadDescription(test.fileSource); + source.loadDescription(test.fileSource); test.renderSourceObserver.tileChanged = [&] (RenderSource& source_, const OverscaledTileID&) { - EXPECT_EQ("source", source_.baseImpl.id); + EXPECT_EQ("source", source_.baseImpl->id); test.end(); }; @@ -148,9 +148,9 @@ TEST(Source, RasterTileEmpty) { FAIL() << "Should never be called"; }; - RenderRasterSource renderSource(*source.impl); - renderSource.setObserver(&test.renderSourceObserver); - renderSource.updateTiles(test.tileParameters); + auto renderSource = source.baseImpl->createRenderSource(); + renderSource->setObserver(&test.renderSourceObserver); + renderSource->updateTiles(test.tileParameters); test.run(); } @@ -168,10 +168,10 @@ TEST(Source, VectorTileEmpty) { tileset.tiles = { "tiles" }; VectorSource source("source", tileset); - source.baseImpl->loadDescription(test.fileSource); + source.loadDescription(test.fileSource); test.renderSourceObserver.tileChanged = [&] (RenderSource& source_, const OverscaledTileID&) { - EXPECT_EQ("source", source_.baseImpl.id); + EXPECT_EQ("source", source_.baseImpl->id); test.end(); }; @@ -179,9 +179,9 @@ TEST(Source, VectorTileEmpty) { FAIL() << "Should never be called"; }; - RenderVectorSource renderSource(*source.impl); - renderSource.setObserver(&test.renderSourceObserver); - renderSource.updateTiles(test.tileParameters); + auto renderSource = source.baseImpl->createRenderSource(); + renderSource->setObserver(&test.renderSourceObserver); + renderSource->updateTiles(test.tileParameters); test.run(); } @@ -201,18 +201,18 @@ TEST(Source, RasterTileFail) { tileset.tiles = { "tiles" }; RasterSource source("source", tileset, 512); - source.baseImpl->loadDescription(test.fileSource); + source.loadDescription(test.fileSource); test.renderSourceObserver.tileError = [&] (RenderSource& source_, const OverscaledTileID& tileID, std::exception_ptr error) { - EXPECT_EQ(SourceType::Raster, source_.baseImpl.type); + EXPECT_EQ(SourceType::Raster, source_.baseImpl->type); EXPECT_EQ(OverscaledTileID(0, 0, 0), tileID); EXPECT_EQ("Failed by the test case", util::toString(error)); test.end(); }; - RenderRasterSource renderSource(*source.impl); - renderSource.setObserver(&test.renderSourceObserver); - renderSource.updateTiles(test.tileParameters); + auto renderSource = source.baseImpl->createRenderSource(); + renderSource->setObserver(&test.renderSourceObserver); + renderSource->updateTiles(test.tileParameters); test.run(); } @@ -232,18 +232,18 @@ TEST(Source, VectorTileFail) { tileset.tiles = { "tiles" }; VectorSource source("source", tileset); - source.baseImpl->loadDescription(test.fileSource); + source.loadDescription(test.fileSource); test.renderSourceObserver.tileError = [&] (RenderSource& source_, const OverscaledTileID& tileID, std::exception_ptr error) { - EXPECT_EQ(SourceType::Vector, source_.baseImpl.type); + EXPECT_EQ(SourceType::Vector, source_.baseImpl->type); EXPECT_EQ(OverscaledTileID(0, 0, 0), tileID); EXPECT_EQ("Failed by the test case", util::toString(error)); test.end(); }; - RenderVectorSource renderSource(*source.impl); - renderSource.setObserver(&test.renderSourceObserver); - renderSource.updateTiles(test.tileParameters); + auto renderSource = source.baseImpl->createRenderSource(); + renderSource->setObserver(&test.renderSourceObserver); + renderSource->updateTiles(test.tileParameters); test.run(); } @@ -261,19 +261,19 @@ TEST(Source, RasterTileCorrupt) { tileset.tiles = { "tiles" }; RasterSource source("source", tileset, 512); - source.baseImpl->loadDescription(test.fileSource); + source.loadDescription(test.fileSource); test.renderSourceObserver.tileError = [&] (RenderSource& source_, const OverscaledTileID& tileID, std::exception_ptr error) { - EXPECT_EQ(source_.baseImpl.type, SourceType::Raster); + EXPECT_EQ(source_.baseImpl->type, SourceType::Raster); EXPECT_EQ(OverscaledTileID(0, 0, 0), tileID); EXPECT_TRUE(bool(error)); // Not asserting on platform-specific error text. test.end(); }; - RenderRasterSource renderSource(*source.impl); - renderSource.setObserver(&test.renderSourceObserver); - renderSource.updateTiles(test.tileParameters); + auto renderSource = source.baseImpl->createRenderSource(); + renderSource->setObserver(&test.renderSourceObserver); + renderSource->updateTiles(test.tileParameters); test.run(); } @@ -296,18 +296,18 @@ TEST(Source, VectorTileCorrupt) { tileset.tiles = { "tiles" }; VectorSource source("source", tileset); - source.baseImpl->loadDescription(test.fileSource); + source.loadDescription(test.fileSource); test.renderSourceObserver.tileError = [&] (RenderSource& source_, const OverscaledTileID& tileID, std::exception_ptr error) { - EXPECT_EQ(source_.baseImpl.type, SourceType::Vector); + EXPECT_EQ(source_.baseImpl->type, SourceType::Vector); EXPECT_EQ(OverscaledTileID(0, 0, 0), tileID); EXPECT_EQ(util::toString(error), "unknown pbf field type exception"); test.end(); }; - RenderVectorSource renderSource(*source.impl); - renderSource.setObserver(&test.renderSourceObserver); - renderSource.updateTiles(test.tileParameters); + auto renderSource = source.baseImpl->createRenderSource(); + renderSource->setObserver(&test.renderSourceObserver); + renderSource->updateTiles(test.tileParameters); test.run(); } @@ -324,7 +324,7 @@ TEST(Source, RasterTileCancel) { tileset.tiles = { "tiles" }; RasterSource source("source", tileset, 512); - source.baseImpl->loadDescription(test.fileSource); + source.loadDescription(test.fileSource); test.renderSourceObserver.tileChanged = [&] (RenderSource&, const OverscaledTileID&) { FAIL() << "Should never be called"; @@ -334,9 +334,9 @@ TEST(Source, RasterTileCancel) { FAIL() << "Should never be called"; }; - RenderRasterSource renderSource(*source.impl); - renderSource.setObserver(&test.renderSourceObserver); - renderSource.updateTiles(test.tileParameters); + auto renderSource = source.baseImpl->createRenderSource(); + renderSource->setObserver(&test.renderSourceObserver); + renderSource->updateTiles(test.tileParameters); test.run(); } @@ -353,7 +353,7 @@ TEST(Source, VectorTileCancel) { tileset.tiles = { "tiles" }; VectorSource source("source", tileset); - source.baseImpl->loadDescription(test.fileSource); + source.loadDescription(test.fileSource); test.renderSourceObserver.tileChanged = [&] (RenderSource&, const OverscaledTileID&) { FAIL() << "Should never be called"; @@ -363,9 +363,9 @@ TEST(Source, VectorTileCancel) { FAIL() << "Should never be called"; }; - RenderVectorSource renderSource(*source.impl); - renderSource.setObserver(&test.renderSourceObserver); - renderSource.updateTiles(test.tileParameters); + auto renderSource = source.baseImpl->createRenderSource(); + renderSource->setObserver(&test.renderSourceObserver); + renderSource->updateTiles(test.tileParameters); test.run(); } @@ -398,11 +398,11 @@ TEST(Source, RasterTileAttribution) { }; RasterSource source("source", "url", 512); - source.baseImpl->setObserver(&test.styleObserver); - source.baseImpl->loadDescription(test.fileSource); + source.setObserver(&test.styleObserver); + source.loadDescription(test.fileSource); - RenderRasterSource renderSource(*source.impl); - renderSource.updateTiles(test.tileParameters); + auto renderSource = source.baseImpl->createRenderSource(); + renderSource->updateTiles(test.tileParameters); test.run(); } @@ -423,10 +423,10 @@ TEST(Source, GeoJSonSourceUrlUpdate) { }; GeoJSONSource source("source"); - source.baseImpl->setObserver(&test.styleObserver); + source.setObserver(&test.styleObserver); // Load initial, so the source state will be loaded=true - source.baseImpl->loadDescription(test.fileSource); + source.loadDescription(test.fileSource); // Schedule an update test.loop.invoke([&] () { diff --git a/test/style/style_layer.test.cpp b/test/style/style_layer.test.cpp index 657dc24a70..2a8379bf20 100644 --- a/test/style/style_layer.test.cpp +++ b/test/style/style_layer.test.cpp @@ -28,15 +28,6 @@ using namespace mbgl::style; namespace { -template <class T, class... Params> void testClone(Params... params) { - auto layer = std::make_unique<T>(std::forward<Params>(params)...); - auto clone = layer->baseImpl->clone(); - EXPECT_NE(layer.get(), clone.get()); - EXPECT_TRUE(reinterpret_cast<typename T::Impl*>(clone->baseImpl.get())); - layer->impl->id = "test"; - EXPECT_EQ("test", layer->baseImpl->clone()->getID()); -} - const auto color = Color { 1, 0, 0, 1 }; const auto opacity = 1.0f; const auto radius = 1.0f; @@ -61,16 +52,6 @@ const auto duration = 1.0f; } // namespace -TEST(Layer, Clone) { - testClone<BackgroundLayer>("background"); - testClone<CircleLayer>("circle", "source"); - testClone<CustomLayer>("custom", [](void*){}, [](void*, const CustomLayerRenderParameters&){}, [](void*){}, nullptr), - testClone<FillLayer>("fill", "source"); - testClone<LineLayer>("line", "source"); - testClone<RasterLayer>("raster", "source"); - testClone<SymbolLayer>("symbol", "source"); -} - TEST(Layer, BackgroundProperties) { auto layer = std::make_unique<BackgroundLayer>("background"); EXPECT_TRUE(layer->is<BackgroundLayer>()); @@ -222,7 +203,7 @@ TEST(Layer, RasterProperties) { TEST(Layer, Observer) { auto layer = std::make_unique<LineLayer>("line", "source"); StubLayerObserver observer; - layer->baseImpl->setObserver(&observer); + layer->setObserver(&observer); // Notifies observer on filter change. bool filterChanged = false; diff --git a/test/tile/geojson_tile.test.cpp b/test/tile/geojson_tile.test.cpp index a0383f06c9..8669c02dfd 100644 --- a/test/tile/geojson_tile.test.cpp +++ b/test/tile/geojson_tile.test.cpp @@ -55,7 +55,7 @@ TEST(GeoJSONTile, Issue7648) { observer.tileChanged = [&] (const Tile&) { // Once present, the bucket should never "disappear", which would cause // flickering. - ASSERT_NE(nullptr, tile.getBucket(*test.style.getRenderLayer("circle"))); + ASSERT_NE(nullptr, tile.getBucket(*test.style.getLayer("circle")->baseImpl)); }; tile.setObserver(&observer); diff --git a/test/tile/vector_tile.test.cpp b/test/tile/vector_tile.test.cpp index 37bfe8512d..a966f3b706 100644 --- a/test/tile/vector_tile.test.cpp +++ b/test/tile/vector_tile.test.cpp @@ -89,7 +89,7 @@ TEST(VectorTile, Issue7615) { 0 }); - EXPECT_EQ(symbolBucket.get(), tile.getBucket(*symbolLayer.baseImpl->createRenderLayer())); + EXPECT_EQ(symbolBucket.get(), tile.getBucket(*symbolLayer.baseImpl)); } TEST(VectorTile, Issue8542) { |