summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/mbgl/annotation/annotation.hpp46
-rw-r--r--include/mbgl/annotation/point_annotation.hpp18
-rw-r--r--include/mbgl/annotation/shape_annotation.hpp54
-rw-r--r--include/mbgl/gl/gl.hpp4
-rw-r--r--include/mbgl/gl/gl_helper.hpp4
-rw-r--r--include/mbgl/gl/gl_values.hpp108
-rw-r--r--include/mbgl/map/camera.hpp4
-rw-r--r--include/mbgl/map/map.hpp47
-rw-r--r--include/mbgl/map/mode.hpp17
-rw-r--r--include/mbgl/map/update.hpp9
-rw-r--r--include/mbgl/map/view.hpp5
-rw-r--r--include/mbgl/platform/darwin/settings_nsuserdefaults.hpp27
-rw-r--r--include/mbgl/platform/default/glfw_view.hpp5
-rw-r--r--include/mbgl/platform/default/headless_view.hpp4
-rw-r--r--include/mbgl/platform/event.hpp31
-rw-r--r--include/mbgl/platform/log.hpp10
-rw-r--r--include/mbgl/storage/default_file_source.hpp4
-rw-r--r--include/mbgl/storage/file_source.hpp8
-rw-r--r--include/mbgl/storage/offline.hpp10
-rw-r--r--include/mbgl/storage/resource.hpp6
-rw-r--r--include/mbgl/storage/response.hpp2
-rw-r--r--include/mbgl/style/conversion.hpp93
-rw-r--r--include/mbgl/style/conversion/constant.hpp174
-rw-r--r--include/mbgl/style/conversion/filter.hpp150
-rw-r--r--include/mbgl/style/conversion/function.hpp69
-rw-r--r--include/mbgl/style/conversion/geojson.hpp15
-rw-r--r--include/mbgl/style/conversion/layer.hpp208
-rw-r--r--include/mbgl/style/conversion/make_property_setters.hpp133
-rw-r--r--include/mbgl/style/conversion/make_property_setters.hpp.ejs45
-rw-r--r--include/mbgl/style/conversion/property_setter.hpp55
-rw-r--r--include/mbgl/style/conversion/property_value.hpp36
-rw-r--r--include/mbgl/style/conversion/source.hpp123
-rw-r--r--include/mbgl/style/conversion/tileset.hpp67
-rw-r--r--include/mbgl/style/filter.hpp115
-rw-r--r--include/mbgl/style/filter_evaluator.hpp181
-rw-r--r--include/mbgl/style/function.hpp27
-rw-r--r--include/mbgl/style/layer.hpp78
-rw-r--r--include/mbgl/style/layers/background_layer.hpp45
-rw-r--r--include/mbgl/style/layers/circle_layer.hpp62
-rw-r--r--include/mbgl/style/layers/custom_layer.hpp71
-rw-r--r--include/mbgl/style/layers/fill_layer.hpp65
-rw-r--r--include/mbgl/style/layers/layer.hpp.ejs75
-rw-r--r--include/mbgl/style/layers/line_layer.hpp90
-rw-r--r--include/mbgl/style/layers/raster_layer.hpp60
-rw-r--r--include/mbgl/style/layers/symbol_layer.hpp192
-rw-r--r--include/mbgl/style/property_transition.hpp17
-rw-r--r--include/mbgl/style/property_value.hpp38
-rw-r--r--include/mbgl/style/source.hpp63
-rw-r--r--include/mbgl/style/sources/geojson_source.hpp23
-rw-r--r--include/mbgl/style/sources/raster_source.hpp20
-rw-r--r--include/mbgl/style/sources/vector_source.hpp20
-rw-r--r--include/mbgl/style/transition_options.hpp15
-rw-r--r--include/mbgl/style/types.hpp78
-rw-r--r--include/mbgl/util/color.hpp40
-rw-r--r--include/mbgl/util/constants.hpp7
-rw-r--r--include/mbgl/util/convert.hpp17
-rw-r--r--include/mbgl/util/enum.hpp60
-rw-r--r--include/mbgl/util/exception.hpp16
-rw-r--r--include/mbgl/util/font_stack.hpp17
-rw-r--r--include/mbgl/util/geo.hpp24
-rw-r--r--include/mbgl/util/geojson.hpp22
-rw-r--r--include/mbgl/util/geometry.hpp44
-rw-r--r--include/mbgl/util/image.hpp16
-rw-r--r--include/mbgl/util/projection.hpp14
-rw-r--r--include/mbgl/util/range.hpp25
-rw-r--r--include/mbgl/util/tileset.hpp20
-rw-r--r--include/mbgl/util/traits.hpp4
-rw-r--r--include/mbgl/util/unitbezier.hpp39
-rw-r--r--include/mbgl/util/variant.hpp10
69 files changed, 2889 insertions, 412 deletions
diff --git a/include/mbgl/annotation/annotation.hpp b/include/mbgl/annotation/annotation.hpp
index 52916549c9..e8ac9a2fb7 100644
--- a/include/mbgl/annotation/annotation.hpp
+++ b/include/mbgl/annotation/annotation.hpp
@@ -1,11 +1,57 @@
#pragma once
+#include <mbgl/util/geometry.hpp>
+#include <mbgl/util/variant.hpp>
+#include <mbgl/util/color.hpp>
+
#include <cstdint>
#include <vector>
+#include <string>
namespace mbgl {
using AnnotationID = uint32_t;
using AnnotationIDs = std::vector<AnnotationID>;
+class SymbolAnnotation {
+public:
+ Point<double> geometry;
+ std::string icon;
+};
+
+using ShapeAnnotationGeometry = variant<
+ LineString<double>,
+ Polygon<double>,
+ MultiLineString<double>,
+ MultiPolygon<double>>;
+
+class LineAnnotation {
+public:
+ ShapeAnnotationGeometry geometry;
+ float opacity = 1;
+ float width = 1;
+ Color color = Color::black();
+};
+
+class FillAnnotation {
+public:
+ ShapeAnnotationGeometry geometry;
+ float opacity = 1;
+ Color color = Color::black();
+ Color outlineColor = { 0, 0, 0, -1 };
+};
+
+// An annotation whose type and properties are sourced from a style layer.
+class StyleSourcedAnnotation {
+public:
+ ShapeAnnotationGeometry geometry;
+ std::string layerID;
+};
+
+using Annotation = variant<
+ SymbolAnnotation,
+ LineAnnotation,
+ FillAnnotation,
+ StyleSourcedAnnotation>;
+
} // namespace mbgl
diff --git a/include/mbgl/annotation/point_annotation.hpp b/include/mbgl/annotation/point_annotation.hpp
deleted file mode 100644
index c9236c3c04..0000000000
--- a/include/mbgl/annotation/point_annotation.hpp
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma once
-
-#include <mbgl/util/geo.hpp>
-
-#include <string>
-
-namespace mbgl {
-
-class PointAnnotation {
-public:
- PointAnnotation(const LatLng& position_, const std::string& icon_ = "")
- : position(position_.wrapped()), icon(icon_) {}
-
- const LatLng position;
- const std::string icon;
-};
-
-} // namespace mbgl
diff --git a/include/mbgl/annotation/shape_annotation.hpp b/include/mbgl/annotation/shape_annotation.hpp
deleted file mode 100644
index 6e3fe95dd4..0000000000
--- a/include/mbgl/annotation/shape_annotation.hpp
+++ /dev/null
@@ -1,54 +0,0 @@
-#pragma once
-
-#include <mbgl/annotation/annotation.hpp>
-#include <mbgl/style/types.hpp>
-
-#include <mbgl/util/geo.hpp>
-#include <mbgl/util/variant.hpp>
-
-namespace mbgl {
-
-using AnnotationSegment = std::vector<LatLng>;
-using AnnotationSegments = std::vector<AnnotationSegment>;
-
-struct FillAnnotationProperties {
- float opacity = 1;
- Color color = {{ 0, 0, 0, 1 }};
- Color outlineColor = {{ 0, 0, 0, -1 }};
-};
-
-struct LineAnnotationProperties {
- float opacity = 1;
- float width = 1;
- Color color = {{ 0, 0, 0, 1 }};
-};
-
-class ShapeAnnotation {
-public:
- using Properties = variant<
- FillAnnotationProperties, // creates a fill annotation
- LineAnnotationProperties, // creates a line annotation
- std::string>; // creates an annotation whose type and properties are sourced from a style layer
-
- ShapeAnnotation(const AnnotationSegments& segments_, const Properties& properties_)
- : segments(wrapCoordinates(segments_)), properties(properties_) {}
-
- const AnnotationSegments segments;
- const Properties properties;
-
-private:
- AnnotationSegments wrapCoordinates(const AnnotationSegments& segments_) {
- AnnotationSegments wrappedSegments;
- // Wrap all segments coordinates.
- for (const auto& segment_ : segments_) {
- AnnotationSegment wrappedSegment;
- for (const auto& latLng_ : segment_) {
- wrappedSegment.push_back(latLng_.wrapped());
- }
- wrappedSegments.push_back(wrappedSegment);
- }
- return wrappedSegments;
- }
-};
-
-} // namespace mbgl
diff --git a/include/mbgl/gl/gl.hpp b/include/mbgl/gl/gl.hpp
index 6d601d8a23..0f54b96110 100644
--- a/include/mbgl/gl/gl.hpp
+++ b/include/mbgl/gl/gl.hpp
@@ -60,14 +60,14 @@ namespace gl {
#endif
struct Error : ::std::runtime_error {
- inline Error(GLenum err, const std::string &msg) : ::std::runtime_error(msg), code(err) {};
+ Error(GLenum err, const std::string &msg) : ::std::runtime_error(msg), code(err) {};
const GLenum code;
};
void checkError(const char *cmd, const char *file, int line);
#if defined(DEBUG)
-#define MBGL_CHECK_ERROR(cmd) ([&]() { struct __MBGL_C_E { inline ~__MBGL_C_E() { ::mbgl::gl::checkError(#cmd, __FILE__, __LINE__); } } __MBGL_C_E; return cmd; }())
+#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
diff --git a/include/mbgl/gl/gl_helper.hpp b/include/mbgl/gl/gl_helper.hpp
index 893c73e0c3..9d46d018c3 100644
--- a/include/mbgl/gl/gl_helper.hpp
+++ b/include/mbgl/gl/gl_helper.hpp
@@ -6,9 +6,9 @@ namespace gl {
template <typename T>
class Preserve {
public:
- inline Preserve() : data(T::Get()) {
+ Preserve() : data(T::Get()) {
}
- inline ~Preserve() {
+ ~Preserve() {
T::Set(data);
}
diff --git a/include/mbgl/gl/gl_values.hpp b/include/mbgl/gl/gl_values.hpp
index 4204ca8e13..1e05984fbc 100644
--- a/include/mbgl/gl/gl_values.hpp
+++ b/include/mbgl/gl/gl_values.hpp
@@ -5,6 +5,7 @@
#include <array>
#include <mbgl/gl/gl.hpp>
+#include <mbgl/util/color.hpp>
namespace mbgl {
namespace gl {
@@ -12,10 +13,10 @@ namespace gl {
struct ClearDepth {
using Type = GLfloat;
static const Type Default;
- inline static void Set(const Type& value) {
+ static void Set(const Type& value) {
MBGL_CHECK_ERROR(glClearDepth(value));
}
- inline static Type Get() {
+ static Type Get() {
Type clearDepth;
MBGL_CHECK_ERROR(glGetFloatv(GL_DEPTH_CLEAR_VALUE, &clearDepth));
return clearDepth;
@@ -23,29 +24,25 @@ struct ClearDepth {
};
struct ClearColor {
- struct Type { GLfloat r, g, b, a; };
+ using Type = Color;
static const Type Default;
- inline static void Set(const Type& value) {
+ static void Set(const Type& value) {
MBGL_CHECK_ERROR(glClearColor(value.r, value.g, value.b, value.a));
}
- inline static Type Get() {
+ static Type Get() {
GLfloat floats[4];
MBGL_CHECK_ERROR(glGetFloatv(GL_COLOR_CLEAR_VALUE, floats));
return { floats[0], floats[1], floats[2], floats[3] };
}
};
-inline bool operator!=(const ClearColor::Type& a, const ClearColor::Type& b) {
- return a.r != b.r || a.g != b.g || a.b != b.b || a.a != b.a;
-}
-
struct ClearStencil {
using Type = GLint;
static const Type Default;
- inline static void Set(const Type& value) {
+ static void Set(const Type& value) {
MBGL_CHECK_ERROR(glClearStencil(value));
}
- inline static Type Get() {
+ static Type Get() {
Type clearStencil;
MBGL_CHECK_ERROR(glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &clearStencil));
return clearStencil;
@@ -55,10 +52,10 @@ struct ClearStencil {
struct StencilMask {
using Type = GLuint;
static const Type Default;
- inline static void Set(const Type& value) {
+ static void Set(const Type& value) {
MBGL_CHECK_ERROR(glStencilMask(value));
}
- inline static Type Get() {
+ static Type Get() {
GLint stencilMask;
MBGL_CHECK_ERROR(glGetIntegerv(GL_STENCIL_WRITEMASK, &stencilMask));
return stencilMask;
@@ -68,10 +65,10 @@ struct StencilMask {
struct DepthMask {
using Type = GLboolean;
static const Type Default;
- inline static void Set(const Type& value) {
+ static void Set(const Type& value) {
MBGL_CHECK_ERROR(glDepthMask(value));
}
- inline static Type Get() {
+ static Type Get() {
Type depthMask;
MBGL_CHECK_ERROR(glGetBooleanv(GL_DEPTH_WRITEMASK, &depthMask));
return depthMask;
@@ -81,10 +78,10 @@ struct DepthMask {
struct ColorMask {
struct Type { bool r, g, b, a; };
static const Type Default;
- inline static void Set(const Type& value) {
+ static void Set(const Type& value) {
MBGL_CHECK_ERROR(glColorMask(value.r, value.g, value.b, value.a));
}
- inline static Type Get() {
+ static Type Get() {
GLboolean bools[4];
MBGL_CHECK_ERROR(glGetBooleanv(GL_COLOR_WRITEMASK, bools));
return { static_cast<bool>(bools[0]), static_cast<bool>(bools[1]),
@@ -92,17 +89,17 @@ struct ColorMask {
}
};
-inline bool operator!=(const ColorMask::Type& a, const ColorMask::Type& b) {
+constexpr bool operator!=(const ColorMask::Type& a, const ColorMask::Type& b) {
return a.r != b.r || a.g != b.g || a.b != b.b || a.a != b.a;
}
struct StencilFunc {
struct Type { GLenum func; GLint ref; GLuint mask; };
static const Type Default;
- inline static void Set(const Type& value) {
+ static void Set(const Type& value) {
MBGL_CHECK_ERROR(glStencilFunc(value.func, value.ref, value.mask));
}
- inline static Type Get() {
+ static Type Get() {
GLint func, ref, mask;
MBGL_CHECK_ERROR(glGetIntegerv(GL_STENCIL_FUNC, &func));
MBGL_CHECK_ERROR(glGetIntegerv(GL_STENCIL_REF, &ref));
@@ -111,17 +108,17 @@ struct StencilFunc {
}
};
-inline bool operator!=(const StencilFunc::Type& a, const StencilFunc::Type& b) {
+constexpr bool operator!=(const StencilFunc::Type& a, const StencilFunc::Type& b) {
return a.func != b.func || a.ref != b.ref || a.mask != b.mask;
}
struct StencilTest {
using Type = bool;
static const Type Default;
- inline static void Set(const Type& value) {
+ static void Set(const Type& value) {
MBGL_CHECK_ERROR(value ? glEnable(GL_STENCIL_TEST) : glDisable(GL_STENCIL_TEST));
}
- inline static Type Get() {
+ static Type Get() {
Type stencilTest;
MBGL_CHECK_ERROR(stencilTest = glIsEnabled(GL_STENCIL_TEST));
return stencilTest;
@@ -131,10 +128,10 @@ struct StencilTest {
struct StencilOp {
struct Type { GLenum sfail, dpfail, dppass; };
static const Type Default;
- inline static void Set(const Type& value) {
+ static void Set(const Type& value) {
MBGL_CHECK_ERROR(glStencilOp(value.sfail, value.dpfail, value.dppass));
}
- inline static Type Get() {
+ static Type Get() {
GLint sfail, dpfail, dppass;
MBGL_CHECK_ERROR(glGetIntegerv(GL_STENCIL_FAIL, &sfail));
MBGL_CHECK_ERROR(glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &dpfail));
@@ -146,27 +143,27 @@ struct StencilOp {
struct DepthRange {
struct Type { GLfloat near, far; };
static const Type Default;
- inline static void Set(const Type& value) {
+ static void Set(const Type& value) {
MBGL_CHECK_ERROR(glDepthRange(value.near, value.far));
}
- inline static Type Get() {
+ static Type Get() {
GLfloat floats[2];
MBGL_CHECK_ERROR(glGetFloatv(GL_DEPTH_RANGE, floats));
return { floats[0], floats[1] };
}
};
-inline bool operator!=(const DepthRange::Type& a, const DepthRange::Type& b) {
+constexpr bool operator!=(const DepthRange::Type& a, const DepthRange::Type& b) {
return a.near != b.near || a.far != b.far;
}
struct DepthTest {
using Type = bool;
static const Type Default;
- inline static void Set(const Type& value) {
+ static void Set(const Type& value) {
MBGL_CHECK_ERROR(value ? glEnable(GL_DEPTH_TEST) : glDisable(GL_DEPTH_TEST));
}
- inline static Type Get() {
+ static Type Get() {
Type depthTest;
MBGL_CHECK_ERROR(depthTest = glIsEnabled(GL_DEPTH_TEST));
return depthTest;
@@ -176,10 +173,10 @@ struct DepthTest {
struct DepthFunc {
using Type = GLenum;
static const Type Default;
- inline static void Set(const Type& value) {
+ static void Set(const Type& value) {
MBGL_CHECK_ERROR(glDepthFunc(value));
}
- inline static Type Get() {
+ static Type Get() {
GLint depthFunc;
MBGL_CHECK_ERROR(glGetIntegerv(GL_DEPTH_FUNC, &depthFunc));
return depthFunc;
@@ -189,10 +186,10 @@ struct DepthFunc {
struct Blend {
using Type = bool;
static const Type Default;
- inline static void Set(const Type& value) {
+ static void Set(const Type& value) {
MBGL_CHECK_ERROR(value ? glEnable(GL_BLEND) : glDisable(GL_BLEND));
}
- inline static Type Get() {
+ static Type Get() {
Type blend;
MBGL_CHECK_ERROR(blend = glIsEnabled(GL_BLEND));
return blend;
@@ -202,10 +199,10 @@ struct Blend {
struct BlendFunc {
struct Type { GLenum sfactor, dfactor; };
static const Type Default;
- inline static void Set(const Type& value) {
+ static void Set(const Type& value) {
MBGL_CHECK_ERROR(glBlendFunc(value.sfactor, value.dfactor));
}
- inline static Type Get() {
+ static Type Get() {
GLint sfactor, dfactor;
MBGL_CHECK_ERROR(glGetIntegerv(GL_BLEND_SRC_ALPHA, &sfactor));
MBGL_CHECK_ERROR(glGetIntegerv(GL_BLEND_DST_ALPHA, &dfactor));
@@ -213,13 +210,30 @@ struct BlendFunc {
}
};
+constexpr bool operator!=(const BlendFunc::Type& a, const BlendFunc::Type& b) {
+ return a.sfactor != b.sfactor || a.dfactor != b.dfactor;
+}
+
+struct BlendColor {
+ using Type = Color;
+ static const Type Default;
+ inline static void Set(const Type& value) {
+ MBGL_CHECK_ERROR(glBlendColor(value.r, value.g, value.b, value.a));
+ }
+ inline static Type Get() {
+ GLfloat floats[4];
+ MBGL_CHECK_ERROR(glGetFloatv(GL_BLEND_COLOR, floats));
+ return { floats[0], floats[1], floats[2], floats[3] };
+ }
+};
+
struct Program {
using Type = GLuint;
static const Type Default;
- inline static void Set(const Type& value) {
+ static void Set(const Type& value) {
MBGL_CHECK_ERROR(glUseProgram(value));
}
- inline static Type Get() {
+ static Type Get() {
GLint program;
MBGL_CHECK_ERROR(glGetIntegerv(GL_CURRENT_PROGRAM, &program));
return program;
@@ -229,10 +243,10 @@ struct Program {
struct LineWidth {
using Type = GLfloat;
static const Type Default;
- inline static void Set(const Type& value) {
+ static void Set(const Type& value) {
MBGL_CHECK_ERROR(glLineWidth(value));
}
- inline static Type Get() {
+ static Type Get() {
Type lineWidth;
MBGL_CHECK_ERROR(glGetFloatv(GL_LINE_WIDTH, &lineWidth));
return lineWidth;
@@ -242,10 +256,10 @@ struct LineWidth {
struct ActiveTexture {
using Type = GLint;
static const Type Default;
- inline static void Set(const Type& value) {
+ static void Set(const Type& value) {
MBGL_CHECK_ERROR(glActiveTexture(value));
}
- inline static Type Get() {
+ static Type Get() {
Type activeTexture;
MBGL_CHECK_ERROR(glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTexture));
return activeTexture;
@@ -257,10 +271,10 @@ struct ActiveTexture {
struct PixelZoom {
struct Type { GLfloat xfactor; GLfloat yfactor; };
static const Type Default;
- inline static void Set(const Type& value) {
+ static void Set(const Type& value) {
MBGL_CHECK_ERROR(glPixelZoom(value.xfactor, value.yfactor));
}
- inline static Type Get() {
+ static Type Get() {
Type value;
MBGL_CHECK_ERROR(glGetFloatv(GL_ZOOM_X, &value.xfactor));
MBGL_CHECK_ERROR(glGetFloatv(GL_ZOOM_Y, &value.yfactor));
@@ -268,17 +282,17 @@ struct PixelZoom {
}
};
-inline bool operator!=(const PixelZoom::Type& a, const PixelZoom::Type& b) {
+constexpr bool operator!=(const PixelZoom::Type& a, const PixelZoom::Type& b) {
return a.xfactor != b.xfactor || a.yfactor != b.yfactor;
}
struct RasterPos {
using Type = std::array<GLdouble, 4>;
static const Type Default;
- inline static void Set(const Type& value) {
+ static void Set(const Type& value) {
MBGL_CHECK_ERROR(glRasterPos4d(value[0], value[1], value[2], value[3]));
}
- inline static Type Get() {
+ static Type Get() {
Type pos;
MBGL_CHECK_ERROR(glGetDoublev(GL_CURRENT_RASTER_POSITION, pos.data()));
return pos;
diff --git a/include/mbgl/map/camera.hpp b/include/mbgl/map/camera.hpp
index 4520321655..3f39ca2dc9 100644
--- a/include/mbgl/map/camera.hpp
+++ b/include/mbgl/map/camera.hpp
@@ -67,10 +67,10 @@ struct AnimationOptions {
std::function<void()> transitionFinishFn;
/** Creates an animation with no options specified. */
- inline AnimationOptions() {}
+ AnimationOptions() {}
/** Creates an animation with the specified duration. */
- inline AnimationOptions(Duration d)
+ AnimationOptions(Duration d)
: duration(d) {}
};
diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp
index f074a5ae54..0e0c04ff0f 100644
--- a/include/mbgl/map/map.hpp
+++ b/include/mbgl/map/map.hpp
@@ -9,8 +9,7 @@
#include <mbgl/util/feature.hpp>
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/annotation/annotation.hpp>
-#include <mbgl/style/types.hpp>
-#include <mbgl/style/property_transition.hpp>
+#include <mbgl/style/transition_options.hpp>
#include <cstdint>
#include <string>
@@ -23,11 +22,14 @@ namespace mbgl {
class FileSource;
class View;
class SpriteImage;
-class PointAnnotation;
-class ShapeAnnotation;
struct CameraOptions;
struct AnimationOptions;
+namespace style {
+class Source;
+class Layer;
+} // namespace style
+
class Map : private util::noncopyable {
public:
explicit Map(View&, FileSource&,
@@ -49,15 +51,15 @@ public:
void update(Update update);
// Styling
- void addClass(const std::string&, const PropertyTransition& = {});
- void removeClass(const std::string&, const PropertyTransition& = {});
- void setClasses(const std::vector<std::string>&, const PropertyTransition& = {});
+ void addClass(const std::string&, const style::TransitionOptions& = {});
+ void removeClass(const std::string&, const style::TransitionOptions& = {});
+ void setClasses(const std::vector<std::string>&, const style::TransitionOptions& = {});
bool hasClass(const std::string&) const;
std::vector<std::string> getClasses() const;
- void setStyleURL(const std::string& url);
- void setStyleJSON(const std::string& json, const std::string& base = "");
+ void setStyleURL(const std::string&);
+ void setStyleJSON(const std::string&);
std::string getStyleURL() const;
std::string getStyleJSON() const;
@@ -142,26 +144,21 @@ public:
void removeAnnotationIcon(const std::string&);
double getTopOffsetPixelsForAnnotationIcon(const std::string&);
- AnnotationID addPointAnnotation(const PointAnnotation&);
- AnnotationIDs addPointAnnotations(const std::vector<PointAnnotation>&);
-
- AnnotationID addShapeAnnotation(const ShapeAnnotation&);
- AnnotationIDs addShapeAnnotations(const std::vector<ShapeAnnotation>&);
-
- void updatePointAnnotation(AnnotationID, const PointAnnotation&);
-
+ AnnotationID addAnnotation(const Annotation&);
+ void updateAnnotation(AnnotationID, const Annotation&);
void removeAnnotation(AnnotationID);
- void removeAnnotations(const AnnotationIDs&);
AnnotationIDs getPointAnnotationsInBounds(const LatLngBounds&);
- void addCustomLayer(const std::string& id,
- CustomLayerInitializeFunction,
- CustomLayerRenderFunction,
- CustomLayerDeinitializeFunction,
- void* context,
- const char* before = nullptr);
- void removeCustomLayer(const std::string& id);
+ // Sources
+ style::Source* getSource(const std::string& sourceID);
+ void addSource(std::unique_ptr<style::Source>);
+ void removeSource(const std::string& sourceID);
+
+ // Layers
+ style::Layer* getLayer(const std::string& layerID);
+ void addLayer(std::unique_ptr<style::Layer>, const optional<std::string>& beforeLayerID = {});
+ void removeLayer(const std::string& layerID);
// Feature queries
std::vector<Feature> queryRenderedFeatures(const ScreenCoordinate&, const optional<std::vector<std::string>>& layerIDs = {});
diff --git a/include/mbgl/map/mode.hpp b/include/mbgl/map/mode.hpp
index 074bc3f08e..c9b9f60953 100644
--- a/include/mbgl/map/mode.hpp
+++ b/include/mbgl/map/mode.hpp
@@ -1,5 +1,7 @@
#pragma once
+#include <mbgl/util/traits.hpp>
+
#include <cstdint>
namespace mbgl {
@@ -41,24 +43,23 @@ enum class MapDebugOptions : EnumType {
ParseStatus = 1 << 2,
Timestamps = 1 << 3,
Collision = 1 << 4,
- Wireframe = 1 << 5,
+ Overdraw = 1 << 5,
// FIXME: https://github.com/mapbox/mapbox-gl-native/issues/5117
#ifndef GL_ES_VERSION_2_0
StencilClip = 1 << 6,
#endif // GL_ES_VERSION_2_0
};
-inline MapDebugOptions operator| (const MapDebugOptions& lhs, const MapDebugOptions& rhs) {
- return MapDebugOptions(static_cast<EnumType>(lhs) | static_cast<EnumType>(rhs));
+constexpr MapDebugOptions operator|(MapDebugOptions lhs, MapDebugOptions rhs) {
+ return MapDebugOptions(mbgl::underlying_type(lhs) | mbgl::underlying_type(rhs));
}
-inline MapDebugOptions& operator|=(MapDebugOptions& lhs, const MapDebugOptions& rhs) {
- lhs = lhs | rhs;
- return lhs;
+constexpr MapDebugOptions& operator|=(MapDebugOptions& lhs, MapDebugOptions rhs) {
+ return (lhs = lhs | rhs);
}
-inline bool operator& (const MapDebugOptions& lhs, const MapDebugOptions& rhs) {
- return static_cast<EnumType>(lhs) & static_cast<EnumType>(rhs);
+constexpr bool operator&(MapDebugOptions lhs, MapDebugOptions rhs) {
+ return mbgl::underlying_type(lhs) & mbgl::underlying_type(rhs);
}
} // namespace mbgl
diff --git a/include/mbgl/map/update.hpp b/include/mbgl/map/update.hpp
index 1c1270ac70..36ce59c01d 100644
--- a/include/mbgl/map/update.hpp
+++ b/include/mbgl/map/update.hpp
@@ -17,16 +17,15 @@ enum class Update : uint8_t {
AnnotationData = 1 << 7,
};
-inline Update operator| (const Update& lhs, const Update& rhs) {
+constexpr Update operator|(Update lhs, Update rhs) {
return Update(mbgl::underlying_type(lhs) | mbgl::underlying_type(rhs));
}
-inline Update& operator|=(Update& lhs, const Update& rhs) {
- lhs = lhs | rhs;
- return lhs;
+constexpr Update& operator|=(Update& lhs, const Update& rhs) {
+ return (lhs = lhs | rhs);
}
-inline bool operator& (const Update& lhs, const Update& rhs) {
+constexpr bool operator& (Update lhs, Update rhs) {
return mbgl::underlying_type(lhs) & mbgl::underlying_type(rhs);
}
diff --git a/include/mbgl/map/view.hpp b/include/mbgl/map/view.hpp
index 4431e2b33c..fa6f91d910 100644
--- a/include/mbgl/map/view.hpp
+++ b/include/mbgl/map/view.hpp
@@ -4,6 +4,7 @@
#include <mbgl/util/chrono.hpp>
#include <mbgl/util/image.hpp>
+#include <array>
#include <functional>
#include <memory>
@@ -36,8 +37,8 @@ public:
// as a matched pair, in four situations:
//
// 1. When releasing GL resources during Map destruction
- // 2. When calling a CustomLayerInitializeFunction, during Map::addCustomLayer
- // 3. When calling a CustomLayerDeinitializeFunction, during Map::removeCustomLayer
+ // 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
diff --git a/include/mbgl/platform/darwin/settings_nsuserdefaults.hpp b/include/mbgl/platform/darwin/settings_nsuserdefaults.hpp
deleted file mode 100644
index b0ca060b85..0000000000
--- a/include/mbgl/platform/darwin/settings_nsuserdefaults.hpp
+++ /dev/null
@@ -1,27 +0,0 @@
-#pragma once
-
-#import <mbgl/ios/MGLTypes.h>
-
-namespace mbgl {
-
-class Settings_NSUserDefaults {
-public:
- Settings_NSUserDefaults();
- void load();
- void save();
- void clear();
-
-public:
- double longitude = 0;
- double latitude = 0;
- double zoom = 0;
- double bearing = 0;
- double pitch = 0;
-
- MGLUserTrackingMode userTrackingMode = MGLUserTrackingModeNone;
- bool showsUserLocation = false;
-
- uint32_t debug = 0;
-};
-
-}
diff --git a/include/mbgl/platform/default/glfw_view.hpp b/include/mbgl/platform/default/glfw_view.hpp
index b5931e6262..83d00a24dd 100644
--- a/include/mbgl/platform/default/glfw_view.hpp
+++ b/include/mbgl/platform/default/glfw_view.hpp
@@ -3,6 +3,7 @@
#include <mbgl/mbgl.hpp>
#include <mbgl/util/run_loop.hpp>
#include <mbgl/util/timer.hpp>
+#include <mbgl/util/geometry.hpp>
#ifdef MBGL_USE_GLES2
#define GLFW_INCLUDE_ES2
@@ -13,7 +14,7 @@
class GLFWView : public mbgl::View {
public:
GLFWView(bool fullscreen = false, bool benchmark = false);
- ~GLFWView();
+ ~GLFWView() override;
float getPixelRatio() const override;
std::array<uint16_t, 2> getSize() const override;
@@ -43,7 +44,7 @@ public:
void report(float duration);
private:
- mbgl::LatLng makeRandomPoint() const;
+ mbgl::Point<double> makeRandomPoint() const;
static std::shared_ptr<const mbgl::SpriteImage>
makeSpriteImage(int width, int height, float pixelRatio);
diff --git a/include/mbgl/platform/default/headless_view.hpp b/include/mbgl/platform/default/headless_view.hpp
index d787eb1691..e3acc8e379 100644
--- a/include/mbgl/platform/default/headless_view.hpp
+++ b/include/mbgl/platform/default/headless_view.hpp
@@ -31,7 +31,7 @@ class HeadlessView : public View {
public:
HeadlessView(float pixelRatio, uint16_t width = 256, uint16_t height = 256);
HeadlessView(std::shared_ptr<HeadlessDisplay> display, float pixelRatio, uint16_t width = 256, uint16_t height = 256);
- ~HeadlessView();
+ ~HeadlessView() override;
float getPixelRatio() const override;
std::array<uint16_t, 2> getSize() const override;
@@ -74,7 +74,7 @@ private:
#if MBGL_USE_GLX
Display *xDisplay = nullptr;
GLXFBConfig *fbConfigs = nullptr;
- GLXContext glContext = 0;
+ GLXContext glContext = nullptr;
GLXPbuffer glxPbuffer = 0;
#endif
diff --git a/include/mbgl/platform/event.hpp b/include/mbgl/platform/event.hpp
index 0b3b79df6b..ee1ce6fa4e 100644
--- a/include/mbgl/platform/event.hpp
+++ b/include/mbgl/platform/event.hpp
@@ -1,7 +1,5 @@
#pragma once
-#include <mbgl/util/enum.hpp>
-
#include <cstdint>
namespace mbgl {
@@ -13,14 +11,6 @@ enum class EventSeverity : uint8_t {
Error,
};
-MBGL_DEFINE_ENUM_CLASS(EventSeverityClass, EventSeverity, {
- { EventSeverity::Debug, "DEBUG" },
- { EventSeverity::Info, "INFO" },
- { EventSeverity::Warning, "WARNING" },
- { EventSeverity::Error, "ERROR" },
- { EventSeverity(-1), "UNKNOWN" },
-});
-
enum class Event : uint8_t {
General,
Setup,
@@ -40,27 +30,6 @@ enum class Event : uint8_t {
Glyph,
};
-MBGL_DEFINE_ENUM_CLASS(EventClass, Event, {
- { Event::General, "General" },
- { Event::Setup, "Setup" },
- { Event::Shader, "Shader" },
- { Event::ParseStyle, "ParseStyle" },
- { Event::ParseTile, "ParseTile" },
- { Event::Render, "Render" },
- { Event::Style, "Style" },
- { Event::Database, "Database" },
- { Event::HttpRequest, "HttpRequest" },
- { Event::Sprite, "Sprite" },
- { Event::Image, "Image" },
- { Event::OpenGL, "OpenGL" },
- { Event::JNI, "JNI" },
- { Event::Android, "Android" },
- { Event::Crash, "Crash" },
- { Event::Glyph, "Glyph" },
- { Event(-1), "Unknown" },
-});
-
-
struct EventPermutation {
const EventSeverity severity;
const Event event;
diff --git a/include/mbgl/platform/log.hpp b/include/mbgl/platform/log.hpp
index 48b9e3dc70..d5bb1c2fcc 100644
--- a/include/mbgl/platform/log.hpp
+++ b/include/mbgl/platform/log.hpp
@@ -37,27 +37,27 @@ private:
public:
template <typename ...Args>
- static inline void Debug(Event event, Args&& ...args) {
+ static void Debug(Event event, Args&& ...args) {
Record(EventSeverity::Debug, event, ::std::forward<Args>(args)...);
}
template <typename ...Args>
- static inline void Info(Event event, Args&& ...args) {
+ static void Info(Event event, Args&& ...args) {
Record(EventSeverity::Info, event, ::std::forward<Args>(args)...);
}
template <typename ...Args>
- static inline void Warning(Event event, Args&& ...args) {
+ static void Warning(Event event, Args&& ...args) {
Record(EventSeverity::Warning, event, ::std::forward<Args>(args)...);
}
template <typename ...Args>
- static inline void Error(Event event, Args&& ...args) {
+ static void Error(Event event, Args&& ...args) {
Record(EventSeverity::Error, event, ::std::forward<Args>(args)...);
}
template <typename ...Args>
- static inline void Record(EventSeverity severity, Event event, Args&& ...args) {
+ static void Record(EventSeverity severity, Event event, Args&& ...args) {
if (!includes(severity, disabledEventSeverities) &&
!includes(event, disabledEvents) &&
!includes({ severity, event }, disabledEventPermutations)) {
diff --git a/include/mbgl/storage/default_file_source.hpp b/include/mbgl/storage/default_file_source.hpp
index e77befda1b..235e738254 100644
--- a/include/mbgl/storage/default_file_source.hpp
+++ b/include/mbgl/storage/default_file_source.hpp
@@ -26,6 +26,10 @@ public:
uint64_t maximumCacheSize = util::DEFAULT_MAX_CACHE_SIZE);
~DefaultFileSource() override;
+ bool supportsOptionalRequests() const override {
+ return true;
+ }
+
void setAccessToken(const std::string&);
std::string getAccessToken() const;
diff --git a/include/mbgl/storage/file_source.hpp b/include/mbgl/storage/file_source.hpp
index 88e0336187..404c683fdb 100644
--- a/include/mbgl/storage/file_source.hpp
+++ b/include/mbgl/storage/file_source.hpp
@@ -23,6 +23,14 @@ public:
// If the request is cancelled before the callback is executed, the callback will
// not be executed.
virtual std::unique_ptr<AsyncRequest> request(const Resource&, Callback) = 0;
+
+ // When a file source supports optional requests, it must return true.
+ // Optional requests are requests that aren't as urgent, but could be useful, e.g.
+ // to cover part of the map while loading. The FileSource should only do cheap actions to
+ // retrieve the data, e.g. load it from a cache, but not from the internet.
+ virtual bool supportsOptionalRequests() const {
+ return false;
+ }
};
} // namespace mbgl
diff --git a/include/mbgl/storage/offline.hpp b/include/mbgl/storage/offline.hpp
index e0c5ba6247..818cfe2ba5 100644
--- a/include/mbgl/storage/offline.hpp
+++ b/include/mbgl/storage/offline.hpp
@@ -1,6 +1,7 @@
#pragma once
#include <mbgl/util/geo.hpp>
+#include <mbgl/util/range.hpp>
#include <mbgl/util/optional.hpp>
#include <mbgl/style/types.hpp>
#include <mbgl/storage/response.hpp>
@@ -12,7 +13,6 @@
namespace mbgl {
class TileID;
-class SourceInfo;
/*
* An offline region defined by a style URL, geographic bounding box, zoom range, and
@@ -27,10 +27,10 @@ class SourceInfo;
*/
class OfflineTilePyramidRegionDefinition {
public:
- OfflineTilePyramidRegionDefinition(const std::string&, const LatLngBounds&, double, double, float);
+ OfflineTilePyramidRegionDefinition(std::string, LatLngBounds, double, double, float);
/* Private */
- std::vector<CanonicalTileID> tileCover(SourceType, uint16_t tileSize, const SourceInfo&) const;
+ std::vector<CanonicalTileID> tileCover(SourceType, uint16_t tileSize, const Range<uint8_t>& zoomRange) const;
const std::string styleURL;
const LatLngBounds bounds;
@@ -200,8 +200,8 @@ private:
friend class OfflineDatabase;
OfflineRegion(int64_t id,
- const OfflineRegionDefinition&,
- const OfflineRegionMetadata&);
+ OfflineRegionDefinition,
+ OfflineRegionMetadata);
const int64_t id;
const OfflineRegionDefinition definition;
diff --git a/include/mbgl/storage/resource.hpp b/include/mbgl/storage/resource.hpp
index 62ee549663..31df069952 100644
--- a/include/mbgl/storage/resource.hpp
+++ b/include/mbgl/storage/resource.hpp
@@ -2,7 +2,7 @@
#include <mbgl/storage/response.hpp>
#include <mbgl/util/optional.hpp>
-#include <mbgl/style/types.hpp>
+#include <mbgl/util/font_stack.hpp>
#include <string>
@@ -33,10 +33,10 @@ public:
Required = true,
};
- Resource(Kind kind_, const std::string& url_, optional<TileData> tileData_ = {}, Necessity necessity_ = Required)
+ Resource(Kind kind_, std::string url_, optional<TileData> tileData_ = {}, Necessity necessity_ = Required)
: kind(kind_),
necessity(necessity_),
- url(url_),
+ url(std::move(url_)),
tileData(std::move(tileData_)) {
}
diff --git a/include/mbgl/storage/response.hpp b/include/mbgl/storage/response.hpp
index 83227573cf..6c79f5e181 100644
--- a/include/mbgl/storage/response.hpp
+++ b/include/mbgl/storage/response.hpp
@@ -49,7 +49,7 @@ public:
std::string message;
public:
- Error(Reason, const std::string& = "");
+ Error(Reason, std::string = "");
};
std::ostream& operator<<(std::ostream&, Response::Error::Reason);
diff --git a/include/mbgl/style/conversion.hpp b/include/mbgl/style/conversion.hpp
new file mode 100644
index 0000000000..bd7db3adfb
--- /dev/null
+++ b/include/mbgl/style/conversion.hpp
@@ -0,0 +1,93 @@
+#pragma once
+
+#include <mbgl/util/variant.hpp>
+
+namespace mbgl {
+namespace style {
+namespace conversion {
+
+/*
+ The `conversion` namespace defines conversions from a templated type `V` representing a JSON
+ object conforming to the schema defined by the Mapbox Style Specification, to the various C++
+ types that form the C++ model of that domain:
+
+ * `std::unique_ptr<Source>`
+ * `std::unique_ptr<Layer>`
+ * `Filter`
+ * `PropertyValue<T>`
+
+ A single template function serves as the public interface:
+
+ template <class T, class V>
+ Result<T> convert(const V& value);
+
+ 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.
+
+ The implementation of `convert` requires that the following are legal expressions for a value `v`
+ of type `const V&`:
+
+ * `isUndefined(v)` -- returns a boolean indication whether `v` is undefined or a JSON null
+
+ * `isArray(v)` -- returns a boolean indicating whether `v` represents a JSON array
+ * `arrayLength(v)` -- called only if `isArray(v)`; returns a size_t length
+ * `arrayMember(v)` -- called only if `isArray(v)`; returns `V` or `V&`
+
+ * `isObject(v)` -- returns a boolean indicating whether `v` represents a JSON object
+ * `objectMember(v, name)` -- called only if `isObject(v)`; `name` is `const char *`; return value:
+ * is true when evaluated in a boolean context iff the named member exists
+ * is convertable to a `V` or `V&` when dereferenced
+ * `eachMember(v, [] (const std::string&, const V&) -> optional<Error> {...})` -- called
+ only if `isObject(v)`; calls the provided lambda once for each key and value of the object;
+ short-circuits if any call returns an `Error`
+
+ * `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
+ * `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
+ unsigned integer, signed integer, or floating point, in descending preference.
+
+ The mbgl core implements these requirements for RapidJSON types, and the node bindings implement
+ them for v8 types.
+*/
+
+struct Error { const char * 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)...);
+}
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/conversion/constant.hpp b/include/mbgl/style/conversion/constant.hpp
new file mode 100644
index 0000000000..05bf968f4d
--- /dev/null
+++ b/include/mbgl/style/conversion/constant.hpp
@@ -0,0 +1,174 @@
+#pragma once
+
+#include <mbgl/style/conversion.hpp>
+#include <mbgl/util/optional.hpp>
+#include <mbgl/util/color.hpp>
+#include <mbgl/util/enum.hpp>
+
+#include <array>
+#include <string>
+#include <vector>
+
+namespace mbgl {
+namespace style {
+namespace conversion {
+
+template <>
+struct Converter<bool> {
+ template <class V>
+ Result<bool> operator()(const V& value) const {
+ optional<bool> converted = toBool(value);
+ if (!converted) {
+ return Error { "value must be a boolean" };
+ }
+ return *converted;
+ }
+};
+
+template <>
+struct Converter<float> {
+ template <class V>
+ Result<float> operator()(const V& value) const {
+ optional<float> converted = toNumber(value);
+ if (!converted) {
+ return Error { "value must be a number" };
+ }
+ return *converted;
+ }
+};
+
+template <>
+struct Converter<std::string> {
+ template <class V>
+ Result<std::string> operator()(const V& value) const {
+ optional<std::string> converted = toString(value);
+ if (!converted) {
+ return Error { "value must be a string" };
+ }
+ return *converted;
+ }
+};
+
+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<std::string> string = toString(value);
+ if (!string) {
+ return Error { "value must be a string" };
+ }
+
+ const auto result = Enum<T>::toEnum(*string);
+ if (!result) {
+ return Error { "value must be a valid enumeration value" };
+ }
+
+ return *result;
+ }
+};
+
+template <>
+struct Converter<Color> {
+ template <class V>
+ Result<Color> operator()(const V& value) const {
+ optional<std::string> string = toString(value);
+ if (!string) {
+ return Error { "value must be a string" };
+ }
+
+ optional<Color> color = Color::parse(*string);
+ if (!color) {
+ return Error { "value must be a valid color" };
+ }
+
+ return *color;
+ }
+};
+
+template <>
+struct Converter<std::array<float, 2>> {
+ 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" };
+ }
+
+ 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" };
+ }
+
+ return std::array<float, 4> {{ *first, *second, *third, *fourth }};
+ }
+};
+
+template <>
+struct Converter<std::vector<float>> {
+ template <class V>
+ Result<std::vector<float>> operator()(const V& value) const {
+ if (!isArray(value)) {
+ return Error { "value must be an array" };
+ }
+
+ std::vector<float> result;
+ result.reserve(arrayLength(value));
+
+ 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" };
+ }
+ result.push_back(*number);
+ }
+
+ return result;
+ }
+};
+
+template <>
+struct Converter<std::vector<std::string>> {
+ template <class V>
+ Result<std::vector<std::string>> operator()(const V& value) const {
+ if (!isArray(value)) {
+ return Error { "value must be an array" };
+ }
+
+ std::vector<std::string> result;
+ result.reserve(arrayLength(value));
+
+ 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" };
+ }
+ result.push_back(*string);
+ }
+
+ return result;
+ }
+};
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/conversion/filter.hpp b/include/mbgl/style/conversion/filter.hpp
new file mode 100644
index 0000000000..3ab91e5bbc
--- /dev/null
+++ b/include/mbgl/style/conversion/filter.hpp
@@ -0,0 +1,150 @@
+#pragma once
+
+#include <mbgl/style/filter.hpp>
+#include <mbgl/style/conversion.hpp>
+#include <mbgl/util/geometry.hpp>
+
+namespace mbgl {
+namespace style {
+namespace conversion {
+
+template <>
+struct Converter<Filter> {
+public:
+ template <class V>
+ Result<Filter> operator()(const V& value) const {
+ if (!isArray(value)) {
+ return Error { "filter expression must be an array" };
+ }
+
+ if (arrayLength(value) < 1) {
+ return Error { "filter expression must have at least 1 element" };
+ }
+
+ optional<std::string> op = toString(arrayMember(value, 0));
+ if (!op) {
+ return Error { "filter operator must be a string" };
+ }
+
+ if (*op == "==") {
+ return convertBinaryFilter<EqualsFilter>(value);
+ } else if (*op == "!=") {
+ return convertBinaryFilter<NotEqualsFilter>(value);
+ } else if (*op == ">") {
+ return convertBinaryFilter<GreaterThanFilter>(value);
+ } else if (*op == ">=") {
+ return convertBinaryFilter<GreaterThanEqualsFilter>(value);
+ } else if (*op == "<") {
+ return convertBinaryFilter<LessThanFilter>(value);
+ } else if (*op == "<=") {
+ return convertBinaryFilter<LessThanEqualsFilter>(value);
+ } else if (*op == "in") {
+ return convertSetFilter<InFilter>(value);
+ } else if (*op == "!in") {
+ return convertSetFilter<NotInFilter>(value);
+ } else if (*op == "all") {
+ return convertCompoundFilter<AllFilter>(value);
+ } else if (*op == "any") {
+ return convertCompoundFilter<AnyFilter>(value);
+ } else if (*op == "none") {
+ return convertCompoundFilter<NoneFilter>(value);
+ } else if (*op == "has") {
+ return convertUnaryFilter<HasFilter>(value);
+ } else if (*op == "!has") {
+ return convertUnaryFilter<NotHasFilter>(value);
+ }
+
+ return Error { "filter operator must be one of \"==\", \"!=\", \">\", \">=\", \"<\", \"<=\", \"in\", \"!in\", \"all\", \"any\", \"none\", \"has\", or \"!has\"" };
+ }
+
+private:
+ Result<Value> normalizeValue(const std::string& key, const optional<Value>& value) const {
+ if (!value) {
+ return Error { "filter expression value must be a boolean, number, or string" };
+ } else if (key != "$type") {
+ 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));
+ } else {
+ return Error { "value for $type filter must be Point, LineString, or Polygon" };
+ }
+ }
+
+ template <class FilterType, class V>
+ Result<Filter> convertUnaryFilter(const V& value) const {
+ if (arrayLength(value) < 2) {
+ return Error { "filter expression must have 2 elements" };
+ }
+
+ optional<std::string> key = toString(arrayMember(value, 1));
+ if (!key) {
+ return Error { "filter expression key must be a string" };
+ }
+
+ return FilterType { *key };
+ }
+
+ template <class FilterType, class V>
+ Result<Filter> convertBinaryFilter(const V& value) const {
+ if (arrayLength(value) < 3) {
+ return Error { "filter expression must have 3 elements" };
+ }
+
+ optional<std::string> key = toString(arrayMember(value, 1));
+ if (!key) {
+ return Error { "filter expression key must be a string" };
+ }
+
+ Result<Value> filterValue = normalizeValue(*key, toValue(arrayMember(value, 2)));
+ if (!filterValue) {
+ return filterValue.error();
+ }
+
+ return FilterType { *key, *filterValue };
+ }
+
+ template <class FilterType, class V>
+ Result<Filter> convertSetFilter(const V& value) const {
+ if (arrayLength(value) < 2) {
+ return Error { "filter expression must at least 2 elements" };
+ }
+
+ optional<std::string> key = toString(arrayMember(value, 1));
+ if (!key) {
+ return Error { "filter expression key must be a string" };
+ }
+
+ 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();
+ }
+ values.push_back(*filterValue);
+ }
+
+ return FilterType { *key, std::move(values) };
+ }
+
+ template <class FilterType, class V>
+ Result<Filter> convertCompoundFilter(const V& value) const {
+ std::vector<Filter> filters;
+ for (std::size_t i = 1; i < arrayLength(value); ++i) {
+ Result<Filter> element = operator()(arrayMember(value, i));
+ if (!element) {
+ return element.error();
+ }
+ filters.push_back(*element);
+ }
+
+ return FilterType { std::move(filters) };
+ }
+};
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/conversion/function.hpp b/include/mbgl/style/conversion/function.hpp
new file mode 100644
index 0000000000..f14b5089be
--- /dev/null
+++ b/include/mbgl/style/conversion/function.hpp
@@ -0,0 +1,69 @@
+#pragma once
+
+#include <mbgl/style/function.hpp>
+#include <mbgl/style/conversion.hpp>
+#include <mbgl/style/conversion/constant.hpp>
+
+namespace mbgl {
+namespace style {
+namespace conversion {
+
+template <class T>
+struct Converter<Function<T>> {
+ template <class V>
+ Result<Function<T>> operator()(const V& value) const {
+ if (!isObject(value)) {
+ return Error { "function must be an object" };
+ }
+
+ auto stopsValue = objectMember(value, "stops");
+ if (!stopsValue) {
+ return Error { "function value must specify stops" };
+ }
+
+ if (!isArray(*stopsValue)) {
+ return Error { "function stops must be an array" };
+ }
+
+ std::vector<std::pair<float, T>> stops;
+ for (std::size_t i = 0; i < arrayLength(*stopsValue); ++i) {
+ const auto& stopValue = arrayMember(*stopsValue, i);
+
+ if (!isArray(stopValue)) {
+ return Error { "function stop must be an array" };
+ }
+
+ if (arrayLength(stopValue) != 2) {
+ return Error { "function stop must have two elements" };
+ }
+
+ optional<float> z = toNumber(arrayMember(stopValue, 0));
+ if (!z) {
+ return Error { "function stop zoom level must be a number" };
+ }
+
+ Result<T> v = convert<T>(arrayMember(stopValue, 1));
+ if (!v) {
+ return v.error();
+ }
+
+ stops.emplace_back(*z, *v);
+ }
+
+ auto baseValue = objectMember(value, "base");
+ if (!baseValue) {
+ return Function<T>(stops, 1.0f);
+ }
+
+ optional<float> base = toNumber(*baseValue);
+ if (!base) {
+ return Error { "function base must be a number"};
+ }
+
+ return Function<T>(stops, *base);
+ }
+};
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/conversion/geojson.hpp b/include/mbgl/style/conversion/geojson.hpp
new file mode 100644
index 0000000000..ba10b3ecc8
--- /dev/null
+++ b/include/mbgl/style/conversion/geojson.hpp
@@ -0,0 +1,15 @@
+#pragma once
+
+#include <mbgl/style/conversion.hpp>
+#include <mbgl/style/sources/geojson_source.hpp>
+
+namespace mbgl {
+namespace style {
+namespace conversion {
+
+template <class V>
+Result<GeoJSON> convertGeoJSON(const V& value);
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/conversion/layer.hpp b/include/mbgl/style/conversion/layer.hpp
new file mode 100644
index 0000000000..0539dcf9ad
--- /dev/null
+++ b/include/mbgl/style/conversion/layer.hpp
@@ -0,0 +1,208 @@
+#pragma once
+
+#include <mbgl/style/layer.hpp>
+#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/line_layer.hpp>
+#include <mbgl/style/layers/raster_layer.hpp>
+#include <mbgl/style/layers/symbol_layer.hpp>
+#include <mbgl/style/conversion.hpp>
+#include <mbgl/style/conversion/constant.hpp>
+#include <mbgl/style/conversion/filter.hpp>
+#include <mbgl/style/conversion/make_property_setters.hpp>
+
+namespace mbgl {
+namespace style {
+namespace conversion {
+
+template <class V>
+optional<Error> setLayoutProperty(Layer& layer, const std::string& name, const V& value) {
+ static const auto setters = makeLayoutPropertySetters<V>();
+ auto it = setters.find(name);
+ if (it == setters.end()) {
+ return Error { "property not found" };
+ }
+ return it->second(layer, value);
+}
+
+template <class V>
+optional<Error> setPaintProperty(Layer& layer, const std::string& name, const V& value, const optional<std::string>& klass) {
+ 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);
+}
+
+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);
+ });
+ });
+}
+
+template <>
+struct Converter<std::unique_ptr<Layer>> {
+public:
+ template <class V>
+ Result<std::unique_ptr<Layer>> operator()(const V& value) const {
+ if (!isObject(value)) {
+ return Error { "layer must be an object" };
+ }
+
+ auto idValue = objectMember(value, "id");
+ if (!idValue) {
+ return Error { "layer must have an id" };
+ }
+
+ optional<std::string> id = toString(*idValue);
+ if (!id) {
+ return Error { "layer id must be a string" };
+ }
+
+ auto typeValue = objectMember(value, "type");
+ if (!typeValue) {
+ return Error { "layer must have a type" };
+ }
+
+ optional<std::string> type = toString(*typeValue);
+ if (!type) {
+ return Error { "layer type must be a string" };
+ }
+
+ Result<std::unique_ptr<Layer>> converted;
+
+ if (*type == "fill") {
+ converted = convertVectorLayer<FillLayer>(*id, value);
+ } else if (*type == "line") {
+ converted = convertVectorLayer<LineLayer>(*id, value);
+ } else if (*type == "circle") {
+ converted = convertVectorLayer<CircleLayer>(*id, value);
+ } else if (*type == "symbol") {
+ converted = convertVectorLayer<SymbolLayer>(*id, value);
+ } else if (*type == "raster") {
+ converted = convertRasterLayer(*id, value);
+ } else if (*type == "background") {
+ converted = convertBackgroundLayer(*id, value);
+ } else {
+ return Error { "invalid layer type" };
+ }
+
+ if (!converted) {
+ return converted;
+ }
+
+ std::unique_ptr<Layer> layer = std::move(*converted);
+
+ auto minzoomValue = objectMember(value, "minzoom");
+ if (minzoomValue) {
+ optional<float> minzoom = toNumber(*minzoomValue);
+ if (!minzoom) {
+ return Error { "minzoom must be numeric" };
+ }
+ layer->setMinZoom(*minzoom);
+ }
+
+ auto maxzoomValue = objectMember(value, "maxzoom");
+ if (maxzoomValue) {
+ optional<float> maxzoom = toNumber(*maxzoomValue);
+ if (!maxzoom) {
+ return Error { "maxzoom must be numeric" };
+ }
+ layer->setMaxZoom(*maxzoom);
+ }
+
+ auto layoutValue = objectMember(value, "layout");
+ if (layoutValue) {
+ if (!isObject(*layoutValue)) {
+ return Error { "layout must be an object" };
+ }
+ optional<Error> error = eachMember(*layoutValue, [&] (const std::string& k, const V& v) {
+ return setLayoutProperty(*layer, k, v);
+ });
+ if (error) {
+ return *error;
+ }
+ }
+
+ optional<Error> error = setPaintProperties(*layer, value);
+ if (error) {
+ return *error;
+ }
+
+ return std::move(layer);
+ }
+
+private:
+ template <class LayerType, class V>
+ Result<std::unique_ptr<Layer>> convertVectorLayer(const std::string& id, const V& value) const {
+ auto sourceValue = objectMember(value, "source");
+ if (!sourceValue) {
+ return Error { "layer must have a source" };
+ }
+
+ optional<std::string> source = toString(*sourceValue);
+ if (!source) {
+ return Error { "layer source must be a string" };
+ }
+
+ std::unique_ptr<LayerType> layer = std::make_unique<LayerType>(id, *source);
+
+ auto sourceLayerValue = objectMember(value, "source-layer");
+ if (sourceLayerValue) {
+ optional<std::string> sourceLayer = toString(*sourceLayerValue);
+ if (!sourceLayer) {
+ return Error { "layer source-layer must be a string" };
+ }
+ layer->setSourceLayer(*sourceLayer);
+ }
+
+ auto filterValue = objectMember(value, "filter");
+ if (filterValue) {
+ Result<Filter> filter = convert<Filter>(*filterValue);
+ if (!filter) {
+ return filter.error();
+ }
+ layer->setFilter(*filter);
+ }
+
+ return std::move(layer);
+ }
+
+ template <class V>
+ Result<std::unique_ptr<Layer>> convertRasterLayer(const std::string& id, const V& value) const {
+ auto sourceValue = objectMember(value, "source");
+ if (!sourceValue) {
+ return Error { "layer must have a source" };
+ }
+
+ optional<std::string> source = toString(*sourceValue);
+ if (!source) {
+ return Error { "layer source must be a string" };
+ }
+
+ 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);
+ }
+};
+
+} // 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
new file mode 100644
index 0000000000..4c0089deaf
--- /dev/null
+++ b/include/mbgl/style/conversion/make_property_setters.hpp
@@ -0,0 +1,133 @@
+// This file is generated. Edit make_property_setters.hpp.ejs, then run `make style-code`.
+
+#include <mbgl/style/conversion/property_setter.hpp>
+
+#include <mbgl/style/layers/fill_layer.hpp>
+#include <mbgl/style/layers/line_layer.hpp>
+#include <mbgl/style/layers/symbol_layer.hpp>
+#include <mbgl/style/layers/circle_layer.hpp>
+#include <mbgl/style/layers/raster_layer.hpp>
+#include <mbgl/style/layers/background_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>;
+
+
+ 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);
+
+
+
+
+ return result;
+}
+
+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["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);
+
+ return result;
+}
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/conversion/make_property_setters.hpp.ejs b/include/mbgl/style/conversion/make_property_setters.hpp.ejs
new file mode 100644
index 0000000000..493c68ea31
--- /dev/null
+++ b/include/mbgl/style/conversion/make_property_setters.hpp.ejs
@@ -0,0 +1,45 @@
+// 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 %>_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/property_setter.hpp b/include/mbgl/style/conversion/property_setter.hpp
new file mode 100644
index 0000000000..38dd934252
--- /dev/null
+++ b/include/mbgl/style/conversion/property_setter.hpp
@@ -0,0 +1,55 @@
+#include <mbgl/style/layer.hpp>
+#include <mbgl/style/conversion.hpp>
+#include <mbgl/style/conversion/constant.hpp>
+#include <mbgl/style/conversion/property_value.hpp>
+
+#include <functional>
+#include <string>
+
+namespace mbgl {
+namespace style {
+namespace conversion {
+
+template <class V>
+using LayoutPropertySetter = std::function<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>
+optional<Error> setVisibility(Layer& layer, const V& value) {
+ if (isUndefined(value)) {
+ layer.setVisibility(VisibilityType::Visible);
+ return {};
+ }
+
+ Result<VisibilityType> visibility = convert<VisibilityType>(value);
+ if (!visibility) {
+ return visibility.error();
+ }
+
+ layer.setVisibility(*visibility);
+ return {};
+}
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/conversion/property_value.hpp b/include/mbgl/style/conversion/property_value.hpp
new file mode 100644
index 0000000000..de95b56155
--- /dev/null
+++ b/include/mbgl/style/conversion/property_value.hpp
@@ -0,0 +1,36 @@
+#pragma once
+
+#include <mbgl/style/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<PropertyValue<T>> {
+ template <class V>
+ Result<PropertyValue<T>> operator()(const V& value) const {
+ if (isUndefined(value)) {
+ return {};
+ } else if (isObject(value)) {
+ Result<Function<T>> function = convert<Function<T>>(value);
+ if (!function) {
+ return function.error();
+ }
+ return *function;
+ } else {
+ Result<T> constant = convert<T>(value);
+ if (!constant) {
+ return constant.error();
+ }
+ return *constant;
+ }
+ }
+};
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/conversion/source.hpp b/include/mbgl/style/conversion/source.hpp
new file mode 100644
index 0000000000..00c6afb9fe
--- /dev/null
+++ b/include/mbgl/style/conversion/source.hpp
@@ -0,0 +1,123 @@
+#pragma once
+
+#include <mbgl/style/source.hpp>
+#include <mbgl/style/sources/geojson_source.hpp>
+#include <mbgl/style/sources/raster_source.hpp>
+#include <mbgl/style/sources/vector_source.hpp>
+#include <mbgl/style/conversion.hpp>
+#include <mbgl/style/conversion/tileset.hpp>
+#include <mbgl/style/conversion/geojson.hpp>
+
+namespace mbgl {
+namespace style {
+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 {
+ if (!isObject(value)) {
+ return Error { "source must be an object" };
+ }
+
+ auto typeValue = objectMember(value, "type");
+ if (!typeValue) {
+ return Error { "source must have a type" };
+ }
+
+ optional<std::string> type = toString(*typeValue);
+ if (!type) {
+ return Error { "source type must be a string" };
+ }
+
+ if (*type == "raster") {
+ return convertRasterSource(id, value);
+ } else if (*type == "vector") {
+ return convertVectorSource(id, value);
+ } else if (*type == "geojson") {
+ return convertGeoJSONSource(id, value);
+ } else {
+ return Error { "invalid source type" };
+ }
+ }
+
+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 {
+ auto urlVal = objectMember(value, "url");
+ if (!urlVal) {
+ Result<Tileset> tileset = convert<Tileset>(value);
+ if (!tileset) {
+ return tileset.error();
+ }
+ return *tileset;
+ }
+
+ optional<std::string> url = toString(*urlVal);
+ if (!url) {
+ return Error { "source url must be a string" };
+ }
+
+ 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);
+ if (!urlOrTileset) {
+ return urlOrTileset.error();
+ }
+
+ uint16_t tileSize = util::tileSize;
+ auto tileSizeValue = objectMember(value, "tileSize");
+ if (tileSizeValue) {
+ optional<float> size = toNumber(*tileSizeValue);
+ if (!size || *size < 0 || *size > std::numeric_limits<uint16_t>::max()) {
+ return Error { "invalid tileSize" };
+ }
+ tileSize = *size;
+ }
+
+ 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);
+ if (!urlOrTileset) {
+ return urlOrTileset.error();
+ }
+
+ 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 {
+ auto dataValue = objectMember(value, "data");
+ if (!dataValue) {
+ return Error { "GeoJSON source must have a data value" };
+ }
+
+ auto result = std::make_unique<GeoJSONSource>(id);
+
+ if (isObject(*dataValue)) {
+ Result<GeoJSON> geoJSON = convertGeoJSON(*dataValue);
+ if (!geoJSON) {
+ return geoJSON.error();
+ }
+ 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" };
+ }
+
+ return std::move(result);
+ }
+};
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/conversion/tileset.hpp b/include/mbgl/style/conversion/tileset.hpp
new file mode 100644
index 0000000000..46425597af
--- /dev/null
+++ b/include/mbgl/style/conversion/tileset.hpp
@@ -0,0 +1,67 @@
+#pragma once
+
+#include <mbgl/util/tileset.hpp>
+#include <mbgl/style/conversion.hpp>
+
+namespace mbgl {
+namespace style {
+namespace conversion {
+
+template <>
+struct Converter<Tileset> {
+public:
+ template <class V>
+ Result<Tileset> operator()(const V& value) const {
+ Tileset result;
+
+ auto tiles = objectMember(value, "tiles");
+ if (!tiles) {
+ return Error { "source must have tiles" };
+ }
+
+ if (!isArray(*tiles)) {
+ return Error { "source tiles must be an array" };
+ }
+
+ 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" };
+ }
+ result.tiles.push_back(std::move(*urlTemplate));
+ }
+
+ auto minzoomValue = objectMember(value, "minzoom");
+ if (minzoomValue) {
+ optional<float> minzoom = toNumber(*minzoomValue);
+ if (!minzoom || *minzoom < 0 || *minzoom > std::numeric_limits<uint8_t>::max()) {
+ return Error { "invalid minzoom" };
+ }
+ result.zoomRange.min = *minzoom;
+ }
+
+ auto maxzoomValue = objectMember(value, "maxzoom");
+ if (maxzoomValue) {
+ optional<float> maxzoom = toNumber(*maxzoomValue);
+ if (!maxzoom || *maxzoom < 0 || *maxzoom > std::numeric_limits<uint8_t>::max()) {
+ return Error { "invalid maxzoom" };
+ }
+ result.zoomRange.max = *maxzoom;
+ }
+
+ auto attributionValue = objectMember(value, "attribution");
+ if (attributionValue) {
+ optional<std::string> attribution = toString(*attributionValue);
+ if (!attribution) {
+ return Error { "source attribution must be a string" };
+ }
+ result.attribution = std::move(*attribution);
+ }
+
+ return result;
+ }
+};
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/filter.hpp b/include/mbgl/style/filter.hpp
new file mode 100644
index 0000000000..6a5afb7b47
--- /dev/null
+++ b/include/mbgl/style/filter.hpp
@@ -0,0 +1,115 @@
+#pragma once
+
+#include <mbgl/util/variant.hpp>
+#include <mbgl/util/feature.hpp>
+#include <mbgl/util/geometry.hpp>
+
+#include <string>
+#include <vector>
+
+namespace mbgl {
+namespace style {
+
+class Filter;
+
+class NullFilter {};
+
+class EqualsFilter {
+public:
+ std::string key;
+ Value value;
+};
+
+class NotEqualsFilter {
+public:
+ std::string key;
+ Value value;
+};
+
+class LessThanFilter {
+public:
+ std::string key;
+ Value value;
+};
+
+class LessThanEqualsFilter {
+public:
+ std::string key;
+ Value value;
+};
+
+class GreaterThanFilter {
+public:
+ std::string key;
+ Value value;
+};
+
+class GreaterThanEqualsFilter {
+public:
+ std::string key;
+ Value value;
+};
+
+class InFilter {
+public:
+ std::string key;
+ std::vector<Value> values;
+};
+
+class NotInFilter {
+public:
+ std::string key;
+ std::vector<Value> values;
+};
+
+class AnyFilter {
+public:
+ std::vector<Filter> filters;
+};
+
+class AllFilter {
+public:
+ std::vector<Filter> filters;
+};
+
+class NoneFilter {
+public:
+ std::vector<Filter> filters;
+};
+
+class HasFilter {
+public:
+ std::string key;
+};
+
+class NotHasFilter {
+public:
+ std::string key;
+};
+
+using FilterBase = variant<
+ class NullFilter,
+ class EqualsFilter,
+ class NotEqualsFilter,
+ class LessThanFilter,
+ class LessThanEqualsFilter,
+ class GreaterThanFilter,
+ class GreaterThanEqualsFilter,
+ class InFilter,
+ class NotInFilter,
+ class AnyFilter,
+ class AllFilter,
+ class NoneFilter,
+ class HasFilter,
+ class NotHasFilter>;
+
+class Filter : public FilterBase {
+public:
+ using FilterBase::FilterBase;
+
+ template <class PropertyAccessor>
+ bool operator()(FeatureType type, PropertyAccessor accessor) const;
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/filter_evaluator.hpp b/include/mbgl/style/filter_evaluator.hpp
new file mode 100644
index 0000000000..e7b6e0f5a0
--- /dev/null
+++ b/include/mbgl/style/filter_evaluator.hpp
@@ -0,0 +1,181 @@
+#pragma once
+
+#include <mbgl/style/filter.hpp>
+#include <mbgl/util/geometry.hpp>
+
+#include <type_traits>
+
+namespace mbgl {
+namespace style {
+
+/*
+ A visitor that evaluates a `Filter` for a given feature type and properties. For maximum
+ flexibility, it is templated on the PropertyAccessor type, which must be a callable type with
+ function signature `optional<Value> (const std::string&)`, returning the value for the given
+ key, if it exists.
+
+ Use via `Filter::operator()`. For example:
+
+ if (filter(feature.getType(), [&] (const std::string& key) { return feature.getValue(key); })) {
+ // matches the filter
+ } else {
+ // does not match
+ }
+*/
+template <class PropertyAccessor>
+class FilterEvaluator {
+public:
+ const FeatureType featureType;
+ const PropertyAccessor propertyAccessor;
+
+ bool operator()(const NullFilter&) const {
+ return true;
+ }
+
+ bool operator()(const EqualsFilter& filter) const {
+ optional<Value> actual = getValue(filter.key);
+ return actual && equal(*actual, filter.value);
+ }
+
+ bool operator()(const NotEqualsFilter& filter) const {
+ optional<Value> actual = getValue(filter.key);
+ return !actual || !equal(*actual, filter.value);
+ }
+
+ bool operator()(const LessThanFilter& filter) const {
+ optional<Value> actual = getValue(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);
+ 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);
+ 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);
+ 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);
+ if (!actual)
+ return false;
+ for (const auto& v: filter.values) {
+ if (equal(*actual, v)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ bool operator()(const NotInFilter& filter) const {
+ optional<Value> actual = getValue(filter.key);
+ if (!actual)
+ return true;
+ for (const auto& v: filter.values) {
+ if (equal(*actual, v)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ bool operator()(const AnyFilter& filter) const {
+ for (const auto& f: filter.filters) {
+ if (Filter::visit(f, *this)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ bool operator()(const AllFilter& filter) const {
+ for (const auto& f: filter.filters) {
+ if (!Filter::visit(f, *this)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ bool operator()(const NoneFilter& filter) const {
+ for (const auto& f: filter.filters) {
+ if (Filter::visit(f, *this)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ bool operator()(const HasFilter& filter) const {
+ return bool(getValue(filter.key));
+ }
+
+ bool operator()(const NotHasFilter& filter) const {
+ return !getValue(filter.key);
+ }
+
+private:
+ optional<Value> getValue(const std::string& key_) const {
+ return key_ == "$type"
+ ? optional<Value>(uint64_t(featureType))
+ : propertyAccessor(key_);
+ }
+
+ template <class Op>
+ struct Comparator {
+ const Op& op;
+
+ template <class T>
+ bool operator()(const T& lhs, const T& rhs) const {
+ return op(lhs, rhs);
+ }
+
+ template <class T0, class T1>
+ auto operator()(const T0& lhs, const T1& rhs) const
+ -> typename std::enable_if_t<std::is_arithmetic<T0>::value && !std::is_same<T0, bool>::value &&
+ std::is_arithmetic<T1>::value && !std::is_same<T1, bool>::value, bool> {
+ return op(double(lhs), double(rhs));
+ }
+
+ template <class T0, class T1>
+ auto operator()(const T0&, const T1&) const
+ -> typename std::enable_if_t<!std::is_arithmetic<T0>::value || std::is_same<T0, bool>::value ||
+ !std::is_arithmetic<T1>::value || std::is_same<T1, bool>::value, bool> {
+ return false;
+ }
+
+ bool operator()(const std::vector<Value>&,
+ const std::vector<Value>&) const {
+ return false;
+ }
+
+ bool operator()(const std::unordered_map<std::string, Value>&,
+ const std::unordered_map<std::string, Value>&) const {
+ return false;
+ }
+ };
+
+ template <class Op>
+ bool compare(const Value& lhs, const Value& rhs, const Op& op) const {
+ return Value::binary_visit(lhs, rhs, Comparator<Op> { op });
+ }
+
+ bool equal(const Value& lhs, const Value& rhs) const {
+ return compare(lhs, rhs, [] (const auto& lhs_, const auto& rhs_) { return lhs_ == rhs_; });
+ }
+};
+
+template <class PropertyAccessor>
+bool Filter::operator()(FeatureType type, PropertyAccessor accessor) const {
+ return FilterBase::visit(*this, FilterEvaluator<PropertyAccessor> { type, accessor });
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/function.hpp b/include/mbgl/style/function.hpp
new file mode 100644
index 0000000000..44ffa31079
--- /dev/null
+++ b/include/mbgl/style/function.hpp
@@ -0,0 +1,27 @@
+#pragma once
+
+#include <vector>
+#include <utility>
+
+namespace mbgl {
+namespace style {
+
+template <typename T>
+class Function {
+public:
+ using Stop = std::pair<float, T>;
+ using Stops = std::vector<Stop>;
+
+ explicit Function(Stops stops_, float base_)
+ : base(base_), stops(std::move(stops_)) {}
+
+ float getBase() const { return base; }
+ const std::vector<std::pair<float, T>>& getStops() const { return stops; }
+
+private:
+ float base = 1;
+ std::vector<std::pair<float, T>> stops;
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/layer.hpp b/include/mbgl/style/layer.hpp
new file mode 100644
index 0000000000..1eff9eb3dc
--- /dev/null
+++ b/include/mbgl/style/layer.hpp
@@ -0,0 +1,78 @@
+#pragma once
+
+#include <mbgl/util/noncopyable.hpp>
+#include <mbgl/style/types.hpp>
+
+#include <memory>
+
+namespace mbgl {
+namespace style {
+
+/**
+ * The runtime representation of a [layer](https://www.mapbox.com/mapbox-gl-style-spec/#layers) from the Mapbox Style
+ * Specification.
+ *
+ * `Layer` is an abstract base class; concrete derived classes are provided for each layer type. `Layer` contains
+ * functionality that is common to all layer types:
+ *
+ * * Runtime type information: type predicates and casting
+ * * Accessors for properties common to all layer types: ID, visibility, etc.
+ * * Cloning and copying
+ *
+ * All other functionality lives in the derived classes. To instantiate a layer, create an instance of the desired
+ * type, passing the ID:
+ *
+ * auto circleLayer = std::make_unique<CircleLayer>("my-circle-layer");
+ */
+class Layer : public mbgl::util::noncopyable {
+public:
+ virtual ~Layer();
+
+ // Check whether this layer is of the given subtype.
+ template <class T>
+ bool is() const;
+
+ // Dynamically cast this layer to the given subtype.
+ template <class T>
+ T* as() {
+ return is<T>() ? reinterpret_cast<T*>(this) : nullptr;
+ }
+
+ template <class T>
+ const T* as() const {
+ return is<T>() ? reinterpret_cast<const T*>(this) : nullptr;
+ }
+
+ const std::string& getID() const;
+
+ // Visibility
+ VisibilityType getVisibility() const;
+ void setVisibility(VisibilityType);
+
+ // Zoom range
+ float getMinZoom() const;
+ void setMinZoom(float) const;
+ float getMaxZoom() const;
+ void setMaxZoom(float) const;
+
+ // Private implementation
+ class Impl;
+ const std::unique_ptr<Impl> baseImpl;
+
+protected:
+ enum class Type {
+ Fill,
+ Line,
+ Circle,
+ Symbol,
+ Raster,
+ Background,
+ Custom,
+ };
+
+ const Type type;
+ Layer(Type, std::unique_ptr<Impl>);
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/layers/background_layer.hpp b/include/mbgl/style/layers/background_layer.hpp
new file mode 100644
index 0000000000..ac97ec2e6d
--- /dev/null
+++ b/include/mbgl/style/layers/background_layer.hpp
@@ -0,0 +1,45 @@
+// 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>
+
+namespace mbgl {
+namespace style {
+
+class BackgroundLayer : public Layer {
+public:
+ BackgroundLayer(const std::string& layerID);
+ ~BackgroundLayer() final;
+
+ // Paint properties
+
+ PropertyValue<Color> getBackgroundColor() const;
+ void setBackgroundColor(PropertyValue<Color>, const optional<std::string>& klass = {});
+
+ PropertyValue<std::string> getBackgroundPattern() const;
+ void setBackgroundPattern(PropertyValue<std::string>, const optional<std::string>& klass = {});
+
+ PropertyValue<float> getBackgroundOpacity() const;
+ void setBackgroundOpacity(PropertyValue<float>, const optional<std::string>& klass = {});
+
+ // Private implementation
+
+ class Impl;
+ Impl* const impl;
+
+ BackgroundLayer(const Impl&);
+ BackgroundLayer(const BackgroundLayer&) = delete;
+};
+
+template <>
+inline bool Layer::is<BackgroundLayer>() const {
+ return type == Type::Background;
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/layers/circle_layer.hpp b/include/mbgl/style/layers/circle_layer.hpp
new file mode 100644
index 0000000000..c8d99ab30e
--- /dev/null
+++ b/include/mbgl/style/layers/circle_layer.hpp
@@ -0,0 +1,62 @@
+// 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>
+
+namespace mbgl {
+namespace style {
+
+class CircleLayer : public Layer {
+public:
+ CircleLayer(const std::string& layerID, const std::string& sourceID);
+ ~CircleLayer() final;
+
+ // Source
+ const std::string& getSourceID() const;
+ const std::string& getSourceLayer() const;
+ void setSourceLayer(const std::string& sourceLayer);
+
+ void setFilter(const Filter&);
+ const Filter& getFilter() const;
+
+ // Paint properties
+
+ PropertyValue<float> getCircleRadius() const;
+ void setCircleRadius(PropertyValue<float>, const optional<std::string>& klass = {});
+
+ PropertyValue<Color> getCircleColor() const;
+ void setCircleColor(PropertyValue<Color>, const optional<std::string>& klass = {});
+
+ PropertyValue<float> getCircleBlur() const;
+ void setCircleBlur(PropertyValue<float>, const optional<std::string>& klass = {});
+
+ PropertyValue<float> getCircleOpacity() const;
+ void setCircleOpacity(PropertyValue<float>, const optional<std::string>& klass = {});
+
+ PropertyValue<std::array<float, 2>> getCircleTranslate() const;
+ void setCircleTranslate(PropertyValue<std::array<float, 2>>, const optional<std::string>& klass = {});
+
+ PropertyValue<TranslateAnchorType> getCircleTranslateAnchor() const;
+ void setCircleTranslateAnchor(PropertyValue<TranslateAnchorType>, const optional<std::string>& klass = {});
+
+ // Private implementation
+
+ class Impl;
+ Impl* const impl;
+
+ CircleLayer(const Impl&);
+ CircleLayer(const CircleLayer&) = delete;
+};
+
+template <>
+inline bool Layer::is<CircleLayer>() const {
+ return type == Type::Circle;
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/layers/custom_layer.hpp b/include/mbgl/style/layers/custom_layer.hpp
new file mode 100644
index 0000000000..d3867e2c4f
--- /dev/null
+++ b/include/mbgl/style/layers/custom_layer.hpp
@@ -0,0 +1,71 @@
+#pragma once
+
+#include <mbgl/style/layer.hpp>
+
+namespace mbgl {
+namespace style {
+
+/**
+ * Initialize any GL state needed by the custom layer. This method is called once, from the
+ * rendering thread, at a point when the GL context is active but before rendering for the
+ * first time.
+ *
+ * Resources that are acquired in this method must be released in the UninitializeFunction.
+ */
+using CustomLayerInitializeFunction = void (*)(void* context);
+
+/**
+ * Parameters that define the current camera position for a CustomLayerRenderFunction.
+ */
+struct CustomLayerRenderParameters {
+ double width;
+ double height;
+ double latitude;
+ double longitude;
+ double zoom;
+ double bearing;
+ double pitch;
+ double altitude;
+};
+
+/**
+ * Render the layer. This method is called once per frame. The implementation should not make
+ * any assumptions about the GL state (other than that the correct context is active). It may
+ * make changes to the state, and is not required to reset values such as the depth mask, stencil
+ * mask, and corresponding test flags to their original values.
+ */
+using CustomLayerRenderFunction = void (*)(void* context, const CustomLayerRenderParameters&);
+
+/**
+ * Destroy any GL state needed by the custom layer, and deallocate context, if necessary. This
+ * method is called once, from the rendering thread, at a point when the GL context is active.
+ *
+ * Note that it may be called even when the InitializeFunction has not been called.
+ */
+using CustomLayerDeinitializeFunction = void (*)(void* context);
+
+class CustomLayer : public Layer {
+public:
+ CustomLayer(const std::string& id,
+ CustomLayerInitializeFunction,
+ CustomLayerRenderFunction,
+ CustomLayerDeinitializeFunction,
+ void* context);
+ ~CustomLayer() final;
+
+ // Private implementation
+
+ class Impl;
+ Impl* impl;
+
+ CustomLayer(const Impl&);
+ CustomLayer(const CustomLayer&) = delete;
+};
+
+template <>
+inline bool Layer::is<CustomLayer>() const {
+ return type == Type::Custom;
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/layers/fill_layer.hpp b/include/mbgl/style/layers/fill_layer.hpp
new file mode 100644
index 0000000000..e70d67f538
--- /dev/null
+++ b/include/mbgl/style/layers/fill_layer.hpp
@@ -0,0 +1,65 @@
+// 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>
+
+namespace mbgl {
+namespace style {
+
+class FillLayer : public Layer {
+public:
+ FillLayer(const std::string& layerID, const std::string& sourceID);
+ ~FillLayer() final;
+
+ // Source
+ const std::string& getSourceID() const;
+ const std::string& getSourceLayer() const;
+ void setSourceLayer(const std::string& sourceLayer);
+
+ void setFilter(const Filter&);
+ const Filter& getFilter() const;
+
+ // Paint properties
+
+ PropertyValue<bool> getFillAntialias() const;
+ void setFillAntialias(PropertyValue<bool>, const optional<std::string>& klass = {});
+
+ PropertyValue<float> getFillOpacity() const;
+ void setFillOpacity(PropertyValue<float>, const optional<std::string>& klass = {});
+
+ PropertyValue<Color> getFillColor() const;
+ void setFillColor(PropertyValue<Color>, const optional<std::string>& klass = {});
+
+ PropertyValue<Color> getFillOutlineColor() const;
+ void setFillOutlineColor(PropertyValue<Color>, const optional<std::string>& klass = {});
+
+ PropertyValue<std::array<float, 2>> getFillTranslate() const;
+ void setFillTranslate(PropertyValue<std::array<float, 2>>, const optional<std::string>& klass = {});
+
+ PropertyValue<TranslateAnchorType> getFillTranslateAnchor() const;
+ void setFillTranslateAnchor(PropertyValue<TranslateAnchorType>, const optional<std::string>& klass = {});
+
+ PropertyValue<std::string> getFillPattern() const;
+ void setFillPattern(PropertyValue<std::string>, const optional<std::string>& klass = {});
+
+ // Private implementation
+
+ class Impl;
+ Impl* const impl;
+
+ FillLayer(const Impl&);
+ FillLayer(const FillLayer&) = delete;
+};
+
+template <>
+inline bool Layer::is<FillLayer>() const {
+ return type == Type::Fill;
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/layers/layer.hpp.ejs b/include/mbgl/style/layers/layer.hpp.ejs
new file mode 100644
index 0000000000..aaae30287c
--- /dev/null
+++ b/include/mbgl/style/layers/layer.hpp.ejs
@@ -0,0 +1,75 @@
+<%
+ 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) { -%>
+ PropertyValue<<%- propertyType(property) %>> get<%- camelize(property.name) %>() const;
+ void set<%- camelize(property.name) %>(PropertyValue<<%- propertyType(property) %>>);
+
+<% } -%>
+<% } -%>
+ // Paint properties
+
+<% for (const property of paintProperties) { -%>
+ PropertyValue<<%- propertyType(property) %>> get<%- camelize(property.name) %>() 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
new file mode 100644
index 0000000000..abcb425b96
--- /dev/null
+++ b/include/mbgl/style/layers/line_layer.hpp
@@ -0,0 +1,90 @@
+// 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>
+
+#include <vector>
+
+namespace mbgl {
+namespace style {
+
+class LineLayer : public Layer {
+public:
+ LineLayer(const std::string& layerID, const std::string& sourceID);
+ ~LineLayer() final;
+
+ // Source
+ const std::string& getSourceID() const;
+ const std::string& getSourceLayer() const;
+ void setSourceLayer(const std::string& sourceLayer);
+
+ void setFilter(const Filter&);
+ const Filter& getFilter() const;
+
+ // Layout properties
+
+ PropertyValue<LineCapType> getLineCap() const;
+ void setLineCap(PropertyValue<LineCapType>);
+
+ PropertyValue<LineJoinType> getLineJoin() const;
+ void setLineJoin(PropertyValue<LineJoinType>);
+
+ PropertyValue<float> getLineMiterLimit() const;
+ void setLineMiterLimit(PropertyValue<float>);
+
+ PropertyValue<float> getLineRoundLimit() const;
+ void setLineRoundLimit(PropertyValue<float>);
+
+ // Paint properties
+
+ PropertyValue<float> getLineOpacity() const;
+ void setLineOpacity(PropertyValue<float>, const optional<std::string>& klass = {});
+
+ PropertyValue<Color> getLineColor() const;
+ void setLineColor(PropertyValue<Color>, const optional<std::string>& klass = {});
+
+ PropertyValue<std::array<float, 2>> getLineTranslate() const;
+ void setLineTranslate(PropertyValue<std::array<float, 2>>, const optional<std::string>& klass = {});
+
+ PropertyValue<TranslateAnchorType> getLineTranslateAnchor() const;
+ void setLineTranslateAnchor(PropertyValue<TranslateAnchorType>, const optional<std::string>& klass = {});
+
+ PropertyValue<float> getLineWidth() const;
+ void setLineWidth(PropertyValue<float>, const optional<std::string>& klass = {});
+
+ PropertyValue<float> getLineGapWidth() const;
+ void setLineGapWidth(PropertyValue<float>, const optional<std::string>& klass = {});
+
+ PropertyValue<float> getLineOffset() const;
+ void setLineOffset(PropertyValue<float>, const optional<std::string>& klass = {});
+
+ PropertyValue<float> getLineBlur() const;
+ void setLineBlur(PropertyValue<float>, const optional<std::string>& klass = {});
+
+ PropertyValue<std::vector<float>> getLineDasharray() const;
+ void setLineDasharray(PropertyValue<std::vector<float>>, const optional<std::string>& klass = {});
+
+ PropertyValue<std::string> getLinePattern() const;
+ void setLinePattern(PropertyValue<std::string>, const optional<std::string>& klass = {});
+
+ // Private implementation
+
+ class Impl;
+ Impl* const impl;
+
+ LineLayer(const Impl&);
+ LineLayer(const LineLayer&) = delete;
+};
+
+template <>
+inline bool Layer::is<LineLayer>() const {
+ return type == Type::Line;
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/layers/raster_layer.hpp b/include/mbgl/style/layers/raster_layer.hpp
new file mode 100644
index 0000000000..dea0c26bf3
--- /dev/null
+++ b/include/mbgl/style/layers/raster_layer.hpp
@@ -0,0 +1,60 @@
+// 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>
+
+namespace mbgl {
+namespace style {
+
+class RasterLayer : public Layer {
+public:
+ RasterLayer(const std::string& layerID, const std::string& sourceID);
+ ~RasterLayer() final;
+
+ // Source
+ const std::string& getSourceID() const;
+
+ // Paint properties
+
+ PropertyValue<float> getRasterOpacity() const;
+ void setRasterOpacity(PropertyValue<float>, const optional<std::string>& klass = {});
+
+ PropertyValue<float> getRasterHueRotate() const;
+ void setRasterHueRotate(PropertyValue<float>, const optional<std::string>& klass = {});
+
+ PropertyValue<float> getRasterBrightnessMin() const;
+ void setRasterBrightnessMin(PropertyValue<float>, const optional<std::string>& klass = {});
+
+ PropertyValue<float> getRasterBrightnessMax() const;
+ void setRasterBrightnessMax(PropertyValue<float>, const optional<std::string>& klass = {});
+
+ PropertyValue<float> getRasterSaturation() const;
+ void setRasterSaturation(PropertyValue<float>, const optional<std::string>& klass = {});
+
+ PropertyValue<float> getRasterContrast() const;
+ void setRasterContrast(PropertyValue<float>, const optional<std::string>& klass = {});
+
+ PropertyValue<float> getRasterFadeDuration() const;
+ void setRasterFadeDuration(PropertyValue<float>, const optional<std::string>& klass = {});
+
+ // Private implementation
+
+ class Impl;
+ Impl* const impl;
+
+ RasterLayer(const Impl&);
+ RasterLayer(const RasterLayer&) = delete;
+};
+
+template <>
+inline bool Layer::is<RasterLayer>() const {
+ return type == Type::Raster;
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/layers/symbol_layer.hpp b/include/mbgl/style/layers/symbol_layer.hpp
new file mode 100644
index 0000000000..77b63d9b91
--- /dev/null
+++ b/include/mbgl/style/layers/symbol_layer.hpp
@@ -0,0 +1,192 @@
+// 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>
+
+#include <vector>
+
+namespace mbgl {
+namespace style {
+
+class SymbolLayer : public Layer {
+public:
+ SymbolLayer(const std::string& layerID, const std::string& sourceID);
+ ~SymbolLayer() final;
+
+ // Source
+ const std::string& getSourceID() const;
+ const std::string& getSourceLayer() const;
+ void setSourceLayer(const std::string& sourceLayer);
+
+ void setFilter(const Filter&);
+ const Filter& getFilter() const;
+
+ // Layout properties
+
+ PropertyValue<SymbolPlacementType> getSymbolPlacement() const;
+ void setSymbolPlacement(PropertyValue<SymbolPlacementType>);
+
+ PropertyValue<float> getSymbolSpacing() const;
+ void setSymbolSpacing(PropertyValue<float>);
+
+ PropertyValue<bool> getSymbolAvoidEdges() const;
+ void setSymbolAvoidEdges(PropertyValue<bool>);
+
+ PropertyValue<bool> getIconAllowOverlap() const;
+ void setIconAllowOverlap(PropertyValue<bool>);
+
+ PropertyValue<bool> getIconIgnorePlacement() const;
+ void setIconIgnorePlacement(PropertyValue<bool>);
+
+ PropertyValue<bool> getIconOptional() const;
+ void setIconOptional(PropertyValue<bool>);
+
+ PropertyValue<AlignmentType> getIconRotationAlignment() const;
+ void setIconRotationAlignment(PropertyValue<AlignmentType>);
+
+ PropertyValue<float> getIconSize() const;
+ void setIconSize(PropertyValue<float>);
+
+ PropertyValue<IconTextFitType> getIconTextFit() const;
+ void setIconTextFit(PropertyValue<IconTextFitType>);
+
+ PropertyValue<std::array<float, 4>> getIconTextFitPadding() const;
+ void setIconTextFitPadding(PropertyValue<std::array<float, 4>>);
+
+ PropertyValue<std::string> getIconImage() const;
+ void setIconImage(PropertyValue<std::string>);
+
+ PropertyValue<float> getIconRotate() const;
+ void setIconRotate(PropertyValue<float>);
+
+ PropertyValue<float> getIconPadding() const;
+ void setIconPadding(PropertyValue<float>);
+
+ PropertyValue<bool> getIconKeepUpright() const;
+ void setIconKeepUpright(PropertyValue<bool>);
+
+ PropertyValue<std::array<float, 2>> getIconOffset() const;
+ void setIconOffset(PropertyValue<std::array<float, 2>>);
+
+ PropertyValue<AlignmentType> getTextPitchAlignment() const;
+ void setTextPitchAlignment(PropertyValue<AlignmentType>);
+
+ PropertyValue<AlignmentType> getTextRotationAlignment() const;
+ void setTextRotationAlignment(PropertyValue<AlignmentType>);
+
+ PropertyValue<std::string> getTextField() const;
+ void setTextField(PropertyValue<std::string>);
+
+ PropertyValue<std::vector<std::string>> getTextFont() const;
+ void setTextFont(PropertyValue<std::vector<std::string>>);
+
+ PropertyValue<float> getTextSize() const;
+ void setTextSize(PropertyValue<float>);
+
+ PropertyValue<float> getTextMaxWidth() const;
+ void setTextMaxWidth(PropertyValue<float>);
+
+ PropertyValue<float> getTextLineHeight() const;
+ void setTextLineHeight(PropertyValue<float>);
+
+ PropertyValue<float> getTextLetterSpacing() const;
+ void setTextLetterSpacing(PropertyValue<float>);
+
+ PropertyValue<TextJustifyType> getTextJustify() const;
+ void setTextJustify(PropertyValue<TextJustifyType>);
+
+ PropertyValue<TextAnchorType> getTextAnchor() const;
+ void setTextAnchor(PropertyValue<TextAnchorType>);
+
+ PropertyValue<float> getTextMaxAngle() const;
+ void setTextMaxAngle(PropertyValue<float>);
+
+ PropertyValue<float> getTextRotate() const;
+ void setTextRotate(PropertyValue<float>);
+
+ PropertyValue<float> getTextPadding() const;
+ void setTextPadding(PropertyValue<float>);
+
+ PropertyValue<bool> getTextKeepUpright() const;
+ void setTextKeepUpright(PropertyValue<bool>);
+
+ PropertyValue<TextTransformType> getTextTransform() const;
+ void setTextTransform(PropertyValue<TextTransformType>);
+
+ PropertyValue<std::array<float, 2>> getTextOffset() const;
+ void setTextOffset(PropertyValue<std::array<float, 2>>);
+
+ PropertyValue<bool> getTextAllowOverlap() const;
+ void setTextAllowOverlap(PropertyValue<bool>);
+
+ PropertyValue<bool> getTextIgnorePlacement() const;
+ void setTextIgnorePlacement(PropertyValue<bool>);
+
+ PropertyValue<bool> getTextOptional() const;
+ void setTextOptional(PropertyValue<bool>);
+
+ // Paint properties
+
+ PropertyValue<float> getIconOpacity() const;
+ void setIconOpacity(PropertyValue<float>, const optional<std::string>& klass = {});
+
+ PropertyValue<Color> getIconColor() const;
+ void setIconColor(PropertyValue<Color>, const optional<std::string>& klass = {});
+
+ PropertyValue<Color> getIconHaloColor() const;
+ void setIconHaloColor(PropertyValue<Color>, const optional<std::string>& klass = {});
+
+ PropertyValue<float> getIconHaloWidth() const;
+ void setIconHaloWidth(PropertyValue<float>, const optional<std::string>& klass = {});
+
+ PropertyValue<float> getIconHaloBlur() const;
+ void setIconHaloBlur(PropertyValue<float>, const optional<std::string>& klass = {});
+
+ PropertyValue<std::array<float, 2>> getIconTranslate() const;
+ void setIconTranslate(PropertyValue<std::array<float, 2>>, const optional<std::string>& klass = {});
+
+ PropertyValue<TranslateAnchorType> getIconTranslateAnchor() const;
+ void setIconTranslateAnchor(PropertyValue<TranslateAnchorType>, const optional<std::string>& klass = {});
+
+ PropertyValue<float> getTextOpacity() const;
+ void setTextOpacity(PropertyValue<float>, const optional<std::string>& klass = {});
+
+ PropertyValue<Color> getTextColor() const;
+ void setTextColor(PropertyValue<Color>, const optional<std::string>& klass = {});
+
+ PropertyValue<Color> getTextHaloColor() const;
+ void setTextHaloColor(PropertyValue<Color>, const optional<std::string>& klass = {});
+
+ PropertyValue<float> getTextHaloWidth() const;
+ void setTextHaloWidth(PropertyValue<float>, const optional<std::string>& klass = {});
+
+ PropertyValue<float> getTextHaloBlur() const;
+ void setTextHaloBlur(PropertyValue<float>, const optional<std::string>& klass = {});
+
+ PropertyValue<std::array<float, 2>> getTextTranslate() const;
+ void setTextTranslate(PropertyValue<std::array<float, 2>>, const optional<std::string>& klass = {});
+
+ PropertyValue<TranslateAnchorType> getTextTranslateAnchor() const;
+ void setTextTranslateAnchor(PropertyValue<TranslateAnchorType>, const optional<std::string>& klass = {});
+
+ // Private implementation
+
+ class Impl;
+ Impl* const impl;
+
+ SymbolLayer(const Impl&);
+ SymbolLayer(const SymbolLayer&) = delete;
+};
+
+template <>
+inline bool Layer::is<SymbolLayer>() const {
+ return type == Type::Symbol;
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/property_transition.hpp b/include/mbgl/style/property_transition.hpp
deleted file mode 100644
index b9a301feea..0000000000
--- a/include/mbgl/style/property_transition.hpp
+++ /dev/null
@@ -1,17 +0,0 @@
-#pragma once
-
-#include <mbgl/util/chrono.hpp>
-#include <mbgl/util/optional.hpp>
-
-namespace mbgl {
-
-class PropertyTransition {
-public:
- PropertyTransition(const optional<Duration>& duration_ = {}, const optional<Duration>& delay_ = {})
- : duration(duration_), delay(delay_) {}
-
- optional<Duration> duration;
- optional<Duration> delay;
-};
-
-} // namespace mbgl
diff --git a/include/mbgl/style/property_value.hpp b/include/mbgl/style/property_value.hpp
new file mode 100644
index 0000000000..d8f83a0fb3
--- /dev/null
+++ b/include/mbgl/style/property_value.hpp
@@ -0,0 +1,38 @@
+#pragma once
+
+#include <mbgl/util/variant.hpp>
+#include <mbgl/style/function.hpp>
+
+namespace mbgl {
+namespace style {
+
+class Undefined {};
+
+template <class T>
+class PropertyValue {
+private:
+ using Value = variant<Undefined, T, Function<T>>;
+ Value value;
+
+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; }
+
+ const T & asConstant() const { return value.template get< T >(); }
+ const Function<T>& asFunction() const { return value.template get<Function<T>>(); }
+
+ explicit operator bool() const { return !isUndefined(); };
+
+ template <typename Visitor>
+ static auto visit(const PropertyValue<T>& value, Visitor&& visitor) {
+ return Value::visit(value.value, visitor);
+ }
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/source.hpp b/include/mbgl/style/source.hpp
new file mode 100644
index 0000000000..92341066b1
--- /dev/null
+++ b/include/mbgl/style/source.hpp
@@ -0,0 +1,63 @@
+#pragma once
+
+#include <mbgl/util/noncopyable.hpp>
+#include <mbgl/style/types.hpp>
+
+#include <memory>
+#include <string>
+
+namespace mbgl {
+namespace style {
+
+/**
+ * The runtime representation of a [source](https://www.mapbox.com/mapbox-gl-style-spec/#sources) from the Mapbox Style
+ * Specification.
+ *
+ * `Source` is an abstract base class; concrete derived classes are provided for each source type. `Source` contains
+ * functionality that is common to all layer types:
+ *
+ * * Runtime type information: type predicates and casting
+ * * Accessors for properties common to all source types: ID, etc.
+ * * Cloning and copying
+ *
+ * All other functionality lives in the derived classes. To instantiate a source, create an instance of the desired
+ * type, passing the ID:
+ *
+ * auto vectorSource = std::make_unique<VectorSource>("my-vector-source");
+ */
+class Source : public mbgl::util::noncopyable {
+public:
+ virtual ~Source();
+
+ // Check whether this source is of the given subtype.
+ template <class T>
+ bool is() const;
+
+ // Dynamically cast this source to the given subtype.
+ template <class T>
+ T* as() {
+ return is<T>() ? reinterpret_cast<T*>(this) : nullptr;
+ }
+
+ template <class T>
+ const T* as() const {
+ 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;
+
+ // Private implementation
+ class Impl;
+ const std::unique_ptr<Impl> baseImpl;
+
+protected:
+ const SourceType type;
+ Source(SourceType, std::unique_ptr<Impl>);
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/sources/geojson_source.hpp b/include/mbgl/style/sources/geojson_source.hpp
new file mode 100644
index 0000000000..3736dd44bc
--- /dev/null
+++ b/include/mbgl/style/sources/geojson_source.hpp
@@ -0,0 +1,23 @@
+#pragma once
+
+#include <mbgl/style/source.hpp>
+#include <mbgl/util/geojson.hpp>
+
+namespace mbgl {
+namespace style {
+
+class GeoJSONSource : public Source {
+public:
+ GeoJSONSource(const std::string& id);
+
+ void setURL(const std::string& url);
+ void setGeoJSON(GeoJSON&&);
+
+ // Private implementation
+
+ class Impl;
+ Impl* const impl;
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/sources/raster_source.hpp b/include/mbgl/style/sources/raster_source.hpp
new file mode 100644
index 0000000000..2d1d648eec
--- /dev/null
+++ b/include/mbgl/style/sources/raster_source.hpp
@@ -0,0 +1,20 @@
+#pragma once
+
+#include <mbgl/style/source.hpp>
+#include <mbgl/util/tileset.hpp>
+#include <mbgl/util/variant.hpp>
+
+namespace mbgl {
+namespace style {
+
+class RasterSource : public Source {
+public:
+ RasterSource(std::string id, variant<std::string, Tileset> urlOrTileset, uint16_t tileSize);
+
+ // Private implementation
+
+ class Impl;
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/sources/vector_source.hpp b/include/mbgl/style/sources/vector_source.hpp
new file mode 100644
index 0000000000..3d53362734
--- /dev/null
+++ b/include/mbgl/style/sources/vector_source.hpp
@@ -0,0 +1,20 @@
+#pragma once
+
+#include <mbgl/style/source.hpp>
+#include <mbgl/util/tileset.hpp>
+#include <mbgl/util/variant.hpp>
+
+namespace mbgl {
+namespace style {
+
+class VectorSource : public Source {
+public:
+ VectorSource(std::string id, variant<std::string, Tileset> urlOrTileset);
+
+ // Private implementation
+
+ class Impl;
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/transition_options.hpp b/include/mbgl/style/transition_options.hpp
new file mode 100644
index 0000000000..d7a6633f0c
--- /dev/null
+++ b/include/mbgl/style/transition_options.hpp
@@ -0,0 +1,15 @@
+#pragma once
+
+#include <mbgl/util/chrono.hpp>
+#include <mbgl/util/optional.hpp>
+
+namespace mbgl {
+namespace style {
+
+struct TransitionOptions {
+ optional<Duration> duration = {};
+ optional<Duration> delay = {};
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/types.hpp b/include/mbgl/style/types.hpp
index 9b03ab8a2d..28ebda9fb9 100644
--- a/include/mbgl/style/types.hpp
+++ b/include/mbgl/style/types.hpp
@@ -1,27 +1,10 @@
#pragma once
-#include <mbgl/util/enum.hpp>
-
-#include <string>
-#include <array>
-#include <vector>
+#include <cstdint>
namespace mbgl {
-// Stores a premultiplied color, with all four channels ranging from 0..1
-using Color = std::array<float, 4>;
-
-// An array of font names
-using FontStack = std::vector<std::string>;
-
-std::string fontStackToString(const FontStack&);
-
-struct FontStackHash {
- std::size_t operator()(const FontStack&) const;
-};
-
-// -------------------------------------------------------------------------------------------------
-
+// TODO: should be in public source.hpp header and style namespace
enum class SourceType : uint8_t {
Vector,
Raster,
@@ -30,15 +13,7 @@ enum class SourceType : uint8_t {
Annotations
};
-MBGL_DEFINE_ENUM_CLASS(SourceTypeClass, SourceType, {
- { SourceType::Vector, "vector" },
- { SourceType::Raster, "raster" },
- { SourceType::GeoJSON, "geojson" },
- { SourceType::Video, "video" },
- { SourceType::Annotations, "annotations" },
-});
-
-// -------------------------------------------------------------------------------------------------
+namespace style {
enum class VisibilityType : bool {
Visible,
@@ -75,9 +50,10 @@ enum class SymbolPlacementType : bool {
Line,
};
-enum class RotationAlignmentType : bool {
+enum class AlignmentType : uint8_t {
Map,
Viewport,
+ Undefined,
};
enum class TextJustifyType : uint8_t {
@@ -104,44 +80,12 @@ enum class TextTransformType : uint8_t {
Lowercase,
};
-/**
- * Initialize any GL state needed by the custom layer. This method is called once, from the
- * rendering thread, at a point when the GL context is active but before rendering for the
- * first time.
- *
- * Resources that are acquired in this method must be released in the UninitializeFunction.
- */
-using CustomLayerInitializeFunction = void (*)(void* context);
-
-/**
- * Parameters that define the current camera position for a CustomLayerRenderFunction.
- */
-struct CustomLayerRenderParameters {
- double width;
- double height;
- double latitude;
- double longitude;
- double zoom;
- double bearing;
- double pitch;
- double altitude;
+enum class IconTextFitType : uint8_t {
+ None,
+ Both,
+ Width,
+ Height
};
-/**
- * Render the layer. This method is called once per frame. The implementation should not make
- * any assumptions about the GL state (other than that the correct context is active). It may
- * make changes to the state, and is not required to reset values such as the depth mask, stencil
- * mask, and corresponding test flags to their original values.
- */
-using CustomLayerRenderFunction = void (*)(void* context, const CustomLayerRenderParameters&);
-
-/**
- * Destroy any GL state needed by the custom layer, and deallocate context, if necessary. This
- * method is called once, from the rendering thread, at a point when the GL context is active.
- *
- * Note that it may be called even when the InitializeFunction has not been called.
- */
-using CustomLayerDeinitializeFunction = void (*)(void* context);
-
+} // namespace style
} // namespace mbgl
-
diff --git a/include/mbgl/util/color.hpp b/include/mbgl/util/color.hpp
new file mode 100644
index 0000000000..4be380fde3
--- /dev/null
+++ b/include/mbgl/util/color.hpp
@@ -0,0 +1,40 @@
+#pragma once
+
+#include <mbgl/util/optional.hpp>
+
+#include <string>
+
+namespace mbgl {
+
+// Stores a premultiplied color, with all four channels ranging from 0..1
+class Color {
+public:
+ float r = 0.0f;
+ float g = 0.0f;
+ float b = 0.0f;
+ float a = 0.0f;
+
+ static constexpr Color black() { return { 0.0f, 0.0f, 0.0f, 1.0f }; };
+ static constexpr Color white() { return { 1.0f, 1.0f, 1.0f, 1.0f }; };
+
+ static optional<Color> parse(const std::string&);
+};
+
+constexpr bool operator==(const Color& colorA, const Color& colorB) {
+ return colorA.r == colorB.r && colorA.g == colorB.g && colorA.b == colorB.b && colorA.a == colorB.a;
+}
+
+constexpr bool operator!=(const Color& colorA, const Color& colorB) {
+ return !(colorA == colorB);
+}
+
+constexpr Color operator*(const Color& color, float alpha) {
+ return {
+ color.r * alpha,
+ color.g * alpha,
+ color.b * alpha,
+ color.a * alpha
+ };
+}
+
+} // namespace mbgl
diff --git a/include/mbgl/util/constants.hpp b/include/mbgl/util/constants.hpp
index 621fc1820e..3c0b3eb93e 100644
--- a/include/mbgl/util/constants.hpp
+++ b/include/mbgl/util/constants.hpp
@@ -1,6 +1,7 @@
#pragma once
#include <mbgl/util/chrono.hpp>
+#include <mbgl/util/unitbezier.hpp>
#include <cmath>
#include <string>
@@ -17,7 +18,7 @@ constexpr float tileSize = 512;
* In practice, all features are converted to this extent before being added.
*
* Positions are stored as signed 16bit integers.
- * One bit is lost for signedness to support featuers extending past the left edge of the tile.
+ * One bit is lost for signedness to support features extending past the left edge of the tile.
* One bit is lost because the line vertex buffer packs 1 bit of other data into the int.
* One bit is lost to support features extending past the extent on the right edge of the tile.
* This leaves us with 2^13 = 8192
@@ -35,11 +36,13 @@ constexpr double PITCH_MAX = M_PI / 3;
constexpr double MIN_ZOOM = 0.0;
constexpr double MAX_ZOOM = 25.5;
-constexpr uint64_t DEFAULT_MAX_CACHE_SIZE = 50 * 1024 * 1024;;
+constexpr uint64_t DEFAULT_MAX_CACHE_SIZE = 50 * 1024 * 1024;
constexpr Duration DEFAULT_FADE_DURATION = Milliseconds(300);
constexpr Seconds CLOCK_SKEW_RETRY_TIMEOUT { 30 };
+constexpr UnitBezier DEFAULT_TRANSITION_EASE = { 0, 0, 0.25, 1 };
+
} // namespace util
namespace debug {
diff --git a/include/mbgl/util/convert.hpp b/include/mbgl/util/convert.hpp
new file mode 100644
index 0000000000..c2b3d9950d
--- /dev/null
+++ b/include/mbgl/util/convert.hpp
@@ -0,0 +1,17 @@
+#include <array>
+#include <type_traits>
+#include <utility>
+
+namespace mbgl {
+namespace util {
+
+template<typename To, typename From, std::size_t Size,
+ typename = std::enable_if_t<std::is_convertible<From, To>::value>>
+constexpr std::array<To, Size> convert(const std::array<From, Size>&from) {
+ std::array<To, Size> to {};
+ std::copy(std::begin(from), std::end(from), std::begin(to));
+ return to;
+}
+
+} // namespace util
+} // namespace mbgl
diff --git a/include/mbgl/util/enum.hpp b/include/mbgl/util/enum.hpp
index 3fbf313aed..48ffda463e 100644
--- a/include/mbgl/util/enum.hpp
+++ b/include/mbgl/util/enum.hpp
@@ -1,52 +1,36 @@
#pragma once
-#include <iosfwd>
+#include <mbgl/util/optional.hpp>
+
+#include <algorithm>
+#include <cassert>
#include <string>
namespace mbgl {
-template <typename Type>
-struct EnumValue {
- const Type value;
- const char *name;
-};
-
-template <typename EnumName, const EnumValue<EnumName> *names, const size_t length>
-struct Enum {
- using Type = EnumName;
- Type value;
- static const constexpr size_t l = length;
-private:
- static constexpr inline bool compare(const char *a, const char *b) {
- return *a == *b && (*a == '\0' || compare(a + 1, b + 1));
- }
- static constexpr inline const char *lookup_type(Type e, EnumValue<Type> const * const list, size_t r) {
- return r == 0 ? "" : list->value == e ? list->name : lookup_type(e, list + 1, r - 1);
- }
- static constexpr inline Type lookup_name(const char *n, EnumValue<Type> const * const list, size_t r) {
- return r == 0 ? Type(-1) : compare(list->name, n) ? list->value : lookup_name(n, list + 1, r - 1);
- }
+template <typename T>
+class Enum {
public:
- inline constexpr Enum(const char *n) : value(lookup_name(n, names, length)) {}
- inline constexpr Enum(const std::string &n) : value(lookup_name(n.c_str(), names, length)) {}
- inline constexpr Enum(Type t) : value(t) {}
-
- inline void operator=(const char *n) { value = lookup_name(n, names, length); }
- inline void operator=(const std::string &n) { *this = n.c_str(); }
- inline void operator=(Type t) { value = t; }
+ using Value = std::pair<const T, const char *>;
- inline constexpr bool valid() const { return value != Type(-1); }
+ 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;
+ }
- inline constexpr const char *c_str() const { return lookup_type(value, names, length); }
- inline std::string str() const { return c_str(); }
+ 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;
+ }
- inline constexpr operator Type() const { return value; }
+private:
+ static const Value* begin;
+ static const Value* end;
};
-#define MBGL_DEFINE_ENUM_CLASS(name, type, strings...) \
- const constexpr ::mbgl::EnumValue<type> type##_names[] = strings; \
- using name = ::mbgl::Enum<type, type##_names, sizeof(type##_names) / sizeof(::mbgl::EnumValue<type>)>; \
- inline std::ostream& operator<<(std::ostream& os, type t) { return os << name(t).str(); }
+#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)
} // namespace mbgl
-
diff --git a/include/mbgl/util/exception.hpp b/include/mbgl/util/exception.hpp
index b73a94fcd2..7c331636d4 100644
--- a/include/mbgl/util/exception.hpp
+++ b/include/mbgl/util/exception.hpp
@@ -6,23 +6,23 @@ namespace mbgl {
namespace util {
struct Exception : std::runtime_error {
- inline Exception(const char *msg) : std::runtime_error(msg) {}
- inline Exception(const std::string &msg) : std::runtime_error(msg) {}
+ Exception(const char *msg) : std::runtime_error(msg) {}
+ Exception(const std::string &msg) : std::runtime_error(msg) {}
};
struct SpriteImageException : Exception {
- inline SpriteImageException(const char *msg) : Exception(msg) {}
- inline SpriteImageException(const std::string &msg) : Exception(msg) {}
+ SpriteImageException(const char *msg) : Exception(msg) {}
+ SpriteImageException(const std::string &msg) : Exception(msg) {}
};
struct MisuseException : Exception {
- inline MisuseException(const char *msg) : Exception(msg) {}
- inline MisuseException(const std::string &msg) : Exception(msg) {}
+ MisuseException(const char *msg) : Exception(msg) {}
+ MisuseException(const std::string &msg) : Exception(msg) {}
};
struct ShaderException : Exception {
- inline ShaderException(const char *msg) : Exception(msg) {}
- inline ShaderException(const std::string &msg) : Exception(msg) {}
+ ShaderException(const char *msg) : Exception(msg) {}
+ ShaderException(const std::string &msg) : Exception(msg) {}
};
} // namespace util
diff --git a/include/mbgl/util/font_stack.hpp b/include/mbgl/util/font_stack.hpp
new file mode 100644
index 0000000000..d0b431e9ea
--- /dev/null
+++ b/include/mbgl/util/font_stack.hpp
@@ -0,0 +1,17 @@
+#pragma once
+
+#include <string>
+#include <vector>
+
+namespace mbgl {
+
+// An array of font names
+using FontStack = std::vector<std::string>;
+
+std::string fontStackToString(const FontStack&);
+
+struct FontStackHash {
+ std::size_t operator()(const FontStack&) const;
+};
+
+} // namespace mbgl
diff --git a/include/mbgl/util/geo.hpp b/include/mbgl/util/geo.hpp
index 7e15d5c2f1..a68058048d 100644
--- a/include/mbgl/util/geo.hpp
+++ b/include/mbgl/util/geo.hpp
@@ -57,18 +57,18 @@ public:
LatLng(const UnwrappedTileID& id);
};
-inline bool operator==(const LatLng& a, const LatLng& b) {
+constexpr bool operator==(const LatLng& a, const LatLng& b) {
return a.latitude == b.latitude && a.longitude == b.longitude;
}
-inline bool operator!=(const LatLng& a, const LatLng& b) {
+constexpr bool operator!=(const LatLng& a, const LatLng& b) {
return !(a == b);
}
class ProjectedMeters {
public:
- double northing = 0;
- double easting = 0;
+ double northing;
+ double easting;
ProjectedMeters(double n = 0, double e = 0)
: northing(n), easting(e) {}
@@ -78,6 +78,10 @@ public:
}
};
+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.
@@ -157,18 +161,18 @@ private:
LatLng sw;
LatLng ne;
- LatLngBounds(const LatLng& sw_, const LatLng& ne_)
- : sw(sw_), ne(ne_) {}
+ LatLngBounds(LatLng sw_, LatLng ne_)
+ : sw(std::move(sw_)), ne(std::move(ne_)) {}
- friend bool operator==(const LatLngBounds&, const LatLngBounds&);
- friend bool operator!=(const LatLngBounds&, const LatLngBounds&);
+ friend constexpr bool operator==(const LatLngBounds&, const LatLngBounds&);
+ friend constexpr bool operator!=(const LatLngBounds&, const LatLngBounds&);
};
-inline bool operator==(const LatLngBounds& a, const LatLngBounds& b) {
+constexpr bool operator==(const LatLngBounds& a, const LatLngBounds& b) {
return a.sw == b.sw && a.ne == b.ne;
}
-inline bool operator!=(const LatLngBounds& a, const LatLngBounds& b) {
+constexpr bool operator!=(const LatLngBounds& a, const LatLngBounds& b) {
return !(a == b);
}
diff --git a/include/mbgl/util/geojson.hpp b/include/mbgl/util/geojson.hpp
new file mode 100644
index 0000000000..3fd8c6ac4b
--- /dev/null
+++ b/include/mbgl/util/geojson.hpp
@@ -0,0 +1,22 @@
+#pragma once
+
+#include <memory>
+
+namespace mapbox {
+namespace geojsonvt {
+class GeoJSONVT;
+} // namespace geojsonvt
+} // namespace mapbox
+
+namespace mbgl {
+
+class GeoJSON {
+public:
+ GeoJSON(std::unique_ptr<mapbox::geojsonvt::GeoJSONVT>);
+ GeoJSON(GeoJSON&&);
+ ~GeoJSON();
+
+ std::unique_ptr<mapbox::geojsonvt::GeoJSONVT> impl;
+};
+
+} // namespace mbgl
diff --git a/include/mbgl/util/geometry.hpp b/include/mbgl/util/geometry.hpp
new file mode 100644
index 0000000000..7fc2668c2c
--- /dev/null
+++ b/include/mbgl/util/geometry.hpp
@@ -0,0 +1,44 @@
+#pragma once
+
+#include <mapbox/geometry/geometry.hpp>
+#include <mapbox/geometry/point_arithmetic.hpp>
+
+namespace mbgl {
+
+enum class FeatureType : uint8_t {
+ Unknown = 0,
+ Point = 1,
+ LineString = 2,
+ Polygon = 3
+};
+
+template <class T>
+using Point = mapbox::geometry::point<T>;
+
+template <class T>
+using LineString = mapbox::geometry::line_string<T>;
+
+template <class T>
+using Polygon = mapbox::geometry::polygon<T>;
+
+template <class T>
+using MultiPoint = mapbox::geometry::multi_point<T>;
+
+template <class T>
+using MultiLineString = mapbox::geometry::multi_line_string<T>;
+
+template <class T>
+using MultiPolygon = mapbox::geometry::multi_polygon<T>;
+
+template <class T>
+using LinearRing = mapbox::geometry::linear_ring<T>;
+
+template <class T>
+using Geometry = mapbox::geometry::geometry<T>;
+
+template <class S, class T>
+Point<S> convertPoint(const Point<T>& p) {
+ return Point<S>(p.x, p.y);
+}
+
+} // namespace mbgl
diff --git a/include/mbgl/util/image.hpp b/include/mbgl/util/image.hpp
index fbb0686a7b..124cdca7cd 100644
--- a/include/mbgl/util/image.hpp
+++ b/include/mbgl/util/image.hpp
@@ -1,5 +1,7 @@
#pragma once
+#include <mbgl/util/noncopyable.hpp>
+
#include <string>
#include <memory>
#include <algorithm>
@@ -12,7 +14,7 @@ enum ImageAlphaMode {
};
template <ImageAlphaMode Mode>
-class Image {
+class Image : private util::noncopyable {
public:
Image() = default;
@@ -26,6 +28,18 @@ public:
height(h),
data(std::move(data_)) {}
+ Image(Image&& o)
+ : width(o.width),
+ height(o.height),
+ data(std::move(o.data)) {}
+
+ Image& operator=(Image&& o) {
+ width = o.width;
+ height = o.height;
+ data = std::move(o.data);
+ return *this;
+ }
+
bool operator==(const Image& rhs) const {
return width == rhs.width && height == rhs.height &&
std::equal(data.get(), data.get() + size(), rhs.data.get(),
diff --git a/include/mbgl/util/projection.hpp b/include/mbgl/util/projection.hpp
index 8e1c994657..eb45088580 100644
--- a/include/mbgl/util/projection.hpp
+++ b/include/mbgl/util/projection.hpp
@@ -11,30 +11,32 @@ namespace mbgl {
class Projection {
public:
- static inline double getMetersPerPixelAtLatitude(double lat, double zoom) {
- const double mapPixelWidthAtZoom = std::pow(2.0, zoom) * util::tileSize;
+ static double getMetersPerPixelAtLatitude(double lat, double zoom) {
+ const double constrainedZoom = util::clamp(zoom, util::MIN_ZOOM, util::MAX_ZOOM);
+ const double mapPixelWidthAtZoom = std::pow(2.0, constrainedZoom) * util::tileSize;
const double constrainedLatitude = util::clamp(lat, -util::LATITUDE_MAX, util::LATITUDE_MAX);
-
return std::cos(constrainedLatitude * util::DEG2RAD) * util::M2PI * util::EARTH_RADIUS_M / mapPixelWidthAtZoom;
}
- static inline ProjectedMeters projectedMetersForLatLng(const LatLng& latLng) {
+ 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 m = 1 - 1e-15;
const double f = util::clamp(std::sin(util::DEG2RAD * constrainedLatitude), -m, m);
- const double easting = util::EARTH_RADIUS_M * latLng.longitude * util::DEG2RAD;
+ const double easting = util::EARTH_RADIUS_M * constrainedLongitude * util::DEG2RAD;
const double northing = 0.5 * util::EARTH_RADIUS_M * std::log((1 + f) / (1 - f));
return ProjectedMeters(northing, easting);
}
- static inline LatLng latLngForProjectedMeters(const ProjectedMeters& projectedMeters) {
+ static LatLng latLngForProjectedMeters(const ProjectedMeters& projectedMeters) {
double latitude = (2 * std::atan(std::exp(projectedMeters.northing / util::EARTH_RADIUS_M)) - (M_PI / 2)) * 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);
return LatLng(latitude, longitude);
}
diff --git a/include/mbgl/util/range.hpp b/include/mbgl/util/range.hpp
new file mode 100644
index 0000000000..8da2dd45bb
--- /dev/null
+++ b/include/mbgl/util/range.hpp
@@ -0,0 +1,25 @@
+#pragma once
+
+namespace mbgl {
+
+template <class T>
+class Range {
+public:
+ Range(const T& min_, const T& max_)
+ : min(min_), max(max_) {}
+
+ T min;
+ T max;
+};
+
+template <class T>
+bool operator==(const Range<T>& a, const Range<T>& b) {
+ return a.min == b.min && a.max == b.max;
+}
+
+template <class T>
+bool operator!=(const Range<T>& a, const Range<T>& b) {
+ return !(a == b);
+}
+
+} // namespace mbgl
diff --git a/include/mbgl/util/tileset.hpp b/include/mbgl/util/tileset.hpp
new file mode 100644
index 0000000000..8a7fbe9b73
--- /dev/null
+++ b/include/mbgl/util/tileset.hpp
@@ -0,0 +1,20 @@
+#pragma once
+
+#include <mbgl/util/range.hpp>
+
+#include <vector>
+#include <string>
+#include <cstdint>
+
+namespace mbgl {
+
+class Tileset {
+public:
+ std::vector<std::string> tiles;
+ Range<uint8_t> zoomRange { 0, 22 };
+ std::string attribution;
+
+ // TileJSON also includes center, zoom, and bounds, but they are not used by mbgl.
+};
+
+} // namespace mbgl
diff --git a/include/mbgl/util/traits.hpp b/include/mbgl/util/traits.hpp
index 7c9499897e..9d6f947cd2 100644
--- a/include/mbgl/util/traits.hpp
+++ b/include/mbgl/util/traits.hpp
@@ -5,8 +5,8 @@
namespace mbgl {
template<typename T>
-constexpr auto underlying_type(T t) -> typename std::underlying_type<T>::type {
- return static_cast<typename std::underlying_type<T>::type>(t);
+constexpr auto underlying_type(T t) -> typename std::underlying_type_t<T> {
+ return typename std::underlying_type_t<T>(t);
}
} // namespace mbgl
diff --git a/include/mbgl/util/unitbezier.hpp b/include/mbgl/util/unitbezier.hpp
index ce3e78f3cc..3a4994917b 100644
--- a/include/mbgl/util/unitbezier.hpp
+++ b/include/mbgl/util/unitbezier.hpp
@@ -31,32 +31,31 @@ namespace mbgl {
namespace util {
struct UnitBezier {
- UnitBezier(double p1x, double p1y, double p2x, double p2y) {
- // Calculate the polynomial coefficients, implicit first and last control points are (0,0) and (1,1).
- cx = 3.0 * p1x;
- bx = 3.0 * (p2x - p1x) - cx;
- ax = 1.0 - cx - bx;
-
- cy = 3.0 * p1y;
- by = 3.0 * (p2y - p1y) - cy;
- ay = 1.0 - cy - by;
+ // Calculate the polynomial coefficients, implicit first and last control points are (0,0) and (1,1).
+ constexpr UnitBezier(double p1x, double p1y, double p2x, double p2y)
+ : cx(3.0 * p1x)
+ , bx(3.0 * (p2x - p1x) - cx)
+ , ax(1.0 - cx - bx)
+ , cy(3.0 * p1y)
+ , by(3.0 * (p2y - p1y) - cy)
+ , ay(1.0 - cy - by) {
}
- double sampleCurveX(double t) {
+ double sampleCurveX(double t) const {
// `ax t^3 + bx t^2 + cx t' expanded using Horner's rule.
return ((ax * t + bx) * t + cx) * t;
}
- double sampleCurveY(double t) {
+ double sampleCurveY(double t) const {
return ((ay * t + by) * t + cy) * t;
}
- double sampleCurveDerivativeX(double t) {
+ double sampleCurveDerivativeX(double t) const {
return (3.0 * ax * t + 2.0 * bx) * t + cx;
}
// Given an x value, find a parametric value it came from.
- double solveCurveX(double x, double epsilon) {
+ double solveCurveX(double x, double epsilon) const {
double t0;
double t1;
double t2;
@@ -100,18 +99,18 @@ struct UnitBezier {
return t2;
}
- double solve(double x, double epsilon) {
+ double solve(double x, double epsilon) const {
return sampleCurveY(solveCurveX(x, epsilon));
}
private:
- double ax;
- double bx;
- double cx;
+ const double cx;
+ const double bx;
+ const double ax;
- double ay;
- double by;
- double cy;
+ const double cy;
+ const double by;
+ const double ay;
};
} // namespace util
diff --git a/include/mbgl/util/variant.hpp b/include/mbgl/util/variant.hpp
new file mode 100644
index 0000000000..68a1208a17
--- /dev/null
+++ b/include/mbgl/util/variant.hpp
@@ -0,0 +1,10 @@
+#pragma once
+
+#include <mapbox/variant.hpp>
+
+namespace mbgl {
+
+template <typename... T>
+using variant = mapbox::util::variant<T...>;
+
+} // namespace mbgl