summaryrefslogtreecommitdiff
path: root/src/mbgl/style/expression/format_expression.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mbgl/style/expression/format_expression.cpp')
-rw-r--r--src/mbgl/style/expression/format_expression.cpp134
1 files changed, 74 insertions, 60 deletions
diff --git a/src/mbgl/style/expression/format_expression.cpp b/src/mbgl/style/expression/format_expression.cpp
index 743942c769..201e189f41 100644
--- a/src/mbgl/style/expression/format_expression.cpp
+++ b/src/mbgl/style/expression/format_expression.cpp
@@ -6,21 +6,23 @@ namespace mbgl {
namespace style {
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>> textColor_)
- : text(std::move(text_))
-{
+FormatExpressionSection::FormatExpressionSection(std::unique_ptr<Expression> content_) : content(std::move(content_)) {}
+
+void FormatExpressionSection::setTextSectionOptions(optional<std::unique_ptr<Expression>> fontScale_,
+ optional<std::unique_ptr<Expression>> textFont_,
+ optional<std::unique_ptr<Expression>> textColor_) {
if (fontScale_) {
+ assert(*fontScale_);
fontScale = std::shared_ptr<Expression>(std::move(*fontScale_));
}
if (textFont_) {
+ assert(*textFont_);
textFont = std::shared_ptr<Expression>(std::move(*textFont_));
}
if (textColor_) {
+ assert(*textColor_);
textColor = std::shared_ptr<Expression>(std::move(*textColor_));
}
}
@@ -34,68 +36,69 @@ using namespace mbgl::style::conversion;
ParseResult FormatExpression::parse(const Convertible& value, ParsingContext& ctx) {
std::size_t argsLength = arrayLength(value);
- if (argsLength < 3) {
- ctx.error("Expected at least two arguments.");
+ if (argsLength < 2) {
+ ctx.error("Expected at least one argument.");
return ParseResult();
}
-
- if ((argsLength - 1) % 2 != 0) {
- ctx.error("Expected an even number of arguments.");
+
+ if (isObject(arrayMember(value, 1))) {
+ ctx.error("First argument must be an image or text section.");
return ParseResult();
}
-
+
std::vector<FormatExpressionSection> sections;
- for (std::size_t i = 1; i < argsLength - 1; i += 2) {
- auto textArg = arrayMember(value, i);
- ParseResult text = ctx.parse(textArg, 1, {type::Value});
- if (!text) {
- return ParseResult();
- }
- auto options = arrayMember(value, i + 1);
- if (!isObject(options)) {
- ctx.error("Format options argument must be an object.");
- return ParseResult();
- }
-
- const optional<Convertible> fontScaleOption = objectMember(options, kFormattedSectionFontScale);
- ParseResult fontScale;
- if (fontScaleOption) {
- fontScale = ctx.parse(*fontScaleOption, 1, {type::Number});
- if (!fontScale) {
- return ParseResult();
+ bool nextTokenMayBeObject = false;
+ for (std::size_t i = 1; i <= argsLength - 1; ++i) {
+ auto arg = arrayMember(value, i);
+
+ if (nextTokenMayBeObject && isObject(arg)) {
+ nextTokenMayBeObject = false;
+
+ const optional<Convertible> fontScaleOption = objectMember(arg, kFormattedSectionFontScale);
+ ParseResult fontScale;
+ if (fontScaleOption) {
+ fontScale = ctx.parse(*fontScaleOption, 1, {type::Number});
+ if (!fontScale) {
+ return ParseResult();
+ }
}
- }
-
- const optional<Convertible> textFontOption = objectMember(options, kFormattedSectionTextFont);
- ParseResult textFont;
- if (textFontOption) {
- textFont = ctx.parse(*textFontOption, 1, {type::Array(type::String)});
- if (!textFont) {
- return ParseResult();
+
+ const optional<Convertible> textFontOption = objectMember(arg, kFormattedSectionTextFont);
+ ParseResult textFont;
+ if (textFontOption) {
+ textFont = ctx.parse(*textFontOption, 1, {type::Array(type::String)});
+ if (!textFont) {
+ return ParseResult();
+ }
+ }
+ const optional<Convertible> textColorOption = objectMember(arg, kFormattedSectionTextColor);
+ ParseResult textColor;
+ if (textColorOption) {
+ textColor = ctx.parse(*textColorOption, 1, {type::Color});
+ if (!textColor) {
+ return ParseResult();
+ }
}
- }
- const optional<Convertible> textColorOption = objectMember(options, kFormattedSectionTextColor);
- ParseResult textColor;
- if (textColorOption) {
- textColor = ctx.parse(*textColorOption, 1, {type::Color});
- if (!textColor) {
+ sections.back().setTextSectionOptions(std::move(fontScale), std::move(textFont), std::move(textColor));
+ } else {
+ ParseResult parsedArg = ctx.parse(arg, 1, {type::Value});
+ if (!parsedArg) {
+ ctx.error("Cannot parse formatted section.");
return ParseResult();
}
- }
- sections.emplace_back(std::move(*text),
- std::move(fontScale),
- std::move(textFont),
- std::move(textColor));
+ nextTokenMayBeObject = true;
+ sections.emplace_back(std::move(*parsedArg));
+ }
}
-
+
return ParseResult(std::make_unique<FormatExpression>(std::move(sections)));
}
void FormatExpression::eachChild(const std::function<void(const Expression&)>& fn) const {
for (auto& section : sections) {
- fn(*section.text);
+ fn(*section.content);
if (section.fontScale) {
fn(**section.fontScale);
}
@@ -117,7 +120,7 @@ bool FormatExpression::operator==(const Expression& e) const {
for (std::size_t i = 0; i < sections.size(); i++) {
const auto& lhsSection = sections.at(i);
const auto& rhsSection = rhs->sections.at(i);
- if (*lhsSection.text != *rhsSection.text) {
+ if (*lhsSection.content != *rhsSection.content) {
return false;
}
if ((lhsSection.fontScale && (!rhsSection.fontScale || **lhsSection.fontScale != **rhsSection.fontScale)) ||
@@ -141,7 +144,7 @@ bool FormatExpression::operator==(const Expression& e) const {
mbgl::Value FormatExpression::serialize() const {
std::vector<mbgl::Value> serialized{{ getOperator() }};
for (const auto& section : sections) {
- serialized.push_back(section.text->serialize());
+ serialized.push_back(section.content->serialize());
std::unordered_map<std::string, mbgl::Value> options;
if (section.fontScale) {
options.emplace(kFormattedSectionFontScale, (*section.fontScale)->serialize());
@@ -160,14 +163,25 @@ mbgl::Value FormatExpression::serialize() const {
EvaluationResult FormatExpression::evaluate(const EvaluationContext& params) const {
std::vector<FormattedSection> evaluatedSections;
for (const auto& section : sections) {
- auto textResult = section.text->evaluate(params);
- if (!textResult) {
- return textResult.error();
+ auto contentResult = section.content->evaluate(params);
+ if (!contentResult) {
+ return contentResult.error();
}
-
- optional<std::string> evaluatedText = toString(*textResult);
- if (!evaluatedText) {
- return EvaluationError({ "Could not coerce format expression text input to string." });
+
+ optional<std::string> evaluatedText;
+ if (typeOf(*contentResult) == type::Image) {
+ const auto& image = contentResult->get<Image>();
+ // Omit sections with empty image ids.
+ if (!image.id().empty()) {
+ evaluatedSections.emplace_back(image);
+ }
+ // Continue evaluation of a next section, as the image section does not have section options.
+ continue;
+ } else {
+ evaluatedText = toString(*contentResult);
+ if (!evaluatedText) {
+ return EvaluationError({"Could not coerce format expression text input to string."});
+ }
}
optional<double> evaluatedFontScale;