diff options
author | Chris Loer <chris.loer@gmail.com> | 2018-10-02 17:03:50 -0700 |
---|---|---|
committer | Chris Loer <chris.loer@mapbox.com> | 2018-10-15 13:15:46 -0700 |
commit | ce76bde13d0f4381ee861f81daf636defaff0bc5 (patch) | |
tree | e37d93d14fc64620069bac5488bae871af2fa431 /include/mbgl | |
parent | bc718257748f1ad87658e85f8c31b574afca57a9 (diff) | |
download | qtlocation-mapboxgl-ce76bde13d0f4381ee861f81daf636defaff0bc5.tar.gz |
[core] Initial implementation of 'format' expression
Diffstat (limited to 'include/mbgl')
19 files changed, 156 insertions, 10 deletions
diff --git a/include/mbgl/style/conversion/function.hpp b/include/mbgl/style/conversion/function.hpp index ba9acd7a3b..47ce6843b5 100644 --- a/include/mbgl/style/conversion/function.hpp +++ b/include/mbgl/style/conversion/function.hpp @@ -11,6 +11,7 @@ namespace style { namespace conversion { bool hasTokens(const std::string&); +std::unique_ptr<expression::Expression> convertTokenStringToFormatExpression(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 f6f36db983..9d619f7a02 100644 --- a/include/mbgl/style/conversion/property_value.hpp +++ b/include/mbgl/style/conversion/property_value.hpp @@ -28,6 +28,17 @@ struct Converter<PropertyValue<T>> { ? PropertyValue<T>(PropertyExpression<T>(convertTokenStringToExpression(t))) : PropertyValue<T>(t); } + + PropertyValue<T> maybeConvertTokens(const expression::Formatted& t) const { + // This only works with a single-section `Formatted` created automatically + // by parsing a plain-text `text-field` property. + // Token conversion happens later than the initial string->Formatted conversion + // General purpose `format` expressions with embedded tokens are not supported + const std::string& firstUnformattedSection = t.sections[0].text; + return hasTokens(firstUnformattedSection) + ? PropertyValue<T>(PropertyExpression<T>(convertTokenStringToFormatExpression(firstUnformattedSection))) + : PropertyValue<T>(t); + } }; } // namespace conversion diff --git a/include/mbgl/style/expression/coercion.hpp b/include/mbgl/style/expression/coercion.hpp index d83bd6dfa7..28c2c0c679 100644 --- a/include/mbgl/style/expression/coercion.hpp +++ b/include/mbgl/style/expression/coercion.hpp @@ -10,11 +10,6 @@ namespace mbgl { namespace style { namespace expression { -/** - * 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. - */ class Coercion : public Expression { public: Coercion(type::Type type_, std::vector<std::unique_ptr<Expression>> inputs_); @@ -23,6 +18,8 @@ public: EvaluationResult evaluate(const EvaluationContext& params) const override; void eachChild(const std::function<void(const Expression&)>& visit) const override; + + mbgl::Value serialize() const override; bool operator==(const Expression& e) const override; diff --git a/include/mbgl/style/expression/expression.hpp b/include/mbgl/style/expression/expression.hpp index ce02c4114b..97b143b3d9 100644 --- a/include/mbgl/style/expression/expression.hpp +++ b/include/mbgl/style/expression/expression.hpp @@ -133,6 +133,7 @@ enum class Kind : int32_t { Any, All, Comparison, + FormatExpression, }; class Expression { diff --git a/include/mbgl/style/expression/format_expression.hpp b/include/mbgl/style/expression/format_expression.hpp new file mode 100644 index 0000000000..b00674a88e --- /dev/null +++ b/include/mbgl/style/expression/format_expression.hpp @@ -0,0 +1,52 @@ +#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 { +namespace expression { + +struct FormatExpressionSection { + FormatExpressionSection(std::unique_ptr<Expression> text_, + optional<std::unique_ptr<Expression>> fontScale_, + optional<std::unique_ptr<Expression>> textFont_); + + std::shared_ptr<Expression> text; + optional<std::shared_ptr<Expression>> fontScale; + optional<std::shared_ptr<Expression>> textFont; +}; + +class FormatExpression : public Expression { +public: + FormatExpression(std::vector<FormatExpressionSection> sections); + + 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 { + // Technically the combinatoric set of all children + // Usually, this.text will be undefined anyway + return { nullopt }; + } + + 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 +} // namespace style +} // namespace mbgl diff --git a/include/mbgl/style/expression/formatted.hpp b/include/mbgl/style/expression/formatted.hpp new file mode 100644 index 0000000000..9e7e7308cb --- /dev/null +++ b/include/mbgl/style/expression/formatted.hpp @@ -0,0 +1,62 @@ +#pragma once + +#include <mbgl/style/conversion.hpp> +#include <mbgl/util/font_stack.hpp> +#include <mbgl/util/optional.hpp> +#include <mbgl/util/variant.hpp> + +#include <vector> +#include <string> + +namespace mbgl { +namespace style { +namespace expression { + +struct FormattedSection { + FormattedSection(std::string text_, optional<double> fontScale_, optional<FontStack> fontStack_) + : text(std::move(text_)) + , fontScale(std::move(fontScale_)) + , fontStack(std::move(fontStack_)) + {} + std::string text; + optional<double> fontScale; + optional<FontStack> fontStack; +}; + +class Formatted { +public: + Formatted() = default; + + Formatted(const char* plainU8String) { + sections.emplace_back(std::string(plainU8String), nullopt, nullopt); + } + + Formatted(std::vector<FormattedSection> sections_) + : sections(std::move(sections_)) + {} + + bool operator==(const Formatted& ) const; + + std::string toString() const; + + bool empty() const { + return sections.empty() || sections.at(0).text.empty(); + } + + std::vector<FormattedSection> sections; +}; + +} // namespace expression + +namespace conversion { + +template <> +struct Converter<mbgl::style::expression::Formatted> { +public: + optional<mbgl::style::expression::Formatted> operator()(const Convertible& value, Error& error) const; +}; + +} // namespace conversion + +} // namespace style +} // namespace mbgl diff --git a/include/mbgl/style/expression/type.hpp b/include/mbgl/style/expression/type.hpp index 316496839b..a5a1e76164 100644 --- a/include/mbgl/style/expression/type.hpp +++ b/include/mbgl/style/expression/type.hpp @@ -66,6 +66,13 @@ struct CollatorType { std::string getName() const { return "collator"; } bool operator==(const CollatorType&) const { return true; } }; + +struct FormattedType { + constexpr FormattedType() {}; // NOLINT + std::string getName() const { return "formatted"; } + bool operator==(const FormattedType&) const { return true; } +}; + constexpr NullType Null; constexpr NumberType Number; @@ -75,6 +82,7 @@ constexpr ColorType Color; constexpr ValueType Value; constexpr ObjectType Object; constexpr CollatorType Collator; +constexpr FormattedType Formatted; constexpr ErrorType Error; struct Array; @@ -89,6 +97,7 @@ using Type = variant< ValueType, mapbox::util::recursive_wrapper<Array>, CollatorType, + FormattedType, ErrorType>; struct Array { diff --git a/include/mbgl/style/expression/value.hpp b/include/mbgl/style/expression/value.hpp index 2036ab8abe..91239d083f 100644 --- a/include/mbgl/style/expression/value.hpp +++ b/include/mbgl/style/expression/value.hpp @@ -1,6 +1,7 @@ #pragma once #include <mbgl/style/expression/collator.hpp> +#include <mbgl/style/expression/formatted.hpp> #include <mbgl/style/expression/type.hpp> #include <mbgl/style/position.hpp> #include <mbgl/style/types.hpp> @@ -25,6 +26,7 @@ using ValueBase = variant< std::string, Color, Collator, + Formatted, mapbox::util::recursive_wrapper<std::vector<Value>>, mapbox::util::recursive_wrapper<std::unordered_map<std::string, Value>>>; struct Value : ValueBase { diff --git a/include/mbgl/style/layers/background_layer.hpp b/include/mbgl/style/layers/background_layer.hpp index 76230df12c..ef01ea41be 100644 --- a/include/mbgl/style/layers/background_layer.hpp +++ b/include/mbgl/style/layers/background_layer.hpp @@ -5,6 +5,7 @@ #include <mbgl/style/layer.hpp> #include <mbgl/style/filter.hpp> #include <mbgl/style/property_value.hpp> +#include <mbgl/style/expression/formatted.hpp> #include <mbgl/util/color.hpp> diff --git a/include/mbgl/style/layers/circle_layer.hpp b/include/mbgl/style/layers/circle_layer.hpp index cde691c893..0f8d1c0c13 100644 --- a/include/mbgl/style/layers/circle_layer.hpp +++ b/include/mbgl/style/layers/circle_layer.hpp @@ -5,6 +5,7 @@ #include <mbgl/style/layer.hpp> #include <mbgl/style/filter.hpp> #include <mbgl/style/property_value.hpp> +#include <mbgl/style/expression/formatted.hpp> #include <mbgl/util/color.hpp> diff --git a/include/mbgl/style/layers/fill_extrusion_layer.hpp b/include/mbgl/style/layers/fill_extrusion_layer.hpp index e72fcade61..d30ffa26da 100644 --- a/include/mbgl/style/layers/fill_extrusion_layer.hpp +++ b/include/mbgl/style/layers/fill_extrusion_layer.hpp @@ -5,6 +5,7 @@ #include <mbgl/style/layer.hpp> #include <mbgl/style/filter.hpp> #include <mbgl/style/property_value.hpp> +#include <mbgl/style/expression/formatted.hpp> #include <mbgl/util/color.hpp> diff --git a/include/mbgl/style/layers/fill_layer.hpp b/include/mbgl/style/layers/fill_layer.hpp index 430d7a011f..25c46d312f 100644 --- a/include/mbgl/style/layers/fill_layer.hpp +++ b/include/mbgl/style/layers/fill_layer.hpp @@ -5,6 +5,7 @@ #include <mbgl/style/layer.hpp> #include <mbgl/style/filter.hpp> #include <mbgl/style/property_value.hpp> +#include <mbgl/style/expression/formatted.hpp> #include <mbgl/util/color.hpp> diff --git a/include/mbgl/style/layers/heatmap_layer.hpp b/include/mbgl/style/layers/heatmap_layer.hpp index fd0051f44c..347bb8a4aa 100644 --- a/include/mbgl/style/layers/heatmap_layer.hpp +++ b/include/mbgl/style/layers/heatmap_layer.hpp @@ -6,6 +6,7 @@ #include <mbgl/style/layer.hpp> #include <mbgl/style/filter.hpp> #include <mbgl/style/property_value.hpp> +#include <mbgl/style/expression/formatted.hpp> #include <mbgl/util/color.hpp> diff --git a/include/mbgl/style/layers/hillshade_layer.hpp b/include/mbgl/style/layers/hillshade_layer.hpp index 89d0ae686f..697d4c71ad 100644 --- a/include/mbgl/style/layers/hillshade_layer.hpp +++ b/include/mbgl/style/layers/hillshade_layer.hpp @@ -5,6 +5,7 @@ #include <mbgl/style/layer.hpp> #include <mbgl/style/filter.hpp> #include <mbgl/style/property_value.hpp> +#include <mbgl/style/expression/formatted.hpp> #include <mbgl/util/color.hpp> diff --git a/include/mbgl/style/layers/layer.hpp.ejs b/include/mbgl/style/layers/layer.hpp.ejs index cf31a4d672..9d595d2035 100644 --- a/include/mbgl/style/layers/layer.hpp.ejs +++ b/include/mbgl/style/layers/layer.hpp.ejs @@ -13,6 +13,7 @@ #include <mbgl/style/layer.hpp> #include <mbgl/style/filter.hpp> #include <mbgl/style/property_value.hpp> +#include <mbgl/style/expression/formatted.hpp> #include <mbgl/util/color.hpp> diff --git a/include/mbgl/style/layers/line_layer.hpp b/include/mbgl/style/layers/line_layer.hpp index 9350b3d102..1e55561bbd 100644 --- a/include/mbgl/style/layers/line_layer.hpp +++ b/include/mbgl/style/layers/line_layer.hpp @@ -6,6 +6,7 @@ #include <mbgl/style/layer.hpp> #include <mbgl/style/filter.hpp> #include <mbgl/style/property_value.hpp> +#include <mbgl/style/expression/formatted.hpp> #include <mbgl/util/color.hpp> diff --git a/include/mbgl/style/layers/raster_layer.hpp b/include/mbgl/style/layers/raster_layer.hpp index fcc35412a0..b1c716c17f 100644 --- a/include/mbgl/style/layers/raster_layer.hpp +++ b/include/mbgl/style/layers/raster_layer.hpp @@ -5,6 +5,7 @@ #include <mbgl/style/layer.hpp> #include <mbgl/style/filter.hpp> #include <mbgl/style/property_value.hpp> +#include <mbgl/style/expression/formatted.hpp> #include <mbgl/util/color.hpp> diff --git a/include/mbgl/style/layers/symbol_layer.hpp b/include/mbgl/style/layers/symbol_layer.hpp index aabda0d794..6d82e5df85 100644 --- a/include/mbgl/style/layers/symbol_layer.hpp +++ b/include/mbgl/style/layers/symbol_layer.hpp @@ -5,6 +5,7 @@ #include <mbgl/style/layer.hpp> #include <mbgl/style/filter.hpp> #include <mbgl/style/property_value.hpp> +#include <mbgl/style/expression/formatted.hpp> #include <mbgl/util/color.hpp> @@ -121,9 +122,9 @@ public: PropertyValue<AlignmentType> getTextRotationAlignment() const; void setTextRotationAlignment(PropertyValue<AlignmentType>); - static PropertyValue<std::string> getDefaultTextField(); - PropertyValue<std::string> getTextField() const; - void setTextField(PropertyValue<std::string>); + static PropertyValue<expression::Formatted> getDefaultTextField(); + PropertyValue<expression::Formatted> getTextField() const; + void setTextField(PropertyValue<expression::Formatted>); static PropertyValue<std::vector<std::string>> getDefaultTextFont(); PropertyValue<std::vector<std::string>> getTextFont() const; diff --git a/include/mbgl/util/font_stack.hpp b/include/mbgl/util/font_stack.hpp index ace60a4ba6..ccc1a06068 100644 --- a/include/mbgl/util/font_stack.hpp +++ b/include/mbgl/util/font_stack.hpp @@ -11,11 +11,12 @@ namespace mbgl { // An array of font names using FontStack = std::vector<std::string>; +using FontStackHash = std::size_t; std::string fontStackToString(const FontStack&); -struct FontStackHash { - std::size_t operator()(const FontStack&) const; +struct FontStackHasher { + FontStackHash operator()(const FontStack&) const; }; // Statically evaluate layer properties to determine what font stacks are used. |