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