diff options
Diffstat (limited to 'include/mbgl')
78 files changed, 2130 insertions, 771 deletions
diff --git a/include/mbgl/actor/actor.hpp b/include/mbgl/actor/actor.hpp new file mode 100644 index 0000000000..a0df19208e --- /dev/null +++ b/include/mbgl/actor/actor.hpp @@ -0,0 +1,98 @@ +#pragma once + +#include <mbgl/actor/mailbox.hpp> +#include <mbgl/actor/message.hpp> +#include <mbgl/actor/actor_ref.hpp> +#include <mbgl/util/noncopyable.hpp> + +#include <memory> +#include <future> +#include <type_traits> + +namespace mbgl { + +/* + An `Actor<O>` is an owning reference to an asynchronous object of type `O`: an "actor". + Communication with an actor happens via message passing: you send a message to the object + (using `invoke`), passing a pointer to the member function to call and arguments which + are then forwarded to the actor. + + The actor receives messages sent to it asynchronously, in a manner defined its `Scheduler`. + To store incoming messages before their receipt, each actor has a `Mailbox`, which acts as + a FIFO queue. Messages sent from actor S to actor R are guaranteed to be processed in the + order sent. However, relative order of messages sent by two *different* actors S1 and S2 + to R is *not* guaranteed (and can't be: S1 and S2 may be acting asynchronously with respect + to each other). + + An `Actor<O>` can be converted to an `ActorRef<O>`, a non-owning value object representing + a (weak) reference to the actor. Messages can be sent via the `Ref` as well. + + It's safe -- and encouraged -- to pass `Ref`s between actors via messages. This is how two-way + communication and other forms of collaboration between multiple actors is accomplished. + + It's safe for a `Ref` to outlive its `Actor` -- the reference is "weak", and does not extend + the lifetime of the owning Actor, and sending a message to a `Ref` whose `Actor` has died is + a no-op. (In the future, a dead-letters queue or log may be implemented.) + + Construction and destruction of an actor is currently synchronous: the corresponding `O` + object is constructed synchronously by the `Actor` constructor, and destructed synchronously + by the `~Actor` destructor, after ensuring that the `O` is not currently receiving an + asynchronous message. (Construction and destruction may change to be asynchronous in the + future.) The constructor of `O` is passed an `ActorRef<O>` referring to itself (which it + can use to self-send messages), followed by the forwarded arguments passed to `Actor<O>`. + + Please don't send messages that contain shared pointers or references. That subverts the + purpose of the actor model: prohibiting direct concurrent access to shared state. +*/ + +template <class Object> +class Actor : public util::noncopyable { +public: + + // Enabled for Objects with a constructor taking ActorRef<Object> as the first parameter + template <typename U = Object, class... Args, typename std::enable_if<std::is_constructible<U, ActorRef<U>, Args...>::value>::type * = nullptr> + Actor(Scheduler& scheduler, Args&&... args_) + : mailbox(std::make_shared<Mailbox>(scheduler)), + object(self(), std::forward<Args>(args_)...) { + } + + // Enabled for plain Objects + template<typename U = Object, class... Args, typename std::enable_if<!std::is_constructible<U, ActorRef<U>, Args...>::value>::type * = nullptr> + Actor(Scheduler& scheduler, Args&& ... args_) + : mailbox(std::make_shared<Mailbox>(scheduler)), object(std::forward<Args>(args_)...) { + } + + ~Actor() { + mailbox->close(); + } + + template <typename Fn, class... Args> + void invoke(Fn fn, Args&&... args) { + mailbox->push(actor::makeMessage(object, fn, std::forward<Args>(args)...)); + } + + template <typename Fn, class... Args> + auto ask(Fn fn, Args&&... args) { + // Result type is deduced from the function's return type + using ResultType = typename std::result_of<decltype(fn)(Object, Args...)>::type; + + std::promise<ResultType> promise; + auto future = promise.get_future(); + mailbox->push(actor::makeMessage(std::move(promise), object, fn, std::forward<Args>(args)...)); + return future; + } + + ActorRef<std::decay_t<Object>> self() { + return ActorRef<std::decay_t<Object>>(object, mailbox); + } + + operator ActorRef<std::decay_t<Object>>() { + return self(); + } + +private: + std::shared_ptr<Mailbox> mailbox; + Object object; +}; + +} // namespace mbgl diff --git a/include/mbgl/actor/actor_ref.hpp b/include/mbgl/actor/actor_ref.hpp new file mode 100644 index 0000000000..958ee3777c --- /dev/null +++ b/include/mbgl/actor/actor_ref.hpp @@ -0,0 +1,64 @@ +#pragma once + +#include <mbgl/actor/mailbox.hpp> +#include <mbgl/actor/message.hpp> + +#include <memory> + +namespace mbgl { + +/* + An `ActorRef<O>` is a *non*-owning, weak reference to an actor of type `O`. You can send it + messages just like an `Actor<O>`. It's a value object: safe to copy and pass between actors + via messages. + + An `ActorRef<O>` does not extend the lifetime of the corresponding `Actor<O>`. That's determined + entirely by whichever object owns the `Actor<O>` -- the actor's "supervisor". + + It's safe for a `Ref` to outlive its `Actor` -- the reference is "weak", and does not extend + the lifetime of the owning Actor, and sending a message to a `Ref` whose `Actor` has died is + a no-op. (In the future, a dead-letters queue or log may be implemented.) +*/ + +template <class Object> +class ActorRef { +public: + ActorRef(Object& object_, std::weak_ptr<Mailbox> weakMailbox_) + : object(&object_), + weakMailbox(std::move(weakMailbox_)) { + } + + template <typename Fn, class... Args> + void invoke(Fn fn, Args&&... args) { + if (auto mailbox = weakMailbox.lock()) { + mailbox->push(actor::makeMessage(*object, fn, std::forward<Args>(args)...)); + } + } + + template <typename Fn, class... Args> + auto ask(Fn fn, Args&&... args) { + // Result type is deduced from the function's return type + using ResultType = typename std::result_of<decltype(fn)(Object, Args...)>::type; + + std::promise<ResultType> promise; + auto future = promise.get_future(); + + if (auto mailbox = weakMailbox.lock()) { + mailbox->push( + actor::makeMessage( + std::move(promise), *object, fn, std::forward<Args>(args)... + ) + ); + } else { + promise.set_exception(std::make_exception_ptr(std::runtime_error("Actor has gone away"))); + } + + return future; + } + +private: + Object* object; + std::weak_ptr<Mailbox> weakMailbox; +}; + +} // namespace mbgl diff --git a/include/mbgl/actor/mailbox.hpp b/include/mbgl/actor/mailbox.hpp index cff0de243a..8ecf91701a 100644 --- a/include/mbgl/actor/mailbox.hpp +++ b/include/mbgl/actor/mailbox.hpp @@ -23,8 +23,10 @@ public: private: Scheduler& scheduler; - std::mutex closingMutex; - bool closing { false }; + std::recursive_mutex receivingMutex; + std::mutex pushingMutex; + + bool closed { false }; std::mutex queueMutex; std::queue<std::unique_ptr<Message>> queue; diff --git a/include/mbgl/actor/message.hpp b/include/mbgl/actor/message.hpp new file mode 100644 index 0000000000..0a20993352 --- /dev/null +++ b/include/mbgl/actor/message.hpp @@ -0,0 +1,108 @@ +#pragma once + +#include <mbgl/util/optional.hpp> + +#include <future> +#include <utility> + +namespace mbgl { + +// A movable type-erasing function wrapper. This allows to store arbitrary invokable +// things (like std::function<>, or the result of a movable-only std::bind()) in the queue. +// Source: http://stackoverflow.com/a/29642072/331379 +class Message { +public: + virtual ~Message() = default; + virtual void operator()() = 0; +}; + +template <class Object, class MemberFn, class ArgsTuple> +class MessageImpl : public Message { +public: + MessageImpl(Object& object_, MemberFn memberFn_, ArgsTuple argsTuple_) + : object(object_), + memberFn(memberFn_), + argsTuple(std::move(argsTuple_)) { + } + + void operator()() override { + invoke(std::make_index_sequence<std::tuple_size<ArgsTuple>::value>()); + } + + template <std::size_t... I> + void invoke(std::index_sequence<I...>) { + (object.*memberFn)(std::move(std::get<I>(argsTuple))...); + } + + Object& object; + MemberFn memberFn; + ArgsTuple argsTuple; +}; + +template <class ResultType, class Object, class MemberFn, class ArgsTuple> +class AskMessageImpl : public Message { +public: + AskMessageImpl(std::promise<ResultType> promise_, Object& object_, MemberFn memberFn_, ArgsTuple argsTuple_) + : object(object_), + memberFn(memberFn_), + argsTuple(std::move(argsTuple_)), + promise(std::move(promise_)) { + } + + void operator()() override { + promise.set_value(ask(std::make_index_sequence<std::tuple_size<ArgsTuple>::value>())); + } + + template <std::size_t... I> + ResultType ask(std::index_sequence<I...>) { + return (object.*memberFn)(std::move(std::get<I>(argsTuple))...); + } + + Object& object; + MemberFn memberFn; + ArgsTuple argsTuple; + std::promise<ResultType> promise; +}; + +template <class Object, class MemberFn, class ArgsTuple> +class AskMessageImpl<void, Object, MemberFn, ArgsTuple> : public Message { +public: + AskMessageImpl(std::promise<void> promise_, Object& object_, MemberFn memberFn_, ArgsTuple argsTuple_) + : object(object_), + memberFn(memberFn_), + argsTuple(std::move(argsTuple_)), + promise(std::move(promise_)) { + } + + void operator()() override { + ask(std::make_index_sequence<std::tuple_size<ArgsTuple>::value>()); + promise.set_value(); + } + + template <std::size_t... I> + void ask(std::index_sequence<I...>) { + (object.*memberFn)(std::move(std::get<I>(argsTuple))...); + } + + Object& object; + MemberFn memberFn; + ArgsTuple argsTuple; + std::promise<void> promise; +}; + +namespace actor { + +template <class Object, class MemberFn, class... Args> +std::unique_ptr<Message> makeMessage(Object& object, MemberFn memberFn, Args&&... args) { + auto tuple = std::make_tuple(std::forward<Args>(args)...); + return std::make_unique<MessageImpl<Object, MemberFn, decltype(tuple)>>(object, memberFn, std::move(tuple)); +} + +template <class ResultType, class Object, class MemberFn, class... Args> +std::unique_ptr<Message> makeMessage(std::promise<ResultType>&& promise, Object& object, MemberFn memberFn, Args&&... args) { + auto tuple = std::make_tuple(std::forward<Args>(args)...); + return std::make_unique<AskMessageImpl<ResultType, Object, MemberFn, decltype(tuple)>>(std::move(promise), object, memberFn, std::move(tuple)); +} + +} // namespace actor +} // namespace mbgl diff --git a/include/mbgl/actor/scheduler.hpp b/include/mbgl/actor/scheduler.hpp index 83689c3348..d8a26ebeab 100644 --- a/include/mbgl/actor/scheduler.hpp +++ b/include/mbgl/actor/scheduler.hpp @@ -21,18 +21,21 @@ class Mailbox; Subject to these constraints, processing can happen on whatever thread in the pool is available. - * `RunLoop` is a `Scheduler` that is typically used to create a mailbox and - `ActorRef` for an object that lives on the main thread and is not itself wrapped - as an `Actor`: - - auto mailbox = std::make_shared<Mailbox>(*util::RunLoop::Get()); + * `Scheduler::GetCurrent()` is typically used to create a mailbox and `ActorRef` + for an object that lives on the main thread and is not itself wrapped an + `Actor`. The underlying implementation of this Scheduler should usually be + a `RunLoop` + auto mailbox = std::make_shared<Mailbox>(*Scheduler::Get()); Actor<Worker> worker(threadPool, ActorRef<Foo>(*this, mailbox)); */ - class Scheduler { public: virtual ~Scheduler() = default; virtual void schedule(std::weak_ptr<Mailbox>) = 0; + + // Set/Get the current Scheduler for this thread + static Scheduler* GetCurrent(); + static void SetCurrent(Scheduler*); }; } // namespace mbgl diff --git a/include/mbgl/annotation/annotation.hpp b/include/mbgl/annotation/annotation.hpp index de83d24712..bbe479b5ba 100644 --- a/include/mbgl/annotation/annotation.hpp +++ b/include/mbgl/annotation/annotation.hpp @@ -17,6 +17,10 @@ using AnnotationIDs = std::vector<AnnotationID>; class SymbolAnnotation { public: + SymbolAnnotation(Point<double> geometry_, std::string icon_ = {}) + : geometry(std::move(geometry_)), + icon(std::move(icon_)) {} + Point<double> geometry; std::string icon; }; @@ -29,31 +33,41 @@ using ShapeAnnotationGeometry = variant< class LineAnnotation { public: + LineAnnotation(ShapeAnnotationGeometry geometry_, + style::DataDrivenPropertyValue<float> opacity_ = 1.0f, + style::DataDrivenPropertyValue<float> width_ = 1.0f, + style::DataDrivenPropertyValue<Color> color_ = Color::black()) + : geometry(std::move(geometry_)), + opacity(std::move(opacity_)), + width(std::move(width_)), + color(std::move(color_)) {} + ShapeAnnotationGeometry geometry; - style::DataDrivenPropertyValue<float> opacity { 1.0f }; - style::PropertyValue<float> width { 1.0f }; - style::DataDrivenPropertyValue<Color> color { Color::black() }; + style::DataDrivenPropertyValue<float> opacity; + style::DataDrivenPropertyValue<float> width; + style::DataDrivenPropertyValue<Color> color; }; class FillAnnotation { public: - ShapeAnnotationGeometry geometry; - style::DataDrivenPropertyValue<float> opacity { 1.0f }; - style::DataDrivenPropertyValue<Color> color { Color::black() }; - style::DataDrivenPropertyValue<Color> outlineColor {}; -}; + FillAnnotation(ShapeAnnotationGeometry geometry_, + style::DataDrivenPropertyValue<float> opacity_ = 1.0f, + style::DataDrivenPropertyValue<Color> color_ = Color::black(), + style::DataDrivenPropertyValue<Color> outlineColor_ = {}) + : geometry(std::move(geometry_)), + opacity(std::move(opacity_)), + color(std::move(color_)), + outlineColor(std::move(outlineColor_)) {} -// An annotation whose type and properties are sourced from a style layer. -class StyleSourcedAnnotation { -public: ShapeAnnotationGeometry geometry; - std::string layerID; + style::DataDrivenPropertyValue<float> opacity; + style::DataDrivenPropertyValue<Color> color; + style::DataDrivenPropertyValue<Color> outlineColor; }; using Annotation = variant< SymbolAnnotation, LineAnnotation, - FillAnnotation, - StyleSourcedAnnotation>; + FillAnnotation>; } // namespace mbgl diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp index bbeeeac6cc..4108725776 100644 --- a/include/mbgl/map/map.hpp +++ b/include/mbgl/map/map.hpp @@ -4,14 +4,10 @@ #include <mbgl/util/chrono.hpp> #include <mbgl/map/map_observer.hpp> #include <mbgl/map/mode.hpp> -#include <mbgl/util/geo.hpp> -#include <mbgl/util/feature.hpp> #include <mbgl/util/noncopyable.hpp> #include <mbgl/util/size.hpp> #include <mbgl/annotation/annotation.hpp> -#include <mbgl/style/transition_options.hpp> #include <mbgl/map/camera.hpp> -#include <mbgl/map/query.hpp> #include <cstdint> #include <string> @@ -21,58 +17,41 @@ namespace mbgl { -class Backend; -class View; class FileSource; class Scheduler; +class RendererFrontend; namespace style { class Image; -class Source; -class Layer; -class Light; +class Style; } // namespace style class Map : private util::noncopyable { public: - explicit Map(Backend&, + explicit Map(RendererFrontend&, + MapObserver&, Size size, float pixelRatio, FileSource&, Scheduler&, MapMode mapMode = MapMode::Continuous, - GLContextMode contextMode = GLContextMode::Unique, ConstrainMode constrainMode = ConstrainMode::HeightOnly, - ViewportMode viewportMode = ViewportMode::Default, - const optional<std::string>& programCacheDir = {}); + ViewportMode viewportMode = ViewportMode::Default); ~Map(); // Register a callback that will get called (on the render thread) when all resources have // been loaded and a complete render occurs. using StillImageCallback = std::function<void (std::exception_ptr)>; - void renderStill(View&, StillImageCallback callback); + void renderStill(StillImageCallback); + void renderStill(const CameraOptions&, MapDebugOptions, StillImageCallback); // Triggers a repaint. void triggerRepaint(); - // Main render function. - void render(View&); + style::Style& getStyle(); + const style::Style& getStyle() const; - // Styling - void addClass(const std::string&); - void removeClass(const std::string&); - void setClasses(const std::vector<std::string>&); - - style::TransitionOptions getTransitionOptions() const; - void setTransitionOptions(const style::TransitionOptions&); - - bool hasClass(const std::string&) const; - std::vector<std::string> getClasses() const; - - void setStyleURL(const std::string&); - void setStyleJSON(const std::string&); - std::string getStyleURL() const; - std::string getStyleJSON() const; + void setStyle(std::unique_ptr<style::Style>); // Transition void cancelTransitions(); @@ -155,7 +134,7 @@ public: LatLng latLngForPixel(const ScreenCoordinate&) const; // Annotations - void addAnnotationImage(const std::string&, std::unique_ptr<style::Image>); + void addAnnotationImage(std::unique_ptr<style::Image>); void removeAnnotationImage(const std::string&); double getTopOffsetPixelsForAnnotationImage(const std::string&); @@ -163,44 +142,14 @@ public: void updateAnnotation(AnnotationID, const Annotation&); void removeAnnotation(AnnotationID); - // Sources - std::vector<style::Source*> getSources(); - style::Source* getSource(const std::string& sourceID); - void addSource(std::unique_ptr<style::Source>); - std::unique_ptr<style::Source> removeSource(const std::string& sourceID); - - // Layers - std::vector<style::Layer*> getLayers(); - style::Layer* getLayer(const std::string& layerID); - void addLayer(std::unique_ptr<style::Layer>, const optional<std::string>& beforeLayerID = {}); - std::unique_ptr<style::Layer> removeLayer(const std::string& layerID); - - // Images - void addImage(const std::string&, std::unique_ptr<style::Image>); - void removeImage(const std::string&); - const style::Image* getImage(const std::string&); - - // Light - void setLight(std::unique_ptr<style::Light>); - style::Light* getLight(); - - // Defaults - std::string getStyleName() const; - LatLng getDefaultLatLng() const; - double getDefaultZoom() const; - double getDefaultBearing() const; - double getDefaultPitch() const; - - // Feature queries - std::vector<Feature> queryRenderedFeatures(const ScreenCoordinate&, const RenderedQueryOptions& options = {}); - std::vector<Feature> queryRenderedFeatures(const ScreenBox&, const RenderedQueryOptions& options = {}); - std::vector<Feature> querySourceFeatures(const std::string& sourceID, const SourceQueryOptions& options = {}); - - AnnotationIDs queryPointAnnotations(const ScreenBox&); - - // Memory - void setSourceTileCacheSize(size_t); - void onLowMemory(); + // Tile prefetching + // + // When loading a map, if `PrefetchZoomDelta` is set to any number greater than 0, the map will + // first request a tile for `zoom = getZoom() - delta` in a attempt to display a full map at + // lower resolution as quick as possible. It will get clamped at the tile source minimum zoom. + // The default `delta` is 4. + void setPrefetchZoomDelta(uint8_t delta); + uint8_t getPrefetchZoomDelta() const; // Debug void setDebug(MapDebugOptions); diff --git a/include/mbgl/map/mode.hpp b/include/mbgl/map/mode.hpp index afec5c0a08..05de2df22c 100644 --- a/include/mbgl/map/mode.hpp +++ b/include/mbgl/map/mode.hpp @@ -1,5 +1,6 @@ #pragma once +#include <mbgl/util/util.hpp> #include <mbgl/util/traits.hpp> #include <cstdint> @@ -51,23 +52,23 @@ enum class MapDebugOptions : EnumType { #endif // MBGL_USE_GLES2 }; -constexpr MapDebugOptions operator|(MapDebugOptions lhs, MapDebugOptions rhs) { +MBGL_CONSTEXPR MapDebugOptions operator|(MapDebugOptions lhs, MapDebugOptions rhs) { return MapDebugOptions(mbgl::underlying_type(lhs) | mbgl::underlying_type(rhs)); } -constexpr MapDebugOptions& operator|=(MapDebugOptions& lhs, MapDebugOptions rhs) { +MBGL_CONSTEXPR MapDebugOptions& operator|=(MapDebugOptions& lhs, MapDebugOptions rhs) { return (lhs = MapDebugOptions(mbgl::underlying_type(lhs) | mbgl::underlying_type(rhs))); } -constexpr bool operator&(MapDebugOptions lhs, MapDebugOptions rhs) { +MBGL_CONSTEXPR bool operator&(MapDebugOptions lhs, MapDebugOptions rhs) { return mbgl::underlying_type(lhs) & mbgl::underlying_type(rhs); } -constexpr MapDebugOptions& operator&=(MapDebugOptions& lhs, MapDebugOptions rhs) { +MBGL_CONSTEXPR MapDebugOptions& operator&=(MapDebugOptions& lhs, MapDebugOptions rhs) { return (lhs = MapDebugOptions(mbgl::underlying_type(lhs) & mbgl::underlying_type(rhs))); } -constexpr MapDebugOptions operator~(MapDebugOptions value) { +MBGL_CONSTEXPR MapDebugOptions operator~(MapDebugOptions value) { return MapDebugOptions(~mbgl::underlying_type(value)); } diff --git a/include/mbgl/map/view.hpp b/include/mbgl/map/view.hpp deleted file mode 100644 index 295779fe51..0000000000 --- a/include/mbgl/map/view.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -namespace mbgl { - -class Map; - -class View { -public: - virtual ~View() = default; - - // Called when this View is used for rendering. Implementations should ensure that a renderable - // object is bound and glClear/glDraw* calls can be done. They should also make sure that - // calling .bind() repeatedly is a no-op and that the appropriate gl::Context values are - // set to the current state. - virtual void bind() = 0; -}; - -} // namespace mbgl diff --git a/include/mbgl/math/log2.hpp b/include/mbgl/math/log2.hpp index 8a3bc7f1c0..53d5e45545 100644 --- a/include/mbgl/math/log2.hpp +++ b/include/mbgl/math/log2.hpp @@ -17,9 +17,9 @@ typename std::enable_if_t<std::is_floating_point<T>::value, T> log2(T x) // log2() is producing wrong results on ARMv5 binaries // running on ARMv7+ CPUs. #if defined(__ANDROID__) - return std::log(x) / M_LN2; + return ::log(x) / M_LN2; #else - return std::log2(x); + return ::log2(x); #endif } diff --git a/include/mbgl/map/backend_scope.hpp b/include/mbgl/renderer/backend_scope.hpp index 322c17b3fc..73bafc84c7 100644 --- a/include/mbgl/map/backend_scope.hpp +++ b/include/mbgl/renderer/backend_scope.hpp @@ -2,7 +2,7 @@ namespace mbgl { -class Backend; +class RendererBackend; class BackendScope { public: @@ -15,7 +15,7 @@ public: Explicit, }; - BackendScope(Backend&, ScopeType = ScopeType::Explicit); + BackendScope(RendererBackend&, ScopeType = ScopeType::Explicit); ~BackendScope(); // Returns true when there is currently a BackendScope active in this thread. @@ -27,7 +27,7 @@ private: BackendScope* priorScope; BackendScope* nextScope; - Backend& backend; + RendererBackend& backend; const ScopeType scopeType; bool activated = false; }; diff --git a/include/mbgl/map/query.hpp b/include/mbgl/renderer/query.hpp index 9fac60d71d..4cadf4f017 100644 --- a/include/mbgl/map/query.hpp +++ b/include/mbgl/renderer/query.hpp @@ -13,6 +13,11 @@ namespace mbgl { */ class RenderedQueryOptions { public: + RenderedQueryOptions(optional<std::vector<std::string>> layerIDs_ = {}, + optional<style::Filter> filter_ = {}) + : layerIDs(std::move(layerIDs_)), + filter(std::move(filter_)) {} + /** layerIDs to include in the query */ optional<std::vector<std::string>> layerIDs; @@ -24,10 +29,15 @@ public: */ class SourceQueryOptions { public: + SourceQueryOptions(optional<std::vector<std::string>> sourceLayers_ = {}, + optional<style::Filter> filter_ = {}) + : sourceLayers(std::move(sourceLayers_)), + filter(std::move(filter_)) {} + // Required for VectorSource, ignored for GeoJSONSource optional<std::vector<std::string>> sourceLayers; optional<style::Filter> filter; }; -} +} // namespace mbgl diff --git a/include/mbgl/renderer/renderer.hpp b/include/mbgl/renderer/renderer.hpp new file mode 100644 index 0000000000..be8abb2c29 --- /dev/null +++ b/include/mbgl/renderer/renderer.hpp @@ -0,0 +1,55 @@ +#pragma once + +#include <mbgl/map/mode.hpp> +#include <mbgl/renderer/query.hpp> +#include <mbgl/annotation/annotation.hpp> +#include <mbgl/util/geo.hpp> +#include <mbgl/util/geo.hpp> + +#include <functional> +#include <memory> +#include <string> +#include <vector> + +namespace mbgl { + +class FileSource; +class RendererBackend; +class RendererObserver; +class RenderedQueryOptions; +class Scheduler; +class SourceQueryOptions; +class UpdateParameters; + +class Renderer { +public: + Renderer(RendererBackend&, float pixelRatio_, FileSource&, Scheduler&, + GLContextMode = GLContextMode::Unique, + const optional<std::string> programCacheDir = {}); + ~Renderer(); + + void markContextLost(); + + void setObserver(RendererObserver*); + + void render(const UpdateParameters&); + + // Feature queries + std::vector<Feature> queryRenderedFeatures(const ScreenLineString&, const RenderedQueryOptions& options = {}) const; + std::vector<Feature> queryRenderedFeatures(const ScreenCoordinate& point, const RenderedQueryOptions& options = {}) const; + std::vector<Feature> queryRenderedFeatures(const ScreenBox& box, const RenderedQueryOptions& options = {}) const; + std::vector<Feature> querySourceFeatures(const std::string& sourceID, const SourceQueryOptions& options = {}) const; + AnnotationIDs queryPointAnnotations(const ScreenBox& box) const; + + // Debug + void dumpDebugLogs(); + + // Memory + void onLowMemory(); + +private: + class Impl; + std::unique_ptr<Impl> impl; +}; + +} // namespace mbgl diff --git a/include/mbgl/map/backend.hpp b/include/mbgl/renderer/renderer_backend.hpp index 69a998709b..295838c71b 100644 --- a/include/mbgl/map/backend.hpp +++ b/include/mbgl/renderer/renderer_backend.hpp @@ -1,6 +1,6 @@ #pragma once -#include <mbgl/map/map_observer.hpp> +#include <mbgl/renderer/backend_scope.hpp> #include <mbgl/util/image.hpp> #include <mbgl/util/size.hpp> #include <mbgl/util/util.hpp> @@ -16,12 +16,12 @@ using ProcAddress = void (*)(); using FramebufferID = uint32_t; } // namespace gl -class BackendScope; - -class Backend : public MapObserver { +// The RendererBackend is used by the Renderer to facilitate +// the actual rendering. +class RendererBackend { public: - Backend(); - virtual ~Backend(); + RendererBackend(); + virtual ~RendererBackend(); // Returns the backend's context which manages OpenGL state. gl::Context& getContext(); @@ -29,26 +29,28 @@ public: // Called prior to rendering to update the internally assumed OpenGL state. virtual void updateAssumedState() = 0; - // Called when the map needs to be rendered; the backend should call Map::render() at some point - // in the near future. (Not called for Map::renderStill() mode.) - virtual void invalidate() = 0; + // Called when this backend is used for rendering. Implementations should ensure that a renderable + // object is bound and glClear/glDraw* calls can be done. They should also make sure that + // calling .bind() repeatedly is a no-op and that the appropriate gl::Context values are + // set to the current state. + virtual void bind() = 0; + + virtual Size getFramebufferSize() const = 0; protected: - // Called with the name of an OpenGL extension that should be loaded. Backend implementations + // Called with the name of an OpenGL extension that should be loaded. RendererBackend implementations // must call the API-specific version that obtains the function pointer for this function, // or a null pointer if unsupported/unavailable. virtual gl::ProcAddress initializeExtension(const char*) = 0; // Called when the backend's GL context needs to be made active or inactive. These are called, - // as a matched pair, in four situations: - // - // 1. When releasing GL resources during Map destruction - // 2. When calling a CustomLayerInitializeFunction, during Map::addLayer - // 3. When calling a CustomLayerDeinitializeFunction, during Map::removeLayer - // 4. When rendering for Map::renderStill + // as a matched pair, exclusively through BackendScope, in two situations: // - // They are *not* called for Map::render; it is assumed that the correct context is already - // activated prior to calling Map::render. + // 1. When releasing GL resources during Renderer destruction + // (Including calling CustomLayerDeinitializeFunction during RenderCustomLayer destruction) + // 2. When renderering through Renderer::render() + // (Including calling CustomLayerDeinitializeFunction for newly added custom layers and + // CustomLayerDeinitializeFunction on layer removal) virtual void activate() = 0; virtual void deactivate() = 0; @@ -62,7 +64,8 @@ protected: // Tells the renderer that OpenGL state has already been set by the windowing toolkit. // It sets the internal assumed state to the supplied values. void assumeFramebufferBinding(gl::FramebufferID fbo); - void assumeViewportSize(const Size&); + void assumeViewport(int32_t x, int32_t y, const Size&); + void assumeScissorTest(bool); // Returns true when assumed framebuffer binding hasn't changed from the implicit binding. bool implicitFramebufferBound(); @@ -70,7 +73,8 @@ protected: // Triggers an OpenGL state update if the internal assumed state doesn't match the // supplied values. void setFramebufferBinding(gl::FramebufferID fbo); - void setViewportSize(const Size&); + void setViewport(int32_t x, int32_t y, const Size&); + void setScissorTest(bool); protected: std::unique_ptr<gl::Context> context; @@ -81,7 +85,7 @@ private: friend class BackendScope; }; -constexpr bool operator==(const Backend& a, const Backend& b) { +MBGL_CONSTEXPR bool operator==(const RendererBackend& a, const RendererBackend& b) { return &a == &b; } diff --git a/include/mbgl/renderer/renderer_frontend.hpp b/include/mbgl/renderer/renderer_frontend.hpp new file mode 100644 index 0000000000..f72b0ccdde --- /dev/null +++ b/include/mbgl/renderer/renderer_frontend.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include <memory> + +namespace mbgl { + +class RendererObserver; +class UpdateParameters; + +// The RenderFrontend is the bridge between the Map and +// platform used to update and observer the Renderer +// +// It hides any threading specifics and always replies on +// the original thread. +class RendererFrontend { +public: + + virtual ~RendererFrontend() = default; + + // Must synchronously clean up the Renderer if set + virtual void reset() = 0; + + // Implementer must bind the renderer observer to the renderer in a + // appropriate manner so that the callbacks occur on the main thread + virtual void setObserver(RendererObserver&) = 0; + + // Coalescing updates is up to the implementer + virtual void update(std::shared_ptr<UpdateParameters>) = 0; +}; + +} // namespace mbgl diff --git a/include/mbgl/storage/default_file_source.hpp b/include/mbgl/storage/default_file_source.hpp index f612a01aac..91e442cf85 100644 --- a/include/mbgl/storage/default_file_source.hpp +++ b/include/mbgl/storage/default_file_source.hpp @@ -1,10 +1,13 @@ #pragma once +#include <mbgl/actor/actor_ref.hpp> #include <mbgl/storage/file_source.hpp> #include <mbgl/storage/offline.hpp> #include <mbgl/util/constants.hpp> +#include <mbgl/util/optional.hpp> #include <vector> +#include <mutex> namespace mbgl { @@ -12,6 +15,8 @@ namespace util { template <typename T> class Thread; } // namespace util +class ResourceTransform; + class DefaultFileSource : public FileSource { public: /* @@ -34,12 +39,12 @@ public: } void setAPIBaseURL(const std::string&); - std::string getAPIBaseURL() const; + std::string getAPIBaseURL(); void setAccessToken(const std::string&); - std::string getAccessToken() const; + std::string getAccessToken(); - void setResourceTransform(std::function<std::string(Resource::Kind, std::string&&)>); + void setResourceTransform(optional<ActorRef<ResourceTransform>>&&); std::unique_ptr<AsyncRequest> request(const Resource&, Callback) override; @@ -135,15 +140,20 @@ public: void resume(); // For testing only. + void setOnlineStatus(bool); void put(const Resource&, const Response&); class Impl; private: - const std::unique_ptr<util::Thread<Impl>> thread; - const std::unique_ptr<FileSource> assetFileSource; - const std::unique_ptr<FileSource> localFileSource; + // Shared so destruction is done on this thread + const std::shared_ptr<FileSource> assetFileSource; + const std::unique_ptr<util::Thread<Impl>> impl; + + std::mutex cachedBaseURLMutex; std::string cachedBaseURL = mbgl::util::API_BASE_URL; + + std::mutex cachedAccessTokenMutex; std::string cachedAccessToken; }; diff --git a/include/mbgl/storage/offline.hpp b/include/mbgl/storage/offline.hpp index 818cfe2ba5..117dd0591b 100644 --- a/include/mbgl/storage/offline.hpp +++ b/include/mbgl/storage/offline.hpp @@ -31,12 +31,14 @@ public: /* Private */ std::vector<CanonicalTileID> tileCover(SourceType, uint16_t tileSize, const Range<uint8_t>& zoomRange) const; - + uint64_t tileCount(SourceType, uint16_t tileSize, const Range<uint8_t>& zoomRange) const; const std::string styleURL; const LatLngBounds bounds; const double minZoom; const double maxZoom; const float pixelRatio; +private: + Range<uint8_t> coveringZoomRange(SourceType, uint16_t tileSize, const Range<uint8_t>& zoomRange) const; }; /* diff --git a/include/mbgl/storage/online_file_source.hpp b/include/mbgl/storage/online_file_source.hpp index 51cfc5a2a1..28d70ce544 100644 --- a/include/mbgl/storage/online_file_source.hpp +++ b/include/mbgl/storage/online_file_source.hpp @@ -1,10 +1,14 @@ #pragma once +#include <mbgl/actor/actor_ref.hpp> #include <mbgl/storage/file_source.hpp> #include <mbgl/util/constants.hpp> +#include <mbgl/util/optional.hpp> namespace mbgl { +class ResourceTransform; + class OnlineFileSource : public FileSource { public: OnlineFileSource(); @@ -16,12 +20,13 @@ public: void setAccessToken(const std::string& t) { accessToken = t; } std::string getAccessToken() const { return accessToken; } - using ResourceTransform = - std::function<std::unique_ptr<AsyncRequest>(Resource::Kind, std::string&&, std::function<void(std::string&&)>)>; - void setResourceTransform(ResourceTransform&& cb); + void setResourceTransform(optional<ActorRef<ResourceTransform>>&&); std::unique_ptr<AsyncRequest> request(const Resource&, Callback) override; + // For testing only. + void setOnlineStatus(bool); + private: friend class OnlineFileRequest; diff --git a/include/mbgl/storage/resource.hpp b/include/mbgl/storage/resource.hpp index c05f40b65c..5d44f4869f 100644 --- a/include/mbgl/storage/resource.hpp +++ b/include/mbgl/storage/resource.hpp @@ -18,7 +18,8 @@ public: Tile, Glyphs, SpriteImage, - SpriteJSON + SpriteJSON, + Image }; struct TileData { @@ -55,7 +56,8 @@ public: const std::pair<uint16_t, uint16_t>& glyphRange); static Resource spriteImage(const std::string& base, float pixelRatio); static Resource spriteJSON(const std::string& base, float pixelRatio); - + static Resource image(const std::string& url); + Kind kind; Necessity necessity; std::string url; @@ -66,6 +68,7 @@ public: optional<Timestamp> priorModified = {}; optional<Timestamp> priorExpires = {}; optional<std::string> priorEtag = {}; + std::shared_ptr<const std::string> priorData; }; } // namespace mbgl diff --git a/include/mbgl/storage/resource_transform.hpp b/include/mbgl/storage/resource_transform.hpp new file mode 100644 index 0000000000..738c497176 --- /dev/null +++ b/include/mbgl/storage/resource_transform.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include <mbgl/actor/actor_ref.hpp> +#include <mbgl/storage/resource.hpp> + +#include <functional> +#include <string> + +namespace mbgl { + +class Mailbox; + +class ResourceTransform { +public: + using TransformCallback = std::function<std::string(Resource::Kind kind, const std::string&& url)>; + using FinishedCallback = std::function<void(const std::string&&)>; + + ResourceTransform(ActorRef<ResourceTransform>, TransformCallback&&); + + void transform(Resource::Kind, const std::string&& url, FinishedCallback&&); + +private: + TransformCallback transformCallback; +}; + +} // namespace mbgl diff --git a/include/mbgl/storage/response.hpp b/include/mbgl/storage/response.hpp index 32fe4e0c8a..711f008e83 100644 --- a/include/mbgl/storage/response.hpp +++ b/include/mbgl/storage/response.hpp @@ -27,6 +27,10 @@ public: // This is set to true for 304 Not Modified responses. bool notModified = false; + // This is set to true when the server requested that no expired resources be used by + // specifying "Cache-Control: must-revalidate". + bool mustRevalidate = false; + // The actual data of the response. Present only for non-error, non-notModified responses. std::shared_ptr<const std::string> data; @@ -37,6 +41,12 @@ public: bool isFresh() const { return expires ? *expires > util::now() : !error; } + + // Indicates whether we are allowed to use this response according to HTTP caching rules. + // It may or may not be stale. + bool isUsable() const { + return !mustRevalidate || (expires && *expires > util::now()); + } }; class Response::Error { diff --git a/include/mbgl/style/conversion.hpp b/include/mbgl/style/conversion.hpp index d6fb3a6dd0..27504a89b1 100644 --- a/include/mbgl/style/conversion.hpp +++ b/include/mbgl/style/conversion.hpp @@ -46,6 +46,7 @@ namespace conversion { * `toBool(v)` -- returns `optional<bool>`, absence indicating `v` is not a JSON boolean * `toNumber(v)` -- returns `optional<float>`, absence indicating `v` is not a JSON number + * `toDouble(v)` -- returns `optional<double>`, absence indicating `v` is not a JSON number * `toString(v)` -- returns `optional<std::string>`, absence indicating `v` is not a JSON string * `toValue(v)` -- returns `optional<mbgl::Value>`, a variant type, for generic conversion, absence indicating `v` is not a boolean, number, or string. Numbers should be converted to diff --git a/include/mbgl/style/conversion/coordinate.hpp b/include/mbgl/style/conversion/coordinate.hpp new file mode 100644 index 0000000000..732624e77f --- /dev/null +++ b/include/mbgl/style/conversion/coordinate.hpp @@ -0,0 +1,37 @@ +#pragma once + +#include <mbgl/style/conversion.hpp> +#include <mbgl/util/geo.hpp> + +namespace mbgl { +namespace style { +namespace conversion { + +template<> +struct Converter<LatLng> { +public: + template <class V> + optional<LatLng> operator() (const V& value, Error& error) const { + if (!isArray(value) || arrayLength(value) < 2 ) { + error = { "coordinate array must contain numeric longitude and latitude values" }; + return {}; + } + //Style spec uses GeoJSON convention for specifying coordinates + optional<double> latitude = toDouble(arrayMember(value, 1)); + optional<double> longitude = toDouble(arrayMember(value, 0)); + + if (!latitude || !longitude) { + error = { "coordinate array must contain numeric longitude and latitude values" }; + return {}; + } + if (*latitude < -90 || *latitude > 90 ){ + error = { "coordinate latitude must be between -90 and 90" }; + return {}; + } + return LatLng(*latitude, *longitude); + } +}; + +} // namespace conversion +} // namespace style +} // namespace mbgl diff --git a/include/mbgl/style/conversion/filter.hpp b/include/mbgl/style/conversion/filter.hpp index 1f8f0fd161..986d1bf80d 100644 --- a/include/mbgl/style/conversion/filter.hpp +++ b/include/mbgl/style/conversion/filter.hpp @@ -57,7 +57,7 @@ public: return convertUnaryFilter<NotHasFilter, NotHasIdentifierFilter>(value, error); } - error = { "filter operator must be one of \"==\", \"!=\", \">\", \">=\", \"<\", \"<=\", \"in\", \"!in\", \"all\", \"any\", \"none\", \"has\", or \"!has\"" }; + error = { R"(filter operator must be one of "==", "!=", ">", ">=", "<", "<=", "in", "!in", "all", "any", "none", "has", or "!has")" }; return {}; } diff --git a/include/mbgl/style/conversion/function.hpp b/include/mbgl/style/conversion/function.hpp index fa8af1e2be..752b6dd045 100644 --- a/include/mbgl/style/conversion/function.hpp +++ b/include/mbgl/style/conversion/function.hpp @@ -156,7 +156,7 @@ struct StopsConverter<T, variant<Ts...>> { public: template <class V> optional<variant<Ts...>> operator()(const V& value, Error& error) const { - std::string type = util::Interpolatable<T> ? "exponential" : "interval"; + std::string type = util::Interpolatable<T>::value ? "exponential" : "interval"; auto typeValue = objectMember(value, "type"); if (typeValue && toString(*typeValue)) { @@ -218,7 +218,7 @@ optional<optional<T>> convertDefaultValue(const V& value, Error& error) { auto defaultValue = convert<T>(*defaultValueValue, error); if (!defaultValue) { - error = { "wrong type for \"default\": " + error.message }; + error = { R"(wrong type for "default": )" + error.message }; return {}; } diff --git a/include/mbgl/style/conversion/layer.hpp b/include/mbgl/style/conversion/layer.hpp index 3a64c36bf5..1fe467165d 100644 --- a/include/mbgl/style/conversion/layer.hpp +++ b/include/mbgl/style/conversion/layer.hpp @@ -28,30 +28,23 @@ optional<Error> setLayoutProperty(Layer& layer, const std::string& name, const V } template <class V> -optional<Error> setPaintProperty(Layer& layer, const std::string& name, const V& value, const optional<std::string>& klass) { +optional<Error> setPaintProperty(Layer& layer, const std::string& name, const V& value) { static const auto setters = makePaintPropertySetters<V>(); auto it = setters.find(name); if (it == setters.end()) { return Error { "property not found" }; } - return it->second(layer, value, klass); + return it->second(layer, value); } template <class V> optional<Error> setPaintProperties(Layer& layer, const V& value) { - return eachMember(value, [&] (const std::string& paintName, const V& paintValue) -> optional<Error> { - if (paintName.compare(0, 5, "paint") != 0) { - return {}; - } - - optional<std::string> klass; - if (paintName.compare(0, 6, "paint.") == 0) { - klass = paintName.substr(6); - } - - return eachMember(paintValue, [&] (const std::string& k, const V& v) { - return setPaintProperty(layer, k, v, klass); - }); + auto paintValue = objectMember(value, "paint"); + if (!paintValue) { + return {}; + } + return eachMember(*paintValue, [&] (const std::string& k, const V& v) { + return setPaintProperty(layer, k, v); }); } diff --git a/include/mbgl/style/conversion/make_property_setters.hpp b/include/mbgl/style/conversion/make_property_setters.hpp index 105cca99d6..59b0e7be32 100644 --- a/include/mbgl/style/conversion/make_property_setters.hpp +++ b/include/mbgl/style/conversion/make_property_setters.hpp @@ -20,50 +20,52 @@ namespace conversion { template <class V> auto makeLayoutPropertySetters() { - std::unordered_map<std::string, LayoutPropertySetter<V>> result; + std::unordered_map<std::string, PropertySetter<V>> result; result["visibility"] = &setVisibility<V>; - result["line-cap"] = &setLayoutProperty<V, LineLayer, PropertyValue<LineCapType>, &LineLayer::setLineCap>; - result["line-join"] = &setLayoutProperty<V, LineLayer, PropertyValue<LineJoinType>, &LineLayer::setLineJoin>; - result["line-miter-limit"] = &setLayoutProperty<V, LineLayer, PropertyValue<float>, &LineLayer::setLineMiterLimit>; - result["line-round-limit"] = &setLayoutProperty<V, LineLayer, PropertyValue<float>, &LineLayer::setLineRoundLimit>; - - result["symbol-placement"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<SymbolPlacementType>, &SymbolLayer::setSymbolPlacement>; - result["symbol-spacing"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<float>, &SymbolLayer::setSymbolSpacing>; - result["symbol-avoid-edges"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<bool>, &SymbolLayer::setSymbolAvoidEdges>; - result["icon-allow-overlap"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<bool>, &SymbolLayer::setIconAllowOverlap>; - result["icon-ignore-placement"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<bool>, &SymbolLayer::setIconIgnorePlacement>; - result["icon-optional"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<bool>, &SymbolLayer::setIconOptional>; - result["icon-rotation-alignment"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<AlignmentType>, &SymbolLayer::setIconRotationAlignment>; - result["icon-size"] = &setLayoutProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setIconSize>; - result["icon-text-fit"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<IconTextFitType>, &SymbolLayer::setIconTextFit>; - result["icon-text-fit-padding"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<std::array<float, 4>>, &SymbolLayer::setIconTextFitPadding>; - result["icon-image"] = &setLayoutProperty<V, SymbolLayer, DataDrivenPropertyValue<std::string>, &SymbolLayer::setIconImage>; - result["icon-rotate"] = &setLayoutProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setIconRotate>; - result["icon-padding"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<float>, &SymbolLayer::setIconPadding>; - result["icon-keep-upright"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<bool>, &SymbolLayer::setIconKeepUpright>; - result["icon-offset"] = &setLayoutProperty<V, SymbolLayer, DataDrivenPropertyValue<std::array<float, 2>>, &SymbolLayer::setIconOffset>; - result["text-pitch-alignment"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<AlignmentType>, &SymbolLayer::setTextPitchAlignment>; - result["text-rotation-alignment"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<AlignmentType>, &SymbolLayer::setTextRotationAlignment>; - result["text-field"] = &setLayoutProperty<V, SymbolLayer, DataDrivenPropertyValue<std::string>, &SymbolLayer::setTextField>; - result["text-font"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<std::vector<std::string>>, &SymbolLayer::setTextFont>; - result["text-size"] = &setLayoutProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setTextSize>; - result["text-max-width"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<float>, &SymbolLayer::setTextMaxWidth>; - result["text-line-height"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<float>, &SymbolLayer::setTextLineHeight>; - result["text-letter-spacing"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<float>, &SymbolLayer::setTextLetterSpacing>; - result["text-justify"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<TextJustifyType>, &SymbolLayer::setTextJustify>; - result["text-anchor"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<TextAnchorType>, &SymbolLayer::setTextAnchor>; - result["text-max-angle"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<float>, &SymbolLayer::setTextMaxAngle>; - result["text-rotate"] = &setLayoutProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setTextRotate>; - result["text-padding"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<float>, &SymbolLayer::setTextPadding>; - result["text-keep-upright"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<bool>, &SymbolLayer::setTextKeepUpright>; - result["text-transform"] = &setLayoutProperty<V, SymbolLayer, DataDrivenPropertyValue<TextTransformType>, &SymbolLayer::setTextTransform>; - result["text-offset"] = &setLayoutProperty<V, SymbolLayer, DataDrivenPropertyValue<std::array<float, 2>>, &SymbolLayer::setTextOffset>; - result["text-allow-overlap"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<bool>, &SymbolLayer::setTextAllowOverlap>; - result["text-ignore-placement"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<bool>, &SymbolLayer::setTextIgnorePlacement>; - result["text-optional"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<bool>, &SymbolLayer::setTextOptional>; + result["line-cap"] = &setProperty<V, LineLayer, PropertyValue<LineCapType>, &LineLayer::setLineCap>; + result["line-join"] = &setProperty<V, LineLayer, DataDrivenPropertyValue<LineJoinType>, &LineLayer::setLineJoin>; + result["line-miter-limit"] = &setProperty<V, LineLayer, PropertyValue<float>, &LineLayer::setLineMiterLimit>; + result["line-round-limit"] = &setProperty<V, LineLayer, PropertyValue<float>, &LineLayer::setLineRoundLimit>; + + result["symbol-placement"] = &setProperty<V, SymbolLayer, PropertyValue<SymbolPlacementType>, &SymbolLayer::setSymbolPlacement>; + result["symbol-spacing"] = &setProperty<V, SymbolLayer, PropertyValue<float>, &SymbolLayer::setSymbolSpacing>; + result["symbol-avoid-edges"] = &setProperty<V, SymbolLayer, PropertyValue<bool>, &SymbolLayer::setSymbolAvoidEdges>; + result["icon-allow-overlap"] = &setProperty<V, SymbolLayer, PropertyValue<bool>, &SymbolLayer::setIconAllowOverlap>; + result["icon-ignore-placement"] = &setProperty<V, SymbolLayer, PropertyValue<bool>, &SymbolLayer::setIconIgnorePlacement>; + result["icon-optional"] = &setProperty<V, SymbolLayer, PropertyValue<bool>, &SymbolLayer::setIconOptional>; + result["icon-rotation-alignment"] = &setProperty<V, SymbolLayer, PropertyValue<AlignmentType>, &SymbolLayer::setIconRotationAlignment>; + result["icon-size"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setIconSize>; + result["icon-text-fit"] = &setProperty<V, SymbolLayer, PropertyValue<IconTextFitType>, &SymbolLayer::setIconTextFit>; + result["icon-text-fit-padding"] = &setProperty<V, SymbolLayer, PropertyValue<std::array<float, 4>>, &SymbolLayer::setIconTextFitPadding>; + result["icon-image"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<std::string>, &SymbolLayer::setIconImage>; + result["icon-rotate"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setIconRotate>; + result["icon-padding"] = &setProperty<V, SymbolLayer, PropertyValue<float>, &SymbolLayer::setIconPadding>; + result["icon-keep-upright"] = &setProperty<V, SymbolLayer, PropertyValue<bool>, &SymbolLayer::setIconKeepUpright>; + result["icon-offset"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<std::array<float, 2>>, &SymbolLayer::setIconOffset>; + result["icon-anchor"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<SymbolAnchorType>, &SymbolLayer::setIconAnchor>; + result["icon-pitch-alignment"] = &setProperty<V, SymbolLayer, PropertyValue<AlignmentType>, &SymbolLayer::setIconPitchAlignment>; + result["text-pitch-alignment"] = &setProperty<V, SymbolLayer, PropertyValue<AlignmentType>, &SymbolLayer::setTextPitchAlignment>; + result["text-rotation-alignment"] = &setProperty<V, SymbolLayer, PropertyValue<AlignmentType>, &SymbolLayer::setTextRotationAlignment>; + result["text-field"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<std::string>, &SymbolLayer::setTextField>; + result["text-font"] = &setProperty<V, SymbolLayer, PropertyValue<std::vector<std::string>>, &SymbolLayer::setTextFont>; + result["text-size"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setTextSize>; + result["text-max-width"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setTextMaxWidth>; + result["text-line-height"] = &setProperty<V, SymbolLayer, PropertyValue<float>, &SymbolLayer::setTextLineHeight>; + result["text-letter-spacing"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setTextLetterSpacing>; + result["text-justify"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<TextJustifyType>, &SymbolLayer::setTextJustify>; + result["text-anchor"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<SymbolAnchorType>, &SymbolLayer::setTextAnchor>; + result["text-max-angle"] = &setProperty<V, SymbolLayer, PropertyValue<float>, &SymbolLayer::setTextMaxAngle>; + result["text-rotate"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setTextRotate>; + result["text-padding"] = &setProperty<V, SymbolLayer, PropertyValue<float>, &SymbolLayer::setTextPadding>; + result["text-keep-upright"] = &setProperty<V, SymbolLayer, PropertyValue<bool>, &SymbolLayer::setTextKeepUpright>; + result["text-transform"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<TextTransformType>, &SymbolLayer::setTextTransform>; + result["text-offset"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<std::array<float, 2>>, &SymbolLayer::setTextOffset>; + result["text-allow-overlap"] = &setProperty<V, SymbolLayer, PropertyValue<bool>, &SymbolLayer::setTextAllowOverlap>; + result["text-ignore-placement"] = &setProperty<V, SymbolLayer, PropertyValue<bool>, &SymbolLayer::setTextIgnorePlacement>; + result["text-optional"] = &setProperty<V, SymbolLayer, PropertyValue<bool>, &SymbolLayer::setTextOptional>; @@ -74,129 +76,131 @@ auto makeLayoutPropertySetters() { template <class V> auto makePaintPropertySetters() { - std::unordered_map<std::string, PaintPropertySetter<V>> result; + std::unordered_map<std::string, PropertySetter<V>> result; - result["fill-antialias"] = &setPaintProperty<V, FillLayer, PropertyValue<bool>, &FillLayer::setFillAntialias>; + result["fill-antialias"] = &setProperty<V, FillLayer, PropertyValue<bool>, &FillLayer::setFillAntialias>; result["fill-antialias-transition"] = &setTransition<V, FillLayer, &FillLayer::setFillAntialiasTransition>; - result["fill-opacity"] = &setPaintProperty<V, FillLayer, DataDrivenPropertyValue<float>, &FillLayer::setFillOpacity>; + result["fill-opacity"] = &setProperty<V, FillLayer, DataDrivenPropertyValue<float>, &FillLayer::setFillOpacity>; result["fill-opacity-transition"] = &setTransition<V, FillLayer, &FillLayer::setFillOpacityTransition>; - result["fill-color"] = &setPaintProperty<V, FillLayer, DataDrivenPropertyValue<Color>, &FillLayer::setFillColor>; + result["fill-color"] = &setProperty<V, FillLayer, DataDrivenPropertyValue<Color>, &FillLayer::setFillColor>; result["fill-color-transition"] = &setTransition<V, FillLayer, &FillLayer::setFillColorTransition>; - result["fill-outline-color"] = &setPaintProperty<V, FillLayer, DataDrivenPropertyValue<Color>, &FillLayer::setFillOutlineColor>; + result["fill-outline-color"] = &setProperty<V, FillLayer, DataDrivenPropertyValue<Color>, &FillLayer::setFillOutlineColor>; result["fill-outline-color-transition"] = &setTransition<V, FillLayer, &FillLayer::setFillOutlineColorTransition>; - result["fill-translate"] = &setPaintProperty<V, FillLayer, PropertyValue<std::array<float, 2>>, &FillLayer::setFillTranslate>; + result["fill-translate"] = &setProperty<V, FillLayer, PropertyValue<std::array<float, 2>>, &FillLayer::setFillTranslate>; result["fill-translate-transition"] = &setTransition<V, FillLayer, &FillLayer::setFillTranslateTransition>; - result["fill-translate-anchor"] = &setPaintProperty<V, FillLayer, PropertyValue<TranslateAnchorType>, &FillLayer::setFillTranslateAnchor>; + result["fill-translate-anchor"] = &setProperty<V, FillLayer, PropertyValue<TranslateAnchorType>, &FillLayer::setFillTranslateAnchor>; result["fill-translate-anchor-transition"] = &setTransition<V, FillLayer, &FillLayer::setFillTranslateAnchorTransition>; - result["fill-pattern"] = &setPaintProperty<V, FillLayer, PropertyValue<std::string>, &FillLayer::setFillPattern>; + result["fill-pattern"] = &setProperty<V, FillLayer, PropertyValue<std::string>, &FillLayer::setFillPattern>; result["fill-pattern-transition"] = &setTransition<V, FillLayer, &FillLayer::setFillPatternTransition>; - result["line-opacity"] = &setPaintProperty<V, LineLayer, DataDrivenPropertyValue<float>, &LineLayer::setLineOpacity>; + result["line-opacity"] = &setProperty<V, LineLayer, DataDrivenPropertyValue<float>, &LineLayer::setLineOpacity>; result["line-opacity-transition"] = &setTransition<V, LineLayer, &LineLayer::setLineOpacityTransition>; - result["line-color"] = &setPaintProperty<V, LineLayer, DataDrivenPropertyValue<Color>, &LineLayer::setLineColor>; + result["line-color"] = &setProperty<V, LineLayer, DataDrivenPropertyValue<Color>, &LineLayer::setLineColor>; result["line-color-transition"] = &setTransition<V, LineLayer, &LineLayer::setLineColorTransition>; - result["line-translate"] = &setPaintProperty<V, LineLayer, PropertyValue<std::array<float, 2>>, &LineLayer::setLineTranslate>; + result["line-translate"] = &setProperty<V, LineLayer, PropertyValue<std::array<float, 2>>, &LineLayer::setLineTranslate>; result["line-translate-transition"] = &setTransition<V, LineLayer, &LineLayer::setLineTranslateTransition>; - result["line-translate-anchor"] = &setPaintProperty<V, LineLayer, PropertyValue<TranslateAnchorType>, &LineLayer::setLineTranslateAnchor>; + result["line-translate-anchor"] = &setProperty<V, LineLayer, PropertyValue<TranslateAnchorType>, &LineLayer::setLineTranslateAnchor>; result["line-translate-anchor-transition"] = &setTransition<V, LineLayer, &LineLayer::setLineTranslateAnchorTransition>; - result["line-width"] = &setPaintProperty<V, LineLayer, PropertyValue<float>, &LineLayer::setLineWidth>; + result["line-width"] = &setProperty<V, LineLayer, DataDrivenPropertyValue<float>, &LineLayer::setLineWidth>; result["line-width-transition"] = &setTransition<V, LineLayer, &LineLayer::setLineWidthTransition>; - result["line-gap-width"] = &setPaintProperty<V, LineLayer, DataDrivenPropertyValue<float>, &LineLayer::setLineGapWidth>; + result["line-gap-width"] = &setProperty<V, LineLayer, DataDrivenPropertyValue<float>, &LineLayer::setLineGapWidth>; result["line-gap-width-transition"] = &setTransition<V, LineLayer, &LineLayer::setLineGapWidthTransition>; - result["line-offset"] = &setPaintProperty<V, LineLayer, DataDrivenPropertyValue<float>, &LineLayer::setLineOffset>; + result["line-offset"] = &setProperty<V, LineLayer, DataDrivenPropertyValue<float>, &LineLayer::setLineOffset>; result["line-offset-transition"] = &setTransition<V, LineLayer, &LineLayer::setLineOffsetTransition>; - result["line-blur"] = &setPaintProperty<V, LineLayer, DataDrivenPropertyValue<float>, &LineLayer::setLineBlur>; + result["line-blur"] = &setProperty<V, LineLayer, DataDrivenPropertyValue<float>, &LineLayer::setLineBlur>; result["line-blur-transition"] = &setTransition<V, LineLayer, &LineLayer::setLineBlurTransition>; - result["line-dasharray"] = &setPaintProperty<V, LineLayer, PropertyValue<std::vector<float>>, &LineLayer::setLineDasharray>; + result["line-dasharray"] = &setProperty<V, LineLayer, PropertyValue<std::vector<float>>, &LineLayer::setLineDasharray>; result["line-dasharray-transition"] = &setTransition<V, LineLayer, &LineLayer::setLineDasharrayTransition>; - result["line-pattern"] = &setPaintProperty<V, LineLayer, PropertyValue<std::string>, &LineLayer::setLinePattern>; + result["line-pattern"] = &setProperty<V, LineLayer, PropertyValue<std::string>, &LineLayer::setLinePattern>; result["line-pattern-transition"] = &setTransition<V, LineLayer, &LineLayer::setLinePatternTransition>; - result["icon-opacity"] = &setPaintProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setIconOpacity>; + result["icon-opacity"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setIconOpacity>; result["icon-opacity-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setIconOpacityTransition>; - result["icon-color"] = &setPaintProperty<V, SymbolLayer, DataDrivenPropertyValue<Color>, &SymbolLayer::setIconColor>; + result["icon-color"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<Color>, &SymbolLayer::setIconColor>; result["icon-color-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setIconColorTransition>; - result["icon-halo-color"] = &setPaintProperty<V, SymbolLayer, DataDrivenPropertyValue<Color>, &SymbolLayer::setIconHaloColor>; + result["icon-halo-color"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<Color>, &SymbolLayer::setIconHaloColor>; result["icon-halo-color-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setIconHaloColorTransition>; - result["icon-halo-width"] = &setPaintProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setIconHaloWidth>; + result["icon-halo-width"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setIconHaloWidth>; result["icon-halo-width-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setIconHaloWidthTransition>; - result["icon-halo-blur"] = &setPaintProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setIconHaloBlur>; + result["icon-halo-blur"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setIconHaloBlur>; result["icon-halo-blur-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setIconHaloBlurTransition>; - result["icon-translate"] = &setPaintProperty<V, SymbolLayer, PropertyValue<std::array<float, 2>>, &SymbolLayer::setIconTranslate>; + result["icon-translate"] = &setProperty<V, SymbolLayer, PropertyValue<std::array<float, 2>>, &SymbolLayer::setIconTranslate>; result["icon-translate-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setIconTranslateTransition>; - result["icon-translate-anchor"] = &setPaintProperty<V, SymbolLayer, PropertyValue<TranslateAnchorType>, &SymbolLayer::setIconTranslateAnchor>; + result["icon-translate-anchor"] = &setProperty<V, SymbolLayer, PropertyValue<TranslateAnchorType>, &SymbolLayer::setIconTranslateAnchor>; result["icon-translate-anchor-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setIconTranslateAnchorTransition>; - result["text-opacity"] = &setPaintProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setTextOpacity>; + result["text-opacity"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setTextOpacity>; result["text-opacity-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setTextOpacityTransition>; - result["text-color"] = &setPaintProperty<V, SymbolLayer, DataDrivenPropertyValue<Color>, &SymbolLayer::setTextColor>; + result["text-color"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<Color>, &SymbolLayer::setTextColor>; result["text-color-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setTextColorTransition>; - result["text-halo-color"] = &setPaintProperty<V, SymbolLayer, DataDrivenPropertyValue<Color>, &SymbolLayer::setTextHaloColor>; + result["text-halo-color"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<Color>, &SymbolLayer::setTextHaloColor>; result["text-halo-color-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setTextHaloColorTransition>; - result["text-halo-width"] = &setPaintProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setTextHaloWidth>; + result["text-halo-width"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setTextHaloWidth>; result["text-halo-width-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setTextHaloWidthTransition>; - result["text-halo-blur"] = &setPaintProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setTextHaloBlur>; + result["text-halo-blur"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setTextHaloBlur>; result["text-halo-blur-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setTextHaloBlurTransition>; - result["text-translate"] = &setPaintProperty<V, SymbolLayer, PropertyValue<std::array<float, 2>>, &SymbolLayer::setTextTranslate>; + result["text-translate"] = &setProperty<V, SymbolLayer, PropertyValue<std::array<float, 2>>, &SymbolLayer::setTextTranslate>; result["text-translate-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setTextTranslateTransition>; - result["text-translate-anchor"] = &setPaintProperty<V, SymbolLayer, PropertyValue<TranslateAnchorType>, &SymbolLayer::setTextTranslateAnchor>; + result["text-translate-anchor"] = &setProperty<V, SymbolLayer, PropertyValue<TranslateAnchorType>, &SymbolLayer::setTextTranslateAnchor>; result["text-translate-anchor-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setTextTranslateAnchorTransition>; - result["circle-radius"] = &setPaintProperty<V, CircleLayer, DataDrivenPropertyValue<float>, &CircleLayer::setCircleRadius>; + result["circle-radius"] = &setProperty<V, CircleLayer, DataDrivenPropertyValue<float>, &CircleLayer::setCircleRadius>; result["circle-radius-transition"] = &setTransition<V, CircleLayer, &CircleLayer::setCircleRadiusTransition>; - result["circle-color"] = &setPaintProperty<V, CircleLayer, DataDrivenPropertyValue<Color>, &CircleLayer::setCircleColor>; + result["circle-color"] = &setProperty<V, CircleLayer, DataDrivenPropertyValue<Color>, &CircleLayer::setCircleColor>; result["circle-color-transition"] = &setTransition<V, CircleLayer, &CircleLayer::setCircleColorTransition>; - result["circle-blur"] = &setPaintProperty<V, CircleLayer, DataDrivenPropertyValue<float>, &CircleLayer::setCircleBlur>; + result["circle-blur"] = &setProperty<V, CircleLayer, DataDrivenPropertyValue<float>, &CircleLayer::setCircleBlur>; result["circle-blur-transition"] = &setTransition<V, CircleLayer, &CircleLayer::setCircleBlurTransition>; - result["circle-opacity"] = &setPaintProperty<V, CircleLayer, DataDrivenPropertyValue<float>, &CircleLayer::setCircleOpacity>; + result["circle-opacity"] = &setProperty<V, CircleLayer, DataDrivenPropertyValue<float>, &CircleLayer::setCircleOpacity>; result["circle-opacity-transition"] = &setTransition<V, CircleLayer, &CircleLayer::setCircleOpacityTransition>; - result["circle-translate"] = &setPaintProperty<V, CircleLayer, PropertyValue<std::array<float, 2>>, &CircleLayer::setCircleTranslate>; + result["circle-translate"] = &setProperty<V, CircleLayer, PropertyValue<std::array<float, 2>>, &CircleLayer::setCircleTranslate>; result["circle-translate-transition"] = &setTransition<V, CircleLayer, &CircleLayer::setCircleTranslateTransition>; - result["circle-translate-anchor"] = &setPaintProperty<V, CircleLayer, PropertyValue<TranslateAnchorType>, &CircleLayer::setCircleTranslateAnchor>; + result["circle-translate-anchor"] = &setProperty<V, CircleLayer, PropertyValue<TranslateAnchorType>, &CircleLayer::setCircleTranslateAnchor>; result["circle-translate-anchor-transition"] = &setTransition<V, CircleLayer, &CircleLayer::setCircleTranslateAnchorTransition>; - result["circle-pitch-scale"] = &setPaintProperty<V, CircleLayer, PropertyValue<CirclePitchScaleType>, &CircleLayer::setCirclePitchScale>; + result["circle-pitch-scale"] = &setProperty<V, CircleLayer, PropertyValue<CirclePitchScaleType>, &CircleLayer::setCirclePitchScale>; result["circle-pitch-scale-transition"] = &setTransition<V, CircleLayer, &CircleLayer::setCirclePitchScaleTransition>; - result["circle-stroke-width"] = &setPaintProperty<V, CircleLayer, DataDrivenPropertyValue<float>, &CircleLayer::setCircleStrokeWidth>; + result["circle-pitch-alignment"] = &setProperty<V, CircleLayer, PropertyValue<AlignmentType>, &CircleLayer::setCirclePitchAlignment>; + result["circle-pitch-alignment-transition"] = &setTransition<V, CircleLayer, &CircleLayer::setCirclePitchAlignmentTransition>; + result["circle-stroke-width"] = &setProperty<V, CircleLayer, DataDrivenPropertyValue<float>, &CircleLayer::setCircleStrokeWidth>; result["circle-stroke-width-transition"] = &setTransition<V, CircleLayer, &CircleLayer::setCircleStrokeWidthTransition>; - result["circle-stroke-color"] = &setPaintProperty<V, CircleLayer, DataDrivenPropertyValue<Color>, &CircleLayer::setCircleStrokeColor>; + result["circle-stroke-color"] = &setProperty<V, CircleLayer, DataDrivenPropertyValue<Color>, &CircleLayer::setCircleStrokeColor>; result["circle-stroke-color-transition"] = &setTransition<V, CircleLayer, &CircleLayer::setCircleStrokeColorTransition>; - result["circle-stroke-opacity"] = &setPaintProperty<V, CircleLayer, DataDrivenPropertyValue<float>, &CircleLayer::setCircleStrokeOpacity>; + result["circle-stroke-opacity"] = &setProperty<V, CircleLayer, DataDrivenPropertyValue<float>, &CircleLayer::setCircleStrokeOpacity>; result["circle-stroke-opacity-transition"] = &setTransition<V, CircleLayer, &CircleLayer::setCircleStrokeOpacityTransition>; - result["fill-extrusion-opacity"] = &setPaintProperty<V, FillExtrusionLayer, PropertyValue<float>, &FillExtrusionLayer::setFillExtrusionOpacity>; + result["fill-extrusion-opacity"] = &setProperty<V, FillExtrusionLayer, PropertyValue<float>, &FillExtrusionLayer::setFillExtrusionOpacity>; result["fill-extrusion-opacity-transition"] = &setTransition<V, FillExtrusionLayer, &FillExtrusionLayer::setFillExtrusionOpacityTransition>; - result["fill-extrusion-color"] = &setPaintProperty<V, FillExtrusionLayer, DataDrivenPropertyValue<Color>, &FillExtrusionLayer::setFillExtrusionColor>; + result["fill-extrusion-color"] = &setProperty<V, FillExtrusionLayer, DataDrivenPropertyValue<Color>, &FillExtrusionLayer::setFillExtrusionColor>; result["fill-extrusion-color-transition"] = &setTransition<V, FillExtrusionLayer, &FillExtrusionLayer::setFillExtrusionColorTransition>; - result["fill-extrusion-translate"] = &setPaintProperty<V, FillExtrusionLayer, PropertyValue<std::array<float, 2>>, &FillExtrusionLayer::setFillExtrusionTranslate>; + result["fill-extrusion-translate"] = &setProperty<V, FillExtrusionLayer, PropertyValue<std::array<float, 2>>, &FillExtrusionLayer::setFillExtrusionTranslate>; result["fill-extrusion-translate-transition"] = &setTransition<V, FillExtrusionLayer, &FillExtrusionLayer::setFillExtrusionTranslateTransition>; - result["fill-extrusion-translate-anchor"] = &setPaintProperty<V, FillExtrusionLayer, PropertyValue<TranslateAnchorType>, &FillExtrusionLayer::setFillExtrusionTranslateAnchor>; + result["fill-extrusion-translate-anchor"] = &setProperty<V, FillExtrusionLayer, PropertyValue<TranslateAnchorType>, &FillExtrusionLayer::setFillExtrusionTranslateAnchor>; result["fill-extrusion-translate-anchor-transition"] = &setTransition<V, FillExtrusionLayer, &FillExtrusionLayer::setFillExtrusionTranslateAnchorTransition>; - result["fill-extrusion-pattern"] = &setPaintProperty<V, FillExtrusionLayer, PropertyValue<std::string>, &FillExtrusionLayer::setFillExtrusionPattern>; + result["fill-extrusion-pattern"] = &setProperty<V, FillExtrusionLayer, PropertyValue<std::string>, &FillExtrusionLayer::setFillExtrusionPattern>; result["fill-extrusion-pattern-transition"] = &setTransition<V, FillExtrusionLayer, &FillExtrusionLayer::setFillExtrusionPatternTransition>; - result["fill-extrusion-height"] = &setPaintProperty<V, FillExtrusionLayer, DataDrivenPropertyValue<float>, &FillExtrusionLayer::setFillExtrusionHeight>; + result["fill-extrusion-height"] = &setProperty<V, FillExtrusionLayer, DataDrivenPropertyValue<float>, &FillExtrusionLayer::setFillExtrusionHeight>; result["fill-extrusion-height-transition"] = &setTransition<V, FillExtrusionLayer, &FillExtrusionLayer::setFillExtrusionHeightTransition>; - result["fill-extrusion-base"] = &setPaintProperty<V, FillExtrusionLayer, DataDrivenPropertyValue<float>, &FillExtrusionLayer::setFillExtrusionBase>; + result["fill-extrusion-base"] = &setProperty<V, FillExtrusionLayer, DataDrivenPropertyValue<float>, &FillExtrusionLayer::setFillExtrusionBase>; result["fill-extrusion-base-transition"] = &setTransition<V, FillExtrusionLayer, &FillExtrusionLayer::setFillExtrusionBaseTransition>; - result["raster-opacity"] = &setPaintProperty<V, RasterLayer, PropertyValue<float>, &RasterLayer::setRasterOpacity>; + result["raster-opacity"] = &setProperty<V, RasterLayer, PropertyValue<float>, &RasterLayer::setRasterOpacity>; result["raster-opacity-transition"] = &setTransition<V, RasterLayer, &RasterLayer::setRasterOpacityTransition>; - result["raster-hue-rotate"] = &setPaintProperty<V, RasterLayer, PropertyValue<float>, &RasterLayer::setRasterHueRotate>; + result["raster-hue-rotate"] = &setProperty<V, RasterLayer, PropertyValue<float>, &RasterLayer::setRasterHueRotate>; result["raster-hue-rotate-transition"] = &setTransition<V, RasterLayer, &RasterLayer::setRasterHueRotateTransition>; - result["raster-brightness-min"] = &setPaintProperty<V, RasterLayer, PropertyValue<float>, &RasterLayer::setRasterBrightnessMin>; + result["raster-brightness-min"] = &setProperty<V, RasterLayer, PropertyValue<float>, &RasterLayer::setRasterBrightnessMin>; result["raster-brightness-min-transition"] = &setTransition<V, RasterLayer, &RasterLayer::setRasterBrightnessMinTransition>; - result["raster-brightness-max"] = &setPaintProperty<V, RasterLayer, PropertyValue<float>, &RasterLayer::setRasterBrightnessMax>; + result["raster-brightness-max"] = &setProperty<V, RasterLayer, PropertyValue<float>, &RasterLayer::setRasterBrightnessMax>; result["raster-brightness-max-transition"] = &setTransition<V, RasterLayer, &RasterLayer::setRasterBrightnessMaxTransition>; - result["raster-saturation"] = &setPaintProperty<V, RasterLayer, PropertyValue<float>, &RasterLayer::setRasterSaturation>; + result["raster-saturation"] = &setProperty<V, RasterLayer, PropertyValue<float>, &RasterLayer::setRasterSaturation>; result["raster-saturation-transition"] = &setTransition<V, RasterLayer, &RasterLayer::setRasterSaturationTransition>; - result["raster-contrast"] = &setPaintProperty<V, RasterLayer, PropertyValue<float>, &RasterLayer::setRasterContrast>; + result["raster-contrast"] = &setProperty<V, RasterLayer, PropertyValue<float>, &RasterLayer::setRasterContrast>; result["raster-contrast-transition"] = &setTransition<V, RasterLayer, &RasterLayer::setRasterContrastTransition>; - result["raster-fade-duration"] = &setPaintProperty<V, RasterLayer, PropertyValue<float>, &RasterLayer::setRasterFadeDuration>; + result["raster-fade-duration"] = &setProperty<V, RasterLayer, PropertyValue<float>, &RasterLayer::setRasterFadeDuration>; result["raster-fade-duration-transition"] = &setTransition<V, RasterLayer, &RasterLayer::setRasterFadeDurationTransition>; - result["background-color"] = &setPaintProperty<V, BackgroundLayer, PropertyValue<Color>, &BackgroundLayer::setBackgroundColor>; + result["background-color"] = &setProperty<V, BackgroundLayer, PropertyValue<Color>, &BackgroundLayer::setBackgroundColor>; result["background-color-transition"] = &setTransition<V, BackgroundLayer, &BackgroundLayer::setBackgroundColorTransition>; - result["background-pattern"] = &setPaintProperty<V, BackgroundLayer, PropertyValue<std::string>, &BackgroundLayer::setBackgroundPattern>; + result["background-pattern"] = &setProperty<V, BackgroundLayer, PropertyValue<std::string>, &BackgroundLayer::setBackgroundPattern>; result["background-pattern-transition"] = &setTransition<V, BackgroundLayer, &BackgroundLayer::setBackgroundPatternTransition>; - result["background-opacity"] = &setPaintProperty<V, BackgroundLayer, PropertyValue<float>, &BackgroundLayer::setBackgroundOpacity>; + result["background-opacity"] = &setProperty<V, BackgroundLayer, PropertyValue<float>, &BackgroundLayer::setBackgroundOpacity>; result["background-opacity-transition"] = &setTransition<V, BackgroundLayer, &BackgroundLayer::setBackgroundOpacityTransition>; return result; diff --git a/include/mbgl/style/conversion/make_property_setters.hpp.ejs b/include/mbgl/style/conversion/make_property_setters.hpp.ejs index a99e75aec7..19c9f70538 100644 --- a/include/mbgl/style/conversion/make_property_setters.hpp.ejs +++ b/include/mbgl/style/conversion/make_property_setters.hpp.ejs @@ -16,13 +16,13 @@ namespace conversion { template <class V> auto makeLayoutPropertySetters() { - std::unordered_map<std::string, LayoutPropertySetter<V>> result; + std::unordered_map<std::string, PropertySetter<V>> result; result["visibility"] = &setVisibility<V>; <% for (const layer of locals.layers) { -%> <% for (const property of layer.layoutProperties) { -%> - result["<%- property.name %>"] = &setLayoutProperty<V, <%- camelize(layer.type) %>Layer, <%- propertyValueType(property) %>, &<%- camelize(layer.type) %>Layer::set<%- camelize(property.name) %>>; + result["<%- property.name %>"] = &setProperty<V, <%- camelize(layer.type) %>Layer, <%- propertyValueType(property) %>, &<%- camelize(layer.type) %>Layer::set<%- camelize(property.name) %>>; <% } -%> <% } -%> @@ -31,11 +31,11 @@ auto makeLayoutPropertySetters() { template <class V> auto makePaintPropertySetters() { - std::unordered_map<std::string, PaintPropertySetter<V>> result; + std::unordered_map<std::string, PropertySetter<V>> result; <% for (const layer of locals.layers) { -%> <% for (const property of layer.paintProperties) { -%> - result["<%- property.name %>"] = &setPaintProperty<V, <%- camelize(layer.type) %>Layer, <%- propertyValueType(property) %>, &<%- camelize(layer.type) %>Layer::set<%- camelize(property.name) %>>; + result["<%- property.name %>"] = &setProperty<V, <%- camelize(layer.type) %>Layer, <%- propertyValueType(property) %>, &<%- camelize(layer.type) %>Layer::set<%- camelize(property.name) %>>; result["<%- property.name %>-transition"] = &setTransition<V, <%- camelize(layer.type) %>Layer, &<%- camelize(layer.type) %>Layer::set<%- camelize(property.name) %>Transition>; <% } -%> diff --git a/include/mbgl/style/conversion/property_setter.hpp b/include/mbgl/style/conversion/property_setter.hpp index 1f537f3c4d..759c4512cc 100644 --- a/include/mbgl/style/conversion/property_setter.hpp +++ b/include/mbgl/style/conversion/property_setter.hpp @@ -14,14 +14,11 @@ namespace style { namespace conversion { template <class V> -using LayoutPropertySetter = optional<Error> (*) (Layer&, const V&); - -template <class V> -using PaintPropertySetter = optional<Error> (*) (Layer&, const V&, const optional<std::string>&); +using PropertySetter = optional<Error> (*) (Layer&, const V&); template <class V, class L, class PropertyValue, void (L::*setter)(PropertyValue)> -optional<Error> setLayoutProperty(Layer& layer, const V& value) { - L* typedLayer = layer.as<L>(); +optional<Error> setProperty(Layer& layer, const V& value) { + auto* typedLayer = layer.as<L>(); if (!typedLayer) { return Error { "layer doesn't support this property" }; } @@ -36,26 +33,9 @@ optional<Error> setLayoutProperty(Layer& layer, const V& value) { return {}; } -template <class V, class L, class PropertyValue, void (L::*setter)(PropertyValue, const optional<std::string>&)> -optional<Error> setPaintProperty(Layer& layer, const V& value, const optional<std::string>& klass) { - L* typedLayer = layer.as<L>(); - if (!typedLayer) { - return Error { "layer doesn't support this property" }; - } - - Error error; - optional<PropertyValue> typedValue = convert<PropertyValue>(value, error); - if (!typedValue) { - return error; - } - - (typedLayer->*setter)(*typedValue, klass); - return {}; -} - -template <class V, class L, void (L::*setter)(const TransitionOptions&, const optional<std::string>&)> -optional<Error> setTransition(Layer& layer, const V& value, const optional<std::string>& klass) { - L* typedLayer = layer.as<L>(); +template <class V, class L, void (L::*setter)(const TransitionOptions&)> +optional<Error> setTransition(Layer& layer, const V& value) { + auto* typedLayer = layer.as<L>(); if (!typedLayer) { return Error { "layer doesn't support this property" }; } @@ -66,7 +46,7 @@ optional<Error> setTransition(Layer& layer, const V& value, const optional<std:: return error; } - (typedLayer->*setter)(*transition, klass); + (typedLayer->*setter)(*transition); return {}; } diff --git a/include/mbgl/style/conversion/source.hpp b/include/mbgl/style/conversion/source.hpp index dc7cdc0d42..e0563ac10b 100644 --- a/include/mbgl/style/conversion/source.hpp +++ b/include/mbgl/style/conversion/source.hpp @@ -1,6 +1,7 @@ #pragma once #include <mbgl/style/conversion.hpp> +#include <mbgl/style/conversion/coordinate.hpp> #include <mbgl/style/conversion/geojson.hpp> #include <mbgl/style/conversion/geojson_options.hpp> #include <mbgl/style/conversion/tileset.hpp> @@ -8,6 +9,8 @@ #include <mbgl/style/sources/geojson_source.hpp> #include <mbgl/style/sources/raster_source.hpp> #include <mbgl/style/sources/vector_source.hpp> +#include <mbgl/style/sources/image_source.hpp> +#include <mbgl/util/geo.hpp> namespace mbgl { namespace style { @@ -16,6 +19,7 @@ namespace conversion { template <> struct Converter<std::unique_ptr<Source>> { public: + template <class V> optional<std::unique_ptr<Source>> operator()(const V& value, Error& error, const std::string& id) const { if (!isObject(value)) { @@ -41,6 +45,8 @@ public: return convertVectorSource(id, value, error); } else if (*type == "geojson") { return convertGeoJSONSource(id, value, error); + } else if (*type == "image") { + return convertImageSource(id, value, error); } else { error = { "invalid source type" }; return {}; @@ -136,6 +142,47 @@ private: return { std::move(result) }; } + + template <class V> + optional<std::unique_ptr<Source>> convertImageSource(const std::string& id, + const V& value, + Error& error) const { + auto urlValue = objectMember(value, "url"); + if (!urlValue) { + error = { "Image source must have a url value" }; + return {}; + } + + auto urlString = toString(*urlValue); + if (!urlString) { + error = { "Image url must be a URL string" }; + return {}; + } + + auto coordinatesValue = objectMember(value, "coordinates"); + if (!coordinatesValue) { + error = { "Image source must have a coordinates values" }; + return {}; + } + + if (!isArray(*coordinatesValue) || arrayLength(*coordinatesValue) != 4) { + error = { "Image coordinates must be an array of four longitude latitude pairs" }; + return {}; + } + + std::array<LatLng, 4> coordinates; + for (std::size_t i=0; i < 4; i++) { + auto latLng = conversion::convert<LatLng>(arrayMember(*coordinatesValue,i), error); + if (!latLng) { + return {}; + } + coordinates[i] = *latLng; + } + auto result = std::make_unique<ImageSource>(id, coordinates); + result->setURL(*urlString); + + return { std::move(result) }; + } }; } // namespace conversion diff --git a/include/mbgl/style/data_driven_property_value.hpp b/include/mbgl/style/data_driven_property_value.hpp index 5acf800840..5d7c596363 100644 --- a/include/mbgl/style/data_driven_property_value.hpp +++ b/include/mbgl/style/data_driven_property_value.hpp @@ -49,16 +49,20 @@ public: bool isZoomConstant() const { return !value.template is<CameraFunction<T>>() && !value.template is<CompositeFunction<T>>(); } - + template <class... Ts> auto match(Ts&&... ts) const { return value.match(std::forward<Ts>(ts)...); } template <typename Evaluator> - auto evaluate(const Evaluator& evaluator) const { + auto evaluate(const Evaluator& evaluator, TimePoint = {}) const { return Value::visit(value, evaluator); } + + bool hasDataDrivenPropertyDifference(const DataDrivenPropertyValue<T>& other) const { + return *this != other && (isDataDriven() || other.isDataDriven()); + } }; } // namespace style diff --git a/include/mbgl/style/function/camera_function.hpp b/include/mbgl/style/function/camera_function.hpp index 2e4aac2238..7fde365b3d 100644 --- a/include/mbgl/style/function/camera_function.hpp +++ b/include/mbgl/style/function/camera_function.hpp @@ -12,7 +12,7 @@ template <class T> class CameraFunction { public: using Stops = std::conditional_t< - util::Interpolatable<T>, + util::Interpolatable<T>::value, variant< ExponentialStops<T>, IntervalStops<T>>, @@ -25,7 +25,7 @@ public: T evaluate(float zoom) const { return stops.match([&] (const auto& s) { - return s.evaluate(Value(double(zoom))).value_or(T()); + return s.evaluate(zoom).value_or(T()); }); } @@ -35,6 +35,7 @@ public: } Stops stops; + bool useIntegerZoom = false; }; } // namespace style diff --git a/include/mbgl/style/function/composite_function.hpp b/include/mbgl/style/function/composite_function.hpp index b82e63bc37..7b524b6021 100644 --- a/include/mbgl/style/function/composite_function.hpp +++ b/include/mbgl/style/function/composite_function.hpp @@ -24,7 +24,7 @@ template <class T> class CompositeFunction { public: using InnerStops = std::conditional_t< - util::Interpolatable<T>, + util::Interpolatable<T>::value, variant< ExponentialStops<T>, IntervalStops<T>, @@ -34,7 +34,7 @@ public: CategoricalStops<T>>>; using Stops = std::conditional_t< - util::Interpolatable<T>, + util::Interpolatable<T>::value, variant< CompositeExponentialStops<T>, CompositeIntervalStops<T>, @@ -67,7 +67,7 @@ public: // lower_bound yields first element >= zoom, but we want the *last* // element <= zoom, so if we found a stop > zoom, back up by one. - if (minIt != s.stops.begin() && minIt->first > zoom) { + if (minIt != s.stops.begin() && minIt != s.stops.end() && minIt->first > zoom) { minIt--; } @@ -135,6 +135,7 @@ public: std::string property; Stops stops; optional<T> defaultValue; + bool useIntegerZoom = false; private: T evaluateFinal(const CoveringRanges& ranges, const Value& value, T finalDefaultValue) const { diff --git a/include/mbgl/style/function/exponential_stops.hpp b/include/mbgl/style/function/exponential_stops.hpp index 051f5aa9aa..b3866c4059 100644 --- a/include/mbgl/style/function/exponential_stops.hpp +++ b/include/mbgl/style/function/exponential_stops.hpp @@ -22,26 +22,28 @@ public: base(base_) { } - optional<T> evaluate(const Value& value) const { + optional<T> evaluate(float z) const { if (stops.empty()) { - assert(false); - return T(); - } - - optional<float> z = numericValue<float>(value); - if (!z) { - return T(); + return {}; } - auto it = stops.upper_bound(*z); + auto it = stops.upper_bound(z); if (it == stops.end()) { return stops.rbegin()->second; } else if (it == stops.begin()) { return stops.begin()->second; } else { return util::interpolate(std::prev(it)->second, it->second, - util::interpolationFactor(base, { std::prev(it)->first, it->first }, *z)); + util::interpolationFactor(base, { std::prev(it)->first, it->first }, z)); + } + } + + optional<T> evaluate(const Value& value) const { + optional<float> z = numericValue<float>(value); + if (!z) { + return {}; } + return evaluate(*z); } friend bool operator==(const ExponentialStops& lhs, diff --git a/include/mbgl/style/function/interval_stops.hpp b/include/mbgl/style/function/interval_stops.hpp index 50f2b48453..45e2dc6f2e 100644 --- a/include/mbgl/style/function/interval_stops.hpp +++ b/include/mbgl/style/function/interval_stops.hpp @@ -18,18 +18,12 @@ public: : stops(std::move(stops_)) { } - optional<T> evaluate(const Value& value) const { + optional<T> evaluate(float z) const { if (stops.empty()) { - assert(false); return {}; } - optional<float> z = numericValue<float>(value); - if (!z) { - return {}; - } - - auto it = stops.upper_bound(*z); + auto it = stops.upper_bound(z); if (it == stops.end()) { return stops.rbegin()->second; } else if (it == stops.begin()) { @@ -39,6 +33,14 @@ public: } } + optional<T> evaluate(const Value& value) const { + optional<float> z = numericValue<float>(value); + if (!z) { + return {}; + } + return evaluate(*z); + } + friend bool operator==(const IntervalStops& lhs, const IntervalStops& rhs) { return lhs.stops == rhs.stops; diff --git a/include/mbgl/style/function/source_function.hpp b/include/mbgl/style/function/source_function.hpp index f6601d9ea3..9c2ad101ec 100644 --- a/include/mbgl/style/function/source_function.hpp +++ b/include/mbgl/style/function/source_function.hpp @@ -16,7 +16,7 @@ template <class T> class SourceFunction { public: using Stops = std::conditional_t< - util::Interpolatable<T>, + util::Interpolatable<T>::value, variant< ExponentialStops<T>, IntervalStops<T>, @@ -53,6 +53,7 @@ public: std::string property; Stops stops; optional<T> defaultValue; + bool useIntegerZoom = false; }; } // namespace style diff --git a/include/mbgl/style/image.hpp b/include/mbgl/style/image.hpp index 499377467e..ff3bfedf46 100644 --- a/include/mbgl/style/image.hpp +++ b/include/mbgl/style/image.hpp @@ -1,24 +1,30 @@ #pragma once #include <mbgl/util/image.hpp> +#include <mbgl/util/immutable.hpp> + +#include <string> namespace mbgl { namespace style { class Image { public: - Image(PremultipliedImage&&, float pixelRatio, bool sdf = false); + Image(std::string id, PremultipliedImage&&, float pixelRatio, bool sdf = false); + Image(const Image&); + + std::string getID() const; - PremultipliedImage image; + const PremultipliedImage& getImage() const; // Pixel ratio of the sprite image. - const float pixelRatio; + float getPixelRatio() const; // Whether this image should be interpreted as a signed distance field icon. - const bool sdf; + bool isSdf() const; - float getWidth() const { return image.size.width / pixelRatio; } - float getHeight() const { return image.size.height / pixelRatio; } + class Impl; + Immutable<Impl> baseImpl; }; } // namespace style diff --git a/include/mbgl/style/layer.hpp b/include/mbgl/style/layer.hpp index 016b3a1c8b..c6a3c0e735 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> @@ -21,6 +22,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 @@ -40,15 +42,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. @@ -80,23 +73,23 @@ public: // template <class V> auto accept(V&& visitor) { - switch (type) { + switch (getType()) { case LayerType::Fill: - return visitor(*as<FillLayer>()); + return std::forward<V>(visitor)(*as<FillLayer>()); case LayerType::Line: - return visitor(*as<LineLayer>()); + return std::forward<V>(visitor)(*as<LineLayer>()); case LayerType::Circle: - return visitor(*as<CircleLayer>()); + return std::forward<V>(visitor)(*as<CircleLayer>()); case LayerType::Symbol: - return visitor(*as<SymbolLayer>()); + return std::forward<V>(visitor)(*as<SymbolLayer>()); case LayerType::Raster: - return visitor(*as<RasterLayer>()); + return std::forward<V>(visitor)(*as<RasterLayer>()); case LayerType::Background: - return visitor(*as<BackgroundLayer>()); + return std::forward<V>(visitor)(*as<BackgroundLayer>()); case LayerType::Custom: - return visitor(*as<CustomLayer>()); + return std::forward<V>(visitor)(*as<CustomLayer>()); case LayerType::FillExtrusion: - return visitor(*as<FillExtrusionLayer>()); + return std::forward<V>(visitor)(*as<FillExtrusionLayer>()); } @@ -105,20 +98,30 @@ public: throw new std::runtime_error("unknown layer type"); } - const std::string& getID() const; + LayerType getType() 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..903983844f 100644 --- a/include/mbgl/style/layers/background_layer.hpp +++ b/include/mbgl/style/layers/background_layer.hpp @@ -19,38 +19,46 @@ 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(); - PropertyValue<Color> getBackgroundColor(const optional<std::string>& klass = {}) const; - void setBackgroundColor(PropertyValue<Color>, const optional<std::string>& klass = {}); - void setBackgroundColorTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getBackgroundColorTransition(const optional<std::string>& klass = {}) const; + PropertyValue<Color> getBackgroundColor() const; + void setBackgroundColor(PropertyValue<Color>); + void setBackgroundColorTransition(const TransitionOptions&); + TransitionOptions getBackgroundColorTransition() const; static PropertyValue<std::string> getDefaultBackgroundPattern(); - PropertyValue<std::string> getBackgroundPattern(const optional<std::string>& klass = {}) const; - void setBackgroundPattern(PropertyValue<std::string>, const optional<std::string>& klass = {}); - void setBackgroundPatternTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getBackgroundPatternTransition(const optional<std::string>& klass = {}) const; + PropertyValue<std::string> getBackgroundPattern() const; + void setBackgroundPattern(PropertyValue<std::string>); + void setBackgroundPatternTransition(const TransitionOptions&); + TransitionOptions getBackgroundPatternTransition() const; static PropertyValue<float> getDefaultBackgroundOpacity(); - PropertyValue<float> getBackgroundOpacity(const optional<std::string>& klass = {}) const; - void setBackgroundOpacity(PropertyValue<float>, const optional<std::string>& klass = {}); - void setBackgroundOpacityTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getBackgroundOpacityTransition(const optional<std::string>& klass = {}) const; + PropertyValue<float> getBackgroundOpacity() const; + void setBackgroundOpacity(PropertyValue<float>); + void setBackgroundOpacityTransition(const TransitionOptions&); + TransitionOptions getBackgroundOpacityTransition() const; // 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..942dd67503 100644 --- a/include/mbgl/style/layers/circle_layer.hpp +++ b/include/mbgl/style/layers/circle_layer.hpp @@ -27,80 +27,94 @@ 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(); - DataDrivenPropertyValue<float> getCircleRadius(const optional<std::string>& klass = {}) const; - void setCircleRadius(DataDrivenPropertyValue<float>, const optional<std::string>& klass = {}); - void setCircleRadiusTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getCircleRadiusTransition(const optional<std::string>& klass = {}) const; + DataDrivenPropertyValue<float> getCircleRadius() const; + void setCircleRadius(DataDrivenPropertyValue<float>); + void setCircleRadiusTransition(const TransitionOptions&); + TransitionOptions getCircleRadiusTransition() const; static DataDrivenPropertyValue<Color> getDefaultCircleColor(); - DataDrivenPropertyValue<Color> getCircleColor(const optional<std::string>& klass = {}) const; - void setCircleColor(DataDrivenPropertyValue<Color>, const optional<std::string>& klass = {}); - void setCircleColorTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getCircleColorTransition(const optional<std::string>& klass = {}) const; + DataDrivenPropertyValue<Color> getCircleColor() const; + void setCircleColor(DataDrivenPropertyValue<Color>); + void setCircleColorTransition(const TransitionOptions&); + TransitionOptions getCircleColorTransition() const; static DataDrivenPropertyValue<float> getDefaultCircleBlur(); - DataDrivenPropertyValue<float> getCircleBlur(const optional<std::string>& klass = {}) const; - void setCircleBlur(DataDrivenPropertyValue<float>, const optional<std::string>& klass = {}); - void setCircleBlurTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getCircleBlurTransition(const optional<std::string>& klass = {}) const; + DataDrivenPropertyValue<float> getCircleBlur() const; + void setCircleBlur(DataDrivenPropertyValue<float>); + void setCircleBlurTransition(const TransitionOptions&); + TransitionOptions getCircleBlurTransition() const; static DataDrivenPropertyValue<float> getDefaultCircleOpacity(); - DataDrivenPropertyValue<float> getCircleOpacity(const optional<std::string>& klass = {}) const; - void setCircleOpacity(DataDrivenPropertyValue<float>, const optional<std::string>& klass = {}); - void setCircleOpacityTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getCircleOpacityTransition(const optional<std::string>& klass = {}) const; + DataDrivenPropertyValue<float> getCircleOpacity() const; + void setCircleOpacity(DataDrivenPropertyValue<float>); + void setCircleOpacityTransition(const TransitionOptions&); + TransitionOptions getCircleOpacityTransition() const; static PropertyValue<std::array<float, 2>> getDefaultCircleTranslate(); - PropertyValue<std::array<float, 2>> getCircleTranslate(const optional<std::string>& klass = {}) const; - void setCircleTranslate(PropertyValue<std::array<float, 2>>, const optional<std::string>& klass = {}); - void setCircleTranslateTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getCircleTranslateTransition(const optional<std::string>& klass = {}) const; + PropertyValue<std::array<float, 2>> getCircleTranslate() const; + void setCircleTranslate(PropertyValue<std::array<float, 2>>); + void setCircleTranslateTransition(const TransitionOptions&); + TransitionOptions getCircleTranslateTransition() const; static PropertyValue<TranslateAnchorType> getDefaultCircleTranslateAnchor(); - PropertyValue<TranslateAnchorType> getCircleTranslateAnchor(const optional<std::string>& klass = {}) const; - void setCircleTranslateAnchor(PropertyValue<TranslateAnchorType>, const optional<std::string>& klass = {}); - void setCircleTranslateAnchorTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getCircleTranslateAnchorTransition(const optional<std::string>& klass = {}) const; + PropertyValue<TranslateAnchorType> getCircleTranslateAnchor() const; + void setCircleTranslateAnchor(PropertyValue<TranslateAnchorType>); + void setCircleTranslateAnchorTransition(const TransitionOptions&); + TransitionOptions getCircleTranslateAnchorTransition() const; static PropertyValue<CirclePitchScaleType> getDefaultCirclePitchScale(); - PropertyValue<CirclePitchScaleType> getCirclePitchScale(const optional<std::string>& klass = {}) const; - void setCirclePitchScale(PropertyValue<CirclePitchScaleType>, const optional<std::string>& klass = {}); - void setCirclePitchScaleTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getCirclePitchScaleTransition(const optional<std::string>& klass = {}) const; + PropertyValue<CirclePitchScaleType> getCirclePitchScale() const; + void setCirclePitchScale(PropertyValue<CirclePitchScaleType>); + void setCirclePitchScaleTransition(const TransitionOptions&); + TransitionOptions getCirclePitchScaleTransition() const; + + static PropertyValue<AlignmentType> getDefaultCirclePitchAlignment(); + PropertyValue<AlignmentType> getCirclePitchAlignment() const; + void setCirclePitchAlignment(PropertyValue<AlignmentType>); + void setCirclePitchAlignmentTransition(const TransitionOptions&); + TransitionOptions getCirclePitchAlignmentTransition() const; static DataDrivenPropertyValue<float> getDefaultCircleStrokeWidth(); - DataDrivenPropertyValue<float> getCircleStrokeWidth(const optional<std::string>& klass = {}) const; - void setCircleStrokeWidth(DataDrivenPropertyValue<float>, const optional<std::string>& klass = {}); - void setCircleStrokeWidthTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getCircleStrokeWidthTransition(const optional<std::string>& klass = {}) const; + DataDrivenPropertyValue<float> getCircleStrokeWidth() const; + void setCircleStrokeWidth(DataDrivenPropertyValue<float>); + void setCircleStrokeWidthTransition(const TransitionOptions&); + TransitionOptions getCircleStrokeWidthTransition() const; static DataDrivenPropertyValue<Color> getDefaultCircleStrokeColor(); - DataDrivenPropertyValue<Color> getCircleStrokeColor(const optional<std::string>& klass = {}) const; - void setCircleStrokeColor(DataDrivenPropertyValue<Color>, const optional<std::string>& klass = {}); - void setCircleStrokeColorTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getCircleStrokeColorTransition(const optional<std::string>& klass = {}) const; + DataDrivenPropertyValue<Color> getCircleStrokeColor() const; + void setCircleStrokeColor(DataDrivenPropertyValue<Color>); + void setCircleStrokeColorTransition(const TransitionOptions&); + TransitionOptions getCircleStrokeColorTransition() const; static DataDrivenPropertyValue<float> getDefaultCircleStrokeOpacity(); - DataDrivenPropertyValue<float> getCircleStrokeOpacity(const optional<std::string>& klass = {}) const; - void setCircleStrokeOpacity(DataDrivenPropertyValue<float>, const optional<std::string>& klass = {}); - void setCircleStrokeOpacityTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getCircleStrokeOpacityTransition(const optional<std::string>& klass = {}) const; + DataDrivenPropertyValue<float> getCircleStrokeOpacity() const; + void setCircleStrokeOpacity(DataDrivenPropertyValue<float>); + void setCircleStrokeOpacityTransition(const TransitionOptions&); + TransitionOptions getCircleStrokeOpacityTransition() const; // 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..bf3387f95b 100644 --- a/include/mbgl/style/layers/custom_layer.hpp +++ b/include/mbgl/style/layers/custom_layer.hpp @@ -39,6 +39,14 @@ struct CustomLayerRenderParameters { using CustomLayerRenderFunction = void (*)(void* context, const CustomLayerRenderParameters&); /** + * Called when the system has destroyed the underlying GL context. The + * `CustomLayerDeinitializeFunction` will not be called in this case, however + * `CustomLayerInitializeFunction` will be called instead to prepare for a new render. + * + */ +using CustomLayerContextLostFunction = void (*)(void* context); + +/** * Destroy any GL state needed by the custom layer, and deallocate context, if necessary. This * method is called once, from the main thread, at a point when the GL context is active. * @@ -51,16 +59,33 @@ public: CustomLayer(const std::string& id, CustomLayerInitializeFunction, CustomLayerRenderFunction, + CustomLayerContextLostFunction, + CustomLayerDeinitializeFunction, + void* context); + + CustomLayer(const std::string& id, + CustomLayerInitializeFunction, + CustomLayerRenderFunction, CustomLayerDeinitializeFunction, 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..e1c54f54ee 100644 --- a/include/mbgl/style/layers/fill_extrusion_layer.hpp +++ b/include/mbgl/style/layers/fill_extrusion_layer.hpp @@ -27,62 +27,70 @@ 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(); - PropertyValue<float> getFillExtrusionOpacity(const optional<std::string>& klass = {}) const; - void setFillExtrusionOpacity(PropertyValue<float>, const optional<std::string>& klass = {}); - void setFillExtrusionOpacityTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getFillExtrusionOpacityTransition(const optional<std::string>& klass = {}) const; + PropertyValue<float> getFillExtrusionOpacity() const; + void setFillExtrusionOpacity(PropertyValue<float>); + void setFillExtrusionOpacityTransition(const TransitionOptions&); + TransitionOptions getFillExtrusionOpacityTransition() const; static DataDrivenPropertyValue<Color> getDefaultFillExtrusionColor(); - DataDrivenPropertyValue<Color> getFillExtrusionColor(const optional<std::string>& klass = {}) const; - void setFillExtrusionColor(DataDrivenPropertyValue<Color>, const optional<std::string>& klass = {}); - void setFillExtrusionColorTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getFillExtrusionColorTransition(const optional<std::string>& klass = {}) const; + DataDrivenPropertyValue<Color> getFillExtrusionColor() const; + void setFillExtrusionColor(DataDrivenPropertyValue<Color>); + void setFillExtrusionColorTransition(const TransitionOptions&); + TransitionOptions getFillExtrusionColorTransition() const; static PropertyValue<std::array<float, 2>> getDefaultFillExtrusionTranslate(); - PropertyValue<std::array<float, 2>> getFillExtrusionTranslate(const optional<std::string>& klass = {}) const; - void setFillExtrusionTranslate(PropertyValue<std::array<float, 2>>, const optional<std::string>& klass = {}); - void setFillExtrusionTranslateTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getFillExtrusionTranslateTransition(const optional<std::string>& klass = {}) const; + PropertyValue<std::array<float, 2>> getFillExtrusionTranslate() const; + void setFillExtrusionTranslate(PropertyValue<std::array<float, 2>>); + void setFillExtrusionTranslateTransition(const TransitionOptions&); + TransitionOptions getFillExtrusionTranslateTransition() const; static PropertyValue<TranslateAnchorType> getDefaultFillExtrusionTranslateAnchor(); - PropertyValue<TranslateAnchorType> getFillExtrusionTranslateAnchor(const optional<std::string>& klass = {}) const; - void setFillExtrusionTranslateAnchor(PropertyValue<TranslateAnchorType>, const optional<std::string>& klass = {}); - void setFillExtrusionTranslateAnchorTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getFillExtrusionTranslateAnchorTransition(const optional<std::string>& klass = {}) const; + PropertyValue<TranslateAnchorType> getFillExtrusionTranslateAnchor() const; + void setFillExtrusionTranslateAnchor(PropertyValue<TranslateAnchorType>); + void setFillExtrusionTranslateAnchorTransition(const TransitionOptions&); + TransitionOptions getFillExtrusionTranslateAnchorTransition() const; static PropertyValue<std::string> getDefaultFillExtrusionPattern(); - PropertyValue<std::string> getFillExtrusionPattern(const optional<std::string>& klass = {}) const; - void setFillExtrusionPattern(PropertyValue<std::string>, const optional<std::string>& klass = {}); - void setFillExtrusionPatternTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getFillExtrusionPatternTransition(const optional<std::string>& klass = {}) const; + PropertyValue<std::string> getFillExtrusionPattern() const; + void setFillExtrusionPattern(PropertyValue<std::string>); + void setFillExtrusionPatternTransition(const TransitionOptions&); + TransitionOptions getFillExtrusionPatternTransition() const; static DataDrivenPropertyValue<float> getDefaultFillExtrusionHeight(); - DataDrivenPropertyValue<float> getFillExtrusionHeight(const optional<std::string>& klass = {}) const; - void setFillExtrusionHeight(DataDrivenPropertyValue<float>, const optional<std::string>& klass = {}); - void setFillExtrusionHeightTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getFillExtrusionHeightTransition(const optional<std::string>& klass = {}) const; + DataDrivenPropertyValue<float> getFillExtrusionHeight() const; + void setFillExtrusionHeight(DataDrivenPropertyValue<float>); + void setFillExtrusionHeightTransition(const TransitionOptions&); + TransitionOptions getFillExtrusionHeightTransition() const; static DataDrivenPropertyValue<float> getDefaultFillExtrusionBase(); - DataDrivenPropertyValue<float> getFillExtrusionBase(const optional<std::string>& klass = {}) const; - void setFillExtrusionBase(DataDrivenPropertyValue<float>, const optional<std::string>& klass = {}); - void setFillExtrusionBaseTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getFillExtrusionBaseTransition(const optional<std::string>& klass = {}) const; + DataDrivenPropertyValue<float> getFillExtrusionBase() const; + void setFillExtrusionBase(DataDrivenPropertyValue<float>); + void setFillExtrusionBaseTransition(const TransitionOptions&); + TransitionOptions getFillExtrusionBaseTransition() const; // 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..dfbe69d7fe 100644 --- a/include/mbgl/style/layers/fill_layer.hpp +++ b/include/mbgl/style/layers/fill_layer.hpp @@ -27,62 +27,70 @@ 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(); - PropertyValue<bool> getFillAntialias(const optional<std::string>& klass = {}) const; - void setFillAntialias(PropertyValue<bool>, const optional<std::string>& klass = {}); - void setFillAntialiasTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getFillAntialiasTransition(const optional<std::string>& klass = {}) const; + PropertyValue<bool> getFillAntialias() const; + void setFillAntialias(PropertyValue<bool>); + void setFillAntialiasTransition(const TransitionOptions&); + TransitionOptions getFillAntialiasTransition() const; static DataDrivenPropertyValue<float> getDefaultFillOpacity(); - DataDrivenPropertyValue<float> getFillOpacity(const optional<std::string>& klass = {}) const; - void setFillOpacity(DataDrivenPropertyValue<float>, const optional<std::string>& klass = {}); - void setFillOpacityTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getFillOpacityTransition(const optional<std::string>& klass = {}) const; + DataDrivenPropertyValue<float> getFillOpacity() const; + void setFillOpacity(DataDrivenPropertyValue<float>); + void setFillOpacityTransition(const TransitionOptions&); + TransitionOptions getFillOpacityTransition() const; static DataDrivenPropertyValue<Color> getDefaultFillColor(); - DataDrivenPropertyValue<Color> getFillColor(const optional<std::string>& klass = {}) const; - void setFillColor(DataDrivenPropertyValue<Color>, const optional<std::string>& klass = {}); - void setFillColorTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getFillColorTransition(const optional<std::string>& klass = {}) const; + DataDrivenPropertyValue<Color> getFillColor() const; + void setFillColor(DataDrivenPropertyValue<Color>); + void setFillColorTransition(const TransitionOptions&); + TransitionOptions getFillColorTransition() const; static DataDrivenPropertyValue<Color> getDefaultFillOutlineColor(); - DataDrivenPropertyValue<Color> getFillOutlineColor(const optional<std::string>& klass = {}) const; - void setFillOutlineColor(DataDrivenPropertyValue<Color>, const optional<std::string>& klass = {}); - void setFillOutlineColorTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getFillOutlineColorTransition(const optional<std::string>& klass = {}) const; + DataDrivenPropertyValue<Color> getFillOutlineColor() const; + void setFillOutlineColor(DataDrivenPropertyValue<Color>); + void setFillOutlineColorTransition(const TransitionOptions&); + TransitionOptions getFillOutlineColorTransition() const; static PropertyValue<std::array<float, 2>> getDefaultFillTranslate(); - PropertyValue<std::array<float, 2>> getFillTranslate(const optional<std::string>& klass = {}) const; - void setFillTranslate(PropertyValue<std::array<float, 2>>, const optional<std::string>& klass = {}); - void setFillTranslateTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getFillTranslateTransition(const optional<std::string>& klass = {}) const; + PropertyValue<std::array<float, 2>> getFillTranslate() const; + void setFillTranslate(PropertyValue<std::array<float, 2>>); + void setFillTranslateTransition(const TransitionOptions&); + TransitionOptions getFillTranslateTransition() const; static PropertyValue<TranslateAnchorType> getDefaultFillTranslateAnchor(); - PropertyValue<TranslateAnchorType> getFillTranslateAnchor(const optional<std::string>& klass = {}) const; - void setFillTranslateAnchor(PropertyValue<TranslateAnchorType>, const optional<std::string>& klass = {}); - void setFillTranslateAnchorTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getFillTranslateAnchorTransition(const optional<std::string>& klass = {}) const; + PropertyValue<TranslateAnchorType> getFillTranslateAnchor() const; + void setFillTranslateAnchor(PropertyValue<TranslateAnchorType>); + void setFillTranslateAnchorTransition(const TransitionOptions&); + TransitionOptions getFillTranslateAnchorTransition() const; static PropertyValue<std::string> getDefaultFillPattern(); - PropertyValue<std::string> getFillPattern(const optional<std::string>& klass = {}) const; - void setFillPattern(PropertyValue<std::string>, const optional<std::string>& klass = {}); - void setFillPatternTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getFillPatternTransition(const optional<std::string>& klass = {}) const; + PropertyValue<std::string> getFillPattern() const; + void setFillPattern(PropertyValue<std::string>); + void setFillPatternTransition(const TransitionOptions&); + TransitionOptions getFillPatternTransition() const; // 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..4ee5545247 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 @@ -58,24 +65,25 @@ public: <% for (const property of paintProperties) { -%> static <%- propertyValueType(property) %> getDefault<%- camelize(property.name) %>(); - <%- propertyValueType(property) %> get<%- camelize(property.name) %>(const optional<std::string>& klass = {}) const; - void set<%- camelize(property.name) %>(<%- propertyValueType(property) %>, const optional<std::string>& klass = {}); - void set<%- camelize(property.name) %>Transition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions get<%- camelize(property.name) %>Transition(const optional<std::string>& klass = {}) const; + <%- propertyValueType(property) %> get<%- camelize(property.name) %>() const; + void set<%- camelize(property.name) %>(<%- propertyValueType(property) %>); + void set<%- camelize(property.name) %>Transition(const TransitionOptions&); + TransitionOptions get<%- camelize(property.name) %>Transition() const; <% } -%> // 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..4519296323 100644 --- a/include/mbgl/style/layers/line_layer.hpp +++ b/include/mbgl/style/layers/line_layer.hpp @@ -29,15 +29,22 @@ 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(); PropertyValue<LineCapType> getLineCap() const; void setLineCap(PropertyValue<LineCapType>); - static PropertyValue<LineJoinType> getDefaultLineJoin(); - PropertyValue<LineJoinType> getLineJoin() const; - void setLineJoin(PropertyValue<LineJoinType>); + static DataDrivenPropertyValue<LineJoinType> getDefaultLineJoin(); + DataDrivenPropertyValue<LineJoinType> getLineJoin() const; + void setLineJoin(DataDrivenPropertyValue<LineJoinType>); static PropertyValue<float> getDefaultLineMiterLimit(); PropertyValue<float> getLineMiterLimit() const; @@ -50,77 +57,78 @@ public: // Paint properties static DataDrivenPropertyValue<float> getDefaultLineOpacity(); - DataDrivenPropertyValue<float> getLineOpacity(const optional<std::string>& klass = {}) const; - void setLineOpacity(DataDrivenPropertyValue<float>, const optional<std::string>& klass = {}); - void setLineOpacityTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getLineOpacityTransition(const optional<std::string>& klass = {}) const; + DataDrivenPropertyValue<float> getLineOpacity() const; + void setLineOpacity(DataDrivenPropertyValue<float>); + void setLineOpacityTransition(const TransitionOptions&); + TransitionOptions getLineOpacityTransition() const; static DataDrivenPropertyValue<Color> getDefaultLineColor(); - DataDrivenPropertyValue<Color> getLineColor(const optional<std::string>& klass = {}) const; - void setLineColor(DataDrivenPropertyValue<Color>, const optional<std::string>& klass = {}); - void setLineColorTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getLineColorTransition(const optional<std::string>& klass = {}) const; + DataDrivenPropertyValue<Color> getLineColor() const; + void setLineColor(DataDrivenPropertyValue<Color>); + void setLineColorTransition(const TransitionOptions&); + TransitionOptions getLineColorTransition() const; static PropertyValue<std::array<float, 2>> getDefaultLineTranslate(); - PropertyValue<std::array<float, 2>> getLineTranslate(const optional<std::string>& klass = {}) const; - void setLineTranslate(PropertyValue<std::array<float, 2>>, const optional<std::string>& klass = {}); - void setLineTranslateTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getLineTranslateTransition(const optional<std::string>& klass = {}) const; + PropertyValue<std::array<float, 2>> getLineTranslate() const; + void setLineTranslate(PropertyValue<std::array<float, 2>>); + void setLineTranslateTransition(const TransitionOptions&); + TransitionOptions getLineTranslateTransition() const; static PropertyValue<TranslateAnchorType> getDefaultLineTranslateAnchor(); - PropertyValue<TranslateAnchorType> getLineTranslateAnchor(const optional<std::string>& klass = {}) const; - void setLineTranslateAnchor(PropertyValue<TranslateAnchorType>, const optional<std::string>& klass = {}); - void setLineTranslateAnchorTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getLineTranslateAnchorTransition(const optional<std::string>& klass = {}) const; + PropertyValue<TranslateAnchorType> getLineTranslateAnchor() const; + void setLineTranslateAnchor(PropertyValue<TranslateAnchorType>); + void setLineTranslateAnchorTransition(const TransitionOptions&); + TransitionOptions getLineTranslateAnchorTransition() const; - static PropertyValue<float> getDefaultLineWidth(); - PropertyValue<float> getLineWidth(const optional<std::string>& klass = {}) const; - void setLineWidth(PropertyValue<float>, const optional<std::string>& klass = {}); - void setLineWidthTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getLineWidthTransition(const optional<std::string>& klass = {}) const; + static DataDrivenPropertyValue<float> getDefaultLineWidth(); + DataDrivenPropertyValue<float> getLineWidth() const; + void setLineWidth(DataDrivenPropertyValue<float>); + void setLineWidthTransition(const TransitionOptions&); + TransitionOptions getLineWidthTransition() const; static DataDrivenPropertyValue<float> getDefaultLineGapWidth(); - DataDrivenPropertyValue<float> getLineGapWidth(const optional<std::string>& klass = {}) const; - void setLineGapWidth(DataDrivenPropertyValue<float>, const optional<std::string>& klass = {}); - void setLineGapWidthTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getLineGapWidthTransition(const optional<std::string>& klass = {}) const; + DataDrivenPropertyValue<float> getLineGapWidth() const; + void setLineGapWidth(DataDrivenPropertyValue<float>); + void setLineGapWidthTransition(const TransitionOptions&); + TransitionOptions getLineGapWidthTransition() const; static DataDrivenPropertyValue<float> getDefaultLineOffset(); - DataDrivenPropertyValue<float> getLineOffset(const optional<std::string>& klass = {}) const; - void setLineOffset(DataDrivenPropertyValue<float>, const optional<std::string>& klass = {}); - void setLineOffsetTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getLineOffsetTransition(const optional<std::string>& klass = {}) const; + DataDrivenPropertyValue<float> getLineOffset() const; + void setLineOffset(DataDrivenPropertyValue<float>); + void setLineOffsetTransition(const TransitionOptions&); + TransitionOptions getLineOffsetTransition() const; static DataDrivenPropertyValue<float> getDefaultLineBlur(); - DataDrivenPropertyValue<float> getLineBlur(const optional<std::string>& klass = {}) const; - void setLineBlur(DataDrivenPropertyValue<float>, const optional<std::string>& klass = {}); - void setLineBlurTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getLineBlurTransition(const optional<std::string>& klass = {}) const; + DataDrivenPropertyValue<float> getLineBlur() const; + void setLineBlur(DataDrivenPropertyValue<float>); + void setLineBlurTransition(const TransitionOptions&); + TransitionOptions getLineBlurTransition() const; static PropertyValue<std::vector<float>> getDefaultLineDasharray(); - PropertyValue<std::vector<float>> getLineDasharray(const optional<std::string>& klass = {}) const; - void setLineDasharray(PropertyValue<std::vector<float>>, const optional<std::string>& klass = {}); - void setLineDasharrayTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getLineDasharrayTransition(const optional<std::string>& klass = {}) const; + PropertyValue<std::vector<float>> getLineDasharray() const; + void setLineDasharray(PropertyValue<std::vector<float>>); + void setLineDasharrayTransition(const TransitionOptions&); + TransitionOptions getLineDasharrayTransition() const; static PropertyValue<std::string> getDefaultLinePattern(); - PropertyValue<std::string> getLinePattern(const optional<std::string>& klass = {}) const; - void setLinePattern(PropertyValue<std::string>, const optional<std::string>& klass = {}); - void setLinePatternTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getLinePatternTransition(const optional<std::string>& klass = {}) const; + PropertyValue<std::string> getLinePattern() const; + void setLinePattern(PropertyValue<std::string>); + void setLinePatternTransition(const TransitionOptions&); + TransitionOptions getLinePatternTransition() const; // 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..8111364709 100644 --- a/include/mbgl/style/layers/raster_layer.hpp +++ b/include/mbgl/style/layers/raster_layer.hpp @@ -22,62 +22,70 @@ 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(); - PropertyValue<float> getRasterOpacity(const optional<std::string>& klass = {}) const; - void setRasterOpacity(PropertyValue<float>, const optional<std::string>& klass = {}); - void setRasterOpacityTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getRasterOpacityTransition(const optional<std::string>& klass = {}) const; + PropertyValue<float> getRasterOpacity() const; + void setRasterOpacity(PropertyValue<float>); + void setRasterOpacityTransition(const TransitionOptions&); + TransitionOptions getRasterOpacityTransition() const; static PropertyValue<float> getDefaultRasterHueRotate(); - PropertyValue<float> getRasterHueRotate(const optional<std::string>& klass = {}) const; - void setRasterHueRotate(PropertyValue<float>, const optional<std::string>& klass = {}); - void setRasterHueRotateTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getRasterHueRotateTransition(const optional<std::string>& klass = {}) const; + PropertyValue<float> getRasterHueRotate() const; + void setRasterHueRotate(PropertyValue<float>); + void setRasterHueRotateTransition(const TransitionOptions&); + TransitionOptions getRasterHueRotateTransition() const; static PropertyValue<float> getDefaultRasterBrightnessMin(); - PropertyValue<float> getRasterBrightnessMin(const optional<std::string>& klass = {}) const; - void setRasterBrightnessMin(PropertyValue<float>, const optional<std::string>& klass = {}); - void setRasterBrightnessMinTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getRasterBrightnessMinTransition(const optional<std::string>& klass = {}) const; + PropertyValue<float> getRasterBrightnessMin() const; + void setRasterBrightnessMin(PropertyValue<float>); + void setRasterBrightnessMinTransition(const TransitionOptions&); + TransitionOptions getRasterBrightnessMinTransition() const; static PropertyValue<float> getDefaultRasterBrightnessMax(); - PropertyValue<float> getRasterBrightnessMax(const optional<std::string>& klass = {}) const; - void setRasterBrightnessMax(PropertyValue<float>, const optional<std::string>& klass = {}); - void setRasterBrightnessMaxTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getRasterBrightnessMaxTransition(const optional<std::string>& klass = {}) const; + PropertyValue<float> getRasterBrightnessMax() const; + void setRasterBrightnessMax(PropertyValue<float>); + void setRasterBrightnessMaxTransition(const TransitionOptions&); + TransitionOptions getRasterBrightnessMaxTransition() const; static PropertyValue<float> getDefaultRasterSaturation(); - PropertyValue<float> getRasterSaturation(const optional<std::string>& klass = {}) const; - void setRasterSaturation(PropertyValue<float>, const optional<std::string>& klass = {}); - void setRasterSaturationTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getRasterSaturationTransition(const optional<std::string>& klass = {}) const; + PropertyValue<float> getRasterSaturation() const; + void setRasterSaturation(PropertyValue<float>); + void setRasterSaturationTransition(const TransitionOptions&); + TransitionOptions getRasterSaturationTransition() const; static PropertyValue<float> getDefaultRasterContrast(); - PropertyValue<float> getRasterContrast(const optional<std::string>& klass = {}) const; - void setRasterContrast(PropertyValue<float>, const optional<std::string>& klass = {}); - void setRasterContrastTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getRasterContrastTransition(const optional<std::string>& klass = {}) const; + PropertyValue<float> getRasterContrast() const; + void setRasterContrast(PropertyValue<float>); + void setRasterContrastTransition(const TransitionOptions&); + TransitionOptions getRasterContrastTransition() const; static PropertyValue<float> getDefaultRasterFadeDuration(); - PropertyValue<float> getRasterFadeDuration(const optional<std::string>& klass = {}) const; - void setRasterFadeDuration(PropertyValue<float>, const optional<std::string>& klass = {}); - void setRasterFadeDurationTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getRasterFadeDurationTransition(const optional<std::string>& klass = {}) const; + PropertyValue<float> getRasterFadeDuration() const; + void setRasterFadeDuration(PropertyValue<float>); + void setRasterFadeDurationTransition(const TransitionOptions&); + TransitionOptions getRasterFadeDurationTransition() const; // 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..a72baa0b4e 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(); @@ -91,6 +98,14 @@ public: DataDrivenPropertyValue<std::array<float, 2>> getIconOffset() const; void setIconOffset(DataDrivenPropertyValue<std::array<float, 2>>); + static DataDrivenPropertyValue<SymbolAnchorType> getDefaultIconAnchor(); + DataDrivenPropertyValue<SymbolAnchorType> getIconAnchor() const; + void setIconAnchor(DataDrivenPropertyValue<SymbolAnchorType>); + + static PropertyValue<AlignmentType> getDefaultIconPitchAlignment(); + PropertyValue<AlignmentType> getIconPitchAlignment() const; + void setIconPitchAlignment(PropertyValue<AlignmentType>); + static PropertyValue<AlignmentType> getDefaultTextPitchAlignment(); PropertyValue<AlignmentType> getTextPitchAlignment() const; void setTextPitchAlignment(PropertyValue<AlignmentType>); @@ -111,25 +126,25 @@ public: DataDrivenPropertyValue<float> getTextSize() const; void setTextSize(DataDrivenPropertyValue<float>); - static PropertyValue<float> getDefaultTextMaxWidth(); - PropertyValue<float> getTextMaxWidth() const; - void setTextMaxWidth(PropertyValue<float>); + static DataDrivenPropertyValue<float> getDefaultTextMaxWidth(); + DataDrivenPropertyValue<float> getTextMaxWidth() const; + void setTextMaxWidth(DataDrivenPropertyValue<float>); static PropertyValue<float> getDefaultTextLineHeight(); PropertyValue<float> getTextLineHeight() const; void setTextLineHeight(PropertyValue<float>); - static PropertyValue<float> getDefaultTextLetterSpacing(); - PropertyValue<float> getTextLetterSpacing() const; - void setTextLetterSpacing(PropertyValue<float>); + static DataDrivenPropertyValue<float> getDefaultTextLetterSpacing(); + DataDrivenPropertyValue<float> getTextLetterSpacing() const; + void setTextLetterSpacing(DataDrivenPropertyValue<float>); - static PropertyValue<TextJustifyType> getDefaultTextJustify(); - PropertyValue<TextJustifyType> getTextJustify() const; - void setTextJustify(PropertyValue<TextJustifyType>); + static DataDrivenPropertyValue<TextJustifyType> getDefaultTextJustify(); + DataDrivenPropertyValue<TextJustifyType> getTextJustify() const; + void setTextJustify(DataDrivenPropertyValue<TextJustifyType>); - static PropertyValue<TextAnchorType> getDefaultTextAnchor(); - PropertyValue<TextAnchorType> getTextAnchor() const; - void setTextAnchor(PropertyValue<TextAnchorType>); + static DataDrivenPropertyValue<SymbolAnchorType> getDefaultTextAnchor(); + DataDrivenPropertyValue<SymbolAnchorType> getTextAnchor() const; + void setTextAnchor(DataDrivenPropertyValue<SymbolAnchorType>); static PropertyValue<float> getDefaultTextMaxAngle(); PropertyValue<float> getTextMaxAngle() const; @@ -170,101 +185,102 @@ public: // Paint properties static DataDrivenPropertyValue<float> getDefaultIconOpacity(); - DataDrivenPropertyValue<float> getIconOpacity(const optional<std::string>& klass = {}) const; - void setIconOpacity(DataDrivenPropertyValue<float>, const optional<std::string>& klass = {}); - void setIconOpacityTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getIconOpacityTransition(const optional<std::string>& klass = {}) const; + DataDrivenPropertyValue<float> getIconOpacity() const; + void setIconOpacity(DataDrivenPropertyValue<float>); + void setIconOpacityTransition(const TransitionOptions&); + TransitionOptions getIconOpacityTransition() const; static DataDrivenPropertyValue<Color> getDefaultIconColor(); - DataDrivenPropertyValue<Color> getIconColor(const optional<std::string>& klass = {}) const; - void setIconColor(DataDrivenPropertyValue<Color>, const optional<std::string>& klass = {}); - void setIconColorTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getIconColorTransition(const optional<std::string>& klass = {}) const; + DataDrivenPropertyValue<Color> getIconColor() const; + void setIconColor(DataDrivenPropertyValue<Color>); + void setIconColorTransition(const TransitionOptions&); + TransitionOptions getIconColorTransition() const; static DataDrivenPropertyValue<Color> getDefaultIconHaloColor(); - DataDrivenPropertyValue<Color> getIconHaloColor(const optional<std::string>& klass = {}) const; - void setIconHaloColor(DataDrivenPropertyValue<Color>, const optional<std::string>& klass = {}); - void setIconHaloColorTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getIconHaloColorTransition(const optional<std::string>& klass = {}) const; + DataDrivenPropertyValue<Color> getIconHaloColor() const; + void setIconHaloColor(DataDrivenPropertyValue<Color>); + void setIconHaloColorTransition(const TransitionOptions&); + TransitionOptions getIconHaloColorTransition() const; static DataDrivenPropertyValue<float> getDefaultIconHaloWidth(); - DataDrivenPropertyValue<float> getIconHaloWidth(const optional<std::string>& klass = {}) const; - void setIconHaloWidth(DataDrivenPropertyValue<float>, const optional<std::string>& klass = {}); - void setIconHaloWidthTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getIconHaloWidthTransition(const optional<std::string>& klass = {}) const; + DataDrivenPropertyValue<float> getIconHaloWidth() const; + void setIconHaloWidth(DataDrivenPropertyValue<float>); + void setIconHaloWidthTransition(const TransitionOptions&); + TransitionOptions getIconHaloWidthTransition() const; static DataDrivenPropertyValue<float> getDefaultIconHaloBlur(); - DataDrivenPropertyValue<float> getIconHaloBlur(const optional<std::string>& klass = {}) const; - void setIconHaloBlur(DataDrivenPropertyValue<float>, const optional<std::string>& klass = {}); - void setIconHaloBlurTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getIconHaloBlurTransition(const optional<std::string>& klass = {}) const; + DataDrivenPropertyValue<float> getIconHaloBlur() const; + void setIconHaloBlur(DataDrivenPropertyValue<float>); + void setIconHaloBlurTransition(const TransitionOptions&); + TransitionOptions getIconHaloBlurTransition() const; static PropertyValue<std::array<float, 2>> getDefaultIconTranslate(); - PropertyValue<std::array<float, 2>> getIconTranslate(const optional<std::string>& klass = {}) const; - void setIconTranslate(PropertyValue<std::array<float, 2>>, const optional<std::string>& klass = {}); - void setIconTranslateTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getIconTranslateTransition(const optional<std::string>& klass = {}) const; + PropertyValue<std::array<float, 2>> getIconTranslate() const; + void setIconTranslate(PropertyValue<std::array<float, 2>>); + void setIconTranslateTransition(const TransitionOptions&); + TransitionOptions getIconTranslateTransition() const; static PropertyValue<TranslateAnchorType> getDefaultIconTranslateAnchor(); - PropertyValue<TranslateAnchorType> getIconTranslateAnchor(const optional<std::string>& klass = {}) const; - void setIconTranslateAnchor(PropertyValue<TranslateAnchorType>, const optional<std::string>& klass = {}); - void setIconTranslateAnchorTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getIconTranslateAnchorTransition(const optional<std::string>& klass = {}) const; + PropertyValue<TranslateAnchorType> getIconTranslateAnchor() const; + void setIconTranslateAnchor(PropertyValue<TranslateAnchorType>); + void setIconTranslateAnchorTransition(const TransitionOptions&); + TransitionOptions getIconTranslateAnchorTransition() const; static DataDrivenPropertyValue<float> getDefaultTextOpacity(); - DataDrivenPropertyValue<float> getTextOpacity(const optional<std::string>& klass = {}) const; - void setTextOpacity(DataDrivenPropertyValue<float>, const optional<std::string>& klass = {}); - void setTextOpacityTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getTextOpacityTransition(const optional<std::string>& klass = {}) const; + DataDrivenPropertyValue<float> getTextOpacity() const; + void setTextOpacity(DataDrivenPropertyValue<float>); + void setTextOpacityTransition(const TransitionOptions&); + TransitionOptions getTextOpacityTransition() const; static DataDrivenPropertyValue<Color> getDefaultTextColor(); - DataDrivenPropertyValue<Color> getTextColor(const optional<std::string>& klass = {}) const; - void setTextColor(DataDrivenPropertyValue<Color>, const optional<std::string>& klass = {}); - void setTextColorTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getTextColorTransition(const optional<std::string>& klass = {}) const; + DataDrivenPropertyValue<Color> getTextColor() const; + void setTextColor(DataDrivenPropertyValue<Color>); + void setTextColorTransition(const TransitionOptions&); + TransitionOptions getTextColorTransition() const; static DataDrivenPropertyValue<Color> getDefaultTextHaloColor(); - DataDrivenPropertyValue<Color> getTextHaloColor(const optional<std::string>& klass = {}) const; - void setTextHaloColor(DataDrivenPropertyValue<Color>, const optional<std::string>& klass = {}); - void setTextHaloColorTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getTextHaloColorTransition(const optional<std::string>& klass = {}) const; + DataDrivenPropertyValue<Color> getTextHaloColor() const; + void setTextHaloColor(DataDrivenPropertyValue<Color>); + void setTextHaloColorTransition(const TransitionOptions&); + TransitionOptions getTextHaloColorTransition() const; static DataDrivenPropertyValue<float> getDefaultTextHaloWidth(); - DataDrivenPropertyValue<float> getTextHaloWidth(const optional<std::string>& klass = {}) const; - void setTextHaloWidth(DataDrivenPropertyValue<float>, const optional<std::string>& klass = {}); - void setTextHaloWidthTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getTextHaloWidthTransition(const optional<std::string>& klass = {}) const; + DataDrivenPropertyValue<float> getTextHaloWidth() const; + void setTextHaloWidth(DataDrivenPropertyValue<float>); + void setTextHaloWidthTransition(const TransitionOptions&); + TransitionOptions getTextHaloWidthTransition() const; static DataDrivenPropertyValue<float> getDefaultTextHaloBlur(); - DataDrivenPropertyValue<float> getTextHaloBlur(const optional<std::string>& klass = {}) const; - void setTextHaloBlur(DataDrivenPropertyValue<float>, const optional<std::string>& klass = {}); - void setTextHaloBlurTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getTextHaloBlurTransition(const optional<std::string>& klass = {}) const; + DataDrivenPropertyValue<float> getTextHaloBlur() const; + void setTextHaloBlur(DataDrivenPropertyValue<float>); + void setTextHaloBlurTransition(const TransitionOptions&); + TransitionOptions getTextHaloBlurTransition() const; static PropertyValue<std::array<float, 2>> getDefaultTextTranslate(); - PropertyValue<std::array<float, 2>> getTextTranslate(const optional<std::string>& klass = {}) const; - void setTextTranslate(PropertyValue<std::array<float, 2>>, const optional<std::string>& klass = {}); - void setTextTranslateTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getTextTranslateTransition(const optional<std::string>& klass = {}) const; + PropertyValue<std::array<float, 2>> getTextTranslate() const; + void setTextTranslate(PropertyValue<std::array<float, 2>>); + void setTextTranslateTransition(const TransitionOptions&); + TransitionOptions getTextTranslateTransition() const; static PropertyValue<TranslateAnchorType> getDefaultTextTranslateAnchor(); - PropertyValue<TranslateAnchorType> getTextTranslateAnchor(const optional<std::string>& klass = {}) const; - void setTextTranslateAnchor(PropertyValue<TranslateAnchorType>, const optional<std::string>& klass = {}); - void setTextTranslateAnchorTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - TransitionOptions getTextTranslateAnchorTransition(const optional<std::string>& klass = {}) const; + PropertyValue<TranslateAnchorType> getTextTranslateAnchor() const; + void setTextTranslateAnchor(PropertyValue<TranslateAnchorType>); + void setTextTranslateAnchorTransition(const TransitionOptions&); + TransitionOptions getTextTranslateAnchorTransition() const; // 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/position.hpp b/include/mbgl/style/position.hpp index 078e62bda8..3be8d1c55e 100644 --- a/include/mbgl/style/position.hpp +++ b/include/mbgl/style/position.hpp @@ -9,7 +9,7 @@ namespace style { class Position { public: Position() = default; - Position(const std::array<float, 3>& position_) + Position(std::array<float, 3>& position_) : radial(position_[0]), azimuthal(position_[1]), polar(position_[2]) { calculateCartesian(); }; diff --git a/include/mbgl/style/property_value.hpp b/include/mbgl/style/property_value.hpp index 8bec7388e5..02d3a31148 100644 --- a/include/mbgl/style/property_value.hpp +++ b/include/mbgl/style/property_value.hpp @@ -35,9 +35,13 @@ public: const CameraFunction<T>& asCameraFunction() const { return value.template get<CameraFunction<T>>(); } template <typename Evaluator> - auto evaluate(const Evaluator& evaluator) const { + auto evaluate(const Evaluator& evaluator, TimePoint = {}) const { return Value::visit(value, evaluator); } + + bool hasDataDrivenPropertyDifference(const PropertyValue<T>&) const { + return false; + } }; } // namespace style diff --git a/include/mbgl/style/source.hpp b/include/mbgl/style/source.hpp index 4c82e472a6..cec9619451 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; } - const std::string& getID() const; + SourceType getType() 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/image_source.hpp b/include/mbgl/style/sources/image_source.hpp new file mode 100644 index 0000000000..009764291f --- /dev/null +++ b/include/mbgl/style/sources/image_source.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include <mbgl/style/source.hpp> +#include <mbgl/util/image.hpp> +#include <mbgl/util/optional.hpp> + +namespace mbgl { +class LatLng; +class AsyncRequest; + +namespace style { + +class ImageSource : public Source { +public: + ImageSource(std::string id, const std::array<LatLng, 4>); + ~ImageSource() override; + + optional<std::string> getURL() const; + void setURL(const std::string& url); + + void setImage(PremultipliedImage&&); + + void setCoordinates(const std::array<LatLng, 4>&); + std::array<LatLng, 4> getCoordinates() const; + + class Impl; + const Impl& impl() const; + + void loadDescription(FileSource&) final; +private: + optional<std::string> url; + std::unique_ptr<AsyncRequest> req; +}; + +template <> +inline bool Source::is<ImageSource>() const { + return getType() == SourceType::Image; +} + +} // namespace style +} // namespace mbgl 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/style/style.hpp b/include/mbgl/style/style.hpp new file mode 100644 index 0000000000..d6fdbd8f2c --- /dev/null +++ b/include/mbgl/style/style.hpp @@ -0,0 +1,79 @@ +#pragma once + +#include <mbgl/style/transition_options.hpp> +#include <mbgl/map/camera.hpp> +#include <mbgl/util/geo.hpp> + +#include <string> +#include <vector> +#include <memory> + +namespace mbgl { + +class FileSource; +class Scheduler; + +namespace style { + +class Light; +class Image; +class Source; +class Layer; + +class Style { +public: + Style(Scheduler&, FileSource&, float pixelRatio); + ~Style(); + + void loadJSON(const std::string&); + void loadURL(const std::string&); + + std::string getJSON() const; + std::string getURL() const; + + // Defaults + std::string getName() const; + CameraOptions getDefaultCamera() const; + + // TransitionOptions + TransitionOptions getTransitionOptions() const; + void setTransitionOptions(const TransitionOptions&); + + // Light + Light* getLight(); + const Light* getLight() const; + + void setLight(std::unique_ptr<Light>); + + // Images + const Image* getImage(const std::string&) const; + void addImage(std::unique_ptr<Image>); + void removeImage(const std::string&); + + // Sources + std::vector< Source*> getSources(); + std::vector<const Source*> getSources() const; + + Source* getSource(const std::string&); + const Source* getSource(const std::string&) const; + + void addSource(std::unique_ptr<Source>); + std::unique_ptr<Source> removeSource(const std::string& sourceID); + + // Layers + std::vector< Layer*> getLayers(); + std::vector<const Layer*> getLayers() const; + + Layer* getLayer(const std::string&); + const Layer* getLayer(const std::string&) const; + + void addLayer(std::unique_ptr<Layer>, const optional<std::string>& beforeLayerID = {}); + std::unique_ptr<Layer> removeLayer(const std::string& layerID); + + // Private implementation + class Impl; + const std::unique_ptr<Impl> impl; +}; + +} // namespace style +} // namespace mbgl diff --git a/include/mbgl/style/transition_options.hpp b/include/mbgl/style/transition_options.hpp index 1583667025..87a81717a0 100644 --- a/include/mbgl/style/transition_options.hpp +++ b/include/mbgl/style/transition_options.hpp @@ -8,8 +8,13 @@ namespace style { class TransitionOptions { public: - optional<Duration> duration = {}; - optional<Duration> delay = {}; + optional<Duration> duration; + optional<Duration> delay; + + TransitionOptions(optional<Duration> duration_ = {}, + optional<Duration> delay_ = {}) + : duration(std::move(duration_)), + delay(std::move(delay_)) {} TransitionOptions reverseMerge(const TransitionOptions& defaults) const { return { diff --git a/include/mbgl/style/types.hpp b/include/mbgl/style/types.hpp index e0436efb67..ec7358de8c 100644 --- a/include/mbgl/style/types.hpp +++ b/include/mbgl/style/types.hpp @@ -10,7 +10,8 @@ enum class SourceType : uint8_t { Raster, GeoJSON, Video, - Annotations + Annotations, + Image }; namespace style { @@ -67,7 +68,7 @@ enum class TextJustifyType : uint8_t { Right }; -enum class TextAnchorType : uint8_t { +enum class SymbolAnchorType : uint8_t { Center, Left, Right, diff --git a/include/mbgl/tile/tile_id.hpp b/include/mbgl/tile/tile_id.hpp new file mode 100644 index 0000000000..0457dd3a07 --- /dev/null +++ b/include/mbgl/tile/tile_id.hpp @@ -0,0 +1,263 @@ +#pragma once + +#include <mbgl/util/constants.hpp> + +#include <cstdint> +#include <array> +#include <tuple> +#include <forward_list> +#include <algorithm> +#include <iosfwd> +#include <cassert> + +namespace mbgl { + +class OverscaledTileID; +class CanonicalTileID; +class UnwrappedTileID; + +// Has integer z/x/y coordinates +// All tiles must be derived from 0/0/0 (=no tiles outside of the main tile pyramid) +// Used for requesting data; represents data tiles that exist out there. +// z is never larger than the source's maxzoom +class CanonicalTileID { +public: + CanonicalTileID(uint8_t z, uint32_t x, uint32_t y); + bool operator==(const CanonicalTileID&) const; + bool operator!=(const CanonicalTileID&) const; + bool operator<(const CanonicalTileID&) const; + bool isChildOf(const CanonicalTileID&) const; + CanonicalTileID scaledTo(uint8_t z) const; + std::array<CanonicalTileID, 4> children() const; + + const uint8_t z; + const uint32_t x; + const uint32_t y; +}; + +::std::ostream& operator<<(::std::ostream& os, const CanonicalTileID& rhs); +namespace util { +std::string toString(const CanonicalTileID&); +} // namespace util + +// Has integer z/x/y coordinates +// overscaledZ describes the zoom level this tile is intented to represent, e.g. when parsing data +// z is never larger than the source's maxzoom +// z/x/y describe the +class OverscaledTileID { +public: + OverscaledTileID(uint8_t overscaledZ, int16_t wrap, CanonicalTileID); + OverscaledTileID(uint8_t overscaledZ, int16_t wrap, uint8_t z, uint32_t x, uint32_t y); + OverscaledTileID(uint8_t z, uint32_t x, uint32_t y); + explicit OverscaledTileID(const CanonicalTileID&); + explicit OverscaledTileID(CanonicalTileID&&); + bool operator==(const OverscaledTileID&) const; + bool operator!=(const OverscaledTileID&) const; + bool operator<(const OverscaledTileID&) const; + bool isChildOf(const OverscaledTileID&) const; + uint32_t overscaleFactor() const; + OverscaledTileID scaledTo(uint8_t z) const; + UnwrappedTileID toUnwrapped() const; + + const uint8_t overscaledZ; + const int16_t wrap; + const CanonicalTileID canonical; +}; + +::std::ostream& operator<<(::std::ostream& os, const OverscaledTileID& rhs); +namespace util { +std::string toString(const OverscaledTileID&); +} // namespace util + +// Has integer z/x/y coordinates +// wrap describes tiles that are left/right of the main tile pyramid, e.g. when wrapping the world +// Used for describing what position tiles are getting rendered at (= calc the matrix) +// z is never larger than the source's maxzoom +class UnwrappedTileID { +public: + UnwrappedTileID(uint8_t z, int64_t x, int64_t y); + UnwrappedTileID(int16_t wrap, CanonicalTileID); + bool operator==(const UnwrappedTileID&) const; + bool operator!=(const UnwrappedTileID&) const; + bool operator<(const UnwrappedTileID&) const; + bool isChildOf(const UnwrappedTileID&) const; + std::array<UnwrappedTileID, 4> children() const; + OverscaledTileID overscaleTo(uint8_t z) const; + float pixelsToTileUnits(float pixelValue, float zoom) const; + + const int16_t wrap; + const CanonicalTileID canonical; +}; + +::std::ostream& operator<<(::std::ostream& os, const UnwrappedTileID& rhs); +namespace util { +std::string toString(const UnwrappedTileID&); +} // namespace util + +inline CanonicalTileID::CanonicalTileID(uint8_t z_, uint32_t x_, uint32_t y_) : z(z_), x(x_), y(y_) { + assert(z <= 32); + assert(x < (1ull << z)); + assert(y < (1ull << z)); +} + +inline bool CanonicalTileID::operator==(const CanonicalTileID& rhs) const { + return z == rhs.z && x == rhs.x && y == rhs.y; +} + +inline bool CanonicalTileID::operator!=(const CanonicalTileID& rhs) const { + return z != rhs.z || x != rhs.x || y != rhs.y; +} + +inline bool CanonicalTileID::operator<(const CanonicalTileID& rhs) const { + return std::tie(z, x, y) < std::tie(rhs.z, rhs.x, rhs.y); +} + +inline bool CanonicalTileID::isChildOf(const CanonicalTileID& parent) const { + // We're first testing for z == 0, to avoid a 32 bit shift, which is undefined. + return parent.z == 0 || + (parent.z < z && parent.x == (x >> (z - parent.z)) && parent.y == (y >> (z - parent.z))); +} + +inline CanonicalTileID CanonicalTileID::scaledTo(uint8_t targetZ) const { + if (targetZ <= z) { + return { targetZ, x >> (z - targetZ), y >> (z - targetZ) }; // parent or same + } else { + return { targetZ, x << (targetZ - z), y << (targetZ - z) }; // child + } +} + +inline std::array<CanonicalTileID, 4> CanonicalTileID::children() const { + const uint8_t childZ = z + 1; + const uint32_t childX = x * 2; + const uint32_t childY = y * 2; + return { { + { childZ, childX, childY }, + { childZ, childX, childY + 1 }, + { childZ, childX + 1, childY }, + { childZ, childX + 1, childY + 1 }, + } }; +} + +inline OverscaledTileID::OverscaledTileID(uint8_t overscaledZ_, int16_t wrap_, CanonicalTileID canonical_) + : overscaledZ(overscaledZ_), wrap(wrap_), canonical(std::move(canonical_)) { + assert(overscaledZ >= canonical.z); +} + +inline OverscaledTileID::OverscaledTileID(uint8_t overscaledZ_, int16_t wrap_, uint8_t z, uint32_t x, uint32_t y) + : overscaledZ(overscaledZ_), wrap(wrap_), canonical(z, x, y) { + assert(overscaledZ >= canonical.z); +} + +inline OverscaledTileID::OverscaledTileID(uint8_t z, uint32_t x, uint32_t y) + : overscaledZ(z), wrap(0), canonical(z, x, y) { +} + +inline OverscaledTileID::OverscaledTileID(const CanonicalTileID& canonical_) + : overscaledZ(canonical_.z), wrap(0), canonical(canonical_) { + assert(overscaledZ >= canonical.z); +} + +inline OverscaledTileID::OverscaledTileID(CanonicalTileID&& canonical_) + : overscaledZ(canonical_.z), wrap(0), canonical(std::forward<CanonicalTileID>(canonical_)) { + assert(overscaledZ >= canonical.z); +} + +inline bool OverscaledTileID::operator==(const OverscaledTileID& rhs) const { + return overscaledZ == rhs.overscaledZ && wrap == rhs.wrap &&canonical == rhs.canonical; +} + +inline bool OverscaledTileID::operator!=(const OverscaledTileID& rhs) const { + return overscaledZ != rhs.overscaledZ || wrap != rhs.wrap || canonical != rhs.canonical; +} + +inline bool OverscaledTileID::operator<(const OverscaledTileID& rhs) const { + return std::tie(overscaledZ, wrap, canonical) < std::tie(rhs.overscaledZ, rhs.wrap, rhs.canonical); +} + +inline uint32_t OverscaledTileID::overscaleFactor() const { + return 1u << (overscaledZ - canonical.z); +} + +inline bool OverscaledTileID::isChildOf(const OverscaledTileID& rhs) const { + return overscaledZ > rhs.overscaledZ && + (canonical == rhs.canonical || canonical.isChildOf(rhs.canonical)); +} + +inline OverscaledTileID OverscaledTileID::scaledTo(uint8_t z) const { + return { z, wrap, z >= canonical.z ? canonical : canonical.scaledTo(z) }; +} + +inline UnwrappedTileID OverscaledTileID::toUnwrapped() const { + return { wrap, canonical }; +} + +inline UnwrappedTileID::UnwrappedTileID(uint8_t z_, int64_t x_, int64_t y_) + : wrap((x_ < 0 ? x_ - (1ll << z_) + 1 : x_) / (1ll << z_)), + canonical( + z_, + static_cast<uint32_t>(x_ - wrap * (1ll << z_)), + y_ < 0 ? 0 : std::min(static_cast<uint32_t>(y_), static_cast<uint32_t>(1ull << z_) - 1)) { +} + +inline UnwrappedTileID::UnwrappedTileID(int16_t wrap_, CanonicalTileID canonical_) + : wrap(wrap_), canonical(std::move(canonical_)) { +} + +inline bool UnwrappedTileID::operator==(const UnwrappedTileID& rhs) const { + return wrap == rhs.wrap && canonical == rhs.canonical; +} + +inline bool UnwrappedTileID::operator!=(const UnwrappedTileID& rhs) const { + return wrap != rhs.wrap || canonical != rhs.canonical; +} + +inline bool UnwrappedTileID::operator<(const UnwrappedTileID& rhs) const { + return std::tie(wrap, canonical) < std::tie(rhs.wrap, rhs.canonical); +} + +inline bool UnwrappedTileID::isChildOf(const UnwrappedTileID& parent) const { + return wrap == parent.wrap && canonical.isChildOf(parent.canonical); +} + +inline std::array<UnwrappedTileID, 4> UnwrappedTileID::children() const { + const uint8_t childZ = canonical.z + 1; + const uint32_t childX = canonical.x * 2; + const uint32_t childY = canonical.y * 2; + return { { + { wrap, { childZ, childX, childY } }, + { wrap, { childZ, childX, childY + 1 } }, + { wrap, { childZ, childX + 1, childY } }, + { wrap, { childZ, childX + 1, childY + 1 } }, + } }; +} + +inline OverscaledTileID UnwrappedTileID::overscaleTo(const uint8_t overscaledZ) const { + assert(overscaledZ >= canonical.z); + return { overscaledZ, wrap, canonical }; +} + +inline float UnwrappedTileID::pixelsToTileUnits(const float pixelValue, const float zoom) const { + return pixelValue * (util::EXTENT / (util::tileSize * std::pow(2, zoom - canonical.z))); +} + +} // namespace mbgl + +namespace std { + +template <> +struct hash<mbgl::CanonicalTileID> { + size_t operator()(const mbgl::CanonicalTileID& id) const; +}; + +template <> +struct hash<mbgl::UnwrappedTileID> { + size_t operator()(const mbgl::UnwrappedTileID& id) const; +}; + +template <> +struct hash<mbgl::OverscaledTileID> { + size_t operator()(const mbgl::OverscaledTileID& id) const; +}; + +} // namespace std + diff --git a/include/mbgl/util/constants.hpp b/include/mbgl/util/constants.hpp index dbc4bddde5..d5e55065c4 100644 --- a/include/mbgl/util/constants.hpp +++ b/include/mbgl/util/constants.hpp @@ -38,10 +38,13 @@ constexpr double MIN_ZOOM = 0.0; constexpr double MAX_ZOOM = 25.5; constexpr float MIN_ZOOM_F = MIN_ZOOM; constexpr float MAX_ZOOM_F = MAX_ZOOM; +constexpr uint8_t DEFAULT_MAX_ZOOM = 22; + +constexpr uint8_t DEFAULT_PREFETCH_ZOOM_DELTA = 4; constexpr uint64_t DEFAULT_MAX_CACHE_SIZE = 50 * 1024 * 1024; -constexpr Duration DEFAULT_FADE_DURATION = Milliseconds(300); +constexpr Duration DEFAULT_TRANSITION_DURATION = Milliseconds(300); constexpr Seconds CLOCK_SKEW_RETRY_TIMEOUT { 30 }; constexpr UnitBezier DEFAULT_TRANSITION_EASE = { 0, 0, 0.25, 1 }; @@ -58,7 +61,6 @@ extern const bool tileParseWarnings; extern const bool styleParseWarnings; extern const bool spriteWarnings; extern const bool renderWarnings; -extern const bool renderTree; extern const bool labelTextMissingWarning; extern const bool missingFontStackWarning; extern const bool missingFontFaceWarning; diff --git a/include/mbgl/util/convert.hpp b/include/mbgl/util/convert.hpp index c2b3d9950d..02ec7feef9 100644 --- a/include/mbgl/util/convert.hpp +++ b/include/mbgl/util/convert.hpp @@ -1,3 +1,5 @@ +#include <mbgl/util/util.hpp> + #include <array> #include <type_traits> #include <utility> @@ -7,8 +9,8 @@ namespace util { template<typename To, typename From, std::size_t Size, typename = std::enable_if_t<std::is_convertible<From, To>::value>> -constexpr std::array<To, Size> convert(const std::array<From, Size>&from) { - std::array<To, Size> to {}; +MBGL_CONSTEXPR std::array<To, Size> convert(const std::array<From, Size>&from) { + std::array<To, Size> to {{}}; std::copy(std::begin(from), std::end(from), std::begin(to)); return to; } diff --git a/include/mbgl/util/image.hpp b/include/mbgl/util/image.hpp index a41b8462bd..4887058f79 100644 --- a/include/mbgl/util/image.hpp +++ b/include/mbgl/util/image.hpp @@ -5,6 +5,7 @@ #include <mbgl/util/size.hpp> #include <string> +#include <cstring> #include <memory> #include <algorithm> @@ -66,9 +67,9 @@ public: template <typename T = Image> T clone() const { - T copy(size); - std::copy(data.get(), data.get() + bytes(), copy.data.get()); - return copy; + T copy_(size); + std::copy(data.get(), data.get() + bytes(), copy_.data.get()); + return copy_; } size_t stride() const { return channels * size.width; } @@ -78,10 +79,52 @@ public: std::fill(data.get(), data.get() + bytes(), value); } + void resize(Size size_) { + if (size == size_) { + return; + } + Image newImage(size_); + newImage.fill(0); + copy(*this, newImage, {0, 0}, {0, 0}, { + std::min(size.width, size_.width), + std::min(size.height, size_.height) + }); + operator=(std::move(newImage)); + } + + // Clears the rect area specified by `pt` and `size` from `dstImage`. + static void clear(Image& dstImg, const Point<uint32_t>& pt, const Size& size) { + if (size.isEmpty()) { + return; + } + + if (!dstImg.valid()) { + throw std::invalid_argument("invalid destination for image clear"); + } + + if (size.width > dstImg.size.width || + size.height > dstImg.size.height || + pt.x > dstImg.size.width - size.width || + pt.y > dstImg.size.height - size.height) { + throw std::out_of_range("out of range destination coordinates for image clear"); + } + + uint8_t* dstData = dstImg.data.get(); + + for (uint32_t y = 0; y < size.height; y++) { + const std::size_t dstOffset = (pt.y + y) * dstImg.stride() + pt.x * channels; + std::memset(dstData + dstOffset, 0, size.width * channels); + } + } + // Copy image data within `rect` from `src` to the rectangle of the same size at `pt` // in `dst`. If the specified bounds exceed the bounds of the source or destination, // throw `std::out_of_range`. Must not be used to move data within a single Image. static void copy(const Image& srcImg, Image& dstImg, const Point<uint32_t>& srcPt, const Point<uint32_t>& dstPt, const Size& size) { + if (size.isEmpty()) { + return; + } + if (!srcImg.valid()) { throw std::invalid_argument("invalid source for image copy"); } diff --git a/include/mbgl/util/immutable.hpp b/include/mbgl/util/immutable.hpp new file mode 100644 index 0000000000..eb26c0d282 --- /dev/null +++ b/include/mbgl/util/immutable.hpp @@ -0,0 +1,133 @@ +#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, class U> friend Immutable<S> staticImmutableCast(const Immutable<U>&); +}; + +template <class S, class U> +Immutable<S> staticImmutableCast(const Immutable<U>& u) { + return Immutable<S>(std::static_pointer_cast<const S>(u.ptr)); +} + +/** + * Constrained mutation of an immutable reference. Makes a temporarily-mutable copy of the + * input Immutable using the inner type's copy constructor, runs the given callable on the + * mutable copy, and then freezes the copy and reassigns it to the input reference. + * + * Note that other Immutables referring to the same inner instance are not affected; they + * continue to referencing the original immutable instance. + */ +template <class T, class Fn> +void mutate(Immutable<T>& immutable, Fn&& fn) { + Mutable<T> mut = makeMutable<T>(*immutable); + std::forward<Fn>(fn)(*mut); + immutable = std::move(mut); +} + +} // namespace mbgl diff --git a/include/mbgl/util/indexed_tuple.hpp b/include/mbgl/util/indexed_tuple.hpp index a414639530..fd0b931d36 100644 --- a/include/mbgl/util/indexed_tuple.hpp +++ b/include/mbgl/util/indexed_tuple.hpp @@ -31,16 +31,13 @@ public: using std::tuple<Ts...>::tuple; template <class I> - static constexpr std::size_t Index = TypeIndex<I, Is...>::value; - - template <class I> auto& get() { - return std::get<Index<I>>(*this); + return std::get<TypeIndex<I, Is...>::value>(*this); } template <class I> const auto& get() const { - return std::get<Index<I>>(*this); + return std::get<TypeIndex<I, Is...>::value>(*this); } template <class... Js, class... Us> diff --git a/include/mbgl/util/interpolate.hpp b/include/mbgl/util/interpolate.hpp index a2103f18b2..6738987598 100644 --- a/include/mbgl/util/interpolate.hpp +++ b/include/mbgl/util/interpolate.hpp @@ -95,7 +95,11 @@ struct Interpolator<std::vector<T>> : Uninterpolated {}; template <class T> -constexpr bool Interpolatable = !std::is_base_of<Uninterpolated, Interpolator<T>>::value; +struct Interpolatable + : std::conditional_t< + !std::is_base_of<Uninterpolated, Interpolator<T>>::value, + std::true_type, + std::false_type> {}; } // namespace util } // namespace mbgl diff --git a/include/mbgl/util/noncopyable.hpp b/include/mbgl/util/noncopyable.hpp index 105a76a9a0..8cb7e198d9 100644 --- a/include/mbgl/util/noncopyable.hpp +++ b/include/mbgl/util/noncopyable.hpp @@ -7,15 +7,17 @@ namespace non_copyable_ class noncopyable { +public: + noncopyable( noncopyable const& ) = delete; + noncopyable& operator=(noncopyable const& ) = delete; + protected: constexpr noncopyable() = default; ~noncopyable() = default; - noncopyable( noncopyable const& ) = delete; - noncopyable& operator=(noncopyable const& ) = delete; }; } // namespace non_copyable_ -typedef non_copyable_::noncopyable noncopyable; +using noncopyable = non_copyable_::noncopyable; } // namespace util } // namespace mbgl diff --git a/include/mbgl/util/projection.hpp b/include/mbgl/util/projection.hpp index 3cc1146513..f64502c5bc 100644 --- a/include/mbgl/util/projection.hpp +++ b/include/mbgl/util/projection.hpp @@ -75,10 +75,7 @@ public: } static Point<double> project(const LatLng& latLng, double scale) { - return Point<double> { - util::LONGITUDE_MAX + latLng.longitude(), - util::LONGITUDE_MAX - util::RAD2DEG * std::log(std::tan(M_PI / 4 + latLng.latitude() * M_PI / util::DEGREES_MAX)) - } * worldSize(scale) / util::DEGREES_MAX; + return project_(latLng, worldSize(scale)); } static LatLng unproject(const Point<double>& p, double scale, LatLng::WrapMode wrapMode = LatLng::Unwrapped) { @@ -89,6 +86,23 @@ public: wrapMode }; } + + // Project lat, lon to point in a zoom-dependent world size + static Point<double> project(const LatLng& point, uint8_t zoom, uint16_t tileSize) { + const double t2z = tileSize * std::pow(2, zoom); + Point<double> pt = project_(point, t2z); + // Flip y coordinate + auto x = std::round(std::min(pt.x, t2z)); + auto y = std::round(std::min(t2z - pt.y, t2z)); + return { x, y }; + } +private: + static Point<double> project_(const LatLng& latLng, double worldSize) { + return Point<double> { + util::LONGITUDE_MAX + latLng.longitude(), + util::LONGITUDE_MAX - util::RAD2DEG * std::log(std::tan(M_PI / 4 + latLng.latitude() * M_PI / util::DEGREES_MAX)) + } * worldSize / util::DEGREES_MAX; + } }; } // namespace mbgl diff --git a/include/mbgl/util/range.hpp b/include/mbgl/util/range.hpp index f7fa92eb8b..5591a22a1f 100644 --- a/include/mbgl/util/range.hpp +++ b/include/mbgl/util/range.hpp @@ -1,3 +1,5 @@ +#include <utility> + #pragma once namespace mbgl { @@ -5,8 +7,8 @@ namespace mbgl { template <class T> class Range { public: - constexpr Range(const T& min_, const T& max_) - : min(min_), max(max_) {} + constexpr Range(T min_, T max_) + : min(std::move(min_)), max(std::move(max_)) {} T min; T max; diff --git a/include/mbgl/util/run_loop.hpp b/include/mbgl/util/run_loop.hpp index 5236850d83..acbea80273 100644 --- a/include/mbgl/util/run_loop.hpp +++ b/include/mbgl/util/run_loop.hpp @@ -16,7 +16,7 @@ namespace mbgl { namespace util { -typedef void * LOOP_HANDLE; +using LOOP_HANDLE = void *; class RunLoop : public Scheduler, private util::noncopyable { @@ -62,14 +62,11 @@ public: push(task); return std::make_unique<WorkRequest>(task); } - - // Invoke fn(args...) on this RunLoop, then invoke callback(results...) on the current RunLoop. - template <class Fn, class... Args> - std::unique_ptr<AsyncRequest> - invokeWithCallback(Fn&& fn, Args&&... args) { - std::shared_ptr<WorkTask> task = WorkTask::makeWithCallback(std::forward<Fn>(fn), std::forward<Args>(args)...); - push(task); - return std::make_unique<WorkRequest>(task); + + void schedule(std::weak_ptr<Mailbox> mailbox) override { + invoke([mailbox] () { + Mailbox::maybeReceive(mailbox); + }); } class Impl; @@ -81,12 +78,6 @@ private: void push(std::shared_ptr<WorkTask>); - void schedule(std::weak_ptr<Mailbox> mailbox) override { - invoke([mailbox] () { - Mailbox::maybeReceive(mailbox); - }); - } - void withMutex(std::function<void()>&& fn) { std::lock_guard<std::mutex> lock(mutex); fn(); diff --git a/include/mbgl/util/size.hpp b/include/mbgl/util/size.hpp index 45c303969c..12c0ad056b 100644 --- a/include/mbgl/util/size.hpp +++ b/include/mbgl/util/size.hpp @@ -15,6 +15,10 @@ public: constexpr uint32_t area() const { return width * height; } + + constexpr float aspectRatio() const { + return static_cast<float>(width) / static_cast<float>(height); + } constexpr bool isEmpty() const { return width == 0 || height == 0; diff --git a/include/mbgl/util/string.hpp b/include/mbgl/util/string.hpp index de061647b5..82d317c620 100644 --- a/include/mbgl/util/string.hpp +++ b/include/mbgl/util/string.hpp @@ -1,9 +1,34 @@ #pragma once +#include <sstream> #include <string> #include <cassert> +#include <cstdlib> #include <exception> +// Polyfill needed by Qt when building for Android with GCC +#if defined(__ANDROID__) && defined(__GLIBCXX__) + +namespace std { + +template <typename T> +std::string to_string(T value) +{ + std::ostringstream oss; + oss << value; + + return oss.str(); +} + +inline int stoi(const std::string &str) +{ + return atoi(str.c_str()); +} + +} // namespace std + +#endif + namespace mbgl { namespace util { diff --git a/include/mbgl/util/thread.hpp b/include/mbgl/util/thread.hpp new file mode 100644 index 0000000000..672eebf6db --- /dev/null +++ b/include/mbgl/util/thread.hpp @@ -0,0 +1,161 @@ +#pragma once + +#include <mbgl/actor/actor.hpp> +#include <mbgl/actor/mailbox.hpp> +#include <mbgl/actor/scheduler.hpp> +#include <mbgl/util/platform.hpp> +#include <mbgl/util/run_loop.hpp> +#include <mbgl/util/util.hpp> + +#include <cassert> +#include <future> +#include <memory> +#include <mutex> +#include <queue> +#include <string> +#include <thread> +#include <utility> + +namespace mbgl { +namespace util { + +// Manages a thread with `Object`. + +// Upon creation of this object, it launches a thread and creates an object of type `Object` +// in that thread. When the `Thread<>` object is destructed, the destructor waits +// for thread termination. The `Thread<>` constructor blocks until the thread and +// the `Object` are fully created, so after the object creation, it's safe to obtain the +// `Object` stored in this thread. The thread created will always have low priority on +// the platforms that support setting thread priority. +// +// The following properties make this class different from `ThreadPool`: +// +// - Only one thread is created. +// - `Object` will live in a single thread, providing thread affinity. +// - It is safe to use `ThreadLocal` in an `Object` managed by `Thread<>` +// - A `RunLoop` is created for the `Object` thread. +// - `Object` can use `Timer` and do asynchronous I/O, like wait for sockets events. +// +template<class Object> +class Thread : public Scheduler { +public: + template <class... Args> + Thread(const std::string& name, Args&&... args) { + std::promise<void> running; + + thread = std::thread([&] { + platform::setCurrentThreadName(name); + platform::makeThreadLowPriority(); + + util::RunLoop loop_(util::RunLoop::Type::New); + loop = &loop_; + + object = std::make_unique<Actor<Object>>(*this, std::forward<Args>(args)...); + running.set_value(); + + loop->run(); + loop = nullptr; + }); + + running.get_future().get(); + } + + ~Thread() override { + if (paused) { + resume(); + } + + std::promise<void> joinable; + + // Kill the actor, so we don't get more + // messages posted on this scheduler after + // we delete the RunLoop. + loop->invoke([&] { + object.reset(); + joinable.set_value(); + }); + + joinable.get_future().get(); + + loop->stop(); + thread.join(); + } + + // Returns a non-owning reference to `Object` that + // can be used to send messages to `Object`. It is safe + // to the non-owning reference to outlive this object + // and be used after the `Thread<>` gets destroyed. + ActorRef<std::decay_t<Object>> actor() const { + return object->self(); + } + + // Pauses the `Object` thread. It will prevent the object to wake + // up from events such as timers and file descriptor I/O. Messages + // sent to a paused `Object` will be queued and only processed after + // `resume()` is called. + void pause() { + MBGL_VERIFY_THREAD(tid); + + assert(!paused); + + paused = std::make_unique<std::promise<void>>(); + resumed = std::make_unique<std::promise<void>>(); + + auto pausing = paused->get_future(); + + loop->invoke([this] { + auto resuming = resumed->get_future(); + paused->set_value(); + resuming.get(); + }); + + pausing.get(); + } + + // Resumes the `Object` thread previously paused by `pause()`. + void resume() { + MBGL_VERIFY_THREAD(tid); + + assert(paused); + + resumed->set_value(); + + resumed.reset(); + paused.reset(); + } + +private: + MBGL_STORE_THREAD(tid); + + void schedule(std::weak_ptr<Mailbox> mailbox) override { + { + std::lock_guard<std::mutex> lock(mutex); + queue.push(mailbox); + } + + loop->invoke([this] { receive(); }); + } + + void receive() { + std::unique_lock<std::mutex> lock(mutex); + + auto mailbox = queue.front(); + queue.pop(); + lock.unlock(); + + Mailbox::maybeReceive(mailbox); + } + + std::mutex mutex; + std::queue<std::weak_ptr<Mailbox>> queue; + std::thread thread; + std::unique_ptr<Actor<Object>> object; + + std::unique_ptr<std::promise<void>> paused; + std::unique_ptr<std::promise<void>> resumed; + + util::RunLoop* loop = nullptr; +}; + +} // namespace util +} // namespace mbgl diff --git a/include/mbgl/util/tileset.hpp b/include/mbgl/util/tileset.hpp index 1f28a5039a..61aa47d4ea 100644 --- a/include/mbgl/util/tileset.hpp +++ b/include/mbgl/util/tileset.hpp @@ -1,6 +1,7 @@ #pragma once #include <mbgl/util/range.hpp> +#include <mbgl/util/constants.hpp> #include <vector> #include <string> @@ -13,11 +14,25 @@ public: enum class Scheme : bool { XYZ, TMS }; std::vector<std::string> tiles; - Range<uint8_t> zoomRange { 0, 22 }; + Range<uint8_t> zoomRange; std::string attribution; - Scheme scheme = Scheme::XYZ; + Scheme scheme; + + Tileset(std::vector<std::string> tiles_ = std::vector<std::string>(), + Range<uint8_t> zoomRange_ = { 0, util::DEFAULT_MAX_ZOOM }, + std::string attribution_ = {}, + Scheme scheme_ = Scheme::XYZ) + : tiles(std::move(tiles_)), + zoomRange(std::move(zoomRange_)), + attribution(std::move(attribution_)), + scheme(scheme_) {} // 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/include/mbgl/util/unitbezier.hpp b/include/mbgl/util/unitbezier.hpp index 3a4994917b..6e644e2d1f 100644 --- a/include/mbgl/util/unitbezier.hpp +++ b/include/mbgl/util/unitbezier.hpp @@ -34,11 +34,11 @@ struct UnitBezier { // Calculate the polynomial coefficients, implicit first and last control points are (0,0) and (1,1). constexpr UnitBezier(double p1x, double p1y, double p2x, double p2y) : cx(3.0 * p1x) - , bx(3.0 * (p2x - p1x) - cx) - , ax(1.0 - cx - bx) + , bx(3.0 * (p2x - p1x) - (3.0 * p1x)) + , ax(1.0 - (3.0 * p1x) - (3.0 * (p2x - p1x) - (3.0 * p1x))) , cy(3.0 * p1y) - , by(3.0 * (p2y - p1y) - cy) - , ay(1.0 - cy - by) { + , by(3.0 * (p2y - p1y) - (3.0 * p1y)) + , ay(1.0 - (3.0 * p1y) - (3.0 * (p2y - p1y) - (3.0 * p1y))) { } double sampleCurveX(double t) const { diff --git a/include/mbgl/util/util.hpp b/include/mbgl/util/util.hpp index c5a7cb3780..7960b40299 100644 --- a/include/mbgl/util/util.hpp +++ b/include/mbgl/util/util.hpp @@ -12,3 +12,10 @@ #define MBGL_VERIFY_THREAD(tid) #endif + +// GCC 4.9 compatibility +#if !defined(__GNUC__) || __GNUC__ >= 5 +#define MBGL_CONSTEXPR constexpr +#else +#define MBGL_CONSTEXPR inline +#endif diff --git a/include/mbgl/util/work_task.hpp b/include/mbgl/util/work_task.hpp index dda8e5d00f..f2dcfcfe86 100644 --- a/include/mbgl/util/work_task.hpp +++ b/include/mbgl/util/work_task.hpp @@ -18,9 +18,6 @@ public: template <class Fn, class... Args> static std::shared_ptr<WorkTask> make(Fn&&, Args&&...); - - template <class Fn, class... Args> - static std::shared_ptr<WorkTask> makeWithCallback(Fn&&, Args&&...); }; } // namespace mbgl diff --git a/include/mbgl/util/work_task_impl.hpp b/include/mbgl/util/work_task_impl.hpp index 8ebc7d45f8..276e0d6237 100644 --- a/include/mbgl/util/work_task_impl.hpp +++ b/include/mbgl/util/work_task_impl.hpp @@ -62,48 +62,4 @@ std::shared_ptr<WorkTask> WorkTask::make(Fn&& fn, Args&&... args) { flag); } -namespace detail { -template <class Tuple, size_t... Indexes> -auto packageArgumentsAndCallback(std::shared_ptr<std::atomic<bool>> flag, - Tuple&& args, - std::index_sequence<Indexes...>) { - auto callback = std::get<sizeof...(Indexes)>(args); - - // Create a lambda L1 that invokes another lambda L2 on the current RunLoop R, that calls - // the callback C. Both lambdas check the flag before proceeding. L1 needs to check the flag - // because if the request was cancelled, then R might have been destroyed. L2 needs to check - // the flag because the request may have been cancelled after L2 was invoked but before it - // began executing. - - auto l2 = [flag, callback] (auto&&... results) { - if (!*flag) { - callback(std::forward<decltype(results)>(results)...); - } - }; - - auto l1 = [flag, current = util::RunLoop::Get(), l2_ = l2] (auto&&... results) { - if (!*flag) { - current->invoke(l2_, std::forward<decltype(results)>(results)...); - } - }; - - return std::make_tuple(std::get<Indexes>(std::forward<Tuple>(args))..., l1); -} -} // namespace detail - -template <class Fn, class... Args> -std::shared_ptr<WorkTask> WorkTask::makeWithCallback(Fn&& fn, Args&&... args) { - auto flag = std::make_shared<std::atomic<bool>>(); - *flag = false; - - auto tuple = detail::packageArgumentsAndCallback(flag, - std::forward_as_tuple(std::forward<Args>(args)...), - std::make_index_sequence<sizeof...(Args) - 1>()); - - return std::make_shared<WorkTaskImpl<std::decay_t<Fn>, decltype(tuple)>>( - std::forward<Fn>(fn), - std::move(tuple), - flag); -} - } // namespace mbgl |