1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
#include <mbgl/sprite/sprite_loader.hpp>
#include <mbgl/sprite/sprite_loader_worker.hpp>
#include <mbgl/sprite/sprite_loader_observer.hpp>
#include <mbgl/sprite/sprite_parser.hpp>
#include <mbgl/util/logging.hpp>
#include <mbgl/util/platform.hpp>
#include <mbgl/util/std.hpp>
#include <mbgl/util/constants.hpp>
#include <mbgl/util/exception.hpp>
#include <mbgl/storage/file_source.hpp>
#include <mbgl/storage/resource.hpp>
#include <mbgl/storage/response.hpp>
#include <mbgl/actor/actor.hpp>
#include <mbgl/actor/scheduler.hpp>
#include <cassert>
namespace mbgl {
static SpriteLoaderObserver nullObserver;
struct SpriteLoader::Loader {
Loader(Scheduler& scheduler, SpriteLoader& imageManager)
: mailbox(std::make_shared<Mailbox>(*Scheduler::GetCurrent())),
worker(scheduler, 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, Scheduler& scheduler, FileSource& fileSource) {
if (url.empty()) {
// Treat a non-existent sprite as a successfully loaded empty sprite.
observer->onSpriteLoaded({});
return;
}
loader = std::make_unique<Loader>(scheduler, *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<std::unique_ptr<style::Image>>&& 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
|