use SpriteStore from the SpriteAtlas
This commit is contained in:
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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<const SpriteImage>(width, height, ratio, std::move(data));
|
||||
return std::make_unique<const SpriteImage>(width, height, ratio, std::move(data), sdf);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -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<std::recursive_mutex> 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::dimension> 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::dimension> SpriteAtlas::allocateImage(const size_t pixel_width
|
||||
return rect;
|
||||
}
|
||||
|
||||
Rect<SpriteAtlas::dimension> SpriteAtlas::getImage(const std::string& name, const bool wrap) {
|
||||
SpriteAtlasElement SpriteAtlas::getImage(const std::string& name, const bool wrap) {
|
||||
std::lock_guard<std::recursive_mutex> 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<dimension> { 0, 0, 0, 0 };
|
||||
return { Rect<dimension> { 0, 0, 0, 0 }, nullptr };
|
||||
}
|
||||
|
||||
Rect<dimension> rect = allocateImage(sprite->width, sprite->height);
|
||||
@@ -104,19 +66,19 @@ Rect<SpriteAtlas::dimension> SpriteAtlas::getImage(const std::string& name, cons
|
||||
if (debug::spriteWarnings) {
|
||||
Log::Warning(Event::Sprite, "sprite atlas bitmap overflow");
|
||||
}
|
||||
return rect;
|
||||
return { Rect<dimension> { 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<std::recursive_mutex> lock(mtx);
|
||||
|
||||
Rect<dimension> 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> sprite_) {
|
||||
// std::lock_guard<std::recursive_mutex> lock(mtx);
|
||||
|
||||
// sprite = sprite_;
|
||||
|
||||
// if (!sprite->isLoaded()) return;
|
||||
|
||||
// util::erase_if(uninitialized, [this](const std::string &name) {
|
||||
// Rect<dimension> 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<const char *>(data), width * pixelRatio, height * pixelRatio, width * pixelRatio, height * pixelRatio);
|
||||
// platform::showColorDebugImage("Sprite Atlas", reinterpret_cast<const char*>(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<const SpriteImage>& texture_,
|
||||
const Rect<dimension>& pos_)
|
||||
: texture(texture_), pos(pos_) {
|
||||
}
|
||||
|
||||
SpriteAtlas::Holder::Holder(Holder&& h) : texture(std::move(h.texture)), pos(h.pos) {
|
||||
}
|
||||
|
||||
@@ -29,6 +29,11 @@ struct SpriteAtlasPosition {
|
||||
std::array<float, 2> br;
|
||||
};
|
||||
|
||||
struct SpriteAtlasElement {
|
||||
const Rect<uint16_t> pos;
|
||||
const std::shared_ptr<const SpriteImage> 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<dimension> 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 SpriteImage>&, const Rect<dimension>&);
|
||||
Holder(Holder&&);
|
||||
inline Holder(const std::shared_ptr<const SpriteImage>&, const Rect<dimension>&);
|
||||
inline Holder(Holder&&);
|
||||
std::shared_ptr<const SpriteImage> texture;
|
||||
std::set<uintptr_t> references;
|
||||
const Rect<dimension> pos;
|
||||
};
|
||||
|
||||
@@ -80,9 +81,9 @@ private:
|
||||
void copy(const Holder& holder, const bool wrap);
|
||||
|
||||
std::recursive_mutex mtx;
|
||||
float pixelRatio = 1.0f;
|
||||
BinPack<dimension> bin;
|
||||
SpriteStore& store;
|
||||
const float pixelRatio;
|
||||
BinPack<dimension> bin;
|
||||
std::map<std::string, Holder> images;
|
||||
std::set<std::string> uninitialized;
|
||||
std::unique_ptr<uint32_t[]> data;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <mbgl/map/view.hpp>
|
||||
#include <mbgl/map/still_image.hpp>
|
||||
#include <mbgl/map/annotation.hpp>
|
||||
#include <mbgl/annotation/sprite_store.hpp>
|
||||
|
||||
#include <mbgl/platform/log.hpp>
|
||||
|
||||
@@ -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<Style>(json, base, asyncUpdate->get()->loop);
|
||||
style = std::make_unique<Style>(json, base, data, asyncUpdate->get()->loop);
|
||||
style->cascade(data.getClasses());
|
||||
style->setDefaultTransitionDuration(data.getDefaultTransitionDuration());
|
||||
style->setObserver(this);
|
||||
@@ -257,7 +258,7 @@ void MapContext::update() {
|
||||
style->recalculate(transformState.getNormalizedZoom(), now);
|
||||
}
|
||||
|
||||
style->update(data, transformState, *texturePool);
|
||||
style->update(transformState, *texturePool);
|
||||
|
||||
if (data.mode == MapMode::Continuous) {
|
||||
view.invalidate();
|
||||
@@ -343,8 +344,12 @@ bool MapContext::isLoaded() const {
|
||||
|
||||
double MapContext::getTopOffsetPixelsForAnnotationSymbol(const std::string& symbol) {
|
||||
assert(util::ThreadContext::currentlyOn(util::ThreadType::Map));
|
||||
const SpritePosition pos = style->sprite->getSpritePosition(symbol);
|
||||
return -pos.height / pos.pixelRatio / 2;
|
||||
auto sprite = style->spriteStore->getSprite(symbol);
|
||||
if (sprite) {
|
||||
return -sprite->height / 2;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void MapContext::setSourceTileCacheSize(size_t size) {
|
||||
|
||||
@@ -17,20 +17,8 @@
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
SpritePosition::SpritePosition(uint16_t x_, uint16_t y_, uint16_t width_, uint16_t height_, float pixelRatio_, bool sdf_)
|
||||
: x(x_),
|
||||
y(y_),
|
||||
width(width_),
|
||||
height(height_),
|
||||
pixelRatio(pixelRatio_),
|
||||
sdf(sdf_) {
|
||||
}
|
||||
|
||||
Sprite::Sprite(const std::string& baseUrl, float pixelRatio_)
|
||||
: pixelRatio(pixelRatio_ > 1 ? 2 : 1),
|
||||
raster(),
|
||||
loadedImage(false),
|
||||
loadedJSON(false) {
|
||||
: pixelRatio(pixelRatio_ > 1 ? 2 : 1) {
|
||||
if (baseUrl.empty()) {
|
||||
// Treat a non-existent sprite as a successfully loaded empty sprite.
|
||||
loadedImage = true;
|
||||
@@ -45,8 +33,8 @@ Sprite::Sprite(const std::string& baseUrl, float pixelRatio_)
|
||||
jsonRequest = fs->request({ Resource::Kind::JSON, jsonURL }, util::RunLoop::getLoop(), [this, jsonURL](const Response &res) {
|
||||
jsonRequest = nullptr;
|
||||
if (res.status == Response::Successful) {
|
||||
body = res.data;
|
||||
parseJSON(jsonURL);
|
||||
json = res.data;
|
||||
loadedJSON = true;
|
||||
} else {
|
||||
std::stringstream message;
|
||||
message << "Failed to load [" << jsonURL << "]: " << res.message;
|
||||
@@ -60,7 +48,7 @@ Sprite::Sprite(const std::string& baseUrl, float pixelRatio_)
|
||||
spriteRequest = nullptr;
|
||||
if (res.status == Response::Successful) {
|
||||
image = res.data;
|
||||
parseImage(spriteURL);
|
||||
loadedImage = true;
|
||||
} else {
|
||||
std::stringstream message;
|
||||
message << "Failed to load [" << spriteURL << "]: " << res.message;
|
||||
@@ -100,69 +88,6 @@ bool Sprite::isLoaded() const {
|
||||
return loadedImage && loadedJSON;
|
||||
}
|
||||
|
||||
bool Sprite::hasPixelRatio(float ratio) const {
|
||||
return pixelRatio == (ratio > 1 ? 2 : 1);
|
||||
}
|
||||
|
||||
void Sprite::parseImage(const std::string& spriteURL) {
|
||||
raster = std::make_unique<util::Image>(image);
|
||||
if (!*raster) {
|
||||
raster.reset();
|
||||
std::stringstream message;
|
||||
message << "Failed to parse [" << spriteURL << "]";
|
||||
emitSpriteLoadingFailed(message.str());
|
||||
return;
|
||||
}
|
||||
|
||||
image.clear();
|
||||
loadedImage = true;
|
||||
}
|
||||
|
||||
void Sprite::parseJSON(const std::string& jsonURL) {
|
||||
rapidjson::Document d;
|
||||
d.Parse<0>(body.c_str());
|
||||
body.clear();
|
||||
|
||||
if (d.HasParseError()) {
|
||||
std::stringstream message;
|
||||
message << "Failed to parse [" << jsonURL << "]: " << d.GetErrorOffset() << " - " << d.GetParseError();
|
||||
emitSpriteLoadingFailed(message.str());
|
||||
} else if (d.IsObject()) {
|
||||
for (rapidjson::Value::ConstMemberIterator itr = d.MemberBegin(); itr != d.MemberEnd(); ++itr) {
|
||||
const std::string name = { itr->name.GetString(), itr->name.GetStringLength() };
|
||||
const rapidjson::Value& value = itr->value;
|
||||
|
||||
if (value.IsObject()) {
|
||||
uint16_t x = 0;
|
||||
uint16_t y = 0;
|
||||
uint16_t width = 0;
|
||||
uint16_t height = 0;
|
||||
float spritePixelRatio = 1.0f;
|
||||
bool sdf = false;
|
||||
|
||||
if (value.HasMember("x")) x = value["x"].GetInt();
|
||||
if (value.HasMember("y")) y = value["y"].GetInt();
|
||||
if (value.HasMember("width")) width = value["width"].GetInt();
|
||||
if (value.HasMember("height")) height = value["height"].GetInt();
|
||||
if (value.HasMember("pixelRatio")) spritePixelRatio = value["pixelRatio"].GetInt();
|
||||
if (value.HasMember("sdf")) sdf = value["sdf"].GetBool();
|
||||
pos.emplace(name, SpritePosition { x, y, width, height, spritePixelRatio, sdf });
|
||||
}
|
||||
}
|
||||
loadedJSON = true;
|
||||
} else {
|
||||
std::stringstream message;
|
||||
message << "Failed to parse [" << jsonURL << "]: Root is not an object";
|
||||
emitSpriteLoadingFailed(message.str());
|
||||
}
|
||||
}
|
||||
|
||||
const SpritePosition &Sprite::getSpritePosition(const std::string& name) const {
|
||||
if (!isLoaded()) return empty;
|
||||
auto it = pos.find(name);
|
||||
return it == pos.end() ? empty : it->second;
|
||||
}
|
||||
|
||||
void Sprite::setObserver(Observer* observer_) {
|
||||
observer = observer_;
|
||||
}
|
||||
|
||||
@@ -16,21 +16,6 @@ namespace mbgl {
|
||||
|
||||
class Request;
|
||||
|
||||
class SpritePosition {
|
||||
public:
|
||||
explicit SpritePosition() {}
|
||||
explicit SpritePosition(uint16_t x, uint16_t y, uint16_t width, uint16_t height, float pixelRatio, bool sdf);
|
||||
|
||||
operator bool() const {
|
||||
return !(width == 0 && height == 0 && x == 0 && y == 0);
|
||||
}
|
||||
|
||||
uint16_t x = 0, y = 0;
|
||||
uint16_t width = 0, height = 0;
|
||||
float pixelRatio = 1.0f;
|
||||
bool sdf = false;
|
||||
};
|
||||
|
||||
class Sprite : private util::noncopyable {
|
||||
public:
|
||||
class Observer {
|
||||
@@ -44,29 +29,24 @@ public:
|
||||
Sprite(const std::string& baseUrl, float pixelRatio);
|
||||
~Sprite();
|
||||
|
||||
const SpritePosition &getSpritePosition(const std::string& name) const;
|
||||
|
||||
bool hasPixelRatio(float ratio) const;
|
||||
|
||||
bool isLoaded() const;
|
||||
|
||||
const float pixelRatio;
|
||||
std::unique_ptr<util::Image> raster;
|
||||
|
||||
void setObserver(Observer* observer);
|
||||
|
||||
inline const std::string& getImage() const { return image; }
|
||||
inline const std::string& getJSON() const { return json; }
|
||||
|
||||
private:
|
||||
void emitSpriteLoadedIfComplete();
|
||||
void emitSpriteLoadingFailed(const std::string& message);
|
||||
|
||||
void parseJSON(const std::string& jsonURL);
|
||||
void parseImage(const std::string& spriteURL);
|
||||
bool loadedJSON = false;
|
||||
std::string json;
|
||||
|
||||
std::string body;
|
||||
bool loadedImage = false;
|
||||
std::string image;
|
||||
std::atomic<bool> loadedImage;
|
||||
std::atomic<bool> loadedJSON;
|
||||
std::unordered_map<std::string, SpritePosition> pos;
|
||||
const SpritePosition empty;
|
||||
|
||||
Request* jsonRequest = nullptr;
|
||||
Request* spriteRequest = nullptr;
|
||||
|
||||
@@ -265,8 +265,8 @@ std::unique_ptr<Bucket> TileWorker::createSymbolBucket(const GeometryTileLayer&
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bucket->addFeatures(
|
||||
reinterpret_cast<uintptr_t>(this), *style.spriteAtlas, *style.sprite, *style.glyphAtlas, *style.glyphStore);
|
||||
bucket->addFeatures(reinterpret_cast<uintptr_t>(this), *style.spriteAtlas, *style.glyphAtlas,
|
||||
*style.glyphStore);
|
||||
|
||||
return bucket->hasData() ? std::move(bucket) : nullptr;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <mbgl/renderer/symbol_bucket.hpp>
|
||||
#include <mbgl/map/geometry_tile.hpp>
|
||||
#include <mbgl/style/style_layout.hpp>
|
||||
#include <mbgl/annotation/sprite_image.hpp>
|
||||
#include <mbgl/geometry/text_buffer.hpp>
|
||||
#include <mbgl/geometry/icon_buffer.hpp>
|
||||
#include <mbgl/geometry/glyph_atlas.hpp>
|
||||
@@ -172,7 +173,6 @@ bool SymbolBucket::needsDependencies(const GeometryTileLayer& layer,
|
||||
|
||||
void SymbolBucket::addFeatures(uintptr_t tileUID,
|
||||
SpriteAtlas& spriteAtlas,
|
||||
Sprite& sprite,
|
||||
GlyphAtlas& glyphAtlas,
|
||||
GlyphStore& glyphStore) {
|
||||
float horizontalAlign = 0.5;
|
||||
@@ -246,11 +246,13 @@ void SymbolBucket::addFeatures(uintptr_t tileUID,
|
||||
|
||||
// if feature has icon, get sprite atlas position
|
||||
if (feature.sprite.length()) {
|
||||
Rect<uint16_t> image = spriteAtlas.getImage(feature.sprite, false);
|
||||
shapedIcon = shapeIcon(image, layout);
|
||||
|
||||
if (sprite.getSpritePosition(feature.sprite).sdf) {
|
||||
sdfIcons = true;
|
||||
auto image = spriteAtlas.getImage(feature.sprite, false);
|
||||
if (image.pos.hasArea() && image.texture) {
|
||||
shapedIcon = shapeIcon(image.pos, layout);
|
||||
assert(image.texture);
|
||||
if (image.texture->sdf) {
|
||||
sdfIcons = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -76,7 +76,6 @@ public:
|
||||
|
||||
void addFeatures(uintptr_t tileUID,
|
||||
SpriteAtlas&,
|
||||
Sprite&,
|
||||
GlyphAtlas&,
|
||||
GlyphStore&);
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
#include <mbgl/map/map_data.hpp>
|
||||
#include <mbgl/map/source.hpp>
|
||||
#include <mbgl/map/transform_state.hpp>
|
||||
#include <mbgl/annotation/sprite_store.hpp>
|
||||
#include <mbgl/annotation/sprite_parser.hpp>
|
||||
#include <mbgl/style/style_layer.hpp>
|
||||
#include <mbgl/style/style_parser.hpp>
|
||||
#include <mbgl/style/style_bucket.hpp>
|
||||
@@ -20,17 +22,19 @@
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
Style::Style(const std::string& data, const std::string&,
|
||||
Style::Style(const std::string& json, const std::string&, MapData& data_,
|
||||
uv_loop_t* loop)
|
||||
: glyphStore(std::make_unique<GlyphStore>(loop)),
|
||||
: data(data_),
|
||||
glyphStore(std::make_unique<GlyphStore>(loop)),
|
||||
glyphAtlas(std::make_unique<GlyphAtlas>(1024, 1024)),
|
||||
spriteStore(std::make_unique<SpriteStore>(data.pixelRatio)),
|
||||
spriteAtlas(std::make_unique<SpriteAtlas>(512, 512, *spriteStore)),
|
||||
lineAtlas(std::make_unique<LineAtlas>(512, 512)),
|
||||
mtx(std::make_unique<uv::rwlock>()),
|
||||
workers(4) {
|
||||
|
||||
rapidjson::Document doc;
|
||||
doc.Parse<0>((const char *const)data.c_str());
|
||||
doc.Parse<0>((const char *const)json.c_str());
|
||||
if (doc.HasParseError()) {
|
||||
Log::Error(Event::ParseStyle, "Error parsing style JSON at %i: %s", doc.GetErrorOffset(), doc.GetParseError());
|
||||
return;
|
||||
@@ -42,7 +46,9 @@ Style::Style(const std::string& data, const std::string&,
|
||||
sources = parser.getSources();
|
||||
layers = parser.getLayers();
|
||||
|
||||
spriteURL = parser.getSprite();
|
||||
sprite = std::make_unique<Sprite>(parser.getSprite(), data.pixelRatio);
|
||||
sprite->setObserver(this);
|
||||
|
||||
glyphStore->setURL(parser.getGlyphURL());
|
||||
|
||||
for (const auto& source : sources) {
|
||||
@@ -65,17 +71,8 @@ Style::~Style() {
|
||||
}
|
||||
}
|
||||
|
||||
void Style::update(MapData& data,
|
||||
const TransformState& transform,
|
||||
void Style::update(const TransformState& transform,
|
||||
TexturePool& texturePool) {
|
||||
if (!sprite || !sprite->hasPixelRatio(data.pixelRatio)) {
|
||||
sprite = std::make_unique<Sprite>(spriteURL, data.pixelRatio);
|
||||
sprite->setObserver(this);
|
||||
|
||||
spriteAtlas->resize(data.pixelRatio);
|
||||
spriteAtlas->setSprite(sprite);
|
||||
}
|
||||
|
||||
bool allTilesUpdated = true;
|
||||
for (const auto& source : sources) {
|
||||
if (!source->update(data, transform, *this, texturePool, shouldReparsePartialTiles)) {
|
||||
@@ -195,6 +192,9 @@ void Style::onTileLoadingFailed(std::exception_ptr error) {
|
||||
}
|
||||
|
||||
void Style::onSpriteLoaded() {
|
||||
// Add all sprite images to the SpriteStore object
|
||||
spriteStore->setSprites(parseSprite(sprite->getImage(), sprite->getJSON()));
|
||||
|
||||
shouldReparsePartialTiles = true;
|
||||
|
||||
emitTileDataChanged();
|
||||
|
||||
@@ -22,6 +22,7 @@ namespace mbgl {
|
||||
|
||||
class GlyphAtlas;
|
||||
class GlyphStore;
|
||||
class SpriteStore;
|
||||
class SpriteAtlas;
|
||||
class LineAtlas;
|
||||
class StyleLayer;
|
||||
@@ -33,6 +34,7 @@ class Style : public GlyphStore::Observer,
|
||||
public:
|
||||
Style(const std::string& data,
|
||||
const std::string& base,
|
||||
MapData&,
|
||||
uv_loop_t*);
|
||||
~Style();
|
||||
|
||||
@@ -50,7 +52,7 @@ public:
|
||||
|
||||
// Fetch the tiles needed by the current viewport and emit a signal when
|
||||
// a tile is ready so observers can render the tile.
|
||||
void update(MapData&, const TransformState&, TexturePool&);
|
||||
void update(const TransformState&, TexturePool&);
|
||||
|
||||
void cascade(const std::vector<std::string>&);
|
||||
void recalculate(float z, TimePoint now);
|
||||
@@ -64,9 +66,11 @@ public:
|
||||
|
||||
Source* getSource(const std::string& id) const;
|
||||
|
||||
MapData& data;
|
||||
std::unique_ptr<GlyphStore> glyphStore;
|
||||
std::unique_ptr<GlyphAtlas> glyphAtlas;
|
||||
util::ptr<Sprite> sprite;
|
||||
std::unique_ptr<SpriteStore> spriteStore;
|
||||
std::unique_ptr<SpriteAtlas> spriteAtlas;
|
||||
std::unique_ptr<LineAtlas> lineAtlas;
|
||||
|
||||
@@ -97,7 +101,6 @@ private:
|
||||
|
||||
std::exception_ptr lastError;
|
||||
|
||||
std::string spriteURL;
|
||||
PropertyTransition defaultTransition;
|
||||
std::unique_ptr<uv::rwlock> mtx;
|
||||
ZoomHistory zoomHistory;
|
||||
|
||||
@@ -32,7 +32,7 @@ public:
|
||||
transform_.setLatLngZoom({0, 0}, 16);
|
||||
|
||||
const std::string style = util::read_file("test/fixtures/resources/style.json");
|
||||
style_ = std::make_unique<Style>(style, "", util::RunLoop::getLoop());
|
||||
style_ = std::make_unique<Style>(style, "", data_, util::RunLoop::getLoop());
|
||||
style_->setObserver(this);
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ public:
|
||||
data_.setAnimationTime(now);
|
||||
transform_.updateTransitions(now);
|
||||
|
||||
style_->update(data_, transform_.getState(), texturePool_);
|
||||
style_->update(transform_.getState(), texturePool_);
|
||||
}
|
||||
|
||||
// Style::Observer implementation.
|
||||
|
||||
Reference in New Issue
Block a user