From df20b0cbecb25b8bc6812c4a558fc0f0e6cfb7ed Mon Sep 17 00:00:00 2001 From: Asheem Mamoowala Date: Mon, 2 Oct 2017 13:42:26 -0700 Subject: [core] Add `cameraForLatLngs()` method with modified bearing --- src/mbgl/map/map.cpp | 45 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index 7534fe67ad..6eb555ad1e 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -364,27 +364,27 @@ void Map::setLatLngZoom(const LatLng& latLng, double zoom, const EdgeInsets& pad impl->onUpdate(); } -CameraOptions Map::cameraForLatLngBounds(const LatLngBounds& bounds, const EdgeInsets& padding) const { +CameraOptions Map::cameraForLatLngBounds(const LatLngBounds& bounds, const EdgeInsets& padding, optional bearing) const { return cameraForLatLngs({ bounds.northwest(), bounds.southwest(), bounds.southeast(), bounds.northeast(), - }, padding); + }, padding, bearing); } -CameraOptions Map::cameraForLatLngs(const std::vector& latLngs, const EdgeInsets& padding) const { +CameraOptions cameraForLatLngs(const std::vector& latLngs, const Transform& transform, const EdgeInsets& padding) { CameraOptions options; if (latLngs.empty()) { return options; } - + Size size = transform.getState().getSize(); // Calculate the bounds of the possibly rotated shape with respect to the viewport. ScreenCoordinate nePixel = {-INFINITY, -INFINITY}; ScreenCoordinate swPixel = {INFINITY, INFINITY}; - double viewportHeight = getSize().height; + double viewportHeight = size.height; for (LatLng latLng : latLngs) { - ScreenCoordinate pixel = impl->transform.latLngToScreenCoordinate(latLng); + ScreenCoordinate pixel = transform.latLngToScreenCoordinate(latLng); swPixel.x = std::min(swPixel.x, pixel.x); nePixel.x = std::max(nePixel.x, pixel.x); swPixel.y = std::min(swPixel.y, viewportHeight - pixel.y); @@ -396,14 +396,14 @@ CameraOptions Map::cameraForLatLngs(const std::vector& latLngs, const Ed // Calculate the zoom level. double minScale = INFINITY; if (width > 0 || height > 0) { - double scaleX = double(getSize().width) / width; - double scaleY = double(getSize().height) / height; + double scaleX = double(size.width) / width; + double scaleY = double(size.height) / height; scaleX -= (padding.left() + padding.right()) / width; scaleY -= (padding.top() + padding.bottom()) / height; minScale = util::min(scaleX, scaleY); } - double zoom = getZoom() + util::log2(minScale); - zoom = util::clamp(zoom, getMinZoom(), getMaxZoom()); + double zoom = transform.getZoom() + util::log2(minScale); + zoom = util::clamp(zoom, transform.getState().getMinZoom(), transform.getState().getMaxZoom()); // Calculate the center point of a virtual bounds that is extended in all directions by padding. ScreenCoordinate centerPixel = nePixel + swPixel; @@ -421,11 +421,34 @@ CameraOptions Map::cameraForLatLngs(const std::vector& latLngs, const Ed // CameraOptions origin is at the top-left corner. centerPixel.y = viewportHeight - centerPixel.y; - options.center = latLngForPixel(centerPixel); + options.center = transform.screenCoordinateToLatLng(centerPixel); options.zoom = zoom; return options; } +CameraOptions Map::cameraForLatLngs(const std::vector& latLngs, const EdgeInsets& padding, optional bearing) const { + if(bearing) { + double angle = -*bearing * util::DEG2RAD; // Convert to radians + Transform transform(impl->transform.getState()); + transform.setAngle(angle); + CameraOptions options = mbgl::cameraForLatLngs(latLngs, transform, padding); + options.angle = angle; + return options; + } else { + return mbgl::cameraForLatLngs(latLngs, impl->transform, padding); + } +} + +CameraOptions Map::cameraForGeometry(const Geometry& geometry, const EdgeInsets& padding, optional bearing) const { + + std::vector latLngs; + forEachPoint(geometry, [&](const Point& pt) { + latLngs.push_back({ pt.y, pt.x }); + }); + return cameraForLatLngs(latLngs, padding, bearing); + +} + LatLngBounds Map::latLngBoundsForCamera(const CameraOptions& camera) const { Transform shallow { impl->transform.getState() }; Size size = shallow.getState().getSize(); -- cgit v1.2.1 From 78ea88d757ecf3a0a75b786ae343d746617ba46b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20K=C3=A4fer?= Date: Mon, 9 Oct 2017 12:59:27 +0200 Subject: [core] make forcing cache/network only more explicit Previously, we used the existence of a `prior*` field in the Resource object as an indication for whether we should consult the cache or not. However, this is prone to error, since a failed cache lookup won't set any prior fields. Therefore, we manually set `priorExpires` to 0. This in turn triggered another bug where generated wrong expiration timestamps when the server response we got was expired (or expired between sending and receiving). This commit changes the flags so that we can now explicitly request CacheOnly/NetworkOnly (or All) loading methods, rather than the implicit Optional/Required naming scheme. --- src/mbgl/algorithm/update_renderables.hpp | 25 ++++++++----- src/mbgl/annotation/annotation_tile.cpp | 3 -- src/mbgl/annotation/annotation_tile.hpp | 2 -- src/mbgl/renderer/tile_pyramid.cpp | 4 +-- src/mbgl/storage/resource.cpp | 4 +-- src/mbgl/style/sources/image_source.cpp | 2 +- src/mbgl/tile/geojson_tile.cpp | 2 -- src/mbgl/tile/geojson_tile.hpp | 2 -- src/mbgl/tile/raster_tile.cpp | 8 ++--- src/mbgl/tile/raster_tile.hpp | 7 ++-- src/mbgl/tile/tile.cpp | 2 +- src/mbgl/tile/tile.hpp | 14 +++----- src/mbgl/tile/tile_loader.hpp | 12 +++---- src/mbgl/tile/tile_loader_impl.hpp | 58 +++++++++++++++++-------------- src/mbgl/tile/vector_tile.cpp | 8 ++--- src/mbgl/tile/vector_tile.hpp | 7 ++-- 16 files changed, 77 insertions(+), 83 deletions(-) (limited to 'src') diff --git a/src/mbgl/algorithm/update_renderables.hpp b/src/mbgl/algorithm/update_renderables.hpp index 0c2266ff47..c583b6b2b6 100644 --- a/src/mbgl/algorithm/update_renderables.hpp +++ b/src/mbgl/algorithm/update_renderables.hpp @@ -1,8 +1,8 @@ #pragma once #include +#include #include -#include #include @@ -40,15 +40,15 @@ void updateRenderables(GetTileFn getTile, // if (source has the tile and bucket is loaded) { if (tile->isRenderable()) { - retainTile(*tile, Resource::Necessity::Required); + retainTile(*tile, TileNecessity::Required); renderTile(idealRenderTileID, *tile); } else { // We are now attempting to load child and parent tiles. - bool parentHasTriedOptional = tile->hasTriedOptional(); + bool parentHasTriedOptional = tile->hasTriedCache(); bool parentIsLoaded = tile->isLoaded(); // The tile isn't loaded yet, but retain it anyway because it's an ideal tile. - retainTile(*tile, Resource::Necessity::Required); + retainTile(*tile, TileNecessity::Required); covered = true; overscaledZ = dataTileZoom + 1; if (overscaledZ > zoomRange.max) { @@ -56,7 +56,7 @@ void updateRenderables(GetTileFn getTile, const auto childDataTileID = idealDataTileID.scaledTo(overscaledZ); tile = getTile(childDataTileID); if (tile && tile->isRenderable()) { - retainTile(*tile, Resource::Necessity::Optional); + retainTile(*tile, TileNecessity::Optional); renderTile(idealRenderTileID, *tile); } else { covered = false; @@ -67,7 +67,7 @@ void updateRenderables(GetTileFn getTile, const OverscaledTileID childDataTileID(overscaledZ, idealRenderTileID.wrap, childTileID); tile = getTile(childDataTileID); if (tile && tile->isRenderable()) { - retainTile(*tile, Resource::Necessity::Optional); + retainTile(*tile, TileNecessity::Optional); renderTile(childDataTileID.toUnwrapped(), *tile); } else { // At least one child tile doesn't exist, so we are going to look for @@ -97,12 +97,19 @@ void updateRenderables(GetTileFn getTile, } if (tile) { - retainTile(*tile, parentIsLoaded ? Resource::Necessity::Required - : Resource::Necessity::Optional); + if (!parentIsLoaded) { + // We haven't completed loading the child, so we only do an optional + // (cache) request in an attempt to quickly load data that we can show. + retainTile(*tile, TileNecessity::Optional); + } else { + // Now that we've checked the child and know for sure that we can't load + // it, we attempt to load the parent from the network. + retainTile(*tile, TileNecessity::Required); + } // Save the current values, since they're the parent of the next iteration // of the parent tile ascent loop. - parentHasTriedOptional = tile->hasTriedOptional(); + parentHasTriedOptional = tile->hasTriedCache(); parentIsLoaded = tile->isLoaded(); if (tile->isRenderable()) { diff --git a/src/mbgl/annotation/annotation_tile.cpp b/src/mbgl/annotation/annotation_tile.cpp index 0596d60f4f..d405418a45 100644 --- a/src/mbgl/annotation/annotation_tile.cpp +++ b/src/mbgl/annotation/annotation_tile.cpp @@ -19,9 +19,6 @@ AnnotationTile::~AnnotationTile() { annotationManager.removeTile(*this); } -void AnnotationTile::setNecessity(Necessity) { -} - class AnnotationTileFeatureData { public: AnnotationTileFeatureData(const AnnotationID id_, diff --git a/src/mbgl/annotation/annotation_tile.hpp b/src/mbgl/annotation/annotation_tile.hpp index 88505c50e3..a4d1e66802 100644 --- a/src/mbgl/annotation/annotation_tile.hpp +++ b/src/mbgl/annotation/annotation_tile.hpp @@ -14,8 +14,6 @@ public: AnnotationTile(const OverscaledTileID&, const TileParameters&); ~AnnotationTile() override; - void setNecessity(Necessity) final; - private: AnnotationManager& annotationManager; }; diff --git a/src/mbgl/renderer/tile_pyramid.cpp b/src/mbgl/renderer/tile_pyramid.cpp index 6cd9bd9ebd..3e2311089d 100644 --- a/src/mbgl/renderer/tile_pyramid.cpp +++ b/src/mbgl/renderer/tile_pyramid.cpp @@ -121,7 +121,7 @@ void TilePyramid::update(const std::vector>& layer // we're actively using, e.g. as a replacement for tile that aren't loaded yet. std::set retain; - auto retainTileFn = [&](Tile& tile, Resource::Necessity necessity) -> void { + auto retainTileFn = [&](Tile& tile, TileNecessity necessity) -> void { if (retain.emplace(tile.id).second) { tile.setNecessity(necessity); } @@ -179,7 +179,7 @@ void TilePyramid::update(const std::vector>& layer while (tilesIt != tiles.end()) { if (retainIt == retain.end() || tilesIt->first < *retainIt) { if (!needsRelayout) { - tilesIt->second->setNecessity(Tile::Necessity::Optional); + tilesIt->second->setNecessity(TileNecessity::Optional); cache.add(tilesIt->first, std::move(tilesIt->second)); } tiles.erase(tilesIt++); diff --git a/src/mbgl/storage/resource.cpp b/src/mbgl/storage/resource.cpp index 94bba7f8bf..e75302b986 100644 --- a/src/mbgl/storage/resource.cpp +++ b/src/mbgl/storage/resource.cpp @@ -95,7 +95,7 @@ Resource Resource::tile(const std::string& urlTemplate, int32_t y, int8_t z, Tileset::Scheme scheme, - Necessity necessity) { + LoadingMethod loadingMethod) { bool supportsRatio = urlTemplate.find("{ratio}") != std::string::npos; if (scheme == Tileset::Scheme::TMS) { y = (1 << z) - y - 1; @@ -131,7 +131,7 @@ Resource Resource::tile(const std::string& urlTemplate, y, z }, - necessity + loadingMethod }; } diff --git a/src/mbgl/style/sources/image_source.cpp b/src/mbgl/style/sources/image_source.cpp index 9b60ba1a48..fa268da0ef 100644 --- a/src/mbgl/style/sources/image_source.cpp +++ b/src/mbgl/style/sources/image_source.cpp @@ -59,7 +59,7 @@ void ImageSource::loadDescription(FileSource& fileSource) { if (req || loaded) { return; } - const Resource imageResource { Resource::Image, *url, {}, Resource::Necessity::Required }; + const Resource imageResource { Resource::Image, *url, {} }; req = fileSource.request(imageResource, [this](Response res) { if (res.error) { diff --git a/src/mbgl/tile/geojson_tile.cpp b/src/mbgl/tile/geojson_tile.cpp index ee4989462c..d648d2e5ff 100644 --- a/src/mbgl/tile/geojson_tile.cpp +++ b/src/mbgl/tile/geojson_tile.cpp @@ -17,8 +17,6 @@ GeoJSONTile::GeoJSONTile(const OverscaledTileID& overscaledTileID, void GeoJSONTile::updateData(mapbox::geometry::feature_collection features) { setData(std::make_unique(std::move(features))); } - -void GeoJSONTile::setNecessity(Necessity) {} void GeoJSONTile::querySourceFeatures( std::vector& result, diff --git a/src/mbgl/tile/geojson_tile.hpp b/src/mbgl/tile/geojson_tile.hpp index d8a0a379d7..270406267c 100644 --- a/src/mbgl/tile/geojson_tile.hpp +++ b/src/mbgl/tile/geojson_tile.hpp @@ -15,8 +15,6 @@ public: mapbox::geometry::feature_collection); void updateData(mapbox::geometry::feature_collection); - - void setNecessity(Necessity) final; void querySourceFeatures( std::vector& result, diff --git a/src/mbgl/tile/raster_tile.cpp b/src/mbgl/tile/raster_tile.cpp index 2a3c9eeb0e..85fcea77b7 100644 --- a/src/mbgl/tile/raster_tile.cpp +++ b/src/mbgl/tile/raster_tile.cpp @@ -32,12 +32,12 @@ void RasterTile::setError(std::exception_ptr err) { observer->onTileError(*this, err); } -void RasterTile::setData(std::shared_ptr data, - optional modified_, - optional expires_) { +void RasterTile::setMetadata(optional modified_, optional expires_) { modified = modified_; expires = expires_; +} +void RasterTile::setData(std::shared_ptr data) { pending = true; ++correlationID; worker.invoke(&RasterTileWorker::parse, data, correlationID); @@ -77,7 +77,7 @@ void RasterTile::setMask(TileMask&& mask) { } } -void RasterTile::setNecessity(Necessity necessity) { +void RasterTile::setNecessity(TileNecessity necessity) { loader.setNecessity(necessity); } diff --git a/src/mbgl/tile/raster_tile.hpp b/src/mbgl/tile/raster_tile.hpp index 2cb64e8ed7..192769ed8f 100644 --- a/src/mbgl/tile/raster_tile.hpp +++ b/src/mbgl/tile/raster_tile.hpp @@ -22,12 +22,11 @@ public: const Tileset&); ~RasterTile() final; - void setNecessity(Necessity) final; + void setNecessity(TileNecessity) final; void setError(std::exception_ptr); - void setData(std::shared_ptr data, - optional modified_, - optional expires_); + void setMetadata(optional modified, optional expires); + void setData(std::shared_ptr data); void cancel() override; diff --git a/src/mbgl/tile/tile.cpp b/src/mbgl/tile/tile.cpp index 7d7eb0b3fc..f36a472e72 100644 --- a/src/mbgl/tile/tile.cpp +++ b/src/mbgl/tile/tile.cpp @@ -18,7 +18,7 @@ void Tile::setObserver(TileObserver* observer_) { observer = observer_; } -void Tile::setTriedOptional() { +void Tile::setTriedCache() { triedOptional = true; observer->onTileChanged(*this); } diff --git a/src/mbgl/tile/tile.hpp b/src/mbgl/tile/tile.hpp index 39cc0de8bd..8be7c4d862 100644 --- a/src/mbgl/tile/tile.hpp +++ b/src/mbgl/tile/tile.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -38,14 +39,7 @@ public: void setObserver(TileObserver* observer); - // Tiles can have two states: optional or required. - // - optional means that only low-cost actions should be taken to obtain the data - // (e.g. load from cache, but accept stale data) - // - required means that every effort should be taken to obtain the data (e.g. load - // from internet and keep the data fresh if it expires) - using Necessity = Resource::Necessity; - - virtual void setNecessity(Necessity) = 0; + virtual void setNecessity(TileNecessity) {} // Mark this tile as no longer needed and cancel any pending work. virtual void cancel() = 0; @@ -68,11 +62,11 @@ public: std::vector& result, const SourceQueryOptions&); - void setTriedOptional(); + void setTriedCache(); // Returns true when the tile source has received a first response, regardless of whether a load // error occurred or actual data was loaded. - bool hasTriedOptional() const { + bool hasTriedCache() const { return triedOptional; } diff --git a/src/mbgl/tile/tile_loader.hpp b/src/mbgl/tile/tile_loader.hpp index bc408ebaf6..92ca74330f 100644 --- a/src/mbgl/tile/tile_loader.hpp +++ b/src/mbgl/tile/tile_loader.hpp @@ -21,12 +21,10 @@ public: const Tileset&); ~TileLoader(); - using Necessity = Resource::Necessity; - - void setNecessity(Necessity newNecessity) { + void setNecessity(TileNecessity newNecessity) { if (newNecessity != necessity) { necessity = newNecessity; - if (necessity == Necessity::Required) { + if (necessity == TileNecessity::Required) { makeRequired(); } else { makeOptional(); @@ -45,12 +43,12 @@ private: // an up-to-date version or load new data void makeOptional(); - void loadOptional(); + void loadFromCache(); void loadedData(const Response&); - void loadRequired(); + void loadFromNetwork(); T& tile; - Necessity necessity; + TileNecessity necessity; Resource resource; FileSource& fileSource; std::unique_ptr request; diff --git a/src/mbgl/tile/tile_loader_impl.hpp b/src/mbgl/tile/tile_loader_impl.hpp index 598ec32c10..1b29638269 100644 --- a/src/mbgl/tile/tile_loader_impl.hpp +++ b/src/mbgl/tile/tile_loader_impl.hpp @@ -15,32 +15,31 @@ TileLoader::TileLoader(T& tile_, const TileParameters& parameters, const Tileset& tileset) : tile(tile_), - necessity(Necessity::Optional), + necessity(TileNecessity::Optional), resource(Resource::tile( tileset.tiles.at(0), parameters.pixelRatio, id.canonical.x, id.canonical.y, id.canonical.z, - tileset.scheme)), + tileset.scheme, + Resource::LoadingMethod::CacheOnly)), fileSource(parameters.fileSource) { assert(!request); - if (fileSource.supportsOptionalRequests()) { + if (fileSource.supportsCacheOnlyRequests()) { // When supported, the first request is always optional, even if the TileLoader // is marked as required. That way, we can let the first optional request continue // to load when the TileLoader is later changed from required to optional. If we // started out with a required request, we'd have to cancel everything, including the // initial optional part of the request. - loadOptional(); + loadFromCache(); + } else if (necessity == TileNecessity::Required) { + // When the file source doesn't support cache-only requests, and we definiitely need this + // data, we can start out with a network request immediately. + loadFromNetwork(); } else { - // When the FileSource doesn't support optional requests, we do nothing until the + // When the FileSource doesn't support cache-only requests, we do nothing until the // data is definitely required. - if (necessity == Necessity::Required) { - loadRequired(); - } else { - // We're using this field to check whether the pending request is optional or required. - resource.necessity = Resource::Optional; - } } } @@ -48,29 +47,31 @@ template TileLoader::~TileLoader() = default; template -void TileLoader::loadOptional() { +void TileLoader::loadFromCache() { assert(!request); - resource.necessity = Resource::Optional; + resource.loadingMethod = Resource::LoadingMethod::CacheOnly; request = fileSource.request(resource, [this](Response res) { request.reset(); - tile.setTriedOptional(); + tile.setTriedCache(); if (res.error && res.error->reason == Response::Error::Reason::NotFound) { - // When the optional request could not be satisfied, don't treat it as an error. - // Instead, we make sure that the next request knows that there has been an optional - // request before by setting one of the prior* fields. + // When the cache-only request could not be satisfied, don't treat it as an error. + // A cache lookup could still return data, _and_ an error, in particular when we were + // able to find the data, but it is expired and the Cache-Control headers indicated that + // we aren't allowed to use expired responses. In this case, we still get the data which + // we can use in our conditional network request. resource.priorModified = res.modified; - resource.priorExpires = Timestamp{ Seconds::zero() }; + resource.priorExpires = res.expires; resource.priorEtag = res.etag; resource.priorData = res.data; } else { loadedData(res); } - if (necessity == Necessity::Required) { - loadRequired(); + if (necessity == TileNecessity::Required) { + loadFromNetwork(); } }); } @@ -78,14 +79,15 @@ void TileLoader::loadOptional() { template void TileLoader::makeRequired() { if (!request) { - loadRequired(); + loadFromNetwork(); } } template void TileLoader::makeOptional() { - if (resource.necessity == Resource::Required && request) { - // Abort a potential HTTP request. + if (resource.loadingMethod == Resource::LoadingMethod::NetworkOnly && request) { + // Abort the current request, but only when we know that we're specifically querying for a + // network resource only. request.reset(); } } @@ -98,19 +100,23 @@ void TileLoader::loadedData(const Response& res) { resource.priorExpires = res.expires; // Do not notify the tile; when we get this message, it already has the current // version of the data. + tile.setMetadata(res.modified, res.expires); } else { resource.priorModified = res.modified; resource.priorExpires = res.expires; resource.priorEtag = res.etag; - tile.setData(res.noContent ? nullptr : res.data, res.modified, res.expires); + tile.setMetadata(res.modified, res.expires); + tile.setData(res.noContent ? nullptr : res.data); } } template -void TileLoader::loadRequired() { +void TileLoader::loadFromNetwork() { assert(!request); - resource.necessity = Resource::Required; + // Instead of using Resource::LoadingMethod::All, we're first doing a CacheOnly, and then a + // NetworkOnly request. + resource.loadingMethod = Resource::LoadingMethod::NetworkOnly; request = fileSource.request(resource, [this](Response res) { loadedData(res); }); } diff --git a/src/mbgl/tile/vector_tile.cpp b/src/mbgl/tile/vector_tile.cpp index e2e700b7b7..0756d3e526 100644 --- a/src/mbgl/tile/vector_tile.cpp +++ b/src/mbgl/tile/vector_tile.cpp @@ -12,16 +12,16 @@ VectorTile::VectorTile(const OverscaledTileID& id_, : GeometryTile(id_, sourceID_, parameters), loader(*this, id_, parameters, tileset) { } -void VectorTile::setNecessity(Necessity necessity) { +void VectorTile::setNecessity(TileNecessity necessity) { loader.setNecessity(necessity); } -void VectorTile::setData(std::shared_ptr data_, - optional modified_, - optional expires_) { +void VectorTile::setMetadata(optional modified_, optional expires_) { modified = modified_; expires = expires_; +} +void VectorTile::setData(std::shared_ptr data_) { GeometryTile::setData(data_ ? std::make_unique(data_) : nullptr); } diff --git a/src/mbgl/tile/vector_tile.hpp b/src/mbgl/tile/vector_tile.hpp index 566cde4f37..7dae414fef 100644 --- a/src/mbgl/tile/vector_tile.hpp +++ b/src/mbgl/tile/vector_tile.hpp @@ -15,10 +15,9 @@ public: const TileParameters&, const Tileset&); - void setNecessity(Necessity) final; - void setData(std::shared_ptr data, - optional modified, - optional expires); + void setNecessity(TileNecessity) final; + void setMetadata(optional modified, optional expires); + void setData(std::shared_ptr data); private: TileLoader loader; -- cgit v1.2.1 From d7d3d2c7311c5fed79537e39b8c3ea1f954b8ccf Mon Sep 17 00:00:00 2001 From: Asheem Mamoowala Date: Mon, 9 Oct 2017 16:26:22 -0700 Subject: [core] Fix out-of-bounds array access --- src/mbgl/util/i18n.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/mbgl/util/i18n.cpp b/src/mbgl/util/i18n.cpp index 16f1d669f3..3e3a68e248 100644 --- a/src/mbgl/util/i18n.cpp +++ b/src/mbgl/util/i18n.cpp @@ -554,7 +554,7 @@ std::u16string verticalizePunctuation(const std::u16string& input) { std::u16string output; for (size_t i = 0; i < input.size(); i++) { - char16_t nextCharCode = i < input.size() ? input[i + 1] : 0; + char16_t nextCharCode = i < input.size() - 1 ? input[i + 1] : 0; char16_t prevCharCode = i ? input[i - 1] : 0; bool canReplacePunctuation = -- cgit v1.2.1 From 0cd646180e787a59e600cb184b189a801e261c5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20K=C3=A4fer?= Date: Fri, 13 Oct 2017 17:53:30 -0700 Subject: [core] don't generate clip IDs for buckets/layers that don't need to be clipped --- src/mbgl/algorithm/generate_clip_ids_impl.hpp | 2 +- src/mbgl/renderer/render_tile.hpp | 1 + src/mbgl/renderer/renderer_impl.cpp | 7 +++++++ 3 files changed, 9 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/mbgl/algorithm/generate_clip_ids_impl.hpp b/src/mbgl/algorithm/generate_clip_ids_impl.hpp index db62214220..6a316dcdad 100644 --- a/src/mbgl/algorithm/generate_clip_ids_impl.hpp +++ b/src/mbgl/algorithm/generate_clip_ids_impl.hpp @@ -17,7 +17,7 @@ void ClipIDGenerator::update(std::vector> ren const auto end = renderables.end(); for (auto it = renderables.begin(); it != end; it++) { auto& renderable = it->get(); - if (!renderable.used) { + if (!renderable.used || !renderable.needsClipping) { continue; } diff --git a/src/mbgl/renderer/render_tile.hpp b/src/mbgl/renderer/render_tile.hpp index b498972f5c..3db02393d2 100644 --- a/src/mbgl/renderer/render_tile.hpp +++ b/src/mbgl/renderer/render_tile.hpp @@ -28,6 +28,7 @@ public: mat4 matrix; mat4 nearClippedMatrix; bool used = false; + bool needsClipping = false; mat4 translatedMatrix(const std::array& translate, style::TranslateAnchorType anchor, diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp index 1a828b80a3..6a8c18792e 100644 --- a/src/mbgl/renderer/renderer_impl.cpp +++ b/src/mbgl/renderer/renderer_impl.cpp @@ -370,6 +370,13 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) { if (bucket) { sortedTilesForInsertion.emplace_back(tile); tile.used = true; + + // We only need clipping when we're _not_ drawing a symbol layer. The only exception + // for symbol layers is when we're rendering still images. See render_symbol_layer.cpp + // for the exception we make there. + if (!symbolLayer || parameters.mapMode == MapMode::Still) { + tile.needsClipping = true; + } } } layer->setRenderTiles(std::move(sortedTilesForInsertion)); -- cgit v1.2.1 From 9c12a311f2ba2b26a44a6e13edd38bf8050e5d16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20K=C3=A4fer?= Date: Tue, 17 Oct 2017 14:00:52 -0700 Subject: [core] correctly alter sprite URLs when attaching sprite.png/sprite.json filenames --- src/mbgl/storage/resource.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/mbgl/storage/resource.cpp b/src/mbgl/storage/resource.cpp index e75302b986..207dd2ee69 100644 --- a/src/mbgl/storage/resource.cpp +++ b/src/mbgl/storage/resource.cpp @@ -61,17 +61,19 @@ Resource Resource::image(const std::string& url) { } Resource Resource::spriteImage(const std::string& base, float pixelRatio) { - return Resource { - Resource::Kind::SpriteImage, - base + (pixelRatio > 1 ? "@2x" : "") + ".png" - }; + util::URL url(base); + return Resource{ Resource::Kind::SpriteImage, + base.substr(0, url.path.first + url.path.second) + + (pixelRatio > 1 ? "@2x" : "") + ".png" + + base.substr(url.query.first, url.query.second) }; } Resource Resource::spriteJSON(const std::string& base, float pixelRatio) { - return Resource { - Resource::Kind::SpriteJSON, - base + (pixelRatio > 1 ? "@2x" : "") + ".json" - }; + util::URL url(base); + return Resource{ Resource::Kind::SpriteJSON, + base.substr(0, url.path.first + url.path.second) + + (pixelRatio > 1 ? "@2x" : "") + ".json" + + base.substr(url.query.first, url.query.second) }; } Resource Resource::glyphs(const std::string& urlTemplate, const FontStack& fontStack, const std::pair& glyphRange) { -- cgit v1.2.1 From b7b8baef9d30d31a757dbbc0fbb8cb2c5cf3585e Mon Sep 17 00:00:00 2001 From: Fabian Guerra Soto Date: Wed, 18 Oct 2017 15:18:54 -0400 Subject: [ios, macos] Add selection support to MGLMultiPoint annotations. (#9984) * [ios, macos] Add selection support to MGLMultiPoint annotations. * [ios, macos] Update changelogs. --- src/mbgl/annotation/annotation_manager.cpp | 1 + src/mbgl/annotation/annotation_manager.hpp | 1 + src/mbgl/annotation/shape_annotation_impl.cpp | 3 ++- src/mbgl/renderer/renderer.cpp | 15 +++++++++++++++ src/mbgl/renderer/renderer_impl.cpp | 19 +++++++++++++++++++ src/mbgl/renderer/renderer_impl.hpp | 3 +++ 6 files changed, 41 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/mbgl/annotation/annotation_manager.cpp b/src/mbgl/annotation/annotation_manager.cpp index 1f2d01e9eb..a4d53bbd3f 100644 --- a/src/mbgl/annotation/annotation_manager.cpp +++ b/src/mbgl/annotation/annotation_manager.cpp @@ -18,6 +18,7 @@ using namespace style; const std::string AnnotationManager::SourceID = "com.mapbox.annotations"; const std::string AnnotationManager::PointLayerID = "com.mapbox.annotations.points"; +const std::string AnnotationManager::ShapeLayerID = "com.mapbox.annotations.shape."; AnnotationManager::AnnotationManager(Style& style_) : style(style_) { diff --git a/src/mbgl/annotation/annotation_manager.hpp b/src/mbgl/annotation/annotation_manager.hpp index a028a8f1ba..22b25cd2ac 100644 --- a/src/mbgl/annotation/annotation_manager.hpp +++ b/src/mbgl/annotation/annotation_manager.hpp @@ -46,6 +46,7 @@ public: static const std::string SourceID; static const std::string PointLayerID; + static const std::string ShapeLayerID; private: void add(const AnnotationID&, const SymbolAnnotation&, const uint8_t); diff --git a/src/mbgl/annotation/shape_annotation_impl.cpp b/src/mbgl/annotation/shape_annotation_impl.cpp index 0c1a631ad8..9288159b6a 100644 --- a/src/mbgl/annotation/shape_annotation_impl.cpp +++ b/src/mbgl/annotation/shape_annotation_impl.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -15,7 +16,7 @@ namespace geojsonvt = mapbox::geojsonvt; ShapeAnnotationImpl::ShapeAnnotationImpl(const AnnotationID id_, const uint8_t maxZoom_) : id(id_), maxZoom(maxZoom_), - layerID("com.mapbox.annotations.shape." + util::toString(id)) { + layerID(AnnotationManager::ShapeLayerID + util::toString(id)) { } void ShapeAnnotationImpl::updateTileData(const CanonicalTileID& tileID, AnnotationTileData& data) { diff --git a/src/mbgl/renderer/renderer.cpp b/src/mbgl/renderer/renderer.cpp index e915f5e146..8953b419f7 100644 --- a/src/mbgl/renderer/renderer.cpp +++ b/src/mbgl/renderer/renderer.cpp @@ -57,6 +57,21 @@ AnnotationIDs Renderer::queryPointAnnotations(const ScreenBox& box) const { RenderedQueryOptions options; options.layerIDs = {{ AnnotationManager::PointLayerID }}; auto features = queryRenderedFeatures(box, options); + return getAnnotationIDs(features); +} + +AnnotationIDs Renderer::queryShapeAnnotations(const ScreenBox& box) const { + auto features = impl->queryShapeAnnotations({ + box.min, + {box.max.x, box.min.y}, + box.max, + {box.min.x, box.max.y}, + box.min + }); + return getAnnotationIDs(features); +} + +AnnotationIDs Renderer::getAnnotationIDs(const std::vector& features) const { std::set set; for (auto &feature : features) { assert(feature.id); diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp index 6a8c18792e..7339756e52 100644 --- a/src/mbgl/renderer/renderer_impl.cpp +++ b/src/mbgl/renderer/renderer_impl.cpp @@ -629,6 +629,10 @@ std::vector Renderer::Impl::queryRenderedFeatures(const ScreenLineStrin } } + return queryRenderedFeatures(geometry, options, layers); +} + +std::vector Renderer::Impl::queryRenderedFeatures(const ScreenLineString& geometry, const RenderedQueryOptions& options, const std::vector& layers) const { std::unordered_set sourceIDs; for (const RenderLayer* layer : layers) { sourceIDs.emplace(layer->baseImpl->source); @@ -663,6 +667,21 @@ std::vector Renderer::Impl::queryRenderedFeatures(const ScreenLineStrin return result; } +std::vector Renderer::Impl::queryShapeAnnotations(const ScreenLineString& geometry) const { + std::vector shapeAnnotationLayers; + RenderedQueryOptions options; + for (const auto& layerImpl : *layerImpls) { + if (std::mismatch(layerImpl->id.begin(), layerImpl->id.end(), + AnnotationManager::ShapeLayerID.begin(), AnnotationManager::ShapeLayerID.end()).second == AnnotationManager::ShapeLayerID.end()) { + if (const RenderLayer* layer = getRenderLayer(layerImpl->id)) { + shapeAnnotationLayers.emplace_back(layer); + } + } + } + + return queryRenderedFeatures(geometry, options, shapeAnnotationLayers); +} + std::vector Renderer::Impl::querySourceFeatures(const std::string& sourceID, const SourceQueryOptions& options) const { const RenderSource* source = getRenderSource(sourceID); if (!source) return {}; diff --git a/src/mbgl/renderer/renderer_impl.hpp b/src/mbgl/renderer/renderer_impl.hpp index 30e7f70722..db2a6e7a74 100644 --- a/src/mbgl/renderer/renderer_impl.hpp +++ b/src/mbgl/renderer/renderer_impl.hpp @@ -49,6 +49,7 @@ public: std::vector queryRenderedFeatures(const ScreenLineString&, const RenderedQueryOptions&) const; std::vector querySourceFeatures(const std::string& sourceID, const SourceQueryOptions&) const; + std::vector queryShapeAnnotations(const ScreenLineString&) const; void onLowMemory(); void dumDebugLogs(); @@ -61,6 +62,8 @@ private: RenderLayer* getRenderLayer(const std::string& id); const RenderLayer* getRenderLayer(const std::string& id) const; + + std::vector queryRenderedFeatures(const ScreenLineString&, const RenderedQueryOptions&, const std::vector&) const; // GlyphManagerObserver implementation. void onGlyphsError(const FontStack&, const GlyphRange&, std::exception_ptr) override; -- cgit v1.2.1 From 61ea2f43e4ea0233283f545982d5179b8397cde6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20K=C3=A4fer?= Date: Fri, 13 Oct 2017 16:41:23 -0700 Subject: [core] limit annotation tile source to z16 --- src/mbgl/annotation/render_annotation_source.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/mbgl/annotation/render_annotation_source.cpp b/src/mbgl/annotation/render_annotation_source.cpp index 34fb576727..ba80be0da0 100644 --- a/src/mbgl/annotation/render_annotation_source.cpp +++ b/src/mbgl/annotation/render_annotation_source.cpp @@ -38,7 +38,9 @@ void RenderAnnotationSource::update(Immutable baseImpl_, parameters, SourceType::Annotations, util::tileSize, - { 0, util::DEFAULT_MAX_ZOOM }, + // Zoom level 16 is typically sufficient for annotations. + // See https://github.com/mapbox/mapbox-gl-native/issues/10197 + { 0, 16 }, [&] (const OverscaledTileID& tileID) { return std::make_unique(tileID, parameters); }); -- cgit v1.2.1 From ba8342a12e332a9caf2a21bb022bbc9f2b2214b3 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Tue, 24 Oct 2017 11:46:45 -0700 Subject: [core] Add layer before notifying observer --- src/mbgl/style/style_impl.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/mbgl/style/style_impl.cpp b/src/mbgl/style/style_impl.cpp index 37907d3f60..3214c6316e 100644 --- a/src/mbgl/style/style_impl.cpp +++ b/src/mbgl/style/style_impl.cpp @@ -204,9 +204,10 @@ Layer* Style::Impl::addLayer(std::unique_ptr layer, optional } layer->setObserver(this); + Layer* result = layers.add(std::move(layer), before); observer->onUpdate(); - return layers.add(std::move(layer), before); + return result; } std::unique_ptr Style::Impl::removeLayer(const std::string& id) { -- cgit v1.2.1 From c9d7951e0d0ab85614ab296573e583ed44dbe7c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20K=C3=A4fer?= Date: Tue, 17 Oct 2017 09:10:50 -0700 Subject: [core] fix crash when querying GeoJSON tiles --- src/mbgl/tile/geojson_tile.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/mbgl/tile/geojson_tile.cpp b/src/mbgl/tile/geojson_tile.cpp index d648d2e5ff..bbec899950 100644 --- a/src/mbgl/tile/geojson_tile.cpp +++ b/src/mbgl/tile/geojson_tile.cpp @@ -23,19 +23,19 @@ void GeoJSONTile::querySourceFeatures( const SourceQueryOptions& options) { // Ignore the sourceLayer, there is only one - auto layer = getData()->getLayer({}); - - if (layer) { - auto featureCount = layer->featureCount(); - for (std::size_t i = 0; i < featureCount; i++) { - auto feature = layer->getFeature(i); - - // Apply filter, if any - if (options.filter && !(*options.filter)(*feature)) { - continue; + if (auto tileData = getData()) { + if (auto layer = tileData->getLayer({})) { + auto featureCount = layer->featureCount(); + for (std::size_t i = 0; i < featureCount; i++) { + auto feature = layer->getFeature(i); + + // Apply filter, if any + if (options.filter && !(*options.filter)(*feature)) { + continue; + } + + result.push_back(convertFeature(*feature, id.canonical)); } - - result.push_back(convertFeature(*feature, id.canonical)); } } } -- cgit v1.2.1 From bf9c1fb1b3f6121d4c939757ee043a70bef560e4 Mon Sep 17 00:00:00 2001 From: Ivo van Dongen Date: Fri, 20 Oct 2017 12:44:02 -0700 Subject: [core] blacklist VAO usage on adreno 3xx - Causes crashes on usage of glBuffer(Sub)Data --- src/mbgl/gl/context.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/mbgl/gl/context.cpp b/src/mbgl/gl/context.cpp index d0c538efb0..22b446e6d0 100644 --- a/src/mbgl/gl/context.cpp +++ b/src/mbgl/gl/context.cpp @@ -248,7 +248,14 @@ UniqueTexture Context::createTexture() { } bool Context::supportsVertexArrays() const { - return vertexArray && + static bool blacklisted = []() { + // Blacklist Adreno 3xx as it crashes on glBuffer(Sub)Data + const std::string renderer = reinterpret_cast(glGetString(GL_RENDERER)); + return renderer.find("Adreno (TM) 3") != std::string::npos; + }(); + + return !blacklisted && + vertexArray && vertexArray->genVertexArrays && vertexArray->bindVertexArray && vertexArray->deleteVertexArrays; -- cgit v1.2.1