From fd58861fcd0d71534e4fed2eeada8802cd36fbd0 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Wed, 17 Jun 2015 14:08:40 -0700 Subject: [PATCH] Change StyleBucket::source to indirect reference This eliminates a reference loop: VectorTileData holds StyleLayers which hold StyleBuckets which held Sources which hold VectorTileDatas. This breaks the StyleBucket -> Source link in favor of manually resolving the reference where necessary. --- src/mbgl/map/map_context.cpp | 10 ++-------- src/mbgl/renderer/painter.cpp | 5 +++-- src/mbgl/style/style.cpp | 19 +++++++++++++++++-- src/mbgl/style/style.hpp | 2 ++ src/mbgl/style/style_bucket.hpp | 4 +--- src/mbgl/style/style_parser.cpp | 13 ++++++------- 6 files changed, 31 insertions(+), 22 deletions(-) diff --git a/src/mbgl/map/map_context.cpp b/src/mbgl/map/map_context.cpp index bd288a5cd..e9442ce8a 100644 --- a/src/mbgl/map/map_context.cpp +++ b/src/mbgl/map/map_context.cpp @@ -139,13 +139,7 @@ void MapContext::updateAnnotationTiles(const std::unordered_setsources.begin(), style->sources.end(), - [&shapeID](util::ptr source) { - return (source->info.source_id == shapeID); - }); - assert(source_it != style->sources.end()); - source_it->get()->enabled = true; + style->getSource(shapeID)->enabled = true; // create (if necessary) layers and buckets for each shape for (const auto &shapeAnnotationID : data.annotationManager.getOrderedShapeAnnotations()) { @@ -202,8 +196,8 @@ void MapContext::updateAnnotationTiles(const std::unordered_set shapeBucket = std::make_shared(shapeLayer->type); shapeBucket->name = shapeLayer->id; + shapeBucket->source = shapeID; shapeBucket->source_layer = shapeLayer->id; - shapeBucket->source = *source_it; // apply line layout properties to bucket if (shapeStyle.is()) { diff --git a/src/mbgl/renderer/painter.cpp b/src/mbgl/renderer/painter.cpp index 43d06b69d..70895cbf5 100644 --- a/src/mbgl/renderer/painter.cpp +++ b/src/mbgl/renderer/painter.cpp @@ -323,7 +323,8 @@ std::vector Painter::determineRenderOrder(const Style& style) { continue; } - if (!layer.bucket->source) { + util::ptr source = style.getSource(layer.bucket->source); + if (!source) { Log::Warning(Event::Render, "can't find source for layer '%s'", layer.id.c_str()); continue; } @@ -345,7 +346,7 @@ std::vector Painter::determineRenderOrder(const Style& style) { // Determine what render passes we need for this layer. const RenderPass passes = determineRenderPasses(layer); - const auto& tiles = layer.bucket->source->getTiles(); + const auto& tiles = source->getTiles(); for (auto tile : tiles) { assert(tile); if (!tile->data && !tile->data->isReady()) { diff --git a/src/mbgl/style/style.cpp b/src/mbgl/style/style.cpp index 30798e08e..0713bda0a 100644 --- a/src/mbgl/style/style.cpp +++ b/src/mbgl/style/style.cpp @@ -110,12 +110,27 @@ void Style::recalculate(float z, TimePoint now) { for (const auto& layer : layers) { layer->updateProperties(z, now, zoomHistory); - if (layer->bucket && layer->bucket->source) { - layer->bucket->source->enabled = true; + if (!layer->bucket) { + continue; } + + util::ptr source = getSource(layer->bucket->source); + if (!source) { + continue; + } + + source->enabled = true; } } +util::ptr Style::getSource(const std::string& id) const { + const auto it = std::find_if(sources.begin(), sources.end(), [&](util::ptr source) { + return source->info.source_id == id; + }); + + return it != sources.end() ? *it : nullptr; +} + void Style::setDefaultTransitionDuration(Duration duration) { defaultTransition.duration = duration; } diff --git a/src/mbgl/style/style.hpp b/src/mbgl/style/style.hpp index a22067cb1..7e83a3e70 100644 --- a/src/mbgl/style/style.hpp +++ b/src/mbgl/style/style.hpp @@ -63,6 +63,8 @@ public: return lastError; } + util::ptr getSource(const std::string& id) const; + std::unique_ptr glyphStore; std::unique_ptr glyphAtlas; util::ptr sprite; diff --git a/src/mbgl/style/style_bucket.hpp b/src/mbgl/style/style_bucket.hpp index e29000e5a..49b13e96f 100644 --- a/src/mbgl/style/style_bucket.hpp +++ b/src/mbgl/style/style_bucket.hpp @@ -10,8 +10,6 @@ namespace mbgl { -class Source; - class StyleBucket : public util::noncopyable { public: typedef util::ptr Ptr; @@ -20,7 +18,7 @@ public: const StyleLayerType type; std::string name; - util::ptr source; + std::string source; std::string source_layer; FilterExpression filter; ClassProperties layout; diff --git a/src/mbgl/style/style_parser.cpp b/src/mbgl/style/style_parser.cpp index c2aa115fa..a0410dc0a 100644 --- a/src/mbgl/style/style_parser.cpp +++ b/src/mbgl/style/style_parser.cpp @@ -57,6 +57,7 @@ void StyleParser::parse(JSVal document) { // create point annotations symbol bucket util::ptr pointBucket = std::make_shared(pointAnnotationsLayer->type); pointBucket->name = pointAnnotationsLayer->id; + pointBucket->source = pointID; pointBucket->source_layer = pointAnnotationsLayer->id; // build up point annotations style @@ -74,7 +75,6 @@ void StyleParser::parse(JSVal document) { sources.emplace_back(pointAnnotationsSource); pointAnnotationsSource->info.type = SourceType::Annotations; pointAnnotationsSource->info.source_id = pointID; - pointBucket->source = pointAnnotationsSource; pointAnnotationsLayer->bucket = pointBucket; } @@ -231,6 +231,7 @@ void StyleParser::parseSources(JSVal value) { parseRenderProperty(itr->value, source->info.type, "type"); parseRenderProperty(itr->value, source->info.url, "url"); parseRenderProperty(itr->value, source->info.tile_size, "tileSize"); + source->info.source_id = name; source->info.parseTileJSONProperties(itr->value); sources.emplace_back(source); sourcesMap.emplace(name, source); @@ -947,12 +948,10 @@ void StyleParser::parseBucket(JSVal value, util::ptr &layer) { if (value.HasMember("source")) { JSVal value_source = replaceConstant(value["source"]); if (value_source.IsString()) { - const std::string source_name = { value_source.GetString(), value_source.GetStringLength() }; - auto source_it = sourcesMap.find(source_name); - if (source_it != sourcesMap.end()) { - bucket->source = source_it->second; - } else { - Log::Warning(Event::ParseStyle, "can't find source '%s' required for layer '%s'", source_name.c_str(), layer->id.c_str()); + bucket->source = { value_source.GetString(), value_source.GetStringLength() }; + auto source_it = sourcesMap.find(bucket->source); + if (source_it == sourcesMap.end()) { + Log::Warning(Event::ParseStyle, "can't find source '%s' required for layer '%s'", bucket->source.c_str(), layer->id.c_str()); } } else { Log::Warning(Event::ParseStyle, "source of layer '%s' must be a string", layer->id.c_str());