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