diff options
-rw-r--r-- | include/mbgl/map/update.hpp | 1 | ||||
-rw-r--r-- | src/mbgl/annotation/annotation_manager.cpp | 150 | ||||
-rw-r--r-- | src/mbgl/annotation/annotation_manager.hpp | 27 | ||||
-rw-r--r-- | src/mbgl/map/map.cpp | 12 | ||||
-rw-r--r-- | src/mbgl/map/map_context.cpp | 19 | ||||
-rw-r--r-- | src/mbgl/map/map_context.hpp | 3 | ||||
-rw-r--r-- | src/mbgl/map/source.cpp | 18 | ||||
-rw-r--r-- | src/mbgl/map/source.hpp | 1 | ||||
-rw-r--r-- | src/mbgl/style/style.cpp | 40 | ||||
-rw-r--r-- | src/mbgl/style/style.hpp | 6 | ||||
-rw-r--r-- | src/mbgl/style/style_parser.cpp | 42 | ||||
-rw-r--r-- | test/api/annotations.cpp | 96 | ||||
-rw-r--r-- | test/style/resource_loading.cpp | 4 |
13 files changed, 197 insertions, 222 deletions
diff --git a/include/mbgl/map/update.hpp b/include/mbgl/map/update.hpp index fe9250efcf..83c2637559 100644 --- a/include/mbgl/map/update.hpp +++ b/include/mbgl/map/update.hpp @@ -13,6 +13,7 @@ enum class Update : uint32_t { Zoom = 1 << 4, RenderStill = 1 << 5, Repaint = 1 << 6, + Annotations = 1 << 7, }; inline Update operator| (const Update& lhs, const Update& rhs) { diff --git a/src/mbgl/annotation/annotation_manager.cpp b/src/mbgl/annotation/annotation_manager.cpp index 31b50b1c51..786ca42433 100644 --- a/src/mbgl/annotation/annotation_manager.cpp +++ b/src/mbgl/annotation/annotation_manager.cpp @@ -137,8 +137,13 @@ AnnotationManager::addShapeAnnotation(const ShapeAnnotation& shape, const uint8_ } uint32_t -AnnotationManager::addPointAnnotation(const PointAnnotation& point, const uint8_t maxZoom, - std::unordered_set<TileID, TileID::Hash>& affectedTiles) { +AnnotationManager::addPointAnnotation(const PointAnnotation& point, const uint8_t maxZoom) { + // We pre-generate tiles to contain each annotation up to the map's max zoom. + // We do this for fast rendering without projection conversions on the fly, as well as + // to simplify bounding box queries of annotations later. Tiles get invalidated when + // annotations are added or removed in order to refresh the map render without + // touching the base map underneath. + const uint32_t annotationID = nextID(); // at render time we style the point according to its {sprite} field @@ -178,7 +183,7 @@ AnnotationManager::addPointAnnotation(const PointAnnotation& point, const uint8_ // check for annotation layer & create if necessary util::ptr<LiveTileLayer> layer; - std::string layerID = PointLayerID; + std::string layerID = PointSourceID; if (tile_pos.second || tile_pos.first->second.second->getMutableLayer(layerID) == nullptr) { layer = std::make_shared<LiveTileLayer>(); @@ -198,7 +203,7 @@ AnnotationManager::addPointAnnotation(const PointAnnotation& point, const uint8_ annotation->tilePointFeatures.emplace(featureTileID, std::weak_ptr<const LiveTileFeature>(feature)); // track affected tile - affectedTiles.insert(featureTileID); + stalePointTileIDs.insert(featureTileID); } annotations.emplace(annotationID, std::move(annotation)); @@ -206,37 +211,22 @@ AnnotationManager::addPointAnnotation(const PointAnnotation& point, const uint8_ return annotationID; } -std::pair<AnnotationManager::AffectedTiles, AnnotationIDs> +AnnotationIDs AnnotationManager::addPointAnnotations(const std::vector<PointAnnotation>& points, const uint8_t maxZoom) { - // We pre-generate tiles to contain each annotation up to the map's max zoom. - // We do this for fast rendering without projection conversions on the fly, as well as - // to simplify bounding box queries of annotations later. Tiles get invalidated when - // annotations are added or removed in order to refresh the map render without - // touching the base map underneath. - AnnotationIDs annotationIDs; annotationIDs.reserve(points.size()); - AffectedTiles affectedTiles; - for (const auto& point : points) { - annotationIDs.push_back(addPointAnnotation(point, maxZoom, affectedTiles)); + annotationIDs.push_back(addPointAnnotation(point, maxZoom)); } - // Tile:IDs that need refreshed and the annotation identifiers held onto by the client. - return std::make_pair(affectedTiles, annotationIDs); + return annotationIDs; } -std::pair<AnnotationManager::AffectedTiles, AnnotationIDs> +AnnotationIDs AnnotationManager::addShapeAnnotations(const std::vector<ShapeAnnotation>& shapes, const uint8_t maxZoom) { - // We pre-generate tiles to contain each annotation up to the map's max zoom. - // We do this for fast rendering without projection conversions on the fly, as well as - // to simplify bounding box queries of annotations later. Tiles get invalidated when - // annotations are added or removed in order to refresh the map render without - // touching the base map underneath. - AnnotationIDs annotationIDs; annotationIDs.reserve(shapes.size()); @@ -244,16 +234,10 @@ AnnotationManager::addShapeAnnotations(const std::vector<ShapeAnnotation>& shape annotationIDs.push_back(addShapeAnnotation(shape, maxZoom)); } - // Tile:IDs that need refreshed and the annotation identifiers held onto by the client. - // Shapes are tiled "on-the-fly", so we don't get any "affected tiles" and just expire - // all annotation tiles for shape adds. - return std::make_pair(AffectedTiles(), annotationIDs); + return annotationIDs; } -std::unordered_set<TileID, TileID::Hash> AnnotationManager::removeAnnotations(const AnnotationIDs& ids, - const uint8_t maxZoom) { - std::unordered_set<TileID, TileID::Hash> affectedTiles; - +void AnnotationManager::removeAnnotations(const AnnotationIDs& ids, const uint8_t maxZoom) { std::vector<uint32_t> z2s; const uint8_t zoomCount = maxZoom + 1; z2s.reserve(zoomCount); @@ -287,17 +271,16 @@ std::unordered_set<TileID, TileID::Hash> AnnotationManager::removeAnnotations(co const auto& features_it = annotation->tilePointFeatures.find(tid); if (features_it != annotation->tilePointFeatures.end()) { // points share a layer; remove feature - auto layer = tiles[tid].second->getMutableLayer(PointLayerID); + auto layer = tiles[tid].second->getMutableLayer(PointSourceID); layer->removeFeature(features_it->second); - affectedTiles.insert(tid); + stalePointTileIDs.insert(tid); } } } else { // remove shape layer from tiles if relevant for (auto tile_it = tiles.begin(); tile_it != tiles.end(); ++tile_it) { if (tile_it->second.first.count(annotationID)) { - tile_it->second.second->removeLayer(ShapeLayerID + "." + util::toString(annotationID)); - affectedTiles.insert(tile_it->first); + tile_it->second.second->removeLayer(ShapeSourceID + "." + util::toString(annotationID)); } } @@ -312,9 +295,6 @@ std::unordered_set<TileID, TileID::Hash> AnnotationManager::removeAnnotations(co annotations.erase(annotationID); } } - - // TileIDs for tiles that need refreshed. - return affectedTiles; } AnnotationIDs AnnotationManager::getAnnotationsInBounds(const LatLngBounds& queryBounds, @@ -414,7 +394,7 @@ const LiveTile* AnnotationManager::getTile(const TileID& id) { // create shape tile layers from GeoJSONVT queries for (auto& tiler_it : shapeTilers) { const auto annotationID = tiler_it.first; - const std::string layerID = ShapeLayerID + "." + util::toString(annotationID); + const std::string layerID = ShapeSourceID + "." + util::toString(annotationID); // check for existing render layer auto renderLayer = renderTile->getMutableLayer(layerID); @@ -478,42 +458,48 @@ const LiveTile* AnnotationManager::getTile(const TileID& id) { return renderTile; } -void AnnotationManager::updateTilesIfNeeded(Style* style) { - if (!staleTiles.empty()) { - updateTiles(staleTiles, style); +void AnnotationManager::updateStyle(Style& style) { + // Create shape source + if (!style.getSource(ShapeSourceID)) { + std::unique_ptr<Source> shapeSource = std::make_unique<Source>(); + shapeSource->info.type = SourceType::Annotations; + shapeSource->info.source_id = ShapeSourceID; + shapeSource->enabled = true; + style.addSource(std::move(shapeSource)); } -} - -void AnnotationManager::updateTiles(const AffectedTiles& ids, Style* style) { - std::copy(ids.begin(), ids.end(), std::inserter(staleTiles, staleTiles.begin())); - - if (!style) { - return; - } - - // grab existing, single shape annotations source - const auto& shapeID = AnnotationManager::ShapeLayerID; - Source* shapeAnnotationSource = style->getSource(shapeID); - // Style not parsed yet - if (!shapeAnnotationSource) { - return; + // Create point source and singular layer and bucket + if (!style.getSource(PointSourceID)) { + std::unique_ptr<Source> pointSource = std::make_unique<Source>(); + pointSource->info.type = SourceType::Annotations; + pointSource->info.source_id = PointSourceID; + pointSource->enabled = true; + style.addSource(std::move(pointSource)); + + std::map<ClassID, ClassProperties> pointPaints; + pointPaints.emplace(ClassID::Default, ClassProperties()); + std::unique_ptr<StyleLayer> pointLayer = std::make_unique<StyleLayer>(PointSourceID, std::move(pointPaints)); + pointLayer->type = StyleLayerType::Symbol; + + util::ptr<StyleBucket> pointBucket = std::make_shared<StyleBucket>(pointLayer->type); + pointBucket->name = pointLayer->id; + pointBucket->source = PointSourceID; + pointBucket->source_layer = pointLayer->id; + pointBucket->layout.set(PropertyKey::IconImage, ConstantFunction<std::string>("{sprite}")); + pointBucket->layout.set(PropertyKey::IconAllowOverlap, ConstantFunction<bool>(true)); + + pointLayer->bucket = pointBucket; + style.addLayer(std::move(pointLayer)); } - shapeAnnotationSource->enabled = true; - - const auto& layers = style->layers; - - // create (if necessary) layers and buckets for each shape - for (const auto& shapeAnnotationID : orderedShapeAnnotations) { - const std::string shapeLayerID = shapeID + "." + util::toString(shapeAnnotationID); - - if (std::find_if(layers.begin(), layers.end(), [&](auto l) { return l->id == shapeLayerID; }) != layers.end()) { + // Create new shape layers and buckets + for (const auto& shapeID : orderedShapeAnnotations) { + const std::string shapeLayerID = ShapeSourceID + "." + util::toString(shapeID); + if (style.getLayer(shapeLayerID)) { continue; } - // apply shape paint properties - const StyleProperties& shapeStyle = annotations.at(shapeAnnotationID)->styleProperties; + const StyleProperties& shapeStyle = annotations.at(shapeID)->styleProperties; ClassProperties paintProperties; if (shapeStyle.is<LineProperties>()) { @@ -530,40 +516,28 @@ void AnnotationManager::updateTiles(const AffectedTiles& ids, Style* style) { std::map<ClassID, ClassProperties> shapePaints; shapePaints.emplace(ClassID::Default, std::move(paintProperties)); - - // create shape layer - util::ptr<StyleLayer> shapeLayer = std::make_shared<StyleLayer>(shapeLayerID, std::move(shapePaints)); + std::unique_ptr<StyleLayer> shapeLayer = std::make_unique<StyleLayer>(shapeLayerID, std::move(shapePaints)); shapeLayer->type = (shapeStyle.is<LineProperties>() ? StyleLayerType::Line : StyleLayerType::Fill); - // add to end of other shape layers just before (last) point layer - style->layers.emplace((style->layers.end() - 1), shapeLayer); - - // create shape bucket & connect to source util::ptr<StyleBucket> shapeBucket = std::make_shared<StyleBucket>(shapeLayer->type); shapeBucket->name = shapeLayer->id; - shapeBucket->source = shapeID; + shapeBucket->source = ShapeSourceID; shapeBucket->source_layer = shapeLayer->id; - - // apply line layout properties to bucket if (shapeStyle.is<LineProperties>()) { shapeBucket->layout.set(PropertyKey::LineJoin, ConstantFunction<JoinType>(JoinType::Round)); } - // connect layer to bucket shapeLayer->bucket = shapeBucket; + style.addLayer(std::move(shapeLayer), PointSourceID); } - // invalidate annotations layer tiles - for (const auto &source : style->sources) { - if (source->info.type == SourceType::Annotations) { - source->invalidateTiles(ids); - } - } + style.getSource(PointSourceID)->invalidateTiles(stalePointTileIDs); + style.getSource(ShapeSourceID)->invalidateTiles(); - staleTiles.clear(); + stalePointTileIDs.clear(); } -const std::string AnnotationManager::PointLayerID = "com.mapbox.annotations.points"; -const std::string AnnotationManager::ShapeLayerID = "com.mapbox.annotations.shape"; +const std::string AnnotationManager::PointSourceID = "com.mapbox.annotations.points"; +const std::string AnnotationManager::ShapeSourceID = "com.mapbox.annotations.shape"; } diff --git a/src/mbgl/annotation/annotation_manager.hpp b/src/mbgl/annotation/annotation_manager.hpp index cf8d8e3e77..248fb798d6 100644 --- a/src/mbgl/annotation/annotation_manager.hpp +++ b/src/mbgl/annotation/annotation_manager.hpp @@ -29,48 +29,37 @@ using GeoJSONVT = mapbox::util::geojsonvt::GeoJSONVT; class AnnotationManager : private util::noncopyable { public: - typedef std::unordered_set<TileID, TileID::Hash> AffectedTiles; - AnnotationManager(); ~AnnotationManager(); void setDefaultPointAnnotationSymbol(const std::string& symbol); - std::pair<AffectedTiles, AnnotationIDs> - addPointAnnotations(const std::vector<PointAnnotation>&, const uint8_t maxZoom); - - std::pair<AffectedTiles, AnnotationIDs> - addShapeAnnotations(const std::vector<ShapeAnnotation>&, const uint8_t maxZoom); - - AffectedTiles - removeAnnotations(const AnnotationIDs&, const uint8_t maxZoom); - - void updateTilesIfNeeded(Style*); - void updateTiles(const AffectedTiles&, Style*); + AnnotationIDs addPointAnnotations(const std::vector<PointAnnotation>&, const uint8_t maxZoom); + AnnotationIDs addShapeAnnotations(const std::vector<ShapeAnnotation>&, const uint8_t maxZoom); + void removeAnnotations(const AnnotationIDs&, const uint8_t maxZoom); AnnotationIDs getAnnotationsInBounds(const LatLngBounds&, const uint8_t maxZoom, const AnnotationType& = AnnotationType::Any) const; LatLngBounds getBoundsForAnnotations(const AnnotationIDs&) const; + void updateStyle(Style&); const LiveTile* getTile(const TileID& id); - static const std::string PointLayerID; - static const std::string ShapeLayerID; + static const std::string PointSourceID; + static const std::string ShapeSourceID; private: inline uint32_t nextID(); static vec2<double> projectPoint(const LatLng& point); uint32_t addShapeAnnotation(const ShapeAnnotation&, const uint8_t maxZoom); - uint32_t addPointAnnotation(const PointAnnotation&, const uint8_t maxZoom, AffectedTiles&); - - const StyleProperties getAnnotationStyleProperties(uint32_t) const; + uint32_t addPointAnnotation(const PointAnnotation&, const uint8_t maxZoom); std::string defaultPointAnnotationSymbol; std::unordered_map<uint32_t, std::unique_ptr<Annotation>> annotations; std::vector<uint32_t> orderedShapeAnnotations; std::unordered_map<TileID, std::pair<std::unordered_set<uint32_t>, std::unique_ptr<LiveTile>>, TileID::Hash> tiles; std::unordered_map<uint32_t, std::unique_ptr<GeoJSONVT>> shapeTilers; - std::unordered_set<TileID, TileID::Hash> staleTiles; + std::unordered_set<TileID, TileID::Hash> stalePointTileIDs; uint32_t nextID_ = 0; }; diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index 3e7a61a4e8..4ba8d6cd8f 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -348,8 +348,8 @@ uint32_t Map::addPointAnnotation(const PointAnnotation& annotation) { AnnotationIDs Map::addPointAnnotations(const std::vector<PointAnnotation>& annotations) { auto result = data->getAnnotationManager()->addPointAnnotations(annotations, getMaxZoom()); - context->invoke(&MapContext::updateAnnotationTiles, result.first); - return result.second; + update(Update::Annotations); + return result; } uint32_t Map::addShapeAnnotation(const ShapeAnnotation& annotation) { @@ -358,8 +358,8 @@ uint32_t Map::addShapeAnnotation(const ShapeAnnotation& annotation) { AnnotationIDs Map::addShapeAnnotations(const std::vector<ShapeAnnotation>& annotations) { auto result = data->getAnnotationManager()->addShapeAnnotations(annotations, getMaxZoom()); - context->invoke(&MapContext::updateAnnotationTiles, result.first); - return result.second; + update(Update::Annotations); + return result; } void Map::removeAnnotation(uint32_t annotation) { @@ -367,8 +367,8 @@ void Map::removeAnnotation(uint32_t annotation) { } void Map::removeAnnotations(const std::vector<uint32_t>& annotations) { - auto result = data->getAnnotationManager()->removeAnnotations(annotations, getMaxZoom()); - context->invoke(&MapContext::updateAnnotationTiles, result); + data->getAnnotationManager()->removeAnnotations(annotations, getMaxZoom()); + update(Update::Annotations); } std::vector<uint32_t> Map::getAnnotationsInBounds(const LatLngBounds& bounds, const AnnotationType& type) { diff --git a/src/mbgl/map/map_context.cpp b/src/mbgl/map/map_context.cpp index 1c0c98b599..c2b5900b16 100644 --- a/src/mbgl/map/map_context.cpp +++ b/src/mbgl/map/map_context.cpp @@ -137,13 +137,7 @@ void MapContext::loadStyleJSON(const std::string& json, const std::string& base) // force style cascade, causing all pending transitions to complete. style->cascade(); - updateFlags |= Update::DefaultTransition | Update::Classes | Update::Zoom; - asyncUpdate->send(); -} - -void MapContext::updateAnnotationTiles(const std::unordered_set<TileID, TileID::Hash>& ids) { - data.getAnnotationManager()->updateTiles(ids, style.get()); - updateFlags |= Update::Classes; + updateFlags |= Update::DefaultTransition | Update::Classes | Update::Zoom | Update::Annotations; asyncUpdate->send(); } @@ -160,6 +154,11 @@ void MapContext::update() { data.setAnimationTime(Clock::now()); + if (style->sprite && updateFlags & Update::Annotations) { + data.getAnnotationManager()->updateStyle(*style); + updateFlags |= Update::Classes; + } + if (updateFlags & Update::Classes) { style->cascade(); } @@ -313,10 +312,4 @@ void MapContext::onResourceLoadingFailed(std::exception_ptr error) { } } -void MapContext::onSpriteStoreLoaded() { - data.getAnnotationManager()->updateTilesIfNeeded(style.get()); - updateFlags |= Update::Classes; - asyncUpdate->send(); -} - } diff --git a/src/mbgl/map/map_context.hpp b/src/mbgl/map/map_context.hpp index f3ac636a40..b78d3283a7 100644 --- a/src/mbgl/map/map_context.hpp +++ b/src/mbgl/map/map_context.hpp @@ -54,7 +54,7 @@ public: bool isLoaded() const; double getTopOffsetPixelsForAnnotationSymbol(const std::string& symbol); - void updateAnnotationTiles(const std::unordered_set<TileID, TileID::Hash>&); + void updateAnnotations(); void setSourceTileCacheSize(size_t size); void onLowMemory(); @@ -66,7 +66,6 @@ public: // Style::Observer implementation. void onTileDataChanged() override; void onResourceLoadingFailed(std::exception_ptr error) override; - void onSpriteStoreLoaded() override; private: // Update the state indicated by the accumulated Update flags, then render. diff --git a/src/mbgl/map/source.cpp b/src/mbgl/map/source.cpp index 572973b79a..989d2eb75d 100644 --- a/src/mbgl/map/source.cpp +++ b/src/mbgl/map/source.cpp @@ -515,18 +515,20 @@ bool Source::update(MapData& data, void Source::invalidateTiles(const std::unordered_set<TileID, TileID::Hash>& ids) { cache.clear(); - if (!ids.empty()) { - for (auto& id : ids) { - tiles.erase(id); - tile_data.erase(id); - } - } else { - tiles.clear(); - tile_data.clear(); + for (const auto& id : ids) { + tiles.erase(id); + tile_data.erase(id); } updateTilePtrs(); } +void Source::invalidateTiles() { + cache.clear(); + tiles.clear(); + tile_data.clear(); + updateTilePtrs(); +} + void Source::updateTilePtrs() { tilePtrs.clear(); for (const auto& pair : tiles) { diff --git a/src/mbgl/map/source.hpp b/src/mbgl/map/source.hpp index 336caa5b93..421f819640 100644 --- a/src/mbgl/map/source.hpp +++ b/src/mbgl/map/source.hpp @@ -78,6 +78,7 @@ public: bool shouldReparsePartialTiles); void invalidateTiles(const std::unordered_set<TileID, TileID::Hash>&); + void invalidateTiles(); void updateMatrices(const mat4 &projMatrix, const TransformState &transform); void drawClippingMasks(Painter &painter); diff --git a/src/mbgl/style/style.cpp b/src/mbgl/style/style.cpp index d4c9bd4e56..7945a45b1d 100644 --- a/src/mbgl/style/style.cpp +++ b/src/mbgl/style/style.cpp @@ -44,18 +44,18 @@ void Style::setJSON(const std::string& json, const std::string&) { StyleParser parser(data); parser.parse(doc); - sources = parser.getSources(); - layers = parser.getLayers(); + for (auto& source : parser.getSources()) { + addSource(std::move(source)); + } + + for (auto& layer : parser.getLayers()) { + addLayer(std::move(layer)); + } sprite = std::make_unique<Sprite>(parser.getSprite(), data.pixelRatio); sprite->setObserver(this); glyphStore->setURL(parser.getGlyphURL()); - - for (const auto& source : sources) { - source->setObserver(this); - source->load(); - } } Style::~Style() { @@ -70,6 +70,20 @@ Style::~Style() { } } +void Style::addSource(std::unique_ptr<Source> source) { + source->setObserver(this); + source->load(); + sources.emplace_back(std::move(source)); +} + +void Style::addLayer(util::ptr<StyleLayer> layer) { + layers.emplace_back(std::move(layer)); +} + +void Style::addLayer(util::ptr<StyleLayer> layer, const std::string& before) { + layers.emplace(std::find_if(layers.begin(), layers.end(), [&](const auto& l) { return l->id == before; }), std::move(layer)); +} + void Style::update(const TransformState& transform, TexturePool& texturePool) { bool allTilesUpdated = true; @@ -126,6 +140,14 @@ Source* Style::getSource(const std::string& id) const { return it != sources.end() ? it->get() : nullptr; } +StyleLayer* Style::getLayer(const std::string& id) const { + const auto it = std::find_if(layers.begin(), layers.end(), [&](const auto& layer) { + return layer->id == id; + }); + + return it != layers.end() ? it->get() : nullptr; +} + bool Style::hasTransitions() const { for (const auto& layer : layers) { if (layer->hasTransitions()) { @@ -190,10 +212,6 @@ void Style::onSpriteLoaded(const Sprites& sprites) { // Add all sprite images to the SpriteStore object spriteStore->setSprites(sprites); - if (observer) { - observer->onSpriteStoreLoaded(); - } - shouldReparsePartialTiles = true; emitTileDataChanged(); } diff --git a/src/mbgl/style/style.hpp b/src/mbgl/style/style.hpp index 3f9696ffbf..9c5091863e 100644 --- a/src/mbgl/style/style.hpp +++ b/src/mbgl/style/style.hpp @@ -39,7 +39,6 @@ public: virtual ~Observer() = default; virtual void onTileDataChanged() = 0; - virtual void onSpriteStoreLoaded() = 0; virtual void onResourceLoadingFailed(std::exception_ptr error) = 0; }; @@ -63,6 +62,11 @@ public: } Source* getSource(const std::string& id) const; + StyleLayer* getLayer(const std::string& id) const; + + void addSource(std::unique_ptr<Source>); + void addLayer(util::ptr<StyleLayer>); + void addLayer(util::ptr<StyleLayer>, const std::string& beforeLayerID); MapData& data; std::unique_ptr<GlyphStore> glyphStore; diff --git a/src/mbgl/style/style_parser.cpp b/src/mbgl/style/style_parser.cpp index 2e298e9a6c..04c3a45553 100644 --- a/src/mbgl/style/style_parser.cpp +++ b/src/mbgl/style/style_parser.cpp @@ -1,7 +1,6 @@ #include <mbgl/style/style_parser.hpp> #include <mbgl/map/source.hpp> #include <mbgl/style/style_layer.hpp> -#include <mbgl/annotation/annotation_manager.hpp> #include <mbgl/map/map_data.hpp> #include <mbgl/util/constants.hpp> #include <mbgl/util/vec.hpp> @@ -40,47 +39,6 @@ void StyleParser::parse(JSVal document) { if (document.HasMember("layers")) { parseLayers(document["layers"]); - - // create shape annotations source - const std::string& shapeID = AnnotationManager::ShapeLayerID; - - std::unique_ptr<Source> shapeAnnotationsSource = std::make_unique<Source>(); - shapeAnnotationsSource->info.type = SourceType::Annotations; - shapeAnnotationsSource->info.source_id = shapeID; - sourcesMap.emplace(shapeID, shapeAnnotationsSource.get()); - sources.emplace_back(std::move(shapeAnnotationsSource)); - - // create point annotations layer - const std::string& pointID = AnnotationManager::PointLayerID; - - std::map<ClassID, ClassProperties> pointPaints; - util::ptr<StyleLayer> pointAnnotationsLayer = std::make_shared<StyleLayer>(pointID, std::move(pointPaints)); - pointAnnotationsLayer->type = StyleLayerType::Symbol; - layersMap.emplace(pointID, std::pair<JSVal, util::ptr<StyleLayer>> { JSVal(pointID), pointAnnotationsLayer }); - layers.emplace_back(pointAnnotationsLayer); - - // create point annotations symbol bucket - util::ptr<StyleBucket> pointBucket = std::make_shared<StyleBucket>(pointAnnotationsLayer->type); - pointBucket->name = pointAnnotationsLayer->id; - pointBucket->source = pointID; - pointBucket->source_layer = pointAnnotationsLayer->id; - - // build up point annotations style - rapidjson::Document d; - rapidjson::Value iconImage(rapidjson::kObjectType); - iconImage.AddMember("icon-image", "{sprite}", d.GetAllocator()); - parseLayout(iconImage, pointBucket); - rapidjson::Value iconOverlap(rapidjson::kObjectType); - iconOverlap.AddMember("icon-allow-overlap", true, d.GetAllocator()); - parseLayout(iconOverlap, pointBucket); - - // create point annotations source & connect to bucket & layer - std::unique_ptr<Source> pointAnnotationsSource = std::make_unique<Source>(); - pointAnnotationsSource->info.type = SourceType::Annotations; - pointAnnotationsSource->info.source_id = pointID; - pointAnnotationsLayer->bucket = pointBucket; - sourcesMap.emplace(pointID, pointAnnotationsSource.get()); - sources.emplace_back(std::move(pointAnnotationsSource)); } if (document.HasMember("sprite")) { diff --git a/test/api/annotations.cpp b/test/api/annotations.cpp index a9ebb4ab01..a00a449a6d 100644 --- a/test/api/annotations.cpp +++ b/test/api/annotations.cpp @@ -14,9 +14,19 @@ #include <future> #include <vector> -TEST(Annotations, PointAnnotation) { - using namespace mbgl; +using namespace mbgl; + +std::string renderPNG(Map& map) { + std::promise<std::unique_ptr<const StillImage>> promise; + map.renderStill([&](std::exception_ptr, std::unique_ptr<const StillImage> image) { + promise.set_value(std::move(image)); + }); + auto result = promise.get_future().get(); + return util::compress_png(result->width, result->height, result->pixels.get()); +} + +TEST(Annotations, PointAnnotation) { auto display = std::make_shared<mbgl::HeadlessDisplay>(); HeadlessView view(display, 1); DefaultFileSource fileSource(nullptr); @@ -25,19 +35,10 @@ TEST(Annotations, PointAnnotation) { map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"), ""); map.addPointAnnotation(PointAnnotation({ 0, 0 }, "default_marker")); - std::promise<std::unique_ptr<const StillImage>> promise; - map.renderStill([&promise](std::exception_ptr, std::unique_ptr<const StillImage> image) { - promise.set_value(std::move(image)); - }); - - auto result = promise.get_future().get(); - const std::string png = util::compress_png(result->width, result->height, result->pixels.get()); - util::write_file("test/output/point_annotation.png", png); + util::write_file("test/output/point_annotation.png", renderPNG(map)); } TEST(Annotations, LineAnnotation) { - using namespace mbgl; - auto display = std::make_shared<mbgl::HeadlessDisplay>(); HeadlessView view(display, 1); DefaultFileSource fileSource(nullptr); @@ -56,25 +57,55 @@ TEST(Annotations, LineAnnotation) { map.addShapeAnnotation(ShapeAnnotation(segments, styleProperties)); - std::promise<std::unique_ptr<const StillImage>> promise; - map.renderStill([&promise](std::exception_ptr, std::unique_ptr<const StillImage> image) { - promise.set_value(std::move(image)); - }); - - auto result = promise.get_future().get(); - const std::string png = util::compress_png(result->width, result->height, result->pixels.get()); - util::write_file("test/output/line_annotation.png", png); + util::write_file("test/output/line_annotation.png", renderPNG(map)); } TEST(Annotations, FillAnnotation) { - using namespace mbgl; + auto display = std::make_shared<mbgl::HeadlessDisplay>(); + HeadlessView view(display, 1); + DefaultFileSource fileSource(nullptr); + + Map map(view, fileSource, MapMode::Still); + map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"), ""); + + AnnotationSegments segments = {{ {{ { 0, 0 }, { 0, 45 }, { 45, 45 }, { 45, 0 } }} }}; + + FillProperties fillProperties; + fillProperties.fill_color = {{ 255, 0, 0, 1 }}; + + StyleProperties styleProperties; + styleProperties.set<FillProperties>(fillProperties); + + map.addShapeAnnotation(ShapeAnnotation(segments, styleProperties)); + + util::write_file("test/output/fill_annotation.png", renderPNG(map)); +} +TEST(Annotations, AddMultiple) { auto display = std::make_shared<mbgl::HeadlessDisplay>(); HeadlessView view(display, 1); DefaultFileSource fileSource(nullptr); Map map(view, fileSource, MapMode::Still); map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"), ""); + map.addPointAnnotation(PointAnnotation({ 0, -20 }, "default_marker")); + + renderPNG(map); + + map.addPointAnnotation(PointAnnotation({ 0, 20 }, "default_marker")); + + util::write_file("test/output/add_multiple.png", renderPNG(map)); +} + +TEST(Annotations, NonImmediateAdd) { + auto display = std::make_shared<mbgl::HeadlessDisplay>(); + HeadlessView view(display, 1); + DefaultFileSource fileSource(nullptr); + + Map map(view, fileSource, MapMode::Still); + map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"), ""); + + renderPNG(map); AnnotationSegments segments = {{ {{ { 0, 0 }, { 0, 45 }, { 45, 45 }, { 45, 0 } }} }}; @@ -86,12 +117,21 @@ TEST(Annotations, FillAnnotation) { map.addShapeAnnotation(ShapeAnnotation(segments, styleProperties)); - std::promise<std::unique_ptr<const StillImage>> promise; - map.renderStill([&promise](std::exception_ptr, std::unique_ptr<const StillImage> image) { - promise.set_value(std::move(image)); - }); + util::write_file("test/output/non_immediate_add.png", renderPNG(map)); +} - auto result = promise.get_future().get(); - const std::string png = util::compress_png(result->width, result->height, result->pixels.get()); - util::write_file("test/output/fill_annotation.png", png); +TEST(Annotations, SwitchStyle) { + auto display = std::make_shared<mbgl::HeadlessDisplay>(); + HeadlessView view(display, 1); + DefaultFileSource fileSource(nullptr); + + Map map(view, fileSource, MapMode::Still); + map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"), ""); + map.addPointAnnotation(PointAnnotation({ 0, 0 }, "default_marker")); + + renderPNG(map); + + map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"), ""); + + util::write_file("test/output/switch_style.png", renderPNG(map)); } diff --git a/test/style/resource_loading.cpp b/test/style/resource_loading.cpp index 5ed09065a1..0562434586 100644 --- a/test/style/resource_loading.cpp +++ b/test/style/resource_loading.cpp @@ -63,10 +63,6 @@ public: callback_(error); } - void onSpriteStoreLoaded() override { - // no-op - } - private: MapData data_; Transform transform_; |