[core] use stale sprite data

This is a naïve implementation that essentially merges updated data into existing data. It will *not* remove icons from the stale sprite if they aren't present in the fresh sprite (we aren't tracking the source of a sprite, and the user could have changed it as well). Similarly, it will not update icons that have changed in dimension. This is a rare edge case and probably not worth implementing.
This commit is contained in:
Konstantin Käfer
2016-01-07 16:21:45 +01:00
parent 40e908677e
commit bd1f71cdbd
6 changed files with 82 additions and 16 deletions

View File

@@ -40,15 +40,17 @@ void SpriteStore::setURL(const std::string& url) {
FileSource* fs = util::ThreadContext::getFileSource();
loader->jsonRequest = fs->request({ Resource::Kind::SpriteJSON, jsonURL },
[this, jsonURL](Response res) {
if (res.stale) {
// Only handle fresh responses.
return;
}
loader->jsonRequest = nullptr;
if (res.error) {
observer->onSpriteError(std::make_exception_ptr(std::runtime_error(res.error->message)));
} else {
}
if (res.notModified) {
// We got the same data back as last time. Abort early.
return;
}
if (!loader->json || *loader->json != *res.data) {
// Only trigger a sprite loaded event we got new data.
loader->json = res.data;
emitSpriteLoadedIfComplete();
}
@@ -57,15 +59,16 @@ void SpriteStore::setURL(const std::string& url) {
loader->spriteRequest =
fs->request({ Resource::Kind::SpriteImage, spriteURL },
[this, spriteURL](Response res) {
if (res.stale) {
// Only handle fresh responses.
return;
}
loader->spriteRequest = nullptr;
if (res.error) {
observer->onSpriteError(std::make_exception_ptr(std::runtime_error(res.error->message)));
} else {
}
if (res.notModified) {
// We got the same data back as last time. Abort early.
return;
}
if (!loader->image || *loader->image != *res.data) {
loader->image = res.data;
emitSpriteLoadedIfComplete();
}
@@ -79,8 +82,7 @@ void SpriteStore::emitSpriteLoadedIfComplete() {
return;
}
auto local = std::move(loader);
auto result = parseSprite(*local->image, *local->json);
auto result = parseSprite(*loader->image, *loader->json);
if (result.is<Sprites>()) {
loaded = true;
setSprites(result.get<Sprites>());

10
test/fixtures/stale/sprite.json vendored Normal file
View File

@@ -0,0 +1,10 @@
{
"noise": {
"x": 0,
"y": 0,
"width": 32,
"height": 32,
"pixelRatio": 1,
"sdf": false
}
}

BIN
test/fixtures/stale/sprite.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@@ -0,0 +1,26 @@
{
"version": 8,
"name": "Water",
"sources": {
"mapbox": {
"type": "vector",
"url": "asset://test/fixtures/stale/streets.json"
}
},
"sprite": "http://127.0.0.1:3000/stale/sprite",
"layers": [{
"id": "background",
"type": "background",
"paint": {
"background-color": "red"
}
}, {
"id": "water",
"type": "fill",
"source": "mapbox",
"source-layer": "water",
"paint": {
"fill-pattern": "noise"
}
}]
}

View File

@@ -72,3 +72,31 @@ TEST_F(Storage, CacheStaleStyleAndTileJSON) {
checkRendering(map, "stale_style_and_tilejson", 1000ms);
}
TEST_F(Storage, CacheStaleStyleAndSprite) {
HeadlessView view(display, 1);
auto cache = SQLiteCache::getShared(":memory:");
// Rig the cache with an expired stylesheet.
const std::string stylePath = "stale/style_and_sprite.json";
const Resource styleResource{ Resource::Kind::Style, prefix + "/" + stylePath };
cache->put(styleResource, expiredItem(stylePath));
// Rig the cache with an expired sprite JSON.
const std::string spritejsonPath = "stale/sprite.json";
const Resource spritejsonResource{ Resource::Kind::SpriteJSON, prefix + "/" + spritejsonPath };
cache->put(spritejsonResource, expiredItem(spritejsonPath));
// Rig the cache with an expired sprite JSON.
const std::string spriteimagePath = "stale/sprite.png";
const Resource spriteimageResource{ Resource::Kind::SpriteImage, prefix + "/" + spriteimagePath };
cache->put(spriteimageResource, expiredItem(spriteimagePath));
DefaultFileSource fileSource(":memory:", ".");
Map map(view, fileSource, MapMode::Still);
map.setStyleURL(styleResource.url);
checkRendering(map, "stale_style_and_sprite", 1000ms);
}