summaryrefslogtreecommitdiff
path: root/src/mbgl/style/style_impl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mbgl/style/style_impl.cpp')
-rw-r--r--src/mbgl/style/style_impl.cpp321
1 files changed, 321 insertions, 0 deletions
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