1 #include <mbgl/style/conversion/layer.hpp>
2 #include <mbgl/style/conversion/constant.hpp>
3 #include <mbgl/style/conversion/filter.hpp>
4 #include <mbgl/style/conversion/make_property_setters.hpp>
5 #include <mbgl/style/layers/background_layer.hpp>
6 #include <mbgl/style/layers/circle_layer.hpp>
7 #include <mbgl/style/layers/fill_layer.hpp>
8 #include <mbgl/style/layers/fill_extrusion_layer.hpp>
9 #include <mbgl/style/layers/heatmap_layer.hpp>
10 #include <mbgl/style/layers/hillshade_layer.hpp>
11 #include <mbgl/style/layers/line_layer.hpp>
12 #include <mbgl/style/layers/raster_layer.hpp>
13 #include <mbgl/style/layers/symbol_layer.hpp>
14 
15 namespace mbgl {
16 namespace style {
17 namespace conversion {
18 
setLayoutProperty(Layer & layer,const std::string & name,const Convertible & value)19 optional<Error> setLayoutProperty(Layer& layer, const std::string& name, const Convertible& value) {
20     static const auto setters = makeLayoutPropertySetters();
21     auto it = setters.find(name);
22     if (it == setters.end()) {
23         return Error { "property not found" };
24     }
25     return it->second(layer, value);
26 }
27 
setPaintProperty(Layer & layer,const std::string & name,const Convertible & value)28 optional<Error> setPaintProperty(Layer& layer, const std::string& name, const Convertible& value) {
29     static const auto setters = makePaintPropertySetters();
30     auto it = setters.find(name);
31     if (it == setters.end()) {
32         return Error { "property not found" };
33     }
34     return it->second(layer, value);
35 }
36 
setPaintProperties(Layer & layer,const Convertible & value)37 optional<Error> setPaintProperties(Layer& layer, const Convertible& value) {
38     auto paintValue = objectMember(value, "paint");
39     if (!paintValue) {
40         return {};
41     }
42     if (!isObject(*paintValue)) {
43         return { { "paint must be an object" } };
44     }
45     return eachMember(*paintValue, [&] (const std::string& k, const Convertible& v) {
46         return setPaintProperty(layer, k, v);
47     });
48 }
49 
50 template <class LayerType>
convertVectorLayer(const std::string & id,const Convertible & value,Error & error)51 optional<std::unique_ptr<Layer>> convertVectorLayer(const std::string& id, const Convertible& value, Error& error) {
52     auto sourceValue = objectMember(value, "source");
53     if (!sourceValue) {
54         error = { "layer must have a source" };
55         return {};
56     }
57 
58     optional<std::string> source = toString(*sourceValue);
59     if (!source) {
60         error = { "layer source must be a string" };
61         return {};
62     }
63 
64     std::unique_ptr<LayerType> layer = std::make_unique<LayerType>(id, *source);
65 
66     auto sourceLayerValue = objectMember(value, "source-layer");
67     if (sourceLayerValue) {
68         optional<std::string> sourceLayer = toString(*sourceLayerValue);
69         if (!sourceLayer) {
70             error = { "layer source-layer must be a string" };
71             return {};
72         }
73         layer->setSourceLayer(*sourceLayer);
74     }
75 
76     auto filterValue = objectMember(value, "filter");
77     if (filterValue) {
78         optional<Filter> filter = convert<Filter>(*filterValue, error);
79         if (!filter) {
80             return {};
81         }
82         layer->setFilter(*filter);
83     }
84 
85     return { std::move(layer) };
86 }
87 
convertRasterLayer(const std::string & id,const Convertible & value,Error & error)88 static optional<std::unique_ptr<Layer>> convertRasterLayer(const std::string& id, const Convertible& value, Error& error) {
89     auto sourceValue = objectMember(value, "source");
90     if (!sourceValue) {
91         error = { "layer must have a source" };
92         return {};
93     }
94 
95     optional<std::string> source = toString(*sourceValue);
96     if (!source) {
97         error = { "layer source must be a string" };
98         return {};
99     }
100 
101     return { std::make_unique<RasterLayer>(id, *source) };
102 }
103 
convertHillshadeLayer(const std::string & id,const Convertible & value,Error & error)104 static optional<std::unique_ptr<Layer>> convertHillshadeLayer(const std::string& id, const Convertible& value, Error& error) {
105     auto sourceValue = objectMember(value, "source");
106     if (!sourceValue) {
107         error = { "layer must have a source" };
108         return {};
109     }
110 
111     optional<std::string> source = toString(*sourceValue);
112     if (!source) {
113         error = { "layer source must be a string" };
114         return {};
115     }
116 
117     return { std::make_unique<HillshadeLayer>(id, *source) };
118 }
119 
120 
convertBackgroundLayer(const std::string & id,const Convertible &,Error &)121 static optional<std::unique_ptr<Layer>> convertBackgroundLayer(const std::string& id, const Convertible&, Error&) {
122     return { std::make_unique<BackgroundLayer>(id) };
123 }
124 
operator ()(const Convertible & value,Error & error) const125 optional<std::unique_ptr<Layer>> Converter<std::unique_ptr<Layer>>::operator()(const Convertible& value, Error& error) const {
126     if (!isObject(value)) {
127         error = { "layer must be an object" };
128         return {};
129     }
130 
131     auto idValue = objectMember(value, "id");
132     if (!idValue) {
133         error = { "layer must have an id" };
134         return {};
135     }
136 
137     optional<std::string> id = toString(*idValue);
138     if (!id) {
139         error = { "layer id must be a string" };
140         return {};
141     }
142 
143     auto typeValue = objectMember(value, "type");
144     if (!typeValue) {
145         error = { "layer must have a type" };
146         return {};
147     }
148 
149     optional<std::string> type = toString(*typeValue);
150     if (!type) {
151         error = { "layer type must be a string" };
152         return {};
153     }
154 
155     optional<std::unique_ptr<Layer>> converted;
156 
157     if (*type == "fill") {
158         converted = convertVectorLayer<FillLayer>(*id, value, error);
159     } else if (*type == "fill-extrusion") {
160         converted = convertVectorLayer<FillExtrusionLayer>(*id, value, error);
161     } else if (*type == "line") {
162         converted = convertVectorLayer<LineLayer>(*id, value, error);
163     } else if (*type == "circle") {
164         converted = convertVectorLayer<CircleLayer>(*id, value, error);
165     } else if (*type == "symbol") {
166         converted = convertVectorLayer<SymbolLayer>(*id, value, error);
167     } else if (*type == "raster") {
168         converted = convertRasterLayer(*id, value, error);
169     } else if (*type == "heatmap") {
170         converted = convertVectorLayer<HeatmapLayer>(*id, value, error);
171     } else if (*type == "hillshade") {
172         converted = convertHillshadeLayer(*id, value, error);
173     } else if (*type == "background") {
174         converted = convertBackgroundLayer(*id, value, error);
175     } else {
176         error = { "invalid layer type" };
177         return {};
178     }
179 
180     if (!converted) {
181         return converted;
182     }
183 
184     std::unique_ptr<Layer> layer = std::move(*converted);
185 
186     auto minzoomValue = objectMember(value, "minzoom");
187     if (minzoomValue) {
188         optional<float> minzoom = toNumber(*minzoomValue);
189         if (!minzoom) {
190             error = { "minzoom must be numeric" };
191             return {};
192         }
193         layer->setMinZoom(*minzoom);
194     }
195 
196     auto maxzoomValue = objectMember(value, "maxzoom");
197     if (maxzoomValue) {
198         optional<float> maxzoom = toNumber(*maxzoomValue);
199         if (!maxzoom) {
200             error = { "maxzoom must be numeric" };
201             return {};
202         }
203         layer->setMaxZoom(*maxzoom);
204     }
205 
206     auto layoutValue = objectMember(value, "layout");
207     if (layoutValue) {
208         if (!isObject(*layoutValue)) {
209             error = { "layout must be an object" };
210             return {};
211         }
212         optional<Error> error_ = eachMember(*layoutValue, [&] (const std::string& k, const Convertible& v) {
213             return setLayoutProperty(*layer, k, v);
214         });
215         if (error_) {
216             error = *error_;
217             return {};
218         }
219     }
220 
221     optional<Error> error_ = setPaintProperties(*layer, value);
222     if (error_) {
223         error = *error_;
224         return {};
225     }
226 
227     return std::move(layer);
228 }
229 
230 } // namespace conversion
231 } // namespace style
232 } // namespace mbgl
233