summaryrefslogtreecommitdiff
path: root/include/mbgl
diff options
context:
space:
mode:
authorAlexander Shalamov <alexander.shalamov@mapbox.com>2019-03-11 10:26:19 +0200
committerAlexander Shalamov <alexander.shalamov@mapbox.com>2019-03-13 17:14:53 +0200
commit8be135231d9efe41a3b12037518d02b36104e8cf (patch)
treeefecd5380232f899aed2cd5824dc16f057f0469a /include/mbgl
parent8a51362bccbd6487dd1ed8518443b16ba6114fd8 (diff)
downloadqtlocation-mapboxgl-8be135231d9efe41a3b12037518d02b36104e8cf.tar.gz
[core] Add possibility of overriding paint properties inside format expression #14062
* [core] Add format override expression and formatted section to evaluation context * [core] Add textColor to TaggedString's formatted section * [core] Add FormatSectionOverrides and introduce overridable properties * [core] Populate symbol layer paint properties for text sections * [core] Add benchmark for style that uses text-color override * [core] Add unit test for FormatOverrideExpression * [core] Add unit test for FormatSectionOverrides
Diffstat (limited to 'include/mbgl')
-rw-r--r--include/mbgl/style/expression/expression.hpp17
-rw-r--r--include/mbgl/style/expression/format_expression.hpp17
-rw-r--r--include/mbgl/style/expression/format_section_override.hpp82
-rw-r--r--include/mbgl/style/expression/formatted.hpp16
-rw-r--r--include/mbgl/style/property_expression.hpp103
5 files changed, 147 insertions, 88 deletions
diff --git a/include/mbgl/style/expression/expression.hpp b/include/mbgl/style/expression/expression.hpp
index 97b143b3d9..22ae57c2be 100644
--- a/include/mbgl/style/expression/expression.hpp
+++ b/include/mbgl/style/expression/expression.hpp
@@ -25,18 +25,26 @@ public:
class EvaluationContext {
public:
- EvaluationContext(float zoom_) : zoom(zoom_), feature(nullptr) {}
- EvaluationContext(GeometryTileFeature const * feature_) : zoom(optional<float>()), feature(feature_) {}
+ 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(optional<float> zoom_, GeometryTileFeature const * feature_, optional<double> colorRampParameter_) :
zoom(std::move(zoom_)), feature(feature_), colorRampParameter(std::move(colorRampParameter_))
{}
-
+
+ EvaluationContext& withFormattedSection(const Value* formattedSection_) noexcept {
+ formattedSection = formattedSection_;
+ return *this;
+ };
+
optional<float> zoom;
- GeometryTileFeature const * feature;
+ GeometryTileFeature const * feature = nullptr;
optional<double> colorRampParameter;
+ // Contains formatted section object, std::unordered_map<std::string, Value>.
+ const Value* formattedSection = nullptr;
};
template <typename T>
@@ -134,6 +142,7 @@ enum class Kind : int32_t {
All,
Comparison,
FormatExpression,
+ FormatSectionOverride
};
class Expression {
diff --git a/include/mbgl/style/expression/format_expression.hpp b/include/mbgl/style/expression/format_expression.hpp
index b00674a88e..180df0139d 100644
--- a/include/mbgl/style/expression/format_expression.hpp
+++ b/include/mbgl/style/expression/format_expression.hpp
@@ -1,11 +1,7 @@
#pragma once
#include <mbgl/style/expression/expression.hpp>
-#include <mbgl/style/expression/formatted.hpp>
#include <mbgl/style/expression/parsing_context.hpp>
-#include <mbgl/style/conversion.hpp>
-
-#include <memory>
namespace mbgl {
namespace style {
@@ -14,16 +10,18 @@ namespace expression {
struct FormatExpressionSection {
FormatExpressionSection(std::unique_ptr<Expression> text_,
optional<std::unique_ptr<Expression>> fontScale_,
- optional<std::unique_ptr<Expression>> textFont_);
+ optional<std::unique_ptr<Expression>> textFont_,
+ optional<std::unique_ptr<Expression>> textColor_);
std::shared_ptr<Expression> text;
optional<std::shared_ptr<Expression>> fontScale;
optional<std::shared_ptr<Expression>> textFont;
+ optional<std::shared_ptr<Expression>> textColor;
};
-class FormatExpression : public Expression {
+class FormatExpression final : public Expression {
public:
- FormatExpression(std::vector<FormatExpressionSection> sections);
+ explicit FormatExpression(std::vector<FormatExpressionSection> sections);
EvaluationResult evaluate(const EvaluationContext&) const override;
static ParseResult parse(const mbgl::style::conversion::Convertible&, ParsingContext&);
@@ -38,13 +36,12 @@ public:
return { nullopt };
}
+ const std::vector<FormatExpressionSection>& getSections() const { return sections; }
+
mbgl::Value serialize() const override;
std::string getOperator() const override { return "format"; }
private:
std::vector<FormatExpressionSection> sections;
- std::unique_ptr<Expression> text;
- optional<std::unique_ptr<Expression>> fontScale;
- optional<std::unique_ptr<Expression>> textFont;
};
} // namespace expression
diff --git a/include/mbgl/style/expression/format_section_override.hpp b/include/mbgl/style/expression/format_section_override.hpp
new file mode 100644
index 0000000000..7dc3a8dbb4
--- /dev/null
+++ b/include/mbgl/style/expression/format_section_override.hpp
@@ -0,0 +1,82 @@
+#pragma once
+
+#include <mbgl/style/expression/expression.hpp>
+#include <mbgl/renderer/possibly_evaluated_property_value.hpp>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+template<class T>
+class FormatSectionOverride final : public Expression {
+public:
+ FormatSectionOverride(const type::Type& type_,
+ PossiblyEvaluatedPropertyValue<T> defaultValue_,
+ std::string propertyName_) :
+ Expression(Kind::FormatSectionOverride, type_),
+ defaultValue(std::move(defaultValue_)),
+ propertyName(std::move(propertyName_))
+ {}
+
+ EvaluationResult evaluate(const EvaluationContext& context) const final {
+ using Object = std::unordered_map<std::string, expression::Value>;
+ if (context.formattedSection &&
+ context.formattedSection->is<Object>()) {
+ const auto& section = context.formattedSection->get<Object>();
+ if (section.find(propertyName) != section.end()) {
+ return section.at(propertyName);
+ }
+ }
+ return defaultValue.evaluate(*context.feature, *context.zoom, T());
+ }
+
+ void eachChild(const std::function<void(const Expression&)>& fn) const final {
+ defaultValue.match([&fn] (const style::PropertyExpression<T>& e) { fn(e.getExpression()); },
+ [] (const T&) {});
+ }
+
+ bool operator==(const Expression& e) const final {
+ if (e.getKind() == Kind::FormatSectionOverride) {
+ const auto* other = static_cast<const FormatSectionOverride*>(&e);
+
+ if (getType() != other->getType() || propertyName != other->propertyName) {
+ return false;
+ }
+
+ // Check that default values or property expressions are equal.
+ return defaultValue.match(
+ [other] (const style::PropertyExpression<T>& thisExpr) {
+ return other->defaultValue.match([&thisExpr] (const style::PropertyExpression<T>& otherExpr) {
+ return thisExpr == otherExpr;
+ },
+ [] (const T&) {
+ return false;
+ });
+ },
+ [other] (const T& thisValue) {
+ return other->defaultValue.match([&thisValue] (const T& otherValue) {
+ return thisValue == otherValue;
+ },
+ [] (const style::PropertyExpression<T>&) {
+ return false;
+ });
+ });
+ }
+
+ return false;
+ }
+
+ std::vector<optional<Value>> possibleOutputs() const final {
+ return {nullopt};
+ }
+
+ std::string getOperator() const final { return "format-section-override"; }
+
+private:
+ PossiblyEvaluatedPropertyValue<T> defaultValue;
+ std::string propertyName;
+};
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/expression/formatted.hpp b/include/mbgl/style/expression/formatted.hpp
index 9e7e7308cb..f4f08e9197 100644
--- a/include/mbgl/style/expression/formatted.hpp
+++ b/include/mbgl/style/expression/formatted.hpp
@@ -1,9 +1,9 @@
#pragma once
#include <mbgl/style/conversion.hpp>
+#include <mbgl/util/color.hpp>
#include <mbgl/util/font_stack.hpp>
#include <mbgl/util/optional.hpp>
-#include <mbgl/util/variant.hpp>
#include <vector>
#include <string>
@@ -12,15 +12,25 @@ namespace mbgl {
namespace style {
namespace expression {
+extern const char* const kFormattedSectionFontScale;
+extern const char* const kFormattedSectionTextFont;
+extern const char* const kFormattedSectionTextColor;
+
struct FormattedSection {
- FormattedSection(std::string text_, optional<double> fontScale_, optional<FontStack> fontStack_)
+ FormattedSection(std::string text_,
+ optional<double> fontScale_,
+ optional<FontStack> fontStack_,
+ optional<Color> textColor_)
: text(std::move(text_))
, fontScale(std::move(fontScale_))
, fontStack(std::move(fontStack_))
+ , textColor(std::move(textColor_))
{}
+
std::string text;
optional<double> fontScale;
optional<FontStack> fontStack;
+ optional<Color> textColor;
};
class Formatted {
@@ -28,7 +38,7 @@ public:
Formatted() = default;
Formatted(const char* plainU8String) {
- sections.emplace_back(std::string(plainU8String), nullopt, nullopt);
+ sections.emplace_back(std::string(plainU8String), nullopt, nullopt, nullopt);
}
Formatted(std::vector<FormattedSection> sections_)
diff --git a/include/mbgl/style/property_expression.hpp b/include/mbgl/style/property_expression.hpp
index b198de02b2..32983e2380 100644
--- a/include/mbgl/style/property_expression.hpp
+++ b/include/mbgl/style/property_expression.hpp
@@ -1,7 +1,6 @@
#pragma once
#include <mbgl/style/expression/expression.hpp>
-#include <mbgl/style/expression/value.hpp>
#include <mbgl/style/expression/is_constant.hpp>
#include <mbgl/style/expression/interpolate.hpp>
#include <mbgl/style/expression/step.hpp>
@@ -11,46 +10,38 @@
namespace mbgl {
namespace style {
-template <class T>
-class PropertyExpression {
+class PropertyExpressionBase {
public:
- // Second parameter to be used only for conversions from legacy functions.
- PropertyExpression(std::unique_ptr<expression::Expression> expression_, optional<T> defaultValue_ = {})
- : expression(std::move(expression_)),
- defaultValue(std::move(defaultValue_)),
- zoomCurve(expression::findZoomCurveChecked(expression.get())) {
- }
+ explicit PropertyExpressionBase(std::unique_ptr<expression::Expression>);
- bool isZoomConstant() const { return expression::isZoomConstant(*expression); }
- bool isFeatureConstant() const { return expression::isFeatureConstant(*expression); }
+ bool isZoomConstant() const noexcept;
+ bool isFeatureConstant() const noexcept;
+ bool canEvaluateWith(const expression::EvaluationContext&) 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;
- T evaluate(float zoom) const {
- assert(!expression::isZoomConstant(*expression));
- assert(expression::isFeatureConstant(*expression));
- const expression::EvaluationResult result = expression->evaluate(expression::EvaluationContext(zoom, nullptr));
- if (result) {
- const optional<T> typed = expression::fromExpressionValue<T>(*result);
- return typed ? *typed : defaultValue ? *defaultValue : T();
- }
- return defaultValue ? *defaultValue : T();
- }
+ bool useIntegerZoom = false;
- template <class Feature>
- T evaluate(const Feature& feature, T finalDefaultValue) const {
- assert(expression::isZoomConstant(*expression));
- assert(!expression::isFeatureConstant(*expression));
- const expression::EvaluationResult result = expression->evaluate(expression::EvaluationContext(&feature));
- if (result) {
- const optional<T> typed = expression::fromExpressionValue<T>(*result);
- return typed ? *typed : defaultValue ? *defaultValue : finalDefaultValue;
- }
- return defaultValue ? *defaultValue : finalDefaultValue;
+protected:
+ std::shared_ptr<const expression::Expression> expression;
+ variant<std::nullptr_t, const expression::Interpolate*, const expression::Step*> zoomCurve;
+ bool isZoomConstant_;
+ bool isFeatureConstant_;
+};
+
+template <class T>
+class PropertyExpression final : public PropertyExpressionBase {
+public:
+ // Second parameter to be used only for conversions from legacy functions.
+ PropertyExpression(std::unique_ptr<expression::Expression> expression_, optional<T> defaultValue_ = nullopt)
+ : PropertyExpressionBase(std::move(expression_)),
+ defaultValue(std::move(defaultValue_)) {
}
- template <class Feature>
- T evaluate(float zoom, const Feature& feature, T finalDefaultValue) const {
- assert(!expression::isFeatureConstant(*expression));
- const expression::EvaluationResult result = expression->evaluate(expression::EvaluationContext({zoom}, &feature));
+ 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);
return typed ? *typed : defaultValue ? *defaultValue : finalDefaultValue;
@@ -58,59 +49,29 @@ public:
return defaultValue ? *defaultValue : finalDefaultValue;
}
- float interpolationFactor(const Range<float>& inputLevels, const float inputValue) const {
- return zoomCurve.match(
- [](std::nullptr_t) {
- assert(false);
- return 0.0f;
- },
- [&](const expression::Interpolate* z) {
- return z->interpolationFactor(Range<double> { inputLevels.min, inputLevels.max }, inputValue);
- },
- [&](const expression::Step*) {
- return 0.0f;
- }
- );
+ T evaluate(float zoom) const {
+ return evaluate(expression::EvaluationContext(zoom));
}
- Range<float> getCoveringStops(const float lower, const float upper) const {
- return zoomCurve.match(
- [](std::nullptr_t) {
- assert(false);
- return Range<float>(0.0f, 0.0f);
- },
- [&](auto z) {
- return z->getCoveringStops(lower, upper);
- }
- );
+ T evaluate(const GeometryTileFeature& feature, T finalDefaultValue) const {
+ return evaluate(expression::EvaluationContext(&feature), finalDefaultValue);
}
- // Return the range obtained by evaluating the function at each of the zoom levels in zoomRange
- template <class Feature>
- Range<T> evaluate(const Range<float>& zoomRange, const Feature& feature, T finalDefaultValue) {
- return Range<T> {
- evaluate(zoomRange.min, feature, finalDefaultValue),
- evaluate(zoomRange.max, feature, finalDefaultValue)
- };
+ T evaluate(float zoom, const GeometryTileFeature& feature, T finalDefaultValue) const {
+ return evaluate(expression::EvaluationContext(zoom, &feature), finalDefaultValue);
}
std::vector<optional<T>> possibleOutputs() const {
return expression::fromExpressionValues<T>(expression->possibleOutputs());
}
- const expression::Expression& getExpression() const { return *expression; }
-
- bool useIntegerZoom = false;
-
friend bool operator==(const PropertyExpression& lhs,
const PropertyExpression& rhs) {
return *lhs.expression == *rhs.expression;
}
private:
- std::shared_ptr<const expression::Expression> expression;
optional<T> defaultValue;
- variant<std::nullptr_t, const expression::Interpolate*, const expression::Step*> zoomCurve;
};
} // namespace style