summaryrefslogtreecommitdiff
path: root/src/mbgl/style
diff options
context:
space:
mode:
Diffstat (limited to 'src/mbgl/style')
-rw-r--r--src/mbgl/style/function_properties.cpp22
-rw-r--r--src/mbgl/style/piecewisefunction_properties.cpp52
-rw-r--r--src/mbgl/style/piecewisefunction_properties.hpp24
-rw-r--r--src/mbgl/style/property_fallback.cpp18
-rw-r--r--src/mbgl/style/property_key.hpp18
-rw-r--r--src/mbgl/style/property_value.hpp27
-rw-r--r--src/mbgl/style/style.cpp4
-rw-r--r--src/mbgl/style/style.hpp2
-rw-r--r--src/mbgl/style/style_layer.cpp131
-rw-r--r--src/mbgl/style/style_layer.hpp9
-rw-r--r--src/mbgl/style/style_layer_group.cpp4
-rw-r--r--src/mbgl/style/style_layer_group.hpp2
-rw-r--r--src/mbgl/style/style_parser.cpp358
-rw-r--r--src/mbgl/style/style_parser.hpp14
-rw-r--r--src/mbgl/style/style_properties.hpp10
-rw-r--r--src/mbgl/style/types.hpp10
-rw-r--r--src/mbgl/style/zoom_history.hpp38
17 files changed, 494 insertions, 249 deletions
diff --git a/src/mbgl/style/function_properties.cpp b/src/mbgl/style/function_properties.cpp
index 81b1c85c72..1ac2863a7c 100644
--- a/src/mbgl/style/function_properties.cpp
+++ b/src/mbgl/style/function_properties.cpp
@@ -13,7 +13,18 @@ template <> inline bool defaultStopsValue() { return true; }
template <> inline float defaultStopsValue() { return 1.0f; }
template <> inline Color defaultStopsValue() { return {{ 0, 0, 0, 1 }}; }
template <> inline std::vector<float> defaultStopsValue() { return {{ 1, 0 }}; }
+template <> inline std::array<float, 2> defaultStopsValue() { return {{ 0, 0 }}; }
+template <> inline std:: string defaultStopsValue() { return {}; }
+template <> inline TranslateAnchorType defaultStopsValue() { return {}; };
+template <> inline RotateAnchorType defaultStopsValue() { return {}; };
+template <> inline CapType defaultStopsValue() { return {}; };
+template <> inline JoinType defaultStopsValue() { return {}; };
+template <> inline PlacementType defaultStopsValue() { return {}; };
+template <> inline TextAnchorType defaultStopsValue() { return {}; };
+template <> inline TextJustifyType defaultStopsValue() { return {}; };
+template <> inline TextTransformType defaultStopsValue() { return {}; };
+template <> inline RotationAlignmentType defaultStopsValue() { return {}; };
template <typename T>
T StopsFunction<T>::evaluate(float z) const {
@@ -66,5 +77,16 @@ template bool StopsFunction<bool>::evaluate(float z) const;
template float StopsFunction<float>::evaluate(float z) const;
template Color StopsFunction<Color>::evaluate(float z) const;
template std::vector<float> StopsFunction<std::vector<float>>::evaluate(float z) const;
+template std::array<float, 2> StopsFunction<std::array<float, 2>>::evaluate(float z) const;
+template std::string StopsFunction<std::string>::evaluate(float z) const;
+template TranslateAnchorType StopsFunction<TranslateAnchorType>::evaluate(float z) const;
+template RotateAnchorType StopsFunction<RotateAnchorType>::evaluate(float z) const;
+template CapType StopsFunction<CapType>::evaluate(float z) const;
+template JoinType StopsFunction<JoinType>::evaluate(float z) const;
+template PlacementType StopsFunction<PlacementType>::evaluate(float z) const;
+template TextAnchorType StopsFunction<TextAnchorType>::evaluate(float z) const;
+template TextJustifyType StopsFunction<TextJustifyType>::evaluate(float z) const;
+template TextTransformType StopsFunction<TextTransformType>::evaluate(float z) const;
+template RotationAlignmentType StopsFunction<RotationAlignmentType>::evaluate(float z) const;
}
diff --git a/src/mbgl/style/piecewisefunction_properties.cpp b/src/mbgl/style/piecewisefunction_properties.cpp
new file mode 100644
index 0000000000..72ed0b8f73
--- /dev/null
+++ b/src/mbgl/style/piecewisefunction_properties.cpp
@@ -0,0 +1,52 @@
+#include <mbgl/style/piecewisefunction_properties.hpp>
+#include <mbgl/style/types.hpp>
+
+#include <cmath>
+
+namespace mbgl {
+
+template <typename T>
+size_t getBiggestStopLessThan(std::vector<std::pair<float, T>> stops, float z) {
+ for (uint32_t i = 0; i < stops.size(); i++) {
+ if (stops[i].first > z) {
+ return i == 0 ? i : i - 1;
+ }
+ }
+ return stops.size() - 1;
+}
+
+template <typename T>
+T PiecewiseConstantFunction<T>::evaluate(float z, const ZoomHistory &zh) const {
+ T result;
+
+ float fraction = std::fmod(z, 1.0f);
+ float t = std::min((std::chrono::steady_clock::now() - zh.lastIntegerZoomTime) / duration, 1.0f);
+ float fromScale = 1.0f;
+ float toScale = 1.0f;
+ size_t from, to;
+
+ if (z > zh.lastIntegerZoom) {
+ result.t = fraction + (1.0f - fraction) * t;
+ from = getBiggestStopLessThan(values, z - 1.0f);
+ to = getBiggestStopLessThan(values, z);
+ fromScale *= 2.0f;
+
+ } else {
+ result.t = 1 - (1 - t) * fraction;
+ to = getBiggestStopLessThan(values, z);
+ from = getBiggestStopLessThan(values, z + 1.0f);
+ fromScale /= 2.0f;
+ }
+
+
+ result.from = values[from].second.to;
+ result.to = values[to].second.to;
+ result.fromScale = fromScale;
+ result.toScale = toScale;
+ return result;
+}
+
+template Faded<std::string> PiecewiseConstantFunction<Faded<std::string>>::evaluate(float z, const ZoomHistory &zoomHistory) const;
+template Faded<std::vector<float>> PiecewiseConstantFunction<Faded<std::vector<float>>>::evaluate(float z, const ZoomHistory &zoomHistory) const;
+
+}
diff --git a/src/mbgl/style/piecewisefunction_properties.hpp b/src/mbgl/style/piecewisefunction_properties.hpp
new file mode 100644
index 0000000000..0440655ba5
--- /dev/null
+++ b/src/mbgl/style/piecewisefunction_properties.hpp
@@ -0,0 +1,24 @@
+#ifndef MBGL_STYLE_FADEDFUNCTION_PROPERTIES
+#define MBGL_STYLE_FADEDFUNCTION_PROPERTIES
+
+#include <mbgl/style/zoom_history.hpp>
+
+#include <vector>
+
+namespace mbgl {
+
+template <typename T>
+struct PiecewiseConstantFunction {
+ inline PiecewiseConstantFunction(const std::vector<std::pair<float, T>> &values_, std::chrono::duration<float> duration_) : values(values_), duration(duration_) {}
+ inline PiecewiseConstantFunction(T &value, std::chrono::duration<float> duration_) : values({{ 0, value }}), duration(duration_) {}
+ inline PiecewiseConstantFunction() : values(), duration(std::chrono::milliseconds(300)) {}
+ T evaluate(float z, const ZoomHistory &zoomHistory) const;
+
+private:
+ const std::vector<std::pair<float, T>> values;
+ const std::chrono::duration<float> duration;
+};
+
+}
+
+#endif
diff --git a/src/mbgl/style/property_fallback.cpp b/src/mbgl/style/property_fallback.cpp
index 5fc3ce1f04..2827fd6149 100644
--- a/src/mbgl/style/property_fallback.cpp
+++ b/src/mbgl/style/property_fallback.cpp
@@ -9,14 +9,12 @@ const std::map<PropertyKey, PropertyValue> PropertyFallbackValue::properties = {
{ PropertyKey::FillOpacity, defaultStyleProperties<FillProperties>().opacity },
{ PropertyKey::FillColor, defaultStyleProperties<FillProperties>().fill_color },
// no FillOutlineColor on purpose.
- { PropertyKey::FillTranslateX, defaultStyleProperties<FillProperties>().translate[0] },
- { PropertyKey::FillTranslateY, defaultStyleProperties<FillProperties>().translate[1] },
+ { PropertyKey::FillTranslate, defaultStyleProperties<FillProperties>().translate },
{ PropertyKey::FillTranslateAnchor, defaultStyleProperties<FillProperties>().translateAnchor },
{ PropertyKey::LineOpacity, defaultStyleProperties<LineProperties>().opacity },
{ PropertyKey::LineColor, defaultStyleProperties<LineProperties>().color },
- { PropertyKey::LineTranslateX, defaultStyleProperties<LineProperties>().translate[0] },
- { PropertyKey::LineTranslateY, defaultStyleProperties<LineProperties>().translate[1] },
+ { PropertyKey::LineTranslate, defaultStyleProperties<LineProperties>().translate },
{ PropertyKey::LineTranslateAnchor, defaultStyleProperties<LineProperties>().translateAnchor },
{ PropertyKey::LineWidth, defaultStyleProperties<LineProperties>().width },
{ PropertyKey::LineGapWidth, defaultStyleProperties<LineProperties>().gap_width },
@@ -29,8 +27,7 @@ const std::map<PropertyKey, PropertyValue> PropertyFallbackValue::properties = {
{ PropertyKey::IconHaloColor, defaultStyleProperties<SymbolProperties>().icon.halo_color },
{ PropertyKey::IconHaloWidth, defaultStyleProperties<SymbolProperties>().icon.halo_width },
{ PropertyKey::IconHaloBlur, defaultStyleProperties<SymbolProperties>().icon.halo_blur },
- { PropertyKey::IconTranslateX, defaultStyleProperties<SymbolProperties>().icon.translate[0] },
- { PropertyKey::IconTranslateY, defaultStyleProperties<SymbolProperties>().icon.translate[1] },
+ { PropertyKey::IconTranslate, defaultStyleProperties<SymbolProperties>().icon.translate },
{ PropertyKey::IconTranslateAnchor, defaultStyleProperties<SymbolProperties>().icon.translate_anchor },
{ PropertyKey::TextOpacity, defaultStyleProperties<SymbolProperties>().text.opacity },
@@ -39,8 +36,7 @@ const std::map<PropertyKey, PropertyValue> PropertyFallbackValue::properties = {
{ PropertyKey::TextHaloColor, defaultStyleProperties<SymbolProperties>().text.halo_color },
{ PropertyKey::TextHaloWidth, defaultStyleProperties<SymbolProperties>().text.halo_width },
{ PropertyKey::TextHaloBlur, defaultStyleProperties<SymbolProperties>().text.halo_blur },
- { PropertyKey::TextTranslateX, defaultStyleProperties<SymbolProperties>().text.translate[0] },
- { PropertyKey::TextTranslateY, defaultStyleProperties<SymbolProperties>().text.translate[1] },
+ { PropertyKey::TextTranslate, defaultStyleProperties<SymbolProperties>().text.translate },
{ PropertyKey::TextTranslateAnchor, defaultStyleProperties<SymbolProperties>().text.translate_anchor },
{ PropertyKey::RasterOpacity, defaultStyleProperties<RasterProperties>().opacity },
@@ -72,8 +68,7 @@ const std::map<PropertyKey, PropertyValue> PropertyFallbackValue::properties = {
{ PropertyKey::IconRotate, defaultLayoutProperties<StyleBucketSymbol>().icon.rotate },
{ PropertyKey::IconPadding, defaultLayoutProperties<StyleBucketSymbol>().icon.padding },
{ PropertyKey::IconKeepUpright, defaultLayoutProperties<StyleBucketSymbol>().icon.keep_upright },
- { PropertyKey::IconOffsetX, defaultLayoutProperties<StyleBucketSymbol>().icon.offset[0] },
- { PropertyKey::IconOffsetY, defaultLayoutProperties<StyleBucketSymbol>().icon.offset[1] },
+ { PropertyKey::IconOffset, defaultLayoutProperties<StyleBucketSymbol>().icon.offset },
{ PropertyKey::TextRotationAlignment, defaultLayoutProperties<StyleBucketSymbol>().text.rotation_alignment },
{ PropertyKey::TextField, defaultLayoutProperties<StyleBucketSymbol>().text.field },
@@ -89,8 +84,7 @@ const std::map<PropertyKey, PropertyValue> PropertyFallbackValue::properties = {
{ PropertyKey::TextPadding, defaultLayoutProperties<StyleBucketSymbol>().text.padding },
{ PropertyKey::TextKeepUpright, defaultLayoutProperties<StyleBucketSymbol>().text.keep_upright },
{ PropertyKey::TextTransform, defaultLayoutProperties<StyleBucketSymbol>().text.transform },
- { PropertyKey::TextOffsetX, defaultLayoutProperties<StyleBucketSymbol>().text.offset[0] },
- { PropertyKey::TextOffsetY, defaultLayoutProperties<StyleBucketSymbol>().text.offset[1] },
+ { PropertyKey::TextOffset, defaultLayoutProperties<StyleBucketSymbol>().text.offset },
{ PropertyKey::TextAllowOverlap, defaultLayoutProperties<StyleBucketSymbol>().text.allow_overlap },
{ PropertyKey::TextIgnorePlacement, defaultLayoutProperties<StyleBucketSymbol>().text.ignore_placement },
{ PropertyKey::TextOptional, defaultLayoutProperties<StyleBucketSymbol>().text.optional },
diff --git a/src/mbgl/style/property_key.hpp b/src/mbgl/style/property_key.hpp
index f10607a7af..dfe82e4bb0 100644
--- a/src/mbgl/style/property_key.hpp
+++ b/src/mbgl/style/property_key.hpp
@@ -9,16 +9,12 @@ enum class PropertyKey {
FillColor,
FillOutlineColor,
FillTranslate, // for transitions only
- FillTranslateX,
- FillTranslateY,
FillTranslateAnchor,
FillImage,
LineOpacity,
LineColor,
LineTranslate, // for transitions only
- LineTranslateX,
- LineTranslateY,
LineTranslateAnchor,
LineWidth,
LineGapWidth,
@@ -41,9 +37,7 @@ enum class PropertyKey {
IconHaloColor,
IconHaloWidth,
IconHaloBlur,
- IconTranslate, // for transitions only
- IconTranslateX,
- IconTranslateY,
+ IconTranslate,
IconTranslateAnchor,
IconAllowOverlap,
@@ -52,11 +46,10 @@ enum class PropertyKey {
IconRotationAlignment,
IconMaxSize,
IconImage,
+ IconOffset,
IconPadding,
IconRotate,
IconKeepUpright,
- IconOffsetX,
- IconOffsetY,
TextOpacity,
TextSize,
@@ -64,9 +57,7 @@ enum class PropertyKey {
TextHaloColor,
TextHaloWidth,
TextHaloBlur,
- TextTranslate, // for transitions only
- TextTranslateX,
- TextTranslateY,
+ TextTranslate,
TextTranslateAnchor,
TextRotationAlignment,
@@ -85,8 +76,7 @@ enum class PropertyKey {
TextAnchor,
TextKeepUpright,
TextTransform,
- TextOffsetX,
- TextOffsetY,
+ TextOffset,
TextAllowOverlap,
RasterOpacity,
diff --git a/src/mbgl/style/property_value.hpp b/src/mbgl/style/property_value.hpp
index ff5a2f8685..fbc3f3bd6a 100644
--- a/src/mbgl/style/property_value.hpp
+++ b/src/mbgl/style/property_value.hpp
@@ -3,29 +3,32 @@
#include <mbgl/util/variant.hpp>
#include <mbgl/style/function_properties.hpp>
+#include <mbgl/style/piecewisefunction_properties.hpp>
#include <mbgl/style/types.hpp>
#include <vector>
+#include <array>
namespace mbgl {
typedef mapbox::util::variant<
- std::string,
- TranslateAnchorType,
- RotateAnchorType,
- bool,
- CapType,
- JoinType,
+ Function<std::string>,
+ Function<TranslateAnchorType>,
+ Function<RotateAnchorType>,
+ Function<CapType>,
+ Function<JoinType>,
VisibilityType,
- PlacementType,
- RotationAlignmentType,
- TextTransformType,
- TextJustifyType,
- TextAnchorType,
+ Function<PlacementType>,
+ Function<RotationAlignmentType>,
+ Function<TextTransformType>,
+ Function<TextJustifyType>,
+ Function<TextAnchorType>,
+ Function<std::array<float, 2>>,
Function<bool>,
Function<float>,
Function<Color>,
- Function<std::vector<float>>
+ PiecewiseConstantFunction<Faded<std::vector<float>>>,
+ PiecewiseConstantFunction<Faded<std::string>>
> PropertyValue;
}
diff --git a/src/mbgl/style/style.cpp b/src/mbgl/style/style.cpp
index 01781afe3c..45217950f6 100644
--- a/src/mbgl/style/style.cpp
+++ b/src/mbgl/style/style.cpp
@@ -28,8 +28,10 @@ Style::~Style() {}
void Style::updateProperties(float z, std::chrono::steady_clock::time_point now) {
uv::writelock lock(mtx);
+ zoomHistory.update(z, now);
+
if (layers) {
- layers->updateProperties(z, now);
+ layers->updateProperties(z, now, zoomHistory);
}
// Apply transitions after the first time.
diff --git a/src/mbgl/style/style.hpp b/src/mbgl/style/style.hpp
index 751a91be62..4de827a38c 100644
--- a/src/mbgl/style/style.hpp
+++ b/src/mbgl/style/style.hpp
@@ -3,6 +3,7 @@
#include <mbgl/style/property_transition.hpp>
#include <mbgl/style/style_source.hpp>
+#include <mbgl/style/zoom_history.hpp>
#include <mbgl/util/uv.hpp>
#include <mbgl/util/ptr.hpp>
@@ -50,6 +51,7 @@ private:
PropertyTransition defaultTransition;
bool initial_render_complete = false;
std::unique_ptr<uv::rwlock> mtx;
+ ZoomHistory zoomHistory;
};
}
diff --git a/src/mbgl/style/style_layer.cpp b/src/mbgl/style/style_layer.cpp
index 3b82d7f94a..1a4354be27 100644
--- a/src/mbgl/style/style_layer.cpp
+++ b/src/mbgl/style/style_layer.cpp
@@ -94,7 +94,7 @@ void StyleLayer::applyClassProperties(const ClassID class_id,
template <typename T>
struct PropertyEvaluator {
typedef T result_type;
- PropertyEvaluator(float z_) : z(z_) {}
+ PropertyEvaluator(float z_, const ZoomHistory &zoomHistory_) : z(z_), zoomHistory(zoomHistory_) {}
template <typename P, typename std::enable_if<std::is_convertible<P, T>::value, int>::type = 0>
T operator()(const P &value) const {
@@ -105,6 +105,10 @@ struct PropertyEvaluator {
return mapbox::util::apply_visitor(FunctionEvaluator<T>(z), value);
}
+ T operator()(const PiecewiseConstantFunction<T> &value) const {
+ return value.evaluate(z, zoomHistory);
+ }
+
template <typename P, typename std::enable_if<!std::is_convertible<P, T>::value, int>::type = 0>
T operator()(const P &) const {
return T();
@@ -112,15 +116,16 @@ struct PropertyEvaluator {
private:
const float z;
+ const ZoomHistory &zoomHistory;
};
template <typename T>
-void StyleLayer::applyStyleProperty(PropertyKey key, T &target, const float z, const std::chrono::steady_clock::time_point now) {
+void StyleLayer::applyStyleProperty(PropertyKey key, T &target, const float z, const std::chrono::steady_clock::time_point now, const ZoomHistory &zoomHistory) {
auto it = appliedStyle.find(key);
if (it != appliedStyle.end()) {
AppliedClassProperties &applied = it->second;
// Iterate through all properties that we need to apply in order.
- const PropertyEvaluator<T> evaluator(z);
+ const PropertyEvaluator<T> evaluator(z, zoomHistory);
for (AppliedClassProperty &property : applied.properties) {
if (now >= property.begin) {
// We overwrite the current property with the new value.
@@ -133,12 +138,12 @@ void StyleLayer::applyStyleProperty(PropertyKey key, T &target, const float z, c
}
template <typename T>
-void StyleLayer::applyTransitionedStyleProperty(PropertyKey key, T &target, const float z, const std::chrono::steady_clock::time_point now) {
+void StyleLayer::applyTransitionedStyleProperty(PropertyKey key, T &target, const float z, const std::chrono::steady_clock::time_point now, const ZoomHistory &zoomHistory) {
auto it = appliedStyle.find(key);
if (it != appliedStyle.end()) {
AppliedClassProperties &applied = it->second;
// Iterate through all properties that we need to apply in order.
- const PropertyEvaluator<T> evaluator(z);
+ const PropertyEvaluator<T> evaluator(z, zoomHistory);
for (AppliedClassProperty &property : applied.properties) {
if (now >= property.end) {
// We overwrite the current property with the new value.
@@ -155,95 +160,91 @@ void StyleLayer::applyTransitionedStyleProperty(PropertyKey key, T &target, cons
}
template <>
-void StyleLayer::applyStyleProperties<FillProperties>(const float z, const std::chrono::steady_clock::time_point now) {
+void StyleLayer::applyStyleProperties<FillProperties>(const float z, const std::chrono::steady_clock::time_point now, const ZoomHistory &zoomHistory) {
properties.set<FillProperties>();
FillProperties &fill = properties.get<FillProperties>();
- applyStyleProperty(PropertyKey::FillAntialias, fill.antialias, z, now);
- applyTransitionedStyleProperty(PropertyKey::FillOpacity, fill.opacity, z, now);
- applyTransitionedStyleProperty(PropertyKey::FillColor, fill.fill_color, z, now);
- applyTransitionedStyleProperty(PropertyKey::FillOutlineColor, fill.stroke_color, z, now);
- applyTransitionedStyleProperty(PropertyKey::FillTranslateX, fill.translate[0], z, now);
- applyTransitionedStyleProperty(PropertyKey::FillTranslateY, fill.translate[1], z, now);
- applyStyleProperty(PropertyKey::FillTranslateAnchor, fill.translateAnchor, z, now);
- applyStyleProperty(PropertyKey::FillImage, fill.image, z, now);
+ applyStyleProperty(PropertyKey::FillAntialias, fill.antialias, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::FillOpacity, fill.opacity, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::FillColor, fill.fill_color, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::FillOutlineColor, fill.stroke_color, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::FillTranslate, fill.translate, z, now, zoomHistory);
+ applyStyleProperty(PropertyKey::FillTranslateAnchor, fill.translateAnchor, z, now, zoomHistory);
+ applyStyleProperty(PropertyKey::FillImage, fill.image, z, now, zoomHistory);
}
template <>
-void StyleLayer::applyStyleProperties<LineProperties>(const float z, const std::chrono::steady_clock::time_point now) {
+void StyleLayer::applyStyleProperties<LineProperties>(const float z, const std::chrono::steady_clock::time_point now, const ZoomHistory &zoomHistory) {
properties.set<LineProperties>();
LineProperties &line = properties.get<LineProperties>();
- applyTransitionedStyleProperty(PropertyKey::LineOpacity, line.opacity, z, now);
- applyTransitionedStyleProperty(PropertyKey::LineColor, line.color, z, now);
- applyTransitionedStyleProperty(PropertyKey::LineTranslateX, line.translate[0], z, now);
- applyTransitionedStyleProperty(PropertyKey::LineTranslateY, line.translate[1], z, now);
- applyStyleProperty(PropertyKey::LineTranslateAnchor, line.translateAnchor, z, now);
- applyTransitionedStyleProperty(PropertyKey::LineWidth, line.width, z, now);
- applyTransitionedStyleProperty(PropertyKey::LineGapWidth, line.gap_width, z, now);
- applyTransitionedStyleProperty(PropertyKey::LineBlur, line.blur, z, now);
- applyStyleProperty(PropertyKey::LineDashArray, line.dash_array, z, now);
- applyStyleProperty(PropertyKey::LineImage, line.image, z, now);
+ applyTransitionedStyleProperty(PropertyKey::LineOpacity, line.opacity, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::LineColor, line.color, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::LineTranslate, line.translate, z, now, zoomHistory);
+ applyStyleProperty(PropertyKey::LineTranslateAnchor, line.translateAnchor, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::LineWidth, line.width, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::LineGapWidth, line.gap_width, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::LineBlur, line.blur, z, now, zoomHistory);
+ applyStyleProperty(PropertyKey::LineDashArray, line.dash_array, z, now, zoomHistory);
+ applyStyleProperty(PropertyKey::LineImage, line.image, z, now, zoomHistory);
// for scaling dasharrays
- applyStyleProperty(PropertyKey::LineWidth, line.dash_line_width, std::floor(z), std::chrono::steady_clock::time_point::max());
+ applyStyleProperty(PropertyKey::LineWidth, line.dash_line_width, std::floor(z), std::chrono::steady_clock::time_point::max(), zoomHistory);
}
template <>
-void StyleLayer::applyStyleProperties<SymbolProperties>(const float z, const std::chrono::steady_clock::time_point now) {
+void StyleLayer::applyStyleProperties<SymbolProperties>(const float z, const std::chrono::steady_clock::time_point now, const ZoomHistory &zoomHistory) {
properties.set<SymbolProperties>();
SymbolProperties &symbol = properties.get<SymbolProperties>();
- applyTransitionedStyleProperty(PropertyKey::IconOpacity, symbol.icon.opacity, z, now);
- applyTransitionedStyleProperty(PropertyKey::IconRotate, symbol.icon.rotate, z, now);
- applyTransitionedStyleProperty(PropertyKey::IconSize, symbol.icon.size, z, now);
- applyTransitionedStyleProperty(PropertyKey::IconColor, symbol.icon.color, z, now);
- applyTransitionedStyleProperty(PropertyKey::IconHaloColor, symbol.icon.halo_color, z, now);
- applyTransitionedStyleProperty(PropertyKey::IconHaloWidth, symbol.icon.halo_width, z, now);
- applyTransitionedStyleProperty(PropertyKey::IconHaloBlur, symbol.icon.halo_blur, z, now);
- applyTransitionedStyleProperty(PropertyKey::IconTranslateX, symbol.icon.translate[0], z, now);
- applyTransitionedStyleProperty(PropertyKey::IconTranslateY, symbol.icon.translate[1], z, now);
- applyStyleProperty(PropertyKey::IconTranslateAnchor, symbol.icon.translate_anchor, z, now);
-
- applyTransitionedStyleProperty(PropertyKey::TextOpacity, symbol.text.opacity, z, now);
- applyTransitionedStyleProperty(PropertyKey::TextSize, symbol.text.size, z, now);
- applyTransitionedStyleProperty(PropertyKey::TextColor, symbol.text.color, z, now);
- applyTransitionedStyleProperty(PropertyKey::TextHaloColor, symbol.text.halo_color, z, now);
- applyTransitionedStyleProperty(PropertyKey::TextHaloWidth, symbol.text.halo_width, z, now);
- applyTransitionedStyleProperty(PropertyKey::TextHaloBlur, symbol.text.halo_blur, z, now);
- applyTransitionedStyleProperty(PropertyKey::TextTranslateX, symbol.text.translate[0], z, now);
- applyTransitionedStyleProperty(PropertyKey::TextTranslateY, symbol.text.translate[1], z, now);
- applyStyleProperty(PropertyKey::TextTranslateAnchor, symbol.text.translate_anchor, z, now);
+ applyTransitionedStyleProperty(PropertyKey::IconOpacity, symbol.icon.opacity, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::IconRotate, symbol.icon.rotate, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::IconSize, symbol.icon.size, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::IconColor, symbol.icon.color, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::IconHaloColor, symbol.icon.halo_color, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::IconHaloWidth, symbol.icon.halo_width, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::IconHaloBlur, symbol.icon.halo_blur, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::IconTranslate, symbol.icon.translate, z, now, zoomHistory);
+ applyStyleProperty(PropertyKey::IconTranslateAnchor, symbol.icon.translate_anchor, z, now, zoomHistory);
+
+ applyTransitionedStyleProperty(PropertyKey::TextOpacity, symbol.text.opacity, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::TextSize, symbol.text.size, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::TextColor, symbol.text.color, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::TextHaloColor, symbol.text.halo_color, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::TextHaloWidth, symbol.text.halo_width, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::TextHaloBlur, symbol.text.halo_blur, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::TextTranslate, symbol.text.translate, z, now, zoomHistory);
+ applyStyleProperty(PropertyKey::TextTranslateAnchor, symbol.text.translate_anchor, z, now, zoomHistory);
}
template <>
-void StyleLayer::applyStyleProperties<RasterProperties>(const float z, const std::chrono::steady_clock::time_point now) {
+void StyleLayer::applyStyleProperties<RasterProperties>(const float z, const std::chrono::steady_clock::time_point now, const ZoomHistory &zoomHistory) {
properties.set<RasterProperties>();
RasterProperties &raster = properties.get<RasterProperties>();
- applyTransitionedStyleProperty(PropertyKey::RasterOpacity, raster.opacity, z, now);
- applyTransitionedStyleProperty(PropertyKey::RasterHueRotate, raster.hue_rotate, z, now);
- applyTransitionedStyleProperty(PropertyKey::RasterBrightnessLow, raster.brightness[0], z, now);
- applyTransitionedStyleProperty(PropertyKey::RasterBrightnessHigh, raster.brightness[1], z, now);
- applyTransitionedStyleProperty(PropertyKey::RasterSaturation, raster.saturation, z, now);
- applyTransitionedStyleProperty(PropertyKey::RasterContrast, raster.contrast, z, now);
- applyTransitionedStyleProperty(PropertyKey::RasterFade, raster.fade, z, now);
+ applyTransitionedStyleProperty(PropertyKey::RasterOpacity, raster.opacity, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::RasterHueRotate, raster.hue_rotate, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::RasterBrightnessLow, raster.brightness[0], z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::RasterBrightnessHigh, raster.brightness[1], z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::RasterSaturation, raster.saturation, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::RasterContrast, raster.contrast, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::RasterFade, raster.fade, z, now, zoomHistory);
}
template <>
-void StyleLayer::applyStyleProperties<BackgroundProperties>(const float z, const std::chrono::steady_clock::time_point now) {
+void StyleLayer::applyStyleProperties<BackgroundProperties>(const float z, const std::chrono::steady_clock::time_point now, const ZoomHistory &zoomHistory) {
properties.set<BackgroundProperties>();
BackgroundProperties &background = properties.get<BackgroundProperties>();
- applyTransitionedStyleProperty(PropertyKey::BackgroundOpacity, background.opacity, z, now);
- applyTransitionedStyleProperty(PropertyKey::BackgroundColor, background.color, z, now);
- applyStyleProperty(PropertyKey::BackgroundImage, background.image, z, now);
+ applyTransitionedStyleProperty(PropertyKey::BackgroundOpacity, background.opacity, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::BackgroundColor, background.color, z, now, zoomHistory);
+ applyStyleProperty(PropertyKey::BackgroundImage, background.image, z, now, zoomHistory);
}
-void StyleLayer::updateProperties(float z, const std::chrono::steady_clock::time_point now) {
+void StyleLayer::updateProperties(float z, const std::chrono::steady_clock::time_point now, ZoomHistory &zoomHistory) {
cleanupAppliedStyleProperties(now);
switch (type) {
- case StyleLayerType::Fill: applyStyleProperties<FillProperties>(z, now); break;
- case StyleLayerType::Line: applyStyleProperties<LineProperties>(z, now); break;
- case StyleLayerType::Symbol: applyStyleProperties<SymbolProperties>(z, now); break;
- case StyleLayerType::Raster: applyStyleProperties<RasterProperties>(z, now); break;
- case StyleLayerType::Background: applyStyleProperties<BackgroundProperties>(z, now); break;
+ case StyleLayerType::Fill: applyStyleProperties<FillProperties>(z, now, zoomHistory); break;
+ case StyleLayerType::Line: applyStyleProperties<LineProperties>(z, now, zoomHistory); break;
+ case StyleLayerType::Symbol: applyStyleProperties<SymbolProperties>(z, now, zoomHistory); break;
+ case StyleLayerType::Raster: applyStyleProperties<RasterProperties>(z, now, zoomHistory); break;
+ case StyleLayerType::Background: applyStyleProperties<BackgroundProperties>(z, now, zoomHistory); break;
default: properties.set<std::false_type>(); break;
}
}
diff --git a/src/mbgl/style/style_layer.hpp b/src/mbgl/style/style_layer.hpp
index b6cfe779c7..69af1dc230 100644
--- a/src/mbgl/style/style_layer.hpp
+++ b/src/mbgl/style/style_layer.hpp
@@ -5,6 +5,7 @@
#include <mbgl/style/class_properties.hpp>
#include <mbgl/style/style_properties.hpp>
#include <mbgl/style/applied_class_properties.hpp>
+#include <mbgl/style/zoom_history.hpp>
#include <mbgl/util/ptr.hpp>
@@ -36,7 +37,7 @@ public:
// Updates the StyleProperties information in this layer by evaluating all
// pending transitions and applied classes in order.
- void updateProperties(float z, std::chrono::steady_clock::time_point now);
+ void updateProperties(float z, std::chrono::steady_clock::time_point now, ZoomHistory &zoomHistory);
// Sets the list of classes and creates transitions to the currently applied values.
void setClasses(const std::vector<std::string> &class_names, std::chrono::steady_clock::time_point now,
@@ -51,9 +52,9 @@ private:
// Sets the properties of this object by evaluating all pending transitions and
// aplied classes in order.
- template <typename T> void applyStyleProperties(float z, std::chrono::steady_clock::time_point now);
- template <typename T> void applyStyleProperty(PropertyKey key, T &, float z, std::chrono::steady_clock::time_point now);
- template <typename T> void applyTransitionedStyleProperty(PropertyKey key, T &, float z, std::chrono::steady_clock::time_point now);
+ template <typename T> void applyStyleProperties(float z, std::chrono::steady_clock::time_point now, const ZoomHistory &zoomHistory);
+ template <typename T> void applyStyleProperty(PropertyKey key, T &, float z, std::chrono::steady_clock::time_point now, const ZoomHistory &zoomHistory);
+ template <typename T> void applyTransitionedStyleProperty(PropertyKey key, T &, float z, std::chrono::steady_clock::time_point now, const ZoomHistory &zoomHistory);
// Removes all expired style transitions.
void cleanupAppliedStyleProperties(std::chrono::steady_clock::time_point now);
diff --git a/src/mbgl/style/style_layer_group.cpp b/src/mbgl/style/style_layer_group.cpp
index 3f1a4a5111..f57ec5cc7b 100644
--- a/src/mbgl/style/style_layer_group.cpp
+++ b/src/mbgl/style/style_layer_group.cpp
@@ -11,10 +11,10 @@ void StyleLayerGroup::setClasses(const std::vector<std::string> &class_names, st
}
}
-void StyleLayerGroup::updateProperties(float z, std::chrono::steady_clock::time_point now) {
+void StyleLayerGroup::updateProperties(float z, std::chrono::steady_clock::time_point now, ZoomHistory &zoomHistory) {
for (const util::ptr<StyleLayer> &layer: layers) {
if (layer) {
- layer->updateProperties(z, now);
+ layer->updateProperties(z, now, zoomHistory);
}
}
}
diff --git a/src/mbgl/style/style_layer_group.hpp b/src/mbgl/style/style_layer_group.hpp
index 3f5a20073d..79b75a55e9 100644
--- a/src/mbgl/style/style_layer_group.hpp
+++ b/src/mbgl/style/style_layer_group.hpp
@@ -12,7 +12,7 @@ class StyleLayerGroup {
public:
void setClasses(const std::vector<std::string> &class_names, std::chrono::steady_clock::time_point now,
const PropertyTransition &defaultTransition);
- void updateProperties(float z, std::chrono::steady_clock::time_point now);
+ void updateProperties(float z, std::chrono::steady_clock::time_point now, ZoomHistory &zoomHistory);
bool hasTransitions() const;
public:
diff --git a/src/mbgl/style/style_parser.cpp b/src/mbgl/style/style_parser.cpp
index 15aedd8ead..af6a84492d 100644
--- a/src/mbgl/style/style_parser.cpp
+++ b/src/mbgl/style/style_parser.cpp
@@ -209,7 +209,7 @@ Color parseColor(JSVal value) {
css_color.a}};
}
-std::tuple<bool,std::vector<float>> parseFloatArray(JSVal value) {
+std::tuple<bool,std::vector<float>> StyleParser::parseFloatArray(JSVal value) {
if (!value.IsArray()) {
Log::Warning(Event::ParseStyle, "dasharray value must be an array of numbers");
return std::tuple<bool, std::vector<float>> { false, std::vector<float>() };
@@ -217,7 +217,7 @@ std::tuple<bool,std::vector<float>> parseFloatArray(JSVal value) {
std::vector<float> vec;
for (rapidjson::SizeType i = 0; i < value.Size(); ++i) {
- JSVal part = value[i];
+ JSVal part = replaceConstant(value[i]);
if (!part.IsNumber()) {
Log::Warning(Event::ParseStyle, "dasharray value must be an array of numbers");
return std::tuple<bool, std::vector<float>> { false, std::vector<float>() };
@@ -228,46 +228,101 @@ std::tuple<bool,std::vector<float>> parseFloatArray(JSVal value) {
}
template <>
-bool StyleParser::parseFunctionArgument(JSVal value) {
- JSVal rvalue = replaceConstant(value);
- if (rvalue.IsBool()) {
- return rvalue.GetBool();
- } else if (rvalue.IsNumber()) {
- return rvalue.GetDouble();
+std::tuple<bool, std::array<float, 2>> StyleParser::parseProperty(JSVal value, const char*) {
+ if (value.IsArray() && value.Size() == 2 &&
+ value[rapidjson::SizeType(0)].IsNumber() &&
+ value[rapidjson::SizeType(1)].IsNumber()) {
+
+ float first = value[rapidjson::SizeType(0)].GetDouble();
+ float second = value[rapidjson::SizeType(1)].GetDouble();
+ return std::tuple<bool, std::array<float, 2>> { false, {{ first, second }} };
} else {
- Log::Warning(Event::ParseStyle, "function argument must be a boolean or numeric value");
- return false;
+ Log::Warning(Event::ParseStyle, "value must be array of two numbers");
+ return std::tuple<bool, std::array<float, 2>> { false, {{ 0.0f, 0.0f }} };
}
}
template <>
-float StyleParser::parseFunctionArgument(JSVal value) {
+std::tuple<bool, float> StyleParser::parseProperty(JSVal value, const char* property_name) {
JSVal rvalue = replaceConstant(value);
if (rvalue.IsNumber()) {
- return rvalue.GetDouble();
+ return std::tuple<bool, float> { true, rvalue.GetDouble() };
} else {
- Log::Warning(Event::ParseStyle, "function argument must be a numeric value");
- return 0.0f;
+ Log::Warning(Event::ParseStyle, "value of '%s' must be a number, or a number function", property_name);
+ return std::tuple<bool, float> { false, 0.0f };
}
}
template <>
-Color StyleParser::parseFunctionArgument(JSVal value) {
+std::tuple<bool, Color> StyleParser::parseProperty(JSVal value, const char*) {
+ JSVal rvalue = replaceConstant(value);
+ return std::tuple<bool, Color> { true, parseColor(rvalue) };
+}
+
+template <>
+std::tuple<bool, Faded<std::vector<float>>> StyleParser::parseProperty(JSVal value, const char*) {
+ Faded<std::vector<float>> parsed;
JSVal rvalue = replaceConstant(value);
- return parseColor(rvalue);
+ parsed.to = std::get<1>(parseFloatArray(rvalue));
+ return std::tuple<bool, Faded<std::vector<float>>> { true, parsed };
}
template <>
-std::vector<float> StyleParser::parseFunctionArgument(JSVal value) {
+std::tuple<bool, Faded<std::string>> StyleParser::parseProperty(JSVal value, const char *property_name) {
JSVal rvalue = replaceConstant(value);
- return std::get<1>(parseFloatArray(rvalue));
+ Faded<std::string> parsed;
+ if (rvalue.IsString()) {
+ parsed.to = { value.GetString(), value.GetStringLength() };
+ return std::tuple<bool, Faded<std::string>> { true, parsed };
+ } else {
+ Log::Warning(Event::ParseStyle, "value of '%s' must be a string, or a string function", property_name);
+ return std::tuple<bool, Faded<std::string>> { false, parsed };
+ }
+}
+
+template <typename T>
+std::tuple<bool, std::vector<std::pair<float, T>>> StyleParser::parseStops(JSVal value_stops, const char *property_name) {
+
+ if (!value_stops.IsArray()) {
+ Log::Warning(Event::ParseStyle, "stops function must specify a stops array");
+ return std::tuple<bool, std::vector<std::pair<float, T>>> { false, {}};
+ }
+
+ std::vector<std::pair<float, T>> stops;
+
+ for (rapidjson::SizeType i = 0; i < value_stops.Size(); ++i) {
+ JSVal stop = value_stops[i];
+ if (stop.IsArray()) {
+ if (stop.Size() != 2) {
+ Log::Warning(Event::ParseStyle, "stop must have zoom level and value specification");
+ return std::tuple<bool, std::vector<std::pair<float, T>>> { false, {}};
+ }
+
+ JSVal z = stop[rapidjson::SizeType(0)];
+ if (!z.IsNumber()) {
+ Log::Warning(Event::ParseStyle, "zoom level in stop must be a number");
+ return std::tuple<bool, std::vector<std::pair<float, T>>> { false, {}};
+ }
+
+ stops.emplace_back(z.GetDouble(), std::get<1>(parseProperty<T>(replaceConstant(stop[rapidjson::SizeType(1)]), property_name)));
+ } else {
+ Log::Warning(Event::ParseStyle, "function argument must be a numeric value");
+ return std::tuple<bool, std::vector<std::pair<float, T>>> { false, {}};
+ }
+ }
+ return std::tuple<bool, std::vector<std::pair<float, T>>>(true, stops);
}
template <typename T> inline float defaultBaseValue() { return 1.75; }
template <> inline float defaultBaseValue<Color>() { return 1.0; }
template <typename T>
-std::tuple<bool, Function<T>> StyleParser::parseFunction(JSVal value) {
+std::tuple<bool, Function<T>> StyleParser::parseFunction(JSVal value, const char *property_name) {
+
+ if (!value.IsObject()) {
+ return std::tuple<bool, Function<T>> { true, ConstantFunction<T>(std::get<1>(parseProperty<T>(value, property_name))) };
+ }
+
if (!value.HasMember("stops")) {
Log::Warning(Event::ParseStyle, "function must specify a function type");
return std::tuple<bool, Function<T>> { false, ConstantFunction<T>(T()) };
@@ -284,47 +339,47 @@ std::tuple<bool, Function<T>> StyleParser::parseFunction(JSVal value) {
}
}
- JSVal value_stops = value["stops"];
- if (!value_stops.IsArray()) {
- Log::Warning(Event::ParseStyle, "stops function must specify a stops array");
+ auto stops = parseStops<T>(value["stops"], property_name);
+
+ if (!std::get<0>(stops)) {
return std::tuple<bool, Function<T>> { false, ConstantFunction<T>(T()) };
}
- std::vector<std::pair<float, T>> stops;
- for (rapidjson::SizeType i = 0; i < value_stops.Size(); ++i) {
- JSVal stop = value_stops[i];
- if (stop.IsArray()) {
- if (stop.Size() != 2) {
- Log::Warning(Event::ParseStyle, "stop must have zoom level and value specification");
- return std::tuple<bool, Function<T>> { false, ConstantFunction<T>(T()) };
- }
+ return std::tuple<bool, Function<T>> { true, StopsFunction<T>(std::get<1>(stops), base) };
+}
- JSVal z = stop[rapidjson::SizeType(0)];
- if (!z.IsNumber()) {
- Log::Warning(Event::ParseStyle, "zoom level in stop must be a number");
- return std::tuple<bool, Function<T>> { false, ConstantFunction<T>(T()) };
- }
+template <typename T>
+std::tuple<bool, PiecewiseConstantFunction<T>> StyleParser::parsePiecewiseConstantFunction(JSVal value, std::chrono::steady_clock::duration duration) {
+ if (!value.HasMember("stops")) {
+ Log::Warning(Event::ParseStyle, "function must specify a function type");
+ return std::tuple<bool, PiecewiseConstantFunction<T>> { false, {} };
+ }
- stops.emplace_back(z.GetDouble(), parseFunctionArgument<T>(stop[rapidjson::SizeType(1)]));
- } else {
- Log::Warning(Event::ParseStyle, "function argument must be a numeric value");
- return std::tuple<bool, Function<T>> { false, ConstantFunction<T>(T()) };
- }
+ auto stops = parseStops<T>(value["stops"], "");
+
+ if (!std::get<0>(stops)) {
+ return std::tuple<bool, PiecewiseConstantFunction<T>> { false, {} };
}
- return std::tuple<bool, Function<T>> { true, StopsFunction<T>(stops, base) };
+ return std::tuple<bool, PiecewiseConstantFunction<T>> { true, { std::get<1>(stops), duration } };
}
-
template <typename T>
bool StyleParser::setProperty(JSVal value, const char *property_name, PropertyKey key, ClassProperties &klass) {
- bool parsed;
- T result;
- std::tie(parsed, result) = parseProperty<T>(value, property_name);
- if (parsed) {
- klass.set(key, result);
+ auto res = parseProperty<T>(value, property_name);
+ if (std::get<0>(res)) {
+ klass.set(key, std::get<1>(res));
+ }
+ return std::get<0>(res);
+}
+
+template <typename T>
+bool StyleParser::setProperty(JSVal value, const char *property_name, PropertyKey key, ClassProperties &klass, JSVal transition) {
+ auto res = parseProperty<T>(value, property_name, transition);
+ if (std::get<0>(res)) {
+ klass.set(key, std::get<1>(res));
}
- return parsed;
+ return std::get<0>(res);
}
template<typename T>
@@ -348,6 +403,21 @@ bool StyleParser::parseOptionalProperty(const char *property_name, PropertyKey k
}
}
+template<typename T>
+bool StyleParser::parseOptionalProperty(const char *property_name, PropertyKey key, ClassProperties &klass, JSVal value, const char *transition_name) {
+ if (!value.HasMember(property_name)) {
+ return false;
+ } else {
+ if (value.HasMember(transition_name)) {
+ return setProperty<T>(replaceConstant(value[property_name]), property_name, key, klass, value[transition_name]);
+ } else {
+ JSVal val = JSVal(rapidjson::kObjectType);
+ return setProperty<T>(replaceConstant(value[property_name]), property_name, key, klass, val);
+ }
+ }
+}
+
+
template<> std::tuple<bool, std::string> StyleParser::parseProperty(JSVal value, const char *property_name) {
if (!value.IsString()) {
Log::Warning(Event::ParseStyle, "value of '%s' must be a string", property_name);
@@ -465,72 +535,99 @@ template<> std::tuple<bool, PropertyTransition> StyleParser::parseProperty(JSVal
return std::tuple<bool, PropertyTransition> { true, std::move(transition) };
}
+template<> std::tuple<bool, Function<std::array<float, 2>>> StyleParser::parseProperty(JSVal value, const char *property_name) {
+ return parseFunction<std::array<float, 2>>(value, property_name);
+}
+
+template<> std::tuple<bool, Function<std::string>> StyleParser::parseProperty(JSVal value, const char *property_name) {
+ return parseFunction<std::string>(value, property_name);
+}
+
+template<> std::tuple<bool, Function<TranslateAnchorType>> StyleParser::parseProperty(JSVal value, const char *property_name) {
+ return parseFunction<TranslateAnchorType>(value, property_name);
+}
+
+template<> std::tuple<bool, Function<RotateAnchorType>> StyleParser::parseProperty(JSVal value, const char *property_name) {
+ return parseFunction<RotateAnchorType>(value, property_name);
+}
+
+template<> std::tuple<bool, Function<CapType>> StyleParser::parseProperty(JSVal value, const char *property_name) {
+ return parseFunction<CapType>(value, property_name);
+}
+
+template<> std::tuple<bool, Function<JoinType>> StyleParser::parseProperty(JSVal value, const char *property_name) {
+ return parseFunction<JoinType>(value, property_name);
+}
+
+template<> std::tuple<bool, Function<PlacementType>> StyleParser::parseProperty(JSVal value, const char *property_name) {
+ return parseFunction<PlacementType>(value, property_name);
+}
+
+template<> std::tuple<bool, Function<TextAnchorType>> StyleParser::parseProperty(JSVal value, const char *property_name) {
+ return parseFunction<TextAnchorType>(value, property_name);
+}
+
+template<> std::tuple<bool, Function<TextJustifyType>> StyleParser::parseProperty(JSVal value, const char *property_name) {
+ return parseFunction<TextJustifyType>(value, property_name);
+}
+
+template<> std::tuple<bool, Function<TextTransformType>> StyleParser::parseProperty(JSVal value, const char *property_name) {
+ return parseFunction<TextTransformType>(value, property_name);
+}
+
+template<> std::tuple<bool, Function<RotationAlignmentType>> StyleParser::parseProperty(JSVal value, const char *property_name) {
+ return parseFunction<RotationAlignmentType>(value, property_name);
+}
+
+
template<> std::tuple<bool, Function<bool>> StyleParser::parseProperty(JSVal value, const char *property_name) {
- if (value.IsObject()) {
- return parseFunction<bool>(value);
- } else if (value.IsNumber()) {
- return std::tuple<bool, Function<bool>> { true, ConstantFunction<bool>(value.GetDouble()) };
- } else if (value.IsBool()) {
- return std::tuple<bool, Function<bool>> { true, ConstantFunction<bool>(value.GetBool()) };
- } else {
- Log::Warning(Event::ParseStyle, "value of '%s' must be convertible to boolean, or a boolean function", property_name);
- return std::tuple<bool, Function<bool>> { false, ConstantFunction<bool>(false) };
- }
+ return parseFunction<bool>(value, property_name);
}
template<> std::tuple<bool, Function<float>> StyleParser::parseProperty(JSVal value, const char *property_name) {
- if (value.IsObject()) {
- return parseFunction<float>(value);
- } else if (value.IsNumber()) {
- return std::tuple<bool, Function<float>> { true, ConstantFunction<float>(value.GetDouble()) };
- } else if (value.IsBool()) {
- return std::tuple<bool, Function<float>> { true, ConstantFunction<float>(value.GetBool()) };
- } else {
- Log::Warning(Event::ParseStyle, "value of '%s' must be a number, or a number function", property_name);
- return std::tuple<bool, Function<float>> { false, ConstantFunction<float>(0) };
- }
+ return parseFunction<float>(value, property_name);
}
template<> std::tuple<bool, Function<Color>> StyleParser::parseProperty(JSVal value, const char *property_name) {
- if (value.IsObject()) {
- return parseFunction<Color>(value);
- } else if (value.IsString()) {
- return std::tuple<bool, Function<Color>> { true, ConstantFunction<Color>(parseColor(value)) };
- } else {
- Log::Warning(Event::ParseStyle, "value of '%s' must be a color, or a color function", property_name);
- return std::tuple<bool, Function<Color>> { false, ConstantFunction<Color>(Color {{ 0, 0, 0, 0 }}) };
- }
+ return parseFunction<Color>(value, property_name);
}
-template<> std::tuple<bool, Function<std::vector<float>>> StyleParser::parseProperty(JSVal value, const char *property_name) {
+template<> std::tuple<bool, PiecewiseConstantFunction<Faded<std::vector<float>>>> StyleParser::parseProperty(JSVal value, const char *property_name, JSVal transition) {
+ std::chrono::steady_clock::duration duration = std::chrono::milliseconds(300);
+ if (transition.HasMember("duration")) {
+ duration = std::chrono::milliseconds(transition["duration"].GetUint());
+ }
+
if (value.IsObject()) {
- return parseFunction<std::vector<float>>(value);
+ return parsePiecewiseConstantFunction<Faded<std::vector<float>>>(value, duration);
} else if (value.IsArray()) {
- std::tuple<bool, std::vector<float>> parsed = parseFloatArray(value);
- return std::tuple<bool, Function<std::vector<float>>> { std::get<0>(parsed), ConstantFunction<std::vector<float>>(std::get<1>(parsed)) };
+ Faded<std::vector<float>> parsed;
+ std::tuple<bool, std::vector<float>> floatarray = parseFloatArray(value);
+ parsed.to = std::get<1>(floatarray);
+ return std::tuple<bool, PiecewiseConstantFunction<Faded<std::vector<float>>>> { std::get<0>(floatarray), { parsed, duration } };
} else {
Log::Warning(Event::ParseStyle, "value of '%s' must be an array of numbers, or a number array function", property_name);
- return std::tuple<bool, Function<std::vector<float>>> { false, ConstantFunction<std::vector<float>>(std::vector<float>()) };
+ return std::tuple<bool, PiecewiseConstantFunction<Faded<std::vector<float>>>> { false, {} };
}
}
-template <typename T>
-bool StyleParser::parseOptionalProperty(const char *property_name, const std::vector<PropertyKey> &keys, ClassProperties &klass, JSVal value) {
- if (value.HasMember(property_name)) {
- JSVal rvalue = replaceConstant(value[property_name]);
- if (!rvalue.IsArray()) {
- Log::Warning(Event::ParseStyle, "array value must be an array");
- }
+template<> std::tuple<bool, PiecewiseConstantFunction<Faded<std::string>>> StyleParser::parseProperty(JSVal value, const char *property_name, JSVal transition) {
- if (rvalue.Size() != keys.size()) {
- Log::Warning(Event::ParseStyle, "array value has unexpected number of elements");
- }
+ std::chrono::steady_clock::duration duration = std::chrono::milliseconds(300);
+ if (transition.HasMember("duration")) {
+ duration = std::chrono::milliseconds(transition["duration"].GetUint());
+ }
- for (uint16_t i = 0; i < keys.size(); i++) {
- setProperty<T>(rvalue[(rapidjson::SizeType)i], property_name, keys[i], klass);
- }
+ if (value.IsObject()) {
+ return parsePiecewiseConstantFunction<Faded<std::string>>(value, duration);
+ } else if (value.IsString()) {
+ Faded<std::string> parsed;
+ parsed.to = { value.GetString(), value.GetStringLength() };
+ return std::tuple<bool, PiecewiseConstantFunction<Faded<std::string>>> { true, { parsed, duration } };
+ } else {
+ Log::Warning(Event::ParseStyle, "value of '%s' must be string or a string function", property_name);
+ return std::tuple<bool, PiecewiseConstantFunction<Faded<std::string>>> { false, {} };
}
- return true;
}
#pragma mark - Parse Layers
@@ -654,26 +751,26 @@ void StyleParser::parsePaint(JSVal value, ClassProperties &klass) {
parseOptionalProperty<PropertyTransition>("fill-color-transition", Key::FillColor, klass, value);
parseOptionalProperty<Function<Color>>("fill-outline-color", Key::FillOutlineColor, klass, value);
parseOptionalProperty<PropertyTransition>("fill-outline-color-transition", Key::FillOutlineColor, klass, value);
- parseOptionalProperty<Function<float>>("fill-translate", { Key::FillTranslateX, Key::FillTranslateY }, klass, value);
+ parseOptionalProperty<Function<std::array<float, 2>>>("fill-translate", Key::FillTranslate, klass, value);
parseOptionalProperty<PropertyTransition>("fill-translate-transition", Key::FillTranslate, klass, value);
- parseOptionalProperty<TranslateAnchorType>("fill-translate-anchor", Key::FillTranslateAnchor, klass, value);
- parseOptionalProperty<std::string>("fill-image", Key::FillImage, klass, value);
+ parseOptionalProperty<Function<TranslateAnchorType>>("fill-translate-anchor", Key::FillTranslateAnchor, klass, value);
+ parseOptionalProperty<PiecewiseConstantFunction<Faded<std::string>>>("fill-image", Key::FillImage, klass, value, "fill-image-transition");
parseOptionalProperty<Function<float>>("line-opacity", Key::LineOpacity, klass, value);
parseOptionalProperty<PropertyTransition>("line-opacity-transition", Key::LineOpacity, klass, value);
parseOptionalProperty<Function<Color>>("line-color", Key::LineColor, klass, value);
parseOptionalProperty<PropertyTransition>("line-color-transition", Key::LineColor, klass, value);
- parseOptionalProperty<Function<float>>("line-translate", { Key::LineTranslateX, Key::LineTranslateY }, klass, value);
+ parseOptionalProperty<Function<std::array<float,2>>>("line-translate", Key::LineTranslate, klass, value);
parseOptionalProperty<PropertyTransition>("line-translate-transition", Key::LineTranslate, klass, value);
- parseOptionalProperty<TranslateAnchorType>("line-translate-anchor", Key::LineTranslateAnchor, klass, value);
+ parseOptionalProperty<Function<TranslateAnchorType>>("line-translate-anchor", Key::LineTranslateAnchor, klass, value);
parseOptionalProperty<Function<float>>("line-width", Key::LineWidth, klass, value);
parseOptionalProperty<PropertyTransition>("line-width-transition", Key::LineWidth, klass, value);
parseOptionalProperty<Function<float>>("line-gap-width", Key::LineGapWidth, klass, value);
parseOptionalProperty<PropertyTransition>("line-gap-width-transition", Key::LineGapWidth, klass, value);
parseOptionalProperty<Function<float>>("line-blur", Key::LineBlur, klass, value);
parseOptionalProperty<PropertyTransition>("line-blur-transition", Key::LineBlur, klass, value);
- parseOptionalProperty<Function<std::vector<float>>>("line-dasharray", Key::LineDashArray, klass, value);
- parseOptionalProperty<std::string>("line-image", Key::LineImage, klass, value);
+ parseOptionalProperty<PiecewiseConstantFunction<Faded<std::vector<float>>>>("line-dasharray", Key::LineDashArray, klass, value, "line-dasharray-transition");
+ parseOptionalProperty<PiecewiseConstantFunction<Faded<std::string>>>("line-image", Key::LineImage, klass, value, "line-image-transition");
parseOptionalProperty<Function<float>>("icon-opacity", Key::IconOpacity, klass, value);
parseOptionalProperty<PropertyTransition>("icon-opacity-transition", Key::IconOpacity, klass, value);
@@ -688,9 +785,9 @@ void StyleParser::parsePaint(JSVal value, ClassProperties &klass) {
parseOptionalProperty<PropertyTransition>("icon-halo-width-transition", Key::IconHaloWidth, klass, value);
parseOptionalProperty<Function<float>>("icon-halo-blur", Key::IconHaloBlur, klass, value);
parseOptionalProperty<PropertyTransition>("icon-halo-blur-transition", Key::IconHaloBlur, klass, value);
- parseOptionalProperty<Function<float>>("icon-translate", { Key::IconTranslateX, Key::IconTranslateY }, klass, value);
+ parseOptionalProperty<Function<std::array<float, 2>>>("icon-translate", Key::IconTranslate, klass, value);
parseOptionalProperty<PropertyTransition>("icon-translate-transition", Key::IconTranslate, klass, value);
- parseOptionalProperty<TranslateAnchorType>("icon-translate-anchor", Key::IconTranslateAnchor, klass, value);
+ parseOptionalProperty<Function<TranslateAnchorType>>("icon-translate-anchor", Key::IconTranslateAnchor, klass, value);
parseOptionalProperty<Function<float>>("text-opacity", Key::TextOpacity, klass, value);
parseOptionalProperty<PropertyTransition>("text-opacity-transition", Key::TextOpacity, klass, value);
@@ -704,15 +801,16 @@ void StyleParser::parsePaint(JSVal value, ClassProperties &klass) {
parseOptionalProperty<PropertyTransition>("text-halo-width-transition", Key::TextHaloWidth, klass, value);
parseOptionalProperty<Function<float>>("text-halo-blur", Key::TextHaloBlur, klass, value);
parseOptionalProperty<PropertyTransition>("text-halo-blur-transition", Key::TextHaloBlur, klass, value);
- parseOptionalProperty<Function<float>>("text-translate", { Key::TextTranslateX, Key::TextTranslateY }, klass, value);
+ parseOptionalProperty<Function<std::array<float, 2>>>("text-translate", Key::TextTranslate, klass, value);
parseOptionalProperty<PropertyTransition>("text-translate-transition", Key::TextTranslate, klass, value);
- parseOptionalProperty<TranslateAnchorType>("text-translate-anchor", Key::TextTranslateAnchor, klass, value);
+ parseOptionalProperty<Function<TranslateAnchorType>>("text-translate-anchor", Key::TextTranslateAnchor, klass, value);
parseOptionalProperty<Function<float>>("raster-opacity", Key::RasterOpacity, klass, value);
parseOptionalProperty<PropertyTransition>("raster-opacity-transition", Key::RasterOpacity, klass, value);
parseOptionalProperty<Function<float>>("raster-hue-rotate", Key::RasterHueRotate, klass, value);
parseOptionalProperty<PropertyTransition>("raster-hue-rotate-transition", Key::RasterHueRotate, klass, value);
- parseOptionalProperty<Function<float>>("raster-brightness", { Key::RasterBrightnessLow, Key::RasterBrightnessHigh }, klass, value);
+ parseOptionalProperty<Function<float>>("raster-brightness-min", Key::RasterBrightnessLow, klass, value);
+ parseOptionalProperty<Function<float>>("raster-brightness-max", Key::RasterBrightnessHigh, klass, value);
parseOptionalProperty<PropertyTransition>("raster-brightness-transition", Key::RasterBrightness, klass, value);
parseOptionalProperty<Function<float>>("raster-saturation", Key::RasterSaturation, klass, value);
parseOptionalProperty<PropertyTransition>("raster-saturation-transition", Key::RasterSaturation, klass, value);
@@ -723,7 +821,7 @@ void StyleParser::parsePaint(JSVal value, ClassProperties &klass) {
parseOptionalProperty<Function<float>>("background-opacity", Key::BackgroundOpacity, klass, value);
parseOptionalProperty<Function<Color>>("background-color", Key::BackgroundColor, klass, value);
- parseOptionalProperty<std::string>("background-image", Key::BackgroundImage, klass, value);
+ parseOptionalProperty<PiecewiseConstantFunction<Faded<std::string>>>("background-image", Key::BackgroundImage, klass, value, "background-image-transition");
}
void StyleParser::parseLayout(JSVal value, util::ptr<StyleBucket> &bucket) {
@@ -731,42 +829,42 @@ void StyleParser::parseLayout(JSVal value, util::ptr<StyleBucket> &bucket) {
parseVisibility<VisibilityType>(*bucket, value);
- parseOptionalProperty<CapType>("line-cap", Key::LineCap, bucket->layout, value);
- parseOptionalProperty<JoinType>("line-join", Key::LineJoin, bucket->layout, value);
+ parseOptionalProperty<Function<CapType>>("line-cap", Key::LineCap, bucket->layout, value);
+ parseOptionalProperty<Function<JoinType>>("line-join", Key::LineJoin, bucket->layout, value);
parseOptionalProperty<Function<float>>("line-miter-limit", Key::LineMiterLimit, bucket->layout, value);
parseOptionalProperty<Function<float>>("line-round-limit", Key::LineRoundLimit, bucket->layout, value);
- parseOptionalProperty<PlacementType>("symbol-placement", Key::SymbolPlacement, bucket->layout, value);
+ parseOptionalProperty<Function<PlacementType>>("symbol-placement", Key::SymbolPlacement, bucket->layout, value);
parseOptionalProperty<Function<float>>("symbol-min-distance", Key::SymbolMinDistance, bucket->layout, value);
- parseOptionalProperty<bool>("symbol-avoid-edges", Key::SymbolAvoidEdges, bucket->layout, value);
- parseOptionalProperty<bool>("icon-allow-overlap", Key::IconAllowOverlap, bucket->layout, value);
- parseOptionalProperty<bool>("icon-ignore-placement", Key::IconIgnorePlacement, bucket->layout, value);
- parseOptionalProperty<bool>("icon-optional", Key::IconOptional, bucket->layout, value);
- parseOptionalProperty<RotationAlignmentType>("icon-rotation-alignment", Key::IconRotationAlignment, bucket->layout, value);
+ parseOptionalProperty<Function<bool>>("symbol-avoid-edges", Key::SymbolAvoidEdges, bucket->layout, value);
+ parseOptionalProperty<Function<bool>>("icon-allow-overlap", Key::IconAllowOverlap, bucket->layout, value);
+ parseOptionalProperty<Function<bool>>("icon-ignore-placement", Key::IconIgnorePlacement, bucket->layout, value);
+ parseOptionalProperty<Function<bool>>("icon-optional", Key::IconOptional, bucket->layout, value);
+ parseOptionalProperty<Function<RotationAlignmentType>>("icon-rotation-alignment", Key::IconRotationAlignment, bucket->layout, value);
parseOptionalProperty<Function<float>>("icon-max-size", Key::IconMaxSize, bucket->layout, value);
- parseOptionalProperty<std::string>("icon-image", Key::IconImage, bucket->layout, value);
+ parseOptionalProperty<Function<std::string>>("icon-image", Key::IconImage, bucket->layout, value);
parseOptionalProperty<Function<float>>("icon-rotate", Key::IconRotate, bucket->layout, value);
parseOptionalProperty<Function<float>>("icon-padding", Key::IconPadding, bucket->layout, value);
- parseOptionalProperty<bool>("icon-keep-upright", Key::IconKeepUpright, bucket->layout, value);
- parseOptionalProperty<Function<float>>("icon-offset", { Key::IconOffsetX, Key::IconOffsetY }, bucket->layout, value);
- parseOptionalProperty<RotationAlignmentType>("text-rotation-alignment", Key::TextRotationAlignment, bucket->layout, value);
- parseOptionalProperty<std::string>("text-field", Key::TextField, bucket->layout, value);
- parseOptionalProperty<std::string>("text-font", Key::TextFont, bucket->layout, value);
+ parseOptionalProperty<Function<bool>>("icon-keep-upright", Key::IconKeepUpright, bucket->layout, value);
+ parseOptionalProperty<Function<std::array<float, 2>>>("icon-offset", Key::IconOffset, bucket->layout, value);
+ parseOptionalProperty<Function<RotationAlignmentType>>("text-rotation-alignment", Key::TextRotationAlignment, bucket->layout, value);
+ parseOptionalProperty<Function<std::string>>("text-field", Key::TextField, bucket->layout, value);
+ parseOptionalProperty<Function<std::string>>("text-font", Key::TextFont, bucket->layout, value);
parseOptionalProperty<Function<float>>("text-max-size", Key::TextMaxSize, bucket->layout, value);
parseOptionalProperty<Function<float>>("text-max-width", Key::TextMaxWidth, bucket->layout, value);
parseOptionalProperty<Function<float>>("text-line-height", Key::TextLineHeight, bucket->layout, value);
parseOptionalProperty<Function<float>>("text-letter-spacing", Key::TextLetterSpacing, bucket->layout, value);
- parseOptionalProperty<TextJustifyType>("text-justify", Key::TextJustify, bucket->layout, value);
- parseOptionalProperty<TextAnchorType>("text-anchor", Key::TextAnchor, bucket->layout, value);
+ parseOptionalProperty<Function<TextJustifyType>>("text-justify", Key::TextJustify, bucket->layout, value);
+ parseOptionalProperty<Function<TextAnchorType>>("text-anchor", Key::TextAnchor, bucket->layout, value);
parseOptionalProperty<Function<float>>("text-max-angle", Key::TextMaxAngle, bucket->layout, value);
parseOptionalProperty<Function<float>>("text-rotate", Key::TextRotate, bucket->layout, value);
parseOptionalProperty<Function<float>>("text-padding", Key::TextPadding, bucket->layout, value);
- parseOptionalProperty<bool>("text-keep-upright", Key::TextKeepUpright, bucket->layout, value);
- parseOptionalProperty<TextTransformType>("text-transform", Key::TextTransform, bucket->layout, value);
- parseOptionalProperty<Function<float>>("text-offset", { Key::TextOffsetX, Key::TextOffsetY }, bucket->layout, value);
- parseOptionalProperty<bool>("text-allow-overlap", Key::TextAllowOverlap, bucket->layout, value);
- parseOptionalProperty<bool>("text-ignore-placement", Key::TextIgnorePlacement, bucket->layout, value);
- parseOptionalProperty<bool>("text-optional", Key::TextOptional, bucket->layout, value);
+ parseOptionalProperty<Function<bool>>("text-keep-upright", Key::TextKeepUpright, bucket->layout, value);
+ parseOptionalProperty<Function<TextTransformType>>("text-transform", Key::TextTransform, bucket->layout, value);
+ parseOptionalProperty<Function<std::array<float, 2>>>("text-offset", Key::TextOffset, bucket->layout, value);
+ parseOptionalProperty<Function<bool>>("text-allow-overlap", Key::TextAllowOverlap, bucket->layout, value);
+ parseOptionalProperty<Function<bool>>("text-ignore-placement", Key::TextIgnorePlacement, bucket->layout, value);
+ parseOptionalProperty<Function<bool>>("text-optional", Key::TextOptional, bucket->layout, value);
}
diff --git a/src/mbgl/style/style_parser.hpp b/src/mbgl/style/style_parser.hpp
index 24fd4292a0..736cb9e9fa 100644
--- a/src/mbgl/style/style_parser.hpp
+++ b/src/mbgl/style/style_parser.hpp
@@ -69,17 +69,25 @@ private:
template <typename T>
bool parseOptionalProperty(const char *property_name, PropertyKey key, ClassProperties &klass, JSVal value);
template <typename T>
- bool parseOptionalProperty(const char *property_name, const std::vector<PropertyKey> &keys, ClassProperties &klass, JSVal value);
+ bool parseOptionalProperty(const char *property_name, PropertyKey key, ClassProperties &klass, JSVal value, const char *transition_name);
template <typename T>
bool setProperty(JSVal value, const char *property_name, PropertyKey key, ClassProperties &klass);
+ template <typename T>
+ bool setProperty(JSVal value, const char *property_name, PropertyKey key, ClassProperties &klass, JSVal transition);
template <typename T>
std::tuple<bool, T> parseProperty(JSVal value, const char *property_name);
+ template <typename T>
+ std::tuple<bool, T> parseProperty(JSVal value, const char *property_name, JSVal transition);
template <typename T>
- std::tuple<bool, Function<T>> parseFunction(JSVal value);
+ std::tuple<bool, Function<T>> parseFunction(JSVal value, const char *);
template <typename T>
- T parseFunctionArgument(JSVal value);
+ std::tuple<bool, PiecewiseConstantFunction<T>> parsePiecewiseConstantFunction(JSVal value, std::chrono::steady_clock::duration duration);
+ template <typename T>
+ std::tuple<bool, std::vector<std::pair<float, T>>> parseStops(JSVal value, const char *property_name);
+
+ std::tuple<bool,std::vector<float>> parseFloatArray(JSVal value);
FilterExpression parseFilter(JSVal);
diff --git a/src/mbgl/style/style_properties.hpp b/src/mbgl/style/style_properties.hpp
index c5149b2d1c..f50722542d 100644
--- a/src/mbgl/style/style_properties.hpp
+++ b/src/mbgl/style/style_properties.hpp
@@ -3,7 +3,7 @@
#include <mbgl/util/variant.hpp>
#include <mbgl/style/types.hpp>
-#include <mbgl/style/function_properties.hpp>
+#include <mbgl/style/piecewisefunction_properties.hpp>
#include <array>
#include <string>
@@ -21,7 +21,7 @@ struct FillProperties {
Color stroke_color = {{ 0, 0, 0, -1 }};
std::array<float, 2> translate = {{ 0, 0 }};
TranslateAnchorType translateAnchor = TranslateAnchorType::Map;
- std::string image;
+ Faded<std::string> image;
inline bool isVisible() const {
return opacity > 0 && (fill_color[3] > 0 || stroke_color[3] > 0);
@@ -37,9 +37,9 @@ struct LineProperties {
float width = 1;
float gap_width = 0;
float blur = 0;
- std::vector<float> dash_array;
+ Faded<std::vector<float>> dash_array;
float dash_line_width = 1;
- std::string image;
+ Faded<std::string> image;
inline bool isVisible() const {
return opacity > 0 && color[3] > 0 && width > 0;
@@ -96,7 +96,7 @@ struct BackgroundProperties {
inline BackgroundProperties() {}
float opacity = 1.0f;
Color color = {{ 0, 0, 0, 1 }};
- std::string image;
+ Faded<std::string> image;
};
typedef mapbox::util::variant<
diff --git a/src/mbgl/style/types.hpp b/src/mbgl/style/types.hpp
index 6149270170..78938a2823 100644
--- a/src/mbgl/style/types.hpp
+++ b/src/mbgl/style/types.hpp
@@ -11,6 +11,16 @@ namespace mbgl {
// Stores a premultiplied color, with all four channels ranging from 0..1
typedef std::array<float, 4> Color;
+
+template <typename T>
+struct Faded {
+ T from;
+ float fromScale;
+ T to;
+ float toScale;
+ float t;
+};
+
// -------------------------------------------------------------------------------------------------
enum class StyleLayerType : uint8_t {
diff --git a/src/mbgl/style/zoom_history.hpp b/src/mbgl/style/zoom_history.hpp
new file mode 100644
index 0000000000..2488687108
--- /dev/null
+++ b/src/mbgl/style/zoom_history.hpp
@@ -0,0 +1,38 @@
+#ifndef MBGL_STYLE_ZOOM_HISTORY
+#define MBGL_STYLE_ZOOM_HISTORY
+
+#include <chrono>
+#include <cmath>
+
+namespace mbgl {
+
+struct ZoomHistory {
+ float lastZoom;
+ float lastIntegerZoom;
+ std::chrono::steady_clock::time_point lastIntegerZoomTime;
+ bool first = true;
+
+ void update(float z, std::chrono::steady_clock::time_point now) {
+ if (first) {
+ first = false;
+
+ lastIntegerZoom = std::floor(z);
+ lastIntegerZoomTime = std::chrono::steady_clock::time_point(std::chrono::steady_clock::duration(0));
+ 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;
+ }
+};
+}
+
+#endif