1 #include <mbgl/style/style_impl.hpp>
2 #include <mbgl/style/observer.hpp>
3 #include <mbgl/style/source_impl.hpp>
4 #include <mbgl/style/layers/symbol_layer.hpp>
5 #include <mbgl/style/layers/custom_layer.hpp>
6 #include <mbgl/style/layers/background_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/line_layer.hpp>
11 #include <mbgl/style/layers/circle_layer.hpp>
12 #include <mbgl/style/layers/raster_layer.hpp>
13 #include <mbgl/style/layers/hillshade_layer.hpp>
14 #include <mbgl/style/layer_impl.hpp>
15 #include <mbgl/style/parser.hpp>
16 #include <mbgl/style/transition_options.hpp>
17 #include <mbgl/sprite/sprite_loader.hpp>
18 #include <mbgl/util/exception.hpp>
19 #include <mbgl/util/string.hpp>
20 #include <mbgl/util/logging.hpp>
21 #include <mbgl/storage/file_source.hpp>
22 #include <mbgl/storage/resource.hpp>
23 #include <mbgl/storage/response.hpp>
24
25 namespace mbgl {
26 namespace style {
27
28 static Observer nullObserver;
29
Impl(Scheduler & scheduler_,FileSource & fileSource_,float pixelRatio)30 Style::Impl::Impl(Scheduler& scheduler_, FileSource& fileSource_, float pixelRatio)
31 : scheduler(scheduler_),
32 fileSource(fileSource_),
33 spriteLoader(std::make_unique<SpriteLoader>(pixelRatio)),
34 light(std::make_unique<Light>()),
35 observer(&nullObserver) {
36 spriteLoader->setObserver(this);
37 light->setObserver(this);
38 }
39
40 Style::Impl::~Impl() = default;
41
loadJSON(const std::string & json_)42 void Style::Impl::loadJSON(const std::string& json_) {
43 lastError = nullptr;
44 observer->onStyleLoading();
45
46 url.clear();
47 parse(json_);
48 }
49
loadURL(const std::string & url_)50 void Style::Impl::loadURL(const std::string& url_) {
51 lastError = nullptr;
52 observer->onStyleLoading();
53
54 loaded = false;
55 url = url_;
56
57 styleRequest = fileSource.request(Resource::style(url), [this](Response res) {
58 // Don't allow a loaded, mutated style to be overwritten with a new version.
59 if (mutated && loaded) {
60 return;
61 }
62
63 if (res.error) {
64 const std::string message = "loading style failed: " + res.error->message;
65 Log::Error(Event::Setup, message.c_str());
66 observer->onStyleError(std::make_exception_ptr(util::StyleLoadException(message)));
67 observer->onResourceError(std::make_exception_ptr(std::runtime_error(res.error->message)));
68 } else if (res.notModified || res.noContent) {
69 return;
70 } else {
71 parse(*res.data);
72 }
73 });
74 }
75
parse(const std::string & json_)76 void Style::Impl::parse(const std::string& json_) {
77 Parser parser;
78
79 if (auto error = parser.parse(json_)) {
80 std::string message = "Failed to parse style: " + util::toString(error);
81 Log::Error(Event::ParseStyle, message.c_str());
82 observer->onStyleError(std::make_exception_ptr(util::StyleParseException(message)));
83 observer->onResourceError(error);
84 return;
85 }
86
87 mutated = false;
88 loaded = false;
89 json = json_;
90
91 sources.clear();
92 layers.clear();
93 images.clear();
94
95 transitionOptions = {};
96 transitionOptions.duration = util::DEFAULT_TRANSITION_DURATION;
97
98 for (auto& source : parser.sources) {
99 addSource(std::move(source));
100 }
101
102 for (auto& layer : parser.layers) {
103 addLayer(std::move(layer));
104 }
105
106 name = parser.name;
107 defaultCamera.center = parser.latLng;
108 defaultCamera.zoom = parser.zoom;
109 defaultCamera.angle = parser.bearing;
110 defaultCamera.pitch = parser.pitch;
111
112 setLight(std::make_unique<Light>(parser.light));
113
114 spriteLoaded = false;
115 spriteLoader->load(parser.spriteURL, scheduler, fileSource);
116 glyphURL = parser.glyphURL;
117
118 loaded = true;
119 observer->onStyleLoaded();
120 }
121
getJSON() const122 std::string Style::Impl::getJSON() const {
123 return json;
124 }
125
getURL() const126 std::string Style::Impl::getURL() const {
127 return url;
128 }
129
setTransitionOptions(const TransitionOptions & options)130 void Style::Impl::setTransitionOptions(const TransitionOptions& options) {
131 transitionOptions = options;
132 }
133
getTransitionOptions() const134 TransitionOptions Style::Impl::getTransitionOptions() const {
135 return transitionOptions;
136 }
137
addSource(std::unique_ptr<Source> source)138 void Style::Impl::addSource(std::unique_ptr<Source> source) {
139 if (sources.get(source->getID())) {
140 std::string msg = "Source " + source->getID() + " already exists";
141 throw std::runtime_error(msg.c_str());
142 }
143
144 source->setObserver(this);
145 source->loadDescription(fileSource);
146
147 sources.add(std::move(source));
148 }
149
150 struct SourceIdUsageEvaluator {
151 const std::string& sourceId;
152
operator ()mbgl::style::SourceIdUsageEvaluator153 bool operator()(BackgroundLayer&) { return false; }
operator ()mbgl::style::SourceIdUsageEvaluator154 bool operator()(CustomLayer&) { return false; }
155
156 template <class LayerType>
operator ()mbgl::style::SourceIdUsageEvaluator157 bool operator()(LayerType& layer) {
158 return layer.getSourceID() == sourceId;
159 }
160 };
161
removeSource(const std::string & id)162 std::unique_ptr<Source> Style::Impl::removeSource(const std::string& id) {
163 // Check if source is in use
164 SourceIdUsageEvaluator sourceIdEvaluator {id};
165 auto layerIt = std::find_if(layers.begin(), layers.end(), [&](const auto& layer) {
166 return layer->accept(sourceIdEvaluator);
167 });
168
169 if (layerIt != layers.end()) {
170 Log::Warning(Event::General, "Source '%s' is in use, cannot remove", id.c_str());
171 return nullptr;
172 }
173
174 std::unique_ptr<Source> source = sources.remove(id);
175
176 if (source) {
177 source->setObserver(nullptr);
178 }
179
180 return source;
181 }
182
getLayers()183 std::vector<Layer*> Style::Impl::getLayers() {
184 return layers.getWrappers();
185 }
186
getLayers() const187 std::vector<const Layer*> Style::Impl::getLayers() const {
188 auto wrappers = layers.getWrappers();
189 return std::vector<const Layer*>(wrappers.begin(), wrappers.end());
190 }
191
getLayer(const std::string & id) const192 Layer* Style::Impl::getLayer(const std::string& id) const {
193 return layers.get(id);
194 }
195
addLayer(std::unique_ptr<Layer> layer,optional<std::string> before)196 Layer* Style::Impl::addLayer(std::unique_ptr<Layer> layer, optional<std::string> before) {
197 // TODO: verify source
198
199 if (layers.get(layer->getID())) {
200 throw std::runtime_error(std::string{"Layer "} + layer->getID() + " already exists");
201 }
202
203 layer->setObserver(this);
204 Layer* result = layers.add(std::move(layer), before);
205 observer->onUpdate();
206
207 return result;
208 }
209
removeLayer(const std::string & id)210 std::unique_ptr<Layer> Style::Impl::removeLayer(const std::string& id) {
211 std::unique_ptr<Layer> layer = layers.remove(id);
212
213 if (layer) {
214 layer->setObserver(nullptr);
215 observer->onUpdate();
216 }
217
218 return layer;
219 }
220
setLight(std::unique_ptr<Light> light_)221 void Style::Impl::setLight(std::unique_ptr<Light> light_) {
222 light = std::move(light_);
223 light->setObserver(this);
224 onLightChanged(*light);
225 }
226
getLight() const227 Light* Style::Impl::getLight() const {
228 return light.get();
229 }
230
getName() const231 std::string Style::Impl::getName() const {
232 return name;
233 }
234
getDefaultCamera() const235 CameraOptions Style::Impl::getDefaultCamera() const {
236 return defaultCamera;
237 }
238
getSources()239 std::vector<Source*> Style::Impl::getSources() {
240 return sources.getWrappers();
241 }
242
getSources() const243 std::vector<const Source*> Style::Impl::getSources() const {
244 auto wrappers = sources.getWrappers();
245 return std::vector<const Source*>(wrappers.begin(), wrappers.end());
246 }
247
getSource(const std::string & id) const248 Source* Style::Impl::getSource(const std::string& id) const {
249 return sources.get(id);
250 }
251
isLoaded() const252 bool Style::Impl::isLoaded() const {
253 if (!loaded) {
254 return false;
255 }
256
257 if (!spriteLoaded) {
258 return false;
259 }
260
261 for (const auto& source: sources) {
262 if (!source->loaded) {
263 return false;
264 }
265 }
266
267 return true;
268 }
269
addImage(std::unique_ptr<style::Image> image)270 void Style::Impl::addImage(std::unique_ptr<style::Image> image) {
271 images.remove(image->getID()); // We permit using addImage to update.
272 images.add(std::move(image));
273 }
274
removeImage(const std::string & id)275 void Style::Impl::removeImage(const std::string& id) {
276 images.remove(id);
277 }
278
getImage(const std::string & id) const279 const style::Image* Style::Impl::getImage(const std::string& id) const {
280 return images.get(id);
281 }
282
setObserver(style::Observer * observer_)283 void Style::Impl::setObserver(style::Observer* observer_) {
284 observer = observer_;
285 }
286
onSourceLoaded(Source & source)287 void Style::Impl::onSourceLoaded(Source& source) {
288 sources.update(source);
289 observer->onSourceLoaded(source);
290 observer->onUpdate();
291 }
292
onSourceChanged(Source & source)293 void Style::Impl::onSourceChanged(Source& source) {
294 sources.update(source);
295 observer->onSourceChanged(source);
296 observer->onUpdate();
297 }
298
onSourceError(Source & source,std::exception_ptr error)299 void Style::Impl::onSourceError(Source& source, std::exception_ptr error) {
300 lastError = error;
301 Log::Error(Event::Style, "Failed to load source %s: %s",
302 source.getID().c_str(), util::toString(error).c_str());
303 observer->onSourceError(source, error);
304 observer->onResourceError(error);
305 }
306
onSourceDescriptionChanged(Source & source)307 void Style::Impl::onSourceDescriptionChanged(Source& source) {
308 sources.update(source);
309 observer->onSourceDescriptionChanged(source);
310 if (!source.loaded) {
311 source.loadDescription(fileSource);
312 }
313 }
314
onSpriteLoaded(std::vector<std::unique_ptr<Image>> && images_)315 void Style::Impl::onSpriteLoaded(std::vector<std::unique_ptr<Image>>&& images_) {
316 for (auto& image : images_) {
317 addImage(std::move(image));
318 }
319 spriteLoaded = true;
320 observer->onUpdate(); // For *-pattern properties.
321 }
322
onSpriteError(std::exception_ptr error)323 void Style::Impl::onSpriteError(std::exception_ptr error) {
324 lastError = error;
325 Log::Error(Event::Style, "Failed to load sprite: %s", util::toString(error).c_str());
326 observer->onResourceError(error);
327 }
328
onLayerChanged(Layer & layer)329 void Style::Impl::onLayerChanged(Layer& layer) {
330 layers.update(layer);
331 observer->onUpdate();
332 }
333
onLightChanged(const Light &)334 void Style::Impl::onLightChanged(const Light&) {
335 observer->onUpdate();
336 }
337
dumpDebugLogs() const338 void Style::Impl::dumpDebugLogs() const {
339 Log::Info(Event::General, "styleURL: %s", url.c_str());
340 for (const auto& source : sources) {
341 source->dumpDebugLogs();
342 }
343 }
344
getGlyphURL() const345 const std::string& Style::Impl::getGlyphURL() const {
346 return glyphURL;
347 }
348
getImageImpls() const349 Immutable<std::vector<Immutable<Image::Impl>>> Style::Impl::getImageImpls() const {
350 return images.getImpls();
351 }
352
getSourceImpls() const353 Immutable<std::vector<Immutable<Source::Impl>>> Style::Impl::getSourceImpls() const {
354 return sources.getImpls();
355 }
356
getLayerImpls() const357 Immutable<std::vector<Immutable<Layer::Impl>>> Style::Impl::getLayerImpls() const {
358 return layers.getImpls();
359 }
360
361 } // namespace style
362 } // namespace mbgl
363