Merge pull request #901 from mapbox/const-style-bucket
Make StyleLayout* objects immutable
This commit is contained in:
@@ -7,7 +7,7 @@ using namespace mbgl;
|
||||
|
||||
RasterTileData::RasterTileData(Tile::ID const& id_, TexturePool& texturePool, const SourceInfo& source_, FileSource& fileSource_)
|
||||
: TileData(id_, source_, fileSource_),
|
||||
bucket(texturePool, properties) {
|
||||
bucket(texturePool, layout) {
|
||||
}
|
||||
|
||||
RasterTileData::~RasterTileData() {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <mbgl/map/tile.hpp>
|
||||
#include <mbgl/map/tile_data.hpp>
|
||||
#include <mbgl/style/style_layout.hpp>
|
||||
#include <mbgl/renderer/raster_bucket.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
@@ -24,7 +25,7 @@ public:
|
||||
virtual bool hasData(StyleLayer const& layer_desc) const;
|
||||
|
||||
protected:
|
||||
StyleBucketRaster properties;
|
||||
StyleLayoutRaster layout;
|
||||
RasterBucket bucket;
|
||||
};
|
||||
|
||||
|
||||
@@ -190,7 +190,7 @@ TileData::State Source::addTile(Map& map, uv::worker& worker,
|
||||
new_tile.data = std::make_shared<VectorTileData>(normalized_id, map.getMaxZoom(), style,
|
||||
glyphAtlas, glyphStore,
|
||||
spriteAtlas, sprite,
|
||||
texturePool, info, fileSource);
|
||||
info, fileSource);
|
||||
} else if (info.type == SourceType::Raster) {
|
||||
new_tile.data = std::make_shared<RasterTileData>(normalized_id, texturePool, info, fileSource);
|
||||
} else {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <mbgl/style/style.hpp>
|
||||
#include <mbgl/style/style_layer.hpp>
|
||||
#include <mbgl/style/style_layer_group.hpp>
|
||||
#include <mbgl/style/style_layout.hpp>
|
||||
#include <mbgl/renderer/fill_bucket.hpp>
|
||||
#include <mbgl/renderer/line_bucket.hpp>
|
||||
#include <mbgl/renderer/symbol_bucket.hpp>
|
||||
@@ -33,8 +34,7 @@ TileParser::TileParser(const std::string &data, VectorTileData &tile_,
|
||||
GlyphAtlas & glyphAtlas_,
|
||||
GlyphStore & glyphStore_,
|
||||
SpriteAtlas & spriteAtlas_,
|
||||
const util::ptr<Sprite> &sprite_,
|
||||
TexturePool& texturePool_)
|
||||
const util::ptr<Sprite> &sprite_)
|
||||
: vector_data(pbf((const uint8_t *)data.data(), data.size())),
|
||||
tile(tile_),
|
||||
style(style_),
|
||||
@@ -42,7 +42,6 @@ TileParser::TileParser(const std::string &data, VectorTileData &tile_,
|
||||
glyphStore(glyphStore_),
|
||||
spriteAtlas(spriteAtlas_),
|
||||
sprite(sprite_),
|
||||
texturePool(texturePool_),
|
||||
collision(util::make_unique<Collision>(tile.id.z, 4096, tile.source.tile_size, tile.depth)) {
|
||||
assert(&tile != nullptr);
|
||||
assert(style);
|
||||
@@ -56,12 +55,12 @@ void TileParser::parse() {
|
||||
|
||||
bool TileParser::obsolete() const { return tile.state == TileData::State::obsolete; }
|
||||
|
||||
void TileParser::parseStyleLayers(util::ptr<StyleLayerGroup> group) {
|
||||
void TileParser::parseStyleLayers(util::ptr<const StyleLayerGroup> group) {
|
||||
if (!group) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const util::ptr<StyleLayer> &layer_desc : group->layers) {
|
||||
for (const util::ptr<const StyleLayer> &layer_desc : group->layers) {
|
||||
// Cancel early when parsing.
|
||||
if (obsolete()) {
|
||||
return;
|
||||
@@ -78,7 +77,7 @@ void TileParser::parseStyleLayers(util::ptr<StyleLayerGroup> group) {
|
||||
auto bucket_it = tile.buckets.find(layer_desc->bucket->name);
|
||||
if (bucket_it == tile.buckets.end()) {
|
||||
// We need to create this bucket since it doesn't exist yet.
|
||||
std::unique_ptr<Bucket> bucket = createBucket(layer_desc->bucket);
|
||||
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.
|
||||
@@ -115,35 +114,33 @@ private:
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
void TileParser::applyLayoutProperty(PropertyKey key, ClassProperties &classProperties, T &target, const float z) {
|
||||
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);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
void TileParser::applyLayoutProperties<FillProperties>(StyleBucket &bucket_desc, const float) {
|
||||
bucket_desc.render.set<StyleBucketFill>();
|
||||
std::unique_ptr<StyleLayoutFill> parseStyleLayoutFill(const StyleBucket &/*bucket*/, const float /*z*/) {
|
||||
// no-op; Fill buckets don't currently have any applicable layout properties
|
||||
auto fillPtr = util::make_unique<StyleLayoutFill>();
|
||||
return fillPtr;
|
||||
}
|
||||
|
||||
template<>
|
||||
void TileParser::applyLayoutProperties<LineProperties>(StyleBucket &bucket_desc, const float z) {
|
||||
bucket_desc.render.set<StyleBucketLine>();
|
||||
StyleBucketLine &line = bucket_desc.render.get<StyleBucketLine>();
|
||||
std::unique_ptr<StyleLayoutLine> parseStyleLayoutLine(const StyleBucket &bucket_desc, const float z) {
|
||||
auto linePtr = util::make_unique<StyleLayoutLine>();
|
||||
auto &line = *linePtr;
|
||||
applyLayoutProperty(PropertyKey::LineCap, bucket_desc.layout, line.cap, z);
|
||||
applyLayoutProperty(PropertyKey::LineJoin, bucket_desc.layout, line.join, z);
|
||||
applyLayoutProperty(PropertyKey::LineMiterLimit, bucket_desc.layout, line.miter_limit, z);
|
||||
applyLayoutProperty(PropertyKey::LineRoundLimit, bucket_desc.layout, line.round_limit, z);
|
||||
return linePtr;
|
||||
}
|
||||
|
||||
template<>
|
||||
void TileParser::applyLayoutProperties<SymbolProperties>(StyleBucket &bucket_desc, const float z) {
|
||||
bucket_desc.render.set<StyleBucketSymbol>();
|
||||
StyleBucketSymbol &symbol = bucket_desc.render.get<StyleBucketSymbol>();
|
||||
std::unique_ptr<StyleLayoutSymbol> parseStyleLayoutSymbol(const StyleBucket &bucket_desc, const float z) {
|
||||
auto symbolPtr = util::make_unique<StyleLayoutSymbol>();
|
||||
auto &symbol = *symbolPtr;
|
||||
applyLayoutProperty(PropertyKey::SymbolPlacement, bucket_desc.layout, symbol.placement, z);
|
||||
if (symbol.placement == PlacementType::Line) {
|
||||
symbol.icon.rotation_alignment = RotationAlignmentType::Map;
|
||||
@@ -181,41 +178,34 @@ void TileParser::applyLayoutProperties<SymbolProperties>(StyleBucket &bucket_des
|
||||
applyLayoutProperty(PropertyKey::TextTransform, bucket_desc.layout, symbol.text.transform, z);
|
||||
applyLayoutProperty(PropertyKey::TextOffset, bucket_desc.layout, symbol.text.offset, z);
|
||||
applyLayoutProperty(PropertyKey::TextAllowOverlap, bucket_desc.layout, symbol.text.allow_overlap, z);
|
||||
return symbolPtr;
|
||||
}
|
||||
|
||||
std::unique_ptr<Bucket> TileParser::createBucket(util::ptr<StyleBucket> bucket_desc) {
|
||||
if (!bucket_desc) {
|
||||
fprintf(stderr, "missing bucket desc\n");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<Bucket> TileParser::createBucket(const StyleBucket &bucket_desc) {
|
||||
// Skip this bucket if we are to not render this
|
||||
if (tile.id.z < std::floor(bucket_desc->min_zoom) && std::floor(bucket_desc->min_zoom) < tile.source.max_zoom) return nullptr;
|
||||
if (tile.id.z >= std::ceil(bucket_desc->max_zoom)) return nullptr;
|
||||
if (bucket_desc->visibility == mbgl::VisibilityType::None) return nullptr;
|
||||
if (tile.id.z < std::floor(bucket_desc.min_zoom) && std::floor(bucket_desc.min_zoom) < tile.source.max_zoom) return nullptr;
|
||||
if (tile.id.z >= std::ceil(bucket_desc.max_zoom)) return nullptr;
|
||||
if (bucket_desc.visibility == mbgl::VisibilityType::None) return nullptr;
|
||||
|
||||
auto layer_it = vector_data.layers.find(bucket_desc->source_layer);
|
||||
auto layer_it = vector_data.layers.find(bucket_desc.source_layer);
|
||||
if (layer_it != vector_data.layers.end()) {
|
||||
const VectorTileLayer &layer = layer_it->second;
|
||||
if (bucket_desc->type == StyleLayerType::Fill) {
|
||||
applyLayoutProperties<FillProperties>(*bucket_desc, tile.id.z);
|
||||
return createFillBucket(layer, bucket_desc->filter, bucket_desc->render.get<StyleBucketFill>());
|
||||
} else if (bucket_desc->type == StyleLayerType::Line) {
|
||||
applyLayoutProperties<LineProperties>(*bucket_desc, tile.id.z);
|
||||
return createLineBucket(layer, bucket_desc->filter, bucket_desc->render.get<StyleBucketLine>());
|
||||
} else if (bucket_desc->type == StyleLayerType::Symbol) {
|
||||
applyLayoutProperties<SymbolProperties>(*bucket_desc, tile.id.z);
|
||||
return createSymbolBucket(layer, bucket_desc->filter, bucket_desc->render.get<StyleBucketSymbol>());
|
||||
} else if (bucket_desc->type == StyleLayerType::Raster) {
|
||||
if (bucket_desc.type == StyleLayerType::Fill) {
|
||||
return createFillBucket(layer, bucket_desc);
|
||||
} else if (bucket_desc.type == StyleLayerType::Line) {
|
||||
return createLineBucket(layer, bucket_desc);
|
||||
} else if (bucket_desc.type == StyleLayerType::Symbol) {
|
||||
return createSymbolBucket(layer, bucket_desc);
|
||||
} else if (bucket_desc.type == StyleLayerType::Raster) {
|
||||
return nullptr;
|
||||
} else {
|
||||
fprintf(stderr, "[WARNING] unknown bucket render type for layer '%s' (source layer '%s')\n", bucket_desc->name.c_str(), bucket_desc->source_layer.c_str());
|
||||
fprintf(stderr, "[WARNING] unknown bucket render type for layer '%s' (source layer '%s')\n", bucket_desc.name.c_str(), bucket_desc.source_layer.c_str());
|
||||
}
|
||||
} else {
|
||||
// The layer specified in the bucket does not exist. Do nothing.
|
||||
if (debug::tileParseWarnings) {
|
||||
fprintf(stderr, "[WARNING] layer '%s' does not exist in tile %d/%d/%d\n",
|
||||
bucket_desc->source_layer.c_str(), tile.id.z, tile.id.x, tile.id.y);
|
||||
bucket_desc.source_layer.c_str(), tile.id.z, tile.id.x, tile.id.y);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,27 +230,34 @@ void TileParser::addBucketGeometries(Bucket& bucket, const VectorTileLayer& laye
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<Bucket> TileParser::createFillBucket(const VectorTileLayer& layer, const FilterExpression &filter, const StyleBucketFill &fill) {
|
||||
std::unique_ptr<FillBucket> bucket = util::make_unique<FillBucket>(tile.fillVertexBuffer, tile.triangleElementsBuffer, tile.lineElementsBuffer, fill);
|
||||
addBucketGeometries(bucket, layer, filter);
|
||||
std::unique_ptr<Bucket> TileParser::createFillBucket(const VectorTileLayer &layer,
|
||||
const StyleBucket &bucket_desc) {
|
||||
auto fill = parseStyleLayoutFill(bucket_desc, tile.id.z);
|
||||
auto bucket = util::make_unique<FillBucket>(std::move(fill),
|
||||
tile.fillVertexBuffer,
|
||||
tile.triangleElementsBuffer,
|
||||
tile.lineElementsBuffer);
|
||||
addBucketGeometries(bucket, layer, bucket_desc.filter);
|
||||
return obsolete() ? nullptr : std::move(bucket);
|
||||
}
|
||||
|
||||
std::unique_ptr<Bucket> TileParser::createRasterBucket(const StyleBucketRaster &raster) {
|
||||
std::unique_ptr<RasterBucket> bucket = util::make_unique<RasterBucket>(texturePool, raster);
|
||||
std::unique_ptr<Bucket> TileParser::createLineBucket(const VectorTileLayer &layer,
|
||||
const StyleBucket &bucket_desc) {
|
||||
auto line = parseStyleLayoutLine(bucket_desc, tile.id.z);
|
||||
auto bucket = util::make_unique<LineBucket>(std::move(line),
|
||||
tile.lineVertexBuffer,
|
||||
tile.triangleElementsBuffer,
|
||||
tile.pointElementsBuffer);
|
||||
addBucketGeometries(bucket, layer, bucket_desc.filter);
|
||||
return obsolete() ? nullptr : std::move(bucket);
|
||||
}
|
||||
|
||||
std::unique_ptr<Bucket> TileParser::createLineBucket(const VectorTileLayer& layer, const FilterExpression &filter, const StyleBucketLine &line) {
|
||||
std::unique_ptr<LineBucket> bucket = util::make_unique<LineBucket>(tile.lineVertexBuffer, tile.triangleElementsBuffer, tile.pointElementsBuffer, line);
|
||||
addBucketGeometries(bucket, layer, filter);
|
||||
std::unique_ptr<Bucket> TileParser::createSymbolBucket(const VectorTileLayer &layer,
|
||||
const StyleBucket &bucket_desc) {
|
||||
auto symbol = parseStyleLayoutSymbol(bucket_desc, tile.id.z);
|
||||
auto bucket = util::make_unique<SymbolBucket>(std::move(symbol), *collision);
|
||||
bucket->addFeatures(
|
||||
layer, bucket_desc.filter, tile.id, spriteAtlas, *sprite, glyphAtlas, glyphStore);
|
||||
return obsolete() ? nullptr : std::move(bucket);
|
||||
}
|
||||
|
||||
std::unique_ptr<Bucket> TileParser::createSymbolBucket(const VectorTileLayer& layer, const FilterExpression &filter, const StyleBucketSymbol &symbol) {
|
||||
std::unique_ptr<SymbolBucket> bucket = util::make_unique<SymbolBucket>(symbol, *collision);
|
||||
bucket->addFeatures(layer, filter, tile.id, spriteAtlas, *sprite, glyphAtlas, glyphStore);
|
||||
return obsolete() ? nullptr : std::move(bucket);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,10 +23,10 @@ class SpriteAtlas;
|
||||
class Sprite;
|
||||
class Style;
|
||||
class StyleBucket;
|
||||
class StyleBucketFill;
|
||||
class StyleBucketRaster;
|
||||
class StyleBucketLine;
|
||||
class StyleBucketSymbol;
|
||||
class StyleLayoutFill;
|
||||
class StyleLayoutRaster;
|
||||
class StyleLayoutLine;
|
||||
class StyleLayoutSymbol;
|
||||
class StyleLayerGroup;
|
||||
class VectorTileData;
|
||||
class Collision;
|
||||
@@ -40,8 +40,7 @@ public:
|
||||
GlyphAtlas & glyphAtlas,
|
||||
GlyphStore & glyphStore,
|
||||
SpriteAtlas & spriteAtlas,
|
||||
const util::ptr<Sprite> &sprite,
|
||||
TexturePool& texturePool);
|
||||
const util::ptr<Sprite> &sprite);
|
||||
~TileParser();
|
||||
|
||||
public:
|
||||
@@ -49,17 +48,12 @@ public:
|
||||
|
||||
private:
|
||||
bool obsolete() const;
|
||||
void parseStyleLayers(util::ptr<StyleLayerGroup> group);
|
||||
void parseStyleLayers(util::ptr<const StyleLayerGroup> group);
|
||||
|
||||
template <typename T> void applyLayoutProperties(StyleBucket &bucket, float z);
|
||||
template <typename T> void applyLayoutProperty(PropertyKey key, ClassProperties &classProperties, T &, float z);
|
||||
|
||||
std::unique_ptr<Bucket> createBucket(util::ptr<StyleBucket> bucket_desc);
|
||||
|
||||
std::unique_ptr<Bucket> createFillBucket(const VectorTileLayer& layer, const FilterExpression &filter, const StyleBucketFill &fill);
|
||||
std::unique_ptr<Bucket> createRasterBucket(const StyleBucketRaster &raster);
|
||||
std::unique_ptr<Bucket> createLineBucket(const VectorTileLayer& layer, const FilterExpression &filter, const StyleBucketLine &line);
|
||||
std::unique_ptr<Bucket> createSymbolBucket(const VectorTileLayer& layer, const FilterExpression &filter, const StyleBucketSymbol &symbol);
|
||||
std::unique_ptr<Bucket> createBucket(const StyleBucket &bucket_desc);
|
||||
std::unique_ptr<Bucket> createFillBucket(const VectorTileLayer &layer, const StyleBucket &bucket_desc);
|
||||
std::unique_ptr<Bucket> createLineBucket(const VectorTileLayer& layer, const StyleBucket &bucket_desc);
|
||||
std::unique_ptr<Bucket> createSymbolBucket(const VectorTileLayer& layer, const StyleBucket &bucket_desc);
|
||||
|
||||
template <class Bucket> void addBucketGeometries(Bucket& bucket, const VectorTileLayer& layer, const FilterExpression &filter);
|
||||
|
||||
@@ -73,7 +67,6 @@ private:
|
||||
GlyphStore & glyphStore;
|
||||
SpriteAtlas & spriteAtlas;
|
||||
util::ptr<Sprite> sprite;
|
||||
TexturePool& texturePool;
|
||||
|
||||
std::unique_ptr<Collision> collision;
|
||||
};
|
||||
|
||||
@@ -13,14 +13,12 @@ VectorTileData::VectorTileData(Tile::ID const& id_,
|
||||
float mapMaxZoom, util::ptr<Style> style_,
|
||||
GlyphAtlas& glyphAtlas_, GlyphStore& glyphStore_,
|
||||
SpriteAtlas& spriteAtlas_, util::ptr<Sprite> sprite_,
|
||||
TexturePool& texturePool_,
|
||||
const SourceInfo& source_, FileSource &fileSource_)
|
||||
: TileData(id_, source_, fileSource_),
|
||||
glyphAtlas(glyphAtlas_),
|
||||
glyphStore(glyphStore_),
|
||||
spriteAtlas(spriteAtlas_),
|
||||
sprite(sprite_),
|
||||
texturePool(texturePool_),
|
||||
style(style_),
|
||||
depth(id.z >= source.max_zoom ? mapMaxZoom - id.z : 1) {
|
||||
}
|
||||
@@ -45,8 +43,7 @@ void VectorTileData::parse() {
|
||||
// is going to be discarded afterwards.
|
||||
TileParser parser(data, *this, style,
|
||||
glyphAtlas, glyphStore,
|
||||
spriteAtlas, sprite,
|
||||
texturePool);
|
||||
spriteAtlas, sprite);
|
||||
// Clear the style so that we don't have a cycle in the shared_ptr references.
|
||||
style.reset();
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ class GlyphAtlas;
|
||||
class GlyphStore;
|
||||
class SpriteAtlas;
|
||||
class Sprite;
|
||||
class TexturePool;
|
||||
class Style;
|
||||
|
||||
class VectorTileData : public TileData {
|
||||
@@ -35,7 +34,6 @@ public:
|
||||
float mapMaxZoom, util::ptr<Style>,
|
||||
GlyphAtlas&, GlyphStore&,
|
||||
SpriteAtlas&, util::ptr<Sprite>,
|
||||
TexturePool&,
|
||||
const SourceInfo&, FileSource &);
|
||||
~VectorTileData();
|
||||
|
||||
@@ -62,7 +60,6 @@ protected:
|
||||
GlyphStore& glyphStore;
|
||||
SpriteAtlas& spriteAtlas;
|
||||
util::ptr<Sprite> sprite;
|
||||
TexturePool& texturePool;
|
||||
util::ptr<Style> style;
|
||||
|
||||
public:
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include <mbgl/renderer/painter.hpp>
|
||||
#include <mbgl/style/style.hpp>
|
||||
#include <mbgl/style/style_layout.hpp>
|
||||
#include <mbgl/map/vector_tile.hpp>
|
||||
#include <mbgl/util/std.hpp>
|
||||
|
||||
@@ -31,18 +32,22 @@ void FillBucket::free(void *, void *ptr) {
|
||||
::free(ptr);
|
||||
}
|
||||
|
||||
FillBucket::FillBucket(FillVertexBuffer &vertexBuffer_,
|
||||
FillBucket::FillBucket(std::unique_ptr<const StyleLayoutFill> styleLayout_,
|
||||
FillVertexBuffer &vertexBuffer_,
|
||||
TriangleElementsBuffer &triangleElementsBuffer_,
|
||||
LineElementsBuffer &lineElementsBuffer_,
|
||||
const StyleBucketFill &properties_)
|
||||
: properties(properties_),
|
||||
allocator(new TESSalloc{&alloc, &realloc, &free, nullptr, // userData
|
||||
64, // meshEdgeBucketSize
|
||||
64, // meshVertexBucketSize
|
||||
32, // meshFaceBucketSize
|
||||
64, // dictNodeBucketSize
|
||||
8, // regionBucketSize
|
||||
128, // extraVertices allocated for the priority queue.
|
||||
LineElementsBuffer &lineElementsBuffer_)
|
||||
: styleLayout(std::move(styleLayout_)),
|
||||
allocator(new TESSalloc{
|
||||
&alloc,
|
||||
&realloc,
|
||||
&free,
|
||||
nullptr, // userData
|
||||
64, // meshEdgeBucketSize
|
||||
64, // meshVertexBucketSize
|
||||
32, // meshFaceBucketSize
|
||||
64, // dictNodeBucketSize
|
||||
8, // regionBucketSize
|
||||
128, // extraVertices allocated for the priority queue.
|
||||
}),
|
||||
tesselator(tessNewTess(allocator)),
|
||||
vertexBuffer(vertexBuffer_),
|
||||
@@ -52,6 +57,7 @@ FillBucket::FillBucket(FillVertexBuffer &vertexBuffer_,
|
||||
triangle_elements_start(triangleElementsBuffer_.index()),
|
||||
line_elements_start(lineElementsBuffer.index()) {
|
||||
assert(tesselator);
|
||||
assert(styleLayout);
|
||||
}
|
||||
|
||||
FillBucket::~FillBucket() {
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
namespace mbgl {
|
||||
|
||||
class Style;
|
||||
class StyleLayoutFill;
|
||||
class FillVertexBuffer;
|
||||
class TriangleElementsBuffer;
|
||||
class LineElementsBuffer;
|
||||
@@ -38,10 +39,10 @@ class FillBucket : public Bucket {
|
||||
typedef ElementGroup<1> line_group_type;
|
||||
|
||||
public:
|
||||
FillBucket(FillVertexBuffer& vertexBuffer,
|
||||
TriangleElementsBuffer& triangleElementsBuffer,
|
||||
LineElementsBuffer& lineElementsBuffer,
|
||||
const StyleBucketFill& properties);
|
||||
FillBucket(std::unique_ptr<const StyleLayoutFill> styleLayout,
|
||||
FillVertexBuffer &vertexBuffer,
|
||||
TriangleElementsBuffer &triangleElementsBuffer,
|
||||
LineElementsBuffer &lineElementsBuffer);
|
||||
~FillBucket();
|
||||
|
||||
virtual void render(Painter& painter, util::ptr<StyleLayer> layer_desc, const Tile::ID& id, const mat4 &matrix);
|
||||
@@ -55,7 +56,7 @@ public:
|
||||
void drawVertices(OutlineShader& shader);
|
||||
|
||||
public:
|
||||
const StyleBucketFill &properties;
|
||||
const std::unique_ptr<const StyleLayoutFill> styleLayout;
|
||||
|
||||
private:
|
||||
TESSalloc *allocator;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <mbgl/renderer/painter.hpp>
|
||||
#include <mbgl/style/style.hpp>
|
||||
#include <mbgl/style/style_layout.hpp>
|
||||
#include <mbgl/map/vector_tile.hpp>
|
||||
|
||||
#include <mbgl/util/math.hpp>
|
||||
@@ -18,20 +19,25 @@ struct geometry_too_long_exception : std::exception {};
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
LineBucket::LineBucket(LineVertexBuffer& vertexBuffer_,
|
||||
TriangleElementsBuffer& triangleElementsBuffer_,
|
||||
PointElementsBuffer& pointElementsBuffer_,
|
||||
const StyleBucketLine& properties_)
|
||||
: properties(properties_),
|
||||
LineBucket::LineBucket(std::unique_ptr<const StyleLayoutLine> styleLayout_,
|
||||
LineVertexBuffer &vertexBuffer_,
|
||||
TriangleElementsBuffer &triangleElementsBuffer_,
|
||||
PointElementsBuffer &pointElementsBuffer_)
|
||||
: styleLayout(std::move(styleLayout_)),
|
||||
vertexBuffer(vertexBuffer_),
|
||||
triangleElementsBuffer(triangleElementsBuffer_),
|
||||
pointElementsBuffer(pointElementsBuffer_),
|
||||
vertex_start(vertexBuffer_.index()),
|
||||
triangle_elements_start(triangleElementsBuffer_.index()),
|
||||
point_elements_start(pointElementsBuffer_.index())
|
||||
{
|
||||
point_elements_start(pointElementsBuffer_.index()) {
|
||||
assert(styleLayout);
|
||||
}
|
||||
|
||||
LineBucket::~LineBucket() {
|
||||
// Do not remove. header file only contains forward definitions to unique pointers.
|
||||
}
|
||||
|
||||
|
||||
void LineBucket::addGeometry(pbf& geom) {
|
||||
std::vector<Coordinate> line;
|
||||
Geometry::command cmd;
|
||||
@@ -61,6 +67,7 @@ struct TriangleElement {
|
||||
typedef uint16_t PointElement;
|
||||
|
||||
void LineBucket::addGeometry(const std::vector<Coordinate>& vertices) {
|
||||
auto &layout = *styleLayout;
|
||||
// TODO: use roundLimit
|
||||
// const float roundLimit = geometry.round_limit;
|
||||
|
||||
@@ -78,8 +85,8 @@ void LineBucket::addGeometry(const std::vector<Coordinate>& vertices) {
|
||||
return;
|
||||
}
|
||||
|
||||
CapType beginCap = properties.cap;
|
||||
CapType endCap = closed ? CapType::Butt : properties.cap;
|
||||
CapType beginCap = layout.cap;
|
||||
CapType endCap = closed ? CapType::Butt : layout.cap;
|
||||
|
||||
JoinType currentJoin = JoinType::Miter;
|
||||
|
||||
@@ -109,7 +116,7 @@ void LineBucket::addGeometry(const std::vector<Coordinate>& vertices) {
|
||||
if (currentVertex) prevVertex = currentVertex;
|
||||
|
||||
currentVertex = vertices[i];
|
||||
currentJoin = properties.join;
|
||||
currentJoin = layout.join;
|
||||
|
||||
if (prevVertex) distance += util::dist<double>(currentVertex, prevVertex);
|
||||
|
||||
@@ -162,7 +169,7 @@ void LineBucket::addGeometry(const std::vector<Coordinate>& vertices) {
|
||||
|
||||
// Switch to miter joins if the angle is very low.
|
||||
if (currentJoin != JoinType::Miter) {
|
||||
if (std::fabs(joinAngularity) < 0.5 && roundness < properties.miter_limit) {
|
||||
if (std::fabs(joinAngularity) < 0.5 && roundness < layout.miter_limit) {
|
||||
currentJoin = JoinType::Miter;
|
||||
}
|
||||
}
|
||||
@@ -211,14 +218,14 @@ void LineBucket::addGeometry(const std::vector<Coordinate>& vertices) {
|
||||
// The two normals are almost parallel.
|
||||
joinNormal.x = -nextNormal.y;
|
||||
joinNormal.y = nextNormal.x;
|
||||
} else if (roundness > properties.miter_limit) {
|
||||
} else if (roundness > layout.miter_limit) {
|
||||
// If the miter grows too large, flip the direction to make a
|
||||
// bevel join.
|
||||
joinNormal.x = (prevNormal.x - nextNormal.x) / joinAngularity;
|
||||
joinNormal.y = (prevNormal.y - nextNormal.y) / joinAngularity;
|
||||
}
|
||||
|
||||
if (roundness > properties.miter_limit) {
|
||||
if (roundness > layout.miter_limit) {
|
||||
flip = -flip;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,12 +6,14 @@
|
||||
#include <mbgl/geometry/elements_buffer.hpp>
|
||||
#include <mbgl/geometry/line_buffer.hpp>
|
||||
#include <mbgl/style/style_bucket.hpp>
|
||||
#include <mbgl/util/vec.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class Style;
|
||||
class StyleLayoutLine;
|
||||
class LineVertexBuffer;
|
||||
class TriangleElementsBuffer;
|
||||
class LineShader;
|
||||
@@ -25,10 +27,11 @@ class LineBucket : public Bucket {
|
||||
typedef ElementGroup<1> point_group_type;
|
||||
|
||||
public:
|
||||
LineBucket(LineVertexBuffer& vertexBuffer,
|
||||
TriangleElementsBuffer& triangleElementsBuffer,
|
||||
PointElementsBuffer& pointElementsBuffer,
|
||||
const StyleBucketLine& properties);
|
||||
LineBucket(std::unique_ptr<const StyleLayoutLine> styleLayout,
|
||||
LineVertexBuffer &vertexBuffer,
|
||||
TriangleElementsBuffer &triangleElementsBuffer,
|
||||
PointElementsBuffer &pointElementsBuffer);
|
||||
~LineBucket();
|
||||
|
||||
virtual void render(Painter& painter, util::ptr<StyleLayer> layer_desc, const Tile::ID& id, const mat4 &matrix);
|
||||
virtual bool hasData() const;
|
||||
@@ -44,7 +47,7 @@ public:
|
||||
void drawPoints(LinejoinShader& shader);
|
||||
|
||||
public:
|
||||
const StyleBucketLine &properties;
|
||||
const std::unique_ptr<const StyleLayoutLine> styleLayout;
|
||||
|
||||
private:
|
||||
LineVertexBuffer& vertexBuffer;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <mbgl/renderer/fill_bucket.hpp>
|
||||
#include <mbgl/style/style.hpp>
|
||||
#include <mbgl/style/style_layer.hpp>
|
||||
#include <mbgl/style/style_layout.hpp>
|
||||
#include <mbgl/map/map.hpp>
|
||||
#include <mbgl/map/sprite.hpp>
|
||||
#include <mbgl/geometry/sprite_atlas.hpp>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <mbgl/renderer/line_bucket.hpp>
|
||||
#include <mbgl/style/style.hpp>
|
||||
#include <mbgl/style/style_layer.hpp>
|
||||
#include <mbgl/style/style_layout.hpp>
|
||||
#include <mbgl/map/sprite.hpp>
|
||||
#include <mbgl/geometry/sprite_atlas.hpp>
|
||||
#include <mbgl/geometry/line_atlas.hpp>
|
||||
@@ -14,7 +15,8 @@ void Painter::renderLine(LineBucket& bucket, util::ptr<StyleLayer> layer_desc, c
|
||||
if (pass == RenderPass::Opaque) return;
|
||||
if (!bucket.hasData()) return;
|
||||
|
||||
const LineProperties &properties = layer_desc->getProperties<LineProperties>();
|
||||
const auto &properties = layer_desc->getProperties<LineProperties>();
|
||||
const auto &layout = *bucket.styleLayout;
|
||||
|
||||
// the distance over which the line edge fades out.
|
||||
// Retina devices need a smaller distance to avoid aliasing.
|
||||
@@ -81,8 +83,8 @@ void Painter::renderLine(LineBucket& bucket, util::ptr<StyleLayer> layer_desc, c
|
||||
linesdfShader->u_blur = blur;
|
||||
linesdfShader->u_color = color;
|
||||
|
||||
LinePatternPos posA = lineAtlas.getDashPosition(properties.dash_array.from, bucket.properties.cap == CapType::Round);
|
||||
LinePatternPos posB = lineAtlas.getDashPosition(properties.dash_array.to, bucket.properties.cap == CapType::Round);
|
||||
LinePatternPos posA = lineAtlas.getDashPosition(properties.dash_array.from, layout.cap == CapType::Round);
|
||||
LinePatternPos posB = lineAtlas.getDashPosition(properties.dash_array.to, layout.cap == CapType::Round);
|
||||
lineAtlas.bind();
|
||||
|
||||
float patternratio = std::pow(2.0, std::floor(std::log2(state.getScale())) - id.z) / 8.0;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <mbgl/renderer/painter.hpp>
|
||||
#include <mbgl/renderer/symbol_bucket.hpp>
|
||||
#include <mbgl/style/style_layer.hpp>
|
||||
#include <mbgl/style/style_layout.hpp>
|
||||
#include <mbgl/geometry/glyph_atlas.hpp>
|
||||
#include <mbgl/geometry/sprite_atlas.hpp>
|
||||
#include <mbgl/map/map.hpp>
|
||||
@@ -117,7 +118,8 @@ void Painter::renderSymbol(SymbolBucket &bucket, util::ptr<StyleLayer> layer_des
|
||||
return;
|
||||
}
|
||||
|
||||
const SymbolProperties &properties = layer_desc->getProperties<SymbolProperties>();
|
||||
const auto &properties = layer_desc->getProperties<SymbolProperties>();
|
||||
const auto &layout = *bucket.styleLayout;
|
||||
|
||||
MBGL_CHECK_ERROR(glDisable(GL_STENCIL_TEST));
|
||||
|
||||
@@ -125,21 +127,21 @@ void Painter::renderSymbol(SymbolBucket &bucket, util::ptr<StyleLayer> layer_des
|
||||
bool sdf = bucket.sdfIcons;
|
||||
|
||||
const float angleOffset =
|
||||
bucket.properties.icon.rotation_alignment == RotationAlignmentType::Map
|
||||
layout.icon.rotation_alignment == RotationAlignmentType::Map
|
||||
? state.getAngle()
|
||||
: 0;
|
||||
|
||||
// If layerStyle.size > bucket.info.fontSize then labels may collide
|
||||
const float fontSize = properties.icon.size != 0 ? properties.icon.size : bucket.properties.icon.max_size;
|
||||
const float fontSize = properties.icon.size != 0 ? properties.icon.size : layout.icon.max_size;
|
||||
const float fontScale = fontSize / 1.0f;
|
||||
|
||||
spriteAtlas.bind(state.isChanging() || bucket.properties.placement == PlacementType::Line || angleOffset != 0 || fontScale != 1 || sdf);
|
||||
spriteAtlas.bind(state.isChanging() || layout.placement == PlacementType::Line || angleOffset != 0 || fontScale != 1 || sdf);
|
||||
|
||||
if (sdf) {
|
||||
renderSDF(bucket,
|
||||
id,
|
||||
matrix,
|
||||
bucket.properties.icon,
|
||||
layout.icon,
|
||||
properties.icon,
|
||||
1.0f,
|
||||
{{ float(spriteAtlas.getWidth()) / 4.0f, float(spriteAtlas.getHeight()) / 4.0f }},
|
||||
@@ -166,12 +168,12 @@ void Painter::renderSymbol(SymbolBucket &bucket, util::ptr<StyleLayer> layer_des
|
||||
const float angle = std::round(state.getAngle() / M_PI * 128);
|
||||
|
||||
// adjust min/max zooms for variable font sies
|
||||
float zoomAdjust = std::log(fontSize / bucket.properties.icon.max_size) / std::log(2);
|
||||
float zoomAdjust = std::log(fontSize / layout.icon.max_size) / std::log(2);
|
||||
|
||||
iconShader->u_angle = (int32_t)(angle + 256) % 256;
|
||||
|
||||
bool flip = (bucket.properties.icon.rotation_alignment == RotationAlignmentType::Map)
|
||||
&& bucket.properties.icon.keep_upright;
|
||||
bool flip = (layout.icon.rotation_alignment == RotationAlignmentType::Map)
|
||||
&& layout.icon.keep_upright;
|
||||
iconShader->u_flip = flip ? 1 : 0;
|
||||
iconShader->u_zoom = (state.getNormalizedZoom() - zoomAdjust) * 10; // current zoom level
|
||||
|
||||
@@ -192,7 +194,7 @@ void Painter::renderSymbol(SymbolBucket &bucket, util::ptr<StyleLayer> layer_des
|
||||
renderSDF(bucket,
|
||||
id,
|
||||
matrix,
|
||||
bucket.properties.text,
|
||||
layout.text,
|
||||
properties.text,
|
||||
24.0f,
|
||||
{{ float(glyphAtlas.width) / 4, float(glyphAtlas.height) / 4 }},
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
RasterBucket::RasterBucket(TexturePool& texturePool, const StyleBucketRaster& properties_)
|
||||
: properties(properties_),
|
||||
RasterBucket::RasterBucket(TexturePool& texturePool, const StyleLayoutRaster& layout_)
|
||||
: layout(layout_),
|
||||
raster(texturePool) {
|
||||
}
|
||||
|
||||
|
||||
@@ -9,20 +9,21 @@
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class StyleLayoutRaster;
|
||||
class RasterShader;
|
||||
class StaticVertexBuffer;
|
||||
class VertexArrayObject;
|
||||
|
||||
class RasterBucket : public Bucket {
|
||||
public:
|
||||
RasterBucket(TexturePool&, const StyleBucketRaster&);
|
||||
RasterBucket(TexturePool&, const StyleLayoutRaster&);
|
||||
|
||||
virtual void render(Painter& painter, util::ptr<StyleLayer> layer_desc, const Tile::ID& id, const mat4 &matrix);
|
||||
virtual bool hasData() const;
|
||||
|
||||
bool setImage(const std::string &data);
|
||||
|
||||
const StyleBucketRaster &properties;
|
||||
const StyleLayoutRaster &layout;
|
||||
|
||||
void drawRaster(RasterShader& shader, StaticVertexBuffer &vertices, VertexArrayObject &array);
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include <mbgl/style/style_layout.hpp>
|
||||
#include <mbgl/renderer/symbol_bucket.hpp>
|
||||
#include <mbgl/geometry/text_buffer.hpp>
|
||||
#include <mbgl/geometry/icon_buffer.hpp>
|
||||
@@ -20,8 +21,14 @@
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
SymbolBucket::SymbolBucket(const StyleBucketSymbol &properties_, Collision &collision_)
|
||||
: properties(properties_), collision(collision_) {}
|
||||
SymbolBucket::SymbolBucket(std::unique_ptr<const StyleLayoutSymbol> styleLayout_, Collision &collision_)
|
||||
: styleLayout(std::move(styleLayout_)), collision(collision_) {
|
||||
assert(styleLayout);
|
||||
}
|
||||
|
||||
SymbolBucket::~SymbolBucket() {
|
||||
// Do not remove. header file only contains forward definitions to unique pointers.
|
||||
}
|
||||
|
||||
void SymbolBucket::render(Painter &painter, util::ptr<StyleLayer> layer_desc,
|
||||
const Tile::ID &id, const mat4 &matrix) {
|
||||
@@ -44,8 +51,9 @@ std::vector<SymbolFeature> SymbolBucket::processFeatures(const VectorTileLayer &
|
||||
const FilterExpression &filter,
|
||||
GlyphStore &glyphStore,
|
||||
const Sprite &sprite) {
|
||||
const bool has_text = properties.text.field.size();
|
||||
const bool has_icon = properties.icon.image.size();
|
||||
auto &layout = *styleLayout;
|
||||
const bool has_text = layout.text.field.size();
|
||||
const bool has_icon = layout.icon.image.size();
|
||||
|
||||
std::vector<SymbolFeature> features;
|
||||
|
||||
@@ -63,11 +71,11 @@ std::vector<SymbolFeature> SymbolBucket::processFeatures(const VectorTileLayer &
|
||||
SymbolFeature ft;
|
||||
|
||||
if (has_text) {
|
||||
std::string u8string = util::replaceTokens(properties.text.field, feature.properties);
|
||||
std::string u8string = util::replaceTokens(layout.text.field, feature.properties);
|
||||
|
||||
if (properties.text.transform == TextTransformType::Uppercase) {
|
||||
if (layout.text.transform == TextTransformType::Uppercase) {
|
||||
u8string = platform::uppercase(u8string);
|
||||
} else if (properties.text.transform == TextTransformType::Lowercase) {
|
||||
} else if (layout.text.transform == TextTransformType::Lowercase) {
|
||||
u8string = platform::lowercase(u8string);
|
||||
}
|
||||
|
||||
@@ -82,7 +90,7 @@ std::vector<SymbolFeature> SymbolBucket::processFeatures(const VectorTileLayer &
|
||||
}
|
||||
|
||||
if (has_icon) {
|
||||
ft.sprite = util::replaceTokens(properties.icon.image, feature.properties);
|
||||
ft.sprite = util::replaceTokens(layout.icon.image, feature.properties);
|
||||
}
|
||||
|
||||
if (ft.label.length() || ft.sprite.length()) {
|
||||
@@ -107,11 +115,11 @@ std::vector<SymbolFeature> SymbolBucket::processFeatures(const VectorTileLayer &
|
||||
}
|
||||
}
|
||||
|
||||
if (properties.placement == PlacementType::Line) {
|
||||
if (layout.placement == PlacementType::Line) {
|
||||
util::mergeLines(features);
|
||||
}
|
||||
|
||||
glyphStore.waitForGlyphRanges(properties.text.font, ranges);
|
||||
glyphStore.waitForGlyphRanges(layout.text.font, ranges);
|
||||
sprite.waitUntilLoaded();
|
||||
|
||||
return features;
|
||||
@@ -120,13 +128,13 @@ std::vector<SymbolFeature> SymbolBucket::processFeatures(const VectorTileLayer &
|
||||
void SymbolBucket::addFeatures(const VectorTileLayer &layer, const FilterExpression &filter,
|
||||
const Tile::ID &id, SpriteAtlas &spriteAtlas, Sprite &sprite,
|
||||
GlyphAtlas & glyphAtlas, GlyphStore &glyphStore) {
|
||||
|
||||
auto &layout = *styleLayout;
|
||||
const std::vector<SymbolFeature> features = processFeatures(layer, filter, glyphStore, sprite);
|
||||
|
||||
float horizontalAlign = 0.5;
|
||||
float verticalAlign = 0.5;
|
||||
|
||||
switch (properties.text.anchor) {
|
||||
switch (layout.text.anchor) {
|
||||
case TextAnchorType::Top:
|
||||
case TextAnchorType::Bottom:
|
||||
case TextAnchorType::Center:
|
||||
@@ -143,7 +151,7 @@ void SymbolBucket::addFeatures(const VectorTileLayer &layer, const FilterExpress
|
||||
break;
|
||||
}
|
||||
|
||||
switch (properties.text.anchor) {
|
||||
switch (layout.text.anchor) {
|
||||
case TextAnchorType::Left:
|
||||
case TextAnchorType::Right:
|
||||
case TextAnchorType::Center:
|
||||
@@ -161,10 +169,10 @@ void SymbolBucket::addFeatures(const VectorTileLayer &layer, const FilterExpress
|
||||
}
|
||||
|
||||
float justify = 0.5;
|
||||
if (properties.text.justify == TextJustifyType::Right) justify = 1;
|
||||
else if (properties.text.justify == TextJustifyType::Left) justify = 0;
|
||||
if (layout.text.justify == TextJustifyType::Right) justify = 1;
|
||||
else if (layout.text.justify == TextJustifyType::Left) justify = 0;
|
||||
|
||||
const FontStack &fontStack = glyphStore.getFontStack(properties.text.font);
|
||||
const FontStack &fontStack = glyphStore.getFontStack(layout.text.font);
|
||||
|
||||
for (const SymbolFeature &feature : features) {
|
||||
if (!feature.geometry.size()) continue;
|
||||
@@ -177,17 +185,17 @@ void SymbolBucket::addFeatures(const VectorTileLayer &layer, const FilterExpress
|
||||
if (feature.label.length()) {
|
||||
shaping = fontStack.getShaping(
|
||||
/* string */ feature.label,
|
||||
/* maxWidth: ems */ properties.text.max_width * 24,
|
||||
/* lineHeight: ems */ properties.text.line_height * 24,
|
||||
/* maxWidth: ems */ layout.text.max_width * 24,
|
||||
/* lineHeight: ems */ layout.text.line_height * 24,
|
||||
/* horizontalAlign */ horizontalAlign,
|
||||
/* verticalAlign */ verticalAlign,
|
||||
/* justify */ justify,
|
||||
/* spacing: ems */ properties.text.letter_spacing * 24,
|
||||
/* translate */ vec2<float>(properties.text.offset[0], properties.text.offset[1]));
|
||||
/* spacing: ems */ layout.text.letter_spacing * 24,
|
||||
/* translate */ vec2<float>(layout.text.offset[0], layout.text.offset[1]));
|
||||
|
||||
// Add the glyphs we need for this label to the glyph atlas.
|
||||
if (shaping.size()) {
|
||||
SymbolBucket::addGlyphsToAtlas(id.to_uint64(), properties.text.font, feature.label, fontStack,
|
||||
SymbolBucket::addGlyphsToAtlas(id.to_uint64(), layout.text.font, feature.label, fontStack,
|
||||
glyphAtlas, face);
|
||||
}
|
||||
}
|
||||
@@ -220,24 +228,25 @@ const PlacementRange fullRange{{2 * M_PI, 0}};
|
||||
void SymbolBucket::addFeature(const std::vector<Coordinate> &line, const Shaping &shaping,
|
||||
const GlyphPositions &face, const Rect<uint16_t> &image) {
|
||||
assert(line.size());
|
||||
auto &layout = *styleLayout;
|
||||
|
||||
const float minScale = 0.5f;
|
||||
const float glyphSize = 24.0f;
|
||||
|
||||
const bool horizontalText =
|
||||
properties.text.rotation_alignment == RotationAlignmentType::Viewport;
|
||||
layout.text.rotation_alignment == RotationAlignmentType::Viewport;
|
||||
const bool horizontalIcon =
|
||||
properties.icon.rotation_alignment == RotationAlignmentType::Viewport;
|
||||
const float fontScale = properties.text.max_size / glyphSize;
|
||||
layout.icon.rotation_alignment == RotationAlignmentType::Viewport;
|
||||
const float fontScale = layout.text.max_size / glyphSize;
|
||||
const float textBoxScale = collision.tilePixelRatio * fontScale;
|
||||
const float iconBoxScale = collision.tilePixelRatio * properties.icon.max_size;
|
||||
const bool iconWithoutText = properties.text.optional || !shaping.size();
|
||||
const bool textWithoutIcon = properties.icon.optional || !image;
|
||||
const bool avoidEdges = properties.avoid_edges && properties.placement != PlacementType::Line;
|
||||
const float iconBoxScale = collision.tilePixelRatio * layout.icon.max_size;
|
||||
const bool iconWithoutText = layout.text.optional || !shaping.size();
|
||||
const bool textWithoutIcon = layout.icon.optional || !image;
|
||||
const bool avoidEdges = layout.avoid_edges && layout.placement != PlacementType::Line;
|
||||
|
||||
Anchors anchors;
|
||||
|
||||
if (properties.placement == PlacementType::Line) {
|
||||
if (layout.placement == PlacementType::Line) {
|
||||
float resampleOffset = 0;
|
||||
|
||||
if (shaping.size()) {
|
||||
@@ -252,7 +261,7 @@ void SymbolBucket::addFeature(const std::vector<Coordinate> &line, const Shaping
|
||||
}
|
||||
|
||||
// Line labels
|
||||
anchors = resample(line, properties.min_distance, minScale, collision.maxPlacementScale,
|
||||
anchors = resample(line, layout.min_distance, minScale, collision.maxPlacementScale,
|
||||
collision.tilePixelRatio, resampleOffset);
|
||||
|
||||
// Sort anchors by segment so that we can start placement with the
|
||||
@@ -280,9 +289,9 @@ void SymbolBucket::addFeature(const std::vector<Coordinate> &line, const Shaping
|
||||
|
||||
if (shaping.size()) {
|
||||
glyphPlacement = Placement::getGlyphs(anchor, origin, shaping, face, textBoxScale,
|
||||
horizontalText, line, properties);
|
||||
horizontalText, line, layout);
|
||||
glyphScale =
|
||||
properties.text.allow_overlap
|
||||
layout.text.allow_overlap
|
||||
? glyphPlacement.minScale
|
||||
: collision.getPlacementScale(glyphPlacement.boxes, glyphPlacement.minScale, avoidEdges);
|
||||
if (!glyphScale && !iconWithoutText)
|
||||
@@ -290,9 +299,9 @@ void SymbolBucket::addFeature(const std::vector<Coordinate> &line, const Shaping
|
||||
}
|
||||
|
||||
if (image) {
|
||||
iconPlacement = Placement::getIcon(anchor, image, iconBoxScale, line, properties);
|
||||
iconPlacement = Placement::getIcon(anchor, image, iconBoxScale, line, layout);
|
||||
iconScale =
|
||||
properties.icon.allow_overlap
|
||||
layout.icon.allow_overlap
|
||||
? iconPlacement.minScale
|
||||
: collision.getPlacementScale(iconPlacement.boxes, iconPlacement.minScale, avoidEdges);
|
||||
if (!iconScale && !textWithoutIcon)
|
||||
@@ -309,11 +318,11 @@ void SymbolBucket::addFeature(const std::vector<Coordinate> &line, const Shaping
|
||||
|
||||
// Get the rotation ranges it is safe to show the glyphs
|
||||
PlacementRange glyphRange =
|
||||
(!glyphScale || properties.text.allow_overlap)
|
||||
(!glyphScale || layout.text.allow_overlap)
|
||||
? fullRange
|
||||
: collision.getPlacementRange(glyphPlacement.boxes, glyphScale, horizontalText);
|
||||
PlacementRange iconRange =
|
||||
(!iconScale || properties.icon.allow_overlap)
|
||||
(!iconScale || layout.icon.allow_overlap)
|
||||
? fullRange
|
||||
: collision.getPlacementRange(iconPlacement.boxes, iconScale, horizontalIcon);
|
||||
|
||||
@@ -331,7 +340,7 @@ void SymbolBucket::addFeature(const std::vector<Coordinate> &line, const Shaping
|
||||
|
||||
// Insert final placement into collision tree and add glyphs/icons to buffers
|
||||
if (glyphScale && std::isfinite(glyphScale)) {
|
||||
if (!properties.text.ignore_placement) {
|
||||
if (!layout.text.ignore_placement) {
|
||||
collision.insert(glyphPlacement.boxes, anchor, glyphScale, glyphRange,
|
||||
horizontalText);
|
||||
}
|
||||
@@ -339,7 +348,7 @@ void SymbolBucket::addFeature(const std::vector<Coordinate> &line, const Shaping
|
||||
}
|
||||
|
||||
if (iconScale && std::isfinite(iconScale)) {
|
||||
if (!properties.icon.ignore_placement) {
|
||||
if (!layout.icon.ignore_placement) {
|
||||
collision.insert(iconPlacement.boxes, anchor, iconScale, iconRange, horizontalIcon);
|
||||
}
|
||||
if (inside) addSymbols<IconBuffer, IconElementGroup>(icon, iconPlacement.shapes, iconScale, iconRange);
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
namespace mbgl {
|
||||
|
||||
class Style;
|
||||
class StyleLayoutSymbol;
|
||||
class SDFShader;
|
||||
class IconShader;
|
||||
class DotShader;
|
||||
@@ -54,7 +55,8 @@ class SymbolBucket : public Bucket {
|
||||
typedef ElementGroup<2> IconElementGroup;
|
||||
|
||||
public:
|
||||
SymbolBucket(const StyleBucketSymbol &properties, Collision &collision);
|
||||
SymbolBucket(std::unique_ptr<const StyleLayoutSymbol> styleLayout, Collision &collision);
|
||||
~SymbolBucket();
|
||||
|
||||
virtual void render(Painter &painter, util::ptr<StyleLayer> layer_desc, const Tile::ID &id, const mat4 &matrix);
|
||||
virtual bool hasData() const;
|
||||
@@ -89,7 +91,7 @@ private:
|
||||
const FontStack &fontStack, GlyphAtlas &glyphAtlas, GlyphPositions &face);
|
||||
|
||||
public:
|
||||
const StyleBucketSymbol &properties;
|
||||
const std::unique_ptr<const StyleLayoutSymbol> styleLayout;
|
||||
bool sdfIcons = false;
|
||||
|
||||
private:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <mbgl/style/property_fallback.hpp>
|
||||
#include <mbgl/style/style_properties.hpp>
|
||||
#include <mbgl/style/style_bucket.hpp>
|
||||
#include <mbgl/style/style_layout.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
@@ -50,44 +51,44 @@ const std::map<PropertyKey, PropertyValue> PropertyFallbackValue::properties = {
|
||||
{ PropertyKey::BackgroundOpacity, defaultStyleProperties<BackgroundProperties>().opacity },
|
||||
{ PropertyKey::BackgroundColor, defaultStyleProperties<BackgroundProperties>().color },
|
||||
|
||||
{ PropertyKey::LineCap, defaultLayoutProperties<StyleBucketLine>().cap },
|
||||
{ PropertyKey::LineJoin, defaultLayoutProperties<StyleBucketLine>().join },
|
||||
{ PropertyKey::LineMiterLimit, defaultLayoutProperties<StyleBucketLine>().miter_limit },
|
||||
{ PropertyKey::LineRoundLimit, defaultLayoutProperties<StyleBucketLine>().round_limit },
|
||||
{ PropertyKey::LineCap, defaultStyleLayout<StyleLayoutLine>().cap },
|
||||
{ PropertyKey::LineJoin, defaultStyleLayout<StyleLayoutLine>().join },
|
||||
{ PropertyKey::LineMiterLimit, defaultStyleLayout<StyleLayoutLine>().miter_limit },
|
||||
{ PropertyKey::LineRoundLimit, defaultStyleLayout<StyleLayoutLine>().round_limit },
|
||||
|
||||
{ PropertyKey::SymbolPlacement, defaultLayoutProperties<StyleBucketSymbol>().placement },
|
||||
{ PropertyKey::SymbolMinDistance, defaultLayoutProperties<StyleBucketSymbol>().min_distance },
|
||||
{ PropertyKey::SymbolAvoidEdges, defaultLayoutProperties<StyleBucketSymbol>().avoid_edges },
|
||||
{ PropertyKey::SymbolPlacement, defaultStyleLayout<StyleLayoutSymbol>().placement },
|
||||
{ PropertyKey::SymbolMinDistance, defaultStyleLayout<StyleLayoutSymbol>().min_distance },
|
||||
{ PropertyKey::SymbolAvoidEdges, defaultStyleLayout<StyleLayoutSymbol>().avoid_edges },
|
||||
|
||||
{ PropertyKey::IconAllowOverlap, defaultLayoutProperties<StyleBucketSymbol>().icon.allow_overlap },
|
||||
{ PropertyKey::IconIgnorePlacement, defaultLayoutProperties<StyleBucketSymbol>().icon.ignore_placement },
|
||||
{ PropertyKey::IconOptional, defaultLayoutProperties<StyleBucketSymbol>().icon.optional },
|
||||
{ PropertyKey::IconRotationAlignment, defaultLayoutProperties<StyleBucketSymbol>().icon.rotation_alignment },
|
||||
{ PropertyKey::IconMaxSize, defaultLayoutProperties<StyleBucketSymbol>().icon.max_size },
|
||||
{ PropertyKey::IconImage, defaultLayoutProperties<StyleBucketSymbol>().icon.image },
|
||||
{ PropertyKey::IconRotate, defaultLayoutProperties<StyleBucketSymbol>().icon.rotate },
|
||||
{ PropertyKey::IconPadding, defaultLayoutProperties<StyleBucketSymbol>().icon.padding },
|
||||
{ PropertyKey::IconKeepUpright, defaultLayoutProperties<StyleBucketSymbol>().icon.keep_upright },
|
||||
{ PropertyKey::IconOffset, defaultLayoutProperties<StyleBucketSymbol>().icon.offset },
|
||||
{ PropertyKey::IconAllowOverlap, defaultStyleLayout<StyleLayoutSymbol>().icon.allow_overlap },
|
||||
{ PropertyKey::IconIgnorePlacement, defaultStyleLayout<StyleLayoutSymbol>().icon.ignore_placement },
|
||||
{ PropertyKey::IconOptional, defaultStyleLayout<StyleLayoutSymbol>().icon.optional },
|
||||
{ PropertyKey::IconRotationAlignment, defaultStyleLayout<StyleLayoutSymbol>().icon.rotation_alignment },
|
||||
{ PropertyKey::IconMaxSize, defaultStyleLayout<StyleLayoutSymbol>().icon.max_size },
|
||||
{ PropertyKey::IconImage, defaultStyleLayout<StyleLayoutSymbol>().icon.image },
|
||||
{ PropertyKey::IconRotate, defaultStyleLayout<StyleLayoutSymbol>().icon.rotate },
|
||||
{ PropertyKey::IconPadding, defaultStyleLayout<StyleLayoutSymbol>().icon.padding },
|
||||
{ PropertyKey::IconKeepUpright, defaultStyleLayout<StyleLayoutSymbol>().icon.keep_upright },
|
||||
{ PropertyKey::IconOffset, defaultStyleLayout<StyleLayoutSymbol>().icon.offset },
|
||||
|
||||
{ PropertyKey::TextRotationAlignment, defaultLayoutProperties<StyleBucketSymbol>().text.rotation_alignment },
|
||||
{ PropertyKey::TextField, defaultLayoutProperties<StyleBucketSymbol>().text.field },
|
||||
{ PropertyKey::TextFont, defaultLayoutProperties<StyleBucketSymbol>().text.font },
|
||||
{ PropertyKey::TextMaxSize, defaultLayoutProperties<StyleBucketSymbol>().text.max_size },
|
||||
{ PropertyKey::TextMaxWidth, defaultLayoutProperties<StyleBucketSymbol>().text.max_width },
|
||||
{ PropertyKey::TextLineHeight, defaultLayoutProperties<StyleBucketSymbol>().text.line_height },
|
||||
{ PropertyKey::TextLetterSpacing, defaultLayoutProperties<StyleBucketSymbol>().text.letter_spacing },
|
||||
{ PropertyKey::TextJustify, defaultLayoutProperties<StyleBucketSymbol>().text.justify },
|
||||
{ PropertyKey::TextAnchor, defaultLayoutProperties<StyleBucketSymbol>().text.anchor },
|
||||
{ PropertyKey::TextMaxAngle, defaultLayoutProperties<StyleBucketSymbol>().text.max_angle },
|
||||
{ PropertyKey::TextRotate, defaultLayoutProperties<StyleBucketSymbol>().text.rotate },
|
||||
{ PropertyKey::TextPadding, defaultLayoutProperties<StyleBucketSymbol>().text.padding },
|
||||
{ PropertyKey::TextKeepUpright, defaultLayoutProperties<StyleBucketSymbol>().text.keep_upright },
|
||||
{ PropertyKey::TextTransform, defaultLayoutProperties<StyleBucketSymbol>().text.transform },
|
||||
{ PropertyKey::TextOffset, defaultLayoutProperties<StyleBucketSymbol>().text.offset },
|
||||
{ PropertyKey::TextAllowOverlap, defaultLayoutProperties<StyleBucketSymbol>().text.allow_overlap },
|
||||
{ PropertyKey::TextIgnorePlacement, defaultLayoutProperties<StyleBucketSymbol>().text.ignore_placement },
|
||||
{ PropertyKey::TextOptional, defaultLayoutProperties<StyleBucketSymbol>().text.optional },
|
||||
{ PropertyKey::TextRotationAlignment, defaultStyleLayout<StyleLayoutSymbol>().text.rotation_alignment },
|
||||
{ PropertyKey::TextField, defaultStyleLayout<StyleLayoutSymbol>().text.field },
|
||||
{ PropertyKey::TextFont, defaultStyleLayout<StyleLayoutSymbol>().text.font },
|
||||
{ PropertyKey::TextMaxSize, defaultStyleLayout<StyleLayoutSymbol>().text.max_size },
|
||||
{ PropertyKey::TextMaxWidth, defaultStyleLayout<StyleLayoutSymbol>().text.max_width },
|
||||
{ PropertyKey::TextLineHeight, defaultStyleLayout<StyleLayoutSymbol>().text.line_height },
|
||||
{ PropertyKey::TextLetterSpacing, defaultStyleLayout<StyleLayoutSymbol>().text.letter_spacing },
|
||||
{ PropertyKey::TextJustify, defaultStyleLayout<StyleLayoutSymbol>().text.justify },
|
||||
{ PropertyKey::TextAnchor, defaultStyleLayout<StyleLayoutSymbol>().text.anchor },
|
||||
{ PropertyKey::TextMaxAngle, defaultStyleLayout<StyleLayoutSymbol>().text.max_angle },
|
||||
{ PropertyKey::TextRotate, defaultStyleLayout<StyleLayoutSymbol>().text.rotate },
|
||||
{ PropertyKey::TextPadding, defaultStyleLayout<StyleLayoutSymbol>().text.padding },
|
||||
{ PropertyKey::TextKeepUpright, defaultStyleLayout<StyleLayoutSymbol>().text.keep_upright },
|
||||
{ PropertyKey::TextTransform, defaultStyleLayout<StyleLayoutSymbol>().text.transform },
|
||||
{ PropertyKey::TextOffset, defaultStyleLayout<StyleLayoutSymbol>().text.offset },
|
||||
{ PropertyKey::TextAllowOverlap, defaultStyleLayout<StyleLayoutSymbol>().text.allow_overlap },
|
||||
{ PropertyKey::TextIgnorePlacement, defaultStyleLayout<StyleLayoutSymbol>().text.ignore_placement },
|
||||
{ PropertyKey::TextOptional, defaultStyleLayout<StyleLayoutSymbol>().text.optional },
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
#include <mbgl/style/style_bucket.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
template<> const StyleBucketFill &defaultLayoutProperties() { static StyleBucketFill p; return p; }
|
||||
template<> const StyleBucketLine &defaultLayoutProperties() { static StyleBucketLine p; return p; }
|
||||
template<> const StyleBucketSymbol &defaultLayoutProperties() { static StyleBucketSymbol p; return p; }
|
||||
template<> const StyleBucketRaster &defaultLayoutProperties() { static StyleBucketRaster p; return p; }
|
||||
template<> const StyleBucketBackground &defaultLayoutProperties() { static StyleBucketBackground p; return p; }
|
||||
|
||||
StyleBucket::StyleBucket(StyleLayerType type_) : type(type_) {
|
||||
switch (type) {
|
||||
case StyleLayerType::Fill: render.set<StyleBucketFill>(); break;
|
||||
case StyleLayerType::Line: render.set<StyleBucketLine>(); break;
|
||||
case StyleLayerType::Symbol: render.set<StyleBucketSymbol>(); break;
|
||||
case StyleLayerType::Raster: render.set<StyleBucketRaster>(); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,130 +4,31 @@
|
||||
#include <mbgl/style/types.hpp>
|
||||
#include <mbgl/style/filter_expression.hpp>
|
||||
#include <mbgl/style/style_source.hpp>
|
||||
|
||||
#include <mbgl/util/vec.hpp>
|
||||
#include <mbgl/util/variant.hpp>
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
#include <mbgl/util/ptr.hpp>
|
||||
#include <mbgl/style/class_properties.hpp>
|
||||
|
||||
#include <forward_list>
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
#include <mbgl/util/ptr.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class Source;
|
||||
|
||||
class StyleBucketFill {
|
||||
public:
|
||||
// Make movable only.
|
||||
StyleBucketFill() = default;
|
||||
StyleBucketFill(StyleBucketFill &&) = default;
|
||||
StyleBucketFill& operator=(StyleBucketFill &&) = default;
|
||||
StyleBucketFill(const StyleBucketFill &) = delete;
|
||||
StyleBucketFill& operator=(const StyleBucketFill &) = delete;
|
||||
};
|
||||
|
||||
class StyleBucketLine {
|
||||
public:
|
||||
// Make movable only.
|
||||
StyleBucketLine() = default;
|
||||
StyleBucketLine(StyleBucketLine &&) = default;
|
||||
StyleBucketLine& operator=(StyleBucketLine &&) = default;
|
||||
StyleBucketLine(const StyleBucketLine &) = delete;
|
||||
StyleBucketLine& operator=(const StyleBucketLine &) = delete;
|
||||
|
||||
CapType cap = CapType::Butt;
|
||||
JoinType join = JoinType::Miter;
|
||||
float miter_limit = 2.0f;
|
||||
float round_limit = 1.0f;
|
||||
};
|
||||
|
||||
class StyleBucketSymbol {
|
||||
public:
|
||||
// Make movable only.
|
||||
StyleBucketSymbol() = default;
|
||||
StyleBucketSymbol(StyleBucketSymbol &&) = default;
|
||||
StyleBucketSymbol& operator=(StyleBucketSymbol &&) = default;
|
||||
StyleBucketSymbol(const StyleBucketSymbol &) = delete;
|
||||
StyleBucketSymbol& operator=(const StyleBucketSymbol &) = delete;
|
||||
|
||||
PlacementType placement = PlacementType::Point;
|
||||
float min_distance = 250.0f;
|
||||
bool avoid_edges = false;
|
||||
|
||||
struct {
|
||||
bool allow_overlap = false;
|
||||
bool ignore_placement = false;
|
||||
bool optional = false;
|
||||
RotationAlignmentType rotation_alignment = RotationAlignmentType::Viewport;
|
||||
float max_size = 1.0f;
|
||||
std::string image;
|
||||
float rotate = 0.0f;
|
||||
float padding = 2.0f;
|
||||
bool keep_upright = false;
|
||||
std::array<float, 2> offset = {{ 0, 0 }};
|
||||
} icon;
|
||||
|
||||
struct {
|
||||
RotationAlignmentType rotation_alignment = RotationAlignmentType::Viewport;
|
||||
std::string field;
|
||||
std::string font;
|
||||
float max_size = 16.0f;
|
||||
float max_width = 15.0f /* em */;
|
||||
float line_height = 1.2f /* em */;
|
||||
float letter_spacing = 0.0f /* em */;
|
||||
TextJustifyType justify = TextJustifyType::Center;
|
||||
TextAnchorType anchor = TextAnchorType::Center;
|
||||
float max_angle = 45.0f /* degrees */;
|
||||
float rotate = 0.0f;
|
||||
float padding = 2.0f;
|
||||
bool keep_upright = true;
|
||||
TextTransformType transform = TextTransformType::None;
|
||||
std::array<float, 2> offset = {{ 0, 0 }};
|
||||
bool allow_overlap = false;
|
||||
bool ignore_placement = false;
|
||||
bool optional = false;
|
||||
} text;
|
||||
};
|
||||
|
||||
class StyleBucketRaster {
|
||||
public:
|
||||
// Make movable only.
|
||||
StyleBucketRaster() = default;
|
||||
StyleBucketRaster(StyleBucketRaster &&) = default;
|
||||
StyleBucketRaster& operator=(StyleBucketRaster &&) = default;
|
||||
StyleBucketRaster(const StyleBucketRaster &) = delete;
|
||||
StyleBucketRaster& operator=(const StyleBucketRaster &) = delete;
|
||||
};
|
||||
|
||||
class StyleBucketBackground {
|
||||
public:
|
||||
};
|
||||
|
||||
typedef mapbox::util::variant<StyleBucketFill, StyleBucketLine, StyleBucketSymbol,
|
||||
StyleBucketRaster, StyleBucketBackground, std::false_type> StyleBucketRender;
|
||||
|
||||
|
||||
class StyleBucket : public util::noncopyable {
|
||||
public:
|
||||
typedef util::ptr<StyleBucket> Ptr;
|
||||
|
||||
StyleBucket(StyleLayerType type);
|
||||
StyleLayerType type;
|
||||
inline StyleBucket(StyleLayerType type_) : type(type_) {}
|
||||
const StyleLayerType type;
|
||||
std::string name;
|
||||
util::ptr<StyleSource> style_source;
|
||||
std::string source_layer;
|
||||
FilterExpression filter;
|
||||
ClassProperties layout;
|
||||
StyleBucketRender render = std::false_type();
|
||||
float min_zoom = -std::numeric_limits<float>::infinity();
|
||||
float max_zoom = std::numeric_limits<float>::infinity();
|
||||
VisibilityType visibility = VisibilityType::Visible;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
const T &defaultLayoutProperties();
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -67,7 +67,7 @@ public:
|
||||
|
||||
// Bucket information, telling the renderer how to generate the geometries
|
||||
// for this layer (feature property filters, tessellation instructions, ...).
|
||||
util::ptr<StyleBucket> bucket;
|
||||
util::ptr<const StyleBucket> bucket;
|
||||
|
||||
// Contains all style classes that can be applied to this layer.
|
||||
const std::map<ClassID, ClassProperties> styles;
|
||||
|
||||
11
src/mbgl/style/style_layout.cpp
Normal file
11
src/mbgl/style/style_layout.cpp
Normal file
@@ -0,0 +1,11 @@
|
||||
#include <mbgl/style/style_layout.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
template<> const StyleLayoutFill &defaultStyleLayout() { static StyleLayoutFill p; return p; }
|
||||
template<> const StyleLayoutLine &defaultStyleLayout() { static StyleLayoutLine p; return p; }
|
||||
template<> const StyleLayoutSymbol &defaultStyleLayout() { static StyleLayoutSymbol p; return p; }
|
||||
template<> const StyleLayoutRaster &defaultStyleLayout() { static StyleLayoutRaster p; return p; }
|
||||
template<> const StyleLayoutBackground &defaultStyleLayout() { static StyleLayoutBackground p; return p; }
|
||||
|
||||
}
|
||||
108
src/mbgl/style/style_layout.hpp
Normal file
108
src/mbgl/style/style_layout.hpp
Normal file
@@ -0,0 +1,108 @@
|
||||
#ifndef MBGL_STYLE_STYLE_LAYOUT
|
||||
#define MBGL_STYLE_STYLE_LAYOUT
|
||||
|
||||
#include <mbgl/style/types.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class Source;
|
||||
|
||||
class StyleLayoutFill {
|
||||
public:
|
||||
// Make movable only.
|
||||
StyleLayoutFill() = default;
|
||||
StyleLayoutFill(StyleLayoutFill &&) = default;
|
||||
StyleLayoutFill& operator=(StyleLayoutFill &&) = default;
|
||||
StyleLayoutFill(const StyleLayoutFill &) = delete;
|
||||
StyleLayoutFill& operator=(const StyleLayoutFill &) = delete;
|
||||
};
|
||||
|
||||
class StyleLayoutLine {
|
||||
public:
|
||||
// Make movable only.
|
||||
StyleLayoutLine() = default;
|
||||
StyleLayoutLine(StyleLayoutLine &&) = default;
|
||||
StyleLayoutLine& operator=(StyleLayoutLine &&) = default;
|
||||
StyleLayoutLine(const StyleLayoutLine &) = delete;
|
||||
StyleLayoutLine& operator=(const StyleLayoutLine &) = delete;
|
||||
|
||||
CapType cap = CapType::Butt;
|
||||
JoinType join = JoinType::Miter;
|
||||
float miter_limit = 2.0f;
|
||||
float round_limit = 1.0f;
|
||||
};
|
||||
|
||||
class StyleLayoutSymbol {
|
||||
public:
|
||||
// Make movable only.
|
||||
StyleLayoutSymbol() = default;
|
||||
StyleLayoutSymbol(StyleLayoutSymbol &&) = default;
|
||||
StyleLayoutSymbol& operator=(StyleLayoutSymbol &&) = default;
|
||||
StyleLayoutSymbol(const StyleLayoutSymbol &) = delete;
|
||||
StyleLayoutSymbol& operator=(const StyleLayoutSymbol &) = delete;
|
||||
|
||||
PlacementType placement = PlacementType::Point;
|
||||
float min_distance = 250.0f;
|
||||
bool avoid_edges = false;
|
||||
|
||||
struct {
|
||||
bool allow_overlap = false;
|
||||
bool ignore_placement = false;
|
||||
bool optional = false;
|
||||
RotationAlignmentType rotation_alignment = RotationAlignmentType::Viewport;
|
||||
float max_size = 1.0f;
|
||||
std::string image;
|
||||
float rotate = 0.0f;
|
||||
float padding = 2.0f;
|
||||
bool keep_upright = false;
|
||||
std::array<float, 2> offset = {{ 0, 0 }};
|
||||
} icon;
|
||||
|
||||
struct {
|
||||
RotationAlignmentType rotation_alignment = RotationAlignmentType::Viewport;
|
||||
std::string field;
|
||||
std::string font;
|
||||
float max_size = 16.0f;
|
||||
float max_width = 15.0f /* em */;
|
||||
float line_height = 1.2f /* em */;
|
||||
float letter_spacing = 0.0f /* em */;
|
||||
TextJustifyType justify = TextJustifyType::Center;
|
||||
TextAnchorType anchor = TextAnchorType::Center;
|
||||
float max_angle = 45.0f /* degrees */;
|
||||
float rotate = 0.0f;
|
||||
float padding = 2.0f;
|
||||
bool keep_upright = true;
|
||||
TextTransformType transform = TextTransformType::None;
|
||||
std::array<float, 2> offset = {{ 0, 0 }};
|
||||
bool allow_overlap = false;
|
||||
bool ignore_placement = false;
|
||||
bool optional = false;
|
||||
} text;
|
||||
};
|
||||
|
||||
class StyleLayoutRaster {
|
||||
public:
|
||||
// Make movable only.
|
||||
StyleLayoutRaster() = default;
|
||||
StyleLayoutRaster(StyleLayoutRaster &&) = default;
|
||||
StyleLayoutRaster& operator=(StyleLayoutRaster &&) = default;
|
||||
StyleLayoutRaster(const StyleLayoutRaster &) = delete;
|
||||
StyleLayoutRaster& operator=(const StyleLayoutRaster &) = delete;
|
||||
};
|
||||
|
||||
class StyleLayoutBackground {
|
||||
public:
|
||||
// Make movable only.
|
||||
StyleLayoutBackground() = default;
|
||||
StyleLayoutBackground(StyleLayoutBackground &&) = default;
|
||||
StyleLayoutBackground& operator=(StyleLayoutBackground &&) = default;
|
||||
StyleLayoutBackground(const StyleLayoutBackground &) = delete;
|
||||
StyleLayoutBackground& operator=(const StyleLayoutBackground &) = delete;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
const T &defaultStyleLayout();
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <mbgl/style/style_layer_group.hpp>
|
||||
#include <mbgl/util/constants.hpp>
|
||||
#include <mbgl/util/std.hpp>
|
||||
#include <mbgl/util/vec.hpp>
|
||||
#include <mbgl/platform/log.hpp>
|
||||
#include <csscolorparser/csscolorparser.hpp>
|
||||
|
||||
@@ -894,10 +895,10 @@ void StyleParser::parseReference(JSVal value, util::ptr<StyleLayer> &layer) {
|
||||
#pragma mark - Parse Bucket
|
||||
|
||||
void StyleParser::parseBucket(JSVal value, util::ptr<StyleLayer> &layer) {
|
||||
layer->bucket = std::make_shared<StyleBucket>(layer->type);
|
||||
util::ptr<StyleBucket> bucket = std::make_shared<StyleBucket>(layer->type);
|
||||
|
||||
// We name the buckets according to the layer that defined it.
|
||||
layer->bucket->name = layer->id;
|
||||
bucket->name = layer->id;
|
||||
|
||||
if (value.HasMember("source")) {
|
||||
JSVal value_source = replaceConstant(value["source"]);
|
||||
@@ -905,7 +906,7 @@ void StyleParser::parseBucket(JSVal value, util::ptr<StyleLayer> &layer) {
|
||||
const std::string source_name = { value_source.GetString(), value_source.GetStringLength() };
|
||||
auto source_it = sources.find(source_name);
|
||||
if (source_it != sources.end()) {
|
||||
layer->bucket->style_source = source_it->second;
|
||||
bucket->style_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());
|
||||
}
|
||||
@@ -917,7 +918,7 @@ void StyleParser::parseBucket(JSVal value, util::ptr<StyleLayer> &layer) {
|
||||
if (value.HasMember("source-layer")) {
|
||||
JSVal value_source_layer = replaceConstant(value["source-layer"]);
|
||||
if (value_source_layer.IsString()) {
|
||||
layer->bucket->source_layer = { value_source_layer.GetString(), value_source_layer.GetStringLength() };
|
||||
bucket->source_layer = { value_source_layer.GetString(), value_source_layer.GetStringLength() };
|
||||
} else {
|
||||
Log::Warning(Event::ParseStyle, "source-layer of layer '%s' must be a string", layer->id.c_str());
|
||||
}
|
||||
@@ -925,18 +926,18 @@ void StyleParser::parseBucket(JSVal value, util::ptr<StyleLayer> &layer) {
|
||||
|
||||
if (value.HasMember("filter")) {
|
||||
JSVal value_filter = replaceConstant(value["filter"]);
|
||||
layer->bucket->filter = parseFilterExpression(value_filter);
|
||||
bucket->filter = parseFilterExpression(value_filter);
|
||||
}
|
||||
|
||||
if (value.HasMember("layout")) {
|
||||
JSVal value_render = replaceConstant(value["layout"]);
|
||||
parseLayout(value_render, layer->bucket);
|
||||
parseLayout(value_render, bucket);
|
||||
}
|
||||
|
||||
if (value.HasMember("minzoom")) {
|
||||
JSVal min_zoom = value["minzoom"];
|
||||
if (min_zoom.IsNumber()) {
|
||||
layer->bucket->min_zoom = min_zoom.GetDouble();
|
||||
bucket->min_zoom = min_zoom.GetDouble();
|
||||
} else {
|
||||
Log::Warning(Event::ParseStyle, "minzoom of layer %s must be numeric", layer->id.c_str());
|
||||
}
|
||||
@@ -945,11 +946,13 @@ void StyleParser::parseBucket(JSVal value, util::ptr<StyleLayer> &layer) {
|
||||
if (value.HasMember("maxzoom")) {
|
||||
JSVal max_zoom = value["maxzoom"];
|
||||
if (max_zoom.IsNumber()) {
|
||||
layer->bucket->min_zoom = max_zoom.GetDouble();
|
||||
bucket->min_zoom = max_zoom.GetDouble();
|
||||
} else {
|
||||
Log::Warning(Event::ParseStyle, "maxzoom of layer %s must be numeric", layer->id.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
layer->bucket = bucket;
|
||||
}
|
||||
|
||||
void StyleParser::parseSprite(JSVal value) {
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <mbgl/text/placement.hpp>
|
||||
#include <mbgl/text/glyph_store.hpp>
|
||||
#include <mbgl/style/style_bucket.hpp>
|
||||
#include <mbgl/style/style_layout.hpp>
|
||||
|
||||
#include <mbgl/util/math.hpp>
|
||||
|
||||
@@ -129,10 +130,10 @@ GlyphBox getMergedBoxes(const GlyphBoxes &glyphs, const Anchor &anchor) {
|
||||
}
|
||||
|
||||
Placement Placement::getIcon(Anchor &anchor, const Rect<uint16_t> &image, float boxScale,
|
||||
const std::vector<Coordinate> &line, const StyleBucketSymbol &props) {
|
||||
const std::vector<Coordinate> &line, const StyleLayoutSymbol &layout) {
|
||||
|
||||
const float dx = props.icon.offset[0];
|
||||
const float dy = props.icon.offset[1];
|
||||
const float dx = layout.icon.offset[0];
|
||||
const float dy = layout.icon.offset[1];
|
||||
float x1 = dx - image.originalW / 2.0f;
|
||||
float x2 = x1 + image.w;
|
||||
float y1 = dy - image.originalH / 2.0f;
|
||||
@@ -143,8 +144,8 @@ Placement Placement::getIcon(Anchor &anchor, const Rect<uint16_t> &image, float
|
||||
vec2<float> br{x2, y2};
|
||||
vec2<float> bl{x1, y2};
|
||||
|
||||
float angle = props.icon.rotate * M_PI / 180.0f;
|
||||
if (anchor.segment >= 0 && props.icon.rotation_alignment != RotationAlignmentType::Viewport) {
|
||||
float angle = layout.icon.rotate * M_PI / 180.0f;
|
||||
if (anchor.segment >= 0 && layout.icon.rotation_alignment != RotationAlignmentType::Viewport) {
|
||||
const Coordinate &next = line[anchor.segment];
|
||||
angle += -std::atan2(next.x - anchor.x, next.y - anchor.y) + M_PI / 2;
|
||||
}
|
||||
@@ -178,7 +179,7 @@ Placement Placement::getIcon(Anchor &anchor, const Rect<uint16_t> &image, float
|
||||
/* anchor */ anchor,
|
||||
/* minScale */ Placement::globalMinScale,
|
||||
/* maxScale */ std::numeric_limits<float>::infinity(),
|
||||
/* padding */ props.icon.padding);
|
||||
/* padding */ layout.icon.padding);
|
||||
|
||||
placement.shapes.emplace_back(
|
||||
/* tl */ tl,
|
||||
@@ -199,12 +200,12 @@ Placement Placement::getIcon(Anchor &anchor, const Rect<uint16_t> &image, float
|
||||
Placement Placement::getGlyphs(Anchor &anchor, const vec2<float> &origin, const Shaping &shaping,
|
||||
const GlyphPositions &face, float boxScale, bool horizontal,
|
||||
const std::vector<Coordinate> &line,
|
||||
const StyleBucketSymbol &props) {
|
||||
const float maxAngle = props.text.max_angle * M_PI / 180;
|
||||
const float rotate = props.text.rotate * M_PI / 180;
|
||||
const float padding = props.text.padding;
|
||||
const bool alongLine = props.text.rotation_alignment != RotationAlignmentType::Viewport;
|
||||
const bool keepUpright = props.text.keep_upright;
|
||||
const StyleLayoutSymbol &layout) {
|
||||
const float maxAngle = layout.text.max_angle * M_PI / 180;
|
||||
const float rotate = layout.text.rotate * M_PI / 180;
|
||||
const float padding = layout.text.padding;
|
||||
const bool alongLine = layout.text.rotation_alignment != RotationAlignmentType::Viewport;
|
||||
const bool keepUpright = layout.text.keep_upright;
|
||||
|
||||
Placement placement;
|
||||
|
||||
|
||||
@@ -9,16 +9,16 @@
|
||||
namespace mbgl {
|
||||
|
||||
struct Anchor;
|
||||
class StyleBucketSymbol;
|
||||
class StyleLayoutSymbol;
|
||||
|
||||
class Placement {
|
||||
public:
|
||||
static Placement getIcon(Anchor &anchor, const Rect<uint16_t> &image, float iconBoxScale,
|
||||
const std::vector<Coordinate> &line, const StyleBucketSymbol &props);
|
||||
const std::vector<Coordinate> &line, const StyleLayoutSymbol &layout);
|
||||
|
||||
static Placement getGlyphs(Anchor &anchor, const vec2<float> &origin, const Shaping &shaping,
|
||||
const GlyphPositions &face, float boxScale, bool horizontal,
|
||||
const std::vector<Coordinate> &line, const StyleBucketSymbol &props);
|
||||
const std::vector<Coordinate> &line, const StyleLayoutSymbol &layout);
|
||||
|
||||
static const float globalMinScale;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user