diff options
author | Alexander Shalamov <alexander.shalamov@mapbox.com> | 2019-10-30 10:21:17 +0200 |
---|---|---|
committer | Alexander Shalamov <alexander.shalamov@mapbox.com> | 2019-11-11 18:20:01 +0200 |
commit | c6f3cc8b60e0cff032020a780d4fd3de1cb2a112 (patch) | |
tree | 155fe444f21ae88dda664e81cfc8378e28297b0e /include | |
parent | e1556fc539607db626b978040895716c1564c9b9 (diff) | |
download | qtlocation-mapboxgl-c6f3cc8b60e0cff032020a780d4fd3de1cb2a112.tar.gz |
[core] Implement image expression (#15877)
* [core] Bump gl-js version
* [core] Implement image expression
* [core] Use new image expression
* [core] Coerce image expression to / from string
* [core] Serialize evaluated image
* [core] Pass available images to layout
* [core] Pass images to evaluation context
* [core] Set available flag value based on image availability
* [core] Allow image coercion to boolean to indicate image availability
* [core] Coalesce image expression
* [core] Add image expression to next build system
* [core] Align serialization format and evaluated type with gl-js
* [core] Add images to expression evaluation method
* [core] Add support for Image expression to expression test runner
* [core] Unskip image expression tests
* [core] Update unit tests
* [core] Use image expression in annotation manager
* [core] Add string to ImageExpression conversion
* [core] Add image expression to expression dsl
* [core] Convert tokens for implicitly created Image literal
* [core] Fix clang format
* [core] Split generated style code lines that are over 120 characters
* [core] Add unit test for image expression equality
* [core] Add image property expression evaluation unit test
* [core] Unskip image expression render test
* [core] Skip 'in' expression tests
* [core] Ignore fill-pattern/update-feature-state render test
* [core] Rename Image::serialize to Image::toValue
Diffstat (limited to 'include')
-rw-r--r-- | include/mbgl/style/conversion/function.hpp | 1 | ||||
-rw-r--r-- | include/mbgl/style/conversion/property_value.hpp | 6 | ||||
-rw-r--r-- | include/mbgl/style/conversion_impl.hpp | 1 | ||||
-rw-r--r-- | include/mbgl/style/expression/dsl.hpp | 4 | ||||
-rw-r--r-- | include/mbgl/style/expression/expression.hpp | 20 | ||||
-rw-r--r-- | include/mbgl/style/expression/formatted.hpp | 2 | ||||
-rw-r--r-- | include/mbgl/style/expression/image.hpp | 49 | ||||
-rw-r--r-- | include/mbgl/style/expression/image_expression.hpp | 33 | ||||
-rw-r--r-- | include/mbgl/style/expression/is_constant.hpp | 2 | ||||
-rw-r--r-- | include/mbgl/style/expression/type.hpp | 50 | ||||
-rw-r--r-- | include/mbgl/style/expression/value.hpp | 21 | ||||
-rw-r--r-- | include/mbgl/style/layers/background_layer.hpp | 6 | ||||
-rw-r--r-- | include/mbgl/style/layers/fill_extrusion_layer.hpp | 6 | ||||
-rw-r--r-- | include/mbgl/style/layers/fill_layer.hpp | 6 | ||||
-rw-r--r-- | include/mbgl/style/layers/line_layer.hpp | 6 | ||||
-rw-r--r-- | include/mbgl/style/layers/symbol_layer.hpp | 6 | ||||
-rw-r--r-- | include/mbgl/style/property_expression.hpp | 24 |
17 files changed, 188 insertions, 55 deletions
diff --git a/include/mbgl/style/conversion/function.hpp b/include/mbgl/style/conversion/function.hpp index 47ce6843b5..9ceeb979ce 100644 --- a/include/mbgl/style/conversion/function.hpp +++ b/include/mbgl/style/conversion/function.hpp @@ -12,6 +12,7 @@ namespace conversion { bool hasTokens(const std::string&); std::unique_ptr<expression::Expression> convertTokenStringToFormatExpression(const std::string&); +std::unique_ptr<expression::Expression> convertTokenStringToImageExpression(const std::string&); std::unique_ptr<expression::Expression> convertTokenStringToExpression(const std::string&); optional<std::unique_ptr<expression::Expression>> convertFunctionToExpression(expression::type::Type, const Convertible&, Error&, bool convertTokens); diff --git a/include/mbgl/style/conversion/property_value.hpp b/include/mbgl/style/conversion/property_value.hpp index 9d619f7a02..61360b7440 100644 --- a/include/mbgl/style/conversion/property_value.hpp +++ b/include/mbgl/style/conversion/property_value.hpp @@ -39,6 +39,12 @@ struct Converter<PropertyValue<T>> { ? PropertyValue<T>(PropertyExpression<T>(convertTokenStringToFormatExpression(firstUnformattedSection))) : PropertyValue<T>(t); } + + PropertyValue<T> maybeConvertTokens(const expression::Image& image) const { + return hasTokens(image.id()) + ? PropertyValue<T>(PropertyExpression<T>(convertTokenStringToImageExpression(image.id()))) + : PropertyValue<T>(image); + } }; } // namespace conversion diff --git a/include/mbgl/style/conversion_impl.hpp b/include/mbgl/style/conversion_impl.hpp index 3e1b8455e5..73d83302a0 100644 --- a/include/mbgl/style/conversion_impl.hpp +++ b/include/mbgl/style/conversion_impl.hpp @@ -2,6 +2,7 @@ #include <mbgl/style/color_ramp_property_value.hpp> #include <mbgl/style/conversion.hpp> +#include <mbgl/style/expression/image.hpp> #include <mbgl/style/layer.hpp> #include <mbgl/style/property_value.hpp> #include <mbgl/style/transition_options.hpp> diff --git a/include/mbgl/style/expression/dsl.hpp b/include/mbgl/style/expression/dsl.hpp index 4abeac7989..347861abc9 100644 --- a/include/mbgl/style/expression/dsl.hpp +++ b/include/mbgl/style/expression/dsl.hpp @@ -49,6 +49,7 @@ std::unique_ptr<Expression> toString(std::unique_ptr<Expression>, std::unique_ptr<Expression> def = nullptr); std::unique_ptr<Expression> toFormatted(std::unique_ptr<Expression>, std::unique_ptr<Expression> def = nullptr); +std::unique_ptr<Expression> toImage(std::unique_ptr<Expression>, std::unique_ptr<Expression> def = nullptr); std::unique_ptr<Expression> get(const char* value); std::unique_ptr<Expression> get(std::unique_ptr<Expression>); @@ -89,6 +90,9 @@ std::unique_ptr<Expression> concat(std::vector<std::unique_ptr<Expression>> inpu std::unique_ptr<Expression> format(const char* value); std::unique_ptr<Expression> format(std::unique_ptr<Expression>); +std::unique_ptr<Expression> image(const char* value); +std::unique_ptr<Expression> image(std::unique_ptr<Expression>); + } // namespace dsl } // namespace expression } // namespace style diff --git a/include/mbgl/style/expression/expression.hpp b/include/mbgl/style/expression/expression.hpp index 1341a8d041..9893daa8c4 100644 --- a/include/mbgl/style/expression/expression.hpp +++ b/include/mbgl/style/expression/expression.hpp @@ -28,9 +28,7 @@ public: EvaluationContext() = default; explicit EvaluationContext(float zoom_) : zoom(zoom_) {} explicit EvaluationContext(GeometryTileFeature const * feature_) : feature(feature_) {} - EvaluationContext(float zoom_, GeometryTileFeature const * feature_) : - zoom(zoom_), feature(feature_) - {} + EvaluationContext(float zoom_, GeometryTileFeature const* feature_) : zoom(zoom_), feature(feature_) {} EvaluationContext(optional<mbgl::Value> accumulated_, GeometryTileFeature const * feature_) : accumulated(std::move(accumulated_)), feature(feature_) {} @@ -50,6 +48,11 @@ public: return *this; }; + EvaluationContext& withAvailableImages(const std::set<std::string>* availableImages_) noexcept { + availableImages = availableImages_; + return *this; + }; + optional<float> zoom; optional<mbgl::Value> accumulated; GeometryTileFeature const * feature = nullptr; @@ -57,6 +60,7 @@ public: // Contains formatted section object, std::unordered_map<std::string, Value>. const Value* formattedSection = nullptr; const FeatureState* featureState = nullptr; + const std::set<std::string>* availableImages = nullptr; }; template <typename T> @@ -155,7 +159,8 @@ enum class Kind : int32_t { Comparison, FormatExpression, FormatSectionOverride, - NumberFormat + NumberFormat, + ImageExpression }; class Expression { @@ -172,9 +177,14 @@ public: Kind getKind() const { return kind; }; type::Type getType() const { return type; }; - + EvaluationResult evaluate(optional<float> zoom, const Feature& feature, optional<double> colorRampParameter) const; + EvaluationResult evaluate(optional<float> zoom, + const Feature& feature, + optional<double> colorRampParameter, + const std::set<std::string>& availableImages) const; EvaluationResult evaluate(optional<mbgl::Value> accumulated, const Feature& feature) const; + /** * Statically analyze the expression, attempting to enumerate possible outputs. Returns * an array of values plus the sentinel null optional value, used to indicate that the diff --git a/include/mbgl/style/expression/formatted.hpp b/include/mbgl/style/expression/formatted.hpp index bb3d609c91..09edad240f 100644 --- a/include/mbgl/style/expression/formatted.hpp +++ b/include/mbgl/style/expression/formatted.hpp @@ -36,7 +36,7 @@ struct FormattedSection { class Formatted { public: Formatted() = default; - + Formatted(const char* plainU8String) { sections.emplace_back(std::string(plainU8String), nullopt, nullopt, nullopt); } diff --git a/include/mbgl/style/expression/image.hpp b/include/mbgl/style/expression/image.hpp new file mode 100644 index 0000000000..0bc4794a24 --- /dev/null +++ b/include/mbgl/style/expression/image.hpp @@ -0,0 +1,49 @@ +#pragma once + +#include <mbgl/style/conversion.hpp> +#include <mbgl/util/color.hpp> +#include <mbgl/util/optional.hpp> + +#include <string> +#include <vector> + +namespace mbgl { +namespace style { +namespace expression { + +class Image { +public: + Image() = default; + Image(const char* imageID); + Image(std::string imageID); + explicit Image(std::string imageID, bool available); + bool operator==(const Image&) const; + mbgl::Value toValue() const; + const std::string& id() const; + bool isAvailable() const; + bool empty() const; + +private: + std::string imageID; + bool available; +}; + +} // namespace expression + +namespace conversion { + +template <> +struct Converter<expression::Image> { +public: + optional<expression::Image> operator()(const Convertible& value, Error& error) const; +}; + +template <> +struct ValueFactory<expression::Image> { + static Value make(const expression::Image& image) { return image.toValue(); } +}; + +} // namespace conversion + +} // namespace style +} // namespace mbgl diff --git a/include/mbgl/style/expression/image_expression.hpp b/include/mbgl/style/expression/image_expression.hpp new file mode 100644 index 0000000000..cd3d375284 --- /dev/null +++ b/include/mbgl/style/expression/image_expression.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include <mbgl/style/expression/expression.hpp> + +namespace mbgl { +namespace style { +namespace expression { + +class ParsingContext; + +class ImageExpression final : public Expression { +public: + explicit ImageExpression(std::unique_ptr<Expression> imageID); + + EvaluationResult evaluate(const EvaluationContext&) const override; + static ParseResult parse(const mbgl::style::conversion::Convertible&, ParsingContext&); + + void eachChild(const std::function<void(const Expression&)>&) const override; + + bool operator==(const Expression& e) const override; + + std::vector<optional<Value>> possibleOutputs() const override { return {nullopt}; } + + mbgl::Value serialize() const override; + std::string getOperator() const override { return "image"; } + +private: + std::shared_ptr<Expression> imageID; +}; + +} // namespace expression +} // namespace style +} // namespace mbgl diff --git a/include/mbgl/style/expression/is_constant.hpp b/include/mbgl/style/expression/is_constant.hpp index 2861407af0..a9c41e48b1 100644 --- a/include/mbgl/style/expression/is_constant.hpp +++ b/include/mbgl/style/expression/is_constant.hpp @@ -30,6 +30,8 @@ bool isGlobalPropertyConstant(const Expression& expression, const T& properties) bool isFeatureConstant(const Expression& expression); bool isZoomConstant(const Expression& e); +// Returns true if expression does not depend on information provided by the runtime. +bool isRuntimeConstant(const Expression& e); } // namespace expression } // namespace style diff --git a/include/mbgl/style/expression/type.hpp b/include/mbgl/style/expression/type.hpp index a5a1e76164..ab398741f0 100644 --- a/include/mbgl/style/expression/type.hpp +++ b/include/mbgl/style/expression/type.hpp @@ -14,65 +14,70 @@ template <class T> std::string toString(const T& t); struct NullType { - constexpr NullType() {}; + constexpr NullType() = default; std::string getName() const { return "null"; } bool operator==(const NullType&) const { return true; } }; struct NumberType { - constexpr NumberType() {}; + constexpr NumberType() = default; std::string getName() const { return "number"; } bool operator==(const NumberType&) const { return true; } }; struct BooleanType { - constexpr BooleanType() {}; + constexpr BooleanType() = default; std::string getName() const { return "boolean"; } bool operator==(const BooleanType&) const { return true; } }; struct StringType { - constexpr StringType() {}; + constexpr StringType() = default; std::string getName() const { return "string"; } bool operator==(const StringType&) const { return true; } }; struct ColorType { - constexpr ColorType() {}; + constexpr ColorType() = default; std::string getName() const { return "color"; } bool operator==(const ColorType&) const { return true; } }; struct ObjectType { - constexpr ObjectType() {}; + constexpr ObjectType() = default; std::string getName() const { return "object"; } bool operator==(const ObjectType&) const { return true; } }; struct ErrorType { - constexpr ErrorType() {}; + constexpr ErrorType() = default; std::string getName() const { return "error"; } bool operator==(const ErrorType&) const { return true; } }; struct ValueType { - constexpr ValueType() {}; + constexpr ValueType() = default; std::string getName() const { return "value"; } bool operator==(const ValueType&) const { return true; } }; struct CollatorType { - constexpr CollatorType() {}; // NOLINT + constexpr CollatorType() = default; std::string getName() const { return "collator"; } bool operator==(const CollatorType&) const { return true; } }; struct FormattedType { - constexpr FormattedType() {}; // NOLINT + constexpr FormattedType() = default; std::string getName() const { return "formatted"; } bool operator==(const FormattedType&) const { return true; } }; +struct ImageType { + constexpr ImageType() = default; + std::string getName() const { return "resolvedImage"; } + bool operator==(const ImageType&) const { return true; } +}; constexpr NullType Null; constexpr NumberType Number; @@ -84,21 +89,22 @@ constexpr ObjectType Object; constexpr CollatorType Collator; constexpr FormattedType Formatted; constexpr ErrorType Error; +constexpr ImageType Image; struct Array; -using Type = variant< - NullType, - NumberType, - BooleanType, - StringType, - ColorType, - ObjectType, - ValueType, - mapbox::util::recursive_wrapper<Array>, - CollatorType, - FormattedType, - ErrorType>; +using Type = variant<NullType, + NumberType, + BooleanType, + StringType, + ColorType, + ObjectType, + ValueType, + mapbox::util::recursive_wrapper<Array>, + CollatorType, + FormattedType, + ErrorType, + ImageType>; struct Array { explicit Array(Type itemType_) : itemType(std::move(itemType_)) {} diff --git a/include/mbgl/style/expression/value.hpp b/include/mbgl/style/expression/value.hpp index 91239d083f..902f5ae209 100644 --- a/include/mbgl/style/expression/value.hpp +++ b/include/mbgl/style/expression/value.hpp @@ -2,6 +2,7 @@ #include <mbgl/style/expression/collator.hpp> #include <mbgl/style/expression/formatted.hpp> +#include <mbgl/style/expression/image.hpp> #include <mbgl/style/expression/type.hpp> #include <mbgl/style/position.hpp> #include <mbgl/style/types.hpp> @@ -19,16 +20,16 @@ namespace expression { struct Value; -using ValueBase = variant< - NullValue, - bool, - double, - std::string, - Color, - Collator, - Formatted, - mapbox::util::recursive_wrapper<std::vector<Value>>, - mapbox::util::recursive_wrapper<std::unordered_map<std::string, Value>>>; +using ValueBase = variant<NullValue, + bool, + double, + std::string, + Color, + Collator, + Formatted, + Image, + mapbox::util::recursive_wrapper<std::vector<Value>>, + mapbox::util::recursive_wrapper<std::unordered_map<std::string, Value>>>; struct Value : ValueBase { using ValueBase::ValueBase; diff --git a/include/mbgl/style/layers/background_layer.hpp b/include/mbgl/style/layers/background_layer.hpp index ebdce35d0f..bc9d5222fd 100644 --- a/include/mbgl/style/layers/background_layer.hpp +++ b/include/mbgl/style/layers/background_layer.hpp @@ -40,9 +40,9 @@ public: void setBackgroundOpacityTransition(const TransitionOptions&); TransitionOptions getBackgroundOpacityTransition() const; - static PropertyValue<std::string> getDefaultBackgroundPattern(); - const PropertyValue<std::string>& getBackgroundPattern() const; - void setBackgroundPattern(const PropertyValue<std::string>&); + static PropertyValue<expression::Image> getDefaultBackgroundPattern(); + const PropertyValue<expression::Image>& getBackgroundPattern() const; + void setBackgroundPattern(const PropertyValue<expression::Image>&); void setBackgroundPatternTransition(const TransitionOptions&); TransitionOptions getBackgroundPatternTransition() const; diff --git a/include/mbgl/style/layers/fill_extrusion_layer.hpp b/include/mbgl/style/layers/fill_extrusion_layer.hpp index 76c2359617..2996cd0066 100644 --- a/include/mbgl/style/layers/fill_extrusion_layer.hpp +++ b/include/mbgl/style/layers/fill_extrusion_layer.hpp @@ -52,9 +52,9 @@ public: void setFillExtrusionOpacityTransition(const TransitionOptions&); TransitionOptions getFillExtrusionOpacityTransition() const; - static PropertyValue<std::string> getDefaultFillExtrusionPattern(); - const PropertyValue<std::string>& getFillExtrusionPattern() const; - void setFillExtrusionPattern(const PropertyValue<std::string>&); + static PropertyValue<expression::Image> getDefaultFillExtrusionPattern(); + const PropertyValue<expression::Image>& getFillExtrusionPattern() const; + void setFillExtrusionPattern(const PropertyValue<expression::Image>&); void setFillExtrusionPatternTransition(const TransitionOptions&); TransitionOptions getFillExtrusionPatternTransition() const; diff --git a/include/mbgl/style/layers/fill_layer.hpp b/include/mbgl/style/layers/fill_layer.hpp index 9ec33d7e96..90e51c85a3 100644 --- a/include/mbgl/style/layers/fill_layer.hpp +++ b/include/mbgl/style/layers/fill_layer.hpp @@ -52,9 +52,9 @@ public: void setFillOutlineColorTransition(const TransitionOptions&); TransitionOptions getFillOutlineColorTransition() const; - static PropertyValue<std::string> getDefaultFillPattern(); - const PropertyValue<std::string>& getFillPattern() const; - void setFillPattern(const PropertyValue<std::string>&); + static PropertyValue<expression::Image> getDefaultFillPattern(); + const PropertyValue<expression::Image>& getFillPattern() const; + void setFillPattern(const PropertyValue<expression::Image>&); void setFillPatternTransition(const TransitionOptions&); TransitionOptions getFillPatternTransition() const; diff --git a/include/mbgl/style/layers/line_layer.hpp b/include/mbgl/style/layers/line_layer.hpp index 4f2cf53708..33312795d0 100644 --- a/include/mbgl/style/layers/line_layer.hpp +++ b/include/mbgl/style/layers/line_layer.hpp @@ -91,9 +91,9 @@ public: void setLineOpacityTransition(const TransitionOptions&); TransitionOptions getLineOpacityTransition() const; - static PropertyValue<std::string> getDefaultLinePattern(); - const PropertyValue<std::string>& getLinePattern() const; - void setLinePattern(const PropertyValue<std::string>&); + static PropertyValue<expression::Image> getDefaultLinePattern(); + const PropertyValue<expression::Image>& getLinePattern() const; + void setLinePattern(const PropertyValue<expression::Image>&); void setLinePatternTransition(const TransitionOptions&); TransitionOptions getLinePatternTransition() const; diff --git a/include/mbgl/style/layers/symbol_layer.hpp b/include/mbgl/style/layers/symbol_layer.hpp index 92e214919a..0ef212a3b9 100644 --- a/include/mbgl/style/layers/symbol_layer.hpp +++ b/include/mbgl/style/layers/symbol_layer.hpp @@ -42,9 +42,9 @@ public: const PropertyValue<bool>& getIconIgnorePlacement() const; void setIconIgnorePlacement(const PropertyValue<bool>&); - static PropertyValue<std::string> getDefaultIconImage(); - const PropertyValue<std::string>& getIconImage() const; - void setIconImage(const PropertyValue<std::string>&); + static PropertyValue<expression::Image> getDefaultIconImage(); + const PropertyValue<expression::Image>& getIconImage() const; + void setIconImage(const PropertyValue<expression::Image>&); static PropertyValue<bool> getDefaultIconKeepUpright(); const PropertyValue<bool>& getIconKeepUpright() const; diff --git a/include/mbgl/style/property_expression.hpp b/include/mbgl/style/property_expression.hpp index f68285fb1b..7dcd818dde 100644 --- a/include/mbgl/style/property_expression.hpp +++ b/include/mbgl/style/property_expression.hpp @@ -16,7 +16,7 @@ public: bool isZoomConstant() const noexcept; bool isFeatureConstant() const noexcept; - bool canEvaluateWith(const expression::EvaluationContext&) const noexcept; + bool isRuntimeConstant() const noexcept; float interpolationFactor(const Range<float>&, const float) const noexcept; Range<float> getCoveringStops(const float, const float) const noexcept; const expression::Expression& getExpression() const noexcept; @@ -28,6 +28,7 @@ protected: variant<std::nullptr_t, const expression::Interpolate*, const expression::Step*> zoomCurve; bool isZoomConstant_; bool isFeatureConstant_; + bool isRuntimeConstant_; }; template <class T> @@ -40,7 +41,6 @@ public: } T evaluate(const expression::EvaluationContext& context, T finalDefaultValue = T()) const { - assert(canEvaluateWith(context)); const expression::EvaluationResult result = expression->evaluate(context); if (result) { const optional<T> typed = expression::fromExpressionValue<T>(*result); @@ -50,18 +50,38 @@ public: } T evaluate(float zoom) const { + assert(!isZoomConstant()); + assert(isFeatureConstant()); return evaluate(expression::EvaluationContext(zoom)); } T evaluate(const GeometryTileFeature& feature, T finalDefaultValue) const { + assert(isZoomConstant()); + assert(!isFeatureConstant()); return evaluate(expression::EvaluationContext(&feature), finalDefaultValue); } + T evaluate(const GeometryTileFeature& feature, + const std::set<std::string>& availableImages, + T finalDefaultValue) const { + return evaluate(expression::EvaluationContext(&feature).withAvailableImages(&availableImages), + finalDefaultValue); + } + T evaluate(float zoom, const GeometryTileFeature& feature, T finalDefaultValue) const { return evaluate(expression::EvaluationContext(zoom, &feature), finalDefaultValue); } + T evaluate(float zoom, + const GeometryTileFeature& feature, + const std::set<std::string>& availableImages, + T finalDefaultValue) const { + return evaluate(expression::EvaluationContext(zoom, &feature).withAvailableImages(&availableImages), + finalDefaultValue); + } + T evaluate(float zoom, const GeometryTileFeature& feature, const FeatureState& state, T finalDefaultValue) const { + assert(!isFeatureConstant()); return evaluate(expression::EvaluationContext(zoom, &feature, &state), finalDefaultValue); } |