summaryrefslogtreecommitdiff
path: root/platform/default/mbgl/storage/offline_download.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'platform/default/mbgl/storage/offline_download.cpp')
-rw-r--r--platform/default/mbgl/storage/offline_download.cpp116
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,