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