Merge pull request #1532 from mapbox/1465-text_collision
Calculate text collision correctly
This commit is contained in:
committed by
Justin R. Miller
parent
1ae3b1d122
commit
ac1dcecef6
@@ -21,7 +21,7 @@ LiveTileData::LiveTileData(const TileID& id_,
|
||||
spriteAtlas_, sprite_, source_),
|
||||
annotationManager(annotationManager_) {
|
||||
// live features are always ready
|
||||
state = State::loaded;
|
||||
setState(State::loaded);
|
||||
}
|
||||
|
||||
LiveTileData::~LiveTileData() {
|
||||
@@ -31,7 +31,7 @@ LiveTileData::~LiveTileData() {
|
||||
}
|
||||
|
||||
void LiveTileData::parse() {
|
||||
if (state != State::loaded) {
|
||||
if (getState() != State::loaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -46,12 +46,12 @@ void LiveTileData::parse() {
|
||||
parser.parse();
|
||||
} catch (const std::exception& ex) {
|
||||
Log::Error(Event::ParseTile, "Live-parsing [%d/%d/%d] failed: %s", id.z, id.x, id.y, ex.what());
|
||||
state = State::obsolete;
|
||||
setState(State::obsolete);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (state != State::obsolete) {
|
||||
state = State::parsed;
|
||||
if (getState() != State::obsolete) {
|
||||
setState(State::parsed);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,14 +15,14 @@ RasterTileData::~RasterTileData() {
|
||||
}
|
||||
|
||||
void RasterTileData::parse() {
|
||||
if (state != State::loaded) {
|
||||
if (getState() != State::loaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (bucket.setImage(data)) {
|
||||
state = State::parsed;
|
||||
setState(State::parsed);
|
||||
} else {
|
||||
state = State::invalid;
|
||||
setState(State::invalid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -127,7 +127,7 @@ bool Source::isLoaded() const {
|
||||
}
|
||||
|
||||
for (const auto& tile : tiles) {
|
||||
if (tile.second->data->state != TileData::State::parsed) {
|
||||
if (tile.second->data->getState() != TileData::State::parsed) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -193,11 +193,11 @@ void Source::finishRender(Painter &painter) {
|
||||
}
|
||||
}
|
||||
|
||||
std::forward_list<Tile *> Source::getLoadedTiles() const {
|
||||
std::forward_list<Tile *> ptrs;
|
||||
std::forward_list<Tile*> Source::getLoadedTiles() const {
|
||||
std::forward_list<Tile*> ptrs;
|
||||
auto it = ptrs.before_begin();
|
||||
for (const auto &pair : tiles) {
|
||||
if (pair.second->data->ready()) {
|
||||
for (const auto& pair : tiles) {
|
||||
if (pair.second->data->isReady()) {
|
||||
it = ptrs.insert_after(it, pair.second.get());
|
||||
}
|
||||
}
|
||||
@@ -211,16 +211,16 @@ const std::vector<Tile*>& Source::getTiles() const {
|
||||
TileData::State Source::hasTile(const TileID& id) {
|
||||
auto it = tiles.find(id);
|
||||
if (it != tiles.end()) {
|
||||
Tile &tile = *it->second;
|
||||
Tile& tile = *it->second;
|
||||
if (tile.id == id && tile.data) {
|
||||
return tile.data->state;
|
||||
return tile.data->getState();
|
||||
}
|
||||
}
|
||||
|
||||
return TileData::State::invalid;
|
||||
}
|
||||
|
||||
void Source::handlePartialTile(const TileID &id, Worker &worker) {
|
||||
void Source::handlePartialTile(const TileID& id, Worker& worker) {
|
||||
const TileID normalized_id = id.normalized();
|
||||
|
||||
auto it = tile_data.find(normalized_id);
|
||||
@@ -265,7 +265,7 @@ TileData::State Source::addTile(MapData& data,
|
||||
new_tile.data = it->second.lock();
|
||||
}
|
||||
|
||||
if (new_tile.data && new_tile.data->state == TileData::State::obsolete) {
|
||||
if (new_tile.data && new_tile.data->getState() == TileData::State::obsolete) {
|
||||
// Do not consider the tile if it's already obsolete.
|
||||
new_tile.data.reset();
|
||||
}
|
||||
@@ -296,7 +296,7 @@ TileData::State Source::addTile(MapData& data,
|
||||
tile_data.emplace(new_tile.data->id, new_tile.data);
|
||||
}
|
||||
|
||||
return new_tile.data->state;
|
||||
return new_tile.data->getState();
|
||||
}
|
||||
|
||||
double Source::getZoom(const TransformState& state) const {
|
||||
@@ -453,7 +453,7 @@ void Source::update(MapData& data,
|
||||
bool obsolete = std::find(retain.begin(), retain.end(), tile.id) == retain.end();
|
||||
if (!obsolete) {
|
||||
retain_data.insert(tile.data->id);
|
||||
} else if (type != SourceType::Raster && tile.data->state == TileData::State::parsed) {
|
||||
} else if (type != SourceType::Raster && tile.data->getState() == TileData::State::parsed) {
|
||||
// Partially parsed tiles are never added to the cache because otherwise
|
||||
// they never get updated if the go out from the viewport and the pending
|
||||
// resources arrive.
|
||||
|
||||
@@ -46,7 +46,7 @@ std::shared_ptr<TileData> TileCache::get(uint64_t key) {
|
||||
data = it->second;
|
||||
tiles.erase(it);
|
||||
orderedKeys.remove(key);
|
||||
assert(data->ready());
|
||||
assert(data->isReady());
|
||||
}
|
||||
|
||||
return data;
|
||||
|
||||
@@ -12,10 +12,9 @@ using namespace mbgl;
|
||||
TileData::TileData(const TileID& id_, const SourceInfo& source_)
|
||||
: id(id_),
|
||||
name(id),
|
||||
state(State::initial),
|
||||
parsing(ATOMIC_FLAG_INIT),
|
||||
source(source_),
|
||||
env(Environment::Get()),
|
||||
state(State::initial),
|
||||
debugBucket(debugFontBuffer) {
|
||||
// Initialize tile debug coordinates
|
||||
debugFontBuffer.addText(name.c_str(), 50, 200, 5);
|
||||
@@ -29,6 +28,12 @@ const std::string TileData::toString() const {
|
||||
return std::string { "[tile " } + name + "]";
|
||||
}
|
||||
|
||||
void TileData::setState(const State& state_) {
|
||||
assert(!isImmutable());
|
||||
|
||||
state = state_;
|
||||
}
|
||||
|
||||
void TileData::request(Worker& worker, float pixelRatio, std::function<void()> callback) {
|
||||
std::string url = source.tileURL(id, pixelRatio);
|
||||
state = State::loading;
|
||||
|
||||
@@ -49,10 +49,24 @@ public:
|
||||
void cancel();
|
||||
const std::string toString() const;
|
||||
|
||||
inline bool ready() const {
|
||||
inline bool isReady() const {
|
||||
return isReadyState(state);
|
||||
}
|
||||
|
||||
// Returns true if the TileData is in a final state and we cannot
|
||||
// make changes to it anymore.
|
||||
inline bool isImmutable() const {
|
||||
return state == State::parsed || state == State::obsolete;
|
||||
}
|
||||
|
||||
// We let subclasses override setState() so they
|
||||
// can intercept the state change and react accordingly.
|
||||
virtual void setState(const State& state);
|
||||
|
||||
inline State getState() const {
|
||||
return state;
|
||||
}
|
||||
|
||||
void endParsing();
|
||||
|
||||
// Override this in the child class.
|
||||
@@ -61,8 +75,7 @@ public:
|
||||
|
||||
const TileID id;
|
||||
const std::string name;
|
||||
std::atomic<State> state;
|
||||
std::atomic_flag parsing;
|
||||
std::atomic_flag parsing = ATOMIC_FLAG_INIT;
|
||||
|
||||
protected:
|
||||
// Set the internal parsing state to true so we prevent
|
||||
@@ -81,6 +94,10 @@ protected:
|
||||
|
||||
std::unique_ptr<WorkRequest> workRequest;
|
||||
|
||||
private:
|
||||
std::atomic<State> state;
|
||||
|
||||
protected:
|
||||
// Contains the tile ID string for painting debug information.
|
||||
DebugFontBuffer debugFontBuffer;
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include <mbgl/renderer/line_bucket.hpp>
|
||||
#include <mbgl/renderer/symbol_bucket.hpp>
|
||||
#include <mbgl/util/constants.hpp>
|
||||
#include <mbgl/text/collision.hpp>
|
||||
#include <mbgl/util/std.hpp>
|
||||
#include <mbgl/style/style.hpp>
|
||||
|
||||
@@ -35,13 +34,13 @@ TileParser::TileParser(const GeometryTile& geometryTile_,
|
||||
glyphStore(glyphStore_),
|
||||
spriteAtlas(spriteAtlas_),
|
||||
sprite(sprite_),
|
||||
collision(util::make_unique<Collision>(tile.id.z, 4096, tile.source.tile_size, tile.depth)),
|
||||
partialParse(false) {
|
||||
assert(sprite);
|
||||
assert(collision);
|
||||
}
|
||||
|
||||
bool TileParser::obsolete() const { return tile.state == TileData::State::obsolete; }
|
||||
bool TileParser::obsolete() const {
|
||||
return tile.getState() == TileData::State::obsolete;
|
||||
}
|
||||
|
||||
void TileParser::parse() {
|
||||
for (const auto& layer_desc : style.layers) {
|
||||
@@ -119,6 +118,10 @@ std::unique_ptr<Bucket> TileParser::createBucket(const StyleBucket &bucketDesc)
|
||||
} else if (bucketDesc.type == StyleLayerType::Line) {
|
||||
return createLineBucket(*layer, bucketDesc);
|
||||
} else if (bucketDesc.type == StyleLayerType::Symbol) {
|
||||
if (partialParse) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool needsResources = false;
|
||||
auto symbolBucket = createSymbolBucket(*layer, bucketDesc, needsResources);
|
||||
if (needsResources) {
|
||||
@@ -194,7 +197,7 @@ std::unique_ptr<Bucket> TileParser::createSymbolBucket(const GeometryTileLayer&
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto bucket = util::make_unique<SymbolBucket>(*collision);
|
||||
auto bucket = util::make_unique<SymbolBucket>(*tile.getCollision());
|
||||
|
||||
const float z = tile.id.z;
|
||||
auto& layout = bucket->layout;
|
||||
|
||||
@@ -29,7 +29,6 @@ class StyleLayoutRaster;
|
||||
class StyleLayoutLine;
|
||||
class StyleLayoutSymbol;
|
||||
class VectorTileData;
|
||||
class Collision;
|
||||
|
||||
class TileParser : private util::noncopyable {
|
||||
public:
|
||||
@@ -69,7 +68,6 @@ private:
|
||||
SpriteAtlas& spriteAtlas;
|
||||
util::ptr<Sprite> sprite;
|
||||
|
||||
std::unique_ptr<Collision> collision;
|
||||
bool partialParse;
|
||||
};
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <mbgl/map/source.hpp>
|
||||
#include <mbgl/geometry/glyph_atlas.hpp>
|
||||
#include <mbgl/platform/log.hpp>
|
||||
#include <mbgl/text/collision.hpp>
|
||||
#include <mbgl/util/pbf.hpp>
|
||||
|
||||
using namespace mbgl;
|
||||
@@ -19,12 +20,13 @@ VectorTileData::VectorTileData(const TileID& id_,
|
||||
util::ptr<Sprite> sprite_,
|
||||
const SourceInfo& source_)
|
||||
: TileData(id_, source_),
|
||||
depth(id_.z >= source_.max_zoom ? mapMaxZoom - id_.z : 1),
|
||||
glyphAtlas(glyphAtlas_),
|
||||
glyphStore(glyphStore_),
|
||||
spriteAtlas(spriteAtlas_),
|
||||
sprite(sprite_),
|
||||
style(style_),
|
||||
depth(id.z >= source.max_zoom ? mapMaxZoom - id.z : 1) {
|
||||
collision(util::make_unique<Collision>(id_.z, 4096, source_.tile_size, depth)) {
|
||||
}
|
||||
|
||||
VectorTileData::~VectorTileData() {
|
||||
@@ -35,7 +37,7 @@ VectorTileData::~VectorTileData() {
|
||||
}
|
||||
|
||||
void VectorTileData::parse() {
|
||||
if (state != State::loaded && state != State::partial) {
|
||||
if (getState() != State::loaded && getState() != State::partial) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -48,24 +50,24 @@ void VectorTileData::parse() {
|
||||
TileParser parser(*vt, *this, style, glyphAtlas, glyphStore, spriteAtlas, sprite);
|
||||
parser.parse();
|
||||
|
||||
if (state == State::obsolete) {
|
||||
if (getState() == State::obsolete) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (parser.isPartialParse()) {
|
||||
state = State::partial;
|
||||
setState(State::partial);
|
||||
} else {
|
||||
state = State::parsed;
|
||||
setState(State::parsed);
|
||||
}
|
||||
} catch (const std::exception& ex) {
|
||||
Log::Error(Event::ParseTile, "Parsing [%d/%d/%d] failed: %s", id.z, id.x, id.y, ex.what());
|
||||
state = State::obsolete;
|
||||
setState(State::obsolete);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Bucket* VectorTileData::getBucket(StyleLayer const& layer) {
|
||||
if (!ready() || !layer.bucket) {
|
||||
if (!isReady() || !layer.bucket) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -91,3 +93,11 @@ void VectorTileData::setBucket(StyleLayer const& layer, std::unique_ptr<Bucket>
|
||||
|
||||
buckets[layer.bucket->name] = std::move(bucket);
|
||||
}
|
||||
|
||||
void VectorTileData::setState(const State& state_) {
|
||||
TileData::setState(state_);
|
||||
|
||||
if (isImmutable()) {
|
||||
collision.reset();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
namespace mbgl {
|
||||
|
||||
class Bucket;
|
||||
class Collision;
|
||||
class Painter;
|
||||
class SourceInfo;
|
||||
class StyleLayer;
|
||||
@@ -45,6 +46,14 @@ public:
|
||||
|
||||
void setBucket(StyleLayer const &layer_desc, std::unique_ptr<Bucket> bucket);
|
||||
|
||||
void setState(const State& state) override;
|
||||
|
||||
inline Collision* getCollision() const {
|
||||
return collision.get();
|
||||
}
|
||||
|
||||
const float depth;
|
||||
|
||||
protected:
|
||||
// Holds the actual geometries in this tile.
|
||||
FillVertexBuffer fillVertexBuffer;
|
||||
@@ -69,8 +78,7 @@ private:
|
||||
std::unordered_map<std::string, std::unique_ptr<Bucket>> buckets;
|
||||
mutable std::mutex bucketsMutex;
|
||||
|
||||
public:
|
||||
const float depth;
|
||||
std::unique_ptr<Collision> collision;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -381,7 +381,7 @@ std::vector<RenderItem> Painter::determineRenderOrder(const Style& style) {
|
||||
const auto& tiles = layer.bucket->source->getTiles();
|
||||
for (auto tile : tiles) {
|
||||
assert(tile);
|
||||
if (!tile->data && !tile->data->ready()) {
|
||||
if (!tile->data && !tile->data->isReady()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user