summaryrefslogtreecommitdiff
path: root/src/mbgl/style
diff options
context:
space:
mode:
Diffstat (limited to 'src/mbgl/style')
-rw-r--r--src/mbgl/style/conversion/function.cpp20
-rw-r--r--src/mbgl/style/conversion/property_value.cpp1
-rw-r--r--src/mbgl/style/conversion/stringify.hpp11
-rw-r--r--src/mbgl/style/expression/check_subtype.cpp1
-rw-r--r--src/mbgl/style/expression/coercion.cpp30
-rw-r--r--src/mbgl/style/expression/dsl.cpp15
-rw-r--r--src/mbgl/style/expression/format_expression.cpp175
-rw-r--r--src/mbgl/style/expression/formatted.cpp61
-rw-r--r--src/mbgl/style/expression/parsing_context.cpp4
-rw-r--r--src/mbgl/style/expression/value.cpp35
-rw-r--r--src/mbgl/style/layers/symbol_layer.cpp31
-rw-r--r--src/mbgl/style/layers/symbol_layer_properties.hpp4
12 files changed, 368 insertions, 20 deletions
diff --git a/src/mbgl/style/conversion/function.cpp b/src/mbgl/style/conversion/function.cpp
index 69fb0725d8..34ac52ec1b 100644
--- a/src/mbgl/style/conversion/function.cpp
+++ b/src/mbgl/style/conversion/function.cpp
@@ -6,6 +6,7 @@
#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/util/string.hpp>
#include <cassert>
@@ -36,6 +37,13 @@ bool hasTokens(const std::string& source) {
return false;
}
+
+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);
+ return std::make_unique<FormatExpression>(sections);
+}
std::unique_ptr<Expression> convertTokenStringToExpression(const std::string& source) {
std::vector<std::unique_ptr<Expression>> inputs;
@@ -138,6 +146,9 @@ 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);
// 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
@@ -280,6 +291,15 @@ static optional<std::unique_ptr<Expression>> convertLiteral(type::Type type, con
[&] (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>> {
+ auto result = convert<std::string>(value, error);
+ if (!result) {
+ return nullopt;
+ }
+ return convertTokens ?
+ convertTokenStringToFormatExpression(*result) :
+ literal(Formatted(result->c_str()));
}
);
}
diff --git a/src/mbgl/style/conversion/property_value.cpp b/src/mbgl/style/conversion/property_value.cpp
index 3b79ecc0db..ff038908b6 100644
--- a/src/mbgl/style/conversion/property_value.cpp
+++ b/src/mbgl/style/conversion/property_value.cpp
@@ -78,6 +78,7 @@ template optional<PropertyValue<SymbolZOrderType>> Converter<PropertyValue<Symbo
template optional<PropertyValue<TextJustifyType>> Converter<PropertyValue<TextJustifyType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
template optional<PropertyValue<TextTransformType>> Converter<PropertyValue<TextTransformType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
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;
} // namespace conversion
} // namespace style
diff --git a/src/mbgl/style/conversion/stringify.hpp b/src/mbgl/style/conversion/stringify.hpp
index 3d188b6390..c5cd52093f 100644
--- a/src/mbgl/style/conversion/stringify.hpp
+++ b/src/mbgl/style/conversion/stringify.hpp
@@ -2,6 +2,8 @@
#include <mbgl/style/filter.hpp>
#include <mbgl/style/property_value.hpp>
+#include <mbgl/style/expression/value.hpp>
+#include <mbgl/style/expression/formatted.hpp>
#include <mbgl/util/enum.hpp>
#include <mbgl/util/color.hpp>
#include <mbgl/util/feature.hpp>
@@ -129,6 +131,15 @@ void stringify(Writer& writer, const Filter& filter) {
if (!filter.expression) writer.Null();
else stringify(writer, (*filter.expression)->serialize());
}
+
+
+template <class Writer>
+void stringify(Writer& writer, const expression::Formatted& v) {
+ // Convert to mbgl::Value and then use the existing stringify
+ // Serialization strategy for Formatted objects is to return the constant
+ // expression that would generate them.
+ stringify(writer, expression::ValueConverter<mbgl::Value>::fromExpressionValue(v));
+}
template <class Writer>
void stringify(Writer& writer, const Undefined&) {
diff --git a/src/mbgl/style/expression/check_subtype.cpp b/src/mbgl/style/expression/check_subtype.cpp
index 73f7d18a34..73e6e3bff7 100644
--- a/src/mbgl/style/expression/check_subtype.cpp
+++ b/src/mbgl/style/expression/check_subtype.cpp
@@ -40,6 +40,7 @@ optional<std::string> checkSubtype(const Type& expected, const Type& t) {
String,
Object,
Color,
+ Formatted,
Array(Value)
};
diff --git a/src/mbgl/style/expression/coercion.cpp b/src/mbgl/style/expression/coercion.cpp
index 4a17895991..75a6056081 100644
--- a/src/mbgl/style/expression/coercion.cpp
+++ b/src/mbgl/style/expression/coercion.cpp
@@ -82,6 +82,10 @@ EvaluationResult toColor(const Value& colorValue) {
);
}
+EvaluationResult toFormatted(const Value& formattedValue) {
+ return Formatted(toString(formattedValue).c_str());
+}
+
Coercion::Coercion(type::Type type_, std::vector<std::unique_ptr<Expression>> inputs_) :
Expression(Kind::Coercion, std::move(type_)),
inputs(std::move(inputs_))
@@ -96,11 +100,26 @@ Coercion::Coercion(type::Type type_, std::vector<std::unique_ptr<Expression>> in
coerceSingleValue = toNumber;
} else if (t.is<type::StringType>()) {
coerceSingleValue = [] (const Value& v) -> EvaluationResult { return toString(v); };
+ } else if (t.is<type::FormattedType>()) {
+ coerceSingleValue = toFormatted;
} else {
assert(false);
}
}
+mbgl::Value Coercion::serialize() const {
+ if (getType().is<type::FormattedType>()) {
+ // Since there's no explicit "to-formatted" coercion, the only coercions should be created
+ // by string expressions that get implicitly coerced to "formatted".
+ std::vector<mbgl::Value> serialized{{ std::string("format") }};
+ serialized.push_back(inputs[0]->serialize());
+ serialized.push_back(std::unordered_map<std::string, mbgl::Value>());
+ return serialized;
+ } else {
+ return Expression::serialize();
+ }
+};
+
std::string Coercion::getOperator() const {
return getType().match(
[](const type::BooleanType&) { return "to-boolean"; },
@@ -129,10 +148,16 @@ 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) && length != 2) {
+ if ((it->second == type::Boolean || it->second == type::String || it->second == type::Formatted) && 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
+ * arguments, only evaluating one at a time until one succeeds.
+ */
std::vector<std::unique_ptr<Expression>> parsed;
parsed.reserve(length - 1);
@@ -186,6 +211,3 @@ std::vector<optional<Value>> Coercion::possibleOutputs() const {
} // namespace expression
} // namespace style
} // namespace mbgl
-
-
-
diff --git a/src/mbgl/style/expression/dsl.cpp b/src/mbgl/style/expression/dsl.cpp
index c6318fb637..f5ff83a9e7 100644
--- a/src/mbgl/style/expression/dsl.cpp
+++ b/src/mbgl/style/expression/dsl.cpp
@@ -7,6 +7,7 @@
#include <mbgl/style/expression/step.hpp>
#include <mbgl/style/expression/interpolate.hpp>
#include <mbgl/style/expression/compound_expression.hpp>
+#include <mbgl/style/expression/format_expression.hpp>
namespace mbgl {
namespace style {
@@ -77,6 +78,10 @@ std::unique_ptr<Expression> toString(std::unique_ptr<Expression> value) {
return std::make_unique<Coercion>(type::String, vec(std::move(value)));
}
+std::unique_ptr<Expression> toFormatted(std::unique_ptr<Expression> value) {
+ return std::make_unique<Coercion>(type::Formatted, vec(std::move(value)));
+}
+
std::unique_ptr<Expression> get(const char* value) {
return get(literal(value));
}
@@ -181,6 +186,16 @@ std::unique_ptr<Expression> concat(std::vector<std::unique_ptr<Expression>> inpu
return compound("concat", std::move(inputs));
}
+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);
+ return std::make_unique<FormatExpression>(sections);
+}
+
} // namespace dsl
} // namespace expression
} // namespace style
diff --git a/src/mbgl/style/expression/format_expression.cpp b/src/mbgl/style/expression/format_expression.cpp
new file mode 100644
index 0000000000..144df4b160
--- /dev/null
+++ b/src/mbgl/style/expression/format_expression.cpp
@@ -0,0 +1,175 @@
+#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>
+
+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_)
+ : text(std::move(text_))
+{
+ if (fontScale_) {
+ fontScale = std::shared_ptr<Expression>(std::move(*fontScale_));
+ }
+ if (textFont_) {
+ textFont = std::shared_ptr<Expression>(std::move(*textFont_));
+ }
+}
+
+FormatExpression::FormatExpression(std::vector<FormatExpressionSection> sections_)
+ : Expression(Kind::FormatExpression, type::Formatted)
+ , sections(std::move(sections_))
+{}
+
+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.");
+ return ParseResult();
+ }
+
+ if ((argsLength - 1) % 2 != 0) {
+ ctx.error("Expected an even number of arguments.");
+ 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, "font-scale");
+ ParseResult fontScale;
+ if (fontScaleOption) {
+ fontScale = ctx.parse(*fontScaleOption, 1, {type::Number});
+ if (!fontScale) {
+ return ParseResult();
+ }
+ }
+
+ const optional<Convertible> textFontOption = objectMember(options, "text-font");
+ ParseResult textFont;
+ if (textFontOption) {
+ textFont = ctx.parse(*textFontOption, 1, {type::Array(type::String)});
+ if (!textFont) {
+ return ParseResult();
+ }
+ }
+ sections.emplace_back(std::move(*text), std::move(fontScale), std::move(textFont));
+ }
+
+ 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);
+ if (section.fontScale) {
+ fn(**section.fontScale);
+ }
+ if (section.textFont) {
+ fn(**section.textFont);
+ }
+ }
+}
+
+bool FormatExpression::operator==(const Expression& e) const {
+ if (e.getKind() == Kind::FormatExpression) {
+ auto rhs = static_cast<const FormatExpression*>(&e);
+ if (sections.size() != rhs->sections.size()) {
+ return false;
+ }
+ 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) {
+ return false;
+ }
+ if ((lhsSection.fontScale && (!rhsSection.fontScale || **lhsSection.fontScale != **rhsSection.fontScale)) ||
+ (!lhsSection.fontScale && rhsSection.fontScale)) {
+ return false;
+ }
+ if ((lhsSection.textFont && (!rhsSection.textFont || **lhsSection.textFont != **rhsSection.textFont)) ||
+ (!lhsSection.textFont && rhsSection.textFont)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+mbgl::Value FormatExpression::serialize() const {
+ std::vector<mbgl::Value> serialized{{ std::string("format") }};
+ 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());
+ }
+ if (section.textFont) {
+ options.emplace("text-font", (*section.textFont)->serialize());
+ }
+ serialized.push_back(options);
+ }
+ return serialized;
+}
+
+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();
+ }
+
+ optional<std::string> evaluatedText = toString(*textResult);
+ if (!evaluatedText) {
+ return EvaluationError({ "Could not coerce format expression text input to string." });
+ }
+
+ optional<double> evaluatedFontScale;
+ if (section.fontScale) {
+ auto fontScaleResult = (*section.fontScale)->evaluate(params);
+ if (!fontScaleResult) {
+ return fontScaleResult.error();
+ }
+ evaluatedFontScale = fontScaleResult->get<double>();
+ }
+
+ optional<FontStack> evaluatedTextFont;
+ if (section.textFont) {
+ auto textFontResult = (*section.textFont)->evaluate(params);
+ if (!textFontResult) {
+ return textFontResult.error();
+ }
+ auto textFontValue = ValueConverter<std::vector<std::string>>::fromExpressionValue(*textFontResult);
+ if (!textFontValue) {
+ return EvaluationError { "Format text-font option must evaluate to an array of strings" };
+ }
+ evaluatedTextFont = *textFontValue;
+ }
+ evaluatedSections.emplace_back(*evaluatedText, evaluatedFontScale, evaluatedTextFont);
+ }
+ return Formatted(evaluatedSections);
+}
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
+
diff --git a/src/mbgl/style/expression/formatted.cpp b/src/mbgl/style/expression/formatted.cpp
new file mode 100644
index 0000000000..6eb106dfec
--- /dev/null
+++ b/src/mbgl/style/expression/formatted.cpp
@@ -0,0 +1,61 @@
+#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>
+
+namespace mbgl {
+namespace style {
+
+namespace expression {
+
+bool Formatted::operator==(const Formatted& other) const {
+ if (other.sections.size() != sections.size()) {
+ return false;
+ }
+ for (std::size_t i = 0; i < sections.size(); i++) {
+ const auto& thisSection = sections.at(i);
+ const auto& otherSection = other.sections.at(i);
+ if (thisSection.text != otherSection.text ||
+ thisSection.fontScale != otherSection.fontScale ||
+ thisSection.fontStack != otherSection.fontStack) {
+ return false;
+ }
+ }
+ return true;
+}
+
+
+std::string Formatted::toString() const {
+ std::string result;
+ for (const auto& section : sections) {
+ result += section.text;
+ }
+ return result;
+}
+
+} // namespace expression
+
+namespace conversion {
+
+using namespace mbgl::style::expression;
+
+optional<Formatted> Converter<Formatted>::operator()(const Convertible& value, Error&) const {
+ using namespace mbgl::style::expression;
+
+ auto result = toString(value);
+ if (result) {
+ return Formatted(result->c_str());
+ } else {
+ return nullopt;
+ }
+}
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
+
diff --git a/src/mbgl/style/expression/parsing_context.cpp b/src/mbgl/style/expression/parsing_context.cpp
index 0373b9721f..34fbc5c380 100644
--- a/src/mbgl/style/expression/parsing_context.cpp
+++ b/src/mbgl/style/expression/parsing_context.cpp
@@ -13,6 +13,7 @@
#include <mbgl/style/expression/coercion.hpp>
#include <mbgl/style/expression/compound_expression.hpp>
#include <mbgl/style/expression/comparison.hpp>
+#include <mbgl/style/expression/format_expression.hpp>
#include <mbgl/style/expression/interpolate.hpp>
#include <mbgl/style/expression/length.hpp>
#include <mbgl/style/expression/let.hpp>
@@ -110,6 +111,7 @@ const ExpressionRegistry& getExpressionRegistry() {
{"case", Case::parse},
{"coalesce", Coalesce::parse},
{"collator", CollatorExpression::parse},
+ {"format", FormatExpression::parse},
{"interpolate", parseInterpolate},
{"length", Length::parse},
{"let", Let::parse},
@@ -183,7 +185,7 @@ 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 && (actual == type::Value || actual == type::String)) {
+ } else if ((*expected == type::Color || *expected == type::Formatted) && (actual == type::Value || actual == type::String)) {
parsed = { annotate(std::move(*parsed), *expected, typeAnnotationOption.value_or(TypeAnnotationOption::coerce)) };
} else {
checkType((*parsed)->getType());
diff --git a/src/mbgl/style/expression/value.cpp b/src/mbgl/style/expression/value.cpp
index 4bac8116c2..436ed83ecd 100644
--- a/src/mbgl/style/expression/value.cpp
+++ b/src/mbgl/style/expression/value.cpp
@@ -1,6 +1,7 @@
#include <rapidjson/writer.h>
#include <rapidjson/stringbuffer.h>
#include <mbgl/style/expression/value.hpp>
+#include <mbgl/style/conversion/stringify.hpp>
namespace mbgl {
namespace style {
@@ -13,6 +14,7 @@ type::Type typeOf(const Value& value) {
[&](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 {
@@ -38,6 +40,7 @@ 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_); }
);
@@ -58,6 +61,12 @@ void writeJSON(rapidjson::Writer<rapidjson::StringBuffer>& writer, const Value&
// 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) {
@@ -136,6 +145,31 @@ mbgl::Value ValueConverter<mbgl::Value>::fromExpressionValue(const Value& value)
assert(false);
return 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;
+ static std::string formatOperator("format");
+ serialized.emplace_back(formatOperator);
+ for (const auto& section : formatted.sections) {
+ serialized.emplace_back(section.text);
+ std::unordered_map<std::string, mbgl::Value> options;
+
+ if (section.fontScale) {
+ options.emplace("font-scale", *section.fontScale);
+ }
+
+ if (section.fontStack) {
+ std::vector<mbgl::Value> fontStack;
+ for (const auto& font : *section.fontStack) {
+ fontStack.emplace_back(font);
+ }
+ options.emplace("text-font", std::vector<mbgl::Value>{ std::string("literal"), fontStack });
+ }
+ serialized.push_back(options);
+ }
+ return serialized;
+ },
[&](const std::vector<Value>& values)->mbgl::Value {
std::vector<mbgl::Value> converted;
converted.reserve(values.size());
@@ -262,6 +296,7 @@ template <> type::Type valueTypeToExpressionType<double>() { return type::Number
template <> type::Type valueTypeToExpressionType<std::string>() { return type::String; }
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<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/symbol_layer.cpp b/src/mbgl/style/layers/symbol_layer.cpp
index c116d5b7e9..848678b5f1 100644
--- a/src/mbgl/style/layers/symbol_layer.cpp
+++ b/src/mbgl/style/layers/symbol_layer.cpp
@@ -421,15 +421,15 @@ void SymbolLayer::setTextRotationAlignment(PropertyValue<AlignmentType> value) {
baseImpl = std::move(impl_);
observer->onLayerChanged(*this);
}
-PropertyValue<std::string> SymbolLayer::getDefaultTextField() {
+PropertyValue<expression::Formatted> SymbolLayer::getDefaultTextField() {
return TextField::defaultValue();
}
-PropertyValue<std::string> SymbolLayer::getTextField() const {
+PropertyValue<expression::Formatted> SymbolLayer::getTextField() const {
return impl().layout.get<TextField>();
}
-void SymbolLayer::setTextField(PropertyValue<std::string> value) {
+void SymbolLayer::setTextField(PropertyValue<expression::Formatted> value) {
if (value == getTextField())
return;
auto impl_ = mutableImpl();
@@ -1928,22 +1928,15 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co
}
- if (property == Property::IconImage || property == Property::TextField) {
+ if (property == Property::IconImage) {
Error error;
optional<PropertyValue<std::string>> typedValue = convert<PropertyValue<std::string>>(value, error, true, true);
if (!typedValue) {
return error;
}
- if (property == Property::IconImage) {
- setIconImage(*typedValue);
- return nullopt;
- }
-
- if (property == Property::TextField) {
- setTextField(*typedValue);
- return nullopt;
- }
+ setIconImage(*typedValue);
+ return nullopt;
}
@@ -1985,6 +1978,18 @@ 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);
+ if (!typedValue) {
+ return error;
+ }
+
+ setTextField(*typedValue);
+ return nullopt;
+
+ }
+
if (property == Property::TextFont) {
Error error;
optional<PropertyValue<std::vector<std::string>>> typedValue = convert<PropertyValue<std::vector<std::string>>>(value, error, true, false);
diff --git a/src/mbgl/style/layers/symbol_layer_properties.hpp b/src/mbgl/style/layers/symbol_layer_properties.hpp
index 10d059e787..6c147f440d 100644
--- a/src/mbgl/style/layers/symbol_layer_properties.hpp
+++ b/src/mbgl/style/layers/symbol_layer_properties.hpp
@@ -112,9 +112,9 @@ struct TextRotationAlignment : LayoutProperty<AlignmentType> {
static AlignmentType defaultValue() { return AlignmentType::Auto; }
};
-struct TextField : DataDrivenLayoutProperty<std::string> {
+struct TextField : DataDrivenLayoutProperty<expression::Formatted> {
static constexpr const char * key = "text-field";
- static std::string defaultValue() { return ""; }
+ static expression::Formatted defaultValue() { return ""; }
};
struct TextFont : DataDrivenLayoutProperty<std::vector<std::string>> {