summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/mbgl/map/update.hpp1
-rw-r--r--src/mbgl/annotation/annotation_manager.cpp150
-rw-r--r--src/mbgl/annotation/annotation_manager.hpp27
-rw-r--r--src/mbgl/map/map.cpp12
-rw-r--r--src/mbgl/map/map_context.cpp19
-rw-r--r--src/mbgl/map/map_context.hpp3
-rw-r--r--src/mbgl/map/source.cpp18
-rw-r--r--src/mbgl/map/source.hpp1
-rw-r--r--src/mbgl/style/style.cpp40
-rw-r--r--src/mbgl/style/style.hpp6
-rw-r--r--src/mbgl/style/style_parser.cpp42
-rw-r--r--test/api/annotations.cpp96
-rw-r--r--test/style/resource_loading.cpp4
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_;