diff options
Diffstat (limited to 'src/mbgl/sprite/sprite_store.cpp')
-rw-r--r-- | src/mbgl/sprite/sprite_store.cpp | 115 |
1 files changed, 114 insertions, 1 deletions
diff --git a/src/mbgl/sprite/sprite_store.cpp b/src/mbgl/sprite/sprite_store.cpp index fb6833114e..27b33e51e3 100644 --- a/src/mbgl/sprite/sprite_store.cpp +++ b/src/mbgl/sprite/sprite_store.cpp @@ -1,9 +1,122 @@ #include <mbgl/sprite/sprite_store.hpp> - +#include <mbgl/sprite/sprite_parser.hpp> #include <mbgl/platform/log.hpp> +#include <mbgl/storage/file_source.hpp> +#include <mbgl/storage/resource.hpp> +#include <mbgl/storage/response.hpp> +#include <mbgl/storage/request_holder.hpp> +#include <mbgl/util/exception.hpp> +#include <mbgl/util/thread_context.hpp> +#include <mbgl/util/run_loop.hpp> + +#include <string> +#include <sstream> namespace mbgl { +struct SpriteStore::Loader { + std::shared_ptr<const std::string> image; + std::shared_ptr<const std::string> json; + RequestHolder jsonRequest; + RequestHolder spriteRequest; +}; + +SpriteStore::SpriteStore(float pixelRatio_) + : pixelRatio(pixelRatio_ > 1 ? 2 : 1) { +} + +SpriteStore::~SpriteStore() = default; + +void SpriteStore::setURL(const std::string& url) { + if (url.empty()) { + // Treat a non-existent sprite as a successfully loaded empty sprite. + loaded = true; + return; + } + + std::string spriteURL(url + (pixelRatio > 1 ? "@2x" : "") + ".png"); + std::string jsonURL(url + (pixelRatio > 1 ? "@2x" : "") + ".json"); + + loader = std::make_unique<Loader>(); + + FileSource* fs = util::ThreadContext::getFileSource(); + loader->jsonRequest = fs->request({ Resource::Kind::SpriteJSON, jsonURL }, util::RunLoop::getLoop(), + [this, jsonURL](const Response& res) { + if (res.stale) { + // Only handle fresh responses. + return; + } + loader->jsonRequest = nullptr; + + if (res.error) { + std::stringstream message; + message << "Failed to load [" << jsonURL << "]: " << res.error->message; + emitSpriteLoadingFailed(message.str()); + return; + } else { + loader->json = res.data; + } + emitSpriteLoadedIfComplete(); + }); + + loader->spriteRequest = + fs->request({ Resource::Kind::SpriteImage, spriteURL }, util::RunLoop::getLoop(), + [this, spriteURL](const Response& res) { + if (res.stale) { + // Only handle fresh responses. + return; + } + loader->spriteRequest = nullptr; + + if (res.error) { + std::stringstream message; + message << "Failed to load [" << spriteURL << "]: " << res.error->message; + emitSpriteLoadingFailed(message.str()); + return; + } else { + loader->image = res.data; + } + emitSpriteLoadedIfComplete(); + }); +} + +void SpriteStore::emitSpriteLoadedIfComplete() { + assert(loader); + + if (!loader->image || !loader->json) { + return; + } + + auto local = std::move(loader); + auto result = parseSprite(*local->image, *local->json); + if (result.is<Sprites>()) { + loaded = true; + setSprites(result.get<Sprites>()); + if (observer) { + observer->onSpriteLoaded(); + } + } else { + emitSpriteLoadingFailed(result.get<std::string>()); + } +} + +void SpriteStore::emitSpriteLoadingFailed(const std::string& message) { + if (!observer) { + return; + } + + auto error = std::make_exception_ptr(util::SpriteLoadingException(message)); + observer->onSpriteLoadingFailed(error); +} + +void SpriteStore::setObserver(Observer* observer_) { + observer = observer_; +} + +void SpriteStore::dumpDebugLogs() const { + Log::Info(Event::General, "SpriteStore::loaded: %d", loaded); +} + void SpriteStore::setSprite(const std::string& name, std::shared_ptr<const SpriteImage> sprite) { std::lock_guard<std::mutex> lock(mutex); _setSprite(name, sprite); |