From bd1f71cdbd4aa55ffa1beb61ddee1dd6da32412d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20K=C3=A4fer?= Date: Thu, 7 Jan 2016 16:21:45 +0100 Subject: [PATCH] [core] use stale sprite data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- src/mbgl/sprite/sprite_store.cpp | 34 +++++++++--------- test/fixtures/stale/sprite.json | 10 ++++++ test/fixtures/stale/sprite.png | Bin 0 -> 3351 bytes .../stale/stale_style_and_sprite/expected.png | Bin 0 -> 26859 bytes test/fixtures/stale/style_and_sprite.json | 26 ++++++++++++++ test/storage/cache_stale.cpp | 28 +++++++++++++++ 6 files changed, 82 insertions(+), 16 deletions(-) create mode 100644 test/fixtures/stale/sprite.json create mode 100644 test/fixtures/stale/sprite.png create mode 100644 test/fixtures/stale/stale_style_and_sprite/expected.png create mode 100644 test/fixtures/stale/style_and_sprite.json diff --git a/src/mbgl/sprite/sprite_store.cpp b/src/mbgl/sprite/sprite_store.cpp index 0c3a7d3ba..8f99ea762 100644 --- a/src/mbgl/sprite/sprite_store.cpp +++ b/src/mbgl/sprite/sprite_store.cpp @@ -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()) { loaded = true; setSprites(result.get()); diff --git a/test/fixtures/stale/sprite.json b/test/fixtures/stale/sprite.json new file mode 100644 index 000000000..e64036551 --- /dev/null +++ b/test/fixtures/stale/sprite.json @@ -0,0 +1,10 @@ +{ + "noise": { + "x": 0, + "y": 0, + "width": 32, + "height": 32, + "pixelRatio": 1, + "sdf": false + } +} diff --git a/test/fixtures/stale/sprite.png b/test/fixtures/stale/sprite.png new file mode 100644 index 0000000000000000000000000000000000000000..a02d8eb5428e27d4af28de19535e7c04f3f3101e GIT binary patch literal 3351 zcmZ{nc|6qH8^;INPT6-grjmpi#5H5hjO_bPVlXt88O;pFzGPpr=2ldMe#llNsg!IZ zqshKx-<2pOMET9Ad#|70z2DdCe9!kh&*y!f^E~IAKfZ}(Cc2z#B5VKvfKy)&VL|PI zw8lbDeeVc;D5Q3Dcne)^K;>((CF+3HPtP6?0I>7Y8Xe$9o)7@QP=dCyBiI=m!Q8OE za!7ZqD@u;&>qk`s0BS@S_0tzcKmv)rJ{UZVs1Djwz^LCeGZ+NilMuYsL3YMwKsXkM z0xHR!k%NFV*nmKw8qVDVW`Q{O3#X3MK^F-GKNuJs7#JuQs3?cUd4lDkP$(Fp09H_t zr7C3cK^Ov(D2u@#`#H&<^B_=oHyqlJfW~5gw0V)PSbu^#2t*6?*Yj(gzJ7lN!r*^p zMa>UPMEZf{bDg7mViliR~5R=Ni?h6@?jN-O(OF2qXce zp#YIrmW9a6LVmZBSB634VNi$~_<-i`4EJa_4uvFOaaLHYkA@kVi1P8J4S|Z(x-0x- z_bc|nv^-#@I5dh{U|Jb9F=&DY zbwzt24ww&8_J8{|e*cr%Z#)Rt{S&a?xDTLh1Z=NTb_ldD3bU7sA~niCIu3$xtPd7v z>4$Vf(dxB_>@yuy?}f4dw=nx0zd$uG?JVy*+dnVPo|SrYG}x#+`sXdwU>mFNuA|;# z7JbB7D?LtY8?>3#F#pQVt2A=j@rcZ%4swx&~q*c z-pOWiTKe%em4f02`WLIB@*OshOX@y%!u!3(Xa;k0kC_D=%Nx+>P#pYxj*Rk)?(~at zrym&es%~)ms>b)A@$46h$hpJG#?F;K)7R*R1jeBrg6w>1j3bUV27?uy&zEbCT9#CO z>@eW*%zl(_AnF9Pt(tG*A7fmv6<^%g4C}ui6$894!FbsZt7O^j@ld8gV zQ(u=^7tKh9BDvbk^UolD%)a@y|g+Fl8q%>zM z#2NzWnwzikFQiTNp+5J-evJnxw8DqM@jcyrcF!3KavF+&o5teFdAr{ zGc?Kxzo?+T;sXis>s31C907U#oUvmgU|zzU^aA5OLz@uj`m5M+Ig?6P47CS5?7I> z8_Nr?Fk7EuddPmasb;t#*)EOI+p4v@he72D*jw>kw~|py+x)f5S`U9O+h!TGFP61s z6j<#{S8pS+3-h|G)bFtB4&2<;uVg51{ zBhHfw1(AfQ)=yV$n^Nxgt;tagEDCqEYdB0)g>pcyi}Ogq4q>`5(pz-}%z_xSIwI9q5&bv_&5~l=mBqKAtgr6xZ0UDrb&SZ8`Sy<%wM}%GwGn~$j%U<9| zI*KzfUayJYrh2h_9vt3U#PgUXg8)0td&T}4USeFe1LRhlp_J7>f6WP3+S^rkaig=( zaCbDc@m1V*imNAdVyxi7{pGSYcitz3d|$N#c=&CTiP)bcyJ3 z1V2RCoBT*1d&#WXV6Asa!xNr~bS$e=p6tbEh zFBp1!aQCn=_}oY31h_c0scxjQDh#*+afxu(>p2tnFzF^Ui3PpE;e`C~ zDcJ@#Gx(3TW^y5;W+;fefR09Xm_%9>x70UZEhoLPWxzdj> z_wUplvl-KV9(b?(>y|G3>u+QPB977Nzjd~Sh^~szQ~7fBO&_g-7B})wu+7tjPa+D7GTqsH}#krUHY2x zyVmdKCUnt=#3pnE=a~<~7Di?5xo|ilB1c?(O?=lZR2|Uei2aSc;3^l_=NxvuX*Ani zhKW*i>t)*Ap~GX!EN+DvB|>D~SJGa0Vs{0fq$Qq2n4fd1Ux*(Bn`h|Mo`?;_RIaU0 zJ}IQT0JYtE_u-W{$^DQ#?v5m)DLpi$7}P7R*@)`CQ5SIDKXtj@sW7+l`6Fo6`M$&! zaie0ka4sIMtay%0LYBxW#8#NTSC{w`xq!j*mx@T`FG$~)%&)#b+$i~3>egE|Xk5QS zuzE)awOykB3%|;==l}o! literal 0 HcmV?d00001 diff --git a/test/fixtures/stale/stale_style_and_sprite/expected.png b/test/fixtures/stale/stale_style_and_sprite/expected.png new file mode 100644 index 0000000000000000000000000000000000000000..171599bf5c0799842c5dd1cc24a7bda28b492563 GIT binary patch literal 26859 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 Y>TSZYT%}#Ww-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); +}