From b7e2b11a75fd1b12d0ff948b9602fcd3db3779cf Mon Sep 17 00:00:00 2001 From: Chris Loer Date: Tue, 18 Dec 2018 17:26:31 -0800 Subject: [core] Support for excluding ideographic glyphs from offline downloads. --- include/mbgl/storage/offline.hpp | 6 +- platform/default/src/mbgl/storage/offline.cpp | 19 ++-- .../default/src/mbgl/storage/offline_download.cpp | 13 ++- src/mbgl/text/glyph_range.hpp | 2 + test/storage/offline.test.cpp | 6 +- test/storage/offline_database.test.cpp | 31 +++--- test/storage/offline_download.test.cpp | 115 +++++++++++++++++---- 7 files changed, 146 insertions(+), 46 deletions(-) diff --git a/include/mbgl/storage/offline.hpp b/include/mbgl/storage/offline.hpp index b4e40cb5f3..b3d258a7e3 100644 --- a/include/mbgl/storage/offline.hpp +++ b/include/mbgl/storage/offline.hpp @@ -29,7 +29,7 @@ class TileID; */ class OfflineTilePyramidRegionDefinition { public: - OfflineTilePyramidRegionDefinition(std::string, LatLngBounds, double, double, float); + OfflineTilePyramidRegionDefinition(std::string, LatLngBounds, double, double, float, bool); /* Private */ const std::string styleURL; @@ -37,6 +37,7 @@ public: const double minZoom; const double maxZoom; const float pixelRatio; + const bool includeIdeographs; }; /* @@ -52,7 +53,7 @@ public: */ class OfflineGeometryRegionDefinition { public: - OfflineGeometryRegionDefinition(std::string styleURL, Geometry, double minZoom, double maxZoom, float pixelRatio); + OfflineGeometryRegionDefinition(std::string styleURL, Geometry, double minZoom, double maxZoom, float pixelRatio, bool includeIdeographs); /* Private */ const std::string styleURL; @@ -60,6 +61,7 @@ public: const double minZoom; const double maxZoom; const float pixelRatio; + const bool includeIdeographs; }; /* diff --git a/platform/default/src/mbgl/storage/offline.cpp b/platform/default/src/mbgl/storage/offline.cpp index e1ec0acb31..fd945c724f 100644 --- a/platform/default/src/mbgl/storage/offline.cpp +++ b/platform/default/src/mbgl/storage/offline.cpp @@ -16,12 +16,13 @@ namespace mbgl { // OfflineTilePyramidRegionDefinition OfflineTilePyramidRegionDefinition::OfflineTilePyramidRegionDefinition( - std::string styleURL_, LatLngBounds bounds_, double minZoom_, double maxZoom_, float pixelRatio_) + std::string styleURL_, LatLngBounds bounds_, double minZoom_, double maxZoom_, float pixelRatio_, bool includeIdeographs_) : styleURL(std::move(styleURL_)), bounds(std::move(bounds_)), minZoom(minZoom_), maxZoom(maxZoom_), - pixelRatio(pixelRatio_) { + pixelRatio(pixelRatio_), + includeIdeographs(includeIdeographs_) { if (minZoom < 0 || maxZoom < 0 || maxZoom < minZoom || pixelRatio < 0 || !std::isfinite(minZoom) || std::isnan(maxZoom) || !std::isfinite(pixelRatio)) { throw std::invalid_argument("Invalid offline region definition"); @@ -31,12 +32,13 @@ OfflineTilePyramidRegionDefinition::OfflineTilePyramidRegionDefinition( // OfflineGeometryRegionDefinition -OfflineGeometryRegionDefinition::OfflineGeometryRegionDefinition(std::string styleURL_, Geometry geometry_, double minZoom_, double maxZoom_, float pixelRatio_) +OfflineGeometryRegionDefinition::OfflineGeometryRegionDefinition(std::string styleURL_, Geometry geometry_, double minZoom_, double maxZoom_, float pixelRatio_, bool includeIdeographs_) : styleURL(styleURL_) , geometry(std::move(geometry_)) , minZoom(minZoom_) , maxZoom(maxZoom_) - , pixelRatio(pixelRatio_) { + , pixelRatio(pixelRatio_) + , includeIdeographs(includeIdeographs_){ if (minZoom < 0 || maxZoom < 0 || maxZoom < minZoom || pixelRatio < 0 || !std::isfinite(minZoom) || std::isnan(maxZoom) || !std::isfinite(pixelRatio)) { throw std::invalid_argument("Invalid offline region definition"); @@ -64,7 +66,8 @@ OfflineRegionDefinition decodeOfflineRegionDefinition(const std::string& region) || !(hasValidBounds() || hasValidGeometry()) || !doc.HasMember("min_zoom") || !doc["min_zoom"].IsDouble() || (doc.HasMember("max_zoom") && !doc["max_zoom"].IsDouble()) - || !doc.HasMember("pixel_ratio") || !doc["pixel_ratio"].IsDouble()) { + || !doc.HasMember("pixel_ratio") || !doc["pixel_ratio"].IsDouble() + || (doc.HasMember("include_ideographs") && !doc["include_ideographs"].IsBool())) { throw std::runtime_error("Malformed offline region definition"); } @@ -74,6 +77,7 @@ OfflineRegionDefinition decodeOfflineRegionDefinition(const std::string& region) double minZoom = doc["min_zoom"].GetDouble(); double maxZoom = doc.HasMember("max_zoom") ? doc["max_zoom"].GetDouble() : INFINITY; float pixelRatio = doc["pixel_ratio"].GetDouble(); + bool includeIdeographs = doc.HasMember("include_ideographs") ? doc["include_ideographs"].GetBool() : true; if (doc.HasMember("bounds")) { return OfflineTilePyramidRegionDefinition{ @@ -81,12 +85,12 @@ OfflineRegionDefinition decodeOfflineRegionDefinition(const std::string& region) LatLngBounds::hull( LatLng(doc["bounds"][0].GetDouble(), doc["bounds"][1].GetDouble()), LatLng(doc["bounds"][2].GetDouble(), doc["bounds"][3].GetDouble())), - minZoom, maxZoom, pixelRatio }; + minZoom, maxZoom, pixelRatio, includeIdeographs }; } else { return OfflineGeometryRegionDefinition{ styleURL, mapbox::geojson::convert>(doc["geometry"].GetObject()), - minZoom, maxZoom, pixelRatio }; + minZoom, maxZoom, pixelRatio, includeIdeographs }; }; } @@ -104,6 +108,7 @@ std::string encodeOfflineRegionDefinition(const OfflineRegionDefinition& region) } doc.AddMember("pixel_ratio", _region.pixelRatio, doc.GetAllocator()); + doc.AddMember("include_ideographs", _region.includeIdeographs, doc.GetAllocator()); }); // Encode specific properties diff --git a/platform/default/src/mbgl/storage/offline_download.cpp b/platform/default/src/mbgl/storage/offline_download.cpp index c97797a5a2..d60ae786dd 100644 --- a/platform/default/src/mbgl/storage/offline_download.cpp +++ b/platform/default/src/mbgl/storage/offline_download.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -205,7 +206,10 @@ OfflineRegionStatus OfflineDownload::getStatus() const { } if (!parser.glyphURL.empty()) { - result->requiredResourceCount += parser.fontStacks().size() * GLYPH_RANGES_PER_FONT_STACK; + result->requiredResourceCount += parser.fontStacks().size() * + (definition.match([](auto& reg){ return reg.includeIdeographs; }) ? + GLYPH_RANGES_PER_FONT_STACK : + NON_IDEOGRAPH_GLYPH_RANGES_PER_FONT_STACK); } if (!parser.spriteURL.empty()) { @@ -298,9 +302,14 @@ void OfflineDownload::activateDownload() { } if (!parser.glyphURL.empty()) { + const bool includeIdeographs = definition.match([](auto& reg){ return reg.includeIdeographs; }); for (const auto& fontStack : parser.fontStacks()) { for (char16_t i = 0; i < GLYPH_RANGES_PER_FONT_STACK; i++) { - queueResource(Resource::glyphs(parser.glyphURL, fontStack, getGlyphRange(i * GLYPHS_PER_GLYPH_RANGE))); + // Assumes that if a glyph range starts with fixed width/ideographic characters, the entire + // range will be fixed width. + if (includeIdeographs || !util::i18n::allowsFixedWidthGlyphGeneration(i * GLYPHS_PER_GLYPH_RANGE)) { + queueResource(Resource::glyphs(parser.glyphURL, fontStack, getGlyphRange(i * GLYPHS_PER_GLYPH_RANGE))); + } } } } diff --git a/src/mbgl/text/glyph_range.hpp b/src/mbgl/text/glyph_range.hpp index 35a1f74b94..17dc8c8272 100644 --- a/src/mbgl/text/glyph_range.hpp +++ b/src/mbgl/text/glyph_range.hpp @@ -11,6 +11,8 @@ using GlyphRange = std::pair; constexpr uint32_t GLYPHS_PER_GLYPH_RANGE = 256; constexpr uint32_t GLYPH_RANGES_PER_FONT_STACK = 256; +// 256 - 126 ranges skipped w/ i18n::allowsFixedWidthGlyphGeneration +constexpr uint32_t NON_IDEOGRAPH_GLYPH_RANGES_PER_FONT_STACK = 130; } // end namespace mbgl diff --git a/test/storage/offline.test.cpp b/test/storage/offline.test.cpp index 90f9570320..46e7d68c3f 100644 --- a/test/storage/offline.test.cpp +++ b/test/storage/offline.test.cpp @@ -8,7 +8,7 @@ using SourceType = mbgl::style::SourceType; TEST(OfflineTilePyramidRegionDefinition, EncodeDecode) { - OfflineTilePyramidRegionDefinition region("mapbox://style", LatLngBounds::hull({ 37.6609, -122.5744 }, { 37.8271, -122.3204 }), 0, 20, 1.0); + OfflineTilePyramidRegionDefinition region("mapbox://style", LatLngBounds::hull({ 37.6609, -122.5744 }, { 37.8271, -122.3204 }), 0, 20, 1.0, true); auto encoded = encodeOfflineRegionDefinition(region); auto decoded = decodeOfflineRegionDefinition(encoded).get(); @@ -19,10 +19,11 @@ TEST(OfflineTilePyramidRegionDefinition, EncodeDecode) { EXPECT_EQ(decoded.pixelRatio, region.pixelRatio); EXPECT_EQ(decoded.bounds.southwest(), region.bounds.southwest()); EXPECT_EQ(decoded.bounds.northeast(), region.bounds.northeast()); + EXPECT_EQ(decoded.includeIdeographs, region.includeIdeographs); } TEST(OfflineGeometryRegionDefinition, EncodeDecode) { - OfflineGeometryRegionDefinition region("mapbox://style", Point(-122.5744, 37.6609), 0, 2, 1.0); + OfflineGeometryRegionDefinition region("mapbox://style", Point(-122.5744, 37.6609), 0, 2, 1.0, false); auto encoded = encodeOfflineRegionDefinition(region); auto decoded = decodeOfflineRegionDefinition(encoded).get(); @@ -32,4 +33,5 @@ TEST(OfflineGeometryRegionDefinition, EncodeDecode) { EXPECT_EQ(decoded.maxZoom, region.maxZoom); EXPECT_EQ(decoded.pixelRatio, region.pixelRatio); EXPECT_EQ(decoded.geometry, region.geometry); + EXPECT_EQ(decoded.includeIdeographs, region.includeIdeographs); } diff --git a/test/storage/offline_database.test.cpp b/test/storage/offline_database.test.cpp index 809771af07..d6405fd452 100644 --- a/test/storage/offline_database.test.cpp +++ b/test/storage/offline_database.test.cpp @@ -412,7 +412,7 @@ TEST(OfflineDatabase, PutTileNotFound) { TEST(OfflineDatabase, CreateRegion) { FixtureLog log; OfflineDatabase db(":memory:"); - OfflineTilePyramidRegionDefinition definition { "http://example.com/style", LatLngBounds::hull({1, 2}, {3, 4}), 5, 6, 2.0 }; + OfflineTilePyramidRegionDefinition definition { "http://example.com/style", LatLngBounds::hull({1, 2}, {3, 4}), 5, 6, 2.0, true }; OfflineRegionMetadata metadata {{ 1, 2, 3 }}; auto region = db.createRegion(definition, metadata); ASSERT_TRUE(region); @@ -426,6 +426,7 @@ TEST(OfflineDatabase, CreateRegion) { EXPECT_EQ(definition.minZoom, def.minZoom); EXPECT_EQ(definition.maxZoom, def.maxZoom); EXPECT_EQ(definition.pixelRatio, def.pixelRatio); + EXPECT_EQ(definition.includeIdeographs, def.includeIdeographs); }, [](auto&) { EXPECT_FALSE(false); } @@ -436,7 +437,7 @@ TEST(OfflineDatabase, CreateRegion) { TEST(OfflineDatabase, UpdateMetadata) { FixtureLog log; OfflineDatabase db(":memory:"); - OfflineTilePyramidRegionDefinition definition { "http://example.com/style", LatLngBounds::hull({1, 2}, {3, 4}), 5, 6, 2.0 }; + OfflineTilePyramidRegionDefinition definition { "http://example.com/style", LatLngBounds::hull({1, 2}, {3, 4}), 5, 6, 2.0, true }; OfflineRegionMetadata metadata {{ 1, 2, 3 }}; auto region = db.createRegion(definition, metadata); ASSERT_TRUE(region); @@ -452,7 +453,7 @@ TEST(OfflineDatabase, UpdateMetadata) { TEST(OfflineDatabase, ListRegions) { FixtureLog log; OfflineDatabase db(":memory:"); - OfflineTilePyramidRegionDefinition definition { "http://example.com/style", LatLngBounds::hull({1, 2}, {3, 4}), 5, 6, 2.0 }; + OfflineTilePyramidRegionDefinition definition { "http://example.com/style", LatLngBounds::hull({1, 2}, {3, 4}), 5, 6, 2.0, false }; OfflineRegionMetadata metadata {{ 1, 2, 3 }}; auto region = db.createRegion(definition, metadata); @@ -469,6 +470,7 @@ TEST(OfflineDatabase, ListRegions) { EXPECT_EQ(definition.minZoom, def.minZoom); EXPECT_EQ(definition.maxZoom, def.maxZoom); EXPECT_EQ(definition.pixelRatio, def.pixelRatio); + EXPECT_EQ(definition.includeIdeographs, def.includeIdeographs); }, [&](auto&) { EXPECT_FALSE(false); @@ -481,7 +483,7 @@ TEST(OfflineDatabase, ListRegions) { TEST(OfflineDatabase, GetRegionDefinition) { FixtureLog log; OfflineDatabase db(":memory:"); - OfflineTilePyramidRegionDefinition definition { "http://example.com/style", LatLngBounds::hull({1, 2}, {3, 4}), 5, 6, 2.0 }; + OfflineTilePyramidRegionDefinition definition { "http://example.com/style", LatLngBounds::hull({1, 2}, {3, 4}), 5, 6, 2.0, false }; OfflineRegionMetadata metadata {{ 1, 2, 3 }}; EXPECT_EQ(0u, log.uncheckedCount()); @@ -494,6 +496,7 @@ TEST(OfflineDatabase, GetRegionDefinition) { EXPECT_EQ(definition.minZoom, result.minZoom); EXPECT_EQ(definition.maxZoom, result.maxZoom); EXPECT_EQ(definition.pixelRatio, result.pixelRatio); + EXPECT_EQ(definition.includeIdeographs, result.includeIdeographs); }, [&](auto&) { EXPECT_FALSE(false); @@ -504,7 +507,7 @@ TEST(OfflineDatabase, GetRegionDefinition) { TEST(OfflineDatabase, DeleteRegion) { FixtureLog log; OfflineDatabase db(":memory:"); - OfflineTilePyramidRegionDefinition definition { "http://example.com/style", LatLngBounds::hull({1, 2}, {3, 4}), 5, 6, 2.0 }; + OfflineTilePyramidRegionDefinition definition { "http://example.com/style", LatLngBounds::hull({1, 2}, {3, 4}), 5, 6, 2.0, true }; OfflineRegionMetadata metadata {{ 1, 2, 3 }}; auto region = db.createRegion(definition, metadata); ASSERT_TRUE(region); @@ -526,7 +529,7 @@ TEST(OfflineDatabase, DeleteRegion) { TEST(OfflineDatabase, CreateRegionInfiniteMaxZoom) { FixtureLog log; OfflineDatabase db(":memory:"); - OfflineTilePyramidRegionDefinition definition { "", LatLngBounds::world(), 0, INFINITY, 1.0 }; + OfflineTilePyramidRegionDefinition definition { "", LatLngBounds::world(), 0, INFINITY, 1.0, false }; OfflineRegionMetadata metadata; auto region = db.createRegion(definition, metadata); ASSERT_TRUE(region); @@ -619,7 +622,7 @@ TEST(OfflineDatabase, PutEvictsLeastRecentlyUsedResources) { TEST(OfflineDatabase, PutRegionResourceDoesNotEvict) { FixtureLog log; OfflineDatabase db(":memory:", 1024 * 100); - OfflineTilePyramidRegionDefinition definition { "", LatLngBounds::world(), 0, INFINITY, 1.0 }; + OfflineTilePyramidRegionDefinition definition { "", LatLngBounds::world(), 0, INFINITY, 1.0, true }; auto region = db.createRegion(definition, OfflineRegionMetadata()); ASSERT_TRUE(region); @@ -656,7 +659,7 @@ TEST(OfflineDatabase, PutFailsWhenEvictionInsuffices) { TEST(OfflineDatabase, GetRegionCompletedStatus) { FixtureLog log; OfflineDatabase db(":memory:"); - OfflineTilePyramidRegionDefinition definition { "http://example.com/style", LatLngBounds::hull({1, 2}, {3, 4}), 5, 6, 2.0 }; + OfflineTilePyramidRegionDefinition definition { "http://example.com/style", LatLngBounds::hull({1, 2}, {3, 4}), 5, 6, 2.0, false }; OfflineRegionMetadata metadata; auto region = db.createRegion(definition, metadata); ASSERT_TRUE(region); @@ -695,7 +698,7 @@ TEST(OfflineDatabase, GetRegionCompletedStatus) { TEST(OfflineDatabase, HasRegionResource) { FixtureLog log; OfflineDatabase db(":memory:", 1024 * 100); - OfflineTilePyramidRegionDefinition definition { "", LatLngBounds::world(), 0, INFINITY, 1.0 }; + OfflineTilePyramidRegionDefinition definition { "", LatLngBounds::world(), 0, INFINITY, 1.0, true }; auto region = db.createRegion(definition, OfflineRegionMetadata()); ASSERT_TRUE(region); @@ -719,7 +722,7 @@ TEST(OfflineDatabase, HasRegionResource) { TEST(OfflineDatabase, HasRegionResourceTile) { FixtureLog log; OfflineDatabase db(":memory:", 1024 * 100); - OfflineTilePyramidRegionDefinition definition { "", LatLngBounds::world(), 0, INFINITY, 1.0 }; + OfflineTilePyramidRegionDefinition definition { "", LatLngBounds::world(), 0, INFINITY, 1.0, false }; auto region = db.createRegion(definition, OfflineRegionMetadata()); ASSERT_TRUE(region); @@ -753,7 +756,7 @@ TEST(OfflineDatabase, HasRegionResourceTile) { TEST(OfflineDatabase, OfflineMapboxTileCount) { FixtureLog log; OfflineDatabase db(":memory:"); - OfflineTilePyramidRegionDefinition definition { "http://example.com/style", LatLngBounds::hull({1, 2}, {3, 4}), 5, 6, 2.0 }; + OfflineTilePyramidRegionDefinition definition { "http://example.com/style", LatLngBounds::hull({1, 2}, {3, 4}), 5, 6, 2.0 , true}; OfflineRegionMetadata metadata; auto region1 = db.createRegion(definition, metadata); @@ -814,7 +817,7 @@ TEST(OfflineDatabase, OfflineMapboxTileCount) { TEST(OfflineDatabase, BatchInsertion) { FixtureLog log; OfflineDatabase db(":memory:", 1024 * 100); - OfflineTilePyramidRegionDefinition definition { "", LatLngBounds::world(), 0, INFINITY, 1.0 }; + OfflineTilePyramidRegionDefinition definition { "", LatLngBounds::world(), 0, INFINITY, 1.0, true }; auto region = db.createRegion(definition, OfflineRegionMetadata()); ASSERT_TRUE(region); @@ -840,7 +843,7 @@ TEST(OfflineDatabase, BatchInsertionMapboxTileCountExceeded) { FixtureLog log; OfflineDatabase db(":memory:", 1024 * 100); db.setOfflineMapboxTileCountLimit(1); - OfflineTilePyramidRegionDefinition definition { "", LatLngBounds::world(), 0, INFINITY, 1.0 }; + OfflineTilePyramidRegionDefinition definition { "", LatLngBounds::world(), 0, INFINITY, 1.0, false }; auto region = db.createRegion(definition, OfflineRegionMetadata()); ASSERT_TRUE(region); @@ -1051,7 +1054,7 @@ TEST(OfflineDatabase, TEST_REQUIRES_WRITE(DisallowedIO)) { // First, create a region object so that we can try deleting it later. OfflineTilePyramidRegionDefinition definition( - "mapbox://style", LatLngBounds::hull({ 37.66, -122.57 }, { 37.83, -122.32 }), 0, 8, 2); + "mapbox://style", LatLngBounds::hull({ 37.66, -122.57 }, { 37.83, -122.32 }), 0, 8, 2, false); auto region = db.createRegion(definition, {}); ASSERT_TRUE(region); diff --git a/test/storage/offline_download.test.cpp b/test/storage/offline_download.test.cpp index 2195585bf5..68f8ea2484 100644 --- a/test/storage/offline_download.test.cpp +++ b/test/storage/offline_download.test.cpp @@ -66,7 +66,7 @@ public: std::size_t size = 0; auto createRegion() { - OfflineTilePyramidRegionDefinition definition { "", LatLngBounds::hull({1, 2}, {3, 4}), 5, 6, 1.0 }; + OfflineTilePyramidRegionDefinition definition { "", LatLngBounds::hull({1, 2}, {3, 4}), 5, 6, 1.0, true }; OfflineRegionMetadata metadata; return db.createRegion(definition, metadata); } @@ -87,7 +87,7 @@ TEST(OfflineDownload, NoSubresources) { ASSERT_TRUE(region); OfflineDownload download( region->getID(), - OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0), + OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0, false), test.db, test.fileSource); test.fileSource.styleResponse = [&] (const Resource& resource) { @@ -128,7 +128,7 @@ TEST(OfflineDownload, InlineSource) { ASSERT_TRUE(region); OfflineDownload download( region->getID(), - OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0), + OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0, true), test.db, test.fileSource); test.fileSource.styleResponse = [&] (const Resource& resource) { @@ -169,7 +169,7 @@ TEST(OfflineDownload, GeoJSONSource) { ASSERT_TRUE(region); OfflineDownload download( region->getID(), - OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0), + OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0, false), test.db, test.fileSource); test.fileSource.styleResponse = [&] (const Resource& resource) { @@ -205,7 +205,7 @@ TEST(OfflineDownload, Activate) { ASSERT_TRUE(region); OfflineDownload download( region->getID(), - OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0), + OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0, true), test.db, test.fileSource); test.fileSource.styleResponse = [&] (const Resource& resource) { @@ -276,6 +276,83 @@ TEST(OfflineDownload, Activate) { test.loop.run(); } +TEST(OfflineDownload, ExcludeIdeographs) { + OfflineTest test; + auto region = test.createRegion(); + ASSERT_TRUE(region); + OfflineDownload download( + region->getID(), + OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0, false), + test.db, test.fileSource); + + test.fileSource.styleResponse = [&] (const Resource& resource) { + EXPECT_EQ("http://127.0.0.1:3000/style.json", resource.url); + return test.response("style.json"); + }; + + test.fileSource.spriteImageResponse = [&] (const Resource& resource) { + EXPECT_TRUE(resource.url == "http://127.0.0.1:3000/sprite.png" || + resource.url == "http://127.0.0.1:3000/sprite@2x.png"); + return test.response("sprite.png"); + }; + + test.fileSource.imageResponse = [&] (const Resource& resource) { + EXPECT_EQ("http://127.0.0.1:3000/radar.gif", resource.url); + return test.response("radar.gif"); + }; + + test.fileSource.spriteJSONResponse = [&] (const Resource& resource) { + EXPECT_TRUE(resource.url == "http://127.0.0.1:3000/sprite.json" || + resource.url == "http://127.0.0.1:3000/sprite@2x.json"); + return test.response("sprite.json"); + }; + + test.fileSource.glyphsResponse = [&] (const Resource&) { + return test.response("glyph.pbf"); + }; + + test.fileSource.sourceResponse = [&] (const Resource& resource) { + EXPECT_EQ("http://127.0.0.1:3000/streets.json", resource.url); + return test.response("streets.json"); + }; + + test.fileSource.tileResponse = [&] (const Resource& resource) { + const Resource::TileData& tile = *resource.tileData; + EXPECT_EQ("http://127.0.0.1:3000/{z}-{x}-{y}.vector.pbf", tile.urlTemplate); + EXPECT_EQ(1, tile.pixelRatio); + EXPECT_EQ(0, tile.x); + EXPECT_EQ(0, tile.y); + EXPECT_EQ(0, tile.z); + return test.response("0-0-0.vector.pbf"); + }; + + auto observer = std::make_unique(); + + observer->statusChangedFn = [&] (OfflineRegionStatus status) { + if (status.complete()) { + EXPECT_EQ(138u, status.completedResourceCount); // 130 glyphs, 2 sprite images, 2 sprite jsons, 1 tile, 1 style, source, image + EXPECT_EQ(test.size, status.completedResourceSize); + + download.setState(OfflineRegionDownloadState::Inactive); + OfflineRegionStatus computedStatus = download.getStatus(); + EXPECT_EQ(OfflineRegionDownloadState::Inactive, computedStatus.downloadState); + EXPECT_EQ(status.requiredResourceCount, computedStatus.requiredResourceCount); + EXPECT_EQ(status.completedResourceCount, computedStatus.completedResourceCount); + EXPECT_EQ(status.completedResourceSize, computedStatus.completedResourceSize); + EXPECT_EQ(status.completedTileCount, computedStatus.completedTileCount); + EXPECT_EQ(status.completedTileSize, computedStatus.completedTileSize); + EXPECT_TRUE(status.requiredResourceCountIsPrecise); + + test.loop.stop(); + } + }; + + download.setObserver(std::move(observer)); + download.setState(OfflineRegionDownloadState::Active); + + test.loop.run(); +} + TEST(OfflineDownload, DoesNotFloodTheFileSourceWithRequests) { OfflineTest test; FakeOnlineFileSource fileSource; @@ -283,7 +360,7 @@ TEST(OfflineDownload, DoesNotFloodTheFileSourceWithRequests) { ASSERT_TRUE(region); OfflineDownload download( region->getID(), - OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0), + OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0, true), test.db, fileSource); auto observer = std::make_unique(); @@ -306,7 +383,7 @@ TEST(OfflineDownload, GetStatusNoResources) { ASSERT_TRUE(region); OfflineDownload download( region->getID(), - OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0), + OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0, false), test.db, test.fileSource); OfflineRegionStatus status = download.getStatus(); @@ -324,7 +401,7 @@ TEST(OfflineDownload, GetStatusStyleComplete) { ASSERT_TRUE(region); OfflineDownload download( region->getID(), - OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0), + OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0, true), test.db, test.fileSource); test.db.putRegionResource(1, @@ -347,7 +424,7 @@ TEST(OfflineDownload, GetStatusStyleAndSourceComplete) { ASSERT_TRUE(region); OfflineDownload download( region->getID(), - OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0), + OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0, true), test.db, test.fileSource); test.db.putRegionResource(1, @@ -374,7 +451,7 @@ TEST(OfflineDownload, RequestError) { ASSERT_TRUE(region); OfflineDownload download( region->getID(), - OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0), + OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0, false), test.db, test.fileSource); test.fileSource.styleResponse = [&] (const Resource&) { @@ -403,7 +480,7 @@ TEST(OfflineDownload, RequestErrorsAreRetried) { ASSERT_TRUE(region); OfflineDownload download( region->getID(), - OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0), + OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0, true), test.db, test.fileSource); test.fileSource.styleResponse = [&] (const Resource&) { @@ -437,7 +514,7 @@ TEST(OfflineDownload, TileCountLimitExceededNoTileResponse) { ASSERT_TRUE(region); OfflineDownload download( region->getID(), - OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0), + OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0, false), test.db, test.fileSource); uint64_t tileLimit = 0; @@ -480,7 +557,7 @@ TEST(OfflineDownload, TileCountLimitExceededWithTileResponse) { ASSERT_TRUE(region); OfflineDownload download( region->getID(), - OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0), + OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0, true), test.db, test.fileSource); uint64_t tileLimit = 1; @@ -535,7 +612,7 @@ TEST(OfflineDownload, WithPreviouslyExistingTile) { ASSERT_TRUE(region); OfflineDownload download( region->getID(), - OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0), + OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0, false), test.db, test.fileSource); test.fileSource.styleResponse = [&] (const Resource& resource) { @@ -570,7 +647,7 @@ TEST(OfflineDownload, ReactivatePreviouslyCompletedDownload) { ASSERT_TRUE(region); OfflineDownload download( region->getID(), - OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0), + OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0, true), test.db, test.fileSource); test.fileSource.styleResponse = [&] (const Resource& resource) { @@ -596,7 +673,7 @@ TEST(OfflineDownload, ReactivatePreviouslyCompletedDownload) { OfflineDownload redownload( region->getID(), - OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0), + OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0, false), test.db, test.fileSource); std::vector statusesAfterReactivate; @@ -638,7 +715,7 @@ TEST(OfflineDownload, Deactivate) { ASSERT_TRUE(region); OfflineDownload download( region->getID(), - OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0), + OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0, false), test.db, test.fileSource); test.fileSource.styleResponse = [&] (const Resource& resource) { @@ -669,7 +746,7 @@ TEST(OfflineDownload, AllOfflineRequestsHaveLowPriority) { ASSERT_TRUE(region); OfflineDownload download( region->getID(), - OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0), + OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0, true), test.db, test.fileSource); test.fileSource.styleResponse = [&] (const Resource& resource) { @@ -740,7 +817,7 @@ TEST(OfflineDownload, DiskFull) { OfflineDownload download( region->getID(), - OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0), + OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0, false), test.db, test.fileSource); bool hasRequestedStyle = false; -- cgit v1.2.1