summaryrefslogtreecommitdiff
path: root/src/mbgl/style
diff options
context:
space:
mode:
Diffstat (limited to 'src/mbgl/style')
-rw-r--r--src/mbgl/style/bucket_parameters.cpp (renamed from src/mbgl/style/style_bucket_parameters.cpp)6
-rw-r--r--src/mbgl/style/bucket_parameters.hpp (renamed from src/mbgl/style/style_bucket_parameters.hpp)7
-rw-r--r--src/mbgl/style/calculation_parameters.hpp30
-rw-r--r--src/mbgl/style/cascade_parameters.hpp22
-rw-r--r--src/mbgl/style/class_dictionary.cpp2
-rw-r--r--src/mbgl/style/class_dictionary.hpp2
-rw-r--r--src/mbgl/style/filter_evaluator.hpp2
-rw-r--r--src/mbgl/style/layer.cpp50
-rw-r--r--src/mbgl/style/layer_impl.cpp19
-rw-r--r--src/mbgl/style/layer_impl.hpp92
-rw-r--r--src/mbgl/style/layers/background_layer.cpp57
-rw-r--r--src/mbgl/style/layers/background_layer_impl.cpp28
-rw-r--r--src/mbgl/style/layers/background_layer_impl.hpp26
-rw-r--r--src/mbgl/style/layers/background_layer_properties.cpp31
-rw-r--r--src/mbgl/style/layers/background_layer_properties.hpp27
-rw-r--r--src/mbgl/style/layers/circle_layer.cpp105
-rw-r--r--src/mbgl/style/layers/circle_layer_impl.cpp62
-rw-r--r--src/mbgl/style/layers/circle_layer_impl.hpp33
-rw-r--r--src/mbgl/style/layers/circle_layer_properties.cpp40
-rw-r--r--src/mbgl/style/layers/circle_layer_properties.hpp30
-rw-r--r--src/mbgl/style/layers/custom_layer.cpp24
-rw-r--r--src/mbgl/style/layers/custom_layer_impl.cpp68
-rw-r--r--src/mbgl/style/layers/custom_layer_impl.hpp44
-rw-r--r--src/mbgl/style/layers/fill_layer.cpp113
-rw-r--r--src/mbgl/style/layers/fill_layer_impl.cpp68
-rw-r--r--src/mbgl/style/layers/fill_layer_impl.hpp33
-rw-r--r--src/mbgl/style/layers/fill_layer_properties.cpp43
-rw-r--r--src/mbgl/style/layers/fill_layer_properties.hpp31
-rw-r--r--src/mbgl/style/layers/line_layer.cpp165
-rw-r--r--src/mbgl/style/layers/line_layer_impl.cpp116
-rw-r--r--src/mbgl/style/layers/line_layer_impl.hpp40
-rw-r--r--src/mbgl/style/layers/line_layer_properties.cpp66
-rw-r--r--src/mbgl/style/layers/line_layer_properties.hpp45
-rw-r--r--src/mbgl/style/layers/raster_layer.cpp98
-rw-r--r--src/mbgl/style/layers/raster_layer_impl.cpp28
-rw-r--r--src/mbgl/style/layers/raster_layer_impl.hpp26
-rw-r--r--src/mbgl/style/layers/raster_layer_properties.cpp43
-rw-r--r--src/mbgl/style/layers/raster_layer_properties.hpp31
-rw-r--r--src/mbgl/style/layers/symbol_layer.cpp386
-rw-r--r--src/mbgl/style/layers/symbol_layer_impl.cpp82
-rw-r--r--src/mbgl/style/layers/symbol_layer_impl.hpp35
-rw-r--r--src/mbgl/style/layers/symbol_layer_properties.cpp132
-rw-r--r--src/mbgl/style/layers/symbol_layer_properties.hpp76
-rw-r--r--src/mbgl/style/layout_property.hpp4
-rw-r--r--src/mbgl/style/observer.hpp (renamed from src/mbgl/style/style_observer.hpp)14
-rw-r--r--src/mbgl/style/paint_property.hpp18
-rw-r--r--src/mbgl/style/parser.cpp (renamed from src/mbgl/style/style_parser.cpp)69
-rw-r--r--src/mbgl/style/parser.hpp (renamed from src/mbgl/style/style_parser.hpp)21
-rw-r--r--src/mbgl/style/property_evaluator.cpp5
-rw-r--r--src/mbgl/style/property_evaluator.hpp15
-rw-r--r--src/mbgl/style/property_parsing.cpp7
-rw-r--r--src/mbgl/style/property_parsing.hpp7
-rw-r--r--src/mbgl/style/property_value.hpp36
-rw-r--r--src/mbgl/style/query_parameters.hpp (renamed from src/mbgl/style/style_query_parameters.hpp)5
-rw-r--r--src/mbgl/style/render_item.hpp9
-rw-r--r--src/mbgl/style/source.cpp428
-rw-r--r--src/mbgl/style/source.hpp113
-rw-r--r--src/mbgl/style/source_observer.hpp25
-rw-r--r--src/mbgl/style/style.cpp52
-rw-r--r--src/mbgl/style/style.hpp39
-rw-r--r--src/mbgl/style/style_calculation_parameters.hpp28
-rw-r--r--src/mbgl/style/style_cascade_parameters.hpp20
-rw-r--r--src/mbgl/style/style_render_parameters.hpp15
-rw-r--r--src/mbgl/style/types.cpp16
-rw-r--r--src/mbgl/style/update_parameters.hpp (renamed from src/mbgl/style/style_update_parameters.hpp)12
-rw-r--r--src/mbgl/style/zoom_history.hpp36
66 files changed, 3182 insertions, 276 deletions
diff --git a/src/mbgl/style/style_bucket_parameters.cpp b/src/mbgl/style/bucket_parameters.cpp
index 0b4b2affcd..f3367d57e1 100644
--- a/src/mbgl/style/style_bucket_parameters.cpp
+++ b/src/mbgl/style/bucket_parameters.cpp
@@ -1,10 +1,11 @@
-#include <mbgl/style/style_bucket_parameters.hpp>
+#include <mbgl/style/bucket_parameters.hpp>
#include <mbgl/style/filter_evaluator.hpp>
#include <mbgl/tile/geometry_tile.hpp>
namespace mbgl {
+namespace style {
-void StyleBucketParameters::eachFilteredFeature(const Filter& filter,
+void BucketParameters::eachFilteredFeature(const Filter& filter,
std::function<void (const GeometryTileFeature&, std::size_t index, const std::string& layerName)> function) {
auto name = layer.getName();
for (std::size_t i = 0; !cancelled() && i < layer.featureCount(); i++) {
@@ -18,4 +19,5 @@ void StyleBucketParameters::eachFilteredFeature(const Filter& filter,
}
}
+} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/style_bucket_parameters.hpp b/src/mbgl/style/bucket_parameters.hpp
index 17639afae7..f85e1e17ef 100644
--- a/src/mbgl/style/style_bucket_parameters.hpp
+++ b/src/mbgl/style/bucket_parameters.hpp
@@ -18,9 +18,11 @@ class GlyphStore;
class CollisionTile;
class FeatureIndex;
-class StyleBucketParameters {
+namespace style {
+
+class BucketParameters {
public:
- StyleBucketParameters(const OverscaledTileID& tileID_,
+ BucketParameters(const OverscaledTileID& tileID_,
const GeometryTileLayer& layer_,
const std::atomic<bool>& obsolete_,
uintptr_t tileUID_,
@@ -59,4 +61,5 @@ public:
const MapMode mode;
};
+} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/calculation_parameters.hpp b/src/mbgl/style/calculation_parameters.hpp
new file mode 100644
index 0000000000..2afd7c4b34
--- /dev/null
+++ b/src/mbgl/style/calculation_parameters.hpp
@@ -0,0 +1,30 @@
+#pragma once
+
+#include <mbgl/map/zoom_history.hpp>
+#include <mbgl/util/chrono.hpp>
+
+namespace mbgl {
+namespace style {
+
+class CalculationParameters {
+public:
+ explicit CalculationParameters(float z_)
+ : z(z_) {}
+
+ CalculationParameters(float z_,
+ const TimePoint& now_,
+ const ZoomHistory& zoomHistory_,
+ const Duration& defaultFadeDuration_)
+ : z(z_),
+ now(now_),
+ zoomHistory(zoomHistory_),
+ defaultFadeDuration(defaultFadeDuration_) {}
+
+ float z;
+ TimePoint now;
+ ZoomHistory zoomHistory;
+ Duration defaultFadeDuration;
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/cascade_parameters.hpp b/src/mbgl/style/cascade_parameters.hpp
new file mode 100644
index 0000000000..4ad6da2ce3
--- /dev/null
+++ b/src/mbgl/style/cascade_parameters.hpp
@@ -0,0 +1,22 @@
+#pragma once
+
+#include <mbgl/util/chrono.hpp>
+#include <mbgl/style/class_dictionary.hpp>
+#include <mbgl/style/transition_options.hpp>
+
+#include <vector>
+
+namespace mbgl {
+namespace style {
+
+class TransitionOptions;
+
+class CascadeParameters {
+public:
+ std::vector<ClassID> classes;
+ TimePoint now;
+ TransitionOptions transition;
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/class_dictionary.cpp b/src/mbgl/style/class_dictionary.cpp
index 53ea5c1484..ec06ee7d9d 100644
--- a/src/mbgl/style/class_dictionary.cpp
+++ b/src/mbgl/style/class_dictionary.cpp
@@ -3,6 +3,7 @@
#include <pthread.h>
namespace mbgl {
+namespace style {
ClassDictionary::ClassDictionary() {}
@@ -46,4 +47,5 @@ ClassID ClassDictionary::normalize(ClassID id) {
}
}
+} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/class_dictionary.hpp b/src/mbgl/style/class_dictionary.hpp
index 703e27b438..c95773d7c3 100644
--- a/src/mbgl/style/class_dictionary.hpp
+++ b/src/mbgl/style/class_dictionary.hpp
@@ -5,6 +5,7 @@
#include <unordered_map>
namespace mbgl {
+namespace style {
enum class ClassID : uint32_t {
Fallback = 0, // These values are from the fallback properties
@@ -31,4 +32,5 @@ private:
uint32_t offset = 0;
};
+} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/filter_evaluator.hpp b/src/mbgl/style/filter_evaluator.hpp
index b607a0c658..e03beaa4d0 100644
--- a/src/mbgl/style/filter_evaluator.hpp
+++ b/src/mbgl/style/filter_evaluator.hpp
@@ -6,6 +6,7 @@
#include <type_traits>
namespace mbgl {
+namespace style {
class FilterEvaluator {
public:
@@ -159,3 +160,4 @@ private:
};
} // namespace mbgl
+} // namespace mbgl
diff --git a/src/mbgl/style/layer.cpp b/src/mbgl/style/layer.cpp
new file mode 100644
index 0000000000..342699a2c9
--- /dev/null
+++ b/src/mbgl/style/layer.cpp
@@ -0,0 +1,50 @@
+#include <mbgl/style/layer.hpp>
+#include <mbgl/style/layer_impl.hpp>
+
+namespace mbgl {
+namespace style {
+
+Layer::Layer(Type type_, std::unique_ptr<Impl> baseImpl_)
+ : baseImpl(std::move(baseImpl_)), type(type_) {
+}
+
+Layer::~Layer() = default;
+
+const std::string& Layer::getID() const {
+ return baseImpl->id;
+}
+
+VisibilityType Layer::getVisibility() const {
+ return baseImpl->visibility;
+}
+
+void Layer::setVisibility(VisibilityType value) {
+ baseImpl->visibility = value;
+}
+
+float Layer::getMinZoom() const {
+ return baseImpl->minZoom;
+}
+
+void Layer::setMinZoom(float minZoom) const {
+ baseImpl->minZoom = minZoom;
+}
+
+float Layer::getMaxZoom() const {
+ return baseImpl->maxZoom;
+}
+
+void Layer::setMaxZoom(float maxZoom) const {
+ baseImpl->maxZoom = maxZoom;
+}
+
+std::unique_ptr<Layer> Layer::copy(const std::string& id,
+ const std::string& ref) const {
+ std::unique_ptr<Layer> result = baseImpl->clone();
+ result->baseImpl->id = id;
+ result->baseImpl->ref = ref;
+ return result;
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layer_impl.cpp b/src/mbgl/style/layer_impl.cpp
new file mode 100644
index 0000000000..74cc80d253
--- /dev/null
+++ b/src/mbgl/style/layer_impl.cpp
@@ -0,0 +1,19 @@
+#include <mbgl/style/layer_impl.hpp>
+
+namespace mbgl {
+namespace style {
+
+const std::string& Layer::Impl::bucketName() const {
+ return ref.empty() ? id : ref;
+}
+
+bool Layer::Impl::hasRenderPass(RenderPass pass) const {
+ return bool(passes & pass);
+}
+
+bool Layer::Impl::needsRendering() const {
+ return passes != RenderPass::None && visibility != VisibilityType::None;
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layer_impl.hpp b/src/mbgl/style/layer_impl.hpp
new file mode 100644
index 0000000000..dcd5d9906b
--- /dev/null
+++ b/src/mbgl/style/layer_impl.hpp
@@ -0,0 +1,92 @@
+#pragma once
+
+#include <mbgl/style/layer.hpp>
+#include <mbgl/style/types.hpp>
+#include <mbgl/style/filter.hpp>
+#include <mbgl/renderer/render_pass.hpp>
+#include <mbgl/util/noncopyable.hpp>
+#include <mbgl/util/rapidjson.hpp>
+#include <mbgl/tile/geometry_tile.hpp>
+
+#include <memory>
+#include <string>
+#include <limits>
+
+namespace mbgl {
+
+class Bucket;
+
+namespace style {
+
+class CascadeParameters;
+class CalculationParameters;
+class BucketParameters;
+
+/**
+ * `Layer::Impl` contains the internal implementation of `Layer`: the details that need to be accessible to other parts
+ * of the code, but hidden from the public API. Like `Layer`, it is an abstract base class, with derived classes for
+ * each layer type.
+ *
+ * Members that are public in `Layer` are part of the public API for all layers.
+ * Members that are public in `FooLayer` are part of the public API for "foo" layers.
+ * Members that are public in `Layer::Impl` are part of the internal API for all layers.
+ * Members that are public in `FooLayer::Impl` are part of the internal API for "foo" layers.
+ * Members that are private in `FooLayer::Impl` are internal to "foo" layers.
+ */
+class Layer::Impl {
+public:
+ virtual ~Impl() = default;
+
+ // Create an identical copy of this layer.
+ virtual std::unique_ptr<Layer> clone() const = 0;
+
+ virtual void parseLayout(const JSValue& value) = 0;
+ virtual void parsePaints(const JSValue& value) = 0;
+
+ // If the layer has a ref, the ref. Otherwise, the id.
+ const std::string& bucketName() const;
+
+ // Partially evaluate paint properties based on a set of classes.
+ virtual void cascade(const CascadeParameters&) = 0;
+
+ // Fully evaluate cascaded paint properties based on a zoom level.
+ // Returns true if any paint properties have active transitions.
+ virtual bool recalculate(const CalculationParameters&) = 0;
+
+ virtual std::unique_ptr<Bucket> createBucket(BucketParameters&) const = 0;
+
+ // Checks whether this layer needs to be rendered in the given render pass.
+ bool hasRenderPass(RenderPass) const;
+
+ // Checks whether this layer can be rendered.
+ bool needsRendering() const;
+
+ virtual float getQueryRadius() const { return 0; }
+ virtual bool queryIntersectsGeometry(
+ const GeometryCollection&,
+ const GeometryCollection&,
+ const float,
+ const float) const { return false; };
+
+public:
+ std::string id;
+ std::string ref;
+ std::string source;
+ std::string sourceLayer;
+ Filter filter;
+ float minZoom = -std::numeric_limits<float>::infinity();
+ float maxZoom = std::numeric_limits<float>::infinity();
+ VisibilityType visibility = VisibilityType::Visible;
+
+protected:
+ Impl() = default;
+ Impl(const Impl&) = default;
+ Impl& operator=(const Impl&) = delete;
+
+ // Stores what render passes this layer is currently enabled for. This depends on the
+ // evaluated StyleProperties object and is updated accordingly.
+ RenderPass passes = RenderPass::None;
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layers/background_layer.cpp b/src/mbgl/style/layers/background_layer.cpp
new file mode 100644
index 0000000000..aeb4067503
--- /dev/null
+++ b/src/mbgl/style/layers/background_layer.cpp
@@ -0,0 +1,57 @@
+// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`.
+
+#include <mbgl/style/layers/background_layer.hpp>
+#include <mbgl/style/layers/background_layer_impl.hpp>
+
+namespace mbgl {
+namespace style {
+
+BackgroundLayer::BackgroundLayer(const std::string& layerID)
+ : Layer(Type::Background, std::make_unique<Impl>())
+ , impl(static_cast<Impl*>(baseImpl.get())) {
+ impl->id = layerID;
+}
+
+BackgroundLayer::BackgroundLayer(const Impl& other)
+ : Layer(Type::Background, std::make_unique<Impl>(other))
+ , impl(static_cast<Impl*>(baseImpl.get())) {
+}
+
+BackgroundLayer::~BackgroundLayer() = default;
+
+std::unique_ptr<Layer> BackgroundLayer::Impl::clone() const {
+ return std::make_unique<BackgroundLayer>(*this);
+}
+
+
+// Layout properties
+
+
+// Paint properties
+
+PropertyValue<Color> BackgroundLayer::getBackgroundColor() const {
+ return impl->paint.backgroundColor.get();
+}
+
+void BackgroundLayer::setBackgroundColor(PropertyValue<Color> value) {
+ impl->paint.backgroundColor.set(value);
+}
+
+PropertyValue<std::string> BackgroundLayer::getBackgroundPattern() const {
+ return impl->paint.backgroundPattern.get();
+}
+
+void BackgroundLayer::setBackgroundPattern(PropertyValue<std::string> value) {
+ impl->paint.backgroundPattern.set(value);
+}
+
+PropertyValue<float> BackgroundLayer::getBackgroundOpacity() const {
+ return impl->paint.backgroundOpacity.get();
+}
+
+void BackgroundLayer::setBackgroundOpacity(PropertyValue<float> value) {
+ impl->paint.backgroundOpacity.set(value);
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layers/background_layer_impl.cpp b/src/mbgl/style/layers/background_layer_impl.cpp
new file mode 100644
index 0000000000..0c09c5d158
--- /dev/null
+++ b/src/mbgl/style/layers/background_layer_impl.cpp
@@ -0,0 +1,28 @@
+#include <mbgl/style/layers/background_layer_impl.hpp>
+#include <mbgl/renderer/bucket.hpp>
+
+namespace mbgl {
+namespace style {
+
+void BackgroundLayer::Impl::parsePaints(const JSValue& layer) {
+ paint.parse(layer);
+}
+
+void BackgroundLayer::Impl::cascade(const CascadeParameters& parameters) {
+ paint.cascade(parameters);
+}
+
+bool BackgroundLayer::Impl::recalculate(const CalculationParameters& parameters) {
+ bool hasTransitions = paint.recalculate(parameters);
+
+ passes = paint.backgroundOpacity > 0 ? RenderPass::Translucent : RenderPass::None;
+
+ return hasTransitions;
+}
+
+std::unique_ptr<Bucket> BackgroundLayer::Impl::createBucket(BucketParameters&) const {
+ return nullptr;
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layers/background_layer_impl.hpp b/src/mbgl/style/layers/background_layer_impl.hpp
new file mode 100644
index 0000000000..19e2a062a4
--- /dev/null
+++ b/src/mbgl/style/layers/background_layer_impl.hpp
@@ -0,0 +1,26 @@
+#pragma once
+
+#include <mbgl/style/layer_impl.hpp>
+#include <mbgl/style/layers/background_layer.hpp>
+#include <mbgl/style/layers/background_layer_properties.hpp>
+
+namespace mbgl {
+namespace style {
+
+class BackgroundLayer::Impl : public Layer::Impl {
+public:
+ std::unique_ptr<Layer> clone() const override;
+
+ void parseLayout(const JSValue&) override {};
+ void parsePaints(const JSValue&) override;
+
+ void cascade(const CascadeParameters&) override;
+ bool recalculate(const CalculationParameters&) override;
+
+ std::unique_ptr<Bucket> createBucket(BucketParameters&) const override;
+
+ BackgroundPaintProperties paint;
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layers/background_layer_properties.cpp b/src/mbgl/style/layers/background_layer_properties.cpp
new file mode 100644
index 0000000000..a20cedf12c
--- /dev/null
+++ b/src/mbgl/style/layers/background_layer_properties.cpp
@@ -0,0 +1,31 @@
+// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`.
+
+#include <mbgl/style/layers/background_layer_properties.hpp>
+
+namespace mbgl {
+namespace style {
+
+void BackgroundPaintProperties::parse(const JSValue& value) {
+ backgroundColor.parse("background-color", value);
+ backgroundPattern.parse("background-pattern", value);
+ backgroundOpacity.parse("background-opacity", value);
+}
+
+void BackgroundPaintProperties::cascade(const CascadeParameters& parameters) {
+ backgroundColor.cascade(parameters);
+ backgroundPattern.cascade(parameters);
+ backgroundOpacity.cascade(parameters);
+}
+
+bool BackgroundPaintProperties::recalculate(const CalculationParameters& parameters) {
+ bool hasTransitions = false;
+
+ hasTransitions |= backgroundColor.calculate(parameters);
+ hasTransitions |= backgroundPattern.calculate(parameters);
+ hasTransitions |= backgroundOpacity.calculate(parameters);
+
+ return hasTransitions;
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layers/background_layer_properties.hpp b/src/mbgl/style/layers/background_layer_properties.hpp
new file mode 100644
index 0000000000..a1a1a3a5a7
--- /dev/null
+++ b/src/mbgl/style/layers/background_layer_properties.hpp
@@ -0,0 +1,27 @@
+// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`.
+
+#pragma once
+
+#include <mbgl/style/layout_property.hpp>
+#include <mbgl/style/paint_property.hpp>
+#include <mbgl/util/rapidjson.hpp>
+
+namespace mbgl {
+namespace style {
+
+class CascadeParameters;
+class CalculationParameters;
+
+class BackgroundPaintProperties {
+public:
+ void parse(const JSValue&);
+ void cascade(const CascadeParameters&);
+ bool recalculate(const CalculationParameters&);
+
+ PaintProperty<Color> backgroundColor { {{ 0, 0, 0, 1 }} };
+ PaintProperty<std::string, CrossFadedPropertyEvaluator> backgroundPattern { "" };
+ PaintProperty<float> backgroundOpacity { 1 };
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layers/circle_layer.cpp b/src/mbgl/style/layers/circle_layer.cpp
new file mode 100644
index 0000000000..bdfbf629e6
--- /dev/null
+++ b/src/mbgl/style/layers/circle_layer.cpp
@@ -0,0 +1,105 @@
+// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`.
+
+#include <mbgl/style/layers/circle_layer.hpp>
+#include <mbgl/style/layers/circle_layer_impl.hpp>
+
+namespace mbgl {
+namespace style {
+
+CircleLayer::CircleLayer(const std::string& layerID)
+ : Layer(Type::Circle, std::make_unique<Impl>())
+ , impl(static_cast<Impl*>(baseImpl.get())) {
+ impl->id = layerID;
+}
+
+CircleLayer::CircleLayer(const Impl& other)
+ : Layer(Type::Circle, std::make_unique<Impl>(other))
+ , impl(static_cast<Impl*>(baseImpl.get())) {
+}
+
+CircleLayer::~CircleLayer() = default;
+
+std::unique_ptr<Layer> CircleLayer::Impl::clone() const {
+ return std::make_unique<CircleLayer>(*this);
+}
+
+// Source
+
+void CircleLayer::setSource(const std::string& sourceID, const std::string& sourceLayer) {
+ impl->source = sourceID;
+ impl->sourceLayer = sourceLayer;
+}
+
+const std::string& CircleLayer::getSourceID() const {
+ return impl->source;
+}
+
+const std::string& CircleLayer::getSourceLayer() const {
+ return impl->sourceLayer;
+}
+
+// Filter
+
+void CircleLayer::setFilter(const Filter& filter) {
+ impl->filter = filter;
+}
+
+const Filter& CircleLayer::getFilter() const {
+ return impl->filter;
+}
+
+// Layout properties
+
+
+// Paint properties
+
+PropertyValue<float> CircleLayer::getCircleRadius() const {
+ return impl->paint.circleRadius.get();
+}
+
+void CircleLayer::setCircleRadius(PropertyValue<float> value) {
+ impl->paint.circleRadius.set(value);
+}
+
+PropertyValue<Color> CircleLayer::getCircleColor() const {
+ return impl->paint.circleColor.get();
+}
+
+void CircleLayer::setCircleColor(PropertyValue<Color> value) {
+ impl->paint.circleColor.set(value);
+}
+
+PropertyValue<float> CircleLayer::getCircleBlur() const {
+ return impl->paint.circleBlur.get();
+}
+
+void CircleLayer::setCircleBlur(PropertyValue<float> value) {
+ impl->paint.circleBlur.set(value);
+}
+
+PropertyValue<float> CircleLayer::getCircleOpacity() const {
+ return impl->paint.circleOpacity.get();
+}
+
+void CircleLayer::setCircleOpacity(PropertyValue<float> value) {
+ impl->paint.circleOpacity.set(value);
+}
+
+PropertyValue<std::array<float, 2>> CircleLayer::getCircleTranslate() const {
+ return impl->paint.circleTranslate.get();
+}
+
+void CircleLayer::setCircleTranslate(PropertyValue<std::array<float, 2>> value) {
+ impl->paint.circleTranslate.set(value);
+}
+
+PropertyValue<TranslateAnchorType> CircleLayer::getCircleTranslateAnchor() const {
+ return impl->paint.circleTranslateAnchor.get();
+}
+
+void CircleLayer::setCircleTranslateAnchor(PropertyValue<TranslateAnchorType> value) {
+ impl->paint.circleTranslateAnchor.set(value);
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layers/circle_layer_impl.cpp b/src/mbgl/style/layers/circle_layer_impl.cpp
new file mode 100644
index 0000000000..c2efac5cef
--- /dev/null
+++ b/src/mbgl/style/layers/circle_layer_impl.cpp
@@ -0,0 +1,62 @@
+#include <mbgl/style/layers/circle_layer_impl.hpp>
+#include <mbgl/style/bucket_parameters.hpp>
+#include <mbgl/renderer/circle_bucket.hpp>
+#include <mbgl/geometry/feature_index.hpp>
+#include <mbgl/util/math.hpp>
+#include <mbgl/util/intersection_tests.hpp>
+
+namespace mbgl {
+namespace style {
+
+void CircleLayer::Impl::parsePaints(const JSValue& layer) {
+ paint.parse(layer);
+}
+
+void CircleLayer::Impl::cascade(const CascadeParameters& parameters) {
+ paint.cascade(parameters);
+}
+
+bool CircleLayer::Impl::recalculate(const CalculationParameters& parameters) {
+ bool hasTransitions = paint.recalculate(parameters);
+
+ passes = (paint.circleRadius > 0 && paint.circleColor.value[3] > 0 && paint.circleOpacity > 0)
+ ? RenderPass::Translucent : RenderPass::None;
+
+ return hasTransitions;
+}
+
+std::unique_ptr<Bucket> CircleLayer::Impl::createBucket(BucketParameters& parameters) const {
+ auto bucket = std::make_unique<CircleBucket>(parameters.mode);
+
+ auto& name = bucketName();
+ parameters.eachFilteredFeature(filter, [&] (const auto& feature, std::size_t index, const std::string& layerName) {
+ auto geometries = feature.getGeometries();
+ bucket->addGeometry(geometries);
+ parameters.featureIndex.insert(geometries, index, layerName, name);
+ });
+
+ return std::move(bucket);
+}
+
+float CircleLayer::Impl::getQueryRadius() const {
+ const std::array<float, 2>& translate = paint.circleTranslate;
+ return paint.circleRadius + util::length(translate[0], translate[1]);
+}
+
+bool CircleLayer::Impl::queryIntersectsGeometry(
+ const GeometryCollection& queryGeometry,
+ const GeometryCollection& geometry,
+ const float bearing,
+ const float pixelsToTileUnits) const {
+
+ auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry(
+ queryGeometry, paint.circleTranslate, paint.circleTranslateAnchor, bearing, pixelsToTileUnits);
+
+ auto circleRadius = paint.circleRadius * pixelsToTileUnits;
+
+ return util::multiPolygonIntersectsBufferedMultiPoint(
+ translatedQueryGeometry.value_or(queryGeometry), geometry, circleRadius);
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layers/circle_layer_impl.hpp b/src/mbgl/style/layers/circle_layer_impl.hpp
new file mode 100644
index 0000000000..463f3ca18d
--- /dev/null
+++ b/src/mbgl/style/layers/circle_layer_impl.hpp
@@ -0,0 +1,33 @@
+#pragma once
+
+#include <mbgl/style/layer_impl.hpp>
+#include <mbgl/style/layers/circle_layer.hpp>
+#include <mbgl/style/layers/circle_layer_properties.hpp>
+
+namespace mbgl {
+namespace style {
+
+class CircleLayer::Impl : public Layer::Impl {
+public:
+ std::unique_ptr<Layer> clone() const override;
+
+ void parseLayout(const JSValue&) override {};
+ void parsePaints(const JSValue&) override;
+
+ void cascade(const CascadeParameters&) override;
+ bool recalculate(const CalculationParameters&) override;
+
+ std::unique_ptr<Bucket> createBucket(BucketParameters&) const override;
+
+ float getQueryRadius() const override;
+ bool queryIntersectsGeometry(
+ const GeometryCollection& queryGeometry,
+ const GeometryCollection& geometry,
+ const float bearing,
+ const float pixelsToTileUnits) const override;
+
+ CirclePaintProperties paint;
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layers/circle_layer_properties.cpp b/src/mbgl/style/layers/circle_layer_properties.cpp
new file mode 100644
index 0000000000..b21df1e2d0
--- /dev/null
+++ b/src/mbgl/style/layers/circle_layer_properties.cpp
@@ -0,0 +1,40 @@
+// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`.
+
+#include <mbgl/style/layers/circle_layer_properties.hpp>
+
+namespace mbgl {
+namespace style {
+
+void CirclePaintProperties::parse(const JSValue& value) {
+ circleRadius.parse("circle-radius", value);
+ circleColor.parse("circle-color", value);
+ circleBlur.parse("circle-blur", value);
+ circleOpacity.parse("circle-opacity", value);
+ circleTranslate.parse("circle-translate", value);
+ circleTranslateAnchor.parse("circle-translate-anchor", value);
+}
+
+void CirclePaintProperties::cascade(const CascadeParameters& parameters) {
+ circleRadius.cascade(parameters);
+ circleColor.cascade(parameters);
+ circleBlur.cascade(parameters);
+ circleOpacity.cascade(parameters);
+ circleTranslate.cascade(parameters);
+ circleTranslateAnchor.cascade(parameters);
+}
+
+bool CirclePaintProperties::recalculate(const CalculationParameters& parameters) {
+ bool hasTransitions = false;
+
+ hasTransitions |= circleRadius.calculate(parameters);
+ hasTransitions |= circleColor.calculate(parameters);
+ hasTransitions |= circleBlur.calculate(parameters);
+ hasTransitions |= circleOpacity.calculate(parameters);
+ hasTransitions |= circleTranslate.calculate(parameters);
+ hasTransitions |= circleTranslateAnchor.calculate(parameters);
+
+ return hasTransitions;
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layers/circle_layer_properties.hpp b/src/mbgl/style/layers/circle_layer_properties.hpp
new file mode 100644
index 0000000000..956e423c45
--- /dev/null
+++ b/src/mbgl/style/layers/circle_layer_properties.hpp
@@ -0,0 +1,30 @@
+// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`.
+
+#pragma once
+
+#include <mbgl/style/layout_property.hpp>
+#include <mbgl/style/paint_property.hpp>
+#include <mbgl/util/rapidjson.hpp>
+
+namespace mbgl {
+namespace style {
+
+class CascadeParameters;
+class CalculationParameters;
+
+class CirclePaintProperties {
+public:
+ void parse(const JSValue&);
+ void cascade(const CascadeParameters&);
+ bool recalculate(const CalculationParameters&);
+
+ PaintProperty<float> circleRadius { 5 };
+ PaintProperty<Color> circleColor { {{ 0, 0, 0, 1 }} };
+ PaintProperty<float> circleBlur { 0 };
+ PaintProperty<float> circleOpacity { 1 };
+ PaintProperty<std::array<float, 2>> circleTranslate { {{ 0, 0 }} };
+ PaintProperty<TranslateAnchorType> circleTranslateAnchor { TranslateAnchorType::Map };
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layers/custom_layer.cpp b/src/mbgl/style/layers/custom_layer.cpp
new file mode 100644
index 0000000000..3407a7f5a5
--- /dev/null
+++ b/src/mbgl/style/layers/custom_layer.cpp
@@ -0,0 +1,24 @@
+#include <mbgl/style/layers/custom_layer.hpp>
+#include <mbgl/style/layers/custom_layer_impl.hpp>
+
+namespace mbgl {
+namespace style {
+
+CustomLayer::CustomLayer(const std::string& layerID,
+ CustomLayerInitializeFunction init,
+ CustomLayerRenderFunction render,
+ CustomLayerDeinitializeFunction deinit,
+ void* context)
+ : Layer(Type::Custom, std::make_unique<Impl>(layerID, init, render, deinit, context))
+ , impl(static_cast<Impl*>(baseImpl.get())) {
+}
+
+CustomLayer::CustomLayer(const Impl& other)
+ : Layer(Type::Custom, std::make_unique<Impl>(other))
+ , impl(static_cast<Impl*>(baseImpl.get())) {
+}
+
+CustomLayer::~CustomLayer() = default;
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layers/custom_layer_impl.cpp b/src/mbgl/style/layers/custom_layer_impl.cpp
new file mode 100644
index 0000000000..214d4ce663
--- /dev/null
+++ b/src/mbgl/style/layers/custom_layer_impl.cpp
@@ -0,0 +1,68 @@
+#include <mbgl/style/layers/custom_layer_impl.hpp>
+#include <mbgl/renderer/bucket.hpp>
+#include <mbgl/map/transform_state.hpp>
+
+namespace mbgl {
+namespace style {
+
+CustomLayer::Impl::Impl(const std::string& id_,
+ CustomLayerInitializeFunction initializeFn_,
+ CustomLayerRenderFunction renderFn_,
+ CustomLayerDeinitializeFunction deinitializeFn_,
+ void* context_) {
+ id = id_;
+ initializeFn = initializeFn_;
+ renderFn = renderFn_;
+ deinitializeFn = deinitializeFn_;
+ context = context_;
+}
+
+CustomLayer::Impl::Impl(const CustomLayer::Impl& other)
+ : Layer::Impl(other) {
+ id = other.id;
+ // Don't copy anything else.
+}
+
+CustomLayer::Impl::~Impl() {
+ if (deinitializeFn) {
+ deinitializeFn(context);
+ }
+}
+
+std::unique_ptr<Layer> CustomLayer::Impl::clone() const {
+ return std::make_unique<CustomLayer>(*this);
+}
+
+void CustomLayer::Impl::initialize() {
+ assert(initializeFn);
+ initializeFn(context);
+}
+
+void CustomLayer::Impl::render(const TransformState& state) const {
+ assert(renderFn);
+
+ CustomLayerRenderParameters parameters;
+
+ parameters.width = state.getWidth();
+ parameters.height = state.getHeight();
+ parameters.latitude = state.getLatLng().latitude;
+ parameters.longitude = state.getLatLng().longitude;
+ parameters.zoom = state.getZoom();
+ parameters.bearing = -state.getAngle() * util::RAD2DEG;
+ parameters.pitch = state.getPitch();
+ parameters.altitude = state.getAltitude();
+
+ renderFn(context, parameters);
+}
+
+bool CustomLayer::Impl::recalculate(const CalculationParameters&) {
+ passes = RenderPass::Translucent;
+ return false;
+}
+
+std::unique_ptr<Bucket> CustomLayer::Impl::createBucket(BucketParameters&) const {
+ return nullptr;
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layers/custom_layer_impl.hpp b/src/mbgl/style/layers/custom_layer_impl.hpp
new file mode 100644
index 0000000000..00e576b6a3
--- /dev/null
+++ b/src/mbgl/style/layers/custom_layer_impl.hpp
@@ -0,0 +1,44 @@
+#pragma once
+
+#include <mbgl/style/layer_impl.hpp>
+#include <mbgl/style/layers/custom_layer.hpp>
+
+namespace mbgl {
+
+class TransformState;
+
+namespace style {
+
+class CustomLayer::Impl : public Layer::Impl {
+public:
+ Impl(const std::string& id,
+ CustomLayerInitializeFunction,
+ CustomLayerRenderFunction,
+ CustomLayerDeinitializeFunction,
+ void* context);
+
+ Impl(const Impl&);
+ ~Impl() final;
+
+ void initialize();
+ void render(const TransformState&) const;
+
+private:
+ std::unique_ptr<Layer> clone() const override;
+
+ void parseLayout(const JSValue&) final {}
+ void parsePaints(const JSValue&) final {}
+
+ void cascade(const CascadeParameters&) final {}
+ bool recalculate(const CalculationParameters&) final;
+
+ std::unique_ptr<Bucket> createBucket(BucketParameters&) const final;
+
+ CustomLayerInitializeFunction initializeFn = nullptr;
+ CustomLayerRenderFunction renderFn = nullptr;
+ CustomLayerDeinitializeFunction deinitializeFn = nullptr;
+ void* context = nullptr;
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layers/fill_layer.cpp b/src/mbgl/style/layers/fill_layer.cpp
new file mode 100644
index 0000000000..1deaabb5ef
--- /dev/null
+++ b/src/mbgl/style/layers/fill_layer.cpp
@@ -0,0 +1,113 @@
+// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`.
+
+#include <mbgl/style/layers/fill_layer.hpp>
+#include <mbgl/style/layers/fill_layer_impl.hpp>
+
+namespace mbgl {
+namespace style {
+
+FillLayer::FillLayer(const std::string& layerID)
+ : Layer(Type::Fill, std::make_unique<Impl>())
+ , impl(static_cast<Impl*>(baseImpl.get())) {
+ impl->id = layerID;
+}
+
+FillLayer::FillLayer(const Impl& other)
+ : Layer(Type::Fill, std::make_unique<Impl>(other))
+ , impl(static_cast<Impl*>(baseImpl.get())) {
+}
+
+FillLayer::~FillLayer() = default;
+
+std::unique_ptr<Layer> FillLayer::Impl::clone() const {
+ return std::make_unique<FillLayer>(*this);
+}
+
+// Source
+
+void FillLayer::setSource(const std::string& sourceID, const std::string& sourceLayer) {
+ impl->source = sourceID;
+ impl->sourceLayer = sourceLayer;
+}
+
+const std::string& FillLayer::getSourceID() const {
+ return impl->source;
+}
+
+const std::string& FillLayer::getSourceLayer() const {
+ return impl->sourceLayer;
+}
+
+// Filter
+
+void FillLayer::setFilter(const Filter& filter) {
+ impl->filter = filter;
+}
+
+const Filter& FillLayer::getFilter() const {
+ return impl->filter;
+}
+
+// Layout properties
+
+
+// Paint properties
+
+PropertyValue<bool> FillLayer::getFillAntialias() const {
+ return impl->paint.fillAntialias.get();
+}
+
+void FillLayer::setFillAntialias(PropertyValue<bool> value) {
+ impl->paint.fillAntialias.set(value);
+}
+
+PropertyValue<float> FillLayer::getFillOpacity() const {
+ return impl->paint.fillOpacity.get();
+}
+
+void FillLayer::setFillOpacity(PropertyValue<float> value) {
+ impl->paint.fillOpacity.set(value);
+}
+
+PropertyValue<Color> FillLayer::getFillColor() const {
+ return impl->paint.fillColor.get();
+}
+
+void FillLayer::setFillColor(PropertyValue<Color> value) {
+ impl->paint.fillColor.set(value);
+}
+
+PropertyValue<Color> FillLayer::getFillOutlineColor() const {
+ return impl->paint.fillOutlineColor.get();
+}
+
+void FillLayer::setFillOutlineColor(PropertyValue<Color> value) {
+ impl->paint.fillOutlineColor.set(value);
+}
+
+PropertyValue<std::array<float, 2>> FillLayer::getFillTranslate() const {
+ return impl->paint.fillTranslate.get();
+}
+
+void FillLayer::setFillTranslate(PropertyValue<std::array<float, 2>> value) {
+ impl->paint.fillTranslate.set(value);
+}
+
+PropertyValue<TranslateAnchorType> FillLayer::getFillTranslateAnchor() const {
+ return impl->paint.fillTranslateAnchor.get();
+}
+
+void FillLayer::setFillTranslateAnchor(PropertyValue<TranslateAnchorType> value) {
+ impl->paint.fillTranslateAnchor.set(value);
+}
+
+PropertyValue<std::string> FillLayer::getFillPattern() const {
+ return impl->paint.fillPattern.get();
+}
+
+void FillLayer::setFillPattern(PropertyValue<std::string> value) {
+ impl->paint.fillPattern.set(value);
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layers/fill_layer_impl.cpp b/src/mbgl/style/layers/fill_layer_impl.cpp
new file mode 100644
index 0000000000..c183617482
--- /dev/null
+++ b/src/mbgl/style/layers/fill_layer_impl.cpp
@@ -0,0 +1,68 @@
+#include <mbgl/style/layers/fill_layer_impl.hpp>
+#include <mbgl/style/bucket_parameters.hpp>
+#include <mbgl/renderer/fill_bucket.hpp>
+#include <mbgl/geometry/feature_index.hpp>
+#include <mbgl/util/math.hpp>
+#include <mbgl/util/intersection_tests.hpp>
+
+namespace mbgl {
+namespace style {
+
+void FillLayer::Impl::parsePaints(const JSValue& layer) {
+ paint.parse(layer);
+}
+
+void FillLayer::Impl::cascade(const CascadeParameters& parameters) {
+ paint.cascade(parameters);
+}
+
+bool FillLayer::Impl::recalculate(const CalculationParameters& parameters) {
+ bool hasTransitions = paint.recalculate(parameters);
+
+ passes = RenderPass::None;
+
+ if (paint.fillAntialias) {
+ passes |= RenderPass::Translucent;
+ }
+
+ if (!paint.fillPattern.value.from.empty() || (paint.fillColor.value[3] * paint.fillOpacity) < 1.0f) {
+ passes |= RenderPass::Translucent;
+ } else {
+ passes |= RenderPass::Opaque;
+ }
+
+ return hasTransitions;
+}
+
+std::unique_ptr<Bucket> FillLayer::Impl::createBucket(BucketParameters& parameters) const {
+ auto bucket = std::make_unique<FillBucket>();
+
+ auto& name = bucketName();
+ parameters.eachFilteredFeature(filter, [&] (const auto& feature, std::size_t index, const std::string& layerName) {
+ auto geometries = feature.getGeometries();
+ bucket->addGeometry(geometries);
+ parameters.featureIndex.insert(geometries, index, layerName, name);
+ });
+
+ return std::move(bucket);
+}
+
+float FillLayer::Impl::getQueryRadius() const {
+ const std::array<float, 2>& translate = paint.fillTranslate;
+ return util::length(translate[0], translate[1]);
+}
+
+bool FillLayer::Impl::queryIntersectsGeometry(
+ const GeometryCollection& queryGeometry,
+ const GeometryCollection& geometry,
+ const float bearing,
+ const float pixelsToTileUnits) const {
+
+ auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry(
+ queryGeometry, paint.fillTranslate, paint.fillTranslateAnchor, bearing, pixelsToTileUnits);
+
+ return util::multiPolygonIntersectsMultiPolygon(translatedQueryGeometry.value_or(queryGeometry), geometry);
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layers/fill_layer_impl.hpp b/src/mbgl/style/layers/fill_layer_impl.hpp
new file mode 100644
index 0000000000..a37dd76ace
--- /dev/null
+++ b/src/mbgl/style/layers/fill_layer_impl.hpp
@@ -0,0 +1,33 @@
+#pragma once
+
+#include <mbgl/style/layer_impl.hpp>
+#include <mbgl/style/layers/fill_layer.hpp>
+#include <mbgl/style/layers/fill_layer_properties.hpp>
+
+namespace mbgl {
+namespace style {
+
+class FillLayer::Impl : public Layer::Impl {
+public:
+ std::unique_ptr<Layer> clone() const override;
+
+ void parseLayout(const JSValue&) override {};
+ void parsePaints(const JSValue&) override;
+
+ void cascade(const CascadeParameters&) override;
+ bool recalculate(const CalculationParameters&) override;
+
+ std::unique_ptr<Bucket> createBucket(BucketParameters&) const override;
+
+ float getQueryRadius() const override;
+ bool queryIntersectsGeometry(
+ const GeometryCollection& queryGeometry,
+ const GeometryCollection& geometry,
+ const float bearing,
+ const float pixelsToTileUnits) const override;
+
+ FillPaintProperties paint;
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layers/fill_layer_properties.cpp b/src/mbgl/style/layers/fill_layer_properties.cpp
new file mode 100644
index 0000000000..a4714689f9
--- /dev/null
+++ b/src/mbgl/style/layers/fill_layer_properties.cpp
@@ -0,0 +1,43 @@
+// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`.
+
+#include <mbgl/style/layers/fill_layer_properties.hpp>
+
+namespace mbgl {
+namespace style {
+
+void FillPaintProperties::parse(const JSValue& value) {
+ fillAntialias.parse("fill-antialias", value);
+ fillOpacity.parse("fill-opacity", value);
+ fillColor.parse("fill-color", value);
+ fillOutlineColor.parse("fill-outline-color", value);
+ fillTranslate.parse("fill-translate", value);
+ fillTranslateAnchor.parse("fill-translate-anchor", value);
+ fillPattern.parse("fill-pattern", value);
+}
+
+void FillPaintProperties::cascade(const CascadeParameters& parameters) {
+ fillAntialias.cascade(parameters);
+ fillOpacity.cascade(parameters);
+ fillColor.cascade(parameters);
+ fillOutlineColor.cascade(parameters);
+ fillTranslate.cascade(parameters);
+ fillTranslateAnchor.cascade(parameters);
+ fillPattern.cascade(parameters);
+}
+
+bool FillPaintProperties::recalculate(const CalculationParameters& parameters) {
+ bool hasTransitions = false;
+
+ hasTransitions |= fillAntialias.calculate(parameters);
+ hasTransitions |= fillOpacity.calculate(parameters);
+ hasTransitions |= fillColor.calculate(parameters);
+ hasTransitions |= fillOutlineColor.calculate(parameters);
+ hasTransitions |= fillTranslate.calculate(parameters);
+ hasTransitions |= fillTranslateAnchor.calculate(parameters);
+ hasTransitions |= fillPattern.calculate(parameters);
+
+ return hasTransitions;
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layers/fill_layer_properties.hpp b/src/mbgl/style/layers/fill_layer_properties.hpp
new file mode 100644
index 0000000000..43396f45d2
--- /dev/null
+++ b/src/mbgl/style/layers/fill_layer_properties.hpp
@@ -0,0 +1,31 @@
+// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`.
+
+#pragma once
+
+#include <mbgl/style/layout_property.hpp>
+#include <mbgl/style/paint_property.hpp>
+#include <mbgl/util/rapidjson.hpp>
+
+namespace mbgl {
+namespace style {
+
+class CascadeParameters;
+class CalculationParameters;
+
+class FillPaintProperties {
+public:
+ void parse(const JSValue&);
+ void cascade(const CascadeParameters&);
+ bool recalculate(const CalculationParameters&);
+
+ PaintProperty<bool> fillAntialias { true };
+ PaintProperty<float> fillOpacity { 1 };
+ PaintProperty<Color> fillColor { {{ 0, 0, 0, 1 }} };
+ PaintProperty<Color> fillOutlineColor { {{ 0, 0, 0, -1 }} };
+ PaintProperty<std::array<float, 2>> fillTranslate { {{ 0, 0 }} };
+ PaintProperty<TranslateAnchorType> fillTranslateAnchor { TranslateAnchorType::Map };
+ PaintProperty<std::string, CrossFadedPropertyEvaluator> fillPattern { "" };
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layers/line_layer.cpp b/src/mbgl/style/layers/line_layer.cpp
new file mode 100644
index 0000000000..abe326a672
--- /dev/null
+++ b/src/mbgl/style/layers/line_layer.cpp
@@ -0,0 +1,165 @@
+// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`.
+
+#include <mbgl/style/layers/line_layer.hpp>
+#include <mbgl/style/layers/line_layer_impl.hpp>
+
+namespace mbgl {
+namespace style {
+
+LineLayer::LineLayer(const std::string& layerID)
+ : Layer(Type::Line, std::make_unique<Impl>())
+ , impl(static_cast<Impl*>(baseImpl.get())) {
+ impl->id = layerID;
+}
+
+LineLayer::LineLayer(const Impl& other)
+ : Layer(Type::Line, std::make_unique<Impl>(other))
+ , impl(static_cast<Impl*>(baseImpl.get())) {
+}
+
+LineLayer::~LineLayer() = default;
+
+std::unique_ptr<Layer> LineLayer::Impl::clone() const {
+ return std::make_unique<LineLayer>(*this);
+}
+
+// Source
+
+void LineLayer::setSource(const std::string& sourceID, const std::string& sourceLayer) {
+ impl->source = sourceID;
+ impl->sourceLayer = sourceLayer;
+}
+
+const std::string& LineLayer::getSourceID() const {
+ return impl->source;
+}
+
+const std::string& LineLayer::getSourceLayer() const {
+ return impl->sourceLayer;
+}
+
+// Filter
+
+void LineLayer::setFilter(const Filter& filter) {
+ impl->filter = filter;
+}
+
+const Filter& LineLayer::getFilter() const {
+ return impl->filter;
+}
+
+// Layout properties
+
+PropertyValue<LineCapType> LineLayer::getLineCap() const {
+ return impl->layout.lineCap.get();
+}
+
+void LineLayer::setLineCap(PropertyValue<LineCapType> value) {
+ impl->layout.lineCap.set(value);
+}
+PropertyValue<LineJoinType> LineLayer::getLineJoin() const {
+ return impl->layout.lineJoin.get();
+}
+
+void LineLayer::setLineJoin(PropertyValue<LineJoinType> value) {
+ impl->layout.lineJoin.set(value);
+}
+PropertyValue<float> LineLayer::getLineMiterLimit() const {
+ return impl->layout.lineMiterLimit.get();
+}
+
+void LineLayer::setLineMiterLimit(PropertyValue<float> value) {
+ impl->layout.lineMiterLimit.set(value);
+}
+PropertyValue<float> LineLayer::getLineRoundLimit() const {
+ return impl->layout.lineRoundLimit.get();
+}
+
+void LineLayer::setLineRoundLimit(PropertyValue<float> value) {
+ impl->layout.lineRoundLimit.set(value);
+}
+
+// Paint properties
+
+PropertyValue<float> LineLayer::getLineOpacity() const {
+ return impl->paint.lineOpacity.get();
+}
+
+void LineLayer::setLineOpacity(PropertyValue<float> value) {
+ impl->paint.lineOpacity.set(value);
+}
+
+PropertyValue<Color> LineLayer::getLineColor() const {
+ return impl->paint.lineColor.get();
+}
+
+void LineLayer::setLineColor(PropertyValue<Color> value) {
+ impl->paint.lineColor.set(value);
+}
+
+PropertyValue<std::array<float, 2>> LineLayer::getLineTranslate() const {
+ return impl->paint.lineTranslate.get();
+}
+
+void LineLayer::setLineTranslate(PropertyValue<std::array<float, 2>> value) {
+ impl->paint.lineTranslate.set(value);
+}
+
+PropertyValue<TranslateAnchorType> LineLayer::getLineTranslateAnchor() const {
+ return impl->paint.lineTranslateAnchor.get();
+}
+
+void LineLayer::setLineTranslateAnchor(PropertyValue<TranslateAnchorType> value) {
+ impl->paint.lineTranslateAnchor.set(value);
+}
+
+PropertyValue<float> LineLayer::getLineWidth() const {
+ return impl->paint.lineWidth.get();
+}
+
+void LineLayer::setLineWidth(PropertyValue<float> value) {
+ impl->paint.lineWidth.set(value);
+}
+
+PropertyValue<float> LineLayer::getLineGapWidth() const {
+ return impl->paint.lineGapWidth.get();
+}
+
+void LineLayer::setLineGapWidth(PropertyValue<float> value) {
+ impl->paint.lineGapWidth.set(value);
+}
+
+PropertyValue<float> LineLayer::getLineOffset() const {
+ return impl->paint.lineOffset.get();
+}
+
+void LineLayer::setLineOffset(PropertyValue<float> value) {
+ impl->paint.lineOffset.set(value);
+}
+
+PropertyValue<float> LineLayer::getLineBlur() const {
+ return impl->paint.lineBlur.get();
+}
+
+void LineLayer::setLineBlur(PropertyValue<float> value) {
+ impl->paint.lineBlur.set(value);
+}
+
+PropertyValue<std::vector<float>> LineLayer::getLineDasharray() const {
+ return impl->paint.lineDasharray.get();
+}
+
+void LineLayer::setLineDasharray(PropertyValue<std::vector<float>> value) {
+ impl->paint.lineDasharray.set(value);
+}
+
+PropertyValue<std::string> LineLayer::getLinePattern() const {
+ return impl->paint.linePattern.get();
+}
+
+void LineLayer::setLinePattern(PropertyValue<std::string> value) {
+ impl->paint.linePattern.set(value);
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layers/line_layer_impl.cpp b/src/mbgl/style/layers/line_layer_impl.cpp
new file mode 100644
index 0000000000..b7ee9dc5bf
--- /dev/null
+++ b/src/mbgl/style/layers/line_layer_impl.cpp
@@ -0,0 +1,116 @@
+#include <mbgl/style/layers/line_layer_impl.hpp>
+#include <mbgl/style/bucket_parameters.hpp>
+#include <mbgl/renderer/line_bucket.hpp>
+#include <mbgl/geometry/feature_index.hpp>
+#include <mbgl/util/math.hpp>
+#include <mbgl/util/intersection_tests.hpp>
+
+namespace mbgl {
+namespace style {
+
+void LineLayer::Impl::parseLayout(const JSValue& value) {
+ layout.parse(value);
+}
+
+void LineLayer::Impl::parsePaints(const JSValue& layer) {
+ paint.parse(layer);
+}
+
+void LineLayer::Impl::cascade(const CascadeParameters& parameters) {
+ paint.cascade(parameters);
+}
+
+bool LineLayer::Impl::recalculate(const CalculationParameters& parameters) {
+ // for scaling dasharrays
+ CalculationParameters dashArrayParams = parameters;
+ dashArrayParams.z = std::floor(dashArrayParams.z);
+ paint.lineWidth.calculate(dashArrayParams);
+ dashLineWidth = paint.lineWidth;
+
+ bool hasTransitions = paint.recalculate(parameters);
+
+ passes = (paint.lineOpacity > 0 && paint.lineColor.value[3] > 0 && paint.lineWidth > 0)
+ ? RenderPass::Translucent : RenderPass::None;
+
+ return hasTransitions;
+}
+
+std::unique_ptr<Bucket> LineLayer::Impl::createBucket(BucketParameters& parameters) const {
+ auto bucket = std::make_unique<LineBucket>(parameters.tileID.overscaleFactor());
+
+ bucket->layout = layout;
+ bucket->layout.recalculate(CalculationParameters(parameters.tileID.overscaledZ));
+
+ auto& name = bucketName();
+ parameters.eachFilteredFeature(filter, [&] (const auto& feature, std::size_t index, const std::string& layerName) {
+ auto geometries = feature.getGeometries();
+ bucket->addGeometry(geometries);
+ parameters.featureIndex.insert(geometries, index, layerName, name);
+ });
+
+ return std::move(bucket);
+}
+
+float LineLayer::Impl::getLineWidth() const {
+ if (paint.lineGapWidth > 0) {
+ return paint.lineGapWidth + 2 * paint.lineWidth;
+ } else {
+ return paint.lineWidth;
+ }
+}
+
+optional<GeometryCollection> offsetLine(const GeometryCollection& rings, const double offset) {
+ if (offset == 0) return {};
+
+ GeometryCollection newRings;
+ Point<double> zero(0, 0);
+ for (const auto& ring : rings) {
+ newRings.emplace_back();
+ auto& newRing = newRings.back();
+
+ for (auto i = ring.begin(); i != ring.end(); i++) {
+ auto& p = *i;
+
+ Point<double> aToB = i == ring.begin() ?
+ zero :
+ util::perp(util::unit(convertPoint<double>(p - *(i - 1))));
+ Point<double> bToC = i + 1 == ring.end() ?
+ zero :
+ util::perp(util::unit(convertPoint<double>(*(i + 1) - p)));
+ Point<double> extrude = util::unit(aToB + bToC);
+
+ const double cosHalfAngle = extrude.x * bToC.x + extrude.y * bToC.y;
+ extrude *= (1.0 / cosHalfAngle);
+
+ newRing.push_back(convertPoint<int16_t>(extrude * offset) + p);
+ }
+ }
+
+ return newRings;
+}
+
+float LineLayer::Impl::getQueryRadius() const {
+ const std::array<float, 2>& translate = paint.lineTranslate;
+ return getLineWidth() / 2.0 + std::abs(paint.lineOffset) + util::length(translate[0], translate[1]);
+}
+
+bool LineLayer::Impl::queryIntersectsGeometry(
+ const GeometryCollection& queryGeometry,
+ const GeometryCollection& geometry,
+ const float bearing,
+ const float pixelsToTileUnits) const {
+
+ const float halfWidth = getLineWidth() / 2.0 * pixelsToTileUnits;
+
+ auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry(
+ queryGeometry, paint.lineTranslate, paint.lineTranslateAnchor, bearing, pixelsToTileUnits);
+ auto offsetGeometry = offsetLine(geometry, paint.lineOffset * pixelsToTileUnits);
+
+ return util::multiPolygonIntersectsBufferedMultiLine(
+ translatedQueryGeometry.value_or(queryGeometry),
+ offsetGeometry.value_or(geometry),
+ halfWidth);
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layers/line_layer_impl.hpp b/src/mbgl/style/layers/line_layer_impl.hpp
new file mode 100644
index 0000000000..3356dc2ceb
--- /dev/null
+++ b/src/mbgl/style/layers/line_layer_impl.hpp
@@ -0,0 +1,40 @@
+#pragma once
+
+#include <mbgl/style/layer_impl.hpp>
+#include <mbgl/style/layers/line_layer.hpp>
+#include <mbgl/style/layers/line_layer_properties.hpp>
+
+namespace mbgl {
+namespace style {
+
+class LineLayer::Impl : public Layer::Impl {
+public:
+ std::unique_ptr<Layer> clone() const override;
+
+ void parseLayout(const JSValue&) override;
+ void parsePaints(const JSValue&) override;
+
+ void cascade(const CascadeParameters&) override;
+ bool recalculate(const CalculationParameters&) override;
+
+ std::unique_ptr<Bucket> createBucket(BucketParameters&) const override;
+
+ float getQueryRadius() const override;
+ bool queryIntersectsGeometry(
+ const GeometryCollection& queryGeometry,
+ const GeometryCollection& geometry,
+ const float bearing,
+ const float pixelsToTileUnits) const override;
+
+ LineLayoutProperties layout;
+ LinePaintProperties paint;
+
+ // Special case
+ float dashLineWidth = 1;
+
+private:
+ float getLineWidth() const;
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layers/line_layer_properties.cpp b/src/mbgl/style/layers/line_layer_properties.cpp
new file mode 100644
index 0000000000..7c74f6de04
--- /dev/null
+++ b/src/mbgl/style/layers/line_layer_properties.cpp
@@ -0,0 +1,66 @@
+// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`.
+
+#include <mbgl/style/layers/line_layer_properties.hpp>
+
+namespace mbgl {
+namespace style {
+
+void LineLayoutProperties::parse(const JSValue& value) {
+ lineCap.parse("line-cap", value);
+ lineJoin.parse("line-join", value);
+ lineMiterLimit.parse("line-miter-limit", value);
+ lineRoundLimit.parse("line-round-limit", value);
+}
+
+void LineLayoutProperties::recalculate(const CalculationParameters& parameters) {
+ lineCap.calculate(parameters);
+ lineJoin.calculate(parameters);
+ lineMiterLimit.calculate(parameters);
+ lineRoundLimit.calculate(parameters);
+}
+
+void LinePaintProperties::parse(const JSValue& value) {
+ lineOpacity.parse("line-opacity", value);
+ lineColor.parse("line-color", value);
+ lineTranslate.parse("line-translate", value);
+ lineTranslateAnchor.parse("line-translate-anchor", value);
+ lineWidth.parse("line-width", value);
+ lineGapWidth.parse("line-gap-width", value);
+ lineOffset.parse("line-offset", value);
+ lineBlur.parse("line-blur", value);
+ lineDasharray.parse("line-dasharray", value);
+ linePattern.parse("line-pattern", value);
+}
+
+void LinePaintProperties::cascade(const CascadeParameters& parameters) {
+ lineOpacity.cascade(parameters);
+ lineColor.cascade(parameters);
+ lineTranslate.cascade(parameters);
+ lineTranslateAnchor.cascade(parameters);
+ lineWidth.cascade(parameters);
+ lineGapWidth.cascade(parameters);
+ lineOffset.cascade(parameters);
+ lineBlur.cascade(parameters);
+ lineDasharray.cascade(parameters);
+ linePattern.cascade(parameters);
+}
+
+bool LinePaintProperties::recalculate(const CalculationParameters& parameters) {
+ bool hasTransitions = false;
+
+ hasTransitions |= lineOpacity.calculate(parameters);
+ hasTransitions |= lineColor.calculate(parameters);
+ hasTransitions |= lineTranslate.calculate(parameters);
+ hasTransitions |= lineTranslateAnchor.calculate(parameters);
+ hasTransitions |= lineWidth.calculate(parameters);
+ hasTransitions |= lineGapWidth.calculate(parameters);
+ hasTransitions |= lineOffset.calculate(parameters);
+ hasTransitions |= lineBlur.calculate(parameters);
+ hasTransitions |= lineDasharray.calculate(parameters);
+ hasTransitions |= linePattern.calculate(parameters);
+
+ return hasTransitions;
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layers/line_layer_properties.hpp b/src/mbgl/style/layers/line_layer_properties.hpp
new file mode 100644
index 0000000000..e0c63b516b
--- /dev/null
+++ b/src/mbgl/style/layers/line_layer_properties.hpp
@@ -0,0 +1,45 @@
+// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`.
+
+#pragma once
+
+#include <mbgl/style/layout_property.hpp>
+#include <mbgl/style/paint_property.hpp>
+#include <mbgl/util/rapidjson.hpp>
+
+namespace mbgl {
+namespace style {
+
+class CascadeParameters;
+class CalculationParameters;
+
+class LineLayoutProperties {
+public:
+ void parse(const JSValue&);
+ void recalculate(const CalculationParameters&);
+
+ LayoutProperty<LineCapType> lineCap { LineCapType::Butt };
+ LayoutProperty<LineJoinType> lineJoin { LineJoinType::Miter };
+ LayoutProperty<float> lineMiterLimit { 2 };
+ LayoutProperty<float> lineRoundLimit { 1.05 };
+};
+
+class LinePaintProperties {
+public:
+ void parse(const JSValue&);
+ void cascade(const CascadeParameters&);
+ bool recalculate(const CalculationParameters&);
+
+ PaintProperty<float> lineOpacity { 1 };
+ PaintProperty<Color> lineColor { {{ 0, 0, 0, 1 }} };
+ PaintProperty<std::array<float, 2>> lineTranslate { {{ 0, 0 }} };
+ PaintProperty<TranslateAnchorType> lineTranslateAnchor { TranslateAnchorType::Map };
+ PaintProperty<float> lineWidth { 1 };
+ PaintProperty<float> lineGapWidth { 0 };
+ PaintProperty<float> lineOffset { 0 };
+ PaintProperty<float> lineBlur { 0 };
+ PaintProperty<std::vector<float>, CrossFadedPropertyEvaluator> lineDasharray { { } };
+ PaintProperty<std::string, CrossFadedPropertyEvaluator> linePattern { "" };
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layers/raster_layer.cpp b/src/mbgl/style/layers/raster_layer.cpp
new file mode 100644
index 0000000000..fb7f08fbe9
--- /dev/null
+++ b/src/mbgl/style/layers/raster_layer.cpp
@@ -0,0 +1,98 @@
+// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`.
+
+#include <mbgl/style/layers/raster_layer.hpp>
+#include <mbgl/style/layers/raster_layer_impl.hpp>
+
+namespace mbgl {
+namespace style {
+
+RasterLayer::RasterLayer(const std::string& layerID)
+ : Layer(Type::Raster, std::make_unique<Impl>())
+ , impl(static_cast<Impl*>(baseImpl.get())) {
+ impl->id = layerID;
+}
+
+RasterLayer::RasterLayer(const Impl& other)
+ : Layer(Type::Raster, std::make_unique<Impl>(other))
+ , impl(static_cast<Impl*>(baseImpl.get())) {
+}
+
+RasterLayer::~RasterLayer() = default;
+
+std::unique_ptr<Layer> RasterLayer::Impl::clone() const {
+ return std::make_unique<RasterLayer>(*this);
+}
+
+// Source
+
+void RasterLayer::setSource(const std::string& sourceID) {
+ impl->source = sourceID;
+}
+
+const std::string& RasterLayer::getSourceID() const {
+ return impl->source;
+}
+
+// Layout properties
+
+
+// Paint properties
+
+PropertyValue<float> RasterLayer::getRasterOpacity() const {
+ return impl->paint.rasterOpacity.get();
+}
+
+void RasterLayer::setRasterOpacity(PropertyValue<float> value) {
+ impl->paint.rasterOpacity.set(value);
+}
+
+PropertyValue<float> RasterLayer::getRasterHueRotate() const {
+ return impl->paint.rasterHueRotate.get();
+}
+
+void RasterLayer::setRasterHueRotate(PropertyValue<float> value) {
+ impl->paint.rasterHueRotate.set(value);
+}
+
+PropertyValue<float> RasterLayer::getRasterBrightnessMin() const {
+ return impl->paint.rasterBrightnessMin.get();
+}
+
+void RasterLayer::setRasterBrightnessMin(PropertyValue<float> value) {
+ impl->paint.rasterBrightnessMin.set(value);
+}
+
+PropertyValue<float> RasterLayer::getRasterBrightnessMax() const {
+ return impl->paint.rasterBrightnessMax.get();
+}
+
+void RasterLayer::setRasterBrightnessMax(PropertyValue<float> value) {
+ impl->paint.rasterBrightnessMax.set(value);
+}
+
+PropertyValue<float> RasterLayer::getRasterSaturation() const {
+ return impl->paint.rasterSaturation.get();
+}
+
+void RasterLayer::setRasterSaturation(PropertyValue<float> value) {
+ impl->paint.rasterSaturation.set(value);
+}
+
+PropertyValue<float> RasterLayer::getRasterContrast() const {
+ return impl->paint.rasterContrast.get();
+}
+
+void RasterLayer::setRasterContrast(PropertyValue<float> value) {
+ impl->paint.rasterContrast.set(value);
+}
+
+PropertyValue<float> RasterLayer::getRasterFadeDuration() const {
+ return impl->paint.rasterFadeDuration.get();
+}
+
+void RasterLayer::setRasterFadeDuration(PropertyValue<float> value) {
+ impl->paint.rasterFadeDuration.set(value);
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layers/raster_layer_impl.cpp b/src/mbgl/style/layers/raster_layer_impl.cpp
new file mode 100644
index 0000000000..4854ec041d
--- /dev/null
+++ b/src/mbgl/style/layers/raster_layer_impl.cpp
@@ -0,0 +1,28 @@
+#include <mbgl/style/layers/raster_layer_impl.hpp>
+#include <mbgl/renderer/bucket.hpp>
+
+namespace mbgl {
+namespace style {
+
+void RasterLayer::Impl::parsePaints(const JSValue& layer) {
+ paint.parse(layer);
+}
+
+void RasterLayer::Impl::cascade(const CascadeParameters& parameters) {
+ paint.cascade(parameters);
+}
+
+bool RasterLayer::Impl::recalculate(const CalculationParameters& parameters) {
+ bool hasTransitions = paint.recalculate(parameters);
+
+ passes = paint.rasterOpacity > 0 ? RenderPass::Translucent : RenderPass::None;
+
+ return hasTransitions;
+}
+
+std::unique_ptr<Bucket> RasterLayer::Impl::createBucket(BucketParameters&) const {
+ return nullptr;
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layers/raster_layer_impl.hpp b/src/mbgl/style/layers/raster_layer_impl.hpp
new file mode 100644
index 0000000000..6812b469a6
--- /dev/null
+++ b/src/mbgl/style/layers/raster_layer_impl.hpp
@@ -0,0 +1,26 @@
+#pragma once
+
+#include <mbgl/style/layer_impl.hpp>
+#include <mbgl/style/layers/raster_layer.hpp>
+#include <mbgl/style/layers/raster_layer_properties.hpp>
+
+namespace mbgl {
+namespace style {
+
+class RasterLayer::Impl : public Layer::Impl {
+public:
+ std::unique_ptr<Layer> clone() const override;
+
+ void parseLayout(const JSValue&) override {};
+ void parsePaints(const JSValue&) override;
+
+ void cascade(const CascadeParameters&) override;
+ bool recalculate(const CalculationParameters&) override;
+
+ std::unique_ptr<Bucket> createBucket(BucketParameters&) const override;
+
+ RasterPaintProperties paint;
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layers/raster_layer_properties.cpp b/src/mbgl/style/layers/raster_layer_properties.cpp
new file mode 100644
index 0000000000..0e6afc5e9c
--- /dev/null
+++ b/src/mbgl/style/layers/raster_layer_properties.cpp
@@ -0,0 +1,43 @@
+// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`.
+
+#include <mbgl/style/layers/raster_layer_properties.hpp>
+
+namespace mbgl {
+namespace style {
+
+void RasterPaintProperties::parse(const JSValue& value) {
+ rasterOpacity.parse("raster-opacity", value);
+ rasterHueRotate.parse("raster-hue-rotate", value);
+ rasterBrightnessMin.parse("raster-brightness-min", value);
+ rasterBrightnessMax.parse("raster-brightness-max", value);
+ rasterSaturation.parse("raster-saturation", value);
+ rasterContrast.parse("raster-contrast", value);
+ rasterFadeDuration.parse("raster-fade-duration", value);
+}
+
+void RasterPaintProperties::cascade(const CascadeParameters& parameters) {
+ rasterOpacity.cascade(parameters);
+ rasterHueRotate.cascade(parameters);
+ rasterBrightnessMin.cascade(parameters);
+ rasterBrightnessMax.cascade(parameters);
+ rasterSaturation.cascade(parameters);
+ rasterContrast.cascade(parameters);
+ rasterFadeDuration.cascade(parameters);
+}
+
+bool RasterPaintProperties::recalculate(const CalculationParameters& parameters) {
+ bool hasTransitions = false;
+
+ hasTransitions |= rasterOpacity.calculate(parameters);
+ hasTransitions |= rasterHueRotate.calculate(parameters);
+ hasTransitions |= rasterBrightnessMin.calculate(parameters);
+ hasTransitions |= rasterBrightnessMax.calculate(parameters);
+ hasTransitions |= rasterSaturation.calculate(parameters);
+ hasTransitions |= rasterContrast.calculate(parameters);
+ hasTransitions |= rasterFadeDuration.calculate(parameters);
+
+ return hasTransitions;
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layers/raster_layer_properties.hpp b/src/mbgl/style/layers/raster_layer_properties.hpp
new file mode 100644
index 0000000000..049da87312
--- /dev/null
+++ b/src/mbgl/style/layers/raster_layer_properties.hpp
@@ -0,0 +1,31 @@
+// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`.
+
+#pragma once
+
+#include <mbgl/style/layout_property.hpp>
+#include <mbgl/style/paint_property.hpp>
+#include <mbgl/util/rapidjson.hpp>
+
+namespace mbgl {
+namespace style {
+
+class CascadeParameters;
+class CalculationParameters;
+
+class RasterPaintProperties {
+public:
+ void parse(const JSValue&);
+ void cascade(const CascadeParameters&);
+ bool recalculate(const CalculationParameters&);
+
+ PaintProperty<float> rasterOpacity { 1 };
+ PaintProperty<float> rasterHueRotate { 0 };
+ PaintProperty<float> rasterBrightnessMin { 0 };
+ PaintProperty<float> rasterBrightnessMax { 1 };
+ PaintProperty<float> rasterSaturation { 0 };
+ PaintProperty<float> rasterContrast { 0 };
+ PaintProperty<float> rasterFadeDuration { 300 };
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layers/symbol_layer.cpp b/src/mbgl/style/layers/symbol_layer.cpp
new file mode 100644
index 0000000000..d7d6a02ace
--- /dev/null
+++ b/src/mbgl/style/layers/symbol_layer.cpp
@@ -0,0 +1,386 @@
+// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`.
+
+#include <mbgl/style/layers/symbol_layer.hpp>
+#include <mbgl/style/layers/symbol_layer_impl.hpp>
+
+namespace mbgl {
+namespace style {
+
+SymbolLayer::SymbolLayer(const std::string& layerID)
+ : Layer(Type::Symbol, std::make_unique<Impl>())
+ , impl(static_cast<Impl*>(baseImpl.get())) {
+ impl->id = layerID;
+}
+
+SymbolLayer::SymbolLayer(const Impl& other)
+ : Layer(Type::Symbol, std::make_unique<Impl>(other))
+ , impl(static_cast<Impl*>(baseImpl.get())) {
+}
+
+SymbolLayer::~SymbolLayer() = default;
+
+std::unique_ptr<Layer> SymbolLayer::Impl::clone() const {
+ return std::make_unique<SymbolLayer>(*this);
+}
+
+// Source
+
+void SymbolLayer::setSource(const std::string& sourceID, const std::string& sourceLayer) {
+ impl->source = sourceID;
+ impl->sourceLayer = sourceLayer;
+}
+
+const std::string& SymbolLayer::getSourceID() const {
+ return impl->source;
+}
+
+const std::string& SymbolLayer::getSourceLayer() const {
+ return impl->sourceLayer;
+}
+
+// Filter
+
+void SymbolLayer::setFilter(const Filter& filter) {
+ impl->filter = filter;
+}
+
+const Filter& SymbolLayer::getFilter() const {
+ return impl->filter;
+}
+
+// Layout properties
+
+PropertyValue<SymbolPlacementType> SymbolLayer::getSymbolPlacement() const {
+ return impl->layout.symbolPlacement.get();
+}
+
+void SymbolLayer::setSymbolPlacement(PropertyValue<SymbolPlacementType> value) {
+ impl->layout.symbolPlacement.set(value);
+}
+PropertyValue<float> SymbolLayer::getSymbolSpacing() const {
+ return impl->layout.symbolSpacing.get();
+}
+
+void SymbolLayer::setSymbolSpacing(PropertyValue<float> value) {
+ impl->layout.symbolSpacing.set(value);
+}
+PropertyValue<bool> SymbolLayer::getSymbolAvoidEdges() const {
+ return impl->layout.symbolAvoidEdges.get();
+}
+
+void SymbolLayer::setSymbolAvoidEdges(PropertyValue<bool> value) {
+ impl->layout.symbolAvoidEdges.set(value);
+}
+PropertyValue<bool> SymbolLayer::getIconAllowOverlap() const {
+ return impl->layout.iconAllowOverlap.get();
+}
+
+void SymbolLayer::setIconAllowOverlap(PropertyValue<bool> value) {
+ impl->layout.iconAllowOverlap.set(value);
+}
+PropertyValue<bool> SymbolLayer::getIconIgnorePlacement() const {
+ return impl->layout.iconIgnorePlacement.get();
+}
+
+void SymbolLayer::setIconIgnorePlacement(PropertyValue<bool> value) {
+ impl->layout.iconIgnorePlacement.set(value);
+}
+PropertyValue<bool> SymbolLayer::getIconOptional() const {
+ return impl->layout.iconOptional.get();
+}
+
+void SymbolLayer::setIconOptional(PropertyValue<bool> value) {
+ impl->layout.iconOptional.set(value);
+}
+PropertyValue<RotationAlignmentType> SymbolLayer::getIconRotationAlignment() const {
+ return impl->layout.iconRotationAlignment.get();
+}
+
+void SymbolLayer::setIconRotationAlignment(PropertyValue<RotationAlignmentType> value) {
+ impl->layout.iconRotationAlignment.set(value);
+}
+PropertyValue<float> SymbolLayer::getIconSize() const {
+ return impl->layout.iconSize.get();
+}
+
+void SymbolLayer::setIconSize(PropertyValue<float> value) {
+ impl->layout.iconSize.set(value);
+}
+PropertyValue<std::string> SymbolLayer::getIconImage() const {
+ return impl->layout.iconImage.get();
+}
+
+void SymbolLayer::setIconImage(PropertyValue<std::string> value) {
+ impl->layout.iconImage.set(value);
+}
+PropertyValue<float> SymbolLayer::getIconRotate() const {
+ return impl->layout.iconRotate.get();
+}
+
+void SymbolLayer::setIconRotate(PropertyValue<float> value) {
+ impl->layout.iconRotate.set(value);
+}
+PropertyValue<float> SymbolLayer::getIconPadding() const {
+ return impl->layout.iconPadding.get();
+}
+
+void SymbolLayer::setIconPadding(PropertyValue<float> value) {
+ impl->layout.iconPadding.set(value);
+}
+PropertyValue<bool> SymbolLayer::getIconKeepUpright() const {
+ return impl->layout.iconKeepUpright.get();
+}
+
+void SymbolLayer::setIconKeepUpright(PropertyValue<bool> value) {
+ impl->layout.iconKeepUpright.set(value);
+}
+PropertyValue<std::array<float, 2>> SymbolLayer::getIconOffset() const {
+ return impl->layout.iconOffset.get();
+}
+
+void SymbolLayer::setIconOffset(PropertyValue<std::array<float, 2>> value) {
+ impl->layout.iconOffset.set(value);
+}
+PropertyValue<RotationAlignmentType> SymbolLayer::getTextRotationAlignment() const {
+ return impl->layout.textRotationAlignment.get();
+}
+
+void SymbolLayer::setTextRotationAlignment(PropertyValue<RotationAlignmentType> value) {
+ impl->layout.textRotationAlignment.set(value);
+}
+PropertyValue<std::string> SymbolLayer::getTextField() const {
+ return impl->layout.textField.get();
+}
+
+void SymbolLayer::setTextField(PropertyValue<std::string> value) {
+ impl->layout.textField.set(value);
+}
+PropertyValue<std::vector<std::string>> SymbolLayer::getTextFont() const {
+ return impl->layout.textFont.get();
+}
+
+void SymbolLayer::setTextFont(PropertyValue<std::vector<std::string>> value) {
+ impl->layout.textFont.set(value);
+}
+PropertyValue<float> SymbolLayer::getTextSize() const {
+ return impl->layout.textSize.get();
+}
+
+void SymbolLayer::setTextSize(PropertyValue<float> value) {
+ impl->layout.textSize.set(value);
+}
+PropertyValue<float> SymbolLayer::getTextMaxWidth() const {
+ return impl->layout.textMaxWidth.get();
+}
+
+void SymbolLayer::setTextMaxWidth(PropertyValue<float> value) {
+ impl->layout.textMaxWidth.set(value);
+}
+PropertyValue<float> SymbolLayer::getTextLineHeight() const {
+ return impl->layout.textLineHeight.get();
+}
+
+void SymbolLayer::setTextLineHeight(PropertyValue<float> value) {
+ impl->layout.textLineHeight.set(value);
+}
+PropertyValue<float> SymbolLayer::getTextLetterSpacing() const {
+ return impl->layout.textLetterSpacing.get();
+}
+
+void SymbolLayer::setTextLetterSpacing(PropertyValue<float> value) {
+ impl->layout.textLetterSpacing.set(value);
+}
+PropertyValue<TextJustifyType> SymbolLayer::getTextJustify() const {
+ return impl->layout.textJustify.get();
+}
+
+void SymbolLayer::setTextJustify(PropertyValue<TextJustifyType> value) {
+ impl->layout.textJustify.set(value);
+}
+PropertyValue<TextAnchorType> SymbolLayer::getTextAnchor() const {
+ return impl->layout.textAnchor.get();
+}
+
+void SymbolLayer::setTextAnchor(PropertyValue<TextAnchorType> value) {
+ impl->layout.textAnchor.set(value);
+}
+PropertyValue<float> SymbolLayer::getTextMaxAngle() const {
+ return impl->layout.textMaxAngle.get();
+}
+
+void SymbolLayer::setTextMaxAngle(PropertyValue<float> value) {
+ impl->layout.textMaxAngle.set(value);
+}
+PropertyValue<float> SymbolLayer::getTextRotate() const {
+ return impl->layout.textRotate.get();
+}
+
+void SymbolLayer::setTextRotate(PropertyValue<float> value) {
+ impl->layout.textRotate.set(value);
+}
+PropertyValue<float> SymbolLayer::getTextPadding() const {
+ return impl->layout.textPadding.get();
+}
+
+void SymbolLayer::setTextPadding(PropertyValue<float> value) {
+ impl->layout.textPadding.set(value);
+}
+PropertyValue<bool> SymbolLayer::getTextKeepUpright() const {
+ return impl->layout.textKeepUpright.get();
+}
+
+void SymbolLayer::setTextKeepUpright(PropertyValue<bool> value) {
+ impl->layout.textKeepUpright.set(value);
+}
+PropertyValue<TextTransformType> SymbolLayer::getTextTransform() const {
+ return impl->layout.textTransform.get();
+}
+
+void SymbolLayer::setTextTransform(PropertyValue<TextTransformType> value) {
+ impl->layout.textTransform.set(value);
+}
+PropertyValue<std::array<float, 2>> SymbolLayer::getTextOffset() const {
+ return impl->layout.textOffset.get();
+}
+
+void SymbolLayer::setTextOffset(PropertyValue<std::array<float, 2>> value) {
+ impl->layout.textOffset.set(value);
+}
+PropertyValue<bool> SymbolLayer::getTextAllowOverlap() const {
+ return impl->layout.textAllowOverlap.get();
+}
+
+void SymbolLayer::setTextAllowOverlap(PropertyValue<bool> value) {
+ impl->layout.textAllowOverlap.set(value);
+}
+PropertyValue<bool> SymbolLayer::getTextIgnorePlacement() const {
+ return impl->layout.textIgnorePlacement.get();
+}
+
+void SymbolLayer::setTextIgnorePlacement(PropertyValue<bool> value) {
+ impl->layout.textIgnorePlacement.set(value);
+}
+PropertyValue<bool> SymbolLayer::getTextOptional() const {
+ return impl->layout.textOptional.get();
+}
+
+void SymbolLayer::setTextOptional(PropertyValue<bool> value) {
+ impl->layout.textOptional.set(value);
+}
+
+// Paint properties
+
+PropertyValue<float> SymbolLayer::getIconOpacity() const {
+ return impl->paint.iconOpacity.get();
+}
+
+void SymbolLayer::setIconOpacity(PropertyValue<float> value) {
+ impl->paint.iconOpacity.set(value);
+}
+
+PropertyValue<Color> SymbolLayer::getIconColor() const {
+ return impl->paint.iconColor.get();
+}
+
+void SymbolLayer::setIconColor(PropertyValue<Color> value) {
+ impl->paint.iconColor.set(value);
+}
+
+PropertyValue<Color> SymbolLayer::getIconHaloColor() const {
+ return impl->paint.iconHaloColor.get();
+}
+
+void SymbolLayer::setIconHaloColor(PropertyValue<Color> value) {
+ impl->paint.iconHaloColor.set(value);
+}
+
+PropertyValue<float> SymbolLayer::getIconHaloWidth() const {
+ return impl->paint.iconHaloWidth.get();
+}
+
+void SymbolLayer::setIconHaloWidth(PropertyValue<float> value) {
+ impl->paint.iconHaloWidth.set(value);
+}
+
+PropertyValue<float> SymbolLayer::getIconHaloBlur() const {
+ return impl->paint.iconHaloBlur.get();
+}
+
+void SymbolLayer::setIconHaloBlur(PropertyValue<float> value) {
+ impl->paint.iconHaloBlur.set(value);
+}
+
+PropertyValue<std::array<float, 2>> SymbolLayer::getIconTranslate() const {
+ return impl->paint.iconTranslate.get();
+}
+
+void SymbolLayer::setIconTranslate(PropertyValue<std::array<float, 2>> value) {
+ impl->paint.iconTranslate.set(value);
+}
+
+PropertyValue<TranslateAnchorType> SymbolLayer::getIconTranslateAnchor() const {
+ return impl->paint.iconTranslateAnchor.get();
+}
+
+void SymbolLayer::setIconTranslateAnchor(PropertyValue<TranslateAnchorType> value) {
+ impl->paint.iconTranslateAnchor.set(value);
+}
+
+PropertyValue<float> SymbolLayer::getTextOpacity() const {
+ return impl->paint.textOpacity.get();
+}
+
+void SymbolLayer::setTextOpacity(PropertyValue<float> value) {
+ impl->paint.textOpacity.set(value);
+}
+
+PropertyValue<Color> SymbolLayer::getTextColor() const {
+ return impl->paint.textColor.get();
+}
+
+void SymbolLayer::setTextColor(PropertyValue<Color> value) {
+ impl->paint.textColor.set(value);
+}
+
+PropertyValue<Color> SymbolLayer::getTextHaloColor() const {
+ return impl->paint.textHaloColor.get();
+}
+
+void SymbolLayer::setTextHaloColor(PropertyValue<Color> value) {
+ impl->paint.textHaloColor.set(value);
+}
+
+PropertyValue<float> SymbolLayer::getTextHaloWidth() const {
+ return impl->paint.textHaloWidth.get();
+}
+
+void SymbolLayer::setTextHaloWidth(PropertyValue<float> value) {
+ impl->paint.textHaloWidth.set(value);
+}
+
+PropertyValue<float> SymbolLayer::getTextHaloBlur() const {
+ return impl->paint.textHaloBlur.get();
+}
+
+void SymbolLayer::setTextHaloBlur(PropertyValue<float> value) {
+ impl->paint.textHaloBlur.set(value);
+}
+
+PropertyValue<std::array<float, 2>> SymbolLayer::getTextTranslate() const {
+ return impl->paint.textTranslate.get();
+}
+
+void SymbolLayer::setTextTranslate(PropertyValue<std::array<float, 2>> value) {
+ impl->paint.textTranslate.set(value);
+}
+
+PropertyValue<TranslateAnchorType> SymbolLayer::getTextTranslateAnchor() const {
+ return impl->paint.textTranslateAnchor.get();
+}
+
+void SymbolLayer::setTextTranslateAnchor(PropertyValue<TranslateAnchorType> value) {
+ impl->paint.textTranslateAnchor.set(value);
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layers/symbol_layer_impl.cpp b/src/mbgl/style/layers/symbol_layer_impl.cpp
new file mode 100644
index 0000000000..a4dc264ed2
--- /dev/null
+++ b/src/mbgl/style/layers/symbol_layer_impl.cpp
@@ -0,0 +1,82 @@
+#include <mbgl/style/layers/symbol_layer_impl.hpp>
+#include <mbgl/renderer/symbol_bucket.hpp>
+#include <mbgl/style/bucket_parameters.hpp>
+
+namespace mbgl {
+namespace style {
+
+void SymbolLayer::Impl::parseLayout(const JSValue& value) {
+ layout.parse(value);
+}
+
+void SymbolLayer::Impl::parsePaints(const JSValue& layer) {
+ paint.parse(layer);
+}
+
+void SymbolLayer::Impl::cascade(const CascadeParameters& parameters) {
+ paint.cascade(parameters);
+}
+
+bool SymbolLayer::Impl::recalculate(const CalculationParameters& parameters) {
+ bool hasTransitions = paint.recalculate(parameters);
+
+ // text-size and icon-size are layout properties but they also need to be evaluated as paint properties:
+ layout.iconSize.calculate(parameters);
+ layout.textSize.calculate(parameters);
+ iconSize = layout.iconSize;
+ textSize = layout.textSize;
+
+ passes = ((paint.iconOpacity > 0 && (paint.iconColor.value[3] > 0 || paint.iconHaloColor.value[3] > 0) && iconSize > 0)
+ || (paint.textOpacity > 0 && (paint.textColor.value[3] > 0 || paint.textHaloColor.value[3] > 0) && textSize > 0))
+ ? RenderPass::Translucent : RenderPass::None;
+
+ return hasTransitions;
+}
+
+std::unique_ptr<Bucket> SymbolLayer::Impl::createBucket(BucketParameters& parameters) const {
+ auto bucket = std::make_unique<SymbolBucket>(parameters.tileID.overscaleFactor(),
+ parameters.tileID.overscaledZ,
+ parameters.mode,
+ id,
+ parameters.layer.getName());
+
+ bucket->layout = layout;
+
+ CalculationParameters p(parameters.tileID.overscaledZ);
+ bucket->layout.symbolPlacement.calculate(p);
+ if (bucket->layout.symbolPlacement.value == SymbolPlacementType::Line) {
+ bucket->layout.iconRotationAlignment.value = RotationAlignmentType::Map;
+ bucket->layout.textRotationAlignment.value = RotationAlignmentType::Map;
+ };
+
+ bucket->layout.recalculate(p);
+
+ bucket->layout.iconSize.calculate(CalculationParameters(18));
+ bucket->layout.textSize.calculate(CalculationParameters(18));
+ bucket->iconMaxSize = bucket->layout.iconSize;
+ bucket->textMaxSize = bucket->layout.textSize;
+ bucket->layout.iconSize.calculate(CalculationParameters(p.z + 1));
+ bucket->layout.textSize.calculate(CalculationParameters(p.z + 1));
+
+ bucket->parseFeatures(parameters.layer, filter);
+
+ if (bucket->needsDependencies(parameters.glyphStore, parameters.spriteStore)) {
+ parameters.partialParse = true;
+ }
+
+ // We do not add features if the parser is in a "partial" state because
+ // the layer ordering needs to be respected when calculating text
+ // collisions. Although, at this point, we requested all the resources
+ // needed by this tile.
+ if (!parameters.partialParse) {
+ bucket->addFeatures(parameters.tileUID,
+ *spriteAtlas,
+ parameters.glyphAtlas,
+ parameters.glyphStore);
+ }
+
+ return std::move(bucket);
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layers/symbol_layer_impl.hpp b/src/mbgl/style/layers/symbol_layer_impl.hpp
new file mode 100644
index 0000000000..9727cc6480
--- /dev/null
+++ b/src/mbgl/style/layers/symbol_layer_impl.hpp
@@ -0,0 +1,35 @@
+#pragma once
+
+#include <mbgl/style/layer_impl.hpp>
+#include <mbgl/style/layers/symbol_layer.hpp>
+#include <mbgl/style/layers/symbol_layer_properties.hpp>
+
+namespace mbgl {
+
+class SpriteAtlas;
+
+namespace style {
+
+class SymbolLayer::Impl : public Layer::Impl {
+public:
+ std::unique_ptr<Layer> clone() const override;
+
+ void parseLayout(const JSValue&) override;
+ void parsePaints(const JSValue&) override;
+
+ void cascade(const CascadeParameters&) override;
+ bool recalculate(const CalculationParameters&) override;
+
+ std::unique_ptr<Bucket> createBucket(BucketParameters&) const override;
+
+ SymbolLayoutProperties layout;
+ SymbolPaintProperties paint;
+
+ float iconSize = 1.0f;
+ float textSize = 16.0f;
+
+ SpriteAtlas* spriteAtlas = nullptr;
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layers/symbol_layer_properties.cpp b/src/mbgl/style/layers/symbol_layer_properties.cpp
new file mode 100644
index 0000000000..ce16ae2e50
--- /dev/null
+++ b/src/mbgl/style/layers/symbol_layer_properties.cpp
@@ -0,0 +1,132 @@
+// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`.
+
+#include <mbgl/style/layers/symbol_layer_properties.hpp>
+
+namespace mbgl {
+namespace style {
+
+void SymbolLayoutProperties::parse(const JSValue& value) {
+ symbolPlacement.parse("symbol-placement", value);
+ symbolSpacing.parse("symbol-spacing", value);
+ symbolAvoidEdges.parse("symbol-avoid-edges", value);
+ iconAllowOverlap.parse("icon-allow-overlap", value);
+ iconIgnorePlacement.parse("icon-ignore-placement", value);
+ iconOptional.parse("icon-optional", value);
+ iconRotationAlignment.parse("icon-rotation-alignment", value);
+ iconSize.parse("icon-size", value);
+ iconImage.parse("icon-image", value);
+ iconRotate.parse("icon-rotate", value);
+ iconPadding.parse("icon-padding", value);
+ iconKeepUpright.parse("icon-keep-upright", value);
+ iconOffset.parse("icon-offset", value);
+ textRotationAlignment.parse("text-rotation-alignment", value);
+ textField.parse("text-field", value);
+ textFont.parse("text-font", value);
+ textSize.parse("text-size", value);
+ textMaxWidth.parse("text-max-width", value);
+ textLineHeight.parse("text-line-height", value);
+ textLetterSpacing.parse("text-letter-spacing", value);
+ textJustify.parse("text-justify", value);
+ textAnchor.parse("text-anchor", value);
+ textMaxAngle.parse("text-max-angle", value);
+ textRotate.parse("text-rotate", value);
+ textPadding.parse("text-padding", value);
+ textKeepUpright.parse("text-keep-upright", value);
+ textTransform.parse("text-transform", value);
+ textOffset.parse("text-offset", value);
+ textAllowOverlap.parse("text-allow-overlap", value);
+ textIgnorePlacement.parse("text-ignore-placement", value);
+ textOptional.parse("text-optional", value);
+}
+
+void SymbolLayoutProperties::recalculate(const CalculationParameters& parameters) {
+ symbolPlacement.calculate(parameters);
+ symbolSpacing.calculate(parameters);
+ symbolAvoidEdges.calculate(parameters);
+ iconAllowOverlap.calculate(parameters);
+ iconIgnorePlacement.calculate(parameters);
+ iconOptional.calculate(parameters);
+ iconRotationAlignment.calculate(parameters);
+ iconSize.calculate(parameters);
+ iconImage.calculate(parameters);
+ iconRotate.calculate(parameters);
+ iconPadding.calculate(parameters);
+ iconKeepUpright.calculate(parameters);
+ iconOffset.calculate(parameters);
+ textRotationAlignment.calculate(parameters);
+ textField.calculate(parameters);
+ textFont.calculate(parameters);
+ textSize.calculate(parameters);
+ textMaxWidth.calculate(parameters);
+ textLineHeight.calculate(parameters);
+ textLetterSpacing.calculate(parameters);
+ textJustify.calculate(parameters);
+ textAnchor.calculate(parameters);
+ textMaxAngle.calculate(parameters);
+ textRotate.calculate(parameters);
+ textPadding.calculate(parameters);
+ textKeepUpright.calculate(parameters);
+ textTransform.calculate(parameters);
+ textOffset.calculate(parameters);
+ textAllowOverlap.calculate(parameters);
+ textIgnorePlacement.calculate(parameters);
+ textOptional.calculate(parameters);
+}
+
+void SymbolPaintProperties::parse(const JSValue& value) {
+ iconOpacity.parse("icon-opacity", value);
+ iconColor.parse("icon-color", value);
+ iconHaloColor.parse("icon-halo-color", value);
+ iconHaloWidth.parse("icon-halo-width", value);
+ iconHaloBlur.parse("icon-halo-blur", value);
+ iconTranslate.parse("icon-translate", value);
+ iconTranslateAnchor.parse("icon-translate-anchor", value);
+ textOpacity.parse("text-opacity", value);
+ textColor.parse("text-color", value);
+ textHaloColor.parse("text-halo-color", value);
+ textHaloWidth.parse("text-halo-width", value);
+ textHaloBlur.parse("text-halo-blur", value);
+ textTranslate.parse("text-translate", value);
+ textTranslateAnchor.parse("text-translate-anchor", value);
+}
+
+void SymbolPaintProperties::cascade(const CascadeParameters& parameters) {
+ iconOpacity.cascade(parameters);
+ iconColor.cascade(parameters);
+ iconHaloColor.cascade(parameters);
+ iconHaloWidth.cascade(parameters);
+ iconHaloBlur.cascade(parameters);
+ iconTranslate.cascade(parameters);
+ iconTranslateAnchor.cascade(parameters);
+ textOpacity.cascade(parameters);
+ textColor.cascade(parameters);
+ textHaloColor.cascade(parameters);
+ textHaloWidth.cascade(parameters);
+ textHaloBlur.cascade(parameters);
+ textTranslate.cascade(parameters);
+ textTranslateAnchor.cascade(parameters);
+}
+
+bool SymbolPaintProperties::recalculate(const CalculationParameters& parameters) {
+ bool hasTransitions = false;
+
+ hasTransitions |= iconOpacity.calculate(parameters);
+ hasTransitions |= iconColor.calculate(parameters);
+ hasTransitions |= iconHaloColor.calculate(parameters);
+ hasTransitions |= iconHaloWidth.calculate(parameters);
+ hasTransitions |= iconHaloBlur.calculate(parameters);
+ hasTransitions |= iconTranslate.calculate(parameters);
+ hasTransitions |= iconTranslateAnchor.calculate(parameters);
+ hasTransitions |= textOpacity.calculate(parameters);
+ hasTransitions |= textColor.calculate(parameters);
+ hasTransitions |= textHaloColor.calculate(parameters);
+ hasTransitions |= textHaloWidth.calculate(parameters);
+ hasTransitions |= textHaloBlur.calculate(parameters);
+ hasTransitions |= textTranslate.calculate(parameters);
+ hasTransitions |= textTranslateAnchor.calculate(parameters);
+
+ return hasTransitions;
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layers/symbol_layer_properties.hpp b/src/mbgl/style/layers/symbol_layer_properties.hpp
new file mode 100644
index 0000000000..38455b5cac
--- /dev/null
+++ b/src/mbgl/style/layers/symbol_layer_properties.hpp
@@ -0,0 +1,76 @@
+// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`.
+
+#pragma once
+
+#include <mbgl/style/layout_property.hpp>
+#include <mbgl/style/paint_property.hpp>
+#include <mbgl/util/rapidjson.hpp>
+
+namespace mbgl {
+namespace style {
+
+class CascadeParameters;
+class CalculationParameters;
+
+class SymbolLayoutProperties {
+public:
+ void parse(const JSValue&);
+ void recalculate(const CalculationParameters&);
+
+ LayoutProperty<SymbolPlacementType> symbolPlacement { SymbolPlacementType::Point };
+ LayoutProperty<float> symbolSpacing { 250 };
+ LayoutProperty<bool> symbolAvoidEdges { false };
+ LayoutProperty<bool> iconAllowOverlap { false };
+ LayoutProperty<bool> iconIgnorePlacement { false };
+ LayoutProperty<bool> iconOptional { false };
+ LayoutProperty<RotationAlignmentType> iconRotationAlignment { RotationAlignmentType::Viewport };
+ LayoutProperty<float> iconSize { 1 };
+ LayoutProperty<std::string> iconImage { "" };
+ LayoutProperty<float> iconRotate { 0 };
+ LayoutProperty<float> iconPadding { 2 };
+ LayoutProperty<bool> iconKeepUpright { false };
+ LayoutProperty<std::array<float, 2>> iconOffset { {{ 0, 0 }} };
+ LayoutProperty<RotationAlignmentType> textRotationAlignment { RotationAlignmentType::Viewport };
+ LayoutProperty<std::string> textField { "" };
+ LayoutProperty<std::vector<std::string>> textFont { { "Open Sans Regular", "Arial Unicode MS Regular" } };
+ LayoutProperty<float> textSize { 16 };
+ LayoutProperty<float> textMaxWidth { 10 };
+ LayoutProperty<float> textLineHeight { 1.2 };
+ LayoutProperty<float> textLetterSpacing { 0 };
+ LayoutProperty<TextJustifyType> textJustify { TextJustifyType::Center };
+ LayoutProperty<TextAnchorType> textAnchor { TextAnchorType::Center };
+ LayoutProperty<float> textMaxAngle { 45 };
+ LayoutProperty<float> textRotate { 0 };
+ LayoutProperty<float> textPadding { 2 };
+ LayoutProperty<bool> textKeepUpright { true };
+ LayoutProperty<TextTransformType> textTransform { TextTransformType::None };
+ LayoutProperty<std::array<float, 2>> textOffset { {{ 0, 0 }} };
+ LayoutProperty<bool> textAllowOverlap { false };
+ LayoutProperty<bool> textIgnorePlacement { false };
+ LayoutProperty<bool> textOptional { false };
+};
+
+class SymbolPaintProperties {
+public:
+ void parse(const JSValue&);
+ void cascade(const CascadeParameters&);
+ bool recalculate(const CalculationParameters&);
+
+ PaintProperty<float> iconOpacity { 1 };
+ PaintProperty<Color> iconColor { {{ 0, 0, 0, 1 }} };
+ PaintProperty<Color> iconHaloColor { {{ 0, 0, 0, 0 }} };
+ PaintProperty<float> iconHaloWidth { 0 };
+ PaintProperty<float> iconHaloBlur { 0 };
+ PaintProperty<std::array<float, 2>> iconTranslate { {{ 0, 0 }} };
+ PaintProperty<TranslateAnchorType> iconTranslateAnchor { TranslateAnchorType::Map };
+ PaintProperty<float> textOpacity { 1 };
+ PaintProperty<Color> textColor { {{ 0, 0, 0, 1 }} };
+ PaintProperty<Color> textHaloColor { {{ 0, 0, 0, 0 }} };
+ PaintProperty<float> textHaloWidth { 0 };
+ PaintProperty<float> textHaloBlur { 0 };
+ PaintProperty<std::array<float, 2>> textTranslate { {{ 0, 0 }} };
+ PaintProperty<TranslateAnchorType> textTranslateAnchor { TranslateAnchorType::Map };
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layout_property.hpp b/src/mbgl/style/layout_property.hpp
index b4857aeae5..f5045b47fc 100644
--- a/src/mbgl/style/layout_property.hpp
+++ b/src/mbgl/style/layout_property.hpp
@@ -8,6 +8,7 @@
#include <utility>
namespace mbgl {
+namespace style {
template <typename T>
class LayoutProperty {
@@ -30,7 +31,7 @@ public:
}
}
- void calculate(const StyleCalculationParameters& parameters) {
+ void calculate(const CalculationParameters& parameters) {
if (currentValue) {
PropertyEvaluator<T> evaluator(parameters, defaultValue);
value = PropertyValue<T>::visit(currentValue, evaluator);
@@ -46,4 +47,5 @@ private:
PropertyValue<T> currentValue;
};
+} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/style_observer.hpp b/src/mbgl/style/observer.hpp
index 9e2c946f7d..c19f58904f 100644
--- a/src/mbgl/style/style_observer.hpp
+++ b/src/mbgl/style/observer.hpp
@@ -2,22 +2,24 @@
#include <mbgl/text/glyph_store_observer.hpp>
#include <mbgl/sprite/sprite_store_observer.hpp>
-#include <mbgl/source/source_observer.hpp>
+#include <mbgl/style/source_observer.hpp>
namespace mbgl {
+namespace style {
-class StyleObserver : public GlyphStoreObserver, public SpriteStoreObserver, public SourceObserver {
+class Observer : public GlyphStoreObserver,
+ public SpriteStoreObserver,
+ public SourceObserver {
public:
- virtual ~StyleObserver() = default;
-
/**
* In addition to the individual glyph, sprite, and source events, the
* following "rollup" events are provided for convenience. They are
* strictly additive; e.g. when a source is loaded, both `onSourceLoaded`
* and `onResourceLoaded` will be called.
*/
- virtual void onResourceLoaded() {}
- virtual void onResourceError(std::exception_ptr) {}
+ virtual void onResourceLoaded() {};
+ virtual void onResourceError(std::exception_ptr) {};
};
+} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/paint_property.hpp b/src/mbgl/style/paint_property.hpp
index 8428a90533..62fd59684e 100644
--- a/src/mbgl/style/paint_property.hpp
+++ b/src/mbgl/style/paint_property.hpp
@@ -3,9 +3,9 @@
#include <mbgl/style/class_dictionary.hpp>
#include <mbgl/style/property_parsing.hpp>
#include <mbgl/style/property_evaluator.hpp>
-#include <mbgl/style/property_transition.hpp>
-#include <mbgl/style/style_cascade_parameters.hpp>
-#include <mbgl/style/style_calculation_parameters.hpp>
+#include <mbgl/style/transition_options.hpp>
+#include <mbgl/style/cascade_parameters.hpp>
+#include <mbgl/style/calculation_parameters.hpp>
#include <mbgl/util/interpolate.hpp>
#include <mbgl/util/std.hpp>
#include <mbgl/util/rapidjson.hpp>
@@ -14,6 +14,7 @@
#include <utility>
namespace mbgl {
+namespace style {
template <class T, template <class S> class Evaluator = PropertyEvaluator>
class PaintProperty {
@@ -62,14 +63,14 @@ public:
}
if (it->value.HasMember(transitionName.c_str())) {
- if (auto v = parsePropertyTransition(name, it->value[transitionName.c_str()])) {
+ if (auto v = parseTransitionOptions(name, it->value[transitionName.c_str()])) {
transitions.emplace(classID, *v);
}
}
}
}
- void cascade(const StyleCascadeParameters& params) {
+ void cascade(const CascadeParameters& params) {
const bool overrideTransition = !params.transition.delay && !params.transition.duration;
Duration delay = params.transition.delay.value_or(Duration::zero());
Duration duration = params.transition.duration.value_or(Duration::zero());
@@ -79,7 +80,7 @@ public:
continue;
if (overrideTransition && transitions.find(classID) != transitions.end()) {
- const PropertyTransition& transition = transitions[classID];
+ const TransitionOptions& transition = transitions[classID];
if (transition.delay) delay = *transition.delay;
if (transition.duration) duration = *transition.duration;
}
@@ -95,7 +96,7 @@ public:
assert(cascaded);
}
- bool calculate(const StyleCalculationParameters& parameters) {
+ bool calculate(const CalculationParameters& parameters) {
assert(cascaded);
Evaluator<T> evaluator(parameters, defaultValue);
value = cascaded->calculate(evaluator, parameters.now);
@@ -109,7 +110,7 @@ public:
private:
T defaultValue;
std::map<ClassID, PropertyValue<T>> values;
- std::map<ClassID, PropertyTransition> transitions;
+ std::map<ClassID, TransitionOptions> transitions;
struct CascadedValue {
CascadedValue(std::unique_ptr<CascadedValue> prior_,
@@ -147,4 +148,5 @@ private:
std::unique_ptr<CascadedValue> cascaded;
};
+} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/style_parser.cpp b/src/mbgl/style/parser.cpp
index 95ab36498d..28a7d2e81b 100644
--- a/src/mbgl/style/style_parser.cpp
+++ b/src/mbgl/style/parser.cpp
@@ -1,11 +1,11 @@
-#include <mbgl/style/style_parser.hpp>
-#include <mbgl/layer/fill_layer.hpp>
-#include <mbgl/layer/line_layer.hpp>
-#include <mbgl/layer/circle_layer.hpp>
-#include <mbgl/layer/symbol_layer.hpp>
-#include <mbgl/layer/raster_layer.hpp>
-#include <mbgl/layer/background_layer.hpp>
-#include <mbgl/layer/layer_impl.hpp>
+#include <mbgl/style/parser.hpp>
+#include <mbgl/style/layer_impl.hpp>
+#include <mbgl/style/layers/fill_layer.hpp>
+#include <mbgl/style/layers/line_layer.hpp>
+#include <mbgl/style/layers/circle_layer.hpp>
+#include <mbgl/style/layers/symbol_layer.hpp>
+#include <mbgl/style/layers/raster_layer.hpp>
+#include <mbgl/style/layers/background_layer.hpp>
#include <mbgl/platform/log.hpp>
@@ -23,7 +23,7 @@
#include <set>
namespace mbgl {
-
+namespace style {
namespace {
@@ -102,9 +102,9 @@ void parseTileJSONMember(const JSValue& value, std::array<double, 4>& target, co
} // end namespace
-StyleParser::~StyleParser() = default;
+Parser::~Parser() = default;
-void StyleParser::parse(const std::string& json) {
+void Parser::parse(const std::string& json) {
rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> document;
document.Parse<0>(json.c_str());
@@ -143,7 +143,7 @@ void StyleParser::parse(const std::string& json) {
}
}
-void StyleParser::parseSources(const JSValue& value) {
+void Parser::parseSources(const JSValue& value) {
if (!value.IsObject()) {
Log::Warning(Event::ParseStyle, "sources must be an object");
return;
@@ -174,7 +174,7 @@ void StyleParser::parseSources(const JSValue& value) {
uint16_t tileSize = util::tileSize;
- std::unique_ptr<SourceInfo> info;
+ std::unique_ptr<Tileset> tileset;
std::unique_ptr<mapbox::geojsonvt::GeoJSONVT> geojsonvt;
switch (type) {
@@ -200,12 +200,12 @@ void StyleParser::parseSources(const JSValue& value) {
continue;
}
} else {
- info = parseTileJSON(sourceVal);
+ tileset = parseTileJSON(sourceVal);
}
break;
case SourceType::GeoJSON:
- info = std::make_unique<SourceInfo>();
+ tileset = std::make_unique<Tileset>();
// We should probably split this up to have URLs in the url property, and actual data
// in the data property. Until then, we're going to detect the content based on the
@@ -218,7 +218,7 @@ void StyleParser::parseSources(const JSValue& value) {
} else if (dataVal.IsObject()) {
// We need to parse dataVal as a GeoJSON object
geojsonvt = parseGeoJSON(dataVal);
- info->maxZoom = geojsonvt->options.maxZoom;
+ tileset->maxZoom = geojsonvt->options.maxZoom;
} else {
Log::Error(Event::ParseStyle, "GeoJSON data must be a URL or an object");
continue;
@@ -236,14 +236,14 @@ void StyleParser::parseSources(const JSValue& value) {
}
const std::string id { nameVal.GetString(), nameVal.GetStringLength() };
- std::unique_ptr<Source> source = std::make_unique<Source>(type, id, url, tileSize, std::move(info), std::move(geojsonvt));
+ std::unique_ptr<Source> source = std::make_unique<Source>(type, id, url, tileSize, std::move(tileset), std::move(geojsonvt));
sourcesMap.emplace(id, source.get());
sources.emplace_back(std::move(source));
}
}
-std::unique_ptr<mapbox::geojsonvt::GeoJSONVT> StyleParser::parseGeoJSON(const JSValue& value) {
+std::unique_ptr<mapbox::geojsonvt::GeoJSONVT> parseGeoJSON(const JSValue& value) {
using namespace mapbox::geojsonvt;
Options options;
@@ -260,7 +260,7 @@ std::unique_ptr<mapbox::geojsonvt::GeoJSONVT> StyleParser::parseGeoJSON(const JS
}
}
-std::unique_ptr<SourceInfo> StyleParser::parseTileJSON(const std::string& json, const std::string& sourceURL, SourceType type, uint16_t tileSize) {
+std::unique_ptr<Tileset> parseTileJSON(const std::string& json, const std::string& sourceURL, SourceType type, uint16_t tileSize) {
rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> document;
document.Parse<0>(json.c_str());
@@ -270,7 +270,7 @@ std::unique_ptr<SourceInfo> StyleParser::parseTileJSON(const std::string& json,
throw std::runtime_error(message.str());
}
- std::unique_ptr<SourceInfo> result = StyleParser::parseTileJSON(document);
+ std::unique_ptr<Tileset> result = parseTileJSON(document);
// TODO: Remove this hack by delivering proper URLs in the TileJSON to begin with.
if (util::mapbox::isMapboxURL(sourceURL)) {
@@ -282,24 +282,24 @@ std::unique_ptr<SourceInfo> StyleParser::parseTileJSON(const std::string& json,
return result;
}
-std::unique_ptr<SourceInfo> StyleParser::parseTileJSON(const JSValue& value) {
- auto info = std::make_unique<SourceInfo>();
- parseTileJSONMember(value, info->tiles, "tiles");
- parseTileJSONMember(value, info->minZoom, "minzoom");
- parseTileJSONMember(value, info->maxZoom, "maxzoom");
- parseTileJSONMember(value, info->attribution, "attribution");
+std::unique_ptr<Tileset> parseTileJSON(const JSValue& value) {
+ auto tileset = std::make_unique<Tileset>();
+ parseTileJSONMember(value, tileset->tiles, "tiles");
+ parseTileJSONMember(value, tileset->minZoom, "minzoom");
+ parseTileJSONMember(value, tileset->maxZoom, "maxzoom");
+ parseTileJSONMember(value, tileset->attribution, "attribution");
std::array<double, 4> array;
parseTileJSONMember(value, array, "center");
- info->center = { array[0], array[1] };
- info->zoom = array[2];
+ tileset->center = { array[0], array[1] };
+ tileset->zoom = array[2];
parseTileJSONMember(value, array, "bounds");
- info->bounds = LatLngBounds::hull({ array[0], array[1] }, { array[2], array[3] });
+ tileset->bounds = LatLngBounds::hull({ array[0], array[1] }, { array[2], array[3] });
- return info;
+ return tileset;
}
-void StyleParser::parseLayers(const JSValue& value) {
+void Parser::parseLayers(const JSValue& value) {
std::vector<std::string> ids;
if (!value.IsArray()) {
@@ -353,7 +353,7 @@ void StyleParser::parseLayers(const JSValue& value) {
}
}
-void StyleParser::parseLayer(const std::string& id, const JSValue& value, std::unique_ptr<Layer>& layer) {
+void Parser::parseLayer(const std::string& id, const JSValue& value, std::unique_ptr<Layer>& layer) {
if (layer) {
// Skip parsing this again. We already have a valid layer definition.
return;
@@ -486,7 +486,7 @@ MBGL_DEFINE_ENUM_CLASS(VisibilityTypeClass, VisibilityType, {
{ VisibilityType::None, "none" },
});
-void StyleParser::parseVisibility(Layer& layer, const JSValue& value) {
+void Parser::parseVisibility(Layer& layer, const JSValue& value) {
Layer::Impl& impl = *layer.baseImpl;
if (!value.HasMember("visibility")) {
return;
@@ -664,7 +664,7 @@ Filter parseFilter(const JSValue& value) {
}
}
-std::vector<FontStack> StyleParser::fontStacks() const {
+std::vector<FontStack> Parser::fontStacks() const {
std::set<FontStack> result;
for (const auto& layer : layers) {
@@ -685,4 +685,5 @@ std::vector<FontStack> StyleParser::fontStacks() const {
return std::vector<FontStack>(result.begin(), result.end());
}
+} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/style_parser.hpp b/src/mbgl/style/parser.hpp
index b5445bbfb3..ea821fabde 100644
--- a/src/mbgl/style/style_parser.hpp
+++ b/src/mbgl/style/parser.hpp
@@ -1,10 +1,11 @@
#pragma once
-#include <mbgl/style/types.hpp>
#include <mbgl/style/layer.hpp>
-#include <mbgl/source/source.hpp>
+#include <mbgl/style/source.hpp>
#include <mbgl/style/filter.hpp>
+
#include <mbgl/util/rapidjson.hpp>
+#include <mbgl/util/font_stack.hpp>
#include <vector>
#include <memory>
@@ -13,12 +14,18 @@
#include <forward_list>
namespace mbgl {
+namespace style {
+
+std::unique_ptr<Tileset> parseTileJSON(const std::string& json, const std::string& sourceURL, SourceType, uint16_t tileSize);
+std::unique_ptr<Tileset> parseTileJSON(const JSValue&);
+
+std::unique_ptr<mapbox::geojsonvt::GeoJSONVT> parseGeoJSON(const JSValue&);
Filter parseFilter(const JSValue&);
-class StyleParser {
+class Parser {
public:
- ~StyleParser();
+ ~Parser();
void parse(const std::string&);
@@ -31,11 +38,6 @@ public:
// Statically evaluate layer properties to determine what font stacks are used.
std::vector<FontStack> fontStacks() const;
- static std::unique_ptr<SourceInfo> parseTileJSON(const std::string& json, const std::string& sourceURL, SourceType, uint16_t tileSize);
- static std::unique_ptr<SourceInfo> parseTileJSON(const JSValue&);
-
- static std::unique_ptr<mapbox::geojsonvt::GeoJSONVT> parseGeoJSON(const JSValue&);
-
private:
void parseSources(const JSValue&);
void parseLayers(const JSValue&);
@@ -49,4 +51,5 @@ private:
std::forward_list<std::string> stack;
};
+} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/property_evaluator.cpp b/src/mbgl/style/property_evaluator.cpp
index 08eea899c2..d2e633c782 100644
--- a/src/mbgl/style/property_evaluator.cpp
+++ b/src/mbgl/style/property_evaluator.cpp
@@ -1,12 +1,14 @@
#include <mbgl/style/property_evaluator.hpp>
-#include <mbgl/style/style_calculation_parameters.hpp>
+#include <mbgl/style/calculation_parameters.hpp>
#include <mbgl/style/types.hpp>
#include <mbgl/util/interpolate.hpp>
#include <mbgl/util/chrono.hpp>
+#include <mbgl/util/color.hpp>
#include <cmath>
namespace mbgl {
+namespace style {
template <typename T>
inline T defaultStopsValue();
@@ -140,4 +142,5 @@ Faded<T> CrossFadedPropertyEvaluator<T>::calculate(const T& min, const T& mid, c
template class CrossFadedPropertyEvaluator<std::string>;
template class CrossFadedPropertyEvaluator<std::vector<float>>;
+} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/property_evaluator.hpp b/src/mbgl/style/property_evaluator.hpp
index 112c373a44..77100bda46 100644
--- a/src/mbgl/style/property_evaluator.hpp
+++ b/src/mbgl/style/property_evaluator.hpp
@@ -4,15 +4,16 @@
#include <mbgl/util/interpolate.hpp>
namespace mbgl {
+namespace style {
-class StyleCalculationParameters;
+class CalculationParameters;
template <typename T>
class PropertyEvaluator {
public:
using ResultType = T;
- PropertyEvaluator(const StyleCalculationParameters& parameters_, const T& defaultValue_)
+ PropertyEvaluator(const CalculationParameters& parameters_, const T& defaultValue_)
: parameters(parameters_),
defaultValue(defaultValue_) {}
@@ -21,7 +22,7 @@ public:
T operator()(const Function<T>&) const;
private:
- const StyleCalculationParameters& parameters;
+ const CalculationParameters& parameters;
T defaultValue;
};
@@ -39,7 +40,7 @@ class CrossFadedPropertyEvaluator {
public:
using ResultType = Faded<T>;
- CrossFadedPropertyEvaluator(const StyleCalculationParameters& parameters_, const T& defaultValue_)
+ CrossFadedPropertyEvaluator(const CalculationParameters& parameters_, const T& defaultValue_)
: parameters(parameters_),
defaultValue(defaultValue_) {}
@@ -50,13 +51,15 @@ public:
private:
Faded<T> calculate(const T& min, const T& mid, const T& max) const;
- const StyleCalculationParameters& parameters;
+ const CalculationParameters& parameters;
T defaultValue;
};
+} // namespace style
+
namespace util {
template <typename T>
-struct Interpolator<Faded<T>>
+struct Interpolator<style::Faded<T>>
: Uninterpolated {};
}
diff --git a/src/mbgl/style/property_parsing.cpp b/src/mbgl/style/property_parsing.cpp
index 67baa3ec8d..9f60ddf3b6 100644
--- a/src/mbgl/style/property_parsing.cpp
+++ b/src/mbgl/style/property_parsing.cpp
@@ -1,11 +1,11 @@
#include <mbgl/style/property_parsing.hpp>
-#include <mbgl/style/property_transition.hpp>
#include <mbgl/platform/log.hpp>
#include <csscolorparser/csscolorparser.hpp>
namespace mbgl {
+namespace style {
template <>
optional<bool> parseConstant(const char* name, const JSValue& value) {
@@ -264,7 +264,7 @@ optional<std::vector<std::string>> parseConstant(const char* name, const JSValue
return result;
}
-optional<PropertyTransition> parsePropertyTransition(const char *, const JSValue& value) {
+optional<TransitionOptions> parseTransitionOptions(const char *, const JSValue& value) {
if (!value.IsObject()) {
return {};
}
@@ -283,7 +283,8 @@ optional<PropertyTransition> parsePropertyTransition(const char *, const JSValue
return {};
}
- return PropertyTransition(duration, delay);
+ return TransitionOptions(duration, delay);
}
+} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/property_parsing.hpp b/src/mbgl/style/property_parsing.hpp
index c0fe5ce2bc..bb894c2407 100644
--- a/src/mbgl/style/property_parsing.hpp
+++ b/src/mbgl/style/property_parsing.hpp
@@ -2,10 +2,11 @@
#include <mbgl/style/types.hpp>
#include <mbgl/style/property_value.hpp>
-#include <mbgl/style/property_transition.hpp>
+#include <mbgl/style/transition_options.hpp>
#include <mbgl/util/rapidjson.hpp>
#include <mbgl/util/optional.hpp>
+#include <mbgl/util/color.hpp>
#include <mbgl/platform/log.hpp>
@@ -14,6 +15,7 @@
#include <vector>
namespace mbgl {
+namespace style {
template <typename T>
optional<T> parseConstant(const char* name, const JSValue&);
@@ -104,6 +106,7 @@ PropertyValue<T> parseProperty(const char* name, const JSValue& value) {
return Function<T>(stops, base);
}
-optional<PropertyTransition> parsePropertyTransition(const char * name, const JSValue&);
+optional<TransitionOptions> parseTransitionOptions(const char * name, const JSValue&);
+} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/property_value.hpp b/src/mbgl/style/property_value.hpp
deleted file mode 100644
index 377e4f17e0..0000000000
--- a/src/mbgl/style/property_value.hpp
+++ /dev/null
@@ -1,36 +0,0 @@
-#pragma once
-
-#include <mbgl/util/variant.hpp>
-#include <mbgl/style/types.hpp>
-
-namespace mbgl {
-
-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);
- }
-};
-
-}
diff --git a/src/mbgl/style/style_query_parameters.hpp b/src/mbgl/style/query_parameters.hpp
index 33115bdfb2..3c1abf3b70 100644
--- a/src/mbgl/style/style_query_parameters.hpp
+++ b/src/mbgl/style/query_parameters.hpp
@@ -8,11 +8,14 @@ namespace mbgl {
class TransformState;
-class StyleQueryParameters {
+namespace style {
+
+class QueryParameters {
public:
const ScreenLineString& geometry;
const TransformState& transformState;
const optional<std::vector<std::string>>& layerIDs;
};
+} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/render_item.hpp b/src/mbgl/style/render_item.hpp
index ebf6799828..da59591c36 100644
--- a/src/mbgl/style/render_item.hpp
+++ b/src/mbgl/style/render_item.hpp
@@ -2,12 +2,15 @@
namespace mbgl {
-class Layer;
class Tile;
class Bucket;
+namespace style {
+class Layer;
+}
+
struct RenderItem {
- inline RenderItem(const Layer& layer_,
+ inline RenderItem(const style::Layer& layer_,
const Tile* tile_ = nullptr,
Bucket* bucket_ = nullptr)
: tile(tile_), bucket(bucket_), layer(layer_) {
@@ -15,7 +18,7 @@ struct RenderItem {
const Tile* const tile;
Bucket* const bucket;
- const Layer& layer;
+ const style::Layer& layer;
};
} // namespace mbgl
diff --git a/src/mbgl/style/source.cpp b/src/mbgl/style/source.cpp
new file mode 100644
index 0000000000..8e5973f412
--- /dev/null
+++ b/src/mbgl/style/source.cpp
@@ -0,0 +1,428 @@
+#include <mbgl/style/source.hpp>
+#include <mbgl/style/source_observer.hpp>
+#include <mbgl/map/transform.hpp>
+#include <mbgl/tile/tile.hpp>
+#include <mbgl/tile/vector_tile.hpp>
+#include <mbgl/annotation/annotation_tile.hpp>
+#include <mbgl/tile/geojson_tile.hpp>
+#include <mbgl/renderer/painter.hpp>
+#include <mbgl/util/exception.hpp>
+#include <mbgl/util/constants.hpp>
+#include <mbgl/storage/resource.hpp>
+#include <mbgl/storage/response.hpp>
+#include <mbgl/storage/file_source.hpp>
+#include <mbgl/style/layer.hpp>
+#include <mbgl/style/update_parameters.hpp>
+#include <mbgl/style/query_parameters.hpp>
+#include <mbgl/platform/log.hpp>
+#include <mbgl/math/minmax.hpp>
+#include <mbgl/math/clamp.hpp>
+#include <mbgl/util/std.hpp>
+#include <mbgl/util/token.hpp>
+#include <mbgl/util/string.hpp>
+#include <mbgl/util/tile_cover.hpp>
+
+#include <mbgl/tile/vector_tile_data.hpp>
+#include <mbgl/tile/raster_tile_data.hpp>
+#include <mbgl/style/parser.hpp>
+#include <mbgl/gl/debugging.hpp>
+
+#include <mbgl/algorithm/update_renderables.hpp>
+
+#include <mapbox/geojsonvt.hpp>
+#include <mapbox/geojsonvt/convert.hpp>
+#include <mapbox/geometry/envelope.hpp>
+
+#include <rapidjson/error/en.h>
+
+#include <algorithm>
+#include <sstream>
+
+namespace mbgl {
+namespace style {
+
+static SourceObserver nullObserver;
+
+Source::Source(SourceType type_,
+ const std::string& id_,
+ const std::string& url_,
+ uint16_t tileSize_,
+ std::unique_ptr<Tileset>&& tileset_,
+ std::unique_ptr<mapbox::geojsonvt::GeoJSONVT>&& geojsonvt_)
+ : type(type_),
+ id(id_),
+ url(url_),
+ tileSize(tileSize_),
+ tileset(std::move(tileset_)),
+ geojsonvt(std::move(geojsonvt_)),
+ observer(&nullObserver) {
+}
+
+Source::~Source() = default;
+
+bool Source::isLoaded() const {
+ if (!loaded) return false;
+
+ for (const auto& pair : tileDataMap) {
+ if (!pair.second->isComplete()) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool Source::isLoading() const {
+ return !loaded && req.operator bool();
+}
+
+void Source::load(FileSource& fileSource) {
+ if (url.empty()) {
+ // In case there is no URL set, we assume that we already have all of the data because the
+ // TileJSON was specified inline in the stylesheet.
+ loaded = true;
+ return;
+ }
+
+ if (req) {
+ // We don't have a Tileset object yet, but there's already a request underway to load
+ // the data.
+ return;
+ }
+
+ // URL may either be a TileJSON file, or a GeoJSON file.
+ req = fileSource.request(Resource::source(url), [this](Response res) {
+ if (res.error) {
+ observer->onSourceError(*this, std::make_exception_ptr(std::runtime_error(res.error->message)));
+ } else if (res.notModified) {
+ return;
+ } else if (res.noContent) {
+ observer->onSourceError(*this, std::make_exception_ptr(std::runtime_error("unexpectedly empty source")));
+ } else {
+ bool reloadTiles = false;
+
+ if (type == SourceType::Vector || type == SourceType::Raster) {
+ std::unique_ptr<Tileset> newTileset;
+
+ // Create a new copy of the Tileset object that holds the base values we've parsed
+ // from the stylesheet. Then merge in the values parsed from the TileJSON we retrieved
+ // via the URL.
+ try {
+ newTileset = style::parseTileJSON(*res.data, url, type, tileSize);
+ } catch (...) {
+ observer->onSourceError(*this, std::current_exception());
+ return;
+ }
+
+ // Check whether previous information specifies different tile
+ if (tileset && tileset->tiles != newTileset->tiles) {
+ reloadTiles = true;
+
+ // Tile size changed: We need to recalculate the tiles we need to load because we
+ // might have to load tiles for a different zoom level
+ // This is done automatically when we trigger the onSourceLoaded observer below.
+
+ // Min/Max zoom changed: We need to recalculate what tiles to load, if we have tiles
+ // loaded that are outside the new zoom range
+ // This is done automatically when we trigger the onSourceLoaded observer below.
+
+ // Attribution changed: We need to notify the embedding application that this
+ // changed. See https://github.com/mapbox/mapbox-gl-native/issues/2723
+ // This is not yet implemented.
+
+ // Center/bounds changed: We're not using these values currently
+ }
+
+ tileset = std::move(newTileset);
+ } else if (type == SourceType::GeoJSON) {
+ std::unique_ptr<Tileset> newTileset = std::make_unique<Tileset>();
+
+ rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> d;
+ d.Parse<0>(res.data->c_str());
+
+ if (d.HasParseError()) {
+ std::stringstream message;
+ message << d.GetErrorOffset() << " - " << rapidjson::GetParseError_En(d.GetParseError());
+ observer->onSourceError(*this, std::make_exception_ptr(std::runtime_error(message.str())));
+ return;
+ }
+
+ geojsonvt = style::parseGeoJSON(d);
+ reloadTiles = true;
+
+ newTileset->maxZoom = geojsonvt->options.maxZoom;
+ tileset = std::move(newTileset);
+ }
+
+ if (reloadTiles) {
+ // Tile information changed because we got new GeoJSON data, or a new tile URL.
+ tileDataMap.clear();
+ tiles.clear();
+ cache.clear();
+ }
+
+ loaded = true;
+ observer->onSourceLoaded(*this);
+ }
+ });
+}
+
+void Source::updateMatrices(const mat4 &projMatrix, const TransformState &transform) {
+ for (auto& pair : tiles) {
+ auto& tile = pair.second;
+ transform.matrixFor(tile.matrix, tile.id);
+ matrix::multiply(tile.matrix, projMatrix, tile.matrix);
+ }
+}
+
+void Source::finishRender(Painter &painter) {
+ for (auto& pair : tiles) {
+ auto& tile = pair.second;
+ painter.renderTileDebug(tile);
+ }
+}
+
+const std::map<UnwrappedTileID, Tile>& Source::getTiles() const {
+ return tiles;
+}
+
+std::unique_ptr<TileData> Source::createTile(const OverscaledTileID& overscaledTileID,
+ const UpdateParameters& parameters) {
+ std::unique_ptr<TileData> data = cache.get(overscaledTileID);
+ if (data) {
+ return data;
+ }
+
+ auto callback = std::bind(&Source::tileLoadingCallback, this, overscaledTileID,
+ std::placeholders::_1, true);
+
+ // If we don't find working tile data, we're just going to load it.
+ if (type == SourceType::Raster) {
+ data = std::make_unique<RasterTileData>(overscaledTileID, parameters.pixelRatio,
+ tileset->tiles.at(0), parameters.texturePool,
+ parameters.worker, parameters.fileSource, callback);
+ } else {
+ std::unique_ptr<GeometryTileMonitor> monitor;
+
+ if (type == SourceType::Vector) {
+ monitor = std::make_unique<VectorTileMonitor>(overscaledTileID, parameters.pixelRatio, tileset->tiles.at(0), parameters.fileSource);
+ } else if (type == SourceType::Annotations) {
+ monitor = std::make_unique<AnnotationTileMonitor>(overscaledTileID, parameters.annotationManager);
+ } else if (type == SourceType::GeoJSON) {
+ monitor = std::make_unique<GeoJSONTileMonitor>(geojsonvt.get(), overscaledTileID);
+ } else {
+ Log::Warning(Event::Style, "Source type '%s' is not implemented", SourceTypeClass(type).c_str());
+ return nullptr;
+ }
+
+ data = std::make_unique<VectorTileData>(overscaledTileID, std::move(monitor), id,
+ parameters.style, parameters.mode, callback);
+ }
+
+ return data;
+}
+
+TileData* Source::getTileData(const OverscaledTileID& overscaledTileID) const {
+ auto it = tileDataMap.find(overscaledTileID);
+ if (it != tileDataMap.end()) {
+ return it->second.get();
+ } else {
+ return nullptr;
+ }
+}
+
+bool Source::update(const UpdateParameters& parameters) {
+ bool allTilesUpdated = true;
+
+ if (!loaded || parameters.animationTime <= updated) {
+ return allTilesUpdated;
+ }
+
+ // Determine the overzooming/underzooming amounts and required tiles.
+ int32_t overscaledZoom = util::coveringZoomLevel(parameters.transformState.getZoom(), type, tileSize);
+ int32_t dataTileZoom = overscaledZoom;
+
+ std::vector<UnwrappedTileID> idealTiles;
+ if (overscaledZoom >= tileset->minZoom) {
+ int32_t idealZoom = std::min<int32_t>(tileset->maxZoom, overscaledZoom);
+
+ // Make sure we're not reparsing overzoomed raster tiles.
+ if (type == SourceType::Raster) {
+ dataTileZoom = idealZoom;
+ }
+
+ idealTiles = util::tileCover(parameters.transformState, idealZoom);
+ }
+
+ // Stores a list of all the data tiles that we're definitely going to retain. There are two
+ // kinds of tiles we need: the ideal tiles determined by the tile cover. They may not yet be in
+ // use because they're still loading. In addition to that, we also need to retain all tiles that
+ // we're actively using, e.g. as a replacement for tile that aren't loaded yet.
+ std::set<OverscaledTileID> retain;
+
+ auto retainTileDataFn = [&retain](const TileData& tileData) -> void {
+ retain.emplace(tileData.id);
+ };
+ auto getTileDataFn = [this](const OverscaledTileID& dataTileID) -> TileData* {
+ return getTileData(dataTileID);
+ };
+ auto createTileDataFn = [this, &parameters](const OverscaledTileID& dataTileID) -> TileData* {
+ if (auto data = createTile(dataTileID, parameters)) {
+ return tileDataMap.emplace(dataTileID, std::move(data)).first->second.get();
+ } else {
+ return nullptr;
+ }
+ };
+ auto renderTileFn = [this](const UnwrappedTileID& renderTileID, TileData& tileData) {
+ tiles.emplace(renderTileID, Tile{ renderTileID, tileData });
+ };
+
+ tiles.clear();
+ algorithm::updateRenderables(getTileDataFn, createTileDataFn, retainTileDataFn, renderTileFn,
+ idealTiles, *tileset, dataTileZoom);
+
+ if (type != SourceType::Raster && type != SourceType::Annotations && cache.getSize() == 0) {
+ size_t conservativeCacheSize =
+ ((float)parameters.transformState.getWidth() / util::tileSize) *
+ ((float)parameters.transformState.getHeight() / util::tileSize) *
+ (parameters.transformState.getMaxZoom() - parameters.transformState.getMinZoom() + 1) *
+ 0.5;
+ cache.setSize(conservativeCacheSize);
+ }
+
+ // Remove stale data tiles from the active set of tiles.
+ // This goes through the (sorted!) tileDataMap and retain set in lockstep and removes items from
+ // tileDataMap that don't have the corresponding key in the retain set.
+ auto dataIt = tileDataMap.begin();
+ auto retainIt = retain.begin();
+ while (dataIt != tileDataMap.end()) {
+ if (retainIt == retain.end() || dataIt->first < *retainIt) {
+ cache.add(dataIt->first, std::move(dataIt->second));
+ tileDataMap.erase(dataIt++);
+ } else {
+ if (!(*retainIt < dataIt->first)) {
+ ++dataIt;
+ }
+ ++retainIt;
+ }
+ }
+
+ for (auto& pair : tileDataMap) {
+ const auto& dataTileID = pair.first;
+ auto tileData = pair.second.get();
+ if (parameters.shouldReparsePartialTiles && tileData->isIncomplete()) {
+ auto callback = std::bind(&Source::tileLoadingCallback, this, dataTileID,
+ std::placeholders::_1, false);
+
+ if (!tileData->parsePending(callback)) {
+ allTilesUpdated = false;
+ }
+ } else {
+ tileData->redoPlacement({ parameters.transformState.getAngle(),
+ parameters.transformState.getPitch(),
+ parameters.debugOptions & MapDebugOptions::Collision },
+ [this]() { observer->onPlacementRedone(); });
+ }
+ }
+
+ updated = parameters.animationTime;
+
+ return allTilesUpdated;
+}
+
+static Point<int16_t> coordinateToTilePoint(const UnwrappedTileID& tileID, const Point<double>& p) {
+ auto zoomedCoord = TileCoordinate { p, 0 }.zoomTo(tileID.canonical.z);
+ return {
+ int16_t(util::clamp<int64_t>((zoomedCoord.p.x - tileID.canonical.x - tileID.wrap * std::pow(2, tileID.canonical.z)) * util::EXTENT,
+ std::numeric_limits<int16_t>::min(),
+ std::numeric_limits<int16_t>::max())),
+ int16_t(util::clamp<int64_t>((zoomedCoord.p.y - tileID.canonical.y) * util::EXTENT,
+ std::numeric_limits<int16_t>::min(),
+ std::numeric_limits<int16_t>::max()))
+ };
+}
+
+std::unordered_map<std::string, std::vector<Feature>> Source::queryRenderedFeatures(const QueryParameters& parameters) const {
+ LineString<double> queryGeometry;
+
+ for (const auto& p : parameters.geometry) {
+ queryGeometry.push_back(TileCoordinate::fromScreenCoordinate(
+ parameters.transformState, 0, { p.x, parameters.transformState.getHeight() - p.y }).p);
+ }
+
+ mapbox::geometry::box<double> box = mapbox::geometry::envelope(queryGeometry);
+
+ std::unordered_map<std::string, std::vector<Feature>> result;
+
+ for (const auto& tilePtr : tiles) {
+ const Tile& tile = tilePtr.second;
+
+ Point<int16_t> tileSpaceBoundsMin = coordinateToTilePoint(tile.id, box.min);
+ Point<int16_t> tileSpaceBoundsMax = coordinateToTilePoint(tile.id, box.max);
+
+ if (tileSpaceBoundsMin.x >= util::EXTENT || tileSpaceBoundsMin.y >= util::EXTENT ||
+ tileSpaceBoundsMax.x < 0 || tileSpaceBoundsMax.y < 0) continue;
+
+ GeometryCoordinates tileSpaceQueryGeometry;
+
+ for (const auto& c : queryGeometry) {
+ tileSpaceQueryGeometry.push_back(coordinateToTilePoint(tile.id, c));
+ }
+
+ tile.data.queryRenderedFeatures(result,
+ tileSpaceQueryGeometry,
+ parameters.transformState,
+ parameters.layerIDs);
+ }
+
+ return result;
+}
+
+void Source::setCacheSize(size_t size) {
+ cache.setSize(size);
+}
+
+void Source::onLowMemory() {
+ cache.clear();
+}
+
+void Source::setObserver(SourceObserver* observer_) {
+ observer = observer_;
+}
+
+void Source::tileLoadingCallback(const OverscaledTileID& tileID,
+ std::exception_ptr error,
+ bool isNewTile) {
+ auto it = tileDataMap.find(tileID);
+ if (it == tileDataMap.end()) {
+ return;
+ }
+
+ auto& tileData = it->second;
+ if (!tileData) {
+ return;
+ }
+
+ if (error) {
+ observer->onTileError(*this, tileID, error);
+ return;
+ }
+
+ tileData->redoPlacement([this]() {
+ observer->onPlacementRedone();
+ });
+ observer->onTileLoaded(*this, tileID, isNewTile);
+}
+
+void Source::dumpDebugLogs() const {
+ Log::Info(Event::General, "Source::id: %s", id.c_str());
+ Log::Info(Event::General, "Source::loaded: %d", loaded);
+
+ for (const auto& pair : tileDataMap) {
+ auto& tileData = pair.second;
+ tileData->dumpDebugLogs();
+ }
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/source.hpp b/src/mbgl/style/source.hpp
new file mode 100644
index 0000000000..cadc45c25c
--- /dev/null
+++ b/src/mbgl/style/source.hpp
@@ -0,0 +1,113 @@
+#pragma once
+
+#include <mbgl/tile/tile_id.hpp>
+#include <mbgl/tile/tile_data.hpp>
+#include <mbgl/tile/tile_cache.hpp>
+#include <mbgl/style/types.hpp>
+#include <mbgl/renderer/renderable.hpp>
+
+#include <mbgl/util/mat4.hpp>
+#include <mbgl/util/rapidjson.hpp>
+#include <mbgl/util/feature.hpp>
+#include <mbgl/util/tileset.hpp>
+
+#include <forward_list>
+#include <vector>
+#include <map>
+
+namespace mapbox {
+namespace geojsonvt {
+class GeoJSONVT;
+} // namespace geojsonvt
+} // namespace mapbox
+
+namespace mbgl {
+
+class Painter;
+class FileSource;
+class AsyncRequest;
+class TransformState;
+class Tile;
+struct ClipID;
+
+namespace style {
+
+class Style;
+class UpdateParameters;
+class QueryParameters;
+class SourceObserver;
+
+class Source : private util::noncopyable {
+public:
+ Source(SourceType,
+ const std::string& id,
+ const std::string& url,
+ uint16_t tileSize,
+ std::unique_ptr<Tileset>&&,
+ std::unique_ptr<mapbox::geojsonvt::GeoJSONVT>&&);
+ ~Source();
+
+ bool loaded = false;
+ void load(FileSource&);
+ bool isLoading() const;
+ bool isLoaded() const;
+
+ const Tileset* getTileset() const { return tileset.get(); }
+
+ // Request or parse all the tiles relevant for the "TransformState". This method
+ // will return true if all the tiles were scheduled for updating of false if
+ // they were not. shouldReparsePartialTiles must be set to "true" if there is
+ // new data available that a tile in the "partial" state might be interested at.
+ bool update(const UpdateParameters&);
+
+ template <typename ClipIDGenerator>
+ void updateClipIDs(ClipIDGenerator& generator) {
+ generator.update(tiles);
+ }
+
+ void updateMatrices(const mat4 &projMatrix, const TransformState &transform);
+ void finishRender(Painter &painter);
+
+ const std::map<UnwrappedTileID, Tile>& getTiles() const;
+
+ TileData* getTileData(const OverscaledTileID&) const;
+
+ std::unordered_map<std::string, std::vector<Feature>>
+ queryRenderedFeatures(const QueryParameters&) const;
+
+ void setCacheSize(size_t);
+ void onLowMemory();
+
+ void setObserver(SourceObserver* observer);
+ void dumpDebugLogs() const;
+
+ const SourceType type;
+ const std::string id;
+ const std::string url;
+ uint16_t tileSize = util::tileSize;
+ bool enabled = false;
+
+private:
+ void tileLoadingCallback(const OverscaledTileID&, std::exception_ptr, bool isNewTile);
+
+ std::unique_ptr<TileData> createTile(const OverscaledTileID&, const UpdateParameters&);
+
+private:
+ std::unique_ptr<const Tileset> tileset;
+
+ std::unique_ptr<mapbox::geojsonvt::GeoJSONVT> geojsonvt;
+
+ // Stores the time when this source was most recently updated.
+ TimePoint updated = TimePoint::min();
+
+ std::map<UnwrappedTileID, Tile> tiles;
+ std::map<OverscaledTileID, std::unique_ptr<TileData>> tileDataMap;
+ TileCache cache;
+
+ std::unique_ptr<AsyncRequest> req;
+
+ SourceObserver* observer = nullptr;
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/source_observer.hpp b/src/mbgl/style/source_observer.hpp
new file mode 100644
index 0000000000..a669e8e756
--- /dev/null
+++ b/src/mbgl/style/source_observer.hpp
@@ -0,0 +1,25 @@
+#pragma once
+
+#include <exception>
+
+namespace mbgl {
+
+class OverscaledTileID;
+
+namespace style {
+
+class Source;
+
+class SourceObserver {
+public:
+ virtual ~SourceObserver() = default;
+
+ virtual void onSourceLoaded(Source&) {}
+ virtual void onSourceError(Source&, std::exception_ptr) {}
+ virtual void onTileLoaded(Source&, const OverscaledTileID&, bool /* isNewTile */) {}
+ virtual void onTileError(Source&, const OverscaledTileID&, std::exception_ptr) {}
+ virtual void onPlacementRedone() {}
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/style.cpp b/src/mbgl/style/style.cpp
index ee847ccf57..136c98df03 100644
--- a/src/mbgl/style/style.cpp
+++ b/src/mbgl/style/style.cpp
@@ -1,23 +1,23 @@
#include <mbgl/style/style.hpp>
-#include <mbgl/style/style_observer.hpp>
-#include <mbgl/source/source.hpp>
+#include <mbgl/style/observer.hpp>
+#include <mbgl/style/source.hpp>
#include <mbgl/tile/tile.hpp>
#include <mbgl/map/transform_state.hpp>
-#include <mbgl/layer/symbol_layer.hpp>
-#include <mbgl/layer/symbol_layer_impl.hpp>
-#include <mbgl/layer/custom_layer.hpp>
-#include <mbgl/layer/custom_layer_impl.hpp>
-#include <mbgl/layer/background_layer.hpp>
-#include <mbgl/layer/background_layer_impl.hpp>
+#include <mbgl/style/layers/symbol_layer.hpp>
+#include <mbgl/style/layers/symbol_layer_impl.hpp>
+#include <mbgl/style/layers/custom_layer.hpp>
+#include <mbgl/style/layers/custom_layer_impl.hpp>
+#include <mbgl/style/layers/background_layer.hpp>
+#include <mbgl/style/layers/background_layer_impl.hpp>
#include <mbgl/sprite/sprite_store.hpp>
#include <mbgl/sprite/sprite_atlas.hpp>
-#include <mbgl/layer/layer_impl.hpp>
-#include <mbgl/style/style_parser.hpp>
-#include <mbgl/style/property_transition.hpp>
+#include <mbgl/style/layer_impl.hpp>
+#include <mbgl/style/parser.hpp>
+#include <mbgl/style/transition_options.hpp>
#include <mbgl/style/class_dictionary.hpp>
-#include <mbgl/style/style_update_parameters.hpp>
-#include <mbgl/style/style_cascade_parameters.hpp>
-#include <mbgl/style/style_calculation_parameters.hpp>
+#include <mbgl/style/update_parameters.hpp>
+#include <mbgl/style/cascade_parameters.hpp>
+#include <mbgl/style/calculation_parameters.hpp>
#include <mbgl/geometry/glyph_atlas.hpp>
#include <mbgl/geometry/line_atlas.hpp>
#include <mbgl/util/constants.hpp>
@@ -30,10 +30,11 @@
#include <algorithm>
namespace mbgl {
+namespace style {
-static StyleObserver nullObserver;
+static Observer nullObserver;
-bool Style::addClass(const std::string& className, const PropertyTransition& properties) {
+bool Style::addClass(const std::string& className, const TransitionOptions& properties) {
if (std::find(classes.begin(), classes.end(), className) != classes.end()) return false;
classes.push_back(className);
transitionProperties = properties;
@@ -44,7 +45,7 @@ bool Style::hasClass(const std::string& className) const {
return std::find(classes.begin(), classes.end(), className) != classes.end();
}
-bool Style::removeClass(const std::string& className, const PropertyTransition& properties) {
+bool Style::removeClass(const std::string& className, const TransitionOptions& properties) {
const auto it = std::find(classes.begin(), classes.end(), className);
if (it != classes.end()) {
classes.erase(it);
@@ -54,7 +55,7 @@ bool Style::removeClass(const std::string& className, const PropertyTransition&
return false;
}
-void Style::setClasses(const std::vector<std::string>& classNames, const PropertyTransition& properties) {
+void Style::setClasses(const std::vector<std::string>& classNames, const TransitionOptions& properties) {
classes = classNames;
transitionProperties = properties;
}
@@ -81,7 +82,7 @@ void Style::setJSON(const std::string& json, const std::string&) {
layers.clear();
classes.clear();
- StyleParser parser;
+ Parser parser;
parser.parse(json);
for (auto& source : parser.sources) {
@@ -153,7 +154,7 @@ void Style::removeLayer(const std::string& id) {
layers.erase(it);
}
-void Style::update(const StyleUpdateParameters& parameters) {
+void Style::update(const UpdateParameters& parameters) {
bool allTilesUpdated = true;
for (const auto& source : sources) {
@@ -172,7 +173,7 @@ void Style::update(const StyleUpdateParameters& parameters) {
void Style::cascade(const TimePoint& timePoint, MapMode mode) {
// When in continuous mode, we can either have user- or style-defined
// transitions. Still mode is always immediate.
- static const PropertyTransition immediateTransition;
+ static const TransitionOptions immediateTransition;
std::vector<ClassID> classIDs;
for (const auto& className : classes) {
@@ -181,7 +182,7 @@ void Style::cascade(const TimePoint& timePoint, MapMode mode) {
classIDs.push_back(ClassID::Default);
classIDs.push_back(ClassID::Fallback);
- const StyleCascadeParameters parameters {
+ const CascadeParameters parameters {
classIDs,
mode == MapMode::Continuous ? timePoint : Clock::time_point::max(),
mode == MapMode::Continuous ? transitionProperties.value_or(immediateTransition) : immediateTransition
@@ -201,7 +202,7 @@ void Style::recalculate(float z, const TimePoint& timePoint, MapMode mode) {
zoomHistory.update(z, timePoint);
- const StyleCalculationParameters parameters {
+ const CalculationParameters parameters {
z,
mode == MapMode::Continuous ? timePoint : Clock::time_point::max(),
zoomHistory,
@@ -325,7 +326,7 @@ RenderData Style::getRenderData() const {
return result;
}
-std::vector<Feature> Style::queryRenderedFeatures(const StyleQueryParameters& parameters) const {
+std::vector<Feature> Style::queryRenderedFeatures(const QueryParameters& parameters) const {
std::unordered_map<std::string, std::vector<Feature>> resultsByLayer;
for (const auto& source : sources) {
@@ -367,7 +368,7 @@ void Style::onLowMemory() {
}
}
-void Style::setObserver(StyleObserver* observer_) {
+void Style::setObserver(style::Observer* observer_) {
observer = observer_;
}
@@ -440,4 +441,5 @@ void Style::dumpDebugLogs() const {
spriteStore->dumpDebugLogs();
}
+} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/style.hpp b/src/mbgl/style/style.hpp
index 6892f4967a..49af674336 100644
--- a/src/mbgl/style/style.hpp
+++ b/src/mbgl/style/style.hpp
@@ -1,20 +1,21 @@
#pragma once
#include <mbgl/style/render_item.hpp>
-#include <mbgl/style/zoom_history.hpp>
-#include <mbgl/style/types.hpp>
-#include <mbgl/style/property_transition.hpp>
+#include <mbgl/style/transition_options.hpp>
-#include <mbgl/source/source_observer.hpp>
+#include <mbgl/style/observer.hpp>
+#include <mbgl/style/source_observer.hpp>
#include <mbgl/text/glyph_store_observer.hpp>
#include <mbgl/sprite/sprite_store_observer.hpp>
#include <mbgl/map/mode.hpp>
+#include <mbgl/map/zoom_history.hpp>
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/util/chrono.hpp>
#include <mbgl/util/worker.hpp>
#include <mbgl/util/optional.hpp>
#include <mbgl/util/feature.hpp>
+#include <mbgl/util/color.hpp>
#include <cstdint>
#include <string>
@@ -25,20 +26,20 @@ namespace mbgl {
class FileSource;
class GlyphAtlas;
-class GlyphStore;
-class SpriteStore;
class SpriteAtlas;
class LineAtlas;
-class StyleUpdateParameters;
-class StyleQueryParameters;
-class StyleObserver;
struct RenderData {
Color backgroundColor = {{ 0, 0, 0, 0 }};
- std::set<Source*> sources;
+ std::set<style::Source*> sources;
std::vector<RenderItem> order;
};
+namespace style {
+
+class UpdateParameters;
+class QueryParameters;
+
class Style : public GlyphStoreObserver,
public SpriteStoreObserver,
public SourceObserver,
@@ -49,13 +50,13 @@ public:
void setJSON(const std::string& data, const std::string& base);
- void setObserver(StyleObserver*);
+ void setObserver(Observer*);
bool isLoaded() const;
// Fetch the tiles needed by the current viewport and emit a signal when
// a tile is ready so observers can render the tile.
- void update(const StyleUpdateParameters&);
+ void update(const UpdateParameters&);
void cascade(const TimePoint&, MapMode);
void recalculate(float z, const TimePoint&, MapMode);
@@ -75,15 +76,15 @@ public:
optional<std::string> beforeLayerID = {});
void removeLayer(const std::string& layerID);
- bool addClass(const std::string&, const PropertyTransition& = {});
- bool removeClass(const std::string&, const PropertyTransition& = {});
+ bool addClass(const std::string&, const TransitionOptions& = {});
+ bool removeClass(const std::string&, const TransitionOptions& = {});
bool hasClass(const std::string&) const;
- void setClasses(const std::vector<std::string>&, const PropertyTransition& = {});
+ void setClasses(const std::vector<std::string>&, const TransitionOptions& = {});
std::vector<std::string> getClasses() const;
RenderData getRenderData() const;
- std::vector<Feature> queryRenderedFeatures(const StyleQueryParameters&) const;
+ std::vector<Feature> queryRenderedFeatures(const QueryParameters&) const;
float getQueryRadius() const;
@@ -103,7 +104,7 @@ private:
std::vector<std::unique_ptr<Source>> sources;
std::vector<std::unique_ptr<Layer>> layers;
std::vector<std::string> classes;
- optional<PropertyTransition> transitionProperties;
+ optional<TransitionOptions> transitionProperties;
std::vector<std::unique_ptr<Layer>>::const_iterator findLayer(const std::string& layerID) const;
@@ -122,7 +123,8 @@ private:
void onTileError(Source&, const OverscaledTileID&, std::exception_ptr) override;
void onPlacementRedone() override;
- StyleObserver* observer = nullptr;
+ Observer nullObserver;
+ Observer* observer = &nullObserver;
std::exception_ptr lastError;
@@ -135,4 +137,5 @@ public:
Worker workers;
};
+} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/style_calculation_parameters.hpp b/src/mbgl/style/style_calculation_parameters.hpp
deleted file mode 100644
index 1c50bd6128..0000000000
--- a/src/mbgl/style/style_calculation_parameters.hpp
+++ /dev/null
@@ -1,28 +0,0 @@
-#pragma once
-
-#include <mbgl/style/zoom_history.hpp>
-#include <mbgl/util/chrono.hpp>
-
-namespace mbgl {
-
-class StyleCalculationParameters {
-public:
- explicit StyleCalculationParameters(float z_)
- : z(z_) {}
-
- StyleCalculationParameters(float z_,
- const TimePoint& now_,
- const ZoomHistory& zoomHistory_,
- const Duration& defaultFadeDuration_)
- : z(z_),
- now(now_),
- zoomHistory(zoomHistory_),
- defaultFadeDuration(defaultFadeDuration_) {}
-
- float z;
- TimePoint now;
- ZoomHistory zoomHistory;
- Duration defaultFadeDuration;
-};
-
-} // namespace mbgl
diff --git a/src/mbgl/style/style_cascade_parameters.hpp b/src/mbgl/style/style_cascade_parameters.hpp
deleted file mode 100644
index 569145bd04..0000000000
--- a/src/mbgl/style/style_cascade_parameters.hpp
+++ /dev/null
@@ -1,20 +0,0 @@
-#pragma once
-
-#include <mbgl/map/mode.hpp>
-#include <mbgl/util/chrono.hpp>
-#include <mbgl/style/types.hpp>
-
-#include <vector>
-
-namespace mbgl {
-
-class PropertyTransition;
-
-class StyleCascadeParameters {
-public:
- std::vector<ClassID> classes;
- TimePoint now;
- PropertyTransition transition;
-};
-
-} // namespace mbgl
diff --git a/src/mbgl/style/style_render_parameters.hpp b/src/mbgl/style/style_render_parameters.hpp
deleted file mode 100644
index 7347717a1d..0000000000
--- a/src/mbgl/style/style_render_parameters.hpp
+++ /dev/null
@@ -1,15 +0,0 @@
-#pragma once
-
-namespace mbgl {
-
-class TransformState;
-
-class StyleRenderParameters {
-public:
- StyleRenderParameters(const TransformState& state_)
- : state(state_) {}
-
- const TransformState& state;
-};
-
-}
diff --git a/src/mbgl/style/types.cpp b/src/mbgl/style/types.cpp
deleted file mode 100644
index 27574afa93..0000000000
--- a/src/mbgl/style/types.cpp
+++ /dev/null
@@ -1,16 +0,0 @@
-#include <mbgl/style/types.hpp>
-
-#include <boost/functional/hash.hpp>
-#include <boost/algorithm/string/join.hpp>
-
-namespace mbgl {
-
-std::string fontStackToString(const FontStack& fontStack) {
- return boost::algorithm::join(fontStack, ",");
-}
-
-std::size_t FontStackHash::operator()(const FontStack& fontStack) const {
- return boost::hash_range(fontStack.begin(), fontStack.end());
-}
-
-} // namespace mbgl
diff --git a/src/mbgl/style/style_update_parameters.hpp b/src/mbgl/style/update_parameters.hpp
index 73ed500e8e..9faaa32d6f 100644
--- a/src/mbgl/style/style_update_parameters.hpp
+++ b/src/mbgl/style/update_parameters.hpp
@@ -7,13 +7,16 @@ namespace mbgl {
class TransformState;
class Worker;
class FileSource;
-class Style;
namespace gl { class TexturePool; }
class AnnotationManager;
-class StyleUpdateParameters {
+namespace style {
+
+class Style;
+
+class UpdateParameters {
public:
- StyleUpdateParameters(float pixelRatio_,
+ UpdateParameters(float pixelRatio_,
MapDebugOptions debugOptions_,
TimePoint animationTime_,
const TransformState& transformState_,
@@ -51,4 +54,5 @@ public:
Style& style;
};
-}
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/zoom_history.hpp b/src/mbgl/style/zoom_history.hpp
deleted file mode 100644
index 8c88ea6507..0000000000
--- a/src/mbgl/style/zoom_history.hpp
+++ /dev/null
@@ -1,36 +0,0 @@
-#pragma once
-
-#include <mbgl/util/chrono.hpp>
-
-#include <cmath>
-
-namespace mbgl {
-
-struct ZoomHistory {
- float lastZoom;
- float lastIntegerZoom;
- TimePoint lastIntegerZoomTime;
- bool first = true;
-
- void update(float z, const TimePoint& now) {
- if (first) {
- first = false;
-
- lastIntegerZoom = std::floor(z);
- lastIntegerZoomTime = TimePoint(Duration::zero());
- lastZoom = z;
- }
-
- if (std::floor(lastZoom) < std::floor(z)) {
- lastIntegerZoom = std::floor(z);
- lastIntegerZoomTime = now;
-
- } else if (std::floor(lastZoom) > std::floor(z)) {
- lastIntegerZoom = std::floor(z + 1);
- lastIntegerZoomTime = now;
- }
-
- lastZoom = z;
- }
-};
-} // namespace mbgl