make sure we retain shared state when destructing the map object
refs #261
This commit is contained in:
@@ -97,13 +97,13 @@ public:
|
||||
|
||||
public:
|
||||
inline const TransformState &getState() const { return state; }
|
||||
inline const Style &getStyle() const { return style; }
|
||||
inline GlyphAtlas &getGlyphAtlas() { return glyphAtlas; }
|
||||
inline GlyphStore &getGlyphStore() { return glyphStore; }
|
||||
inline SpriteAtlas &getSpriteAtlas() { return spriteAtlas; }
|
||||
inline std::shared_ptr<const Style> getStyle() const { return style; }
|
||||
inline std::shared_ptr<GlyphAtlas> getGlyphAtlas() { return glyphAtlas; }
|
||||
inline std::shared_ptr<GlyphStore> getGlyphStore() { return glyphStore; }
|
||||
inline std::shared_ptr<SpriteAtlas> getSpriteAtlas() { return spriteAtlas; }
|
||||
inline std::shared_ptr<Texturepool> getTexturepool() { return texturepool; }
|
||||
inline uv_loop_t *getLoop() { return loop; }
|
||||
inline time getAnimationTime() const { return animationTime; }
|
||||
inline Texturepool &getTexturepool() { return texturepool; }
|
||||
inline const Sources &getSources() { return sources; }
|
||||
|
||||
private:
|
||||
@@ -151,11 +151,12 @@ private:
|
||||
Transform transform;
|
||||
TransformState state;
|
||||
|
||||
Texturepool texturepool;
|
||||
Style style;
|
||||
GlyphAtlas glyphAtlas;
|
||||
GlyphStore glyphStore;
|
||||
SpriteAtlas spriteAtlas;
|
||||
std::shared_ptr<Style> style;
|
||||
std::shared_ptr<GlyphAtlas> glyphAtlas;
|
||||
std::shared_ptr<GlyphStore> glyphStore;
|
||||
std::shared_ptr<SpriteAtlas> spriteAtlas;
|
||||
std::shared_ptr<Texturepool> texturepool;
|
||||
|
||||
Painter painter;
|
||||
|
||||
Sources sources;
|
||||
|
||||
@@ -46,7 +46,9 @@ public:
|
||||
const std::string toString() const;
|
||||
|
||||
// Override this in the child class.
|
||||
virtual void beforeParse();
|
||||
virtual void parse() = 0;
|
||||
virtual void afterParse();
|
||||
virtual void render(Painter &painter, const LayerDescription& layer_desc) = 0;
|
||||
virtual bool hasData(const LayerDescription& layer_desc) const = 0;
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#ifndef LLMR_MAP_TILE_PARSER
|
||||
#define LLMR_MAP_TILE_PARSER
|
||||
|
||||
#include <llmr/map/vector_tile_data.hpp>
|
||||
#include <llmr/map/vector_tile.hpp>
|
||||
#include <llmr/text/placement.hpp>
|
||||
#include <llmr/text/glyph_store.hpp>
|
||||
@@ -14,13 +13,21 @@ class Style;
|
||||
class GlyphAtlas;
|
||||
class GlyphStore;
|
||||
class SpriteAtlas;
|
||||
class VectorTileData;
|
||||
|
||||
class LayerDescription;
|
||||
class Bucket;
|
||||
|
||||
class TileParser {
|
||||
public:
|
||||
TileParser(const std::string& data, VectorTileData& tile, const Style& style, GlyphAtlas& glyphAtlas, GlyphStore &glyphStore, SpriteAtlas &spriteAtlas);
|
||||
TileParser(const std::string &data, VectorTileData &tile,
|
||||
const std::shared_ptr<const Style> &style,
|
||||
const std::shared_ptr<GlyphAtlas> &glyphAtlas,
|
||||
const std::shared_ptr<GlyphStore> &glyphStore,
|
||||
const std::shared_ptr<SpriteAtlas> &spriteAtlas);
|
||||
|
||||
public:
|
||||
void parse();
|
||||
|
||||
private:
|
||||
bool obsolete() const;
|
||||
@@ -38,10 +45,13 @@ private:
|
||||
private:
|
||||
const VectorTile vector_data;
|
||||
VectorTileData& tile;
|
||||
const Style& style;
|
||||
GlyphAtlas& glyphAtlas;
|
||||
GlyphStore &glyphStore;
|
||||
SpriteAtlas &spriteAtlas;
|
||||
|
||||
// Cross-thread shared data.
|
||||
std::shared_ptr<const Style> style;
|
||||
std::shared_ptr<GlyphAtlas> glyphAtlas;
|
||||
std::shared_ptr<GlyphStore> glyphStore;
|
||||
std::shared_ptr<SpriteAtlas> spriteAtlas;
|
||||
|
||||
Placement placement;
|
||||
};
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <llmr/geometry/line_buffer.hpp>
|
||||
#include <llmr/geometry/icon_buffer.hpp>
|
||||
#include <llmr/geometry/text_buffer.hpp>
|
||||
#include <llmr/map/tile_parser.hpp>
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
@@ -25,7 +26,9 @@ public:
|
||||
VectorTileData(Tile::ID id, Map &map, const std::string url);
|
||||
~VectorTileData();
|
||||
|
||||
virtual void beforeParse();
|
||||
virtual void parse();
|
||||
virtual void afterParse();
|
||||
virtual void render(Painter &painter, const LayerDescription& layer_desc);
|
||||
virtual bool hasData(const LayerDescription& layer_desc) const;
|
||||
|
||||
@@ -44,6 +47,7 @@ protected:
|
||||
// They contain the location offsets in the buffers stored above
|
||||
std::unordered_map<std::string, std::unique_ptr<Bucket>> buckets;
|
||||
|
||||
std::unique_ptr<TileParser> parser;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ class VertexArrayObject;
|
||||
|
||||
class RasterBucket : public Bucket {
|
||||
public:
|
||||
RasterBucket(Texturepool &texturepool);
|
||||
RasterBucket(const std::shared_ptr<Texturepool> &texturepool);
|
||||
|
||||
virtual void render(Painter& painter, const std::string& layer_name, const Tile::ID& id);
|
||||
virtual bool hasData() const;
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace llmr {
|
||||
class Raster : public std::enable_shared_from_this<Raster> {
|
||||
|
||||
public:
|
||||
Raster(Texturepool &texturepool);
|
||||
Raster(const std::shared_ptr<Texturepool> &texturepool);
|
||||
~Raster();
|
||||
|
||||
// load image data
|
||||
@@ -53,7 +53,7 @@ private:
|
||||
bool loaded = false;
|
||||
|
||||
// shared texture pool
|
||||
Texturepool &texturepool;
|
||||
std::shared_ptr<Texturepool> texturepool;
|
||||
|
||||
// min/mag filter
|
||||
uint32_t filter = 0;
|
||||
|
||||
@@ -19,10 +19,11 @@ using namespace llmr;
|
||||
Map::Map(View& view)
|
||||
: view(view),
|
||||
transform(),
|
||||
texturepool(),
|
||||
style(),
|
||||
glyphAtlas(1024, 1024),
|
||||
spriteAtlas(512, 512),
|
||||
style(std::make_shared<Style>()),
|
||||
glyphAtlas(std::make_shared<GlyphAtlas>(1024, 1024)),
|
||||
glyphStore(std::make_shared<GlyphStore>()),
|
||||
spriteAtlas(std::make_shared<SpriteAtlas>(512, 512)),
|
||||
texturepool(std::make_shared<Texturepool>()),
|
||||
painter(*this),
|
||||
loop(uv_loop_new()) {
|
||||
|
||||
@@ -35,6 +36,10 @@ Map::Map(View& view)
|
||||
}
|
||||
|
||||
Map::~Map() {
|
||||
if (async) {
|
||||
stop();
|
||||
}
|
||||
|
||||
uv_loop_delete(loop);
|
||||
loop = nullptr;
|
||||
}
|
||||
@@ -186,7 +191,7 @@ void Map::setup() {
|
||||
}
|
||||
|
||||
void Map::loadStyle(const uint8_t *const data, uint32_t bytes) {
|
||||
style.loadJSON(data, bytes);
|
||||
style->loadJSON(data, bytes);
|
||||
update();
|
||||
}
|
||||
|
||||
@@ -386,18 +391,18 @@ bool Map::getDebug() const {
|
||||
}
|
||||
|
||||
void Map::toggleRaster() {
|
||||
style.setDefaultTransitionDuration(300);
|
||||
style.cancelTransitions();
|
||||
style->setDefaultTransitionDuration(300);
|
||||
style->cancelTransitions();
|
||||
|
||||
auto it = sources.find("satellite");
|
||||
if (it != sources.end()) {
|
||||
Source &satellite_source = *it->second;
|
||||
if (satellite_source.enabled) {
|
||||
satellite_source.enabled = false;
|
||||
style.appliedClasses.erase("satellite");
|
||||
style->appliedClasses.erase("satellite");
|
||||
} else {
|
||||
satellite_source.enabled = true;
|
||||
style.appliedClasses.insert("satellite");
|
||||
style->appliedClasses.insert("satellite");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -451,28 +456,28 @@ void Map::prepare() {
|
||||
oldState.getFramebufferHeight() != state.getFramebufferHeight();
|
||||
|
||||
if (pixelRatioChanged) {
|
||||
style.sprite = std::make_shared<Sprite>(*this, state.getPixelRatio());
|
||||
style.sprite->load(kSpriteURL);
|
||||
style->sprite = std::make_shared<Sprite>(*this, state.getPixelRatio());
|
||||
style->sprite->load(kSpriteURL);
|
||||
|
||||
spriteAtlas.resize(state.getPixelRatio());
|
||||
spriteAtlas->resize(state.getPixelRatio());
|
||||
}
|
||||
|
||||
if (pixelRatioChanged || dimensionsChanged) {
|
||||
painter.clearFramebuffers();
|
||||
}
|
||||
|
||||
style.cascade(state.getNormalizedZoom());
|
||||
style->cascade(state.getNormalizedZoom());
|
||||
|
||||
// Update style transitions.
|
||||
animationTime = util::now();
|
||||
if (style.needsTransition()) {
|
||||
style.updateTransitions(animationTime);
|
||||
if (style->needsTransition()) {
|
||||
style->updateTransitions(animationTime);
|
||||
update();
|
||||
}
|
||||
|
||||
// Allow the sprite atlas to potentially pull new sprite images if needed.
|
||||
if (style.sprite && style.sprite->isLoaded()) {
|
||||
spriteAtlas.update(*style.sprite);
|
||||
if (style->sprite && style->sprite->isLoaded()) {
|
||||
spriteAtlas->update(*style->sprite);
|
||||
}
|
||||
|
||||
updateTiles();
|
||||
@@ -506,7 +511,7 @@ void Map::render() {
|
||||
#endif
|
||||
// Actually render the layers
|
||||
if (debug::renderTree) { std::cout << "{" << std::endl; indent++; }
|
||||
renderLayers(style.layers);
|
||||
renderLayers(style->layers);
|
||||
if (debug::renderTree) { std::cout << "}" << std::endl; indent--; }
|
||||
|
||||
// Finalize the rendering, e.g. by calling debug render calls per tile.
|
||||
@@ -603,8 +608,8 @@ void Map::renderLayer(const LayerDescription& layer_desc, RenderPass pass) {
|
||||
if (layer_desc.child_layer.size()) {
|
||||
// This is a layer group. We render them during our translucent render pass.
|
||||
if (pass == Translucent) {
|
||||
auto it = find_style(style.computed.composites, layer_desc);
|
||||
const CompositeProperties &properties = (it != style.computed.composites.end()) ? it->second : defaultCompositeProperties;
|
||||
auto it = find_style(style->computed.composites, layer_desc);
|
||||
const CompositeProperties &properties = (it != style->computed.composites.end()) ? it->second : defaultCompositeProperties;
|
||||
if (properties.isVisible()) {
|
||||
gl::group group(std::string("group: ") + layer_desc.name);
|
||||
|
||||
@@ -633,31 +638,31 @@ void Map::renderLayer(const LayerDescription& layer_desc, RenderPass pass) {
|
||||
// This is a singular layer. Try to find the bucket associated with
|
||||
// this layer and render it.
|
||||
|
||||
auto bucket_it = style.buckets.find(layer_desc.bucket_name);
|
||||
if (bucket_it != style.buckets.end()) {
|
||||
auto bucket_it = style->buckets.find(layer_desc.bucket_name);
|
||||
if (bucket_it != style->buckets.end()) {
|
||||
const BucketDescription &bucket_desc = bucket_it->second;
|
||||
|
||||
// Abort early if we can already deduce from the bucket type that
|
||||
// we're not going to render anything anyway during this pass.
|
||||
switch (bucket_desc.type) {
|
||||
case BucketType::Fill:
|
||||
if (is_invisible(style.computed.fills, layer_desc)) return;
|
||||
if (is_invisible(style->computed.fills, layer_desc)) return;
|
||||
break;
|
||||
case BucketType::Line:
|
||||
if (pass == Opaque) return;
|
||||
if (is_invisible(style.computed.lines, layer_desc)) return;
|
||||
if (is_invisible(style->computed.lines, layer_desc)) return;
|
||||
break;
|
||||
case BucketType::Icon:
|
||||
if (pass == Opaque) return;
|
||||
if (is_invisible(style.computed.icons, layer_desc)) return;
|
||||
if (is_invisible(style->computed.icons, layer_desc)) return;
|
||||
break;
|
||||
case BucketType::Text:
|
||||
if (pass == Opaque) return;
|
||||
if (is_invisible(style.computed.texts, layer_desc)) return;
|
||||
if (is_invisible(style->computed.texts, layer_desc)) return;
|
||||
break;
|
||||
case BucketType::Raster:
|
||||
if (pass == Translucent) return;
|
||||
if (is_invisible(style.computed.rasters, layer_desc)) return;
|
||||
if (is_invisible(style->computed.rasters, layer_desc)) return;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -56,12 +56,23 @@ void TileData::cancel() {
|
||||
}
|
||||
}
|
||||
|
||||
void TileData::beforeParse() {}
|
||||
|
||||
void TileData::reparse() {
|
||||
beforeParse();
|
||||
|
||||
// We're creating a new work request. The work request deletes itself after it executed
|
||||
// the after work handler
|
||||
new uv::work<std::shared_ptr<TileData>>(
|
||||
map.getLoop(),
|
||||
[](std::shared_ptr<TileData> &tile) { tile->parse(); },
|
||||
[](std::shared_ptr<TileData> &tile) { tile->map.update(); },
|
||||
[](std::shared_ptr<TileData> &tile) {
|
||||
tile->parse();
|
||||
},
|
||||
[](std::shared_ptr<TileData> &tile) {
|
||||
tile->afterParse();
|
||||
tile->map.update();
|
||||
},
|
||||
shared_from_this());
|
||||
}
|
||||
|
||||
void TileData::afterParse() {}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <llmr/map/tile_parser.hpp>
|
||||
|
||||
#include <llmr/map/vector_tile_data.hpp>
|
||||
#include <llmr/style/style.hpp>
|
||||
#include <llmr/renderer/fill_bucket.hpp>
|
||||
#include <llmr/renderer/line_bucket.hpp>
|
||||
@@ -17,7 +18,11 @@
|
||||
|
||||
using namespace llmr;
|
||||
|
||||
TileParser::TileParser(const std::string& data, VectorTileData& tile, const Style& style, GlyphAtlas& glyphAtlas, GlyphStore &glyphStore, SpriteAtlas &spriteAtlas)
|
||||
TileParser::TileParser(const std::string &data, VectorTileData &tile,
|
||||
const std::shared_ptr<const Style> &style,
|
||||
const std::shared_ptr<GlyphAtlas> &glyphAtlas,
|
||||
const std::shared_ptr<GlyphStore> &glyphStore,
|
||||
const std::shared_ptr<SpriteAtlas> &spriteAtlas)
|
||||
: vector_data(pbf((const uint8_t *)data.data(), data.size())),
|
||||
tile(tile),
|
||||
style(style),
|
||||
@@ -25,14 +30,17 @@ TileParser::TileParser(const std::string& data, VectorTileData& tile, const Styl
|
||||
glyphStore(glyphStore),
|
||||
spriteAtlas(spriteAtlas),
|
||||
placement(tile.id.z) {
|
||||
parseStyleLayers(style.layers);
|
||||
}
|
||||
|
||||
bool TileParser::obsolete() const {
|
||||
return tile.state == TileData::State::obsolete;
|
||||
void TileParser::parse() {
|
||||
parseStyleLayers(style->layers);
|
||||
}
|
||||
|
||||
void TileParser::addGlyph(uint64_t tileid, const std::string stackname, const std::u32string &string, const FontStack &fontStack, GlyphAtlas &glyphAtlas, GlyphPositions &face) {
|
||||
bool TileParser::obsolete() const { return tile.state == TileData::State::obsolete; }
|
||||
|
||||
void TileParser::addGlyph(uint64_t tileid, const std::string stackname,
|
||||
const std::u32string &string, const FontStack &fontStack,
|
||||
GlyphAtlas &glyphAtlas, GlyphPositions &face) {
|
||||
std::map<uint32_t, SDFGlyph> sdfs = fontStack.getSDFs();
|
||||
// Loop through all characters and add glyph to atlas, positions.
|
||||
for (uint32_t chr : string) {
|
||||
@@ -42,8 +50,8 @@ void TileParser::addGlyph(uint64_t tileid, const std::string stackname, const st
|
||||
}
|
||||
}
|
||||
|
||||
void TileParser::parseStyleLayers(const std::vector<LayerDescription>& layers) {
|
||||
for (const LayerDescription& layer_desc : layers) {
|
||||
void TileParser::parseStyleLayers(const std::vector<LayerDescription> &layers) {
|
||||
for (const LayerDescription &layer_desc : layers) {
|
||||
// Cancel early when parsing.
|
||||
if (obsolete()) {
|
||||
return;
|
||||
@@ -59,12 +67,11 @@ void TileParser::parseStyleLayers(const std::vector<LayerDescription>& layers) {
|
||||
// parse this bucket.
|
||||
auto bucket_it = tile.buckets.find(layer_desc.bucket_name);
|
||||
if (bucket_it == tile.buckets.end()) {
|
||||
auto bucket_it = style.buckets.find(layer_desc.bucket_name);
|
||||
auto bucket_it = style->buckets.find(layer_desc.bucket_name);
|
||||
if (layer_desc.bucket_name == "background") {
|
||||
// background is a special, fake bucket
|
||||
continue;
|
||||
}
|
||||
else if (bucket_it != style.buckets.end()) {
|
||||
} else if (bucket_it != style->buckets.end()) {
|
||||
// Only create the new bucket if we have an actual specification
|
||||
// for it.
|
||||
std::unique_ptr<Bucket> bucket = createBucket(bucket_it->second);
|
||||
@@ -86,10 +93,10 @@ void TileParser::parseStyleLayers(const std::vector<LayerDescription>& layers) {
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<Bucket> TileParser::createBucket(const BucketDescription& bucket_desc) {
|
||||
std::unique_ptr<Bucket> TileParser::createBucket(const BucketDescription &bucket_desc) {
|
||||
auto layer_it = vector_data.layers.find(bucket_desc.source_layer);
|
||||
if (layer_it != vector_data.layers.end()) {
|
||||
const VectorTileLayer& layer = layer_it->second;
|
||||
const VectorTileLayer &layer = layer_it->second;
|
||||
if (bucket_desc.type == BucketType::Fill) {
|
||||
return createFillBucket(layer, bucket_desc);
|
||||
} else if (bucket_desc.type == BucketType::Line) {
|
||||
@@ -114,10 +121,12 @@ std::unique_ptr<Bucket> TileParser::createBucket(const BucketDescription& bucket
|
||||
}
|
||||
|
||||
template <class Bucket>
|
||||
void TileParser::addBucketFeatures(Bucket& bucket, const VectorTileLayer& layer, const BucketDescription& bucket_desc) {
|
||||
void TileParser::addBucketFeatures(Bucket &bucket, const VectorTileLayer &layer,
|
||||
const BucketDescription &bucket_desc) {
|
||||
FilteredVectorTileLayer filtered_layer(layer, bucket_desc);
|
||||
for (pbf feature : filtered_layer) {
|
||||
if (obsolete()) return;
|
||||
if (obsolete())
|
||||
return;
|
||||
|
||||
while (feature.next(4)) { // geometry
|
||||
pbf geometry_pbf = feature.message();
|
||||
@@ -130,39 +139,45 @@ void TileParser::addBucketFeatures(Bucket& bucket, const VectorTileLayer& layer,
|
||||
}
|
||||
}
|
||||
|
||||
template <class Bucket, typename ...Args>
|
||||
void TileParser::addBucketFeatures(Bucket& bucket, const VectorTileLayer& layer, const BucketDescription& bucket_desc, Args&& ...args) {
|
||||
template <class Bucket, typename... Args>
|
||||
void TileParser::addBucketFeatures(Bucket &bucket, const VectorTileLayer &layer,
|
||||
const BucketDescription &bucket_desc, Args &&... args) {
|
||||
FilteredVectorTileLayer filtered_layer(layer, bucket_desc);
|
||||
for (const pbf& feature_pbf : filtered_layer) {
|
||||
if (obsolete()) return;
|
||||
bucket->addFeature({ feature_pbf, layer }, std::forward<Args>(args)...);
|
||||
for (const pbf &feature_pbf : filtered_layer) {
|
||||
if (obsolete())
|
||||
return;
|
||||
bucket->addFeature({feature_pbf, layer}, std::forward<Args>(args)...);
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<Bucket> TileParser::createFillBucket(const VectorTileLayer& layer, const BucketDescription& bucket_desc) {
|
||||
std::unique_ptr<Bucket> TileParser::createFillBucket(const VectorTileLayer &layer,
|
||||
const BucketDescription &bucket_desc) {
|
||||
std::unique_ptr<FillBucket> bucket = std::make_unique<FillBucket>(
|
||||
tile.fillVertexBuffer, tile.triangleElementsBuffer, tile.lineElementsBuffer, bucket_desc);
|
||||
addBucketFeatures(bucket, layer, bucket_desc);
|
||||
return obsolete() ? nullptr : std::move(bucket);
|
||||
}
|
||||
|
||||
std::unique_ptr<Bucket> TileParser::createLineBucket(const VectorTileLayer& layer, const BucketDescription& bucket_desc) {
|
||||
std::unique_ptr<Bucket> TileParser::createLineBucket(const VectorTileLayer &layer,
|
||||
const BucketDescription &bucket_desc) {
|
||||
std::unique_ptr<LineBucket> bucket = std::make_unique<LineBucket>(
|
||||
tile.lineVertexBuffer, tile.triangleElementsBuffer, tile.pointElementsBuffer, bucket_desc);
|
||||
addBucketFeatures(bucket, layer, bucket_desc);
|
||||
return obsolete() ? nullptr : std::move(bucket);
|
||||
}
|
||||
|
||||
std::unique_ptr<Bucket> TileParser::createIconBucket(const VectorTileLayer& layer, const BucketDescription& bucket_desc) {
|
||||
std::unique_ptr<IconBucket> bucket = std::make_unique<IconBucket>(
|
||||
tile.iconVertexBuffer, bucket_desc);
|
||||
addBucketFeatures(bucket, layer, bucket_desc, spriteAtlas);
|
||||
std::unique_ptr<Bucket> TileParser::createIconBucket(const VectorTileLayer &layer,
|
||||
const BucketDescription &bucket_desc) {
|
||||
std::unique_ptr<IconBucket> bucket =
|
||||
std::make_unique<IconBucket>(tile.iconVertexBuffer, bucket_desc);
|
||||
addBucketFeatures(bucket, layer, bucket_desc, *spriteAtlas);
|
||||
return obsolete() ? nullptr : std::move(bucket);
|
||||
}
|
||||
|
||||
typedef std::pair<uint16_t, uint16_t> GlyphRange;
|
||||
|
||||
std::unique_ptr<Bucket> TileParser::createTextBucket(const VectorTileLayer& layer, const BucketDescription& bucket_desc) {
|
||||
std::unique_ptr<Bucket> TileParser::createTextBucket(const VectorTileLayer &layer,
|
||||
const BucketDescription &bucket_desc) {
|
||||
std::unique_ptr<TextBucket> bucket = std::make_unique<TextBucket>(
|
||||
tile.textVertexBuffer, tile.triangleElementsBuffer, bucket_desc, placement);
|
||||
|
||||
@@ -173,15 +188,18 @@ std::unique_ptr<Bucket> TileParser::createTextBucket(const VectorTileLayer& laye
|
||||
std::set<GlyphRange> ranges;
|
||||
|
||||
FilteredVectorTileLayer filtered_layer(layer, bucket_desc);
|
||||
for (const pbf& feature_pbf : filtered_layer) {
|
||||
if (obsolete()) return nullptr;
|
||||
VectorTileFeature feature { feature_pbf, layer };
|
||||
for (const pbf &feature_pbf : filtered_layer) {
|
||||
if (obsolete())
|
||||
return nullptr;
|
||||
VectorTileFeature feature{feature_pbf, layer};
|
||||
|
||||
auto it_prop = feature.properties.find(bucket_desc.geometry.field);
|
||||
if (it_prop == feature.properties.end()) {
|
||||
// feature does not have the correct property
|
||||
if (debug::labelTextMissingWarning) {
|
||||
fprintf(stderr, "[WARNING] feature doesn't have property '%s' required for labelling\n", bucket_desc.geometry.field.c_str());
|
||||
fprintf(stderr,
|
||||
"[WARNING] feature doesn't have property '%s' required for labelling\n",
|
||||
bucket_desc.geometry.field.c_str());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -194,25 +212,28 @@ std::unique_ptr<Bucket> TileParser::createTextBucket(const VectorTileLayer& laye
|
||||
}
|
||||
}
|
||||
|
||||
glyphStore.waitForGlyphRanges(bucket_desc.geometry.font, ranges);
|
||||
glyphStore->waitForGlyphRanges(bucket_desc.geometry.font, ranges);
|
||||
}
|
||||
|
||||
// Create a copy!
|
||||
const FontStack &fontStack = glyphStore.getFontStack(bucket_desc.geometry.font);
|
||||
const FontStack &fontStack = glyphStore->getFontStack(bucket_desc.geometry.font);
|
||||
GlyphPositions face;
|
||||
|
||||
// Shape and place all labels.
|
||||
{
|
||||
FilteredVectorTileLayer filtered_layer(layer, bucket_desc);
|
||||
for (const pbf& feature_pbf : filtered_layer) {
|
||||
if (obsolete()) return nullptr;
|
||||
VectorTileFeature feature { feature_pbf, layer };
|
||||
for (const pbf &feature_pbf : filtered_layer) {
|
||||
if (obsolete())
|
||||
return nullptr;
|
||||
VectorTileFeature feature{feature_pbf, layer};
|
||||
|
||||
auto it_prop = feature.properties.find(bucket_desc.geometry.field);
|
||||
if (it_prop == feature.properties.end()) {
|
||||
// feature does not have the correct property
|
||||
if (debug::labelTextMissingWarning) {
|
||||
fprintf(stderr, "[WARNING] feature doesn't have property '%s' required for labelling\n", bucket_desc.geometry.field.c_str());
|
||||
fprintf(stderr,
|
||||
"[WARNING] feature doesn't have property '%s' required for labelling\n",
|
||||
bucket_desc.geometry.field.c_str());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -224,7 +245,8 @@ std::unique_ptr<Bucket> TileParser::createTextBucket(const VectorTileLayer& laye
|
||||
const Shaping shaping = fontStack.getShaping(string);
|
||||
|
||||
// Place labels.
|
||||
addGlyph(tile.id.to_uint64(), bucket_desc.geometry.font, string, fontStack, glyphAtlas, face);
|
||||
addGlyph(tile.id.to_uint64(), bucket_desc.geometry.font, string, fontStack, *glyphAtlas,
|
||||
face);
|
||||
|
||||
bucket->addFeature(feature.geometry, face, shaping);
|
||||
}
|
||||
@@ -232,4 +254,3 @@ std::unique_ptr<Bucket> TileParser::createTextBucket(const VectorTileLayer& laye
|
||||
|
||||
return std::move(bucket);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include <llmr/map/vector_tile_data.hpp>
|
||||
|
||||
#include <llmr/util/std.hpp>
|
||||
#include <llmr/map/map.hpp>
|
||||
#include <llmr/map/tile_parser.hpp>
|
||||
|
||||
using namespace llmr;
|
||||
|
||||
@@ -10,7 +9,11 @@ VectorTileData::VectorTileData(Tile::ID id, Map &map, const std::string url)
|
||||
}
|
||||
|
||||
VectorTileData::~VectorTileData() {
|
||||
map.getGlyphAtlas().removeGlyphs(id.to_uint64());
|
||||
map.getGlyphAtlas()->removeGlyphs(id.to_uint64());
|
||||
}
|
||||
|
||||
void VectorTileData::beforeParse() {
|
||||
parser = std::make_unique<TileParser>(data, *this, map.getStyle(), map.getGlyphAtlas(), map.getGlyphStore(), map.getSpriteAtlas());
|
||||
}
|
||||
|
||||
void VectorTileData::parse() {
|
||||
@@ -22,7 +25,7 @@ void VectorTileData::parse() {
|
||||
// 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(data, *this, map.getStyle(), map.getGlyphAtlas(), map.getGlyphStore(), map.getSpriteAtlas());
|
||||
parser->parse();
|
||||
} catch (const std::exception& ex) {
|
||||
#if defined(DEBUG)
|
||||
fprintf(stderr, "[%p] exception [%d/%d/%d]... failed: %s\n", this, id.z, id.x, id.y, ex.what());
|
||||
@@ -36,6 +39,10 @@ void VectorTileData::parse() {
|
||||
}
|
||||
}
|
||||
|
||||
void VectorTileData::afterParse() {
|
||||
parser.reset();
|
||||
}
|
||||
|
||||
void VectorTileData::render(Painter &painter, const LayerDescription& layer_desc) {
|
||||
auto databucket_it = buckets.find(layer_desc.bucket_name);
|
||||
if (databucket_it != buckets.end()) {
|
||||
|
||||
@@ -15,11 +15,13 @@ void Painter::drawClippingMasks(const Sources &sources) {
|
||||
glDepthRange(1.0f, 1.0f);
|
||||
glStencilMask(0xFF);
|
||||
|
||||
Color background = map.getStyle().computed.background.color;
|
||||
background[0] *= map.getStyle().computed.background.opacity;
|
||||
background[1] *= map.getStyle().computed.background.opacity;
|
||||
background[2] *= map.getStyle().computed.background.opacity;
|
||||
background[3] *= map.getStyle().computed.background.opacity;
|
||||
const BackgroundProperties &properties = map.getStyle()->computed.background;
|
||||
Color background = properties.color;
|
||||
const float opacity = properties.opacity;
|
||||
background[0] *= opacity;
|
||||
background[1] *= opacity;
|
||||
background[2] *= opacity;
|
||||
background[3] *= opacity;
|
||||
plainShader->setColor(background);
|
||||
|
||||
coveringPlainArray.bind(*plainShader, tileStencilBuffer, BUFFER_OFFSET(0));
|
||||
|
||||
@@ -65,9 +65,9 @@ void Painter::renderFill(FillBucket& bucket, const FillProperties& properties, c
|
||||
}
|
||||
|
||||
if ((fill_color[3] >= 1.0f) == (pass == Opaque)) {
|
||||
auto &sprite = map.getStyle().sprite;
|
||||
const std::shared_ptr<Sprite> &sprite = map.getStyle()->sprite;
|
||||
if (properties.image.size() && sprite) {
|
||||
auto &spriteAtlas = map.getSpriteAtlas();
|
||||
SpriteAtlas &spriteAtlas = *map.getSpriteAtlas();
|
||||
Rect<uint16_t> imagePos = spriteAtlas.getImage(properties.image, *sprite);
|
||||
|
||||
|
||||
@@ -144,7 +144,7 @@ void Painter::renderFill(FillBucket& bucket, const std::string& layer_name, cons
|
||||
// Abort early.
|
||||
if (!bucket.hasData()) return;
|
||||
|
||||
const std::unordered_map<std::string, FillProperties> &fill_properties = map.getStyle().computed.fills;
|
||||
const std::unordered_map<std::string, FillProperties> &fill_properties = map.getStyle()->computed.fills;
|
||||
const std::unordered_map<std::string, FillProperties>::const_iterator fill_properties_it = fill_properties.find(layer_name);
|
||||
|
||||
const FillProperties &properties = fill_properties_it != fill_properties.end()
|
||||
|
||||
@@ -11,7 +11,7 @@ void Painter::renderIcon(IconBucket& bucket, const std::string& layer_name, cons
|
||||
if (!bucket.hasData()) return;
|
||||
if (pass == Opaque) return;
|
||||
|
||||
const std::unordered_map<std::string, IconProperties> &icon_properties = map.getStyle().computed.icons;
|
||||
const std::unordered_map<std::string, IconProperties> &icon_properties = map.getStyle()->computed.icons;
|
||||
const std::unordered_map<std::string, IconProperties>::const_iterator icon_properties_it = icon_properties.find(layer_name);
|
||||
|
||||
const IconProperties &properties = icon_properties_it != icon_properties.end()
|
||||
@@ -27,7 +27,7 @@ void Painter::renderIcon(IconBucket& bucket, const std::string& layer_name, cons
|
||||
|
||||
const mat4 &vtxMatrix = translatedMatrix(properties.translate, id, properties.translateAnchor);
|
||||
|
||||
SpriteAtlas &spriteAtlas = map.getSpriteAtlas();
|
||||
SpriteAtlas &spriteAtlas = *map.getSpriteAtlas();
|
||||
|
||||
useProgram(iconShader->program);
|
||||
iconShader->setMatrix(vtxMatrix);
|
||||
|
||||
@@ -9,7 +9,7 @@ void Painter::renderLine(LineBucket& bucket, const std::string& layer_name, cons
|
||||
if (pass == Opaque) return;
|
||||
if (!bucket.hasData()) return;
|
||||
|
||||
const std::unordered_map<std::string, LineProperties> &line_properties = map.getStyle().computed.lines;
|
||||
const std::unordered_map<std::string, LineProperties> &line_properties = map.getStyle()->computed.lines;
|
||||
const std::unordered_map<std::string, LineProperties>::const_iterator line_properties_it = line_properties.find(layer_name);
|
||||
|
||||
const LineProperties &properties = line_properties_it != line_properties.end()
|
||||
|
||||
@@ -7,7 +7,7 @@ using namespace llmr;
|
||||
void Painter::renderRaster(RasterBucket& bucket, const std::string& layer_name, const Tile::ID& /*id*/) {
|
||||
if (pass == Translucent) return;
|
||||
|
||||
const std::unordered_map<std::string, RasterProperties> &raster_properties = map.getStyle().computed.rasters;
|
||||
const std::unordered_map<std::string, RasterProperties> &raster_properties = map.getStyle()->computed.rasters;
|
||||
const std::unordered_map<std::string, RasterProperties>::const_iterator raster_properties_it = raster_properties.find(layer_name);
|
||||
|
||||
const RasterProperties &properties = raster_properties_it != raster_properties.end()
|
||||
|
||||
@@ -10,7 +10,7 @@ void Painter::renderText(TextBucket& bucket, const std::string& layer_name, cons
|
||||
if (pass == Opaque) return;
|
||||
if (!bucket.hasData()) return;
|
||||
|
||||
const std::unordered_map<std::string, TextProperties> &text_properties = map.getStyle().computed.texts;
|
||||
const std::unordered_map<std::string, TextProperties> &text_properties = map.getStyle()->computed.texts;
|
||||
const std::unordered_map<std::string, TextProperties>::const_iterator text_properties_it = text_properties.find(layer_name);
|
||||
|
||||
const TextProperties &properties = text_properties_it != text_properties.end()
|
||||
@@ -39,9 +39,10 @@ void Painter::renderText(TextBucket& bucket, const std::string& layer_name, cons
|
||||
textShader->setMatrix(vtxMatrix);
|
||||
textShader->setExtrudeMatrix(exMatrix);
|
||||
|
||||
map.getGlyphAtlas().bind();
|
||||
textShader->setTextureSize({{static_cast<float>(map.getGlyphAtlas().width),
|
||||
static_cast<float>(map.getGlyphAtlas().height)}});
|
||||
GlyphAtlas &glyphAtlas = *map.getGlyphAtlas();
|
||||
glyphAtlas.bind();
|
||||
textShader->setTextureSize({{static_cast<float>(glyphAtlas.width),
|
||||
static_cast<float>(glyphAtlas.height)}});
|
||||
|
||||
// Convert the -pi..pi to an int8 range.
|
||||
float angle = std::round((map.getState().getAngle() + rotate) / M_PI * 128);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
using namespace llmr;
|
||||
|
||||
RasterBucket::RasterBucket(Texturepool &texturepool)
|
||||
RasterBucket::RasterBucket(const std::shared_ptr<Texturepool> &texturepool)
|
||||
: raster(texturepool) {
|
||||
}
|
||||
|
||||
|
||||
@@ -14,13 +14,13 @@
|
||||
|
||||
using namespace llmr;
|
||||
|
||||
Raster::Raster(Texturepool &texturepool)
|
||||
Raster::Raster(const std::shared_ptr<Texturepool> &texturepool)
|
||||
: texturepool(texturepool)
|
||||
{}
|
||||
|
||||
Raster::~Raster() {
|
||||
if (textured) {
|
||||
texturepool.removeTextureID(texture);
|
||||
texturepool->removeTextureID(texture);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ void Raster::bind(bool linear) {
|
||||
}
|
||||
|
||||
if (img && !textured) {
|
||||
texture = texturepool.getTextureID();
|
||||
texture = texturepool->getTextureID();
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
Reference in New Issue
Block a user