diff options
author | John Firebaugh <john.firebaugh@gmail.com> | 2015-06-04 19:32:07 -0700 |
---|---|---|
committer | John Firebaugh <john.firebaugh@gmail.com> | 2015-07-01 15:21:09 -0700 |
commit | 4676553a3e31bef3094e8be5d6f9dce2809ef5ae (patch) | |
tree | 2ef00b7c7db4a6a83fb02569a0e7a857b82694c7 /src | |
parent | 875ef979be0140332ab219e422022ccb38b99a1e (diff) | |
download | qtlocation-mapboxgl-4676553a3e31bef3094e8be5d6f9dce2809ef5ae.tar.gz |
Merge TileParser into TileWorker
Diffstat (limited to 'src')
-rw-r--r-- | src/mbgl/map/tile_parser.cpp | 235 | ||||
-rw-r--r-- | src/mbgl/map/tile_parser.hpp | 62 | ||||
-rw-r--r-- | src/mbgl/map/tile_worker.cpp | 218 | ||||
-rw-r--r-- | src/mbgl/map/tile_worker.hpp | 24 |
4 files changed, 232 insertions, 307 deletions
diff --git a/src/mbgl/map/tile_parser.cpp b/src/mbgl/map/tile_parser.cpp deleted file mode 100644 index a88084391f..0000000000 --- a/src/mbgl/map/tile_parser.cpp +++ /dev/null @@ -1,235 +0,0 @@ -#include <mbgl/map/tile_parser.hpp> -#include <mbgl/map/vector_tile_data.hpp> -#include <mbgl/platform/log.hpp> -#include <mbgl/style/style_layer.hpp> -#include <mbgl/map/source.hpp> -#include <mbgl/map/sprite.hpp> -#include <mbgl/renderer/fill_bucket.hpp> -#include <mbgl/renderer/line_bucket.hpp> -#include <mbgl/renderer/symbol_bucket.hpp> -#include <mbgl/util/constants.hpp> -#include <mbgl/style/style.hpp> - -#include <locale> - -namespace mbgl { - -// Note: This destructor is seemingly empty, but we need to declare it anyway -// because this object has a std::unique_ptr<> of a forward-declare type in -// its header file. -TileParser::~TileParser() = default; - -TileParser::TileParser(const GeometryTile& geometryTile_, - TileWorker& tile_, - Style& style_) - : geometryTile(geometryTile_), - tile(tile_), - style(style_), - partialParse(false) { - assert(style.sprite); -} - -bool TileParser::obsolete() const { - return tile.getState() == TileData::State::obsolete; -} - -void TileParser::parse() { - for (const auto& layer_desc : style.layers) { - // Cancel early when parsing. - if (obsolete()) { - return; - } - - if (layer_desc->isBackground()) { - // background is a special, fake bucket - continue; - } - - if (layer_desc->bucket) { - // This is a singular layer. Check if this bucket already exists. If not, - // parse this bucket. - if (tile.getBucket(*layer_desc)) { - continue; - } - - std::unique_ptr<Bucket> bucket = createBucket(*layer_desc->bucket); - if (bucket) { - // Bucket creation might fail because the data tile may not - // contain any data that falls into this bucket. - tile.setBucket(*layer_desc, std::move(bucket)); - } - } else { - Log::Warning(Event::ParseTile, "layer '%s' does not have buckets", layer_desc->id.c_str()); - } - } -} - -template <typename T> -struct PropertyEvaluator { - typedef T result_type; - PropertyEvaluator(float z_) : z(z_) {} - - template <typename P, typename std::enable_if<std::is_convertible<P, T>::value, int>::type = 0> - T operator()(const P &value) const { - return value; - } - - T operator()(const Function<T> &value) const { - return mapbox::util::apply_visitor(FunctionEvaluator<T>(z), value); - } - - template <typename P, typename std::enable_if<!std::is_convertible<P, T>::value, int>::type = 0> - T operator()(const P &) const { - return T(); - } - -private: - const float z; -}; - -template <typename T> -void applyLayoutProperty(PropertyKey key, const ClassProperties &classProperties, T &target, const float z) { - auto it = classProperties.properties.find(key); - if (it != classProperties.properties.end()) { - const PropertyEvaluator<T> evaluator(z); - target = mapbox::util::apply_visitor(evaluator, it->second); - } -} - -std::unique_ptr<Bucket> TileParser::createBucket(const StyleBucket &bucketDesc) { - // Skip this bucket if we are to not render this - if (tile.id.z < std::floor(bucketDesc.min_zoom) && std::floor(bucketDesc.min_zoom) < tile.maxZoom) return nullptr; - if (tile.id.z >= std::ceil(bucketDesc.max_zoom)) return nullptr; - if (bucketDesc.visibility == mbgl::VisibilityType::None) return nullptr; - - auto layer = geometryTile.getLayer(bucketDesc.source_layer); - if (layer) { - if (bucketDesc.type == StyleLayerType::Fill) { - return createFillBucket(*layer, bucketDesc); - } else if (bucketDesc.type == StyleLayerType::Line) { - return createLineBucket(*layer, bucketDesc); - } else if (bucketDesc.type == StyleLayerType::Symbol) { - return createSymbolBucket(*layer, bucketDesc); - } else if (bucketDesc.type == StyleLayerType::Raster) { - return nullptr; - } else { - Log::Warning(Event::ParseTile, "unknown bucket render type for layer '%s' (source layer '%s')", - bucketDesc.name.c_str(), bucketDesc.source_layer.c_str()); - } - } else { - // The layer specified in the bucket does not exist. Do nothing. - if (debug::tileParseWarnings) { - Log::Warning(Event::ParseTile, "layer '%s' does not exist in tile %d/%d/%d", - bucketDesc.source_layer.c_str(), tile.id.z, tile.id.x, tile.id.y); - } - } - - return nullptr; -} - -template <class Bucket> -void TileParser::addBucketGeometries(Bucket& bucket, const GeometryTileLayer& layer, const FilterExpression &filter) { - for (std::size_t i = 0; i < layer.featureCount(); i++) { - auto feature = layer.getFeature(i); - - if (obsolete()) - return; - - GeometryTileFeatureExtractor extractor(*feature); - if (!evaluate(filter, extractor)) - continue; - - bucket->addGeometry(feature->getGeometries()); - } -} - -std::unique_ptr<Bucket> TileParser::createFillBucket(const GeometryTileLayer& layer, - const StyleBucket& bucket_desc) { - auto bucket = std::make_unique<FillBucket>(tile.fillVertexBuffer, - tile.triangleElementsBuffer, - tile.lineElementsBuffer); - addBucketGeometries(bucket, layer, bucket_desc.filter); - return bucket->hasData() ? std::move(bucket) : nullptr; -} - -std::unique_ptr<Bucket> TileParser::createLineBucket(const GeometryTileLayer& layer, - const StyleBucket& bucket_desc) { - auto bucket = std::make_unique<LineBucket>(tile.lineVertexBuffer, - tile.triangleElementsBuffer); - - const float z = tile.id.z; - auto& layout = bucket->layout; - - applyLayoutProperty(PropertyKey::LineCap, bucket_desc.layout, layout.cap, z); - applyLayoutProperty(PropertyKey::LineJoin, bucket_desc.layout, layout.join, z); - applyLayoutProperty(PropertyKey::LineMiterLimit, bucket_desc.layout, layout.miter_limit, z); - applyLayoutProperty(PropertyKey::LineRoundLimit, bucket_desc.layout, layout.round_limit, z); - - addBucketGeometries(bucket, layer, bucket_desc.filter); - return bucket->hasData() ? std::move(bucket) : nullptr; -} - -std::unique_ptr<Bucket> TileParser::createSymbolBucket(const GeometryTileLayer& layer, - const StyleBucket& bucket_desc) { - auto bucket = std::make_unique<SymbolBucket>(*tile.getCollision(), tile.id.overscaling); - - const float z = tile.id.z; - auto& layout = bucket->layout; - - applyLayoutProperty(PropertyKey::SymbolPlacement, bucket_desc.layout, layout.placement, z); - if (layout.placement == PlacementType::Line) { - layout.icon.rotation_alignment = RotationAlignmentType::Map; - layout.text.rotation_alignment = RotationAlignmentType::Map; - }; - applyLayoutProperty(PropertyKey::SymbolMinDistance, bucket_desc.layout, layout.min_distance, z); - applyLayoutProperty(PropertyKey::SymbolAvoidEdges, bucket_desc.layout, layout.avoid_edges, z); - - applyLayoutProperty(PropertyKey::IconAllowOverlap, bucket_desc.layout, layout.icon.allow_overlap, z); - applyLayoutProperty(PropertyKey::IconIgnorePlacement, bucket_desc.layout, layout.icon.ignore_placement, z); - applyLayoutProperty(PropertyKey::IconOptional, bucket_desc.layout, layout.icon.optional, z); - applyLayoutProperty(PropertyKey::IconRotationAlignment, bucket_desc.layout, layout.icon.rotation_alignment, z); - applyLayoutProperty(PropertyKey::IconMaxSize, bucket_desc.layout, layout.icon.max_size, z); - applyLayoutProperty(PropertyKey::IconImage, bucket_desc.layout, layout.icon.image, z); - applyLayoutProperty(PropertyKey::IconPadding, bucket_desc.layout, layout.icon.padding, z); - applyLayoutProperty(PropertyKey::IconRotate, bucket_desc.layout, layout.icon.rotate, z); - applyLayoutProperty(PropertyKey::IconKeepUpright, bucket_desc.layout, layout.icon.keep_upright, z); - applyLayoutProperty(PropertyKey::IconOffset, bucket_desc.layout, layout.icon.offset, z); - - applyLayoutProperty(PropertyKey::TextRotationAlignment, bucket_desc.layout, layout.text.rotation_alignment, z); - applyLayoutProperty(PropertyKey::TextField, bucket_desc.layout, layout.text.field, z); - applyLayoutProperty(PropertyKey::TextFont, bucket_desc.layout, layout.text.font, z); - applyLayoutProperty(PropertyKey::TextMaxSize, bucket_desc.layout, layout.text.max_size, z); - applyLayoutProperty(PropertyKey::TextMaxWidth, bucket_desc.layout, layout.text.max_width, z); - applyLayoutProperty(PropertyKey::TextLineHeight, bucket_desc.layout, layout.text.line_height, z); - applyLayoutProperty(PropertyKey::TextLetterSpacing, bucket_desc.layout, layout.text.letter_spacing, z); - applyLayoutProperty(PropertyKey::TextMaxAngle, bucket_desc.layout, layout.text.max_angle, z); - applyLayoutProperty(PropertyKey::TextRotate, bucket_desc.layout, layout.text.rotate, z); - applyLayoutProperty(PropertyKey::TextPadding, bucket_desc.layout, layout.text.padding, z); - applyLayoutProperty(PropertyKey::TextIgnorePlacement, bucket_desc.layout, layout.text.ignore_placement, z); - applyLayoutProperty(PropertyKey::TextOptional, bucket_desc.layout, layout.text.optional, z); - applyLayoutProperty(PropertyKey::TextJustify, bucket_desc.layout, layout.text.justify, z); - applyLayoutProperty(PropertyKey::TextAnchor, bucket_desc.layout, layout.text.anchor, z); - applyLayoutProperty(PropertyKey::TextKeepUpright, bucket_desc.layout, layout.text.keep_upright, z); - applyLayoutProperty(PropertyKey::TextTransform, bucket_desc.layout, layout.text.transform, z); - applyLayoutProperty(PropertyKey::TextOffset, bucket_desc.layout, layout.text.offset, z); - applyLayoutProperty(PropertyKey::TextAllowOverlap, bucket_desc.layout, layout.text.allow_overlap, z); - - if (bucket->needsDependencies(layer, bucket_desc.filter, *style.glyphStore, *style.sprite)) { - partialParse = true; - } - - // We do not proceed if the parser is in a "partial" state because - // the layer ordering needs to be respected when calculating text - // collisions. Although, at this point, we requested all the resources - // needed by this tile. - if (partialParse) { - return nullptr; - } - - bucket->addFeatures( - reinterpret_cast<uintptr_t>(&tile), *style.spriteAtlas, *style.sprite, *style.glyphAtlas, *style.glyphStore); - - return bucket->hasData() ? std::move(bucket) : nullptr; -} - -} diff --git a/src/mbgl/map/tile_parser.hpp b/src/mbgl/map/tile_parser.hpp deleted file mode 100644 index 63c1fd72aa..0000000000 --- a/src/mbgl/map/tile_parser.hpp +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef MBGL_MAP_TILE_PARSER -#define MBGL_MAP_TILE_PARSER - -#include <mbgl/map/geometry_tile.hpp> -#include <mbgl/map/vector_tile.hpp> -#include <mbgl/style/filter_expression.hpp> -#include <mbgl/style/class_properties.hpp> -#include <mbgl/style/style_bucket.hpp> -#include <mbgl/text/glyph.hpp> -#include <mbgl/util/ptr.hpp> -#include <mbgl/util/noncopyable.hpp> - -#include <cstdint> -#include <iosfwd> -#include <string> - -namespace mbgl { - -class Bucket; -class FontStack; -class Style; -class StyleBucket; -class StyleLayoutFill; -class StyleLayoutRaster; -class StyleLayoutLine; -class StyleLayoutSymbol; -class TileWorker; - -class TileParser : private util::noncopyable { -public: - TileParser(const GeometryTile&, TileWorker&, Style&); - ~TileParser(); - -public: - void parse(); - inline bool isPartialParse() const { - return partialParse; - } - -private: - bool obsolete() const; - - std::unique_ptr<Bucket> createBucket(const StyleBucket&); - std::unique_ptr<Bucket> createFillBucket(const GeometryTileLayer&, const StyleBucket&); - std::unique_ptr<Bucket> createLineBucket(const GeometryTileLayer&, const StyleBucket&); - std::unique_ptr<Bucket> createSymbolBucket(const GeometryTileLayer&, const StyleBucket&); - - template <class Bucket> - void addBucketGeometries(Bucket&, const GeometryTileLayer&, const FilterExpression&); - - const GeometryTile& geometryTile; - TileWorker& tile; - - // Cross-thread shared data. - Style& style; - - bool partialParse; -}; - -} - -#endif diff --git a/src/mbgl/map/tile_worker.cpp b/src/mbgl/map/tile_worker.cpp index 1991ab1885..a70e5a772f 100644 --- a/src/mbgl/map/tile_worker.cpp +++ b/src/mbgl/map/tile_worker.cpp @@ -1,9 +1,13 @@ #include <mbgl/text/collision_tile.hpp> #include <mbgl/map/tile_worker.hpp> -#include <mbgl/map/tile_parser.hpp> #include <mbgl/style/style.hpp> #include <mbgl/style/style_layer.hpp> #include <mbgl/geometry/glyph_atlas.hpp> +#include <mbgl/renderer/fill_bucket.hpp> +#include <mbgl/renderer/line_bucket.hpp> +#include <mbgl/renderer/symbol_bucket.hpp> +#include <mbgl/platform/log.hpp> +#include <mbgl/util/constants.hpp> using namespace mbgl; @@ -12,11 +16,12 @@ TileWorker::TileWorker(const TileID& id_, const uint16_t maxZoom_, const std::atomic<TileData::State>& state_, std::unique_ptr<CollisionTile> collision_) - : id(id_), - style(style_), + : style(style_), + id(id_), maxZoom(maxZoom_), state(state_), collision(std::move(collision_)) { + assert(style.sprite); } TileWorker::~TileWorker() { @@ -53,13 +58,36 @@ size_t TileWorker::countBuckets() const { } TileParseResult TileWorker::parse(const GeometryTile& geometryTile) { - // Parsing creates state that is encapsulated in TileParser. While parsing, - // the TileParser object writes results into this objects. All other state - // is going to be discarded afterwards. - TileParser parser(geometryTile, *this, style); - parser.parse(); + for (const auto& layer_desc : style.layers) { + // Cancel early when parsing. + if (obsolete()) { + return TileData::State::obsolete; + } + + if (layer_desc->isBackground()) { + // background is a special, fake bucket + continue; + } + + if (layer_desc->bucket) { + // This is a singular layer. Check if this bucket already exists. If not, + // parse this bucket. + if (getBucket(*layer_desc)) { + continue; + } + + std::unique_ptr<Bucket> bucket = createBucket(*layer_desc->bucket, geometryTile); + if (bucket) { + // Bucket creation might fail because the data tile may not + // contain any data that falls into this bucket. + setBucket(*layer_desc, std::move(bucket)); + } + } else { + Log::Warning(Event::ParseTile, "layer '%s' does not have buckets", layer_desc->id.c_str()); + } + } - if (parser.isPartialParse()) { + if (isPartialParse()) { return TileData::State::partial; } else { return TileData::State::parsed; @@ -76,3 +104,175 @@ void TileWorker::redoPlacement(float angle, bool collisionDebug) { } } } + +bool TileWorker::obsolete() const { + return getState() == TileData::State::obsolete; +} + +template <typename T> +struct PropertyEvaluator { + typedef T result_type; + PropertyEvaluator(float z_) : z(z_) {} + + template <typename P, typename std::enable_if<std::is_convertible<P, T>::value, int>::type = 0> + T operator()(const P &value) const { + return value; + } + + T operator()(const Function<T> &value) const { + return mapbox::util::apply_visitor(FunctionEvaluator<T>(z), value); + } + + template <typename P, typename std::enable_if<!std::is_convertible<P, T>::value, int>::type = 0> + T operator()(const P &) const { + return T(); + } + +private: + const float z; +}; + +template <typename T> +void applyLayoutProperty(PropertyKey key, const ClassProperties &classProperties, T &target, const float z) { + auto it = classProperties.properties.find(key); + if (it != classProperties.properties.end()) { + const PropertyEvaluator<T> evaluator(z); + target = mapbox::util::apply_visitor(evaluator, it->second); + } +} + +std::unique_ptr<Bucket> TileWorker::createBucket(const StyleBucket& bucketDesc, const GeometryTile& geometryTile) { + // Skip this bucket if we are to not render this + if (id.z < std::floor(bucketDesc.min_zoom) && std::floor(bucketDesc.min_zoom) < maxZoom) return nullptr; + if (id.z >= std::ceil(bucketDesc.max_zoom)) return nullptr; + if (bucketDesc.visibility == mbgl::VisibilityType::None) return nullptr; + + auto layer = geometryTile.getLayer(bucketDesc.source_layer); + if (layer) { + if (bucketDesc.type == StyleLayerType::Fill) { + return createFillBucket(*layer, bucketDesc); + } else if (bucketDesc.type == StyleLayerType::Line) { + return createLineBucket(*layer, bucketDesc); + } else if (bucketDesc.type == StyleLayerType::Symbol) { + return createSymbolBucket(*layer, bucketDesc); + } else if (bucketDesc.type == StyleLayerType::Raster) { + return nullptr; + } else { + Log::Warning(Event::ParseTile, "unknown bucket render type for layer '%s' (source layer '%s')", + bucketDesc.name.c_str(), bucketDesc.source_layer.c_str()); + } + } else { + // The layer specified in the bucket does not exist. Do nothing. + if (debug::tileParseWarnings) { + Log::Warning(Event::ParseTile, "layer '%s' does not exist in tile %d/%d/%d", + bucketDesc.source_layer.c_str(), id.z, id.x, id.y); + } + } + + return nullptr; +} + +template <class Bucket> +void TileWorker::addBucketGeometries(Bucket& bucket, const GeometryTileLayer& layer, const FilterExpression &filter) { + for (std::size_t i = 0; i < layer.featureCount(); i++) { + auto feature = layer.getFeature(i); + + if (obsolete()) + return; + + GeometryTileFeatureExtractor extractor(*feature); + if (!evaluate(filter, extractor)) + continue; + + bucket->addGeometry(feature->getGeometries()); + } +} + +std::unique_ptr<Bucket> TileWorker::createFillBucket(const GeometryTileLayer& layer, + const StyleBucket& bucket_desc) { + auto bucket = std::make_unique<FillBucket>(fillVertexBuffer, + triangleElementsBuffer, + lineElementsBuffer); + addBucketGeometries(bucket, layer, bucket_desc.filter); + return bucket->hasData() ? std::move(bucket) : nullptr; +} + +std::unique_ptr<Bucket> TileWorker::createLineBucket(const GeometryTileLayer& layer, + const StyleBucket& bucket_desc) { + auto bucket = std::make_unique<LineBucket>(lineVertexBuffer, + triangleElementsBuffer); + + const float z = id.z; + auto& layout = bucket->layout; + + applyLayoutProperty(PropertyKey::LineCap, bucket_desc.layout, layout.cap, z); + applyLayoutProperty(PropertyKey::LineJoin, bucket_desc.layout, layout.join, z); + applyLayoutProperty(PropertyKey::LineMiterLimit, bucket_desc.layout, layout.miter_limit, z); + applyLayoutProperty(PropertyKey::LineRoundLimit, bucket_desc.layout, layout.round_limit, z); + + addBucketGeometries(bucket, layer, bucket_desc.filter); + return bucket->hasData() ? std::move(bucket) : nullptr; +} + +std::unique_ptr<Bucket> TileWorker::createSymbolBucket(const GeometryTileLayer& layer, + const StyleBucket& bucket_desc) { + auto bucket = std::make_unique<SymbolBucket>(*getCollision(), id.overscaling); + + const float z = id.z; + auto& layout = bucket->layout; + + applyLayoutProperty(PropertyKey::SymbolPlacement, bucket_desc.layout, layout.placement, z); + if (layout.placement == PlacementType::Line) { + layout.icon.rotation_alignment = RotationAlignmentType::Map; + layout.text.rotation_alignment = RotationAlignmentType::Map; + }; + applyLayoutProperty(PropertyKey::SymbolMinDistance, bucket_desc.layout, layout.min_distance, z); + applyLayoutProperty(PropertyKey::SymbolAvoidEdges, bucket_desc.layout, layout.avoid_edges, z); + + applyLayoutProperty(PropertyKey::IconAllowOverlap, bucket_desc.layout, layout.icon.allow_overlap, z); + applyLayoutProperty(PropertyKey::IconIgnorePlacement, bucket_desc.layout, layout.icon.ignore_placement, z); + applyLayoutProperty(PropertyKey::IconOptional, bucket_desc.layout, layout.icon.optional, z); + applyLayoutProperty(PropertyKey::IconRotationAlignment, bucket_desc.layout, layout.icon.rotation_alignment, z); + applyLayoutProperty(PropertyKey::IconMaxSize, bucket_desc.layout, layout.icon.max_size, z); + applyLayoutProperty(PropertyKey::IconImage, bucket_desc.layout, layout.icon.image, z); + applyLayoutProperty(PropertyKey::IconPadding, bucket_desc.layout, layout.icon.padding, z); + applyLayoutProperty(PropertyKey::IconRotate, bucket_desc.layout, layout.icon.rotate, z); + applyLayoutProperty(PropertyKey::IconKeepUpright, bucket_desc.layout, layout.icon.keep_upright, z); + applyLayoutProperty(PropertyKey::IconOffset, bucket_desc.layout, layout.icon.offset, z); + + applyLayoutProperty(PropertyKey::TextRotationAlignment, bucket_desc.layout, layout.text.rotation_alignment, z); + applyLayoutProperty(PropertyKey::TextField, bucket_desc.layout, layout.text.field, z); + applyLayoutProperty(PropertyKey::TextFont, bucket_desc.layout, layout.text.font, z); + applyLayoutProperty(PropertyKey::TextMaxSize, bucket_desc.layout, layout.text.max_size, z); + applyLayoutProperty(PropertyKey::TextMaxWidth, bucket_desc.layout, layout.text.max_width, z); + applyLayoutProperty(PropertyKey::TextLineHeight, bucket_desc.layout, layout.text.line_height, z); + applyLayoutProperty(PropertyKey::TextLetterSpacing, bucket_desc.layout, layout.text.letter_spacing, z); + applyLayoutProperty(PropertyKey::TextMaxAngle, bucket_desc.layout, layout.text.max_angle, z); + applyLayoutProperty(PropertyKey::TextRotate, bucket_desc.layout, layout.text.rotate, z); + applyLayoutProperty(PropertyKey::TextPadding, bucket_desc.layout, layout.text.padding, z); + applyLayoutProperty(PropertyKey::TextIgnorePlacement, bucket_desc.layout, layout.text.ignore_placement, z); + applyLayoutProperty(PropertyKey::TextOptional, bucket_desc.layout, layout.text.optional, z); + applyLayoutProperty(PropertyKey::TextJustify, bucket_desc.layout, layout.text.justify, z); + applyLayoutProperty(PropertyKey::TextAnchor, bucket_desc.layout, layout.text.anchor, z); + applyLayoutProperty(PropertyKey::TextKeepUpright, bucket_desc.layout, layout.text.keep_upright, z); + applyLayoutProperty(PropertyKey::TextTransform, bucket_desc.layout, layout.text.transform, z); + applyLayoutProperty(PropertyKey::TextOffset, bucket_desc.layout, layout.text.offset, z); + applyLayoutProperty(PropertyKey::TextAllowOverlap, bucket_desc.layout, layout.text.allow_overlap, z); + + if (bucket->needsDependencies(layer, bucket_desc.filter, *style.glyphStore, *style.sprite)) { + partialParse = true; + } + + // We do not proceed if the parser is in a "partial" state because + // the layer ordering needs to be respected when calculating text + // collisions. Although, at this point, we requested all the resources + // needed by this tile. + if (partialParse) { + return nullptr; + } + + bucket->addFeatures( + reinterpret_cast<uintptr_t>(this), *style.spriteAtlas, *style.sprite, *style.glyphAtlas, *style.glyphStore); + + return bucket->hasData() ? std::move(bucket) : nullptr; +} diff --git a/src/mbgl/map/tile_worker.hpp b/src/mbgl/map/tile_worker.hpp index 420b0bf9f2..c3f131ccd4 100644 --- a/src/mbgl/map/tile_worker.hpp +++ b/src/mbgl/map/tile_worker.hpp @@ -7,7 +7,9 @@ #include <mbgl/geometry/fill_buffer.hpp> #include <mbgl/geometry/line_buffer.hpp> #include <mbgl/util/noncopyable.hpp> +#include <mbgl/style/filter_expression.hpp> +#include <string> #include <memory> #include <mutex> #include <unordered_map> @@ -18,6 +20,8 @@ class CollisionTile; class GeometryTile; class Style; class Bucket; +class StyleBucket; +class GeometryTileLayer; using TileParseResult = mapbox::util::variant< TileData::State, // success @@ -44,14 +48,32 @@ public: return collision.get(); } + inline bool isPartialParse() const { + return partialParse; + } + TileParseResult parse(const GeometryTile&); void redoPlacement(float angle, bool collisionDebug); - const TileID id; Style& style; + +private: + bool obsolete() const; + + std::unique_ptr<Bucket> createBucket(const StyleBucket&, const GeometryTile&); + std::unique_ptr<Bucket> createFillBucket(const GeometryTileLayer&, const StyleBucket&); + std::unique_ptr<Bucket> createLineBucket(const GeometryTileLayer&, const StyleBucket&); + std::unique_ptr<Bucket> createSymbolBucket(const GeometryTileLayer&, const StyleBucket&); + + template <class Bucket> + void addBucketGeometries(Bucket&, const GeometryTileLayer&, const FilterExpression&); + + const TileID id; const uint16_t maxZoom; const std::atomic<TileData::State>& state; + bool partialParse = false; + FillVertexBuffer fillVertexBuffer; LineVertexBuffer lineVertexBuffer; |