summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Firebaugh <john.firebaugh@gmail.com>2018-07-13 18:14:12 -0700
committerJohn Firebaugh <john.firebaugh@gmail.com>2018-07-20 11:56:30 -0700
commitc8edbb0500cbf4baf1d5fdb0e63679539e166585 (patch)
tree750f3b72b9e3b1c91ddbc0541cfc64d7d80ffe71 /src
parent6d7072162b764c2432c010cd463a5a2c0093d606 (diff)
downloadqtlocation-mapboxgl-c8edbb0500cbf4baf1d5fdb0e63679539e166585.tar.gz
[core] Replace {Source,Camera,Composite}Function with PropertyExpression
Diffstat (limited to 'src')
-rw-r--r--src/mbgl/programs/symbol_program.cpp18
-rw-r--r--src/mbgl/programs/symbol_program.hpp42
-rw-r--r--src/mbgl/renderer/cross_faded_property_evaluator.cpp8
-rw-r--r--src/mbgl/renderer/cross_faded_property_evaluator.hpp2
-rw-r--r--src/mbgl/renderer/data_driven_property_evaluator.hpp19
-rw-r--r--src/mbgl/renderer/paint_property_binder.hpp33
-rw-r--r--src/mbgl/renderer/possibly_evaluated_property_value.hpp23
-rw-r--r--src/mbgl/renderer/property_evaluator.hpp2
-rw-r--r--src/mbgl/style/conversion/function.cpp297
-rw-r--r--src/mbgl/style/conversion/stringify.hpp12
-rw-r--r--src/mbgl/style/expression/find_zoom_curve.cpp14
-rw-r--r--src/mbgl/style/properties.hpp5
12 files changed, 216 insertions, 259 deletions
diff --git a/src/mbgl/programs/symbol_program.cpp b/src/mbgl/programs/symbol_program.cpp
index 84a7a53f1d..8df3b4ae3c 100644
--- a/src/mbgl/programs/symbol_program.cpp
+++ b/src/mbgl/programs/symbol_program.cpp
@@ -17,14 +17,20 @@ std::unique_ptr<SymbolSizeBinder> SymbolSizeBinder::create(const float tileZoom,
const style::DataDrivenPropertyValue<float>& sizeProperty,
const float defaultValue) {
return sizeProperty.match(
- [&] (const style::CompositeFunction<float>& function) -> std::unique_ptr<SymbolSizeBinder> {
- return std::make_unique<CompositeFunctionSymbolSizeBinder>(tileZoom, function, defaultValue);
- },
- [&] (const style::SourceFunction<float>& function) {
- return std::make_unique<SourceFunctionSymbolSizeBinder>(tileZoom, function, defaultValue);
+ [&] (const Undefined& value) -> std::unique_ptr<SymbolSizeBinder> {
+ return std::make_unique<ConstantSymbolSizeBinder>(tileZoom, value, defaultValue);
},
- [&] (const auto& value) -> std::unique_ptr<SymbolSizeBinder> {
+ [&] (float value) -> std::unique_ptr<SymbolSizeBinder> {
return std::make_unique<ConstantSymbolSizeBinder>(tileZoom, value, defaultValue);
+ },
+ [&] (const style::PropertyExpression<float>& expression) -> std::unique_ptr<SymbolSizeBinder> {
+ if (expression.isFeatureConstant()) {
+ return std::make_unique<ConstantSymbolSizeBinder>(tileZoom, expression, defaultValue);
+ } else if (expression.isZoomConstant()) {
+ return std::make_unique<SourceFunctionSymbolSizeBinder>(tileZoom, expression, defaultValue);
+ } else {
+ return std::make_unique<CompositeFunctionSymbolSizeBinder>(tileZoom, expression, defaultValue);
+ }
}
);
}
diff --git a/src/mbgl/programs/symbol_program.hpp b/src/mbgl/programs/symbol_program.hpp
index 51f9a48f7f..35b5821918 100644
--- a/src/mbgl/programs/symbol_program.hpp
+++ b/src/mbgl/programs/symbol_program.hpp
@@ -143,13 +143,13 @@ public:
ConstantSymbolSizeBinder(const float /*tileZoom*/, const style::Undefined&, const float defaultValue)
: layoutSize(defaultValue) {}
- ConstantSymbolSizeBinder(const float tileZoom, const style::CameraFunction<float>& function_, const float /*defaultValue*/)
- : layoutSize(function_.evaluate(tileZoom + 1)),
- function(function_) {
- const Range<float> zoomLevels = function_.getCoveringStops(tileZoom, tileZoom + 1);
+ ConstantSymbolSizeBinder(const float tileZoom, const style::PropertyExpression<float>& expression_, const float /*defaultValue*/)
+ : layoutSize(expression_.evaluate(tileZoom + 1)),
+ expression(expression_) {
+ const Range<float> zoomLevels = expression_.getCoveringStops(tileZoom, tileZoom + 1);
coveringRanges = std::make_tuple(
zoomLevels,
- Range<float> { function_.evaluate(zoomLevels.min), function_.evaluate(zoomLevels.max) }
+ Range<float> { expression_.evaluate(zoomLevels.min), expression_.evaluate(zoomLevels.max) }
);
}
@@ -157,7 +157,7 @@ public:
ZoomEvaluatedSize evaluateForZoom(float currentZoom) const override {
float size = layoutSize;
- bool isZoomConstant = !(coveringRanges || function);
+ bool isZoomConstant = !(coveringRanges || expression);
if (coveringRanges) {
// Even though we could get the exact value of the camera function
// at z = currentZoom, we intentionally do not: instead, we interpolate
@@ -167,12 +167,12 @@ public:
const Range<float>& zoomLevels = std::get<0>(*coveringRanges);
const Range<float>& sizeLevels = std::get<1>(*coveringRanges);
float t = util::clamp(
- function->interpolationFactor(zoomLevels, currentZoom),
+ expression->interpolationFactor(zoomLevels, currentZoom),
0.0f, 1.0f
);
size = sizeLevels.min + t * (sizeLevels.max - sizeLevels.min);
- } else if (function) {
- size = function->evaluate(currentZoom);
+ } else if (expression) {
+ size = expression->evaluate(currentZoom);
}
const float unused = 0.0f;
@@ -181,7 +181,7 @@ public:
float layoutSize;
optional<std::tuple<Range<float>, Range<float>>> coveringRanges;
- optional<style::CameraFunction<float>> function;
+ optional<style::PropertyExpression<float>> expression;
};
class SourceFunctionSymbolSizeBinder final : public SymbolSizeBinder {
@@ -190,13 +190,13 @@ public:
using VertexVector = gl::VertexVector<Vertex>;
using VertexBuffer = gl::VertexBuffer<Vertex>;
- SourceFunctionSymbolSizeBinder(const float /*tileZoom*/, const style::SourceFunction<float>& function_, const float defaultValue_)
- : function(function_),
+ SourceFunctionSymbolSizeBinder(const float /*tileZoom*/, style::PropertyExpression<float> expression_, const float defaultValue_)
+ : expression(std::move(expression_)),
defaultValue(defaultValue_) {
}
Range<float> getVertexSizeData(const GeometryTileFeature& feature) override {
- const float size = function.evaluate(feature, defaultValue);
+ const float size = expression.evaluate(feature, defaultValue);
return { size, size };
};
@@ -205,30 +205,30 @@ public:
return { true, false, unused, unused, unused };
}
- style::SourceFunction<float> function;
+ style::PropertyExpression<float> expression;
const float defaultValue;
};
class CompositeFunctionSymbolSizeBinder final : public SymbolSizeBinder {
public:
- CompositeFunctionSymbolSizeBinder(const float tileZoom, const style::CompositeFunction<float>& function_, const float defaultValue_)
- : function(function_),
+ CompositeFunctionSymbolSizeBinder(const float tileZoom, style::PropertyExpression<float> expression_, const float defaultValue_)
+ : expression(std::move(expression_)),
defaultValue(defaultValue_),
layoutZoom(tileZoom + 1),
- coveringZoomStops(function.getCoveringStops(tileZoom, tileZoom + 1))
+ coveringZoomStops(expression.getCoveringStops(tileZoom, tileZoom + 1))
{}
Range<float> getVertexSizeData(const GeometryTileFeature& feature) override {
return {
- function.evaluate(coveringZoomStops.min, feature, defaultValue),
- function.evaluate(coveringZoomStops.max, feature, defaultValue)
+ expression.evaluate(coveringZoomStops.min, feature, defaultValue),
+ expression.evaluate(coveringZoomStops.max, feature, defaultValue)
};
};
ZoomEvaluatedSize evaluateForZoom(float currentZoom) const override {
float sizeInterpolationT = util::clamp(
- function.interpolationFactor(coveringZoomStops, currentZoom),
+ expression.interpolationFactor(coveringZoomStops, currentZoom),
0.0f, 1.0f
);
@@ -236,7 +236,7 @@ public:
return { false, false, sizeInterpolationT, unused, unused };
}
- style::CompositeFunction<float> function;
+ style::PropertyExpression<float> expression;
const float defaultValue;
float layoutZoom;
Range<float> coveringZoomStops;
diff --git a/src/mbgl/renderer/cross_faded_property_evaluator.cpp b/src/mbgl/renderer/cross_faded_property_evaluator.cpp
index 4dff9dbf12..9a7af8636c 100644
--- a/src/mbgl/renderer/cross_faded_property_evaluator.cpp
+++ b/src/mbgl/renderer/cross_faded_property_evaluator.cpp
@@ -16,10 +16,10 @@ Faded<T> CrossFadedPropertyEvaluator<T>::operator()(const T& constant) const {
}
template <typename T>
-Faded<T> CrossFadedPropertyEvaluator<T>::operator()(const style::CameraFunction<T>& function) const {
- return calculate(function.evaluate(parameters.z - 1.0f),
- function.evaluate(parameters.z),
- function.evaluate(parameters.z + 1.0f));
+Faded<T> CrossFadedPropertyEvaluator<T>::operator()(const style::PropertyExpression<T>& expression) const {
+ return calculate(expression.evaluate(parameters.z - 1.0f),
+ expression.evaluate(parameters.z),
+ expression.evaluate(parameters.z + 1.0f));
}
template <typename T>
diff --git a/src/mbgl/renderer/cross_faded_property_evaluator.hpp b/src/mbgl/renderer/cross_faded_property_evaluator.hpp
index 40ecba5d93..1d17c5eb2f 100644
--- a/src/mbgl/renderer/cross_faded_property_evaluator.hpp
+++ b/src/mbgl/renderer/cross_faded_property_evaluator.hpp
@@ -27,7 +27,7 @@ public:
Faded<T> operator()(const style::Undefined&) const;
Faded<T> operator()(const T& constant) const;
- Faded<T> operator()(const style::CameraFunction<T>&) const;
+ Faded<T> operator()(const style::PropertyExpression<T>&) const;
private:
Faded<T> calculate(const T& min, const T& mid, const T& max) const;
diff --git a/src/mbgl/renderer/data_driven_property_evaluator.hpp b/src/mbgl/renderer/data_driven_property_evaluator.hpp
index 79ecd0d495..f9452cc572 100644
--- a/src/mbgl/renderer/data_driven_property_evaluator.hpp
+++ b/src/mbgl/renderer/data_driven_property_evaluator.hpp
@@ -23,21 +23,18 @@ public:
return ResultType(constant);
}
- ResultType operator()(const style::CameraFunction<T>& function) const {
- if (!parameters.useIntegerZoom) {
- return ResultType(function.evaluate(parameters.z));
+ ResultType operator()(const style::PropertyExpression<T>& expression) const {
+ if (!expression.isFeatureConstant()) {
+ auto returnExpression = expression;
+ returnExpression.useIntegerZoom = parameters.useIntegerZoom;
+ return ResultType(returnExpression);
+ } else if (!parameters.useIntegerZoom) {
+ return ResultType(expression.evaluate(parameters.z));
} else {
- return ResultType(function.evaluate(floor(parameters.z)));
+ return ResultType(expression.evaluate(floor(parameters.z)));
}
}
- template <class Function>
- ResultType operator()(const Function& function) const {
- auto returnFunction = function;
- returnFunction.useIntegerZoom = parameters.useIntegerZoom;
- return ResultType(returnFunction);
- }
-
private:
const PropertyEvaluationParameters& parameters;
T defaultValue;
diff --git a/src/mbgl/renderer/paint_property_binder.hpp b/src/mbgl/renderer/paint_property_binder.hpp
index 3a49882f12..aade672ae7 100644
--- a/src/mbgl/renderer/paint_property_binder.hpp
+++ b/src/mbgl/renderer/paint_property_binder.hpp
@@ -130,13 +130,13 @@ public:
using Attribute = ZoomInterpolatedAttributeType<A>;
using AttributeBinding = typename Attribute::Binding;
- SourceFunctionPaintPropertyBinder(style::SourceFunction<T> function_, T defaultValue_)
- : function(std::move(function_)),
+ SourceFunctionPaintPropertyBinder(style::PropertyExpression<T> expression_, T defaultValue_)
+ : expression(std::move(expression_)),
defaultValue(std::move(defaultValue_)) {
}
void populateVertexVector(const GeometryTileFeature& feature, std::size_t length) override {
- auto evaluated = function.evaluate(feature, defaultValue);
+ auto evaluated = expression.evaluate(feature, defaultValue);
this->statistics.add(evaluated);
auto value = attributeValue(evaluated);
for (std::size_t i = vertexVector.vertexSize(); i < length; ++i) {
@@ -170,7 +170,7 @@ public:
}
private:
- style::SourceFunction<T> function;
+ style::PropertyExpression<T> expression;
T defaultValue;
gl::VertexVector<BaseVertex> vertexVector;
optional<gl::VertexBuffer<BaseVertex>> vertexBuffer;
@@ -187,14 +187,14 @@ public:
using AttributeBinding = typename Attribute::Binding;
using Vertex = gl::detail::Vertex<Attribute>;
- CompositeFunctionPaintPropertyBinder(style::CompositeFunction<T> function_, float zoom, T defaultValue_)
- : function(std::move(function_)),
+ CompositeFunctionPaintPropertyBinder(style::PropertyExpression<T> expression_, float zoom, T defaultValue_)
+ : expression(std::move(expression_)),
defaultValue(std::move(defaultValue_)),
zoomRange({zoom, zoom + 1}) {
}
void populateVertexVector(const GeometryTileFeature& feature, std::size_t length) override {
- Range<T> range = function.evaluate(zoomRange, feature, defaultValue);
+ Range<T> range = expression.evaluate(zoomRange, feature, defaultValue);
this->statistics.add(range.min);
this->statistics.add(range.max);
AttributeValue value = zoomInterpolatedAttributeValue(
@@ -218,10 +218,10 @@ public:
}
float interpolationFactor(float currentZoom) const override {
- if (function.useIntegerZoom) {
- return function.interpolationFactor(zoomRange, std::floor(currentZoom));
+ if (expression.useIntegerZoom) {
+ return expression.interpolationFactor(zoomRange, std::floor(currentZoom));
} else {
- return function.interpolationFactor(zoomRange, currentZoom);
+ return expression.interpolationFactor(zoomRange, currentZoom);
}
}
@@ -235,7 +235,7 @@ public:
}
private:
- style::CompositeFunction<T> function;
+ style::PropertyExpression<T> expression;
T defaultValue;
Range<float> zoomRange;
gl::VertexVector<Vertex> vertexVector;
@@ -249,11 +249,12 @@ PaintPropertyBinder<T, A>::create(const PossiblyEvaluatedPropertyValue<T>& value
[&] (const T& constant) -> std::unique_ptr<PaintPropertyBinder<T, A>> {
return std::make_unique<ConstantPaintPropertyBinder<T, A>>(constant);
},
- [&] (const style::SourceFunction<T>& function) {
- return std::make_unique<SourceFunctionPaintPropertyBinder<T, A>>(function, defaultValue);
- },
- [&] (const style::CompositeFunction<T>& function) {
- return std::make_unique<CompositeFunctionPaintPropertyBinder<T, A>>(function, zoom, defaultValue);
+ [&] (const style::PropertyExpression<T>& expression) -> std::unique_ptr<PaintPropertyBinder<T, A>> {
+ if (expression.isZoomConstant()) {
+ return std::make_unique<SourceFunctionPaintPropertyBinder<T, A>>(expression, defaultValue);
+ } else {
+ return std::make_unique<CompositeFunctionPaintPropertyBinder<T, A>>(expression, zoom, defaultValue);
+ }
}
);
}
diff --git a/src/mbgl/renderer/possibly_evaluated_property_value.hpp b/src/mbgl/renderer/possibly_evaluated_property_value.hpp
index e662d5dfb1..f2d265f2f7 100644
--- a/src/mbgl/renderer/possibly_evaluated_property_value.hpp
+++ b/src/mbgl/renderer/possibly_evaluated_property_value.hpp
@@ -1,7 +1,6 @@
#pragma once
-#include <mbgl/style/function/source_function.hpp>
-#include <mbgl/style/function/composite_function.hpp>
+#include <mbgl/style/property_expression.hpp>
#include <mbgl/util/interpolate.hpp>
#include <mbgl/util/variant.hpp>
@@ -12,8 +11,7 @@ class PossiblyEvaluatedPropertyValue {
private:
using Value = variant<
T,
- style::SourceFunction<T>,
- style::CompositeFunction<T>>;
+ style::PropertyExpression<T>>;
Value value;
@@ -45,17 +43,14 @@ public:
template <class Feature>
T evaluate(const Feature& feature, float zoom, T defaultValue) const {
return this->match(
- [&] (const T& constant_) { return constant_; },
- [&] (const style::SourceFunction<T>& function) {
- return function.evaluate(feature, defaultValue);
- },
- [&] (const style::CompositeFunction<T>& function) {
- if (useIntegerZoom) {
- return function.evaluate(floor(zoom), feature, defaultValue);
- } else {
- return function.evaluate(zoom, feature, defaultValue);
- }
+ [&] (const T& constant_) { return constant_; },
+ [&] (const style::PropertyExpression<T>& expression) {
+ if (useIntegerZoom) {
+ return expression.evaluate(floor(zoom), feature, defaultValue);
+ } else {
+ return expression.evaluate(zoom, feature, defaultValue);
}
+ }
);
}
diff --git a/src/mbgl/renderer/property_evaluator.hpp b/src/mbgl/renderer/property_evaluator.hpp
index 3ac0573920..03e0f5a002 100644
--- a/src/mbgl/renderer/property_evaluator.hpp
+++ b/src/mbgl/renderer/property_evaluator.hpp
@@ -16,7 +16,7 @@ public:
T operator()(const style::Undefined&) const { return defaultValue; }
T operator()(const T& constant) const { return constant; }
- T operator()(const style::CameraFunction<T>& fn) const { return fn.evaluate(parameters.z); }
+ T operator()(const style::PropertyExpression<T>& fn) const { return fn.evaluate(parameters.z); }
private:
const PropertyEvaluationParameters& parameters;
diff --git a/src/mbgl/style/conversion/function.cpp b/src/mbgl/style/conversion/function.cpp
index 64adf522a1..39e061d75a 100644
--- a/src/mbgl/style/conversion/function.cpp
+++ b/src/mbgl/style/conversion/function.cpp
@@ -66,29 +66,6 @@ static bool interpolatable(type::Type type) {
);
}
-static FunctionType functionType(type::Type type, const Convertible& value) {
- auto typeValue = objectMember(value, "type");
- if (!typeValue) {
- return interpolatable(type) ? FunctionType::Exponential : FunctionType::Interval;
- }
-
- optional<std::string> string = toString(*typeValue);
- if (!string) {
- return FunctionType::Invalid;
- }
-
- if (*string == "interval")
- return FunctionType::Interval;
- if (*string == "exponential" && interpolatable(type))
- return FunctionType::Exponential;
- if (*string == "categorical")
- return FunctionType::Categorical;
- if (*string == "identity")
- return FunctionType::Identity;
-
- return FunctionType::Invalid;
-}
-
static optional<std::unique_ptr<Expression>> convertLiteral(type::Type type, const Convertible& value, Error& error) {
return type.match(
[&] (const type::NumberType&) -> optional<std::unique_ptr<Expression>> {
@@ -426,106 +403,16 @@ static optional<std::unique_ptr<Expression>> convertCategoricalFunction(type::Ty
return {};
}
-optional<std::unique_ptr<Expression>> convertCameraFunctionToExpression(type::Type type,
- const Convertible& value,
- Error& error) {
- if (!isObject(value)) {
- error = { "function must be an object" };
- return {};
- }
-
- switch (functionType(type, value)) {
- case FunctionType::Interval:
- return convertIntervalFunction(type, value, error, zoom());
- case FunctionType::Exponential:
- return convertExponentialFunction(type, value, error, zoom());
- default:
- error = { "unsupported function type" };
- return {};
- }
-}
-
-optional<std::unique_ptr<Expression>> convertSourceFunctionToExpression(type::Type type,
- const Convertible& value,
- Error& error) {
- if (!isObject(value)) {
- error = { "function must be an object" };
- return {};
- }
-
- auto propertyValue = objectMember(value, "property");
- if (!propertyValue) {
- error = { "function must specify property" };
- return {};
- }
-
- auto property = toString(*propertyValue);
- if (!property) {
- error = { "function property must be a string" };
- return {};
- }
-
- switch (functionType(type, value)) {
- case FunctionType::Interval:
- return convertIntervalFunction(type, value, error, number(get(literal(*property))));
- case FunctionType::Exponential:
- return convertExponentialFunction(type, value, error, number(get(literal(*property))));
- case FunctionType::Categorical:
- return convertCategoricalFunction(type, value, error, *property);
- case FunctionType::Identity:
- return type.match(
- [&] (const type::StringType&) -> optional<std::unique_ptr<Expression>> {
- return string(get(literal(*property)));
- },
- [&] (const type::NumberType&) -> optional<std::unique_ptr<Expression>> {
- return number(get(literal(*property)));
- },
- [&] (const type::BooleanType&) -> optional<std::unique_ptr<Expression>> {
- return boolean(get(literal(*property)));
- },
- [&] (const type::ColorType&) -> optional<std::unique_ptr<Expression>> {
- return toColor(get(literal(*property)));
- },
- [&] (const type::Array& array) -> optional<std::unique_ptr<Expression>> {
- return std::unique_ptr<Expression>(
- std::make_unique<ArrayAssertion>(array, get(literal(*property))));
- },
- [&] (const auto&) -> optional<std::unique_ptr<Expression>> {
- assert(false); // No properties use this type.
- return {};
- }
- );
- default:
- error = { "unsupported function type" };
- return {};
- }
-}
-
-template <class T>
+template <class T, class Fn>
optional<std::unique_ptr<Expression>> composite(type::Type type,
const Convertible& value,
Error& error,
- std::unique_ptr<Expression> (*makeInnerExpression) (type::Type type,
- double base,
- const std::string& property,
- std::map<T, std::unique_ptr<Expression>>)) {
- auto propertyValue = objectMember(value, "property");
- if (!propertyValue) {
- error = { "function must specify property" };
- return {};
- }
-
+ const Fn& makeInnerExpression) {
auto base = convertBase(value, error);
if (!base) {
return {};
}
- auto propertyString = toString(*propertyValue);
- if (!propertyString) {
- error = { "function property must be a string" };
- return {};
- }
-
auto stopsValue = objectMember(value, "stops");
// Checked by caller.
@@ -587,7 +474,7 @@ optional<std::unique_ptr<Expression>> composite(type::Type type,
std::map<double, std::unique_ptr<Expression>> stops;
for (auto& e : map) {
- stops.emplace(e.first, makeInnerExpression(type, *base, *propertyString, std::move(e.second)));
+ stops.emplace(e.first, makeInnerExpression(type, *base, std::move(e.second)));
}
if (interpolatable(type)) {
@@ -597,14 +484,83 @@ optional<std::unique_ptr<Expression>> composite(type::Type type,
}
}
-optional<std::unique_ptr<Expression>> convertCompositeFunctionToExpression(type::Type type,
- const Convertible& value,
- Error& err) {
+optional<std::unique_ptr<Expression>> convertFunctionToExpression(type::Type type,
+ const Convertible& value,
+ Error& err) {
if (!isObject(value)) {
err = { "function must be an object" };
return {};
}
+ FunctionType functionType = FunctionType::Invalid;
+
+ auto typeValue = objectMember(value, "type");
+ if (!typeValue) {
+ functionType = interpolatable(type) ? FunctionType::Exponential : FunctionType::Interval;
+ } else {
+ optional<std::string> string = toString(*typeValue);
+ if (string) {
+ if (*string == "interval")
+ functionType = FunctionType::Interval;
+ if (*string == "exponential" && interpolatable(type))
+ functionType = FunctionType::Exponential;
+ if (*string == "categorical")
+ functionType = FunctionType::Categorical;
+ if (*string == "identity")
+ functionType = FunctionType::Identity;
+ }
+ }
+
+ if (!objectMember(value, "property")) {
+ // Camera function.
+ switch (functionType) {
+ case FunctionType::Interval:
+ return convertIntervalFunction(type, value, err, zoom());
+ case FunctionType::Exponential:
+ return convertExponentialFunction(type, value, err, zoom());
+ default:
+ err = { "unsupported function type" };
+ return {};
+ }
+ }
+
+ auto propertyValue = objectMember(value, "property");
+ if (!propertyValue) {
+ err = { "function must specify property" };
+ return {};
+ }
+
+ auto property = toString(*propertyValue);
+ if (!property) {
+ err = { "function property must be a string" };
+ return {};
+ }
+
+ if (functionType == FunctionType::Identity) {
+ return type.match(
+ [&] (const type::StringType&) -> optional<std::unique_ptr<Expression>> {
+ return string(get(literal(*property)));
+ },
+ [&] (const type::NumberType&) -> optional<std::unique_ptr<Expression>> {
+ return number(get(literal(*property)));
+ },
+ [&] (const type::BooleanType&) -> optional<std::unique_ptr<Expression>> {
+ return boolean(get(literal(*property)));
+ },
+ [&] (const type::ColorType&) -> optional<std::unique_ptr<Expression>> {
+ return toColor(get(literal(*property)));
+ },
+ [&] (const type::Array& array) -> optional<std::unique_ptr<Expression>> {
+ return std::unique_ptr<Expression>(
+ std::make_unique<ArrayAssertion>(array, get(literal(*property))));
+ },
+ [&] (const auto&) -> optional<std::unique_ptr<Expression>> {
+ assert(false); // No properties use this type.
+ return {};
+ }
+ );
+ }
+
auto stopsValue = objectMember(value, "stops");
if (!stopsValue) {
err = { "function value must specify stops" };
@@ -636,62 +592,73 @@ optional<std::unique_ptr<Expression>> convertCompositeFunctionToExpression(type:
const auto& stop = arrayMember(first, 0);
if (!isObject(stop)) {
- err = { "stop must be an object" };
- return {};
- }
-
- auto sourceValue = objectMember(stop, "value");
- if (!sourceValue) {
- err = { "stop must specify value" };
- return {};
- }
-
- if (toBool(*sourceValue)) {
- switch (functionType(type, value)) {
- case FunctionType::Categorical:
- return composite<bool>(type, value, err, [] (type::Type type_, double, const std::string& property, std::map<bool, std::unique_ptr<Expression>> stops) {
- return categorical<bool>(type_, property, std::move(stops));
- });
- default:
- err = { "unsupported function type" };
- return {};
- }
- }
-
- if (toNumber(*sourceValue)) {
- switch (functionType(type, value)) {
+ // Source function.
+ switch (functionType) {
case FunctionType::Interval:
- return composite<double>(type, value, err, [] (type::Type type_, double, const std::string& property, std::map<double, std::unique_ptr<Expression>> stops) {
- return step(type_, number(get(literal(property))), std::move(stops));
- });
+ return convertIntervalFunction(type, value, err, number(get(literal(*property))));
case FunctionType::Exponential:
- return composite<double>(type, value, err, [] (type::Type type_, double base, const std::string& property, std::map<double, std::unique_ptr<Expression>> stops) {
- return interpolate(type_, exponential(base), number(get(literal(property))), std::move(stops));
- });
+ return convertExponentialFunction(type, value, err, number(get(literal(*property))));
case FunctionType::Categorical:
- return composite<int64_t>(type, value, err, [] (type::Type type_, double, const std::string& property, std::map<int64_t, std::unique_ptr<Expression>> stops) {
- return categorical<int64_t>(type_, property, std::move(stops));
- });
+ return convertCategoricalFunction(type, value, err, *property);
default:
err = { "unsupported function type" };
return {};
}
- }
-
- if (toString(*sourceValue)) {
- switch (functionType(type, value)) {
- case FunctionType::Categorical:
- return composite<std::string>(type, value, err, [] (type::Type type_, double, const std::string& property, std::map<std::string, std::unique_ptr<Expression>> stops) {
- return categorical<std::string>(type_, property, std::move(stops));
- });
- default:
- err = { "unsupported function type" };
+ } else {
+ // Composite function.
+ auto sourceValue = objectMember(stop, "value");
+ if (!sourceValue) {
+ err = { "stop must specify value" };
return {};
}
- }
- err = { "stop domain value must be a number, string, or boolean" };
- return {};
+ if (toBool(*sourceValue)) {
+ switch (functionType) {
+ case FunctionType::Categorical:
+ return composite<bool>(type, value, err, [&] (type::Type type_, double, std::map<bool, std::unique_ptr<Expression>> stops) {
+ return categorical<bool>(type_, *property, std::move(stops));
+ });
+ default:
+ err = { "unsupported function type" };
+ return {};
+ }
+ }
+
+ if (toNumber(*sourceValue)) {
+ switch (functionType) {
+ case FunctionType::Interval:
+ return composite<double>(type, value, err, [&] (type::Type type_, double, std::map<double, std::unique_ptr<Expression>> stops) {
+ return step(type_, number(get(literal(*property))), std::move(stops));
+ });
+ case FunctionType::Exponential:
+ return composite<double>(type, value, err, [&] (type::Type type_, double base, std::map<double, std::unique_ptr<Expression>> stops) {
+ return interpolate(type_, exponential(base), number(get(literal(*property))), std::move(stops));
+ });
+ case FunctionType::Categorical:
+ return composite<int64_t>(type, value, err, [&] (type::Type type_, double, std::map<int64_t, std::unique_ptr<Expression>> stops) {
+ return categorical<int64_t>(type_, *property, std::move(stops));
+ });
+ default:
+ err = { "unsupported function type" };
+ return {};
+ }
+ }
+
+ if (toString(*sourceValue)) {
+ switch (functionType) {
+ case FunctionType::Categorical:
+ return composite<std::string>(type, value, err, [&] (type::Type type_, double, std::map<std::string, std::unique_ptr<Expression>> stops) {
+ return categorical<std::string>(type_, *property, std::move(stops));
+ });
+ default:
+ err = { "unsupported function type" };
+ return {};
+ }
+ }
+
+ err = { "stop domain value must be a number, string, or boolean" };
+ return {};
+ }
}
} // namespace conversion
diff --git a/src/mbgl/style/conversion/stringify.hpp b/src/mbgl/style/conversion/stringify.hpp
index 74171763a0..77a39c51f9 100644
--- a/src/mbgl/style/conversion/stringify.hpp
+++ b/src/mbgl/style/conversion/stringify.hpp
@@ -138,17 +138,7 @@ void stringify(Writer& writer, const Undefined&) {
}
template <class Writer, class T>
-void stringify(Writer& writer, const CameraFunction<T>& fn) {
- stringify(writer, fn.getExpression().serialize());
-}
-
-template <class Writer, class T>
-void stringify(Writer& writer, const SourceFunction<T>& fn) {
- stringify(writer, fn.getExpression().serialize());
-}
-
-template <class Writer, class T>
-void stringify(Writer& writer, const CompositeFunction<T>& fn) {
+void stringify(Writer& writer, const PropertyExpression<T>& fn) {
stringify(writer, fn.getExpression().serialize());
}
diff --git a/src/mbgl/style/expression/find_zoom_curve.cpp b/src/mbgl/style/expression/find_zoom_curve.cpp
index ce8487a3af..1e0a936605 100644
--- a/src/mbgl/style/expression/find_zoom_curve.cpp
+++ b/src/mbgl/style/expression/find_zoom_curve.cpp
@@ -2,6 +2,7 @@
#include <mbgl/style/expression/compound_expression.hpp>
#include <mbgl/style/expression/let.hpp>
#include <mbgl/style/expression/coalesce.hpp>
+#include <mbgl/style/expression/is_constant.hpp>
#include <mbgl/util/variant.hpp>
#include <mbgl/util/optional.hpp>
@@ -59,14 +60,17 @@ optional<variant<const Interpolate*, const Step*, ParsingError>> findZoomCurve(c
return result;
}
-variant<const Interpolate*, const Step*> findZoomCurveChecked(const expression::Expression* e) {
+variant<std::nullptr_t, const Interpolate*, const Step*> findZoomCurveChecked(const expression::Expression* e) {
+ if (isZoomConstant(*e)) {
+ return nullptr;
+ }
return findZoomCurve(e)->match(
- [](const ParsingError&) -> variant<const Interpolate*, const Step*> {
+ [](const ParsingError&) -> variant<std::nullptr_t, const Interpolate*, const Step*> {
assert(false);
- return {};
+ return nullptr;
},
- [](auto zoomCurve) -> variant<const Interpolate*, const Step*> {
- return {std::move(zoomCurve)};
+ [](auto zoomCurve) -> variant<std::nullptr_t, const Interpolate*, const Step*> {
+ return zoomCurve;
}
);
}
diff --git a/src/mbgl/style/properties.hpp b/src/mbgl/style/properties.hpp
index dfcf7993a7..9206e96982 100644
--- a/src/mbgl/style/properties.hpp
+++ b/src/mbgl/style/properties.hpp
@@ -154,10 +154,7 @@ public:
[&] (const T& t) {
return t;
},
- [&] (const SourceFunction<T>& t) {
- return t.evaluate(feature, defaultValue);
- },
- [&] (const CompositeFunction<T>& t) {
+ [&] (const PropertyExpression<T>& t) {
return t.evaluate(z, feature, defaultValue);
});
}