diff options
author | John Firebaugh <john.firebaugh@gmail.com> | 2016-06-22 16:28:21 -0700 |
---|---|---|
committer | John Firebaugh <john.firebaugh@gmail.com> | 2016-06-24 09:39:51 -0700 |
commit | 16c435b1517b15a5ea8654987979ef58800b838b (patch) | |
tree | 8f81c4e202e1337d0966a06f27842d45a113fded /include/mbgl/style/conversion | |
parent | c4e4cc5081965d03132eea754c27ece3c95961cb (diff) | |
download | qtlocation-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.hpp | 208 | ||||
-rw-r--r-- | include/mbgl/style/conversion/make_property_setters.hpp | 133 | ||||
-rw-r--r-- | include/mbgl/style/conversion/make_property_setters.hpp.ejs | 45 | ||||
-rw-r--r-- | include/mbgl/style/conversion/property_setter.hpp | 55 | ||||
-rw-r--r-- | include/mbgl/style/conversion/property_value.hpp | 4 |
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(); |