diff options
86 files changed, 1051 insertions, 526 deletions
diff --git a/expression-test/expression_test_parser.cpp b/expression-test/expression_test_parser.cpp index 3b40eeb3b0..15136f0231 100644 --- a/expression-test/expression_test_parser.cpp +++ b/expression-test/expression_test_parser.cpp @@ -104,8 +104,7 @@ optional<Value> toValue(const JSValue& jsvalue) { style::expression::type::Type stringToType(const std::string& type) { using namespace style::expression; - if (type == "string"s || type == "number-format"s || - type == "image"s) { // TODO: replace once we implement image expressions + if (type == "string"s || type == "number-format"s) { return type::String; } else if (type == "number"s) { return type::Number; @@ -119,6 +118,8 @@ style::expression::type::Type stringToType(const std::string& type) { return type::Value; } else if (type == "formatted"s) { return type::Formatted; + } else if (type == "resolvedImage"s) { + return type::Image; } // Should not reach. @@ -253,6 +254,16 @@ bool parseInputs(const JSValue& inputsValue, TestData& data) { heatmapDensity = evaluationContext["heatmapDensity"].GetDouble(); } + // Parse availableImages + std::set<std::string> availableImages; + if (evaluationContext.HasMember("availableImages")) { + assert(evaluationContext["availableImages"].IsArray()); + for (const auto& image : evaluationContext["availableImages"].GetArray()) { + assert(image.IsString()); + availableImages.emplace(toString(image)); + } + } + // Parse feature properties Feature feature(mapbox::geometry::point<double>(0.0, 0.0)); const auto& featureObject = input[1].GetObject(); @@ -271,7 +282,8 @@ bool parseInputs(const JSValue& inputsValue, TestData& data) { feature.id = mapbox::geojson::convert<mapbox::feature::identifier>(featureObject["id"]); } - data.inputs.emplace_back(std::move(zoom), std::move(heatmapDensity), std::move(feature)); + data.inputs.emplace_back( + std::move(zoom), std::move(heatmapDensity), std::move(availableImages), std::move(feature)); } return true; } diff --git a/expression-test/expression_test_parser.hpp b/expression-test/expression_test_parser.hpp index 561ccd9647..842d8a1563 100644 --- a/expression-test/expression_test_parser.hpp +++ b/expression-test/expression_test_parser.hpp @@ -7,18 +7,24 @@ #include <mbgl/util/optional.hpp> #include <mbgl/util/rapidjson.hpp> -#include <vector> +#include <set> #include <string> +#include <vector> using namespace mbgl; struct Input { - Input(optional<float> zoom_, optional<double> heatmapDensity_, Feature feature_) + Input(optional<float> zoom_, + optional<double> heatmapDensity_, + std::set<std::string> availableImages_, + Feature feature_) : zoom(std::move(zoom_)), heatmapDensity(std::move(heatmapDensity_)), + availableImages(std::move(availableImages_)), feature(std::move(feature_)) {} optional<float> zoom; optional<double> heatmapDensity; + std::set<std::string> availableImages; Feature feature; }; diff --git a/expression-test/expression_test_runner.cpp b/expression-test/expression_test_runner.cpp index c8a39f07ce..436e449921 100644 --- a/expression-test/expression_test_runner.cpp +++ b/expression-test/expression_test_runner.cpp @@ -104,7 +104,8 @@ TestRunOutput runExpressionTest(TestData& data, const std::string& rootPath, con std::vector<Value> outputs; if (!data.inputs.empty()) { for (const auto& input : data.inputs) { - auto evaluationResult = expression->evaluate(input.zoom, input.feature, input.heatmapDensity); + auto evaluationResult = + expression->evaluate(input.zoom, input.feature, input.heatmapDensity, input.availableImages); if (!evaluationResult) { std::unordered_map<std::string, Value> error{{"error", Value{evaluationResult.error().message}}}; outputs.emplace_back(Value{std::move(error)}); 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); } diff --git a/mapbox-gl-js b/mapbox-gl-js -Subproject 6453c38a5118e52e7cc7fb9b6e23d28e5bf5268 +Subproject cbbbbfc523ed78bb0d8d03de2efabe825e55f19 diff --git a/next/CMakeLists.txt b/next/CMakeLists.txt index aa26e3a572..5ba734f481 100644 --- a/next/CMakeLists.txt +++ b/next/CMakeLists.txt @@ -151,6 +151,8 @@ add_library( ${MBGL_ROOT}/include/mbgl/style/expression/format_section_override.hpp ${MBGL_ROOT}/include/mbgl/style/expression/formatted.hpp ${MBGL_ROOT}/include/mbgl/style/expression/get_covering_stops.hpp + ${MBGL_ROOT}/include/mbgl/style/expression/image.hpp + ${MBGL_ROOT}/include/mbgl/style/expression/image_expression.hpp ${MBGL_ROOT}/include/mbgl/style/expression/interpolate.hpp ${MBGL_ROOT}/include/mbgl/style/expression/interpolator.hpp ${MBGL_ROOT}/include/mbgl/style/expression/is_constant.hpp @@ -613,6 +615,8 @@ add_library( ${MBGL_ROOT}/src/mbgl/style/expression/format_expression.cpp ${MBGL_ROOT}/src/mbgl/style/expression/formatted.cpp ${MBGL_ROOT}/src/mbgl/style/expression/get_covering_stops.cpp + ${MBGL_ROOT}/src/mbgl/style/expression/image.cpp + ${MBGL_ROOT}/src/mbgl/style/expression/image_expression.cpp ${MBGL_ROOT}/src/mbgl/style/expression/interpolate.cpp ${MBGL_ROOT}/src/mbgl/style/expression/is_constant.cpp ${MBGL_ROOT}/src/mbgl/style/expression/is_expression.cpp diff --git a/platform/node/src/node_expression.cpp b/platform/node/src/node_expression.cpp index e1c3ba0c39..81d5c74767 100644 --- a/platform/node/src/node_expression.cpp +++ b/platform/node/src/node_expression.cpp @@ -35,16 +35,14 @@ void NodeExpression::Init(v8::Local<v8::Object> target) { } type::Type parseType(v8::Local<v8::Object> type) { - static std::unordered_map<std::string, type::Type> types = { - {"string", type::String}, - {"number", type::Number}, - {"boolean", type::Boolean}, - {"object", type::Object}, - {"color", type::Color}, - {"value", type::Value}, - {"formatted", type::Formatted}, - {"number-format", type::String} - }; + static std::unordered_map<std::string, type::Type> types = {{"string", type::String}, + {"number", type::Number}, + {"boolean", type::Boolean}, + {"object", type::Object}, + {"color", type::Color}, + {"value", type::Value}, + {"formatted", type::Formatted}, + {"number-format", type::String}}; v8::Local<v8::Value> v8kind = Nan::Get(type, Nan::New("kind").ToLocalChecked()).ToLocalChecked(); std::string kind(*v8::String::Utf8Value(v8kind)); diff --git a/platform/node/test/ignores.json b/platform/node/test/ignores.json index 51decb351c..438677fff9 100644 --- a/platform/node/test/ignores.json +++ b/platform/node/test/ignores.json @@ -16,10 +16,12 @@ "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/tokens-zoom": "https://github.com/mapbox/mapbox-gl-native/issues/12747", - "expression-tests/image/basic": "https://github.com/mapbox/mapbox-gl-native/issues/15800", - "expression-tests/image/compound": "https://github.com/mapbox/mapbox-gl-native/issues/15800", - "expression-tests/image/coalesce": "https://github.com/mapbox/mapbox-gl-native/issues/15800", - "expression-tests/image/implicit-assert": "https://github.com/mapbox/mapbox-gl-native/issues/15800", + "expression-tests/in/assert-array": "https://github.com/mapbox/mapbox-gl-native/issues/15893", + "expression-tests/in/assert-string": "https://github.com/mapbox/mapbox-gl-native/issues/15893", + "expression-tests/in/basic-array": "https://github.com/mapbox/mapbox-gl-native/issues/15893", + "expression-tests/in/basic-string": "https://github.com/mapbox/mapbox-gl-native/issues/15893", + "expression-tests/in/invalid-haystack": "https://github.com/mapbox/mapbox-gl-native/issues/15893", + "expression-tests/in/invalid-needle": "https://github.com/mapbox/mapbox-gl-native/issues/15893", "query-tests/geometry/multilinestring": "needs investigation", "query-tests/geometry/multipolygon": "needs investigation", "query-tests/geometry/polygon": "needs investigation", @@ -77,7 +79,6 @@ "render-tests/line-sort-key/literal": "https://github.com/mapbox/mapbox-gl-native/issues/15008", "render-tests/regressions/mapbox-gl-js#8817": "skip - https://github.com/mapbox/mapbox-gl-native/issues/15737", "render-tests/text-max-width/zero-width-point-placement": "https://github.com/mapbox/mapbox-gl-native/issues/15648", - "render-tests/icon-image/image-expression": "https://github.com/mapbox/mapbox-gl-native/issues/15800", "render-tests/icon-text-fit/text-variable-anchor-overlap": "https://github.com/mapbox/mapbox-gl-native/issues/15809", "query-tests/fill-extrusion/base-in": "https://github.com/mapbox/mapbox-gl-native/issues/13139", "query-tests/fill-extrusion/box-in": "https://github.com/mapbox/mapbox-gl-native/issues/13139", @@ -87,5 +88,6 @@ "query-tests/fill-extrusion/sort-rotated": "https://github.com/mapbox/mapbox-gl-native/issues/13139", "query-tests/fill-extrusion/sort": "https://github.com/mapbox/mapbox-gl-native/issues/13139", "query-tests/fill-extrusion/top-in": "https://github.com/mapbox/mapbox-gl-native/issues/13139", - "query-tests/regressions/mapbox-gl-js#7883": "https://github.com/mapbox/mapbox-gl-native/issues/14585" + "query-tests/regressions/mapbox-gl-js#7883": "https://github.com/mapbox/mapbox-gl-native/issues/14585", + "render-tests/fill-pattern/update-feature-state": "https://github.com/mapbox/mapbox-gl-native/issues/15895" } diff --git a/scripts/generate-style-code.js b/scripts/generate-style-code.js index 0aedba909b..db2548680e 100755 --- a/scripts/generate-style-code.js +++ b/scripts/generate-style-code.js @@ -35,8 +35,9 @@ global.expressionType = function (property) { case 'number': case 'enum': return 'NumberType'; + case 'image': + return 'ImageType'; case 'string': - case 'image': // TODO: replace once we implement image expressions return 'StringType'; case 'color': return `ColorType`; @@ -66,10 +67,11 @@ global.evaluatedType = function (property) { return 'bool'; case 'number': return 'float'; + case 'resolvedImage': + return 'expression::Image'; case 'formatted': return 'expression::Formatted'; case 'string': - case 'image': // TODO: replace once we implement image expressions return 'std::string'; case 'enum': return (isLightProperty(property) ? 'Light' : '') + `${camelize(property.name)}Type`; @@ -168,8 +170,8 @@ global.defaultValue = function (property) { } case 'formatted': case 'string': - case 'image': // TODO: replace once we implement image expressions - return JSON.stringify(property.default || ""); + case 'resolvedImage': + return property.default ? `{${JSON.stringify(property.default)}}` : '{}'; case 'enum': if (property.default === undefined) { return `${evaluatedType(property)}::Undefined`; @@ -191,9 +193,9 @@ global.defaultValue = function (property) { case 'array': const defaults = (property.default || []).map((e) => defaultValue({ type: property.value, default: e })); if (property.length) { - return `{{ ${defaults.join(', ')} }}`; + return `{{${defaults.join(', ')}}}`; } else { - return `{ ${defaults.join(', ')} }`; + return `{${defaults.join(', ')}}`; } default: return property.default; diff --git a/src/core-files.json b/src/core-files.json index c25e8273d4..b0bf177c2e 100644 --- a/src/core-files.json +++ b/src/core-files.json @@ -192,6 +192,8 @@ "src/mbgl/style/expression/format_expression.cpp", "src/mbgl/style/expression/formatted.cpp", "src/mbgl/style/expression/get_covering_stops.cpp", + "src/mbgl/style/expression/image.cpp", + "src/mbgl/style/expression/image_expression.cpp", "src/mbgl/style/expression/interpolate.cpp", "src/mbgl/style/expression/is_constant.cpp", "src/mbgl/style/expression/is_expression.cpp", @@ -418,6 +420,8 @@ "mbgl/style/expression/format_section_override.hpp": "include/mbgl/style/expression/format_section_override.hpp", "mbgl/style/expression/formatted.hpp": "include/mbgl/style/expression/formatted.hpp", "mbgl/style/expression/get_covering_stops.hpp": "include/mbgl/style/expression/get_covering_stops.hpp", + "mbgl/style/expression/image.hpp": "include/mbgl/style/expression/image.hpp", + "mbgl/style/expression/image_expression.hpp": "include/mbgl/style/expression/image_expression.hpp", "mbgl/style/expression/interpolate.hpp": "include/mbgl/style/expression/interpolate.hpp", "mbgl/style/expression/interpolator.hpp": "include/mbgl/style/expression/interpolator.hpp", "mbgl/style/expression/is_constant.hpp": "include/mbgl/style/expression/is_constant.hpp", diff --git a/src/mbgl/annotation/annotation_manager.cpp b/src/mbgl/annotation/annotation_manager.cpp index 345171b96e..b5dfea8e1a 100644 --- a/src/mbgl/annotation/annotation_manager.cpp +++ b/src/mbgl/annotation/annotation_manager.cpp @@ -1,15 +1,16 @@ #include <mbgl/annotation/annotation_manager.hpp> #include <mbgl/annotation/annotation_source.hpp> #include <mbgl/annotation/annotation_tile.hpp> -#include <mbgl/annotation/symbol_annotation_impl.hpp> -#include <mbgl/annotation/line_annotation_impl.hpp> #include <mbgl/annotation/fill_annotation_impl.hpp> +#include <mbgl/annotation/line_annotation_impl.hpp> +#include <mbgl/annotation/symbol_annotation_impl.hpp> #include <mbgl/layermanager/layer_manager.hpp> -#include <mbgl/style/style.hpp> -#include <mbgl/style/style_impl.hpp> +#include <mbgl/style/expression/dsl.hpp> +#include <mbgl/style/expression/image.hpp> #include <mbgl/style/layers/symbol_layer.hpp> #include <mbgl/style/layers/symbol_layer_impl.hpp> -#include <mbgl/style/expression/dsl.hpp> +#include <mbgl/style/style.hpp> +#include <mbgl/style/style_impl.hpp> #include <boost/function_output_iterator.hpp> @@ -184,7 +185,8 @@ void AnnotationManager::updateStyle() { using namespace expression::dsl; layer->setSourceLayer(PointLayerID); - layer->setIconImage(PropertyExpression<std::string>(concat(vec(literal(SourceID + "."), toString(get("sprite")))))); + layer->setIconImage(PropertyExpression<expression::Image>( + image(concat(vec(literal(SourceID + "."), toString(get("sprite"))))))); layer->setIconAllowOverlap(true); layer->setIconIgnorePlacement(true); diff --git a/src/mbgl/layermanager/fill_extrusion_layer_factory.cpp b/src/mbgl/layermanager/fill_extrusion_layer_factory.cpp index 0163321914..e1bedb5246 100644 --- a/src/mbgl/layermanager/fill_extrusion_layer_factory.cpp +++ b/src/mbgl/layermanager/fill_extrusion_layer_factory.cpp @@ -29,7 +29,7 @@ std::unique_ptr<Layout> FillExtrusionLayerFactory::createLayout(const LayoutPara const std::vector<Immutable<style::LayerProperties>>& group) noexcept { using namespace style; using LayoutType = PatternLayout<FillExtrusionBucket, FillExtrusionLayerProperties, FillExtrusionPattern>; - return std::make_unique<LayoutType>(parameters.bucketParameters, group, std::move(layer), parameters.imageDependencies); + return std::make_unique<LayoutType>(parameters.bucketParameters, group, std::move(layer), parameters); } std::unique_ptr<RenderLayer> FillExtrusionLayerFactory::createRenderLayer(Immutable<style::Layer::Impl> impl) noexcept { diff --git a/src/mbgl/layermanager/fill_layer_factory.cpp b/src/mbgl/layermanager/fill_layer_factory.cpp index f7f24c58a1..265fdc69f6 100644 --- a/src/mbgl/layermanager/fill_layer_factory.cpp +++ b/src/mbgl/layermanager/fill_layer_factory.cpp @@ -30,7 +30,7 @@ FillLayerFactory::createLayout(const LayoutParameters& parameters, const std::vector<Immutable<style::LayerProperties>>& group) noexcept { using namespace style; using LayoutType = PatternLayout<FillBucket, FillLayerProperties, FillPattern>; - return std::make_unique<LayoutType>(parameters.bucketParameters, group, std::move(layer), parameters.imageDependencies); + return std::make_unique<LayoutType>(parameters.bucketParameters, group, std::move(layer), parameters); } std::unique_ptr<RenderLayer> FillLayerFactory::createRenderLayer(Immutable<style::Layer::Impl> impl) noexcept { diff --git a/src/mbgl/layermanager/line_layer_factory.cpp b/src/mbgl/layermanager/line_layer_factory.cpp index b0f2827a80..5770b19f33 100644 --- a/src/mbgl/layermanager/line_layer_factory.cpp +++ b/src/mbgl/layermanager/line_layer_factory.cpp @@ -29,7 +29,7 @@ std::unique_ptr<Layout> LineLayerFactory::createLayout(const LayoutParameters& p const std::vector<Immutable<style::LayerProperties>>& group) noexcept { using namespace style; using LayoutType = PatternLayout<LineBucket, LineLayerProperties, LinePattern, LineLayoutProperties::PossiblyEvaluated>; - return std::make_unique<LayoutType>(parameters.bucketParameters, group, std::move(layer), parameters.imageDependencies); + return std::make_unique<LayoutType>(parameters.bucketParameters, group, std::move(layer), parameters); } std::unique_ptr<RenderLayer> LineLayerFactory::createRenderLayer(Immutable<style::Layer::Impl> impl) noexcept { diff --git a/src/mbgl/layermanager/symbol_layer_factory.cpp b/src/mbgl/layermanager/symbol_layer_factory.cpp index 7141f5a223..11a4f09ec3 100644 --- a/src/mbgl/layermanager/symbol_layer_factory.cpp +++ b/src/mbgl/layermanager/symbol_layer_factory.cpp @@ -27,11 +27,7 @@ std::unique_ptr<style::Layer> SymbolLayerFactory::createLayer(const std::string& std::unique_ptr<Layout> SymbolLayerFactory::createLayout(const LayoutParameters& parameters, std::unique_ptr<GeometryTileLayer> tileLayer, const std::vector<Immutable<style::LayerProperties>>& group) noexcept { - return std::make_unique<SymbolLayout>(parameters.bucketParameters, - group, - std::move(tileLayer), - parameters.imageDependencies, - parameters.glyphDependencies); + return std::make_unique<SymbolLayout>(parameters.bucketParameters, group, std::move(tileLayer), parameters); } std::unique_ptr<RenderLayer> SymbolLayerFactory::createRenderLayer(Immutable<style::Layer::Impl> impl) noexcept { diff --git a/src/mbgl/layout/layout.hpp b/src/mbgl/layout/layout.hpp index d1f03792c1..91d3e3f596 100644 --- a/src/mbgl/layout/layout.hpp +++ b/src/mbgl/layout/layout.hpp @@ -38,6 +38,7 @@ public: const BucketParameters& bucketParameters; GlyphDependencies& glyphDependencies; ImageDependencies& imageDependencies; + std::set<std::string>& availableImages; }; } // namespace mbgl diff --git a/src/mbgl/layout/pattern_layout.hpp b/src/mbgl/layout/pattern_layout.hpp index d6d878955f..48531e836b 100644 --- a/src/mbgl/layout/pattern_layout.hpp +++ b/src/mbgl/layout/pattern_layout.hpp @@ -1,8 +1,9 @@ #pragma once +#include <mbgl/geometry/feature_index.hpp> #include <mbgl/layout/layout.hpp> #include <mbgl/renderer/bucket_parameters.hpp> -#include <mbgl/geometry/feature_index.hpp> #include <mbgl/renderer/render_layer.hpp> +#include <mbgl/style/expression/image.hpp> #include <mbgl/style/layer_properties.hpp> namespace mbgl { @@ -32,11 +33,11 @@ public: PatternLayout(const BucketParameters& parameters, const std::vector<Immutable<style::LayerProperties>>& group, std::unique_ptr<GeometryTileLayer> sourceLayer_, - ImageDependencies& patternDependencies) - : sourceLayer(std::move(sourceLayer_)), - zoom(parameters.tileID.overscaledZ), - overscaling(parameters.tileID.overscaleFactor()), - hasPattern(false) { + const LayoutParameters& layoutParameters) + : sourceLayer(std::move(sourceLayer_)), + zoom(parameters.tileID.overscaledZ), + overscaling(parameters.tileID.overscaleFactor()), + hasPattern(false) { assert(!group.empty()); auto leaderLayerProperties = staticImmutableCast<LayerPropertiesType>(group.front()); layout = leaderLayerProperties->layerImpl().layout.evaluate(PropertyEvaluationParameters(zoom)); @@ -47,15 +48,15 @@ public: const std::string& layerId = layerProperties->baseImpl->id; const auto& evaluated = style::getEvaluated<LayerPropertiesType>(layerProperties); const auto patternProperty = evaluated.template get<PatternPropertyType>(); - const auto constantPattern = patternProperty.constantOr(Faded<std::basic_string<char> >{ "", ""}); + const auto constantPattern = patternProperty.constantOr(Faded<style::expression::Image>{"", ""}); // determine if layer group has any layers that use *-pattern property and add // constant pattern dependencies. if (!patternProperty.isConstant()) { hasPattern = true; - } else if (!constantPattern.to.empty()){ + } else if (!constantPattern.to.id().empty()) { hasPattern = true; - patternDependencies.emplace(constantPattern.to, ImageType::Pattern); - patternDependencies.emplace(constantPattern.from, ImageType::Pattern); + layoutParameters.imageDependencies.emplace(constantPattern.to.id(), ImageType::Pattern); + layoutParameters.imageDependencies.emplace(constantPattern.from.id(), ImageType::Pattern); } layerPropertiesMap.emplace(layerId, layerProperties); } @@ -77,15 +78,22 @@ public: if (!patternProperty.isConstant()) { // For layers with non-data-constant pattern properties, evaluate their expression and add // the patterns to the dependency vector - const auto min = patternProperty.evaluate(*feature, zoom - 1, PatternPropertyType::defaultValue()); - const auto mid = patternProperty.evaluate(*feature, zoom, PatternPropertyType::defaultValue()); - const auto max = patternProperty.evaluate(*feature, zoom + 1, PatternPropertyType::defaultValue()); - - patternDependencies.emplace(min.to, ImageType::Pattern); - patternDependencies.emplace(mid.to, ImageType::Pattern); - patternDependencies.emplace(max.to, ImageType::Pattern); - patternDependencyMap.emplace(layerId, PatternDependency {min.to, mid.to, max.to}); - + const auto min = patternProperty.evaluate(*feature, + zoom - 1, + layoutParameters.availableImages, + PatternPropertyType::defaultValue()); + const auto mid = patternProperty.evaluate( + *feature, zoom, layoutParameters.availableImages, PatternPropertyType::defaultValue()); + const auto max = patternProperty.evaluate(*feature, + zoom + 1, + layoutParameters.availableImages, + PatternPropertyType::defaultValue()); + + layoutParameters.imageDependencies.emplace(min.to.id(), ImageType::Pattern); + layoutParameters.imageDependencies.emplace(mid.to.id(), ImageType::Pattern); + layoutParameters.imageDependencies.emplace(max.to.id(), ImageType::Pattern); + patternDependencyMap.emplace(layerId, + PatternDependency{min.to.id(), mid.to.id(), max.to.id()}); } } } diff --git a/src/mbgl/layout/symbol_feature.hpp b/src/mbgl/layout/symbol_feature.hpp index 03d8e5018d..d0aced1b19 100644 --- a/src/mbgl/layout/symbol_feature.hpp +++ b/src/mbgl/layout/symbol_feature.hpp @@ -1,8 +1,9 @@ #pragma once +#include <mbgl/style/expression/image.hpp> +#include <mbgl/text/tagged_string.hpp> #include <mbgl/tile/geometry_tile_data.hpp> #include <mbgl/util/optional.hpp> -#include <mbgl/text/tagged_string.hpp> #include <array> #include <string> @@ -29,7 +30,7 @@ public: std::unique_ptr<GeometryTileFeature> feature; GeometryCollection geometry; optional<TaggedString> formattedText; - optional<std::string> icon; + optional<style::expression::Image> icon; float sortKey = 0.0f; std::size_t index; bool allowsVerticalWritingMode = false; diff --git a/src/mbgl/layout/symbol_layout.cpp b/src/mbgl/layout/symbol_layout.cpp index d0227c36c5..af0b1bd21b 100644 --- a/src/mbgl/layout/symbol_layout.cpp +++ b/src/mbgl/layout/symbol_layout.cpp @@ -81,8 +81,7 @@ inline Immutable<style::SymbolLayoutProperties::PossiblyEvaluated> createLayout( SymbolLayout::SymbolLayout(const BucketParameters& parameters, const std::vector<Immutable<style::LayerProperties>>& layers, std::unique_ptr<GeometryTileLayer> sourceLayer_, - ImageDependencies& imageDependencies, - GlyphDependencies& glyphDependencies) + const LayoutParameters& layoutParameters) : bucketLeaderID(layers.front()->baseImpl->id), sourceLayer(std::move(sourceLayer_)), overscaling(parameters.tileID.overscaleFactor()), @@ -141,7 +140,7 @@ SymbolLayout::SymbolLayout(const BucketParameters& parameters, ft.index = i; if (hasText) { - auto formatted = layout->evaluate<TextField>(zoom, ft); + auto formatted = layout->evaluate<TextField>(zoom, ft, layoutParameters.availableImages); auto textTransform = layout->evaluate<TextTransform>(zoom, ft); FontStack baseFontStack = layout->evaluate<TextFont>(zoom, ft); @@ -168,7 +167,8 @@ SymbolLayout::SymbolLayout(const BucketParameters& parameters, // Loop through all characters of this text and collect unique codepoints. for (std::size_t j = 0; j < ft.formattedText->length(); j++) { const auto& sectionFontStack = formatted.sections[ft.formattedText->getSectionIndex(j)].fontStack; - GlyphIDs& dependencies = glyphDependencies[sectionFontStack ? *sectionFontStack : baseFontStack]; + GlyphIDs& dependencies = + layoutParameters.glyphDependencies[sectionFontStack ? *sectionFontStack : baseFontStack]; char16_t codePoint = ft.formattedText->getCharCodeAt(j); dependencies.insert(codePoint); if (canVerticalizeText || (allowVerticalPlacement && ft.formattedText->allowsVerticalWritingMode())) { @@ -180,8 +180,8 @@ SymbolLayout::SymbolLayout(const BucketParameters& parameters, } if (hasIcon) { - ft.icon = layout->evaluate<IconImage>(zoom, ft); - imageDependencies.emplace(*ft.icon, ImageType::Icon); + ft.icon = layout->evaluate<IconImage>(zoom, ft, layoutParameters.availableImages); + layoutParameters.imageDependencies.emplace(ft.icon->id(), ImageType::Icon); } if (ft.formattedText || ft.icon) { @@ -448,14 +448,13 @@ void SymbolLayout::prepareSymbols(const GlyphMap& glyphMap, const GlyphPositions // if feature has icon, get sprite atlas position SymbolContent iconType{SymbolContent::None}; if (feature.icon) { - auto image = imageMap.find(*feature.icon); + auto image = imageMap.find(feature.icon->id()); if (image != imageMap.end()) { iconType = SymbolContent::IconRGBA; - shapedIcon = PositionedIcon::shapeIcon( - imagePositions.at(*feature.icon), - layout->evaluate<IconOffset>(zoom, feature), - layout->evaluate<IconAnchor>(zoom, feature), - layout->evaluate<IconRotate>(zoom, feature) * util::DEG2RAD); + shapedIcon = PositionedIcon::shapeIcon(imagePositions.at(feature.icon->id()), + layout->evaluate<IconOffset>(zoom, feature), + layout->evaluate<IconAnchor>(zoom, feature), + layout->evaluate<IconRotate>(zoom, feature) * util::DEG2RAD); if (image->second->sdf) { iconType = SymbolContent::IconSDF; } diff --git a/src/mbgl/layout/symbol_layout.hpp b/src/mbgl/layout/symbol_layout.hpp index 1abcaaa5d6..2b99c2fa24 100644 --- a/src/mbgl/layout/symbol_layout.hpp +++ b/src/mbgl/layout/symbol_layout.hpp @@ -27,9 +27,8 @@ public: SymbolLayout(const BucketParameters&, const std::vector<Immutable<style::LayerProperties>>&, std::unique_ptr<GeometryTileLayer>, - ImageDependencies&, - GlyphDependencies&); - + const LayoutParameters& parameters); + ~SymbolLayout() final = default; void prepareSymbols(const GlyphMap&, const GlyphPositions&, diff --git a/src/mbgl/renderer/cross_faded_property_evaluator.cpp b/src/mbgl/renderer/cross_faded_property_evaluator.cpp index 7be9c2bcf5..65f5b31467 100644 --- a/src/mbgl/renderer/cross_faded_property_evaluator.cpp +++ b/src/mbgl/renderer/cross_faded_property_evaluator.cpp @@ -1,4 +1,5 @@ #include <mbgl/renderer/cross_faded_property_evaluator.hpp> +#include <mbgl/style/expression/image.hpp> #include <mbgl/util/chrono.hpp> #include <cmath> @@ -30,7 +31,7 @@ Faded<T> CrossFadedPropertyEvaluator<T>::calculate(const T& min, const T& mid, c : Faded<T> { max, mid }; } -template class CrossFadedPropertyEvaluator<std::string>; +template class CrossFadedPropertyEvaluator<style::expression::Image>; template class CrossFadedPropertyEvaluator<std::vector<float>>; } // namespace mbgl diff --git a/src/mbgl/renderer/data_driven_property_evaluator.hpp b/src/mbgl/renderer/data_driven_property_evaluator.hpp index efac9e4532..c2e6d9f283 100644 --- a/src/mbgl/renderer/data_driven_property_evaluator.hpp +++ b/src/mbgl/renderer/data_driven_property_evaluator.hpp @@ -26,14 +26,14 @@ public: ResultType operator()(const style::PropertyExpression<T>& expression) const { if (useIntegerZoom) { // Compiler will optimize out the unused branch. - if (!expression.isFeatureConstant()) { + if (!expression.isFeatureConstant() || !expression.isRuntimeConstant()) { auto returnExpression = expression; returnExpression.useIntegerZoom = true; return ResultType(returnExpression); - } + } return ResultType(expression.evaluate(floor(parameters.z))); } else { - if (!expression.isFeatureConstant()) { + if (!expression.isFeatureConstant() || !expression.isRuntimeConstant()) { return ResultType(expression); } return ResultType(expression.evaluate(parameters.z)); @@ -63,7 +63,7 @@ public: } ResultType operator()(const style::PropertyExpression<T>& expression) const { - if (!expression.isFeatureConstant()) { + if (!expression.isFeatureConstant() || !expression.isRuntimeConstant()) { return ResultType(expression); } else { const T evaluated = expression.evaluate(floor(parameters.z)); diff --git a/src/mbgl/renderer/image_manager.cpp b/src/mbgl/renderer/image_manager.cpp index 2ea753d8aa..4927ade8e9 100644 --- a/src/mbgl/renderer/image_manager.cpp +++ b/src/mbgl/renderer/image_manager.cpp @@ -43,6 +43,7 @@ void ImageManager::addImage(Immutable<style::Image::Impl> image_) { if (requestedImages.find(image_->id) != requestedImages.end()) { requestedImagesCacheSize += image_->image.bytes(); } + availableImages.emplace(image_->id); images.emplace(image_->id, std::move(image_)); } @@ -81,6 +82,7 @@ void ImageManager::removeImage(const std::string& id) { requestedImages.erase(requestedIt); } images.erase(it); + availableImages.erase(id); updatedImageVersions.erase(id); } @@ -169,6 +171,10 @@ void ImageManager::reduceMemoryUseIfCacheSizeExceedsLimit() { } } +const std::set<std::string>& ImageManager::getAvailableImages() const { + return availableImages; +} + void ImageManager::checkMissingAndNotify(ImageRequestor& requestor, const ImageRequestPair& pair) { ImageDependencies missingDependencies; diff --git a/src/mbgl/renderer/image_manager.hpp b/src/mbgl/renderer/image_manager.hpp index 5ed6e237f0..7d5884edc1 100644 --- a/src/mbgl/renderer/image_manager.hpp +++ b/src/mbgl/renderer/image_manager.hpp @@ -47,6 +47,7 @@ public: void notifyIfMissingImageAdded(); void reduceMemoryUse(); void reduceMemoryUseIfCacheSizeExceedsLimit(); + const std::set<std::string>& getAvailableImages() const; ImageVersionMap updatedImageVersions; @@ -62,6 +63,8 @@ private: std::map<std::string, std::set<ImageRequestor*>> requestedImages; std::size_t requestedImagesCacheSize = 0ul; ImageMap images; + // Mirror of 'ImageMap images;' keys. + std::set<std::string> availableImages; ImageManagerObserver* observer = nullptr; }; diff --git a/src/mbgl/renderer/layers/render_background_layer.cpp b/src/mbgl/renderer/layers/render_background_layer.cpp index 6f76efda7a..694addcc97 100644 --- a/src/mbgl/renderer/layers/render_background_layer.cpp +++ b/src/mbgl/renderer/layers/render_background_layer.cpp @@ -105,8 +105,10 @@ void RenderBackgroundLayer::render(PaintParameters& parameters) { const auto& evaluated = static_cast<const BackgroundLayerProperties&>(*evaluatedProperties).evaluated; const auto& crossfade = static_cast<const BackgroundLayerProperties&>(*evaluatedProperties).crossfade; if (!evaluated.get<BackgroundPattern>().to.empty()) { - optional<ImagePosition> imagePosA = parameters.patternAtlas.getPattern(evaluated.get<BackgroundPattern>().from); - optional<ImagePosition> imagePosB = parameters.patternAtlas.getPattern(evaluated.get<BackgroundPattern>().to); + optional<ImagePosition> imagePosA = + parameters.patternAtlas.getPattern(evaluated.get<BackgroundPattern>().from.id()); + optional<ImagePosition> imagePosB = + parameters.patternAtlas.getPattern(evaluated.get<BackgroundPattern>().to.id()); if (!imagePosA || !imagePosB) return; @@ -176,8 +178,8 @@ void RenderBackgroundLayer::prepare(const LayerPrepareParameters& params) { if (!evaluated.get<BackgroundPattern>().to.empty()) { // Ensures that the pattern bitmap gets copied to atlas bitmap. // Atlas bitmap is uploaded to atlas texture in upload. - addPatternIfNeeded(evaluated.get<BackgroundPattern>().from, params); - addPatternIfNeeded(evaluated.get<BackgroundPattern>().to, params); + addPatternIfNeeded(evaluated.get<BackgroundPattern>().from.id(), params); + addPatternIfNeeded(evaluated.get<BackgroundPattern>().to.id(), params); } } diff --git a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp index fc830e462c..af0bc788d0 100644 --- a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp +++ b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp @@ -1,20 +1,21 @@ -#include <mbgl/renderer/layers/render_fill_extrusion_layer.hpp> +#include <mbgl/geometry/feature_index.hpp> +#include <mbgl/gfx/cull_face_mode.hpp> +#include <mbgl/gfx/render_pass.hpp> +#include <mbgl/gfx/renderer_backend.hpp> +#include <mbgl/programs/fill_extrusion_program.hpp> +#include <mbgl/programs/programs.hpp> #include <mbgl/renderer/buckets/fill_extrusion_bucket.hpp> -#include <mbgl/renderer/render_tile.hpp> -#include <mbgl/renderer/paint_parameters.hpp> #include <mbgl/renderer/image_manager.hpp> +#include <mbgl/renderer/layers/render_fill_extrusion_layer.hpp> +#include <mbgl/renderer/paint_parameters.hpp> #include <mbgl/renderer/render_static_data.hpp> -#include <mbgl/programs/programs.hpp> -#include <mbgl/programs/fill_extrusion_program.hpp> -#include <mbgl/tile/tile.hpp> +#include <mbgl/renderer/render_tile.hpp> +#include <mbgl/style/expression/image.hpp> #include <mbgl/style/layers/fill_extrusion_layer_impl.hpp> -#include <mbgl/geometry/feature_index.hpp> -#include <mbgl/util/math.hpp> -#include <mbgl/util/intersection_tests.hpp> #include <mbgl/tile/geometry_tile.hpp> -#include <mbgl/gfx/renderer_backend.hpp> -#include <mbgl/gfx/render_pass.hpp> -#include <mbgl/gfx/cull_face_mode.hpp> +#include <mbgl/tile/tile.hpp> +#include <mbgl/util/intersection_tests.hpp> +#include <mbgl/util/math.hpp> namespace mbgl { @@ -171,7 +172,8 @@ void RenderFillExtrusionLayer::render(PaintParameters& parameters) { } } else { // Draw textured extrusions - const auto fillPatternValue = evaluated.get<FillExtrusionPattern>().constantOr(mbgl::Faded<std::basic_string<char> >{"", ""}); + const auto fillPatternValue = + evaluated.get<FillExtrusionPattern>().constantOr(mbgl::Faded<expression::Image>{"", ""}); auto drawTiles = [&](const gfx::StencilMode& stencilMode_, const gfx::ColorMode& colorMode_, const std::string& name) { for (const RenderTile& tile : *renderTiles) { const LayerRenderData* renderData = getRenderDataForPass(tile, parameters.pass); @@ -179,8 +181,8 @@ void RenderFillExtrusionLayer::render(PaintParameters& parameters) { continue; } auto& bucket = static_cast<FillExtrusionBucket&>(*renderData->bucket); - optional<ImagePosition> patternPosA = tile.getPattern(fillPatternValue.from); - optional<ImagePosition> patternPosB = tile.getPattern(fillPatternValue.to); + optional<ImagePosition> patternPosA = tile.getPattern(fillPatternValue.from.id()); + optional<ImagePosition> patternPosB = tile.getPattern(fillPatternValue.to.id()); draw( parameters.programs.getFillExtrusionLayerPrograms().fillExtrusionPattern, diff --git a/src/mbgl/renderer/layers/render_fill_layer.cpp b/src/mbgl/renderer/layers/render_fill_layer.cpp index e855866eea..bbfcef7aba 100644 --- a/src/mbgl/renderer/layers/render_fill_layer.cpp +++ b/src/mbgl/renderer/layers/render_fill_layer.cpp @@ -1,21 +1,22 @@ -#include <mbgl/renderer/layers/render_fill_layer.hpp> -#include <mbgl/renderer/buckets/fill_bucket.hpp> -#include <mbgl/renderer/render_tile.hpp> -#include <mbgl/renderer/render_source.hpp> -#include <mbgl/renderer/paint_parameters.hpp> -#include <mbgl/renderer/image_manager.hpp> -#include <mbgl/programs/programs.hpp> -#include <mbgl/programs/fill_program.hpp> -#include <mbgl/tile/tile.hpp> -#include <mbgl/style/layers/fill_layer_impl.hpp> #include <mbgl/geometry/feature_index.hpp> -#include <mbgl/gfx/renderer_backend.hpp> -#include <mbgl/gfx/cull_face_mode.hpp> #include <mbgl/gfx/context.hpp> +#include <mbgl/gfx/cull_face_mode.hpp> #include <mbgl/gfx/renderable.hpp> -#include <mbgl/util/math.hpp> -#include <mbgl/util/intersection_tests.hpp> +#include <mbgl/gfx/renderer_backend.hpp> +#include <mbgl/programs/fill_program.hpp> +#include <mbgl/programs/programs.hpp> +#include <mbgl/renderer/buckets/fill_bucket.hpp> +#include <mbgl/renderer/image_manager.hpp> +#include <mbgl/renderer/layers/render_fill_layer.hpp> +#include <mbgl/renderer/paint_parameters.hpp> +#include <mbgl/renderer/render_source.hpp> +#include <mbgl/renderer/render_tile.hpp> +#include <mbgl/style/expression/image.hpp> +#include <mbgl/style/layers/fill_layer_impl.hpp> #include <mbgl/tile/geometry_tile.hpp> +#include <mbgl/tile/tile.hpp> +#include <mbgl/util/intersection_tests.hpp> +#include <mbgl/util/math.hpp> namespace mbgl { @@ -171,9 +172,9 @@ void RenderFillLayer::render(PaintParameters& parameters) { const auto& evaluated = getEvaluated<FillLayerProperties>(renderData->layerProperties); const auto& crossfade = getCrossfade<FillLayerProperties>(renderData->layerProperties); - const auto& fillPatternValue = evaluated.get<FillPattern>().constantOr(Faded<std::basic_string<char>>{"", ""}); - optional<ImagePosition> patternPosA = tile.getPattern(fillPatternValue.from); - optional<ImagePosition> patternPosB = tile.getPattern(fillPatternValue.to); + const auto& fillPatternValue = evaluated.get<FillPattern>().constantOr(Faded<expression::Image>{"", ""}); + optional<ImagePosition> patternPosA = tile.getPattern(fillPatternValue.from.id()); + optional<ImagePosition> patternPosB = tile.getPattern(fillPatternValue.to.id()); auto draw = [&] (auto& programInstance, const auto& drawMode, diff --git a/src/mbgl/renderer/layers/render_line_layer.cpp b/src/mbgl/renderer/layers/render_line_layer.cpp index e5bbe74bf9..588cf6286c 100644 --- a/src/mbgl/renderer/layers/render_line_layer.cpp +++ b/src/mbgl/renderer/layers/render_line_layer.cpp @@ -1,20 +1,21 @@ -#include <mbgl/renderer/layers/render_line_layer.hpp> +#include <mbgl/geometry/feature_index.hpp> +#include <mbgl/geometry/line_atlas.hpp> +#include <mbgl/gfx/cull_face_mode.hpp> +#include <mbgl/programs/line_program.hpp> +#include <mbgl/programs/programs.hpp> #include <mbgl/renderer/buckets/line_bucket.hpp> -#include <mbgl/renderer/render_tile.hpp> +#include <mbgl/renderer/image_manager.hpp> +#include <mbgl/renderer/layers/render_line_layer.hpp> +#include <mbgl/renderer/paint_parameters.hpp> #include <mbgl/renderer/render_source.hpp> +#include <mbgl/renderer/render_tile.hpp> #include <mbgl/renderer/upload_parameters.hpp> -#include <mbgl/renderer/paint_parameters.hpp> -#include <mbgl/renderer/image_manager.hpp> -#include <mbgl/programs/programs.hpp> -#include <mbgl/programs/line_program.hpp> -#include <mbgl/geometry/line_atlas.hpp> -#include <mbgl/tile/tile.hpp> +#include <mbgl/style/expression/image.hpp> #include <mbgl/style/layers/line_layer_impl.hpp> -#include <mbgl/gfx/cull_face_mode.hpp> -#include <mbgl/geometry/feature_index.hpp> -#include <mbgl/util/math.hpp> -#include <mbgl/util/intersection_tests.hpp> #include <mbgl/tile/geometry_tile.hpp> +#include <mbgl/tile/tile.hpp> +#include <mbgl/util/intersection_tests.hpp> +#include <mbgl/util/math.hpp> namespace mbgl { @@ -168,11 +169,11 @@ void RenderLineLayer::render(PaintParameters& parameters) { }); } else if (!unevaluated.get<LinePattern>().isUndefined()) { - const auto& linePatternValue = evaluated.get<LinePattern>().constantOr(Faded<std::basic_string<char>>{ "", ""}); + const auto& linePatternValue = evaluated.get<LinePattern>().constantOr(Faded<expression::Image>{"", ""}); const Size& texsize = tile.getIconAtlasTexture().size; - optional<ImagePosition> posA = tile.getPattern(linePatternValue.from); - optional<ImagePosition> posB = tile.getPattern(linePatternValue.to); + optional<ImagePosition> posA = tile.getPattern(linePatternValue.from.id()); + optional<ImagePosition> posB = tile.getPattern(linePatternValue.to.id()); draw(parameters.programs.getLineLayerPrograms().linePattern, LinePatternProgram::layoutUniformValues( diff --git a/src/mbgl/renderer/possibly_evaluated_property_value.hpp b/src/mbgl/renderer/possibly_evaluated_property_value.hpp index 1198e43aae..5e412855a4 100644 --- a/src/mbgl/renderer/possibly_evaluated_property_value.hpp +++ b/src/mbgl/renderer/possibly_evaluated_property_value.hpp @@ -93,16 +93,19 @@ public: } template <class Feature> - Faded<T> evaluate(const Feature& feature, float zoom, T defaultValue) const { + Faded<T> evaluate(const Feature& feature, + float zoom, + const std::set<std::string>& availableImages, + T defaultValue) const { return this->match( [&] (const Faded<T>& constant_) { return constant_; }, [&] (const style::PropertyExpression<T>& expression) { if (!expression.isZoomConstant()) { - const T min = expression.evaluate(floor(zoom), feature, defaultValue); - const T max = expression.evaluate(floor(zoom) + 1, feature, defaultValue); + const T min = expression.evaluate(floor(zoom), feature, availableImages, defaultValue); + const T max = expression.evaluate(floor(zoom) + 1, feature, availableImages, defaultValue); return Faded<T> {min, max}; } else { - const T evaluated = expression.evaluate(feature, defaultValue); + const T evaluated = expression.evaluate(feature, availableImages, defaultValue); return Faded<T> {evaluated, evaluated}; } } diff --git a/src/mbgl/style/conversion/function.cpp b/src/mbgl/style/conversion/function.cpp index 646c1983a2..4b3b8f6c6a 100644 --- a/src/mbgl/style/conversion/function.cpp +++ b/src/mbgl/style/conversion/function.cpp @@ -1,13 +1,14 @@ #include <mbgl/style/conversion/function.hpp> #include <mbgl/style/conversion/position.hpp> #include <mbgl/style/conversion_impl.hpp> +#include <mbgl/style/expression/case.hpp> #include <mbgl/style/expression/dsl.hpp> #include <mbgl/style/expression/dsl_impl.hpp> -#include <mbgl/style/expression/step.hpp> +#include <mbgl/style/expression/format_expression.hpp> +#include <mbgl/style/expression/image_expression.hpp> #include <mbgl/style/expression/interpolate.hpp> #include <mbgl/style/expression/match.hpp> -#include <mbgl/style/expression/case.hpp> -#include <mbgl/style/expression/format_expression.hpp> +#include <mbgl/style/expression/step.hpp> #include <mbgl/util/string.hpp> #include <cassert> @@ -46,6 +47,10 @@ std::unique_ptr<Expression> convertTokenStringToFormatExpression(const std::stri return std::make_unique<FormatExpression>(sections); } +std::unique_ptr<Expression> convertTokenStringToImageExpression(const std::string& source) { + return std::make_unique<ImageExpression>(convertTokenStringToExpression(source)); +} + std::unique_ptr<Expression> convertTokenStringToExpression(const std::string& source) { std::vector<std::unique_ptr<Expression>> inputs; @@ -149,11 +154,11 @@ template optional<PropertyExpression<TextTransformType>> convertFunctionToExpression<TextTransformType>(const Convertible&, Error&, bool); template optional<PropertyExpression<TranslateAnchorType>> convertFunctionToExpression<TranslateAnchorType>(const Convertible&, Error&, bool); - template optional<PropertyExpression<Formatted>> convertFunctionToExpression<Formatted>(const Convertible&, Error&, bool); template optional<PropertyExpression<std::vector<TextWritingModeType>>> convertFunctionToExpression<std::vector<TextWritingModeType>>(const Convertible&, Error&, bool); +template optional<PropertyExpression<Image>> convertFunctionToExpression<Image>(const Convertible&, Error&, bool); // Ad-hoc Converters for double and int64_t. We should replace float with double wholesale, // and promote the int64_t Converter to general use (and it should check that the input is @@ -207,35 +212,35 @@ static bool interpolatable(type::Type type) { static optional<std::unique_ptr<Expression>> convertLiteral(type::Type type, const Convertible& value, Error& error, bool convertTokens = false) { return type.match( - [&] (const type::NumberType&) -> optional<std::unique_ptr<Expression>> { + [&](const type::NumberType&) -> optional<std::unique_ptr<Expression>> { auto result = convert<float>(value, error); if (!result) { return nullopt; } return literal(double(*result)); }, - [&] (const type::BooleanType&) -> optional<std::unique_ptr<Expression>> { + [&](const type::BooleanType&) -> optional<std::unique_ptr<Expression>> { auto result = convert<bool>(value, error); if (!result) { return nullopt; } return literal(*result); }, - [&] (const type::StringType&) -> optional<std::unique_ptr<Expression>> { + [&](const type::StringType&) -> optional<std::unique_ptr<Expression>> { auto result = convert<std::string>(value, error); if (!result) { return nullopt; } return convertTokens ? convertTokenStringToExpression(*result) : literal(*result); }, - [&] (const type::ColorType&) -> optional<std::unique_ptr<Expression>> { + [&](const type::ColorType&) -> optional<std::unique_ptr<Expression>> { auto result = convert<Color>(value, error); if (!result) { return nullopt; } return literal(*result); }, - [&] (const type::Array& array) -> optional<std::unique_ptr<Expression>> { + [&](const type::Array& array) -> optional<std::unique_ptr<Expression>> { if (!isArray(value)) { error.message = "value must be an array"; return nullopt; @@ -277,27 +282,27 @@ static optional<std::unique_ptr<Expression>> convertLiteral(type::Type type, con } ); }, - [&] (const type::NullType&) -> optional<std::unique_ptr<Expression>> { + [&](const type::NullType&) -> optional<std::unique_ptr<Expression>> { assert(false); // No properties use this type. return nullopt; }, - [&] (const type::ObjectType&) -> optional<std::unique_ptr<Expression>> { + [&](const type::ObjectType&) -> optional<std::unique_ptr<Expression>> { assert(false); // No properties use this type. return nullopt; }, - [&] (const type::ErrorType&) -> optional<std::unique_ptr<Expression>> { + [&](const type::ErrorType&) -> optional<std::unique_ptr<Expression>> { assert(false); // No properties use this type. return nullopt; }, - [&] (const type::ValueType&) -> optional<std::unique_ptr<Expression>> { + [&](const type::ValueType&) -> optional<std::unique_ptr<Expression>> { assert(false); // No properties use this type. return nullopt; }, - [&] (const type::CollatorType&) -> optional<std::unique_ptr<Expression>> { + [&](const type::CollatorType&) -> optional<std::unique_ptr<Expression>> { assert(false); // No properties use this type. return nullopt; }, - [&] (const type::FormattedType&) -> optional<std::unique_ptr<Expression>> { + [&](const type::FormattedType&) -> optional<std::unique_ptr<Expression>> { auto result = convert<std::string>(value, error); if (!result) { return nullopt; @@ -305,8 +310,15 @@ static optional<std::unique_ptr<Expression>> convertLiteral(type::Type type, con return convertTokens ? convertTokenStringToFormatExpression(*result) : literal(Formatted(result->c_str())); - } - ); + }, + [&](const type::ImageType&) -> optional<std::unique_ptr<Expression>> { + auto result = convert<std::string>(value, error); + if (!result) { + return nullopt; + } + return convertTokens ? std::make_unique<ImageExpression>(convertTokenStringToImageExpression(*result)) + : literal(Image(result->c_str())); + }); } static optional<std::map<double, std::unique_ptr<Expression>>> convertStops(type::Type type, @@ -749,29 +761,31 @@ optional<std::unique_ptr<Expression>> convertFunctionToExpression(type::Type typ if (functionType == FunctionType::Identity) { return type.match( - [&] (const type::StringType&) -> optional<std::unique_ptr<Expression>> { + [&](const type::StringType&) -> optional<std::unique_ptr<Expression>> { return string(get(literal(*property)), defaultExpr()); }, - [&] (const type::NumberType&) -> optional<std::unique_ptr<Expression>> { + [&](const type::NumberType&) -> optional<std::unique_ptr<Expression>> { return number(get(literal(*property)), defaultExpr()); }, - [&] (const type::BooleanType&) -> optional<std::unique_ptr<Expression>> { + [&](const type::BooleanType&) -> optional<std::unique_ptr<Expression>> { return boolean(get(literal(*property)), defaultExpr()); }, - [&] (const type::ColorType&) -> optional<std::unique_ptr<Expression>> { + [&](const type::ColorType&) -> optional<std::unique_ptr<Expression>> { return toColor(get(literal(*property)), defaultExpr()); }, - [&] (const type::Array& array) -> optional<std::unique_ptr<Expression>> { + [&](const type::Array& array) -> optional<std::unique_ptr<Expression>> { return assertion(array, get(literal(*property)), defaultExpr()); }, - [&] (const type::FormattedType&) -> optional<std::unique_ptr<Expression>> { + [&](const type::FormattedType&) -> optional<std::unique_ptr<Expression>> { return toFormatted(get(literal(*property)), defaultExpr()); }, - [&] (const auto&) -> optional<std::unique_ptr<Expression>> { + [&](const type::ImageType&) -> optional<std::unique_ptr<Expression>> { + return toImage(get(literal(*property)), defaultExpr()); + }, + [&](const auto&) -> optional<std::unique_ptr<Expression>> { assert(false); // No properties use this type. return nullopt; - } - ); + }); } auto stopsValue = objectMember(value, "stops"); diff --git a/src/mbgl/style/conversion/property_value.cpp b/src/mbgl/style/conversion/property_value.cpp index 5c2f720a60..5e03189e64 100644 --- a/src/mbgl/style/conversion/property_value.cpp +++ b/src/mbgl/style/conversion/property_value.cpp @@ -39,7 +39,8 @@ optional<PropertyValue<T>> Converter<PropertyValue<T>>::operator()(const Convert } else if (!allowDataExpressions && !(*expression).isFeatureConstant()) { error.message = "data expressions not supported"; return nullopt; - } else if (!(*expression).isFeatureConstant() || !(*expression).isZoomConstant()) { + } else if (!(*expression).isFeatureConstant() || !(*expression).isZoomConstant() || + !(*expression).isRuntimeConstant()) { return { std::move(*expression) }; } else if ((*expression).getExpression().getKind() == Kind::Literal) { optional<T> constant = fromExpressionValue<T>( @@ -81,6 +82,11 @@ template optional<PropertyValue<TextTransformType>> Converter<PropertyValue<Text template optional<PropertyValue<TranslateAnchorType>> Converter<PropertyValue<TranslateAnchorType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const; template optional<PropertyValue<mbgl::style::expression::Formatted>> Converter<PropertyValue<mbgl::style::expression::Formatted>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const; template optional<PropertyValue<std::vector<TextWritingModeType>>> Converter<PropertyValue<std::vector<TextWritingModeType>>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const; +template optional<PropertyValue<mbgl::style::expression::Image>> +Converter<PropertyValue<mbgl::style::expression::Image>>::operator()(conversion::Convertible const&, + conversion::Error&, + bool, + bool) const; } // namespace conversion } // namespace style diff --git a/src/mbgl/style/conversion/stringify.hpp b/src/mbgl/style/conversion/stringify.hpp index 7520bcac9c..3816182450 100644 --- a/src/mbgl/style/conversion/stringify.hpp +++ b/src/mbgl/style/conversion/stringify.hpp @@ -142,6 +142,11 @@ void stringify(Writer& writer, const expression::Formatted& v) { } template <class Writer> +void stringify(Writer& writer, const expression::Image& v) { + stringify(writer, expression::ValueConverter<mbgl::Value>::fromExpressionValue(v)); +} + +template <class Writer> void stringify(Writer& writer, const Undefined&) { assert(false); // Should be omitted entirely instead. writer.Null(); diff --git a/src/mbgl/style/expression/check_subtype.cpp b/src/mbgl/style/expression/check_subtype.cpp index 73e6e3bff7..9895bce667 100644 --- a/src/mbgl/style/expression/check_subtype.cpp +++ b/src/mbgl/style/expression/check_subtype.cpp @@ -32,18 +32,9 @@ optional<std::string> checkSubtype(const Type& expected, const Type& t) { }, [&] (const ValueType&) -> optional<std::string> { if (t.is<ValueType>()) return {}; - - const Type members[] = { - Null, - Boolean, - Number, - String, - Object, - Color, - Formatted, - Array(Value) - }; - + + const Type members[] = {Null, Boolean, Number, String, Object, Color, Formatted, Image, Array(Value)}; + for (const auto& member : members) { const auto err = checkSubtype(member, t); if (!err) { diff --git a/src/mbgl/style/expression/coalesce.cpp b/src/mbgl/style/expression/coalesce.cpp index 6b43e68ac6..ab30e7a8df 100644 --- a/src/mbgl/style/expression/coalesce.cpp +++ b/src/mbgl/style/expression/coalesce.cpp @@ -8,8 +8,22 @@ namespace expression { EvaluationResult Coalesce::evaluate(const EvaluationContext& params) const { EvaluationResult result = Null; + std::size_t argsCount = args.size(); + optional<Image> requestedImage; for (const auto& arg : args) { + --argsCount; result = arg->evaluate(params); + // We need to keep track of the first requested image in a coalesce statement. + // If coalesce can't find a valid image, we return the first requested image. + if (getType() == type::Image && result) { + const auto image = fromExpressionValue<Image>(*result); + if (image && !image->isAvailable()) { + if (!requestedImage) requestedImage = Image(image->id()); + if (!argsCount) result = *requestedImage; + continue; + } + } + if (!result || *result != Null) break; } return result; diff --git a/src/mbgl/style/expression/coercion.cpp b/src/mbgl/style/expression/coercion.cpp index 284d6f2e3e..d65558e28d 100644 --- a/src/mbgl/style/expression/coercion.cpp +++ b/src/mbgl/style/expression/coercion.cpp @@ -9,13 +9,12 @@ namespace style { namespace expression { EvaluationResult toBoolean(const Value& v) { - return v.match( - [&] (double f) { return static_cast<bool>(f); }, - [&] (const std::string& s) { return s.length() > 0; }, - [&] (bool b) { return b; }, - [&] (const NullValue&) { return false; }, - [&] (const auto&) { return true; } - ); + return v.match([&](double f) { return static_cast<bool>(f); }, + [&](const std::string& s) { return s.length() > 0; }, + [&](bool b) { return b; }, + [&](const NullValue&) { return false; }, + [&](const Image& i) { return i.isAvailable(); }, + [&](const auto&) { return true; }); } EvaluationResult toNumber(const Value& v) { @@ -86,6 +85,10 @@ EvaluationResult toFormatted(const Value& formattedValue) { return Formatted(toString(formattedValue).c_str()); } +EvaluationResult toImage(const Value& imageValue) { + return Image(toString(imageValue).c_str()); +} + Coercion::Coercion(type::Type type_, std::vector<std::unique_ptr<Expression>> inputs_) : Expression(Kind::Coercion, std::move(type_)), inputs(std::move(inputs_)) @@ -102,6 +105,8 @@ Coercion::Coercion(type::Type type_, std::vector<std::unique_ptr<Expression>> in coerceSingleValue = [] (const Value& v) -> EvaluationResult { return toString(v); }; } else if (t.is<type::FormattedType>()) { coerceSingleValue = toFormatted; + } else if (t.is<type::ImageType>()) { + coerceSingleValue = toImage; } else { assert(false); } @@ -115,6 +120,8 @@ mbgl::Value Coercion::serialize() const { serialized.push_back(inputs[0]->serialize()); serialized.emplace_back(std::unordered_map<std::string, mbgl::Value>()); return serialized; + } else if (getType().is<type::ImageType>()) { + return std::vector<mbgl::Value>{{std::string("image")}, inputs[0]->serialize()}; } else { return Expression::serialize(); } @@ -148,11 +155,13 @@ ParseResult Coercion::parse(const Convertible& value, ParsingContext& ctx) { auto it = types.find(*toString(arrayMember(value, 0))); assert(it != types.end()); - if ((it->second == type::Boolean || it->second == type::String || it->second == type::Formatted) && length != 2) { + if ((it->second == type::Boolean || it->second == type::String || it->second == type::Formatted || + it->second == type::Image) && + length != 2) { ctx.error("Expected one argument."); return ParseResult(); } - + /** * Special form for error-coalescing coercion expressions "to-number", * "to-color". Since these coercions can fail at runtime, they accept multiple diff --git a/src/mbgl/style/expression/dsl.cpp b/src/mbgl/style/expression/dsl.cpp index fac7dfbbd9..6405149fe9 100644 --- a/src/mbgl/style/expression/dsl.cpp +++ b/src/mbgl/style/expression/dsl.cpp @@ -1,14 +1,15 @@ -#include <mbgl/style/expression/dsl.hpp> -#include <mbgl/style/expression/dsl_impl.hpp> -#include <mbgl/style/expression/error.hpp> -#include <mbgl/style/expression/literal.hpp> #include <mbgl/style/expression/assertion.hpp> #include <mbgl/style/expression/coercion.hpp> #include <mbgl/style/expression/comparison.hpp> -#include <mbgl/style/expression/step.hpp> -#include <mbgl/style/expression/interpolate.hpp> #include <mbgl/style/expression/compound_expression.hpp> +#include <mbgl/style/expression/dsl.hpp> +#include <mbgl/style/expression/dsl_impl.hpp> +#include <mbgl/style/expression/error.hpp> #include <mbgl/style/expression/format_expression.hpp> +#include <mbgl/style/expression/image_expression.hpp> +#include <mbgl/style/expression/interpolate.hpp> +#include <mbgl/style/expression/literal.hpp> +#include <mbgl/style/expression/step.hpp> #include <mapbox/geojsonvt.hpp> #include <mbgl/style/conversion/json.hpp> @@ -122,7 +123,11 @@ std::unique_ptr<Expression> toFormatted(std::unique_ptr<Expression> value, std::unique_ptr<Expression> def) { return coercion(type::Formatted, std::move(value), std::move(def)); } - + +std::unique_ptr<Expression> toImage(std::unique_ptr<Expression> value, std::unique_ptr<Expression> def) { + return coercion(type::Image, std::move(value), std::move(def)); +} + std::unique_ptr<Expression> get(const char* value) { return get(literal(value)); } @@ -237,6 +242,14 @@ std::unique_ptr<Expression> format(std::unique_ptr<Expression> input) { return std::make_unique<FormatExpression>(sections); } +std::unique_ptr<Expression> image(const char* value) { + return std::make_unique<Literal>(Image(value)); +} + +std::unique_ptr<Expression> image(std::unique_ptr<Expression> expression) { + return std::make_unique<ImageExpression>(std::move(expression)); +} + } // namespace dsl } // namespace expression } // namespace style diff --git a/src/mbgl/style/expression/expression.cpp b/src/mbgl/style/expression/expression.cpp index 6bfda99064..3252bb632f 100644 --- a/src/mbgl/style/expression/expression.cpp +++ b/src/mbgl/style/expression/expression.cpp @@ -25,12 +25,22 @@ public: return optional<mbgl::Value>(); } }; - -EvaluationResult Expression::evaluate(optional<float> zoom, const Feature& feature, optional<double> colorRampParameter) const { + +EvaluationResult Expression::evaluate(optional<float> zoom, + const Feature& feature, + optional<double> colorRampParameter) const { GeoJSONFeature f(feature); return this->evaluate(EvaluationContext(zoom, &f, colorRampParameter)); } +EvaluationResult Expression::evaluate(optional<float> zoom, + const Feature& feature, + optional<double> colorRampParameter, + const std::set<std::string>& availableImages) const { + GeoJSONFeature f(feature); + return this->evaluate(EvaluationContext(zoom, &f, colorRampParameter).withAvailableImages(&availableImages)); +} + EvaluationResult Expression::evaluate(optional<mbgl::Value> accumulated, const Feature& feature) const { GeoJSONFeature f(feature); return this->evaluate(EvaluationContext(accumulated, &f)); diff --git a/src/mbgl/style/expression/image.cpp b/src/mbgl/style/expression/image.cpp new file mode 100644 index 0000000000..1dc7acde56 --- /dev/null +++ b/src/mbgl/style/expression/image.cpp @@ -0,0 +1,67 @@ +#include <mbgl/style/conversion/constant.hpp> +#include <mbgl/style/conversion_impl.hpp> +#include <mbgl/style/expression/image.hpp> + +namespace mbgl { +namespace style { +namespace expression { + +Image::Image(std::string imageID_, bool available_) : imageID(std::move(imageID_)), available(available_) {} + +Image::Image(std::string imageID_) : Image(std::move(imageID_), false) {} + +Image::Image(const char* imageID_) : Image(std::string(imageID_)) { + assert(imageID_); +} + +bool Image::operator==(const Image& other) const { + return imageID == other.imageID && available == other.available; +} + +mbgl::Value Image::toValue() const { + return mapbox::base::ValueObject{{"name", imageID}, {"available", available}}; +} + +const std::string& Image::id() const { + return imageID; +} + +bool Image::isAvailable() const { + return available; +} + +bool Image::empty() const { + return imageID.empty(); +} + +} // namespace expression + +namespace conversion { +using namespace mbgl::style::expression; +optional<Image> Converter<Image>::operator()(const Convertible& value, Error& error) const { + if (isArray(value)) { + Convertible imageParameters = arrayMember(value, 0); + std::size_t imageParametersLength = arrayLength(imageParameters); + if (imageParametersLength < 1) { + error.message = "Image has to contain an ID."; + return nullopt; + } + + optional<std::string> imageID = toString(arrayMember(imageParameters, 0)); + if (!imageID) { + error.message = "Image has to contain an ID."; + return nullopt; + } + + return Image(*imageID, false); + } else if (optional<std::string> result = toString(value)) { + return Image(*result, false); + } else { + error.message = "Image must be plain string or array type."; + return nullopt; + } +} + +} // namespace conversion +} // namespace style +} // namespace mbgl diff --git a/src/mbgl/style/expression/image_expression.cpp b/src/mbgl/style/expression/image_expression.cpp new file mode 100644 index 0000000000..df535d4e81 --- /dev/null +++ b/src/mbgl/style/expression/image_expression.cpp @@ -0,0 +1,68 @@ +#include <mbgl/style/conversion_impl.hpp> +#include <mbgl/style/expression/image.hpp> +#include <mbgl/style/expression/image_expression.hpp> + +namespace mbgl { +namespace style { +namespace expression { + +ImageExpression::ImageExpression(std::unique_ptr<Expression> imageID_) + : Expression(Kind::ImageExpression, type::Image), imageID(std::move(imageID_)) { + assert(imageID); +} + +using namespace mbgl::style::conversion; + +ParseResult ImageExpression::parse(const Convertible& value, ParsingContext& ctx) { + std::size_t argsLength = arrayLength(value); + if (argsLength < 2) { + ctx.error("Invalid number of arguments for 'image' expression."); + return ParseResult(); + } + + // Parse expression that evaluates to image id. + auto imageIDArg = arrayMember(value, 1); + ParseResult imageIDExpr = ctx.parse(imageIDArg, 1, {type::String}); + if (!imageIDExpr) { + return ParseResult(); + } + + return ParseResult(std::make_unique<ImageExpression>(std::move(*imageIDExpr))); +} + +void ImageExpression::eachChild(const std::function<void(const Expression&)>& fn) const { + fn(*imageID); +} + +bool ImageExpression::operator==(const Expression& e) const { + if (e.getKind() == Kind::ImageExpression) { + auto rhs = static_cast<const ImageExpression*>(&e); + return *imageID == *rhs->imageID; + } + return false; +} + +mbgl::Value ImageExpression::serialize() const { + std::vector<mbgl::Value> serialized{{getOperator()}}; + serialized.push_back(imageID->serialize()); + return serialized; +} + +EvaluationResult ImageExpression::evaluate(const EvaluationContext& ctx) const { + auto imageIDResult = imageID->evaluate(ctx); + if (!imageIDResult) { + return imageIDResult.error(); + } + + optional<std::string> evaluatedImageID = toString(*imageIDResult); + if (!evaluatedImageID) { + return EvaluationError({"Could not evaluate ID for 'image' expression."}); + } + + bool available = ctx.availableImages && ctx.availableImages->count(*evaluatedImageID); + return Image(*evaluatedImageID, available); +} + +} // namespace expression +} // namespace style +} // namespace mbgl diff --git a/src/mbgl/style/expression/is_constant.cpp b/src/mbgl/style/expression/is_constant.cpp index 4c4684c86a..eb823bc77c 100644 --- a/src/mbgl/style/expression/is_constant.cpp +++ b/src/mbgl/style/expression/is_constant.cpp @@ -49,6 +49,19 @@ bool isZoomConstant(const Expression& e) { return isGlobalPropertyConstant(e, std::array<std::string, 1>{{"zoom"}}); } +bool isRuntimeConstant(const Expression& expression) { + if (expression.getKind() == Kind::ImageExpression) { + return false; + } + + bool runtimeConstant = true; + expression.eachChild([&](const Expression& e) { + if (runtimeConstant && !isRuntimeConstant(e)) { + runtimeConstant = false; + } + }); + return runtimeConstant; +} } // namespace expression } // namespace style diff --git a/src/mbgl/style/expression/parsing_context.cpp b/src/mbgl/style/expression/parsing_context.cpp index 699190608b..ae991b2e88 100644 --- a/src/mbgl/style/expression/parsing_context.cpp +++ b/src/mbgl/style/expression/parsing_context.cpp @@ -4,22 +4,23 @@ #include <mbgl/style/expression/is_constant.hpp> #include <mbgl/style/expression/type.hpp> -#include <mbgl/style/expression/expression.hpp> -#include <mbgl/style/expression/at.hpp> #include <mbgl/style/expression/assertion.hpp> +#include <mbgl/style/expression/at.hpp> #include <mbgl/style/expression/boolean_operator.hpp> #include <mbgl/style/expression/case.hpp> #include <mbgl/style/expression/coalesce.hpp> #include <mbgl/style/expression/coercion.hpp> -#include <mbgl/style/expression/compound_expression.hpp> #include <mbgl/style/expression/comparison.hpp> -#include <mbgl/style/expression/number_format.hpp> +#include <mbgl/style/expression/compound_expression.hpp> +#include <mbgl/style/expression/expression.hpp> #include <mbgl/style/expression/format_expression.hpp> +#include <mbgl/style/expression/image_expression.hpp> #include <mbgl/style/expression/interpolate.hpp> #include <mbgl/style/expression/length.hpp> #include <mbgl/style/expression/let.hpp> #include <mbgl/style/expression/literal.hpp> #include <mbgl/style/expression/match.hpp> +#include <mbgl/style/expression/number_format.hpp> #include <mbgl/style/expression/step.hpp> #include <mbgl/style/expression/find_zoom_curve.hpp> @@ -117,7 +118,7 @@ MAPBOX_ETERNAL_CONSTEXPR const auto expressionRegistry = {"coalesce", Coalesce::parse}, {"collator", CollatorExpression::parse}, {"format", FormatExpression::parse}, - {"image", Assertion::parse}, // TODO: replace once we implement image expressions + {"image", ImageExpression::parse}, {"interpolate", parseInterpolate}, {"length", Length::parse}, {"let", Let::parse}, @@ -193,7 +194,8 @@ ParseResult ParsingContext::parse(const Convertible& value, optional<TypeAnnotat const type::Type actual = (*parsed)->getType(); if ((*expected == type::String || *expected == type::Number || *expected == type::Boolean || *expected == type::Object || expected->is<type::Array>()) && actual == type::Value) { parsed = { annotate(std::move(*parsed), *expected, typeAnnotationOption.value_or(TypeAnnotationOption::assert)) }; - } else if ((*expected == type::Color || *expected == type::Formatted) && (actual == type::Value || actual == type::String)) { + } else if ((*expected == type::Color || *expected == type::Formatted || *expected == type::Image) && + (actual == type::Value || actual == type::String)) { parsed = { annotate(std::move(*parsed), *expected, typeAnnotationOption.value_or(TypeAnnotationOption::coerce)) }; } else { checkType((*parsed)->getType()); @@ -205,8 +207,9 @@ ParseResult ParsingContext::parse(const Convertible& value, optional<TypeAnnotat // If an expression's arguments are all constant, we can evaluate // it immediately and replace it with a literal value in the - // parsed result. - if ((*parsed)->getKind() != Kind::Literal && isConstant(**parsed)) { + // parsed/compiled result. Expressions that expect an image should + // not be resolved here so we can later get the available images. + if ((*parsed)->getKind() != Kind::Literal && (*parsed)->getType() != type::Image && isConstant(**parsed)) { EvaluationContext params(nullptr); EvaluationResult evaluated((*parsed)->evaluate(params)); if (!evaluated) { diff --git a/src/mbgl/style/expression/value.cpp b/src/mbgl/style/expression/value.cpp index 6d18f1b9bd..7609230b52 100644 --- a/src/mbgl/style/expression/value.cpp +++ b/src/mbgl/style/expression/value.cpp @@ -8,81 +8,78 @@ namespace style { namespace expression { type::Type typeOf(const Value& value) { - return value.match( - [&](bool) -> type::Type { return type::Boolean; }, - [&](double) -> type::Type { return type::Number; }, - [&](const std::string&) -> type::Type { return type::String; }, - [&](const Color&) -> type::Type { return type::Color; }, - [&](const Collator&) -> type::Type { return type::Collator; }, - [&](const Formatted&) -> type::Type { return type::Formatted; }, - [&](const NullValue&) -> type::Type { return type::Null; }, - [&](const std::unordered_map<std::string, Value>&) -> type::Type { return type::Object; }, - [&](const std::vector<Value>& arr) -> type::Type { - optional<type::Type> itemType; - for (const auto& item : arr) { - const type::Type t = typeOf(item); - if (!itemType) { - itemType = {t}; - } else if (*itemType == t) { - continue; - } else { - itemType = {type::Value}; - break; - } - } - - return type::Array(itemType.value_or(type::Value), arr.size()); - } - ); + return value.match([&](bool) -> type::Type { return type::Boolean; }, + [&](double) -> type::Type { return type::Number; }, + [&](const std::string&) -> type::Type { return type::String; }, + [&](const Color&) -> type::Type { return type::Color; }, + [&](const Collator&) -> type::Type { return type::Collator; }, + [&](const Formatted&) -> type::Type { return type::Formatted; }, + [&](const Image&) -> type::Type { return type::Image; }, + [&](const NullValue&) -> type::Type { return type::Null; }, + [&](const std::unordered_map<std::string, Value>&) -> type::Type { return type::Object; }, + [&](const std::vector<Value>& arr) -> type::Type { + optional<type::Type> itemType; + for (const auto& item : arr) { + const type::Type t = typeOf(item); + if (!itemType) { + itemType = {t}; + } else if (*itemType == t) { + continue; + } else { + itemType = {type::Value}; + break; + } + } + + return type::Array(itemType.value_or(type::Value), arr.size()); + }); } std::string toString(const Value& value) { - return value.match( - [](const NullValue&) { return std::string(); }, - [](const Color& c) { return c.stringify(); }, // avoid quoting - [](const Formatted& f) { return f.toString(); }, - [](const std::string& s) { return s; }, // avoid quoting - [](const auto& v_) { return stringify(v_); } - ); + return value.match([](const NullValue&) { return std::string(); }, + [](const Color& c) { return c.stringify(); }, // avoid quoting + [](const Formatted& f) { return f.toString(); }, + [](const Image& i) { return i.id(); }, + [](const std::string& s) { return s; }, // avoid quoting + [](const auto& v_) { return stringify(v_); }); } void writeJSON(rapidjson::Writer<rapidjson::StringBuffer>& writer, const Value& value) { - value.match( - [&] (const NullValue&) { writer.Null(); }, - [&] (bool b) { writer.Bool(b); }, - [&] (double f) { - // make sure integer values are stringified without trailing ".0". - f == std::floor(f) ? writer.Int(f) : writer.Double(f); - }, - [&] (const std::string& s) { writer.String(s); }, - [&] (const Color& c) { writer.String(c.stringify()); }, - [&] (const Collator&) { - // Collators are excluded from constant folding and there's no Literal parser - // for them so there shouldn't be any way to serialize this value. - assert(false); - }, - [&] (const Formatted& f) { - // `stringify` in turns calls ValueConverter::fromExpressionValue below - // Serialization strategy for Formatted objects is to return the constant - // expression that would generate them. - mbgl::style::conversion::stringify(writer, f); - }, - [&] (const std::vector<Value>& arr) { - writer.StartArray(); - for(const auto& item : arr) { - writeJSON(writer, item); - } - writer.EndArray(); - }, - [&] (const std::unordered_map<std::string, Value>& obj) { - writer.StartObject(); - for(const auto& entry : obj) { - writer.Key(entry.first.c_str()); - writeJSON(writer, entry.second); - } - writer.EndObject(); - } - ); + value.match([&](const NullValue&) { writer.Null(); }, + [&](bool b) { writer.Bool(b); }, + [&](double f) { + // make sure integer values are stringified without trailing ".0". + f == std::floor(f) ? writer.Int(f) : writer.Double(f); + }, + [&](const std::string& s) { writer.String(s); }, + [&](const Color& c) { writer.String(c.stringify()); }, + [&](const Collator&) { + // Collators are excluded from constant folding and there's no Literal parser + // for them so there shouldn't be any way to serialize this value. + assert(false); + }, + [&](const Formatted& f) { + // `stringify` in turns calls ValueConverter::fromExpressionValue below + // Serialization strategy for Formatted objects is to return the constant + // expression that would generate them. + mbgl::style::conversion::stringify(writer, f); + }, + [&](const Image& i) { mbgl::style::conversion::stringify(writer, i); }, + [&](const std::vector<Value>& arr) { + writer.StartArray(); + for (const auto& item : arr) { + writeJSON(writer, item); + } + writer.EndArray(); + }, + [&](const std::unordered_map<std::string, Value>& obj) { + writer.StartObject(); + for (const auto& entry : obj) { + writer.Key(entry.first.c_str()); + writeJSON(writer, entry.second); + } + writer.EndObject(); + }); } std::string stringify(const Value& value) { @@ -129,7 +126,7 @@ Value ValueConverter<mbgl::Value>::toExpressionValue(const mbgl::Value& value) { mbgl::Value ValueConverter<mbgl::Value>::fromExpressionValue(const Value& value) { return value.match( - [&](const Color& color)->mbgl::Value { + [&](const Color& color) -> mbgl::Value { std::array<double, 4> array = color.toArray(); return std::vector<mbgl::Value>{ std::string("rgba"), @@ -139,13 +136,13 @@ mbgl::Value ValueConverter<mbgl::Value>::fromExpressionValue(const Value& value) array[3], }; }, - [&](const Collator&)->mbgl::Value { + [&](const Collator&) -> mbgl::Value { // fromExpressionValue can't be used for Collator values, // because they have no meaningful representation as an mbgl::Value assert(false); return mbgl::Value(); }, - [&](const Formatted& formatted)->mbgl::Value { + [&](const Formatted& formatted) -> mbgl::Value { // Serialization strategy for Formatted objects is to return the constant // expression that would generate them. std::vector<mbgl::Value> serialized; @@ -175,7 +172,8 @@ mbgl::Value ValueConverter<mbgl::Value>::fromExpressionValue(const Value& value) } return serialized; }, - [&](const std::vector<Value>& values)->mbgl::Value { + [&](const Image& i) -> mbgl::Value { return i.toValue(); }, + [&](const std::vector<Value>& values) -> mbgl::Value { std::vector<mbgl::Value> converted; converted.reserve(values.size()); for (const Value& v : values) { @@ -183,7 +181,7 @@ mbgl::Value ValueConverter<mbgl::Value>::fromExpressionValue(const Value& value) } return converted; }, - [&](const std::unordered_map<std::string, Value>& values)->mbgl::Value { + [&](const std::unordered_map<std::string, Value>& values) -> mbgl::Value { std::unordered_map<std::string, mbgl::Value> converted; converted.reserve(values.size()); for(const auto& entry : values) { @@ -191,8 +189,7 @@ mbgl::Value ValueConverter<mbgl::Value>::fromExpressionValue(const Value& value) } return converted; }, - [&](const auto& a)->mbgl::Value { return a; } - ); + [&](const auto& a) -> mbgl::Value { return a; }); } Value ValueConverter<float>::toExpressionValue(const float value) { @@ -302,6 +299,10 @@ template <> type::Type valueTypeToExpressionType<std::string>() { return type::S template <> type::Type valueTypeToExpressionType<Color>() { return type::Color; } template <> type::Type valueTypeToExpressionType<Collator>() { return type::Collator; } template <> type::Type valueTypeToExpressionType<Formatted>() { return type::Formatted; } +template <> +type::Type valueTypeToExpressionType<Image>() { + return type::Image; +} template <> type::Type valueTypeToExpressionType<std::unordered_map<std::string, Value>>() { return type::Object; } template <> type::Type valueTypeToExpressionType<std::vector<Value>>() { return type::Array(type::Value); } diff --git a/src/mbgl/style/layers/background_layer.cpp b/src/mbgl/style/layers/background_layer.cpp index 9187784452..6629044018 100644 --- a/src/mbgl/style/layers/background_layer.cpp +++ b/src/mbgl/style/layers/background_layer.cpp @@ -64,7 +64,7 @@ void BackgroundLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringB // Paint properties PropertyValue<Color> BackgroundLayer::getDefaultBackgroundColor() { - return { Color::black() }; + return {Color::black()}; } const PropertyValue<Color>& BackgroundLayer::getBackgroundColor() const { @@ -91,7 +91,7 @@ TransitionOptions BackgroundLayer::getBackgroundColorTransition() const { } PropertyValue<float> BackgroundLayer::getDefaultBackgroundOpacity() { - return { 1 }; + return {1}; } const PropertyValue<float>& BackgroundLayer::getBackgroundOpacity() const { @@ -117,15 +117,15 @@ TransitionOptions BackgroundLayer::getBackgroundOpacityTransition() const { return impl().paint.template get<BackgroundOpacity>().options; } -PropertyValue<std::string> BackgroundLayer::getDefaultBackgroundPattern() { - return { "" }; +PropertyValue<expression::Image> BackgroundLayer::getDefaultBackgroundPattern() { + return {{}}; } -const PropertyValue<std::string>& BackgroundLayer::getBackgroundPattern() const { +const PropertyValue<expression::Image>& BackgroundLayer::getBackgroundPattern() const { return impl().paint.template get<BackgroundPattern>().value; } -void BackgroundLayer::setBackgroundPattern(const PropertyValue<std::string>& value) { +void BackgroundLayer::setBackgroundPattern(const PropertyValue<expression::Image>& value) { if (value == getBackgroundPattern()) return; auto impl_ = mutableImpl(); @@ -208,7 +208,8 @@ optional<Error> BackgroundLayer::setPaintProperty(const std::string& name, const if (property == Property::BackgroundPattern) { Error error; - optional<PropertyValue<std::string>> typedValue = convert<PropertyValue<std::string>>(value, error, false, false); + optional<PropertyValue<expression::Image>> typedValue = + convert<PropertyValue<expression::Image>>(value, error, false, false); if (!typedValue) { return error; } diff --git a/src/mbgl/style/layers/background_layer_properties.hpp b/src/mbgl/style/layers/background_layer_properties.hpp index 11328f78bb..b926295c00 100644 --- a/src/mbgl/style/layers/background_layer_properties.hpp +++ b/src/mbgl/style/layers/background_layer_properties.hpp @@ -24,8 +24,8 @@ struct BackgroundOpacity : PaintProperty<float> { static float defaultValue() { return 1; } }; -struct BackgroundPattern : CrossFadedPaintProperty<std::string> { - static std::string defaultValue() { return ""; } +struct BackgroundPattern : CrossFadedPaintProperty<expression::Image> { + static expression::Image defaultValue() { return {}; } }; class BackgroundPaintProperties : public Properties< diff --git a/src/mbgl/style/layers/circle_layer.cpp b/src/mbgl/style/layers/circle_layer.cpp index 145d76a9a8..619c58c366 100644 --- a/src/mbgl/style/layers/circle_layer.cpp +++ b/src/mbgl/style/layers/circle_layer.cpp @@ -64,7 +64,7 @@ void CircleLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffe // Paint properties PropertyValue<float> CircleLayer::getDefaultCircleBlur() { - return { 0 }; + return {0}; } const PropertyValue<float>& CircleLayer::getCircleBlur() const { @@ -91,7 +91,7 @@ TransitionOptions CircleLayer::getCircleBlurTransition() const { } PropertyValue<Color> CircleLayer::getDefaultCircleColor() { - return { Color::black() }; + return {Color::black()}; } const PropertyValue<Color>& CircleLayer::getCircleColor() const { @@ -118,7 +118,7 @@ TransitionOptions CircleLayer::getCircleColorTransition() const { } PropertyValue<float> CircleLayer::getDefaultCircleOpacity() { - return { 1 }; + return {1}; } const PropertyValue<float>& CircleLayer::getCircleOpacity() const { @@ -145,7 +145,7 @@ TransitionOptions CircleLayer::getCircleOpacityTransition() const { } PropertyValue<AlignmentType> CircleLayer::getDefaultCirclePitchAlignment() { - return { AlignmentType::Viewport }; + return {AlignmentType::Viewport}; } const PropertyValue<AlignmentType>& CircleLayer::getCirclePitchAlignment() const { @@ -172,7 +172,7 @@ TransitionOptions CircleLayer::getCirclePitchAlignmentTransition() const { } PropertyValue<CirclePitchScaleType> CircleLayer::getDefaultCirclePitchScale() { - return { CirclePitchScaleType::Map }; + return {CirclePitchScaleType::Map}; } const PropertyValue<CirclePitchScaleType>& CircleLayer::getCirclePitchScale() const { @@ -199,7 +199,7 @@ TransitionOptions CircleLayer::getCirclePitchScaleTransition() const { } PropertyValue<float> CircleLayer::getDefaultCircleRadius() { - return { 5 }; + return {5}; } const PropertyValue<float>& CircleLayer::getCircleRadius() const { @@ -226,7 +226,7 @@ TransitionOptions CircleLayer::getCircleRadiusTransition() const { } PropertyValue<Color> CircleLayer::getDefaultCircleStrokeColor() { - return { Color::black() }; + return {Color::black()}; } const PropertyValue<Color>& CircleLayer::getCircleStrokeColor() const { @@ -253,7 +253,7 @@ TransitionOptions CircleLayer::getCircleStrokeColorTransition() const { } PropertyValue<float> CircleLayer::getDefaultCircleStrokeOpacity() { - return { 1 }; + return {1}; } const PropertyValue<float>& CircleLayer::getCircleStrokeOpacity() const { @@ -280,7 +280,7 @@ TransitionOptions CircleLayer::getCircleStrokeOpacityTransition() const { } PropertyValue<float> CircleLayer::getDefaultCircleStrokeWidth() { - return { 0 }; + return {0}; } const PropertyValue<float>& CircleLayer::getCircleStrokeWidth() const { @@ -307,7 +307,7 @@ TransitionOptions CircleLayer::getCircleStrokeWidthTransition() const { } PropertyValue<std::array<float, 2>> CircleLayer::getDefaultCircleTranslate() { - return { {{ 0, 0 }} }; + return {{{0, 0}}}; } const PropertyValue<std::array<float, 2>>& CircleLayer::getCircleTranslate() const { @@ -334,7 +334,7 @@ TransitionOptions CircleLayer::getCircleTranslateTransition() const { } PropertyValue<TranslateAnchorType> CircleLayer::getDefaultCircleTranslateAnchor() { - return { TranslateAnchorType::Map }; + return {TranslateAnchorType::Map}; } const PropertyValue<TranslateAnchorType>& CircleLayer::getCircleTranslateAnchor() const { @@ -497,7 +497,8 @@ optional<Error> CircleLayer::setPaintProperty(const std::string& name, const Con if (property == Property::CirclePitchScale) { Error error; - optional<PropertyValue<CirclePitchScaleType>> typedValue = convert<PropertyValue<CirclePitchScaleType>>(value, error, false, false); + optional<PropertyValue<CirclePitchScaleType>> typedValue = + convert<PropertyValue<CirclePitchScaleType>>(value, error, false, false); if (!typedValue) { return error; } @@ -509,7 +510,8 @@ optional<Error> CircleLayer::setPaintProperty(const std::string& name, const Con if (property == Property::CircleTranslate) { Error error; - optional<PropertyValue<std::array<float, 2>>> typedValue = convert<PropertyValue<std::array<float, 2>>>(value, error, false, false); + optional<PropertyValue<std::array<float, 2>>> typedValue = + convert<PropertyValue<std::array<float, 2>>>(value, error, false, false); if (!typedValue) { return error; } @@ -521,7 +523,8 @@ optional<Error> CircleLayer::setPaintProperty(const std::string& name, const Con if (property == Property::CircleTranslateAnchor) { Error error; - optional<PropertyValue<TranslateAnchorType>> typedValue = convert<PropertyValue<TranslateAnchorType>>(value, error, false, false); + optional<PropertyValue<TranslateAnchorType>> typedValue = + convert<PropertyValue<TranslateAnchorType>>(value, error, false, false); if (!typedValue) { return error; } diff --git a/src/mbgl/style/layers/circle_layer_properties.hpp b/src/mbgl/style/layers/circle_layer_properties.hpp index a5f7a584df..5204421d0b 100644 --- a/src/mbgl/style/layers/circle_layer_properties.hpp +++ b/src/mbgl/style/layers/circle_layer_properties.hpp @@ -53,7 +53,7 @@ struct CircleStrokeWidth : DataDrivenPaintProperty<float, attributes::stroke_wid }; struct CircleTranslate : PaintProperty<std::array<float, 2>> { - static std::array<float, 2> defaultValue() { return {{ 0, 0 }}; } + static std::array<float, 2> defaultValue() { return {{0, 0}}; } }; struct CircleTranslateAnchor : PaintProperty<TranslateAnchorType> { diff --git a/src/mbgl/style/layers/fill_extrusion_layer.cpp b/src/mbgl/style/layers/fill_extrusion_layer.cpp index 87e196926f..e04e192298 100644 --- a/src/mbgl/style/layers/fill_extrusion_layer.cpp +++ b/src/mbgl/style/layers/fill_extrusion_layer.cpp @@ -64,7 +64,7 @@ void FillExtrusionLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::Stri // Paint properties PropertyValue<float> FillExtrusionLayer::getDefaultFillExtrusionBase() { - return { 0 }; + return {0}; } const PropertyValue<float>& FillExtrusionLayer::getFillExtrusionBase() const { @@ -91,7 +91,7 @@ TransitionOptions FillExtrusionLayer::getFillExtrusionBaseTransition() const { } PropertyValue<Color> FillExtrusionLayer::getDefaultFillExtrusionColor() { - return { Color::black() }; + return {Color::black()}; } const PropertyValue<Color>& FillExtrusionLayer::getFillExtrusionColor() const { @@ -118,7 +118,7 @@ TransitionOptions FillExtrusionLayer::getFillExtrusionColorTransition() const { } PropertyValue<float> FillExtrusionLayer::getDefaultFillExtrusionHeight() { - return { 0 }; + return {0}; } const PropertyValue<float>& FillExtrusionLayer::getFillExtrusionHeight() const { @@ -145,7 +145,7 @@ TransitionOptions FillExtrusionLayer::getFillExtrusionHeightTransition() const { } PropertyValue<float> FillExtrusionLayer::getDefaultFillExtrusionOpacity() { - return { 1 }; + return {1}; } const PropertyValue<float>& FillExtrusionLayer::getFillExtrusionOpacity() const { @@ -171,15 +171,15 @@ TransitionOptions FillExtrusionLayer::getFillExtrusionOpacityTransition() const return impl().paint.template get<FillExtrusionOpacity>().options; } -PropertyValue<std::string> FillExtrusionLayer::getDefaultFillExtrusionPattern() { - return { "" }; +PropertyValue<expression::Image> FillExtrusionLayer::getDefaultFillExtrusionPattern() { + return {{}}; } -const PropertyValue<std::string>& FillExtrusionLayer::getFillExtrusionPattern() const { +const PropertyValue<expression::Image>& FillExtrusionLayer::getFillExtrusionPattern() const { return impl().paint.template get<FillExtrusionPattern>().value; } -void FillExtrusionLayer::setFillExtrusionPattern(const PropertyValue<std::string>& value) { +void FillExtrusionLayer::setFillExtrusionPattern(const PropertyValue<expression::Image>& value) { if (value == getFillExtrusionPattern()) return; auto impl_ = mutableImpl(); @@ -199,7 +199,7 @@ TransitionOptions FillExtrusionLayer::getFillExtrusionPatternTransition() const } PropertyValue<std::array<float, 2>> FillExtrusionLayer::getDefaultFillExtrusionTranslate() { - return { {{ 0, 0 }} }; + return {{{0, 0}}}; } const PropertyValue<std::array<float, 2>>& FillExtrusionLayer::getFillExtrusionTranslate() const { @@ -226,7 +226,7 @@ TransitionOptions FillExtrusionLayer::getFillExtrusionTranslateTransition() cons } PropertyValue<TranslateAnchorType> FillExtrusionLayer::getDefaultFillExtrusionTranslateAnchor() { - return { TranslateAnchorType::Map }; + return {TranslateAnchorType::Map}; } const PropertyValue<TranslateAnchorType>& FillExtrusionLayer::getFillExtrusionTranslateAnchor() const { @@ -253,7 +253,7 @@ TransitionOptions FillExtrusionLayer::getFillExtrusionTranslateAnchorTransition( } PropertyValue<bool> FillExtrusionLayer::getDefaultFillExtrusionVerticalGradient() { - return { true }; + return {true}; } const PropertyValue<bool>& FillExtrusionLayer::getFillExtrusionVerticalGradient() const { @@ -382,7 +382,8 @@ optional<Error> FillExtrusionLayer::setPaintProperty(const std::string& name, co if (property == Property::FillExtrusionPattern) { Error error; - optional<PropertyValue<std::string>> typedValue = convert<PropertyValue<std::string>>(value, error, true, false); + optional<PropertyValue<expression::Image>> typedValue = + convert<PropertyValue<expression::Image>>(value, error, true, false); if (!typedValue) { return error; } @@ -394,7 +395,8 @@ optional<Error> FillExtrusionLayer::setPaintProperty(const std::string& name, co if (property == Property::FillExtrusionTranslate) { Error error; - optional<PropertyValue<std::array<float, 2>>> typedValue = convert<PropertyValue<std::array<float, 2>>>(value, error, false, false); + optional<PropertyValue<std::array<float, 2>>> typedValue = + convert<PropertyValue<std::array<float, 2>>>(value, error, false, false); if (!typedValue) { return error; } @@ -406,7 +408,8 @@ optional<Error> FillExtrusionLayer::setPaintProperty(const std::string& name, co if (property == Property::FillExtrusionTranslateAnchor) { Error error; - optional<PropertyValue<TranslateAnchorType>> typedValue = convert<PropertyValue<TranslateAnchorType>>(value, error, false, false); + optional<PropertyValue<TranslateAnchorType>> typedValue = + convert<PropertyValue<TranslateAnchorType>>(value, error, false, false); if (!typedValue) { return error; } diff --git a/src/mbgl/style/layers/fill_extrusion_layer_properties.hpp b/src/mbgl/style/layers/fill_extrusion_layer_properties.hpp index 6936d5e0c4..60a2340b0d 100644 --- a/src/mbgl/style/layers/fill_extrusion_layer_properties.hpp +++ b/src/mbgl/style/layers/fill_extrusion_layer_properties.hpp @@ -32,12 +32,12 @@ struct FillExtrusionOpacity : PaintProperty<float> { static float defaultValue() { return 1; } }; -struct FillExtrusionPattern : CrossFadedDataDrivenPaintProperty<std::string, attributes::pattern_to, uniforms::pattern_to, attributes::pattern_from, uniforms::pattern_from> { - static std::string defaultValue() { return ""; } +struct FillExtrusionPattern : CrossFadedDataDrivenPaintProperty<expression::Image, attributes::pattern_to, uniforms::pattern_to, attributes::pattern_from, uniforms::pattern_from> { + static expression::Image defaultValue() { return {}; } }; struct FillExtrusionTranslate : PaintProperty<std::array<float, 2>> { - static std::array<float, 2> defaultValue() { return {{ 0, 0 }}; } + static std::array<float, 2> defaultValue() { return {{0, 0}}; } }; struct FillExtrusionTranslateAnchor : PaintProperty<TranslateAnchorType> { diff --git a/src/mbgl/style/layers/fill_layer.cpp b/src/mbgl/style/layers/fill_layer.cpp index e3d6c6c708..ad1f0ae847 100644 --- a/src/mbgl/style/layers/fill_layer.cpp +++ b/src/mbgl/style/layers/fill_layer.cpp @@ -64,7 +64,7 @@ void FillLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer> // Paint properties PropertyValue<bool> FillLayer::getDefaultFillAntialias() { - return { true }; + return {true}; } const PropertyValue<bool>& FillLayer::getFillAntialias() const { @@ -91,7 +91,7 @@ TransitionOptions FillLayer::getFillAntialiasTransition() const { } PropertyValue<Color> FillLayer::getDefaultFillColor() { - return { Color::black() }; + return {Color::black()}; } const PropertyValue<Color>& FillLayer::getFillColor() const { @@ -118,7 +118,7 @@ TransitionOptions FillLayer::getFillColorTransition() const { } PropertyValue<float> FillLayer::getDefaultFillOpacity() { - return { 1 }; + return {1}; } const PropertyValue<float>& FillLayer::getFillOpacity() const { @@ -145,7 +145,7 @@ TransitionOptions FillLayer::getFillOpacityTransition() const { } PropertyValue<Color> FillLayer::getDefaultFillOutlineColor() { - return { {} }; + return {{}}; } const PropertyValue<Color>& FillLayer::getFillOutlineColor() const { @@ -171,15 +171,15 @@ TransitionOptions FillLayer::getFillOutlineColorTransition() const { return impl().paint.template get<FillOutlineColor>().options; } -PropertyValue<std::string> FillLayer::getDefaultFillPattern() { - return { "" }; +PropertyValue<expression::Image> FillLayer::getDefaultFillPattern() { + return {{}}; } -const PropertyValue<std::string>& FillLayer::getFillPattern() const { +const PropertyValue<expression::Image>& FillLayer::getFillPattern() const { return impl().paint.template get<FillPattern>().value; } -void FillLayer::setFillPattern(const PropertyValue<std::string>& value) { +void FillLayer::setFillPattern(const PropertyValue<expression::Image>& value) { if (value == getFillPattern()) return; auto impl_ = mutableImpl(); @@ -199,7 +199,7 @@ TransitionOptions FillLayer::getFillPatternTransition() const { } PropertyValue<std::array<float, 2>> FillLayer::getDefaultFillTranslate() { - return { {{ 0, 0 }} }; + return {{{0, 0}}}; } const PropertyValue<std::array<float, 2>>& FillLayer::getFillTranslate() const { @@ -226,7 +226,7 @@ TransitionOptions FillLayer::getFillTranslateTransition() const { } PropertyValue<TranslateAnchorType> FillLayer::getDefaultFillTranslateAnchor() { - return { TranslateAnchorType::Map }; + return {TranslateAnchorType::Map}; } const PropertyValue<TranslateAnchorType>& FillLayer::getFillTranslateAnchor() const { @@ -351,7 +351,8 @@ optional<Error> FillLayer::setPaintProperty(const std::string& name, const Conve if (property == Property::FillPattern) { Error error; - optional<PropertyValue<std::string>> typedValue = convert<PropertyValue<std::string>>(value, error, true, false); + optional<PropertyValue<expression::Image>> typedValue = + convert<PropertyValue<expression::Image>>(value, error, true, false); if (!typedValue) { return error; } @@ -363,7 +364,8 @@ optional<Error> FillLayer::setPaintProperty(const std::string& name, const Conve if (property == Property::FillTranslate) { Error error; - optional<PropertyValue<std::array<float, 2>>> typedValue = convert<PropertyValue<std::array<float, 2>>>(value, error, false, false); + optional<PropertyValue<std::array<float, 2>>> typedValue = + convert<PropertyValue<std::array<float, 2>>>(value, error, false, false); if (!typedValue) { return error; } @@ -375,7 +377,8 @@ optional<Error> FillLayer::setPaintProperty(const std::string& name, const Conve if (property == Property::FillTranslateAnchor) { Error error; - optional<PropertyValue<TranslateAnchorType>> typedValue = convert<PropertyValue<TranslateAnchorType>>(value, error, false, false); + optional<PropertyValue<TranslateAnchorType>> typedValue = + convert<PropertyValue<TranslateAnchorType>>(value, error, false, false); if (!typedValue) { return error; } diff --git a/src/mbgl/style/layers/fill_layer_properties.hpp b/src/mbgl/style/layers/fill_layer_properties.hpp index 38ca506199..ad8ed84892 100644 --- a/src/mbgl/style/layers/fill_layer_properties.hpp +++ b/src/mbgl/style/layers/fill_layer_properties.hpp @@ -32,12 +32,12 @@ struct FillOutlineColor : DataDrivenPaintProperty<Color, attributes::outline_col static Color defaultValue() { return {}; } }; -struct FillPattern : CrossFadedDataDrivenPaintProperty<std::string, attributes::pattern_to, uniforms::pattern_to, attributes::pattern_from, uniforms::pattern_from> { - static std::string defaultValue() { return ""; } +struct FillPattern : CrossFadedDataDrivenPaintProperty<expression::Image, attributes::pattern_to, uniforms::pattern_to, attributes::pattern_from, uniforms::pattern_from> { + static expression::Image defaultValue() { return {}; } }; struct FillTranslate : PaintProperty<std::array<float, 2>> { - static std::array<float, 2> defaultValue() { return {{ 0, 0 }}; } + static std::array<float, 2> defaultValue() { return {{0, 0}}; } }; struct FillTranslateAnchor : PaintProperty<TranslateAnchorType> { diff --git a/src/mbgl/style/layers/heatmap_layer.cpp b/src/mbgl/style/layers/heatmap_layer.cpp index 332c65c6b4..234dda6c73 100644 --- a/src/mbgl/style/layers/heatmap_layer.cpp +++ b/src/mbgl/style/layers/heatmap_layer.cpp @@ -93,7 +93,7 @@ TransitionOptions HeatmapLayer::getHeatmapColorTransition() const { } PropertyValue<float> HeatmapLayer::getDefaultHeatmapIntensity() { - return { 1 }; + return {1}; } const PropertyValue<float>& HeatmapLayer::getHeatmapIntensity() const { @@ -120,7 +120,7 @@ TransitionOptions HeatmapLayer::getHeatmapIntensityTransition() const { } PropertyValue<float> HeatmapLayer::getDefaultHeatmapOpacity() { - return { 1 }; + return {1}; } const PropertyValue<float>& HeatmapLayer::getHeatmapOpacity() const { @@ -147,7 +147,7 @@ TransitionOptions HeatmapLayer::getHeatmapOpacityTransition() const { } PropertyValue<float> HeatmapLayer::getDefaultHeatmapRadius() { - return { 30 }; + return {30}; } const PropertyValue<float>& HeatmapLayer::getHeatmapRadius() const { @@ -174,7 +174,7 @@ TransitionOptions HeatmapLayer::getHeatmapRadiusTransition() const { } PropertyValue<float> HeatmapLayer::getDefaultHeatmapWeight() { - return { 1 }; + return {1}; } const PropertyValue<float>& HeatmapLayer::getHeatmapWeight() const { diff --git a/src/mbgl/style/layers/hillshade_layer.cpp b/src/mbgl/style/layers/hillshade_layer.cpp index a55c079c49..5d84b7ded3 100644 --- a/src/mbgl/style/layers/hillshade_layer.cpp +++ b/src/mbgl/style/layers/hillshade_layer.cpp @@ -64,7 +64,7 @@ void HillshadeLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBu // Paint properties PropertyValue<Color> HillshadeLayer::getDefaultHillshadeAccentColor() { - return { Color::black() }; + return {Color::black()}; } const PropertyValue<Color>& HillshadeLayer::getHillshadeAccentColor() const { @@ -91,7 +91,7 @@ TransitionOptions HillshadeLayer::getHillshadeAccentColorTransition() const { } PropertyValue<float> HillshadeLayer::getDefaultHillshadeExaggeration() { - return { 0.5 }; + return {0.5}; } const PropertyValue<float>& HillshadeLayer::getHillshadeExaggeration() const { @@ -118,7 +118,7 @@ TransitionOptions HillshadeLayer::getHillshadeExaggerationTransition() const { } PropertyValue<Color> HillshadeLayer::getDefaultHillshadeHighlightColor() { - return { Color::white() }; + return {Color::white()}; } const PropertyValue<Color>& HillshadeLayer::getHillshadeHighlightColor() const { @@ -145,7 +145,7 @@ TransitionOptions HillshadeLayer::getHillshadeHighlightColorTransition() const { } PropertyValue<HillshadeIlluminationAnchorType> HillshadeLayer::getDefaultHillshadeIlluminationAnchor() { - return { HillshadeIlluminationAnchorType::Viewport }; + return {HillshadeIlluminationAnchorType::Viewport}; } const PropertyValue<HillshadeIlluminationAnchorType>& HillshadeLayer::getHillshadeIlluminationAnchor() const { @@ -172,7 +172,7 @@ TransitionOptions HillshadeLayer::getHillshadeIlluminationAnchorTransition() con } PropertyValue<float> HillshadeLayer::getDefaultHillshadeIlluminationDirection() { - return { 335 }; + return {335}; } const PropertyValue<float>& HillshadeLayer::getHillshadeIlluminationDirection() const { @@ -199,7 +199,7 @@ TransitionOptions HillshadeLayer::getHillshadeIlluminationDirectionTransition() } PropertyValue<Color> HillshadeLayer::getDefaultHillshadeShadowColor() { - return { Color::black() }; + return {Color::black()}; } const PropertyValue<Color>& HillshadeLayer::getHillshadeShadowColor() const { @@ -320,7 +320,8 @@ optional<Error> HillshadeLayer::setPaintProperty(const std::string& name, const if (property == Property::HillshadeIlluminationAnchor) { Error error; - optional<PropertyValue<HillshadeIlluminationAnchorType>> typedValue = convert<PropertyValue<HillshadeIlluminationAnchorType>>(value, error, false, false); + optional<PropertyValue<HillshadeIlluminationAnchorType>> typedValue = + convert<PropertyValue<HillshadeIlluminationAnchorType>>(value, error, false, false); if (!typedValue) { return error; } diff --git a/src/mbgl/style/layers/layer.cpp.ejs b/src/mbgl/style/layers/layer.cpp.ejs index 775288264f..a47e5b95b4 100644 --- a/src/mbgl/style/layers/layer.cpp.ejs +++ b/src/mbgl/style/layers/layer.cpp.ejs @@ -77,6 +77,15 @@ layerCapabilities['heatmap'] = defaults.require('Source') .set('TileKind', 'Geometry') .finalize(); layerCapabilities['raster'] = defaults.require('Source').set('TileKind', 'Raster').finalize(); + +// Splits lines that are over 120 characters at the firts occurance of '='. +const split120Line = line => { + if (line.length > 120) { + return line.replace('=', '=\n '); + } + return line; +}; + %> // static const LayerTypeInfo* <%- camelize(type) %>Layer::Impl::staticTypeInfo() noexcept { @@ -155,7 +164,7 @@ void <%- camelize(type) %>Layer::set<%- camelize(property.name) %>(const <%- pro std::string rawValue = R"JSON(<%- JSON.stringify(property.default) %>)JSON"; return *conversion::convertJSON<<%- propertyValueType(property)%>>(rawValue, error); <% } else { -%> - return { <%- defaultValue(property) %> }; + return {<%- defaultValue(property) %>}; <% } -%> } @@ -243,7 +252,7 @@ optional<Error> <%- camelize(type) %>Layer::setPaintProperty(const std::string& %> if (<%- properties.map(p => `property == Property::${camelize(p.name)}`).join(' || ') %>) { Error error; - <%- key %>; + <%- split120Line(key) %>; if (!typedValue) { return error; } @@ -323,7 +332,7 @@ optional<Error> <%- camelize(type) %>Layer::setLayoutProperty(const std::string& %> if (<%- properties.map(p => `property == Property::${camelize(p.name)}`).join(' || ') %>) { Error error; - <%- key %>; + <%- split120Line(key) %>; if (!typedValue) { return error; } diff --git a/src/mbgl/style/layers/line_layer.cpp b/src/mbgl/style/layers/line_layer.cpp index 309a81ae2b..813ef68dec 100644 --- a/src/mbgl/style/layers/line_layer.cpp +++ b/src/mbgl/style/layers/line_layer.cpp @@ -129,7 +129,7 @@ void LineLayer::setLineRoundLimit(const PropertyValue<float>& value) { // Paint properties PropertyValue<float> LineLayer::getDefaultLineBlur() { - return { 0 }; + return {0}; } const PropertyValue<float>& LineLayer::getLineBlur() const { @@ -156,7 +156,7 @@ TransitionOptions LineLayer::getLineBlurTransition() const { } PropertyValue<Color> LineLayer::getDefaultLineColor() { - return { Color::black() }; + return {Color::black()}; } const PropertyValue<Color>& LineLayer::getLineColor() const { @@ -183,7 +183,7 @@ TransitionOptions LineLayer::getLineColorTransition() const { } PropertyValue<std::vector<float>> LineLayer::getDefaultLineDasharray() { - return { { } }; + return {{}}; } const PropertyValue<std::vector<float>>& LineLayer::getLineDasharray() const { @@ -210,7 +210,7 @@ TransitionOptions LineLayer::getLineDasharrayTransition() const { } PropertyValue<float> LineLayer::getDefaultLineGapWidth() { - return { 0 }; + return {0}; } const PropertyValue<float>& LineLayer::getLineGapWidth() const { @@ -237,7 +237,7 @@ TransitionOptions LineLayer::getLineGapWidthTransition() const { } ColorRampPropertyValue LineLayer::getDefaultLineGradient() { - return { {} }; + return {{}}; } const ColorRampPropertyValue& LineLayer::getLineGradient() const { @@ -264,7 +264,7 @@ TransitionOptions LineLayer::getLineGradientTransition() const { } PropertyValue<float> LineLayer::getDefaultLineOffset() { - return { 0 }; + return {0}; } const PropertyValue<float>& LineLayer::getLineOffset() const { @@ -291,7 +291,7 @@ TransitionOptions LineLayer::getLineOffsetTransition() const { } PropertyValue<float> LineLayer::getDefaultLineOpacity() { - return { 1 }; + return {1}; } const PropertyValue<float>& LineLayer::getLineOpacity() const { @@ -317,15 +317,15 @@ TransitionOptions LineLayer::getLineOpacityTransition() const { return impl().paint.template get<LineOpacity>().options; } -PropertyValue<std::string> LineLayer::getDefaultLinePattern() { - return { "" }; +PropertyValue<expression::Image> LineLayer::getDefaultLinePattern() { + return {{}}; } -const PropertyValue<std::string>& LineLayer::getLinePattern() const { +const PropertyValue<expression::Image>& LineLayer::getLinePattern() const { return impl().paint.template get<LinePattern>().value; } -void LineLayer::setLinePattern(const PropertyValue<std::string>& value) { +void LineLayer::setLinePattern(const PropertyValue<expression::Image>& value) { if (value == getLinePattern()) return; auto impl_ = mutableImpl(); @@ -345,7 +345,7 @@ TransitionOptions LineLayer::getLinePatternTransition() const { } PropertyValue<std::array<float, 2>> LineLayer::getDefaultLineTranslate() { - return { {{ 0, 0 }} }; + return {{{0, 0}}}; } const PropertyValue<std::array<float, 2>>& LineLayer::getLineTranslate() const { @@ -372,7 +372,7 @@ TransitionOptions LineLayer::getLineTranslateTransition() const { } PropertyValue<TranslateAnchorType> LineLayer::getDefaultLineTranslateAnchor() { - return { TranslateAnchorType::Map }; + return {TranslateAnchorType::Map}; } const PropertyValue<TranslateAnchorType>& LineLayer::getLineTranslateAnchor() const { @@ -399,7 +399,7 @@ TransitionOptions LineLayer::getLineTranslateAnchorTransition() const { } PropertyValue<float> LineLayer::getDefaultLineWidth() { - return { 1 }; + return {1}; } const PropertyValue<float>& LineLayer::getLineWidth() const { @@ -552,7 +552,8 @@ optional<Error> LineLayer::setPaintProperty(const std::string& name, const Conve if (property == Property::LineDasharray) { Error error; - optional<PropertyValue<std::vector<float>>> typedValue = convert<PropertyValue<std::vector<float>>>(value, error, false, false); + optional<PropertyValue<std::vector<float>>> typedValue = + convert<PropertyValue<std::vector<float>>>(value, error, false, false); if (!typedValue) { return error; } @@ -576,7 +577,8 @@ optional<Error> LineLayer::setPaintProperty(const std::string& name, const Conve if (property == Property::LinePattern) { Error error; - optional<PropertyValue<std::string>> typedValue = convert<PropertyValue<std::string>>(value, error, true, false); + optional<PropertyValue<expression::Image>> typedValue = + convert<PropertyValue<expression::Image>>(value, error, true, false); if (!typedValue) { return error; } @@ -588,7 +590,8 @@ optional<Error> LineLayer::setPaintProperty(const std::string& name, const Conve if (property == Property::LineTranslate) { Error error; - optional<PropertyValue<std::array<float, 2>>> typedValue = convert<PropertyValue<std::array<float, 2>>>(value, error, false, false); + optional<PropertyValue<std::array<float, 2>>> typedValue = + convert<PropertyValue<std::array<float, 2>>>(value, error, false, false); if (!typedValue) { return error; } @@ -600,7 +603,8 @@ optional<Error> LineLayer::setPaintProperty(const std::string& name, const Conve if (property == Property::LineTranslateAnchor) { Error error; - optional<PropertyValue<TranslateAnchorType>> typedValue = convert<PropertyValue<TranslateAnchorType>>(value, error, false, false); + optional<PropertyValue<TranslateAnchorType>> typedValue = + convert<PropertyValue<TranslateAnchorType>>(value, error, false, false); if (!typedValue) { return error; } diff --git a/src/mbgl/style/layers/line_layer_properties.hpp b/src/mbgl/style/layers/line_layer_properties.hpp index 2ecbb10993..29ba9ec641 100644 --- a/src/mbgl/style/layers/line_layer_properties.hpp +++ b/src/mbgl/style/layers/line_layer_properties.hpp @@ -45,7 +45,7 @@ struct LineColor : DataDrivenPaintProperty<Color, attributes::color, uniforms::c }; struct LineDasharray : CrossFadedPaintProperty<std::vector<float>> { - static std::vector<float> defaultValue() { return { }; } + static std::vector<float> defaultValue() { return {}; } }; struct LineFloorWidth : DataDrivenPaintProperty<float, attributes::floorwidth, uniforms::floorwidth> { @@ -68,12 +68,12 @@ struct LineOpacity : DataDrivenPaintProperty<float, attributes::opacity, uniform static float defaultValue() { return 1; } }; -struct LinePattern : CrossFadedDataDrivenPaintProperty<std::string, attributes::pattern_to, uniforms::pattern_to, attributes::pattern_from, uniforms::pattern_from> { - static std::string defaultValue() { return ""; } +struct LinePattern : CrossFadedDataDrivenPaintProperty<expression::Image, attributes::pattern_to, uniforms::pattern_to, attributes::pattern_from, uniforms::pattern_from> { + static expression::Image defaultValue() { return {}; } }; struct LineTranslate : PaintProperty<std::array<float, 2>> { - static std::array<float, 2> defaultValue() { return {{ 0, 0 }}; } + static std::array<float, 2> defaultValue() { return {{0, 0}}; } }; struct LineTranslateAnchor : PaintProperty<TranslateAnchorType> { diff --git a/src/mbgl/style/layers/raster_layer.cpp b/src/mbgl/style/layers/raster_layer.cpp index 359e502f3e..b990409886 100644 --- a/src/mbgl/style/layers/raster_layer.cpp +++ b/src/mbgl/style/layers/raster_layer.cpp @@ -64,7 +64,7 @@ void RasterLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffe // Paint properties PropertyValue<float> RasterLayer::getDefaultRasterBrightnessMax() { - return { 1 }; + return {1}; } const PropertyValue<float>& RasterLayer::getRasterBrightnessMax() const { @@ -91,7 +91,7 @@ TransitionOptions RasterLayer::getRasterBrightnessMaxTransition() const { } PropertyValue<float> RasterLayer::getDefaultRasterBrightnessMin() { - return { 0 }; + return {0}; } const PropertyValue<float>& RasterLayer::getRasterBrightnessMin() const { @@ -118,7 +118,7 @@ TransitionOptions RasterLayer::getRasterBrightnessMinTransition() const { } PropertyValue<float> RasterLayer::getDefaultRasterContrast() { - return { 0 }; + return {0}; } const PropertyValue<float>& RasterLayer::getRasterContrast() const { @@ -145,7 +145,7 @@ TransitionOptions RasterLayer::getRasterContrastTransition() const { } PropertyValue<float> RasterLayer::getDefaultRasterFadeDuration() { - return { 300 }; + return {300}; } const PropertyValue<float>& RasterLayer::getRasterFadeDuration() const { @@ -172,7 +172,7 @@ TransitionOptions RasterLayer::getRasterFadeDurationTransition() const { } PropertyValue<float> RasterLayer::getDefaultRasterHueRotate() { - return { 0 }; + return {0}; } const PropertyValue<float>& RasterLayer::getRasterHueRotate() const { @@ -199,7 +199,7 @@ TransitionOptions RasterLayer::getRasterHueRotateTransition() const { } PropertyValue<float> RasterLayer::getDefaultRasterOpacity() { - return { 1 }; + return {1}; } const PropertyValue<float>& RasterLayer::getRasterOpacity() const { @@ -226,7 +226,7 @@ TransitionOptions RasterLayer::getRasterOpacityTransition() const { } PropertyValue<RasterResamplingType> RasterLayer::getDefaultRasterResampling() { - return { RasterResamplingType::Linear }; + return {RasterResamplingType::Linear}; } const PropertyValue<RasterResamplingType>& RasterLayer::getRasterResampling() const { @@ -253,7 +253,7 @@ TransitionOptions RasterLayer::getRasterResamplingTransition() const { } PropertyValue<float> RasterLayer::getDefaultRasterSaturation() { - return { 0 }; + return {0}; } const PropertyValue<float>& RasterLayer::getRasterSaturation() const { @@ -383,7 +383,8 @@ optional<Error> RasterLayer::setPaintProperty(const std::string& name, const Con if (property == Property::RasterResampling) { Error error; - optional<PropertyValue<RasterResamplingType>> typedValue = convert<PropertyValue<RasterResamplingType>>(value, error, false, false); + optional<PropertyValue<RasterResamplingType>> typedValue = + convert<PropertyValue<RasterResamplingType>>(value, error, false, false); if (!typedValue) { return error; } diff --git a/src/mbgl/style/layers/symbol_layer.cpp b/src/mbgl/style/layers/symbol_layer.cpp index b3ee0f698c..1383293d6d 100644 --- a/src/mbgl/style/layers/symbol_layer.cpp +++ b/src/mbgl/style/layers/symbol_layer.cpp @@ -109,15 +109,15 @@ void SymbolLayer::setIconIgnorePlacement(const PropertyValue<bool>& value) { baseImpl = std::move(impl_); observer->onLayerChanged(*this); } -PropertyValue<std::string> SymbolLayer::getDefaultIconImage() { +PropertyValue<expression::Image> SymbolLayer::getDefaultIconImage() { return IconImage::defaultValue(); } -const PropertyValue<std::string>& SymbolLayer::getIconImage() const { +const PropertyValue<expression::Image>& SymbolLayer::getIconImage() const { return impl().layout.get<IconImage>(); } -void SymbolLayer::setIconImage(const PropertyValue<std::string>& value) { +void SymbolLayer::setIconImage(const PropertyValue<expression::Image>& value) { if (value == getIconImage()) return; auto impl_ = mutableImpl(); @@ -721,7 +721,7 @@ void SymbolLayer::setTextWritingMode(const PropertyValue<std::vector<TextWriting // Paint properties PropertyValue<Color> SymbolLayer::getDefaultIconColor() { - return { Color::black() }; + return {Color::black()}; } const PropertyValue<Color>& SymbolLayer::getIconColor() const { @@ -748,7 +748,7 @@ TransitionOptions SymbolLayer::getIconColorTransition() const { } PropertyValue<float> SymbolLayer::getDefaultIconHaloBlur() { - return { 0 }; + return {0}; } const PropertyValue<float>& SymbolLayer::getIconHaloBlur() const { @@ -775,7 +775,7 @@ TransitionOptions SymbolLayer::getIconHaloBlurTransition() const { } PropertyValue<Color> SymbolLayer::getDefaultIconHaloColor() { - return { {} }; + return {{}}; } const PropertyValue<Color>& SymbolLayer::getIconHaloColor() const { @@ -802,7 +802,7 @@ TransitionOptions SymbolLayer::getIconHaloColorTransition() const { } PropertyValue<float> SymbolLayer::getDefaultIconHaloWidth() { - return { 0 }; + return {0}; } const PropertyValue<float>& SymbolLayer::getIconHaloWidth() const { @@ -829,7 +829,7 @@ TransitionOptions SymbolLayer::getIconHaloWidthTransition() const { } PropertyValue<float> SymbolLayer::getDefaultIconOpacity() { - return { 1 }; + return {1}; } const PropertyValue<float>& SymbolLayer::getIconOpacity() const { @@ -856,7 +856,7 @@ TransitionOptions SymbolLayer::getIconOpacityTransition() const { } PropertyValue<std::array<float, 2>> SymbolLayer::getDefaultIconTranslate() { - return { {{ 0, 0 }} }; + return {{{0, 0}}}; } const PropertyValue<std::array<float, 2>>& SymbolLayer::getIconTranslate() const { @@ -883,7 +883,7 @@ TransitionOptions SymbolLayer::getIconTranslateTransition() const { } PropertyValue<TranslateAnchorType> SymbolLayer::getDefaultIconTranslateAnchor() { - return { TranslateAnchorType::Map }; + return {TranslateAnchorType::Map}; } const PropertyValue<TranslateAnchorType>& SymbolLayer::getIconTranslateAnchor() const { @@ -910,7 +910,7 @@ TransitionOptions SymbolLayer::getIconTranslateAnchorTransition() const { } PropertyValue<Color> SymbolLayer::getDefaultTextColor() { - return { Color::black() }; + return {Color::black()}; } const PropertyValue<Color>& SymbolLayer::getTextColor() const { @@ -937,7 +937,7 @@ TransitionOptions SymbolLayer::getTextColorTransition() const { } PropertyValue<float> SymbolLayer::getDefaultTextHaloBlur() { - return { 0 }; + return {0}; } const PropertyValue<float>& SymbolLayer::getTextHaloBlur() const { @@ -964,7 +964,7 @@ TransitionOptions SymbolLayer::getTextHaloBlurTransition() const { } PropertyValue<Color> SymbolLayer::getDefaultTextHaloColor() { - return { {} }; + return {{}}; } const PropertyValue<Color>& SymbolLayer::getTextHaloColor() const { @@ -991,7 +991,7 @@ TransitionOptions SymbolLayer::getTextHaloColorTransition() const { } PropertyValue<float> SymbolLayer::getDefaultTextHaloWidth() { - return { 0 }; + return {0}; } const PropertyValue<float>& SymbolLayer::getTextHaloWidth() const { @@ -1018,7 +1018,7 @@ TransitionOptions SymbolLayer::getTextHaloWidthTransition() const { } PropertyValue<float> SymbolLayer::getDefaultTextOpacity() { - return { 1 }; + return {1}; } const PropertyValue<float>& SymbolLayer::getTextOpacity() const { @@ -1045,7 +1045,7 @@ TransitionOptions SymbolLayer::getTextOpacityTransition() const { } PropertyValue<std::array<float, 2>> SymbolLayer::getDefaultTextTranslate() { - return { {{ 0, 0 }} }; + return {{{0, 0}}}; } const PropertyValue<std::array<float, 2>>& SymbolLayer::getTextTranslate() const { @@ -1072,7 +1072,7 @@ TransitionOptions SymbolLayer::getTextTranslateTransition() const { } PropertyValue<TranslateAnchorType> SymbolLayer::getDefaultTextTranslateAnchor() { - return { TranslateAnchorType::Map }; + return {TranslateAnchorType::Map}; } const PropertyValue<TranslateAnchorType>& SymbolLayer::getTextTranslateAnchor() const { @@ -1332,7 +1332,8 @@ optional<Error> SymbolLayer::setPaintProperty(const std::string& name, const Con if (property == Property::IconTranslate || property == Property::TextTranslate) { Error error; - optional<PropertyValue<std::array<float, 2>>> typedValue = convert<PropertyValue<std::array<float, 2>>>(value, error, false, false); + optional<PropertyValue<std::array<float, 2>>> typedValue = + convert<PropertyValue<std::array<float, 2>>>(value, error, false, false); if (!typedValue) { return error; } @@ -1351,7 +1352,8 @@ optional<Error> SymbolLayer::setPaintProperty(const std::string& name, const Con if (property == Property::IconTranslateAnchor || property == Property::TextTranslateAnchor) { Error error; - optional<PropertyValue<TranslateAnchorType>> typedValue = convert<PropertyValue<TranslateAnchorType>>(value, error, false, false); + optional<PropertyValue<TranslateAnchorType>> typedValue = + convert<PropertyValue<TranslateAnchorType>>(value, error, false, false); if (!typedValue) { return error; } @@ -1665,7 +1667,8 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co if (property == Property::IconAnchor || property == Property::TextAnchor) { Error error; - optional<PropertyValue<SymbolAnchorType>> typedValue = convert<PropertyValue<SymbolAnchorType>>(value, error, true, false); + optional<PropertyValue<SymbolAnchorType>> typedValue = + convert<PropertyValue<SymbolAnchorType>>(value, error, true, false); if (!typedValue) { return error; } @@ -1684,7 +1687,8 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co if (property == Property::IconImage) { Error error; - optional<PropertyValue<std::string>> typedValue = convert<PropertyValue<std::string>>(value, error, true, true); + optional<PropertyValue<expression::Image>> typedValue = + convert<PropertyValue<expression::Image>>(value, error, true, true); if (!typedValue) { return error; } @@ -1696,7 +1700,8 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co if (property == Property::IconOffset || property == Property::TextOffset) { Error error; - optional<PropertyValue<std::array<float, 2>>> typedValue = convert<PropertyValue<std::array<float, 2>>>(value, error, true, false); + optional<PropertyValue<std::array<float, 2>>> typedValue = + convert<PropertyValue<std::array<float, 2>>>(value, error, true, false); if (!typedValue) { return error; } @@ -1827,7 +1832,8 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co if (property == Property::IconTextFit) { Error error; - optional<PropertyValue<IconTextFitType>> typedValue = convert<PropertyValue<IconTextFitType>>(value, error, false, false); + optional<PropertyValue<IconTextFitType>> typedValue = + convert<PropertyValue<IconTextFitType>>(value, error, false, false); if (!typedValue) { return error; } @@ -1839,7 +1845,8 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co if (property == Property::IconTextFitPadding) { Error error; - optional<PropertyValue<std::array<float, 4>>> typedValue = convert<PropertyValue<std::array<float, 4>>>(value, error, false, false); + optional<PropertyValue<std::array<float, 4>>> typedValue = + convert<PropertyValue<std::array<float, 4>>>(value, error, false, false); if (!typedValue) { return error; } @@ -1851,7 +1858,8 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co if (property == Property::SymbolPlacement) { Error error; - optional<PropertyValue<SymbolPlacementType>> typedValue = convert<PropertyValue<SymbolPlacementType>>(value, error, false, false); + optional<PropertyValue<SymbolPlacementType>> typedValue = + convert<PropertyValue<SymbolPlacementType>>(value, error, false, false); if (!typedValue) { return error; } @@ -1863,7 +1871,8 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co if (property == Property::SymbolZOrder) { Error error; - optional<PropertyValue<SymbolZOrderType>> typedValue = convert<PropertyValue<SymbolZOrderType>>(value, error, false, false); + optional<PropertyValue<SymbolZOrderType>> typedValue = + convert<PropertyValue<SymbolZOrderType>>(value, error, false, false); if (!typedValue) { return error; } @@ -1875,7 +1884,8 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co if (property == Property::TextField) { Error error; - optional<PropertyValue<expression::Formatted>> typedValue = convert<PropertyValue<expression::Formatted>>(value, error, true, true); + optional<PropertyValue<expression::Formatted>> typedValue = + convert<PropertyValue<expression::Formatted>>(value, error, true, true); if (!typedValue) { return error; } @@ -1887,7 +1897,8 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co if (property == Property::TextFont) { Error error; - optional<PropertyValue<std::vector<std::string>>> typedValue = convert<PropertyValue<std::vector<std::string>>>(value, error, true, false); + optional<PropertyValue<std::vector<std::string>>> typedValue = + convert<PropertyValue<std::vector<std::string>>>(value, error, true, false); if (!typedValue) { return error; } @@ -1911,7 +1922,8 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co if (property == Property::TextTransform) { Error error; - optional<PropertyValue<TextTransformType>> typedValue = convert<PropertyValue<TextTransformType>>(value, error, true, false); + optional<PropertyValue<TextTransformType>> typedValue = + convert<PropertyValue<TextTransformType>>(value, error, true, false); if (!typedValue) { return error; } @@ -1923,7 +1935,8 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co if (property == Property::TextVariableAnchor) { Error error; - optional<PropertyValue<std::vector<TextVariableAnchorType>>> typedValue = convert<PropertyValue<std::vector<TextVariableAnchorType>>>(value, error, false, false); + optional<PropertyValue<std::vector<TextVariableAnchorType>>> typedValue = + convert<PropertyValue<std::vector<TextVariableAnchorType>>>(value, error, false, false); if (!typedValue) { return error; } @@ -1935,7 +1948,8 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co if (property == Property::TextWritingMode) { Error error; - optional<PropertyValue<std::vector<TextWritingModeType>>> typedValue = convert<PropertyValue<std::vector<TextWritingModeType>>>(value, error, false, false); + optional<PropertyValue<std::vector<TextWritingModeType>>> typedValue = + convert<PropertyValue<std::vector<TextWritingModeType>>>(value, error, false, false); if (!typedValue) { return error; } diff --git a/src/mbgl/style/layers/symbol_layer_properties.hpp b/src/mbgl/style/layers/symbol_layer_properties.hpp index e44e7e404f..6552589971 100644 --- a/src/mbgl/style/layers/symbol_layer_properties.hpp +++ b/src/mbgl/style/layers/symbol_layer_properties.hpp @@ -31,9 +31,9 @@ struct IconIgnorePlacement : LayoutProperty<bool> { static bool defaultValue() { return false; } }; -struct IconImage : DataDrivenLayoutProperty<std::string> { +struct IconImage : DataDrivenLayoutProperty<expression::Image> { static constexpr const char *name() { return "icon-image"; } - static std::string defaultValue() { return ""; } + static expression::Image defaultValue() { return {}; } }; struct IconKeepUpright : LayoutProperty<bool> { @@ -43,7 +43,7 @@ struct IconKeepUpright : LayoutProperty<bool> { struct IconOffset : DataDrivenLayoutProperty<std::array<float, 2>> { static constexpr const char *name() { return "icon-offset"; } - static std::array<float, 2> defaultValue() { return {{ 0, 0 }}; } + static std::array<float, 2> defaultValue() { return {{0, 0}}; } }; struct IconOptional : LayoutProperty<bool> { @@ -83,7 +83,7 @@ struct IconTextFit : LayoutProperty<IconTextFitType> { struct IconTextFitPadding : LayoutProperty<std::array<float, 4>> { static constexpr const char *name() { return "icon-text-fit-padding"; } - static std::array<float, 4> defaultValue() { return {{ 0, 0, 0, 0 }}; } + static std::array<float, 4> defaultValue() { return {{0, 0, 0, 0}}; } }; struct SymbolAvoidEdges : LayoutProperty<bool> { @@ -123,12 +123,12 @@ struct TextAnchor : DataDrivenLayoutProperty<SymbolAnchorType> { struct TextField : DataDrivenLayoutProperty<expression::Formatted> { static constexpr const char *name() { return "text-field"; } - static expression::Formatted defaultValue() { return ""; } + static expression::Formatted defaultValue() { return {}; } }; struct TextFont : DataDrivenLayoutProperty<std::vector<std::string>> { static constexpr const char *name() { return "text-font"; } - static std::vector<std::string> defaultValue() { return { "Open Sans Regular", "Arial Unicode MS Regular" }; } + static std::vector<std::string> defaultValue() { return {{"Open Sans Regular"}, {"Arial Unicode MS Regular"}}; } }; struct TextIgnorePlacement : LayoutProperty<bool> { @@ -168,7 +168,7 @@ struct TextMaxWidth : DataDrivenLayoutProperty<float> { struct TextOffset : DataDrivenLayoutProperty<std::array<float, 2>> { static constexpr const char *name() { return "text-offset"; } - static std::array<float, 2> defaultValue() { return {{ 0, 0 }}; } + static std::array<float, 2> defaultValue() { return {{0, 0}}; } }; struct TextOptional : LayoutProperty<bool> { @@ -213,12 +213,12 @@ struct TextTransform : DataDrivenLayoutProperty<TextTransformType> { struct TextVariableAnchor : LayoutProperty<std::vector<TextVariableAnchorType>> { static constexpr const char *name() { return "text-variable-anchor"; } - static std::vector<TextVariableAnchorType> defaultValue() { return { }; } + static std::vector<TextVariableAnchorType> defaultValue() { return {}; } }; struct TextWritingMode : LayoutProperty<std::vector<TextWritingModeType>> { static constexpr const char *name() { return "text-writing-mode"; } - static std::vector<TextWritingModeType> defaultValue() { return { }; } + static std::vector<TextWritingModeType> defaultValue() { return {}; } }; struct IconColor : DataDrivenPaintProperty<Color, attributes::fill_color, uniforms::fill_color> { @@ -242,7 +242,7 @@ struct IconOpacity : DataDrivenPaintProperty<float, attributes::opacity, uniform }; struct IconTranslate : PaintProperty<std::array<float, 2>> { - static std::array<float, 2> defaultValue() { return {{ 0, 0 }}; } + static std::array<float, 2> defaultValue() { return {{0, 0}}; } }; struct IconTranslateAnchor : PaintProperty<TranslateAnchorType> { @@ -273,7 +273,7 @@ struct TextOpacity : DataDrivenPaintProperty<float, attributes::opacity, uniform }; struct TextTranslate : PaintProperty<std::array<float, 2>> { - static std::array<float, 2> defaultValue() { return {{ 0, 0 }}; } + static std::array<float, 2> defaultValue() { return {{0, 0}}; } }; struct TextTranslateAnchor : PaintProperty<TranslateAnchorType> { diff --git a/src/mbgl/style/properties.hpp b/src/mbgl/style/properties.hpp index db0e54330c..9c8996fcbe 100644 --- a/src/mbgl/style/properties.hpp +++ b/src/mbgl/style/properties.hpp @@ -169,8 +169,10 @@ public: } template <class T> - static T evaluate(float z, const GeometryTileFeature& feature, - const PossiblyEvaluatedPropertyValue<T>& v, const T& defaultValue) { + static T evaluate(float z, + const GeometryTileFeature& feature, + const PossiblyEvaluatedPropertyValue<T>& v, + const T& defaultValue) { return v.match( [&] (const T& t) { return t; @@ -181,6 +183,17 @@ public: } template <class T> + static T evaluate(float z, + const GeometryTileFeature& feature, + const PossiblyEvaluatedPropertyValue<T>& v, + const T& defaultValue, + const std::set<std::string>& availableImages) { + return v.match( + [&](const T& t) { return t; }, + [&](const PropertyExpression<T>& t) { return t.evaluate(z, feature, availableImages, defaultValue); }); + } + + template <class T> static T evaluate(float z, const GeometryTileFeature& feature, const FeatureState& state, const PossiblyEvaluatedPropertyValue<T>& v, const T& defaultValue) { return v.match([&](const T& t) { return t; }, @@ -197,6 +210,11 @@ public: return evaluate(z, feature, state, this->template get<P>(), P::defaultValue()); } + template <class P> + auto evaluate(float z, const GeometryTileFeature& feature, const std::set<std::string>& availableImages) const { + return evaluate(z, feature, this->template get<P>(), P::defaultValue(), availableImages); + } + Evaluated evaluate(float z, const GeometryTileFeature& feature) const { return Evaluated { evaluate<Ps>(z, feature)... diff --git a/src/mbgl/style/property_expression.cpp b/src/mbgl/style/property_expression.cpp index 9ebecc4b40..d531181e71 100644 --- a/src/mbgl/style/property_expression.cpp +++ b/src/mbgl/style/property_expression.cpp @@ -8,6 +8,7 @@ PropertyExpressionBase::PropertyExpressionBase(std::unique_ptr<expression::Expre zoomCurve(expression::findZoomCurveChecked(expression.get())) { isZoomConstant_ = expression::isZoomConstant(*expression); isFeatureConstant_ = expression::isFeatureConstant(*expression); + isRuntimeConstant_ = expression::isRuntimeConstant(*expression); } bool PropertyExpressionBase::isZoomConstant() const noexcept { @@ -18,19 +19,8 @@ bool PropertyExpressionBase::isFeatureConstant() const noexcept { return isFeatureConstant_; } -bool PropertyExpressionBase::canEvaluateWith(const expression::EvaluationContext& context) const noexcept { - if (context.zoom) { - if (context.feature != nullptr) { - return !isFeatureConstant(); - } - return !isZoomConstant() && isFeatureConstant(); - } - - if (context.feature != nullptr) { - return isZoomConstant() && !isFeatureConstant(); - } - - return true; +bool PropertyExpressionBase::isRuntimeConstant() const noexcept { + return isRuntimeConstant_; } float PropertyExpressionBase::interpolationFactor(const Range<float>& inputLevels, const float inputValue) const noexcept { diff --git a/src/mbgl/tile/geometry_tile.cpp b/src/mbgl/tile/geometry_tile.cpp index 9f9c41d229..4a3d91455a 100644 --- a/src/mbgl/tile/geometry_tile.cpp +++ b/src/mbgl/tile/geometry_tile.cpp @@ -182,7 +182,8 @@ void GeometryTile::setData(std::unique_ptr<const GeometryTileData> data_, bool r pending = true; ++correlationID; - worker.self().invoke(&GeometryTileWorker::setData, std::move(data_), resetLayers, correlationID); + worker.self().invoke( + &GeometryTileWorker::setData, std::move(data_), imageManager.getAvailableImages(), resetLayers, correlationID); } std::unique_ptr<TileRenderData> GeometryTile::createRenderData() { @@ -212,7 +213,8 @@ void GeometryTile::setLayers(const std::vector<Immutable<LayerProperties>>& laye } ++correlationID; - worker.self().invoke(&GeometryTileWorker::setLayers, std::move(impls), correlationID); + worker.self().invoke( + &GeometryTileWorker::setLayers, std::move(impls), imageManager.getAvailableImages(), correlationID); } void GeometryTile::setShowCollisionBoxes(const bool showCollisionBoxes_) { diff --git a/src/mbgl/tile/geometry_tile_worker.cpp b/src/mbgl/tile/geometry_tile_worker.cpp index 7815e62b75..de53c69aee 100644 --- a/src/mbgl/tile/geometry_tile_worker.cpp +++ b/src/mbgl/tile/geometry_tile_worker.cpp @@ -116,10 +116,14 @@ GeometryTileWorker::~GeometryTileWorker() = default; completed parse. */ -void GeometryTileWorker::setData(std::unique_ptr<const GeometryTileData> data_, bool resetLayers_, uint64_t correlationID_) { +void GeometryTileWorker::setData(std::unique_ptr<const GeometryTileData> data_, + std::set<std::string> availableImages_, + bool resetLayers_, + uint64_t correlationID_) { try { data = std::move(data_); correlationID = correlationID_; + availableImages = std::move(availableImages_); if (resetLayers_) layers = nullopt; switch (state) { @@ -139,10 +143,13 @@ void GeometryTileWorker::setData(std::unique_ptr<const GeometryTileData> data_, } } -void GeometryTileWorker::setLayers(std::vector<Immutable<LayerProperties>> layers_, uint64_t correlationID_) { +void GeometryTileWorker::setLayers(std::vector<Immutable<LayerProperties>> layers_, + std::set<std::string> availableImages_, + uint64_t correlationID_) { try { layers = std::move(layers_); correlationID = correlationID_; + availableImages = std::move(availableImages_); switch (state) { case Idle: @@ -365,7 +372,8 @@ void GeometryTileWorker::parse() { // and either immediately create a bucket if no images/glyphs are used, or the Layout is stored until // the images/glyphs are available to add the features to the buckets. if (leaderImpl.getTypeInfo()->layout == LayerTypeInfo::Layout::Required) { - std::unique_ptr<Layout> layout = LayerManager::get()->createLayout({parameters, glyphDependencies, imageDependencies}, std::move(geometryLayer), group); + std::unique_ptr<Layout> layout = LayerManager::get()->createLayout( + {parameters, glyphDependencies, imageDependencies, availableImages}, std::move(geometryLayer), group); if (layout->hasDependencies()) { layouts.push_back(std::move(layout)); } else { diff --git a/src/mbgl/tile/geometry_tile_worker.hpp b/src/mbgl/tile/geometry_tile_worker.hpp index 96b4e2e83a..38f7cb9fa6 100644 --- a/src/mbgl/tile/geometry_tile_worker.hpp +++ b/src/mbgl/tile/geometry_tile_worker.hpp @@ -38,8 +38,13 @@ public: const bool showCollisionBoxes_); ~GeometryTileWorker(); - void setLayers(std::vector<Immutable<style::LayerProperties>>, uint64_t correlationID); - void setData(std::unique_ptr<const GeometryTileData>, bool resetLayers, uint64_t correlationID); + void setLayers(std::vector<Immutable<style::LayerProperties>>, + std::set<std::string> availableImages, + uint64_t correlationID); + void setData(std::unique_ptr<const GeometryTileData>, + std::set<std::string> availableImages, + bool resetLayers, + uint64_t correlationID); void setShowCollisionBoxes(bool showCollisionBoxes_, uint64_t correlationID_); void onGlyphsAvailable(GlyphMap glyphs); @@ -96,7 +101,8 @@ private: ImageMap imageMap; ImageMap patternMap; ImageVersionMap versionMap; - + std::set<std::string> availableImages; + bool showCollisionBoxes; bool firstLoad = true; }; diff --git a/test/api/query.test.cpp b/test/api/query.test.cpp index 54ae89767a..9116a3746d 100644 --- a/test/api/query.test.cpp +++ b/test/api/query.test.cpp @@ -55,7 +55,7 @@ std::vector<Feature> getTopClusterFeature(QueryTest& test) { source->loadDescription(*test.fileSource); auto clusterLayer = std::make_unique<SymbolLayer>("cluster_layer"s, "cluster_source"s); - clusterLayer->setIconImage("test-icon"s); + clusterLayer->setIconImage({"test-icon"s}); clusterLayer->setIconSize(12.0f); test.map.jumpTo(CameraOptions().withCenter(coordinate).withZoom(0.0)); diff --git a/test/fixtures/expression_equality/image.a.json b/test/fixtures/expression_equality/image.a.json new file mode 100644 index 0000000000..930b21dd0e --- /dev/null +++ b/test/fixtures/expression_equality/image.a.json @@ -0,0 +1,4 @@ +[ + "image", + "maki-11" +]
\ No newline at end of file diff --git a/test/fixtures/expression_equality/image.b.json b/test/fixtures/expression_equality/image.b.json new file mode 100644 index 0000000000..edec7d0497 --- /dev/null +++ b/test/fixtures/expression_equality/image.b.json @@ -0,0 +1,4 @@ +[ + "image", + "bicycle-15" +]
\ No newline at end of file diff --git a/test/style/expression/expression.test.cpp b/test/style/expression/expression.test.cpp index ef9f7b7930..a289d7600b 100644 --- a/test/style/expression/expression.test.cpp +++ b/test/style/expression/expression.test.cpp @@ -35,7 +35,8 @@ TEST(Expression, IsExpression) { // TODO: "interpolate-hcl": https://github.com/mapbox/mapbox-gl-native/issues/8720 // TODO: "interpolate-lab": https://github.com/mapbox/mapbox-gl-native/issues/8720 - if (name == "interpolate-hcl" || name == "interpolate-lab") { + // TODO: "in": https://github.com/mapbox/mapbox-gl-native/issues/15893 + if (name == "interpolate-hcl" || name == "interpolate-lab" || name == "in") { if (expression::isExpression(conversion::Convertible(expression))) { ASSERT_TRUE(false) << "Expression name" << name << "is implemented - please update Expression.IsExpression test."; } diff --git a/test/style/property_expression.test.cpp b/test/style/property_expression.test.cpp index 75c8c59490..6334fcbe39 100644 --- a/test/style/property_expression.test.cpp +++ b/test/style/property_expression.test.cpp @@ -14,21 +14,17 @@ using namespace mbgl::style::expression::dsl; using namespace std::string_literals; -static StubGeometryTileFeature oneInteger { - PropertyMap {{ "property", uint64_t(1) }} -}; +static const StubGeometryTileFeature oneInteger{PropertyMap{{"property", uint64_t(1)}}}; -static StubGeometryTileFeature oneDouble { - PropertyMap {{ "property", 1.0 }} -}; +static const StubGeometryTileFeature oneDouble{PropertyMap{{"property", 1.0}}}; -static StubGeometryTileFeature oneString { - PropertyMap {{ "property", "1"s }} -}; +static const StubGeometryTileFeature oneString{PropertyMap{{"property", "1"s}}}; -static StubGeometryTileFeature oneColor { - PropertyMap {{ "color", "red"s }} -}; +static const StubGeometryTileFeature oneColor{PropertyMap{{"color", "red"s}}}; + +static const StubGeometryTileFeature oneImage{PropertyMap{{"image_name", "maki-11"s}}}; + +static const StubGeometryTileFeature emptyTileFeature{PropertyMap{}}; float evaluate(PropertyValue<float> value, float zoom) { return value.evaluate(PropertyEvaluator<float>(PropertyEvaluationParameters(zoom), 0)); @@ -171,3 +167,54 @@ TEST(PropertyExpression, FormatSectionOverride) { EXPECT_TRUE(*override1 != *override4); } } + +TEST(PropertyExpression, ImageExpression) { + const std::set<std::string> emptySet; + const std::set<std::string> availableImages = {"maki-11", "airport-11", "bicycle-15"}; + + // evaluation test without available images + { + PropertyExpression<expression::Image> propExpr(image(literal("airport-11"))); + auto evaluatedImage = propExpr.evaluate(emptyTileFeature, emptySet, expression::Image()); + EXPECT_FALSE(evaluatedImage.isAvailable()); + EXPECT_EQ(evaluatedImage.id(), "airport-11"s); + + PropertyExpression<expression::Image> ddPropExpr(image(get(literal("image_name"s)))); + evaluatedImage = ddPropExpr.evaluate(oneImage, emptySet, expression::Image()); + EXPECT_FALSE(evaluatedImage.isAvailable()); + EXPECT_EQ(evaluatedImage.id(), "maki-11"s); + + evaluatedImage = ddPropExpr.evaluate(emptyTileFeature, emptySet, expression::Image()); + EXPECT_FALSE(evaluatedImage.isAvailable()); + EXPECT_EQ(evaluatedImage.id(), ""s); + } + + // evaluation test with available images + { + PropertyExpression<expression::Image> propExpr(image(literal("airport-11"))); + auto evaluatedImage = propExpr.evaluate(emptyTileFeature, availableImages, expression::Image()); + EXPECT_TRUE(evaluatedImage.isAvailable()); + EXPECT_EQ(evaluatedImage.id(), "airport-11"s); + + PropertyExpression<expression::Image> ddPropExpr(image(get(literal("image_name"s)))); + evaluatedImage = ddPropExpr.evaluate(oneImage, availableImages, expression::Image()); + EXPECT_TRUE(evaluatedImage.isAvailable()); + EXPECT_EQ(evaluatedImage.id(), "maki-11"s); + + evaluatedImage = ddPropExpr.evaluate(emptyTileFeature, availableImages, expression::Image()); + EXPECT_FALSE(evaluatedImage.isAvailable()); + EXPECT_EQ(evaluatedImage.id(), ""s); + } + + // evaluation with zoom + { + auto expr = step(zoom(), image(literal("airport-11")), 18.0, image(literal("bicycle-15"))); + PropertyExpression<expression::Image> propExpr(std::move(expr)); + auto evaluatedImage = propExpr.evaluate(0.0, emptyTileFeature, availableImages, expression::Image()); + EXPECT_TRUE(evaluatedImage.isAvailable()); + EXPECT_EQ(evaluatedImage.id(), "airport-11"s); + evaluatedImage = propExpr.evaluate(18.0, emptyTileFeature, availableImages, expression::Image()); + EXPECT_TRUE(evaluatedImage.isAvailable()); + EXPECT_EQ(evaluatedImage.id(), "bicycle-15"s); + } +} diff --git a/test/style/style_layer.test.cpp b/test/style/style_layer.test.cpp index dfced634b7..2d6ef5881a 100644 --- a/test/style/style_layer.test.cpp +++ b/test/style/style_layer.test.cpp @@ -1,7 +1,7 @@ #include <mbgl/style/expression/dsl.hpp> -#include <mbgl/style/expression/match.hpp> #include <mbgl/style/expression/format_expression.hpp> -#include <mbgl/style/style_impl.hpp> +#include <mbgl/style/expression/image.hpp> +#include <mbgl/style/expression/match.hpp> #include <mbgl/style/layers/background_layer.hpp> #include <mbgl/style/layers/background_layer_impl.hpp> #include <mbgl/style/layers/circle_layer.hpp> @@ -16,12 +16,13 @@ #include <mbgl/style/layers/raster_layer_impl.hpp> #include <mbgl/style/layers/symbol_layer.hpp> #include <mbgl/style/layers/symbol_layer_impl.hpp> -#include <mbgl/test/util.hpp> -#include <mbgl/test/stub_layer_observer.hpp> +#include <mbgl/style/style_impl.hpp> #include <mbgl/test/stub_file_source.hpp> +#include <mbgl/test/stub_layer_observer.hpp> +#include <mbgl/test/util.hpp> #include <mbgl/util/color.hpp> -#include <mbgl/util/run_loop.hpp> #include <mbgl/util/io.hpp> +#include <mbgl/util/run_loop.hpp> #include <memory> @@ -37,7 +38,7 @@ const auto color = Color { 1, 0, 0, 1 }; const auto opacity = 1.0f; const auto radius = 1.0f; const auto blur = 1.0f; -const auto pattern = std::string { "foo" }; +const auto pattern = PropertyValue<expression::Image>{"foo"}; const auto antialias = false; const auto translate = std::array<float, 2> {{ 0, 0 }}; const auto translateAnchor = TranslateAnchorType::Map; diff --git a/test/util/merge_lines.test.cpp b/test/util/merge_lines.test.cpp index 5dc846ad6e..5137a245e5 100644 --- a/test/util/merge_lines.test.cpp +++ b/test/util/merge_lines.test.cpp @@ -19,11 +19,15 @@ LineString<int16_t> emptyLine; class SymbolFeatureStub : public SymbolFeature { public: - SymbolFeatureStub(FeatureIdentifier id_, FeatureType type_, GeometryCollection geometry_, - PropertyMap properties_, optional<std::u16string> text_, - optional<std::string> icon_, std::size_t index_) : - SymbolFeature(std::make_unique<StubGeometryTileFeature>(std::move(id_), type_, std::move(geometry_), std::move(properties_))) - { + SymbolFeatureStub(FeatureIdentifier id_, + FeatureType type_, + GeometryCollection geometry_, + PropertyMap properties_, + optional<std::u16string> text_, + optional<style::expression::Image> icon_, + std::size_t index_) + : SymbolFeature(std::make_unique<StubGeometryTileFeature>( + std::move(id_), type_, std::move(geometry_), std::move(properties_))) { if (text_) { formattedText = TaggedString(*text_, SectionOptions(1.0, {})); } |