From b9aa33736e5482be0fb1482878a4a2b6484782a5 Mon Sep 17 00:00:00 2001 From: Alexander Shalamov Date: Wed, 30 Oct 2019 10:21:17 +0200 Subject: [PATCH 01/10] [core] Implement image expression (#15877) * [core] Bump gl-js version * [core] Implement image expression * [core] Use new image expression * [core] Coerce image expression to / from string * [core] Serialize evaluated image * [core] Pass available images to layout * [core] Pass images to evaluation context * [core] Set available flag value based on image availability * [core] Allow image coercion to boolean to indicate image availability * [core] Coalesce image expression * [core] Add image expression to next build system * [core] Align serialization format and evaluated type with gl-js * [core] Add images to expression evaluation method * [core] Add support for Image expression to expression test runner * [core] Unskip image expression tests * [core] Update unit tests * [core] Use image expression in annotation manager * [core] Add string to ImageExpression conversion * [core] Add image expression to expression dsl * [core] Convert tokens for implicitly created Image literal * [core] Fix clang format * [core] Split generated style code lines that are over 120 characters * [core] Add unit test for image expression equality * [core] Add image property expression evaluation unit test * [core] Unskip image expression render test * [core] Skip 'in' expression tests * [core] Ignore fill-pattern/update-feature-state render test * [core] Rename Image::serialize to Image::toValue --- expression-test/expression_test_parser.cpp | 18 ++- expression-test/expression_test_parser.hpp | 10 +- expression-test/expression_test_runner.cpp | 3 +- include/mbgl/style/conversion/function.hpp | 1 + .../mbgl/style/conversion/property_value.hpp | 6 + include/mbgl/style/conversion_impl.hpp | 1 + include/mbgl/style/expression/dsl.hpp | 4 + include/mbgl/style/expression/expression.hpp | 20 ++- include/mbgl/style/expression/formatted.hpp | 2 +- include/mbgl/style/expression/image.hpp | 49 ++++++ .../style/expression/image_expression.hpp | 33 ++++ include/mbgl/style/expression/is_constant.hpp | 2 + include/mbgl/style/expression/type.hpp | 50 +++--- include/mbgl/style/expression/value.hpp | 21 +-- .../mbgl/style/layers/background_layer.hpp | 6 +- .../style/layers/fill_extrusion_layer.hpp | 6 +- include/mbgl/style/layers/fill_layer.hpp | 6 +- include/mbgl/style/layers/line_layer.hpp | 6 +- include/mbgl/style/layers/symbol_layer.hpp | 6 +- include/mbgl/style/property_expression.hpp | 24 ++- mapbox-gl-js | 2 +- next/CMakeLists.txt | 4 + platform/node/src/node_expression.cpp | 18 +-- platform/node/test/ignores.json | 14 +- scripts/generate-style-code.js | 14 +- src/core-files.json | 4 + src/mbgl/annotation/annotation_manager.cpp | 14 +- .../fill_extrusion_layer_factory.cpp | 2 +- src/mbgl/layermanager/fill_layer_factory.cpp | 2 +- src/mbgl/layermanager/line_layer_factory.cpp | 2 +- .../layermanager/symbol_layer_factory.cpp | 6 +- src/mbgl/layout/layout.hpp | 1 + src/mbgl/layout/pattern_layout.hpp | 46 +++--- src/mbgl/layout/symbol_feature.hpp | 5 +- src/mbgl/layout/symbol_layout.cpp | 23 ++- src/mbgl/layout/symbol_layout.hpp | 5 +- .../cross_faded_property_evaluator.cpp | 3 +- .../data_driven_property_evaluator.hpp | 8 +- src/mbgl/renderer/image_manager.cpp | 6 + src/mbgl/renderer/image_manager.hpp | 3 + .../layers/render_background_layer.cpp | 10 +- .../layers/render_fill_extrusion_layer.cpp | 32 ++-- .../renderer/layers/render_fill_layer.cpp | 35 ++-- .../renderer/layers/render_line_layer.cpp | 31 ++-- .../possibly_evaluated_property_value.hpp | 11 +- src/mbgl/style/conversion/function.cpp | 66 +++++--- src/mbgl/style/conversion/property_value.cpp | 8 +- src/mbgl/style/conversion/stringify.hpp | 5 + src/mbgl/style/expression/check_subtype.cpp | 15 +- src/mbgl/style/expression/coalesce.cpp | 14 ++ src/mbgl/style/expression/coercion.cpp | 27 ++-- src/mbgl/style/expression/dsl.cpp | 27 +++- src/mbgl/style/expression/expression.cpp | 14 +- src/mbgl/style/expression/image.cpp | 67 ++++++++ .../style/expression/image_expression.cpp | 68 ++++++++ src/mbgl/style/expression/is_constant.cpp | 13 ++ src/mbgl/style/expression/parsing_context.cpp | 19 ++- src/mbgl/style/expression/value.cpp | 153 +++++++++--------- src/mbgl/style/layers/background_layer.cpp | 15 +- .../layers/background_layer_properties.hpp | 4 +- src/mbgl/style/layers/circle_layer.cpp | 31 ++-- .../style/layers/circle_layer_properties.hpp | 2 +- .../style/layers/fill_extrusion_layer.cpp | 31 ++-- .../fill_extrusion_layer_properties.hpp | 6 +- src/mbgl/style/layers/fill_layer.cpp | 29 ++-- .../style/layers/fill_layer_properties.hpp | 6 +- src/mbgl/style/layers/heatmap_layer.cpp | 8 +- src/mbgl/style/layers/hillshade_layer.cpp | 15 +- src/mbgl/style/layers/layer.cpp.ejs | 15 +- src/mbgl/style/layers/line_layer.cpp | 40 ++--- .../style/layers/line_layer_properties.hpp | 8 +- src/mbgl/style/layers/raster_layer.cpp | 19 +-- src/mbgl/style/layers/symbol_layer.cpp | 76 +++++---- .../style/layers/symbol_layer_properties.hpp | 22 +-- src/mbgl/style/properties.hpp | 22 ++- src/mbgl/style/property_expression.cpp | 16 +- src/mbgl/tile/geometry_tile.cpp | 6 +- src/mbgl/tile/geometry_tile_worker.cpp | 14 +- src/mbgl/tile/geometry_tile_worker.hpp | 12 +- test/api/query.test.cpp | 2 +- .../fixtures/expression_equality/image.a.json | 4 + .../fixtures/expression_equality/image.b.json | 4 + test/style/expression/expression.test.cpp | 3 +- test/style/property_expression.test.cpp | 71 ++++++-- test/style/style_layer.test.cpp | 13 +- test/util/merge_lines.test.cpp | 14 +- 86 files changed, 1052 insertions(+), 527 deletions(-) create mode 100644 include/mbgl/style/expression/image.hpp create mode 100644 include/mbgl/style/expression/image_expression.hpp create mode 100644 src/mbgl/style/expression/image.cpp create mode 100644 src/mbgl/style/expression/image_expression.cpp create mode 100644 test/fixtures/expression_equality/image.a.json create mode 100644 test/fixtures/expression_equality/image.b.json diff --git a/expression-test/expression_test_parser.cpp b/expression-test/expression_test_parser.cpp index 3b40eeb3b0e..15136f02313 100644 --- a/expression-test/expression_test_parser.cpp +++ b/expression-test/expression_test_parser.cpp @@ -104,8 +104,7 @@ optional 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 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(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(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 561ccd96473..842d8a15634 100644 --- a/expression-test/expression_test_parser.hpp +++ b/expression-test/expression_test_parser.hpp @@ -7,18 +7,24 @@ #include #include -#include +#include #include +#include using namespace mbgl; struct Input { - Input(optional zoom_, optional heatmapDensity_, Feature feature_) + Input(optional zoom_, + optional heatmapDensity_, + std::set availableImages_, + Feature feature_) : zoom(std::move(zoom_)), heatmapDensity(std::move(heatmapDensity_)), + availableImages(std::move(availableImages_)), feature(std::move(feature_)) {} optional zoom; optional heatmapDensity; + std::set availableImages; Feature feature; }; diff --git a/expression-test/expression_test_runner.cpp b/expression-test/expression_test_runner.cpp index c8a39f07ceb..436e4499218 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 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 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 47ce6843b58..9ceeb979ce8 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 convertTokenStringToFormatExpression(const std::string&); +std::unique_ptr convertTokenStringToImageExpression(const std::string&); std::unique_ptr convertTokenStringToExpression(const std::string&); optional> 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 9d619f7a029..61360b7440c 100644 --- a/include/mbgl/style/conversion/property_value.hpp +++ b/include/mbgl/style/conversion/property_value.hpp @@ -39,6 +39,12 @@ struct Converter> { ? PropertyValue(PropertyExpression(convertTokenStringToFormatExpression(firstUnformattedSection))) : PropertyValue(t); } + + PropertyValue maybeConvertTokens(const expression::Image& image) const { + return hasTokens(image.id()) + ? PropertyValue(PropertyExpression(convertTokenStringToImageExpression(image.id()))) + : PropertyValue(image); + } }; } // namespace conversion diff --git a/include/mbgl/style/conversion_impl.hpp b/include/mbgl/style/conversion_impl.hpp index 3e1b8455e5a..73d83302a0f 100644 --- a/include/mbgl/style/conversion_impl.hpp +++ b/include/mbgl/style/conversion_impl.hpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include diff --git a/include/mbgl/style/expression/dsl.hpp b/include/mbgl/style/expression/dsl.hpp index 4abeac79891..347861abc91 100644 --- a/include/mbgl/style/expression/dsl.hpp +++ b/include/mbgl/style/expression/dsl.hpp @@ -49,6 +49,7 @@ std::unique_ptr toString(std::unique_ptr, std::unique_ptr def = nullptr); std::unique_ptr toFormatted(std::unique_ptr, std::unique_ptr def = nullptr); +std::unique_ptr toImage(std::unique_ptr, std::unique_ptr def = nullptr); std::unique_ptr get(const char* value); std::unique_ptr get(std::unique_ptr); @@ -89,6 +90,9 @@ std::unique_ptr concat(std::vector> inpu std::unique_ptr format(const char* value); std::unique_ptr format(std::unique_ptr); +std::unique_ptr image(const char* value); +std::unique_ptr image(std::unique_ptr); + } // namespace dsl } // namespace expression } // namespace style diff --git a/include/mbgl/style/expression/expression.hpp b/include/mbgl/style/expression/expression.hpp index 1341a8d0411..9893daa8c42 100644 --- a/include/mbgl/style/expression/expression.hpp +++ b/include/mbgl/style/expression/expression.hpp @@ -28,9 +28,7 @@ class EvaluationContext { 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 accumulated_, GeometryTileFeature const * feature_) : accumulated(std::move(accumulated_)), feature(feature_) {} @@ -50,6 +48,11 @@ class EvaluationContext { return *this; }; + EvaluationContext& withAvailableImages(const std::set* availableImages_) noexcept { + availableImages = availableImages_; + return *this; + }; + optional zoom; optional accumulated; GeometryTileFeature const * feature = nullptr; @@ -57,6 +60,7 @@ class EvaluationContext { // Contains formatted section object, std::unordered_map. const Value* formattedSection = nullptr; const FeatureState* featureState = nullptr; + const std::set* availableImages = nullptr; }; template @@ -155,7 +159,8 @@ enum class Kind : int32_t { Comparison, FormatExpression, FormatSectionOverride, - NumberFormat + NumberFormat, + ImageExpression }; class Expression { @@ -172,9 +177,14 @@ class Expression { Kind getKind() const { return kind; }; type::Type getType() const { return type; }; - + EvaluationResult evaluate(optional zoom, const Feature& feature, optional colorRampParameter) const; + EvaluationResult evaluate(optional zoom, + const Feature& feature, + optional colorRampParameter, + const std::set& availableImages) const; EvaluationResult evaluate(optional 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 bb3d609c912..09edad240fa 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 00000000000..0bc4794a242 --- /dev/null +++ b/include/mbgl/style/expression/image.hpp @@ -0,0 +1,49 @@ +#pragma once + +#include +#include +#include + +#include +#include + +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 { +public: + optional operator()(const Convertible& value, Error& error) const; +}; + +template <> +struct ValueFactory { + 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 00000000000..cd3d3752848 --- /dev/null +++ b/include/mbgl/style/expression/image_expression.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include + +namespace mbgl { +namespace style { +namespace expression { + +class ParsingContext; + +class ImageExpression final : public Expression { +public: + explicit ImageExpression(std::unique_ptr imageID); + + EvaluationResult evaluate(const EvaluationContext&) const override; + static ParseResult parse(const mbgl::style::conversion::Convertible&, ParsingContext&); + + void eachChild(const std::function&) const override; + + bool operator==(const Expression& e) const override; + + std::vector> possibleOutputs() const override { return {nullopt}; } + + mbgl::Value serialize() const override; + std::string getOperator() const override { return "image"; } + +private: + std::shared_ptr 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 2861407af0f..a9c41e48b1a 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 a5a1e761644..ab398741f0a 100644 --- a/include/mbgl/style/expression/type.hpp +++ b/include/mbgl/style/expression/type.hpp @@ -14,65 +14,70 @@ template 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, - CollatorType, - FormattedType, - ErrorType>; +using Type = variant, + 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 91239d083fe..902f5ae2091 100644 --- a/include/mbgl/style/expression/value.hpp +++ b/include/mbgl/style/expression/value.hpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -19,16 +20,16 @@ namespace expression { struct Value; -using ValueBase = variant< - NullValue, - bool, - double, - std::string, - Color, - Collator, - Formatted, - mapbox::util::recursive_wrapper>, - mapbox::util::recursive_wrapper>>; +using ValueBase = variant>, + mapbox::util::recursive_wrapper>>; 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 ebdce35d0f1..bc9d5222fd6 100644 --- a/include/mbgl/style/layers/background_layer.hpp +++ b/include/mbgl/style/layers/background_layer.hpp @@ -40,9 +40,9 @@ class BackgroundLayer : public Layer { void setBackgroundOpacityTransition(const TransitionOptions&); TransitionOptions getBackgroundOpacityTransition() const; - static PropertyValue getDefaultBackgroundPattern(); - const PropertyValue& getBackgroundPattern() const; - void setBackgroundPattern(const PropertyValue&); + static PropertyValue getDefaultBackgroundPattern(); + const PropertyValue& getBackgroundPattern() const; + void setBackgroundPattern(const PropertyValue&); 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 76c2359617b..2996cd00669 100644 --- a/include/mbgl/style/layers/fill_extrusion_layer.hpp +++ b/include/mbgl/style/layers/fill_extrusion_layer.hpp @@ -52,9 +52,9 @@ class FillExtrusionLayer : public Layer { void setFillExtrusionOpacityTransition(const TransitionOptions&); TransitionOptions getFillExtrusionOpacityTransition() const; - static PropertyValue getDefaultFillExtrusionPattern(); - const PropertyValue& getFillExtrusionPattern() const; - void setFillExtrusionPattern(const PropertyValue&); + static PropertyValue getDefaultFillExtrusionPattern(); + const PropertyValue& getFillExtrusionPattern() const; + void setFillExtrusionPattern(const PropertyValue&); 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 9ec33d7e96a..90e51c85a3b 100644 --- a/include/mbgl/style/layers/fill_layer.hpp +++ b/include/mbgl/style/layers/fill_layer.hpp @@ -52,9 +52,9 @@ class FillLayer : public Layer { void setFillOutlineColorTransition(const TransitionOptions&); TransitionOptions getFillOutlineColorTransition() const; - static PropertyValue getDefaultFillPattern(); - const PropertyValue& getFillPattern() const; - void setFillPattern(const PropertyValue&); + static PropertyValue getDefaultFillPattern(); + const PropertyValue& getFillPattern() const; + void setFillPattern(const PropertyValue&); 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 4f2cf537081..33312795d0e 100644 --- a/include/mbgl/style/layers/line_layer.hpp +++ b/include/mbgl/style/layers/line_layer.hpp @@ -91,9 +91,9 @@ class LineLayer : public Layer { void setLineOpacityTransition(const TransitionOptions&); TransitionOptions getLineOpacityTransition() const; - static PropertyValue getDefaultLinePattern(); - const PropertyValue& getLinePattern() const; - void setLinePattern(const PropertyValue&); + static PropertyValue getDefaultLinePattern(); + const PropertyValue& getLinePattern() const; + void setLinePattern(const PropertyValue&); 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 92e214919ab..0ef212a3b98 100644 --- a/include/mbgl/style/layers/symbol_layer.hpp +++ b/include/mbgl/style/layers/symbol_layer.hpp @@ -42,9 +42,9 @@ class SymbolLayer : public Layer { const PropertyValue& getIconIgnorePlacement() const; void setIconIgnorePlacement(const PropertyValue&); - static PropertyValue getDefaultIconImage(); - const PropertyValue& getIconImage() const; - void setIconImage(const PropertyValue&); + static PropertyValue getDefaultIconImage(); + const PropertyValue& getIconImage() const; + void setIconImage(const PropertyValue&); static PropertyValue getDefaultIconKeepUpright(); const PropertyValue& getIconKeepUpright() const; diff --git a/include/mbgl/style/property_expression.hpp b/include/mbgl/style/property_expression.hpp index f68285fb1b1..7dcd818dded 100644 --- a/include/mbgl/style/property_expression.hpp +++ b/include/mbgl/style/property_expression.hpp @@ -16,7 +16,7 @@ class PropertyExpressionBase { bool isZoomConstant() const noexcept; bool isFeatureConstant() const noexcept; - bool canEvaluateWith(const expression::EvaluationContext&) const noexcept; + bool isRuntimeConstant() const noexcept; float interpolationFactor(const Range&, const float) const noexcept; Range getCoveringStops(const float, const float) const noexcept; const expression::Expression& getExpression() const noexcept; @@ -28,6 +28,7 @@ class PropertyExpressionBase { variant zoomCurve; bool isZoomConstant_; bool isFeatureConstant_; + bool isRuntimeConstant_; }; template @@ -40,7 +41,6 @@ class PropertyExpression final : public PropertyExpressionBase { } T evaluate(const expression::EvaluationContext& context, T finalDefaultValue = T()) const { - assert(canEvaluateWith(context)); const expression::EvaluationResult result = expression->evaluate(context); if (result) { const optional typed = expression::fromExpressionValue(*result); @@ -50,18 +50,38 @@ class PropertyExpression final : public PropertyExpressionBase { } 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& 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& 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 index 6453c38a511..cbbbbfc523e 160000 --- a/mapbox-gl-js +++ b/mapbox-gl-js @@ -1 +1 @@ -Subproject commit 6453c38a5118e52e7cc7fb9b6e23d28e5bf5268b +Subproject commit cbbbbfc523ed78bb0d8d03de2efabe825e55f198 diff --git a/next/CMakeLists.txt b/next/CMakeLists.txt index aa26e3a5729..5ba734f4814 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 e1c3ba0c398..81d5c74767c 100644 --- a/platform/node/src/node_expression.cpp +++ b/platform/node/src/node_expression.cpp @@ -35,16 +35,14 @@ void NodeExpression::Init(v8::Local target) { } type::Type parseType(v8::Local type) { - static std::unordered_map 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 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 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 51decb351c0..438677fff98 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 0aedba909b1..db2548680e4 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 c25e8273d4b..b0bf177c2e3 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 345171b96e8..b5dfea8e1a7 100644 --- a/src/mbgl/annotation/annotation_manager.cpp +++ b/src/mbgl/annotation/annotation_manager.cpp @@ -1,15 +1,16 @@ #include #include #include -#include -#include #include +#include +#include #include -#include -#include +#include +#include #include #include -#include +#include +#include #include @@ -184,7 +185,8 @@ void AnnotationManager::updateStyle() { using namespace expression::dsl; layer->setSourceLayer(PointLayerID); - layer->setIconImage(PropertyExpression(concat(vec(literal(SourceID + "."), toString(get("sprite")))))); + layer->setIconImage(PropertyExpression( + 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 0163321914c..e1bedb52460 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 FillExtrusionLayerFactory::createLayout(const LayoutPara const std::vector>& group) noexcept { using namespace style; using LayoutType = PatternLayout; - return std::make_unique(parameters.bucketParameters, group, std::move(layer), parameters.imageDependencies); + return std::make_unique(parameters.bucketParameters, group, std::move(layer), parameters); } std::unique_ptr FillExtrusionLayerFactory::createRenderLayer(Immutable impl) noexcept { diff --git a/src/mbgl/layermanager/fill_layer_factory.cpp b/src/mbgl/layermanager/fill_layer_factory.cpp index f7f24c58a1a..265fdc69f6c 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>& group) noexcept { using namespace style; using LayoutType = PatternLayout; - return std::make_unique(parameters.bucketParameters, group, std::move(layer), parameters.imageDependencies); + return std::make_unique(parameters.bucketParameters, group, std::move(layer), parameters); } std::unique_ptr FillLayerFactory::createRenderLayer(Immutable impl) noexcept { diff --git a/src/mbgl/layermanager/line_layer_factory.cpp b/src/mbgl/layermanager/line_layer_factory.cpp index b0f2827a800..5770b19f33c 100644 --- a/src/mbgl/layermanager/line_layer_factory.cpp +++ b/src/mbgl/layermanager/line_layer_factory.cpp @@ -29,7 +29,7 @@ std::unique_ptr LineLayerFactory::createLayout(const LayoutParameters& p const std::vector>& group) noexcept { using namespace style; using LayoutType = PatternLayout; - return std::make_unique(parameters.bucketParameters, group, std::move(layer), parameters.imageDependencies); + return std::make_unique(parameters.bucketParameters, group, std::move(layer), parameters); } std::unique_ptr LineLayerFactory::createRenderLayer(Immutable impl) noexcept { diff --git a/src/mbgl/layermanager/symbol_layer_factory.cpp b/src/mbgl/layermanager/symbol_layer_factory.cpp index 7141f5a223e..11a4f09ec3f 100644 --- a/src/mbgl/layermanager/symbol_layer_factory.cpp +++ b/src/mbgl/layermanager/symbol_layer_factory.cpp @@ -27,11 +27,7 @@ std::unique_ptr SymbolLayerFactory::createLayer(const std::string& std::unique_ptr SymbolLayerFactory::createLayout(const LayoutParameters& parameters, std::unique_ptr tileLayer, const std::vector>& group) noexcept { - return std::make_unique(parameters.bucketParameters, - group, - std::move(tileLayer), - parameters.imageDependencies, - parameters.glyphDependencies); + return std::make_unique(parameters.bucketParameters, group, std::move(tileLayer), parameters); } std::unique_ptr SymbolLayerFactory::createRenderLayer(Immutable impl) noexcept { diff --git a/src/mbgl/layout/layout.hpp b/src/mbgl/layout/layout.hpp index d1f03792c19..91d3e3f596c 100644 --- a/src/mbgl/layout/layout.hpp +++ b/src/mbgl/layout/layout.hpp @@ -38,6 +38,7 @@ class LayoutParameters { const BucketParameters& bucketParameters; GlyphDependencies& glyphDependencies; ImageDependencies& imageDependencies; + std::set& availableImages; }; } // namespace mbgl diff --git a/src/mbgl/layout/pattern_layout.hpp b/src/mbgl/layout/pattern_layout.hpp index d6d878955f3..48531e836ba 100644 --- a/src/mbgl/layout/pattern_layout.hpp +++ b/src/mbgl/layout/pattern_layout.hpp @@ -1,8 +1,9 @@ #pragma once +#include #include #include -#include #include +#include #include namespace mbgl { @@ -32,11 +33,11 @@ class PatternLayout : public Layout { PatternLayout(const BucketParameters& parameters, const std::vector>& group, std::unique_ptr 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(group.front()); layout = leaderLayerProperties->layerImpl().layout.evaluate(PropertyEvaluationParameters(zoom)); @@ -47,15 +48,15 @@ class PatternLayout : public Layout { const std::string& layerId = layerProperties->baseImpl->id; const auto& evaluated = style::getEvaluated(layerProperties); const auto patternProperty = evaluated.template get(); - const auto constantPattern = patternProperty.constantOr(Faded >{ "", ""}); + const auto constantPattern = patternProperty.constantOr(Faded{"", ""}); // 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 @@ class PatternLayout : public Layout { 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 03d8e5018db..d0aced1b19a 100644 --- a/src/mbgl/layout/symbol_feature.hpp +++ b/src/mbgl/layout/symbol_feature.hpp @@ -1,8 +1,9 @@ #pragma once +#include +#include #include #include -#include #include #include @@ -29,7 +30,7 @@ class SymbolFeature : public GeometryTileFeature { std::unique_ptr feature; GeometryCollection geometry; optional formattedText; - optional icon; + optional 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 d0227c36c56..af0b1bd21b4 100644 --- a/src/mbgl/layout/symbol_layout.cpp +++ b/src/mbgl/layout/symbol_layout.cpp @@ -81,8 +81,7 @@ inline Immutable createLayout( SymbolLayout::SymbolLayout(const BucketParameters& parameters, const std::vector>& layers, std::unique_ptr 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(zoom, ft); + auto formatted = layout->evaluate(zoom, ft, layoutParameters.availableImages); auto textTransform = layout->evaluate(zoom, ft); FontStack baseFontStack = layout->evaluate(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(zoom, ft); - imageDependencies.emplace(*ft.icon, ImageType::Icon); + ft.icon = layout->evaluate(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(zoom, feature), - layout->evaluate(zoom, feature), - layout->evaluate(zoom, feature) * util::DEG2RAD); + shapedIcon = PositionedIcon::shapeIcon(imagePositions.at(feature.icon->id()), + layout->evaluate(zoom, feature), + layout->evaluate(zoom, feature), + layout->evaluate(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 1abcaaa5d6a..2b99c2fa24d 100644 --- a/src/mbgl/layout/symbol_layout.hpp +++ b/src/mbgl/layout/symbol_layout.hpp @@ -27,9 +27,8 @@ class SymbolLayout final : public Layout { SymbolLayout(const BucketParameters&, const std::vector>&, std::unique_ptr, - 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 7be9c2bcf55..65f5b31467b 100644 --- a/src/mbgl/renderer/cross_faded_property_evaluator.cpp +++ b/src/mbgl/renderer/cross_faded_property_evaluator.cpp @@ -1,4 +1,5 @@ #include +#include #include #include @@ -30,7 +31,7 @@ Faded CrossFadedPropertyEvaluator::calculate(const T& min, const T& mid, c : Faded { max, mid }; } -template class CrossFadedPropertyEvaluator; +template class CrossFadedPropertyEvaluator; template class CrossFadedPropertyEvaluator>; } // namespace mbgl diff --git a/src/mbgl/renderer/data_driven_property_evaluator.hpp b/src/mbgl/renderer/data_driven_property_evaluator.hpp index efac9e4532e..c2e6d9f2839 100644 --- a/src/mbgl/renderer/data_driven_property_evaluator.hpp +++ b/src/mbgl/renderer/data_driven_property_evaluator.hpp @@ -26,14 +26,14 @@ class DataDrivenPropertyEvaluator { ResultType operator()(const style::PropertyExpression& 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 @@ class DataDrivenPropertyEvaluator> { } ResultType operator()(const style::PropertyExpression& 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 2ea753d8aa0..4927ade8e9e 100644 --- a/src/mbgl/renderer/image_manager.cpp +++ b/src/mbgl/renderer/image_manager.cpp @@ -43,6 +43,7 @@ void ImageManager::addImage(Immutable 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& 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 5ed6e237f03..7d5884edc16 100644 --- a/src/mbgl/renderer/image_manager.hpp +++ b/src/mbgl/renderer/image_manager.hpp @@ -47,6 +47,7 @@ class ImageManager { void notifyIfMissingImageAdded(); void reduceMemoryUse(); void reduceMemoryUseIfCacheSizeExceedsLimit(); + const std::set& getAvailableImages() const; ImageVersionMap updatedImageVersions; @@ -62,6 +63,8 @@ class ImageManager { std::map> requestedImages; std::size_t requestedImagesCacheSize = 0ul; ImageMap images; + // Mirror of 'ImageMap images;' keys. + std::set 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 6f76efda7a9..694addcc97b 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(*evaluatedProperties).evaluated; const auto& crossfade = static_cast(*evaluatedProperties).crossfade; if (!evaluated.get().to.empty()) { - optional imagePosA = parameters.patternAtlas.getPattern(evaluated.get().from); - optional imagePosB = parameters.patternAtlas.getPattern(evaluated.get().to); + optional imagePosA = + parameters.patternAtlas.getPattern(evaluated.get().from.id()); + optional imagePosB = + parameters.patternAtlas.getPattern(evaluated.get().to.id()); if (!imagePosA || !imagePosB) return; @@ -176,8 +178,8 @@ void RenderBackgroundLayer::prepare(const LayerPrepareParameters& params) { if (!evaluated.get().to.empty()) { // Ensures that the pattern bitmap gets copied to atlas bitmap. // Atlas bitmap is uploaded to atlas texture in upload. - addPatternIfNeeded(evaluated.get().from, params); - addPatternIfNeeded(evaluated.get().to, params); + addPatternIfNeeded(evaluated.get().from.id(), params); + addPatternIfNeeded(evaluated.get().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 fc830e462cd..af0bc788d05 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 +#include +#include +#include +#include +#include +#include #include -#include -#include #include +#include +#include #include -#include -#include -#include +#include +#include #include -#include -#include -#include #include -#include -#include -#include +#include +#include +#include namespace mbgl { @@ -171,7 +172,8 @@ void RenderFillExtrusionLayer::render(PaintParameters& parameters) { } } else { // Draw textured extrusions - const auto fillPatternValue = evaluated.get().constantOr(mbgl::Faded >{"", ""}); + const auto fillPatternValue = + evaluated.get().constantOr(mbgl::Faded{"", ""}); 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(*renderData->bucket); - optional patternPosA = tile.getPattern(fillPatternValue.from); - optional patternPosB = tile.getPattern(fillPatternValue.to); + optional patternPosA = tile.getPattern(fillPatternValue.from.id()); + optional 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 e855866eeaa..bbfcef7aba4 100644 --- a/src/mbgl/renderer/layers/render_fill_layer.cpp +++ b/src/mbgl/renderer/layers/render_fill_layer.cpp @@ -1,21 +1,22 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include #include +#include #include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include +#include +#include namespace mbgl { @@ -171,9 +172,9 @@ void RenderFillLayer::render(PaintParameters& parameters) { const auto& evaluated = getEvaluated(renderData->layerProperties); const auto& crossfade = getCrossfade(renderData->layerProperties); - const auto& fillPatternValue = evaluated.get().constantOr(Faded>{"", ""}); - optional patternPosA = tile.getPattern(fillPatternValue.from); - optional patternPosB = tile.getPattern(fillPatternValue.to); + const auto& fillPatternValue = evaluated.get().constantOr(Faded{"", ""}); + optional patternPosA = tile.getPattern(fillPatternValue.from.id()); + optional 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 e5bbe74bf97..588cf6286cf 100644 --- a/src/mbgl/renderer/layers/render_line_layer.cpp +++ b/src/mbgl/renderer/layers/render_line_layer.cpp @@ -1,20 +1,21 @@ -#include +#include +#include +#include +#include +#include #include -#include +#include +#include +#include #include +#include #include -#include -#include -#include -#include -#include -#include +#include #include -#include -#include -#include -#include #include +#include +#include +#include namespace mbgl { @@ -168,11 +169,11 @@ void RenderLineLayer::render(PaintParameters& parameters) { }); } else if (!unevaluated.get().isUndefined()) { - const auto& linePatternValue = evaluated.get().constantOr(Faded>{ "", ""}); + const auto& linePatternValue = evaluated.get().constantOr(Faded{"", ""}); const Size& texsize = tile.getIconAtlasTexture().size; - optional posA = tile.getPattern(linePatternValue.from); - optional posB = tile.getPattern(linePatternValue.to); + optional posA = tile.getPattern(linePatternValue.from.id()); + optional 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 1198e43aae0..5e412855a4a 100644 --- a/src/mbgl/renderer/possibly_evaluated_property_value.hpp +++ b/src/mbgl/renderer/possibly_evaluated_property_value.hpp @@ -93,16 +93,19 @@ class PossiblyEvaluatedPropertyValue> { } template - Faded evaluate(const Feature& feature, float zoom, T defaultValue) const { + Faded evaluate(const Feature& feature, + float zoom, + const std::set& availableImages, + T defaultValue) const { return this->match( [&] (const Faded& constant_) { return constant_; }, [&] (const style::PropertyExpression& 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 {min, max}; } else { - const T evaluated = expression.evaluate(feature, defaultValue); + const T evaluated = expression.evaluate(feature, availableImages, defaultValue); return Faded {evaluated, evaluated}; } } diff --git a/src/mbgl/style/conversion/function.cpp b/src/mbgl/style/conversion/function.cpp index 646c1983a2e..4b3b8f6c6a8 100644 --- a/src/mbgl/style/conversion/function.cpp +++ b/src/mbgl/style/conversion/function.cpp @@ -1,13 +1,14 @@ #include #include #include +#include #include #include -#include +#include +#include #include #include -#include -#include +#include #include #include @@ -46,6 +47,10 @@ std::unique_ptr convertTokenStringToFormatExpression(const std::stri return std::make_unique(sections); } +std::unique_ptr convertTokenStringToImageExpression(const std::string& source) { + return std::make_unique(convertTokenStringToExpression(source)); +} + std::unique_ptr convertTokenStringToExpression(const std::string& source) { std::vector> inputs; @@ -149,11 +154,11 @@ template optional> convertFunctionToExpression(const Convertible&, Error&, bool); template optional> convertFunctionToExpression(const Convertible&, Error&, bool); - template optional> convertFunctionToExpression(const Convertible&, Error&, bool); template optional>> convertFunctionToExpression>(const Convertible&, Error&, bool); +template optional> convertFunctionToExpression(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> convertLiteral(type::Type type, const Convertible& value, Error& error, bool convertTokens = false) { return type.match( - [&] (const type::NumberType&) -> optional> { + [&](const type::NumberType&) -> optional> { auto result = convert(value, error); if (!result) { return nullopt; } return literal(double(*result)); }, - [&] (const type::BooleanType&) -> optional> { + [&](const type::BooleanType&) -> optional> { auto result = convert(value, error); if (!result) { return nullopt; } return literal(*result); }, - [&] (const type::StringType&) -> optional> { + [&](const type::StringType&) -> optional> { auto result = convert(value, error); if (!result) { return nullopt; } return convertTokens ? convertTokenStringToExpression(*result) : literal(*result); }, - [&] (const type::ColorType&) -> optional> { + [&](const type::ColorType&) -> optional> { auto result = convert(value, error); if (!result) { return nullopt; } return literal(*result); }, - [&] (const type::Array& array) -> optional> { + [&](const type::Array& array) -> optional> { if (!isArray(value)) { error.message = "value must be an array"; return nullopt; @@ -277,27 +282,27 @@ static optional> convertLiteral(type::Type type, con } ); }, - [&] (const type::NullType&) -> optional> { + [&](const type::NullType&) -> optional> { assert(false); // No properties use this type. return nullopt; }, - [&] (const type::ObjectType&) -> optional> { + [&](const type::ObjectType&) -> optional> { assert(false); // No properties use this type. return nullopt; }, - [&] (const type::ErrorType&) -> optional> { + [&](const type::ErrorType&) -> optional> { assert(false); // No properties use this type. return nullopt; }, - [&] (const type::ValueType&) -> optional> { + [&](const type::ValueType&) -> optional> { assert(false); // No properties use this type. return nullopt; }, - [&] (const type::CollatorType&) -> optional> { + [&](const type::CollatorType&) -> optional> { assert(false); // No properties use this type. return nullopt; }, - [&] (const type::FormattedType&) -> optional> { + [&](const type::FormattedType&) -> optional> { auto result = convert(value, error); if (!result) { return nullopt; @@ -305,8 +310,15 @@ static optional> convertLiteral(type::Type type, con return convertTokens ? convertTokenStringToFormatExpression(*result) : literal(Formatted(result->c_str())); - } - ); + }, + [&](const type::ImageType&) -> optional> { + auto result = convert(value, error); + if (!result) { + return nullopt; + } + return convertTokens ? std::make_unique(convertTokenStringToImageExpression(*result)) + : literal(Image(result->c_str())); + }); } static optional>> convertStops(type::Type type, @@ -749,29 +761,31 @@ optional> convertFunctionToExpression(type::Type typ if (functionType == FunctionType::Identity) { return type.match( - [&] (const type::StringType&) -> optional> { + [&](const type::StringType&) -> optional> { return string(get(literal(*property)), defaultExpr()); }, - [&] (const type::NumberType&) -> optional> { + [&](const type::NumberType&) -> optional> { return number(get(literal(*property)), defaultExpr()); }, - [&] (const type::BooleanType&) -> optional> { + [&](const type::BooleanType&) -> optional> { return boolean(get(literal(*property)), defaultExpr()); }, - [&] (const type::ColorType&) -> optional> { + [&](const type::ColorType&) -> optional> { return toColor(get(literal(*property)), defaultExpr()); }, - [&] (const type::Array& array) -> optional> { + [&](const type::Array& array) -> optional> { return assertion(array, get(literal(*property)), defaultExpr()); }, - [&] (const type::FormattedType&) -> optional> { + [&](const type::FormattedType&) -> optional> { return toFormatted(get(literal(*property)), defaultExpr()); }, - [&] (const auto&) -> optional> { + [&](const type::ImageType&) -> optional> { + return toImage(get(literal(*property)), defaultExpr()); + }, + [&](const auto&) -> optional> { 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 5c2f720a60c..5e03189e646 100644 --- a/src/mbgl/style/conversion/property_value.cpp +++ b/src/mbgl/style/conversion/property_value.cpp @@ -39,7 +39,8 @@ optional> Converter>::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 constant = fromExpressionValue( @@ -81,6 +82,11 @@ template optional> Converter> Converter>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const; template optional> Converter>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const; template optional>> Converter>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const; +template optional> +Converter>::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 7520bcac9c2..38161824509 100644 --- a/src/mbgl/style/conversion/stringify.hpp +++ b/src/mbgl/style/conversion/stringify.hpp @@ -141,6 +141,11 @@ void stringify(Writer& writer, const expression::Formatted& v) { stringify(writer, expression::ValueConverter::fromExpressionValue(v)); } +template +void stringify(Writer& writer, const expression::Image& v) { + stringify(writer, expression::ValueConverter::fromExpressionValue(v)); +} + template void stringify(Writer& writer, const Undefined&) { assert(false); // Should be omitted entirely instead. diff --git a/src/mbgl/style/expression/check_subtype.cpp b/src/mbgl/style/expression/check_subtype.cpp index 73e6e3bff70..9895bce667f 100644 --- a/src/mbgl/style/expression/check_subtype.cpp +++ b/src/mbgl/style/expression/check_subtype.cpp @@ -32,18 +32,9 @@ optional checkSubtype(const Type& expected, const Type& t) { }, [&] (const ValueType&) -> optional { if (t.is()) 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 6b43e68ac6f..ab30e7a8df9 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 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(*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 284d6f2e3e1..d65558e28d2 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(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(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> inputs_) : Expression(Kind::Coercion, std::move(type_)), inputs(std::move(inputs_)) @@ -102,6 +105,8 @@ Coercion::Coercion(type::Type type_, std::vector> in coerceSingleValue = [] (const Value& v) -> EvaluationResult { return toString(v); }; } else if (t.is()) { coerceSingleValue = toFormatted; + } else if (t.is()) { + 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()); return serialized; + } else if (getType().is()) { + return std::vector{{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 fac7dfbbd93..6405149fe9b 100644 --- a/src/mbgl/style/expression/dsl.cpp +++ b/src/mbgl/style/expression/dsl.cpp @@ -1,14 +1,15 @@ -#include -#include -#include -#include #include #include #include -#include -#include #include +#include +#include +#include #include +#include +#include +#include +#include #include #include @@ -122,7 +123,11 @@ std::unique_ptr toFormatted(std::unique_ptr value, std::unique_ptr def) { return coercion(type::Formatted, std::move(value), std::move(def)); } - + +std::unique_ptr toImage(std::unique_ptr value, std::unique_ptr def) { + return coercion(type::Image, std::move(value), std::move(def)); +} + std::unique_ptr get(const char* value) { return get(literal(value)); } @@ -237,6 +242,14 @@ std::unique_ptr format(std::unique_ptr input) { return std::make_unique(sections); } +std::unique_ptr image(const char* value) { + return std::make_unique(Image(value)); +} + +std::unique_ptr image(std::unique_ptr expression) { + return std::make_unique(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 6bfda99064d..3252bb632f7 100644 --- a/src/mbgl/style/expression/expression.cpp +++ b/src/mbgl/style/expression/expression.cpp @@ -25,12 +25,22 @@ class GeoJSONFeature : public GeometryTileFeature { return optional(); } }; - -EvaluationResult Expression::evaluate(optional zoom, const Feature& feature, optional colorRampParameter) const { + +EvaluationResult Expression::evaluate(optional zoom, + const Feature& feature, + optional colorRampParameter) const { GeoJSONFeature f(feature); return this->evaluate(EvaluationContext(zoom, &f, colorRampParameter)); } +EvaluationResult Expression::evaluate(optional zoom, + const Feature& feature, + optional colorRampParameter, + const std::set& availableImages) const { + GeoJSONFeature f(feature); + return this->evaluate(EvaluationContext(zoom, &f, colorRampParameter).withAvailableImages(&availableImages)); +} + EvaluationResult Expression::evaluate(optional 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 00000000000..1dc7acde56c --- /dev/null +++ b/src/mbgl/style/expression/image.cpp @@ -0,0 +1,67 @@ +#include +#include +#include + +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 Converter::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 imageID = toString(arrayMember(imageParameters, 0)); + if (!imageID) { + error.message = "Image has to contain an ID."; + return nullopt; + } + + return Image(*imageID, false); + } else if (optional 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 00000000000..df535d4e819 --- /dev/null +++ b/src/mbgl/style/expression/image_expression.cpp @@ -0,0 +1,68 @@ +#include +#include +#include + +namespace mbgl { +namespace style { +namespace expression { + +ImageExpression::ImageExpression(std::unique_ptr 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(std::move(*imageIDExpr))); +} + +void ImageExpression::eachChild(const std::function& fn) const { + fn(*imageID); +} + +bool ImageExpression::operator==(const Expression& e) const { + if (e.getKind() == Kind::ImageExpression) { + auto rhs = static_cast(&e); + return *imageID == *rhs->imageID; + } + return false; +} + +mbgl::Value ImageExpression::serialize() const { + std::vector 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 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 4c4684c86ad..eb823bc77c4 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{{"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 699190608bd..ae991b2e880 100644 --- a/src/mbgl/style/expression/parsing_context.cpp +++ b/src/mbgl/style/expression/parsing_context.cpp @@ -4,22 +4,23 @@ #include #include -#include -#include #include +#include #include #include #include #include -#include #include -#include +#include +#include #include +#include #include #include #include #include #include +#include #include #include @@ -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, optionalgetType(); if ((*expected == type::String || *expected == type::Number || *expected == type::Boolean || *expected == type::Object || expected->is()) && 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, optionalgetKind() != 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 6d18f1b9bd0..7609230b52f 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&) -> type::Type { return type::Object; }, - [&](const std::vector& arr) -> type::Type { - optional 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&) -> type::Type { return type::Object; }, + [&](const std::vector& arr) -> type::Type { + optional 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& 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& arr) { - writer.StartArray(); - for(const auto& item : arr) { - writeJSON(writer, item); - } - writer.EndArray(); - }, - [&] (const std::unordered_map& 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& arr) { + writer.StartArray(); + for (const auto& item : arr) { + writeJSON(writer, item); + } + writer.EndArray(); + }, + [&](const std::unordered_map& 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::toExpressionValue(const mbgl::Value& value) { mbgl::Value ValueConverter::fromExpressionValue(const Value& value) { return value.match( - [&](const Color& color)->mbgl::Value { + [&](const Color& color) -> mbgl::Value { std::array array = color.toArray(); return std::vector{ std::string("rgba"), @@ -139,13 +136,13 @@ mbgl::Value ValueConverter::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 serialized; @@ -175,7 +172,8 @@ mbgl::Value ValueConverter::fromExpressionValue(const Value& value) } return serialized; }, - [&](const std::vector& values)->mbgl::Value { + [&](const Image& i) -> mbgl::Value { return i.toValue(); }, + [&](const std::vector& values) -> mbgl::Value { std::vector converted; converted.reserve(values.size()); for (const Value& v : values) { @@ -183,7 +181,7 @@ mbgl::Value ValueConverter::fromExpressionValue(const Value& value) } return converted; }, - [&](const std::unordered_map& values)->mbgl::Value { + [&](const std::unordered_map& values) -> mbgl::Value { std::unordered_map converted; converted.reserve(values.size()); for(const auto& entry : values) { @@ -191,8 +189,7 @@ mbgl::Value ValueConverter::fromExpressionValue(const Value& value) } return converted; }, - [&](const auto& a)->mbgl::Value { return a; } - ); + [&](const auto& a) -> mbgl::Value { return a; }); } Value ValueConverter::toExpressionValue(const float value) { @@ -302,6 +299,10 @@ template <> type::Type valueTypeToExpressionType() { return type::S template <> type::Type valueTypeToExpressionType() { return type::Color; } template <> type::Type valueTypeToExpressionType() { return type::Collator; } template <> type::Type valueTypeToExpressionType() { return type::Formatted; } +template <> +type::Type valueTypeToExpressionType() { + return type::Image; +} template <> type::Type valueTypeToExpressionType>() { return type::Object; } template <> type::Type valueTypeToExpressionType>() { return type::Array(type::Value); } diff --git a/src/mbgl/style/layers/background_layer.cpp b/src/mbgl/style/layers/background_layer.cpp index 9187784452c..66290440185 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 BackgroundLayer::getDefaultBackgroundColor() { - return { Color::black() }; + return {Color::black()}; } const PropertyValue& BackgroundLayer::getBackgroundColor() const { @@ -91,7 +91,7 @@ TransitionOptions BackgroundLayer::getBackgroundColorTransition() const { } PropertyValue BackgroundLayer::getDefaultBackgroundOpacity() { - return { 1 }; + return {1}; } const PropertyValue& BackgroundLayer::getBackgroundOpacity() const { @@ -117,15 +117,15 @@ TransitionOptions BackgroundLayer::getBackgroundOpacityTransition() const { return impl().paint.template get().options; } -PropertyValue BackgroundLayer::getDefaultBackgroundPattern() { - return { "" }; +PropertyValue BackgroundLayer::getDefaultBackgroundPattern() { + return {{}}; } -const PropertyValue& BackgroundLayer::getBackgroundPattern() const { +const PropertyValue& BackgroundLayer::getBackgroundPattern() const { return impl().paint.template get().value; } -void BackgroundLayer::setBackgroundPattern(const PropertyValue& value) { +void BackgroundLayer::setBackgroundPattern(const PropertyValue& value) { if (value == getBackgroundPattern()) return; auto impl_ = mutableImpl(); @@ -208,7 +208,8 @@ optional BackgroundLayer::setPaintProperty(const std::string& name, const if (property == Property::BackgroundPattern) { Error error; - optional> typedValue = convert>(value, error, false, false); + optional> typedValue = + convert>(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 11328f78bbb..b926295c00d 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 { static float defaultValue() { return 1; } }; -struct BackgroundPattern : CrossFadedPaintProperty { - static std::string defaultValue() { return ""; } +struct BackgroundPattern : CrossFadedPaintProperty { + 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 145d76a9a8f..619c58c366b 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 CircleLayer::getDefaultCircleBlur() { - return { 0 }; + return {0}; } const PropertyValue& CircleLayer::getCircleBlur() const { @@ -91,7 +91,7 @@ TransitionOptions CircleLayer::getCircleBlurTransition() const { } PropertyValue CircleLayer::getDefaultCircleColor() { - return { Color::black() }; + return {Color::black()}; } const PropertyValue& CircleLayer::getCircleColor() const { @@ -118,7 +118,7 @@ TransitionOptions CircleLayer::getCircleColorTransition() const { } PropertyValue CircleLayer::getDefaultCircleOpacity() { - return { 1 }; + return {1}; } const PropertyValue& CircleLayer::getCircleOpacity() const { @@ -145,7 +145,7 @@ TransitionOptions CircleLayer::getCircleOpacityTransition() const { } PropertyValue CircleLayer::getDefaultCirclePitchAlignment() { - return { AlignmentType::Viewport }; + return {AlignmentType::Viewport}; } const PropertyValue& CircleLayer::getCirclePitchAlignment() const { @@ -172,7 +172,7 @@ TransitionOptions CircleLayer::getCirclePitchAlignmentTransition() const { } PropertyValue CircleLayer::getDefaultCirclePitchScale() { - return { CirclePitchScaleType::Map }; + return {CirclePitchScaleType::Map}; } const PropertyValue& CircleLayer::getCirclePitchScale() const { @@ -199,7 +199,7 @@ TransitionOptions CircleLayer::getCirclePitchScaleTransition() const { } PropertyValue CircleLayer::getDefaultCircleRadius() { - return { 5 }; + return {5}; } const PropertyValue& CircleLayer::getCircleRadius() const { @@ -226,7 +226,7 @@ TransitionOptions CircleLayer::getCircleRadiusTransition() const { } PropertyValue CircleLayer::getDefaultCircleStrokeColor() { - return { Color::black() }; + return {Color::black()}; } const PropertyValue& CircleLayer::getCircleStrokeColor() const { @@ -253,7 +253,7 @@ TransitionOptions CircleLayer::getCircleStrokeColorTransition() const { } PropertyValue CircleLayer::getDefaultCircleStrokeOpacity() { - return { 1 }; + return {1}; } const PropertyValue& CircleLayer::getCircleStrokeOpacity() const { @@ -280,7 +280,7 @@ TransitionOptions CircleLayer::getCircleStrokeOpacityTransition() const { } PropertyValue CircleLayer::getDefaultCircleStrokeWidth() { - return { 0 }; + return {0}; } const PropertyValue& CircleLayer::getCircleStrokeWidth() const { @@ -307,7 +307,7 @@ TransitionOptions CircleLayer::getCircleStrokeWidthTransition() const { } PropertyValue> CircleLayer::getDefaultCircleTranslate() { - return { {{ 0, 0 }} }; + return {{{0, 0}}}; } const PropertyValue>& CircleLayer::getCircleTranslate() const { @@ -334,7 +334,7 @@ TransitionOptions CircleLayer::getCircleTranslateTransition() const { } PropertyValue CircleLayer::getDefaultCircleTranslateAnchor() { - return { TranslateAnchorType::Map }; + return {TranslateAnchorType::Map}; } const PropertyValue& CircleLayer::getCircleTranslateAnchor() const { @@ -497,7 +497,8 @@ optional CircleLayer::setPaintProperty(const std::string& name, const Con if (property == Property::CirclePitchScale) { Error error; - optional> typedValue = convert>(value, error, false, false); + optional> typedValue = + convert>(value, error, false, false); if (!typedValue) { return error; } @@ -509,7 +510,8 @@ optional CircleLayer::setPaintProperty(const std::string& name, const Con if (property == Property::CircleTranslate) { Error error; - optional>> typedValue = convert>>(value, error, false, false); + optional>> typedValue = + convert>>(value, error, false, false); if (!typedValue) { return error; } @@ -521,7 +523,8 @@ optional CircleLayer::setPaintProperty(const std::string& name, const Con if (property == Property::CircleTranslateAnchor) { Error error; - optional> typedValue = convert>(value, error, false, false); + optional> typedValue = + convert>(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 a5f7a584df7..5204421d0b9 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> { - static std::array defaultValue() { return {{ 0, 0 }}; } + static std::array defaultValue() { return {{0, 0}}; } }; struct CircleTranslateAnchor : PaintProperty { diff --git a/src/mbgl/style/layers/fill_extrusion_layer.cpp b/src/mbgl/style/layers/fill_extrusion_layer.cpp index 87e196926f8..e04e1922984 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 FillExtrusionLayer::getDefaultFillExtrusionBase() { - return { 0 }; + return {0}; } const PropertyValue& FillExtrusionLayer::getFillExtrusionBase() const { @@ -91,7 +91,7 @@ TransitionOptions FillExtrusionLayer::getFillExtrusionBaseTransition() const { } PropertyValue FillExtrusionLayer::getDefaultFillExtrusionColor() { - return { Color::black() }; + return {Color::black()}; } const PropertyValue& FillExtrusionLayer::getFillExtrusionColor() const { @@ -118,7 +118,7 @@ TransitionOptions FillExtrusionLayer::getFillExtrusionColorTransition() const { } PropertyValue FillExtrusionLayer::getDefaultFillExtrusionHeight() { - return { 0 }; + return {0}; } const PropertyValue& FillExtrusionLayer::getFillExtrusionHeight() const { @@ -145,7 +145,7 @@ TransitionOptions FillExtrusionLayer::getFillExtrusionHeightTransition() const { } PropertyValue FillExtrusionLayer::getDefaultFillExtrusionOpacity() { - return { 1 }; + return {1}; } const PropertyValue& FillExtrusionLayer::getFillExtrusionOpacity() const { @@ -171,15 +171,15 @@ TransitionOptions FillExtrusionLayer::getFillExtrusionOpacityTransition() const return impl().paint.template get().options; } -PropertyValue FillExtrusionLayer::getDefaultFillExtrusionPattern() { - return { "" }; +PropertyValue FillExtrusionLayer::getDefaultFillExtrusionPattern() { + return {{}}; } -const PropertyValue& FillExtrusionLayer::getFillExtrusionPattern() const { +const PropertyValue& FillExtrusionLayer::getFillExtrusionPattern() const { return impl().paint.template get().value; } -void FillExtrusionLayer::setFillExtrusionPattern(const PropertyValue& value) { +void FillExtrusionLayer::setFillExtrusionPattern(const PropertyValue& value) { if (value == getFillExtrusionPattern()) return; auto impl_ = mutableImpl(); @@ -199,7 +199,7 @@ TransitionOptions FillExtrusionLayer::getFillExtrusionPatternTransition() const } PropertyValue> FillExtrusionLayer::getDefaultFillExtrusionTranslate() { - return { {{ 0, 0 }} }; + return {{{0, 0}}}; } const PropertyValue>& FillExtrusionLayer::getFillExtrusionTranslate() const { @@ -226,7 +226,7 @@ TransitionOptions FillExtrusionLayer::getFillExtrusionTranslateTransition() cons } PropertyValue FillExtrusionLayer::getDefaultFillExtrusionTranslateAnchor() { - return { TranslateAnchorType::Map }; + return {TranslateAnchorType::Map}; } const PropertyValue& FillExtrusionLayer::getFillExtrusionTranslateAnchor() const { @@ -253,7 +253,7 @@ TransitionOptions FillExtrusionLayer::getFillExtrusionTranslateAnchorTransition( } PropertyValue FillExtrusionLayer::getDefaultFillExtrusionVerticalGradient() { - return { true }; + return {true}; } const PropertyValue& FillExtrusionLayer::getFillExtrusionVerticalGradient() const { @@ -382,7 +382,8 @@ optional FillExtrusionLayer::setPaintProperty(const std::string& name, co if (property == Property::FillExtrusionPattern) { Error error; - optional> typedValue = convert>(value, error, true, false); + optional> typedValue = + convert>(value, error, true, false); if (!typedValue) { return error; } @@ -394,7 +395,8 @@ optional FillExtrusionLayer::setPaintProperty(const std::string& name, co if (property == Property::FillExtrusionTranslate) { Error error; - optional>> typedValue = convert>>(value, error, false, false); + optional>> typedValue = + convert>>(value, error, false, false); if (!typedValue) { return error; } @@ -406,7 +408,8 @@ optional FillExtrusionLayer::setPaintProperty(const std::string& name, co if (property == Property::FillExtrusionTranslateAnchor) { Error error; - optional> typedValue = convert>(value, error, false, false); + optional> typedValue = + convert>(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 6936d5e0c4a..60a2340b0dd 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 { static float defaultValue() { return 1; } }; -struct FillExtrusionPattern : CrossFadedDataDrivenPaintProperty { - static std::string defaultValue() { return ""; } +struct FillExtrusionPattern : CrossFadedDataDrivenPaintProperty { + static expression::Image defaultValue() { return {}; } }; struct FillExtrusionTranslate : PaintProperty> { - static std::array defaultValue() { return {{ 0, 0 }}; } + static std::array defaultValue() { return {{0, 0}}; } }; struct FillExtrusionTranslateAnchor : PaintProperty { diff --git a/src/mbgl/style/layers/fill_layer.cpp b/src/mbgl/style/layers/fill_layer.cpp index e3d6c6c7088..ad1f0ae8477 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 // Paint properties PropertyValue FillLayer::getDefaultFillAntialias() { - return { true }; + return {true}; } const PropertyValue& FillLayer::getFillAntialias() const { @@ -91,7 +91,7 @@ TransitionOptions FillLayer::getFillAntialiasTransition() const { } PropertyValue FillLayer::getDefaultFillColor() { - return { Color::black() }; + return {Color::black()}; } const PropertyValue& FillLayer::getFillColor() const { @@ -118,7 +118,7 @@ TransitionOptions FillLayer::getFillColorTransition() const { } PropertyValue FillLayer::getDefaultFillOpacity() { - return { 1 }; + return {1}; } const PropertyValue& FillLayer::getFillOpacity() const { @@ -145,7 +145,7 @@ TransitionOptions FillLayer::getFillOpacityTransition() const { } PropertyValue FillLayer::getDefaultFillOutlineColor() { - return { {} }; + return {{}}; } const PropertyValue& FillLayer::getFillOutlineColor() const { @@ -171,15 +171,15 @@ TransitionOptions FillLayer::getFillOutlineColorTransition() const { return impl().paint.template get().options; } -PropertyValue FillLayer::getDefaultFillPattern() { - return { "" }; +PropertyValue FillLayer::getDefaultFillPattern() { + return {{}}; } -const PropertyValue& FillLayer::getFillPattern() const { +const PropertyValue& FillLayer::getFillPattern() const { return impl().paint.template get().value; } -void FillLayer::setFillPattern(const PropertyValue& value) { +void FillLayer::setFillPattern(const PropertyValue& value) { if (value == getFillPattern()) return; auto impl_ = mutableImpl(); @@ -199,7 +199,7 @@ TransitionOptions FillLayer::getFillPatternTransition() const { } PropertyValue> FillLayer::getDefaultFillTranslate() { - return { {{ 0, 0 }} }; + return {{{0, 0}}}; } const PropertyValue>& FillLayer::getFillTranslate() const { @@ -226,7 +226,7 @@ TransitionOptions FillLayer::getFillTranslateTransition() const { } PropertyValue FillLayer::getDefaultFillTranslateAnchor() { - return { TranslateAnchorType::Map }; + return {TranslateAnchorType::Map}; } const PropertyValue& FillLayer::getFillTranslateAnchor() const { @@ -351,7 +351,8 @@ optional FillLayer::setPaintProperty(const std::string& name, const Conve if (property == Property::FillPattern) { Error error; - optional> typedValue = convert>(value, error, true, false); + optional> typedValue = + convert>(value, error, true, false); if (!typedValue) { return error; } @@ -363,7 +364,8 @@ optional FillLayer::setPaintProperty(const std::string& name, const Conve if (property == Property::FillTranslate) { Error error; - optional>> typedValue = convert>>(value, error, false, false); + optional>> typedValue = + convert>>(value, error, false, false); if (!typedValue) { return error; } @@ -375,7 +377,8 @@ optional FillLayer::setPaintProperty(const std::string& name, const Conve if (property == Property::FillTranslateAnchor) { Error error; - optional> typedValue = convert>(value, error, false, false); + optional> typedValue = + convert>(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 38ca506199c..ad8ed848929 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 { - static std::string defaultValue() { return ""; } +struct FillPattern : CrossFadedDataDrivenPaintProperty { + static expression::Image defaultValue() { return {}; } }; struct FillTranslate : PaintProperty> { - static std::array defaultValue() { return {{ 0, 0 }}; } + static std::array defaultValue() { return {{0, 0}}; } }; struct FillTranslateAnchor : PaintProperty { diff --git a/src/mbgl/style/layers/heatmap_layer.cpp b/src/mbgl/style/layers/heatmap_layer.cpp index 332c65c6b4c..234dda6c730 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 HeatmapLayer::getDefaultHeatmapIntensity() { - return { 1 }; + return {1}; } const PropertyValue& HeatmapLayer::getHeatmapIntensity() const { @@ -120,7 +120,7 @@ TransitionOptions HeatmapLayer::getHeatmapIntensityTransition() const { } PropertyValue HeatmapLayer::getDefaultHeatmapOpacity() { - return { 1 }; + return {1}; } const PropertyValue& HeatmapLayer::getHeatmapOpacity() const { @@ -147,7 +147,7 @@ TransitionOptions HeatmapLayer::getHeatmapOpacityTransition() const { } PropertyValue HeatmapLayer::getDefaultHeatmapRadius() { - return { 30 }; + return {30}; } const PropertyValue& HeatmapLayer::getHeatmapRadius() const { @@ -174,7 +174,7 @@ TransitionOptions HeatmapLayer::getHeatmapRadiusTransition() const { } PropertyValue HeatmapLayer::getDefaultHeatmapWeight() { - return { 1 }; + return {1}; } const PropertyValue& HeatmapLayer::getHeatmapWeight() const { diff --git a/src/mbgl/style/layers/hillshade_layer.cpp b/src/mbgl/style/layers/hillshade_layer.cpp index a55c079c492..5d84b7ded3b 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 HillshadeLayer::getDefaultHillshadeAccentColor() { - return { Color::black() }; + return {Color::black()}; } const PropertyValue& HillshadeLayer::getHillshadeAccentColor() const { @@ -91,7 +91,7 @@ TransitionOptions HillshadeLayer::getHillshadeAccentColorTransition() const { } PropertyValue HillshadeLayer::getDefaultHillshadeExaggeration() { - return { 0.5 }; + return {0.5}; } const PropertyValue& HillshadeLayer::getHillshadeExaggeration() const { @@ -118,7 +118,7 @@ TransitionOptions HillshadeLayer::getHillshadeExaggerationTransition() const { } PropertyValue HillshadeLayer::getDefaultHillshadeHighlightColor() { - return { Color::white() }; + return {Color::white()}; } const PropertyValue& HillshadeLayer::getHillshadeHighlightColor() const { @@ -145,7 +145,7 @@ TransitionOptions HillshadeLayer::getHillshadeHighlightColorTransition() const { } PropertyValue HillshadeLayer::getDefaultHillshadeIlluminationAnchor() { - return { HillshadeIlluminationAnchorType::Viewport }; + return {HillshadeIlluminationAnchorType::Viewport}; } const PropertyValue& HillshadeLayer::getHillshadeIlluminationAnchor() const { @@ -172,7 +172,7 @@ TransitionOptions HillshadeLayer::getHillshadeIlluminationAnchorTransition() con } PropertyValue HillshadeLayer::getDefaultHillshadeIlluminationDirection() { - return { 335 }; + return {335}; } const PropertyValue& HillshadeLayer::getHillshadeIlluminationDirection() const { @@ -199,7 +199,7 @@ TransitionOptions HillshadeLayer::getHillshadeIlluminationDirectionTransition() } PropertyValue HillshadeLayer::getDefaultHillshadeShadowColor() { - return { Color::black() }; + return {Color::black()}; } const PropertyValue& HillshadeLayer::getHillshadeShadowColor() const { @@ -320,7 +320,8 @@ optional HillshadeLayer::setPaintProperty(const std::string& name, const if (property == Property::HillshadeIlluminationAnchor) { Error error; - optional> typedValue = convert>(value, error, false, false); + optional> typedValue = + convert>(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 775288264fa..a47e5b95b4a 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 <%- 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 <%- 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 309a81ae2b7..813ef68decc 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& value) { // Paint properties PropertyValue LineLayer::getDefaultLineBlur() { - return { 0 }; + return {0}; } const PropertyValue& LineLayer::getLineBlur() const { @@ -156,7 +156,7 @@ TransitionOptions LineLayer::getLineBlurTransition() const { } PropertyValue LineLayer::getDefaultLineColor() { - return { Color::black() }; + return {Color::black()}; } const PropertyValue& LineLayer::getLineColor() const { @@ -183,7 +183,7 @@ TransitionOptions LineLayer::getLineColorTransition() const { } PropertyValue> LineLayer::getDefaultLineDasharray() { - return { { } }; + return {{}}; } const PropertyValue>& LineLayer::getLineDasharray() const { @@ -210,7 +210,7 @@ TransitionOptions LineLayer::getLineDasharrayTransition() const { } PropertyValue LineLayer::getDefaultLineGapWidth() { - return { 0 }; + return {0}; } const PropertyValue& 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 LineLayer::getDefaultLineOffset() { - return { 0 }; + return {0}; } const PropertyValue& LineLayer::getLineOffset() const { @@ -291,7 +291,7 @@ TransitionOptions LineLayer::getLineOffsetTransition() const { } PropertyValue LineLayer::getDefaultLineOpacity() { - return { 1 }; + return {1}; } const PropertyValue& LineLayer::getLineOpacity() const { @@ -317,15 +317,15 @@ TransitionOptions LineLayer::getLineOpacityTransition() const { return impl().paint.template get().options; } -PropertyValue LineLayer::getDefaultLinePattern() { - return { "" }; +PropertyValue LineLayer::getDefaultLinePattern() { + return {{}}; } -const PropertyValue& LineLayer::getLinePattern() const { +const PropertyValue& LineLayer::getLinePattern() const { return impl().paint.template get().value; } -void LineLayer::setLinePattern(const PropertyValue& value) { +void LineLayer::setLinePattern(const PropertyValue& value) { if (value == getLinePattern()) return; auto impl_ = mutableImpl(); @@ -345,7 +345,7 @@ TransitionOptions LineLayer::getLinePatternTransition() const { } PropertyValue> LineLayer::getDefaultLineTranslate() { - return { {{ 0, 0 }} }; + return {{{0, 0}}}; } const PropertyValue>& LineLayer::getLineTranslate() const { @@ -372,7 +372,7 @@ TransitionOptions LineLayer::getLineTranslateTransition() const { } PropertyValue LineLayer::getDefaultLineTranslateAnchor() { - return { TranslateAnchorType::Map }; + return {TranslateAnchorType::Map}; } const PropertyValue& LineLayer::getLineTranslateAnchor() const { @@ -399,7 +399,7 @@ TransitionOptions LineLayer::getLineTranslateAnchorTransition() const { } PropertyValue LineLayer::getDefaultLineWidth() { - return { 1 }; + return {1}; } const PropertyValue& LineLayer::getLineWidth() const { @@ -552,7 +552,8 @@ optional LineLayer::setPaintProperty(const std::string& name, const Conve if (property == Property::LineDasharray) { Error error; - optional>> typedValue = convert>>(value, error, false, false); + optional>> typedValue = + convert>>(value, error, false, false); if (!typedValue) { return error; } @@ -576,7 +577,8 @@ optional LineLayer::setPaintProperty(const std::string& name, const Conve if (property == Property::LinePattern) { Error error; - optional> typedValue = convert>(value, error, true, false); + optional> typedValue = + convert>(value, error, true, false); if (!typedValue) { return error; } @@ -588,7 +590,8 @@ optional LineLayer::setPaintProperty(const std::string& name, const Conve if (property == Property::LineTranslate) { Error error; - optional>> typedValue = convert>>(value, error, false, false); + optional>> typedValue = + convert>>(value, error, false, false); if (!typedValue) { return error; } @@ -600,7 +603,8 @@ optional LineLayer::setPaintProperty(const std::string& name, const Conve if (property == Property::LineTranslateAnchor) { Error error; - optional> typedValue = convert>(value, error, false, false); + optional> typedValue = + convert>(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 2ecbb109934..29ba9ec6413 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> { - static std::vector defaultValue() { return { }; } + static std::vector defaultValue() { return {}; } }; struct LineFloorWidth : DataDrivenPaintProperty { @@ -68,12 +68,12 @@ struct LineOpacity : DataDrivenPaintProperty { - static std::string defaultValue() { return ""; } +struct LinePattern : CrossFadedDataDrivenPaintProperty { + static expression::Image defaultValue() { return {}; } }; struct LineTranslate : PaintProperty> { - static std::array defaultValue() { return {{ 0, 0 }}; } + static std::array defaultValue() { return {{0, 0}}; } }; struct LineTranslateAnchor : PaintProperty { diff --git a/src/mbgl/style/layers/raster_layer.cpp b/src/mbgl/style/layers/raster_layer.cpp index 359e502f3e5..b9904098862 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 RasterLayer::getDefaultRasterBrightnessMax() { - return { 1 }; + return {1}; } const PropertyValue& RasterLayer::getRasterBrightnessMax() const { @@ -91,7 +91,7 @@ TransitionOptions RasterLayer::getRasterBrightnessMaxTransition() const { } PropertyValue RasterLayer::getDefaultRasterBrightnessMin() { - return { 0 }; + return {0}; } const PropertyValue& RasterLayer::getRasterBrightnessMin() const { @@ -118,7 +118,7 @@ TransitionOptions RasterLayer::getRasterBrightnessMinTransition() const { } PropertyValue RasterLayer::getDefaultRasterContrast() { - return { 0 }; + return {0}; } const PropertyValue& RasterLayer::getRasterContrast() const { @@ -145,7 +145,7 @@ TransitionOptions RasterLayer::getRasterContrastTransition() const { } PropertyValue RasterLayer::getDefaultRasterFadeDuration() { - return { 300 }; + return {300}; } const PropertyValue& RasterLayer::getRasterFadeDuration() const { @@ -172,7 +172,7 @@ TransitionOptions RasterLayer::getRasterFadeDurationTransition() const { } PropertyValue RasterLayer::getDefaultRasterHueRotate() { - return { 0 }; + return {0}; } const PropertyValue& RasterLayer::getRasterHueRotate() const { @@ -199,7 +199,7 @@ TransitionOptions RasterLayer::getRasterHueRotateTransition() const { } PropertyValue RasterLayer::getDefaultRasterOpacity() { - return { 1 }; + return {1}; } const PropertyValue& RasterLayer::getRasterOpacity() const { @@ -226,7 +226,7 @@ TransitionOptions RasterLayer::getRasterOpacityTransition() const { } PropertyValue RasterLayer::getDefaultRasterResampling() { - return { RasterResamplingType::Linear }; + return {RasterResamplingType::Linear}; } const PropertyValue& RasterLayer::getRasterResampling() const { @@ -253,7 +253,7 @@ TransitionOptions RasterLayer::getRasterResamplingTransition() const { } PropertyValue RasterLayer::getDefaultRasterSaturation() { - return { 0 }; + return {0}; } const PropertyValue& RasterLayer::getRasterSaturation() const { @@ -383,7 +383,8 @@ optional RasterLayer::setPaintProperty(const std::string& name, const Con if (property == Property::RasterResampling) { Error error; - optional> typedValue = convert>(value, error, false, false); + optional> typedValue = + convert>(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 b3ee0f698cb..1383293d6d0 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& value) { baseImpl = std::move(impl_); observer->onLayerChanged(*this); } -PropertyValue SymbolLayer::getDefaultIconImage() { +PropertyValue SymbolLayer::getDefaultIconImage() { return IconImage::defaultValue(); } -const PropertyValue& SymbolLayer::getIconImage() const { +const PropertyValue& SymbolLayer::getIconImage() const { return impl().layout.get(); } -void SymbolLayer::setIconImage(const PropertyValue& value) { +void SymbolLayer::setIconImage(const PropertyValue& value) { if (value == getIconImage()) return; auto impl_ = mutableImpl(); @@ -721,7 +721,7 @@ void SymbolLayer::setTextWritingMode(const PropertyValue SymbolLayer::getDefaultIconColor() { - return { Color::black() }; + return {Color::black()}; } const PropertyValue& SymbolLayer::getIconColor() const { @@ -748,7 +748,7 @@ TransitionOptions SymbolLayer::getIconColorTransition() const { } PropertyValue SymbolLayer::getDefaultIconHaloBlur() { - return { 0 }; + return {0}; } const PropertyValue& SymbolLayer::getIconHaloBlur() const { @@ -775,7 +775,7 @@ TransitionOptions SymbolLayer::getIconHaloBlurTransition() const { } PropertyValue SymbolLayer::getDefaultIconHaloColor() { - return { {} }; + return {{}}; } const PropertyValue& SymbolLayer::getIconHaloColor() const { @@ -802,7 +802,7 @@ TransitionOptions SymbolLayer::getIconHaloColorTransition() const { } PropertyValue SymbolLayer::getDefaultIconHaloWidth() { - return { 0 }; + return {0}; } const PropertyValue& SymbolLayer::getIconHaloWidth() const { @@ -829,7 +829,7 @@ TransitionOptions SymbolLayer::getIconHaloWidthTransition() const { } PropertyValue SymbolLayer::getDefaultIconOpacity() { - return { 1 }; + return {1}; } const PropertyValue& SymbolLayer::getIconOpacity() const { @@ -856,7 +856,7 @@ TransitionOptions SymbolLayer::getIconOpacityTransition() const { } PropertyValue> SymbolLayer::getDefaultIconTranslate() { - return { {{ 0, 0 }} }; + return {{{0, 0}}}; } const PropertyValue>& SymbolLayer::getIconTranslate() const { @@ -883,7 +883,7 @@ TransitionOptions SymbolLayer::getIconTranslateTransition() const { } PropertyValue SymbolLayer::getDefaultIconTranslateAnchor() { - return { TranslateAnchorType::Map }; + return {TranslateAnchorType::Map}; } const PropertyValue& SymbolLayer::getIconTranslateAnchor() const { @@ -910,7 +910,7 @@ TransitionOptions SymbolLayer::getIconTranslateAnchorTransition() const { } PropertyValue SymbolLayer::getDefaultTextColor() { - return { Color::black() }; + return {Color::black()}; } const PropertyValue& SymbolLayer::getTextColor() const { @@ -937,7 +937,7 @@ TransitionOptions SymbolLayer::getTextColorTransition() const { } PropertyValue SymbolLayer::getDefaultTextHaloBlur() { - return { 0 }; + return {0}; } const PropertyValue& SymbolLayer::getTextHaloBlur() const { @@ -964,7 +964,7 @@ TransitionOptions SymbolLayer::getTextHaloBlurTransition() const { } PropertyValue SymbolLayer::getDefaultTextHaloColor() { - return { {} }; + return {{}}; } const PropertyValue& SymbolLayer::getTextHaloColor() const { @@ -991,7 +991,7 @@ TransitionOptions SymbolLayer::getTextHaloColorTransition() const { } PropertyValue SymbolLayer::getDefaultTextHaloWidth() { - return { 0 }; + return {0}; } const PropertyValue& SymbolLayer::getTextHaloWidth() const { @@ -1018,7 +1018,7 @@ TransitionOptions SymbolLayer::getTextHaloWidthTransition() const { } PropertyValue SymbolLayer::getDefaultTextOpacity() { - return { 1 }; + return {1}; } const PropertyValue& SymbolLayer::getTextOpacity() const { @@ -1045,7 +1045,7 @@ TransitionOptions SymbolLayer::getTextOpacityTransition() const { } PropertyValue> SymbolLayer::getDefaultTextTranslate() { - return { {{ 0, 0 }} }; + return {{{0, 0}}}; } const PropertyValue>& SymbolLayer::getTextTranslate() const { @@ -1072,7 +1072,7 @@ TransitionOptions SymbolLayer::getTextTranslateTransition() const { } PropertyValue SymbolLayer::getDefaultTextTranslateAnchor() { - return { TranslateAnchorType::Map }; + return {TranslateAnchorType::Map}; } const PropertyValue& SymbolLayer::getTextTranslateAnchor() const { @@ -1332,7 +1332,8 @@ optional SymbolLayer::setPaintProperty(const std::string& name, const Con if (property == Property::IconTranslate || property == Property::TextTranslate) { Error error; - optional>> typedValue = convert>>(value, error, false, false); + optional>> typedValue = + convert>>(value, error, false, false); if (!typedValue) { return error; } @@ -1351,7 +1352,8 @@ optional SymbolLayer::setPaintProperty(const std::string& name, const Con if (property == Property::IconTranslateAnchor || property == Property::TextTranslateAnchor) { Error error; - optional> typedValue = convert>(value, error, false, false); + optional> typedValue = + convert>(value, error, false, false); if (!typedValue) { return error; } @@ -1665,7 +1667,8 @@ optional SymbolLayer::setLayoutProperty(const std::string& name, const Co if (property == Property::IconAnchor || property == Property::TextAnchor) { Error error; - optional> typedValue = convert>(value, error, true, false); + optional> typedValue = + convert>(value, error, true, false); if (!typedValue) { return error; } @@ -1684,7 +1687,8 @@ optional SymbolLayer::setLayoutProperty(const std::string& name, const Co if (property == Property::IconImage) { Error error; - optional> typedValue = convert>(value, error, true, true); + optional> typedValue = + convert>(value, error, true, true); if (!typedValue) { return error; } @@ -1696,7 +1700,8 @@ optional SymbolLayer::setLayoutProperty(const std::string& name, const Co if (property == Property::IconOffset || property == Property::TextOffset) { Error error; - optional>> typedValue = convert>>(value, error, true, false); + optional>> typedValue = + convert>>(value, error, true, false); if (!typedValue) { return error; } @@ -1827,7 +1832,8 @@ optional SymbolLayer::setLayoutProperty(const std::string& name, const Co if (property == Property::IconTextFit) { Error error; - optional> typedValue = convert>(value, error, false, false); + optional> typedValue = + convert>(value, error, false, false); if (!typedValue) { return error; } @@ -1839,7 +1845,8 @@ optional SymbolLayer::setLayoutProperty(const std::string& name, const Co if (property == Property::IconTextFitPadding) { Error error; - optional>> typedValue = convert>>(value, error, false, false); + optional>> typedValue = + convert>>(value, error, false, false); if (!typedValue) { return error; } @@ -1851,7 +1858,8 @@ optional SymbolLayer::setLayoutProperty(const std::string& name, const Co if (property == Property::SymbolPlacement) { Error error; - optional> typedValue = convert>(value, error, false, false); + optional> typedValue = + convert>(value, error, false, false); if (!typedValue) { return error; } @@ -1863,7 +1871,8 @@ optional SymbolLayer::setLayoutProperty(const std::string& name, const Co if (property == Property::SymbolZOrder) { Error error; - optional> typedValue = convert>(value, error, false, false); + optional> typedValue = + convert>(value, error, false, false); if (!typedValue) { return error; } @@ -1875,7 +1884,8 @@ optional SymbolLayer::setLayoutProperty(const std::string& name, const Co if (property == Property::TextField) { Error error; - optional> typedValue = convert>(value, error, true, true); + optional> typedValue = + convert>(value, error, true, true); if (!typedValue) { return error; } @@ -1887,7 +1897,8 @@ optional SymbolLayer::setLayoutProperty(const std::string& name, const Co if (property == Property::TextFont) { Error error; - optional>> typedValue = convert>>(value, error, true, false); + optional>> typedValue = + convert>>(value, error, true, false); if (!typedValue) { return error; } @@ -1911,7 +1922,8 @@ optional SymbolLayer::setLayoutProperty(const std::string& name, const Co if (property == Property::TextTransform) { Error error; - optional> typedValue = convert>(value, error, true, false); + optional> typedValue = + convert>(value, error, true, false); if (!typedValue) { return error; } @@ -1923,7 +1935,8 @@ optional SymbolLayer::setLayoutProperty(const std::string& name, const Co if (property == Property::TextVariableAnchor) { Error error; - optional>> typedValue = convert>>(value, error, false, false); + optional>> typedValue = + convert>>(value, error, false, false); if (!typedValue) { return error; } @@ -1935,7 +1948,8 @@ optional SymbolLayer::setLayoutProperty(const std::string& name, const Co if (property == Property::TextWritingMode) { Error error; - optional>> typedValue = convert>>(value, error, false, false); + optional>> typedValue = + convert>>(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 e44e7e404f1..65525899715 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 { static bool defaultValue() { return false; } }; -struct IconImage : DataDrivenLayoutProperty { +struct IconImage : DataDrivenLayoutProperty { static constexpr const char *name() { return "icon-image"; } - static std::string defaultValue() { return ""; } + static expression::Image defaultValue() { return {}; } }; struct IconKeepUpright : LayoutProperty { @@ -43,7 +43,7 @@ struct IconKeepUpright : LayoutProperty { struct IconOffset : DataDrivenLayoutProperty> { static constexpr const char *name() { return "icon-offset"; } - static std::array defaultValue() { return {{ 0, 0 }}; } + static std::array defaultValue() { return {{0, 0}}; } }; struct IconOptional : LayoutProperty { @@ -83,7 +83,7 @@ struct IconTextFit : LayoutProperty { struct IconTextFitPadding : LayoutProperty> { static constexpr const char *name() { return "icon-text-fit-padding"; } - static std::array defaultValue() { return {{ 0, 0, 0, 0 }}; } + static std::array defaultValue() { return {{0, 0, 0, 0}}; } }; struct SymbolAvoidEdges : LayoutProperty { @@ -123,12 +123,12 @@ struct TextAnchor : DataDrivenLayoutProperty { struct TextField : DataDrivenLayoutProperty { static constexpr const char *name() { return "text-field"; } - static expression::Formatted defaultValue() { return ""; } + static expression::Formatted defaultValue() { return {}; } }; struct TextFont : DataDrivenLayoutProperty> { static constexpr const char *name() { return "text-font"; } - static std::vector defaultValue() { return { "Open Sans Regular", "Arial Unicode MS Regular" }; } + static std::vector defaultValue() { return {{"Open Sans Regular"}, {"Arial Unicode MS Regular"}}; } }; struct TextIgnorePlacement : LayoutProperty { @@ -168,7 +168,7 @@ struct TextMaxWidth : DataDrivenLayoutProperty { struct TextOffset : DataDrivenLayoutProperty> { static constexpr const char *name() { return "text-offset"; } - static std::array defaultValue() { return {{ 0, 0 }}; } + static std::array defaultValue() { return {{0, 0}}; } }; struct TextOptional : LayoutProperty { @@ -213,12 +213,12 @@ struct TextTransform : DataDrivenLayoutProperty { struct TextVariableAnchor : LayoutProperty> { static constexpr const char *name() { return "text-variable-anchor"; } - static std::vector defaultValue() { return { }; } + static std::vector defaultValue() { return {}; } }; struct TextWritingMode : LayoutProperty> { static constexpr const char *name() { return "text-writing-mode"; } - static std::vector defaultValue() { return { }; } + static std::vector defaultValue() { return {}; } }; struct IconColor : DataDrivenPaintProperty { @@ -242,7 +242,7 @@ struct IconOpacity : DataDrivenPaintProperty> { - static std::array defaultValue() { return {{ 0, 0 }}; } + static std::array defaultValue() { return {{0, 0}}; } }; struct IconTranslateAnchor : PaintProperty { @@ -273,7 +273,7 @@ struct TextOpacity : DataDrivenPaintProperty> { - static std::array defaultValue() { return {{ 0, 0 }}; } + static std::array defaultValue() { return {{0, 0}}; } }; struct TextTranslateAnchor : PaintProperty { diff --git a/src/mbgl/style/properties.hpp b/src/mbgl/style/properties.hpp index db0e54330c8..9c8996fcbe7 100644 --- a/src/mbgl/style/properties.hpp +++ b/src/mbgl/style/properties.hpp @@ -169,8 +169,10 @@ class Properties { } template - static T evaluate(float z, const GeometryTileFeature& feature, - const PossiblyEvaluatedPropertyValue& v, const T& defaultValue) { + static T evaluate(float z, + const GeometryTileFeature& feature, + const PossiblyEvaluatedPropertyValue& v, + const T& defaultValue) { return v.match( [&] (const T& t) { return t; @@ -180,6 +182,17 @@ class Properties { }); } + template + static T evaluate(float z, + const GeometryTileFeature& feature, + const PossiblyEvaluatedPropertyValue& v, + const T& defaultValue, + const std::set& availableImages) { + return v.match( + [&](const T& t) { return t; }, + [&](const PropertyExpression& t) { return t.evaluate(z, feature, availableImages, defaultValue); }); + } + template static T evaluate(float z, const GeometryTileFeature& feature, const FeatureState& state, const PossiblyEvaluatedPropertyValue& v, const T& defaultValue) { @@ -197,6 +210,11 @@ class Properties { return evaluate(z, feature, state, this->template get

(), P::defaultValue()); } + template + auto evaluate(float z, const GeometryTileFeature& feature, const std::set& availableImages) const { + return evaluate(z, feature, this->template get

(), P::defaultValue(), availableImages); + } + Evaluated evaluate(float z, const GeometryTileFeature& feature) const { return Evaluated { evaluate(z, feature)... diff --git a/src/mbgl/style/property_expression.cpp b/src/mbgl/style/property_expression.cpp index 9ebecc4b409..d531181e712 100644 --- a/src/mbgl/style/property_expression.cpp +++ b/src/mbgl/style/property_expression.cpp @@ -8,6 +8,7 @@ PropertyExpressionBase::PropertyExpressionBase(std::unique_ptr& inputLevels, const float inputValue) const noexcept { diff --git a/src/mbgl/tile/geometry_tile.cpp b/src/mbgl/tile/geometry_tile.cpp index 9f9c41d2298..4a3d91455ab 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 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 GeometryTile::createRenderData() { @@ -212,7 +213,8 @@ void GeometryTile::setLayers(const std::vector>& 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 7815e62b75e..de53c69aee2 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 data_, bool resetLayers_, uint64_t correlationID_) { +void GeometryTileWorker::setData(std::unique_ptr data_, + std::set 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 data_, } } -void GeometryTileWorker::setLayers(std::vector> layers_, uint64_t correlationID_) { +void GeometryTileWorker::setLayers(std::vector> layers_, + std::set 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 = LayerManager::get()->createLayout({parameters, glyphDependencies, imageDependencies}, std::move(geometryLayer), group); + std::unique_ptr 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 96b4e2e83a7..38f7cb9fa6f 100644 --- a/src/mbgl/tile/geometry_tile_worker.hpp +++ b/src/mbgl/tile/geometry_tile_worker.hpp @@ -38,8 +38,13 @@ class GeometryTileWorker { const bool showCollisionBoxes_); ~GeometryTileWorker(); - void setLayers(std::vector>, uint64_t correlationID); - void setData(std::unique_ptr, bool resetLayers, uint64_t correlationID); + void setLayers(std::vector>, + std::set availableImages, + uint64_t correlationID); + void setData(std::unique_ptr, + std::set availableImages, + bool resetLayers, + uint64_t correlationID); void setShowCollisionBoxes(bool showCollisionBoxes_, uint64_t correlationID_); void onGlyphsAvailable(GlyphMap glyphs); @@ -96,7 +101,8 @@ class GeometryTileWorker { ImageMap imageMap; ImageMap patternMap; ImageVersionMap versionMap; - + std::set availableImages; + bool showCollisionBoxes; bool firstLoad = true; }; diff --git a/test/api/query.test.cpp b/test/api/query.test.cpp index 54ae89767a1..9116a3746d4 100644 --- a/test/api/query.test.cpp +++ b/test/api/query.test.cpp @@ -55,7 +55,7 @@ std::vector getTopClusterFeature(QueryTest& test) { source->loadDescription(*test.fileSource); auto clusterLayer = std::make_unique("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 00000000000..930b21dd0ea --- /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 00000000000..edec7d0497e --- /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 ef9f7b79309..a289d7600b0 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 75c8c594909..6334fcbe390 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 value, float zoom) { return value.evaluate(PropertyEvaluator(PropertyEvaluationParameters(zoom), 0)); @@ -171,3 +167,54 @@ TEST(PropertyExpression, FormatSectionOverride) { EXPECT_TRUE(*override1 != *override4); } } + +TEST(PropertyExpression, ImageExpression) { + const std::set emptySet; + const std::set availableImages = {"maki-11", "airport-11", "bicycle-15"}; + + // evaluation test without available images + { + PropertyExpression 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 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 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 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 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 dfced634b71..2d6ef5881a3 100644 --- a/test/style/style_layer.test.cpp +++ b/test/style/style_layer.test.cpp @@ -1,7 +1,7 @@ #include -#include #include -#include +#include +#include #include #include #include @@ -16,12 +16,13 @@ #include #include #include -#include -#include +#include #include +#include +#include #include -#include #include +#include #include @@ -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{"foo"}; const auto antialias = false; const auto translate = std::array {{ 0, 0 }}; const auto translateAnchor = TranslateAnchorType::Map; diff --git a/test/util/merge_lines.test.cpp b/test/util/merge_lines.test.cpp index 5dc846ad6e1..5137a245e5e 100644 --- a/test/util/merge_lines.test.cpp +++ b/test/util/merge_lines.test.cpp @@ -19,11 +19,15 @@ LineString emptyLine; class SymbolFeatureStub : public SymbolFeature { public: - SymbolFeatureStub(FeatureIdentifier id_, FeatureType type_, GeometryCollection geometry_, - PropertyMap properties_, optional text_, - optional icon_, std::size_t index_) : - SymbolFeature(std::make_unique(std::move(id_), type_, std::move(geometry_), std::move(properties_))) - { + SymbolFeatureStub(FeatureIdentifier id_, + FeatureType type_, + GeometryCollection geometry_, + PropertyMap properties_, + optional text_, + optional icon_, + std::size_t index_) + : SymbolFeature(std::make_unique( + std::move(id_), type_, std::move(geometry_), std::move(properties_))) { if (text_) { formattedText = TaggedString(*text_, SectionOptions(1.0, {})); } From 99248089d0295a80ac1273512110c0402a7266db Mon Sep 17 00:00:00 2001 From: Alexander Shalamov Date: Fri, 1 Nov 2019 16:20:35 +0200 Subject: [PATCH 02/10] [node] Add support for Image expression --- platform/node/src/node_expression.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/platform/node/src/node_expression.cpp b/platform/node/src/node_expression.cpp index 81d5c74767c..7e59847da91 100644 --- a/platform/node/src/node_expression.cpp +++ b/platform/node/src/node_expression.cpp @@ -42,7 +42,8 @@ type::Type parseType(v8::Local type) { {"color", type::Color}, {"value", type::Value}, {"formatted", type::Formatted}, - {"number-format", type::String}}; + {"number-format", type::String}, + {"resolvedImage", type::Image}}; v8::Local v8kind = Nan::Get(type, Nan::New("kind").ToLocalChecked()).ToLocalChecked(); std::string kind(*v8::String::Utf8Value(v8kind)); @@ -220,6 +221,8 @@ struct ToValue { return scope.Escape(result); } + + v8::Local operator()(const Image& image) { return toJS(image.toValue()); } }; v8::Local toJS(const Value& value) { From eb2ef8cb1e0f250fe92cfb8806c781b6468e8602 Mon Sep 17 00:00:00 2001 From: Alexander Shalamov Date: Fri, 1 Nov 2019 17:36:31 +0200 Subject: [PATCH 03/10] [android] Update image expression evaluated type name --- platform/android/scripts/generate-style-code.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/platform/android/scripts/generate-style-code.js b/platform/android/scripts/generate-style-code.js index 83fb5c116e3..9e07b364401 100755 --- a/platform/android/scripts/generate-style-code.js +++ b/platform/android/scripts/generate-style-code.js @@ -72,7 +72,7 @@ global.propertyType = function propertyType(property) { case 'formatted': return 'Formatted'; case 'string': - case 'image': // TODO: replace once we implement image expressions + case 'resolvedImage': return 'String'; case 'enum': return 'String'; @@ -94,7 +94,7 @@ global.propertyJavaType = function propertyType(property) { case 'formatted': return 'Formatted'; case 'string': - case 'image': // TODO: replace once we implement image expressions + case 'resolvedImage': return 'String'; case 'enum': return 'String'; @@ -143,7 +143,7 @@ global.propertyNativeType = function (property) { return 'float'; case 'formatted': case 'string': - case 'image': // TODO: replace once we implement image expressions + case 'resolvedImage': // TODO: replace once we implement image expressions return 'std::string'; case 'enum': if(property['light-property']){ @@ -180,7 +180,7 @@ global.defaultExpressionJava = function(property) { case 'formatted': return 'format'; case 'string': - case 'image': // TODO: replace once we implement image expressions + case 'image': return "string"; case 'enum': return "string"; @@ -207,7 +207,7 @@ global.defaultValueJava = function(property) { case 'formatted': return 'new Formatted(new FormattedSection("default"))' case 'string': - case 'image': // TODO: replace once we implement image expressions + case 'resolvedImage': return '"' + property['default'] + '"'; case 'enum': return snakeCaseUpper(property.name) + "_" + snakeCaseUpper(Object.keys(property.values)[0]); @@ -340,7 +340,7 @@ global.evaluatedType = function (property) { return 'float'; case 'formatted': case 'string': - case 'image': // TODO: replace once we implement image expressions + case 'image': return 'std::string'; case 'enum': return (isLightProperty(property) ? 'Light' : '') + `${camelize(property.name)}Type`; From 9b3a9bf83a7aca554a9b31449e68c8f17429c792 Mon Sep 17 00:00:00 2001 From: Alexander Shalamov Date: Mon, 4 Nov 2019 08:17:06 +0200 Subject: [PATCH 04/10] [android] Placeholders for conversion from:to Image --- platform/android/src/conversion/constant.cpp | 5 +++++ platform/android/src/conversion/constant.hpp | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/platform/android/src/conversion/constant.cpp b/platform/android/src/conversion/constant.cpp index a409e5dfdfc..46a91026df5 100644 --- a/platform/android/src/conversion/constant.cpp +++ b/platform/android/src/conversion/constant.cpp @@ -52,6 +52,11 @@ Result>> Converter>, std::vect return result; } +Result>> Converter>, style::expression::Image>::operator()( + jni::JNIEnv& env, const style::expression::Image& value) const { + return jni::Make(env, value.id()); +} + } // namespace conversion } // namespace style } // namespace mbgl diff --git a/platform/android/src/conversion/constant.hpp b/platform/android/src/conversion/constant.hpp index 839e6e84dc9..a9239fe8453 100644 --- a/platform/android/src/conversion/constant.hpp +++ b/platform/android/src/conversion/constant.hpp @@ -6,6 +6,7 @@ #include #include +#include #include @@ -99,6 +100,11 @@ struct Converter>, std::vector, typename std::enable } }; +template <> +struct Converter>, style::expression::Image> { + Result>> operator()(jni::JNIEnv& env, const style::expression::Image& value) const; +}; + } // namespace conversion } // namespace android } // namespace mbgl From 38c84cf7001d6e553a9c2d1fd002987b7ec0b489 Mon Sep 17 00:00:00 2001 From: Alexander Shalamov Date: Fri, 1 Nov 2019 17:33:59 +0200 Subject: [PATCH 05/10] [darwin] Update image expression evaluated type name --- platform/darwin/scripts/generate-style-code.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/platform/darwin/scripts/generate-style-code.js b/platform/darwin/scripts/generate-style-code.js index 75dbdf367cf..5d0434f9eaf 100755 --- a/platform/darwin/scripts/generate-style-code.js +++ b/platform/darwin/scripts/generate-style-code.js @@ -159,7 +159,7 @@ global.objCTestValue = function (property, layerType, arraysAsStructs, indent) { `@"'${_.startCase(propertyName)}'"` : `@"${_.startCase(propertyName)}"`; case 'string': - case 'image': // TODO: replace once we implement image expressions + case 'resolvedImage': // TODO: replace once we implement image expressions return `@"'${_.startCase(propertyName)}'"`; case 'enum': return `@"'${_.last(_.keys(property.values))}'"`; @@ -209,7 +209,7 @@ global.mbglTestValue = function (property, layerType) { return '1.0'; case 'formatted': case 'string': - case 'image': // TODO: replace once we implement image expressions + case 'resolvedImage': // TODO: replace once we implement image expressions return `"${_.startCase(propertyName)}"`; case 'enum': { let type = camelize(originalPropertyName(property)); @@ -477,7 +477,7 @@ global.describeType = function (property) { return 'numeric'; case 'formatted': case 'string': - case 'image': // TODO: replace once we implement image expressions + case 'resolvedImage': // TODO: replace once we implement image expressions return 'string'; case 'enum': return '`MGL' + camelize(property.name) + '`'; @@ -613,7 +613,7 @@ global.propertyType = function (property) { return 'NSNumber *'; case 'formatted': case 'string': - case 'image': // TODO: replace once we implement image expressions + case 'resolvedImage': // TODO: replace once we implement image expressions return 'NSString *'; case 'enum': return 'NSValue *'; @@ -646,7 +646,7 @@ global.isInterpolatable = function (property) { return type !== 'boolean' && type !== 'enum' && type !== 'string' && - type !== 'image' && + type !== 'resolvedImage' && type !== 'formatted'; }; @@ -660,7 +660,7 @@ global.valueTransformerArguments = function (property) { case 'formatted': return ['mbgl::style::expression::Formatted', objCType]; case 'string': - case 'image': // TODO: replace once we implement image expressions + case 'resolvedImage': // TODO: replace once we implement image expressions return ['std::string', objCType]; case 'enum': return [mbglType(property), 'NSValue *', mbglType(property), `MGL${camelize(property.name)}`]; @@ -700,7 +700,7 @@ global.mbglType = function(property) { case 'formatted': return 'mbgl::style::expression::Formatted'; case 'string': - case 'image': // TODO: replace once we implement image expressions + case 'resolvedImage': // TODO: replace once we implement image expressions return 'std::string'; case 'enum': { let type = camelize(originalPropertyName(property)); From 3cd1b3fac13c84e00519acbf65ec2cbedc24828a Mon Sep 17 00:00:00 2001 From: Alexander Shalamov Date: Mon, 4 Nov 2019 10:08:06 +0200 Subject: [PATCH 06/10] [darwin] Add conversion for resolvedImage --- platform/darwin/scripts/generate-style-code.js | 12 +++++++----- platform/darwin/src/MGLBackgroundStyleLayer.mm | 4 ++-- platform/darwin/src/MGLFillExtrusionStyleLayer.mm | 4 ++-- platform/darwin/src/MGLFillStyleLayer.mm | 4 ++-- platform/darwin/src/MGLLineStyleLayer.mm | 4 ++-- platform/darwin/src/MGLStyleLayer.mm.ejs | 3 +++ platform/darwin/src/MGLStyleValue_Private.h | 10 ++++++++++ platform/darwin/src/MGLSymbolStyleLayer.mm | 8 ++++---- platform/darwin/test/MGLBackgroundStyleLayerTests.mm | 8 ++++---- .../darwin/test/MGLFillExtrusionStyleLayerTests.mm | 8 ++++---- platform/darwin/test/MGLFillStyleLayerTests.mm | 8 ++++---- platform/darwin/test/MGLLineStyleLayerTests.mm | 8 ++++---- platform/darwin/test/MGLSymbolStyleLayerTests.mm | 10 +++++----- 13 files changed, 53 insertions(+), 38 deletions(-) diff --git a/platform/darwin/scripts/generate-style-code.js b/platform/darwin/scripts/generate-style-code.js index 5d0434f9eaf..cb2e3a94089 100755 --- a/platform/darwin/scripts/generate-style-code.js +++ b/platform/darwin/scripts/generate-style-code.js @@ -153,13 +153,13 @@ global.objCTestValue = function (property, layerType, arraysAsStructs, indent) { case 'number': return '@"1"'; case 'formatted': + case 'resolvedImage': // Special 'string' case to handle constant expression text-field that automatically // converts Formatted back to string. return layerType === 'string' ? `@"'${_.startCase(propertyName)}'"` : `@"${_.startCase(propertyName)}"`; case 'string': - case 'resolvedImage': // TODO: replace once we implement image expressions return `@"'${_.startCase(propertyName)}'"`; case 'enum': return `@"'${_.last(_.keys(property.values))}'"`; @@ -296,7 +296,7 @@ global.testHelperMessage = function (property, layerType, isFunction) { return 'testNumber' + fnSuffix; case 'formatted': case 'string': - case 'image': // TODO: replace once we implement image expressions + case 'resolvedImage': return 'testString' + fnSuffix; case 'enum': let objCType = global.objCType(layerType, property.name); @@ -526,7 +526,7 @@ global.describeValue = function (value, property, layerType) { return 'the float ' + '`' + formatNumber(value) + '`'; case 'formatted': case 'string': - case 'image': // TODO: replace once we implement image expressions + case 'resolvedImage': if (value === '') { return 'the empty string'; } @@ -659,8 +659,9 @@ global.valueTransformerArguments = function (property) { return ['float', objCType]; case 'formatted': return ['mbgl::style::expression::Formatted', objCType]; + case 'resolvedImage': + return ['mbgl::style::expression::Image', objCType]; case 'string': - case 'resolvedImage': // TODO: replace once we implement image expressions return ['std::string', objCType]; case 'enum': return [mbglType(property), 'NSValue *', mbglType(property), `MGL${camelize(property.name)}`]; @@ -699,8 +700,9 @@ global.mbglType = function(property) { return 'float'; case 'formatted': return 'mbgl::style::expression::Formatted'; + case 'resolvedImage': + return 'mbgl::style::expression::Image'; case 'string': - case 'resolvedImage': // TODO: replace once we implement image expressions return 'std::string'; case 'enum': { let type = camelize(originalPropertyName(property)); diff --git a/platform/darwin/src/MGLBackgroundStyleLayer.mm b/platform/darwin/src/MGLBackgroundStyleLayer.mm index 00b10cf2be0..053e05c5c4a 100644 --- a/platform/darwin/src/MGLBackgroundStyleLayer.mm +++ b/platform/darwin/src/MGLBackgroundStyleLayer.mm @@ -106,7 +106,7 @@ - (void)setBackgroundPattern:(NSExpression *)backgroundPattern { MGLAssertStyleLayerIsValid(); MGLLogDebug(@"Setting backgroundPattern: %@", backgroundPattern); - auto mbglValue = MGLStyleValueTransformer().toPropertyValue>(backgroundPattern, false); + auto mbglValue = MGLStyleValueTransformer().toPropertyValue>(backgroundPattern, false); self.rawLayer->setBackgroundPattern(mbglValue); } @@ -117,7 +117,7 @@ - (NSExpression *)backgroundPattern { if (propertyValue.isUndefined()) { propertyValue = self.rawLayer->getDefaultBackgroundPattern(); } - return MGLStyleValueTransformer().toExpression(propertyValue); + return MGLStyleValueTransformer().toExpression(propertyValue); } - (void)setBackgroundPatternTransition:(MGLTransition )transition { diff --git a/platform/darwin/src/MGLFillExtrusionStyleLayer.mm b/platform/darwin/src/MGLFillExtrusionStyleLayer.mm index 1039a8facc7..ed6cd584606 100644 --- a/platform/darwin/src/MGLFillExtrusionStyleLayer.mm +++ b/platform/darwin/src/MGLFillExtrusionStyleLayer.mm @@ -244,7 +244,7 @@ - (void)setFillExtrusionPattern:(NSExpression *)fillExtrusionPattern { MGLAssertStyleLayerIsValid(); MGLLogDebug(@"Setting fillExtrusionPattern: %@", fillExtrusionPattern); - auto mbglValue = MGLStyleValueTransformer().toPropertyValue>(fillExtrusionPattern, true); + auto mbglValue = MGLStyleValueTransformer().toPropertyValue>(fillExtrusionPattern, true); self.rawLayer->setFillExtrusionPattern(mbglValue); } @@ -255,7 +255,7 @@ - (NSExpression *)fillExtrusionPattern { if (propertyValue.isUndefined()) { propertyValue = self.rawLayer->getDefaultFillExtrusionPattern(); } - return MGLStyleValueTransformer().toExpression(propertyValue); + return MGLStyleValueTransformer().toExpression(propertyValue); } - (void)setFillExtrusionPatternTransition:(MGLTransition )transition { diff --git a/platform/darwin/src/MGLFillStyleLayer.mm b/platform/darwin/src/MGLFillStyleLayer.mm index 5a913206562..d8c5516f3a6 100644 --- a/platform/darwin/src/MGLFillStyleLayer.mm +++ b/platform/darwin/src/MGLFillStyleLayer.mm @@ -211,7 +211,7 @@ - (void)setFillPattern:(NSExpression *)fillPattern { MGLAssertStyleLayerIsValid(); MGLLogDebug(@"Setting fillPattern: %@", fillPattern); - auto mbglValue = MGLStyleValueTransformer().toPropertyValue>(fillPattern, true); + auto mbglValue = MGLStyleValueTransformer().toPropertyValue>(fillPattern, true); self.rawLayer->setFillPattern(mbglValue); } @@ -222,7 +222,7 @@ - (NSExpression *)fillPattern { if (propertyValue.isUndefined()) { propertyValue = self.rawLayer->getDefaultFillPattern(); } - return MGLStyleValueTransformer().toExpression(propertyValue); + return MGLStyleValueTransformer().toExpression(propertyValue); } - (void)setFillPatternTransition:(MGLTransition )transition { diff --git a/platform/darwin/src/MGLLineStyleLayer.mm b/platform/darwin/src/MGLLineStyleLayer.mm index fe37be361c9..62d778a6f3c 100644 --- a/platform/darwin/src/MGLLineStyleLayer.mm +++ b/platform/darwin/src/MGLLineStyleLayer.mm @@ -396,7 +396,7 @@ - (void)setLinePattern:(NSExpression *)linePattern { MGLAssertStyleLayerIsValid(); MGLLogDebug(@"Setting linePattern: %@", linePattern); - auto mbglValue = MGLStyleValueTransformer().toPropertyValue>(linePattern, true); + auto mbglValue = MGLStyleValueTransformer().toPropertyValue>(linePattern, true); self.rawLayer->setLinePattern(mbglValue); } @@ -407,7 +407,7 @@ - (NSExpression *)linePattern { if (propertyValue.isUndefined()) { propertyValue = self.rawLayer->getDefaultLinePattern(); } - return MGLStyleValueTransformer().toExpression(propertyValue); + return MGLStyleValueTransformer().toExpression(propertyValue); } - (void)setLinePatternTransition:(MGLTransition )transition { diff --git a/platform/darwin/src/MGLStyleLayer.mm.ejs b/platform/darwin/src/MGLStyleLayer.mm.ejs index 5d9f546cd73..5664f7fd454 100644 --- a/platform/darwin/src/MGLStyleLayer.mm.ejs +++ b/platform/darwin/src/MGLStyleLayer.mm.ejs @@ -136,6 +136,9 @@ namespace mbgl { <% if (property.type === 'formatted') { -%> self.rawLayer->set<%- camelize(originalPropertyName(property)) %>(mbgl::style::PropertyValue( mbgl::style::conversion::convertTokenStringToFormatExpression(string))); +<% } else if (property.type === 'resolvedImage') { -%> + self.rawLayer->set<%- camelize(originalPropertyName(property)) %>(mbgl::style::PropertyValue( + mbgl::style::conversion::convertTokenStringToImageExpression(string))); <% } else { -%> self.rawLayer->set<%- camelize(originalPropertyName(property)) %>(mbgl::style::PropertyValue( mbgl::style::conversion::convertTokenStringToExpression(string))); diff --git a/platform/darwin/src/MGLStyleValue_Private.h b/platform/darwin/src/MGLStyleValue_Private.h index 82ce232c6bf..07dbd312381 100644 --- a/platform/darwin/src/MGLStyleValue_Private.h +++ b/platform/darwin/src/MGLStyleValue_Private.h @@ -217,6 +217,11 @@ class MGLStyleValueTransformer { mbglValue = rawValue.mgl_color; } + // Image + void getMBGLValue(NSString *rawValue, mbgl::style::expression::Image &mbglValue) { + mbglValue = mbgl::style::expression::Image(rawValue.UTF8String); + } + // Array void getMBGLValue(ObjCType rawValue, std::vector &mbglValue) { mbglValue.reserve(rawValue.count); @@ -295,6 +300,11 @@ class MGLStyleValueTransformer { return [MGLColor mgl_colorWithColor:mbglStopValue]; } + // Image + static NSString *toMGLRawStyleValue(const mbgl::style::expression::Image &mbglImageValue) { + return @(mbglImageValue.id().c_str()); + } + // Array static NSArray *toMGLRawStyleValue(const std::vector &mbglStopValue) { NSMutableArray *array = [NSMutableArray arrayWithCapacity:mbglStopValue.size()]; diff --git a/platform/darwin/src/MGLSymbolStyleLayer.mm b/platform/darwin/src/MGLSymbolStyleLayer.mm index e89b9c3e884..966386e0f22 100644 --- a/platform/darwin/src/MGLSymbolStyleLayer.mm +++ b/platform/darwin/src/MGLSymbolStyleLayer.mm @@ -248,12 +248,12 @@ - (void)setIconImageName:(NSExpression *)iconImageName { if (iconImageName && iconImageName.expressionType == NSConstantValueExpressionType) { std::string string = ((NSString *)iconImageName.constantValue).UTF8String; if (mbgl::style::conversion::hasTokens(string)) { - self.rawLayer->setIconImage(mbgl::style::PropertyValue( - mbgl::style::conversion::convertTokenStringToExpression(string))); + self.rawLayer->setIconImage(mbgl::style::PropertyValue( + mbgl::style::conversion::convertTokenStringToImageExpression(string))); return; } } - auto mbglValue = MGLStyleValueTransformer().toPropertyValue>(iconImageName, true); + auto mbglValue = MGLStyleValueTransformer().toPropertyValue>(iconImageName, true); self.rawLayer->setIconImage(mbglValue); } @@ -264,7 +264,7 @@ - (NSExpression *)iconImageName { if (propertyValue.isUndefined()) { propertyValue = self.rawLayer->getDefaultIconImage(); } - return MGLStyleValueTransformer().toExpression(propertyValue); + return MGLStyleValueTransformer().toExpression(propertyValue); } - (void)setIconImage:(NSExpression *)iconImage { diff --git a/platform/darwin/test/MGLBackgroundStyleLayerTests.mm b/platform/darwin/test/MGLBackgroundStyleLayerTests.mm index 600f81acfec..3e59000c11c 100644 --- a/platform/darwin/test/MGLBackgroundStyleLayerTests.mm +++ b/platform/darwin/test/MGLBackgroundStyleLayerTests.mm @@ -140,21 +140,21 @@ - (void)testProperties { @"background-pattern should be unset initially."); NSExpression *defaultExpression = layer.backgroundPattern; - NSExpression *constantExpression = [NSExpression expressionWithFormat:@"'Background Pattern'"]; + NSExpression *constantExpression = [NSExpression expressionWithFormat:@"Background Pattern"]; layer.backgroundPattern = constantExpression; - mbgl::style::PropertyValue propertyValue = { "Background Pattern" }; + mbgl::style::PropertyValue propertyValue = { "Background Pattern" }; XCTAssertEqual(rawLayer->getBackgroundPattern(), propertyValue, @"Setting backgroundPattern to a constant value expression should update background-pattern."); XCTAssertEqualObjects(layer.backgroundPattern, constantExpression, @"backgroundPattern should round-trip constant value expressions."); - constantExpression = [NSExpression expressionWithFormat:@"'Background Pattern'"]; + constantExpression = [NSExpression expressionWithFormat:@"Background Pattern"]; NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}]; layer.backgroundPattern = functionExpression; { using namespace mbgl::style::expression::dsl; - propertyValue = mbgl::style::PropertyExpression( + propertyValue = mbgl::style::PropertyExpression( step(zoom(), literal("Background Pattern"), 18.0, literal("Background Pattern")) ); } diff --git a/platform/darwin/test/MGLFillExtrusionStyleLayerTests.mm b/platform/darwin/test/MGLFillExtrusionStyleLayerTests.mm index 357ee888bcc..d35d76535ed 100644 --- a/platform/darwin/test/MGLFillExtrusionStyleLayerTests.mm +++ b/platform/darwin/test/MGLFillExtrusionStyleLayerTests.mm @@ -386,21 +386,21 @@ - (void)testProperties { @"fill-extrusion-pattern should be unset initially."); NSExpression *defaultExpression = layer.fillExtrusionPattern; - NSExpression *constantExpression = [NSExpression expressionWithFormat:@"'Fill Extrusion Pattern'"]; + NSExpression *constantExpression = [NSExpression expressionWithFormat:@"Fill Extrusion Pattern"]; layer.fillExtrusionPattern = constantExpression; - mbgl::style::PropertyValue propertyValue = { "Fill Extrusion Pattern" }; + mbgl::style::PropertyValue propertyValue = { "Fill Extrusion Pattern" }; XCTAssertEqual(rawLayer->getFillExtrusionPattern(), propertyValue, @"Setting fillExtrusionPattern to a constant value expression should update fill-extrusion-pattern."); XCTAssertEqualObjects(layer.fillExtrusionPattern, constantExpression, @"fillExtrusionPattern should round-trip constant value expressions."); - constantExpression = [NSExpression expressionWithFormat:@"'Fill Extrusion Pattern'"]; + constantExpression = [NSExpression expressionWithFormat:@"Fill Extrusion Pattern"]; NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}]; layer.fillExtrusionPattern = functionExpression; { using namespace mbgl::style::expression::dsl; - propertyValue = mbgl::style::PropertyExpression( + propertyValue = mbgl::style::PropertyExpression( step(zoom(), literal("Fill Extrusion Pattern"), 18.0, literal("Fill Extrusion Pattern")) ); } diff --git a/platform/darwin/test/MGLFillStyleLayerTests.mm b/platform/darwin/test/MGLFillStyleLayerTests.mm index 3762c4095e6..667d48125ed 100644 --- a/platform/darwin/test/MGLFillStyleLayerTests.mm +++ b/platform/darwin/test/MGLFillStyleLayerTests.mm @@ -333,21 +333,21 @@ - (void)testProperties { @"fill-pattern should be unset initially."); NSExpression *defaultExpression = layer.fillPattern; - NSExpression *constantExpression = [NSExpression expressionWithFormat:@"'Fill Pattern'"]; + NSExpression *constantExpression = [NSExpression expressionWithFormat:@"Fill Pattern"]; layer.fillPattern = constantExpression; - mbgl::style::PropertyValue propertyValue = { "Fill Pattern" }; + mbgl::style::PropertyValue propertyValue = { "Fill Pattern" }; XCTAssertEqual(rawLayer->getFillPattern(), propertyValue, @"Setting fillPattern to a constant value expression should update fill-pattern."); XCTAssertEqualObjects(layer.fillPattern, constantExpression, @"fillPattern should round-trip constant value expressions."); - constantExpression = [NSExpression expressionWithFormat:@"'Fill Pattern'"]; + constantExpression = [NSExpression expressionWithFormat:@"Fill Pattern"]; NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}]; layer.fillPattern = functionExpression; { using namespace mbgl::style::expression::dsl; - propertyValue = mbgl::style::PropertyExpression( + propertyValue = mbgl::style::PropertyExpression( step(zoom(), literal("Fill Pattern"), 18.0, literal("Fill Pattern")) ); } diff --git a/platform/darwin/test/MGLLineStyleLayerTests.mm b/platform/darwin/test/MGLLineStyleLayerTests.mm index f4fd714ad7d..99350c388cf 100644 --- a/platform/darwin/test/MGLLineStyleLayerTests.mm +++ b/platform/darwin/test/MGLLineStyleLayerTests.mm @@ -659,21 +659,21 @@ - (void)testProperties { @"line-pattern should be unset initially."); NSExpression *defaultExpression = layer.linePattern; - NSExpression *constantExpression = [NSExpression expressionWithFormat:@"'Line Pattern'"]; + NSExpression *constantExpression = [NSExpression expressionWithFormat:@"Line Pattern"]; layer.linePattern = constantExpression; - mbgl::style::PropertyValue propertyValue = { "Line Pattern" }; + mbgl::style::PropertyValue propertyValue = { "Line Pattern" }; XCTAssertEqual(rawLayer->getLinePattern(), propertyValue, @"Setting linePattern to a constant value expression should update line-pattern."); XCTAssertEqualObjects(layer.linePattern, constantExpression, @"linePattern should round-trip constant value expressions."); - constantExpression = [NSExpression expressionWithFormat:@"'Line Pattern'"]; + constantExpression = [NSExpression expressionWithFormat:@"Line Pattern"]; NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}]; layer.linePattern = functionExpression; { using namespace mbgl::style::expression::dsl; - propertyValue = mbgl::style::PropertyExpression( + propertyValue = mbgl::style::PropertyExpression( step(zoom(), literal("Line Pattern"), 18.0, literal("Line Pattern")) ); } diff --git a/platform/darwin/test/MGLSymbolStyleLayerTests.mm b/platform/darwin/test/MGLSymbolStyleLayerTests.mm index 5cc9c3c3323..cfb62fd4df4 100644 --- a/platform/darwin/test/MGLSymbolStyleLayerTests.mm +++ b/platform/darwin/test/MGLSymbolStyleLayerTests.mm @@ -182,21 +182,21 @@ - (void)testProperties { @"icon-image should be unset initially."); NSExpression *defaultExpression = layer.iconImageName; - NSExpression *constantExpression = [NSExpression expressionWithFormat:@"'Icon Image'"]; + NSExpression *constantExpression = [NSExpression expressionWithFormat:@"Icon Image"]; layer.iconImageName = constantExpression; - mbgl::style::PropertyValue propertyValue = { "Icon Image" }; + mbgl::style::PropertyValue propertyValue = { "Icon Image" }; XCTAssertEqual(rawLayer->getIconImage(), propertyValue, @"Setting iconImageName to a constant value expression should update icon-image."); XCTAssertEqualObjects(layer.iconImageName, constantExpression, @"iconImageName should round-trip constant value expressions."); - constantExpression = [NSExpression expressionWithFormat:@"'Icon Image'"]; + constantExpression = [NSExpression expressionWithFormat:@"Icon Image"]; NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}]; layer.iconImageName = functionExpression; { using namespace mbgl::style::expression::dsl; - propertyValue = mbgl::style::PropertyExpression( + propertyValue = mbgl::style::PropertyExpression( step(zoom(), literal("Icon Image"), 18.0, literal("Icon Image")) ); } @@ -218,7 +218,7 @@ - (void)testProperties { { using namespace mbgl::style::expression::dsl; - propertyValue = mbgl::style::PropertyExpression( + propertyValue = mbgl::style::PropertyExpression( toString(get(literal("token"))) ); } From bb3c2aefe91ee4deddfd14eb2a9ffc60eb5fd3c3 Mon Sep 17 00:00:00 2001 From: Alexander Shalamov Date: Mon, 4 Nov 2019 10:18:06 +0200 Subject: [PATCH 07/10] [darwin] Fix image roundrip conversion --- platform/darwin/scripts/generate-style-code.js | 11 +++++++---- platform/darwin/src/NSExpression+MGLAdditions.mm | 1 + platform/darwin/test/MGLBackgroundStyleLayerTests.mm | 6 +++--- .../darwin/test/MGLFillExtrusionStyleLayerTests.mm | 6 +++--- platform/darwin/test/MGLFillStyleLayerTests.mm | 6 +++--- platform/darwin/test/MGLLineStyleLayerTests.mm | 6 +++--- platform/darwin/test/MGLStyleLayerTests.mm.ejs | 8 ++++++++ platform/darwin/test/MGLSymbolStyleLayerTests.mm | 10 +++++----- 8 files changed, 33 insertions(+), 21 deletions(-) diff --git a/platform/darwin/scripts/generate-style-code.js b/platform/darwin/scripts/generate-style-code.js index cb2e3a94089..bd5adb96856 100755 --- a/platform/darwin/scripts/generate-style-code.js +++ b/platform/darwin/scripts/generate-style-code.js @@ -153,12 +153,15 @@ global.objCTestValue = function (property, layerType, arraysAsStructs, indent) { case 'number': return '@"1"'; case 'formatted': - case 'resolvedImage': // Special 'string' case to handle constant expression text-field that automatically // converts Formatted back to string. return layerType === 'string' ? `@"'${_.startCase(propertyName)}'"` : `@"${_.startCase(propertyName)}"`; + case 'resolvedImage': + return layerType === 'string' ? + `@"${_.startCase(propertyName)}"` : + `@"MGL_FUNCTION('image', '${_.startCase(propertyName)}')"`; case 'string': return `@"'${_.startCase(propertyName)}'"`; case 'enum': @@ -209,7 +212,7 @@ global.mbglTestValue = function (property, layerType) { return '1.0'; case 'formatted': case 'string': - case 'resolvedImage': // TODO: replace once we implement image expressions + case 'resolvedImage': return `"${_.startCase(propertyName)}"`; case 'enum': { let type = camelize(originalPropertyName(property)); @@ -477,7 +480,7 @@ global.describeType = function (property) { return 'numeric'; case 'formatted': case 'string': - case 'resolvedImage': // TODO: replace once we implement image expressions + case 'resolvedImage': return 'string'; case 'enum': return '`MGL' + camelize(property.name) + '`'; @@ -613,7 +616,7 @@ global.propertyType = function (property) { return 'NSNumber *'; case 'formatted': case 'string': - case 'resolvedImage': // TODO: replace once we implement image expressions + case 'resolvedImage': return 'NSString *'; case 'enum': return 'NSValue *'; diff --git a/platform/darwin/src/NSExpression+MGLAdditions.mm b/platform/darwin/src/NSExpression+MGLAdditions.mm index f139b86a887..80008aa69b6 100644 --- a/platform/darwin/src/NSExpression+MGLAdditions.mm +++ b/platform/darwin/src/NSExpression+MGLAdditions.mm @@ -1229,6 +1229,7 @@ - (id)mgl_jsonExpressionObject { return expressionObject; } + return self.arguments.mgl_jsonExpressionObject; } else if (op == [MGLColor class] && [function isEqualToString:@"colorWithRed:green:blue:alpha:"]) { NSArray *arguments = self.arguments.mgl_jsonExpressionObject; diff --git a/platform/darwin/test/MGLBackgroundStyleLayerTests.mm b/platform/darwin/test/MGLBackgroundStyleLayerTests.mm index 3e59000c11c..4617cff598e 100644 --- a/platform/darwin/test/MGLBackgroundStyleLayerTests.mm +++ b/platform/darwin/test/MGLBackgroundStyleLayerTests.mm @@ -140,7 +140,7 @@ - (void)testProperties { @"background-pattern should be unset initially."); NSExpression *defaultExpression = layer.backgroundPattern; - NSExpression *constantExpression = [NSExpression expressionWithFormat:@"Background Pattern"]; + NSExpression *constantExpression = [NSExpression expressionForConstantValue:@"Background Pattern"]; layer.backgroundPattern = constantExpression; mbgl::style::PropertyValue propertyValue = { "Background Pattern" }; XCTAssertEqual(rawLayer->getBackgroundPattern(), propertyValue, @@ -148,14 +148,14 @@ - (void)testProperties { XCTAssertEqualObjects(layer.backgroundPattern, constantExpression, @"backgroundPattern should round-trip constant value expressions."); - constantExpression = [NSExpression expressionWithFormat:@"Background Pattern"]; + constantExpression = [NSExpression expressionWithFormat:@"MGL_FUNCTION('image', 'Background Pattern')"]; NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}]; layer.backgroundPattern = functionExpression; { using namespace mbgl::style::expression::dsl; propertyValue = mbgl::style::PropertyExpression( - step(zoom(), literal("Background Pattern"), 18.0, literal("Background Pattern")) + step(zoom(), image(literal("Background Pattern")), 18.0, image(literal("Background Pattern"))) ); } diff --git a/platform/darwin/test/MGLFillExtrusionStyleLayerTests.mm b/platform/darwin/test/MGLFillExtrusionStyleLayerTests.mm index d35d76535ed..8dfc0777779 100644 --- a/platform/darwin/test/MGLFillExtrusionStyleLayerTests.mm +++ b/platform/darwin/test/MGLFillExtrusionStyleLayerTests.mm @@ -386,7 +386,7 @@ - (void)testProperties { @"fill-extrusion-pattern should be unset initially."); NSExpression *defaultExpression = layer.fillExtrusionPattern; - NSExpression *constantExpression = [NSExpression expressionWithFormat:@"Fill Extrusion Pattern"]; + NSExpression *constantExpression = [NSExpression expressionForConstantValue:@"Fill Extrusion Pattern"]; layer.fillExtrusionPattern = constantExpression; mbgl::style::PropertyValue propertyValue = { "Fill Extrusion Pattern" }; XCTAssertEqual(rawLayer->getFillExtrusionPattern(), propertyValue, @@ -394,14 +394,14 @@ - (void)testProperties { XCTAssertEqualObjects(layer.fillExtrusionPattern, constantExpression, @"fillExtrusionPattern should round-trip constant value expressions."); - constantExpression = [NSExpression expressionWithFormat:@"Fill Extrusion Pattern"]; + constantExpression = [NSExpression expressionWithFormat:@"MGL_FUNCTION('image', 'Fill Extrusion Pattern')"]; NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}]; layer.fillExtrusionPattern = functionExpression; { using namespace mbgl::style::expression::dsl; propertyValue = mbgl::style::PropertyExpression( - step(zoom(), literal("Fill Extrusion Pattern"), 18.0, literal("Fill Extrusion Pattern")) + step(zoom(), image(literal("Fill Extrusion Pattern")), 18.0, image(literal("Fill Extrusion Pattern"))) ); } diff --git a/platform/darwin/test/MGLFillStyleLayerTests.mm b/platform/darwin/test/MGLFillStyleLayerTests.mm index 667d48125ed..e37bd537a7b 100644 --- a/platform/darwin/test/MGLFillStyleLayerTests.mm +++ b/platform/darwin/test/MGLFillStyleLayerTests.mm @@ -333,7 +333,7 @@ - (void)testProperties { @"fill-pattern should be unset initially."); NSExpression *defaultExpression = layer.fillPattern; - NSExpression *constantExpression = [NSExpression expressionWithFormat:@"Fill Pattern"]; + NSExpression *constantExpression = [NSExpression expressionForConstantValue:@"Fill Pattern"]; layer.fillPattern = constantExpression; mbgl::style::PropertyValue propertyValue = { "Fill Pattern" }; XCTAssertEqual(rawLayer->getFillPattern(), propertyValue, @@ -341,14 +341,14 @@ - (void)testProperties { XCTAssertEqualObjects(layer.fillPattern, constantExpression, @"fillPattern should round-trip constant value expressions."); - constantExpression = [NSExpression expressionWithFormat:@"Fill Pattern"]; + constantExpression = [NSExpression expressionWithFormat:@"MGL_FUNCTION('image', 'Fill Pattern')"]; NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}]; layer.fillPattern = functionExpression; { using namespace mbgl::style::expression::dsl; propertyValue = mbgl::style::PropertyExpression( - step(zoom(), literal("Fill Pattern"), 18.0, literal("Fill Pattern")) + step(zoom(), image(literal("Fill Pattern")), 18.0, image(literal("Fill Pattern"))) ); } diff --git a/platform/darwin/test/MGLLineStyleLayerTests.mm b/platform/darwin/test/MGLLineStyleLayerTests.mm index 99350c388cf..46f040b6019 100644 --- a/platform/darwin/test/MGLLineStyleLayerTests.mm +++ b/platform/darwin/test/MGLLineStyleLayerTests.mm @@ -659,7 +659,7 @@ - (void)testProperties { @"line-pattern should be unset initially."); NSExpression *defaultExpression = layer.linePattern; - NSExpression *constantExpression = [NSExpression expressionWithFormat:@"Line Pattern"]; + NSExpression *constantExpression = [NSExpression expressionForConstantValue:@"Line Pattern"]; layer.linePattern = constantExpression; mbgl::style::PropertyValue propertyValue = { "Line Pattern" }; XCTAssertEqual(rawLayer->getLinePattern(), propertyValue, @@ -667,14 +667,14 @@ - (void)testProperties { XCTAssertEqualObjects(layer.linePattern, constantExpression, @"linePattern should round-trip constant value expressions."); - constantExpression = [NSExpression expressionWithFormat:@"Line Pattern"]; + constantExpression = [NSExpression expressionWithFormat:@"MGL_FUNCTION('image', 'Line Pattern')"]; NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}]; layer.linePattern = functionExpression; { using namespace mbgl::style::expression::dsl; propertyValue = mbgl::style::PropertyExpression( - step(zoom(), literal("Line Pattern"), 18.0, literal("Line Pattern")) + step(zoom(), image(literal("Line Pattern")), 18.0, image(literal("Line Pattern"))) ); } diff --git a/platform/darwin/test/MGLStyleLayerTests.mm.ejs b/platform/darwin/test/MGLStyleLayerTests.mm.ejs index 14c7c397d3f..a764f163be8 100644 --- a/platform/darwin/test/MGLStyleLayerTests.mm.ejs +++ b/platform/darwin/test/MGLStyleLayerTests.mm.ejs @@ -73,6 +73,8 @@ <% if (property.type === 'formatted') { -%> NSExpression *constantExpression = [NSExpression expressionWithFormat:<%- objCTestValue(property, 'string', true, 3) %>]; +<% } else if (property.type === 'resolvedImage'){ -%> + NSExpression *constantExpression = [NSExpression expressionForConstantValue:<%- objCTestValue(property, 'string', true, 3) %>]; <% } else { -%> NSExpression *constantExpression = [NSExpression expressionWithFormat:<%- objCTestValue(property, type, true, 3) %>]; <% } -%> @@ -98,6 +100,8 @@ propertyValue = mbgl::style::PropertyExpression<<%- mbglType(property) %>>( <% if (property.type === 'formatted') { -%> step(zoom(), format(<%- mbglExpressionTestValue(property, type) %>), 18.0, format(<%- mbglExpressionTestValue(property, type) %>)) +<% } else if (property.type === 'resolvedImage') { -%> + step(zoom(), image(literal(<%- mbglExpressionTestValue(property, type) %>)), 18.0, image(literal(<%- mbglExpressionTestValue(property, type) %>))) <% } else { -%> step(zoom(), literal(<%- mbglExpressionTestValue(property, type) %>), 18.0, literal(<%- mbglExpressionTestValue(property, type) %>)) <% } -%> @@ -179,6 +183,8 @@ propertyValue = mbgl::style::PropertyExpression<<%- mbglType(property) %>>( <% if (property.type === 'formatted') { -%> format(toString(get(literal("token")))) +<% } else if (property.type === 'resolvedImage') { -%> + image(toString(get(literal("token")))) <% } else { -%> toString(get(literal("token"))) <% } -%> @@ -192,6 +198,8 @@ MGLAttributedExpression *tokenAttibutedExpression = [[MGLAttributedExpression alloc] initWithExpression:[NSExpression expressionWithFormat:@"CAST(token, 'NSString')"] attributes:@{}]; NSExpression* tokenExpression = [NSExpression mgl_expressionForAttributedExpressions:@[[NSExpression expressionForConstantValue:tokenAttibutedExpression]]]; +<% } else if (property.type === 'resolvedImage') { -%> + NSExpression* tokenExpression = [NSExpression expressionWithFormat:@"MGL_FUNCTION('image', CAST(token, \"NSString\"))"]; <% } else { -%> NSExpression* tokenExpression = [NSExpression expressionWithFormat:@"CAST(token, \"NSString\")"]; <% } -%> diff --git a/platform/darwin/test/MGLSymbolStyleLayerTests.mm b/platform/darwin/test/MGLSymbolStyleLayerTests.mm index cfb62fd4df4..04ef3fc7122 100644 --- a/platform/darwin/test/MGLSymbolStyleLayerTests.mm +++ b/platform/darwin/test/MGLSymbolStyleLayerTests.mm @@ -182,7 +182,7 @@ - (void)testProperties { @"icon-image should be unset initially."); NSExpression *defaultExpression = layer.iconImageName; - NSExpression *constantExpression = [NSExpression expressionWithFormat:@"Icon Image"]; + NSExpression *constantExpression = [NSExpression expressionForConstantValue:@"Icon Image"]; layer.iconImageName = constantExpression; mbgl::style::PropertyValue propertyValue = { "Icon Image" }; XCTAssertEqual(rawLayer->getIconImage(), propertyValue, @@ -190,14 +190,14 @@ - (void)testProperties { XCTAssertEqualObjects(layer.iconImageName, constantExpression, @"iconImageName should round-trip constant value expressions."); - constantExpression = [NSExpression expressionWithFormat:@"Icon Image"]; + constantExpression = [NSExpression expressionWithFormat:@"MGL_FUNCTION('image', 'Icon Image')"]; NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}]; layer.iconImageName = functionExpression; { using namespace mbgl::style::expression::dsl; propertyValue = mbgl::style::PropertyExpression( - step(zoom(), literal("Icon Image"), 18.0, literal("Icon Image")) + step(zoom(), image(literal("Icon Image")), 18.0, image(literal("Icon Image"))) ); } @@ -219,14 +219,14 @@ - (void)testProperties { { using namespace mbgl::style::expression::dsl; propertyValue = mbgl::style::PropertyExpression( - toString(get(literal("token"))) + image(toString(get(literal("token")))) ); } XCTAssertEqual(rawLayer->getIconImage(), propertyValue, @"Setting iconImageName to a constant string with tokens should convert to an expression."); - NSExpression* tokenExpression = [NSExpression expressionWithFormat:@"CAST(token, \"NSString\")"]; + NSExpression* tokenExpression = [NSExpression expressionWithFormat:@"MGL_FUNCTION('image', CAST(token, \"NSString\"))"]; XCTAssertEqualObjects(layer.iconImageName, tokenExpression, @"Setting iconImageName to a constant string with tokens should convert to an expression."); } From 7d362de6ba8049b0487311e8d7dd783b5d3ee1b7 Mon Sep 17 00:00:00 2001 From: Alexander Shalamov Date: Mon, 11 Nov 2019 11:07:12 +0200 Subject: [PATCH 08/10] [node] Update changelog --- platform/node/CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/platform/node/CHANGELOG.md b/platform/node/CHANGELOG.md index 6af55f5d508..b88189c0f2b 100644 --- a/platform/node/CHANGELOG.md +++ b/platform/node/CHANGELOG.md @@ -1,4 +1,7 @@ +# master +* Add support for [image expression](https://docs.mapbox.com/mapbox-gl-js/style-spec/#expressions-types-image). ([#15877](https://github.com/mapbox/mapbox-gl-native/pull/15877)) + # 5.0.0 * No longer supporting source-compile fallback ([#15748](https://github.com/mapbox/mapbox-gl-native/pull/15748)) * Add support for feature state APIs. ([#15480](https://github.com/mapbox/mapbox-gl-native/pull/15480)) From b15c6d0d836584bbc21bfd4fcb2eee14a874a59b Mon Sep 17 00:00:00 2001 From: Alexander Shalamov Date: Mon, 11 Nov 2019 11:13:23 +0200 Subject: [PATCH 09/10] [android] Update changelog --- platform/android/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/android/CHANGELOG.md b/platform/android/CHANGELOG.md index 815a20a5722..7bab764af53 100644 --- a/platform/android/CHANGELOG.md +++ b/platform/android/CHANGELOG.md @@ -3,6 +3,7 @@ Mapbox welcomes participation and contributions from everyone. If you'd like to do so please see the [`Contributing Guide`](https://github.com/mapbox/mapbox-gl-native/blob/master/CONTRIBUTING.md) first to get started. ## master +- Added support for [image expression](https://docs.mapbox.com/mapbox-gl-js/style-spec/#expressions-types-image) in core library. Runtime APIs for image expression will be implemented separately. [#15877](https://github.com/mapbox/mapbox-gl-native/pull/15877) ### Bug fixes - Fixed the rendering bug caused by redundant pending requests for already requested images [#15864](https://github.com/mapbox/mapbox-gl-native/pull/15864) From d0f3bcaf4525b6749ffcae328f7908be77378c7f Mon Sep 17 00:00:00 2001 From: Alexander Shalamov Date: Mon, 11 Nov 2019 11:13:39 +0200 Subject: [PATCH 10/10] [darwin] Update changelog --- platform/ios/CHANGELOG.md | 1 + platform/macos/CHANGELOG.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index da4334db89f..6f715d2f26a 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -3,6 +3,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONTRIBUTING.md](../../CONTRIBUTING.md) to get started. ## master +* Added support for [image expression](https://docs.mapbox.com/mapbox-gl-js/style-spec/#expressions-types-image) in core library. Runtime APIs for image expression will be implemented separately. ([#15877](https://github.com/mapbox/mapbox-gl-native/pull/15877)) ### Other changes * Convert GeoJSON features to tiles for the loaded source description in a background thread and thus unblock the UI thread ([#15885](https://github.com/mapbox/mapbox-gl-native/pull/15885)) diff --git a/platform/macos/CHANGELOG.md b/platform/macos/CHANGELOG.md index fc59457a261..1f3f08cc195 100644 --- a/platform/macos/CHANGELOG.md +++ b/platform/macos/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog for Mapbox Maps SDK for macOS ## master - +* Added support for [image expression](https://docs.mapbox.com/mapbox-gl-js/style-spec/#expressions-types-image) in core library. Runtime APIs for image expression will be implemented separately. ([#15877](https://github.com/mapbox/mapbox-gl-native/pull/15877)) * Fixed crashes triggered when `MGLSource` and `MGLStyleLayer` objects are accessed after having been invalidated after a style change. ([#15539](https://github.com/mapbox/mapbox-gl-native/pull/15539)) * Fixed an issue where it was possible to set the map’s content insets then tilt the map enough to see the horizon, causing performance issues. ([#15195](https://github.com/mapbox/mapbox-gl-native/pull/15195)) * Added an `MGLMapView.prefetchesTiles` property to configure lower-resolution tile prefetching behavior. ([#14816](https://github.com/mapbox/mapbox-gl-native/pull/14816))