From 849e8b32b4b2febc63ad3df8539b483ccc67ac63 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Fri, 22 Jan 2016 19:18:25 -0800 Subject: [PATCH 1/3] [core] Ensure that FileSource has access to tile URL, pixelRatio, x, y, z --- include/mbgl/storage/resource.hpp | 12 ++++++++++++ src/mbgl/map/raster_tile_data.cpp | 32 +++++++++++++++++++++---------- src/mbgl/map/raster_tile_data.hpp | 15 ++++++--------- src/mbgl/map/source.cpp | 11 ++++++----- src/mbgl/map/vector_tile.cpp | 22 +++++++++++++++++---- src/mbgl/map/vector_tile.hpp | 3 ++- 6 files changed, 66 insertions(+), 29 deletions(-) diff --git a/include/mbgl/storage/resource.hpp b/include/mbgl/storage/resource.hpp index 8a617021839..532feff14a0 100644 --- a/include/mbgl/storage/resource.hpp +++ b/include/mbgl/storage/resource.hpp @@ -31,6 +31,18 @@ class Resource { optional priorModified; optional priorExpires; optional priorEtag; + + // Includes auxiliary data if this is a tile request. + + struct TileData { + std::string urlTemplate; + float pixelRatio; + int32_t x; + int32_t y; + int8_t z; + }; + + optional tileData; }; } // namespace mbgl diff --git a/src/mbgl/map/raster_tile_data.cpp b/src/mbgl/map/raster_tile_data.cpp index 92ffb451b0b..fa0bd298b1b 100644 --- a/src/mbgl/map/raster_tile_data.cpp +++ b/src/mbgl/map/raster_tile_data.cpp @@ -5,27 +5,35 @@ #include #include #include +#include using namespace mbgl; RasterTileData::RasterTileData(const TileID& id_, + float pixelRatio, + const std::string& urlTemplate, TexturePool &texturePool_, - Worker& worker_) + Worker& worker_, + const std::function& callback) : TileData(id_), texturePool(texturePool_), worker(worker_) { -} + state = State::loading; -RasterTileData::~RasterTileData() { - cancel(); -} + Resource resource { + Resource::Kind::Tile, + util::templateTileURL(urlTemplate, id, pixelRatio) + }; -void RasterTileData::request(const std::string& url, - const RasterTileData::Callback& callback) { - state = State::loading; + resource.tileData = Resource::TileData { + urlTemplate, + pixelRatio, + id.x, + id.y, + id.z + }; - FileSource* fs = util::ThreadContext::getFileSource(); - req = fs->request({ Resource::Kind::Tile, url }, [url, callback, this](Response res) { + req = util::ThreadContext::getFileSource()->request(resource, [callback, this](Response res) { if (res.error) { std::exception_ptr error; if (res.error->reason == Response::Error::Reason::NotFound) { @@ -76,6 +84,10 @@ void RasterTileData::request(const std::string& url, }); } +RasterTileData::~RasterTileData() { + cancel(); +} + Bucket* RasterTileData::getBucket(StyleLayer const&) { return bucket.get(); } diff --git a/src/mbgl/map/raster_tile_data.hpp b/src/mbgl/map/raster_tile_data.hpp index e8efde48e44..e68fbc94c5e 100644 --- a/src/mbgl/map/raster_tile_data.hpp +++ b/src/mbgl/map/raster_tile_data.hpp @@ -13,25 +13,22 @@ class WorkRequest; class RasterTileData : public TileData { public: - RasterTileData(const TileID&, TexturePool&, Worker&); + RasterTileData(const TileID&, + float pixelRatio, + const std::string& urlTemplate, + TexturePool&, + Worker&, + const std::function& callback); ~RasterTileData(); - using Callback = std::function; - - void request(const std::string& url, - const Callback& callback); - void cancel() override; - Bucket* getBucket(StyleLayer const &layer_desc) override; private: TexturePool& texturePool; Worker& worker; std::unique_ptr req; - std::unique_ptr bucket; - std::unique_ptr workRequest; }; diff --git a/src/mbgl/map/source.cpp b/src/mbgl/map/source.cpp index 8a89fecb877..fbe276f3247 100644 --- a/src/mbgl/map/source.cpp +++ b/src/mbgl/map/source.cpp @@ -267,16 +267,17 @@ TileData::State Source::addTile(const TileID& tileID, const StyleUpdateParameter // If we don't find working tile data, we're just going to load it. if (type == SourceType::Raster) { - auto tileData = std::make_shared(normalizedID, + newTile->data = std::make_shared(normalizedID, + parameters.pixelRatio, + info->tiles.at(0), parameters.texturePool, - parameters.worker); - tileData->request(util::templateTileURL(info->tiles.at(0), normalizedID, parameters.pixelRatio), callback); - newTile->data = tileData; + parameters.worker, + callback); } else { std::unique_ptr monitor; if (type == SourceType::Vector) { - monitor = std::make_unique(normalizedID, info->tiles.at(0)); + monitor = std::make_unique(normalizedID, parameters.pixelRatio, info->tiles.at(0)); } else if (type == SourceType::Annotations) { monitor = std::make_unique(normalizedID, parameters.data); } else if (type == SourceType::GeoJSON) { diff --git a/src/mbgl/map/vector_tile.cpp b/src/mbgl/map/vector_tile.cpp index 8faaae395e2..cfe78d228dc 100644 --- a/src/mbgl/map/vector_tile.cpp +++ b/src/mbgl/map/vector_tile.cpp @@ -178,13 +178,27 @@ util::ptr VectorTileLayer::getFeature(std::size_t i) return std::make_shared(features.at(i), *this); } -VectorTileMonitor::VectorTileMonitor(const TileID& tileID_, const std::string& urlTemplate_) - : tileID(tileID_), urlTemplate(urlTemplate_) { +VectorTileMonitor::VectorTileMonitor(const TileID& tileID_, float pixelRatio_, const std::string& urlTemplate_) + : tileID(tileID_), + pixelRatio(pixelRatio_), + urlTemplate(urlTemplate_) { } std::unique_ptr VectorTileMonitor::monitorTile(const GeometryTileMonitor::Callback& callback) { - const std::string url = util::templateTileURL(urlTemplate, tileID); - return util::ThreadContext::getFileSource()->request({ Resource::Kind::Tile, url }, [callback, this](Response res) { + Resource resource { + Resource::Kind::Tile, + util::templateTileURL(urlTemplate, tileID, pixelRatio) + }; + + resource.tileData = Resource::TileData { + urlTemplate, + pixelRatio, + tileID.x, + tileID.y, + tileID.z + }; + + return util::ThreadContext::getFileSource()->request(resource, [callback, this](Response res) { if (res.notModified) { // We got the same data again. Abort early. return; diff --git a/src/mbgl/map/vector_tile.hpp b/src/mbgl/map/vector_tile.hpp index 1557db784f6..a53c0bc44fa 100644 --- a/src/mbgl/map/vector_tile.hpp +++ b/src/mbgl/map/vector_tile.hpp @@ -61,12 +61,13 @@ class TileID; class VectorTileMonitor : public GeometryTileMonitor { public: - VectorTileMonitor(const TileID&, const std::string& urlTemplate); + VectorTileMonitor(const TileID&, float pixelRatio, const std::string& urlTemplate); std::unique_ptr monitorTile(const GeometryTileMonitor::Callback&) override; private: TileID tileID; + float pixelRatio; std::string urlTemplate; }; From b41a73e1c1dfea982df4a0326d45a48babc22dd4 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Thu, 28 Jan 2016 16:29:54 -0800 Subject: [PATCH 2/3] [core] Rationalize Resource initialization --- include/mbgl/storage/resource.hpp | 41 ++++++++++------ src/mbgl/map/map_context.cpp | 2 +- src/mbgl/map/raster_tile_data.cpp | 15 +----- src/mbgl/map/source.cpp | 2 +- src/mbgl/map/vector_tile.cpp | 14 +----- src/mbgl/sprite/sprite_store.cpp | 36 ++++++-------- src/mbgl/storage/resource.cpp | 82 +++++++++++++++++++++++++++++++ src/mbgl/text/glyph_pbf.cpp | 9 +--- src/mbgl/util/url.cpp | 24 --------- src/mbgl/util/url.hpp | 4 -- test/storage/resource.cpp | 50 +++++++++++++++++++ test/test.gypi | 1 + 12 files changed, 180 insertions(+), 100 deletions(-) create mode 100644 src/mbgl/storage/resource.cpp create mode 100644 test/storage/resource.cpp diff --git a/include/mbgl/storage/resource.hpp b/include/mbgl/storage/resource.hpp index 532feff14a0..d684e16d1be 100644 --- a/include/mbgl/storage/resource.hpp +++ b/include/mbgl/storage/resource.hpp @@ -20,20 +20,6 @@ class Resource { SpriteJSON }; - Resource(Kind kind_, const std::string& url_) - : kind(kind_), - url(url_) { - } - - const Kind kind; - const std::string url; - - optional priorModified; - optional priorExpires; - optional priorEtag; - - // Includes auxiliary data if this is a tile request. - struct TileData { std::string urlTemplate; float pixelRatio; @@ -42,7 +28,34 @@ class Resource { int8_t z; }; + Resource(Kind kind_, const std::string& url_, optional tileData_ = {}) + : kind(kind_), + url(url_), + tileData(tileData_) { + } + + static Resource style(const std::string& url); + static Resource source(const std::string& url); + static Resource tile(const std::string& urlTemplate, + float pixelRatio, + int32_t x, + int32_t y, + int8_t z); + static Resource glyphs(const std::string& urlTemplate, + const std::string& fontStack, + const std::pair& glyphRange); + static Resource spriteImage(const std::string& base, float pixelRatio); + static Resource spriteJSON(const std::string& base, float pixelRatio); + + const Kind kind; + const std::string url; + + // Includes auxiliary data if this is a tile request. optional tileData; + + optional priorModified = {}; + optional priorExpires = {}; + optional priorEtag = {}; }; } // namespace mbgl diff --git a/src/mbgl/map/map_context.cpp b/src/mbgl/map/map_context.cpp index 821741e87e4..dcb4bd0a9e4 100644 --- a/src/mbgl/map/map_context.cpp +++ b/src/mbgl/map/map_context.cpp @@ -104,7 +104,7 @@ void MapContext::setStyleURL(const std::string& url) { } FileSource* fs = util::ThreadContext::getFileSource(); - styleRequest = fs->request({ Resource::Kind::Style, styleURL }, [this, base](Response res) { + styleRequest = fs->request(Resource::style(styleURL), [this, base](Response res) { if (res.error) { if (res.error->reason == Response::Error::Reason::NotFound && util::mapbox::isMapboxURL(styleURL)) { diff --git a/src/mbgl/map/raster_tile_data.cpp b/src/mbgl/map/raster_tile_data.cpp index fa0bd298b1b..f9f5480197c 100644 --- a/src/mbgl/map/raster_tile_data.cpp +++ b/src/mbgl/map/raster_tile_data.cpp @@ -5,7 +5,6 @@ #include #include #include -#include using namespace mbgl; @@ -20,19 +19,7 @@ RasterTileData::RasterTileData(const TileID& id_, worker(worker_) { state = State::loading; - Resource resource { - Resource::Kind::Tile, - util::templateTileURL(urlTemplate, id, pixelRatio) - }; - - resource.tileData = Resource::TileData { - urlTemplate, - pixelRatio, - id.x, - id.y, - id.z - }; - + const Resource resource = Resource::tile(urlTemplate, pixelRatio, id.x, id.y, id.sourceZ); req = util::ThreadContext::getFileSource()->request(resource, [callback, this](Response res) { if (res.error) { std::exception_ptr error; diff --git a/src/mbgl/map/source.cpp b/src/mbgl/map/source.cpp index fbe276f3247..65b9de7abb5 100644 --- a/src/mbgl/map/source.cpp +++ b/src/mbgl/map/source.cpp @@ -91,7 +91,7 @@ void Source::load() { // URL may either be a TileJSON file, or a GeoJSON file. FileSource* fs = util::ThreadContext::getFileSource(); - req = fs->request({ Resource::Kind::Source, url }, [this](Response res) { + req = fs->request(Resource::source(url), [this](Response res) { if (res.error) { observer->onSourceError(*this, std::make_exception_ptr(std::runtime_error(res.error->message))); return; diff --git a/src/mbgl/map/vector_tile.cpp b/src/mbgl/map/vector_tile.cpp index cfe78d228dc..f837714b8d9 100644 --- a/src/mbgl/map/vector_tile.cpp +++ b/src/mbgl/map/vector_tile.cpp @@ -185,19 +185,7 @@ VectorTileMonitor::VectorTileMonitor(const TileID& tileID_, float pixelRatio_, c } std::unique_ptr VectorTileMonitor::monitorTile(const GeometryTileMonitor::Callback& callback) { - Resource resource { - Resource::Kind::Tile, - util::templateTileURL(urlTemplate, tileID, pixelRatio) - }; - - resource.tileData = Resource::TileData { - urlTemplate, - pixelRatio, - tileID.x, - tileID.y, - tileID.z - }; - + const Resource resource = Resource::tile(urlTemplate, pixelRatio, tileID.x, tileID.y, tileID.sourceZ); return util::ThreadContext::getFileSource()->request(resource, [callback, this](Response res) { if (res.notModified) { // We got the same data again. Abort early. diff --git a/src/mbgl/sprite/sprite_store.cpp b/src/mbgl/sprite/sprite_store.cpp index e051b969a1a..15a345cc4d6 100644 --- a/src/mbgl/sprite/sprite_store.cpp +++ b/src/mbgl/sprite/sprite_store.cpp @@ -32,14 +32,10 @@ void SpriteStore::setURL(const std::string& url) { return; } - std::string spriteURL(url + (pixelRatio > 1 ? "@2x" : "") + ".png"); - std::string jsonURL(url + (pixelRatio > 1 ? "@2x" : "") + ".json"); - loader = std::make_unique(); FileSource* fs = util::ThreadContext::getFileSource(); - loader->jsonRequest = fs->request({ Resource::Kind::SpriteJSON, jsonURL }, - [this, jsonURL](Response res) { + loader->jsonRequest = fs->request(Resource::spriteJSON(url, pixelRatio), [this](Response res) { if (res.error) { observer->onSpriteError(std::make_exception_ptr(std::runtime_error(res.error->message))); return; @@ -57,24 +53,22 @@ void SpriteStore::setURL(const std::string& url) { } }); - loader->spriteRequest = - fs->request({ Resource::Kind::SpriteImage, spriteURL }, - [this, spriteURL](Response res) { - if (res.error) { - observer->onSpriteError(std::make_exception_ptr(std::runtime_error(res.error->message))); - return; - } + loader->spriteRequest = fs->request(Resource::spriteImage(url, pixelRatio), [this](Response res) { + if (res.error) { + observer->onSpriteError(std::make_exception_ptr(std::runtime_error(res.error->message))); + return; + } - if (res.notModified) { - // We got the same data back as last time. Abort early. - return; - } + 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(); - } - }); + if (!loader->image || *loader->image != *res.data) { + loader->image = res.data; + emitSpriteLoadedIfComplete(); + } + }); } void SpriteStore::emitSpriteLoadedIfComplete() { diff --git a/src/mbgl/storage/resource.cpp b/src/mbgl/storage/resource.cpp new file mode 100644 index 00000000000..9cdedb59eb9 --- /dev/null +++ b/src/mbgl/storage/resource.cpp @@ -0,0 +1,82 @@ +#include +#include +#include +#include + +namespace mbgl { + +Resource Resource::style(const std::string& url) { + return Resource { + Resource::Kind::Style, + url + }; +} + +Resource Resource::source(const std::string& url) { + return Resource { + Resource::Kind::Source, + url + }; +} + +Resource Resource::spriteImage(const std::string& base, float pixelRatio) { + return Resource { + Resource::Kind::SpriteImage, + base + (pixelRatio > 1 ? "@2x" : "") + ".png" + }; +} + +Resource Resource::spriteJSON(const std::string& base, float pixelRatio) { + return Resource { + Resource::Kind::SpriteJSON, + base + (pixelRatio > 1 ? "@2x" : "") + ".json" + }; +} + +Resource Resource::glyphs(const std::string& urlTemplate, const std::string& fontStack, const std::pair& glyphRange) { + return Resource { + Resource::Kind::Glyphs, + util::replaceTokens(urlTemplate, [&](const std::string& token) { + if (token == "fontstack") { + return util::percentEncode(fontStack); + } else if (token == "range") { + return util::toString(glyphRange.first) + "-" + util::toString(glyphRange.second); + } else { + return std::string(); + } + }) + }; +} + +Resource Resource::tile(const std::string& urlTemplate, float pixelRatio, int32_t x, int32_t y, int8_t z) { + return Resource { + Resource::Kind::Tile, + util::replaceTokens(urlTemplate, [&](const std::string& token) { + if (token == "z") { + return util::toString(z); + } else if (token == "x") { + return util::toString(x); + } else if (token == "y") { + return util::toString(y); + } else if (token == "prefix") { + std::string prefix{ 2 }; + prefix[0] = "0123456789abcdef"[x % 16]; + prefix[1] = "0123456789abcdef"[y % 16]; + return prefix; + } else if (token == "ratio") { + return std::string(pixelRatio > 1.0 ? "@2x" : ""); + } else { + return std::string(); + } + }), + Resource::TileData { + urlTemplate, + pixelRatio, + x, + y, + z + } + }; +} + +} diff --git a/src/mbgl/text/glyph_pbf.cpp b/src/mbgl/text/glyph_pbf.cpp index 37b7cfc9fb9..0dfed6b4307 100644 --- a/src/mbgl/text/glyph_pbf.cpp +++ b/src/mbgl/text/glyph_pbf.cpp @@ -67,15 +67,8 @@ GlyphPBF::GlyphPBF(GlyphStore* store, GlyphStore::Observer* observer_) : parsed(false), observer(observer_) { - // Load the glyph set URL - std::string url = util::replaceTokens(store->getURL(), [&](const std::string &name) -> std::string { - if (name == "fontstack") return util::percentEncode(fontStack); - if (name == "range") return util::toString(glyphRange.first) + "-" + util::toString(glyphRange.second); - return ""; - }); - FileSource* fs = util::ThreadContext::getFileSource(); - req = fs->request({ Resource::Kind::Glyphs, url }, [this, store, fontStack, glyphRange](Response res) { + req = fs->request(Resource::glyphs(store->getURL(), fontStack, glyphRange), [this, store, fontStack, glyphRange](Response res) { if (res.error) { observer->onGlyphsError(fontStack, glyphRange, std::make_exception_ptr(std::runtime_error(res.error->message))); return; diff --git a/src/mbgl/util/url.cpp b/src/mbgl/util/url.cpp index 85d8bc5bd06..bf6fc70ff58 100644 --- a/src/mbgl/util/url.cpp +++ b/src/mbgl/util/url.cpp @@ -1,7 +1,4 @@ #include -#include -#include -#include #include #include @@ -50,26 +47,5 @@ std::string percentDecode(const std::string& input) { return decoded; } -std::string templateTileURL(const std::string& url, const TileID& id, float pixelRatio) { - return util::replaceTokens(url, [&](const std::string& token) -> std::string { - if (token == "z") { - return util::toString(id.sourceZ); - } else if (token == "x") { - return util::toString(id.x); - } else if (token == "y") { - return util::toString(id.y); - } else if (token == "prefix") { - std::string prefix{ 2 }; - prefix[0] = "0123456789abcdef"[id.x % 16]; - prefix[1] = "0123456789abcdef"[id.y % 16]; - return prefix; - } else if (token == "ratio") { - return pixelRatio > 1.0 ? "@2x" : ""; - } else { - return ""; - } - }); -} - } // namespace util } // namespace mbgl diff --git a/src/mbgl/util/url.hpp b/src/mbgl/util/url.hpp index 550fff8aa13..8baa94be1dd 100644 --- a/src/mbgl/util/url.hpp +++ b/src/mbgl/util/url.hpp @@ -5,15 +5,11 @@ namespace mbgl { -class TileID; - namespace util { std::string percentEncode(const std::string&); std::string percentDecode(const std::string&); -std::string templateTileURL(const std::string& url, const TileID& id, float pixelRatio = 1); - } // namespace util } // namespace mbgl diff --git a/test/storage/resource.cpp b/test/storage/resource.cpp new file mode 100644 index 00000000000..30c1597df2c --- /dev/null +++ b/test/storage/resource.cpp @@ -0,0 +1,50 @@ +#include + +#include + +TEST(Resource, Style) { + using namespace mbgl; + Resource resource = Resource::style("http://example.com"); + EXPECT_EQ(Resource::Kind::Style, resource.kind); + EXPECT_EQ("http://example.com", resource.url); +} + +TEST(Resource, Source) { + using namespace mbgl; + Resource resource = Resource::source("http://example.com"); + EXPECT_EQ(Resource::Kind::Source, resource.kind); + EXPECT_EQ("http://example.com", resource.url); +} + +TEST(Resource, Tile) { + using namespace mbgl; + Resource resource = Resource::tile("http://example.com/{z}/{x}/{y}{ratio}.png", 2.0, 1, 2, 3); + EXPECT_EQ(Resource::Kind::Tile, resource.kind); + EXPECT_EQ("http://example.com/3/1/2@2x.png", resource.url); + EXPECT_EQ("http://example.com/{z}/{x}/{y}{ratio}.png", resource.tileData->urlTemplate); + EXPECT_EQ(2.0, resource.tileData->pixelRatio); + EXPECT_EQ(1, resource.tileData->x); + EXPECT_EQ(2, resource.tileData->y); + EXPECT_EQ(3, resource.tileData->z); +} + +TEST(Resource, Glyphs) { + using namespace mbgl; + Resource resource = Resource::glyphs("http://example.com/{fontstack}/{range}", "stack", {0, 255}); + EXPECT_EQ(Resource::Kind::Glyphs, resource.kind); + EXPECT_EQ("http://example.com/stack/0-255", resource.url); +} + +TEST(Resource, SpriteImage) { + using namespace mbgl; + Resource resource = Resource::spriteImage("http://example.com/sprite", 2.0); + EXPECT_EQ(Resource::Kind::SpriteImage, resource.kind); + EXPECT_EQ("http://example.com/sprite@2x.png", resource.url); +} + +TEST(Resource, SpriteJSON) { + using namespace mbgl; + Resource resource = Resource::spriteJSON("http://example.com/sprite", 2.0); + EXPECT_EQ(Resource::Kind::SpriteJSON, resource.kind); + EXPECT_EQ("http://example.com/sprite@2x.json", resource.url); +} diff --git a/test/test.gypi b/test/test.gypi index e0d09517590..628ae3eb3e7 100644 --- a/test/test.gypi +++ b/test/test.gypi @@ -87,6 +87,7 @@ 'storage/http_retry_network_status.cpp', 'storage/http_reading.cpp', 'storage/http_timeout.cpp', + 'storage/resource.cpp', 'style/glyph_store.cpp', 'style/pending_resources.cpp', From 2920020fb87b7bc497a898544d51cfa390b520dd Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Fri, 29 Jan 2016 17:16:06 -0800 Subject: [PATCH 3/3] [core] Change TileData pixelRatio to an integer --- include/mbgl/storage/resource.hpp | 2 +- src/mbgl/storage/resource.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/mbgl/storage/resource.hpp b/include/mbgl/storage/resource.hpp index d684e16d1be..c97384e6a7b 100644 --- a/include/mbgl/storage/resource.hpp +++ b/include/mbgl/storage/resource.hpp @@ -22,7 +22,7 @@ class Resource { struct TileData { std::string urlTemplate; - float pixelRatio; + uint8_t pixelRatio; int32_t x; int32_t y; int8_t z; diff --git a/src/mbgl/storage/resource.cpp b/src/mbgl/storage/resource.cpp index 9cdedb59eb9..6f727a60278 100644 --- a/src/mbgl/storage/resource.cpp +++ b/src/mbgl/storage/resource.cpp @@ -71,7 +71,7 @@ Resource Resource::tile(const std::string& urlTemplate, float pixelRatio, int32_ }), Resource::TileData { urlTemplate, - pixelRatio, + uint8_t(pixelRatio > 1.0 ? 2 : 1), x, y, z