summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Shalamov <alexander.shalamov@mapbox.com>2019-03-04 08:17:06 +0200
committerAlexander Shalamov <alexander.shalamov@mapbox.com>2019-03-04 08:17:06 +0200
commitc7c4f990366739e66bcea6ed8cb2539268527c43 (patch)
treeadfc76781deb9c48880ca412d130c24f29cd95e1
parent67a9dc35bf0c0113d429161be2c125e75981fb5d (diff)
downloadqtlocation-mapboxgl-c7c4f990366739e66bcea6ed8cb2539268527c43.tar.gz
[core] Add ["text-section"] expression
New expression evaluates to formatted section id (string | number) that can be used within decision expressions, such as 'match' or 'case', so that each formatted section can have different paint properties.
-rw-r--r--include/mbgl/style/expression/dsl.hpp1
-rw-r--r--include/mbgl/style/expression/expression.hpp15
-rw-r--r--include/mbgl/style/expression/format_expression.hpp15
-rw-r--r--include/mbgl/style/expression/formatted.hpp22
-rw-r--r--include/mbgl/style/property_expression.hpp103
-rw-r--r--src/core-files.json1
-rw-r--r--src/mbgl/style/conversion/function.cpp2
-rw-r--r--src/mbgl/style/expression/compound_expression.cpp11
-rw-r--r--src/mbgl/style/expression/dsl.cpp10
-rw-r--r--src/mbgl/style/expression/format_expression.cpp62
-rw-r--r--src/mbgl/style/expression/formatted.cpp42
-rw-r--r--src/mbgl/style/expression/is_constant.cpp9
-rw-r--r--src/mbgl/style/property_expression.cpp68
13 files changed, 240 insertions, 121 deletions
diff --git a/include/mbgl/style/expression/dsl.hpp b/include/mbgl/style/expression/dsl.hpp
index bd94a765e7..fcbca25941 100644
--- a/include/mbgl/style/expression/dsl.hpp
+++ b/include/mbgl/style/expression/dsl.hpp
@@ -82,6 +82,7 @@ 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> textSection();
} // namespace dsl
} // namespace expression
diff --git a/include/mbgl/style/expression/expression.hpp b/include/mbgl/style/expression/expression.hpp
index 97b143b3d9..d868b17e00 100644
--- a/include/mbgl/style/expression/expression.hpp
+++ b/include/mbgl/style/expression/expression.hpp
@@ -25,18 +25,25 @@ 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_) {}
+ 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;
+ const Value* formattedSection = nullptr;
};
template <typename T>
diff --git a/include/mbgl/style/expression/format_expression.hpp b/include/mbgl/style/expression/format_expression.hpp
index b00674a88e..09feaf4819 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>> sectionID_);
std::shared_ptr<Expression> text;
optional<std::shared_ptr<Expression>> fontScale;
optional<std::shared_ptr<Expression>> textFont;
+ optional<std::shared_ptr<Expression>> sectionID;
};
-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&);
@@ -42,9 +40,6 @@ public:
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/formatted.hpp b/include/mbgl/style/expression/formatted.hpp
index 9e7e7308cb..28964de941 100644
--- a/include/mbgl/style/expression/formatted.hpp
+++ b/include/mbgl/style/expression/formatted.hpp
@@ -12,15 +12,33 @@ namespace mbgl {
namespace style {
namespace expression {
+extern const char* const kFormattedSectionFontScale;
+extern const char* const kFormattedSectionTextFont;
+extern const char* const kFormattedSectionID;
+
+using FormattedSectionID = variant<double, std::string>;
+
+template<class Variant>
+optional<FormattedSectionID> toFormattedSectionID(const Variant& variant) {
+ return variant.match(
+ [] (double t) -> FormattedSectionID { return t; },
+ [] (const std::string& t) -> FormattedSectionID { return t;},
+ [] (auto&) -> optional<FormattedSectionID> { return nullopt; });
+}
+
struct FormattedSection {
- FormattedSection(std::string text_, optional<double> fontScale_, optional<FontStack> fontStack_)
+ FormattedSection(std::string text_, optional<double> fontScale_,
+ optional<FontStack> fontStack_, optional<FormattedSectionID> id_)
: text(std::move(text_))
, fontScale(std::move(fontScale_))
, fontStack(std::move(fontStack_))
+ , id(std::move(id_))
{}
+
std::string text;
optional<double> fontScale;
optional<FontStack> fontStack;
+ optional<FormattedSectionID> id;
};
class Formatted {
@@ -28,7 +46,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..43e80dfac4 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_ = {})
+ : 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
diff --git a/src/core-files.json b/src/core-files.json
index 42a30a3ea8..f27bd268bd 100644
--- a/src/core-files.json
+++ b/src/core-files.json
@@ -223,6 +223,7 @@
"src/mbgl/style/light.cpp",
"src/mbgl/style/light_impl.cpp",
"src/mbgl/style/parser.cpp",
+ "src/mbgl/style/property_expression.cpp",
"src/mbgl/style/source.cpp",
"src/mbgl/style/source_impl.cpp",
"src/mbgl/style/sources/custom_geometry_source.cpp",
diff --git a/src/mbgl/style/conversion/function.cpp b/src/mbgl/style/conversion/function.cpp
index 5877d0eb7c..79ad2fc7d8 100644
--- a/src/mbgl/style/conversion/function.cpp
+++ b/src/mbgl/style/conversion/function.cpp
@@ -41,7 +41,7 @@ bool hasTokens(const std::string& source) {
std::unique_ptr<Expression> convertTokenStringToFormatExpression(const std::string& source) {
auto textExpression = convertTokenStringToExpression(source);
std::vector<FormatExpressionSection> sections;
- sections.emplace_back(std::move(textExpression), nullopt, nullopt);
+ sections.emplace_back(std::move(textExpression), nullopt, nullopt, nullopt);
return std::make_unique<FormatExpression>(sections);
}
diff --git a/src/mbgl/style/expression/compound_expression.cpp b/src/mbgl/style/expression/compound_expression.cpp
index cc1d58025b..27dfe6c151 100644
--- a/src/mbgl/style/expression/compound_expression.cpp
+++ b/src/mbgl/style/expression/compound_expression.cpp
@@ -662,6 +662,16 @@ const auto& errorCompoundExpression() {
return signature;
}
+const auto& textSectionCompoundExpression() {
+ static auto signature = detail::makeSignature("text-section", [](const EvaluationContext& params) -> Result<Value> {
+ if (!params.formattedSection) {
+ return EvaluationError {"Formatted section is unavailable in the current evaluation context."};
+ }
+ return *params.formattedSection;
+ });
+ return signature;
+}
+
// Legacy Filters
const auto& filterEqualsCompoundExpression() {
static auto signature = detail::makeSignature("filter-==", [](const EvaluationContext& params, const std::string& key, const Value &lhs) -> Result<bool> {
@@ -907,6 +917,7 @@ MAPBOX_ETERNAL_CONSTEXPR const auto compoundExpressionRegistry = mapbox::eternal
{ "concat", concatCompoundExpression },
{ "resolved-locale", resolvedLocaleCompoundExpression },
{ "error", errorCompoundExpression },
+ { "text-section", textSectionCompoundExpression },
// Legacy Filters
{ "filter-==", filterEqualsCompoundExpression },
{ "filter-id-==", filterIdEqualsCompoundExpression },
diff --git a/src/mbgl/style/expression/dsl.cpp b/src/mbgl/style/expression/dsl.cpp
index f5ff83a9e7..f999c90b07 100644
--- a/src/mbgl/style/expression/dsl.cpp
+++ b/src/mbgl/style/expression/dsl.cpp
@@ -189,13 +189,17 @@ std::unique_ptr<Expression> concat(std::vector<std::unique_ptr<Expression>> inpu
std::unique_ptr<Expression> format(const char* value) {
return std::make_unique<Literal>(Formatted(value));
}
-
+
std::unique_ptr<Expression> format(std::unique_ptr<Expression> input) {
std::vector<FormatExpressionSection> sections;
- sections.emplace_back(std::move(input), nullopt, nullopt);
+ sections.emplace_back(std::move(input), nullopt, nullopt, nullopt);
return std::make_unique<FormatExpression>(sections);
}
-
+
+std::unique_ptr<Expression> textSection() {
+ return compound("text-section");
+}
+
} // namespace dsl
} // namespace expression
} // namespace style
diff --git a/src/mbgl/style/expression/format_expression.cpp b/src/mbgl/style/expression/format_expression.cpp
index 144df4b160..57204313b4 100644
--- a/src/mbgl/style/expression/format_expression.cpp
+++ b/src/mbgl/style/expression/format_expression.cpp
@@ -1,8 +1,6 @@
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/style/expression/format_expression.hpp>
-#include <mbgl/style/expression/literal.hpp>
-#include <mbgl/util/font_stack.hpp>
-#include <mbgl/util/string.hpp>
+#include <mbgl/style/expression/formatted.hpp>
namespace mbgl {
namespace style {
@@ -10,15 +8,21 @@ namespace expression {
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>> sectionID_)
: text(std::move(text_))
{
if (fontScale_) {
fontScale = std::shared_ptr<Expression>(std::move(*fontScale_));
}
+
if (textFont_) {
textFont = std::shared_ptr<Expression>(std::move(*textFont_));
}
+
+ if (sectionID_) {
+ sectionID = std::shared_ptr<Expression>(std::move(*sectionID_));
+ }
}
FormatExpression::FormatExpression(std::vector<FormatExpressionSection> sections_)
@@ -53,7 +57,7 @@ ParseResult FormatExpression::parse(const Convertible& value, ParsingContext& ct
return ParseResult();
}
- const optional<Convertible> fontScaleOption = objectMember(options, "font-scale");
+ const optional<Convertible> fontScaleOption = objectMember(options, kFormattedSectionFontScale);
ParseResult fontScale;
if (fontScaleOption) {
fontScale = ctx.parse(*fontScaleOption, 1, {type::Number});
@@ -62,7 +66,7 @@ ParseResult FormatExpression::parse(const Convertible& value, ParsingContext& ct
}
}
- const optional<Convertible> textFontOption = objectMember(options, "text-font");
+ const optional<Convertible> textFontOption = objectMember(options, kFormattedSectionTextFont);
ParseResult textFont;
if (textFontOption) {
textFont = ctx.parse(*textFontOption, 1, {type::Array(type::String)});
@@ -70,7 +74,20 @@ ParseResult FormatExpression::parse(const Convertible& value, ParsingContext& ct
return ParseResult();
}
}
- sections.emplace_back(std::move(*text), std::move(fontScale), std::move(textFont));
+
+ const optional<Convertible> sectionIDOption = objectMember(options, kFormattedSectionID);
+ ParseResult sectionID;
+ if (sectionIDOption) {
+ sectionID = ctx.parse(*sectionIDOption, 1, {type::Value});
+ if (!sectionID) {
+ return ParseResult();
+ }
+ }
+
+ sections.emplace_back(std::move(*text),
+ std::move(fontScale),
+ std::move(textFont),
+ std::move(sectionID));
}
return ParseResult(std::make_unique<FormatExpression>(std::move(sections)));
@@ -85,6 +102,9 @@ void FormatExpression::eachChild(const std::function<void(const Expression&)>& f
if (section.textFont) {
fn(**section.textFont);
}
+ if (section.sectionID) {
+ fn(**section.sectionID);
+ }
}
}
@@ -108,6 +128,10 @@ bool FormatExpression::operator==(const Expression& e) const {
(!lhsSection.textFont && rhsSection.textFont)) {
return false;
}
+ if ((lhsSection.sectionID && (!rhsSection.sectionID || **lhsSection.sectionID != **rhsSection.sectionID)) ||
+ (!lhsSection.sectionID && rhsSection.sectionID)) {
+ return false;
+ }
}
return true;
}
@@ -115,15 +139,18 @@ bool FormatExpression::operator==(const Expression& e) const {
}
mbgl::Value FormatExpression::serialize() const {
- std::vector<mbgl::Value> serialized{{ std::string("format") }};
+ std::vector<mbgl::Value> serialized{{ getOperator() }};
for (const auto& section : sections) {
serialized.push_back(section.text->serialize());
std::unordered_map<std::string, mbgl::Value> options;
if (section.fontScale) {
- options.emplace("font-scale", (*section.fontScale)->serialize());
+ options.emplace(kFormattedSectionFontScale, (*section.fontScale)->serialize());
}
if (section.textFont) {
- options.emplace("text-font", (*section.textFont)->serialize());
+ options.emplace(kFormattedSectionTextFont, (*section.textFont)->serialize());
+ }
+ if (section.sectionID) {
+ options.emplace(kFormattedSectionID, (*section.sectionID)->serialize());
}
serialized.push_back(options);
}
@@ -164,7 +191,20 @@ EvaluationResult FormatExpression::evaluate(const EvaluationContext& params) con
}
evaluatedTextFont = *textFontValue;
}
- evaluatedSections.emplace_back(*evaluatedText, evaluatedFontScale, evaluatedTextFont);
+
+ optional<FormattedSectionID> evaluatedID;
+ if (section.sectionID) {
+ auto sectionIDResult = (*section.sectionID)->evaluate(params);
+ if (!sectionIDResult) {
+ return sectionIDResult.error();
+ }
+
+ evaluatedID = toFormattedSectionID(*sectionIDResult);
+ if (!evaluatedID) {
+ return EvaluationError { "Format section id option must evaluate to string or number" };
+ }
+ }
+ evaluatedSections.emplace_back(*evaluatedText, evaluatedFontScale, evaluatedTextFont, evaluatedID);
}
return Formatted(evaluatedSections);
}
diff --git a/src/mbgl/style/expression/formatted.cpp b/src/mbgl/style/expression/formatted.cpp
index 8232d0c698..fef834b20c 100644
--- a/src/mbgl/style/expression/formatted.cpp
+++ b/src/mbgl/style/expression/formatted.cpp
@@ -1,18 +1,15 @@
#include <mbgl/style/expression/formatted.hpp>
#include <mbgl/style/conversion_impl.hpp>
-#include <mbgl/style/expression/is_constant.hpp>
-#include <mbgl/style/expression/is_expression.hpp>
-#include <mbgl/style/expression/literal.hpp>
-#include <mbgl/style/expression/expression.hpp>
-#include <mbgl/style/expression/type.hpp>
-#include <mbgl/style/expression/compound_expression.hpp>
-#include <mbgl/style/expression/boolean_operator.hpp>
+#include <mbgl/style/conversion/constant.hpp>
namespace mbgl {
namespace style {
-
namespace expression {
+const char* const kFormattedSectionFontScale = "font-scale";
+const char* const kFormattedSectionTextFont = "text-font";
+const char* const kFormattedSectionID = "id";
+
bool Formatted::operator==(const Formatted& other) const {
if (other.sections.size() != sections.size()) {
return false;
@@ -22,14 +19,14 @@ bool Formatted::operator==(const Formatted& other) const {
const auto& otherSection = other.sections.at(i);
if (thisSection.text != otherSection.text ||
thisSection.fontScale != otherSection.fontScale ||
- thisSection.fontStack != otherSection.fontStack) {
+ thisSection.fontStack != otherSection.fontStack ||
+ thisSection.id != otherSection.id) {
return false;
}
}
return true;
}
-
-
+
std::string Formatted::toString() const {
std::string result;
for (const auto& section : sections) {
@@ -37,7 +34,7 @@ std::string Formatted::toString() const {
}
return result;
}
-
+
} // namespace expression
namespace conversion {
@@ -65,6 +62,7 @@ optional<Formatted> Converter<Formatted>::operator()(const Convertible& value, E
optional<double> fontScale;
optional<FontStack> textFont;
+ optional<FormattedSectionID> id;
if (sectionLength > 1) {
Convertible sectionParams = arrayMember(section, 1);
if (!isObject(sectionParams)) {
@@ -72,12 +70,12 @@ optional<Formatted> Converter<Formatted>::operator()(const Convertible& value, E
return nullopt;
}
- optional<Convertible> fontScaleMember = objectMember(sectionParams, "font-scale");
+ optional<Convertible> fontScaleMember = objectMember(sectionParams, kFormattedSectionFontScale);
if (fontScaleMember) {
fontScale = toDouble(*fontScaleMember);
}
- optional<Convertible> textFontMember = objectMember(sectionParams, "text-font");
+ optional<Convertible> textFontMember = objectMember(sectionParams, kFormattedSectionTextFont);
if (textFontMember) {
if (isArray(*textFontMember)) {
std::vector<std::string> fontsVector;
@@ -96,9 +94,23 @@ optional<Formatted> Converter<Formatted>::operator()(const Convertible& value, E
return nullopt;
}
}
+
+ optional<Convertible> sectionIDMember = objectMember(sectionParams, kFormattedSectionID);
+ if (sectionIDMember) {
+ auto result = toValue(*sectionIDMember);
+ if (!result) {
+ return nullopt;
+ }
+
+ id = toFormattedSectionID(*result);
+ if (!id) {
+ error.message = "Section id has to be a string or a number.";
+ return nullopt;
+ }
+ }
}
- sections.push_back(FormattedSection(*sectionText, fontScale, textFont));
+ sections.push_back(FormattedSection(*sectionText, fontScale, textFont, id));
}
return Formatted(sections);
} else if (optional<std::string> result = toString(value)) {
diff --git a/src/mbgl/style/expression/is_constant.cpp b/src/mbgl/style/expression/is_constant.cpp
index 3b20f49a86..8ac362373c 100644
--- a/src/mbgl/style/expression/is_constant.cpp
+++ b/src/mbgl/style/expression/is_constant.cpp
@@ -17,15 +17,16 @@ bool isFeatureConstant(const Expression& expression) {
return false;
} else if (name == "has" && parameterCount && *parameterCount == 1) {
return false;
- } else if (0 == name.rfind(filter, 0)) {
- // Legacy filters begin with "filter-" and are never constant.
- return false;
} else if (
name == "properties" ||
name == "geometry-type" ||
- name == "id"
+ name == "id" ||
+ name == "text-section"
) {
return false;
+ } else if (0 == name.rfind(filter, 0)) {
+ // Legacy filters begin with "filter-" and are never constant.
+ return false;
}
}
diff --git a/src/mbgl/style/property_expression.cpp b/src/mbgl/style/property_expression.cpp
new file mode 100644
index 0000000000..6ba0416ad3
--- /dev/null
+++ b/src/mbgl/style/property_expression.cpp
@@ -0,0 +1,68 @@
+#include <mbgl/style/property_expression.hpp>
+
+namespace mbgl {
+namespace style {
+
+PropertyExpressionBase::PropertyExpressionBase(std::unique_ptr<expression::Expression> expression_)
+ : expression(std::move(expression_)),
+ zoomCurve(expression::findZoomCurveChecked(expression.get())) {
+ isZoomConstant_ = expression::isZoomConstant(*expression);
+ isFeatureConstant_ = expression::isFeatureConstant(*expression);
+}
+
+bool PropertyExpressionBase::isZoomConstant() const noexcept {
+ return isZoomConstant_;
+}
+
+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;
+}
+
+float PropertyExpressionBase::interpolationFactor(const Range<float>& inputLevels, const float inputValue) const noexcept {
+ 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;
+ }
+ );
+}
+
+Range<float> PropertyExpressionBase::getCoveringStops(const float lower, const float upper) const noexcept {
+ return zoomCurve.match(
+ [](std::nullptr_t) {
+ assert(false);
+ return Range<float>(0.0f, 0.0f);
+ },
+ [&](auto z) {
+ return z->getCoveringStops(lower, upper);
+ }
+ );
+}
+
+const expression::Expression& PropertyExpressionBase::getExpression() const noexcept {
+ return *expression;
+}
+
+} // namespace style
+} // namespace mbgl