diff --git a/src/mbgl/annotation/sprite_image.cpp b/src/mbgl/annotation/sprite_image.cpp index 1a5ae8e09..e482d8f13 100644 --- a/src/mbgl/annotation/sprite_image.cpp +++ b/src/mbgl/annotation/sprite_image.cpp @@ -9,13 +9,15 @@ namespace mbgl { SpriteImage::SpriteImage(const uint16_t width_, const uint16_t height_, const float pixelRatio_, - std::string&& data_) + std::string&& data_, + bool sdf_) : width(width_), height(height_), pixelRatio(pixelRatio_), pixelWidth(std::ceil(width * pixelRatio)), pixelHeight(std::ceil(height * pixelRatio)), - data(std::move(data_)) { + data(std::move(data_)), + sdf(sdf_) { const size_t size = pixelWidth * pixelHeight * 4; if (size == 0) { throw util::SpriteImageException("Sprite image dimensions may not be zero"); diff --git a/src/mbgl/annotation/sprite_image.hpp b/src/mbgl/annotation/sprite_image.hpp index 19de77c0c..7d8ea0501 100644 --- a/src/mbgl/annotation/sprite_image.hpp +++ b/src/mbgl/annotation/sprite_image.hpp @@ -12,7 +12,8 @@ namespace mbgl { class SpriteImage : private util::noncopyable { public: - SpriteImage(uint16_t width, uint16_t height, float pixelRatio, std::string&& data); + SpriteImage( + uint16_t width, uint16_t height, float pixelRatio, std::string&& data, bool sdf = false); // Logical dimensions of the sprite image. const uint16_t width; @@ -29,6 +30,9 @@ public: // (width * ratio) * (height * ratio) * 4 (RGBA) bytes. The scan lines may // not have gaps between them (i.e. stride == 0). const std::string data; + + // Whether this image should be interpreted as a signed distance field icon. + const bool sdf; }; } diff --git a/src/mbgl/annotation/sprite_parser.cpp b/src/mbgl/annotation/sprite_parser.cpp index 2791c54a0..c5c731d51 100644 --- a/src/mbgl/annotation/sprite_parser.cpp +++ b/src/mbgl/annotation/sprite_parser.cpp @@ -18,7 +18,7 @@ SpriteImagePtr createSpriteImage(const util::Image& image, const uint16_t srcWidth, const uint16_t srcHeight, const double ratio, - const bool) { + const bool sdf) { // Disallow invalid parameter configurations. if (srcWidth == 0 || srcHeight == 0 || ratio <= 0 || ratio > 10 || srcWidth > 1024 || srcHeight > 1024) { @@ -52,7 +52,7 @@ SpriteImagePtr createSpriteImage(const util::Image& image, } } - return std::make_unique(width, height, ratio, std::move(data)); + return std::make_unique(width, height, ratio, std::move(data), sdf); } namespace { diff --git a/src/mbgl/geometry/sprite_atlas.cpp b/src/mbgl/geometry/sprite_atlas.cpp index b3d2ba724..dc42a97b9 100644 --- a/src/mbgl/geometry/sprite_atlas.cpp +++ b/src/mbgl/geometry/sprite_atlas.cpp @@ -22,50 +22,12 @@ using namespace mbgl; SpriteAtlas::SpriteAtlas(dimension width_, dimension height_, SpriteStore& store_) : width(width_), height(height_), - bin(width_, height_), store(store_), + pixelRatio(store.pixelRatio), + bin(width_, height_), dirty(true) { } -bool SpriteAtlas::resize(const float newRatio) { - if (pixelRatio == newRatio) return false; - - std::lock_guard lock(mtx); - - const float oldRatio = pixelRatio; - pixelRatio = newRatio; - - if (data) { - const auto oldData = std::move(data); - allocate(); - - const int old_w = width * oldRatio; - const int old_h = height * oldRatio; - const int new_w = width * newRatio; - const int new_h = height * newRatio; - - // Basic image scaling. TODO: Replace this with better image scaling. - for (int y = 0; y < new_h; y++) { - const int old_yoffset = ((y * old_h) / new_h) * old_w; - const int new_yoffset = y * new_w; - for (int x = 0; x < new_w; x++) { - const int old_x = (x * old_w) / new_w; - data[new_yoffset + x] = oldData[old_yoffset + old_x]; - } - } - - dirty = true; - fullUploadRequired = true; - - // Mark all sprite images as in need of update - for (const auto &pair : images) { - uninitialized.emplace(pair.first); - } - } - - return dirty; -} - Rect SpriteAtlas::allocateImage(const size_t pixel_width, const size_t pixel_height) { // Increase to next number divisible by 4, but at least 1. // This is so we can scale down the texture coordinates and pack them @@ -86,17 +48,17 @@ Rect SpriteAtlas::allocateImage(const size_t pixel_width return rect; } -Rect SpriteAtlas::getImage(const std::string& name, const bool wrap) { +SpriteAtlasElement SpriteAtlas::getImage(const std::string& name, const bool wrap) { std::lock_guard lock(mtx); auto rect_it = images.find(name); if (rect_it != images.end()) { - return rect_it->second.pos; + return { rect_it->second.pos, rect_it->second.texture }; } auto sprite = store.getSprite(name); if (!sprite) { - return Rect { 0, 0, 0, 0 }; + return { Rect { 0, 0, 0, 0 }, nullptr }; } Rect rect = allocateImage(sprite->width, sprite->height); @@ -104,19 +66,19 @@ Rect SpriteAtlas::getImage(const std::string& name, cons if (debug::spriteWarnings) { Log::Warning(Event::Sprite, "sprite atlas bitmap overflow"); } - return rect; + return { Rect { 0, 0, 0, 0 }, nullptr }; } const Holder& holder = images.emplace(name, Holder{ sprite, rect }).first->second; copy(holder, wrap); - return rect; + return { rect, sprite }; } SpriteAtlasPosition SpriteAtlas::getPosition(const std::string& name, bool repeating) { std::lock_guard lock(mtx); - Rect rect = getImage(name, repeating); + auto rect = getImage(name, repeating).pos; if (repeating) { // When the image is repeating, get the correct position of the image, rather than the // one rounded up to 4 pixels. @@ -202,35 +164,6 @@ void SpriteAtlas::copy(const Holder& holder, const bool wrap) { dirty = true; } -// void SpriteAtlas::setSprite(util::ptr sprite_) { -// std::lock_guard lock(mtx); - -// sprite = sprite_; - -// if (!sprite->isLoaded()) return; - -// util::erase_if(uninitialized, [this](const std::string &name) { -// Rect dst = getImage(name, false); -// const SpritePosition& src = sprite->getSpritePosition(name); -// if (!src) { -// if (debug::spriteWarnings) { -// Log::Warning(Event::Sprite, "sprite doesn't have image with name '%s'", name.c_str()); -// } -// return true; -// } - -// if (src.width == dst.w * pixelRatio && src.height == dst.h * pixelRatio && src.pixelRatio == pixelRatio) { -// copy(dst, src, false); -// return true; -// } else { -// if (debug::spriteWarnings) { -// Log::Warning(Event::Sprite, "sprite icon dimension mismatch"); -// } -// return false; -// } -// }); -// } - void SpriteAtlas::upload() { if (dirty) { bind(); @@ -294,7 +227,9 @@ void SpriteAtlas::bind(bool linear) { dirty = false; #ifndef GL_ES_VERSION_2_0 - // platform::showColorDebugImage("Sprite Atlas", reinterpret_cast(data), width * pixelRatio, height * pixelRatio, width * pixelRatio, height * pixelRatio); + // platform::showColorDebugImage("Sprite Atlas", reinterpret_cast(data.get()), + // width * pixelRatio, height * pixelRatio, width * pixelRatio, + // height * pixelRatio); #endif } }; @@ -306,3 +241,11 @@ SpriteAtlas::~SpriteAtlas() { texture = 0; } } + +SpriteAtlas::Holder::Holder(const std::shared_ptr& texture_, + const Rect& pos_) + : texture(texture_), pos(pos_) { +} + +SpriteAtlas::Holder::Holder(Holder&& h) : texture(std::move(h.texture)), pos(h.pos) { +} diff --git a/src/mbgl/geometry/sprite_atlas.hpp b/src/mbgl/geometry/sprite_atlas.hpp index 57e49e3c9..d80b9cb94 100644 --- a/src/mbgl/geometry/sprite_atlas.hpp +++ b/src/mbgl/geometry/sprite_atlas.hpp @@ -29,6 +29,11 @@ struct SpriteAtlasPosition { std::array br; }; +struct SpriteAtlasElement { + const Rect pos; + const std::shared_ptr texture; +}; + class SpriteAtlas : public util::noncopyable { public: typedef uint16_t dimension; @@ -37,15 +42,12 @@ public: SpriteAtlas(dimension width, dimension height, SpriteStore& store); ~SpriteAtlas(); - // Changes the pixel ratio. - bool resize(float newRatio); - // Returns the coordinates of an image that is sourced from the sprite image. // This getter attempts to read the image from the sprite if it is already loaded. // In that case, it copies it into the sprite atlas and returns the dimensions. // Otherwise, it returns a 0/0/0/0 rect. // This function is used during bucket creation. - Rect getImage(const std::string& name, const bool wrap); + SpriteAtlasElement getImage(const std::string& name, const bool wrap); // This function is used for getting the position during render time. SpriteAtlasPosition getPosition(const std::string& name, bool repeating = false); @@ -68,10 +70,9 @@ public: private: struct Holder : private util::noncopyable { - Holder(const std::shared_ptr&, const Rect&); - Holder(Holder&&); + inline Holder(const std::shared_ptr&, const Rect&); + inline Holder(Holder&&); std::shared_ptr texture; - std::set references; const Rect pos; }; @@ -80,9 +81,9 @@ private: void copy(const Holder& holder, const bool wrap); std::recursive_mutex mtx; - float pixelRatio = 1.0f; - BinPack bin; SpriteStore& store; + const float pixelRatio; + BinPack bin; std::map images; std::set uninitialized; std::unique_ptr data; diff --git a/src/mbgl/map/map_context.cpp b/src/mbgl/map/map_context.cpp index 455539436..05a046fdb 100644 --- a/src/mbgl/map/map_context.cpp +++ b/src/mbgl/map/map_context.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include @@ -124,7 +125,7 @@ void MapContext::loadStyleJSON(const std::string& json, const std::string& base) assert(util::ThreadContext::currentlyOn(util::ThreadType::Map)); style.reset(); - style = std::make_unique