summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorThiago Marcos P. Santos <tmpsantos@gmail.com>2017-08-07 19:19:32 +0300
committerThiago Marcos P. Santos <tmpsantos@gmail.com>2017-08-09 18:02:46 +0300
commitc53896caefc96a8c18ab746026330ddc4fc0338e (patch)
tree8f562b0c416d6c99f7b565e58b758701f6081677 /include
parent9ecbe3642fb4a53b558598239b59bf1d0224c25b (diff)
downloadqtlocation-mapboxgl-c53896caefc96a8c18ab746026330ddc4fc0338e.tar.gz
Bump Mapbox GL Nativeqt-v1.1.0
mapbox-gl-native @ edd7948893fcd40a24d96b790e21d3dd028cecbe
Diffstat (limited to 'include')
-rw-r--r--include/mbgl/actor/actor.hpp98
-rw-r--r--include/mbgl/actor/actor_ref.hpp64
-rw-r--r--include/mbgl/actor/mailbox.hpp35
-rw-r--r--include/mbgl/actor/message.hpp82
-rw-r--r--include/mbgl/actor/scheduler.hpp38
-rw-r--r--include/mbgl/annotation/annotation.hpp55
-rw-r--r--include/mbgl/gl/gl.hpp50
-rw-r--r--include/mbgl/map/backend.hpp64
-rw-r--r--include/mbgl/map/camera.hpp15
-rw-r--r--include/mbgl/map/change.hpp26
-rw-r--r--include/mbgl/map/map.hpp153
-rw-r--r--include/mbgl/map/map_observer.hpp44
-rw-r--r--include/mbgl/map/view.hpp20
-rw-r--r--include/mbgl/math/log2.hpp4
-rw-r--r--include/mbgl/renderer/backend_scope.hpp35
-rw-r--r--include/mbgl/renderer/query.hpp43
-rw-r--r--include/mbgl/renderer/renderer.hpp53
-rw-r--r--include/mbgl/renderer/renderer_backend.hpp90
-rw-r--r--include/mbgl/renderer/renderer_frontend.hpp31
-rw-r--r--include/mbgl/sprite/sprite_image.hpp29
-rw-r--r--include/mbgl/storage/default_file_source.hpp44
-rw-r--r--include/mbgl/storage/online_file_source.hpp8
-rw-r--r--include/mbgl/storage/resource.hpp7
-rw-r--r--include/mbgl/storage/resource_transform.hpp26
-rw-r--r--include/mbgl/storage/response.hpp14
-rw-r--r--include/mbgl/style/conversion.hpp40
-rw-r--r--include/mbgl/style/conversion/constant.hpp94
-rw-r--r--include/mbgl/style/conversion/coordinate.hpp37
-rw-r--r--include/mbgl/style/conversion/data_driven_property_value.hpp46
-rw-r--r--include/mbgl/style/conversion/filter.hpp219
-rw-r--r--include/mbgl/style/conversion/function.hpp403
-rw-r--r--include/mbgl/style/conversion/geojson.hpp14
-rw-r--r--include/mbgl/style/conversion/geojson_options.hpp20
-rw-r--r--include/mbgl/style/conversion/layer.hpp114
-rw-r--r--include/mbgl/style/conversion/light.hpp122
-rw-r--r--include/mbgl/style/conversion/make_property_setters.hpp273
-rw-r--r--include/mbgl/style/conversion/make_property_setters.hpp.ejs47
-rw-r--r--include/mbgl/style/conversion/position.hpp29
-rw-r--r--include/mbgl/style/conversion/property_setter.hpp61
-rw-r--r--include/mbgl/style/conversion/property_value.hpp16
-rw-r--r--include/mbgl/style/conversion/source.hpp126
-rw-r--r--include/mbgl/style/conversion/tileset.hpp20
-rw-r--r--include/mbgl/style/conversion/transition_options.hpp48
-rw-r--r--include/mbgl/style/data_driven_property_value.hpp69
-rw-r--r--include/mbgl/style/filter.hpp104
-rw-r--r--include/mbgl/style/filter_evaluator.hpp97
-rw-r--r--include/mbgl/style/function.hpp40
-rw-r--r--include/mbgl/style/function/camera_function.hpp42
-rw-r--r--include/mbgl/style/function/categorical_stops.hpp40
-rw-r--r--include/mbgl/style/function/composite_categorical_stops.hpp30
-rw-r--r--include/mbgl/style/function/composite_exponential_stops.hpp35
-rw-r--r--include/mbgl/style/function/composite_function.hpp153
-rw-r--r--include/mbgl/style/function/composite_interval_stops.hpp32
-rw-r--r--include/mbgl/style/function/exponential_stops.hpp56
-rw-r--r--include/mbgl/style/function/identity_stops.hpp20
-rw-r--r--include/mbgl/style/function/interval_stops.hpp51
-rw-r--r--include/mbgl/style/function/source_function.hpp60
-rw-r--r--include/mbgl/style/image.hpp31
-rw-r--r--include/mbgl/style/layer.hpp88
-rw-r--r--include/mbgl/style/layer_type.hpp18
-rw-r--r--include/mbgl/style/layers/background_layer.hpp37
-rw-r--r--include/mbgl/style/layers/circle_layer.hpp109
-rw-r--r--include/mbgl/style/layers/custom_layer.hpp17
-rw-r--r--include/mbgl/style/layers/fill_extrusion_layer.hpp71
-rw-r--r--include/mbgl/style/layers/fill_layer.hpp73
-rw-r--r--include/mbgl/style/layers/layer.hpp.ejs77
-rw-r--r--include/mbgl/style/layers/line_layer.hpp105
-rw-r--r--include/mbgl/style/layers/raster_layer.hpp61
-rw-r--r--include/mbgl/style/layers/symbol_layer.hpp211
-rw-r--r--include/mbgl/style/light.hpp53
-rw-r--r--include/mbgl/style/position.hpp68
-rw-r--r--include/mbgl/style/property_value.hpp35
-rw-r--r--include/mbgl/style/source.hpp37
-rw-r--r--include/mbgl/style/sources/geojson_source.hpp33
-rw-r--r--include/mbgl/style/sources/image_source.hpp41
-rw-r--r--include/mbgl/style/sources/raster_source.hpp17
-rw-r--r--include/mbgl/style/sources/vector_source.hpp17
-rw-r--r--include/mbgl/style/style.hpp81
-rw-r--r--include/mbgl/style/transition_options.hpp21
-rw-r--r--include/mbgl/style/types.hpp8
-rw-r--r--include/mbgl/style/undefined.hpp12
-rw-r--r--include/mbgl/util/any.hpp10
-rw-r--r--include/mbgl/util/async_task.hpp24
-rw-r--r--include/mbgl/util/chrono.hpp2
-rw-r--r--include/mbgl/util/color.hpp1
-rw-r--r--include/mbgl/util/compression.hpp4
-rw-r--r--include/mbgl/util/constants.hpp11
-rw-r--r--include/mbgl/util/convert.hpp2
-rw-r--r--include/mbgl/util/enum.hpp38
-rw-r--r--include/mbgl/util/event.hpp2
-rw-r--r--include/mbgl/util/exception.hpp15
-rw-r--r--include/mbgl/util/feature.hpp17
-rw-r--r--include/mbgl/util/geo.hpp210
-rw-r--r--include/mbgl/util/ignore.hpp26
-rw-r--r--include/mbgl/util/image.hpp96
-rw-r--r--include/mbgl/util/immutable.hpp133
-rw-r--r--include/mbgl/util/indexed_tuple.hpp53
-rw-r--r--include/mbgl/util/interpolate.hpp105
-rw-r--r--include/mbgl/util/noncopyable.hpp8
-rw-r--r--include/mbgl/util/premultiply.hpp12
-rw-r--r--include/mbgl/util/projection.hpp41
-rw-r--r--include/mbgl/util/range.hpp6
-rw-r--r--include/mbgl/util/run_loop.hpp11
-rw-r--r--include/mbgl/util/size.hpp19
-rw-r--r--include/mbgl/util/string.hpp17
-rw-r--r--include/mbgl/util/tileset.hpp18
-rw-r--r--include/mbgl/util/type_list.hpp40
-rw-r--r--include/mbgl/util/unitbezier.hpp12
-rw-r--r--include/mbgl/util/version.hpp20
-rw-r--r--include/mbgl/util/work_task.hpp3
-rw-r--r--include/mbgl/util/work_task_impl.hpp44
111 files changed, 4523 insertions, 1484 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
new file mode 100644
index 0000000000..8ecf91701a
--- /dev/null
+++ b/include/mbgl/actor/mailbox.hpp
@@ -0,0 +1,35 @@
+#pragma once
+
+#include <memory>
+#include <mutex>
+#include <queue>
+
+namespace mbgl {
+
+class Scheduler;
+class Message;
+
+class Mailbox : public std::enable_shared_from_this<Mailbox> {
+public:
+ Mailbox(Scheduler&);
+
+ void push(std::unique_ptr<Message>);
+
+ void close();
+ void receive();
+
+ static void maybeReceive(std::weak_ptr<Mailbox>);
+
+private:
+ Scheduler& scheduler;
+
+ std::recursive_mutex receivingMutex;
+ std::mutex pushingMutex;
+
+ bool closed { false };
+
+ std::mutex queueMutex;
+ std::queue<std::unique_ptr<Message>> queue;
+};
+
+} // namespace mbgl
diff --git a/include/mbgl/actor/message.hpp b/include/mbgl/actor/message.hpp
new file mode 100644
index 0000000000..406de425d4
--- /dev/null
+++ b/include/mbgl/actor/message.hpp
@@ -0,0 +1,82 @@
+#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;
+};
+
+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
new file mode 100644
index 0000000000..83689c3348
--- /dev/null
+++ b/include/mbgl/actor/scheduler.hpp
@@ -0,0 +1,38 @@
+#pragma once
+
+#include <memory>
+
+namespace mbgl {
+
+class Mailbox;
+
+/*
+ A `Scheduler` is responsible for coordinating the processing of messages by
+ one or more actors via their mailboxes. It's an abstract interface. Currently,
+ the following concrete implementations exist:
+
+ * `ThreadPool` can coordinate an unlimited number of actors over any number of
+ threads via a pool, preserving the following behaviors:
+
+ - Messages from each individual mailbox are processed in order
+ - Only a single message from a mailbox is processed at a time; there is no
+ concurrency within a 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());
+ Actor<Worker> worker(threadPool, ActorRef<Foo>(*this, mailbox));
+*/
+
+class Scheduler {
+public:
+ virtual ~Scheduler() = default;
+ virtual void schedule(std::weak_ptr<Mailbox>) = 0;
+};
+
+} // namespace mbgl
diff --git a/include/mbgl/annotation/annotation.hpp b/include/mbgl/annotation/annotation.hpp
index 1a107080de..bbe479b5ba 100644
--- a/include/mbgl/annotation/annotation.hpp
+++ b/include/mbgl/annotation/annotation.hpp
@@ -4,6 +4,7 @@
#include <mbgl/util/variant.hpp>
#include <mbgl/util/color.hpp>
#include <mbgl/style/property_value.hpp>
+#include <mbgl/style/data_driven_property_value.hpp>
#include <cstdint>
#include <vector>
@@ -16,10 +17,9 @@ using AnnotationIDs = std::vector<AnnotationID>;
class SymbolAnnotation {
public:
- SymbolAnnotation() = default;
-
- SymbolAnnotation(Point<double> geometry_, std::string icon_)
- : geometry(std::move(geometry_)), icon(std::move(icon_)) {}
+ SymbolAnnotation(Point<double> geometry_, std::string icon_ = {})
+ : geometry(std::move(geometry_)),
+ icon(std::move(icon_)) {}
Point<double> geometry;
std::string icon;
@@ -33,42 +33,41 @@ using ShapeAnnotationGeometry = variant<
class LineAnnotation {
public:
- LineAnnotation(ShapeAnnotationGeometry geometry_, style::PropertyValue<float> opacity_,
- style::PropertyValue<float> width_, style::PropertyValue<Color> color_)
- : geometry(std::move(geometry_)), opacity(std::move(opacity_)), width(std::move(width_)), color(std::move(color_)) {}
+ 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::PropertyValue<float> opacity { 1.0f };
- style::PropertyValue<float> width { 1.0f };
- style::PropertyValue<Color> color { Color::black() };
+ style::DataDrivenPropertyValue<float> opacity;
+ style::DataDrivenPropertyValue<float> width;
+ style::DataDrivenPropertyValue<Color> color;
};
class FillAnnotation {
public:
- FillAnnotation(ShapeAnnotationGeometry geometry_, style::PropertyValue<float> opacity_,
- style::PropertyValue<Color> color_, style::PropertyValue<Color> outlineColor_)
- : geometry(std::move(geometry_)), opacity(std::move(opacity_)), color(std::move(color_)), outlineColor(std::move(outlineColor_)) {}
-
- ShapeAnnotationGeometry geometry;
- style::PropertyValue<float> opacity { 1.0f };
- style::PropertyValue<Color> color { Color::black() };
- style::PropertyValue<Color> outlineColor {};
-};
-
-// An annotation whose type and properties are sourced from a style layer.
-class StyleSourcedAnnotation {
-public:
- StyleSourcedAnnotation(ShapeAnnotationGeometry geometry_, std::string layerID_)
- : geometry(std::move(geometry_)), layerID(std::move(layerID_)) {}
+ 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_)) {}
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/gl/gl.hpp b/include/mbgl/gl/gl.hpp
deleted file mode 100644
index 7985097c8c..0000000000
--- a/include/mbgl/gl/gl.hpp
+++ /dev/null
@@ -1,50 +0,0 @@
-#pragma once
-
-#include <stdexcept>
-#include <limits>
-
-#if __APPLE__
- #include "TargetConditionals.h"
- #if TARGET_OS_IPHONE
- #include <OpenGLES/ES2/gl.h>
- #include <OpenGLES/ES2/glext.h>
- #elif TARGET_IPHONE_SIMULATOR
- #include <OpenGLES/ES2/gl.h>
- #include <OpenGLES/ES2/glext.h>
- #elif TARGET_OS_MAC
- #include <OpenGL/OpenGL.h>
- #include <OpenGL/gl.h>
- #include <OpenGL/glext.h>
- #else
- #error Unsupported Apple platform
- #endif
-#elif __ANDROID__ || MBGL_USE_GLES2
- #define GL_GLEXT_PROTOTYPES
- #include <GLES2/gl2.h>
- #include <GLES2/gl2ext.h>
-#elif __QT__ && QT_VERSION >= 0x050000
- #define GL_GLEXT_PROTOTYPES
- #include <QtGui/qopengl.h>
-#else
- #define GL_GLEXT_PROTOTYPES
- #include <GL/gl.h>
- #include <GL/glext.h>
-#endif
-
-namespace mbgl {
-namespace gl {
-
-struct Error : std::runtime_error {
- using std::runtime_error::runtime_error;
-};
-
-void checkError(const char *cmd, const char *file, int line);
-
-#ifndef NDEBUG
-#define MBGL_CHECK_ERROR(cmd) ([&]() { struct __MBGL_C_E { ~__MBGL_C_E() { ::mbgl::gl::checkError(#cmd, __FILE__, __LINE__); } } __MBGL_C_E; return cmd; }())
-#else
-#define MBGL_CHECK_ERROR(cmd) (cmd)
-#endif
-
-} // namespace gl
-} // namespace mbgl
diff --git a/include/mbgl/map/backend.hpp b/include/mbgl/map/backend.hpp
deleted file mode 100644
index 0468449155..0000000000
--- a/include/mbgl/map/backend.hpp
+++ /dev/null
@@ -1,64 +0,0 @@
-#pragma once
-
-#include <mbgl/map/change.hpp>
-
-#include <memory>
-
-namespace mbgl {
-
-namespace gl {
-class Context;
-} // namespace gl
-
-class BackendScope;
-
-class Backend {
-public:
- Backend();
- virtual ~Backend();
-
- // Returns the backend's context which manages OpenGL state.
- gl::Context& getContext();
-
- // 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;
-
- // Notifies a watcher of map x/y/scale/rotation changes.
- virtual void notifyMapChange(MapChange change);
-
-protected:
- // 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
- //
- // They are *not* called for Map::render; it is assumed that the correct context is already
- // activated prior to calling Map::render.
- virtual void activate() = 0;
- virtual void deactivate() = 0;
-
-private:
- const std::unique_ptr<gl::Context> context;
-
- friend class BackendScope;
-};
-
-class BackendScope {
-public:
- BackendScope(Backend& backend_) : backend(backend_) {
- backend.activate();
- }
-
- ~BackendScope() {
- backend.deactivate();
- }
-
-private:
- Backend& backend;
-};
-
-} // namespace mbgl
diff --git a/include/mbgl/map/camera.hpp b/include/mbgl/map/camera.hpp
index 1c389577f0..53b5b590b1 100644
--- a/include/mbgl/map/camera.hpp
+++ b/include/mbgl/map/camera.hpp
@@ -17,7 +17,7 @@ struct CameraOptions {
/** Padding around the interior of the view that affects the frame of
reference for `center`. */
- optional<EdgeInsets> padding;
+ EdgeInsets padding;
/** Point of reference for `zoom` and `angle`, assuming an origin at the
top-left corner of the view. */
@@ -36,6 +36,19 @@ struct CameraOptions {
optional<double> pitch;
};
+constexpr bool operator==(const CameraOptions& a, const CameraOptions& b) {
+ return a.center == b.center
+ && a.padding == b.padding
+ && a.anchor == b.anchor
+ && a.zoom == b.zoom
+ && a.angle == b.angle
+ && a.pitch == b.pitch;
+}
+
+constexpr bool operator!=(const CameraOptions& a, const CameraOptions& b) {
+ return !(a == b);
+}
+
/** Various options for describing a transition between viewpoints with
animation. All fields are optional; the default values depend on how this
struct is used. */
diff --git a/include/mbgl/map/change.hpp b/include/mbgl/map/change.hpp
new file mode 100644
index 0000000000..3925d655a4
--- /dev/null
+++ b/include/mbgl/map/change.hpp
@@ -0,0 +1,26 @@
+#pragma once
+
+#include <cstdint>
+
+namespace mbgl {
+
+enum MapChange : uint8_t {
+ MapChangeRegionWillChange = 0,
+ MapChangeRegionWillChangeAnimated = 1,
+ MapChangeRegionIsChanging = 2,
+ MapChangeRegionDidChange = 3,
+ MapChangeRegionDidChangeAnimated = 4,
+ MapChangeWillStartLoadingMap = 5,
+ MapChangeDidFinishLoadingMap = 6,
+ MapChangeDidFailLoadingMap = 7,
+ MapChangeWillStartRenderingFrame = 8,
+ MapChangeDidFinishRenderingFrame = 9,
+ MapChangeDidFinishRenderingFrameFullyRendered = 10,
+ MapChangeWillStartRenderingMap = 11,
+ MapChangeDidFinishRenderingMap = 12,
+ MapChangeDidFinishRenderingMapFullyRendered = 13,
+ MapChangeDidFinishLoadingStyle = 14,
+ MapChangeSourceDidChange = 15
+};
+
+} // namespace mbgl
diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp
index c80420371d..7d6678dc93 100644
--- a/include/mbgl/map/map.hpp
+++ b/include/mbgl/map/map.hpp
@@ -2,13 +2,12 @@
#include <mbgl/util/optional.hpp>
#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 <cstdint>
#include <string>
@@ -18,28 +17,24 @@
namespace mbgl {
-class Backend;
-class View;
class FileSource;
class Scheduler;
-class SpriteImage;
-struct CameraOptions;
-struct AnimationOptions;
+class RendererFrontend;
namespace style {
-class Source;
-class Layer;
+class Image;
+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);
~Map();
@@ -47,29 +42,15 @@ public:
// 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 callback);
// 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();
@@ -80,48 +61,55 @@ public:
bool isPanning() const;
// Camera
- CameraOptions getCameraOptions(optional<EdgeInsets>) const;
+ CameraOptions getCameraOptions(const EdgeInsets&) const;
void jumpTo(const CameraOptions&);
void easeTo(const CameraOptions&, const AnimationOptions&);
void flyTo(const CameraOptions&, const AnimationOptions&);
// Position
- void moveBy(const ScreenCoordinate&, const Duration& = Duration::zero());
- void setLatLng(const LatLng&, optional<ScreenCoordinate>, const Duration& = Duration::zero());
- void setLatLng(const LatLng&, optional<EdgeInsets>, const Duration& = Duration::zero());
- void setLatLng(const LatLng&, const Duration& = Duration::zero());
- LatLng getLatLng(optional<EdgeInsets> = {}) const;
- void resetPosition(optional<EdgeInsets> = {});
-
- // Scale
- void scaleBy(double ds, optional<ScreenCoordinate> = {}, const Duration& = Duration::zero());
- void setScale(double scale, optional<ScreenCoordinate> = {}, const Duration& = Duration::zero());
- double getScale() const;
- void setZoom(double zoom, const Duration& = Duration::zero());
- void setZoom(double zoom, optional<EdgeInsets>, const Duration& = Duration::zero());
+ void moveBy(const ScreenCoordinate&, const AnimationOptions& = {});
+ void setLatLng(const LatLng&, optional<ScreenCoordinate>, const AnimationOptions& = {});
+ void setLatLng(const LatLng&, const EdgeInsets&, const AnimationOptions& = {});
+ void setLatLng(const LatLng&, const AnimationOptions& = {});
+ LatLng getLatLng(const EdgeInsets& = {}) const;
+ void resetPosition(const EdgeInsets& = {});
+
+ // Zoom
+ void setZoom(double zoom, const AnimationOptions& = {});
+ void setZoom(double zoom, optional<ScreenCoordinate>, const AnimationOptions& = {});
+ void setZoom(double zoom, const EdgeInsets&, const AnimationOptions& = {});
double getZoom() const;
- void setLatLngZoom(const LatLng&, double zoom, const Duration& = Duration::zero());
- void setLatLngZoom(const LatLng&, double zoom, optional<EdgeInsets>, const Duration& = Duration::zero());
- CameraOptions cameraForLatLngBounds(const LatLngBounds&, optional<EdgeInsets>) const;
- CameraOptions cameraForLatLngs(const std::vector<LatLng>&, optional<EdgeInsets>) const;
+ void setLatLngZoom(const LatLng&, double zoom, const AnimationOptions& = {});
+ void setLatLngZoom(const LatLng&, double zoom, const EdgeInsets&, const AnimationOptions& = {});
+ CameraOptions cameraForLatLngBounds(const LatLngBounds&, const EdgeInsets&) const;
+ CameraOptions cameraForLatLngs(const std::vector<LatLng>&, const EdgeInsets&) const;
+ LatLngBounds latLngBoundsForCamera(const CameraOptions&) const;
void resetZoom();
- void setMinZoom(const double minZoom);
+
+ // Bounds
+ void setLatLngBounds(optional<LatLngBounds>);
+ optional<LatLngBounds> getLatLngBounds() const;
+ void setMinZoom(double);
double getMinZoom() const;
- void setMaxZoom(const double maxZoom);
+ void setMaxZoom(double);
double getMaxZoom() const;
+ void setMinPitch(double);
+ double getMinPitch() const;
+ void setMaxPitch(double);
+ double getMaxPitch() const;
// Rotation
- void rotateBy(const ScreenCoordinate& first, const ScreenCoordinate& second, const Duration& = Duration::zero());
- void setBearing(double degrees, const Duration& = Duration::zero());
- void setBearing(double degrees, optional<ScreenCoordinate>, const Duration& = Duration::zero());
- void setBearing(double degrees, optional<EdgeInsets>, const Duration& = Duration::zero());
+ void rotateBy(const ScreenCoordinate& first, const ScreenCoordinate& second, const AnimationOptions& = {});
+ void setBearing(double degrees, const AnimationOptions& = {});
+ void setBearing(double degrees, optional<ScreenCoordinate>, const AnimationOptions& = {});
+ void setBearing(double degrees, const EdgeInsets&, const AnimationOptions& = {});
double getBearing() const;
- void resetNorth(const Duration& = Milliseconds(500));
- void resetNorth(optional<EdgeInsets>, const Duration& = Milliseconds(500));
+ void resetNorth(const AnimationOptions& = {{mbgl::Milliseconds(500)}});
+ void resetNorth(const EdgeInsets&, const AnimationOptions& = {{mbgl::Milliseconds(500)}});
// Pitch
- void setPitch(double pitch, const Duration& = Duration::zero());
- void setPitch(double pitch, optional<ScreenCoordinate>, const Duration& = Duration::zero());
+ void setPitch(double pitch, const AnimationOptions& = {});
+ void setPitch(double pitch, optional<ScreenCoordinate>, const AnimationOptions& = {});
double getPitch() const;
// North Orientation
@@ -141,53 +129,26 @@ public:
Size getSize() const;
// Projection
- double getMetersPerPixelAtLatitude(double lat, double zoom) const;
- ProjectedMeters projectedMetersForLatLng(const LatLng&) const;
- LatLng latLngForProjectedMeters(const ProjectedMeters&) const;
ScreenCoordinate pixelForLatLng(const LatLng&) const;
LatLng latLngForPixel(const ScreenCoordinate&) const;
// Annotations
- void addAnnotationIcon(const std::string&, std::shared_ptr<const SpriteImage>);
- void removeAnnotationIcon(const std::string&);
- double getTopOffsetPixelsForAnnotationIcon(const std::string&);
+ void addAnnotationImage(std::unique_ptr<style::Image>);
+ void removeAnnotationImage(const std::string&);
+ double getTopOffsetPixelsForAnnotationImage(const std::string&);
AnnotationID addAnnotation(const Annotation&);
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);
-
- // Add image, bound to the style
- void addImage(const std::string&, std::unique_ptr<const SpriteImage>);
- void removeImage(const std::string&);
- const SpriteImage* getImage(const std::string&);
-
- // 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 optional<std::vector<std::string>>& layerIDs = {});
- std::vector<Feature> queryRenderedFeatures(const ScreenBox&, const optional<std::vector<std::string>>& layerIDs = {});
- 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/map_observer.hpp b/include/mbgl/map/map_observer.hpp
new file mode 100644
index 0000000000..f63e5f2af3
--- /dev/null
+++ b/include/mbgl/map/map_observer.hpp
@@ -0,0 +1,44 @@
+#pragma once
+
+#include <mbgl/style/source.hpp>
+
+#include <cstdint>
+#include <exception>
+#include <string>
+
+namespace mbgl {
+
+class MapObserver {
+public:
+ virtual ~MapObserver() = default;
+
+ static MapObserver& nullObserver() {
+ static MapObserver mapObserver;
+ return mapObserver;
+ }
+
+ enum class CameraChangeMode : uint32_t {
+ Immediate,
+ Animated
+ };
+
+ enum class RenderMode : uint32_t {
+ Partial,
+ Full
+ };
+
+ virtual void onCameraWillChange(CameraChangeMode) {}
+ virtual void onCameraIsChanging() {}
+ virtual void onCameraDidChange(CameraChangeMode) {}
+ virtual void onWillStartLoadingMap() {}
+ virtual void onDidFinishLoadingMap() {}
+ virtual void onDidFailLoadingMap(std::exception_ptr) {}
+ virtual void onWillStartRenderingFrame() {}
+ virtual void onDidFinishRenderingFrame(RenderMode) {}
+ virtual void onWillStartRenderingMap() {}
+ virtual void onDidFinishRenderingMap(RenderMode) {}
+ virtual void onDidFinishLoadingStyle() {}
+ virtual void onSourceChanged(style::Source&) {}
+};
+
+} // namespace mbgl
diff --git a/include/mbgl/map/view.hpp b/include/mbgl/map/view.hpp
deleted file mode 100644
index 6517c6b220..0000000000
--- a/include/mbgl/map/view.hpp
+++ /dev/null
@@ -1,20 +0,0 @@
-#pragma once
-
-#include <mbgl/util/noncopyable.hpp>
-
-namespace mbgl {
-
-class Map;
-
-class View : private util::noncopyable {
-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/renderer/backend_scope.hpp b/include/mbgl/renderer/backend_scope.hpp
new file mode 100644
index 0000000000..73bafc84c7
--- /dev/null
+++ b/include/mbgl/renderer/backend_scope.hpp
@@ -0,0 +1,35 @@
+#pragma once
+
+namespace mbgl {
+
+class RendererBackend;
+
+class BackendScope {
+public:
+ // There are two types of scopes: Creating an "Implicit" scope tells Mapbox GL that the
+ // supporting windowing system has already activated the GL Backend and that no further actions
+ // are required. Creating an "Explicit" scope actually enables the GL Backend, and disables it
+ // when the BackendScope is destroyed.
+ enum class ScopeType : bool {
+ Implicit,
+ Explicit,
+ };
+
+ BackendScope(RendererBackend&, ScopeType = ScopeType::Explicit);
+ ~BackendScope();
+
+ // Returns true when there is currently a BackendScope active in this thread.
+ static bool exists();
+
+private:
+ void activate();
+ void deactivate();
+
+ BackendScope* priorScope;
+ BackendScope* nextScope;
+ RendererBackend& backend;
+ const ScopeType scopeType;
+ bool activated = false;
+};
+
+} // namespace mbgl
diff --git a/include/mbgl/renderer/query.hpp b/include/mbgl/renderer/query.hpp
new file mode 100644
index 0000000000..4cadf4f017
--- /dev/null
+++ b/include/mbgl/renderer/query.hpp
@@ -0,0 +1,43 @@
+#pragma once
+
+#include <mbgl/util/optional.hpp>
+#include <mbgl/style/filter.hpp>
+
+#include <string>
+#include <vector>
+
+namespace mbgl {
+
+/**
+ * Options for query rendered features.
+ */
+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;
+
+ optional<style::Filter> filter;
+};
+
+/**
+ * Options for query source features
+ */
+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..95828a1b79
--- /dev/null
+++ b/include/mbgl/renderer/renderer.hpp
@@ -0,0 +1,53 @@
+#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 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/renderer/renderer_backend.hpp b/include/mbgl/renderer/renderer_backend.hpp
new file mode 100644
index 0000000000..f7d19a1791
--- /dev/null
+++ b/include/mbgl/renderer/renderer_backend.hpp
@@ -0,0 +1,90 @@
+#pragma once
+
+#include <mbgl/renderer/backend_scope.hpp>
+#include <mbgl/util/image.hpp>
+#include <mbgl/util/size.hpp>
+#include <mbgl/util/util.hpp>
+
+#include <memory>
+#include <mutex>
+
+namespace mbgl {
+
+namespace gl {
+class Context;
+using ProcAddress = void (*)();
+using FramebufferID = uint32_t;
+} // namespace gl
+
+// The RendererBackend is used by the Renderer to facilitate
+// the actual rendering.
+class RendererBackend {
+public:
+ RendererBackend();
+ virtual ~RendererBackend();
+
+ // Returns the backend's context which manages OpenGL state.
+ gl::Context& getContext();
+
+ // Called prior to rendering to update the internally assumed OpenGL state.
+ virtual void updateAssumedState() = 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;
+
+protected:
+ // 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, exclusively through BackendScope, in two situations:
+ //
+ // 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;
+
+ // Reads the color pixel data from the currently bound framebuffer.
+ PremultipliedImage readFramebuffer(const Size&) const;
+
+ // A constant to signal that a framebuffer is bound, but with an unknown ID.
+ static constexpr const gl::FramebufferID ImplicitFramebufferBinding =
+ std::numeric_limits<gl::FramebufferID>::max();
+
+ // 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 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();
+
+ // Triggers an OpenGL state update if the internal assumed state doesn't match the
+ // supplied values.
+ void setFramebufferBinding(gl::FramebufferID fbo);
+ void setViewport(int32_t x, int32_t y, const Size&);
+ void setScissorTest(bool);
+
+protected:
+ std::unique_ptr<gl::Context> context;
+
+private:
+ std::once_flag initialized;
+
+ friend class BackendScope;
+};
+
+MBGL_CONSTEXPR bool operator==(const RendererBackend& a, const RendererBackend& b) {
+ return &a == &b;
+}
+
+} // namespace mbgl
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/sprite/sprite_image.hpp b/include/mbgl/sprite/sprite_image.hpp
deleted file mode 100644
index 05d9871bf9..0000000000
--- a/include/mbgl/sprite/sprite_image.hpp
+++ /dev/null
@@ -1,29 +0,0 @@
-#pragma once
-
-#include <mbgl/util/noncopyable.hpp>
-#include <mbgl/util/geo.hpp>
-#include <mbgl/util/image.hpp>
-
-#include <string>
-#include <memory>
-#include <cstdint>
-
-namespace mbgl {
-
-class SpriteImage : private util::noncopyable {
-public:
- SpriteImage(PremultipliedImage&&, float pixelRatio, bool sdf = false);
-
- PremultipliedImage image;
-
- // Pixel ratio of the sprite image.
- const float pixelRatio;
-
- // Whether this image should be interpreted as a signed distance field icon.
- const bool sdf;
-
- float getWidth() const { return image.size.width / pixelRatio; }
- float getHeight() const { return image.size.height / pixelRatio; }
-};
-
-} // namespace mbgl
diff --git a/include/mbgl/storage/default_file_source.hpp b/include/mbgl/storage/default_file_source.hpp
index b8f5e1167e..9911e0ce67 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:
/*
@@ -24,17 +29,22 @@ public:
DefaultFileSource(const std::string& cachePath,
const std::string& assetRoot,
uint64_t maximumCacheSize = util::DEFAULT_MAX_CACHE_SIZE);
+ DefaultFileSource(const std::string& cachePath,
+ std::unique_ptr<FileSource>&& assetFileSource,
+ uint64_t maximumCacheSize = util::DEFAULT_MAX_CACHE_SIZE);
~DefaultFileSource() override;
bool supportsOptionalRequests() const override {
return true;
}
-
+
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(optional<ActorRef<ResourceTransform>>&&);
std::unique_ptr<AsyncRequest> request(const Resource&, Callback) override;
@@ -113,15 +123,37 @@ public:
*/
void setOfflineMapboxTileCountLimit(uint64_t) const;
+ /*
+ * Pause file request activity.
+ *
+ * If pause is called then no revalidation or network request activity
+ * will occur.
+ */
+ void pause();
+
+ /*
+ * Resume file request activity.
+ *
+ * Calling resume will unpause the file source and process any tasks that
+ * expired while the file source was paused.
+ */
+ void resume();
+
// For testing only.
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;
};
} // namespace mbgl
diff --git a/include/mbgl/storage/online_file_source.hpp b/include/mbgl/storage/online_file_source.hpp
index 9c7feceb47..ffd75662e6 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();
@@ -12,10 +16,12 @@ public:
void setAPIBaseURL(const std::string& t) { apiBaseURL = t; }
std::string getAPIBaseURL() const { return apiBaseURL; }
-
+
void setAccessToken(const std::string& t) { accessToken = t; }
std::string getAccessToken() const { return accessToken; }
+ void setResourceTransform(optional<ActorRef<ResourceTransform>>&&);
+
std::unique_ptr<AsyncRequest> request(const Resource&, Callback) override;
private:
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 448423c1cb..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;
@@ -35,7 +39,13 @@ public:
optional<std::string> etag;
bool isFresh() const {
- return !expires || *expires > util::now();
+ 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());
}
};
@@ -53,7 +63,7 @@ public:
// An error message from the request handler, e.g. a server message or a system message
// informing the user about the reason for the failure.
std::string message;
-
+
optional<Timestamp> retryAfter;
public:
diff --git a/include/mbgl/style/conversion.hpp b/include/mbgl/style/conversion.hpp
index e53adcb942..27504a89b1 100644
--- a/include/mbgl/style/conversion.hpp
+++ b/include/mbgl/style/conversion.hpp
@@ -1,6 +1,6 @@
#pragma once
-#include <mbgl/util/variant.hpp>
+#include <mbgl/util/optional.hpp>
#include <string>
@@ -21,11 +21,11 @@ namespace conversion {
A single template function serves as the public interface:
template <class T, class V>
- Result<T> convert(const V& value);
+ optional<T> convert(const V& value, Error& error);
- Where `T` is one of the above types. If the conversion fails, the `Error` variant of `Result` is
- returned, which includes diagnostic text suitable for presentation to a library user. Otherwise,
- the `T` variant of `Result` is returned.
+ Where `T` is one of the above types. If the conversion fails, the result is empty, and the
+ error parameter includes diagnostic text suitable for presentation to a library user. Otherwise,
+ a filled optional is returned.
The implementation of `convert` requires that the following are legal expressions for a value `v`
of type `const V&`:
@@ -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
@@ -57,37 +58,12 @@ namespace conversion {
struct Error { std::string message; };
-template <class T>
-class Result : private variant<T, Error> {
-public:
- using variant<T, Error>::variant;
-
- explicit operator bool() const {
- return this->template is<T>();
- }
-
- T& operator*() {
- assert(this->template is<T>());
- return this->template get<T>();
- }
-
- const T& operator*() const {
- assert(this->template is<T>());
- return this->template get<T>();
- }
-
- const Error& error() const {
- assert(this->template is<Error>());
- return this->template get<Error>();
- }
-};
-
template <class T, class Enable = void>
struct Converter;
template <class T, class V, class...Args>
-Result<T> convert(const V& value, Args&&...args) {
- return Converter<T>()(value, std::forward<Args>(args)...);
+optional<T> convert(const V& value, Error& error, Args&&...args) {
+ return Converter<T>()(value, error, std::forward<Args>(args)...);
}
} // namespace conversion
diff --git a/include/mbgl/style/conversion/constant.hpp b/include/mbgl/style/conversion/constant.hpp
index 05bf968f4d..07c0a35fae 100644
--- a/include/mbgl/style/conversion/constant.hpp
+++ b/include/mbgl/style/conversion/constant.hpp
@@ -4,6 +4,7 @@
#include <mbgl/util/optional.hpp>
#include <mbgl/util/color.hpp>
#include <mbgl/util/enum.hpp>
+#include <mbgl/util/string.hpp>
#include <array>
#include <string>
@@ -16,10 +17,11 @@ namespace conversion {
template <>
struct Converter<bool> {
template <class V>
- Result<bool> operator()(const V& value) const {
+ optional<bool> operator()(const V& value, Error& error) const {
optional<bool> converted = toBool(value);
if (!converted) {
- return Error { "value must be a boolean" };
+ error = { "value must be a boolean" };
+ return {};
}
return *converted;
}
@@ -28,10 +30,11 @@ struct Converter<bool> {
template <>
struct Converter<float> {
template <class V>
- Result<float> operator()(const V& value) const {
+ optional<float> operator()(const V& value, Error& error) const {
optional<float> converted = toNumber(value);
if (!converted) {
- return Error { "value must be a number" };
+ error = { "value must be a number" };
+ return {};
}
return *converted;
}
@@ -40,10 +43,11 @@ struct Converter<float> {
template <>
struct Converter<std::string> {
template <class V>
- Result<std::string> operator()(const V& value) const {
+ optional<std::string> operator()(const V& value, Error& error) const {
optional<std::string> converted = toString(value);
if (!converted) {
- return Error { "value must be a string" };
+ error = { "value must be a string" };
+ return {};
}
return *converted;
}
@@ -52,15 +56,17 @@ struct Converter<std::string> {
template <class T>
struct Converter<T, typename std::enable_if_t<std::is_enum<T>::value>> {
template <class V>
- Result<T> operator()(const V& value) const {
+ optional<T> operator()(const V& value, Error& error) const {
optional<std::string> string = toString(value);
if (!string) {
- return Error { "value must be a string" };
+ error = { "value must be a string" };
+ return {};
}
const auto result = Enum<T>::toEnum(*string);
if (!result) {
- return Error { "value must be a valid enumeration value" };
+ error = { "value must be a valid enumeration value" };
+ return {};
}
return *result;
@@ -70,65 +76,52 @@ struct Converter<T, typename std::enable_if_t<std::is_enum<T>::value>> {
template <>
struct Converter<Color> {
template <class V>
- Result<Color> operator()(const V& value) const {
+ optional<Color> operator()(const V& value, Error& error) const {
optional<std::string> string = toString(value);
if (!string) {
- return Error { "value must be a string" };
+ error = { "value must be a string" };
+ return {};
}
optional<Color> color = Color::parse(*string);
if (!color) {
- return Error { "value must be a valid color" };
+ error = { "value must be a valid color" };
+ return {};
}
return *color;
}
};
-template <>
-struct Converter<std::array<float, 2>> {
+template <size_t N>
+struct Converter<std::array<float, N>> {
template <class V>
- Result<std::array<float, 2>> operator()(const V& value) const {
- if (!isArray(value) || arrayLength(value) != 2) {
- return Error { "value must be an array of two numbers" };
- }
-
- optional<float> first = toNumber(arrayMember(value, 0));
- optional<float> second = toNumber(arrayMember(value, 1));
- if (!first || !second) {
- return Error { "value must be an array of two numbers" };
+ optional<std::array<float, N>> operator()(const V& value, Error& error) const {
+ if (!isArray(value) || arrayLength(value) != N) {
+ error = { "value must be an array of " + util::toString(N) + " numbers" };
+ return {};
}
- return std::array<float, 2> {{ *first, *second }};
- }
-};
-
-template <>
-struct Converter<std::array<float, 4>> {
- template <class V>
- Result<std::array<float, 4>> operator()(const V& value) const {
- if (!isArray(value) || arrayLength(value) != 4) {
- return Error { "value must be an array of four numbers" };
- }
-
- optional<float> first = toNumber(arrayMember(value, 0));
- optional<float> second = toNumber(arrayMember(value, 1));
- optional<float> third = toNumber(arrayMember(value, 2));
- optional<float> fourth = toNumber(arrayMember(value, 3));
- if (!first || !second) {
- return Error { "value must be an array of four numbers" };
+ std::array<float, N> result;
+ for (size_t i = 0; i < N; i++) {
+ optional<float> n = toNumber(arrayMember(value, i));
+ if (!n) {
+ error = { "value must be an array of " + util::toString(N) + " numbers" };
+ return {};
+ }
+ result[i] = *n;
}
-
- return std::array<float, 4> {{ *first, *second, *third, *fourth }};
+ return result;
}
};
template <>
struct Converter<std::vector<float>> {
template <class V>
- Result<std::vector<float>> operator()(const V& value) const {
+ optional<std::vector<float>> operator()(const V& value, Error& error) const {
if (!isArray(value)) {
- return Error { "value must be an array" };
+ error = { "value must be an array" };
+ return {};
}
std::vector<float> result;
@@ -137,7 +130,8 @@ struct Converter<std::vector<float>> {
for (std::size_t i = 0; i < arrayLength(value); ++i) {
optional<float> number = toNumber(arrayMember(value, i));
if (!number) {
- return Error { "value must be an array of numbers" };
+ error = { "value must be an array of numbers" };
+ return {};
}
result.push_back(*number);
}
@@ -149,9 +143,10 @@ struct Converter<std::vector<float>> {
template <>
struct Converter<std::vector<std::string>> {
template <class V>
- Result<std::vector<std::string>> operator()(const V& value) const {
+ optional<std::vector<std::string>> operator()(const V& value, Error& error) const {
if (!isArray(value)) {
- return Error { "value must be an array" };
+ error = { "value must be an array" };
+ return {};
}
std::vector<std::string> result;
@@ -160,7 +155,8 @@ struct Converter<std::vector<std::string>> {
for (std::size_t i = 0; i < arrayLength(value); ++i) {
optional<std::string> string = toString(arrayMember(value, i));
if (!string) {
- return Error { "value must be an array of strings" };
+ error = { "value must be an array of strings" };
+ return {};
}
result.push_back(*string);
}
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/data_driven_property_value.hpp b/include/mbgl/style/conversion/data_driven_property_value.hpp
new file mode 100644
index 0000000000..79b15dcfb0
--- /dev/null
+++ b/include/mbgl/style/conversion/data_driven_property_value.hpp
@@ -0,0 +1,46 @@
+#pragma once
+
+#include <mbgl/style/data_driven_property_value.hpp>
+#include <mbgl/style/conversion.hpp>
+#include <mbgl/style/conversion/constant.hpp>
+#include <mbgl/style/conversion/function.hpp>
+
+namespace mbgl {
+namespace style {
+namespace conversion {
+
+template <class T>
+struct Converter<DataDrivenPropertyValue<T>> {
+ template <class V>
+ optional<DataDrivenPropertyValue<T>> operator()(const V& value, Error& error) const {
+ if (isUndefined(value)) {
+ return DataDrivenPropertyValue<T>();
+ } else if (!isObject(value)) {
+ optional<T> constant = convert<T>(value, error);
+ if (!constant) {
+ return {};
+ }
+ return DataDrivenPropertyValue<T>(*constant);
+ } else if (!objectMember(value, "property")) {
+ optional<CameraFunction<T>> function = convert<CameraFunction<T>>(value, error);
+ if (!function) {
+ return {};
+ }
+ return DataDrivenPropertyValue<T>(*function);
+ } else {
+ optional<CompositeFunction<T>> composite = convert<CompositeFunction<T>>(value, error);
+ if (composite) {
+ return DataDrivenPropertyValue<T>(*composite);
+ }
+ optional<SourceFunction<T>> source = convert<SourceFunction<T>>(value, error);
+ if (!source) {
+ return {};
+ }
+ return DataDrivenPropertyValue<T>(*source);
+ }
+ }
+};
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/conversion/filter.hpp b/include/mbgl/style/conversion/filter.hpp
index 3ab91e5bbc..986d1bf80d 100644
--- a/include/mbgl/style/conversion/filter.hpp
+++ b/include/mbgl/style/conversion/filter.hpp
@@ -12,136 +12,245 @@ template <>
struct Converter<Filter> {
public:
template <class V>
- Result<Filter> operator()(const V& value) const {
+ optional<Filter> operator()(const V& value, Error& error) const {
if (!isArray(value)) {
- return Error { "filter expression must be an array" };
+ error = { "filter expression must be an array" };
+ return {};
}
if (arrayLength(value) < 1) {
- return Error { "filter expression must have at least 1 element" };
+ error = { "filter expression must have at least 1 element" };
+ return {};
}
optional<std::string> op = toString(arrayMember(value, 0));
if (!op) {
- return Error { "filter operator must be a string" };
+ error = { "filter operator must be a string" };
+ return {};
}
if (*op == "==") {
- return convertBinaryFilter<EqualsFilter>(value);
+ return convertEqualityFilter<EqualsFilter, TypeEqualsFilter, IdentifierEqualsFilter>(value, error);
} else if (*op == "!=") {
- return convertBinaryFilter<NotEqualsFilter>(value);
+ return convertEqualityFilter<NotEqualsFilter, TypeNotEqualsFilter, IdentifierNotEqualsFilter>(value, error);
} else if (*op == ">") {
- return convertBinaryFilter<GreaterThanFilter>(value);
+ return convertBinaryFilter<GreaterThanFilter>(value, error);
} else if (*op == ">=") {
- return convertBinaryFilter<GreaterThanEqualsFilter>(value);
+ return convertBinaryFilter<GreaterThanEqualsFilter>(value, error);
} else if (*op == "<") {
- return convertBinaryFilter<LessThanFilter>(value);
+ return convertBinaryFilter<LessThanFilter>(value, error);
} else if (*op == "<=") {
- return convertBinaryFilter<LessThanEqualsFilter>(value);
+ return convertBinaryFilter<LessThanEqualsFilter>(value, error);
} else if (*op == "in") {
- return convertSetFilter<InFilter>(value);
+ return convertSetFilter<InFilter, TypeInFilter, IdentifierInFilter>(value, error);
} else if (*op == "!in") {
- return convertSetFilter<NotInFilter>(value);
+ return convertSetFilter<NotInFilter, TypeNotInFilter, IdentifierNotInFilter>(value, error);
} else if (*op == "all") {
- return convertCompoundFilter<AllFilter>(value);
+ return convertCompoundFilter<AllFilter>(value, error);
} else if (*op == "any") {
- return convertCompoundFilter<AnyFilter>(value);
+ return convertCompoundFilter<AnyFilter>(value, error);
} else if (*op == "none") {
- return convertCompoundFilter<NoneFilter>(value);
+ return convertCompoundFilter<NoneFilter>(value, error);
} else if (*op == "has") {
- return convertUnaryFilter<HasFilter>(value);
+ return convertUnaryFilter<HasFilter, HasIdentifierFilter>(value, error);
} else if (*op == "!has") {
- return convertUnaryFilter<NotHasFilter>(value);
+ return convertUnaryFilter<NotHasFilter, NotHasIdentifierFilter>(value, error);
}
- return 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 {};
}
private:
- Result<Value> normalizeValue(const std::string& key, const optional<Value>& value) const {
+ optional<Value> normalizeValue(const optional<Value>& value, Error& error) const {
if (!value) {
- return Error { "filter expression value must be a boolean, number, or string" };
- } else if (key != "$type") {
+ error = { "filter expression value must be a boolean, number, or string" };
+ return {};
+ } else {
return *value;
- } else if (*value == std::string("Point")) {
- return Value(uint64_t(FeatureType::Point));
- } else if (*value == std::string("LineString")) {
- return Value(uint64_t(FeatureType::LineString));
- } else if (*value == std::string("Polygon")) {
- return Value(uint64_t(FeatureType::Polygon));
+ }
+ }
+
+ template <class V>
+ optional<FeatureType> toFeatureType(const V& value, Error& error) const {
+ optional<std::string> type = toString(value);
+ if (!type) {
+ error = { "value for $type filter must be a string" };
+ return {};
+ } else if (*type == "Point") {
+ return FeatureType::Point;
+ } else if (*type == "LineString") {
+ return FeatureType::LineString;
+ } else if (*type == "Polygon") {
+ return FeatureType::Polygon;
} else {
- return Error { "value for $type filter must be Point, LineString, or Polygon" };
+ error = { "value for $type filter must be Point, LineString, or Polygon" };
+ return {};
}
}
- template <class FilterType, class V>
- Result<Filter> convertUnaryFilter(const V& value) const {
+ template <class V>
+ optional<FeatureIdentifier> toFeatureIdentifier(const V& value, Error& error) const {
+ optional<Value> identifier = toValue(value);
+ if (!identifier) {
+ error = { "filter expression value must be a boolean, number, or string" };
+ return {};
+ } else {
+ return (*identifier).match(
+ [] (uint64_t t) -> optional<FeatureIdentifier> { return { t }; },
+ [] ( int64_t t) -> optional<FeatureIdentifier> { return { t }; },
+ [] ( double t) -> optional<FeatureIdentifier> { return { t }; },
+ [] (const std::string& t) -> optional<FeatureIdentifier> { return { t }; },
+ [&] (const auto&) -> optional<FeatureIdentifier> {
+ error = { "filter expression value must be a boolean, number, or string" };
+ return {};
+ });
+ }
+ }
+
+ template <class FilterType, class IdentifierFilterType, class V>
+ optional<Filter> convertUnaryFilter(const V& value, Error& error) const {
if (arrayLength(value) < 2) {
- return Error { "filter expression must have 2 elements" };
+ error = { "filter expression must have 2 elements" };
+ return {};
}
optional<std::string> key = toString(arrayMember(value, 1));
if (!key) {
- return Error { "filter expression key must be a string" };
+ error = { "filter expression key must be a string" };
+ return {};
}
- return FilterType { *key };
+ if (*key == "$id") {
+ return { IdentifierFilterType {} };
+ } else {
+ return { FilterType { *key } };
+ }
+ }
+
+ template <class FilterType, class TypeFilterType, class IdentifierFilterType, class V>
+ optional<Filter> convertEqualityFilter(const V& value, Error& error) const {
+ if (arrayLength(value) < 3) {
+ error = { "filter expression must have 3 elements" };
+ return {};
+ }
+
+ optional<std::string> key = toString(arrayMember(value, 1));
+ if (!key) {
+ error = { "filter expression key must be a string" };
+ return {};
+ }
+
+ if (*key == "$type") {
+ optional<FeatureType> filterValue = toFeatureType(arrayMember(value, 2), error);
+ if (!filterValue) {
+ return {};
+ }
+
+ return { TypeFilterType { *filterValue } };
+
+ } else if (*key == "$id") {
+ optional<FeatureIdentifier> filterValue = toFeatureIdentifier(arrayMember(value, 2), error);
+ if (!filterValue) {
+ return {};
+ }
+
+ return { IdentifierFilterType { *filterValue } };
+
+ } else {
+ optional<Value> filterValue = normalizeValue(toValue(arrayMember(value, 2)), error);
+ if (!filterValue) {
+ return {};
+ }
+
+ return { FilterType { *key, *filterValue } };
+ }
}
template <class FilterType, class V>
- Result<Filter> convertBinaryFilter(const V& value) const {
+ optional<Filter> convertBinaryFilter(const V& value, Error& error) const {
if (arrayLength(value) < 3) {
- return Error { "filter expression must have 3 elements" };
+ error = { "filter expression must have 3 elements" };
+ return {};
}
optional<std::string> key = toString(arrayMember(value, 1));
if (!key) {
- return Error { "filter expression key must be a string" };
+ error = { "filter expression key must be a string" };
+ return {};
}
- Result<Value> filterValue = normalizeValue(*key, toValue(arrayMember(value, 2)));
+ optional<Value> filterValue = normalizeValue(toValue(arrayMember(value, 2)), error);
if (!filterValue) {
- return filterValue.error();
+ return {};
}
- return FilterType { *key, *filterValue };
+ return { FilterType { *key, *filterValue } };
}
- template <class FilterType, class V>
- Result<Filter> convertSetFilter(const V& value) const {
+ template <class FilterType, class TypeFilterType, class IdentifierFilterType, class V>
+ optional<Filter> convertSetFilter(const V& value, Error& error) const {
if (arrayLength(value) < 2) {
- return Error { "filter expression must at least 2 elements" };
+ error = { "filter expression must at least 2 elements" };
+ return {};
}
optional<std::string> key = toString(arrayMember(value, 1));
if (!key) {
- return Error { "filter expression key must be a string" };
+ error = { "filter expression key must be a string" };
+ return {};
}
- std::vector<Value> values;
- for (std::size_t i = 2; i < arrayLength(value); ++i) {
- Result<Value> filterValue = normalizeValue(*key, toValue(arrayMember(value, i)));
- if (!filterValue) {
- return filterValue.error();
+ if (*key == "$type") {
+ std::vector<FeatureType> values;
+ for (std::size_t i = 2; i < arrayLength(value); ++i) {
+ optional<FeatureType> filterValue = toFeatureType(arrayMember(value, i), error);
+ if (!filterValue) {
+ return {};
+ }
+ values.push_back(*filterValue);
+ }
+
+ return { TypeFilterType { std::move(values) } };
+
+ } else if (*key == "$id") {
+ std::vector<FeatureIdentifier> values;
+ for (std::size_t i = 2; i < arrayLength(value); ++i) {
+ optional<FeatureIdentifier> filterValue = toFeatureIdentifier(arrayMember(value, i), error);
+ if (!filterValue) {
+ return {};
+ }
+ values.push_back(*filterValue);
}
- values.push_back(*filterValue);
- }
- return FilterType { *key, std::move(values) };
+ return { IdentifierFilterType { std::move(values) } };
+
+ } else {
+ std::vector<Value> values;
+ for (std::size_t i = 2; i < arrayLength(value); ++i) {
+ optional<Value> filterValue = normalizeValue(toValue(arrayMember(value, i)), error);
+ if (!filterValue) {
+ return {};
+ }
+ values.push_back(*filterValue);
+ }
+
+ return { FilterType { *key, std::move(values) } };
+ }
}
template <class FilterType, class V>
- Result<Filter> convertCompoundFilter(const V& value) const {
+ optional<Filter> convertCompoundFilter(const V& value, Error& error) const {
std::vector<Filter> filters;
for (std::size_t i = 1; i < arrayLength(value); ++i) {
- Result<Filter> element = operator()(arrayMember(value, i));
+ optional<Filter> element = operator()(arrayMember(value, i), error);
if (!element) {
- return element.error();
+ return {};
}
filters.push_back(*element);
}
- return FilterType { std::move(filters) };
+ return { FilterType { std::move(filters) } };
}
};
diff --git a/include/mbgl/style/conversion/function.hpp b/include/mbgl/style/conversion/function.hpp
index 6a0b67618f..752b6dd045 100644
--- a/include/mbgl/style/conversion/function.hpp
+++ b/include/mbgl/style/conversion/function.hpp
@@ -1,70 +1,403 @@
#pragma once
-#include <mbgl/style/function.hpp>
+#include <mbgl/style/function/camera_function.hpp>
+#include <mbgl/style/function/source_function.hpp>
+#include <mbgl/style/function/composite_function.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/constant.hpp>
+#include <mbgl/util/ignore.hpp>
namespace mbgl {
namespace style {
namespace conversion {
+template <class D, class R, class V>
+optional<std::map<D, R>> convertStops(const V& value, Error& error) {
+ auto stopsValue = objectMember(value, "stops");
+ if (!stopsValue) {
+ error = { "function value must specify stops" };
+ return {};
+ }
+
+ if (!isArray(*stopsValue)) {
+ error = { "function stops must be an array" };
+ return {};
+ }
+
+ if (arrayLength(*stopsValue) == 0) {
+ error = { "function must have at least one stop" };
+ return {};
+ }
+
+ std::map<D, R> stops;
+ for (std::size_t i = 0; i < arrayLength(*stopsValue); ++i) {
+ const auto& stopValue = arrayMember(*stopsValue, i);
+
+ if (!isArray(stopValue)) {
+ error = { "function stop must be an array" };
+ return {};
+ }
+
+ if (arrayLength(stopValue) != 2) {
+ error = { "function stop must have two elements" };
+ return {};
+ }
+
+ optional<D> d = convert<D>(arrayMember(stopValue, 0), error);
+ if (!d) {
+ return {};
+ }
+
+ optional<R> r = convert<R>(arrayMember(stopValue, 1), error);
+ if (!r) {
+ return {};
+ }
+
+ stops.emplace(*d, *r);
+ }
+
+ return stops;
+}
+
template <class T>
-struct Converter<Function<T>> {
+struct Converter<ExponentialStops<T>> {
+ static constexpr const char * type = "exponential";
+
template <class V>
- Result<Function<T>> operator()(const V& value) const {
- if (!isObject(value)) {
- return Error { "function must be an object" };
+ optional<ExponentialStops<T>> operator()(const V& value, Error& error) const {
+ auto stops = convertStops<float, T>(value, error);
+ if (!stops) {
+ return {};
}
- auto stopsValue = objectMember(value, "stops");
- if (!stopsValue) {
- return Error { "function value must specify stops" };
+ auto baseValue = objectMember(value, "base");
+ if (!baseValue) {
+ return ExponentialStops<T>(*stops);
}
- if (!isArray(*stopsValue)) {
- return Error { "function stops must be an array" };
+ optional<float> base = toNumber(*baseValue);
+ if (!base) {
+ error = { "function base must be a number"};
+ return {};
}
- if (arrayLength(*stopsValue) == 0) {
- return Error { "function must have at least one stop" };
+ return ExponentialStops<T>(*stops, *base);
+ }
+};
+
+template <class T>
+struct Converter<IntervalStops<T>> {
+ static constexpr const char * type = "interval";
+
+ template <class V>
+ optional<IntervalStops<T>> operator()(const V& value, Error& error) const {
+ auto stops = convertStops<float, T>(value, error);
+ if (!stops) {
+ return {};
}
+ return IntervalStops<T>(*stops);
+ }
+};
- std::vector<std::pair<float, T>> stops;
- for (std::size_t i = 0; i < arrayLength(*stopsValue); ++i) {
- const auto& stopValue = arrayMember(*stopsValue, i);
+template <>
+struct Converter<CategoricalValue> {
+ template <class V>
+ optional<CategoricalValue> operator()(const V& value, Error& error) const {
+ auto b = toBool(value);
+ if (b) {
+ return { *b };
+ }
- if (!isArray(stopValue)) {
- return Error { "function stop must be an array" };
- }
+ auto n = toNumber(value);
+ if (n) {
+ return { int64_t(*n) };
+ }
- if (arrayLength(stopValue) != 2) {
- return Error { "function stop must have two elements" };
- }
+ auto s = toString(value);
+ if (s) {
+ return { *s };
+ }
- optional<float> z = toNumber(arrayMember(stopValue, 0));
- if (!z) {
- return Error { "function stop zoom level must be a number" };
- }
+ error = { "stop domain value must be a number, string, or boolean" };
+ return {};
+ }
+};
+
+template <class T>
+struct Converter<CategoricalStops<T>> {
+ static constexpr const char * type = "categorical";
+
+ template <class V>
+ optional<CategoricalStops<T>> operator()(const V& value, Error& error) const {
+ auto stops = convertStops<CategoricalValue, T>(value, error);
+ if (!stops) {
+ return {};
+ }
+ return CategoricalStops<T>(
+ std::map<CategoricalValue, T>((*stops).begin(), (*stops).end()));
+ }
+};
+
+template <class T>
+struct Converter<IdentityStops<T>> {
+ static constexpr const char * type = "identity";
+
+ template <class V>
+ optional<IdentityStops<T>> operator()(const V&, Error&) const {
+ return IdentityStops<T>();
+ }
+};
+
+template <class, class>
+struct StopsConverter;
+
+template <class T, class... Ts>
+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>::value ? "exponential" : "interval";
+
+ auto typeValue = objectMember(value, "type");
+ if (typeValue && toString(*typeValue)) {
+ type = *toString(*typeValue);
+ }
- Result<T> v = convert<T>(arrayMember(stopValue, 1));
- if (!v) {
- return v.error();
+ bool matched = false;
+ optional<variant<Ts...>> result;
+
+ // Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47226
+ auto tryConvert = [&] (auto* tp) {
+ using Stops = std::decay_t<decltype(*tp)>;
+ if (type == Converter<Stops>::type) {
+ matched = true;
+ optional<Stops> stops = convert<Stops>(value, error);
+ if (stops) {
+ result = variant<Ts...>(*stops);
+ }
}
+ };
+
+ util::ignore({
+ (tryConvert((Ts*)nullptr), 0)...
+ });
+
+ if (!matched) {
+ error = { "unsupported function type" };
+ return {};
+ }
+
+ return result;
+ }
+};
+
+template <class T>
+struct Converter<CameraFunction<T>> {
+ template <class V>
+ optional<CameraFunction<T>> operator()(const V& value, Error& error) const {
+ if (!isObject(value)) {
+ error = { "function must be an object" };
+ return {};
+ }
+
+ auto stops = StopsConverter<T, typename CameraFunction<T>::Stops>()(value, error);
+ if (!stops) {
+ return {};
+ }
+
+ return CameraFunction<T>(*stops);
+ }
+};
+
+template <class T, class V>
+optional<optional<T>> convertDefaultValue(const V& value, Error& error) {
+ auto defaultValueValue = objectMember(value, "default");
+ if (!defaultValueValue) {
+ return optional<T>();
+ }
- stops.emplace_back(*z, *v);
+ auto defaultValue = convert<T>(*defaultValueValue, error);
+ if (!defaultValue) {
+ error = { R"(wrong type for "default": )" + error.message };
+ return {};
+ }
+
+ return { *defaultValue };
+}
+
+template <class T>
+struct Converter<SourceFunction<T>> {
+ template <class V>
+ optional<SourceFunction<T>> operator()(const V& value, Error& error) const {
+ if (!isObject(value)) {
+ error = { "function must be an object" };
+ return {};
+ }
+
+ auto propertyValue = objectMember(value, "property");
+ if (!propertyValue) {
+ error = { "function must specify property" };
+ return {};
+ }
+
+ auto propertyString = toString(*propertyValue);
+ if (!propertyString) {
+ error = { "function property must be a string" };
+ return {};
+ }
+
+ auto stops = StopsConverter<T, typename SourceFunction<T>::Stops>()(value, error);
+ if (!stops) {
+ return {};
+ }
+
+ auto defaultValue = convertDefaultValue<T>(value, error);
+ if (!defaultValue) {
+ return {};
+ }
+
+ return SourceFunction<T>(*propertyString, *stops, *defaultValue);
+ }
+};
+
+template <class S>
+struct CompositeValue : std::pair<float, S> {
+ using std::pair<float, S>::pair;
+};
+
+template <class S>
+struct Converter<CompositeValue<S>> {
+ template <class V>
+ optional<CompositeValue<S>> operator()(const V& value, Error& error) const {
+ if (!isObject(value)) {
+ error = { "stop must be an object" };
+ return {};
+ }
+
+ auto zoomValue = objectMember(value, "zoom");
+ if (!zoomValue) {
+ error = { "stop must specify zoom" };
+ return {};
+ }
+
+ auto propertyValue = objectMember(value, "value");
+ if (!propertyValue) {
+ error = { "stop must specify value" };
+ return {};
+ }
+
+ optional<float> z = convert<float>(*zoomValue, error);
+ if (!z) {
+ return {};
+ }
+
+ optional<S> s = convert<S>(*propertyValue, error);
+ if (!s) {
+ return {};
+ }
+
+ return CompositeValue<S> { *z, *s };
+ }
+};
+
+template <class T>
+struct Converter<CompositeExponentialStops<T>> {
+ static constexpr const char * type = "exponential";
+
+ template <class V>
+ optional<CompositeExponentialStops<T>> operator()(const V& value, Error& error) const {
+ auto stops = convertStops<CompositeValue<float>, T>(value, error);
+ if (!stops) {
+ return {};
}
+ auto base = 1.0f;
auto baseValue = objectMember(value, "base");
- if (!baseValue) {
- return Function<T>(stops, 1.0f);
+ if (baseValue && toNumber(*baseValue)) {
+ base = *toNumber(*baseValue);
}
- optional<float> base = toNumber(*baseValue);
- if (!base) {
- return Error { "function base must be a number"};
+ std::map<float, std::map<float, T>> convertedStops;
+ for (const auto& stop : *stops) {
+ convertedStops[stop.first.first].emplace(stop.first.second, stop.second);
+ }
+
+ return CompositeExponentialStops<T>(convertedStops, base);
+ }
+};
+
+template <class T>
+struct Converter<CompositeIntervalStops<T>> {
+ static constexpr const char * type = "interval";
+
+ template <class V>
+ optional<CompositeIntervalStops<T>> operator()(const V& value, Error& error) const {
+ auto stops = convertStops<CompositeValue<float>, T>(value, error);
+ if (!stops) {
+ return {};
+ }
+
+ std::map<float, std::map<float, T>> convertedStops;
+ for (const auto& stop : *stops) {
+ convertedStops[stop.first.first].emplace(stop.first.second, stop.second);
+ }
+
+ return CompositeIntervalStops<T>(convertedStops);
+ }
+};
+
+template <class T>
+struct Converter<CompositeCategoricalStops<T>> {
+ static constexpr const char * type = "categorical";
+
+ template <class V>
+ optional<CompositeCategoricalStops<T>> operator()(const V& value, Error& error) const {
+ auto stops = convertStops<CompositeValue<CategoricalValue>, T>(value, error);
+ if (!stops) {
+ return {};
+ }
+
+ std::map<float, std::map<CategoricalValue, T>> convertedStops;
+ for (const auto& stop : *stops) {
+ convertedStops[stop.first.first].emplace(stop.first.second, stop.second);
+ }
+
+ return CompositeCategoricalStops<T>(convertedStops);
+ }
+};
+
+template <class T>
+struct Converter<CompositeFunction<T>> {
+ template <class V>
+ optional<CompositeFunction<T>> operator()(const V& value, Error& error) const {
+ if (!isObject(value)) {
+ error = { "function must be an object" };
+ return {};
+ }
+
+ auto propertyValue = objectMember(value, "property");
+ if (!propertyValue) {
+ error = { "function must specify property" };
+ return {};
+ }
+
+ auto propertyString = toString(*propertyValue);
+ if (!propertyString) {
+ error = { "function property must be a string" };
+ return {};
+ }
+
+ auto stops = StopsConverter<T, typename CompositeFunction<T>::Stops>()(value, error);
+ if (!stops) {
+ return {};
+ }
+
+ auto defaultValue = convertDefaultValue<T>(value, error);
+ if (!defaultValue) {
+ return {};
}
- return Function<T>(stops, *base);
+ return CompositeFunction<T>(*propertyString, *stops, *defaultValue);
}
};
diff --git a/include/mbgl/style/conversion/geojson.hpp b/include/mbgl/style/conversion/geojson.hpp
index ba10b3ecc8..0b594f066c 100644
--- a/include/mbgl/style/conversion/geojson.hpp
+++ b/include/mbgl/style/conversion/geojson.hpp
@@ -1,14 +1,22 @@
#pragma once
#include <mbgl/style/conversion.hpp>
-#include <mbgl/style/sources/geojson_source.hpp>
+#include <mbgl/util/geojson.hpp>
namespace mbgl {
namespace style {
namespace conversion {
-template <class V>
-Result<GeoJSON> convertGeoJSON(const V& value);
+template <>
+struct Converter<GeoJSON> {
+public:
+ optional<GeoJSON> operator()(const std::string&, Error&) const;
+
+ // This is explicitly specialized in the .cpp file for JSValue. It may also be explicitly
+ // specialized for SDK-specific types (e.g. mbgl::android::Value).
+ template <class V>
+ optional<GeoJSON> operator()(const V&, Error&) const;
+};
} // namespace conversion
} // namespace style
diff --git a/include/mbgl/style/conversion/geojson_options.hpp b/include/mbgl/style/conversion/geojson_options.hpp
index 880090b402..19383d90ce 100644
--- a/include/mbgl/style/conversion/geojson_options.hpp
+++ b/include/mbgl/style/conversion/geojson_options.hpp
@@ -11,7 +11,7 @@ template <>
struct Converter<GeoJSONOptions> {
template <class V>
- Result<GeoJSONOptions> operator()(const V& value) const {
+ optional<GeoJSONOptions> operator()(const V& value, Error& error) const {
GeoJSONOptions options;
const auto maxzoomValue = objectMember(value, "maxzoom");
@@ -19,7 +19,8 @@ struct Converter<GeoJSONOptions> {
if (toNumber(*maxzoomValue)) {
options.maxzoom = static_cast<uint8_t>(*toNumber(*maxzoomValue));
} else {
- return Error{ "GeoJSON source maxzoom value must be a number" };
+ error = { "GeoJSON source maxzoom value must be a number" };
+ return {};
}
}
@@ -28,7 +29,8 @@ struct Converter<GeoJSONOptions> {
if (toNumber(*bufferValue)) {
options.buffer = static_cast<uint16_t>(*toNumber(*bufferValue));
} else {
- return Error{ "GeoJSON source buffer value must be a number" };
+ error = { "GeoJSON source buffer value must be a number" };
+ return {};
}
}
@@ -37,7 +39,8 @@ struct Converter<GeoJSONOptions> {
if (toNumber(*toleranceValue)) {
options.tolerance = static_cast<double>(*toNumber(*toleranceValue));
} else {
- return Error{ "GeoJSON source tolerance value must be a number" };
+ error = { "GeoJSON source tolerance value must be a number" };
+ return {};
}
}
@@ -46,7 +49,8 @@ struct Converter<GeoJSONOptions> {
if (toBool(*clusterValue)) {
options.cluster = *toBool(*clusterValue);
} else {
- return Error{ "GeoJSON source cluster value must be a boolean" };
+ error = { "GeoJSON source cluster value must be a boolean" };
+ return {};
}
}
@@ -55,7 +59,8 @@ struct Converter<GeoJSONOptions> {
if (toNumber(*clusterMaxZoomValue)) {
options.clusterMaxZoom = static_cast<uint8_t>(*toNumber(*clusterMaxZoomValue));
} else {
- return Error{ "GeoJSON source clusterMaxZoom value must be a number" };
+ error = { "GeoJSON source clusterMaxZoom value must be a number" };
+ return {};
}
}
@@ -64,7 +69,8 @@ struct Converter<GeoJSONOptions> {
if (toNumber(*clusterRadiusValue)) {
options.clusterRadius = static_cast<double>(*toNumber(*clusterRadiusValue));
} else {
- return Error{ "GeoJSON source clusterRadius value must be a number" };
+ error = { "GeoJSON source clusterRadius value must be a number" };
+ return {};
}
}
diff --git a/include/mbgl/style/conversion/layer.hpp b/include/mbgl/style/conversion/layer.hpp
index 0539dcf9ad..1fe467165d 100644
--- a/include/mbgl/style/conversion/layer.hpp
+++ b/include/mbgl/style/conversion/layer.hpp
@@ -4,6 +4,7 @@
#include <mbgl/style/layers/background_layer.hpp>
#include <mbgl/style/layers/circle_layer.hpp>
#include <mbgl/style/layers/fill_layer.hpp>
+#include <mbgl/style/layers/fill_extrusion_layer.hpp>
#include <mbgl/style/layers/line_layer.hpp>
#include <mbgl/style/layers/raster_layer.hpp>
#include <mbgl/style/layers/symbol_layer.hpp>
@@ -27,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);
});
}
@@ -58,47 +52,55 @@ template <>
struct Converter<std::unique_ptr<Layer>> {
public:
template <class V>
- Result<std::unique_ptr<Layer>> operator()(const V& value) const {
+ optional<std::unique_ptr<Layer>> operator()(const V& value, Error& error) const {
if (!isObject(value)) {
- return Error { "layer must be an object" };
+ error = { "layer must be an object" };
+ return {};
}
auto idValue = objectMember(value, "id");
if (!idValue) {
- return Error { "layer must have an id" };
+ error = { "layer must have an id" };
+ return {};
}
optional<std::string> id = toString(*idValue);
if (!id) {
- return Error { "layer id must be a string" };
+ error = { "layer id must be a string" };
+ return {};
}
auto typeValue = objectMember(value, "type");
if (!typeValue) {
- return Error { "layer must have a type" };
+ error = { "layer must have a type" };
+ return {};
}
optional<std::string> type = toString(*typeValue);
if (!type) {
- return Error { "layer type must be a string" };
+ error = { "layer type must be a string" };
+ return {};
}
- Result<std::unique_ptr<Layer>> converted;
+ optional<std::unique_ptr<Layer>> converted;
if (*type == "fill") {
- converted = convertVectorLayer<FillLayer>(*id, value);
+ converted = convertVectorLayer<FillLayer>(*id, value, error);
+ } else if (*type == "fill-extrusion") {
+ converted = convertVectorLayer<FillExtrusionLayer>(*id, value, error);
} else if (*type == "line") {
- converted = convertVectorLayer<LineLayer>(*id, value);
+ converted = convertVectorLayer<LineLayer>(*id, value, error);
} else if (*type == "circle") {
- converted = convertVectorLayer<CircleLayer>(*id, value);
+ converted = convertVectorLayer<CircleLayer>(*id, value, error);
} else if (*type == "symbol") {
- converted = convertVectorLayer<SymbolLayer>(*id, value);
+ converted = convertVectorLayer<SymbolLayer>(*id, value, error);
} else if (*type == "raster") {
- converted = convertRasterLayer(*id, value);
+ converted = convertRasterLayer(*id, value, error);
} else if (*type == "background") {
- converted = convertBackgroundLayer(*id, value);
+ converted = convertBackgroundLayer(*id, value, error);
} else {
- return Error { "invalid layer type" };
+ error = { "invalid layer type" };
+ return {};
}
if (!converted) {
@@ -111,7 +113,8 @@ public:
if (minzoomValue) {
optional<float> minzoom = toNumber(*minzoomValue);
if (!minzoom) {
- return Error { "minzoom must be numeric" };
+ error = { "minzoom must be numeric" };
+ return {};
}
layer->setMinZoom(*minzoom);
}
@@ -120,7 +123,8 @@ public:
if (maxzoomValue) {
optional<float> maxzoom = toNumber(*maxzoomValue);
if (!maxzoom) {
- return Error { "maxzoom must be numeric" };
+ error = { "maxzoom must be numeric" };
+ return {};
}
layer->setMaxZoom(*maxzoom);
}
@@ -128,19 +132,22 @@ public:
auto layoutValue = objectMember(value, "layout");
if (layoutValue) {
if (!isObject(*layoutValue)) {
- return Error { "layout must be an object" };
+ error = { "layout must be an object" };
+ return {};
}
- optional<Error> error = eachMember(*layoutValue, [&] (const std::string& k, const V& v) {
+ optional<Error> error_ = eachMember(*layoutValue, [&] (const std::string& k, const V& v) {
return setLayoutProperty(*layer, k, v);
});
- if (error) {
- return *error;
+ if (error_) {
+ error = *error_;
+ return {};
}
}
- optional<Error> error = setPaintProperties(*layer, value);
- if (error) {
- return *error;
+ optional<Error> error_ = setPaintProperties(*layer, value);
+ if (error_) {
+ error = *error_;
+ return {};
}
return std::move(layer);
@@ -148,15 +155,17 @@ public:
private:
template <class LayerType, class V>
- Result<std::unique_ptr<Layer>> convertVectorLayer(const std::string& id, const V& value) const {
+ optional<std::unique_ptr<Layer>> convertVectorLayer(const std::string& id, const V& value, Error& error) const {
auto sourceValue = objectMember(value, "source");
if (!sourceValue) {
- return Error { "layer must have a source" };
+ error = { "layer must have a source" };
+ return {};
}
optional<std::string> source = toString(*sourceValue);
if (!source) {
- return Error { "layer source must be a string" };
+ error = { "layer source must be a string" };
+ return {};
}
std::unique_ptr<LayerType> layer = std::make_unique<LayerType>(id, *source);
@@ -165,41 +174,44 @@ private:
if (sourceLayerValue) {
optional<std::string> sourceLayer = toString(*sourceLayerValue);
if (!sourceLayer) {
- return Error { "layer source-layer must be a string" };
+ error = { "layer source-layer must be a string" };
+ return {};
}
layer->setSourceLayer(*sourceLayer);
}
auto filterValue = objectMember(value, "filter");
if (filterValue) {
- Result<Filter> filter = convert<Filter>(*filterValue);
+ optional<Filter> filter = convert<Filter>(*filterValue, error);
if (!filter) {
- return filter.error();
+ return {};
}
layer->setFilter(*filter);
}
- return std::move(layer);
+ return { std::move(layer) };
}
template <class V>
- Result<std::unique_ptr<Layer>> convertRasterLayer(const std::string& id, const V& value) const {
+ optional<std::unique_ptr<Layer>> convertRasterLayer(const std::string& id, const V& value, Error& error) const {
auto sourceValue = objectMember(value, "source");
if (!sourceValue) {
- return Error { "layer must have a source" };
+ error = { "layer must have a source" };
+ return {};
}
optional<std::string> source = toString(*sourceValue);
if (!source) {
- return Error { "layer source must be a string" };
+ error = { "layer source must be a string" };
+ return {};
}
- return std::make_unique<RasterLayer>(id, *source);
+ return { std::make_unique<RasterLayer>(id, *source) };
}
template <class V>
- Result<std::unique_ptr<Layer>> convertBackgroundLayer(const std::string& id, const V&) const {
- return std::make_unique<BackgroundLayer>(id);
+ optional<std::unique_ptr<Layer>> convertBackgroundLayer(const std::string& id, const V&, Error&) const {
+ return { std::make_unique<BackgroundLayer>(id) };
}
};
diff --git a/include/mbgl/style/conversion/light.hpp b/include/mbgl/style/conversion/light.hpp
new file mode 100644
index 0000000000..ba162516c0
--- /dev/null
+++ b/include/mbgl/style/conversion/light.hpp
@@ -0,0 +1,122 @@
+#pragma once
+
+#include <mbgl/style/light.hpp>
+#include <mbgl/style/conversion.hpp>
+#include <mbgl/style/conversion/position.hpp>
+#include <mbgl/style/conversion/property_value.hpp>
+#include <mbgl/style/conversion/transition_options.hpp>
+
+namespace mbgl {
+namespace style {
+namespace conversion {
+
+template <>
+struct Converter<Light> {
+public:
+ template <class V>
+ optional<Light> operator()(const V& value, Error& error) const {
+ if (!isObject(value)) {
+ error = { "light must be an object" };
+ return {};
+ }
+
+ Light light;
+
+ const auto anchor = objectMember(value, "anchor");
+ if (anchor) {
+ optional<PropertyValue<LightAnchorType>> convertedAnchor =
+ convert<PropertyValue<LightAnchorType>>(*anchor, error);
+
+ if (convertedAnchor) {
+ light.setAnchor(*convertedAnchor);
+ } else {
+ return {};
+ }
+ }
+
+ const auto anchorTransition = objectMember(value, "anchor-transition");
+ if (anchorTransition) {
+ optional<TransitionOptions> transition =
+ convert<TransitionOptions>(*anchorTransition, error);
+ if (transition) {
+ light.setAnchorTransition(*transition);
+ } else {
+ return {};
+ }
+ }
+
+ const auto color = objectMember(value, "color");
+ if (color) {
+ optional<PropertyValue<Color>> convertedColor =
+ convert<PropertyValue<Color>>(*color, error);
+
+ if (convertedColor) {
+ light.setColor(*convertedColor);
+ } else {
+ return {};
+ }
+ }
+
+ const auto colorTransition = objectMember(value, "color-transition");
+ if (colorTransition) {
+ optional<TransitionOptions> transition =
+ convert<TransitionOptions>(*colorTransition, error);
+ if (transition) {
+ light.setColorTransition(*transition);
+ } else {
+ return {};
+ }
+ }
+
+ const auto position = objectMember(value, "position");
+ if (position) {
+ optional<PropertyValue<Position>> convertedPosition =
+ convert<PropertyValue<Position>>(*position, error);
+
+ if (convertedPosition) {
+ light.setPosition(*convertedPosition);
+ } else {
+ return {};
+ }
+ }
+
+ const auto positionTransition = objectMember(value, "position-transition");
+ if (positionTransition) {
+ optional<TransitionOptions> transition =
+ convert<TransitionOptions>(*positionTransition, error);
+ if (transition) {
+ light.setPositionTransition(*transition);
+ } else {
+ return {};
+ }
+ }
+
+ const auto intensity = objectMember(value, "intensity");
+ if (intensity) {
+ optional<PropertyValue<float>> convertedIntensity =
+ convert<PropertyValue<float>>(*intensity, error);
+
+ if (convertedIntensity) {
+ light.setIntensity(*convertedIntensity);
+ } else {
+ return {};
+ }
+ }
+
+ const auto intensityTransition = objectMember(value, "intensity-transition");
+ if (intensityTransition) {
+ optional<TransitionOptions> transition =
+ convert<TransitionOptions>(*intensityTransition, error);
+ if (transition) {
+ light.setIntensityTransition(*transition);
+ } else {
+ return {};
+ }
+ }
+ return { std::move(light) };
+ };
+};
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/conversion/make_property_setters.hpp b/include/mbgl/style/conversion/make_property_setters.hpp
index e30359937e..9252297d75 100644
--- a/include/mbgl/style/conversion/make_property_setters.hpp
+++ b/include/mbgl/style/conversion/make_property_setters.hpp
@@ -20,50 +20,51 @@ 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"] = makePropertySetter<V>(&LineLayer::setLineCap);
- result["line-join"] = makePropertySetter<V>(&LineLayer::setLineJoin);
- result["line-miter-limit"] = makePropertySetter<V>(&LineLayer::setLineMiterLimit);
- result["line-round-limit"] = makePropertySetter<V>(&LineLayer::setLineRoundLimit);
-
- result["symbol-placement"] = makePropertySetter<V>(&SymbolLayer::setSymbolPlacement);
- result["symbol-spacing"] = makePropertySetter<V>(&SymbolLayer::setSymbolSpacing);
- result["symbol-avoid-edges"] = makePropertySetter<V>(&SymbolLayer::setSymbolAvoidEdges);
- result["icon-allow-overlap"] = makePropertySetter<V>(&SymbolLayer::setIconAllowOverlap);
- result["icon-ignore-placement"] = makePropertySetter<V>(&SymbolLayer::setIconIgnorePlacement);
- result["icon-optional"] = makePropertySetter<V>(&SymbolLayer::setIconOptional);
- result["icon-rotation-alignment"] = makePropertySetter<V>(&SymbolLayer::setIconRotationAlignment);
- result["icon-size"] = makePropertySetter<V>(&SymbolLayer::setIconSize);
- result["icon-text-fit"] = makePropertySetter<V>(&SymbolLayer::setIconTextFit);
- result["icon-text-fit-padding"] = makePropertySetter<V>(&SymbolLayer::setIconTextFitPadding);
- result["icon-image"] = makePropertySetter<V>(&SymbolLayer::setIconImage);
- result["icon-rotate"] = makePropertySetter<V>(&SymbolLayer::setIconRotate);
- result["icon-padding"] = makePropertySetter<V>(&SymbolLayer::setIconPadding);
- result["icon-keep-upright"] = makePropertySetter<V>(&SymbolLayer::setIconKeepUpright);
- result["icon-offset"] = makePropertySetter<V>(&SymbolLayer::setIconOffset);
- result["text-pitch-alignment"] = makePropertySetter<V>(&SymbolLayer::setTextPitchAlignment);
- result["text-rotation-alignment"] = makePropertySetter<V>(&SymbolLayer::setTextRotationAlignment);
- result["text-field"] = makePropertySetter<V>(&SymbolLayer::setTextField);
- result["text-font"] = makePropertySetter<V>(&SymbolLayer::setTextFont);
- result["text-size"] = makePropertySetter<V>(&SymbolLayer::setTextSize);
- result["text-max-width"] = makePropertySetter<V>(&SymbolLayer::setTextMaxWidth);
- result["text-line-height"] = makePropertySetter<V>(&SymbolLayer::setTextLineHeight);
- result["text-letter-spacing"] = makePropertySetter<V>(&SymbolLayer::setTextLetterSpacing);
- result["text-justify"] = makePropertySetter<V>(&SymbolLayer::setTextJustify);
- result["text-anchor"] = makePropertySetter<V>(&SymbolLayer::setTextAnchor);
- result["text-max-angle"] = makePropertySetter<V>(&SymbolLayer::setTextMaxAngle);
- result["text-rotate"] = makePropertySetter<V>(&SymbolLayer::setTextRotate);
- result["text-padding"] = makePropertySetter<V>(&SymbolLayer::setTextPadding);
- result["text-keep-upright"] = makePropertySetter<V>(&SymbolLayer::setTextKeepUpright);
- result["text-transform"] = makePropertySetter<V>(&SymbolLayer::setTextTransform);
- result["text-offset"] = makePropertySetter<V>(&SymbolLayer::setTextOffset);
- result["text-allow-overlap"] = makePropertySetter<V>(&SymbolLayer::setTextAllowOverlap);
- result["text-ignore-placement"] = makePropertySetter<V>(&SymbolLayer::setTextIgnorePlacement);
- result["text-optional"] = makePropertySetter<V>(&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-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, PropertyValue<float>, &SymbolLayer::setTextMaxWidth>;
+ result["text-line-height"] = &setProperty<V, SymbolLayer, PropertyValue<float>, &SymbolLayer::setTextLineHeight>;
+ result["text-letter-spacing"] = &setProperty<V, SymbolLayer, PropertyValue<float>, &SymbolLayer::setTextLetterSpacing>;
+ result["text-justify"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<TextJustifyType>, &SymbolLayer::setTextJustify>;
+ result["text-anchor"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<TextAnchorType>, &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,72 +75,132 @@ auto makeLayoutPropertySetters() {
template <class V>
auto makePaintPropertySetters() {
- std::unordered_map<std::string, PaintPropertySetter<V>> result;
-
- result["fill-antialias"] = makePropertySetter<V>(&FillLayer::setFillAntialias);
- result["fill-opacity"] = makePropertySetter<V>(&FillLayer::setFillOpacity);
- result["fill-color"] = makePropertySetter<V>(&FillLayer::setFillColor);
- result["fill-outline-color"] = makePropertySetter<V>(&FillLayer::setFillOutlineColor);
- result["fill-translate"] = makePropertySetter<V>(&FillLayer::setFillTranslate);
- result["fill-translate-anchor"] = makePropertySetter<V>(&FillLayer::setFillTranslateAnchor);
- result["fill-pattern"] = makePropertySetter<V>(&FillLayer::setFillPattern);
-
- result["line-opacity"] = makePropertySetter<V>(&LineLayer::setLineOpacity);
- result["line-color"] = makePropertySetter<V>(&LineLayer::setLineColor);
- result["line-translate"] = makePropertySetter<V>(&LineLayer::setLineTranslate);
- result["line-translate-anchor"] = makePropertySetter<V>(&LineLayer::setLineTranslateAnchor);
- result["line-width"] = makePropertySetter<V>(&LineLayer::setLineWidth);
- result["line-gap-width"] = makePropertySetter<V>(&LineLayer::setLineGapWidth);
- result["line-offset"] = makePropertySetter<V>(&LineLayer::setLineOffset);
- result["line-blur"] = makePropertySetter<V>(&LineLayer::setLineBlur);
- result["line-dasharray"] = makePropertySetter<V>(&LineLayer::setLineDasharray);
- result["line-pattern"] = makePropertySetter<V>(&LineLayer::setLinePattern);
-
- result["icon-opacity"] = makePropertySetter<V>(&SymbolLayer::setIconOpacity);
- result["icon-color"] = makePropertySetter<V>(&SymbolLayer::setIconColor);
- result["icon-halo-color"] = makePropertySetter<V>(&SymbolLayer::setIconHaloColor);
- result["icon-halo-width"] = makePropertySetter<V>(&SymbolLayer::setIconHaloWidth);
- result["icon-halo-blur"] = makePropertySetter<V>(&SymbolLayer::setIconHaloBlur);
- result["icon-translate"] = makePropertySetter<V>(&SymbolLayer::setIconTranslate);
- result["icon-translate-anchor"] = makePropertySetter<V>(&SymbolLayer::setIconTranslateAnchor);
- result["text-opacity"] = makePropertySetter<V>(&SymbolLayer::setTextOpacity);
- result["text-color"] = makePropertySetter<V>(&SymbolLayer::setTextColor);
- result["text-halo-color"] = makePropertySetter<V>(&SymbolLayer::setTextHaloColor);
- result["text-halo-width"] = makePropertySetter<V>(&SymbolLayer::setTextHaloWidth);
- result["text-halo-blur"] = makePropertySetter<V>(&SymbolLayer::setTextHaloBlur);
- result["text-translate"] = makePropertySetter<V>(&SymbolLayer::setTextTranslate);
- result["text-translate-anchor"] = makePropertySetter<V>(&SymbolLayer::setTextTranslateAnchor);
-
- result["circle-radius"] = makePropertySetter<V>(&CircleLayer::setCircleRadius);
- result["circle-color"] = makePropertySetter<V>(&CircleLayer::setCircleColor);
- result["circle-blur"] = makePropertySetter<V>(&CircleLayer::setCircleBlur);
- result["circle-opacity"] = makePropertySetter<V>(&CircleLayer::setCircleOpacity);
- result["circle-translate"] = makePropertySetter<V>(&CircleLayer::setCircleTranslate);
- result["circle-translate-anchor"] = makePropertySetter<V>(&CircleLayer::setCircleTranslateAnchor);
- result["circle-pitch-scale"] = makePropertySetter<V>(&CircleLayer::setCirclePitchScale);
- result["circle-stroke-width"] = makePropertySetter<V>(&CircleLayer::setCircleStrokeWidth);
- result["circle-stroke-color"] = makePropertySetter<V>(&CircleLayer::setCircleStrokeColor);
- result["circle-stroke-opacity"] = makePropertySetter<V>(&CircleLayer::setCircleStrokeOpacity);
-
- result["fill-extrusion-opacity"] = makePropertySetter<V>(&FillExtrusionLayer::setFillExtrusionOpacity);
- result["fill-extrusion-color"] = makePropertySetter<V>(&FillExtrusionLayer::setFillExtrusionColor);
- result["fill-extrusion-translate"] = makePropertySetter<V>(&FillExtrusionLayer::setFillExtrusionTranslate);
- result["fill-extrusion-translate-anchor"] = makePropertySetter<V>(&FillExtrusionLayer::setFillExtrusionTranslateAnchor);
- result["fill-extrusion-pattern"] = makePropertySetter<V>(&FillExtrusionLayer::setFillExtrusionPattern);
- result["fill-extrusion-height"] = makePropertySetter<V>(&FillExtrusionLayer::setFillExtrusionHeight);
- result["fill-extrusion-base"] = makePropertySetter<V>(&FillExtrusionLayer::setFillExtrusionBase);
-
- result["raster-opacity"] = makePropertySetter<V>(&RasterLayer::setRasterOpacity);
- result["raster-hue-rotate"] = makePropertySetter<V>(&RasterLayer::setRasterHueRotate);
- result["raster-brightness-min"] = makePropertySetter<V>(&RasterLayer::setRasterBrightnessMin);
- result["raster-brightness-max"] = makePropertySetter<V>(&RasterLayer::setRasterBrightnessMax);
- result["raster-saturation"] = makePropertySetter<V>(&RasterLayer::setRasterSaturation);
- result["raster-contrast"] = makePropertySetter<V>(&RasterLayer::setRasterContrast);
- result["raster-fade-duration"] = makePropertySetter<V>(&RasterLayer::setRasterFadeDuration);
-
- result["background-color"] = makePropertySetter<V>(&BackgroundLayer::setBackgroundColor);
- result["background-pattern"] = makePropertySetter<V>(&BackgroundLayer::setBackgroundPattern);
- result["background-opacity"] = makePropertySetter<V>(&BackgroundLayer::setBackgroundOpacity);
+ std::unordered_map<std::string, PropertySetter<V>> result;
+
+ result["fill-antialias"] = &setProperty<V, FillLayer, PropertyValue<bool>, &FillLayer::setFillAntialias>;
+ result["fill-antialias-transition"] = &setTransition<V, FillLayer, &FillLayer::setFillAntialiasTransition>;
+ result["fill-opacity"] = &setProperty<V, FillLayer, DataDrivenPropertyValue<float>, &FillLayer::setFillOpacity>;
+ result["fill-opacity-transition"] = &setTransition<V, FillLayer, &FillLayer::setFillOpacityTransition>;
+ result["fill-color"] = &setProperty<V, FillLayer, DataDrivenPropertyValue<Color>, &FillLayer::setFillColor>;
+ result["fill-color-transition"] = &setTransition<V, FillLayer, &FillLayer::setFillColorTransition>;
+ result["fill-outline-color"] = &setProperty<V, FillLayer, DataDrivenPropertyValue<Color>, &FillLayer::setFillOutlineColor>;
+ result["fill-outline-color-transition"] = &setTransition<V, FillLayer, &FillLayer::setFillOutlineColorTransition>;
+ 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"] = &setProperty<V, FillLayer, PropertyValue<TranslateAnchorType>, &FillLayer::setFillTranslateAnchor>;
+ result["fill-translate-anchor-transition"] = &setTransition<V, FillLayer, &FillLayer::setFillTranslateAnchorTransition>;
+ result["fill-pattern"] = &setProperty<V, FillLayer, PropertyValue<std::string>, &FillLayer::setFillPattern>;
+ result["fill-pattern-transition"] = &setTransition<V, FillLayer, &FillLayer::setFillPatternTransition>;
+
+ result["line-opacity"] = &setProperty<V, LineLayer, DataDrivenPropertyValue<float>, &LineLayer::setLineOpacity>;
+ result["line-opacity-transition"] = &setTransition<V, LineLayer, &LineLayer::setLineOpacityTransition>;
+ result["line-color"] = &setProperty<V, LineLayer, DataDrivenPropertyValue<Color>, &LineLayer::setLineColor>;
+ result["line-color-transition"] = &setTransition<V, LineLayer, &LineLayer::setLineColorTransition>;
+ 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"] = &setProperty<V, LineLayer, PropertyValue<TranslateAnchorType>, &LineLayer::setLineTranslateAnchor>;
+ result["line-translate-anchor-transition"] = &setTransition<V, LineLayer, &LineLayer::setLineTranslateAnchorTransition>;
+ result["line-width"] = &setProperty<V, LineLayer, DataDrivenPropertyValue<float>, &LineLayer::setLineWidth>;
+ result["line-width-transition"] = &setTransition<V, LineLayer, &LineLayer::setLineWidthTransition>;
+ result["line-gap-width"] = &setProperty<V, LineLayer, DataDrivenPropertyValue<float>, &LineLayer::setLineGapWidth>;
+ result["line-gap-width-transition"] = &setTransition<V, LineLayer, &LineLayer::setLineGapWidthTransition>;
+ result["line-offset"] = &setProperty<V, LineLayer, DataDrivenPropertyValue<float>, &LineLayer::setLineOffset>;
+ result["line-offset-transition"] = &setTransition<V, LineLayer, &LineLayer::setLineOffsetTransition>;
+ result["line-blur"] = &setProperty<V, LineLayer, DataDrivenPropertyValue<float>, &LineLayer::setLineBlur>;
+ result["line-blur-transition"] = &setTransition<V, LineLayer, &LineLayer::setLineBlurTransition>;
+ result["line-dasharray"] = &setProperty<V, LineLayer, PropertyValue<std::vector<float>>, &LineLayer::setLineDasharray>;
+ result["line-dasharray-transition"] = &setTransition<V, LineLayer, &LineLayer::setLineDasharrayTransition>;
+ result["line-pattern"] = &setProperty<V, LineLayer, PropertyValue<std::string>, &LineLayer::setLinePattern>;
+ result["line-pattern-transition"] = &setTransition<V, LineLayer, &LineLayer::setLinePatternTransition>;
+
+ result["icon-opacity"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setIconOpacity>;
+ result["icon-opacity-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setIconOpacityTransition>;
+ result["icon-color"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<Color>, &SymbolLayer::setIconColor>;
+ result["icon-color-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setIconColorTransition>;
+ 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"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setIconHaloWidth>;
+ result["icon-halo-width-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setIconHaloWidthTransition>;
+ result["icon-halo-blur"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setIconHaloBlur>;
+ result["icon-halo-blur-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setIconHaloBlurTransition>;
+ 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"] = &setProperty<V, SymbolLayer, PropertyValue<TranslateAnchorType>, &SymbolLayer::setIconTranslateAnchor>;
+ result["icon-translate-anchor-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setIconTranslateAnchorTransition>;
+ result["text-opacity"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setTextOpacity>;
+ result["text-opacity-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setTextOpacityTransition>;
+ result["text-color"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<Color>, &SymbolLayer::setTextColor>;
+ result["text-color-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setTextColorTransition>;
+ 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"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setTextHaloWidth>;
+ result["text-halo-width-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setTextHaloWidthTransition>;
+ result["text-halo-blur"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setTextHaloBlur>;
+ result["text-halo-blur-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setTextHaloBlurTransition>;
+ 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"] = &setProperty<V, SymbolLayer, PropertyValue<TranslateAnchorType>, &SymbolLayer::setTextTranslateAnchor>;
+ result["text-translate-anchor-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setTextTranslateAnchorTransition>;
+
+ result["circle-radius"] = &setProperty<V, CircleLayer, DataDrivenPropertyValue<float>, &CircleLayer::setCircleRadius>;
+ result["circle-radius-transition"] = &setTransition<V, CircleLayer, &CircleLayer::setCircleRadiusTransition>;
+ result["circle-color"] = &setProperty<V, CircleLayer, DataDrivenPropertyValue<Color>, &CircleLayer::setCircleColor>;
+ result["circle-color-transition"] = &setTransition<V, CircleLayer, &CircleLayer::setCircleColorTransition>;
+ result["circle-blur"] = &setProperty<V, CircleLayer, DataDrivenPropertyValue<float>, &CircleLayer::setCircleBlur>;
+ result["circle-blur-transition"] = &setTransition<V, CircleLayer, &CircleLayer::setCircleBlurTransition>;
+ result["circle-opacity"] = &setProperty<V, CircleLayer, DataDrivenPropertyValue<float>, &CircleLayer::setCircleOpacity>;
+ result["circle-opacity-transition"] = &setTransition<V, CircleLayer, &CircleLayer::setCircleOpacityTransition>;
+ 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"] = &setProperty<V, CircleLayer, PropertyValue<TranslateAnchorType>, &CircleLayer::setCircleTranslateAnchor>;
+ result["circle-translate-anchor-transition"] = &setTransition<V, CircleLayer, &CircleLayer::setCircleTranslateAnchorTransition>;
+ result["circle-pitch-scale"] = &setProperty<V, CircleLayer, PropertyValue<CirclePitchScaleType>, &CircleLayer::setCirclePitchScale>;
+ result["circle-pitch-scale-transition"] = &setTransition<V, CircleLayer, &CircleLayer::setCirclePitchScaleTransition>;
+ 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"] = &setProperty<V, CircleLayer, DataDrivenPropertyValue<Color>, &CircleLayer::setCircleStrokeColor>;
+ result["circle-stroke-color-transition"] = &setTransition<V, CircleLayer, &CircleLayer::setCircleStrokeColorTransition>;
+ 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"] = &setProperty<V, FillExtrusionLayer, PropertyValue<float>, &FillExtrusionLayer::setFillExtrusionOpacity>;
+ result["fill-extrusion-opacity-transition"] = &setTransition<V, FillExtrusionLayer, &FillExtrusionLayer::setFillExtrusionOpacityTransition>;
+ 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"] = &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"] = &setProperty<V, FillExtrusionLayer, PropertyValue<TranslateAnchorType>, &FillExtrusionLayer::setFillExtrusionTranslateAnchor>;
+ result["fill-extrusion-translate-anchor-transition"] = &setTransition<V, FillExtrusionLayer, &FillExtrusionLayer::setFillExtrusionTranslateAnchorTransition>;
+ 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"] = &setProperty<V, FillExtrusionLayer, DataDrivenPropertyValue<float>, &FillExtrusionLayer::setFillExtrusionHeight>;
+ result["fill-extrusion-height-transition"] = &setTransition<V, FillExtrusionLayer, &FillExtrusionLayer::setFillExtrusionHeightTransition>;
+ result["fill-extrusion-base"] = &setProperty<V, FillExtrusionLayer, DataDrivenPropertyValue<float>, &FillExtrusionLayer::setFillExtrusionBase>;
+ result["fill-extrusion-base-transition"] = &setTransition<V, FillExtrusionLayer, &FillExtrusionLayer::setFillExtrusionBaseTransition>;
+
+ result["raster-opacity"] = &setProperty<V, RasterLayer, PropertyValue<float>, &RasterLayer::setRasterOpacity>;
+ result["raster-opacity-transition"] = &setTransition<V, RasterLayer, &RasterLayer::setRasterOpacityTransition>;
+ 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"] = &setProperty<V, RasterLayer, PropertyValue<float>, &RasterLayer::setRasterBrightnessMin>;
+ result["raster-brightness-min-transition"] = &setTransition<V, RasterLayer, &RasterLayer::setRasterBrightnessMinTransition>;
+ result["raster-brightness-max"] = &setProperty<V, RasterLayer, PropertyValue<float>, &RasterLayer::setRasterBrightnessMax>;
+ result["raster-brightness-max-transition"] = &setTransition<V, RasterLayer, &RasterLayer::setRasterBrightnessMaxTransition>;
+ result["raster-saturation"] = &setProperty<V, RasterLayer, PropertyValue<float>, &RasterLayer::setRasterSaturation>;
+ result["raster-saturation-transition"] = &setTransition<V, RasterLayer, &RasterLayer::setRasterSaturationTransition>;
+ result["raster-contrast"] = &setProperty<V, RasterLayer, PropertyValue<float>, &RasterLayer::setRasterContrast>;
+ result["raster-contrast-transition"] = &setTransition<V, RasterLayer, &RasterLayer::setRasterContrastTransition>;
+ result["raster-fade-duration"] = &setProperty<V, RasterLayer, PropertyValue<float>, &RasterLayer::setRasterFadeDuration>;
+ result["raster-fade-duration-transition"] = &setTransition<V, RasterLayer, &RasterLayer::setRasterFadeDurationTransition>;
+
+ result["background-color"] = &setProperty<V, BackgroundLayer, PropertyValue<Color>, &BackgroundLayer::setBackgroundColor>;
+ result["background-color-transition"] = &setTransition<V, BackgroundLayer, &BackgroundLayer::setBackgroundColorTransition>;
+ result["background-pattern"] = &setProperty<V, BackgroundLayer, PropertyValue<std::string>, &BackgroundLayer::setBackgroundPattern>;
+ result["background-pattern-transition"] = &setTransition<V, BackgroundLayer, &BackgroundLayer::setBackgroundPatternTransition>;
+ 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
deleted file mode 100644
index ed8f6e891c..0000000000
--- a/include/mbgl/style/conversion/make_property_setters.hpp.ejs
+++ /dev/null
@@ -1,47 +0,0 @@
-#pragma once
-
-// This file is generated. Edit make_property_setters.hpp.ejs, then run `make style-code`.
-
-#include <mbgl/style/conversion/property_setter.hpp>
-
-<% for (const layer of locals.layers) { -%>
-#include <mbgl/style/layers/<%- layer.type.replace('-', '_') %>_layer.hpp>
-<% } -%>
-
-#include <unordered_map>
-
-namespace mbgl {
-namespace style {
-namespace conversion {
-
-template <class V>
-auto makeLayoutPropertySetters() {
- std::unordered_map<std::string, LayoutPropertySetter<V>> result;
-
- result["visibility"] = &setVisibility<V>;
-
-<% for (const layer of locals.layers) { -%>
-<% for (const property of layer.layoutProperties) { -%>
- result["<%- property.name %>"] = makePropertySetter<V>(&<%- camelize(layer.type) %>Layer::set<%- camelize(property.name) %>);
-<% } -%>
-
-<% } -%>
- return result;
-}
-
-template <class V>
-auto makePaintPropertySetters() {
- std::unordered_map<std::string, PaintPropertySetter<V>> result;
-
-<% for (const layer of locals.layers) { -%>
-<% for (const property of layer.paintProperties) { -%>
- result["<%- property.name %>"] = makePropertySetter<V>(&<%- camelize(layer.type) %>Layer::set<%- camelize(property.name) %>);
-<% } -%>
-
-<% } -%>
- return result;
-}
-
-} // namespace conversion
-} // namespace style
-} // namespace mbgl
diff --git a/include/mbgl/style/conversion/position.hpp b/include/mbgl/style/conversion/position.hpp
new file mode 100644
index 0000000000..7036b03822
--- /dev/null
+++ b/include/mbgl/style/conversion/position.hpp
@@ -0,0 +1,29 @@
+#pragma once
+
+#include <mbgl/style/conversion.hpp>
+#include <mbgl/style/position.hpp>
+#include <mbgl/util/optional.hpp>
+
+#include <array>
+
+namespace mbgl {
+namespace style {
+namespace conversion {
+
+template <>
+struct Converter<Position> {
+ template <class V>
+ optional<Position> operator()(const V& value, Error& error) const {
+ optional<std::array<float, 3>> spherical = convert<std::array<float, 3>>(value, error);
+
+ if (!spherical) {
+ return {};
+ }
+
+ return Position(*spherical);
+ }
+};
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/conversion/property_setter.hpp b/include/mbgl/style/conversion/property_setter.hpp
index 1a601c7c1b..759c4512cc 100644
--- a/include/mbgl/style/conversion/property_setter.hpp
+++ b/include/mbgl/style/conversion/property_setter.hpp
@@ -4,8 +4,9 @@
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/constant.hpp>
#include <mbgl/style/conversion/property_value.hpp>
+#include <mbgl/style/conversion/data_driven_property_value.hpp>
+#include <mbgl/style/conversion/transition_options.hpp>
-#include <functional>
#include <string>
namespace mbgl {
@@ -13,27 +14,40 @@ namespace style {
namespace conversion {
template <class V>
-using LayoutPropertySetter = std::function<optional<Error> (Layer&, const V&)>;
+using PropertySetter = optional<Error> (*) (Layer&, const V&);
-template <class V>
-using PaintPropertySetter = std::function<optional<Error> (Layer&, const V&, const optional<std::string>&)>;
-
-template <class V, class L, class T, class...Args>
-auto makePropertySetter(void (L::*setter)(PropertyValue<T>, const Args&...args)) {
- return [setter] (Layer& layer, const V& value, const Args&...args) -> optional<Error> {
- L* typedLayer = layer.as<L>();
- if (!typedLayer) {
- return Error { "layer doesn't support this property" };
- }
-
- Result<PropertyValue<T>> typedValue = convert<PropertyValue<T>>(value);
- if (!typedValue) {
- return typedValue.error();
- }
-
- (typedLayer->*setter)(*typedValue, args...);
- return {};
- };
+template <class V, class L, class PropertyValue, void (L::*setter)(PropertyValue)>
+optional<Error> setProperty(Layer& layer, const V& value) {
+ auto* 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);
+ return {};
+}
+
+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" };
+ }
+
+ Error error;
+ optional<TransitionOptions> transition = convert<TransitionOptions>(value, error);
+ if (!transition) {
+ return error;
+ }
+
+ (typedLayer->*setter)(*transition);
+ return {};
}
template <class V>
@@ -43,9 +57,10 @@ optional<Error> setVisibility(Layer& layer, const V& value) {
return {};
}
- Result<VisibilityType> visibility = convert<VisibilityType>(value);
+ Error error;
+ optional<VisibilityType> visibility = convert<VisibilityType>(value, error);
if (!visibility) {
- return visibility.error();
+ return error;
}
layer.setVisibility(*visibility);
diff --git a/include/mbgl/style/conversion/property_value.hpp b/include/mbgl/style/conversion/property_value.hpp
index de95b56155..f8937da07d 100644
--- a/include/mbgl/style/conversion/property_value.hpp
+++ b/include/mbgl/style/conversion/property_value.hpp
@@ -12,21 +12,21 @@ namespace conversion {
template <class T>
struct Converter<PropertyValue<T>> {
template <class V>
- Result<PropertyValue<T>> operator()(const V& value) const {
+ optional<PropertyValue<T>> operator()(const V& value, Error& error) const {
if (isUndefined(value)) {
- return {};
+ return PropertyValue<T>();
} else if (isObject(value)) {
- Result<Function<T>> function = convert<Function<T>>(value);
+ optional<CameraFunction<T>> function = convert<CameraFunction<T>>(value, error);
if (!function) {
- return function.error();
+ return {};
}
- return *function;
+ return { *function };
} else {
- Result<T> constant = convert<T>(value);
+ optional<T> constant = convert<T>(value, error);
if (!constant) {
- return constant.error();
+ return {};
}
- return *constant;
+ return { *constant };
}
}
};
diff --git a/include/mbgl/style/conversion/source.hpp b/include/mbgl/style/conversion/source.hpp
index 6e1b4347c3..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,60 +19,69 @@ namespace conversion {
template <>
struct Converter<std::unique_ptr<Source>> {
public:
+
template <class V>
- Result<std::unique_ptr<Source>> operator()(const V& value, const std::string& id) const {
+ optional<std::unique_ptr<Source>> operator()(const V& value, Error& error, const std::string& id) const {
if (!isObject(value)) {
- return Error{ "source must be an object" };
+ error = { "source must be an object" };
+ return {};
}
auto typeValue = objectMember(value, "type");
if (!typeValue) {
- return Error{ "source must have a type" };
+ error = { "source must have a type" };
+ return {};
}
optional<std::string> type = toString(*typeValue);
if (!type) {
- return Error{ "source type must be a string" };
+ error = { "source type must be a string" };
+ return {};
}
if (*type == "raster") {
- return convertRasterSource(id, value);
+ return convertRasterSource(id, value, error);
} else if (*type == "vector") {
- return convertVectorSource(id, value);
+ return convertVectorSource(id, value, error);
} else if (*type == "geojson") {
- return convertGeoJSONSource(id, value);
+ return convertGeoJSONSource(id, value, error);
+ } else if (*type == "image") {
+ return convertImageSource(id, value, error);
} else {
- return Error{ "invalid source type" };
+ error = { "invalid source type" };
+ return {};
}
}
private:
// A tile source can either specify a URL to TileJSON, or inline TileJSON.
template <class V>
- Result<variant<std::string, Tileset>> convertURLOrTileset(const V& value) const {
+ optional<variant<std::string, Tileset>> convertURLOrTileset(const V& value, Error& error) const {
auto urlVal = objectMember(value, "url");
if (!urlVal) {
- Result<Tileset> tileset = convert<Tileset>(value);
+ optional<Tileset> tileset = convert<Tileset>(value, error);
if (!tileset) {
- return tileset.error();
+ return {};
}
- return *tileset;
+ return { *tileset };
}
optional<std::string> url = toString(*urlVal);
if (!url) {
- return Error{ "source url must be a string" };
+ error = { "source url must be a string" };
+ return {};
}
- return *url;
+ return { *url };
}
template <class V>
- Result<std::unique_ptr<Source>> convertRasterSource(const std::string& id,
- const V& value) const {
- Result<variant<std::string, Tileset>> urlOrTileset = convertURLOrTileset(value);
+ optional<std::unique_ptr<Source>> convertRasterSource(const std::string& id,
+ const V& value,
+ Error& error) const {
+ optional<variant<std::string, Tileset>> urlOrTileset = convertURLOrTileset(value, error);
if (!urlOrTileset) {
- return urlOrTileset.error();
+ return {};
}
uint16_t tileSize = util::tileSize;
@@ -77,53 +89,99 @@ private:
if (tileSizeValue) {
optional<float> size = toNumber(*tileSizeValue);
if (!size || *size < 0 || *size > std::numeric_limits<uint16_t>::max()) {
- return Error{ "invalid tileSize" };
+ error = { "invalid tileSize" };
+ return {};
}
tileSize = *size;
}
- return std::make_unique<RasterSource>(id, std::move(*urlOrTileset), tileSize);
+ return { std::make_unique<RasterSource>(id, std::move(*urlOrTileset), tileSize) };
}
template <class V>
- Result<std::unique_ptr<Source>> convertVectorSource(const std::string& id,
- const V& value) const {
- Result<variant<std::string, Tileset>> urlOrTileset = convertURLOrTileset(value);
+ optional<std::unique_ptr<Source>> convertVectorSource(const std::string& id,
+ const V& value,
+ Error& error) const {
+ optional<variant<std::string, Tileset>> urlOrTileset = convertURLOrTileset(value, error);
if (!urlOrTileset) {
- return urlOrTileset.error();
+ return {};
}
- return std::make_unique<VectorSource>(id, std::move(*urlOrTileset));
+ return { std::make_unique<VectorSource>(id, std::move(*urlOrTileset)) };
}
template <class V>
- Result<std::unique_ptr<Source>> convertGeoJSONSource(const std::string& id,
- const V& value) const {
+ optional<std::unique_ptr<Source>> convertGeoJSONSource(const std::string& id,
+ const V& value,
+ Error& error) const {
auto dataValue = objectMember(value, "data");
if (!dataValue) {
- return Error{ "GeoJSON source must have a data value" };
+ error = { "GeoJSON source must have a data value" };
+ return {};
}
- Result<GeoJSONOptions> options = convert<GeoJSONOptions>(value);
+ optional<GeoJSONOptions> options = convert<GeoJSONOptions>(value, error);
if (!options) {
- return options.error();
+ return {};
}
auto result = std::make_unique<GeoJSONSource>(id, *options);
if (isObject(*dataValue)) {
- Result<GeoJSON> geoJSON = convertGeoJSON(*dataValue);
+ optional<GeoJSON> geoJSON = convert<GeoJSON>(*dataValue, error);
if (!geoJSON) {
- return geoJSON.error();
+ return {};
}
result->setGeoJSON(std::move(*geoJSON));
} else if (toString(*dataValue)) {
result->setURL(*toString(*dataValue));
} else {
- return Error{ "GeoJSON data must be a URL or an object" };
+ error = { "GeoJSON data must be a URL or an object" };
+ return {};
}
- return std::move(result);
+ 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) };
}
};
diff --git a/include/mbgl/style/conversion/tileset.hpp b/include/mbgl/style/conversion/tileset.hpp
index 1955cc16cf..377170aa6a 100644
--- a/include/mbgl/style/conversion/tileset.hpp
+++ b/include/mbgl/style/conversion/tileset.hpp
@@ -11,22 +11,25 @@ template <>
struct Converter<Tileset> {
public:
template <class V>
- Result<Tileset> operator()(const V& value) const {
+ optional<Tileset> operator()(const V& value, Error& error) const {
Tileset result;
auto tiles = objectMember(value, "tiles");
if (!tiles) {
- return Error { "source must have tiles" };
+ error = { "source must have tiles" };
+ return {};
}
if (!isArray(*tiles)) {
- return Error { "source tiles must be an array" };
+ error = { "source tiles must be an array" };
+ return {};
}
for (std::size_t i = 0; i < arrayLength(*tiles); i++) {
optional<std::string> urlTemplate = toString(arrayMember(*tiles, i));
if (!urlTemplate) {
- return Error { "source tiles member must be a string" };
+ error = { "source tiles member must be a string" };
+ return {};
}
result.tiles.push_back(std::move(*urlTemplate));
}
@@ -43,7 +46,8 @@ public:
if (minzoomValue) {
optional<float> minzoom = toNumber(*minzoomValue);
if (!minzoom || *minzoom < 0 || *minzoom > std::numeric_limits<uint8_t>::max()) {
- return Error { "invalid minzoom" };
+ error = { "invalid minzoom" };
+ return {};
}
result.zoomRange.min = *minzoom;
}
@@ -52,7 +56,8 @@ public:
if (maxzoomValue) {
optional<float> maxzoom = toNumber(*maxzoomValue);
if (!maxzoom || *maxzoom < 0 || *maxzoom > std::numeric_limits<uint8_t>::max()) {
- return Error { "invalid maxzoom" };
+ error = { "invalid maxzoom" };
+ return {};
}
result.zoomRange.max = *maxzoom;
}
@@ -61,7 +66,8 @@ public:
if (attributionValue) {
optional<std::string> attribution = toString(*attributionValue);
if (!attribution) {
- return Error { "source attribution must be a string" };
+ error = { "source attribution must be a string" };
+ return {};
}
result.attribution = std::move(*attribution);
}
diff --git a/include/mbgl/style/conversion/transition_options.hpp b/include/mbgl/style/conversion/transition_options.hpp
new file mode 100644
index 0000000000..de8834d578
--- /dev/null
+++ b/include/mbgl/style/conversion/transition_options.hpp
@@ -0,0 +1,48 @@
+#pragma once
+
+#include <mbgl/style/transition_options.hpp>
+#include <mbgl/style/conversion.hpp>
+
+namespace mbgl {
+namespace style {
+namespace conversion {
+
+template <>
+struct Converter<TransitionOptions> {
+public:
+ template <class V>
+ optional<TransitionOptions> operator()(const V& value, Error& error) const {
+ if (!isObject(value)) {
+ error = { "transition must be an object" };
+ return {};
+ }
+
+ TransitionOptions result;
+
+ auto duration = objectMember(value, "duration");
+ if (duration) {
+ auto number = toNumber(*duration);
+ if (!number) {
+ error = { "duration must be a number" };
+ return {};
+ }
+ result.duration = { std::chrono::milliseconds(int64_t(*number)) };
+ }
+
+ auto delay = objectMember(value, "delay");
+ if (delay) {
+ auto number = toNumber(*delay);
+ if (!number) {
+ error = { "delay must be a number" };
+ return {};
+ }
+ result.delay = { std::chrono::milliseconds(int64_t(*number)) };
+ }
+
+ return result;
+ }
+};
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/data_driven_property_value.hpp b/include/mbgl/style/data_driven_property_value.hpp
new file mode 100644
index 0000000000..5d7c596363
--- /dev/null
+++ b/include/mbgl/style/data_driven_property_value.hpp
@@ -0,0 +1,69 @@
+#pragma once
+
+#include <mbgl/util/variant.hpp>
+#include <mbgl/style/undefined.hpp>
+#include <mbgl/style/function/camera_function.hpp>
+#include <mbgl/style/function/source_function.hpp>
+#include <mbgl/style/function/composite_function.hpp>
+
+namespace mbgl {
+namespace style {
+
+template <class T>
+class DataDrivenPropertyValue {
+private:
+ using Value = variant<
+ Undefined,
+ T,
+ CameraFunction<T>,
+ SourceFunction<T>,
+ CompositeFunction<T>>;
+
+ Value value;
+
+ friend bool operator==(const DataDrivenPropertyValue& lhs,
+ const DataDrivenPropertyValue& rhs) {
+ return lhs.value == rhs.value;
+ }
+
+ friend bool operator!=(const DataDrivenPropertyValue& lhs,
+ const DataDrivenPropertyValue& rhs) {
+ return !(lhs == rhs);
+ }
+
+public:
+ DataDrivenPropertyValue() = default;
+ DataDrivenPropertyValue( T v) : value(std::move(v)) {}
+ DataDrivenPropertyValue( CameraFunction<T> v) : value(std::move(v)) {}
+ DataDrivenPropertyValue( SourceFunction<T> v) : value(std::move(v)) {}
+ DataDrivenPropertyValue(CompositeFunction<T> v) : value(std::move(v)) {}
+
+ bool isUndefined() const {
+ return value.template is<Undefined>();
+ }
+
+ bool isDataDriven() const {
+ return value.template is<SourceFunction<T>>() || value.template is<CompositeFunction<T>>();
+ }
+
+ 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, TimePoint = {}) const {
+ return Value::visit(value, evaluator);
+ }
+
+ bool hasDataDrivenPropertyDifference(const DataDrivenPropertyValue<T>& other) const {
+ return *this != other && (isDataDriven() || other.isDataDriven());
+ }
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/filter.hpp b/include/mbgl/style/filter.hpp
index e5d8081d82..a204a2b17a 100644
--- a/include/mbgl/style/filter.hpp
+++ b/include/mbgl/style/filter.hpp
@@ -145,6 +145,95 @@ public:
}
};
+
+class TypeEqualsFilter {
+public:
+ FeatureType value;
+
+ friend bool operator==(const TypeEqualsFilter& lhs, const TypeEqualsFilter& rhs) {
+ return lhs.value == rhs.value;
+ }
+};
+
+class TypeNotEqualsFilter {
+public:
+ FeatureType value;
+
+ friend bool operator==(const TypeNotEqualsFilter& lhs, const TypeNotEqualsFilter& rhs) {
+ return lhs.value == rhs.value;
+ }
+};
+
+class TypeInFilter {
+public:
+ std::vector<FeatureType> values;
+
+ friend bool operator==(const TypeInFilter& lhs, const TypeInFilter& rhs) {
+ return lhs.values == rhs.values;
+ }
+};
+
+class TypeNotInFilter {
+public:
+ std::vector<FeatureType> values;
+
+ friend bool operator==(const TypeNotInFilter& lhs, const TypeNotInFilter& rhs) {
+ return lhs.values == rhs.values;
+ }
+};
+
+
+class IdentifierEqualsFilter {
+public:
+ FeatureIdentifier value;
+
+ friend bool operator==(const IdentifierEqualsFilter& lhs, const IdentifierEqualsFilter& rhs) {
+ return lhs.value == rhs.value;
+ }
+};
+
+class IdentifierNotEqualsFilter {
+public:
+ FeatureIdentifier value;
+
+ friend bool operator==(const IdentifierNotEqualsFilter& lhs, const IdentifierNotEqualsFilter& rhs) {
+ return lhs.value == rhs.value;
+ }
+};
+
+class IdentifierInFilter {
+public:
+ std::vector<FeatureIdentifier> values;
+
+ friend bool operator==(const IdentifierInFilter& lhs, const IdentifierInFilter& rhs) {
+ return lhs.values == rhs.values;
+ }
+};
+
+class IdentifierNotInFilter {
+public:
+ std::vector<FeatureIdentifier> values;
+
+ friend bool operator==(const IdentifierNotInFilter& lhs, const IdentifierNotInFilter& rhs) {
+ return lhs.values == rhs.values;
+ }
+};
+
+class HasIdentifierFilter {
+public:
+ friend bool operator==(const HasIdentifierFilter&, const HasIdentifierFilter&) {
+ return true;
+ }
+};
+
+class NotHasIdentifierFilter {
+public:
+ friend bool operator==(const NotHasIdentifierFilter&, const NotHasIdentifierFilter&) {
+ return true;
+ }
+};
+
+
using FilterBase = variant<
class NullFilter,
class EqualsFilter,
@@ -159,7 +248,17 @@ using FilterBase = variant<
class AllFilter,
class NoneFilter,
class HasFilter,
- class NotHasFilter>;
+ class NotHasFilter,
+ class TypeEqualsFilter,
+ class TypeNotEqualsFilter,
+ class TypeInFilter,
+ class TypeNotInFilter,
+ class IdentifierEqualsFilter,
+ class IdentifierNotEqualsFilter,
+ class IdentifierInFilter,
+ class IdentifierNotInFilter,
+ class HasIdentifierFilter,
+ class NotHasIdentifierFilter>;
class Filter : public FilterBase {
public:
@@ -167,6 +266,9 @@ public:
bool operator()(const Feature&) const;
+ template <class GeometryTileFeature>
+ bool operator()(const GeometryTileFeature&) const;
+
template <class PropertyAccessor>
bool operator()(FeatureType type, optional<FeatureIdentifier> id, PropertyAccessor accessor) const;
};
diff --git a/include/mbgl/style/filter_evaluator.hpp b/include/mbgl/style/filter_evaluator.hpp
index 659f554bba..66223d7282 100644
--- a/include/mbgl/style/filter_evaluator.hpp
+++ b/include/mbgl/style/filter_evaluator.hpp
@@ -31,37 +31,37 @@ public:
}
bool operator()(const EqualsFilter& filter) const {
- optional<Value> actual = getValue(filter.key);
+ optional<Value> actual = propertyAccessor(filter.key);
return actual && equal(*actual, filter.value);
}
bool operator()(const NotEqualsFilter& filter) const {
- optional<Value> actual = getValue(filter.key);
+ optional<Value> actual = propertyAccessor(filter.key);
return !actual || !equal(*actual, filter.value);
}
bool operator()(const LessThanFilter& filter) const {
- optional<Value> actual = getValue(filter.key);
+ optional<Value> actual = propertyAccessor(filter.key);
return actual && compare(*actual, filter.value, [] (const auto& lhs_, const auto& rhs_) { return lhs_ < rhs_; });
}
bool operator()(const LessThanEqualsFilter& filter) const {
- optional<Value> actual = getValue(filter.key);
+ optional<Value> actual = propertyAccessor(filter.key);
return actual && compare(*actual, filter.value, [] (const auto& lhs_, const auto& rhs_) { return lhs_ <= rhs_; });
}
bool operator()(const GreaterThanFilter& filter) const {
- optional<Value> actual = getValue(filter.key);
+ optional<Value> actual = propertyAccessor(filter.key);
return actual && compare(*actual, filter.value, [] (const auto& lhs_, const auto& rhs_) { return lhs_ > rhs_; });
}
bool operator()(const GreaterThanEqualsFilter& filter) const {
- optional<Value> actual = getValue(filter.key);
+ optional<Value> actual = propertyAccessor(filter.key);
return actual && compare(*actual, filter.value, [] (const auto& lhs_, const auto& rhs_) { return lhs_ >= rhs_; });
}
bool operator()(const InFilter& filter) const {
- optional<Value> actual = getValue(filter.key);
+ optional<Value> actual = propertyAccessor(filter.key);
if (!actual)
return false;
for (const auto& v: filter.values) {
@@ -73,7 +73,7 @@ public:
}
bool operator()(const NotInFilter& filter) const {
- optional<Value> actual = getValue(filter.key);
+ optional<Value> actual = propertyAccessor(filter.key);
if (!actual)
return true;
for (const auto& v: filter.values) {
@@ -112,30 +112,76 @@ public:
}
bool operator()(const HasFilter& filter) const {
- return bool(getValue(filter.key));
+ return bool(propertyAccessor(filter.key));
}
bool operator()(const NotHasFilter& filter) const {
- return !getValue(filter.key);
+ return !propertyAccessor(filter.key);
}
-private:
- optional<Value> getValue(const std::string& key_) const {
- if (key_ == "$type") {
- return optional<Value>(uint64_t(featureType));
- } else if (key_ == "$id") {
- if (featureIdentifier) {
- return FeatureIdentifier::visit(*featureIdentifier, [] (auto id) {
- return Value(std::move(id));
- });
- } else {
- return optional<Value>();
+
+ bool operator()(const TypeEqualsFilter& filter) const {
+ return featureType == filter.value;
+ }
+
+ bool operator()(const TypeNotEqualsFilter& filter) const {
+ return featureType != filter.value;
+ }
+
+ bool operator()(const TypeInFilter& filter) const {
+ for (const auto& v: filter.values) {
+ if (featureType == v) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ bool operator()(const TypeNotInFilter& filter) const {
+ for (const auto& v: filter.values) {
+ if (featureType == v) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+
+ bool operator()(const IdentifierEqualsFilter& filter) const {
+ return featureIdentifier == filter.value;
+ }
+
+ bool operator()(const IdentifierNotEqualsFilter& filter) const {
+ return featureIdentifier != filter.value;
+ }
+
+ bool operator()(const IdentifierInFilter& filter) const {
+ for (const auto& v: filter.values) {
+ if (featureIdentifier == v) {
+ return true;
}
- } else {
- return propertyAccessor(key_);
}
+ return false;
}
+ bool operator()(const IdentifierNotInFilter& filter) const {
+ for (const auto& v: filter.values) {
+ if (featureIdentifier == v) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ bool operator()(const HasIdentifierFilter&) const {
+ return bool(featureIdentifier);
+ }
+
+ bool operator()(const NotHasIdentifierFilter&) const {
+ return !featureIdentifier;
+ }
+
+private:
template <class Op>
struct Comparator {
const Op& op;
@@ -200,6 +246,11 @@ inline bool Filter::operator()(const Feature& feature) const {
});
}
+template <class GeometryTileFeature>
+bool Filter::operator()(const GeometryTileFeature& feature) const {
+ return operator()(feature.getType(), feature.getID(), [&] (const auto& key) { return feature.getValue(key); });
+}
+
template <class PropertyAccessor>
bool Filter::operator()(FeatureType type, optional<FeatureIdentifier> id, PropertyAccessor accessor) const {
return FilterBase::visit(*this, FilterEvaluator<PropertyAccessor> { type, id, accessor });
diff --git a/include/mbgl/style/function.hpp b/include/mbgl/style/function.hpp
deleted file mode 100644
index b023229e4f..0000000000
--- a/include/mbgl/style/function.hpp
+++ /dev/null
@@ -1,40 +0,0 @@
-#pragma once
-
-#include <cassert>
-#include <utility>
-#include <vector>
-
-namespace mbgl {
-namespace style {
-
-template <typename T>
-class Function {
-public:
- using Stop = std::pair<float, T>;
- using Stops = std::vector<Stop>;
-
- Function(Stops stops_, float base_)
- : base(base_), stops(std::move(stops_)) {
- assert(stops.size() > 0);
- }
-
- float getBase() const { return base; }
- const std::vector<std::pair<float, T>>& getStops() const { return stops; }
-
- T evaluate(float z) const;
-
- friend bool operator==(const Function& lhs, const Function& rhs) {
- return lhs.base == rhs.base && lhs.stops == rhs.stops;
- }
-
- friend bool operator!=(const Function& lhs, const Function& rhs) {
- return !(lhs == rhs);
- }
-
-private:
- float base = 1;
- std::vector<std::pair<float, T>> stops;
-};
-
-} // namespace style
-} // namespace mbgl
diff --git a/include/mbgl/style/function/camera_function.hpp b/include/mbgl/style/function/camera_function.hpp
new file mode 100644
index 0000000000..7fde365b3d
--- /dev/null
+++ b/include/mbgl/style/function/camera_function.hpp
@@ -0,0 +1,42 @@
+#pragma once
+
+#include <mbgl/style/function/exponential_stops.hpp>
+#include <mbgl/style/function/interval_stops.hpp>
+#include <mbgl/util/interpolate.hpp>
+#include <mbgl/util/variant.hpp>
+
+namespace mbgl {
+namespace style {
+
+template <class T>
+class CameraFunction {
+public:
+ using Stops = std::conditional_t<
+ util::Interpolatable<T>::value,
+ variant<
+ ExponentialStops<T>,
+ IntervalStops<T>>,
+ variant<
+ IntervalStops<T>>>;
+
+ CameraFunction(Stops stops_)
+ : stops(std::move(stops_)) {
+ }
+
+ T evaluate(float zoom) const {
+ return stops.match([&] (const auto& s) {
+ return s.evaluate(zoom).value_or(T());
+ });
+ }
+
+ friend bool operator==(const CameraFunction& lhs,
+ const CameraFunction& rhs) {
+ return lhs.stops == rhs.stops;
+ }
+
+ Stops stops;
+ bool useIntegerZoom = false;
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/function/categorical_stops.hpp b/include/mbgl/style/function/categorical_stops.hpp
new file mode 100644
index 0000000000..c8505115ab
--- /dev/null
+++ b/include/mbgl/style/function/categorical_stops.hpp
@@ -0,0 +1,40 @@
+#pragma once
+
+#include <mbgl/util/feature.hpp>
+#include <mbgl/util/variant.hpp>
+
+#include <cassert>
+#include <utility>
+#include <map>
+
+namespace mbgl {
+namespace style {
+
+class CategoricalValue : public variant<bool, int64_t, std::string> {
+public:
+ using variant<bool, int64_t, std::string>::variant;
+};
+
+template <class T>
+class CategoricalStops {
+public:
+ using Stops = std::map<CategoricalValue, T>;
+
+ Stops stops;
+
+ CategoricalStops() = default;
+ CategoricalStops(Stops stops_)
+ : stops(std::move(stops_)) {
+ assert(stops.size() > 0);
+ }
+
+ optional<T> evaluate(const Value&) const;
+
+ friend bool operator==(const CategoricalStops& lhs,
+ const CategoricalStops& rhs) {
+ return lhs.stops == rhs.stops;
+ }
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/function/composite_categorical_stops.hpp b/include/mbgl/style/function/composite_categorical_stops.hpp
new file mode 100644
index 0000000000..b796621d1a
--- /dev/null
+++ b/include/mbgl/style/function/composite_categorical_stops.hpp
@@ -0,0 +1,30 @@
+#pragma once
+
+#include <mbgl/style/function/categorical_stops.hpp>
+
+namespace mbgl {
+namespace style {
+
+template <class T>
+class CompositeCategoricalStops {
+public:
+ using Stops = std::map<float, std::map<CategoricalValue, T>>;
+ Stops stops;
+
+ CompositeCategoricalStops() = default;
+ CompositeCategoricalStops(Stops stops_)
+ : stops(std::move(stops_)) {
+ }
+
+ CategoricalStops<T> innerStops(const std::map<CategoricalValue, T>& stops_) const {
+ return CategoricalStops<T>(stops_);
+ }
+
+ friend bool operator==(const CompositeCategoricalStops& lhs,
+ const CompositeCategoricalStops& rhs) {
+ return lhs.stops == rhs.stops;
+ }
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/function/composite_exponential_stops.hpp b/include/mbgl/style/function/composite_exponential_stops.hpp
new file mode 100644
index 0000000000..f1ad32a04d
--- /dev/null
+++ b/include/mbgl/style/function/composite_exponential_stops.hpp
@@ -0,0 +1,35 @@
+#pragma once
+
+#include <mbgl/style/function/exponential_stops.hpp>
+
+#include <map>
+
+namespace mbgl {
+namespace style {
+
+template <class T>
+class CompositeExponentialStops {
+public:
+ using Stops = std::map<float, std::map<float, T>>;
+
+ Stops stops;
+ float base = 1.0f;
+
+ CompositeExponentialStops() = default;
+ CompositeExponentialStops(Stops stops_, float base_ = 1.0f)
+ : stops(std::move(stops_)),
+ base(base_) {
+ }
+
+ ExponentialStops<T> innerStops(const std::map<float, T>& stops_) const {
+ return ExponentialStops<T>(stops_, base);
+ }
+
+ friend bool operator==(const CompositeExponentialStops& lhs,
+ const CompositeExponentialStops& rhs) {
+ return lhs.stops == rhs.stops && lhs.base == rhs.base;
+ }
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/function/composite_function.hpp b/include/mbgl/style/function/composite_function.hpp
new file mode 100644
index 0000000000..7b524b6021
--- /dev/null
+++ b/include/mbgl/style/function/composite_function.hpp
@@ -0,0 +1,153 @@
+#pragma once
+
+#include <mbgl/style/function/composite_exponential_stops.hpp>
+#include <mbgl/style/function/composite_interval_stops.hpp>
+#include <mbgl/style/function/composite_categorical_stops.hpp>
+#include <mbgl/util/interpolate.hpp>
+#include <mbgl/util/range.hpp>
+#include <mbgl/util/variant.hpp>
+
+#include <string>
+#include <tuple>
+
+namespace mbgl {
+
+class GeometryTileFeature;
+
+namespace style {
+
+// A CompositeFunction consists of an outer zoom function whose stop range values are
+// "inner" source functions. It provides the GL Native implementation of
+// "zoom-and-property" functions from the style spec.
+
+template <class T>
+class CompositeFunction {
+public:
+ using InnerStops = std::conditional_t<
+ util::Interpolatable<T>::value,
+ variant<
+ ExponentialStops<T>,
+ IntervalStops<T>,
+ CategoricalStops<T>>,
+ variant<
+ IntervalStops<T>,
+ CategoricalStops<T>>>;
+
+ using Stops = std::conditional_t<
+ util::Interpolatable<T>::value,
+ variant<
+ CompositeExponentialStops<T>,
+ CompositeIntervalStops<T>,
+ CompositeCategoricalStops<T>>,
+ variant<
+ CompositeIntervalStops<T>,
+ CompositeCategoricalStops<T>>>;
+
+ CompositeFunction(std::string property_, Stops stops_, optional<T> defaultValue_ = {})
+ : property(std::move(property_)),
+ stops(std::move(stops_)),
+ defaultValue(std::move(defaultValue_)) {
+ }
+
+ struct CoveringRanges {
+ float zoom;
+ Range<float> coveringZoomRange;
+ Range<InnerStops> coveringStopsRange;
+ };
+
+ // Return the relevant stop zoom values and inner stops that bracket a given zoom level. This
+ // is the first step toward evaluating the function, and is used for in the course of both partial
+ // evaluation of data-driven paint properties, and full evaluation of data-driven layout properties.
+ CoveringRanges coveringRanges(float zoom) const {
+ return stops.match(
+ [&] (const auto& s) {
+ assert(!s.stops.empty());
+ auto minIt = s.stops.lower_bound(zoom);
+ auto maxIt = s.stops.upper_bound(zoom);
+
+ // 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 != s.stops.end() && minIt->first > zoom) {
+ minIt--;
+ }
+
+ return CoveringRanges {
+ zoom,
+ Range<float> {
+ minIt == s.stops.end() ? s.stops.rbegin()->first : minIt->first,
+ maxIt == s.stops.end() ? s.stops.rbegin()->first : maxIt->first
+ },
+ Range<InnerStops> {
+ s.innerStops(minIt == s.stops.end() ? s.stops.rbegin()->second : minIt->second),
+ s.innerStops(maxIt == s.stops.end() ? s.stops.rbegin()->second : maxIt->second)
+ }
+ };
+ }
+ );
+ }
+
+ // Given a range of zoom values (typically two adjacent integer zoom levels, e.g. 5.0 and 6.0),
+ // return the covering ranges for both. This is used in the course of partial evaluation for
+ // data-driven paint properties.
+ Range<CoveringRanges> rangeOfCoveringRanges(Range<float> zoomRange) {
+ return Range<CoveringRanges> {
+ coveringRanges(zoomRange.min),
+ coveringRanges(zoomRange.max)
+ };
+ }
+
+ // Given the covering ranges for range of zoom values (typically two adjacent integer zoom levels,
+ // e.g. 5.0 and 6.0), and a feature, return the results of fully evaluating the function for that
+ // feature at each of the two zoom levels. These two results are what go into the paint vertex buffers
+ // for vertices associated with this feature. The shader will interpolate between them at render time.
+ template <class Feature>
+ Range<T> evaluate(const Range<CoveringRanges>& ranges, const Feature& feature, T finalDefaultValue) {
+ optional<Value> value = feature.getValue(property);
+ if (!value) {
+ return Range<T> {
+ defaultValue.value_or(finalDefaultValue),
+ defaultValue.value_or(finalDefaultValue)
+ };
+ }
+ return Range<T> {
+ evaluateFinal(ranges.min, *value, finalDefaultValue),
+ evaluateFinal(ranges.max, *value, finalDefaultValue)
+ };
+ }
+
+ // Fully evaluate the function for a zoom value and feature. This is used when evaluating data-driven
+ // layout properties.
+ template <class Feature>
+ T evaluate(float zoom, const Feature& feature, T finalDefaultValue) const {
+ optional<Value> value = feature.getValue(property);
+ if (!value) {
+ return defaultValue.value_or(finalDefaultValue);
+ }
+ return evaluateFinal(coveringRanges(zoom), *value, finalDefaultValue);
+ }
+
+ friend bool operator==(const CompositeFunction& lhs,
+ const CompositeFunction& rhs) {
+ return std::tie(lhs.property, lhs.stops, lhs.defaultValue)
+ == std::tie(rhs.property, rhs.stops, rhs.defaultValue);
+ }
+
+ std::string property;
+ Stops stops;
+ optional<T> defaultValue;
+ bool useIntegerZoom = false;
+
+private:
+ T evaluateFinal(const CoveringRanges& ranges, const Value& value, T finalDefaultValue) const {
+ auto eval = [&] (const auto& s) {
+ return s.evaluate(value).value_or(defaultValue.value_or(finalDefaultValue));
+ };
+ return util::interpolate(
+ ranges.coveringStopsRange.min.match(eval),
+ ranges.coveringStopsRange.max.match(eval),
+ util::interpolationFactor(1.0f, ranges.coveringZoomRange, ranges.zoom));
+ }
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/function/composite_interval_stops.hpp b/include/mbgl/style/function/composite_interval_stops.hpp
new file mode 100644
index 0000000000..3c495f2a7f
--- /dev/null
+++ b/include/mbgl/style/function/composite_interval_stops.hpp
@@ -0,0 +1,32 @@
+#pragma once
+
+#include <mbgl/style/function/interval_stops.hpp>
+
+#include <map>
+
+namespace mbgl {
+namespace style {
+
+template <class T>
+class CompositeIntervalStops {
+public:
+ using Stops = std::map<float, std::map<float, T>>;
+ Stops stops;
+
+ CompositeIntervalStops() = default;
+ CompositeIntervalStops(Stops stops_)
+ : stops(std::move(stops_)) {
+ }
+
+ IntervalStops<T> innerStops(const std::map<float, T>& stops_) const {
+ return IntervalStops<T>(stops_);
+ }
+
+ friend bool operator==(const CompositeIntervalStops& lhs,
+ const CompositeIntervalStops& rhs) {
+ return lhs.stops == rhs.stops;
+ }
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/function/exponential_stops.hpp b/include/mbgl/style/function/exponential_stops.hpp
new file mode 100644
index 0000000000..b3866c4059
--- /dev/null
+++ b/include/mbgl/style/function/exponential_stops.hpp
@@ -0,0 +1,56 @@
+#pragma once
+
+#include <mbgl/util/feature.hpp>
+#include <mbgl/util/interpolate.hpp>
+
+#include <map>
+
+namespace mbgl {
+namespace style {
+
+template <class T>
+class ExponentialStops {
+public:
+ using Stops = std::map<float, T>;
+
+ Stops stops;
+ float base = 1.0f;
+
+ ExponentialStops() = default;
+ ExponentialStops(Stops stops_, float base_ = 1.0f)
+ : stops(std::move(stops_)),
+ base(base_) {
+ }
+
+ optional<T> evaluate(float z) const {
+ if (stops.empty()) {
+ return {};
+ }
+
+ 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));
+ }
+ }
+
+ 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,
+ const ExponentialStops& rhs) {
+ return lhs.stops == rhs.stops && lhs.base == rhs.base;
+ }
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/function/identity_stops.hpp b/include/mbgl/style/function/identity_stops.hpp
new file mode 100644
index 0000000000..741ebbbe0c
--- /dev/null
+++ b/include/mbgl/style/function/identity_stops.hpp
@@ -0,0 +1,20 @@
+#pragma once
+
+#include <mbgl/util/feature.hpp>
+
+namespace mbgl {
+namespace style {
+
+template <class T>
+class IdentityStops {
+public:
+ optional<T> evaluate(const Value&) const;
+
+ friend bool operator==(const IdentityStops&,
+ const IdentityStops&) {
+ return true;
+ }
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/function/interval_stops.hpp b/include/mbgl/style/function/interval_stops.hpp
new file mode 100644
index 0000000000..45e2dc6f2e
--- /dev/null
+++ b/include/mbgl/style/function/interval_stops.hpp
@@ -0,0 +1,51 @@
+#pragma once
+
+#include <mbgl/util/feature.hpp>
+
+#include <map>
+
+namespace mbgl {
+namespace style {
+
+template <class T>
+class IntervalStops {
+public:
+ using Stops = std::map<float, T>;
+ Stops stops;
+
+ IntervalStops() = default;
+ IntervalStops(Stops stops_)
+ : stops(std::move(stops_)) {
+ }
+
+ optional<T> evaluate(float z) const {
+ if (stops.empty()) {
+ return {};
+ }
+
+ 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 std::prev(it)->second;
+ }
+ }
+
+ 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;
+ }
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/function/source_function.hpp b/include/mbgl/style/function/source_function.hpp
new file mode 100644
index 0000000000..9c2ad101ec
--- /dev/null
+++ b/include/mbgl/style/function/source_function.hpp
@@ -0,0 +1,60 @@
+#pragma once
+
+#include <mbgl/style/function/exponential_stops.hpp>
+#include <mbgl/style/function/interval_stops.hpp>
+#include <mbgl/style/function/categorical_stops.hpp>
+#include <mbgl/style/function/identity_stops.hpp>
+#include <mbgl/util/interpolate.hpp>
+#include <mbgl/util/variant.hpp>
+
+#include <string>
+
+namespace mbgl {
+namespace style {
+
+template <class T>
+class SourceFunction {
+public:
+ using Stops = std::conditional_t<
+ util::Interpolatable<T>::value,
+ variant<
+ ExponentialStops<T>,
+ IntervalStops<T>,
+ CategoricalStops<T>,
+ IdentityStops<T>>,
+ variant<
+ IntervalStops<T>,
+ CategoricalStops<T>,
+ IdentityStops<T>>>;
+
+ SourceFunction(std::string property_, Stops stops_, optional<T> defaultValue_ = {})
+ : property(std::move(property_)),
+ stops(std::move(stops_)),
+ defaultValue(std::move(defaultValue_)) {
+ }
+
+ template <class Feature>
+ T evaluate(const Feature& feature, T finalDefaultValue) const {
+ optional<Value> v = feature.getValue(property);
+ if (!v) {
+ return defaultValue.value_or(finalDefaultValue);
+ }
+ return stops.match([&] (const auto& s) -> T {
+ return s.evaluate(*v).value_or(defaultValue.value_or(finalDefaultValue));
+ });
+ }
+
+ friend bool operator==(const SourceFunction& lhs,
+ const SourceFunction& rhs) {
+ return std::tie(lhs.property, lhs.stops, lhs.defaultValue)
+ == std::tie(rhs.property, rhs.stops, rhs.defaultValue);
+ }
+
+ std::string property;
+ Stops stops;
+ optional<T> defaultValue;
+ bool useIntegerZoom = false;
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/image.hpp b/include/mbgl/style/image.hpp
new file mode 100644
index 0000000000..ff3bfedf46
--- /dev/null
+++ b/include/mbgl/style/image.hpp
@@ -0,0 +1,31 @@
+#pragma once
+
+#include <mbgl/util/image.hpp>
+#include <mbgl/util/immutable.hpp>
+
+#include <string>
+
+namespace mbgl {
+namespace style {
+
+class Image {
+public:
+ Image(std::string id, PremultipliedImage&&, float pixelRatio, bool sdf = false);
+ Image(const Image&);
+
+ std::string getID() const;
+
+ const PremultipliedImage& getImage() const;
+
+ // Pixel ratio of the sprite image.
+ float getPixelRatio() const;
+
+ // Whether this image should be interpreted as a signed distance field icon.
+ bool isSdf() const;
+
+ class Impl;
+ Immutable<Impl> baseImpl;
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/layer.hpp b/include/mbgl/style/layer.hpp
index 670faa8254..c6a3c0e735 100644
--- a/include/mbgl/style/layer.hpp
+++ b/include/mbgl/style/layer.hpp
@@ -1,10 +1,15 @@
#pragma once
#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>
+#include <cassert>
#include <memory>
#include <string>
+#include <stdexcept>
namespace mbgl {
namespace style {
@@ -17,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
@@ -35,22 +41,6 @@ class FillExtrusionLayer;
* auto circleLayer = std::make_unique<CircleLayer>("my-circle-layer");
*/
class Layer : public mbgl::util::noncopyable {
-protected:
- enum class Type {
- Fill,
- Line,
- Circle,
- Symbol,
- Raster,
- Background,
- Custom,
- FillExtrusion,
- };
-
- class Impl;
- const Type type;
- Layer(Type, std::unique_ptr<Impl>);
-
public:
virtual ~Layer();
@@ -71,7 +61,7 @@ public:
// Convenience method for dynamic dispatch on the concrete layer type. Using
// method overloading, this allows consolidation of logic common to vector-based
- // layers (Fill, Line, Circle, or Symbol). For example:
+ // layers (Fill, FillExtrusion, Line, Circle, or Symbol). For example:
//
// struct Visitor {
// void operator()(CustomLayer&) { ... }
@@ -83,42 +73,60 @@ public:
//
template <class V>
auto accept(V&& visitor) {
- switch (type) {
- case Type::Fill:
- return visitor(*as<FillLayer>());
- case Type::Line:
- return visitor(*as<LineLayer>());
- case Type::Circle:
- return visitor(*as<CircleLayer>());
- case Type::Symbol:
- return visitor(*as<SymbolLayer>());
- case Type::Raster:
- return visitor(*as<RasterLayer>());
- case Type::Background:
- return visitor(*as<BackgroundLayer>());
- case Type::Custom:
- return visitor(*as<CustomLayer>());
- case Type::FillExtrusion:
- return visitor(*as<FillExtrusionLayer>());
+ switch (getType()) {
+ case LayerType::Fill:
+ return std::forward<V>(visitor)(*as<FillLayer>());
+ case LayerType::Line:
+ return std::forward<V>(visitor)(*as<LineLayer>());
+ case LayerType::Circle:
+ return std::forward<V>(visitor)(*as<CircleLayer>());
+ case LayerType::Symbol:
+ return std::forward<V>(visitor)(*as<SymbolLayer>());
+ case LayerType::Raster:
+ return std::forward<V>(visitor)(*as<RasterLayer>());
+ case LayerType::Background:
+ return std::forward<V>(visitor)(*as<BackgroundLayer>());
+ case LayerType::Custom:
+ return std::forward<V>(visitor)(*as<CustomLayer>());
+ case LayerType::FillExtrusion:
+ return std::forward<V>(visitor)(*as<FillExtrusionLayer>());
}
+
+
+ // Not reachable, but placate GCC.
+ assert(false);
+ 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*);
- friend std::string layoutKey(const Layer&);
+ // 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;
};
} // namespace style
diff --git a/include/mbgl/style/layer_type.hpp b/include/mbgl/style/layer_type.hpp
new file mode 100644
index 0000000000..66ff834eee
--- /dev/null
+++ b/include/mbgl/style/layer_type.hpp
@@ -0,0 +1,18 @@
+#pragma once
+
+namespace mbgl {
+namespace style {
+
+enum class LayerType {
+ Fill,
+ Line,
+ Circle,
+ Symbol,
+ Raster,
+ Background,
+ Custom,
+ FillExtrusion,
+};
+
+} // namespace style
+} // namespace mbgl \ No newline at end of file
diff --git a/include/mbgl/style/layers/background_layer.hpp b/include/mbgl/style/layers/background_layer.hpp
index c120b7f493..903983844f 100644
--- a/include/mbgl/style/layers/background_layer.hpp
+++ b/include/mbgl/style/layers/background_layer.hpp
@@ -5,43 +5,60 @@
#include <mbgl/style/layer.hpp>
#include <mbgl/style/filter.hpp>
#include <mbgl/style/property_value.hpp>
+#include <mbgl/style/data_driven_property_value.hpp>
#include <mbgl/util/color.hpp>
namespace mbgl {
namespace style {
+class TransitionOptions;
+
class BackgroundLayer : public Layer {
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 = {});
+ 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 = {});
+ 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 = {});
+ 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 == Type::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 5562126c2f..942dd67503 100644
--- a/include/mbgl/style/layers/circle_layer.hpp
+++ b/include/mbgl/style/layers/circle_layer.hpp
@@ -5,12 +5,15 @@
#include <mbgl/style/layer.hpp>
#include <mbgl/style/filter.hpp>
#include <mbgl/style/property_value.hpp>
+#include <mbgl/style/data_driven_property_value.hpp>
#include <mbgl/util/color.hpp>
namespace mbgl {
namespace style {
+class TransitionOptions;
+
class CircleLayer : public Layer {
public:
CircleLayer(const std::string& layerID, const std::string& sourceID);
@@ -24,60 +27,94 @@ public:
void setFilter(const Filter&);
const Filter& getFilter() const;
- // Paint properties
-
- static PropertyValue<float> getDefaultCircleRadius();
- PropertyValue<float> getCircleRadius(const optional<std::string>& klass = {}) const;
- void setCircleRadius(PropertyValue<float>, const optional<std::string>& klass = {});
+ // Visibility
+ void setVisibility(VisibilityType) final;
- static PropertyValue<Color> getDefaultCircleColor();
- PropertyValue<Color> getCircleColor(const optional<std::string>& klass = {}) const;
- void setCircleColor(PropertyValue<Color>, const optional<std::string>& klass = {});
+ // Zoom range
+ void setMinZoom(float) final;
+ void setMaxZoom(float) final;
- static PropertyValue<float> getDefaultCircleBlur();
- PropertyValue<float> getCircleBlur(const optional<std::string>& klass = {}) const;
- void setCircleBlur(PropertyValue<float>, const optional<std::string>& klass = {});
+ // Paint properties
- static PropertyValue<float> getDefaultCircleOpacity();
- PropertyValue<float> getCircleOpacity(const optional<std::string>& klass = {}) const;
- void setCircleOpacity(PropertyValue<float>, const optional<std::string>& klass = {});
+ static DataDrivenPropertyValue<float> getDefaultCircleRadius();
+ DataDrivenPropertyValue<float> getCircleRadius() const;
+ void setCircleRadius(DataDrivenPropertyValue<float>);
+ void setCircleRadiusTransition(const TransitionOptions&);
+ TransitionOptions getCircleRadiusTransition() const;
+
+ static DataDrivenPropertyValue<Color> getDefaultCircleColor();
+ DataDrivenPropertyValue<Color> getCircleColor() const;
+ void setCircleColor(DataDrivenPropertyValue<Color>);
+ void setCircleColorTransition(const TransitionOptions&);
+ TransitionOptions getCircleColorTransition() const;
+
+ static DataDrivenPropertyValue<float> getDefaultCircleBlur();
+ DataDrivenPropertyValue<float> getCircleBlur() const;
+ void setCircleBlur(DataDrivenPropertyValue<float>);
+ void setCircleBlurTransition(const TransitionOptions&);
+ TransitionOptions getCircleBlurTransition() const;
+
+ static DataDrivenPropertyValue<float> getDefaultCircleOpacity();
+ 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 = {});
+ 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 = {});
+ 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 = {});
-
- static PropertyValue<float> getDefaultCircleStrokeWidth();
- PropertyValue<float> getCircleStrokeWidth(const optional<std::string>& klass = {}) const;
- void setCircleStrokeWidth(PropertyValue<float>, const optional<std::string>& klass = {});
-
- static PropertyValue<Color> getDefaultCircleStrokeColor();
- PropertyValue<Color> getCircleStrokeColor(const optional<std::string>& klass = {}) const;
- void setCircleStrokeColor(PropertyValue<Color>, const optional<std::string>& klass = {});
-
- static PropertyValue<float> getDefaultCircleStrokeOpacity();
- PropertyValue<float> getCircleStrokeOpacity(const optional<std::string>& klass = {}) const;
- void setCircleStrokeOpacity(PropertyValue<float>, const optional<std::string>& klass = {});
+ 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;
+ void setCircleStrokeWidth(DataDrivenPropertyValue<float>);
+ void setCircleStrokeWidthTransition(const TransitionOptions&);
+ TransitionOptions getCircleStrokeWidthTransition() const;
+
+ static DataDrivenPropertyValue<Color> getDefaultCircleStrokeColor();
+ DataDrivenPropertyValue<Color> getCircleStrokeColor() const;
+ void setCircleStrokeColor(DataDrivenPropertyValue<Color>);
+ void setCircleStrokeColorTransition(const TransitionOptions&);
+ TransitionOptions getCircleStrokeColorTransition() const;
+
+ static DataDrivenPropertyValue<float> getDefaultCircleStrokeOpacity();
+ 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 == Type::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 6bde087820..79a353b047 100644
--- a/include/mbgl/style/layers/custom_layer.hpp
+++ b/include/mbgl/style/layers/custom_layer.hpp
@@ -55,19 +55,26 @@ public:
void* context);
~CustomLayer() final;
+ // Visibility
+ void setVisibility(VisibilityType) final;
+
+ // Zoom range
+ void setMinZoom(float) final;
+ void setMaxZoom(float) final;
+
// Private implementation
class Impl;
- Impl* impl;
+ const Impl& impl() const;
+
+ Mutable<Impl> mutableImpl() const;
+ std::unique_ptr<Layer> cloneRef(const std::string& id) const final;
- CustomLayer(const Impl&);
CustomLayer(const CustomLayer&) = delete;
};
template <>
-inline bool Layer::is<CustomLayer>() const {
- return type == Type::Custom;
-}
+bool Layer::is<CustomLayer>() const;
} // namespace style
} // namespace mbgl
diff --git a/include/mbgl/style/layers/fill_extrusion_layer.hpp b/include/mbgl/style/layers/fill_extrusion_layer.hpp
index 08728af309..e1c54f54ee 100644
--- a/include/mbgl/style/layers/fill_extrusion_layer.hpp
+++ b/include/mbgl/style/layers/fill_extrusion_layer.hpp
@@ -5,12 +5,15 @@
#include <mbgl/style/layer.hpp>
#include <mbgl/style/filter.hpp>
#include <mbgl/style/property_value.hpp>
+#include <mbgl/style/data_driven_property_value.hpp>
#include <mbgl/util/color.hpp>
namespace mbgl {
namespace style {
+class TransitionOptions;
+
class FillExtrusionLayer : public Layer {
public:
FillExtrusionLayer(const std::string& layerID, const std::string& sourceID);
@@ -24,48 +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 = {});
+ PropertyValue<float> getFillExtrusionOpacity() const;
+ void setFillExtrusionOpacity(PropertyValue<float>);
+ void setFillExtrusionOpacityTransition(const TransitionOptions&);
+ TransitionOptions getFillExtrusionOpacityTransition() const;
- static PropertyValue<Color> getDefaultFillExtrusionColor();
- PropertyValue<Color> getFillExtrusionColor(const optional<std::string>& klass = {}) const;
- void setFillExtrusionColor(PropertyValue<Color>, const optional<std::string>& klass = {});
+ static DataDrivenPropertyValue<Color> getDefaultFillExtrusionColor();
+ 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 = {});
+ 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 = {});
+ 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 = {});
-
- static PropertyValue<float> getDefaultFillExtrusionHeight();
- PropertyValue<float> getFillExtrusionHeight(const optional<std::string>& klass = {}) const;
- void setFillExtrusionHeight(PropertyValue<float>, const optional<std::string>& klass = {});
-
- static PropertyValue<float> getDefaultFillExtrusionBase();
- PropertyValue<float> getFillExtrusionBase(const optional<std::string>& klass = {}) const;
- void setFillExtrusionBase(PropertyValue<float>, const optional<std::string>& klass = {});
+ 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;
+ void setFillExtrusionHeight(DataDrivenPropertyValue<float>);
+ void setFillExtrusionHeightTransition(const TransitionOptions&);
+ TransitionOptions getFillExtrusionHeightTransition() const;
+
+ static DataDrivenPropertyValue<float> getDefaultFillExtrusionBase();
+ 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 == Type::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 4b9201641d..dfbe69d7fe 100644
--- a/include/mbgl/style/layers/fill_layer.hpp
+++ b/include/mbgl/style/layers/fill_layer.hpp
@@ -5,12 +5,15 @@
#include <mbgl/style/layer.hpp>
#include <mbgl/style/filter.hpp>
#include <mbgl/style/property_value.hpp>
+#include <mbgl/style/data_driven_property_value.hpp>
#include <mbgl/util/color.hpp>
namespace mbgl {
namespace style {
+class TransitionOptions;
+
class FillLayer : public Layer {
public:
FillLayer(const std::string& layerID, const std::string& sourceID);
@@ -24,48 +27,70 @@ public:
void setFilter(const Filter&);
const Filter& getFilter() const;
- // Paint properties
-
- static PropertyValue<bool> getDefaultFillAntialias();
- PropertyValue<bool> getFillAntialias(const optional<std::string>& klass = {}) const;
- void setFillAntialias(PropertyValue<bool>, const optional<std::string>& klass = {});
+ // Visibility
+ void setVisibility(VisibilityType) final;
- static PropertyValue<float> getDefaultFillOpacity();
- PropertyValue<float> getFillOpacity(const optional<std::string>& klass = {}) const;
- void setFillOpacity(PropertyValue<float>, const optional<std::string>& klass = {});
+ // Zoom range
+ void setMinZoom(float) final;
+ void setMaxZoom(float) final;
- static PropertyValue<Color> getDefaultFillColor();
- PropertyValue<Color> getFillColor(const optional<std::string>& klass = {}) const;
- void setFillColor(PropertyValue<Color>, const optional<std::string>& klass = {});
+ // Paint properties
- static PropertyValue<Color> getDefaultFillOutlineColor();
- PropertyValue<Color> getFillOutlineColor(const optional<std::string>& klass = {}) const;
- void setFillOutlineColor(PropertyValue<Color>, const optional<std::string>& klass = {});
+ static PropertyValue<bool> getDefaultFillAntialias();
+ PropertyValue<bool> getFillAntialias() const;
+ void setFillAntialias(PropertyValue<bool>);
+ void setFillAntialiasTransition(const TransitionOptions&);
+ TransitionOptions getFillAntialiasTransition() const;
+
+ static DataDrivenPropertyValue<float> getDefaultFillOpacity();
+ DataDrivenPropertyValue<float> getFillOpacity() const;
+ void setFillOpacity(DataDrivenPropertyValue<float>);
+ void setFillOpacityTransition(const TransitionOptions&);
+ TransitionOptions getFillOpacityTransition() const;
+
+ static DataDrivenPropertyValue<Color> getDefaultFillColor();
+ DataDrivenPropertyValue<Color> getFillColor() const;
+ void setFillColor(DataDrivenPropertyValue<Color>);
+ void setFillColorTransition(const TransitionOptions&);
+ TransitionOptions getFillColorTransition() const;
+
+ static DataDrivenPropertyValue<Color> getDefaultFillOutlineColor();
+ 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 = {});
+ 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 = {});
+ 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 = {});
+ 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 == Type::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
deleted file mode 100644
index 15d0fcee61..0000000000
--- a/include/mbgl/style/layers/layer.hpp.ejs
+++ /dev/null
@@ -1,77 +0,0 @@
-<%
- const type = locals.type;
- const layoutProperties = locals.layoutProperties;
- const paintProperties = locals.paintProperties;
--%>
-// This file is generated. Do not edit.
-
-#pragma once
-
-#include <mbgl/style/layer.hpp>
-#include <mbgl/style/filter.hpp>
-#include <mbgl/style/property_value.hpp>
-
-#include <mbgl/util/color.hpp>
-
-<% if (type === 'line' || type === 'symbol') { -%>
-#include <vector>
-
-<% } -%>
-namespace mbgl {
-namespace style {
-
-class <%- camelize(type) %>Layer : public Layer {
-public:
-<% if (type === 'background') { -%>
- <%- camelize(type) %>Layer(const std::string& layerID);
-<% } else { -%>
- <%- camelize(type) %>Layer(const std::string& layerID, const std::string& sourceID);
-<% } -%>
- ~<%- camelize(type) %>Layer() final;
-
-<% if (type !== 'background') { -%>
- // Source
- const std::string& getSourceID() const;
-<% if (type !== 'raster') { -%>
- const std::string& getSourceLayer() const;
- void setSourceLayer(const std::string& sourceLayer);
-
- void setFilter(const Filter&);
- const Filter& getFilter() const;
-<% } -%>
-
-<% } -%>
-<% if (layoutProperties.length) { -%>
- // Layout properties
-
-<% for (const property of layoutProperties) { -%>
- static PropertyValue<<%- propertyType(property) %>> getDefault<%- camelize(property.name) %>();
- PropertyValue<<%- propertyType(property) %>> get<%- camelize(property.name) %>() const;
- void set<%- camelize(property.name) %>(PropertyValue<<%- propertyType(property) %>>);
-
-<% } -%>
-<% } -%>
- // Paint properties
-
-<% for (const property of paintProperties) { -%>
- static PropertyValue<<%- propertyType(property) %>> getDefault<%- camelize(property.name) %>();
- PropertyValue<<%- propertyType(property) %>> get<%- camelize(property.name) %>(const optional<std::string>& klass = {}) const;
- void set<%- camelize(property.name) %>(PropertyValue<<%- propertyType(property) %>>, const optional<std::string>& klass = {});
-
-<% } -%>
- // Private implementation
-
- class Impl;
- Impl* const impl;
-
- <%- camelize(type) %>Layer(const Impl&);
- <%- camelize(type) %>Layer(const <%- camelize(type) %>Layer&) = delete;
-};
-
-template <>
-inline bool Layer::is<<%- camelize(type) %>Layer>() const {
- return type == Type::<%- camelize(type) %>;
-}
-
-} // namespace style
-} // namespace mbgl
diff --git a/include/mbgl/style/layers/line_layer.hpp b/include/mbgl/style/layers/line_layer.hpp
index c3c1026bcd..4519296323 100644
--- a/include/mbgl/style/layers/line_layer.hpp
+++ b/include/mbgl/style/layers/line_layer.hpp
@@ -5,6 +5,7 @@
#include <mbgl/style/layer.hpp>
#include <mbgl/style/filter.hpp>
#include <mbgl/style/property_value.hpp>
+#include <mbgl/style/data_driven_property_value.hpp>
#include <mbgl/util/color.hpp>
@@ -13,6 +14,8 @@
namespace mbgl {
namespace style {
+class TransitionOptions;
+
class LineLayer : public Layer {
public:
LineLayer(const std::string& layerID, const std::string& sourceID);
@@ -26,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;
@@ -46,58 +56,79 @@ public:
// Paint properties
- static PropertyValue<float> getDefaultLineOpacity();
- PropertyValue<float> getLineOpacity(const optional<std::string>& klass = {}) const;
- void setLineOpacity(PropertyValue<float>, const optional<std::string>& klass = {});
+ static DataDrivenPropertyValue<float> getDefaultLineOpacity();
+ DataDrivenPropertyValue<float> getLineOpacity() const;
+ void setLineOpacity(DataDrivenPropertyValue<float>);
+ void setLineOpacityTransition(const TransitionOptions&);
+ TransitionOptions getLineOpacityTransition() const;
- static PropertyValue<Color> getDefaultLineColor();
- PropertyValue<Color> getLineColor(const optional<std::string>& klass = {}) const;
- void setLineColor(PropertyValue<Color>, const optional<std::string>& klass = {});
+ static DataDrivenPropertyValue<Color> getDefaultLineColor();
+ 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 = {});
+ 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 = {});
-
- static PropertyValue<float> getDefaultLineWidth();
- PropertyValue<float> getLineWidth(const optional<std::string>& klass = {}) const;
- void setLineWidth(PropertyValue<float>, const optional<std::string>& klass = {});
-
- static PropertyValue<float> getDefaultLineGapWidth();
- PropertyValue<float> getLineGapWidth(const optional<std::string>& klass = {}) const;
- void setLineGapWidth(PropertyValue<float>, const optional<std::string>& klass = {});
-
- static PropertyValue<float> getDefaultLineOffset();
- PropertyValue<float> getLineOffset(const optional<std::string>& klass = {}) const;
- void setLineOffset(PropertyValue<float>, const optional<std::string>& klass = {});
-
- static PropertyValue<float> getDefaultLineBlur();
- PropertyValue<float> getLineBlur(const optional<std::string>& klass = {}) const;
- void setLineBlur(PropertyValue<float>, const optional<std::string>& klass = {});
+ PropertyValue<TranslateAnchorType> getLineTranslateAnchor() const;
+ void setLineTranslateAnchor(PropertyValue<TranslateAnchorType>);
+ void setLineTranslateAnchorTransition(const TransitionOptions&);
+ TransitionOptions getLineTranslateAnchorTransition() 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;
+ void setLineGapWidth(DataDrivenPropertyValue<float>);
+ void setLineGapWidthTransition(const TransitionOptions&);
+ TransitionOptions getLineGapWidthTransition() const;
+
+ static DataDrivenPropertyValue<float> getDefaultLineOffset();
+ DataDrivenPropertyValue<float> getLineOffset() const;
+ void setLineOffset(DataDrivenPropertyValue<float>);
+ void setLineOffsetTransition(const TransitionOptions&);
+ TransitionOptions getLineOffsetTransition() const;
+
+ static DataDrivenPropertyValue<float> getDefaultLineBlur();
+ 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 = {});
+ 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 = {});
+ 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 == Type::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 ae6ec7f91c..8111364709 100644
--- a/include/mbgl/style/layers/raster_layer.hpp
+++ b/include/mbgl/style/layers/raster_layer.hpp
@@ -5,12 +5,15 @@
#include <mbgl/style/layer.hpp>
#include <mbgl/style/filter.hpp>
#include <mbgl/style/property_value.hpp>
+#include <mbgl/style/data_driven_property_value.hpp>
#include <mbgl/util/color.hpp>
namespace mbgl {
namespace style {
+class TransitionOptions;
+
class RasterLayer : public Layer {
public:
RasterLayer(const std::string& layerID, const std::string& sourceID);
@@ -19,48 +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 = {});
+ 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 = {});
+ 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 = {});
+ 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 = {});
+ 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 = {});
+ 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 = {});
+ 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 = {});
+ 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 == Type::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 1e2e6ac454..6e355c0057 100644
--- a/include/mbgl/style/layers/symbol_layer.hpp
+++ b/include/mbgl/style/layers/symbol_layer.hpp
@@ -5,6 +5,7 @@
#include <mbgl/style/layer.hpp>
#include <mbgl/style/filter.hpp>
#include <mbgl/style/property_value.hpp>
+#include <mbgl/style/data_driven_property_value.hpp>
#include <mbgl/util/color.hpp>
@@ -13,6 +14,8 @@
namespace mbgl {
namespace style {
+class TransitionOptions;
+
class SymbolLayer : public Layer {
public:
SymbolLayer(const std::string& layerID, const std::string& sourceID);
@@ -26,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();
@@ -56,9 +66,9 @@ public:
PropertyValue<AlignmentType> getIconRotationAlignment() const;
void setIconRotationAlignment(PropertyValue<AlignmentType>);
- static PropertyValue<float> getDefaultIconSize();
- PropertyValue<float> getIconSize() const;
- void setIconSize(PropertyValue<float>);
+ static DataDrivenPropertyValue<float> getDefaultIconSize();
+ DataDrivenPropertyValue<float> getIconSize() const;
+ void setIconSize(DataDrivenPropertyValue<float>);
static PropertyValue<IconTextFitType> getDefaultIconTextFit();
PropertyValue<IconTextFitType> getIconTextFit() const;
@@ -68,13 +78,13 @@ public:
PropertyValue<std::array<float, 4>> getIconTextFitPadding() const;
void setIconTextFitPadding(PropertyValue<std::array<float, 4>>);
- static PropertyValue<std::string> getDefaultIconImage();
- PropertyValue<std::string> getIconImage() const;
- void setIconImage(PropertyValue<std::string>);
+ static DataDrivenPropertyValue<std::string> getDefaultIconImage();
+ DataDrivenPropertyValue<std::string> getIconImage() const;
+ void setIconImage(DataDrivenPropertyValue<std::string>);
- static PropertyValue<float> getDefaultIconRotate();
- PropertyValue<float> getIconRotate() const;
- void setIconRotate(PropertyValue<float>);
+ static DataDrivenPropertyValue<float> getDefaultIconRotate();
+ DataDrivenPropertyValue<float> getIconRotate() const;
+ void setIconRotate(DataDrivenPropertyValue<float>);
static PropertyValue<float> getDefaultIconPadding();
PropertyValue<float> getIconPadding() const;
@@ -84,9 +94,13 @@ public:
PropertyValue<bool> getIconKeepUpright() const;
void setIconKeepUpright(PropertyValue<bool>);
- static PropertyValue<std::array<float, 2>> getDefaultIconOffset();
- PropertyValue<std::array<float, 2>> getIconOffset() const;
- void setIconOffset(PropertyValue<std::array<float, 2>>);
+ static DataDrivenPropertyValue<std::array<float, 2>> getDefaultIconOffset();
+ DataDrivenPropertyValue<std::array<float, 2>> getIconOffset() const;
+ void setIconOffset(DataDrivenPropertyValue<std::array<float, 2>>);
+
+ static PropertyValue<AlignmentType> getDefaultIconPitchAlignment();
+ PropertyValue<AlignmentType> getIconPitchAlignment() const;
+ void setIconPitchAlignment(PropertyValue<AlignmentType>);
static PropertyValue<AlignmentType> getDefaultTextPitchAlignment();
PropertyValue<AlignmentType> getTextPitchAlignment() const;
@@ -96,17 +110,17 @@ public:
PropertyValue<AlignmentType> getTextRotationAlignment() const;
void setTextRotationAlignment(PropertyValue<AlignmentType>);
- static PropertyValue<std::string> getDefaultTextField();
- PropertyValue<std::string> getTextField() const;
- void setTextField(PropertyValue<std::string>);
+ static DataDrivenPropertyValue<std::string> getDefaultTextField();
+ DataDrivenPropertyValue<std::string> getTextField() const;
+ void setTextField(DataDrivenPropertyValue<std::string>);
static PropertyValue<std::vector<std::string>> getDefaultTextFont();
PropertyValue<std::vector<std::string>> getTextFont() const;
void setTextFont(PropertyValue<std::vector<std::string>>);
- static PropertyValue<float> getDefaultTextSize();
- PropertyValue<float> getTextSize() const;
- void setTextSize(PropertyValue<float>);
+ static DataDrivenPropertyValue<float> getDefaultTextSize();
+ DataDrivenPropertyValue<float> getTextSize() const;
+ void setTextSize(DataDrivenPropertyValue<float>);
static PropertyValue<float> getDefaultTextMaxWidth();
PropertyValue<float> getTextMaxWidth() const;
@@ -120,21 +134,21 @@ public:
PropertyValue<float> getTextLetterSpacing() const;
void setTextLetterSpacing(PropertyValue<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<TextAnchorType> getDefaultTextAnchor();
+ DataDrivenPropertyValue<TextAnchorType> getTextAnchor() const;
+ void setTextAnchor(DataDrivenPropertyValue<TextAnchorType>);
static PropertyValue<float> getDefaultTextMaxAngle();
PropertyValue<float> getTextMaxAngle() const;
void setTextMaxAngle(PropertyValue<float>);
- static PropertyValue<float> getDefaultTextRotate();
- PropertyValue<float> getTextRotate() const;
- void setTextRotate(PropertyValue<float>);
+ static DataDrivenPropertyValue<float> getDefaultTextRotate();
+ DataDrivenPropertyValue<float> getTextRotate() const;
+ void setTextRotate(DataDrivenPropertyValue<float>);
static PropertyValue<float> getDefaultTextPadding();
PropertyValue<float> getTextPadding() const;
@@ -144,13 +158,13 @@ public:
PropertyValue<bool> getTextKeepUpright() const;
void setTextKeepUpright(PropertyValue<bool>);
- static PropertyValue<TextTransformType> getDefaultTextTransform();
- PropertyValue<TextTransformType> getTextTransform() const;
- void setTextTransform(PropertyValue<TextTransformType>);
+ static DataDrivenPropertyValue<TextTransformType> getDefaultTextTransform();
+ DataDrivenPropertyValue<TextTransformType> getTextTransform() const;
+ void setTextTransform(DataDrivenPropertyValue<TextTransformType>);
- static PropertyValue<std::array<float, 2>> getDefaultTextOffset();
- PropertyValue<std::array<float, 2>> getTextOffset() const;
- void setTextOffset(PropertyValue<std::array<float, 2>>);
+ static DataDrivenPropertyValue<std::array<float, 2>> getDefaultTextOffset();
+ DataDrivenPropertyValue<std::array<float, 2>> getTextOffset() const;
+ void setTextOffset(DataDrivenPropertyValue<std::array<float, 2>>);
static PropertyValue<bool> getDefaultTextAllowOverlap();
PropertyValue<bool> getTextAllowOverlap() const;
@@ -166,74 +180,103 @@ public:
// Paint properties
- static PropertyValue<float> getDefaultIconOpacity();
- PropertyValue<float> getIconOpacity(const optional<std::string>& klass = {}) const;
- void setIconOpacity(PropertyValue<float>, const optional<std::string>& klass = {});
-
- static PropertyValue<Color> getDefaultIconColor();
- PropertyValue<Color> getIconColor(const optional<std::string>& klass = {}) const;
- void setIconColor(PropertyValue<Color>, const optional<std::string>& klass = {});
-
- static PropertyValue<Color> getDefaultIconHaloColor();
- PropertyValue<Color> getIconHaloColor(const optional<std::string>& klass = {}) const;
- void setIconHaloColor(PropertyValue<Color>, const optional<std::string>& klass = {});
-
- static PropertyValue<float> getDefaultIconHaloWidth();
- PropertyValue<float> getIconHaloWidth(const optional<std::string>& klass = {}) const;
- void setIconHaloWidth(PropertyValue<float>, const optional<std::string>& klass = {});
-
- static PropertyValue<float> getDefaultIconHaloBlur();
- PropertyValue<float> getIconHaloBlur(const optional<std::string>& klass = {}) const;
- void setIconHaloBlur(PropertyValue<float>, const optional<std::string>& klass = {});
+ static DataDrivenPropertyValue<float> getDefaultIconOpacity();
+ DataDrivenPropertyValue<float> getIconOpacity() const;
+ void setIconOpacity(DataDrivenPropertyValue<float>);
+ void setIconOpacityTransition(const TransitionOptions&);
+ TransitionOptions getIconOpacityTransition() const;
+
+ static DataDrivenPropertyValue<Color> getDefaultIconColor();
+ DataDrivenPropertyValue<Color> getIconColor() const;
+ void setIconColor(DataDrivenPropertyValue<Color>);
+ void setIconColorTransition(const TransitionOptions&);
+ TransitionOptions getIconColorTransition() const;
+
+ static DataDrivenPropertyValue<Color> getDefaultIconHaloColor();
+ DataDrivenPropertyValue<Color> getIconHaloColor() const;
+ void setIconHaloColor(DataDrivenPropertyValue<Color>);
+ void setIconHaloColorTransition(const TransitionOptions&);
+ TransitionOptions getIconHaloColorTransition() const;
+
+ static DataDrivenPropertyValue<float> getDefaultIconHaloWidth();
+ DataDrivenPropertyValue<float> getIconHaloWidth() const;
+ void setIconHaloWidth(DataDrivenPropertyValue<float>);
+ void setIconHaloWidthTransition(const TransitionOptions&);
+ TransitionOptions getIconHaloWidthTransition() const;
+
+ static DataDrivenPropertyValue<float> getDefaultIconHaloBlur();
+ 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 = {});
+ 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 = {});
-
- static PropertyValue<float> getDefaultTextOpacity();
- PropertyValue<float> getTextOpacity(const optional<std::string>& klass = {}) const;
- void setTextOpacity(PropertyValue<float>, const optional<std::string>& klass = {});
-
- static PropertyValue<Color> getDefaultTextColor();
- PropertyValue<Color> getTextColor(const optional<std::string>& klass = {}) const;
- void setTextColor(PropertyValue<Color>, const optional<std::string>& klass = {});
-
- static PropertyValue<Color> getDefaultTextHaloColor();
- PropertyValue<Color> getTextHaloColor(const optional<std::string>& klass = {}) const;
- void setTextHaloColor(PropertyValue<Color>, const optional<std::string>& klass = {});
-
- static PropertyValue<float> getDefaultTextHaloWidth();
- PropertyValue<float> getTextHaloWidth(const optional<std::string>& klass = {}) const;
- void setTextHaloWidth(PropertyValue<float>, const optional<std::string>& klass = {});
-
- static PropertyValue<float> getDefaultTextHaloBlur();
- PropertyValue<float> getTextHaloBlur(const optional<std::string>& klass = {}) const;
- void setTextHaloBlur(PropertyValue<float>, const optional<std::string>& klass = {});
+ PropertyValue<TranslateAnchorType> getIconTranslateAnchor() const;
+ void setIconTranslateAnchor(PropertyValue<TranslateAnchorType>);
+ void setIconTranslateAnchorTransition(const TransitionOptions&);
+ TransitionOptions getIconTranslateAnchorTransition() const;
+
+ static DataDrivenPropertyValue<float> getDefaultTextOpacity();
+ DataDrivenPropertyValue<float> getTextOpacity() const;
+ void setTextOpacity(DataDrivenPropertyValue<float>);
+ void setTextOpacityTransition(const TransitionOptions&);
+ TransitionOptions getTextOpacityTransition() const;
+
+ static DataDrivenPropertyValue<Color> getDefaultTextColor();
+ DataDrivenPropertyValue<Color> getTextColor() const;
+ void setTextColor(DataDrivenPropertyValue<Color>);
+ void setTextColorTransition(const TransitionOptions&);
+ TransitionOptions getTextColorTransition() const;
+
+ static DataDrivenPropertyValue<Color> getDefaultTextHaloColor();
+ DataDrivenPropertyValue<Color> getTextHaloColor() const;
+ void setTextHaloColor(DataDrivenPropertyValue<Color>);
+ void setTextHaloColorTransition(const TransitionOptions&);
+ TransitionOptions getTextHaloColorTransition() const;
+
+ static DataDrivenPropertyValue<float> getDefaultTextHaloWidth();
+ DataDrivenPropertyValue<float> getTextHaloWidth() const;
+ void setTextHaloWidth(DataDrivenPropertyValue<float>);
+ void setTextHaloWidthTransition(const TransitionOptions&);
+ TransitionOptions getTextHaloWidthTransition() const;
+
+ static DataDrivenPropertyValue<float> getDefaultTextHaloBlur();
+ 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 = {});
+ 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 = {});
+ 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 == Type::Symbol;
+ return getType() == LayerType::Symbol;
}
} // namespace style
diff --git a/include/mbgl/style/light.hpp b/include/mbgl/style/light.hpp
new file mode 100644
index 0000000000..c82792b28d
--- /dev/null
+++ b/include/mbgl/style/light.hpp
@@ -0,0 +1,53 @@
+// 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 <mbgl/util/immutable.hpp>
+
+namespace mbgl {
+namespace style {
+
+class LightObserver;
+
+class Light {
+public:
+ Light();
+ ~Light();
+
+ static LightAnchorType getDefaultAnchor();
+ PropertyValue<LightAnchorType> getAnchor() const;
+ void setAnchor(PropertyValue<LightAnchorType>);
+ void setAnchorTransition(const TransitionOptions&);
+ TransitionOptions getAnchorTransition() const;
+
+ static Position getDefaultPosition();
+ PropertyValue<Position> getPosition() const;
+ void setPosition(PropertyValue<Position>);
+ void setPositionTransition(const TransitionOptions&);
+ TransitionOptions getPositionTransition() const;
+
+ static Color getDefaultColor();
+ PropertyValue<Color> getColor() const;
+ void setColor(PropertyValue<Color>);
+ void setColorTransition(const TransitionOptions&);
+ TransitionOptions getColorTransition() const;
+
+ static float getDefaultIntensity();
+ PropertyValue<float> getIntensity() const;
+ void setIntensity(PropertyValue<float>);
+ void setIntensityTransition(const TransitionOptions&);
+ TransitionOptions getIntensityTransition() const;
+
+ class Impl;
+ Immutable<Impl> impl;
+ Mutable<Impl> mutableImpl() const;
+
+ LightObserver* observer = nullptr;
+ void setObserver(LightObserver*);
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/position.hpp b/include/mbgl/style/position.hpp
new file mode 100644
index 0000000000..3be8d1c55e
--- /dev/null
+++ b/include/mbgl/style/position.hpp
@@ -0,0 +1,68 @@
+#pragma once
+
+#include <mbgl/util/constants.hpp>
+
+#include <array>
+
+namespace mbgl {
+namespace style {
+class Position {
+public:
+ Position() = default;
+ Position(std::array<float, 3>& position_)
+ : radial(position_[0]), azimuthal(position_[1]), polar(position_[2]) {
+ calculateCartesian();
+ };
+
+ friend bool operator==(const Position& lhs, const Position& rhs) {
+ return lhs.radial == rhs.radial && lhs.azimuthal == rhs.azimuthal && lhs.polar == rhs.polar;
+ // TODO this doesn't address wrapping, which would be better addressed by comparing cartesian coordinates but being calculated floats are ont to be trusted.
+ }
+
+ friend bool operator!=(const Position& lhs, const Position& rhs) {
+ return !(lhs == rhs);
+ }
+
+ const std::array<float, 3> getCartesian() const {
+ return { { x, y, z } };
+ };
+
+ const std::array<float, 3> getSpherical() const {
+ return { { radial, azimuthal, polar } };
+ };
+
+ void set(std::array<float, 3>& position_) {
+ radial = position_[0];
+ azimuthal = position_[1];
+ polar = position_[2];
+ calculateCartesian();
+ };
+
+ // Utility function to be used only during interpolation; this leaves spherical coordinates undefined.
+ void setCartesian(std::array<float, 3>& position_) {
+ x = position_[0];
+ y = position_[1];
+ z = position_[2];
+ }
+
+private:
+ float radial;
+ float azimuthal;
+ float polar;
+ float x;
+ float y;
+ float z;
+
+ void calculateCartesian() {
+ // We abstract "north"/"up" (compass-wise) to be 0° when really this is 90° (π/2): we
+ // correct for that here
+ const float _a = (azimuthal + 90) * util::DEG2RAD;
+ const float _p = polar * util::DEG2RAD;
+
+ x = radial * std::cos(_a) * std::sin(_p);
+ y = radial * std::sin(_a) * std::sin(_p);
+ z = radial * std::cos(_p);
+ };
+};
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/property_value.hpp b/include/mbgl/style/property_value.hpp
index 83c4b4cf1b..02d3a31148 100644
--- a/include/mbgl/style/property_value.hpp
+++ b/include/mbgl/style/property_value.hpp
@@ -1,20 +1,16 @@
#pragma once
#include <mbgl/util/variant.hpp>
-#include <mbgl/style/function.hpp>
+#include <mbgl/style/undefined.hpp>
+#include <mbgl/style/function/camera_function.hpp>
namespace mbgl {
namespace style {
-class Undefined {};
-
-inline bool operator==(const Undefined&, const Undefined&) { return true; }
-inline bool operator!=(const Undefined&, const Undefined&) { return false; }
-
template <class T>
class PropertyValue {
private:
- using Value = variant<Undefined, T, Function<T>>;
+ using Value = variant<Undefined, T, CameraFunction<T>>;
Value value;
friend bool operator==(const PropertyValue& lhs, const PropertyValue& rhs) {
@@ -26,23 +22,26 @@ private:
}
public:
- PropertyValue() : value() {}
- PropertyValue( T constant) : value(constant) {}
- PropertyValue(Function<T> function) : value(function) {}
-
- bool isUndefined() const { return value.which() == 0; }
- bool isConstant() const { return value.which() == 1; }
- bool isFunction() const { return value.which() == 2; }
+ PropertyValue() : value() {}
+ PropertyValue( T constant) : value(constant) {}
+ PropertyValue(CameraFunction<T> function) : value(function) {}
- const T & asConstant() const { return value.template get< T >(); }
- const Function<T>& asFunction() const { return value.template get<Function<T>>(); }
+ bool isUndefined() const { return value.which() == 0; }
+ bool isConstant() const { return value.which() == 1; }
+ bool isCameraFunction() const { return value.which() == 2; }
+ bool isDataDriven() const { return false; }
- explicit operator bool() const { return !isUndefined(); };
+ const T & asConstant() const { return value.template get< T >(); }
+ 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 870c81fda6..cec9619451 100644
--- a/include/mbgl/style/source.hpp
+++ b/include/mbgl/style/source.hpp
@@ -2,14 +2,24 @@
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/util/optional.hpp>
+#include <mbgl/util/any.hpp>
+#include <mbgl/util/immutable.hpp>
#include <mbgl/style/types.hpp>
#include <memory>
#include <string>
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.
@@ -45,21 +55,28 @@ public:
return is<T>() ? reinterpret_cast<const T*>(this) : nullptr;
}
- const std::string& getID() const;
-
- // Create a new source with the specified `id`. All other properties
- // are copied from this source.
- std::unique_ptr<Source> copy(const std::string& id) 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;
-protected:
- const SourceType type;
- Source(SourceType, std::unique_ptr<Impl>);
+ // 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;
};
} // namespace style
diff --git a/include/mbgl/style/sources/geojson_source.hpp b/include/mbgl/style/sources/geojson_source.hpp
index ede0301725..2dcfec51aa 100644
--- a/include/mbgl/style/sources/geojson_source.hpp
+++ b/include/mbgl/style/sources/geojson_source.hpp
@@ -4,26 +4,12 @@
#include <mbgl/util/geojson.hpp>
#include <mbgl/util/optional.hpp>
-#include <mapbox/geojson.hpp>
-
-namespace mapbox {
-
-namespace geojsonvt {
-class GeoJSONVT;
-} // namespace geojsonvt
-
-namespace supercluster {
-class Supercluster;
-} // namespace supercluster
+namespace mbgl {
-} // namespace mapbox
+class AsyncRequest;
-namespace mbgl {
namespace style {
-using GeoJSONVTPointer = std::unique_ptr<mapbox::geojsonvt::GeoJSONVT>;
-using SuperclusterPointer = std::unique_ptr<mapbox::supercluster::Supercluster>;
-
struct GeoJSONOptions {
// GeoJSON-VT options
uint8_t maxzoom = 18;
@@ -38,22 +24,27 @@ struct GeoJSONOptions {
class GeoJSONSource : public Source {
public:
- GeoJSONSource(const std::string& id, const GeoJSONOptions options_ = GeoJSONOptions());
+ 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..cb84922b4d
--- /dev/null
+++ b/include/mbgl/style/style.hpp
@@ -0,0 +1,81 @@
+#pragma once
+
+#include <mbgl/style/transition_options.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;
+ LatLng getDefaultLatLng() const;
+ double getDefaultZoom() const;
+ double getDefaultBearing() const;
+ double getDefaultPitch() 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 eab6ef7039..87a81717a0 100644
--- a/include/mbgl/style/transition_options.hpp
+++ b/include/mbgl/style/transition_options.hpp
@@ -8,19 +8,22 @@ namespace style {
class TransitionOptions {
public:
- optional<Duration> duration = {};
- optional<Duration> delay = {};
+ optional<Duration> duration;
+ optional<Duration> delay;
- TransitionOptions reverseMerge(const TransitionOptions& defaults) const {
- TransitionOptions options;
-
- options.duration = duration ? duration : defaults.duration;
- options.delay = delay ? delay : defaults.delay;
+ TransitionOptions(optional<Duration> duration_ = {},
+ optional<Duration> delay_ = {})
+ : duration(std::move(duration_)),
+ delay(std::move(delay_)) {}
- return options;
+ TransitionOptions reverseMerge(const TransitionOptions& defaults) const {
+ return {
+ duration ? duration : defaults.duration,
+ delay ? delay : defaults.delay
+ };
}
- explicit operator bool() const {
+ bool isDefined() const {
return duration || delay;
}
};
diff --git a/include/mbgl/style/types.hpp b/include/mbgl/style/types.hpp
index 1f2f5c3105..44b16f16e7 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 {
@@ -92,5 +93,10 @@ enum class IconTextFitType : uint8_t {
Height
};
+enum class LightAnchorType: bool {
+ Map,
+ Viewport
+};
+
} // namespace style
} // namespace mbgl
diff --git a/include/mbgl/style/undefined.hpp b/include/mbgl/style/undefined.hpp
new file mode 100644
index 0000000000..e43f132a80
--- /dev/null
+++ b/include/mbgl/style/undefined.hpp
@@ -0,0 +1,12 @@
+#pragma once
+
+namespace mbgl {
+namespace style {
+
+class Undefined {};
+
+inline bool operator==(const Undefined&, const Undefined&) { return true; }
+inline bool operator!=(const Undefined&, const Undefined&) { return false; }
+
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/util/any.hpp b/include/mbgl/util/any.hpp
new file mode 100644
index 0000000000..eea64b188a
--- /dev/null
+++ b/include/mbgl/util/any.hpp
@@ -0,0 +1,10 @@
+#pragma once
+
+#include <linb/any.hpp>
+
+namespace mbgl {
+
+using linb::any;
+using linb::any_cast;
+
+} // namespace mbgl
diff --git a/include/mbgl/util/async_task.hpp b/include/mbgl/util/async_task.hpp
new file mode 100644
index 0000000000..69746c3eb3
--- /dev/null
+++ b/include/mbgl/util/async_task.hpp
@@ -0,0 +1,24 @@
+#pragma once
+
+#include <mbgl/util/noncopyable.hpp>
+
+#include <memory>
+#include <functional>
+
+namespace mbgl {
+namespace util {
+
+class AsyncTask : private util::noncopyable {
+public:
+ AsyncTask(std::function<void()>&&);
+ ~AsyncTask();
+
+ void send();
+
+private:
+ class Impl;
+ std::unique_ptr<Impl> impl;
+};
+
+} // namespace util
+} // namespace mbgl
diff --git a/include/mbgl/util/chrono.hpp b/include/mbgl/util/chrono.hpp
index 4adf030331..723cd131e3 100644
--- a/include/mbgl/util/chrono.hpp
+++ b/include/mbgl/util/chrono.hpp
@@ -29,7 +29,7 @@ std::string rfc1123(Timestamp);
std::string iso8601(Timestamp);
Timestamp parseTimestamp(const char *);
-
+
Timestamp parseTimestamp(const int32_t timestamp);
// C++17 polyfill
diff --git a/include/mbgl/util/color.hpp b/include/mbgl/util/color.hpp
index b595fdb1d7..300d7fae82 100644
--- a/include/mbgl/util/color.hpp
+++ b/include/mbgl/util/color.hpp
@@ -1,7 +1,6 @@
#pragma once
#include <mbgl/util/optional.hpp>
-#include <mbgl/util/util.hpp>
#include <cassert>
#include <string>
diff --git a/include/mbgl/util/compression.hpp b/include/mbgl/util/compression.hpp
index 5e232187c3..93a3ddb8bc 100644
--- a/include/mbgl/util/compression.hpp
+++ b/include/mbgl/util/compression.hpp
@@ -4,9 +4,9 @@
namespace mbgl {
namespace util {
-
+
std::string compress(const std::string& raw);
std::string decompress(const std::string& raw);
-
+
} // namespace util
} // namespace mbgl
diff --git a/include/mbgl/util/constants.hpp b/include/mbgl/util/constants.hpp
index a5a83287bc..c2250c6f2e 100644
--- a/include/mbgl/util/constants.hpp
+++ b/include/mbgl/util/constants.hpp
@@ -2,7 +2,6 @@
#include <mbgl/util/chrono.hpp>
#include <mbgl/util/unitbezier.hpp>
-#include <mbgl/util/util.hpp>
#include <cmath>
#include <string>
@@ -39,17 +38,19 @@ constexpr double MAX_ZOOM = 25.5;
constexpr float MIN_ZOOM_F = MIN_ZOOM;
constexpr float MAX_ZOOM_F = MAX_ZOOM;
+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 };
-const UnitBezier DEFAULT_TRANSITION_EASE = { 0, 0, 0.25, 1 };
-
+constexpr UnitBezier DEFAULT_TRANSITION_EASE = { 0, 0, 0.25, 1 };
+
constexpr int DEFAULT_RATE_LIMIT_TIMEOUT = 5;
constexpr const char* API_BASE_URL = "https://api.mapbox.com";
-
+
} // namespace util
namespace debug {
diff --git a/include/mbgl/util/convert.hpp b/include/mbgl/util/convert.hpp
index bedb1a4a08..02ec7feef9 100644
--- a/include/mbgl/util/convert.hpp
+++ b/include/mbgl/util/convert.hpp
@@ -10,7 +10,7 @@ namespace util {
template<typename To, typename From, std::size_t Size,
typename = std::enable_if_t<std::is_convertible<From, To>::value>>
MBGL_CONSTEXPR std::array<To, Size> convert(const std::array<From, Size>&from) {
- std::array<To, Size> to {};
+ std::array<To, Size> to {{}};
std::copy(std::begin(from), std::end(from), std::begin(to));
return to;
}
diff --git a/include/mbgl/util/enum.hpp b/include/mbgl/util/enum.hpp
index 48ffda463e..369ca86bfd 100644
--- a/include/mbgl/util/enum.hpp
+++ b/include/mbgl/util/enum.hpp
@@ -11,26 +11,26 @@ namespace mbgl {
template <typename T>
class Enum {
public:
- using Value = std::pair<const T, const char *>;
-
- static const char * toString(T t) {
- auto it = std::find_if(begin, end, [&] (const auto& v) { return t == v.first; });
- assert(it != end); return it->second;
- }
-
- static optional<T> toEnum(const std::string& s) {
- auto it = std::find_if(begin, end, [&] (const auto& v) { return s == v.second; });
- return it == end ? optional<T>() : it->first;
- }
-
-private:
- static const Value* begin;
- static const Value* end;
+ static const char * toString(T);
+ static optional<T> toEnum(const std::string&);
};
-#define MBGL_DEFINE_ENUM(type, strings...) \
-const constexpr Enum<type>::Value type##_names[] = strings; \
-template <> const Enum<type>::Value* Enum<type>::begin = std::begin(type##_names); \
-template <> const Enum<type>::Value* Enum<type>::end = std::end(type##_names)
+#define MBGL_DEFINE_ENUM(T, values...) \
+ \
+static const constexpr std::pair<const T, const char *> T##_names[] = values; \
+ \
+template <> \
+const char * Enum<T>::toString(T t) { \
+ auto it = std::find_if(std::begin(T##_names), std::end(T##_names), \
+ [&] (const auto& v) { return t == v.first; }); \
+ assert(it != std::end(T##_names)); return it->second; \
+} \
+ \
+template <> \
+optional<T> Enum<T>::toEnum(const std::string& s) { \
+ auto it = std::find_if(std::begin(T##_names), std::end(T##_names), \
+ [&] (const auto& v) { return s == v.second; }); \
+ return it == std::end(T##_names) ? optional<T>() : it->first; \
+}
} // namespace mbgl
diff --git a/include/mbgl/util/event.hpp b/include/mbgl/util/event.hpp
index 7ad3d914e8..5fe0baae3c 100644
--- a/include/mbgl/util/event.hpp
+++ b/include/mbgl/util/event.hpp
@@ -40,7 +40,7 @@ struct EventPermutation {
};
constexpr EventSeverity disabledEventSeverities[] = {
-#ifdef NDEBUG
+#ifndef NDEBUG
EventSeverity(-1) // Avoid zero size array
#else
EventSeverity::Debug
diff --git a/include/mbgl/util/exception.hpp b/include/mbgl/util/exception.hpp
index 46de8528c7..a9804e96c5 100644
--- a/include/mbgl/util/exception.hpp
+++ b/include/mbgl/util/exception.hpp
@@ -20,5 +20,20 @@ struct MisuseException : Exception {
MisuseException(const std::string &msg) : Exception(msg) {}
};
+struct StyleParseException : Exception {
+ StyleParseException(const char *msg) : Exception(msg) {}
+ StyleParseException(const std::string &msg) : Exception(msg) {}
+};
+
+struct StyleLoadException : Exception {
+ StyleLoadException(const char *msg) : Exception(msg) {}
+ StyleLoadException(const std::string &msg) : Exception(msg) {}
+};
+
+struct NotFoundException : Exception {
+ NotFoundException(const char *msg) : Exception(msg) {}
+ NotFoundException(const std::string &msg) : Exception(msg) {}
+};
+
} // namespace util
} // namespace mbgl
diff --git a/include/mbgl/util/feature.hpp b/include/mbgl/util/feature.hpp
index b72aa15ddd..4eeceda944 100644
--- a/include/mbgl/util/feature.hpp
+++ b/include/mbgl/util/feature.hpp
@@ -12,4 +12,21 @@ using PropertyMap = mapbox::geometry::property_map;
using FeatureIdentifier = mapbox::geometry::identifier;
using Feature = mapbox::geometry::feature<double>;
+template <class T>
+optional<T> numericValue(const Value& value) {
+ return value.match(
+ [] (uint64_t t) {
+ return optional<T>(t);
+ },
+ [] (int64_t t) {
+ return optional<T>(t);
+ },
+ [] (double t) {
+ return optional<T>(t);
+ },
+ [] (auto) {
+ return optional<T>();
+ });
+}
+
} // namespace mbgl
diff --git a/include/mbgl/util/geo.hpp b/include/mbgl/util/geo.hpp
index 9dca10eb84..6d725b102b 100644
--- a/include/mbgl/util/geo.hpp
+++ b/include/mbgl/util/geo.hpp
@@ -1,5 +1,6 @@
#pragma once
+#include <mbgl/math/clamp.hpp>
#include <mbgl/math/wrap.hpp>
#include <mbgl/util/constants.hpp>
@@ -9,6 +10,7 @@
#include <mapbox/geometry/box.hpp>
#include <cmath>
+#include <stdexcept>
namespace mbgl {
@@ -20,68 +22,63 @@ using ScreenLineString = mapbox::geometry::line_string<double>;
using ScreenBox = mapbox::geometry::box<double>;
class LatLng {
-public:
- struct null {};
-
- double latitude;
- double longitude;
+private:
+ double lat;
+ double lon;
+public:
enum WrapMode : bool { Unwrapped, Wrapped };
- LatLng(null) : latitude(std::numeric_limits<double>::quiet_NaN()), longitude(latitude) {}
-
- LatLng(double lat = 0, double lon = 0, WrapMode mode = Unwrapped)
- : latitude(lat), longitude(lon) { if (mode == Wrapped) wrap(); }
-
- LatLng wrapped() const { return { latitude, longitude, Wrapped }; }
+ LatLng(double lat_ = 0, double lon_ = 0, WrapMode mode = Unwrapped)
+ : lat(lat_), lon(lon_) {
+ if (std::isnan(lat)) {
+ throw std::domain_error("latitude must not be NaN");
+ }
+ if (std::isnan(lon)) {
+ throw std::domain_error("longitude must not be NaN");
+ }
+ if (std::abs(lat) > 90.0) {
+ throw std::domain_error("latitude must be between -90 and 90");
+ }
+ if (!std::isfinite(lon)) {
+ throw std::domain_error("longitude must not be infinite");
+ }
+ if (mode == Wrapped) {
+ wrap();
+ }
+ }
+
+ double latitude() const { return lat; }
+ double longitude() const { return lon; }
+
+ LatLng wrapped() const { return { lat, lon, Wrapped }; }
void wrap() {
- longitude = util::wrap(longitude, -util::LONGITUDE_MAX, util::LONGITUDE_MAX);
+ lon = util::wrap(lon, -util::LONGITUDE_MAX, util::LONGITUDE_MAX);
}
// If the distance from start to end longitudes is between half and full
// world, unwrap the start longitude to ensure the shortest path is taken.
void unwrapForShortestPath(const LatLng& end) {
- const double delta = std::abs(end.longitude - longitude);
+ const double delta = std::abs(end.lon - lon);
if (delta < util::LONGITUDE_MAX || delta > util::DEGREES_MAX) return;
- if (longitude > 0 && end.longitude < 0) longitude -= util::DEGREES_MAX;
- else if (longitude < 0 && end.longitude > 0) longitude += util::DEGREES_MAX;
- }
-
- explicit operator bool() const {
- return !(std::isnan(latitude) || std::isnan(longitude));
+ if (lon > 0 && end.lon < 0) lon -= util::DEGREES_MAX;
+ else if (lon < 0 && end.lon > 0) lon += util::DEGREES_MAX;
}
// Constructs a LatLng object with the top left position of the specified tile.
LatLng(const CanonicalTileID& id);
LatLng(const UnwrappedTileID& id);
-};
-constexpr bool operator==(const LatLng& a, const LatLng& b) {
- return a.latitude == b.latitude && a.longitude == b.longitude;
-}
-
-constexpr bool operator!=(const LatLng& a, const LatLng& b) {
- return !(a == b);
-}
-
-class ProjectedMeters {
-public:
- double northing;
- double easting;
-
- ProjectedMeters(double n = 0, double e = 0)
- : northing(n), easting(e) {}
+ friend bool operator==(const LatLng& a, const LatLng& b) {
+ return a.lat == b.lat && a.lon == b.lon;
+ }
- explicit operator bool() const {
- return !(std::isnan(northing) || std::isnan(easting));
+ friend bool operator!=(const LatLng& a, const LatLng& b) {
+ return !(a == b);
}
};
-constexpr bool operator==(const ProjectedMeters& a, const ProjectedMeters& b) {
- return a.northing == b.northing && a.easting == b.easting;
-}
-
class LatLngBounds {
public:
// Return a bounds covering the entire (unwrapped) world.
@@ -111,10 +108,14 @@ public:
// Constructs a LatLngBounds object with the tile's exact boundaries.
LatLngBounds(const CanonicalTileID&);
- double south() const { return sw.latitude; }
- double west() const { return sw.longitude; }
- double north() const { return ne.latitude; }
- double east() const { return ne.longitude; }
+ bool valid() const {
+ return (sw.latitude() <= ne.latitude()) && (sw.longitude() <= ne.longitude());
+ }
+
+ double south() const { return sw.latitude(); }
+ double west() const { return sw.longitude(); }
+ double north() const { return ne.latitude(); }
+ double east() const { return ne.longitude(); }
LatLng southwest() const { return sw; }
LatLng northeast() const { return ne; }
@@ -122,15 +123,25 @@ public:
LatLng northwest() const { return LatLng(north(), west()); }
LatLng center() const {
- return LatLng((sw.latitude + ne.latitude) / 2,
- (sw.longitude + ne.longitude) / 2);
+ return LatLng((sw.latitude() + ne.latitude()) / 2,
+ (sw.longitude() + ne.longitude()) / 2);
+ }
+
+ LatLng constrain(const LatLng& p) const {
+ if (contains(p)) {
+ return p;
+ }
+ return LatLng {
+ util::clamp(p.latitude(), sw.latitude(), ne.latitude()),
+ util::clamp(p.longitude(), sw.longitude(), ne.longitude())
+ };
}
void extend(const LatLng& point) {
- if (point.latitude < sw.latitude) sw.latitude = point.latitude;
- if (point.latitude > ne.latitude) ne.latitude = point.latitude;
- if (point.longitude < sw.longitude) sw.longitude = point.longitude;
- if (point.longitude > ne.longitude) ne.longitude = point.longitude;
+ sw = LatLng(std::min(point.latitude(), sw.latitude()),
+ std::min(point.longitude(), sw.longitude()));
+ ne = LatLng(std::max(point.latitude(), ne.latitude()),
+ std::max(point.longitude(), ne.longitude()));
}
void extend(const LatLngBounds& bounds) {
@@ -139,22 +150,22 @@ public:
}
bool isEmpty() const {
- return sw.latitude > ne.latitude ||
- sw.longitude > ne.longitude;
+ return sw.latitude() > ne.latitude() ||
+ sw.longitude() > ne.longitude();
}
bool contains(const LatLng& point) const {
- return (point.latitude >= sw.latitude &&
- point.latitude <= ne.latitude &&
- point.longitude >= sw.longitude &&
- point.longitude <= ne.longitude);
+ return (point.latitude() >= sw.latitude() &&
+ point.latitude() <= ne.latitude() &&
+ point.longitude() >= sw.longitude() &&
+ point.longitude() <= ne.longitude());
}
bool intersects(const LatLngBounds area) const {
- return (area.ne.latitude > sw.latitude &&
- area.sw.latitude < ne.latitude &&
- area.ne.longitude > sw.longitude &&
- area.sw.longitude < ne.longitude);
+ return (area.ne.latitude() > sw.latitude() &&
+ area.sw.latitude() < ne.latitude() &&
+ area.ne.longitude() > sw.longitude() &&
+ area.sw.longitude() < ne.longitude());
}
private:
@@ -164,17 +175,14 @@ private:
LatLngBounds(LatLng sw_, LatLng ne_)
: sw(std::move(sw_)), ne(std::move(ne_)) {}
- friend constexpr bool operator==(const LatLngBounds&, const LatLngBounds&);
- friend constexpr bool operator!=(const LatLngBounds&, const LatLngBounds&);
-};
-
-constexpr bool operator==(const LatLngBounds& a, const LatLngBounds& b) {
- return a.sw == b.sw && a.ne == b.ne;
-}
+ friend bool operator==(const LatLngBounds& a, const LatLngBounds& b) {
+ return a.sw == b.sw && a.ne == b.ne;
+ }
-constexpr bool operator!=(const LatLngBounds& a, const LatLngBounds& b) {
- return !(a == b);
-}
+ friend bool operator!=(const LatLngBounds& a, const LatLngBounds& b) {
+ return !(a == b);
+ }
+};
// Determines the orientation of the map.
enum class NorthOrientation : uint8_t {
@@ -186,36 +194,60 @@ enum class NorthOrientation : uint8_t {
/// The distance on each side between a rectangle and a rectangle within.
class EdgeInsets {
-public:
- double top = 0; ///< Number of pixels inset from the top edge.
- double left = 0; ///< Number of pixels inset from the left edge.
- double bottom = 0; ///< Number of pixels inset from the bottom edge.
- double right = 0; ///< Number of pixels inset from the right edge.
-
- EdgeInsets() {}
-
- EdgeInsets(const double t, const double l, const double b, const double r)
- : top(t), left(l), bottom(b), right(r) {}
+private:
+ double _top; // Number of pixels inset from the top edge.
+ double _left; // Number of pixels inset from the left edge.
+ double _bottom; // Number of pixels inset from the bottom edge.
+ double _right; // Number of pixels inset from the right edge.
- explicit operator bool() const {
- return !(std::isnan(top) || std::isnan(left) || std::isnan(bottom) || std::isnan(right))
- && (top || left || bottom || right);
+public:
+ EdgeInsets(double t_ = 0, double l_ = 0, double b_ = 0, double r_ = 0)
+ : _top(t_), _left(l_), _bottom(b_), _right(r_) {
+ if (std::isnan(_top)) {
+ throw std::domain_error("top must not be NaN");
+ }
+ if (std::isnan(_left)) {
+ throw std::domain_error("left must not be NaN");
+ }
+ if (std::isnan(_bottom)) {
+ throw std::domain_error("bottom must not be NaN");
+ }
+ if (std::isnan(_right)) {
+ throw std::domain_error("right must not be NaN");
+ }
+ }
+
+ double top() const { return _top; }
+ double left() const { return _left; }
+ double bottom() const { return _bottom; }
+ double right() const { return _right; }
+
+ bool isFlush() const {
+ return _top == 0 && _left == 0 && _bottom == 0 && _right == 0;
}
void operator+=(const EdgeInsets& o) {
- top += o.top;
- left += o.left;
- bottom += o.bottom;
- right += o.right;
+ _top += o._top;
+ _left += o._left;
+ _bottom += o._bottom;
+ _right += o._right;
}
EdgeInsets operator+(const EdgeInsets& o) const {
return {
- top + o.top, left + o.left, bottom + o.bottom, right + o.right,
+ _top + o._top, _left + o._left, _bottom + o._bottom, _right + o._right,
};
}
ScreenCoordinate getCenter(uint16_t width, uint16_t height) const;
+
+ friend bool operator==(const EdgeInsets& a, const EdgeInsets& b) {
+ return a._top == b._top && a._left == b._left && a._bottom == b._bottom && a._right == b._right;
+ }
+
+ friend bool operator!=(const EdgeInsets& a, const EdgeInsets& b) {
+ return !(a == b);
+ }
};
} // namespace mbgl
diff --git a/include/mbgl/util/ignore.hpp b/include/mbgl/util/ignore.hpp
new file mode 100644
index 0000000000..577bcf4d91
--- /dev/null
+++ b/include/mbgl/util/ignore.hpp
@@ -0,0 +1,26 @@
+#pragma once
+
+#include <initializer_list>
+
+namespace mbgl {
+namespace util {
+
+// Accept any number of parameters of any types, and do nothing with them.
+// Useful for providing a context for parameter pack expansion where a legal
+// expansion context is not otherwise available.
+//
+// See https://github.com/mapbox/cpp/blob/master/C%2B%2B%20Structural%20Metaprogramming.md
+// for more details.
+//
+template <class... Ts> void ignore(Ts&&...) {}
+
+// std::initializer_list overload, for situations where you need sequenced
+// modifications.
+//
+template <class T> void ignore(const std::initializer_list<T>&) {}
+
+// Handle the zero-argument case.
+inline void ignore(const std::initializer_list<int>&) {}
+
+} // namespace util
+} // namespace mbgl
diff --git a/include/mbgl/util/image.hpp b/include/mbgl/util/image.hpp
index 1d84d4824a..cb28f3da8d 100644
--- a/include/mbgl/util/image.hpp
+++ b/include/mbgl/util/image.hpp
@@ -1,6 +1,7 @@
#pragma once
#include <mbgl/util/noncopyable.hpp>
+#include <mbgl/util/geometry.hpp>
#include <mbgl/util/size.hpp>
#include <string>
@@ -24,33 +25,116 @@ public:
: size(std::move(size_)),
data(std::make_unique<uint8_t[]>(bytes())) {}
+ Image(Size size_, const uint8_t* srcData, std::size_t srcLength)
+ : size(std::move(size_)) {
+ if (srcLength != bytes()) {
+ throw std::invalid_argument("mismatched image size");
+ }
+ data = std::make_unique<uint8_t[]>(bytes());
+ std::copy(srcData, srcData + srcLength, data.get());
+ }
+
Image(Size size_, std::unique_ptr<uint8_t[]> data_)
: size(std::move(size_)),
data(std::move(data_)) {}
Image(Image&& o)
: size(o.size),
- data(std::move(o.data)) {}
+ data(std::move(o.data)) {
+ o.size.width = o.size.height = 0;
+ }
Image& operator=(Image&& o) {
size = o.size;
data = std::move(o.data);
+ o.size.width = o.size.height = 0;
return *this;
}
- bool operator==(const Image& rhs) const {
- return size == rhs.size &&
- std::equal(data.get(), data.get() + bytes(), rhs.data.get(),
- rhs.data.get() + rhs.bytes());
+ friend bool operator==(const Image& lhs, const Image& rhs) {
+ return std::equal(lhs.data.get(), lhs.data.get() + lhs.bytes(),
+ rhs.data.get(), rhs.data.get() + rhs.bytes());
+ }
+
+ friend bool operator!=(const Image& lhs, const Image& rhs) {
+ return !(lhs == rhs);
}
bool valid() const {
- return size && data.get() != nullptr;
+ return !size.isEmpty() && data.get() != nullptr;
+ }
+
+ template <typename T = Image>
+ T clone() const {
+ T copy_(size);
+ std::copy(data.get(), data.get() + bytes(), copy_.data.get());
+ return copy_;
}
size_t stride() const { return channels * size.width; }
size_t bytes() const { return stride() * size.height; }
+ void fill(uint8_t value) {
+ 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));
+ }
+
+ // 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");
+ }
+
+ if (!dstImg.valid()) {
+ throw std::invalid_argument("invalid destination for image copy");
+ }
+
+ if (size.width > srcImg.size.width ||
+ size.height > srcImg.size.height ||
+ srcPt.x > srcImg.size.width - size.width ||
+ srcPt.y > srcImg.size.height - size.height) {
+ throw std::out_of_range("out of range source coordinates for image copy");
+ }
+
+ if (size.width > dstImg.size.width ||
+ size.height > dstImg.size.height ||
+ dstPt.x > dstImg.size.width - size.width ||
+ dstPt.y > dstImg.size.height - size.height) {
+ throw std::out_of_range("out of range destination coordinates for image copy");
+ }
+
+ const uint8_t* srcData = srcImg.data.get();
+ uint8_t* dstData = dstImg.data.get();
+
+ assert(srcData != dstData);
+
+ for (uint32_t y = 0; y < size.height; y++) {
+ const std::size_t srcOffset = (srcPt.y + y) * srcImg.stride() + srcPt.x * channels;
+ const std::size_t dstOffset = (dstPt.y + y) * dstImg.stride() + dstPt.x * channels;
+ std::copy(srcData + srcOffset,
+ srcData + srcOffset + size.width * channels,
+ dstData + dstOffset);
+ }
+ }
+
Size size;
static constexpr size_t channels = Mode == ImageAlphaMode::Exclusive ? 1 : 4;
std::unique_ptr<uint8_t[]> data;
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
new file mode 100644
index 0000000000..fd0b931d36
--- /dev/null
+++ b/include/mbgl/util/indexed_tuple.hpp
@@ -0,0 +1,53 @@
+#pragma once
+
+#include <mbgl/util/type_list.hpp>
+
+#include <type_traits>
+#include <tuple>
+
+namespace mbgl {
+
+template <class T, class... Ts>
+struct TypeIndex;
+
+template <class T, class... Ts>
+struct TypeIndex<T, T, Ts...> : std::integral_constant<std::size_t, 0> {};
+
+template <class T, class U, class... Ts>
+struct TypeIndex<T, U, Ts...> : std::integral_constant<std::size_t, 1 + TypeIndex<T, Ts...>::value> {};
+
+template <class...> class IndexedTuple;
+
+// A tuple of Ts, where individual members can be accessed via `t.get<I>()` for I ∈ Is.
+//
+// See https://github.com/mapbox/cpp/blob/master/C%2B%2B%20Structural%20Metaprogramming.md
+// for motivation.
+//
+template <class... Is, class... Ts>
+class IndexedTuple<TypeList<Is...>, TypeList<Ts...>> : public std::tuple<Ts...> {
+public:
+ static_assert(sizeof...(Is) == sizeof...(Ts), "IndexedTuple size mismatch");
+
+ using std::tuple<Ts...>::tuple;
+
+ template <class I>
+ auto& get() {
+ return std::get<TypeIndex<I, Is...>::value>(*this);
+ }
+
+ template <class I>
+ const auto& get() const {
+ return std::get<TypeIndex<I, Is...>::value>(*this);
+ }
+
+ template <class... Js, class... Us>
+ IndexedTuple<TypeList<Is..., Js...>, TypeList<Ts..., Us...>>
+ concat(const IndexedTuple<TypeList<Js...>, TypeList<Us...>>& other) const {
+ return IndexedTuple<TypeList<Is..., Js...>, TypeList<Ts..., Us...>> {
+ get<Is>()...,
+ other.template get<Js>()...
+ };
+ }
+};
+
+} // namespace mbgl
diff --git a/include/mbgl/util/interpolate.hpp b/include/mbgl/util/interpolate.hpp
new file mode 100644
index 0000000000..6738987598
--- /dev/null
+++ b/include/mbgl/util/interpolate.hpp
@@ -0,0 +1,105 @@
+#pragma once
+
+#include <mbgl/util/color.hpp>
+#include <mbgl/util/range.hpp>
+#include <mbgl/style/position.hpp>
+
+#include <array>
+#include <vector>
+#include <string>
+#include <type_traits>
+#include <utility>
+
+namespace mbgl {
+namespace util {
+
+float interpolationFactor(float base, Range<float> range, float z);
+
+template <class T, class Enabled = void>
+struct Interpolator;
+
+template <typename T>
+T interpolate(const T& a, const T& b, const double t) {
+ return Interpolator<T>()(a, b, t);
+}
+
+
+template <class T, class Enabled>
+struct Interpolator {
+ T operator()(const T& a, const T& b, const double t) const {
+ return a * (1.0 - t) + b * t;
+ }
+};
+
+template <class T, std::size_t N>
+struct Interpolator<std::array<T, N>> {
+private:
+ using Array = std::array<T, N>;
+
+ template <std::size_t... I>
+ Array operator()(const Array& a, const Array& b, const double t, std::index_sequence<I...>) {
+ return {{ interpolate(a[I], b[I], t)... }};
+ }
+
+public:
+ Array operator()(const Array& a, const Array& b, const double t) {
+ return operator()(a, b, t, std::make_index_sequence<N>());
+ }
+};
+
+template <>
+struct Interpolator<style::Position> {
+public:
+ style::Position operator()(const style::Position& a, const style::Position& b, const double t) {
+ auto pos = style::Position();
+ auto interpolated = interpolate(a.getCartesian(), b.getCartesian(), t);
+ pos.setCartesian(interpolated);
+ return { pos };
+ }
+};
+
+template <>
+struct Interpolator<Color> {
+public:
+ Color operator()(const Color& a, const Color& b, const double t) {
+ return {
+ interpolate(a.r, b.r, t),
+ interpolate(a.g, b.g, t),
+ interpolate(a.b, b.b, t),
+ interpolate(a.a, b.a, t)
+ };
+ }
+};
+
+struct Uninterpolated {
+ template <class T>
+ T operator()(const T& a, const T&, const double) const {
+ return a;
+ }
+};
+
+template <>
+struct Interpolator<bool>
+ : Uninterpolated {};
+
+template <class T>
+struct Interpolator<T, typename std::enable_if_t<std::is_enum<T>::value>>
+ : Uninterpolated {};
+
+template <>
+struct Interpolator<std::string>
+ : Uninterpolated {};
+
+template <class T>
+struct Interpolator<std::vector<T>>
+ : Uninterpolated {};
+
+template <class T>
+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/premultiply.hpp b/include/mbgl/util/premultiply.hpp
new file mode 100644
index 0000000000..532c7cb11d
--- /dev/null
+++ b/include/mbgl/util/premultiply.hpp
@@ -0,0 +1,12 @@
+#pragma once
+
+#include <mbgl/util/image.hpp>
+
+namespace mbgl {
+namespace util {
+
+PremultipliedImage premultiply(UnassociatedImage&&);
+UnassociatedImage unpremultiply(PremultipliedImage&&);
+
+} // namespace util
+} // namespace mbgl
diff --git a/include/mbgl/util/projection.hpp b/include/mbgl/util/projection.hpp
index 9ca3cd4ab5..3cc1146513 100644
--- a/include/mbgl/util/projection.hpp
+++ b/include/mbgl/util/projection.hpp
@@ -5,9 +5,36 @@
#include <mbgl/util/geometry.hpp>
#include <mbgl/math/clamp.hpp>
-
namespace mbgl {
+class ProjectedMeters {
+private:
+ double _northing; // Distance measured northwards.
+ double _easting; // Distance measured eastwards.
+
+public:
+ ProjectedMeters(double n_ = 0, double e_ = 0)
+ : _northing(n_), _easting(e_) {
+ if (std::isnan(_northing)) {
+ throw std::domain_error("northing must not be NaN");
+ }
+ if (std::isnan(_easting)) {
+ throw std::domain_error("easting must not be NaN");
+ }
+ }
+
+ double northing() const { return _northing; }
+ double easting() const { return _easting; }
+
+ friend bool operator==(const ProjectedMeters& a, const ProjectedMeters& b) {
+ return a._northing == b._northing && a._easting == b._easting;
+ }
+
+ friend bool operator!=(const ProjectedMeters& a, const ProjectedMeters& b) {
+ return !(a == b);
+ }
+};
+
// Spherical Mercator projection
// http://docs.openlayers.org/library/spherical_mercator.html
class Projection {
@@ -25,8 +52,8 @@ public:
}
static ProjectedMeters projectedMetersForLatLng(const LatLng& latLng) {
- const double constrainedLatitude = util::clamp(latLng.latitude, -util::LATITUDE_MAX, util::LATITUDE_MAX);
- const double constrainedLongitude = util::clamp(latLng.longitude, -util::LONGITUDE_MAX, util::LONGITUDE_MAX);
+ const double constrainedLatitude = util::clamp(latLng.latitude(), -util::LATITUDE_MAX, util::LATITUDE_MAX);
+ const double constrainedLongitude = util::clamp(latLng.longitude(), -util::LONGITUDE_MAX, util::LONGITUDE_MAX);
const double m = 1 - 1e-15;
const double f = util::clamp(std::sin(util::DEG2RAD * constrainedLatitude), -m, m);
@@ -38,8 +65,8 @@ public:
}
static LatLng latLngForProjectedMeters(const ProjectedMeters& projectedMeters) {
- double latitude = (2 * std::atan(std::exp(projectedMeters.northing / util::EARTH_RADIUS_M)) - (M_PI / 2.0)) * util::RAD2DEG;
- double longitude = projectedMeters.easting * util::RAD2DEG / util::EARTH_RADIUS_M;
+ double latitude = (2 * std::atan(std::exp(projectedMeters.northing() / util::EARTH_RADIUS_M)) - (M_PI / 2.0)) * util::RAD2DEG;
+ double longitude = projectedMeters.easting() * util::RAD2DEG / util::EARTH_RADIUS_M;
latitude = util::clamp(latitude, -util::LATITUDE_MAX, util::LATITUDE_MAX);
longitude = util::clamp(longitude, -util::LONGITUDE_MAX, util::LONGITUDE_MAX);
@@ -49,8 +76,8 @@ 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))
+ 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;
}
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..14352ca823 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 {
@@ -63,15 +63,6 @@ public:
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);
- }
-
class Impl;
private:
diff --git a/include/mbgl/util/size.hpp b/include/mbgl/util/size.hpp
index 1af85bcff5..12c0ad056b 100644
--- a/include/mbgl/util/size.hpp
+++ b/include/mbgl/util/size.hpp
@@ -7,18 +7,25 @@ namespace mbgl {
class Size {
public:
- constexpr Size() : width(0), height(0) {
- }
+ constexpr Size() = default;
constexpr Size(const uint32_t width_, const uint32_t height_) : width(width_), height(height_) {
}
- constexpr explicit operator bool() const {
- return width > 0 && height > 0;
+ 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;
}
- uint32_t width;
- uint32_t height;
+ uint32_t width = 0;
+ uint32_t height = 0;
};
constexpr inline bool operator==(const Size& a, const Size& b) {
diff --git a/include/mbgl/util/string.hpp b/include/mbgl/util/string.hpp
index 6c33866a0b..82d317c620 100644
--- a/include/mbgl/util/string.hpp
+++ b/include/mbgl/util/string.hpp
@@ -6,8 +6,7 @@
#include <cstdlib>
#include <exception>
-#include <mbgl/util/dtoa.hpp>
-
+// Polyfill needed by Qt when building for Android with GCC
#if defined(__ANDROID__) && defined(__GLIBCXX__)
namespace std {
@@ -46,17 +45,9 @@ inline std::string toString(uint8_t num) {
return std::to_string(unsigned(num));
}
-inline std::string toString(float num) {
- return dtoa(num);
-}
-
-inline std::string toString(double num) {
- return dtoa(num);
-}
-
-inline std::string toString(long double num) {
- return dtoa(num);
-}
+std::string toString(float);
+std::string toString(double);
+std::string toString(long double);
inline std::string toString(std::exception_ptr error) {
assert(error);
diff --git a/include/mbgl/util/tileset.hpp b/include/mbgl/util/tileset.hpp
index 1f28a5039a..2fa19d3f53 100644
--- a/include/mbgl/util/tileset.hpp
+++ b/include/mbgl/util/tileset.hpp
@@ -13,11 +13,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, 22 },
+ 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/type_list.hpp b/include/mbgl/util/type_list.hpp
new file mode 100644
index 0000000000..4a5e95c8a4
--- /dev/null
+++ b/include/mbgl/util/type_list.hpp
@@ -0,0 +1,40 @@
+#pragma once
+
+#include <type_traits>
+#include <tuple>
+
+namespace mbgl {
+
+template <class...>
+class TypeList {};
+
+namespace detail {
+
+template <class, class>
+struct TypeCons;
+
+template <class T, class... Ts>
+struct TypeCons<T, TypeList<Ts...>> {
+ using Type = TypeList<T, Ts...>;
+};
+
+template <class, template <class> class>
+struct TypeFilter;
+
+template <template <class> class Predicate>
+struct TypeFilter<TypeList<>, Predicate> {
+ using Type = TypeList<>;
+};
+
+template <template <class> class Predicate, class T, class... Ts>
+struct TypeFilter<TypeList<T, Ts...>, Predicate> {
+ using Tail = typename TypeFilter<TypeList<Ts...>, Predicate>::Type;
+ using Type = std::conditional_t<Predicate<T>::value, typename TypeCons<T, Tail>::Type, Tail>;
+};
+
+} // namespace detail
+
+template <class TypeList, template <class> class Predicate>
+using FilteredTypeList = typename detail::TypeFilter<TypeList, Predicate>::Type;
+
+} // namespace mbgl
diff --git a/include/mbgl/util/unitbezier.hpp b/include/mbgl/util/unitbezier.hpp
index 16e356ac6e..6e644e2d1f 100644
--- a/include/mbgl/util/unitbezier.hpp
+++ b/include/mbgl/util/unitbezier.hpp
@@ -25,8 +25,6 @@
#pragma once
-#include <mbgl/util/util.hpp>
-
#include <cmath>
namespace mbgl {
@@ -34,13 +32,13 @@ namespace util {
struct UnitBezier {
// Calculate the polynomial coefficients, implicit first and last control points are (0,0) and (1,1).
- MBGL_CONSTEXPR UnitBezier(double p1x, double p1y, double p2x, double p2y)
+ 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/version.hpp b/include/mbgl/util/version.hpp
deleted file mode 100644
index 4ce8b98f40..0000000000
--- a/include/mbgl/util/version.hpp
+++ /dev/null
@@ -1,20 +0,0 @@
-// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.
-#pragma once
-
-#define MBGL_VERSION 0x30402
-#define MBGL_VERSION_STRING "3.4.2"
-#define MBGL_VERSION_MAJOR 3
-#define MBGL_VERSION_MINOR 4
-#define MBGL_VERSION_PATCH 2
-#define MBGL_VERSION_REV "2fae03b4"
-
-namespace mbgl {
-namespace version {
-
-extern const int major, minor, patch;
-extern const char *revision;
-extern const char *string;
-extern const unsigned int number;
-
-} // namespace version
-} // namespace mbgl
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