diff options
author | John Firebaugh <john.firebaugh@gmail.com> | 2016-06-13 13:35:24 -0700 |
---|---|---|
committer | John Firebaugh <john.firebaugh@gmail.com> | 2016-06-14 11:25:45 -0700 |
commit | 2a991c6846bc6742abd618ec750bd2f01a13b75e (patch) | |
tree | 0592f4b3ebc63aeed0aeefe5c576ae9a67bfccdc | |
parent | e6ba10ceed93c3b565a80591d8def5f0e7d72aac (diff) | |
download | qtlocation-mapboxgl-2a991c6846bc6742abd618ec750bd2f01a13b75e.tar.gz |
[core] Virtualize Source::load
-rw-r--r-- | src/mbgl/annotation/annotation_source.cpp | 4 | ||||
-rw-r--r-- | src/mbgl/annotation/annotation_source.hpp | 2 | ||||
-rw-r--r-- | src/mbgl/style/source.cpp | 98 | ||||
-rw-r--r-- | src/mbgl/style/source.hpp | 11 | ||||
-rw-r--r-- | src/mbgl/style/sources/geojson_source.cpp | 50 | ||||
-rw-r--r-- | src/mbgl/style/sources/geojson_source.hpp | 2 | ||||
-rw-r--r-- | src/mbgl/style/tile_source.cpp | 62 | ||||
-rw-r--r-- | src/mbgl/style/tile_source.hpp | 2 |
8 files changed, 132 insertions, 99 deletions
diff --git a/src/mbgl/annotation/annotation_source.cpp b/src/mbgl/annotation/annotation_source.cpp index 50fa7a2c09..aa52e2e434 100644 --- a/src/mbgl/annotation/annotation_source.cpp +++ b/src/mbgl/annotation/annotation_source.cpp @@ -8,6 +8,10 @@ AnnotationSource::AnnotationSource() : Source(SourceType::Annotations, AnnotationManager::SourceID, "", util::tileSize, std::make_unique<Tileset>()) { } +void AnnotationSource::load(FileSource&) { + loaded = true; +} + std::unique_ptr<Tile> AnnotationSource::createTile(const OverscaledTileID& tileID, const style::UpdateParameters& parameters) { return std::make_unique<AnnotationTile>(tileID, id, parameters); diff --git a/src/mbgl/annotation/annotation_source.hpp b/src/mbgl/annotation/annotation_source.hpp index 033580b645..565b9273d6 100644 --- a/src/mbgl/annotation/annotation_source.hpp +++ b/src/mbgl/annotation/annotation_source.hpp @@ -8,6 +8,8 @@ class AnnotationSource : public style::Source { public: AnnotationSource(); + void load(FileSource&) final; + private: std::unique_ptr<Tile> createTile(const OverscaledTileID&, const style::UpdateParameters&) final; }; diff --git a/src/mbgl/style/source.cpp b/src/mbgl/style/source.cpp index 35acf3dd51..41c1d0d22b 100644 --- a/src/mbgl/style/source.cpp +++ b/src/mbgl/style/source.cpp @@ -7,7 +7,6 @@ #include <mbgl/util/constants.hpp> #include <mbgl/storage/resource.hpp> #include <mbgl/storage/response.hpp> -#include <mbgl/storage/file_source.hpp> #include <mbgl/style/layer.hpp> #include <mbgl/style/update_parameters.hpp> #include <mbgl/style/query_parameters.hpp> @@ -20,7 +19,6 @@ #include <mbgl/util/tile_cover.hpp> #include <mbgl/util/enum.hpp> -#include <mbgl/style/parser.hpp> #include <mbgl/gl/debugging.hpp> #include <mbgl/algorithm/update_renderables.hpp> @@ -29,10 +27,7 @@ #include <mapbox/geojsonvt/convert.hpp> #include <mapbox/geometry/envelope.hpp> -#include <rapidjson/error/en.h> - #include <algorithm> -#include <sstream> namespace mbgl { namespace style { @@ -70,95 +65,10 @@ bool Source::isLoading() const { return !loaded && req.operator bool(); } -void Source::load(FileSource& fileSource) { - if (url.empty()) { - // In case there is no URL set, we assume that we already have all of the data because the - // TileJSON was specified inline in the stylesheet. - loaded = true; - return; - } - - if (req) { - // We don't have a Tileset object yet, but there's already a request underway to load - // the data. - return; - } - - // URL may either be a TileJSON file, or a GeoJSON file. - req = fileSource.request(Resource::source(url), [this](Response res) { - if (res.error) { - observer->onSourceError(*this, std::make_exception_ptr(std::runtime_error(res.error->message))); - } else if (res.notModified) { - return; - } else if (res.noContent) { - observer->onSourceError(*this, std::make_exception_ptr(std::runtime_error("unexpectedly empty source"))); - } else { - bool reloadTiles = false; - - if (type == SourceType::Vector || type == SourceType::Raster) { - std::unique_ptr<Tileset> newTileset; - - // Create a new copy of the Tileset object that holds the base values we've parsed - // from the stylesheet. Then merge in the values parsed from the TileJSON we retrieved - // via the URL. - try { - newTileset = style::parseTileJSON(*res.data, url, type, tileSize); - } catch (...) { - observer->onSourceError(*this, std::current_exception()); - return; - } - - // Check whether previous information specifies different tile - if (tileset && tileset->tiles != newTileset->tiles) { - reloadTiles = true; - - // Tile size changed: We need to recalculate the tiles we need to load because we - // might have to load tiles for a different zoom level - // This is done automatically when we trigger the onSourceLoaded observer below. - - // Min/Max zoom changed: We need to recalculate what tiles to load, if we have tiles - // loaded that are outside the new zoom range - // This is done automatically when we trigger the onSourceLoaded observer below. - - // Attribution changed: We need to notify the embedding application that this - // changed. See https://github.com/mapbox/mapbox-gl-native/issues/2723 - // This is not yet implemented. - - // Center/bounds changed: We're not using these values currently - } - - tileset = std::move(newTileset); - } else if (type == SourceType::GeoJSON) { - std::unique_ptr<Tileset> newTileset = std::make_unique<Tileset>(); - - rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> d; - d.Parse<0>(res.data->c_str()); - - if (d.HasParseError()) { - std::stringstream message; - message << d.GetErrorOffset() << " - " << rapidjson::GetParseError_En(d.GetParseError()); - observer->onSourceError(*this, std::make_exception_ptr(std::runtime_error(message.str()))); - return; - } - - geojsonvt = style::parseGeoJSON(d); - reloadTiles = true; - - newTileset->maxZoom = geojsonvt->options.maxZoom; - tileset = std::move(newTileset); - } - - if (reloadTiles) { - // Tile information changed because we got new GeoJSON data, or a new tile URL. - tiles.clear(); - renderTiles.clear(); - cache.clear(); - } - - loaded = true; - observer->onSourceLoaded(*this); - } - }); +void Source::invalidateTiles() { + tiles.clear(); + renderTiles.clear(); + cache.clear(); } void Source::updateMatrices(const mat4 &projMatrix, const TransformState &transform) { diff --git a/src/mbgl/style/source.hpp b/src/mbgl/style/source.hpp index 51a9ba5c71..92ca808afb 100644 --- a/src/mbgl/style/source.hpp +++ b/src/mbgl/style/source.hpp @@ -48,7 +48,7 @@ public: ~Source() override; bool loaded = false; - void load(FileSource&); + virtual void load(FileSource&) = 0; bool isLoading() const; bool isLoaded() const; @@ -96,8 +96,13 @@ private: virtual std::unique_ptr<Tile> createTile(const OverscaledTileID&, const UpdateParameters&) = 0; protected: + void invalidateTiles(); + std::unique_ptr<const Tileset> tileset; std::unique_ptr<mapbox::geojsonvt::GeoJSONVT> geojsonvt; + std::unique_ptr<AsyncRequest> req; + + SourceObserver* observer = nullptr; private: // Stores the time when this source was most recently updated. @@ -106,10 +111,6 @@ private: std::map<OverscaledTileID, std::unique_ptr<Tile>> tiles; std::map<UnwrappedTileID, RenderTile> renderTiles; TileCache cache; - - std::unique_ptr<AsyncRequest> req; - - SourceObserver* observer = nullptr; }; } // namespace style diff --git a/src/mbgl/style/sources/geojson_source.cpp b/src/mbgl/style/sources/geojson_source.cpp index caedcffcd5..6ece894e2e 100644 --- a/src/mbgl/style/sources/geojson_source.cpp +++ b/src/mbgl/style/sources/geojson_source.cpp @@ -1,8 +1,15 @@ #include <mbgl/style/sources/geojson_source.hpp> +#include <mbgl/style/source_observer.hpp> +#include <mbgl/style/parser.hpp> #include <mbgl/tile/geojson_tile.hpp> +#include <mbgl/storage/file_source.hpp> #include <mapbox/geojsonvt.hpp> +#include <rapidjson/error/en.h> + +#include <sstream> + namespace mbgl { namespace style { @@ -15,6 +22,49 @@ GeoJSONSource::GeoJSONSource(std::string id_, geojsonvt = std::move(geojsonvt_); } +void GeoJSONSource::load(FileSource& fileSource) { + if (url.empty()) { + // If the URL is empty, the GeoJSON was specified inline in the stylesheet. + loaded = true; + return; + } + + if (req) { + return; + } + + req = fileSource.request(Resource::source(url), [this](Response res) { + if (res.error) { + observer->onSourceError(*this, std::make_exception_ptr(std::runtime_error(res.error->message))); + } else if (res.notModified) { + return; + } else if (res.noContent) { + observer->onSourceError(*this, std::make_exception_ptr(std::runtime_error("unexpectedly empty GeoJSON"))); + } else { + std::unique_ptr<Tileset> newTileset = std::make_unique<Tileset>(); + + rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> d; + d.Parse<0>(res.data->c_str()); + + if (d.HasParseError()) { + std::stringstream message; + message << d.GetErrorOffset() << " - " << rapidjson::GetParseError_En(d.GetParseError()); + observer->onSourceError(*this, std::make_exception_ptr(std::runtime_error(message.str()))); + return; + } + + geojsonvt = style::parseGeoJSON(d); + newTileset->maxZoom = geojsonvt->options.maxZoom; + + invalidateTiles(); + + tileset = std::move(newTileset); + loaded = true; + observer->onSourceLoaded(*this); + } + }); +} + std::unique_ptr<Tile> GeoJSONSource::createTile(const OverscaledTileID& tileID, const UpdateParameters& parameters) { return std::make_unique<GeoJSONTile>(tileID, id, parameters, geojsonvt.get()); diff --git a/src/mbgl/style/sources/geojson_source.hpp b/src/mbgl/style/sources/geojson_source.hpp index c9262f22b7..47984ff9da 100644 --- a/src/mbgl/style/sources/geojson_source.hpp +++ b/src/mbgl/style/sources/geojson_source.hpp @@ -13,6 +13,8 @@ public: std::unique_ptr<Tileset>&&, std::unique_ptr<mapbox::geojsonvt::GeoJSONVT>&&); + void load(FileSource&) final; + private: std::unique_ptr<Tile> createTile(const OverscaledTileID&, const UpdateParameters&) final; }; diff --git a/src/mbgl/style/tile_source.cpp b/src/mbgl/style/tile_source.cpp index 22739035a9..90f4b54d96 100644 --- a/src/mbgl/style/tile_source.cpp +++ b/src/mbgl/style/tile_source.cpp @@ -1,4 +1,7 @@ #include <mbgl/style/tile_source.hpp> +#include <mbgl/style/source_observer.hpp> +#include <mbgl/style/parser.hpp> +#include <mbgl/storage/file_source.hpp> namespace mbgl { namespace style { @@ -11,5 +14,64 @@ TileSource::TileSource(SourceType type_, : Source(type_, std::move(id_), std::move(url_), tileSize_, std::move(tileset_)) { } +void TileSource::load(FileSource& fileSource) { + if (url.empty()) { + // If the URL is empty, the TileJSON was specified inline in the stylesheet. + loaded = true; + return; + } + + if (req) { + return; + } + + // URL may either be a TileJSON file, or a GeoJSON file. + req = fileSource.request(Resource::source(url), [this](Response res) { + if (res.error) { + observer->onSourceError(*this, std::make_exception_ptr(std::runtime_error(res.error->message))); + } else if (res.notModified) { + return; + } else if (res.noContent) { + observer->onSourceError(*this, std::make_exception_ptr(std::runtime_error("unexpectedly empty TileJSON"))); + } else { + std::unique_ptr<Tileset> newTileset; + + // Create a new copy of the Tileset object that holds the base values we've parsed + // from the stylesheet. Then merge in the values parsed from the TileJSON we retrieved + // via the URL. + try { + newTileset = style::parseTileJSON(*res.data, url, type, tileSize); + } catch (...) { + observer->onSourceError(*this, std::current_exception()); + return; + } + + // Check whether previous information specifies different tile + if (tileset && tileset->tiles != newTileset->tiles) { + // Tile URLs changed: force tiles to be reloaded. + invalidateTiles(); + + // Tile size changed: We need to recalculate the tiles we need to load because we + // might have to load tiles for a different zoom level + // This is done automatically when we trigger the onSourceLoaded observer below. + + // Min/Max zoom changed: We need to recalculate what tiles to load, if we have tiles + // loaded that are outside the new zoom range + // This is done automatically when we trigger the onSourceLoaded observer below. + + // Attribution changed: We need to notify the embedding application that this + // changed. See https://github.com/mapbox/mapbox-gl-native/issues/2723 + // This is not yet implemented. + + // Center/bounds changed: We're not using these values currently + } + + tileset = std::move(newTileset); + loaded = true; + observer->onSourceLoaded(*this); + } + }); +} + } // namespace style } // namespace mbgl diff --git a/src/mbgl/style/tile_source.hpp b/src/mbgl/style/tile_source.hpp index 8c69ad451f..dc48080ea0 100644 --- a/src/mbgl/style/tile_source.hpp +++ b/src/mbgl/style/tile_source.hpp @@ -16,6 +16,8 @@ public: std::string url, uint16_t tileSize, std::unique_ptr<Tileset>&&); + + void load(FileSource&) final; }; } // namespace style |