summaryrefslogtreecommitdiff
path: root/include/mbgl/style/conversion
diff options
context:
space:
mode:
authorJohn Firebaugh <john.firebaugh@gmail.com>2016-06-22 16:28:21 -0700
committerJohn Firebaugh <john.firebaugh@gmail.com>2016-06-24 09:39:51 -0700
commit16c435b1517b15a5ea8654987979ef58800b838b (patch)
tree8f81c4e202e1337d0966a06f27842d45a113fded /include/mbgl/style/conversion
parentc4e4cc5081965d03132eea754c27ece3c95961cb (diff)
downloadqtlocation-mapboxgl-16c435b1517b15a5ea8654987979ef58800b838b.tar.gz
[core, node] Implement bindings for addLayer
Diffstat (limited to 'include/mbgl/style/conversion')
-rw-r--r--include/mbgl/style/conversion/layer.hpp208
-rw-r--r--include/mbgl/style/conversion/make_property_setters.hpp133
-rw-r--r--include/mbgl/style/conversion/make_property_setters.hpp.ejs45
-rw-r--r--include/mbgl/style/conversion/property_setter.hpp55
-rw-r--r--include/mbgl/style/conversion/property_value.hpp4
5 files changed, 444 insertions, 1 deletions
diff --git a/include/mbgl/style/conversion/layer.hpp b/include/mbgl/style/conversion/layer.hpp
new file mode 100644
index 0000000000..0539dcf9ad
--- /dev/null
+++ b/include/mbgl/style/conversion/layer.hpp
@@ -0,0 +1,208 @@
+#pragma once
+
+#include <mbgl/style/layer.hpp>
+#include <mbgl/style/layers/background_layer.hpp>
+#include <mbgl/style/layers/circle_layer.hpp>
+#include <mbgl/style/layers/fill_layer.hpp>
+#include <mbgl/style/layers/line_layer.hpp>
+#include <mbgl/style/layers/raster_layer.hpp>
+#include <mbgl/style/layers/symbol_layer.hpp>
+#include <mbgl/style/conversion.hpp>
+#include <mbgl/style/conversion/constant.hpp>
+#include <mbgl/style/conversion/filter.hpp>
+#include <mbgl/style/conversion/make_property_setters.hpp>
+
+namespace mbgl {
+namespace style {
+namespace conversion {
+
+template <class V>
+optional<Error> setLayoutProperty(Layer& layer, const std::string& name, const V& value) {
+ static const auto setters = makeLayoutPropertySetters<V>();
+ auto it = setters.find(name);
+ if (it == setters.end()) {
+ return Error { "property not found" };
+ }
+ return it->second(layer, value);
+}
+
+template <class V>
+optional<Error> setPaintProperty(Layer& layer, const std::string& name, const V& value, const optional<std::string>& klass) {
+ static const auto setters = makePaintPropertySetters<V>();
+ auto it = setters.find(name);
+ if (it == setters.end()) {
+ return Error { "property not found" };
+ }
+ return it->second(layer, value, klass);
+}
+
+template <class V>
+optional<Error> setPaintProperties(Layer& layer, const V& value) {
+ return eachMember(value, [&] (const std::string& paintName, const V& paintValue) -> optional<Error> {
+ if (paintName.compare(0, 5, "paint") != 0) {
+ return {};
+ }
+
+ optional<std::string> klass;
+ if (paintName.compare(0, 6, "paint.") == 0) {
+ klass = paintName.substr(6);
+ }
+
+ return eachMember(paintValue, [&] (const std::string& k, const V& v) {
+ return setPaintProperty(layer, k, v, klass);
+ });
+ });
+}
+
+template <>
+struct Converter<std::unique_ptr<Layer>> {
+public:
+ template <class V>
+ Result<std::unique_ptr<Layer>> operator()(const V& value) const {
+ if (!isObject(value)) {
+ return Error { "layer must be an object" };
+ }
+
+ auto idValue = objectMember(value, "id");
+ if (!idValue) {
+ return Error { "layer must have an id" };
+ }
+
+ optional<std::string> id = toString(*idValue);
+ if (!id) {
+ return Error { "layer id must be a string" };
+ }
+
+ auto typeValue = objectMember(value, "type");
+ if (!typeValue) {
+ return Error { "layer must have a type" };
+ }
+
+ optional<std::string> type = toString(*typeValue);
+ if (!type) {
+ return Error { "layer type must be a string" };
+ }
+
+ Result<std::unique_ptr<Layer>> converted;
+
+ if (*type == "fill") {
+ converted = convertVectorLayer<FillLayer>(*id, value);
+ } else if (*type == "line") {
+ converted = convertVectorLayer<LineLayer>(*id, value);
+ } else if (*type == "circle") {
+ converted = convertVectorLayer<CircleLayer>(*id, value);
+ } else if (*type == "symbol") {
+ converted = convertVectorLayer<SymbolLayer>(*id, value);
+ } else if (*type == "raster") {
+ converted = convertRasterLayer(*id, value);
+ } else if (*type == "background") {
+ converted = convertBackgroundLayer(*id, value);
+ } else {
+ return Error { "invalid layer type" };
+ }
+
+ if (!converted) {
+ return converted;
+ }
+
+ std::unique_ptr<Layer> layer = std::move(*converted);
+
+ auto minzoomValue = objectMember(value, "minzoom");
+ if (minzoomValue) {
+ optional<float> minzoom = toNumber(*minzoomValue);
+ if (!minzoom) {
+ return Error { "minzoom must be numeric" };
+ }
+ layer->setMinZoom(*minzoom);
+ }
+
+ auto maxzoomValue = objectMember(value, "maxzoom");
+ if (maxzoomValue) {
+ optional<float> maxzoom = toNumber(*maxzoomValue);
+ if (!maxzoom) {
+ return Error { "maxzoom must be numeric" };
+ }
+ layer->setMaxZoom(*maxzoom);
+ }
+
+ auto layoutValue = objectMember(value, "layout");
+ if (layoutValue) {
+ if (!isObject(*layoutValue)) {
+ return Error { "layout must be an object" };
+ }
+ optional<Error> error = eachMember(*layoutValue, [&] (const std::string& k, const V& v) {
+ return setLayoutProperty(*layer, k, v);
+ });
+ if (error) {
+ return *error;
+ }
+ }
+
+ optional<Error> error = setPaintProperties(*layer, value);
+ if (error) {
+ return *error;
+ }
+
+ return std::move(layer);
+ }
+
+private:
+ template <class LayerType, class V>
+ Result<std::unique_ptr<Layer>> convertVectorLayer(const std::string& id, const V& value) const {
+ auto sourceValue = objectMember(value, "source");
+ if (!sourceValue) {
+ return Error { "layer must have a source" };
+ }
+
+ optional<std::string> source = toString(*sourceValue);
+ if (!source) {
+ return Error { "layer source must be a string" };
+ }
+
+ std::unique_ptr<LayerType> layer = std::make_unique<LayerType>(id, *source);
+
+ auto sourceLayerValue = objectMember(value, "source-layer");
+ if (sourceLayerValue) {
+ optional<std::string> sourceLayer = toString(*sourceLayerValue);
+ if (!sourceLayer) {
+ return Error { "layer source-layer must be a string" };
+ }
+ layer->setSourceLayer(*sourceLayer);
+ }
+
+ auto filterValue = objectMember(value, "filter");
+ if (filterValue) {
+ Result<Filter> filter = convert<Filter>(*filterValue);
+ if (!filter) {
+ return filter.error();
+ }
+ layer->setFilter(*filter);
+ }
+
+ return std::move(layer);
+ }
+
+ template <class V>
+ Result<std::unique_ptr<Layer>> convertRasterLayer(const std::string& id, const V& value) const {
+ auto sourceValue = objectMember(value, "source");
+ if (!sourceValue) {
+ return Error { "layer must have a source" };
+ }
+
+ optional<std::string> source = toString(*sourceValue);
+ if (!source) {
+ return Error { "layer source must be a string" };
+ }
+
+ return std::make_unique<RasterLayer>(id, *source);
+ }
+
+ template <class V>
+ Result<std::unique_ptr<Layer>> convertBackgroundLayer(const std::string& id, const V&) const {
+ return std::make_unique<BackgroundLayer>(id);
+ }
+};
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/conversion/make_property_setters.hpp b/include/mbgl/style/conversion/make_property_setters.hpp
new file mode 100644
index 0000000000..4c0089deaf
--- /dev/null
+++ b/include/mbgl/style/conversion/make_property_setters.hpp
@@ -0,0 +1,133 @@
+// This file is generated. Edit make_property_setters.hpp.ejs, then run `make style-code`.
+
+#include <mbgl/style/conversion/property_setter.hpp>
+
+#include <mbgl/style/layers/fill_layer.hpp>
+#include <mbgl/style/layers/line_layer.hpp>
+#include <mbgl/style/layers/symbol_layer.hpp>
+#include <mbgl/style/layers/circle_layer.hpp>
+#include <mbgl/style/layers/raster_layer.hpp>
+#include <mbgl/style/layers/background_layer.hpp>
+
+#include <unordered_map>
+
+namespace mbgl {
+namespace style {
+namespace conversion {
+
+template <class V>
+auto makeLayoutPropertySetters() {
+ std::unordered_map<std::string, LayoutPropertySetter<V>> result;
+
+ result["visibility"] = &setVisibility<V>;
+
+
+ result["line-cap"] = makePropertySetter<V>(&LineLayer::setLineCap);
+ result["line-join"] = makePropertySetter<V>(&LineLayer::setLineJoin);
+ result["line-miter-limit"] = makePropertySetter<V>(&LineLayer::setLineMiterLimit);
+ result["line-round-limit"] = makePropertySetter<V>(&LineLayer::setLineRoundLimit);
+
+ result["symbol-placement"] = makePropertySetter<V>(&SymbolLayer::setSymbolPlacement);
+ result["symbol-spacing"] = makePropertySetter<V>(&SymbolLayer::setSymbolSpacing);
+ result["symbol-avoid-edges"] = makePropertySetter<V>(&SymbolLayer::setSymbolAvoidEdges);
+ result["icon-allow-overlap"] = makePropertySetter<V>(&SymbolLayer::setIconAllowOverlap);
+ result["icon-ignore-placement"] = makePropertySetter<V>(&SymbolLayer::setIconIgnorePlacement);
+ result["icon-optional"] = makePropertySetter<V>(&SymbolLayer::setIconOptional);
+ result["icon-rotation-alignment"] = makePropertySetter<V>(&SymbolLayer::setIconRotationAlignment);
+ result["icon-size"] = makePropertySetter<V>(&SymbolLayer::setIconSize);
+ result["icon-text-fit"] = makePropertySetter<V>(&SymbolLayer::setIconTextFit);
+ result["icon-text-fit-padding"] = makePropertySetter<V>(&SymbolLayer::setIconTextFitPadding);
+ result["icon-image"] = makePropertySetter<V>(&SymbolLayer::setIconImage);
+ result["icon-rotate"] = makePropertySetter<V>(&SymbolLayer::setIconRotate);
+ result["icon-padding"] = makePropertySetter<V>(&SymbolLayer::setIconPadding);
+ result["icon-keep-upright"] = makePropertySetter<V>(&SymbolLayer::setIconKeepUpright);
+ result["icon-offset"] = makePropertySetter<V>(&SymbolLayer::setIconOffset);
+ result["text-pitch-alignment"] = makePropertySetter<V>(&SymbolLayer::setTextPitchAlignment);
+ result["text-rotation-alignment"] = makePropertySetter<V>(&SymbolLayer::setTextRotationAlignment);
+ result["text-field"] = makePropertySetter<V>(&SymbolLayer::setTextField);
+ result["text-font"] = makePropertySetter<V>(&SymbolLayer::setTextFont);
+ result["text-size"] = makePropertySetter<V>(&SymbolLayer::setTextSize);
+ result["text-max-width"] = makePropertySetter<V>(&SymbolLayer::setTextMaxWidth);
+ result["text-line-height"] = makePropertySetter<V>(&SymbolLayer::setTextLineHeight);
+ result["text-letter-spacing"] = makePropertySetter<V>(&SymbolLayer::setTextLetterSpacing);
+ result["text-justify"] = makePropertySetter<V>(&SymbolLayer::setTextJustify);
+ result["text-anchor"] = makePropertySetter<V>(&SymbolLayer::setTextAnchor);
+ result["text-max-angle"] = makePropertySetter<V>(&SymbolLayer::setTextMaxAngle);
+ result["text-rotate"] = makePropertySetter<V>(&SymbolLayer::setTextRotate);
+ result["text-padding"] = makePropertySetter<V>(&SymbolLayer::setTextPadding);
+ result["text-keep-upright"] = makePropertySetter<V>(&SymbolLayer::setTextKeepUpright);
+ result["text-transform"] = makePropertySetter<V>(&SymbolLayer::setTextTransform);
+ result["text-offset"] = makePropertySetter<V>(&SymbolLayer::setTextOffset);
+ result["text-allow-overlap"] = makePropertySetter<V>(&SymbolLayer::setTextAllowOverlap);
+ result["text-ignore-placement"] = makePropertySetter<V>(&SymbolLayer::setTextIgnorePlacement);
+ result["text-optional"] = makePropertySetter<V>(&SymbolLayer::setTextOptional);
+
+
+
+
+ return result;
+}
+
+template <class V>
+auto makePaintPropertySetters() {
+ std::unordered_map<std::string, PaintPropertySetter<V>> result;
+
+ result["fill-antialias"] = makePropertySetter<V>(&FillLayer::setFillAntialias);
+ result["fill-opacity"] = makePropertySetter<V>(&FillLayer::setFillOpacity);
+ result["fill-color"] = makePropertySetter<V>(&FillLayer::setFillColor);
+ result["fill-outline-color"] = makePropertySetter<V>(&FillLayer::setFillOutlineColor);
+ result["fill-translate"] = makePropertySetter<V>(&FillLayer::setFillTranslate);
+ result["fill-translate-anchor"] = makePropertySetter<V>(&FillLayer::setFillTranslateAnchor);
+ result["fill-pattern"] = makePropertySetter<V>(&FillLayer::setFillPattern);
+
+ result["line-opacity"] = makePropertySetter<V>(&LineLayer::setLineOpacity);
+ result["line-color"] = makePropertySetter<V>(&LineLayer::setLineColor);
+ result["line-translate"] = makePropertySetter<V>(&LineLayer::setLineTranslate);
+ result["line-translate-anchor"] = makePropertySetter<V>(&LineLayer::setLineTranslateAnchor);
+ result["line-width"] = makePropertySetter<V>(&LineLayer::setLineWidth);
+ result["line-gap-width"] = makePropertySetter<V>(&LineLayer::setLineGapWidth);
+ result["line-offset"] = makePropertySetter<V>(&LineLayer::setLineOffset);
+ result["line-blur"] = makePropertySetter<V>(&LineLayer::setLineBlur);
+ result["line-dasharray"] = makePropertySetter<V>(&LineLayer::setLineDasharray);
+ result["line-pattern"] = makePropertySetter<V>(&LineLayer::setLinePattern);
+
+ result["icon-opacity"] = makePropertySetter<V>(&SymbolLayer::setIconOpacity);
+ result["icon-color"] = makePropertySetter<V>(&SymbolLayer::setIconColor);
+ result["icon-halo-color"] = makePropertySetter<V>(&SymbolLayer::setIconHaloColor);
+ result["icon-halo-width"] = makePropertySetter<V>(&SymbolLayer::setIconHaloWidth);
+ result["icon-halo-blur"] = makePropertySetter<V>(&SymbolLayer::setIconHaloBlur);
+ result["icon-translate"] = makePropertySetter<V>(&SymbolLayer::setIconTranslate);
+ result["icon-translate-anchor"] = makePropertySetter<V>(&SymbolLayer::setIconTranslateAnchor);
+ result["text-opacity"] = makePropertySetter<V>(&SymbolLayer::setTextOpacity);
+ result["text-color"] = makePropertySetter<V>(&SymbolLayer::setTextColor);
+ result["text-halo-color"] = makePropertySetter<V>(&SymbolLayer::setTextHaloColor);
+ result["text-halo-width"] = makePropertySetter<V>(&SymbolLayer::setTextHaloWidth);
+ result["text-halo-blur"] = makePropertySetter<V>(&SymbolLayer::setTextHaloBlur);
+ result["text-translate"] = makePropertySetter<V>(&SymbolLayer::setTextTranslate);
+ result["text-translate-anchor"] = makePropertySetter<V>(&SymbolLayer::setTextTranslateAnchor);
+
+ result["circle-radius"] = makePropertySetter<V>(&CircleLayer::setCircleRadius);
+ result["circle-color"] = makePropertySetter<V>(&CircleLayer::setCircleColor);
+ result["circle-blur"] = makePropertySetter<V>(&CircleLayer::setCircleBlur);
+ result["circle-opacity"] = makePropertySetter<V>(&CircleLayer::setCircleOpacity);
+ result["circle-translate"] = makePropertySetter<V>(&CircleLayer::setCircleTranslate);
+ result["circle-translate-anchor"] = makePropertySetter<V>(&CircleLayer::setCircleTranslateAnchor);
+
+ result["raster-opacity"] = makePropertySetter<V>(&RasterLayer::setRasterOpacity);
+ result["raster-hue-rotate"] = makePropertySetter<V>(&RasterLayer::setRasterHueRotate);
+ result["raster-brightness-min"] = makePropertySetter<V>(&RasterLayer::setRasterBrightnessMin);
+ result["raster-brightness-max"] = makePropertySetter<V>(&RasterLayer::setRasterBrightnessMax);
+ result["raster-saturation"] = makePropertySetter<V>(&RasterLayer::setRasterSaturation);
+ result["raster-contrast"] = makePropertySetter<V>(&RasterLayer::setRasterContrast);
+ result["raster-fade-duration"] = makePropertySetter<V>(&RasterLayer::setRasterFadeDuration);
+
+ result["background-color"] = makePropertySetter<V>(&BackgroundLayer::setBackgroundColor);
+ result["background-pattern"] = makePropertySetter<V>(&BackgroundLayer::setBackgroundPattern);
+ result["background-opacity"] = makePropertySetter<V>(&BackgroundLayer::setBackgroundOpacity);
+
+ return result;
+}
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/conversion/make_property_setters.hpp.ejs b/include/mbgl/style/conversion/make_property_setters.hpp.ejs
new file mode 100644
index 0000000000..493c68ea31
--- /dev/null
+++ b/include/mbgl/style/conversion/make_property_setters.hpp.ejs
@@ -0,0 +1,45 @@
+// This file is generated. Edit make_property_setters.hpp.ejs, then run `make style-code`.
+
+#include <mbgl/style/conversion/property_setter.hpp>
+
+<% for (const layer of locals.layers) { -%>
+#include <mbgl/style/layers/<%- layer.type %>_layer.hpp>
+<% } -%>
+
+#include <unordered_map>
+
+namespace mbgl {
+namespace style {
+namespace conversion {
+
+template <class V>
+auto makeLayoutPropertySetters() {
+ std::unordered_map<std::string, LayoutPropertySetter<V>> result;
+
+ result["visibility"] = &setVisibility<V>;
+
+<% for (const layer of locals.layers) { -%>
+<% for (const property of layer.layoutProperties) { -%>
+ result["<%- property.name %>"] = makePropertySetter<V>(&<%- camelize(layer.type) %>Layer::set<%- camelize(property.name) %>);
+<% } -%>
+
+<% } -%>
+ return result;
+}
+
+template <class V>
+auto makePaintPropertySetters() {
+ std::unordered_map<std::string, PaintPropertySetter<V>> result;
+
+<% for (const layer of locals.layers) { -%>
+<% for (const property of layer.paintProperties) { -%>
+ result["<%- property.name %>"] = makePropertySetter<V>(&<%- camelize(layer.type) %>Layer::set<%- camelize(property.name) %>);
+<% } -%>
+
+<% } -%>
+ return result;
+}
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/conversion/property_setter.hpp b/include/mbgl/style/conversion/property_setter.hpp
new file mode 100644
index 0000000000..38dd934252
--- /dev/null
+++ b/include/mbgl/style/conversion/property_setter.hpp
@@ -0,0 +1,55 @@
+#include <mbgl/style/layer.hpp>
+#include <mbgl/style/conversion.hpp>
+#include <mbgl/style/conversion/constant.hpp>
+#include <mbgl/style/conversion/property_value.hpp>
+
+#include <functional>
+#include <string>
+
+namespace mbgl {
+namespace style {
+namespace conversion {
+
+template <class V>
+using LayoutPropertySetter = std::function<optional<Error> (Layer&, const V&)>;
+
+template <class V>
+using PaintPropertySetter = std::function<optional<Error> (Layer&, const V&, const optional<std::string>&)>;
+
+template <class V, class L, class T, class...Args>
+auto makePropertySetter(void (L::*setter)(PropertyValue<T>, const Args&...args)) {
+ return [setter] (Layer& layer, const V& value, const Args&...args) -> optional<Error> {
+ L* typedLayer = layer.as<L>();
+ if (!typedLayer) {
+ return Error { "layer doesn't support this property" };
+ }
+
+ Result<PropertyValue<T>> typedValue = convert<PropertyValue<T>>(value);
+ if (!typedValue) {
+ return typedValue.error();
+ }
+
+ (typedLayer->*setter)(*typedValue, args...);
+ return {};
+ };
+}
+
+template <class V>
+optional<Error> setVisibility(Layer& layer, const V& value) {
+ if (isUndefined(value)) {
+ layer.setVisibility(VisibilityType::Visible);
+ return {};
+ }
+
+ Result<VisibilityType> visibility = convert<VisibilityType>(value);
+ if (!visibility) {
+ return visibility.error();
+ }
+
+ layer.setVisibility(*visibility);
+ return {};
+}
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/conversion/property_value.hpp b/include/mbgl/style/conversion/property_value.hpp
index 840643abbe..de95b56155 100644
--- a/include/mbgl/style/conversion/property_value.hpp
+++ b/include/mbgl/style/conversion/property_value.hpp
@@ -13,7 +13,9 @@ template <class T>
struct Converter<PropertyValue<T>> {
template <class V>
Result<PropertyValue<T>> operator()(const V& value) const {
- if (isObject(value)) {
+ if (isUndefined(value)) {
+ return {};
+ } else if (isObject(value)) {
Result<Function<T>> function = convert<Function<T>>(value);
if (!function) {
return function.error();