diff options
Diffstat (limited to 'src/mbgl')
-rw-r--r-- | src/mbgl/annotation/annotation_manager.cpp | 4 | ||||
-rw-r--r-- | src/mbgl/layout/symbol_layout.cpp | 30 | ||||
-rw-r--r-- | src/mbgl/style/conversion/function.cpp | 80 | ||||
-rw-r--r-- | src/mbgl/style/conversion/light.cpp | 8 | ||||
-rw-r--r-- | src/mbgl/style/conversion/make_property_setters.hpp | 4 | ||||
-rw-r--r-- | src/mbgl/style/conversion/make_property_setters.hpp.ejs | 2 | ||||
-rw-r--r-- | src/mbgl/style/conversion/property_setter.hpp | 5 | ||||
-rw-r--r-- | src/mbgl/style/expression/dsl.cpp | 28 |
8 files changed, 98 insertions, 63 deletions
diff --git a/src/mbgl/annotation/annotation_manager.cpp b/src/mbgl/annotation/annotation_manager.cpp index b94b0a1bce..41eedf17dc 100644 --- a/src/mbgl/annotation/annotation_manager.cpp +++ b/src/mbgl/annotation/annotation_manager.cpp @@ -8,6 +8,7 @@ #include <mbgl/style/style_impl.hpp> #include <mbgl/style/layers/symbol_layer.hpp> #include <mbgl/style/layers/symbol_layer_impl.hpp> +#include <mbgl/style/expression/dsl.hpp> #include <mbgl/storage/file_source.hpp> #include <boost/function_output_iterator.hpp> @@ -160,8 +161,9 @@ void AnnotationManager::updateStyle() { std::unique_ptr<SymbolLayer> layer = std::make_unique<SymbolLayer>(PointLayerID, SourceID); + using namespace expression::dsl; layer->setSourceLayer(PointLayerID); - layer->setIconImage({SourceID + ".{sprite}"}); + layer->setIconImage(PropertyExpression<std::string>(concat(vec(literal(SourceID + "."), toString(get("sprite")))))); layer->setIconAllowOverlap(true); layer->setIconIgnorePlacement(true); diff --git a/src/mbgl/layout/symbol_layout.cpp b/src/mbgl/layout/symbol_layout.cpp index e71cfb93b0..d4df58b67c 100644 --- a/src/mbgl/layout/symbol_layout.cpp +++ b/src/mbgl/layout/symbol_layout.cpp @@ -10,7 +10,6 @@ #include <mbgl/text/shaping.hpp> #include <mbgl/util/constants.hpp> #include <mbgl/util/utf.hpp> -#include <mbgl/util/token.hpp> #include <mbgl/util/std.hpp> #include <mbgl/util/constants.hpp> #include <mbgl/util/string.hpp> @@ -106,31 +105,10 @@ SymbolLayout::SymbolLayout(const BucketParameters& parameters, ft.index = i; - auto getValue = [&ft](const std::string& key) -> std::string { - auto value = ft.getValue(key); - if (!value) - return std::string(); - if (value->is<std::string>()) - return value->get<std::string>(); - if (value->is<bool>()) - return value->get<bool>() ? "true" : "false"; - if (value->is<int64_t>()) - return util::toString(value->get<int64_t>()); - if (value->is<uint64_t>()) - return util::toString(value->get<uint64_t>()); - if (value->is<double>()) - return util::toString(value->get<double>()); - return "null"; - }; - if (hasText) { std::string u8string = layout.evaluate<TextField>(zoom, ft); - if (layout.get<TextField>().isConstant() && !leader.layout.get<TextField>().isExpression()) { - u8string = util::replaceTokens(u8string, getValue); - } - - auto textTransform = layout.evaluate<TextTransform>(zoom, ft); + auto textTransform = layout.evaluate<TextTransform>(zoom, ft); if (textTransform == TextTransformType::Uppercase) { u8string = platform::uppercase(u8string); } else if (textTransform == TextTransformType::Lowercase) { @@ -157,11 +135,7 @@ SymbolLayout::SymbolLayout(const BucketParameters& parameters, } if (hasIcon) { - std::string icon = layout.evaluate<IconImage>(zoom, ft); - if (layout.get<IconImage>().isConstant() && !leader.layout.get<IconImage>().isExpression()) { - icon = util::replaceTokens(icon, getValue); - } - ft.icon = icon; + ft.icon = layout.evaluate<IconImage>(zoom, ft); imageDependencies.insert(*ft.icon); } diff --git a/src/mbgl/style/conversion/function.cpp b/src/mbgl/style/conversion/function.cpp index 39e061d75a..61b45fcbe5 100644 --- a/src/mbgl/style/conversion/function.cpp +++ b/src/mbgl/style/conversion/function.cpp @@ -16,6 +16,60 @@ namespace conversion { using namespace expression; using namespace expression::dsl; +const static std::string tokenReservedChars = "{}"; + +bool hasTokens(const std::string& source) { + auto pos = source.begin(); + const auto end = source.end(); + + while (pos != end) { + auto brace = std::find(pos, end, '{'); + if (brace == end) + return false; + for (brace++; brace != end && tokenReservedChars.find(*brace) == std::string::npos; brace++); + if (brace != end && *brace == '}') { + return true; + } + pos = brace; + } + + return false; +} + +std::unique_ptr<Expression> convertTokenStringToExpression(const std::string& source) { + std::vector<std::unique_ptr<Expression>> inputs; + + auto pos = source.begin(); + const auto end = source.end(); + + while (pos != end) { + auto brace = std::find(pos, end, '{'); + if (pos != brace) { + inputs.push_back(literal(std::string(pos, brace))); + } + pos = brace; + if (pos != end) { + for (brace++; brace != end && tokenReservedChars.find(*brace) == std::string::npos; brace++); + if (brace != end && *brace == '}') { + inputs.push_back(toString(get(literal(std::string(pos + 1, brace))))); + pos = brace + 1; + } else { + inputs.push_back(literal(std::string(pos, brace))); + pos = brace; + } + } + } + + switch (inputs.size()) { + case 0: + return literal(source); + case 1: + return std::move(inputs[0]); + default: + return concat(std::move(inputs)); + } +} + // 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 // an integer). @@ -66,7 +120,7 @@ static bool interpolatable(type::Type type) { ); } -static optional<std::unique_ptr<Expression>> convertLiteral(type::Type type, const Convertible& value, Error& error) { +static optional<std::unique_ptr<Expression>> convertLiteral(type::Type type, const Convertible& value, Error& error, bool convertTokens = false) { return type.match( [&] (const type::NumberType&) -> optional<std::unique_ptr<Expression>> { auto result = convert<float>(value, error); @@ -87,7 +141,7 @@ static optional<std::unique_ptr<Expression>> convertLiteral(type::Type type, con if (!result) { return {}; } - return literal(*result); + return convertTokens ? convertTokenStringToExpression(*result) : literal(*result); }, [&] (const type::ColorType&) -> optional<std::unique_ptr<Expression>> { auto result = convert<Color>(value, error); @@ -163,7 +217,8 @@ static optional<std::unique_ptr<Expression>> convertLiteral(type::Type type, con static optional<std::map<double, std::unique_ptr<Expression>>> convertStops(type::Type type, const Convertible& value, - Error& error) { + Error& error, + bool convertTokens) { auto stopsValue = objectMember(value, "stops"); if (!stopsValue) { error = { "function value must specify stops" }; @@ -199,7 +254,7 @@ static optional<std::map<double, std::unique_ptr<Expression>>> convertStops(type return {}; } - optional<std::unique_ptr<Expression>> e = convertLiteral(type, arrayMember(stopValue, 1), error); + optional<std::unique_ptr<Expression>> e = convertLiteral(type, arrayMember(stopValue, 1), error, convertTokens); if (!e) { return {}; } @@ -320,8 +375,9 @@ std::unique_ptr<Expression> categorical<bool>(type::Type type, const std::string static optional<std::unique_ptr<Expression>> convertIntervalFunction(type::Type type, const Convertible& value, Error& error, - std::unique_ptr<Expression> input) { - auto stops = convertStops(type, value, error); + std::unique_ptr<Expression> input, + bool convertTokens = false) { + auto stops = convertStops(type, value, error, convertTokens); if (!stops) { return {}; } @@ -331,8 +387,9 @@ static optional<std::unique_ptr<Expression>> convertIntervalFunction(type::Type static optional<std::unique_ptr<Expression>> convertExponentialFunction(type::Type type, const Convertible& value, Error& error, - std::unique_ptr<Expression> input) { - auto stops = convertStops(type, value, error); + std::unique_ptr<Expression> input, + bool convertTokens = false) { + auto stops = convertStops(type, value, error, convertTokens); if (!stops) { return {}; } @@ -486,7 +543,8 @@ optional<std::unique_ptr<Expression>> composite(type::Type type, optional<std::unique_ptr<Expression>> convertFunctionToExpression(type::Type type, const Convertible& value, - Error& err) { + Error& err, + bool convertTokens) { if (!isObject(value)) { err = { "function must be an object" }; return {}; @@ -515,9 +573,9 @@ optional<std::unique_ptr<Expression>> convertFunctionToExpression(type::Type typ // Camera function. switch (functionType) { case FunctionType::Interval: - return convertIntervalFunction(type, value, err, zoom()); + return convertIntervalFunction(type, value, err, zoom(), convertTokens); case FunctionType::Exponential: - return convertExponentialFunction(type, value, err, zoom()); + return convertExponentialFunction(type, value, err, zoom(), convertTokens); default: err = { "unsupported function type" }; return {}; diff --git a/src/mbgl/style/conversion/light.cpp b/src/mbgl/style/conversion/light.cpp index f521f74386..57b61eb340 100644 --- a/src/mbgl/style/conversion/light.cpp +++ b/src/mbgl/style/conversion/light.cpp @@ -18,7 +18,7 @@ optional<Light> Converter<Light>::operator()(const Convertible& value, Error& er const auto anchor = objectMember(value, "anchor"); if (anchor) { optional<PropertyValue<LightAnchorType>> convertedAnchor = - convert<PropertyValue<LightAnchorType>>(*anchor, error); + convert<PropertyValue<LightAnchorType>>(*anchor, error, false); if (convertedAnchor) { light.setAnchor(*convertedAnchor); @@ -41,7 +41,7 @@ optional<Light> Converter<Light>::operator()(const Convertible& value, Error& er const auto color = objectMember(value, "color"); if (color) { optional<PropertyValue<Color>> convertedColor = - convert<PropertyValue<Color>>(*color, error); + convert<PropertyValue<Color>>(*color, error, false); if (convertedColor) { light.setColor(*convertedColor); @@ -64,7 +64,7 @@ optional<Light> Converter<Light>::operator()(const Convertible& value, Error& er const auto position = objectMember(value, "position"); if (position) { optional<PropertyValue<Position>> convertedPosition = - convert<PropertyValue<Position>>(*position, error); + convert<PropertyValue<Position>>(*position, error, false); if (convertedPosition) { light.setPosition(*convertedPosition); @@ -87,7 +87,7 @@ optional<Light> Converter<Light>::operator()(const Convertible& value, Error& er const auto intensity = objectMember(value, "intensity"); if (intensity) { optional<PropertyValue<float>> convertedIntensity = - convert<PropertyValue<float>>(*intensity, error); + convert<PropertyValue<float>>(*intensity, error, false); if (convertedIntensity) { light.setIntensity(*convertedIntensity); diff --git a/src/mbgl/style/conversion/make_property_setters.hpp b/src/mbgl/style/conversion/make_property_setters.hpp index 96aa1b6414..64826106f0 100644 --- a/src/mbgl/style/conversion/make_property_setters.hpp +++ b/src/mbgl/style/conversion/make_property_setters.hpp @@ -41,7 +41,7 @@ inline auto makeLayoutPropertySetters() { result["icon-size"] = &setProperty<SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setIconSize>; result["icon-text-fit"] = &setProperty<SymbolLayer, PropertyValue<IconTextFitType>, &SymbolLayer::setIconTextFit>; result["icon-text-fit-padding"] = &setProperty<SymbolLayer, PropertyValue<std::array<float, 4>>, &SymbolLayer::setIconTextFitPadding>; - result["icon-image"] = &setProperty<SymbolLayer, DataDrivenPropertyValue<std::string>, &SymbolLayer::setIconImage>; + result["icon-image"] = &setProperty<SymbolLayer, DataDrivenPropertyValue<std::string>, &SymbolLayer::setIconImage, true>; result["icon-rotate"] = &setProperty<SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setIconRotate>; result["icon-padding"] = &setProperty<SymbolLayer, PropertyValue<float>, &SymbolLayer::setIconPadding>; result["icon-keep-upright"] = &setProperty<SymbolLayer, PropertyValue<bool>, &SymbolLayer::setIconKeepUpright>; @@ -50,7 +50,7 @@ inline auto makeLayoutPropertySetters() { result["icon-pitch-alignment"] = &setProperty<SymbolLayer, PropertyValue<AlignmentType>, &SymbolLayer::setIconPitchAlignment>; result["text-pitch-alignment"] = &setProperty<SymbolLayer, PropertyValue<AlignmentType>, &SymbolLayer::setTextPitchAlignment>; result["text-rotation-alignment"] = &setProperty<SymbolLayer, PropertyValue<AlignmentType>, &SymbolLayer::setTextRotationAlignment>; - result["text-field"] = &setProperty<SymbolLayer, DataDrivenPropertyValue<std::string>, &SymbolLayer::setTextField>; + result["text-field"] = &setProperty<SymbolLayer, DataDrivenPropertyValue<std::string>, &SymbolLayer::setTextField, true>; result["text-font"] = &setProperty<SymbolLayer, DataDrivenPropertyValue<std::vector<std::string>>, &SymbolLayer::setTextFont>; result["text-size"] = &setProperty<SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setTextSize>; result["text-max-width"] = &setProperty<SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setTextMaxWidth>; diff --git a/src/mbgl/style/conversion/make_property_setters.hpp.ejs b/src/mbgl/style/conversion/make_property_setters.hpp.ejs index 2975cb19f2..2b8925817d 100644 --- a/src/mbgl/style/conversion/make_property_setters.hpp.ejs +++ b/src/mbgl/style/conversion/make_property_setters.hpp.ejs @@ -21,7 +21,7 @@ inline auto makeLayoutPropertySetters() { <% for (const layer of locals.layers) { -%> <% for (const property of layer.layoutProperties) { -%> - result["<%- property.name %>"] = &setProperty<<%- camelize(layer.type) %>Layer, <%- propertyValueType(property) %>, &<%- camelize(layer.type) %>Layer::set<%- camelize(property.name) %>>; + result["<%- property.name %>"] = &setProperty<<%- camelize(layer.type) %>Layer, <%- propertyValueType(property) %>, &<%- camelize(layer.type) %>Layer::set<%- camelize(property.name) %><%- property.name === 'icon-image' || property.name === 'text-field' ? ', true' : '' %>>; <% } -%> <% } -%> diff --git a/src/mbgl/style/conversion/property_setter.hpp b/src/mbgl/style/conversion/property_setter.hpp index e13338f628..8791e36e1f 100644 --- a/src/mbgl/style/conversion/property_setter.hpp +++ b/src/mbgl/style/conversion/property_setter.hpp @@ -1,6 +1,7 @@ #pragma once #include <mbgl/style/layer.hpp> +#include <mbgl/style/layers/symbol_layer.hpp> #include <mbgl/style/conversion.hpp> #include <mbgl/style/conversion/color_ramp_property_value.hpp> #include <mbgl/style/conversion/constant.hpp> @@ -16,7 +17,7 @@ namespace conversion { using PropertySetter = optional<Error> (*) (Layer&, const Convertible&); -template <class L, class PropertyValue, void (L::*setter)(PropertyValue)> +template <class L, class PropertyValue, void (L::*setter)(PropertyValue), bool convertTokens = false> optional<Error> setProperty(Layer& layer, const Convertible& value) { auto* typedLayer = layer.as<L>(); if (!typedLayer) { @@ -24,7 +25,7 @@ optional<Error> setProperty(Layer& layer, const Convertible& value) { } Error error; - optional<PropertyValue> typedValue = convert<PropertyValue>(value, error); + optional<PropertyValue> typedValue = convert<PropertyValue>(value, error, convertTokens); if (!typedValue) { return error; } diff --git a/src/mbgl/style/expression/dsl.cpp b/src/mbgl/style/expression/dsl.cpp index 5532e0a520..a851d82e16 100644 --- a/src/mbgl/style/expression/dsl.cpp +++ b/src/mbgl/style/expression/dsl.cpp @@ -7,26 +7,22 @@ #include <mbgl/style/expression/step.hpp> #include <mbgl/style/expression/interpolate.hpp> #include <mbgl/style/expression/compound_expression.hpp> -#include <mbgl/util/ignore.hpp> namespace mbgl { namespace style { namespace expression { namespace dsl { -template <class... Args> -static std::vector<std::unique_ptr<Expression>> vec(Args... args) { - std::vector<std::unique_ptr<Expression>> result; - util::ignore({ (result.push_back(std::move(args)), 0)... }); - return result; +static std::unique_ptr<Expression> compound(const char* op, std::vector<std::unique_ptr<Expression>> args) { + ParsingContext ctx; + ParseResult result = createCompoundExpression(op, std::move(args), ctx); + assert(result); + return std::move(*result); } template <class... Args> static std::unique_ptr<Expression> compound(const char* op, Args... args) { - ParsingContext ctx; - ParseResult result = createCompoundExpression(op, vec(std::move(args)...), ctx); - assert(result); - return std::move(*result); + return compound(op, vec(std::move(args)...)); } std::unique_ptr<Expression> error(std::string message) { @@ -69,14 +65,14 @@ std::unique_ptr<Expression> boolean(std::unique_ptr<Expression> value) { return std::make_unique<Assertion>(type::Boolean, vec(std::move(value))); } -std::unique_ptr<Expression> toColor(const char* value) { - return toColor(literal(value)); -} - std::unique_ptr<Expression> toColor(std::unique_ptr<Expression> value) { return std::make_unique<Coercion>(type::Color, vec(std::move(value))); } +std::unique_ptr<Expression> toString(std::unique_ptr<Expression> value) { + return compound("to-string", std::move(value)); +} + std::unique_ptr<Expression> get(const char* value) { return get(literal(value)); } @@ -177,6 +173,10 @@ std::unique_ptr<Expression> interpolate(Interpolator interpolator, return std::move(*result); } +std::unique_ptr<Expression> concat(std::vector<std::unique_ptr<Expression>> inputs) { + return compound("concat", std::move(inputs)); +} + } // namespace dsl } // namespace expression } // namespace style |