diff options
-rw-r--r-- | platform/node/test/ignores.json | 8 | ||||
-rw-r--r-- | src/mbgl/style/conversion/function.cpp | 83 |
2 files changed, 63 insertions, 28 deletions
diff --git a/platform/node/test/ignores.json b/platform/node/test/ignores.json index 4cdd7795e6..ec79ed8987 100644 --- a/platform/node/test/ignores.json +++ b/platform/node/test/ignores.json @@ -15,20 +15,12 @@ "expression-tests/legacy/categorical/string": "https://github.com/mapbox/mapbox-gl-native/issues/12747", "expression-tests/legacy/categorical/string-default": "https://github.com/mapbox/mapbox-gl-native/issues/12747", "expression-tests/legacy/categorical/tokens": "https://github.com/mapbox/mapbox-gl-native/issues/12747", - "expression-tests/legacy/exponential/array-default": "https://github.com/mapbox/mapbox-gl-native/issues/12747", - "expression-tests/legacy/exponential/color-default": "https://github.com/mapbox/mapbox-gl-native/issues/12747", "expression-tests/legacy/exponential/color-hcl": "https://github.com/mapbox/mapbox-gl-native/issues/12747", "expression-tests/legacy/exponential/color-lab": "https://github.com/mapbox/mapbox-gl-native/issues/12747", - "expression-tests/legacy/exponential/composite-default": "https://github.com/mapbox/mapbox-gl-native/issues/12747", - "expression-tests/legacy/exponential/number-default": "https://github.com/mapbox/mapbox-gl-native/issues/12747", "expression-tests/legacy/identity/color-default": "https://github.com/mapbox/mapbox-gl-native/issues/12747", "expression-tests/legacy/identity/enum-default": "https://github.com/mapbox/mapbox-gl-native/issues/12747", - "expression-tests/legacy/interval/array-default": "https://github.com/mapbox/mapbox-gl-native/issues/12747", - "expression-tests/legacy/interval/color-default": "https://github.com/mapbox/mapbox-gl-native/issues/12747", "expression-tests/legacy/interval/composite": "https://github.com/mapbox/mapbox-gl-native/issues/12747", "expression-tests/legacy/interval/composite-default": "https://github.com/mapbox/mapbox-gl-native/issues/12747", - "expression-tests/legacy/interval/number-default": "https://github.com/mapbox/mapbox-gl-native/issues/12747", - "expression-tests/legacy/interval/string-default": "https://github.com/mapbox/mapbox-gl-native/issues/12747", "expression-tests/legacy/interval/tokens-zoom": "https://github.com/mapbox/mapbox-gl-native/issues/12747", "query-tests/geometry/multilinestring": "needs investigation", "query-tests/geometry/multipolygon": "needs investigation", diff --git a/src/mbgl/style/conversion/function.cpp b/src/mbgl/style/conversion/function.cpp index 33ed7c9856..f00aa670b1 100644 --- a/src/mbgl/style/conversion/function.cpp +++ b/src/mbgl/style/conversion/function.cpp @@ -2,6 +2,7 @@ #include <mbgl/style/conversion/position.hpp> #include <mbgl/style/conversion_impl.hpp> #include <mbgl/style/expression/dsl.hpp> +#include <mbgl/style/expression/dsl_impl.hpp> #include <mbgl/style/expression/step.hpp> #include <mbgl/style/expression/interpolate.hpp> #include <mbgl/style/expression/match.hpp> @@ -474,23 +475,43 @@ std::unique_ptr<Expression> categorical<bool>(type::Type type, const std::string return std::make_unique<Case>(type, std::move(trueBranch), std::move(falseCase)); } +static std::unique_ptr<Expression> numberOrDefault(type::Type type, + std::unique_ptr<Expression> get, + std::unique_ptr<Expression> expr, + optional<std::unique_ptr<Expression>> def) { + if (!def) { + return expr; + } + + std::vector<Case::Branch> branches; + branches.emplace_back(eq(compound("typeof", std::move(get)), literal("number")), + std::move(expr)); + return std::make_unique<Case>(type, std::move(branches), std::move(*def)); +} + static optional<std::unique_ptr<Expression>> convertIntervalFunction(type::Type type, const Convertible& value, Error& error, - std::unique_ptr<Expression> input, + std::function<std::unique_ptr<Expression> (bool)> makeInput, + optional<std::unique_ptr<Expression>> def, bool convertTokens = false) { auto stops = convertStops(type, value, error, convertTokens); if (!stops) { return nullopt; } omitFirstStop(*stops); - return step(type, std::move(input), std::move(*stops)); + + return numberOrDefault(type, + makeInput(false), + step(type, makeInput(true), std::move(*stops)), + std::move(def)); } static optional<std::unique_ptr<Expression>> convertExponentialFunction(type::Type type, const Convertible& value, Error& error, - std::unique_ptr<Expression> input, + std::function<std::unique_ptr<Expression> (bool)> makeInput, + optional<std::unique_ptr<Expression>> def, bool convertTokens = false) { auto stops = convertStops(type, value, error, convertTokens); if (!stops) { @@ -500,7 +521,11 @@ static optional<std::unique_ptr<Expression>> convertExponentialFunction(type::Ty if (!base) { return nullopt; } - return interpolate(type, exponential(*base), std::move(input), std::move(*stops)); + + return numberOrDefault(type, + makeInput(false), + interpolate(type, exponential(*base), makeInput(true), std::move(*stops)), + std::move(def)); } static optional<std::unique_ptr<Expression>> convertCategoricalFunction(type::Type type, @@ -672,18 +697,21 @@ optional<std::unique_ptr<Expression>> convertFunctionToExpression(type::Type typ } } - optional<std::unique_ptr<Expression>> defaultExpr; - if (objectMember(value, "default")) { - defaultExpr = convertLiteral(type, *objectMember(value, "default"), err); - } + auto defaultExpr = [&]() -> optional<std::unique_ptr<Expression>> { + auto member = objectMember(value, "default"); + if (member) { + return convertLiteral(type, *member, err); + } + return {}; + }; if (!objectMember(value, "property")) { // Camera function. switch (functionType) { case FunctionType::Interval: - return convertIntervalFunction(type, value, err, zoom(), convertTokens); + return convertIntervalFunction(type, value, err, [](bool) { return zoom(); }, defaultExpr(), convertTokens); case FunctionType::Exponential: - return convertExponentialFunction(type, value, err, zoom(), convertTokens); + return convertExponentialFunction(type, value, err, [](bool) { return zoom(); }, defaultExpr(), convertTokens); default: err.message = "unsupported function type"; return nullopt; @@ -705,22 +733,22 @@ optional<std::unique_ptr<Expression>> convertFunctionToExpression(type::Type typ if (functionType == FunctionType::Identity) { return type.match( [&] (const type::StringType&) -> optional<std::unique_ptr<Expression>> { - return string(get(literal(*property)), std::move(defaultExpr)); + return string(get(literal(*property)), defaultExpr()); }, [&] (const type::NumberType&) -> optional<std::unique_ptr<Expression>> { - return number(get(literal(*property)), std::move(defaultExpr)); + return number(get(literal(*property)), defaultExpr()); }, [&] (const type::BooleanType&) -> optional<std::unique_ptr<Expression>> { - return boolean(get(literal(*property)), std::move(defaultExpr)); + return boolean(get(literal(*property)), defaultExpr()); }, [&] (const type::ColorType&) -> optional<std::unique_ptr<Expression>> { - return toColor(get(literal(*property)), std::move(defaultExpr)); + return toColor(get(literal(*property)), defaultExpr()); }, [&] (const type::Array& array) -> optional<std::unique_ptr<Expression>> { - return assertion(array, get(literal(*property)), std::move(defaultExpr)); + return assertion(array, get(literal(*property)), defaultExpr()); }, [&] (const type::FormattedType&) -> optional<std::unique_ptr<Expression>> { - return toFormatted(get(literal(*property)), std::move(defaultExpr)); + return toFormatted(get(literal(*property)), defaultExpr()); }, [&] (const auto&) -> optional<std::unique_ptr<Expression>> { assert(false); // No properties use this type. @@ -759,13 +787,21 @@ optional<std::unique_ptr<Expression>> convertFunctionToExpression(type::Type typ const auto& stop = arrayMember(first, 0); + const auto getProperty = [&](bool coerce) { + if (coerce) { + return number(get(literal(*property))); + } else { + return get(literal(*property)); + } + }; + if (!isObject(stop)) { // Source function. switch (functionType) { case FunctionType::Interval: - return convertIntervalFunction(type, value, err, number(get(literal(*property)))); + return convertIntervalFunction(type, value, err, getProperty, defaultExpr()); case FunctionType::Exponential: - return convertExponentialFunction(type, value, err, number(get(literal(*property)))); + return convertExponentialFunction(type, value, err, getProperty, defaultExpr()); case FunctionType::Categorical: return convertCategoricalFunction(type, value, err, *property); default: @@ -796,11 +832,18 @@ optional<std::unique_ptr<Expression>> convertFunctionToExpression(type::Type typ 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)); + omitFirstStop(stops); + return numberOrDefault(type, + getProperty(false), + step(type_, getProperty(true), std::move(stops)), + defaultExpr()); }); 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)); + return numberOrDefault(type, + getProperty(false), + interpolate(type_, exponential(base), getProperty(true), std::move(stops)), + defaultExpr()); }); case FunctionType::Categorical: return composite<int64_t>(type, value, err, [&] (type::Type type_, double, std::map<int64_t, std::unique_ptr<Expression>> stops) { |