diff --git a/include/mbgl/storage/resource.hpp b/include/mbgl/storage/resource.hpp index 31df0699529..c05f40b65c4 100644 --- a/include/mbgl/storage/resource.hpp +++ b/include/mbgl/storage/resource.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include @@ -47,6 +48,7 @@ class Resource { int32_t x, int32_t y, int8_t z, + Tileset::Scheme scheme, Necessity = Required); static Resource glyphs(const std::string& urlTemplate, const FontStack& fontStack, diff --git a/include/mbgl/style/conversion/tileset.hpp b/include/mbgl/style/conversion/tileset.hpp index 46425597afb..1955cc16cf2 100644 --- a/include/mbgl/style/conversion/tileset.hpp +++ b/include/mbgl/style/conversion/tileset.hpp @@ -31,6 +31,14 @@ struct Converter { result.tiles.push_back(std::move(*urlTemplate)); } + auto schemeValue = objectMember(value, "scheme"); + if (schemeValue) { + optional scheme = toString(*schemeValue); + if (scheme && *scheme == "tms") { + result.scheme = Tileset::Scheme::TMS; + } + } + auto minzoomValue = objectMember(value, "minzoom"); if (minzoomValue) { optional minzoom = toNumber(*minzoomValue); diff --git a/include/mbgl/util/tileset.hpp b/include/mbgl/util/tileset.hpp index 8a7fbe9b73d..1f28a5039a6 100644 --- a/include/mbgl/util/tileset.hpp +++ b/include/mbgl/util/tileset.hpp @@ -10,9 +10,12 @@ namespace mbgl { class Tileset { public: + enum class Scheme : bool { XYZ, TMS }; + std::vector tiles; Range zoomRange { 0, 22 }; std::string attribution; + Scheme scheme = Scheme::XYZ; // TileJSON also includes center, zoom, and bounds, but they are not used by mbgl. }; diff --git a/package.json b/package.json index cd06121f3de..d7e07288f8c 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "express": "^4.11.1", "mapbox-gl-shaders": "mapbox/mapbox-gl-shaders#de2ab007455aa2587c552694c68583f94c9f2747", "mapbox-gl-style-spec": "mapbox/mapbox-gl-style-spec#83b1a3e5837d785af582efd5ed1a212f2df6a4ae", - "mapbox-gl-test-suite": "mapbox/mapbox-gl-test-suite#1619d84e76ff3434becd51237720d370c7405ee5", + "mapbox-gl-test-suite": "mapbox/mapbox-gl-test-suite#7babab52fb02788ebbc38384139bf350e8e38552", "node-cmake": "^1.2.1", "request": "^2.72.0", "tape": "^4.5.1" diff --git a/platform/default/mbgl/storage/offline_download.cpp b/platform/default/mbgl/storage/offline_download.cpp index dd66abf9825..87534f222f5 100644 --- a/platform/default/mbgl/storage/offline_download.cpp +++ b/platform/default/mbgl/storage/offline_download.cpp @@ -81,7 +81,7 @@ OfflineDownload::tileResources(SourceType type, uint16_t tileSize, const Tileset for (const auto& tile : definition.tileCover(type, tileSize, tileset.zoomRange)) { result.push_back( - Resource::tile(tileset.tiles[0], definition.pixelRatio, tile.x, tile.y, tile.z)); + Resource::tile(tileset.tiles[0], definition.pixelRatio, tile.x, tile.y, tile.z, tileset.scheme)); } return result; diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index adb59898bdb..e4f8653a406 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -23,6 +23,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT * Fixed crashes that could occur when loading a malformed stylesheet. ([#5736](https://github.com/mapbox/mapbox-gl-native/pull/5736)) * Fixed a crash that sometimes occurred when initializing an MGLMapView. ([#5932](https://github.com/mapbox/mapbox-gl-native/pull/5932)) * MGLMapDebugOverdrawVisualizationMask no longer has any effect in Release builds of the SDK. This debug mask has been disabled for performance reasons. ([#5555](https://github.com/mapbox/mapbox-gl-native/pull/5555)) +* Added support for `"scheme": "tms"` in TileJSON descriptions. ([#2270](https://github.com/mapbox/mapbox-gl-native/pull/2270)) ## 3.3.4 - August 8, 2016 diff --git a/platform/macos/CHANGELOG.md b/platform/macos/CHANGELOG.md index 05227a41340..604c2135814 100644 --- a/platform/macos/CHANGELOG.md +++ b/platform/macos/CHANGELOG.md @@ -11,6 +11,7 @@ * Improved the precision of annotations at zoom levels greater than 18. ([#5517](https://github.com/mapbox/mapbox-gl-native/pull/5517)) * Fixed an issue where the style zoom levels were not respected when deciding when to render a layer. ([#5811](https://github.com/mapbox/mapbox-gl-native/issues/5811)) * Fixed crashes that could occur when loading a malformed stylesheet. ([#5736](https://github.com/mapbox/mapbox-gl-native/pull/5736)) +* Added support for `"scheme": "tms"` in TileJSON descriptions. ([#2270](https://github.com/mapbox/mapbox-gl-native/pull/2270)) ## 0.2.1 - July 19, 2016 diff --git a/src/mbgl/storage/resource.cpp b/src/mbgl/storage/resource.cpp index bb587dcc33c..20dde1db56f 100644 --- a/src/mbgl/storage/resource.cpp +++ b/src/mbgl/storage/resource.cpp @@ -87,8 +87,12 @@ Resource Resource::tile(const std::string& urlTemplate, int32_t x, int32_t y, int8_t z, + Tileset::Scheme scheme, Necessity necessity) { bool supportsRatio = urlTemplate.find("{ratio}") != std::string::npos; + if (scheme == Tileset::Scheme::TMS) { + y = (1 << z) - y - 1; + } return Resource { Resource::Kind::Tile, util::replaceTokens(urlTemplate, [&](const std::string& token) { diff --git a/src/mbgl/tile/tile_loader_impl.hpp b/src/mbgl/tile/tile_loader_impl.hpp index b987d6ec65c..9a5b35a7af4 100644 --- a/src/mbgl/tile/tile_loader_impl.hpp +++ b/src/mbgl/tile/tile_loader_impl.hpp @@ -21,7 +21,8 @@ TileLoader::TileLoader(T& tile_, parameters.pixelRatio, id.canonical.x, id.canonical.y, - id.canonical.z)), + id.canonical.z, + tileset.scheme)), fileSource(parameters.fileSource) { assert(!request); if (fileSource.supportsOptionalRequests()) { diff --git a/test/map/map.cpp b/test/map/map.cpp index b304712e1fa..d60c7e945c1 100644 --- a/test/map/map.cpp +++ b/test/map/map.cpp @@ -38,7 +38,7 @@ TEST(Map, Offline) { fileSource.put(Resource::source(prefix + "streets.json"), expiredItem("streets.json")); fileSource.put(Resource::spriteJSON(prefix + "sprite", 1.0), expiredItem("sprite.json")); fileSource.put(Resource::spriteImage(prefix + "sprite", 1.0), expiredItem("sprite.png")); - fileSource.put(Resource::tile(prefix + "{z}-{x}-{y}.vector.pbf", 1.0, 0, 0, 0), expiredItem("0-0-0.vector.pbf")); + fileSource.put(Resource::tile(prefix + "{z}-{x}-{y}.vector.pbf", 1.0, 0, 0, 0, Tileset::Scheme::XYZ), expiredItem("0-0-0.vector.pbf")); fileSource.put(Resource::glyphs(prefix + "{fontstack}/{range}.pbf", {{"Helvetica"}}, {0, 255}), expiredItem("glyph.pbf")); NetworkStatus::Set(NetworkStatus::Status::Offline); diff --git a/test/storage/offline_database.cpp b/test/storage/offline_database.cpp index 6a3262abf67..81da46bc78c 100644 --- a/test/storage/offline_database.cpp +++ b/test/storage/offline_database.cpp @@ -323,7 +323,7 @@ TEST(OfflineDatabase, DeleteRegion) { response.noContent = true; db.putRegionResource(region.getID(), Resource::style("http://example.com/"), response); - db.putRegionResource(region.getID(), Resource::tile("http://example.com/", 1.0, 0, 0, 0), response); + db.putRegionResource(region.getID(), Resource::tile("http://example.com/", 1.0, 0, 0, 0, Tileset::Scheme::XYZ), response); db.deleteRegion(std::move(region)); @@ -474,7 +474,7 @@ TEST(OfflineDatabase, GetRegionCompletedStatus) { EXPECT_EQ(0u, status2.completedTileCount); EXPECT_EQ(0u, status2.completedTileSize); - uint64_t tileSize = db.putRegionResource(region.getID(), Resource::tile("http://example.com/", 1.0, 0, 0, 0), response); + uint64_t tileSize = db.putRegionResource(region.getID(), Resource::tile("http://example.com/", 1.0, 0, 0, 0, Tileset::Scheme::XYZ), response); OfflineRegionStatus status3 = db.getRegionCompletedStatus(region.getID()); EXPECT_EQ(2u, status3.completedResourceCount); @@ -493,9 +493,9 @@ TEST(OfflineDatabase, OfflineMapboxTileCount) { OfflineRegion region1 = db.createRegion(definition, metadata); OfflineRegion region2 = db.createRegion(definition, metadata); - Resource nonMapboxTile = Resource::tile("http://example.com/", 1.0, 0, 0, 0); - Resource mapboxTile1 = Resource::tile("mapbox://tiles/1", 1.0, 0, 0, 0); - Resource mapboxTile2 = Resource::tile("mapbox://tiles/2", 1.0, 0, 0, 1); + Resource nonMapboxTile = Resource::tile("http://example.com/", 1.0, 0, 0, 0, Tileset::Scheme::XYZ); + Resource mapboxTile1 = Resource::tile("mapbox://tiles/1", 1.0, 0, 0, 0, Tileset::Scheme::XYZ); + Resource mapboxTile2 = Resource::tile("mapbox://tiles/2", 1.0, 0, 0, 1, Tileset::Scheme::XYZ); Response response; response.data = std::make_shared("data"); diff --git a/test/storage/offline_download.cpp b/test/storage/offline_download.cpp index eb676e3b8d3..76a772dd1b2 100644 --- a/test/storage/offline_download.cpp +++ b/test/storage/offline_download.cpp @@ -476,7 +476,7 @@ TEST(OfflineDownload, WithPreviouslyExistingTile) { }; test.db.put( - Resource::tile("http://127.0.0.1:3000/{z}-{x}-{y}.vector.pbf", 1, 0, 0, 0), + Resource::tile("http://127.0.0.1:3000/{z}-{x}-{y}.vector.pbf", 1, 0, 0, 0, Tileset::Scheme::XYZ), test.response("0-0-0.vector.pbf")); auto observer = std::make_unique(); @@ -510,7 +510,7 @@ TEST(OfflineDownload, ReactivatePreviouslyCompletedDownload) { }; test.db.put( - Resource::tile("http://127.0.0.1:3000/{z}-{x}-{y}.vector.pbf", 1, 0, 0, 0), + Resource::tile("http://127.0.0.1:3000/{z}-{x}-{y}.vector.pbf", 1, 0, 0, 0, Tileset::Scheme::XYZ), test.response("0-0-0.vector.pbf")); auto observer = std::make_unique(); diff --git a/test/storage/resource.cpp b/test/storage/resource.cpp index 02559f3e848..1c15fe65039 100644 --- a/test/storage/resource.cpp +++ b/test/storage/resource.cpp @@ -19,7 +19,7 @@ TEST(Resource, Source) { TEST(Resource, Tile) { using namespace mbgl; - Resource rasterTile = Resource::tile("http://example.com/{z}/{x}/{y}{ratio}.png", 2.0, 1, 2, 3); + Resource rasterTile = Resource::tile("http://example.com/{z}/{x}/{y}{ratio}.png", 2.0, 1, 2, 3, Tileset::Scheme::XYZ); EXPECT_EQ(Resource::Kind::Tile, rasterTile.kind); EXPECT_EQ("http://example.com/3/1/2@2x.png", rasterTile.url); EXPECT_EQ("http://example.com/{z}/{x}/{y}{ratio}.png", rasterTile.tileData->urlTemplate); @@ -28,7 +28,7 @@ TEST(Resource, Tile) { EXPECT_EQ(2, rasterTile.tileData->y); EXPECT_EQ(3, rasterTile.tileData->z); - Resource vectorTile = Resource::tile("http://example.com/{z}/{x}/{y}.mvt", 2.0, 1, 2, 3); + Resource vectorTile = Resource::tile("http://example.com/{z}/{x}/{y}.mvt", 2.0, 1, 2, 3, Tileset::Scheme::XYZ); EXPECT_EQ(Resource::Kind::Tile, vectorTile.kind); EXPECT_EQ("http://example.com/3/1/2.mvt", vectorTile.url); EXPECT_EQ("http://example.com/{z}/{x}/{y}.mvt", vectorTile.tileData->urlTemplate); @@ -37,7 +37,7 @@ TEST(Resource, Tile) { EXPECT_EQ(2, vectorTile.tileData->y); EXPECT_EQ(3, vectorTile.tileData->z); - Resource quadTile = Resource::tile("http://example.com/{quadkey}.png", 2.0, 0, 0, 1); + Resource quadTile = Resource::tile("http://example.com/{quadkey}.png", 2.0, 0, 0, 1, Tileset::Scheme::XYZ); EXPECT_EQ(Resource::Kind::Tile, quadTile.kind); EXPECT_EQ("http://example.com/0.png", quadTile.url); EXPECT_EQ("http://example.com/{quadkey}.png", quadTile.tileData->urlTemplate); @@ -46,7 +46,7 @@ TEST(Resource, Tile) { EXPECT_EQ(0, quadTile.tileData->y); EXPECT_EQ(1, quadTile.tileData->z); - quadTile = Resource::tile("http://example.com/{quadkey}.png", 2.0, 0, 0, 2); + quadTile = Resource::tile("http://example.com/{quadkey}.png", 2.0, 0, 0, 2, Tileset::Scheme::XYZ); EXPECT_EQ(Resource::Kind::Tile, quadTile.kind); EXPECT_EQ("http://example.com/00.png", quadTile.url); EXPECT_EQ("http://example.com/{quadkey}.png", quadTile.tileData->urlTemplate); @@ -55,7 +55,7 @@ TEST(Resource, Tile) { EXPECT_EQ(0, quadTile.tileData->y); EXPECT_EQ(2, quadTile.tileData->z); - quadTile = Resource::tile("http://example.com/{quadkey}.png", 2.0, 1, 1, 2); + quadTile = Resource::tile("http://example.com/{quadkey}.png", 2.0, 1, 1, 2, Tileset::Scheme::XYZ); EXPECT_EQ(Resource::Kind::Tile, quadTile.kind); EXPECT_EQ("http://example.com/03.png", quadTile.url); EXPECT_EQ("http://example.com/{quadkey}.png", quadTile.tileData->urlTemplate); @@ -64,7 +64,7 @@ TEST(Resource, Tile) { EXPECT_EQ(1, quadTile.tileData->y); EXPECT_EQ(2, quadTile.tileData->z); - quadTile = Resource::tile("http://example.com/{quadkey}.png", 2.0, 22914, 52870, 17); + quadTile = Resource::tile("http://example.com/{quadkey}.png", 2.0, 22914, 52870, 17, Tileset::Scheme::XYZ); EXPECT_EQ(Resource::Kind::Tile, quadTile.kind); EXPECT_EQ("http://example.com/02301322130000230.png", quadTile.url); EXPECT_EQ("http://example.com/{quadkey}.png", quadTile.tileData->urlTemplate); @@ -72,10 +72,10 @@ TEST(Resource, Tile) { EXPECT_EQ(22914, quadTile.tileData->x); EXPECT_EQ(52870, quadTile.tileData->y); EXPECT_EQ(17, quadTile.tileData->z); - + // Test case confirmed by quadkeytools package // https://bitbucket.org/steele/quadkeytools/src/master/test/quadkey.js?fileviewer=file-view-default#quadkey.js-57 - quadTile = Resource::tile("http://example.com/{quadkey}.png", 2.0, 29, 3, 6); + quadTile = Resource::tile("http://example.com/{quadkey}.png", 2.0, 29, 3, 6, Tileset::Scheme::XYZ); EXPECT_EQ(Resource::Kind::Tile, quadTile.kind); EXPECT_EQ("http://example.com/011123.png", quadTile.url); EXPECT_EQ("http://example.com/{quadkey}.png", quadTile.tileData->urlTemplate); @@ -84,7 +84,7 @@ TEST(Resource, Tile) { EXPECT_EQ(3, quadTile.tileData->y); EXPECT_EQ(6, quadTile.tileData->z); - Resource wmsTile = Resource::tile("http://example.com/?bbox={bbox-epsg-3857}", 2.0, 0, 0, 1); + Resource wmsTile = Resource::tile("http://example.com/?bbox={bbox-epsg-3857}", 2.0, 0, 0, 1, Tileset::Scheme::XYZ); EXPECT_EQ(Resource::Kind::Tile, wmsTile.kind); EXPECT_EQ("http://example.com/?bbox=-20037508.342789245,0,0,20037508.342789245", wmsTile.url); EXPECT_EQ("http://example.com/?bbox={bbox-epsg-3857}", wmsTile.tileData->urlTemplate); @@ -92,6 +92,15 @@ TEST(Resource, Tile) { EXPECT_EQ(0, wmsTile.tileData->x); EXPECT_EQ(0, wmsTile.tileData->y); EXPECT_EQ(1, wmsTile.tileData->z); + + Resource tmsTile = Resource::tile("http://example.com/{z}/{x}/{y}{ratio}.png", 1.0, 1, 2, 3, Tileset::Scheme::TMS); + EXPECT_EQ(Resource::Kind::Tile, tmsTile.kind); + EXPECT_EQ("http://example.com/3/1/5.png", tmsTile.url); + EXPECT_EQ("http://example.com/{z}/{x}/{y}{ratio}.png", tmsTile.tileData->urlTemplate); + EXPECT_EQ(1, tmsTile.tileData->pixelRatio); + EXPECT_EQ(1, tmsTile.tileData->x); + EXPECT_EQ(5, tmsTile.tileData->y); + EXPECT_EQ(3, tmsTile.tileData->z); } TEST(Resource, Glyphs) {