diff options
Diffstat (limited to 'platform/default/mbgl/storage/offline_download.cpp')
-rw-r--r-- | platform/default/mbgl/storage/offline_download.cpp | 116 |
1 files changed, 91 insertions, 25 deletions
diff --git a/platform/default/mbgl/storage/offline_download.cpp b/platform/default/mbgl/storage/offline_download.cpp index 4da51db655..118f3aad88 100644 --- a/platform/default/mbgl/storage/offline_download.cpp +++ b/platform/default/mbgl/storage/offline_download.cpp @@ -24,6 +24,63 @@ namespace mbgl { using namespace style; +// Generic functions + +template <class RegionDefinition> +Range<uint8_t> coveringZoomRange(const RegionDefinition& definition, + style::SourceType type, uint16_t tileSize, const Range<uint8_t>& zoomRange) { + double minZ = std::max<double>(util::coveringZoomLevel(definition.minZoom, type, tileSize), zoomRange.min); + double maxZ = std::min<double>(util::coveringZoomLevel(definition.maxZoom, type, tileSize), zoomRange.max); + + assert(minZ >= 0); + assert(maxZ >= 0); + assert(minZ < std::numeric_limits<uint8_t>::max()); + assert(maxZ < std::numeric_limits<uint8_t>::max()); + return { static_cast<uint8_t>(minZ), static_cast<uint8_t>(maxZ) }; +} + +template <class Geometry, class Fn> +void tileCover(const Geometry& geometry, uint8_t z, Fn&& fn) { + util::TileCover cover(geometry, z); + while (cover.hasNext()) { + fn(cover.next()->canonical); + } +} + + +template <class Fn> +void tileCover(const OfflineRegionDefinition& definition, style::SourceType type, + uint16_t tileSize, const Range<uint8_t>& zoomRange, Fn&& fn) { + const Range<uint8_t> clampedZoomRange = + definition.match([&](auto& reg) { return coveringZoomRange(reg, type, tileSize, zoomRange); }); + + for (uint8_t z = clampedZoomRange.min; z <= clampedZoomRange.max; z++) { + definition.match( + [&](const OfflineTilePyramidRegionDefinition& reg){ tileCover(reg.bounds, z, fn); }, + [&](const OfflineGeometryRegionDefinition& reg){ tileCover(reg.geometry, z, fn); } + ); + } +} + +uint64_t tileCount(const OfflineRegionDefinition& definition, style::SourceType type, + uint16_t tileSize, const Range<uint8_t>& zoomRange) { + + const Range<uint8_t> clampedZoomRange = + definition.match([&](auto& reg) { return coveringZoomRange(reg, type, tileSize, zoomRange); }); + + unsigned long result = 0;; + for (uint8_t z = clampedZoomRange.min; z <= clampedZoomRange.max; z++) { + result += definition.match( + [&](const OfflineTilePyramidRegionDefinition& reg){ return util::tileCount(reg.bounds, z); }, + [&](const OfflineGeometryRegionDefinition& reg){ return util::tileCount(reg.geometry, z); } + ); + } + + return result; +} + +// OfflineDownload + OfflineDownload::OfflineDownload(int64_t id_, OfflineRegionDefinition&& definition_, OfflineDatabase& offlineDatabase_, @@ -62,39 +119,45 @@ OfflineRegionStatus OfflineDownload::getStatus() const { return status; } - OfflineRegionStatus result = offlineDatabase.getRegionCompletedStatus(id); + auto result = offlineDatabase.getRegionCompletedStatus(id); + if (!result) { + // We can't find this offline region because the database is unavailable, or the download + // does not exist. + return {}; + } - result.requiredResourceCount++; - optional<Response> styleResponse = offlineDatabase.get(Resource::style(definition.styleURL)); + result->requiredResourceCount++; + optional<Response> styleResponse = + offlineDatabase.get(Resource::style(definition.match([](auto& reg){ return reg.styleURL; }))); if (!styleResponse) { - return result; + return *result; } style::Parser parser; parser.parse(*styleResponse->data); - result.requiredResourceCountIsPrecise = true; + result->requiredResourceCountIsPrecise = true; for (const auto& source : parser.sources) { SourceType type = source->getType(); auto handleTiledSource = [&] (const variant<std::string, Tileset>& urlOrTileset, const uint16_t tileSize) { if (urlOrTileset.is<Tileset>()) { - result.requiredResourceCount += - definition.tileCount(type, tileSize, urlOrTileset.get<Tileset>().zoomRange); + result->requiredResourceCount += + tileCount(definition, type, tileSize, urlOrTileset.get<Tileset>().zoomRange); } else { - result.requiredResourceCount += 1; + result->requiredResourceCount += 1; const auto& url = urlOrTileset.get<std::string>(); optional<Response> sourceResponse = offlineDatabase.get(Resource::source(url)); if (sourceResponse) { style::conversion::Error error; optional<Tileset> tileset = style::conversion::convertJSON<Tileset>(*sourceResponse->data, error); if (tileset) { - result.requiredResourceCount += - definition.tileCount(type, tileSize, (*tileset).zoomRange); + result->requiredResourceCount += + tileCount(definition, type, tileSize, (*tileset).zoomRange); } } else { - result.requiredResourceCountIsPrecise = false; + result->requiredResourceCountIsPrecise = false; } } }; @@ -111,7 +174,7 @@ OfflineRegionStatus OfflineDownload::getStatus() const { handleTiledSource(rasterSource.getURLOrTileset(), rasterSource.getTileSize()); break; } - + case SourceType::RasterDEM: { const auto& rasterDEMSource = *source->as<RasterDEMSource>(); handleTiledSource(rasterDEMSource.getURLOrTileset(), rasterDEMSource.getTileSize()); @@ -121,7 +184,7 @@ OfflineRegionStatus OfflineDownload::getStatus() const { case SourceType::GeoJSON: { const auto& geojsonSource = *source->as<GeoJSONSource>(); if (geojsonSource.getURL()) { - result.requiredResourceCount += 1; + result->requiredResourceCount += 1; } break; } @@ -129,7 +192,7 @@ OfflineRegionStatus OfflineDownload::getStatus() const { case SourceType::Image: { const auto& imageSource = *source->as<ImageSource>(); if (imageSource.getURL()) { - result.requiredResourceCount += 1; + result->requiredResourceCount += 1; } break; } @@ -142,21 +205,22 @@ OfflineRegionStatus OfflineDownload::getStatus() const { } if (!parser.glyphURL.empty()) { - result.requiredResourceCount += parser.fontStacks().size() * GLYPH_RANGES_PER_FONT_STACK; + result->requiredResourceCount += parser.fontStacks().size() * GLYPH_RANGES_PER_FONT_STACK; } if (!parser.spriteURL.empty()) { - result.requiredResourceCount += 2; + result->requiredResourceCount += 2; } - return result; + return *result; } void OfflineDownload::activateDownload() { status = OfflineRegionStatus(); status.downloadState = OfflineRegionDownloadState::Active; status.requiredResourceCount++; - ensureResource(Resource::style(definition.styleURL), [&](Response styleResponse) { + ensureResource(Resource::style(definition.match([](auto& reg){ return reg.styleURL; })), + [&](Response styleResponse) { status.requiredResourceCountIsPrecise = true; style::Parser parser; @@ -202,7 +266,7 @@ void OfflineDownload::activateDownload() { handleTiledSource(rasterSource.getURLOrTileset(), rasterSource.getTileSize()); break; } - + case SourceType::RasterDEM: { const auto& rasterDEMSource = *source->as<RasterDEMSource>(); handleTiledSource(rasterDEMSource.getURLOrTileset(), rasterDEMSource.getTileSize()); @@ -242,8 +306,9 @@ void OfflineDownload::activateDownload() { } if (!parser.spriteURL.empty()) { - queueResource(Resource::spriteImage(parser.spriteURL, definition.pixelRatio)); - queueResource(Resource::spriteJSON(parser.spriteURL, definition.pixelRatio)); + auto pixelRatio = definition.match([](auto& reg){ return reg.pixelRatio; }); + queueResource(Resource::spriteImage(parser.spriteURL, pixelRatio)); + queueResource(Resource::spriteJSON(parser.spriteURL, pixelRatio)); } continueDownload(); @@ -291,11 +356,12 @@ void OfflineDownload::queueResource(Resource resource) { } void OfflineDownload::queueTiles(SourceType type, uint16_t tileSize, const Tileset& tileset) { - for (const auto& tile : definition.tileCover(type, tileSize, tileset.zoomRange)) { + tileCover(definition, type, tileSize, tileset.zoomRange, [&](const auto& tile) { status.requiredResourceCount++; - resourcesRemaining.push_back( - Resource::tile(tileset.tiles[0], definition.pixelRatio, tile.x, tile.y, tile.z, tileset.scheme)); - } + resourcesRemaining.push_back(Resource::tile( + tileset.tiles[0], definition.match([](auto& def) { return def.pixelRatio; }), tile.x, + tile.y, tile.z, tileset.scheme)); + }); } void OfflineDownload::ensureResource(const Resource& resource, |