diff options
24 files changed, 243 insertions, 170 deletions
diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp index 62bb39e8c..0636b80f5 100644 --- a/include/mbgl/map/map.hpp +++ b/include/mbgl/map/map.hpp @@ -34,7 +34,7 @@ public: explicit Map(RendererFrontend&, MapObserver&, const MapOptions&, - const ResourceOptions&); + const ResourceOptions &resourceOptions = ResourceOptions()); ~Map(); // Register a callback that will get called (on the render thread) when all resources have @@ -48,8 +48,9 @@ public: style::Style& getStyle(); const style::Style& getStyle() const; + std::shared_ptr<style::Style> getStylePointer(); - void setStyle(std::unique_ptr<style::Style>); + void setStyle(const std::shared_ptr<mbgl::style::Style>&); // Transition void cancelTransitions(); diff --git a/include/mbgl/style/style.hpp b/include/mbgl/style/style.hpp index 83d6ad5bb..1b39c3cbf 100644 --- a/include/mbgl/style/style.hpp +++ b/include/mbgl/style/style.hpp @@ -11,6 +11,7 @@ namespace mbgl { class FileSource; +class ResourceOptions; namespace style { @@ -18,10 +19,12 @@ class Light; class Image; class Source; class Layer; +class StyleImpl; class Style { public: Style(std::shared_ptr<FileSource>, float pixelRatio); + Style(const ResourceOptions& resourceOptions, float pixelRatio); ~Style(); void loadJSON(const std::string&); @@ -70,8 +73,7 @@ public: std::unique_ptr<Layer> removeLayer(const std::string& layerID); // Private implementation - class Impl; - const std::unique_ptr<Impl> impl; + const std::unique_ptr<StyleImpl> impl; }; } // namespace style diff --git a/src/mbgl/annotation/annotation_manager.cpp b/src/mbgl/annotation/annotation_manager.cpp index b5dfea8e1..a2b26aabf 100644 --- a/src/mbgl/annotation/annotation_manager.cpp +++ b/src/mbgl/annotation/annotation_manager.cpp @@ -31,17 +31,12 @@ const std::string AnnotationManager::SourceID = "com.mapbox.annotations"; const std::string AnnotationManager::PointLayerID = "com.mapbox.annotations.points"; const std::string AnnotationManager::ShapeLayerID = "com.mapbox.annotations.shape."; -AnnotationManager::AnnotationManager(Style& style_) +AnnotationManager::AnnotationManager(StyleImpl& style_) : style(style_) { }; AnnotationManager::~AnnotationManager() = default; -void AnnotationManager::setStyle(Style& style_) { - CHECK_ANNOTATIONS_ENABLED_AND_RETURN(); - style = style_; -} - void AnnotationManager::onStyleLoaded() { CHECK_ANNOTATIONS_ENABLED_AND_RETURN(); updateStyle(); @@ -83,13 +78,13 @@ void AnnotationManager::add(const AnnotationID& id, const SymbolAnnotation& anno void AnnotationManager::add(const AnnotationID& id, const LineAnnotation& annotation) { ShapeAnnotationImpl& impl = *shapeAnnotations.emplace(id, std::make_unique<LineAnnotationImpl>(id, annotation)).first->second; - impl.updateStyle(*style.get().impl); + impl.updateStyle(style); } void AnnotationManager::add(const AnnotationID& id, const FillAnnotation& annotation) { ShapeAnnotationImpl& impl = *shapeAnnotations.emplace(id, std::make_unique<FillAnnotationImpl>(id, annotation)).first->second; - impl.updateStyle(*style.get().impl); + impl.updateStyle(style); } void AnnotationManager::update(const AnnotationID& id, const SymbolAnnotation& annotation) { @@ -140,7 +135,7 @@ void AnnotationManager::remove(const AnnotationID& id) { symbolAnnotations.erase(id); } else if (shapeAnnotations.find(id) != shapeAnnotations.end()) { auto it = shapeAnnotations.find(id); - *style.get().impl->removeLayer(it->second->layerID); + style.removeLayer(it->second->layerID); shapeAnnotations.erase(it); } else { assert(false); // Should never happen @@ -178,8 +173,8 @@ std::unique_ptr<AnnotationTileData> AnnotationManager::getTileData(const Canonic void AnnotationManager::updateStyle() { // Create annotation source, point layer, and point bucket. We do everything via Style::Impl // because we don't want annotation mutations to trigger Style::Impl::styleMutated to be set. - if (!style.get().impl->getSource(SourceID)) { - style.get().impl->addSource(std::make_unique<AnnotationSource>()); + if (!style.getSource(SourceID)) { + style.addSource(std::make_unique<AnnotationSource>()); std::unique_ptr<SymbolLayer> layer = std::make_unique<SymbolLayer>(PointLayerID, SourceID); @@ -190,13 +185,13 @@ void AnnotationManager::updateStyle() { layer->setIconAllowOverlap(true); layer->setIconIgnorePlacement(true); - style.get().impl->addLayer(std::move(layer)); + style.addLayer(std::move(layer)); } std::lock_guard<std::mutex> lock(mutex); for (const auto& shape : shapeAnnotations) { - shape.second->updateStyle(*style.get().impl); + shape.second->updateStyle(style); } for (const auto& image : images) { @@ -206,7 +201,7 @@ void AnnotationManager::updateStyle() { // of which images need to be added because we don't know if the style is the same // instance as in the last updateStyle call. If it's a new style, we need to add all // images.) - style.get().impl->addImage(std::make_unique<style::Image>(image.second)); + style.addImage(std::make_unique<style::Image>(image.second)); } } @@ -247,7 +242,7 @@ void AnnotationManager::addImage(std::unique_ptr<style::Image> image) { images.erase(id); auto inserted = images.emplace(id, style::Image(id, image->getImage().clone(), image->getPixelRatio(), image->isSdf())); - style.get().impl->addImage(std::make_unique<style::Image>(inserted.first->second)); + style.addImage(std::make_unique<style::Image>(inserted.first->second)); } void AnnotationManager::removeImage(const std::string& id_) { @@ -255,7 +250,7 @@ void AnnotationManager::removeImage(const std::string& id_) { std::lock_guard<std::mutex> lock(mutex); const std::string id = prefixedImageID(id_); images.erase(id); - style.get().impl->removeImage(id); + style.removeImage(id); } double AnnotationManager::getTopOffsetPixelsForImage(const std::string& id_) { diff --git a/src/mbgl/annotation/annotation_manager.hpp b/src/mbgl/annotation/annotation_manager.hpp index 6c794d7f8..86a378e98 100644 --- a/src/mbgl/annotation/annotation_manager.hpp +++ b/src/mbgl/annotation/annotation_manager.hpp @@ -21,11 +21,12 @@ class ShapeAnnotationImpl; namespace style { class Style; +class StyleImpl; } // namespace style class AnnotationManager : private util::noncopyable { public: - AnnotationManager(style::Style&); + AnnotationManager(style::StyleImpl&); ~AnnotationManager(); AnnotationID addAnnotation(const Annotation&); @@ -36,7 +37,6 @@ public: void removeImage(const std::string&); double getTopOffsetPixelsForImage(const std::string&); - void setStyle(style::Style&); void onStyleLoaded(); void updateData(); @@ -63,7 +63,7 @@ private: std::unique_ptr<AnnotationTileData> getTileData(const CanonicalTileID&); - std::reference_wrapper<style::Style> style; + style::StyleImpl& style; std::mutex mutex; diff --git a/src/mbgl/annotation/fill_annotation_impl.cpp b/src/mbgl/annotation/fill_annotation_impl.cpp index 59b8133cf..7c3e4265d 100644 --- a/src/mbgl/annotation/fill_annotation_impl.cpp +++ b/src/mbgl/annotation/fill_annotation_impl.cpp @@ -12,7 +12,7 @@ FillAnnotationImpl::FillAnnotationImpl(AnnotationID id_, FillAnnotation annotati annotation(ShapeAnnotationGeometry::visit(annotation_.geometry, CloseShapeAnnotation{}), annotation_.opacity, annotation_.color, annotation_.outlineColor) { } -void FillAnnotationImpl::updateStyle(Style::Impl& style) const { +void FillAnnotationImpl::updateStyle(StyleImpl& style) const { Layer* layer = style.getLayer(layerID); if (!layer) { diff --git a/src/mbgl/annotation/fill_annotation_impl.hpp b/src/mbgl/annotation/fill_annotation_impl.hpp index 98f992151..3c672dbff 100644 --- a/src/mbgl/annotation/fill_annotation_impl.hpp +++ b/src/mbgl/annotation/fill_annotation_impl.hpp @@ -9,7 +9,7 @@ class FillAnnotationImpl : public ShapeAnnotationImpl { public: FillAnnotationImpl(AnnotationID, FillAnnotation); - void updateStyle(style::Style::Impl&) const final; + void updateStyle(style::StyleImpl&) const final; const ShapeAnnotationGeometry& geometry() const final; private: diff --git a/src/mbgl/annotation/line_annotation_impl.cpp b/src/mbgl/annotation/line_annotation_impl.cpp index 533a137a3..a03dd13e6 100644 --- a/src/mbgl/annotation/line_annotation_impl.cpp +++ b/src/mbgl/annotation/line_annotation_impl.cpp @@ -12,7 +12,7 @@ LineAnnotationImpl::LineAnnotationImpl(AnnotationID id_, LineAnnotation annotati annotation(ShapeAnnotationGeometry::visit(annotation_.geometry, CloseShapeAnnotation{}), annotation_.opacity, annotation_.width, annotation_.color) { } -void LineAnnotationImpl::updateStyle(Style::Impl& style) const { +void LineAnnotationImpl::updateStyle(StyleImpl& style) const { Layer* layer = style.getLayer(layerID); if (!layer) { diff --git a/src/mbgl/annotation/line_annotation_impl.hpp b/src/mbgl/annotation/line_annotation_impl.hpp index 108787c42..0460428cf 100644 --- a/src/mbgl/annotation/line_annotation_impl.hpp +++ b/src/mbgl/annotation/line_annotation_impl.hpp @@ -9,7 +9,7 @@ class LineAnnotationImpl : public ShapeAnnotationImpl { public: LineAnnotationImpl(AnnotationID, LineAnnotation); - void updateStyle(style::Style::Impl&) const final; + void updateStyle(style::StyleImpl&) const final; const ShapeAnnotationGeometry& geometry() const final; private: diff --git a/src/mbgl/annotation/shape_annotation_impl.hpp b/src/mbgl/annotation/shape_annotation_impl.hpp index 3e28221f7..3c1ca760f 100644 --- a/src/mbgl/annotation/shape_annotation_impl.hpp +++ b/src/mbgl/annotation/shape_annotation_impl.hpp @@ -20,7 +20,7 @@ public: ShapeAnnotationImpl(const AnnotationID); virtual ~ShapeAnnotationImpl() = default; - virtual void updateStyle(style::Style::Impl&) const = 0; + virtual void updateStyle(style::StyleImpl&) const = 0; virtual const ShapeAnnotationGeometry& geometry() const = 0; void updateTileData(const CanonicalTileID&, AnnotationTileData&); diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index 061669f56..f48cd8668 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -33,7 +33,8 @@ Map::Map(RendererFrontend& frontend, : impl(std::make_unique<Impl>( frontend, observer, - FileSourceManager::get() ? FileSourceManager::get()->getFileSource(ResourceLoader, resourceOptions) : nullptr, +// FileSourceManager::get() ? FileSourceManager::get()->getFileSource(ResourceLoader, resourceOptions) : nullptr, + resourceOptions, mapOptions)) {} Map::Map(std::unique_ptr<Impl> impl_) : impl(std::move(impl_)) {} @@ -87,13 +88,14 @@ const style::Style& Map::getStyle() const { return *impl->style; } -void Map::setStyle(std::unique_ptr<Style> style) { +std::shared_ptr<Style> Map::getStylePointer() +{ + return impl->style; +} + +void Map::setStyle(const std::shared_ptr<Style>& style) { assert(style); - impl->onStyleLoading(); - impl->style = std::move(style); - if (LayerManager::annotationsEnabled) { - impl->annotationManager.setStyle(*impl->style); - } + impl->setStyle(style); } #pragma mark - Transitions @@ -399,26 +401,26 @@ std::vector<LatLng> Map::latLngsForPixels(const std::vector<ScreenCoordinate>& s void Map::addAnnotationImage(std::unique_ptr<style::Image> image) { if (LayerManager::annotationsEnabled) { - impl->annotationManager.addImage(std::move(image)); + impl->style->impl->annotationManager.addImage(std::move(image)); } } void Map::removeAnnotationImage(const std::string& id) { if (LayerManager::annotationsEnabled) { - impl->annotationManager.removeImage(id); + impl->style->impl->annotationManager.removeImage(id); } } double Map::getTopOffsetPixelsForAnnotationImage(const std::string& id) { if (LayerManager::annotationsEnabled) { - return impl->annotationManager.getTopOffsetPixelsForImage(id); + return impl->style->impl->annotationManager.getTopOffsetPixelsForImage(id); } return 0.0; } AnnotationID Map::addAnnotation(const Annotation& annotation) { if (LayerManager::annotationsEnabled) { - auto result = impl->annotationManager.addAnnotation(annotation); + auto result = impl->style->impl->annotationManager.addAnnotation(annotation); impl->onUpdate(); return result; } @@ -427,7 +429,7 @@ AnnotationID Map::addAnnotation(const Annotation& annotation) { void Map::updateAnnotation(AnnotationID id, const Annotation& annotation) { if (LayerManager::annotationsEnabled) { - if (impl->annotationManager.updateAnnotation(id, annotation)) { + if (impl->style->impl->annotationManager.updateAnnotation(id, annotation)) { impl->onUpdate(); } } @@ -435,7 +437,7 @@ void Map::updateAnnotation(AnnotationID id, const Annotation& annotation) { void Map::removeAnnotation(AnnotationID annotation) { if (LayerManager::annotationsEnabled) { - impl->annotationManager.removeAnnotation(annotation); + impl->style->impl->annotationManager.removeAnnotation(annotation); impl->onUpdate(); } } diff --git a/src/mbgl/map/map_impl.cpp b/src/mbgl/map/map_impl.cpp index bc2a37fe0..37e3ae9e6 100644 --- a/src/mbgl/map/map_impl.cpp +++ b/src/mbgl/map/map_impl.cpp @@ -9,7 +9,7 @@ namespace mbgl { Map::Impl::Impl(RendererFrontend& frontend_, MapObserver& observer_, - std::shared_ptr<FileSource> fileSource_, + const ResourceOptions &resourceOptions_, const MapOptions& mapOptions) : observer(observer_), rendererFrontend(frontend_), @@ -17,11 +17,27 @@ Map::Impl::Impl(RendererFrontend& frontend_, mode(mapOptions.mapMode()), pixelRatio(mapOptions.pixelRatio()), crossSourceCollisions(mapOptions.crossSourceCollisions()), - fileSource(std::move(fileSource_)), - style(std::make_unique<style::Style>(fileSource, pixelRatio)), - annotationManager(*style) { + style(std::make_shared<style::Style>(resourceOptions_, pixelRatio)) { + init(mapOptions); +} + +Map::Impl::Impl(RendererFrontend &frontend_, + MapObserver &observer_, + std::shared_ptr<FileSource> fileSource_, + const MapOptions &mapOptions) + : observer(observer_), + rendererFrontend(frontend_), + transform(observer, mapOptions.constrainMode(), mapOptions.viewportMode()), + mode(mapOptions.mapMode()), + pixelRatio(mapOptions.pixelRatio()), + crossSourceCollisions(mapOptions.crossSourceCollisions()), + style(std::make_shared<style::Style>(fileSource_, pixelRatio)) { + init(mapOptions); +} + +void Map::Impl::init(const MapOptions& mapOptions) { transform.setNorthOrientation(mapOptions.northOrientation()); - style->impl->setObserver(this); + style->impl->addObserver(this); rendererFrontend.setObserver(*this); transform.resize(mapOptions.size()); } @@ -62,8 +78,8 @@ void Map::Impl::onUpdate() { style->impl->getImageImpls(), style->impl->getSourceImpls(), style->impl->getLayerImpls(), - annotationManager, - fileSource, + style->impl->annotationManager, + style->impl->fileSource, prefetchZoomDelta, bool(stillImageRequest), crossSourceCollisions @@ -82,9 +98,7 @@ void Map::Impl::onStyleLoaded() { if (!cameraMutated) { jumpTo(style->getDefaultCamera()); } - if (LayerManager::annotationsEnabled) { - annotationManager.onStyleLoaded(); - } + observer.onDidFinishLoadingStyle(); } @@ -169,6 +183,18 @@ void Map::Impl::jumpTo(const CameraOptions& camera) { onUpdate(); } +void Map::Impl::setStyle(const std::shared_ptr<style::Style>& style_) +{ + onStyleLoading(); + style->impl->removeObserver(this); + style = style_; + style->impl->addObserver(this); + if (style->impl->isLoaded()) + onStyleLoaded(); + else if (style->impl->getLastError()) + onStyleError(style->impl->getLastError()); +} + void Map::Impl::onStyleImageMissing(const std::string& id, std::function<void()> done) { if (style->getImage(id) == nullptr) { diff --git a/src/mbgl/map/map_impl.hpp b/src/mbgl/map/map_impl.hpp index 416662f9e..4cb0b6389 100644 --- a/src/mbgl/map/map_impl.hpp +++ b/src/mbgl/map/map_impl.hpp @@ -1,6 +1,5 @@ #pragma once -#include <mbgl/annotation/annotation_manager.hpp> #include <mbgl/map/map.hpp> #include <mbgl/map/map_observer.hpp> #include <mbgl/map/map_options.hpp> @@ -28,7 +27,14 @@ struct StillImageRequest { class Map::Impl : public style::Observer, public RendererObserver { public: - Impl(RendererFrontend&, MapObserver&, std::shared_ptr<FileSource>, const MapOptions&); + Impl(RendererFrontend&, + MapObserver&, + const ResourceOptions&, + const MapOptions&); + Impl(RendererFrontend&, + MapObserver&, + std::shared_ptr<FileSource>, + const MapOptions&); // Used in tests ~Impl() final; // StyleObserver @@ -50,6 +56,7 @@ public: // Map void jumpTo(const CameraOptions&); + void setStyle(const std::shared_ptr<style::Style>& style); MapObserver& observer; RendererFrontend& rendererFrontend; @@ -62,10 +69,7 @@ public: MapDebugOptions debugOptions { MapDebugOptions::NoDebug }; - std::shared_ptr<FileSource> fileSource; - - std::unique_ptr<style::Style> style; - AnnotationManager annotationManager; + std::shared_ptr<style::Style> style; bool cameraMutated = false; @@ -74,6 +78,9 @@ public: bool loading = false; bool rendererFullyLoaded; std::unique_ptr<StillImageRequest> stillImageRequest; + +private: + void init(const MapOptions&); }; } // namespace mbgl diff --git a/src/mbgl/style/style.cpp b/src/mbgl/style/style.cpp index 8a821e5a5..6649e2dd1 100644 --- a/src/mbgl/style/style.cpp +++ b/src/mbgl/style/style.cpp @@ -4,12 +4,18 @@ #include <mbgl/style/image.hpp> #include <mbgl/style/source.hpp> #include <mbgl/style/layer.hpp> +#include <mbgl/storage/file_source_manager.hpp> +#include <mbgl/storage/resource_options.hpp> namespace mbgl { namespace style { Style::Style(std::shared_ptr<FileSource> fileSource, float pixelRatio) - : impl(std::make_unique<Impl>(std::move(fileSource), pixelRatio)) {} + : impl(std::make_unique<StyleImpl>(std::move(fileSource), pixelRatio)) {} + +Style::Style(const ResourceOptions &resourceOptions, float pixelRatio) + : impl(std::make_unique<StyleImpl>(FileSourceManager::get() ? FileSourceManager::get()->getFileSource(ResourceLoader, resourceOptions) : nullptr, + pixelRatio)) {} Style::~Style() = default; @@ -79,7 +85,7 @@ std::vector<Source*> Style::getSources() { } std::vector<const Source*> Style::getSources() const { - return const_cast<const Impl&>(*impl).getSources(); + return const_cast<const StyleImpl&>(*impl).getSources(); } Source* Style::getSource(const std::string& id) { @@ -107,7 +113,7 @@ std::vector<Layer*> Style::getLayers() { } std::vector<const Layer*> Style::getLayers() const { - return const_cast<const Impl&>(*impl).getLayers(); + return const_cast<const StyleImpl&>(*impl).getLayers(); } Layer* Style::getLayer(const std::string& layerID) { diff --git a/src/mbgl/style/style_impl.cpp b/src/mbgl/style/style_impl.cpp index d5961b590..13cd7bc4e 100644 --- a/src/mbgl/style/style_impl.cpp +++ b/src/mbgl/style/style_impl.cpp @@ -30,34 +30,38 @@ namespace style { static Observer nullObserver; -Style::Impl::Impl(std::shared_ptr<FileSource> fileSource_, float pixelRatio) - : fileSource(std::move(fileSource_)), +StyleImpl::StyleImpl(std::shared_ptr<FileSource> fileSource_, float pixelRatio) + : annotationManager(*this), + fileSource(std::move(fileSource_)), spriteLoader(std::make_unique<SpriteLoader>(pixelRatio)), - light(std::make_unique<Light>()), - observer(&nullObserver) { + light(std::make_unique<Light>()) { spriteLoader->setObserver(this); light->setObserver(this); } -Style::Impl::~Impl() = default; +StyleImpl::~StyleImpl() = default; -void Style::Impl::loadJSON(const std::string& json_) { +void StyleImpl::loadJSON(const std::string& json_) { lastError = nullptr; - observer->onStyleLoading(); + for (auto &observer: observers) + observer->onStyleLoading(); url.clear(); parse(json_); } -void Style::Impl::loadURL(const std::string& url_) { +void StyleImpl::loadURL(const std::string& url_) { if (!fileSource) { - observer->onStyleError( - std::make_exception_ptr(util::StyleLoadException("Unable to find resource provider for style url."))); + for (auto &observer: observers) { + observer->onStyleError( + std::make_exception_ptr(util::StyleLoadException("Unable to find resource provider for style url."))); + } return; } lastError = nullptr; - observer->onStyleLoading(); + for (auto &observer: observers) + observer->onStyleLoading(); loaded = false; url = url_; @@ -71,8 +75,10 @@ void Style::Impl::loadURL(const std::string& url_) { if (res.error) { const std::string message = "loading style failed: " + res.error->message; Log::Error(Event::Setup, message.c_str()); - observer->onStyleError(std::make_exception_ptr(util::StyleLoadException(message))); - observer->onResourceError(std::make_exception_ptr(std::runtime_error(res.error->message))); + for (auto &observer: observers) { + observer->onStyleError(std::make_exception_ptr(util::StyleLoadException(message))); + observer->onResourceError(std::make_exception_ptr(std::runtime_error(res.error->message))); + } } else if (res.notModified || res.noContent) { return; } else { @@ -81,14 +87,16 @@ void Style::Impl::loadURL(const std::string& url_) { }); } -void Style::Impl::parse(const std::string& json_) { +void StyleImpl::parse(const std::string& json_) { Parser parser; if (auto error = parser.parse(json_)) { std::string message = "Failed to parse style: " + util::toString(error); Log::Error(Event::ParseStyle, message.c_str()); - observer->onStyleError(std::make_exception_ptr(util::StyleParseException(message))); - observer->onResourceError(error); + for (auto &observer: observers) { + observer->onStyleError(std::make_exception_ptr(util::StyleParseException(message))); + observer->onResourceError(error); + } return; } @@ -127,26 +135,29 @@ void Style::Impl::parse(const std::string& json_) { glyphURL = parser.glyphURL; loaded = true; - observer->onStyleLoaded(); + + annotationManager.onStyleLoaded(); + for (auto &observer: observers) + observer->onStyleLoaded(); } -std::string Style::Impl::getJSON() const { +std::string StyleImpl::getJSON() const { return json; } -std::string Style::Impl::getURL() const { +std::string StyleImpl::getURL() const { return url; } -void Style::Impl::setTransitionOptions(const TransitionOptions& options) { +void StyleImpl::setTransitionOptions(const TransitionOptions& options) { transitionOptions = options; } -TransitionOptions Style::Impl::getTransitionOptions() const { +TransitionOptions StyleImpl::getTransitionOptions() const { return transitionOptions; } -void Style::Impl::addSource(std::unique_ptr<Source> source) { +void StyleImpl::addSource(std::unique_ptr<Source> source) { if (sources.get(source->getID())) { std::string msg = "Source " + source->getID() + " already exists"; throw std::runtime_error(msg.c_str()); @@ -159,7 +170,7 @@ void Style::Impl::addSource(std::unique_ptr<Source> source) { } } -std::unique_ptr<Source> Style::Impl::removeSource(const std::string& id) { +std::unique_ptr<Source> StyleImpl::removeSource(const std::string& id) { // Check if source is in use for (const auto& layer: layers) { if (layer->getSourceID() == id) { @@ -177,20 +188,20 @@ std::unique_ptr<Source> Style::Impl::removeSource(const std::string& id) { return source; } -std::vector<Layer*> Style::Impl::getLayers() { +std::vector<Layer*> StyleImpl::getLayers() { return layers.getWrappers(); } -std::vector<const Layer*> Style::Impl::getLayers() const { +std::vector<const Layer*> StyleImpl::getLayers() const { auto wrappers = layers.getWrappers(); return std::vector<const Layer*>(wrappers.begin(), wrappers.end()); } -Layer* Style::Impl::getLayer(const std::string& id) const { +Layer* StyleImpl::getLayer(const std::string& id) const { return layers.get(id); } -Layer* Style::Impl::addLayer(std::unique_ptr<Layer> layer, optional<std::string> before) { +Layer* StyleImpl::addLayer(std::unique_ptr<Layer> layer, optional<std::string> before) { // TODO: verify source if (Source* source = sources.get(layer->getSourceID())) { if (!source->supportsLayerType(layer->baseImpl->getTypeInfo())) { @@ -208,54 +219,56 @@ Layer* Style::Impl::addLayer(std::unique_ptr<Layer> layer, optional<std::string> layer->setObserver(this); Layer* result = layers.add(std::move(layer), before); - observer->onUpdate(); + for (auto &observer: observers) + observer->onUpdate(); return result; } -std::unique_ptr<Layer> Style::Impl::removeLayer(const std::string& id) { +std::unique_ptr<Layer> StyleImpl::removeLayer(const std::string& id) { std::unique_ptr<Layer> layer = layers.remove(id); if (layer) { layer->setObserver(nullptr); - observer->onUpdate(); + for (auto &observer: observers) + observer->onUpdate(); } return layer; } -void Style::Impl::setLight(std::unique_ptr<Light> light_) { +void StyleImpl::setLight(std::unique_ptr<Light> light_) { light = std::move(light_); light->setObserver(this); onLightChanged(*light); } -Light* Style::Impl::getLight() const { +Light* StyleImpl::getLight() const { return light.get(); } -std::string Style::Impl::getName() const { +std::string StyleImpl::getName() const { return name; } -CameraOptions Style::Impl::getDefaultCamera() const { +CameraOptions StyleImpl::getDefaultCamera() const { return defaultCamera; } -std::vector<Source*> Style::Impl::getSources() { +std::vector<Source*> StyleImpl::getSources() { return sources.getWrappers(); } -std::vector<const Source*> Style::Impl::getSources() const { +std::vector<const Source*> StyleImpl::getSources() const { auto wrappers = sources.getWrappers(); return std::vector<const Source*>(wrappers.begin(), wrappers.end()); } -Source* Style::Impl::getSource(const std::string& id) const { +Source* StyleImpl::getSource(const std::string& id) const { return sources.get(id); } -bool Style::Impl::isLoaded() const { +bool StyleImpl::isLoaded() const { if (!loaded) { return false; } @@ -273,98 +286,116 @@ bool Style::Impl::isLoaded() const { return true; } -void Style::Impl::addImage(std::unique_ptr<style::Image> image) { +void StyleImpl::addImage(std::unique_ptr<style::Image> image) { images.remove(image->getID()); // We permit using addImage to update. images.add(std::move(image)); - observer->onUpdate(); + for (auto &observer: observers) + observer->onUpdate(); } -void Style::Impl::removeImage(const std::string& id) { +void StyleImpl::removeImage(const std::string& id) { images.remove(id); } -const style::Image* Style::Impl::getImage(const std::string& id) const { +const style::Image* StyleImpl::getImage(const std::string& id) const { return images.get(id); } -void Style::Impl::setObserver(style::Observer* observer_) { - observer = observer_; +void StyleImpl::addObserver(style::Observer* observer) { + observers.insert(observer); +} + +void StyleImpl::removeObserver(Observer *observer) +{ + observers.erase(observer); } -void Style::Impl::onSourceLoaded(Source& source) { +void StyleImpl::onSourceLoaded(Source& source) { sources.update(source); - observer->onSourceLoaded(source); - observer->onUpdate(); + for (auto &observer: observers) + observer->onSourceLoaded(source); + for (auto &observer: observers) + observer->onUpdate(); } -void Style::Impl::onSourceChanged(Source& source) { +void StyleImpl::onSourceChanged(Source& source) { sources.update(source); - observer->onSourceChanged(source); - observer->onUpdate(); + for (auto &observer: observers) + observer->onSourceChanged(source); + for (auto &observer: observers) + observer->onUpdate(); } -void Style::Impl::onSourceError(Source& source, std::exception_ptr error) { +void StyleImpl::onSourceError(Source& source, std::exception_ptr error) { lastError = error; Log::Error(Event::Style, "Failed to load source %s: %s", source.getID().c_str(), util::toString(error).c_str()); - observer->onSourceError(source, error); - observer->onResourceError(error); + for (auto &observer: observers) + observer->onSourceError(source, error); + for (auto &observer: observers) + observer->onResourceError(error); } -void Style::Impl::onSourceDescriptionChanged(Source& source) { +void StyleImpl::onSourceDescriptionChanged(Source& source) { sources.update(source); - observer->onSourceDescriptionChanged(source); + for (auto &observer: observers) + observer->onSourceDescriptionChanged(source); if (!source.loaded && fileSource) { source.loadDescription(*fileSource); } } -void Style::Impl::onSpriteLoaded(std::vector<std::unique_ptr<Image>>&& images_) { +void StyleImpl::onSpriteLoaded(std::vector<std::unique_ptr<Image>>&& images_) { for (auto& image : images_) { addImage(std::move(image)); } spriteLoaded = true; - observer->onUpdate(); // For *-pattern properties. + for (auto &observer: observers) + observer->onUpdate(); // For *-pattern properties. } -void Style::Impl::onSpriteError(std::exception_ptr error) { +void StyleImpl::onSpriteError(std::exception_ptr error) { lastError = error; Log::Error(Event::Style, "Failed to load sprite: %s", util::toString(error).c_str()); - observer->onResourceError(error); + for (auto &observer: observers) + observer->onResourceError(error); // Unblock rendering tiles (even though sprite request has failed). spriteLoaded = true; - observer->onUpdate(); + for (auto &observer: observers) + observer->onUpdate(); } -void Style::Impl::onLayerChanged(Layer& layer) { +void StyleImpl::onLayerChanged(Layer& layer) { layers.update(layer); - observer->onUpdate(); + for (auto &observer: observers) + observer->onUpdate(); } -void Style::Impl::onLightChanged(const Light&) { - observer->onUpdate(); +void StyleImpl::onLightChanged(const Light&) { + for (auto &observer: observers) + observer->onUpdate(); } -void Style::Impl::dumpDebugLogs() const { +void StyleImpl::dumpDebugLogs() const { Log::Info(Event::General, "styleURL: %s", url.c_str()); for (const auto& source : sources) { source->dumpDebugLogs(); } } -const std::string& Style::Impl::getGlyphURL() const { +const std::string& StyleImpl::getGlyphURL() const { return glyphURL; } -Immutable<std::vector<Immutable<Image::Impl>>> Style::Impl::getImageImpls() const { +Immutable<std::vector<Immutable<Image::Impl>>> StyleImpl::getImageImpls() const { return images.getImpls(); } -Immutable<std::vector<Immutable<Source::Impl>>> Style::Impl::getSourceImpls() const { +Immutable<std::vector<Immutable<Source::Impl>>> StyleImpl::getSourceImpls() const { return sources.getImpls(); } -Immutable<std::vector<Immutable<Layer::Impl>>> Style::Impl::getLayerImpls() const { +Immutable<std::vector<Immutable<Layer::Impl>>> StyleImpl::getLayerImpls() const { return layers.getImpls(); } diff --git a/src/mbgl/style/style_impl.hpp b/src/mbgl/style/style_impl.hpp index ca165e24f..25e278ee8 100644 --- a/src/mbgl/style/style_impl.hpp +++ b/src/mbgl/style/style_impl.hpp @@ -11,6 +11,7 @@ #include <mbgl/style/source.hpp> #include <mbgl/style/layer.hpp> #include <mbgl/style/collection.hpp> +#include <mbgl/annotation/annotation_manager.hpp> #include <mbgl/map/camera.hpp> @@ -22,6 +23,7 @@ #include <string> #include <vector> #include <unordered_map> +#include <set> namespace mbgl { @@ -31,14 +33,14 @@ class SpriteLoader; namespace style { -class Style::Impl : public SpriteLoaderObserver, +class StyleImpl : public SpriteLoaderObserver, public SourceObserver, public LayerObserver, public LightObserver, public util::noncopyable { public: - Impl(std::shared_ptr<FileSource>, float pixelRatio); - ~Impl() override; + StyleImpl(std::shared_ptr<FileSource>, float pixelRatio); + ~StyleImpl() override; void loadJSON(const std::string&); void loadURL(const std::string&); @@ -46,7 +48,8 @@ public: std::string getJSON() const; std::string getURL() const; - void setObserver(Observer*); + void addObserver(Observer* observer); + void removeObserver(Observer* observer); bool isLoaded() const; @@ -90,15 +93,34 @@ public: void dumpDebugLogs() const; - bool mutated = false; - bool loaded = false; - bool spriteLoaded = false; - private: void parse(const std::string&); + // SpriteLoaderObserver implementation. + void onSpriteLoaded(std::vector<std::unique_ptr<Image>>&&) override; + void onSpriteError(std::exception_ptr) override; + + // SourceObserver implementation. + void onSourceLoaded(Source&) override; + void onSourceChanged(Source&) override; + void onSourceError(Source&, std::exception_ptr) override; + void onSourceDescriptionChanged(Source&) override; + + // LayerObserver implementation. + void onLayerChanged(Layer&) override; + + // LightObserver implementation. + void onLightChanged(const Light&) override; + +public: + bool mutated = false; + bool loaded = false; + bool spriteLoaded = false; + AnnotationManager annotationManager; // ToDo: move annotations into an own style, stackable inside the View (=Map), so that + // they can change independently of the rest of the style and be combined with different styles arbitrarily. std::shared_ptr<FileSource> fileSource; +private: std::string url; std::string json; @@ -115,26 +137,7 @@ private: // Defaults std::string name; CameraOptions defaultCamera; - - // SpriteLoaderObserver implementation. - void onSpriteLoaded(std::vector<std::unique_ptr<Image>>&&) override; - void onSpriteError(std::exception_ptr) override; - - // SourceObserver implementation. - void onSourceLoaded(Source&) override; - void onSourceChanged(Source&) override; - void onSourceError(Source&, std::exception_ptr) override; - void onSourceDescriptionChanged(Source&) override; - - // LayerObserver implementation. - void onLayerChanged(Layer&) override; - - // LightObserver implementation. - void onLightChanged(const Light&) override; - - Observer nullObserver; - Observer* observer = &nullObserver; - + std::set<Observer*> observers; std::exception_ptr lastError; }; diff --git a/test/style/source.test.cpp b/test/style/source.test.cpp index 0286aaaec..1825cd08a 100644 --- a/test/style/source.test.cpp +++ b/test/style/source.test.cpp @@ -59,7 +59,7 @@ public: Transform transform; TransformState transformState; Style style{fileSource, 1}; - AnnotationManager annotationManager { style }; + AnnotationManager annotationManager { *style.impl }; ImageManager imageManager; GlyphManager glyphManager; diff --git a/test/style/style.test.cpp b/test/style/style.test.cpp index c866431ac..c9fbd903a 100644 --- a/test/style/style.test.cpp +++ b/test/style/style.test.cpp @@ -19,7 +19,7 @@ TEST(Style, Properties) { util::RunLoop loop; auto fileSource = std::make_shared<StubFileSource>(); - Style::Impl style { fileSource, 1.0 }; + StyleImpl style { fileSource, 1.0 }; style.loadJSON(R"STYLE({"name": "Test"})STYLE"); ASSERT_EQ("Test", style.getName()); @@ -61,7 +61,7 @@ TEST(Style, DuplicateSource) { util::RunLoop loop; auto fileSource = std::make_shared<StubFileSource>(); - Style::Impl style { fileSource, 1.0 }; + StyleImpl style { fileSource, 1.0 }; style.loadJSON(util::read_file("test/fixtures/resources/style-unused-sources.json")); @@ -82,7 +82,7 @@ TEST(Style, RemoveSourceInUse) { Log::setObserver(std::unique_ptr<Log::Observer>(log)); auto fileSource = std::make_shared<StubFileSource>(); - Style::Impl style { fileSource, 1.0 }; + StyleImpl style { fileSource, 1.0 }; style.loadJSON(util::read_file("test/fixtures/resources/style-unused-sources.json")); @@ -107,7 +107,7 @@ TEST(Style, RemoveSourceInUse) { TEST(Style, SourceImplsOrder) { util::RunLoop loop; auto fileSource = std::make_shared<StubFileSource>(); - Style::Impl style{fileSource, 1.0}; + StyleImpl style{fileSource, 1.0}; style.addSource(std::make_unique<VectorSource>("c", "mapbox://mapbox.mapbox-terrain-v2")); style.addSource(std::make_unique<VectorSource>("b", "mapbox://mapbox.mapbox-terrain-v2")); diff --git a/test/style/style_layer.test.cpp b/test/style/style_layer.test.cpp index 77e936ff3..f9ab804cf 100644 --- a/test/style/style_layer.test.cpp +++ b/test/style/style_layer.test.cpp @@ -284,7 +284,7 @@ TEST(Layer, DuplicateLayer) { // Setup style auto fileSource = std::make_shared<StubFileSource>(); - Style::Impl style { fileSource, 1.0 }; + StyleImpl style { fileSource, 1.0 }; style.loadJSON(util::read_file("test/fixtures/resources/style-unused-sources.json")); // Add initial layer @@ -305,7 +305,7 @@ TEST(Layer, IncompatibleLayer) { // Setup style auto fileSource = std::make_shared<StubFileSource>(); - Style::Impl style{fileSource, 1.0}; + StyleImpl style{fileSource, 1.0}; style.loadJSON(util::read_file("test/fixtures/resources/style-unused-sources.json")); // Try to add duplicate diff --git a/test/tile/custom_geometry_tile.test.cpp b/test/tile/custom_geometry_tile.test.cpp index f3d11ab89..bbe0c738e 100644 --- a/test/tile/custom_geometry_tile.test.cpp +++ b/test/tile/custom_geometry_tile.test.cpp @@ -26,7 +26,7 @@ public: TransformState transformState; util::RunLoop loop; style::Style style{fileSource, 1}; - AnnotationManager annotationManager { style }; + AnnotationManager annotationManager { *style.impl }; ImageManager imageManager; GlyphManager glyphManager; diff --git a/test/tile/geojson_tile.test.cpp b/test/tile/geojson_tile.test.cpp index 25fd268dc..ceaee4bb7 100644 --- a/test/tile/geojson_tile.test.cpp +++ b/test/tile/geojson_tile.test.cpp @@ -26,7 +26,7 @@ public: TransformState transformState; util::RunLoop loop; style::Style style{fileSource, 1}; - AnnotationManager annotationManager { style }; + AnnotationManager annotationManager { *style.impl }; ImageManager imageManager; GlyphManager glyphManager; Tileset tileset { { "https://example.com" }, { 0, 22 }, "none" }; diff --git a/test/tile/raster_dem_tile.test.cpp b/test/tile/raster_dem_tile.test.cpp index f5f761009..faefaa53a 100644 --- a/test/tile/raster_dem_tile.test.cpp +++ b/test/tile/raster_dem_tile.test.cpp @@ -20,7 +20,7 @@ public: TransformState transformState; util::RunLoop loop; style::Style style{fileSource, 1}; - AnnotationManager annotationManager { style }; + AnnotationManager annotationManager { *style.impl }; ImageManager imageManager; GlyphManager glyphManager; Tileset tileset { { "https://example.com" }, { 0, 22 }, "none" }; diff --git a/test/tile/raster_tile.test.cpp b/test/tile/raster_tile.test.cpp index a5a2875f2..4428ffc59 100644 --- a/test/tile/raster_tile.test.cpp +++ b/test/tile/raster_tile.test.cpp @@ -20,7 +20,7 @@ public: TransformState transformState; util::RunLoop loop; style::Style style{fileSource, 1}; - AnnotationManager annotationManager { style }; + AnnotationManager annotationManager { *style.impl }; ImageManager imageManager; GlyphManager glyphManager; Tileset tileset { { "https://example.com" }, { 0, 22 }, "none" }; diff --git a/test/tile/tile_cache.test.cpp b/test/tile/tile_cache.test.cpp index 43b409ae8..5ff6888ed 100644 --- a/test/tile/tile_cache.test.cpp +++ b/test/tile/tile_cache.test.cpp @@ -29,7 +29,7 @@ public: TransformState transformState; util::RunLoop loop; style::Style style{fileSource, 1}; - AnnotationManager annotationManager{style}; + AnnotationManager annotationManager { *style.impl }; ImageManager imageManager; GlyphManager glyphManager; Tileset tileset{{"https://example.com"}, {0, 22}, "none"}; diff --git a/test/tile/vector_tile.test.cpp b/test/tile/vector_tile.test.cpp index d282c874e..a31915498 100644 --- a/test/tile/vector_tile.test.cpp +++ b/test/tile/vector_tile.test.cpp @@ -26,7 +26,7 @@ public: TransformState transformState; util::RunLoop loop; style::Style style{fileSource, 1}; - AnnotationManager annotationManager { style }; + AnnotationManager annotationManager { *style.impl }; ImageManager imageManager; GlyphManager glyphManager; Tileset tileset { { "https://example.com" }, { 0, 22 }, "none" }; |