summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAnand Thakker <anandthakker@users.noreply.github.com>2017-02-28 19:54:24 -0800
committerGitHub <noreply@github.com>2017-02-28 19:54:24 -0800
commitf901e776b3e63aaaa6bc0cc4476624bf84127fe6 (patch)
tree3e311971d57109c64e5ace45c111fb5909e7fb7b /src
parentc3ed1f51ca677c8c2045320fe13ec881cbd94772 (diff)
downloadqtlocation-mapboxgl-f901e776b3e63aaaa6bc0cc4476624bf84127fe6.tar.gz
[core] Implement data-driven styling for {text,icon}-{color,opacity,halo-color,halo-blur,halo-width} (#7939)
* Add symbol dds attributes and adapt style code generation * Update to mapbox-gl-js/master * Refactor SymbolFeature as a subclass of GeometryTileFeature Prepares for enabling DDS on symbol paint properties by allowing the SymbolFeatures, which we keep around after constructing SymbolLayout, to be used in evaluating data-driven paint properties later in the layout process. * Draft approach for splitting icon/text paint properties The `Program` types are set up to bind GL attributes to each of the data-driven paint properties specified in the `PaintProperties` type provided. Since `SymbolPaintProperties` specifies both `Text*` and `Icon*` properties, the symbolIcon, symbolIconSDF, and symbolGlyph programs each attempt to bind roughly double the number of attributes that they actually need. This change addresses this by: - Adding the more specific `IconPaintProperties` and `TextPaintProperties` types, which are subsets of the full `SymbolPaintProperties`. - The symbol layer continues to use its `SymbolPaintProperties paint` member to track layer property state, but it provides helpers that construct objects of each the specific `{Icon,Text}PaintProperties::Evaluated` type, for use by the painter. - The three symbol programs instantiate `Program<>` using the appropriate `{Icon,Text}PaintProperties` type. * check in generated style code * Populate paint buffers for symbol DDS properties * Address first round of review comments * Refactor VectorTile{Layer,Feature} to explicitly share data * Update submodule
Diffstat (limited to 'src')
-rw-r--r--src/mbgl/layout/symbol_feature.hpp17
-rw-r--r--src/mbgl/layout/symbol_instance.cpp5
-rw-r--r--src/mbgl/layout/symbol_instance.hpp3
-rw-r--r--src/mbgl/layout/symbol_layout.cpp51
-rw-r--r--src/mbgl/layout/symbol_layout.hpp7
-rw-r--r--src/mbgl/programs/attributes.hpp46
-rw-r--r--src/mbgl/programs/programs.hpp4
-rw-r--r--src/mbgl/programs/symbol_program.cpp88
-rw-r--r--src/mbgl/programs/symbol_program.hpp77
-rw-r--r--src/mbgl/renderer/painter_symbol.cpp46
-rw-r--r--src/mbgl/renderer/symbol_bucket.cpp12
-rw-r--r--src/mbgl/renderer/symbol_bucket.hpp10
-rw-r--r--src/mbgl/shaders/symbol_icon.cpp13
-rw-r--r--src/mbgl/shaders/symbol_sdf.cpp63
-rw-r--r--src/mbgl/style/layers/symbol_layer.cpp132
-rw-r--r--src/mbgl/style/layers/symbol_layer_impl.cpp56
-rw-r--r--src/mbgl/style/layers/symbol_layer_impl.hpp44
-rw-r--r--src/mbgl/style/layers/symbol_layer_properties.hpp20
-rw-r--r--src/mbgl/text/shaping.cpp9
-rw-r--r--src/mbgl/text/shaping.hpp3
-rw-r--r--src/mbgl/tile/vector_tile.cpp70
21 files changed, 503 insertions, 273 deletions
diff --git a/src/mbgl/layout/symbol_feature.hpp b/src/mbgl/layout/symbol_feature.hpp
index e55995f952..f4dc1680bc 100644
--- a/src/mbgl/layout/symbol_feature.hpp
+++ b/src/mbgl/layout/symbol_feature.hpp
@@ -8,14 +8,23 @@
namespace mbgl {
-class SymbolFeature {
+class SymbolFeature : public GeometryTileFeature {
public:
- FeatureType type;
+ SymbolFeature(std::unique_ptr<GeometryTileFeature> feature_) :
+ feature(std::move(feature_)),
+ geometry(feature->getGeometries()) // we need a mutable copy of the geometry for mergeLines()
+ {}
+
+ FeatureType getType() const override { return feature->getType(); }
+ optional<Value> getValue(const std::string& key) const override { return feature->getValue(key); };
+ std::unordered_map<std::string,Value> getProperties() const override { return feature->getProperties(); };
+ optional<FeatureIdentifier> getID() const override { return feature->getID(); };
+ GeometryCollection getGeometries() const override { return geometry; };
+
+ std::unique_ptr<GeometryTileFeature> feature;
GeometryCollection geometry;
optional<std::u16string> text;
optional<std::string> icon;
- std::array<float, 2> iconOffset;
- float iconRotation;
std::size_t index;
};
diff --git a/src/mbgl/layout/symbol_instance.cpp b/src/mbgl/layout/symbol_instance.cpp
index 4f425641e7..d81783b2f6 100644
--- a/src/mbgl/layout/symbol_instance.cpp
+++ b/src/mbgl/layout/symbol_instance.cpp
@@ -10,7 +10,7 @@ SymbolInstance::SymbolInstance(Anchor& anchor, const GeometryCoordinates& line,
const SymbolLayoutProperties::Evaluated& layout, const bool addToBuffers, const uint32_t index_,
const float textBoxScale, const float textPadding, const SymbolPlacementType textPlacement,
const float iconBoxScale, const float iconPadding, const SymbolPlacementType iconPlacement,
- const GlyphPositions& face, const IndexedSubfeature& indexedFeature) :
+ const GlyphPositions& face, const IndexedSubfeature& indexedFeature, const std::size_t featureIndex_) :
point(anchor.point),
index(index_),
hasText(shapedTextOrientations.first || shapedTextOrientations.second),
@@ -18,7 +18,8 @@ SymbolInstance::SymbolInstance(Anchor& anchor, const GeometryCoordinates& line,
// Create the collision features that will be used to check whether this symbol instance can be placed
textCollisionFeature(line, anchor, shapedTextOrientations.second ?: shapedTextOrientations.first, textBoxScale, textPadding, textPlacement, indexedFeature),
- iconCollisionFeature(line, anchor, shapedIcon, iconBoxScale, iconPadding, iconPlacement, indexedFeature) {
+ iconCollisionFeature(line, anchor, shapedIcon, iconBoxScale, iconPadding, iconPlacement, indexedFeature),
+ featureIndex(featureIndex_) {
// Create the quads used for rendering the icon and glyphs.
if (addToBuffers) {
diff --git a/src/mbgl/layout/symbol_instance.hpp b/src/mbgl/layout/symbol_instance.hpp
index 2dbb3bac23..532a4d30d8 100644
--- a/src/mbgl/layout/symbol_instance.hpp
+++ b/src/mbgl/layout/symbol_instance.hpp
@@ -17,7 +17,7 @@ public:
const style::SymbolLayoutProperties::Evaluated&, const bool inside, const uint32_t index,
const float textBoxScale, const float textPadding, style::SymbolPlacementType textPlacement,
const float iconBoxScale, const float iconPadding, style::SymbolPlacementType iconPlacement,
- const GlyphPositions& face, const IndexedSubfeature& indexedfeature);
+ const GlyphPositions& face, const IndexedSubfeature& indexedfeature, const std::size_t featureIndex);
Point<float> point;
uint32_t index;
@@ -28,6 +28,7 @@ public:
CollisionFeature textCollisionFeature;
CollisionFeature iconCollisionFeature;
WritingModeType writingModes;
+ std::size_t featureIndex;
};
} // namespace mbgl
diff --git a/src/mbgl/layout/symbol_layout.cpp b/src/mbgl/layout/symbol_layout.cpp
index cf9e784c26..3a2c082ad8 100644
--- a/src/mbgl/layout/symbol_layout.cpp
+++ b/src/mbgl/layout/symbol_layout.cpp
@@ -87,7 +87,10 @@ SymbolLayout::SymbolLayout(const BucketParameters& parameters,
}
for (const auto& layer : layers) {
- layerPaintProperties.emplace(layer->getID(), layer->as<SymbolLayer>()->impl->paint.evaluated);
+ layerPaintProperties.emplace(layer->getID(), std::make_pair(
+ layer->as<SymbolLayer>()->impl->iconPaintProperties(),
+ layer->as<SymbolLayer>()->impl->textPaintProperties()
+ ));
}
// Determine and load glyph ranges
@@ -96,12 +99,13 @@ SymbolLayout::SymbolLayout(const BucketParameters& parameters,
auto feature = sourceLayer.getFeature(i);
if (!leader.filter(feature->getType(), feature->getID(), [&] (const auto& key) { return feature->getValue(key); }))
continue;
+
+ SymbolFeature ft(std::move(feature));
- SymbolFeature ft;
ft.index = i;
- auto getValue = [&feature](const std::string& key) -> std::string {
- auto value = feature->getValue(key);
+ auto getValue = [&ft](const std::string& key) -> std::string {
+ auto value = ft.getValue(key);
if (!value)
return std::string();
if (value->is<std::string>())
@@ -118,12 +122,12 @@ SymbolLayout::SymbolLayout(const BucketParameters& parameters,
};
if (hasText) {
- std::string u8string = layout.evaluate<TextField>(zoom, *feature);
+ std::string u8string = layout.evaluate<TextField>(zoom, ft);
if (layout.get<TextField>().isConstant()) {
u8string = util::replaceTokens(u8string, getValue);
}
- auto textTransform = layout.evaluate<TextTransform>(zoom, *feature);
+ auto textTransform = layout.evaluate<TextTransform>(zoom, ft);
if (textTransform == TextTransformType::Uppercase) {
u8string = platform::uppercase(u8string);
@@ -144,13 +148,9 @@ SymbolLayout::SymbolLayout(const BucketParameters& parameters,
if (hasIcon) {
ft.icon = util::replaceTokens(layout.get<IconImage>(), getValue);
- ft.iconOffset = layout.evaluate<IconOffset>(zoom, *feature);
- ft.iconRotation = layout.evaluate<IconRotate>(zoom, *feature) * util::DEG2RAD;
}
if (ft.text || ft.icon) {
- ft.type = feature->getType();
- ft.geometry = feature->getGeometries();
features.push_back(std::move(ft));
}
}
@@ -229,7 +229,8 @@ void SymbolLayout::prepare(uintptr_t tileUID,
const bool textAlongLine = layout.get<TextRotationAlignment>() == AlignmentType::Map &&
layout.get<SymbolPlacement>() == SymbolPlacementType::Line;
- for (const auto& feature : features) {
+ for (auto it = features.begin(); it != features.end(); ++it) {
+ auto& feature = *it;
if (feature.geometry.empty()) continue;
std::pair<Shaping, Shaping> shapedTextOrientations;
@@ -273,7 +274,9 @@ void SymbolLayout::prepare(uintptr_t tileUID,
if (feature.icon) {
auto image = spriteAtlas.getIcon(*feature.icon);
if (image) {
- shapedIcon = shapeIcon(*image, feature);
+ shapedIcon = shapeIcon(*image,
+ layout.evaluate<IconOffset>(zoom, feature),
+ layout.evaluate<IconRotate>(zoom, feature) * util::DEG2RAD);
assert((*image).spriteImage);
if ((*image).spriteImage->sdf) {
sdfIcons = true;
@@ -288,15 +291,17 @@ void SymbolLayout::prepare(uintptr_t tileUID,
// if either shapedText or icon position is present, add the feature
if (shapedTextOrientations.first || shapedIcon) {
- addFeature(feature, shapedTextOrientations, shapedIcon, face);
+ addFeature(std::distance(features.begin(), it), feature, shapedTextOrientations, shapedIcon, face);
}
+
+ feature.geometry.clear();
}
- features.clear();
compareText.clear();
}
-void SymbolLayout::addFeature(const SymbolFeature& feature,
+void SymbolLayout::addFeature(const std::size_t index,
+ const SymbolFeature& feature,
const std::pair<Shaping, Shaping>& shapedTextOrientations,
const PositionedIcon& shapedIcon,
const GlyphPositions& face) {
@@ -345,8 +350,10 @@ void SymbolLayout::addFeature(const SymbolFeature& feature,
symbolInstances.emplace_back(anchor, line, shapedTextOrientations, shapedIcon, layout, addToBuffers, symbolInstances.size(),
textBoxScale, textPadding, textPlacement,
iconBoxScale, iconPadding, iconPlacement,
- face, indexedFeature);
+ face, indexedFeature, index);
};
+
+ const auto& type = feature.getType();
if (layout.get<SymbolPlacement>() == SymbolPlacementType::Line) {
auto clippedLines = util::clipLines(feature.geometry, 0, 0, util::EXTENT, util::EXTENT);
@@ -368,7 +375,7 @@ void SymbolLayout::addFeature(const SymbolFeature& feature,
}
}
}
- } else if (feature.type == FeatureType::Polygon) {
+ } else if (type == FeatureType::Polygon) {
for (const auto& polygon : classifyRings(feature.geometry)) {
Polygon<double> poly;
for (const auto& ring : polygon) {
@@ -384,12 +391,12 @@ void SymbolLayout::addFeature(const SymbolFeature& feature,
Anchor anchor(poi.x, poi.y, 0, minScale);
addSymbolInstance(polygon[0], anchor);
}
- } else if (feature.type == FeatureType::LineString) {
+ } else if (type == FeatureType::LineString) {
for (const auto& line : feature.geometry) {
Anchor anchor(line[0].x, line[0].y, 0, minScale);
addSymbolInstance(line, anchor);
}
- } else if (feature.type == FeatureType::Point) {
+ } else if (type == FeatureType::Point) {
for (const auto& points : feature.geometry) {
for (const auto& point : points) {
Anchor anchor(point.x, point.y, 0, minScale);
@@ -503,6 +510,12 @@ std::unique_ptr<SymbolBucket> SymbolLayout::place(CollisionTile& collisionTile)
keepUpright, iconPlacement, collisionTile.config.angle, symbolInstance.writingModes);
}
}
+
+ const auto& feature = features.at(symbolInstance.featureIndex);
+ for (auto& pair : bucket->paintPropertyBinders) {
+ pair.second.first.populateVertexVectors(feature, bucket->icon.vertices.vertexSize());
+ pair.second.second.populateVertexVectors(feature, bucket->text.vertices.vertexSize());
+ }
}
if (collisionTile.config.debug) {
diff --git a/src/mbgl/layout/symbol_layout.hpp b/src/mbgl/layout/symbol_layout.hpp
index dbfdad22d9..491d0078da 100644
--- a/src/mbgl/layout/symbol_layout.hpp
+++ b/src/mbgl/layout/symbol_layout.hpp
@@ -5,6 +5,7 @@
#include <mbgl/layout/symbol_feature.hpp>
#include <mbgl/layout/symbol_instance.hpp>
#include <mbgl/text/bidi.hpp>
+#include <mbgl/style/layers/symbol_layer_impl.hpp>
#include <memory>
#include <map>
@@ -51,10 +52,12 @@ public:
State state = Pending;
- std::unordered_map<std::string, style::SymbolPaintProperties::Evaluated> layerPaintProperties;
+ std::unordered_map<std::string,
+ std::pair<style::IconPaintProperties::Evaluated, style::TextPaintProperties::Evaluated>> layerPaintProperties;
private:
- void addFeature(const SymbolFeature&,
+ void addFeature(const size_t,
+ const SymbolFeature&,
const std::pair<Shaping, Shaping>& shapedTextOrientations,
const PositionedIcon& shapedIcon,
const GlyphPositions& face);
diff --git a/src/mbgl/programs/attributes.hpp b/src/mbgl/programs/attributes.hpp
index c4cc5dea8b..bb90f2c13c 100644
--- a/src/mbgl/programs/attributes.hpp
+++ b/src/mbgl/programs/attributes.hpp
@@ -64,6 +64,34 @@ struct a_color : gl::Attribute<gl::Normalized<uint8_t>, 4> {
}
};
+// used in the symbol sdf shader
+struct a_fill_color : gl::Attribute<gl::Normalized<uint8_t>, 4> {
+ static auto name() { return "a_fill_color"; }
+
+ static Value value(const Color& color) {
+ return {{
+ gl::Normalized<uint8_t>(color.r),
+ gl::Normalized<uint8_t>(color.g),
+ gl::Normalized<uint8_t>(color.b),
+ gl::Normalized<uint8_t>(color.a)
+ }};
+ }
+};
+
+// used in the symbol sdf shader
+struct a_halo_color : gl::Attribute<gl::Normalized<uint8_t>, 4> {
+ static auto name() { return "a_halo_color"; }
+
+ static Value value(const Color& color) {
+ return {{
+ gl::Normalized<uint8_t>(color.r),
+ gl::Normalized<uint8_t>(color.g),
+ gl::Normalized<uint8_t>(color.b),
+ gl::Normalized<uint8_t>(color.a)
+ }};
+ }
+};
+
struct a_stroke_color : gl::Attribute<gl::Normalized<uint8_t>, 4> {
static auto name() { return "a_stroke_color"; }
@@ -171,5 +199,23 @@ struct a_offset<1> : gl::Attribute<float, 1> {
}
};
+struct a_halo_width : gl::Attribute<float, 1> {
+ static auto name() { return "a_halo_width"; }
+
+ static Value value(float width) {
+ return {{ width }};
+ }
+};
+
+struct a_halo_blur : gl::Attribute<float, 1> {
+ static auto name() { return "a_halo_blur"; }
+
+ static Value value(float blur) {
+ return {{ blur }};
+ }
+};
+
+
+
} // namespace attributes
} // namespace mbgl
diff --git a/src/mbgl/programs/programs.hpp b/src/mbgl/programs/programs.hpp
index dd71c2ce97..742c5a221b 100644
--- a/src/mbgl/programs/programs.hpp
+++ b/src/mbgl/programs/programs.hpp
@@ -40,8 +40,8 @@ public:
LinePatternProgram linePattern;
RasterProgram raster;
SymbolIconProgram symbolIcon;
- SymbolSDFProgram symbolIconSDF;
- SymbolSDFProgram symbolGlyph;
+ SymbolSDFIconProgram symbolIconSDF;
+ SymbolSDFTextProgram symbolGlyph;
DebugProgram debug;
CollisionBoxProgram collisionBox;
diff --git a/src/mbgl/programs/symbol_program.cpp b/src/mbgl/programs/symbol_program.cpp
index 3f59000b94..19fe2bc2f6 100644
--- a/src/mbgl/programs/symbol_program.cpp
+++ b/src/mbgl/programs/symbol_program.cpp
@@ -2,6 +2,7 @@
#include <mbgl/renderer/render_tile.hpp>
#include <mbgl/map/transform_state.hpp>
#include <mbgl/style/layers/symbol_layer_impl.hpp>
+#include <mbgl/util/enum.hpp>
namespace mbgl {
@@ -19,6 +20,7 @@ Values makeValues(const style::SymbolPropertyValues& values,
std::array<float, 2> extrudeScale;
const float scale = values.paintSize / values.sdfScale;
+
if (values.pitchAlignment == AlignmentType::Map) {
extrudeScale.fill(tile.id.pixelsToTileUnits(1, state.getZoom()) * scale);
} else {
@@ -27,7 +29,7 @@ Values makeValues(const style::SymbolPropertyValues& values,
pixelsToGLUnits[1] * scale * state.getCameraToCenterDistance()
}};
}
-
+
// adjust min/max zooms for variable font sies
float zoomAdjust = std::log(values.paintSize / values.layoutSize) / std::log(2);
@@ -35,7 +37,6 @@ Values makeValues(const style::SymbolPropertyValues& values,
uniforms::u_matrix::Value{ tile.translatedMatrix(values.translate,
values.translateAnchor,
state) },
- uniforms::u_opacity::Value{ values.opacity },
uniforms::u_extrude_scale::Value{ extrudeScale },
uniforms::u_texsize::Value{ std::array<float, 2> {{ float(texsize.width) / 4, float(texsize.height) / 4 }} },
uniforms::u_zoom::Value{ float((state.getZoom() - zoomAdjust) * 10) },
@@ -62,84 +63,37 @@ SymbolIconProgram::uniformValues(const style::SymbolPropertyValues& values,
);
}
-static SymbolSDFProgram::UniformValues makeSDFValues(const style::SymbolPropertyValues& values,
- const Size& texsize,
- const std::array<float, 2>& pixelsToGLUnits,
- const RenderTile& tile,
- const TransformState& state,
- float pixelRatio,
- Color color,
- float buffer,
- float gammaAdjust)
-{
- // The default gamma value has to be adjust for the current pixelratio so that we're not
- // drawing blurry font on retina screens.
- const float gammaBase = 0.105 * values.sdfScale / values.paintSize / pixelRatio;
- const float gammaScale = (values.pitchAlignment == AlignmentType::Map
- ? 1.0 / std::cos(state.getPitch())
- : 1.0) / state.getCameraToCenterDistance();
-
- return makeValues<SymbolSDFProgram::UniformValues>(
- values,
- texsize,
- pixelsToGLUnits,
- tile,
- state,
- uniforms::u_color::Value{ color },
- uniforms::u_buffer::Value{ buffer },
- uniforms::u_gamma::Value{ (gammaBase + gammaAdjust) * gammaScale },
- uniforms::u_pitch::Value{ state.getPitch() },
- uniforms::u_bearing::Value{ -1.0f * state.getAngle() },
- uniforms::u_aspect_ratio::Value{ (state.getSize().width * 1.0f) / (state.getSize().height * 1.0f) },
- uniforms::u_pitch_with_map::Value{ values.pitchAlignment == AlignmentType::Map }
- );
-}
-
-SymbolSDFProgram::UniformValues
-SymbolSDFProgram::haloUniformValues(const style::SymbolPropertyValues& values,
+template <class PaintProperties>
+typename SymbolSDFProgram<PaintProperties>::UniformValues SymbolSDFProgram<PaintProperties>::uniformValues(const style::SymbolPropertyValues& values,
const Size& texsize,
const std::array<float, 2>& pixelsToGLUnits,
const RenderTile& tile,
const TransformState& state,
- float pixelRatio)
+ const SymbolSDFPart part)
{
const float scale = values.paintSize / values.sdfScale;
- const float sdfPx = 8.0f;
- const float blurOffset = 1.19f;
- const float haloOffset = 6.0f;
-
- return makeSDFValues(
+
+ const float gammaScale = scale * (values.pitchAlignment == AlignmentType::Map
+ ? std::cos(state.getPitch())
+ : 1.0) * state.getCameraToCenterDistance();
+
+ return makeValues<SymbolSDFProgram<PaintProperties>::UniformValues>(
values,
texsize,
pixelsToGLUnits,
tile,
state,
- pixelRatio,
- values.haloColor,
- (haloOffset - values.haloWidth / scale) / sdfPx,
- values.haloBlur * blurOffset / scale / sdfPx
+ uniforms::u_font_scale::Value{ scale },
+ uniforms::u_gamma_scale::Value{ gammaScale },
+ uniforms::u_pitch::Value{ state.getPitch() },
+ uniforms::u_bearing::Value{ -1.0f * state.getAngle() },
+ uniforms::u_aspect_ratio::Value{ (state.getSize().width * 1.0f) / (state.getSize().height * 1.0f) },
+ uniforms::u_pitch_with_map::Value{ values.pitchAlignment == AlignmentType::Map },
+ uniforms::u_is_halo::Value{ part == SymbolSDFPart::Halo }
);
}
-SymbolSDFProgram::UniformValues
-SymbolSDFProgram::foregroundUniformValues(const style::SymbolPropertyValues& values,
- const Size& texsize,
- const std::array<float, 2>& pixelsToGLUnits,
- const RenderTile& tile,
- const TransformState& state,
- float pixelRatio)
-{
- return makeSDFValues(
- values,
- texsize,
- pixelsToGLUnits,
- tile,
- state,
- pixelRatio,
- values.color,
- (256.0f - 64.0f) / 256.0f,
- 0
- );
-}
+template class SymbolSDFProgram<style::IconPaintProperties>;
+template class SymbolSDFProgram<style::TextPaintProperties>;
} // namespace mbgl
diff --git a/src/mbgl/programs/symbol_program.hpp b/src/mbgl/programs/symbol_program.hpp
index e0e90f0fa4..0537c25a2c 100644
--- a/src/mbgl/programs/symbol_program.hpp
+++ b/src/mbgl/programs/symbol_program.hpp
@@ -8,6 +8,7 @@
#include <mbgl/util/geometry.hpp>
#include <mbgl/util/size.hpp>
#include <mbgl/style/layers/symbol_layer_properties.hpp>
+#include <mbgl/style/layers/symbol_layer_impl.hpp>
#include <cmath>
#include <array>
@@ -27,9 +28,10 @@ MBGL_DEFINE_UNIFORM_SCALAR(bool, u_rotate_with_map);
MBGL_DEFINE_UNIFORM_SCALAR(bool, u_pitch_with_map);
MBGL_DEFINE_UNIFORM_SCALAR(gl::TextureUnit, u_texture);
MBGL_DEFINE_UNIFORM_SCALAR(gl::TextureUnit, u_fadetexture);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_buffer);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_gamma);
MBGL_DEFINE_UNIFORM_SCALAR(float, u_aspect_ratio);
+MBGL_DEFINE_UNIFORM_SCALAR(bool, u_is_halo);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_font_scale);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_gamma_scale);
} // namespace uniforms
struct SymbolLayoutAttributes : gl::Attributes<
@@ -75,14 +77,13 @@ class SymbolIconProgram : public Program<
SymbolLayoutAttributes,
gl::Uniforms<
uniforms::u_matrix,
- uniforms::u_opacity,
uniforms::u_extrude_scale,
uniforms::u_texsize,
uniforms::u_zoom,
uniforms::u_rotate_with_map,
uniforms::u_texture,
uniforms::u_fadetexture>,
- style::SymbolPaintProperties>
+ style::IconPaintProperties>
{
public:
using Program::Program;
@@ -94,47 +95,73 @@ public:
const TransformState&);
};
+enum class SymbolSDFPart {
+ Fill = 1,
+ Halo = 0
+};
+
+template <class PaintProperties>
class SymbolSDFProgram : public Program<
shaders::symbol_sdf,
gl::Triangle,
SymbolLayoutAttributes,
gl::Uniforms<
uniforms::u_matrix,
- uniforms::u_opacity,
uniforms::u_extrude_scale,
uniforms::u_texsize,
uniforms::u_zoom,
uniforms::u_rotate_with_map,
uniforms::u_texture,
uniforms::u_fadetexture,
- uniforms::u_color,
- uniforms::u_buffer,
- uniforms::u_gamma,
+ uniforms::u_font_scale,
+ uniforms::u_gamma_scale,
uniforms::u_pitch,
uniforms::u_bearing,
uniforms::u_aspect_ratio,
- uniforms::u_pitch_with_map>,
- style::SymbolPaintProperties>
+ uniforms::u_pitch_with_map,
+ uniforms::u_is_halo>,
+ PaintProperties>
{
public:
- using Program::Program;
+ using BaseProgram = Program<shaders::symbol_sdf,
+ gl::Triangle,
+ SymbolLayoutAttributes,
+ gl::Uniforms<
+ uniforms::u_matrix,
+ uniforms::u_extrude_scale,
+ uniforms::u_texsize,
+ uniforms::u_zoom,
+ uniforms::u_rotate_with_map,
+ uniforms::u_texture,
+ uniforms::u_fadetexture,
+ uniforms::u_font_scale,
+ uniforms::u_gamma_scale,
+ uniforms::u_pitch,
+ uniforms::u_bearing,
+ uniforms::u_aspect_ratio,
+ uniforms::u_pitch_with_map,
+ uniforms::u_is_halo>,
+ PaintProperties>;
+
+ using UniformValues = typename BaseProgram::UniformValues;
+
- static UniformValues haloUniformValues(const style::SymbolPropertyValues&,
- const Size& texsize,
- const std::array<float, 2>& pixelsToGLUnits,
- const RenderTile&,
- const TransformState&,
- float pixelRatio);
-
- static UniformValues foregroundUniformValues(const style::SymbolPropertyValues&,
- const Size& texsize,
- const std::array<float, 2>& pixelsToGLUnits,
- const RenderTile&,
- const TransformState&,
- float pixelRatio);
+
+ using BaseProgram::BaseProgram;
+
+ static UniformValues uniformValues(const style::SymbolPropertyValues&,
+ const Size& texsize,
+ const std::array<float, 2>& pixelsToGLUnits,
+ const RenderTile&,
+ const TransformState&,
+ const SymbolSDFPart);
};
+using SymbolSDFIconProgram = SymbolSDFProgram<style::IconPaintProperties>;
+using SymbolSDFTextProgram = SymbolSDFProgram<style::TextPaintProperties>;
+
using SymbolLayoutVertex = SymbolLayoutAttributes::Vertex;
-using SymbolAttributes = SymbolIconProgram::Attributes;
+using SymbolIconAttributes = SymbolIconProgram::Attributes;
+using SymbolTextAttributes = SymbolSDFTextProgram::Attributes;
} // namespace mbgl
diff --git a/src/mbgl/renderer/painter_symbol.cpp b/src/mbgl/renderer/painter_symbol.cpp
index 0113c15a08..48c2e7ff66 100644
--- a/src/mbgl/renderer/painter_symbol.cpp
+++ b/src/mbgl/renderer/painter_symbol.cpp
@@ -33,7 +33,9 @@ void Painter::renderSymbol(PaintParameters& parameters,
auto draw = [&] (auto& program,
auto&& uniformValues,
const auto& buffers,
- const SymbolPropertyValues& values_)
+ const SymbolPropertyValues& values_,
+ const auto& binders,
+ const auto& paintProperties)
{
// We clip symbols to their tile extent in still mode.
const bool needsClipping = frame.mapMode == MapMode::Still;
@@ -52,14 +54,15 @@ void Painter::renderSymbol(PaintParameters& parameters,
*buffers.vertexBuffer,
*buffers.indexBuffer,
buffers.segments,
- bucket.paintPropertyBinders.at(layer.getID()),
- layer.impl->paint.evaluated,
+ binders,
+ paintProperties,
state.getZoom()
);
};
if (bucket.hasIconData()) {
auto values = layer.impl->iconPropertyValues(layout);
+ auto paintPropertyValues = layer.impl->iconPaintProperties();
SpriteAtlas& atlas = *layer.impl->spriteAtlas;
const bool iconScaled = values.paintSize != 1.0f || frame.pixelRatio != atlas.getPixelRatio() || bucket.iconsNeedLinear;
@@ -69,24 +72,30 @@ void Painter::renderSymbol(PaintParameters& parameters,
const Size texsize = atlas.getSize();
if (bucket.sdfIcons) {
- if (values.hasHalo()) {
+ if (values.hasHalo) {
draw(parameters.programs.symbolIconSDF,
- SymbolSDFProgram::haloUniformValues(values, texsize, pixelsToGLUnits, tile, state, frame.pixelRatio),
+ SymbolSDFIconProgram::uniformValues(values, texsize, pixelsToGLUnits, tile, state, SymbolSDFPart::Halo),
bucket.icon,
- values);
+ values,
+ bucket.paintPropertyBinders.at(layer.getID()).first,
+ paintPropertyValues);
}
- if (values.hasForeground()) {
+ if (values.hasFill) {
draw(parameters.programs.symbolIconSDF,
- SymbolSDFProgram::foregroundUniformValues(values, texsize, pixelsToGLUnits, tile, state, frame.pixelRatio),
+ SymbolSDFIconProgram::uniformValues(values, texsize, pixelsToGLUnits, tile, state, SymbolSDFPart::Fill),
bucket.icon,
- values);
+ values,
+ bucket.paintPropertyBinders.at(layer.getID()).first,
+ paintPropertyValues);
}
} else {
draw(parameters.programs.symbolIcon,
SymbolIconProgram::uniformValues(values, texsize, pixelsToGLUnits, tile, state),
bucket.icon,
- values);
+ values,
+ bucket.paintPropertyBinders.at(layer.getID()).first,
+ paintPropertyValues);
}
}
@@ -94,21 +103,26 @@ void Painter::renderSymbol(PaintParameters& parameters,
glyphAtlas->bind(context, 0);
auto values = layer.impl->textPropertyValues(layout);
+ auto paintPropertyValues = layer.impl->textPaintProperties();
const Size texsize = glyphAtlas->getSize();
- if (values.hasHalo()) {
+ if (values.hasHalo) {
draw(parameters.programs.symbolGlyph,
- SymbolSDFProgram::haloUniformValues(values, texsize, pixelsToGLUnits, tile, state, frame.pixelRatio),
+ SymbolSDFTextProgram::uniformValues(values, texsize, pixelsToGLUnits, tile, state, SymbolSDFPart::Halo),
bucket.text,
- values);
+ values,
+ bucket.paintPropertyBinders.at(layer.getID()).second,
+ paintPropertyValues);
}
- if (values.hasForeground()) {
+ if (values.hasFill) {
draw(parameters.programs.symbolGlyph,
- SymbolSDFProgram::foregroundUniformValues(values, texsize, pixelsToGLUnits, tile, state, frame.pixelRatio),
+ SymbolSDFTextProgram::uniformValues(values, texsize, pixelsToGLUnits, tile, state, SymbolSDFPart::Fill),
bucket.text,
- values);
+ values,
+ bucket.paintPropertyBinders.at(layer.getID()).second,
+ paintPropertyValues);
}
}
diff --git a/src/mbgl/renderer/symbol_bucket.cpp b/src/mbgl/renderer/symbol_bucket.cpp
index 9d4bde9d07..fa4178dda1 100644
--- a/src/mbgl/renderer/symbol_bucket.cpp
+++ b/src/mbgl/renderer/symbol_bucket.cpp
@@ -9,7 +9,8 @@ namespace mbgl {
using namespace style;
SymbolBucket::SymbolBucket(style::SymbolLayoutProperties::Evaluated layout_,
- const std::unordered_map<std::string, style::SymbolPaintProperties::Evaluated>& layerPaintProperties,
+ const std::unordered_map<std::string, std::pair<
+ style::IconPaintProperties::Evaluated, style::TextPaintProperties::Evaluated>>& layerPaintProperties,
float zoom,
bool sdfIcons_,
bool iconsNeedLinear_)
@@ -17,8 +18,10 @@ SymbolBucket::SymbolBucket(style::SymbolLayoutProperties::Evaluated layout_,
sdfIcons(sdfIcons_),
iconsNeedLinear(iconsNeedLinear_) {
for (const auto& pair : layerPaintProperties) {
- paintPropertyBinders.emplace(pair.first,
- SymbolIconProgram::PaintPropertyBinders(pair.second, zoom));
+ paintPropertyBinders.emplace(pair.first, std::make_pair(
+ SymbolIconProgram::PaintPropertyBinders(pair.second.first, zoom),
+ SymbolSDFTextProgram::PaintPropertyBinders(pair.second.second, zoom)
+ ));
}
}
@@ -39,7 +42,8 @@ void SymbolBucket::upload(gl::Context& context) {
}
for (auto& pair : paintPropertyBinders) {
- pair.second.upload(context);
+ pair.second.first.upload(context);
+ pair.second.second.upload(context);
}
uploaded = true;
diff --git a/src/mbgl/renderer/symbol_bucket.hpp b/src/mbgl/renderer/symbol_bucket.hpp
index 0b40bb34ae..dcf3f5f495 100644
--- a/src/mbgl/renderer/symbol_bucket.hpp
+++ b/src/mbgl/renderer/symbol_bucket.hpp
@@ -17,7 +17,7 @@ namespace mbgl {
class SymbolBucket : public Bucket {
public:
SymbolBucket(style::SymbolLayoutProperties::Evaluated,
- const std::unordered_map<std::string, style::SymbolPaintProperties::Evaluated>&,
+ const std::unordered_map<std::string, std::pair<style::IconPaintProperties::Evaluated, style::TextPaintProperties::Evaluated>>&,
float zoom,
bool sdfIcons,
bool iconsNeedLinear);
@@ -33,12 +33,14 @@ public:
const bool sdfIcons;
const bool iconsNeedLinear;
- std::unordered_map<std::string, SymbolIconProgram::PaintPropertyBinders> paintPropertyBinders;
+ std::unordered_map<std::string, std::pair<
+ SymbolIconProgram::PaintPropertyBinders,
+ SymbolSDFTextProgram::PaintPropertyBinders>> paintPropertyBinders;
struct TextBuffer {
gl::VertexVector<SymbolLayoutVertex> vertices;
gl::IndexVector<gl::Triangles> triangles;
- gl::SegmentVector<SymbolAttributes> segments;
+ gl::SegmentVector<SymbolTextAttributes> segments;
optional<gl::VertexBuffer<SymbolLayoutVertex>> vertexBuffer;
optional<gl::IndexBuffer<gl::Triangles>> indexBuffer;
@@ -47,7 +49,7 @@ public:
struct IconBuffer {
gl::VertexVector<SymbolLayoutVertex> vertices;
gl::IndexVector<gl::Triangles> triangles;
- gl::SegmentVector<SymbolAttributes> segments;
+ gl::SegmentVector<SymbolIconAttributes> segments;
optional<gl::VertexBuffer<SymbolLayoutVertex>> vertexBuffer;
optional<gl::IndexBuffer<gl::Triangles>> indexBuffer;
diff --git a/src/mbgl/shaders/symbol_icon.cpp b/src/mbgl/shaders/symbol_icon.cpp
index eca9342d54..e6728e15de 100644
--- a/src/mbgl/shaders/symbol_icon.cpp
+++ b/src/mbgl/shaders/symbol_icon.cpp
@@ -66,6 +66,10 @@ attribute vec2 a_offset;
attribute vec2 a_texture_pos;
attribute vec4 a_data;
+uniform lowp float a_opacity_t;
+attribute lowp float a_opacity_min;
+attribute lowp float a_opacity_max;
+varying lowp float opacity;
// matrix is for the vertex position.
uniform mat4 u_matrix;
@@ -80,6 +84,8 @@ varying vec2 v_tex;
varying vec2 v_fade_tex;
void main() {
+ opacity = mix(a_opacity_min, a_opacity_max, a_opacity_t);
+
vec2 a_tex = a_texture_pos.xy;
mediump float a_labelminzoom = a_data[0];
mediump vec2 a_zoom = a_data.pq;
@@ -122,13 +128,16 @@ precision mediump float;
#endif
uniform sampler2D u_texture;
uniform sampler2D u_fadetexture;
-uniform lowp float u_opacity;
+
+varying lowp float opacity;
varying vec2 v_tex;
varying vec2 v_fade_tex;
void main() {
- lowp float alpha = texture2D(u_fadetexture, v_fade_tex).a * u_opacity;
+
+
+ lowp float alpha = texture2D(u_fadetexture, v_fade_tex).a * opacity;
gl_FragColor = texture2D(u_texture, v_tex) * alpha;
#ifdef OVERDRAW_INSPECTOR
diff --git a/src/mbgl/shaders/symbol_sdf.cpp b/src/mbgl/shaders/symbol_sdf.cpp
index 7554597893..e087242bf8 100644
--- a/src/mbgl/shaders/symbol_sdf.cpp
+++ b/src/mbgl/shaders/symbol_sdf.cpp
@@ -68,6 +68,26 @@ attribute vec2 a_offset;
attribute vec2 a_texture_pos;
attribute vec4 a_data;
+uniform lowp float a_fill_color_t;
+attribute lowp vec4 a_fill_color_min;
+attribute lowp vec4 a_fill_color_max;
+varying lowp vec4 fill_color;
+uniform lowp float a_halo_color_t;
+attribute lowp vec4 a_halo_color_min;
+attribute lowp vec4 a_halo_color_max;
+varying lowp vec4 halo_color;
+uniform lowp float a_opacity_t;
+attribute lowp float a_opacity_min;
+attribute lowp float a_opacity_max;
+varying lowp float opacity;
+uniform lowp float a_halo_width_t;
+attribute lowp float a_halo_width_min;
+attribute lowp float a_halo_width_max;
+varying lowp float halo_width;
+uniform lowp float a_halo_blur_t;
+attribute lowp float a_halo_blur_min;
+attribute lowp float a_halo_blur_max;
+varying lowp float halo_blur;
// matrix is for the vertex position.
uniform mat4 u_matrix;
@@ -87,6 +107,12 @@ varying vec2 v_fade_tex;
varying float v_gamma_scale;
void main() {
+ fill_color = mix(a_fill_color_min, a_fill_color_max, a_fill_color_t);
+ halo_color = mix(a_halo_color_min, a_halo_color_max, a_halo_color_t);
+ opacity = mix(a_opacity_min, a_opacity_max, a_opacity_t);
+ halo_width = mix(a_halo_width_min, a_halo_width_max, a_halo_width_t);
+ halo_blur = mix(a_halo_blur_min, a_halo_blur_max, a_halo_blur_t);
+
vec2 a_tex = a_texture_pos.xy;
mediump float a_labelminzoom = a_data[0];
mediump vec2 a_zoom = a_data.pq;
@@ -163,24 +189,47 @@ precision mediump float;
#endif
#endif
+#define SDF_PX 8.0
+#define EDGE_GAMMA 0.105/DEVICE_PIXEL_RATIO
+
+uniform bool u_is_halo;
+varying lowp vec4 fill_color;
+varying lowp vec4 halo_color;
+varying lowp float opacity;
+varying lowp float halo_width;
+varying lowp float halo_blur;
+
uniform sampler2D u_texture;
uniform sampler2D u_fadetexture;
-uniform lowp vec4 u_color;
-uniform lowp float u_opacity;
-uniform lowp float u_buffer;
-uniform highp float u_gamma;
+uniform lowp float u_font_scale;
+uniform highp float u_gamma_scale;
varying vec2 v_tex;
varying vec2 v_fade_tex;
varying float v_gamma_scale;
void main() {
+
+
+
+
+
+
+ lowp vec4 color = fill_color;
+ lowp float gamma = EDGE_GAMMA / u_gamma_scale;
+ lowp float buff = (256.0 - 64.0) / 256.0;
+ if (u_is_halo) {
+ color = halo_color;
+ gamma = (halo_blur * 1.19 / SDF_PX + EDGE_GAMMA) / u_gamma_scale;
+ buff = (6.0 - halo_width / u_font_scale) / SDF_PX;
+ }
+
lowp float dist = texture2D(u_texture, v_tex).a;
lowp float fade_alpha = texture2D(u_fadetexture, v_fade_tex).a;
- highp float gamma = u_gamma * v_gamma_scale;
- highp float alpha = smoothstep(u_buffer - gamma, u_buffer + gamma, dist) * fade_alpha;
+ highp float gamma_scaled = gamma * v_gamma_scale;
+ highp float alpha = smoothstep(buff - gamma_scaled, buff + gamma_scaled, dist) * fade_alpha;
- gl_FragColor = u_color * (alpha * u_opacity);
+ gl_FragColor = color * (alpha * opacity);
#ifdef OVERDRAW_INSPECTOR
gl_FragColor = vec4(1.0);
diff --git a/src/mbgl/style/layers/symbol_layer.cpp b/src/mbgl/style/layers/symbol_layer.cpp
index 6364091207..d85b8c00e6 100644
--- a/src/mbgl/style/layers/symbol_layer.cpp
+++ b/src/mbgl/style/layers/symbol_layer.cpp
@@ -542,95 +542,115 @@ void SymbolLayer::setTextOptional(PropertyValue<bool> value) {
// Paint properties
-PropertyValue<float> SymbolLayer::getDefaultIconOpacity() {
+DataDrivenPropertyValue<float> SymbolLayer::getDefaultIconOpacity() {
return { 1 };
}
-PropertyValue<float> SymbolLayer::getIconOpacity(const optional<std::string>& klass) const {
+DataDrivenPropertyValue<float> SymbolLayer::getIconOpacity(const optional<std::string>& klass) const {
return impl->paint.get<IconOpacity>(klass);
}
-void SymbolLayer::setIconOpacity(PropertyValue<float> value, const optional<std::string>& klass) {
+void SymbolLayer::setIconOpacity(DataDrivenPropertyValue<float> value, const optional<std::string>& klass) {
if (value == getIconOpacity(klass))
return;
impl->paint.set<IconOpacity>(value, klass);
- impl->observer->onLayerPaintPropertyChanged(*this);
+ if (value.isDataDriven()) {
+ impl->observer->onLayerDataDrivenPaintPropertyChanged(*this);
+ } else {
+ impl->observer->onLayerPaintPropertyChanged(*this);
+ }
}
void SymbolLayer::setIconOpacityTransition(const TransitionOptions& value, const optional<std::string>& klass) {
impl->paint.setTransition<IconOpacity>(value, klass);
}
-PropertyValue<Color> SymbolLayer::getDefaultIconColor() {
+DataDrivenPropertyValue<Color> SymbolLayer::getDefaultIconColor() {
return { Color::black() };
}
-PropertyValue<Color> SymbolLayer::getIconColor(const optional<std::string>& klass) const {
+DataDrivenPropertyValue<Color> SymbolLayer::getIconColor(const optional<std::string>& klass) const {
return impl->paint.get<IconColor>(klass);
}
-void SymbolLayer::setIconColor(PropertyValue<Color> value, const optional<std::string>& klass) {
+void SymbolLayer::setIconColor(DataDrivenPropertyValue<Color> value, const optional<std::string>& klass) {
if (value == getIconColor(klass))
return;
impl->paint.set<IconColor>(value, klass);
- impl->observer->onLayerPaintPropertyChanged(*this);
+ if (value.isDataDriven()) {
+ impl->observer->onLayerDataDrivenPaintPropertyChanged(*this);
+ } else {
+ impl->observer->onLayerPaintPropertyChanged(*this);
+ }
}
void SymbolLayer::setIconColorTransition(const TransitionOptions& value, const optional<std::string>& klass) {
impl->paint.setTransition<IconColor>(value, klass);
}
-PropertyValue<Color> SymbolLayer::getDefaultIconHaloColor() {
+DataDrivenPropertyValue<Color> SymbolLayer::getDefaultIconHaloColor() {
return { {} };
}
-PropertyValue<Color> SymbolLayer::getIconHaloColor(const optional<std::string>& klass) const {
+DataDrivenPropertyValue<Color> SymbolLayer::getIconHaloColor(const optional<std::string>& klass) const {
return impl->paint.get<IconHaloColor>(klass);
}
-void SymbolLayer::setIconHaloColor(PropertyValue<Color> value, const optional<std::string>& klass) {
+void SymbolLayer::setIconHaloColor(DataDrivenPropertyValue<Color> value, const optional<std::string>& klass) {
if (value == getIconHaloColor(klass))
return;
impl->paint.set<IconHaloColor>(value, klass);
- impl->observer->onLayerPaintPropertyChanged(*this);
+ if (value.isDataDriven()) {
+ impl->observer->onLayerDataDrivenPaintPropertyChanged(*this);
+ } else {
+ impl->observer->onLayerPaintPropertyChanged(*this);
+ }
}
void SymbolLayer::setIconHaloColorTransition(const TransitionOptions& value, const optional<std::string>& klass) {
impl->paint.setTransition<IconHaloColor>(value, klass);
}
-PropertyValue<float> SymbolLayer::getDefaultIconHaloWidth() {
+DataDrivenPropertyValue<float> SymbolLayer::getDefaultIconHaloWidth() {
return { 0 };
}
-PropertyValue<float> SymbolLayer::getIconHaloWidth(const optional<std::string>& klass) const {
+DataDrivenPropertyValue<float> SymbolLayer::getIconHaloWidth(const optional<std::string>& klass) const {
return impl->paint.get<IconHaloWidth>(klass);
}
-void SymbolLayer::setIconHaloWidth(PropertyValue<float> value, const optional<std::string>& klass) {
+void SymbolLayer::setIconHaloWidth(DataDrivenPropertyValue<float> value, const optional<std::string>& klass) {
if (value == getIconHaloWidth(klass))
return;
impl->paint.set<IconHaloWidth>(value, klass);
- impl->observer->onLayerPaintPropertyChanged(*this);
+ if (value.isDataDriven()) {
+ impl->observer->onLayerDataDrivenPaintPropertyChanged(*this);
+ } else {
+ impl->observer->onLayerPaintPropertyChanged(*this);
+ }
}
void SymbolLayer::setIconHaloWidthTransition(const TransitionOptions& value, const optional<std::string>& klass) {
impl->paint.setTransition<IconHaloWidth>(value, klass);
}
-PropertyValue<float> SymbolLayer::getDefaultIconHaloBlur() {
+DataDrivenPropertyValue<float> SymbolLayer::getDefaultIconHaloBlur() {
return { 0 };
}
-PropertyValue<float> SymbolLayer::getIconHaloBlur(const optional<std::string>& klass) const {
+DataDrivenPropertyValue<float> SymbolLayer::getIconHaloBlur(const optional<std::string>& klass) const {
return impl->paint.get<IconHaloBlur>(klass);
}
-void SymbolLayer::setIconHaloBlur(PropertyValue<float> value, const optional<std::string>& klass) {
+void SymbolLayer::setIconHaloBlur(DataDrivenPropertyValue<float> value, const optional<std::string>& klass) {
if (value == getIconHaloBlur(klass))
return;
impl->paint.set<IconHaloBlur>(value, klass);
- impl->observer->onLayerPaintPropertyChanged(*this);
+ if (value.isDataDriven()) {
+ impl->observer->onLayerDataDrivenPaintPropertyChanged(*this);
+ } else {
+ impl->observer->onLayerPaintPropertyChanged(*this);
+ }
}
void SymbolLayer::setIconHaloBlurTransition(const TransitionOptions& value, const optional<std::string>& klass) {
@@ -671,99 +691,119 @@ void SymbolLayer::setIconTranslateAnchor(PropertyValue<TranslateAnchorType> valu
impl->observer->onLayerPaintPropertyChanged(*this);
}
-PropertyValue<float> SymbolLayer::getDefaultTextOpacity() {
- return { 1 };
-}
-
void SymbolLayer::setIconTranslateAnchorTransition(const TransitionOptions& value, const optional<std::string>& klass) {
impl->paint.setTransition<IconTranslateAnchor>(value, klass);
}
-PropertyValue<float> SymbolLayer::getTextOpacity(const optional<std::string>& klass) const {
+DataDrivenPropertyValue<float> SymbolLayer::getDefaultTextOpacity() {
+ return { 1 };
+}
+
+DataDrivenPropertyValue<float> SymbolLayer::getTextOpacity(const optional<std::string>& klass) const {
return impl->paint.get<TextOpacity>(klass);
}
-void SymbolLayer::setTextOpacity(PropertyValue<float> value, const optional<std::string>& klass) {
+void SymbolLayer::setTextOpacity(DataDrivenPropertyValue<float> value, const optional<std::string>& klass) {
if (value == getTextOpacity(klass))
return;
impl->paint.set<TextOpacity>(value, klass);
- impl->observer->onLayerPaintPropertyChanged(*this);
-}
-
-PropertyValue<Color> SymbolLayer::getDefaultTextColor() {
- return { Color::black() };
+ if (value.isDataDriven()) {
+ impl->observer->onLayerDataDrivenPaintPropertyChanged(*this);
+ } else {
+ impl->observer->onLayerPaintPropertyChanged(*this);
+ }
}
void SymbolLayer::setTextOpacityTransition(const TransitionOptions& value, const optional<std::string>& klass) {
impl->paint.setTransition<TextOpacity>(value, klass);
}
-PropertyValue<Color> SymbolLayer::getTextColor(const optional<std::string>& klass) const {
+DataDrivenPropertyValue<Color> SymbolLayer::getDefaultTextColor() {
+ return { Color::black() };
+}
+
+DataDrivenPropertyValue<Color> SymbolLayer::getTextColor(const optional<std::string>& klass) const {
return impl->paint.get<TextColor>(klass);
}
-void SymbolLayer::setTextColor(PropertyValue<Color> value, const optional<std::string>& klass) {
+void SymbolLayer::setTextColor(DataDrivenPropertyValue<Color> value, const optional<std::string>& klass) {
if (value == getTextColor(klass))
return;
impl->paint.set<TextColor>(value, klass);
- impl->observer->onLayerPaintPropertyChanged(*this);
+ if (value.isDataDriven()) {
+ impl->observer->onLayerDataDrivenPaintPropertyChanged(*this);
+ } else {
+ impl->observer->onLayerPaintPropertyChanged(*this);
+ }
}
void SymbolLayer::setTextColorTransition(const TransitionOptions& value, const optional<std::string>& klass) {
impl->paint.setTransition<TextColor>(value, klass);
}
-PropertyValue<Color> SymbolLayer::getDefaultTextHaloColor() {
+DataDrivenPropertyValue<Color> SymbolLayer::getDefaultTextHaloColor() {
return { {} };
}
-PropertyValue<Color> SymbolLayer::getTextHaloColor(const optional<std::string>& klass) const {
+DataDrivenPropertyValue<Color> SymbolLayer::getTextHaloColor(const optional<std::string>& klass) const {
return impl->paint.get<TextHaloColor>(klass);
}
-void SymbolLayer::setTextHaloColor(PropertyValue<Color> value, const optional<std::string>& klass) {
+void SymbolLayer::setTextHaloColor(DataDrivenPropertyValue<Color> value, const optional<std::string>& klass) {
if (value == getTextHaloColor(klass))
return;
impl->paint.set<TextHaloColor>(value, klass);
- impl->observer->onLayerPaintPropertyChanged(*this);
+ if (value.isDataDriven()) {
+ impl->observer->onLayerDataDrivenPaintPropertyChanged(*this);
+ } else {
+ impl->observer->onLayerPaintPropertyChanged(*this);
+ }
}
void SymbolLayer::setTextHaloColorTransition(const TransitionOptions& value, const optional<std::string>& klass) {
impl->paint.setTransition<TextHaloColor>(value, klass);
}
-PropertyValue<float> SymbolLayer::getDefaultTextHaloWidth() {
+DataDrivenPropertyValue<float> SymbolLayer::getDefaultTextHaloWidth() {
return { 0 };
}
-PropertyValue<float> SymbolLayer::getTextHaloWidth(const optional<std::string>& klass) const {
+DataDrivenPropertyValue<float> SymbolLayer::getTextHaloWidth(const optional<std::string>& klass) const {
return impl->paint.get<TextHaloWidth>(klass);
}
-void SymbolLayer::setTextHaloWidth(PropertyValue<float> value, const optional<std::string>& klass) {
+void SymbolLayer::setTextHaloWidth(DataDrivenPropertyValue<float> value, const optional<std::string>& klass) {
if (value == getTextHaloWidth(klass))
return;
impl->paint.set<TextHaloWidth>(value, klass);
- impl->observer->onLayerPaintPropertyChanged(*this);
+ if (value.isDataDriven()) {
+ impl->observer->onLayerDataDrivenPaintPropertyChanged(*this);
+ } else {
+ impl->observer->onLayerPaintPropertyChanged(*this);
+ }
}
void SymbolLayer::setTextHaloWidthTransition(const TransitionOptions& value, const optional<std::string>& klass) {
impl->paint.setTransition<TextHaloWidth>(value, klass);
}
-PropertyValue<float> SymbolLayer::getDefaultTextHaloBlur() {
+DataDrivenPropertyValue<float> SymbolLayer::getDefaultTextHaloBlur() {
return { 0 };
}
-PropertyValue<float> SymbolLayer::getTextHaloBlur(const optional<std::string>& klass) const {
+DataDrivenPropertyValue<float> SymbolLayer::getTextHaloBlur(const optional<std::string>& klass) const {
return impl->paint.get<TextHaloBlur>(klass);
}
-void SymbolLayer::setTextHaloBlur(PropertyValue<float> value, const optional<std::string>& klass) {
+void SymbolLayer::setTextHaloBlur(DataDrivenPropertyValue<float> value, const optional<std::string>& klass) {
if (value == getTextHaloBlur(klass))
return;
impl->paint.set<TextHaloBlur>(value, klass);
- impl->observer->onLayerPaintPropertyChanged(*this);
+ if (value.isDataDriven()) {
+ impl->observer->onLayerDataDrivenPaintPropertyChanged(*this);
+ } else {
+ impl->observer->onLayerPaintPropertyChanged(*this);
+ }
}
void SymbolLayer::setTextHaloBlurTransition(const TransitionOptions& value, const optional<std::string>& klass) {
diff --git a/src/mbgl/style/layers/symbol_layer_impl.cpp b/src/mbgl/style/layers/symbol_layer_impl.cpp
index 32547e465a..ff59b14d65 100644
--- a/src/mbgl/style/layers/symbol_layer_impl.cpp
+++ b/src/mbgl/style/layers/symbol_layer_impl.cpp
@@ -16,9 +16,14 @@ bool SymbolLayer::Impl::evaluate(const PropertyEvaluationParameters& parameters)
// text-size and icon-size are layout properties but they also need to be evaluated as paint properties:
iconSize = layout.evaluate<IconSize>(parameters);
textSize = layout.evaluate<TextSize>(parameters);
-
- passes = ((paint.evaluated.get<IconOpacity>() > 0 && (paint.evaluated.get<IconColor>().a > 0 || paint.evaluated.get<IconHaloColor>().a > 0) && iconSize > 0)
- || (paint.evaluated.get<TextOpacity>() > 0 && (paint.evaluated.get<TextColor>().a > 0 || paint.evaluated.get<TextHaloColor>().a > 0) && textSize > 0))
+
+ auto hasIconOpacity = paint.evaluated.get<IconColor>().constantOr(Color::black()).a > 0 ||
+ paint.evaluated.get<IconHaloColor>().constantOr(Color::black()).a > 0;
+ auto hasTextOpacity = paint.evaluated.get<TextColor>().constantOr(Color::black()).a > 0 ||
+ paint.evaluated.get<TextHaloColor>().constantOr(Color::black()).a > 0;
+
+ passes = ((paint.evaluated.get<IconOpacity>().constantOr(1) > 0 && hasIconOpacity && iconSize > 0)
+ || (paint.evaluated.get<TextOpacity>().constantOr(1) > 0 && hasTextOpacity && textSize > 0))
? RenderPass::Translucent : RenderPass::None;
return paint.hasTransition();
@@ -38,20 +43,43 @@ std::unique_ptr<SymbolLayout> SymbolLayer::Impl::createLayout(const BucketParame
*spriteAtlas);
}
-SymbolPropertyValues SymbolLayer::Impl::iconPropertyValues(const SymbolLayoutProperties::Evaluated& layout_) const {
- return SymbolPropertyValues {
- layout_.get<IconRotationAlignment>(), // icon-pitch-alignment is not yet implemented; inherit the rotation alignment
- layout_.get<IconRotationAlignment>(),
- layout_.get<IconSize>(),
+IconPaintProperties::Evaluated SymbolLayer::Impl::iconPaintProperties() const {
+ return IconPaintProperties::Evaluated {
paint.evaluated.get<IconOpacity>(),
paint.evaluated.get<IconColor>(),
paint.evaluated.get<IconHaloColor>(),
paint.evaluated.get<IconHaloWidth>(),
paint.evaluated.get<IconHaloBlur>(),
paint.evaluated.get<IconTranslate>(),
+ paint.evaluated.get<IconTranslateAnchor>()
+ };
+}
+
+TextPaintProperties::Evaluated SymbolLayer::Impl::textPaintProperties() const {
+ return TextPaintProperties::Evaluated {
+ paint.evaluated.get<TextOpacity>(),
+ paint.evaluated.get<TextColor>(),
+ paint.evaluated.get<TextHaloColor>(),
+ paint.evaluated.get<TextHaloWidth>(),
+ paint.evaluated.get<TextHaloBlur>(),
+ paint.evaluated.get<TextTranslate>(),
+ paint.evaluated.get<TextTranslateAnchor>()
+ };
+}
+
+
+SymbolPropertyValues SymbolLayer::Impl::iconPropertyValues(const SymbolLayoutProperties::Evaluated& layout_) const {
+ return SymbolPropertyValues {
+ layout_.get<IconRotationAlignment>(), // icon-pitch-alignment is not yet implemented; inherit the rotation alignment
+ layout_.get<IconRotationAlignment>(),
+ layout_.get<IconSize>(),
+ paint.evaluated.get<IconTranslate>(),
paint.evaluated.get<IconTranslateAnchor>(),
iconSize,
- 1.0f
+ 1.0f,
+ paint.evaluated.get<IconHaloColor>().constantOr(Color::black()).a > 0 &&
+ paint.evaluated.get<IconHaloWidth>().constantOr(1),
+ paint.evaluated.get<IconColor>().constantOr(Color::black()).a > 0
};
}
@@ -60,15 +88,13 @@ SymbolPropertyValues SymbolLayer::Impl::textPropertyValues(const SymbolLayoutPro
layout_.get<TextPitchAlignment>(),
layout_.get<TextRotationAlignment>(),
layout_.get<TextSize>(),
- paint.evaluated.get<TextOpacity>(),
- paint.evaluated.get<TextColor>(),
- paint.evaluated.get<TextHaloColor>(),
- paint.evaluated.get<TextHaloWidth>(),
- paint.evaluated.get<TextHaloBlur>(),
paint.evaluated.get<TextTranslate>(),
paint.evaluated.get<TextTranslateAnchor>(),
textSize,
- 24.0f
+ 24.0f,
+ paint.evaluated.get<TextHaloColor>().constantOr(Color::black()).a > 0 &&
+ paint.evaluated.get<TextHaloWidth>().constantOr(1),
+ paint.evaluated.get<TextColor>().constantOr(Color::black()).a > 0
};
}
diff --git a/src/mbgl/style/layers/symbol_layer_impl.hpp b/src/mbgl/style/layers/symbol_layer_impl.hpp
index c00c2b0bba..1e9f05e4c7 100644
--- a/src/mbgl/style/layers/symbol_layer_impl.hpp
+++ b/src/mbgl/style/layers/symbol_layer_impl.hpp
@@ -1,5 +1,6 @@
#pragma once
+#include <mbgl/util/variant.hpp>
#include <mbgl/style/layer_impl.hpp>
#include <mbgl/style/layers/symbol_layer.hpp>
#include <mbgl/style/layers/symbol_layer_properties.hpp>
@@ -10,6 +11,30 @@ class SpriteAtlas;
class SymbolLayout;
namespace style {
+
+
+// {icon,text}-specific paint-property packs for use in the symbol Programs.
+// Since each program deals either with icons or text, using a smaller property set
+// lets us avoid unnecessarily binding attributes for properties the program wouldn't use.
+class IconPaintProperties : public PaintProperties<
+ IconOpacity,
+ IconColor,
+ IconHaloColor,
+ IconHaloWidth,
+ IconHaloBlur,
+ IconTranslate,
+ IconTranslateAnchor
+> {};
+
+class TextPaintProperties : public PaintProperties<
+ TextOpacity,
+ TextColor,
+ TextHaloColor,
+ TextHaloWidth,
+ TextHaloBlur,
+ TextTranslate,
+ TextTranslateAnchor
+> {};
// Repackaging evaluated values from SymbolLayoutProperties + SymbolPaintProperties
// for genericity over icons vs. text.
@@ -21,24 +46,14 @@ public:
float layoutSize;
// Paint
- float opacity;
- Color color;
- Color haloColor;
- float haloWidth;
- float haloBlur;
std::array<float, 2> translate;
TranslateAnchorType translateAnchor;
float paintSize;
float sdfScale; // Constant (1.0 or 24.0)
-
- bool hasHalo() const {
- return haloColor.a > 0.0f && haloWidth > 0.0f;
- }
-
- bool hasForeground() const {
- return color.a > 0.0f;
- }
+
+ bool hasHalo;
+ bool hasFill;
};
class SymbolLayer::Impl : public Layer::Impl {
@@ -54,6 +69,9 @@ public:
std::unique_ptr<SymbolLayout> createLayout(const BucketParameters&, const std::vector<const Layer*>&,
const GeometryTileLayer&) const;
+ IconPaintProperties::Evaluated iconPaintProperties() const;
+ TextPaintProperties::Evaluated textPaintProperties() const;
+
SymbolPropertyValues iconPropertyValues(const SymbolLayoutProperties::Evaluated&) const;
SymbolPropertyValues textPropertyValues(const SymbolLayoutProperties::Evaluated&) const;
diff --git a/src/mbgl/style/layers/symbol_layer_properties.hpp b/src/mbgl/style/layers/symbol_layer_properties.hpp
index 3bdae377ea..f2b7bfa00f 100644
--- a/src/mbgl/style/layers/symbol_layer_properties.hpp
+++ b/src/mbgl/style/layers/symbol_layer_properties.hpp
@@ -180,23 +180,23 @@ struct TextOptional : LayoutProperty<bool> {
static bool defaultValue() { return false; }
};
-struct IconOpacity : PaintProperty<float> {
+struct IconOpacity : DataDrivenPaintProperty<float, attributes::a_opacity> {
static float defaultValue() { return 1; }
};
-struct IconColor : PaintProperty<Color> {
+struct IconColor : DataDrivenPaintProperty<Color, attributes::a_fill_color> {
static Color defaultValue() { return Color::black(); }
};
-struct IconHaloColor : PaintProperty<Color> {
+struct IconHaloColor : DataDrivenPaintProperty<Color, attributes::a_halo_color> {
static Color defaultValue() { return {}; }
};
-struct IconHaloWidth : PaintProperty<float> {
+struct IconHaloWidth : DataDrivenPaintProperty<float, attributes::a_halo_width> {
static float defaultValue() { return 0; }
};
-struct IconHaloBlur : PaintProperty<float> {
+struct IconHaloBlur : DataDrivenPaintProperty<float, attributes::a_halo_blur> {
static float defaultValue() { return 0; }
};
@@ -208,23 +208,23 @@ struct IconTranslateAnchor : PaintProperty<TranslateAnchorType> {
static TranslateAnchorType defaultValue() { return TranslateAnchorType::Map; }
};
-struct TextOpacity : PaintProperty<float> {
+struct TextOpacity : DataDrivenPaintProperty<float, attributes::a_opacity> {
static float defaultValue() { return 1; }
};
-struct TextColor : PaintProperty<Color> {
+struct TextColor : DataDrivenPaintProperty<Color, attributes::a_fill_color> {
static Color defaultValue() { return Color::black(); }
};
-struct TextHaloColor : PaintProperty<Color> {
+struct TextHaloColor : DataDrivenPaintProperty<Color, attributes::a_halo_color> {
static Color defaultValue() { return {}; }
};
-struct TextHaloWidth : PaintProperty<float> {
+struct TextHaloWidth : DataDrivenPaintProperty<float, attributes::a_halo_width> {
static float defaultValue() { return 0; }
};
-struct TextHaloBlur : PaintProperty<float> {
+struct TextHaloBlur : DataDrivenPaintProperty<float, attributes::a_halo_blur> {
static float defaultValue() { return 0; }
};
diff --git a/src/mbgl/text/shaping.cpp b/src/mbgl/text/shaping.cpp
index b43ba0220c..e68566d419 100644
--- a/src/mbgl/text/shaping.cpp
+++ b/src/mbgl/text/shaping.cpp
@@ -3,16 +3,15 @@
namespace mbgl {
-PositionedIcon shapeIcon(const SpriteAtlasElement& image,
- const SymbolFeature& feature) {
- float dx = feature.iconOffset[0];
- float dy = feature.iconOffset[1];
+PositionedIcon shapeIcon(const SpriteAtlasElement& image, const std::array<float, 2>& iconOffset, const float iconRotation) {
+ float dx = iconOffset[0];
+ float dy = iconOffset[1];
float x1 = dx - image.spriteImage->getWidth() / 2.0f;
float x2 = x1 + image.spriteImage->getWidth();
float y1 = dy - image.spriteImage->getHeight() / 2.0f;
float y2 = y1 + image.spriteImage->getHeight();
- return PositionedIcon(image, y1, y2, x1, x2, feature.iconRotation);
+ return PositionedIcon(image, y1, y2, x1, x2, iconRotation);
}
} // namespace mbgl
diff --git a/src/mbgl/text/shaping.hpp b/src/mbgl/text/shaping.hpp
index b0e6ae3b1d..1b7b8b2733 100644
--- a/src/mbgl/text/shaping.hpp
+++ b/src/mbgl/text/shaping.hpp
@@ -36,7 +36,6 @@ public:
explicit operator bool() const { return image && (*image).pos.hasArea(); }
};
-PositionedIcon shapeIcon(const SpriteAtlasElement&,
- const SymbolFeature&);
+PositionedIcon shapeIcon(const SpriteAtlasElement&, const std::array<float, 2>& iconOffset, const float iconRotation);
} // namespace mbgl
diff --git a/src/mbgl/tile/vector_tile.cpp b/src/mbgl/tile/vector_tile.cpp
index a195885415..68f48e81fd 100644
--- a/src/mbgl/tile/vector_tile.cpp
+++ b/src/mbgl/tile/vector_tile.cpp
@@ -15,9 +15,23 @@ class VectorTileLayer;
using packed_iter_type = protozero::iterator_range<protozero::pbf_reader::const_uint32_iterator>;
+struct VectorTileLayerData {
+ VectorTileLayerData(std::shared_ptr<const std::string>);
+
+ // Hold a reference to the underlying pbf data that backs the lazily-built
+ // components of the owning VectorTileLayer and VectorTileFeature objects
+ std::shared_ptr<const std::string> data;
+
+ uint32_t version = 1;
+ uint32_t extent = 4096;
+ std::unordered_map<std::string, uint32_t> keysMap;
+ std::vector<std::reference_wrapper<const std::string>> keys;
+ std::vector<Value> values;
+};
+
class VectorTileFeature : public GeometryTileFeature {
public:
- VectorTileFeature(protozero::pbf_reader, const VectorTileLayer&);
+ VectorTileFeature(protozero::pbf_reader, std::shared_ptr<VectorTileLayerData> layerData);
FeatureType getType() const override { return type; }
optional<Value> getValue(const std::string&) const override;
@@ -26,16 +40,16 @@ public:
GeometryCollection getGeometries() const override;
private:
- const VectorTileLayer& layer;
+ std::shared_ptr<VectorTileLayerData> layerData;
optional<FeatureIdentifier> id;
FeatureType type = FeatureType::Unknown;
packed_iter_type tags_iter;
packed_iter_type geometry_iter;
};
-
+
class VectorTileLayer : public GeometryTileLayer {
public:
- VectorTileLayer(protozero::pbf_reader);
+ VectorTileLayer(protozero::pbf_reader, std::shared_ptr<const std::string>);
std::size_t featureCount() const override { return features.size(); }
std::unique_ptr<GeometryTileFeature> getFeature(std::size_t) const override;
@@ -46,12 +60,8 @@ private:
friend class VectorTileFeature;
std::string name;
- uint32_t version = 1;
- uint32_t extent = 4096;
- std::unordered_map<std::string, uint32_t> keysMap;
- std::vector<std::reference_wrapper<const std::string>> keys;
- std::vector<Value> values;
std::vector<protozero::pbf_reader> features;
+ std::shared_ptr<VectorTileLayerData> data;
};
class VectorTileData : public GeometryTileData {
@@ -117,8 +127,8 @@ Value parseValue(protozero::pbf_reader data) {
return false;
}
-VectorTileFeature::VectorTileFeature(protozero::pbf_reader feature_pbf, const VectorTileLayer& layer_)
- : layer(layer_) {
+VectorTileFeature::VectorTileFeature(protozero::pbf_reader feature_pbf, std::shared_ptr<VectorTileLayerData> layerData_)
+ : layerData(std::move(layerData_)) {
while (feature_pbf.next()) {
switch (feature_pbf.tag()) {
case 1: // id
@@ -141,8 +151,8 @@ VectorTileFeature::VectorTileFeature(protozero::pbf_reader feature_pbf, const Ve
}
optional<Value> VectorTileFeature::getValue(const std::string& key) const {
- auto keyIter = layer.keysMap.find(key);
- if (keyIter == layer.keysMap.end()) {
+ auto keyIter = layerData->keysMap.find(key);
+ if (keyIter == layerData->keysMap.end()) {
return optional<Value>();
}
@@ -151,7 +161,7 @@ optional<Value> VectorTileFeature::getValue(const std::string& key) const {
while (start_itr != end_itr) {
uint32_t tag_key = static_cast<uint32_t>(*start_itr++);
- if (layer.keysMap.size() <= tag_key) {
+ if (layerData->keysMap.size() <= tag_key) {
throw std::runtime_error("feature referenced out of range key");
}
@@ -160,12 +170,12 @@ optional<Value> VectorTileFeature::getValue(const std::string& key) const {
}
uint32_t tag_val = static_cast<uint32_t>(*start_itr++);;
- if (layer.values.size() <= tag_val) {
+ if (layerData->values.size() <= tag_val) {
throw std::runtime_error("feature referenced out of range value");
}
if (tag_key == keyIter->second) {
- return layer.values[tag_val];
+ return layerData->values[tag_val];
}
}
@@ -182,7 +192,7 @@ std::unordered_map<std::string,Value> VectorTileFeature::getProperties() const {
throw std::runtime_error("uneven number of feature tag ids");
}
uint32_t tag_val = static_cast<uint32_t>(*start_itr++);
- properties[layer.keys.at(tag_key)] = layer.values.at(tag_val);
+ properties[layerData->keys.at(tag_key)] = layerData->values.at(tag_val);
}
return properties;
}
@@ -196,7 +206,7 @@ GeometryCollection VectorTileFeature::getGeometries() const {
uint32_t length = 0;
int32_t x = 0;
int32_t y = 0;
- const float scale = float(util::EXTENT) / layer.extent;
+ const float scale = float(util::EXTENT) / layerData->extent;
GeometryCollection lines;
@@ -234,7 +244,7 @@ GeometryCollection VectorTileFeature::getGeometries() const {
}
}
- if (layer.version >= 2 || type != FeatureType::Polygon) {
+ if (layerData->version >= 2 || type != FeatureType::Polygon) {
return lines;
}
@@ -250,7 +260,7 @@ const GeometryTileLayer* VectorTileData::getLayer(const std::string& name) const
parsed = true;
protozero::pbf_reader tile_pbf(*data);
while (tile_pbf.next(3)) {
- VectorTileLayer layer(tile_pbf.get_message());
+ VectorTileLayer layer(tile_pbf.get_message(), data);
layers.emplace(layer.name, std::move(layer));
}
}
@@ -262,7 +272,13 @@ const GeometryTileLayer* VectorTileData::getLayer(const std::string& name) const
return nullptr;
}
-VectorTileLayer::VectorTileLayer(protozero::pbf_reader layer_pbf) {
+VectorTileLayerData::VectorTileLayerData(std::shared_ptr<const std::string> pbfData) :
+ data(std::move(pbfData))
+{}
+
+VectorTileLayer::VectorTileLayer(protozero::pbf_reader layer_pbf, std::shared_ptr<const std::string> pbfData)
+ : data(std::make_shared<VectorTileLayerData>(std::move(pbfData)))
+{
while (layer_pbf.next()) {
switch (layer_pbf.tag()) {
case 1: // name
@@ -273,18 +289,18 @@ VectorTileLayer::VectorTileLayer(protozero::pbf_reader layer_pbf) {
break;
case 3: // keys
{
- auto iter = keysMap.emplace(layer_pbf.get_string(), keysMap.size());
- keys.emplace_back(std::reference_wrapper<const std::string>(iter.first->first));
+ auto iter = data->keysMap.emplace(layer_pbf.get_string(), data->keysMap.size());
+ data->keys.emplace_back(std::reference_wrapper<const std::string>(iter.first->first));
}
break;
case 4: // values
- values.emplace_back(parseValue(layer_pbf.get_message()));
+ data->values.emplace_back(parseValue(layer_pbf.get_message()));
break;
case 5: // extent
- extent = layer_pbf.get_uint32();
+ data->extent = layer_pbf.get_uint32();
break;
case 15: // version
- version = layer_pbf.get_uint32();
+ data->version = layer_pbf.get_uint32();
break;
default:
layer_pbf.skip();
@@ -294,7 +310,7 @@ VectorTileLayer::VectorTileLayer(protozero::pbf_reader layer_pbf) {
}
std::unique_ptr<GeometryTileFeature> VectorTileLayer::getFeature(std::size_t i) const {
- return std::make_unique<VectorTileFeature>(features.at(i), *this);
+ return std::make_unique<VectorTileFeature>(features.at(i), data);
}
std::string VectorTileLayer::getName() const {