diff options
author | John Firebaugh <john.firebaugh@gmail.com> | 2016-04-26 16:39:56 -0700 |
---|---|---|
committer | John Firebaugh <john.firebaugh@gmail.com> | 2016-06-02 14:51:39 -0700 |
commit | c902f9098b331302aaa1baac77d1575db624a132 (patch) | |
tree | 211901cd04454aedbac40c469198438e46d7038c /src/mbgl/style | |
parent | 18149cbcc27a926f280b08d8d0e09104b2147688 (diff) | |
download | qtlocation-mapboxgl-c902f9098b331302aaa1baac77d1575db624a132.tar.gz |
[core] Rationalize naming for style-related code
Diffstat (limited to 'src/mbgl/style')
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, ¶meters](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 |