summaryrefslogtreecommitdiff
path: root/src/mbgl
diff options
context:
space:
mode:
Diffstat (limited to 'src/mbgl')
-rw-r--r--src/mbgl/annotation/annotation_manager.cpp4
-rw-r--r--src/mbgl/layout/symbol_layout.cpp30
-rw-r--r--src/mbgl/style/conversion/function.cpp80
-rw-r--r--src/mbgl/style/conversion/light.cpp8
-rw-r--r--src/mbgl/style/conversion/make_property_setters.hpp4
-rw-r--r--src/mbgl/style/conversion/make_property_setters.hpp.ejs2
-rw-r--r--src/mbgl/style/conversion/property_setter.hpp5
-rw-r--r--src/mbgl/style/expression/dsl.cpp28
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