106 lines
3.3 KiB
C++
106 lines
3.3 KiB
C++
#include <mbgl/actor/actor.hpp>
|
|
#include <mbgl/actor/scheduler.hpp>
|
|
#include <mbgl/sprite/sprite_loader.hpp>
|
|
#include <mbgl/sprite/sprite_loader_observer.hpp>
|
|
#include <mbgl/sprite/sprite_loader_worker.hpp>
|
|
#include <mbgl/sprite/sprite_parser.hpp>
|
|
#include <mbgl/storage/file_source.hpp>
|
|
#include <mbgl/storage/resource.hpp>
|
|
#include <mbgl/storage/response.hpp>
|
|
#include <mbgl/util/async_request.hpp>
|
|
#include <mbgl/util/constants.hpp>
|
|
#include <mbgl/util/exception.hpp>
|
|
#include <mbgl/util/logging.hpp>
|
|
#include <mbgl/util/platform.hpp>
|
|
#include <mbgl/util/std.hpp>
|
|
|
|
#include <cassert>
|
|
|
|
namespace mbgl {
|
|
|
|
static SpriteLoaderObserver nullObserver;
|
|
|
|
struct SpriteLoader::Loader {
|
|
Loader(SpriteLoader& imageManager)
|
|
: mailbox(std::make_shared<Mailbox>(*Scheduler::GetCurrent())),
|
|
worker(Scheduler::GetBackground(), ActorRef<SpriteLoader>(imageManager, mailbox)) {
|
|
}
|
|
|
|
std::shared_ptr<const std::string> image;
|
|
std::shared_ptr<const std::string> json;
|
|
std::unique_ptr<AsyncRequest> jsonRequest;
|
|
std::unique_ptr<AsyncRequest> spriteRequest;
|
|
std::shared_ptr<Mailbox> mailbox;
|
|
Actor<SpriteLoaderWorker> worker;
|
|
};
|
|
|
|
SpriteLoader::SpriteLoader(float pixelRatio_)
|
|
: pixelRatio(pixelRatio_)
|
|
, observer(&nullObserver) {
|
|
}
|
|
|
|
SpriteLoader::~SpriteLoader() = default;
|
|
|
|
void SpriteLoader::load(const std::string& url, FileSource& fileSource) {
|
|
if (url.empty()) {
|
|
// Treat a non-existent sprite as a successfully loaded empty sprite.
|
|
observer->onSpriteLoaded({});
|
|
return;
|
|
}
|
|
|
|
loader = std::make_unique<Loader>(*this);
|
|
|
|
loader->jsonRequest = fileSource.request(Resource::spriteJSON(url, pixelRatio), [this](Response res) {
|
|
if (res.error) {
|
|
observer->onSpriteError(std::make_exception_ptr(std::runtime_error(res.error->message)));
|
|
} else if (res.notModified) {
|
|
return;
|
|
} else if (res.noContent) {
|
|
loader->json = std::make_shared<std::string>();
|
|
emitSpriteLoadedIfComplete();
|
|
} else {
|
|
// Only trigger a sprite loaded event we got new data.
|
|
loader->json = res.data;
|
|
emitSpriteLoadedIfComplete();
|
|
}
|
|
});
|
|
|
|
loader->spriteRequest = fileSource.request(Resource::spriteImage(url, pixelRatio), [this](Response res) {
|
|
if (res.error) {
|
|
observer->onSpriteError(std::make_exception_ptr(std::runtime_error(res.error->message)));
|
|
} else if (res.notModified) {
|
|
return;
|
|
} else if (res.noContent) {
|
|
loader->image = std::make_shared<std::string>();
|
|
emitSpriteLoadedIfComplete();
|
|
} else {
|
|
loader->image = res.data;
|
|
emitSpriteLoadedIfComplete();
|
|
}
|
|
});
|
|
}
|
|
|
|
void SpriteLoader::emitSpriteLoadedIfComplete() {
|
|
assert(loader);
|
|
|
|
if (!loader->image || !loader->json) {
|
|
return;
|
|
}
|
|
|
|
loader->worker.self().invoke(&SpriteLoaderWorker::parse, loader->image, loader->json);
|
|
}
|
|
|
|
void SpriteLoader::onParsed(std::vector<Immutable<style::Image::Impl>> result) {
|
|
observer->onSpriteLoaded(std::move(result));
|
|
}
|
|
|
|
void SpriteLoader::onError(std::exception_ptr err) {
|
|
observer->onSpriteError(err);
|
|
}
|
|
|
|
void SpriteLoader::setObserver(SpriteLoaderObserver* observer_) {
|
|
observer = observer_;
|
|
}
|
|
|
|
} // namespace mbgl
|