diff options
Diffstat (limited to 'src/mbgl/sprite')
-rw-r--r-- | src/mbgl/sprite/sprite_atlas.cpp | 340 | ||||
-rw-r--r-- | src/mbgl/sprite/sprite_atlas.hpp | 140 | ||||
-rw-r--r-- | src/mbgl/sprite/sprite_atlas_observer.hpp | 15 | ||||
-rw-r--r-- | src/mbgl/sprite/sprite_loader.cpp | 104 | ||||
-rw-r--r-- | src/mbgl/sprite/sprite_loader.hpp | 44 | ||||
-rw-r--r-- | src/mbgl/sprite/sprite_loader_observer.hpp | 21 | ||||
-rw-r--r-- | src/mbgl/sprite/sprite_loader_worker.cpp (renamed from src/mbgl/sprite/sprite_atlas_worker.cpp) | 12 | ||||
-rw-r--r-- | src/mbgl/sprite/sprite_loader_worker.hpp (renamed from src/mbgl/sprite/sprite_atlas_worker.hpp) | 8 | ||||
-rw-r--r-- | src/mbgl/sprite/sprite_parser.cpp | 25 | ||||
-rw-r--r-- | src/mbgl/sprite/sprite_parser.hpp | 24 |
10 files changed, 202 insertions, 531 deletions
diff --git a/src/mbgl/sprite/sprite_atlas.cpp b/src/mbgl/sprite/sprite_atlas.cpp deleted file mode 100644 index fed8451aed..0000000000 --- a/src/mbgl/sprite/sprite_atlas.cpp +++ /dev/null @@ -1,340 +0,0 @@ -#include <mbgl/sprite/sprite_atlas.hpp> -#include <mbgl/sprite/sprite_atlas_worker.hpp> -#include <mbgl/sprite/sprite_atlas_observer.hpp> -#include <mbgl/sprite/sprite_parser.hpp> -#include <mbgl/gl/context.hpp> -#include <mbgl/util/logging.hpp> -#include <mbgl/util/platform.hpp> -#include <mbgl/util/math.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/util/run_loop.hpp> -#include <mbgl/actor/actor.hpp> - -#include <cassert> -#include <cmath> -#include <algorithm> - -namespace mbgl { - -static SpriteAtlasObserver nullObserver; - -struct SpriteAtlas::Loader { - Loader(Scheduler& scheduler, SpriteAtlas& spriteAtlas) - : mailbox(std::make_shared<Mailbox>(*util::RunLoop::Get())), - worker(scheduler, ActorRef<SpriteAtlas>(spriteAtlas, 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<SpriteAtlasWorker> worker; -}; - -SpriteAtlasElement::SpriteAtlasElement(Rect<uint16_t> rect_, - const style::Image& image, - Size size_, float pixelRatio) - : pos(std::move(rect_)), - sdf(image.sdf), - relativePixelRatio(image.pixelRatio / pixelRatio), - width(image.getWidth()), - height(image.getHeight()) { - - const float padding = 1; - - const float w = image.getWidth() * relativePixelRatio; - const float h = image.getHeight() * relativePixelRatio; - - size = {{ float(image.getWidth()), image.getHeight() }}; - tl = {{ float(pos.x + padding) / size_.width, float(pos.y + padding) / size_.height }}; - br = {{ float(pos.x + padding + w) / size_.width, float(pos.y + padding + h) / size_.height }}; -} - -SpriteAtlas::SpriteAtlas(Size size_, float pixelRatio_) - : size(std::move(size_)), - pixelRatio(pixelRatio_), - observer(&nullObserver), - bin(size.width, size.height), - dirty(true) { -} - -SpriteAtlas::~SpriteAtlas() = default; - -void SpriteAtlas::load(const std::string& url, Scheduler& scheduler, FileSource& fileSource) { - if (url.empty()) { - // Treat a non-existent sprite as a successfully loaded empty sprite. - markAsLoaded(); - 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<const 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<const std::string>(); - emitSpriteLoadedIfComplete(); - } else { - loader->image = res.data; - emitSpriteLoadedIfComplete(); - } - }); -} - -void SpriteAtlas::emitSpriteLoadedIfComplete() { - assert(loader); - - if (!loader->image || !loader->json) { - return; - } - - loader->worker.invoke(&SpriteAtlasWorker::parse, loader->image, loader->json); - // TODO: delete the loader? -} - -void SpriteAtlas::onParsed(Images&& result) { - markAsLoaded(); - for (auto& pair : result) { - addImage(pair.first, std::move(pair.second)); - } - observer->onSpriteLoaded(); - for (auto requestor : requestors) { - requestor->onIconsAvailable(buildIconMap()); - } - requestors.clear(); -} - -void SpriteAtlas::onError(std::exception_ptr err) { - observer->onSpriteError(err); -} - -void SpriteAtlas::setObserver(SpriteAtlasObserver* observer_) { - observer = observer_; -} - -void SpriteAtlas::dumpDebugLogs() const { - Log::Info(Event::General, "SpriteAtlas::loaded: %d", loaded); -} - -void SpriteAtlas::addImage(const std::string& id, std::unique_ptr<style::Image> image_) { - icons.clear(); - - auto it = entries.find(id); - if (it == entries.end()) { - entries.emplace(id, Entry { std::move(image_), {}, {} }); - return; - } - - Entry& entry = it->second; - - // There is already a sprite with that name in our store. - if (entry.image->image.size != image_->image.size) { - Log::Warning(Event::Sprite, "Can't change sprite dimensions for '%s'", id.c_str()); - return; - } - - entry.image = std::move(image_); - - if (entry.iconRect) { - copy(entry, &Entry::iconRect); - } - - if (entry.patternRect) { - copy(entry, &Entry::patternRect); - } -} - -void SpriteAtlas::removeImage(const std::string& id) { - icons.clear(); - - auto it = entries.find(id); - if (it == entries.end()) { - return; - } - - Entry& entry = it->second; - - if (entry.iconRect) { - bin.release(*entry.iconRect); - } - - if (entry.patternRect) { - bin.release(*entry.patternRect); - } - - entries.erase(it); -} - -const style::Image* SpriteAtlas::getImage(const std::string& id) const { - const auto it = entries.find(id); - if (it != entries.end()) { - return it->second.image.get(); - } - if (!entries.empty()) { - Log::Info(Event::Sprite, "Can't find sprite named '%s'", id.c_str()); - } - return nullptr; -} - -void SpriteAtlas::getIcons(IconRequestor& requestor) { - if (isLoaded()) { - requestor.onIconsAvailable(buildIconMap()); - } else { - requestors.insert(&requestor); - } -} - -void SpriteAtlas::removeRequestor(IconRequestor& requestor) { - requestors.erase(&requestor); -} - -optional<SpriteAtlasElement> SpriteAtlas::getIcon(const std::string& id) { - return getImage(id, &Entry::iconRect); -} - -optional<SpriteAtlasElement> SpriteAtlas::getPattern(const std::string& id) { - return getImage(id, &Entry::patternRect); -} - -optional<SpriteAtlasElement> SpriteAtlas::getImage(const std::string& id, - optional<Rect<uint16_t>> Entry::*entryRect) { - - auto it = entries.find(id); - if (it == entries.end()) { - if (!entries.empty()) { - Log::Info(Event::Sprite, "Can't find sprite named '%s'", id.c_str()); - } - return {}; - } - - Entry& entry = it->second; - - if (entry.*entryRect) { - assert(entry.image.get()); - return SpriteAtlasElement { - *(entry.*entryRect), - *entry.image, - size, - pixelRatio - }; - } - - const uint16_t pixelWidth = std::ceil(entry.image->image.size.width / pixelRatio); - const uint16_t pixelHeight = std::ceil(entry.image->image.size.height / pixelRatio); - - // Increase to next number divisible by 4, but at least 1. - // This is so we can scale down the texture coordinates and pack them - // into 2 bytes rather than 4 bytes. - const uint16_t packWidth = (pixelWidth + 1) + (4 - (pixelWidth + 1) % 4); - const uint16_t packHeight = (pixelHeight + 1) + (4 - (pixelHeight + 1) % 4); - - // We have to allocate a new area in the bin, and store an empty image in it. - Rect<uint16_t> rect = bin.allocate(packWidth, packHeight); - if (rect.w == 0) { - if (debug::spriteWarnings) { - Log::Warning(Event::Sprite, "sprite atlas bitmap overflow"); - } - return {}; - } - - entry.*entryRect = rect; - copy(entry, entryRect); - - return SpriteAtlasElement { - rect, - *entry.image, - size, - pixelRatio - }; -} - -void SpriteAtlas::copy(const Entry& entry, optional<Rect<uint16_t>> Entry::*entryRect) { - if (!image.valid()) { - image = PremultipliedImage({ static_cast<uint32_t>(std::ceil(size.width * pixelRatio)), - static_cast<uint32_t>(std::ceil(size.height * pixelRatio)) }); - image.fill(0); - } - - const PremultipliedImage& src = entry.image->image; - const Rect<uint16_t>& rect = *(entry.*entryRect); - - const uint32_t padding = 1; - const uint32_t x = (rect.x + padding) * pixelRatio; - const uint32_t y = (rect.y + padding) * pixelRatio; - const uint32_t w = src.size.width; - const uint32_t h = src.size.height; - - PremultipliedImage::copy(src, image, { 0, 0 }, { x, y }, { w, h }); - - if (entryRect == &Entry::patternRect) { - // Add 1 pixel wrapped padding on each side of the image. - PremultipliedImage::copy(src, image, { 0, h - 1 }, { x, y - 1 }, { w, 1 }); // T - PremultipliedImage::copy(src, image, { 0, 0 }, { x, y + h }, { w, 1 }); // B - PremultipliedImage::copy(src, image, { w - 1, 0 }, { x - 1, y }, { 1, h }); // L - PremultipliedImage::copy(src, image, { 0, 0 }, { x + w, y }, { 1, h }); // R - } - - dirty = true; -} - -IconMap SpriteAtlas::buildIconMap() { - if (icons.empty()) { - for (const auto& entry : entries) { - icons.emplace(std::piecewise_construct, - std::forward_as_tuple(entry.first), - std::forward_as_tuple(*getIcon(entry.first))); - - } - } - return icons; -} - -void SpriteAtlas::upload(gl::Context& context, gl::TextureUnit unit) { - if (!texture) { - texture = context.createTexture(image, unit); - } else if (dirty) { - context.updateTexture(*texture, image, unit); - } - -#if not MBGL_USE_GLES2 -// if (dirty) { -// platform::showColorDebugImage("Sprite Atlas", -// reinterpret_cast<const char*>(image.data.get()), size.width, -// size.height, image.size.width, image.size.height); -// } -#endif // MBGL_USE_GLES2 - - dirty = false; -} - -void SpriteAtlas::bind(bool linear, gl::Context& context, gl::TextureUnit unit) { - upload(context, unit); - context.bindTexture(*texture, unit, - linear ? gl::TextureFilter::Linear : gl::TextureFilter::Nearest); -} - -} // namespace mbgl diff --git a/src/mbgl/sprite/sprite_atlas.hpp b/src/mbgl/sprite/sprite_atlas.hpp deleted file mode 100644 index c3efeff44b..0000000000 --- a/src/mbgl/sprite/sprite_atlas.hpp +++ /dev/null @@ -1,140 +0,0 @@ -#pragma once - -#include <mbgl/geometry/binpack.hpp> -#include <mbgl/gl/texture.hpp> -#include <mbgl/util/noncopyable.hpp> -#include <mbgl/util/optional.hpp> -#include <mbgl/style/image.hpp> - -#include <string> -#include <map> -#include <set> -#include <unordered_map> -#include <array> -#include <memory> - -namespace mbgl { - -class Scheduler; -class FileSource; -class SpriteAtlasObserver; - -namespace gl { -class Context; -} // namespace gl - -class SpriteAtlasElement { -public: - SpriteAtlasElement(Rect<uint16_t>, const style::Image&, Size size, float pixelRatio); - - Rect<uint16_t> pos; - bool sdf; - - float relativePixelRatio; - std::array<float, 2> size; - std::array<float, 2> tl; - std::array<float, 2> br; - float width; - float height; -}; - -typedef std::map<std::string, SpriteAtlasElement> IconMap; -typedef std::set<std::string> IconDependencies; - -class IconRequestor { -public: - virtual ~IconRequestor() = default; - virtual void onIconsAvailable(IconMap) = 0; -}; - -class SpriteAtlas : public util::noncopyable { -public: - using Images = std::map<std::string, std::unique_ptr<style::Image>>; - - SpriteAtlas(Size, float pixelRatio); - ~SpriteAtlas(); - - void load(const std::string& url, Scheduler&, FileSource&); - - void markAsLoaded() { - loaded = true; - } - - bool isLoaded() const { - return loaded; - } - - void dumpDebugLogs() const; - - void setObserver(SpriteAtlasObserver*); - - const style::Image* getImage(const std::string&) const; - void addImage(const std::string&, std::unique_ptr<style::Image>); - void removeImage(const std::string&); - - void getIcons(IconRequestor& requestor); - void removeRequestor(IconRequestor& requestor); - - optional<SpriteAtlasElement> getIcon(const std::string& name); - optional<SpriteAtlasElement> getPattern(const std::string& name); - - // Binds the atlas texture to the GPU, and uploads data if it is out of date. - void bind(bool linear, gl::Context&, gl::TextureUnit unit); - - // Uploads the texture to the GPU to be available when we need it. This is a lazy operation; - // the texture is only bound when the data is out of date (=dirty). - void upload(gl::Context&, gl::TextureUnit unit); - - Size getSize() const { return size; } - float getPixelRatio() const { return pixelRatio; } - - // Only for use in tests. - const PremultipliedImage& getAtlasImage() const { - return image; - } - -private: - void emitSpriteLoadedIfComplete(); - - // Invoked by SpriteAtlasWorker - friend class SpriteAtlasWorker; - void onParsed(Images&& result); - void onError(std::exception_ptr); - - const Size size; - const float pixelRatio; - - struct Loader; - std::unique_ptr<Loader> loader; - - bool loaded = false; - - SpriteAtlasObserver* observer = nullptr; - - struct Entry { - std::unique_ptr<style::Image> image; - - // One sprite image might be used as both an icon image and a pattern image. If so, - // it must have two distinct entries in the texture. The one for the icon image has - // a single pixel transparent border, and the one for the pattern image has a single - // pixel border wrapped from the opposite side. - optional<Rect<uint16_t>> iconRect; - optional<Rect<uint16_t>> patternRect; - }; - - optional<SpriteAtlasElement> getImage(const std::string& name, optional<Rect<uint16_t>> Entry::*rect); - void copy(const Entry&, optional<Rect<uint16_t>> Entry::*rect); - - IconMap buildIconMap(); - - std::unordered_map<std::string, Entry> entries; - BinPack<uint16_t> bin; - PremultipliedImage image; - mbgl::optional<gl::Texture> texture; - bool dirty; - - std::set<IconRequestor*> requestors; - IconMap icons; -}; - -} // namespace mbgl diff --git a/src/mbgl/sprite/sprite_atlas_observer.hpp b/src/mbgl/sprite/sprite_atlas_observer.hpp deleted file mode 100644 index 263c95b0e8..0000000000 --- a/src/mbgl/sprite/sprite_atlas_observer.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include <exception> - -namespace mbgl { - -class SpriteAtlasObserver { -public: - virtual ~SpriteAtlasObserver() = default; - - virtual void onSpriteLoaded() {} - virtual void onSpriteError(std::exception_ptr) {} -}; - -} // namespace mbgl diff --git a/src/mbgl/sprite/sprite_loader.cpp b/src/mbgl/sprite/sprite_loader.cpp new file mode 100644 index 0000000000..93d6dfd9ae --- /dev/null +++ b/src/mbgl/sprite/sprite_loader.cpp @@ -0,0 +1,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<const 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<const std::string>(); + emitSpriteLoadedIfComplete(); + } else { + loader->image = res.data; + emitSpriteLoadedIfComplete(); + } + }); +} + +void SpriteLoader::emitSpriteLoadedIfComplete() { + assert(loader); + + if (!loader->image || !loader->json) { + return; + } + + loader->worker.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 diff --git a/src/mbgl/sprite/sprite_loader.hpp b/src/mbgl/sprite/sprite_loader.hpp new file mode 100644 index 0000000000..0daf46be9c --- /dev/null +++ b/src/mbgl/sprite/sprite_loader.hpp @@ -0,0 +1,44 @@ +#pragma once + +#include <mbgl/util/noncopyable.hpp> +#include <mbgl/style/image.hpp> + +#include <string> +#include <map> +#include <set> +#include <vector> +#include <array> +#include <memory> + +namespace mbgl { + +class Scheduler; +class FileSource; +class SpriteLoaderObserver; + +class SpriteLoader : public util::noncopyable { +public: + SpriteLoader(float pixelRatio); + ~SpriteLoader(); + + void load(const std::string& url, Scheduler&, FileSource&); + + void setObserver(SpriteLoaderObserver*); + +private: + void emitSpriteLoadedIfComplete(); + + // Invoked by SpriteAtlasWorker + friend class SpriteLoaderWorker; + void onParsed(std::vector<std::unique_ptr<style::Image>>&&); + void onError(std::exception_ptr); + + const float pixelRatio; + + struct Loader; + std::unique_ptr<Loader> loader; + + SpriteLoaderObserver* observer = nullptr; +}; + +} // namespace mbgl diff --git a/src/mbgl/sprite/sprite_loader_observer.hpp b/src/mbgl/sprite/sprite_loader_observer.hpp new file mode 100644 index 0000000000..c730549c2c --- /dev/null +++ b/src/mbgl/sprite/sprite_loader_observer.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include <exception> +#include <memory> +#include <vector> + +namespace mbgl { + +namespace style { +class Image; +} // namespace style + +class SpriteLoaderObserver { +public: + virtual ~SpriteLoaderObserver() = default; + + virtual void onSpriteLoaded(std::vector<std::unique_ptr<style::Image>>&&) {} + virtual void onSpriteError(std::exception_ptr) {} +}; + +} // namespace mbgl diff --git a/src/mbgl/sprite/sprite_atlas_worker.cpp b/src/mbgl/sprite/sprite_loader_worker.cpp index da507aabab..4bded33d53 100644 --- a/src/mbgl/sprite/sprite_atlas_worker.cpp +++ b/src/mbgl/sprite/sprite_loader_worker.cpp @@ -1,14 +1,14 @@ -#include <mbgl/sprite/sprite_atlas_worker.hpp> -#include <mbgl/sprite/sprite_atlas.hpp> +#include <mbgl/sprite/sprite_loader_worker.hpp> +#include <mbgl/sprite/sprite_loader.hpp> #include <mbgl/sprite/sprite_parser.hpp> namespace mbgl { -SpriteAtlasWorker::SpriteAtlasWorker(ActorRef<SpriteAtlasWorker>, ActorRef<SpriteAtlas> parent_) +SpriteLoaderWorker::SpriteLoaderWorker(ActorRef<SpriteLoaderWorker>, ActorRef<SpriteLoader> parent_) : parent(std::move(parent_)) { } -void SpriteAtlasWorker::parse(std::shared_ptr<const std::string> image, +void SpriteLoaderWorker::parse(std::shared_ptr<const std::string> image, std::shared_ptr<const std::string> json) { try { if (!image) { @@ -20,9 +20,9 @@ void SpriteAtlasWorker::parse(std::shared_ptr<const std::string> image, throw std::runtime_error("missing sprite metadata"); } - parent.invoke(&SpriteAtlas::onParsed, parseSprite(*image, *json)); + parent.invoke(&SpriteLoader::onParsed, parseSprite(*image, *json)); } catch (...) { - parent.invoke(&SpriteAtlas::onError, std::current_exception()); + parent.invoke(&SpriteLoader::onError, std::current_exception()); } } diff --git a/src/mbgl/sprite/sprite_atlas_worker.hpp b/src/mbgl/sprite/sprite_loader_worker.hpp index 70ca0d52e5..d61e07d14f 100644 --- a/src/mbgl/sprite/sprite_atlas_worker.hpp +++ b/src/mbgl/sprite/sprite_loader_worker.hpp @@ -8,16 +8,16 @@ namespace mbgl { -class SpriteAtlas; +class SpriteLoader; -class SpriteAtlasWorker { +class SpriteLoaderWorker { public: - SpriteAtlasWorker(ActorRef<SpriteAtlasWorker>, ActorRef<SpriteAtlas>); + SpriteLoaderWorker(ActorRef<SpriteLoaderWorker>, ActorRef<SpriteLoader>); void parse(std::shared_ptr<const std::string> image, std::shared_ptr<const std::string> json); private: - ActorRef<SpriteAtlas> parent; + ActorRef<SpriteLoader> parent; }; } // namespace mbgl diff --git a/src/mbgl/sprite/sprite_parser.cpp b/src/mbgl/sprite/sprite_parser.cpp index c3ed20d03f..1a36e3e990 100644 --- a/src/mbgl/sprite/sprite_parser.cpp +++ b/src/mbgl/sprite/sprite_parser.cpp @@ -13,13 +13,14 @@ namespace mbgl { -std::unique_ptr<style::Image> createStyleImage(const PremultipliedImage& image, - const uint32_t srcX, - const uint32_t srcY, - const uint32_t width, - const uint32_t height, - const double ratio, - const bool sdf) { +std::unique_ptr<style::Image> createStyleImage(const std::string& id, + const PremultipliedImage& image, + const uint32_t srcX, + const uint32_t srcY, + const uint32_t width, + const uint32_t height, + const double ratio, + const bool sdf) { // Disallow invalid parameter configurations. if (width <= 0 || height <= 0 || width > 1024 || height > 1024 || ratio <= 0 || ratio > 10 || @@ -37,7 +38,7 @@ std::unique_ptr<style::Image> createStyleImage(const PremultipliedImage& image, // Copy from the source image into our individual sprite image PremultipliedImage::copy(image, dstImage, { srcX, srcY }, { 0, 0 }, { width, height }); - return std::make_unique<style::Image>(std::move(dstImage), ratio, sdf); + return std::make_unique<style::Image>(id, std::move(dstImage), ratio, sdf); } namespace { @@ -84,7 +85,7 @@ bool getBoolean(const JSValue& value, const char* name, const bool def = false) } // namespace -Images parseSprite(const std::string& encodedImage, const std::string& json) { +std::vector<std::unique_ptr<style::Image>> parseSprite(const std::string& encodedImage, const std::string& json) { const PremultipliedImage raster = decodeImage(encodedImage); JSDocument doc; @@ -96,7 +97,7 @@ Images parseSprite(const std::string& encodedImage, const std::string& json) { } else if (!doc.IsObject()) { throw std::runtime_error("Sprite JSON root must be an object"); } else { - Images images; + std::vector<std::unique_ptr<style::Image>> images; for (const auto& property : doc.GetObject()) { const std::string name = { property.name.GetString(), property.name.GetStringLength() }; const JSValue& value = property.value; @@ -109,9 +110,9 @@ Images parseSprite(const std::string& encodedImage, const std::string& json) { const double pixelRatio = getDouble(value, "pixelRatio", 1); const bool sdf = getBoolean(value, "sdf", false); - auto image = createStyleImage(raster, x, y, width, height, pixelRatio, sdf); + auto image = createStyleImage(name, raster, x, y, width, height, pixelRatio, sdf); if (image) { - images.emplace(name, std::move(image)); + images.push_back(std::move(image)); } } } diff --git a/src/mbgl/sprite/sprite_parser.hpp b/src/mbgl/sprite/sprite_parser.hpp index 5be8435ebb..f602818d3b 100644 --- a/src/mbgl/sprite/sprite_parser.hpp +++ b/src/mbgl/sprite/sprite_parser.hpp @@ -1,13 +1,10 @@ #pragma once #include <mbgl/util/image.hpp> -#include <mbgl/util/noncopyable.hpp> -#include <mbgl/util/variant.hpp> -#include <mbgl/util/geo.hpp> #include <string> #include <memory> -#include <map> +#include <vector> namespace mbgl { @@ -16,17 +13,16 @@ class Image; } // namespace style // Extracts an individual image from a spritesheet from the given location. -std::unique_ptr<style::Image> createStyleImage(const PremultipliedImage&, - uint32_t srcX, - uint32_t srcY, - uint32_t srcWidth, - uint32_t srcHeight, - double ratio, - bool sdf); - -using Images = std::map<std::string, std::unique_ptr<style::Image>>; +std::unique_ptr<style::Image> createStyleImage(const std::string& id, + const PremultipliedImage&, + uint32_t srcX, + uint32_t srcY, + uint32_t srcWidth, + uint32_t srcHeight, + double ratio, + bool sdf); // Parses an image and an associated JSON file and returns the sprite objects. -Images parseSprite(const std::string& image, const std::string& json); +std::vector<std::unique_ptr<style::Image>> parseSprite(const std::string& image, const std::string& json); } // namespace mbgl |