diff options
author | John Firebaugh <john.firebaugh@gmail.com> | 2017-04-21 13:35:34 -0700 |
---|---|---|
committer | John Firebaugh <john.firebaugh@gmail.com> | 2017-06-22 08:04:39 -0700 |
commit | 1520a56813f82bbe875774fdc2b3df26392278d6 (patch) | |
tree | d8f6ccc10e118bd2be6a954951c037f9c2fc1384 /src | |
parent | be7e9bbb8d54c775127f53d793c117c4bf5e2764 (diff) | |
download | qtlocation-mapboxgl-1520a56813f82bbe875774fdc2b3df26392278d6.tar.gz |
[all] Promote Style to public API
Diffstat (limited to 'src')
-rw-r--r-- | src/mbgl/annotation/annotation_manager.cpp | 7 | ||||
-rw-r--r-- | src/mbgl/annotation/annotation_manager.hpp | 7 | ||||
-rw-r--r-- | src/mbgl/annotation/fill_annotation_impl.cpp | 4 | ||||
-rw-r--r-- | src/mbgl/annotation/fill_annotation_impl.hpp | 2 | ||||
-rw-r--r-- | src/mbgl/annotation/line_annotation_impl.cpp | 4 | ||||
-rw-r--r-- | src/mbgl/annotation/line_annotation_impl.hpp | 2 | ||||
-rw-r--r-- | src/mbgl/annotation/shape_annotation_impl.hpp | 7 | ||||
-rw-r--r-- | src/mbgl/map/map.cpp | 157 | ||||
-rw-r--r-- | src/mbgl/renderer/update_parameters.hpp | 4 | ||||
-rw-r--r-- | src/mbgl/style/style.cpp | 307 | ||||
-rw-r--r-- | src/mbgl/style/style_impl.cpp | 321 | ||||
-rw-r--r-- | src/mbgl/style/style_impl.hpp (renamed from src/mbgl/style/style.hpp) | 24 |
12 files changed, 449 insertions, 397 deletions
diff --git a/src/mbgl/annotation/annotation_manager.cpp b/src/mbgl/annotation/annotation_manager.cpp index 58bda6052e..a69dba1bf2 100644 --- a/src/mbgl/annotation/annotation_manager.cpp +++ b/src/mbgl/annotation/annotation_manager.cpp @@ -4,7 +4,7 @@ #include <mbgl/annotation/symbol_annotation_impl.hpp> #include <mbgl/annotation/line_annotation_impl.hpp> #include <mbgl/annotation/fill_annotation_impl.hpp> -#include <mbgl/style/style.hpp> +#include <mbgl/style/style_impl.hpp> #include <mbgl/style/layers/symbol_layer.hpp> #include <mbgl/style/layers/symbol_layer_impl.hpp> #include <mbgl/storage/file_source.hpp> @@ -149,8 +149,9 @@ std::unique_ptr<AnnotationTileData> AnnotationManager::getTileData(const Canonic return tileData; } -void AnnotationManager::updateStyle(Style& style) { - // Create annotation source, point layer, and point bucket +void AnnotationManager::updateStyle(Style::Impl& style) { + // 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.getSource(SourceID)) { style.addSource(std::make_unique<AnnotationSource>()); diff --git a/src/mbgl/annotation/annotation_manager.hpp b/src/mbgl/annotation/annotation_manager.hpp index c2ed5ba89f..6906791db7 100644 --- a/src/mbgl/annotation/annotation_manager.hpp +++ b/src/mbgl/annotation/annotation_manager.hpp @@ -4,6 +4,7 @@ #include <mbgl/annotation/symbol_annotation_impl.hpp> #include <mbgl/style/image.hpp> #include <mbgl/map/update.hpp> +#include <mbgl/style/style.hpp> #include <mbgl/util/noncopyable.hpp> #include <mutex> @@ -20,10 +21,6 @@ class AnnotationTileData; class SymbolAnnotationImpl; class ShapeAnnotationImpl; -namespace style { -class Style; -} // namespace style - class AnnotationManager : private util::noncopyable { public: AnnotationManager(); @@ -37,7 +34,7 @@ public: void removeImage(const std::string&); double getTopOffsetPixelsForImage(const std::string&); - void updateStyle(style::Style&); + void updateStyle(style::Style::Impl&); void updateData(); void addTile(AnnotationTile&); diff --git a/src/mbgl/annotation/fill_annotation_impl.cpp b/src/mbgl/annotation/fill_annotation_impl.cpp index 484870c45c..5dc36edab0 100644 --- a/src/mbgl/annotation/fill_annotation_impl.cpp +++ b/src/mbgl/annotation/fill_annotation_impl.cpp @@ -1,6 +1,6 @@ #include <mbgl/annotation/fill_annotation_impl.hpp> #include <mbgl/annotation/annotation_manager.hpp> -#include <mbgl/style/style.hpp> +#include <mbgl/style/style_impl.hpp> #include <mbgl/style/layers/fill_layer.hpp> namespace mbgl { @@ -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& style) const { +void FillAnnotationImpl::updateStyle(Style::Impl& 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 6376eee880..5c49e447b8 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, uint8_t maxZoom); - void updateStyle(style::Style&) const final; + void updateStyle(style::Style::Impl&) 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 65379c42a8..8954ecfa58 100644 --- a/src/mbgl/annotation/line_annotation_impl.cpp +++ b/src/mbgl/annotation/line_annotation_impl.cpp @@ -1,6 +1,6 @@ #include <mbgl/annotation/line_annotation_impl.hpp> #include <mbgl/annotation/annotation_manager.hpp> -#include <mbgl/style/style.hpp> +#include <mbgl/style/style_impl.hpp> #include <mbgl/style/layers/line_layer.hpp> namespace mbgl { @@ -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& style) const { +void LineAnnotationImpl::updateStyle(Style::Impl& 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 7945da5d97..548a094d53 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, uint8_t maxZoom); - void updateStyle(style::Style&) const final; + void updateStyle(style::Style::Impl&) 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 800b4ec313..ed9e8d015a 100644 --- a/src/mbgl/annotation/shape_annotation_impl.hpp +++ b/src/mbgl/annotation/shape_annotation_impl.hpp @@ -4,6 +4,7 @@ #include <mbgl/annotation/annotation.hpp> #include <mbgl/util/geometry.hpp> +#include <mbgl/style/style.hpp> #include <string> #include <memory> @@ -13,16 +14,12 @@ namespace mbgl { class AnnotationTileData; class CanonicalTileID; -namespace style { -class Style; -} // namespace style - class ShapeAnnotationImpl { public: ShapeAnnotationImpl(const AnnotationID, const uint8_t maxZoom); virtual ~ShapeAnnotationImpl() = default; - virtual void updateStyle(style::Style&) const = 0; + virtual void updateStyle(style::Style::Impl&) 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 73a540a16a..3aed91cda4 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -6,12 +6,8 @@ #include <mbgl/map/transform.hpp> #include <mbgl/map/transform_state.hpp> #include <mbgl/annotation/annotation_manager.hpp> -#include <mbgl/style/style.hpp> -#include <mbgl/style/source.hpp> -#include <mbgl/style/layer.hpp> -#include <mbgl/style/light.hpp> +#include <mbgl/style/style_impl.hpp> #include <mbgl/style/observer.hpp> -#include <mbgl/style/transition_options.hpp> #include <mbgl/renderer/update_parameters.hpp> #include <mbgl/renderer/painter.hpp> #include <mbgl/renderer/render_source.hpp> @@ -101,7 +97,6 @@ public: std::string styleURL; std::string styleJSON; - bool styleMutated = false; bool cameraMutated = false; std::unique_ptr<AsyncRequest> styleRequest; @@ -166,7 +161,7 @@ Map::Impl::Impl(Map& map_, } }) { style = std::make_unique<Style>(scheduler, fileSource, pixelRatio); - style->setObserver(this); + style->impl->setObserver(this); } Map::~Map() { @@ -196,8 +191,8 @@ void Map::renderStill(View& view, StillImageCallback callback) { return; } - if (impl->style->getLastError()) { - callback(impl->style->getLastError()); + if (impl->style->impl->getLastError()) { + callback(impl->style->impl->getLastError()); return; } @@ -228,8 +223,8 @@ void Map::Impl::render(View& view) { transform.updateTransitions(timePoint); - if (style->loaded && updateFlags & Update::AnnotationStyle) { - annotationManager.updateStyle(*style); + if (style->impl->loaded && updateFlags & Update::AnnotationStyle) { + annotationManager.updateStyle(*style->impl); } if (updateFlags & Update::AnnotationData) { @@ -251,19 +246,19 @@ void Map::Impl::render(View& view) { debugOptions, timePoint, transform.getState(), - style->getGlyphURL(), - style->spriteLoaded, + style->impl->getGlyphURL(), + style->impl->spriteLoaded, style->getTransitionOptions(), style->getLight()->impl, - style->getImageImpls(), - style->getSourceImpls(), - style->getLayerImpls(), + style->impl->getImageImpls(), + style->impl->getSourceImpls(), + style->impl->getLayerImpls(), scheduler, fileSource, annotationManager }); - bool loaded = style->isLoaded() && renderStyle->isLoaded(); + bool loaded = style->impl->isLoaded() && renderStyle->isLoaded(); if (mode == MapMode::Continuous) { if (renderState == RenderState::Never) { @@ -334,24 +329,21 @@ void Map::setStyleURL(const std::string& url) { } impl->loading = true; - impl->observer.onWillStartLoadingMap(); impl->styleRequest = nullptr; impl->styleURL = url; impl->styleJSON.clear(); - - impl->style->loaded = false; - impl->styleMutated = false; + impl->style->impl->loaded = false; impl->styleRequest = impl->fileSource.request(Resource::style(impl->styleURL), [this](Response res) { // Once we get a fresh style, or the style is mutated, stop revalidating. - if (res.isFresh() || impl->styleMutated) { + if (res.isFresh() || impl->style->impl->mutated) { impl->styleRequest.reset(); } // Don't allow a loaded, mutated style to be overwritten with a new version. - if (impl->styleMutated && impl->style->loaded) { + if (impl->style->impl->mutated && impl->style->impl->loaded) { return; } @@ -381,26 +373,25 @@ void Map::setStyleJSON(const std::string& json) { } impl->loading = true; - impl->observer.onWillStartLoadingMap(); impl->styleURL.clear(); impl->styleJSON.clear(); - impl->styleMutated = false; + impl->style->impl->mutated = false; impl->loadStyleJSON(json); } void Map::Impl::loadStyleJSON(const std::string& json) { - style->setJSON(json); + style->impl->setJSON(json); styleJSON = json; if (!cameraMutated) { // Zoom first because it may constrain subsequent operations. - map.setZoom(map.getDefaultZoom()); - map.setLatLng(map.getDefaultLatLng()); - map.setBearing(map.getDefaultBearing()); - map.setPitch(map.getDefaultPitch()); + map.setZoom(style->getDefaultZoom()); + map.setLatLng(style->getDefaultLatLng()); + map.setBearing(style->getDefaultBearing()); + map.setPitch(style->getDefaultPitch()); } onUpdate(Update::AnnotationStyle); @@ -414,6 +405,14 @@ std::string Map::getStyleJSON() const { return impl->styleJSON; } +style::Style& Map::getStyle() { + return *impl->style; +} + +const style::Style& Map::getStyle() const { + return *impl->style; +} + #pragma mark - Transitions void Map::cancelTransitions() { @@ -872,92 +871,6 @@ AnnotationIDs Map::queryPointAnnotations(const ScreenBox& box) { return ids; } -#pragma mark - Style API - -std::vector<style::Source*> Map::getSources() { - return impl->style->getSources(); -} - -style::Source* Map::getSource(const std::string& sourceID) { - impl->styleMutated = true; - return impl->style->getSource(sourceID); -} - -void Map::addSource(std::unique_ptr<style::Source> source) { - impl->styleMutated = true; - impl->style->addSource(std::move(source)); -} - -std::unique_ptr<Source> Map::removeSource(const std::string& sourceID) { - impl->styleMutated = true; - return impl->style->removeSource(sourceID); -} - -std::vector<style::Layer*> Map::getLayers() { - return impl->style->getLayers(); -} - -Layer* Map::getLayer(const std::string& layerID) { - impl->styleMutated = true; - return impl->style->getLayer(layerID); -} - -void Map::addLayer(std::unique_ptr<Layer> layer, const optional<std::string>& before) { - impl->styleMutated = true; - impl->style->addLayer(std::move(layer), before); - impl->onUpdate(Update::Repaint); -} - -std::unique_ptr<Layer> Map::removeLayer(const std::string& id) { - impl->styleMutated = true; - impl->onUpdate(Update::Repaint); - return impl->style->removeLayer(id); -} - -void Map::addImage(std::unique_ptr<style::Image> image) { - impl->styleMutated = true; - impl->style->addImage(std::move(image)); -} - -void Map::removeImage(const std::string& id) { - impl->styleMutated = true; - impl->style->removeImage(id); -} - -const style::Image* Map::getImage(const std::string& id) { - return impl->style->getImage(id); -} - -void Map::setLight(std::unique_ptr<style::Light> light) { - impl->style->setLight(std::move(light)); -} - -style::Light* Map::getLight() { - return impl->style->getLight(); -} - -#pragma mark - Defaults - -std::string Map::getStyleName() const { - return impl->style->getName(); -} - -LatLng Map::getDefaultLatLng() const { - return impl->style->getDefaultLatLng(); -} - -double Map::getDefaultZoom() const { - return impl->style->getDefaultZoom(); -} - -double Map::getDefaultBearing() const { - return impl->style->getDefaultBearing(); -} - -double Map::getDefaultPitch() const { - return impl->style->getDefaultPitch(); -} - #pragma mark - Toggles void Map::setDebug(MapDebugOptions debugOptions) { @@ -994,15 +907,7 @@ MapDebugOptions Map::getDebug() const { } bool Map::isFullyLoaded() const { - return impl->style && impl->style->isLoaded() && impl->renderStyle && impl->renderStyle->isLoaded(); -} - -style::TransitionOptions Map::getTransitionOptions() const { - return impl->style->getTransitionOptions(); -} - -void Map::setTransitionOptions(const style::TransitionOptions& options) { - impl->style->setTransitionOptions(options); + return impl->style->impl->isLoaded() && impl->renderStyle && impl->renderStyle->isLoaded(); } void Map::setSourceTileCacheSize(size_t size) { @@ -1056,7 +961,7 @@ void Map::Impl::onResourceError(std::exception_ptr error) { void Map::dumpDebugLogs() const { Log::Info(Event::General, "--------------------------------------------------------------------------------"); Log::Info(Event::General, "MapContext::styleURL: %s", impl->styleURL.c_str()); - impl->style->dumpDebugLogs(); + impl->style->impl->dumpDebugLogs(); if (impl->renderStyle) { impl->renderStyle->dumpDebugLogs(); } diff --git a/src/mbgl/renderer/update_parameters.hpp b/src/mbgl/renderer/update_parameters.hpp index 7c44064b0b..ce79a4f31b 100644 --- a/src/mbgl/renderer/update_parameters.hpp +++ b/src/mbgl/renderer/update_parameters.hpp @@ -3,6 +3,10 @@ #include <mbgl/map/mode.hpp> #include <mbgl/map/transform_state.hpp> #include <mbgl/util/chrono.hpp> +#include <mbgl/style/light.hpp> +#include <mbgl/style/image.hpp> +#include <mbgl/style/source.hpp> +#include <mbgl/style/layer.hpp> namespace mbgl { diff --git a/src/mbgl/style/style.cpp b/src/mbgl/style/style.cpp index 41b4310dcf..f8dfd48b5c 100644 --- a/src/mbgl/style/style.cpp +++ b/src/mbgl/style/style.cpp @@ -1,308 +1,129 @@ #include <mbgl/style/style.hpp> -#include <mbgl/style/observer.hpp> -#include <mbgl/style/source_impl.hpp> -#include <mbgl/style/layers/symbol_layer.hpp> -#include <mbgl/style/layers/custom_layer.hpp> -#include <mbgl/style/layers/background_layer.hpp> -#include <mbgl/style/layers/fill_layer.hpp> -#include <mbgl/style/layers/fill_extrusion_layer.hpp> -#include <mbgl/style/layers/line_layer.hpp> -#include <mbgl/style/layers/circle_layer.hpp> -#include <mbgl/style/layers/raster_layer.hpp> -#include <mbgl/style/layer_impl.hpp> -#include <mbgl/style/parser.hpp> -#include <mbgl/style/transition_options.hpp> -#include <mbgl/sprite/sprite_loader.hpp> -#include <mbgl/util/exception.hpp> -#include <mbgl/util/string.hpp> -#include <mbgl/util/logging.hpp> +#include <mbgl/style/style_impl.hpp> +#include <mbgl/style/light.hpp> +#include <mbgl/style/image.hpp> +#include <mbgl/style/source.hpp> +#include <mbgl/style/layer.hpp> namespace mbgl { namespace style { -static Observer nullObserver; - -Style::Style(Scheduler& scheduler_, FileSource& fileSource_, float pixelRatio) - : scheduler(scheduler_), - fileSource(fileSource_), - spriteLoader(std::make_unique<SpriteLoader>(pixelRatio)), - light(std::make_unique<Light>()), - observer(&nullObserver) { - spriteLoader->setObserver(this); - light->setObserver(this); +Style::Style(Scheduler& scheduler, FileSource& fileSource, float pixelRatio) + : impl(std::make_unique<Impl>(scheduler, fileSource, pixelRatio)) { } Style::~Style() = default; -void Style::setTransitionOptions(const TransitionOptions& options) { - transitionOptions = options; -} - -TransitionOptions Style::getTransitionOptions() const { - return transitionOptions; -} - -void Style::setJSON(const std::string& json) { - sources.clear(); - layers.clear(); - images.clear(); - - transitionOptions = {}; - transitionOptions.duration = util::DEFAULT_TRANSITION_DURATION; - - Parser parser; - auto error = parser.parse(json); - - if (error) { - 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); - return; - } - - for (auto& source : parser.sources) { - addSource(std::move(source)); - } - - for (auto& layer : parser.layers) { - addLayer(std::move(layer)); - } - - name = parser.name; - defaultLatLng = parser.latLng; - defaultZoom = parser.zoom; - defaultBearing = parser.bearing; - defaultPitch = parser.pitch; - setLight(std::make_unique<Light>(parser.light)); - - spriteLoader->load(parser.spriteURL, scheduler, fileSource); - glyphURL = parser.glyphURL; - - loaded = true; - - observer->onStyleLoaded(); -} - -void Style::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()); - } - - source->setObserver(this); - source->loadDescription(fileSource); - - sources.add(std::move(source)); -} - -struct SourceIdUsageEvaluator { - const std::string& sourceId; - - bool operator()(BackgroundLayer&) { return false; } - bool operator()(CustomLayer&) { return false; } - - template <class LayerType> - bool operator()(LayerType& layer) { - return layer.getSourceID() == sourceId; - } -}; - -std::unique_ptr<Source> Style::removeSource(const std::string& id) { - // Check if source is in use - SourceIdUsageEvaluator sourceIdEvaluator {id}; - auto layerIt = std::find_if(layers.begin(), layers.end(), [&](const auto& layer) { - return layer->accept(sourceIdEvaluator); - }); - - if (layerIt != layers.end()) { - Log::Warning(Event::General, "Source '%s' is in use, cannot remove", id.c_str()); - return nullptr; - } - - std::unique_ptr<Source> source = sources.remove(id); - - if (source) { - source->setObserver(nullptr); - } - - return source; -} - -std::vector<Layer*> Style::getLayers() { - return layers.getWrappers(); -} - -Layer* Style::getLayer(const std::string& id) const { - return layers.get(id); -} - -Layer* Style::addLayer(std::unique_ptr<Layer> layer, optional<std::string> before) { - // TODO: verify source - - if (layers.get(layer->getID())) { - throw std::runtime_error(std::string{"Layer "} + layer->getID() + " already exists"); - } - - layer->setObserver(this); - - return layers.add(std::move(layer), before); -} - -std::unique_ptr<Layer> Style::removeLayer(const std::string& id) { - std::unique_ptr<Layer> layer = layers.remove(id); - - if (layer) { - layer->setObserver(nullptr); - } - - return layer; -} - -void Style::setLight(std::unique_ptr<Light> light_) { - light = std::move(light_); - light->setObserver(this); - onLightChanged(*light); -} - -Light* Style::getLight() const { - return light.get(); -} - std::string Style::getName() const { - return name; + return impl->getName(); } LatLng Style::getDefaultLatLng() const { - return defaultLatLng; + return impl->getDefaultLatLng(); } double Style::getDefaultZoom() const { - return defaultZoom; + return impl->getDefaultZoom(); } double Style::getDefaultBearing() const { - return defaultBearing; + return impl->getDefaultBearing(); } double Style::getDefaultPitch() const { - return defaultPitch; + return impl->getDefaultPitch(); } -std::vector<Source*> Style::getSources() { - return sources.getWrappers(); +TransitionOptions Style::getTransitionOptions() const { + return impl->getTransitionOptions(); } -Source* Style::getSource(const std::string& id) const { - return sources.get(id); +void Style::setTransitionOptions(const TransitionOptions& options) { + impl->mutated = true; + impl->setTransitionOptions(options); } -bool Style::isLoaded() const { - if (!loaded) { - return false; - } - - if (!spriteLoaded) { - return false; - } - - for (const auto& source: sources) { - if (!source->loaded) { - return false; - } - } - - return true; +void Style::setLight(std::unique_ptr<Light> light) { + impl->setLight(std::move(light)); } -void Style::addImage(std::unique_ptr<style::Image> image) { - images.remove(image->getID()); // We permit using addImage to update. - images.add(std::move(image)); +Light* Style::getLight() { + impl->mutated = true; + return impl->getLight(); } -void Style::removeImage(const std::string& id) { - images.remove(id); +const Light* Style::getLight() const { + return impl->getLight(); } -const style::Image* Style::getImage(const std::string& id) const { - return images.get(id); +const Image* Style::getImage(const std::string& name) const { + return impl->getImage(name); } -void Style::setObserver(style::Observer* observer_) { - observer = observer_; +void Style::addImage(std::unique_ptr<Image> image) { + impl->mutated = true; + impl->addImage(std::move(image)); } -void Style::onSourceLoaded(Source& source) { - sources.update(source); - observer->onSourceLoaded(source); - observer->onUpdate(Update::Repaint); +void Style::removeImage(const std::string& name) { + impl->mutated = true; + impl->removeImage(name); } -void Style::onSourceChanged(Source& source) { - sources.update(source); - observer->onSourceChanged(source); - observer->onUpdate(Update::Repaint); +std::vector<Source*> Style::getSources() { + impl->mutated = true; + return impl->getSources(); } -void Style::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); +std::vector<const Source*> Style::getSources() const { + return const_cast<const Impl&>(*impl).getSources(); } -void Style::onSourceDescriptionChanged(Source& source) { - sources.update(source); - observer->onSourceDescriptionChanged(source); - if (!source.loaded) { - source.loadDescription(fileSource); - } +Source* Style::getSource(const std::string& id) { + impl->mutated = true; + return impl->getSource(id); } -void Style::onSpriteLoaded(std::vector<std::unique_ptr<Image>>&& images_) { - for (auto& image : images_) { - addImage(std::move(image)); - } - spriteLoaded = true; - observer->onUpdate(Update::Repaint); // For *-pattern properties. +const Source* Style::getSource(const std::string& id) const { + return impl->getSource(id); } -void Style::onSpriteError(std::exception_ptr error) { - lastError = error; - Log::Error(Event::Style, "Failed to load sprite: %s", util::toString(error).c_str()); - observer->onResourceError(error); +void Style::addSource(std::unique_ptr<Source> source) { + impl->mutated = true; + impl->addSource(std::move(source)); } -void Style::onLayerChanged(Layer& layer) { - layers.update(layer); - observer->onUpdate(Update::Repaint); +std::unique_ptr<Source> Style::removeSource(const std::string& sourceID) { + impl->mutated = true; + return impl->removeSource(sourceID); } -void Style::onLightChanged(const Light&) { - observer->onUpdate(Update::Repaint); +std::vector<Layer*> Style::getLayers() { + impl->mutated = true; + return impl->getLayers(); } -void Style::dumpDebugLogs() const { - for (const auto& source : sources) { - source->dumpDebugLogs(); - } +std::vector<const Layer*> Style::getLayers() const { + return const_cast<const Impl&>(*impl).getLayers(); } -const std::string& Style::getGlyphURL() const { - return glyphURL; +Layer* Style::getLayer(const std::string& layerID) { + impl->mutated = true; + return impl->getLayer(layerID); } -Immutable<std::vector<Immutable<Image::Impl>>> Style::getImageImpls() const { - return images.getImpls(); +const Layer* Style::getLayer(const std::string& layerID) const { + return impl->getLayer(layerID); } -Immutable<std::vector<Immutable<Source::Impl>>> Style::getSourceImpls() const { - return sources.getImpls(); +void Style::addLayer(std::unique_ptr<Layer> layer, const optional<std::string>& before) { + impl->mutated = true; + impl->addLayer(std::move(layer), before); } -Immutable<std::vector<Immutable<Layer::Impl>>> Style::getLayerImpls() const { - return layers.getImpls(); +std::unique_ptr<Layer> Style::removeLayer(const std::string& id) { + impl->mutated = true; + return impl->removeLayer(id); } } // namespace style diff --git a/src/mbgl/style/style_impl.cpp b/src/mbgl/style/style_impl.cpp new file mode 100644 index 0000000000..7235226f84 --- /dev/null +++ b/src/mbgl/style/style_impl.cpp @@ -0,0 +1,321 @@ +#include <mbgl/style/style_impl.hpp> +#include <mbgl/style/observer.hpp> +#include <mbgl/style/source_impl.hpp> +#include <mbgl/style/layers/symbol_layer.hpp> +#include <mbgl/style/layers/custom_layer.hpp> +#include <mbgl/style/layers/background_layer.hpp> +#include <mbgl/style/layers/fill_layer.hpp> +#include <mbgl/style/layers/fill_extrusion_layer.hpp> +#include <mbgl/style/layers/line_layer.hpp> +#include <mbgl/style/layers/circle_layer.hpp> +#include <mbgl/style/layers/raster_layer.hpp> +#include <mbgl/style/layer_impl.hpp> +#include <mbgl/style/parser.hpp> +#include <mbgl/style/transition_options.hpp> +#include <mbgl/sprite/sprite_loader.hpp> +#include <mbgl/util/exception.hpp> +#include <mbgl/util/string.hpp> +#include <mbgl/util/logging.hpp> + +namespace mbgl { +namespace style { + +static Observer nullObserver; + +Style::Impl::Impl(Scheduler& scheduler_, FileSource& fileSource_, float pixelRatio) + : scheduler(scheduler_), + fileSource(fileSource_), + spriteLoader(std::make_unique<SpriteLoader>(pixelRatio)), + light(std::make_unique<Light>()), + observer(&nullObserver) { + spriteLoader->setObserver(this); + light->setObserver(this); +} + +Style::Impl::~Impl() = default; + +void Style::Impl::setTransitionOptions(const TransitionOptions& options) { + transitionOptions = options; +} + +TransitionOptions Style::Impl::getTransitionOptions() const { + return transitionOptions; +} + +void Style::Impl::setJSON(const std::string& json) { + sources.clear(); + layers.clear(); + images.clear(); + + transitionOptions = {}; + transitionOptions.duration = util::DEFAULT_TRANSITION_DURATION; + + Parser parser; + auto error = parser.parse(json); + + if (error) { + 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); + return; + } + + for (auto& source : parser.sources) { + addSource(std::move(source)); + } + + for (auto& layer : parser.layers) { + addLayer(std::move(layer)); + } + + name = parser.name; + defaultLatLng = parser.latLng; + defaultZoom = parser.zoom; + defaultBearing = parser.bearing; + defaultPitch = parser.pitch; + setLight(std::make_unique<Light>(parser.light)); + + spriteLoader->load(parser.spriteURL, scheduler, fileSource); + glyphURL = parser.glyphURL; + + loaded = true; + + observer->onStyleLoaded(); +} + +void Style::Impl::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()); + } + + source->setObserver(this); + source->loadDescription(fileSource); + + sources.add(std::move(source)); +} + +struct SourceIdUsageEvaluator { + const std::string& sourceId; + + bool operator()(BackgroundLayer&) { return false; } + bool operator()(CustomLayer&) { return false; } + + template <class LayerType> + bool operator()(LayerType& layer) { + return layer.getSourceID() == sourceId; + } +}; + +std::unique_ptr<Source> Style::Impl::removeSource(const std::string& id) { + // Check if source is in use + SourceIdUsageEvaluator sourceIdEvaluator {id}; + auto layerIt = std::find_if(layers.begin(), layers.end(), [&](const auto& layer) { + return layer->accept(sourceIdEvaluator); + }); + + if (layerIt != layers.end()) { + Log::Warning(Event::General, "Source '%s' is in use, cannot remove", id.c_str()); + return nullptr; + } + + std::unique_ptr<Source> source = sources.remove(id); + + if (source) { + source->setObserver(nullptr); + } + + return source; +} + +std::vector<Layer*> Style::Impl::getLayers() { + return layers.getWrappers(); +} + +std::vector<const Layer*> Style::Impl::getLayers() const { + auto wrappers = layers.getWrappers(); + return std::vector<const Layer*>(wrappers.begin(), wrappers.end()); +} + +Layer* Style::Impl::getLayer(const std::string& id) const { + return layers.get(id); +} + +Layer* Style::Impl::addLayer(std::unique_ptr<Layer> layer, optional<std::string> before) { + // TODO: verify source + + if (layers.get(layer->getID())) { + throw std::runtime_error(std::string{"Layer "} + layer->getID() + " already exists"); + } + + layer->setObserver(this); + observer->onUpdate(Update::Repaint); + + return layers.add(std::move(layer), before); +} + +std::unique_ptr<Layer> Style::Impl::removeLayer(const std::string& id) { + std::unique_ptr<Layer> layer = layers.remove(id); + + if (layer) { + layer->setObserver(nullptr); + observer->onUpdate(Update::Repaint); + } + + return layer; +} + +void Style::Impl::setLight(std::unique_ptr<Light> light_) { + light = std::move(light_); + light->setObserver(this); + onLightChanged(*light); +} + +Light* Style::Impl::getLight() const { + return light.get(); +} + +std::string Style::Impl::getName() const { + return name; +} + +LatLng Style::Impl::getDefaultLatLng() const { + return defaultLatLng; +} + +double Style::Impl::getDefaultZoom() const { + return defaultZoom; +} + +double Style::Impl::getDefaultBearing() const { + return defaultBearing; +} + +double Style::Impl::getDefaultPitch() const { + return defaultPitch; +} + +std::vector<Source*> Style::Impl::getSources() { + return sources.getWrappers(); +} + +std::vector<const Source*> Style::Impl::getSources() const { + auto wrappers = sources.getWrappers(); + return std::vector<const Source*>(wrappers.begin(), wrappers.end()); +} + +Source* Style::Impl::getSource(const std::string& id) const { + return sources.get(id); +} + +bool Style::Impl::isLoaded() const { + if (!loaded) { + return false; + } + + if (!spriteLoaded) { + return false; + } + + for (const auto& source: sources) { + if (!source->loaded) { + return false; + } + } + + return true; +} + +void Style::Impl::addImage(std::unique_ptr<style::Image> image) { + images.remove(image->getID()); // We permit using addImage to update. + images.add(std::move(image)); +} + +void Style::Impl::removeImage(const std::string& id) { + images.remove(id); +} + +const style::Image* Style::Impl::getImage(const std::string& id) const { + return images.get(id); +} + +void Style::Impl::setObserver(style::Observer* observer_) { + observer = observer_; +} + +void Style::Impl::onSourceLoaded(Source& source) { + sources.update(source); + observer->onSourceLoaded(source); + observer->onUpdate(Update::Repaint); +} + +void Style::Impl::onSourceChanged(Source& source) { + sources.update(source); + observer->onSourceChanged(source); + observer->onUpdate(Update::Repaint); +} + +void Style::Impl::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); +} + +void Style::Impl::onSourceDescriptionChanged(Source& source) { + sources.update(source); + observer->onSourceDescriptionChanged(source); + if (!source.loaded) { + source.loadDescription(fileSource); + } +} + +void Style::Impl::onSpriteLoaded(std::vector<std::unique_ptr<Image>>&& images_) { + for (auto& image : images_) { + addImage(std::move(image)); + } + spriteLoaded = true; + observer->onUpdate(Update::Repaint); // For *-pattern properties. +} + +void Style::Impl::onSpriteError(std::exception_ptr error) { + lastError = error; + Log::Error(Event::Style, "Failed to load sprite: %s", util::toString(error).c_str()); + observer->onResourceError(error); +} + +void Style::Impl::onLayerChanged(Layer& layer) { + layers.update(layer); + observer->onUpdate(Update::Repaint); +} + +void Style::Impl::onLightChanged(const Light&) { + observer->onUpdate(Update::Repaint); +} + +void Style::Impl::dumpDebugLogs() const { + for (const auto& source : sources) { + source->dumpDebugLogs(); + } +} + +const std::string& Style::Impl::getGlyphURL() const { + return glyphURL; +} + +Immutable<std::vector<Immutable<Image::Impl>>> Style::Impl::getImageImpls() const { + return images.getImpls(); +} + +Immutable<std::vector<Immutable<Source::Impl>>> Style::Impl::getSourceImpls() const { + return sources.getImpls(); +} + +Immutable<std::vector<Immutable<Layer::Impl>>> Style::Impl::getLayerImpls() const { + return layers.getImpls(); +} + +} // namespace style +} // namespace mbgl diff --git a/src/mbgl/style/style.hpp b/src/mbgl/style/style_impl.hpp index 7e8f6f640b..2bdb51a26c 100644 --- a/src/mbgl/style/style.hpp +++ b/src/mbgl/style/style_impl.hpp @@ -1,5 +1,6 @@ #pragma once +#include <mbgl/style/style.hpp> #include <mbgl/style/transition_options.hpp> #include <mbgl/style/observer.hpp> #include <mbgl/style/source_observer.hpp> @@ -28,14 +29,14 @@ class SpriteLoader; namespace style { -class Style : public SpriteLoaderObserver, - public SourceObserver, - public LayerObserver, - public LightObserver, - public util::noncopyable { +class Style::Impl : public SpriteLoaderObserver, + public SourceObserver, + public LayerObserver, + public LightObserver, + public util::noncopyable { public: - Style(Scheduler&, FileSource&, float pixelRatio); - ~Style() override; + Impl(Scheduler&, FileSource&, float pixelRatio); + ~Impl() override; void setJSON(const std::string&); @@ -47,13 +48,17 @@ public: return lastError; } - std::vector<Source*> getSources(); + std::vector< Source*> getSources(); + std::vector<const Source*> getSources() const; Source* getSource(const std::string& id) const; + void addSource(std::unique_ptr<Source>); std::unique_ptr<Source> removeSource(const std::string& sourceID); - std::vector<Layer*> getLayers(); + std::vector< Layer*> getLayers(); + std::vector<const Layer*> getLayers() const; Layer* getLayer(const std::string& id) const; + Layer* addLayer(std::unique_ptr<Layer>, optional<std::string> beforeLayerID = {}); std::unique_ptr<Layer> removeLayer(const std::string& layerID); @@ -82,6 +87,7 @@ public: void dumpDebugLogs() const; + bool mutated = false; bool loaded = false; bool spriteLoaded = false; |