summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Shalamov <alexander.shalamov@mapbox.com>2019-03-04 09:37:22 +0200
committerAlexander Shalamov <alexander.shalamov@mapbox.com>2019-03-04 10:20:50 +0200
commit39dcc92f2a1e8ab20bba312f474d34f818be248e (patch)
treeea388cc5a8dabe0df702b9bcac962729f0f01d8f
parent3bfdb110646f33953fe7c44a6f4db7cdbb540d6a (diff)
downloadqtlocation-mapboxgl-39dcc92f2a1e8ab20bba312f474d34f818be248e.tar.gz
[core] Populate symbol layer paint properties for text sections
-rw-r--r--src/mbgl/layout/symbol_layout.cpp126
-rw-r--r--src/mbgl/layout/symbol_layout.hpp18
-rw-r--r--src/mbgl/renderer/buckets/symbol_bucket.hpp15
-rw-r--r--src/mbgl/renderer/paint_property_binder.hpp38
4 files changed, 102 insertions, 95 deletions
diff --git a/src/mbgl/layout/symbol_layout.cpp b/src/mbgl/layout/symbol_layout.cpp
index edacaf9dda..e95fb56c1d 100644
--- a/src/mbgl/layout/symbol_layout.cpp
+++ b/src/mbgl/layout/symbol_layout.cpp
@@ -1,25 +1,16 @@
-#include <mbgl/layout/layout.hpp>
#include <mbgl/layout/symbol_layout.hpp>
#include <mbgl/layout/merge_lines.hpp>
#include <mbgl/layout/clip_lines.hpp>
-#include <mbgl/renderer/buckets/symbol_bucket.hpp>
#include <mbgl/renderer/bucket_parameters.hpp>
#include <mbgl/renderer/layers/render_symbol_layer.hpp>
#include <mbgl/renderer/image_atlas.hpp>
-#include <mbgl/style/layers/symbol_layer_impl.hpp>
#include <mbgl/text/get_anchors.hpp>
#include <mbgl/text/shaping.hpp>
-#include <mbgl/util/constants.hpp>
#include <mbgl/util/utf.hpp>
-#include <mbgl/util/std.hpp>
#include <mbgl/util/constants.hpp>
#include <mbgl/util/string.hpp>
#include <mbgl/util/i18n.hpp>
-#include <mbgl/math/clamp.hpp>
-#include <mbgl/math/minmax.hpp>
-#include <mbgl/math/log2.hpp>
#include <mbgl/util/platform.hpp>
-#include <mbgl/util/logging.hpp>
#include <mbgl/tile/geometry_tile_data.hpp>
#include <mapbox/polylabel.hpp>
@@ -31,11 +22,23 @@ using namespace style;
template <class Property>
static bool has(const style::SymbolLayoutProperties::PossiblyEvaluated& layout) {
return layout.get<Property>().match(
- [&] (const typename Property::Type& t) { return !t.empty(); },
- [&] (const auto&) { return true; }
+ [] (const typename Property::Type& t) { return !t.empty(); },
+ [] (const auto&) { return true; }
);
}
+namespace {
+expression::Value sectionOptionsToValue(const SectionOptions& options) {
+ if (options.id) {
+ return (*options.id).match(
+ [] (double t) -> expression::Value { return t; },
+ [] (const std::string& t) -> expression::Value { return t; },
+ [] (auto&) -> expression::Value { return {}; });
+ }
+ return {};
+}
+} // namespace
+
SymbolLayout::SymbolLayout(const BucketParameters& parameters,
const std::vector<const RenderLayer*>& layers,
std::unique_ptr<GeometryTileLayer> sourceLayer_,
@@ -108,7 +111,6 @@ SymbolLayout::SymbolLayout(const BucketParameters& parameters,
auto formatted = layout.evaluate<TextField>(zoom, ft);
auto textTransform = layout.evaluate<TextTransform>(zoom, ft);
FontStack baseFontStack = layout.evaluate<TextFont>(zoom, ft);
- FontStackHash baseFontStackHash = FontStackHasher()(baseFontStack);
ft.formattedText = TaggedString();
for (std::size_t j = 0; j < formatted.sections.size(); j++) {
@@ -122,8 +124,8 @@ SymbolLayout::SymbolLayout(const BucketParameters& parameters,
ft.formattedText->addSection(applyArabicShaping(util::convertUTF8ToUTF16(u8string)),
section.fontScale ? *section.fontScale : 1.0,
- section.fontStack ? FontStackHasher()(*section.fontStack) : baseFontStackHash);
-
+ section.fontStack ? *section.fontStack : baseFontStack,
+ section.id);
}
@@ -418,43 +420,57 @@ void SymbolLayout::createBucket(const ImagePositions&, std::unique_ptr<FeatureIn
// Insert final placement into collision tree and add glyphs/icons to buffers
- if (hasText) {
- const Range<float> sizeData = bucket->textSizeBinder->getVertexSizeData(feature);
- bucket->text.placedSymbols.emplace_back(symbolInstance.anchor.point, symbolInstance.anchor.segment, sizeData.min, sizeData.max,
- symbolInstance.textOffset, symbolInstance.writingModes, symbolInstance.line, CalculateTileDistances(symbolInstance.line, symbolInstance.anchor));
- symbolInstance.placedTextIndex = bucket->text.placedSymbols.size() - 1;
- PlacedSymbol& horizontalSymbol = bucket->text.placedSymbols.back();
-
- bool firstHorizontal = true;
- for (const auto& symbol : symbolInstance.horizontalGlyphQuads) {
- size_t index = addSymbol(
- bucket->text, sizeData, symbol,
- symbolInstance.anchor, horizontalSymbol);
- if (firstHorizontal) {
- horizontalSymbol.vertexStartIndex = index;
- firstHorizontal = false;
- }
+ if (hasText && feature.formattedText) {
+ const auto& formattedText = *feature.formattedText;
+ std::function<void (std::size_t sectionIndex, bool updateLastSection)> updatePaintProperties;
+ if (formattedText.hasMultipleUniqueSections()) {
+ updatePaintProperties = [&, currentSectionIndex = optional<std::size_t>{}](std::size_t symbolSectionIndex, bool updateLastSection) mutable {
+ if (currentSectionIndex && (updateLastSection || *currentSectionIndex != symbolSectionIndex)) {
+ const auto& formattedSection = sectionOptionsToValue(formattedText.sectionAt(*currentSectionIndex));
+ for (auto& pair : bucket->paintProperties) {
+ pair.second.textBinders.populateVertexVectors(feature, bucket->text.vertices.vertexSize(), {}, {}, formattedSection);
+ }
+ }
+ currentSectionIndex = symbolSectionIndex;
+ };
+ } else {
+ updatePaintProperties = [&](std::size_t, bool updateLastSection) {
+ if (updateLastSection) {
+ const auto& formattedSection = sectionOptionsToValue(formattedText.sectionAt(0));
+ for (auto& pair : bucket->paintProperties) {
+ pair.second.textBinders.populateVertexVectors(feature, bucket->text.vertices.vertexSize(), {}, {}, formattedSection);
+ }
+ }
+ };
}
- if (symbolInstance.writingModes & WritingModeType::Vertical) {
+ const Range<float> sizeData = bucket->textSizeBinder->getVertexSizeData(feature);
+ auto addSymbolGlyphQuads = [&](WritingModeType writingMode,
+ optional<size_t>& placedIndex,
+ const SymbolQuads& glyphQuads) {
bucket->text.placedSymbols.emplace_back(symbolInstance.anchor.point, symbolInstance.anchor.segment, sizeData.min, sizeData.max,
- symbolInstance.textOffset, WritingModeType::Vertical, symbolInstance.line, CalculateTileDistances(symbolInstance.line, symbolInstance.anchor));
- symbolInstance.placedVerticalTextIndex = bucket->text.placedSymbols.size() - 1;
-
- PlacedSymbol& verticalSymbol = bucket->text.placedSymbols.back();
- bool firstVertical = true;
-
- for (const auto& symbol : symbolInstance.verticalGlyphQuads) {
- size_t index = addSymbol(
- bucket->text, sizeData, symbol,
- symbolInstance.anchor, verticalSymbol);
-
- if (firstVertical) {
- verticalSymbol.vertexStartIndex = index;
- firstVertical = false;
+ symbolInstance.textOffset, writingMode, symbolInstance.line, CalculateTileDistances(symbolInstance.line, symbolInstance.anchor));
+ placedIndex = bucket->text.placedSymbols.size() - 1;
+ PlacedSymbol& placedSymbol = bucket->text.placedSymbols.back();
+
+ bool firstSymbol = true;
+ for (const auto& symbolQuad : glyphQuads) {
+ updatePaintProperties(symbolQuad.sectionIndex, false);
+ size_t index = addSymbol(bucket->text, sizeData, symbolQuad, symbolInstance.anchor, placedSymbol);
+ if (firstSymbol) {
+ placedSymbol.vertexStartIndex = index;
+ firstSymbol = false;
}
}
+ };
+
+ addSymbolGlyphQuads(symbolInstance.writingModes, symbolInstance.placedTextIndex, symbolInstance.horizontalGlyphQuads);
+
+ if (symbolInstance.writingModes & WritingModeType::Vertical) {
+ addSymbolGlyphQuads(WritingModeType::Vertical, symbolInstance.placedVerticalTextIndex, symbolInstance.verticalGlyphQuads);
}
+
+ updatePaintProperties(0, true);
}
if (hasIcon) {
@@ -466,12 +482,11 @@ void SymbolLayout::createBucket(const ImagePositions&, std::unique_ptr<FeatureIn
PlacedSymbol& iconSymbol = bucket->icon.placedSymbols.back();
iconSymbol.vertexStartIndex = addSymbol(bucket->icon, sizeData, *symbolInstance.iconQuad,
symbolInstance.anchor, iconSymbol);
- }
- }
- for (auto& pair : bucket->paintProperties) {
- pair.second.iconBinders.populateVertexVectors(feature, bucket->icon.vertices.vertexSize(), {}, {});
- pair.second.textBinders.populateVertexVectors(feature, bucket->text.vertices.vertexSize(), {}, {});
+ for (auto& pair : bucket->paintProperties) {
+ pair.second.iconBinders.populateVertexVectors(feature, bucket->icon.vertices.vertexSize(), {}, {});
+ }
+ }
}
}
@@ -489,12 +504,11 @@ void SymbolLayout::createBucket(const ImagePositions&, std::unique_ptr<FeatureIn
}
-template <typename Buffer>
-size_t SymbolLayout::addSymbol(Buffer& buffer,
- const Range<float> sizeData,
- const SymbolQuad& symbol,
- const Anchor& labelAnchor,
- PlacedSymbol& placedSymbol) {
+size_t SymbolLayout::addSymbol(SymbolBucket::Buffer& buffer,
+ const Range<float> sizeData,
+ const SymbolQuad& symbol,
+ const Anchor& labelAnchor,
+ PlacedSymbol& placedSymbol) {
constexpr const uint16_t vertexLength = 4;
const auto &tl = symbol.tl;
diff --git a/src/mbgl/layout/symbol_layout.hpp b/src/mbgl/layout/symbol_layout.hpp
index ab6dc049a2..870ad4b415 100644
--- a/src/mbgl/layout/symbol_layout.hpp
+++ b/src/mbgl/layout/symbol_layout.hpp
@@ -6,18 +6,15 @@
#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 <mbgl/programs/symbol_program.hpp>
+#include <mbgl/renderer/buckets/symbol_bucket.hpp>
#include <memory>
#include <map>
-#include <unordered_set>
#include <vector>
namespace mbgl {
class BucketParameters;
-class SymbolBucket;
class Anchor;
class RenderLayer;
class PlacedSymbol;
@@ -26,7 +23,7 @@ namespace style {
class Filter;
} // namespace style
-class SymbolLayout : public Layout {
+class SymbolLayout final : public Layout {
public:
SymbolLayout(const BucketParameters&,
const std::vector<const RenderLayer*>&,
@@ -62,12 +59,11 @@ private:
void addToDebugBuffers(SymbolBucket&);
// Adds placed items to the buffer.
- template <typename Buffer>
- size_t addSymbol(Buffer&,
- const Range<float> sizeData,
- const SymbolQuad&,
- const Anchor& labelAnchor,
- PlacedSymbol& placedSymbol);
+ size_t addSymbol(SymbolBucket::Buffer&,
+ const Range<float> sizeData,
+ const SymbolQuad&,
+ const Anchor& labelAnchor,
+ PlacedSymbol& placedSymbol);
// Stores the layer so that we can hold on to GeometryTileFeature instances in SymbolFeature,
// which may reference data from this object.
diff --git a/src/mbgl/renderer/buckets/symbol_bucket.hpp b/src/mbgl/renderer/buckets/symbol_bucket.hpp
index 5b9b11cf4d..ecf9a861df 100644
--- a/src/mbgl/renderer/buckets/symbol_bucket.hpp
+++ b/src/mbgl/renderer/buckets/symbol_bucket.hpp
@@ -87,7 +87,7 @@ public:
std::unique_ptr<SymbolSizeBinder> textSizeBinder;
- struct TextBuffer {
+ struct Buffer {
gl::VertexVector<SymbolLayoutVertex> vertices;
gl::VertexVector<gfx::Vertex<SymbolDynamicLayoutAttributes>> dynamicVertices;
gl::VertexVector<gfx::Vertex<SymbolOpacityAttributes>> opacityVertices;
@@ -103,19 +103,8 @@ public:
std::unique_ptr<SymbolSizeBinder> iconSizeBinder;
- struct IconBuffer {
- gl::VertexVector<SymbolLayoutVertex> vertices;
- gl::VertexVector<gfx::Vertex<SymbolDynamicLayoutAttributes>> dynamicVertices;
- gl::VertexVector<gfx::Vertex<SymbolOpacityAttributes>> opacityVertices;
- gl::IndexVector<gfx::Triangles> triangles;
- SegmentVector<SymbolIconAttributes> segments;
- std::vector<PlacedSymbol> placedSymbols;
+ struct IconBuffer : public Buffer {
PremultipliedImage atlasImage;
-
- optional<gl::VertexBuffer<SymbolLayoutVertex>> vertexBuffer;
- optional<gl::VertexBuffer<gfx::Vertex<SymbolDynamicLayoutAttributes>>> dynamicVertexBuffer;
- optional<gl::VertexBuffer<gfx::Vertex<SymbolOpacityAttributes>>> opacityVertexBuffer;
- optional<gl::IndexBuffer<gfx::Triangles>> indexBuffer;
} icon;
struct CollisionBuffer {
diff --git a/src/mbgl/renderer/paint_property_binder.hpp b/src/mbgl/renderer/paint_property_binder.hpp
index 56f187507f..9659384d33 100644
--- a/src/mbgl/renderer/paint_property_binder.hpp
+++ b/src/mbgl/renderer/paint_property_binder.hpp
@@ -95,7 +95,10 @@ public:
virtual ~PaintPropertyBinder() = default;
- virtual void populateVertexVector(const GeometryTileFeature& feature, std::size_t length, const ImagePositions&, const optional<PatternDependency>&) = 0;
+ virtual void populateVertexVector(const GeometryTileFeature& feature,
+ std::size_t length, const ImagePositions&,
+ const optional<PatternDependency>&,
+ const style::expression::Value&) = 0;
virtual void upload(gl::Context& context) = 0;
virtual void setPatternParameters(const optional<ImagePosition>&, const optional<ImagePosition>&, CrossfadeParameters&) = 0;
virtual std::tuple<ExpandToType<As, optional<gl::AttributeBinding>>...> attributeBinding(const PossiblyEvaluatedType& currentValue) const = 0;
@@ -108,13 +111,13 @@ public:
};
template <class T, class A>
-class ConstantPaintPropertyBinder : public PaintPropertyBinder<T, T, PossiblyEvaluatedPropertyValue<T>, A> {
+class ConstantPaintPropertyBinder final : public PaintPropertyBinder<T, T, PossiblyEvaluatedPropertyValue<T>, A> {
public:
ConstantPaintPropertyBinder(T constant_)
: constant(std::move(constant_)) {
}
- void populateVertexVector(const GeometryTileFeature&, std::size_t, const ImagePositions&, const optional<PatternDependency>&) override {}
+ void populateVertexVector(const GeometryTileFeature&, std::size_t, const ImagePositions&, const optional<PatternDependency>&, const style::expression::Value&) override {}
void upload(gl::Context&) override {}
void setPatternParameters(const optional<ImagePosition>&, const optional<ImagePosition>&, CrossfadeParameters&) override {};
@@ -135,13 +138,13 @@ private:
};
template <class T, class... As>
-class ConstantCrossFadedPaintPropertyBinder : public PaintPropertyBinder<T, std::array<uint16_t, 4>,PossiblyEvaluatedPropertyValue<Faded<T>>, As...> {
+class ConstantCrossFadedPaintPropertyBinder final : public PaintPropertyBinder<T, std::array<uint16_t, 4>,PossiblyEvaluatedPropertyValue<Faded<T>>, As...> {
public:
ConstantCrossFadedPaintPropertyBinder(Faded<T> constant_)
: constant(std::move(constant_)), constantPatternPositions({}) {
}
- void populateVertexVector(const GeometryTileFeature&, std::size_t, const ImagePositions&, const optional<PatternDependency>&) override {}
+ void populateVertexVector(const GeometryTileFeature&, std::size_t, const ImagePositions&, const optional<PatternDependency>&, const style::expression::Value&) override {}
void upload(gl::Context&) override {}
void setPatternParameters(const optional<ImagePosition>& posA, const optional<ImagePosition>& posB, CrossfadeParameters&) override {
@@ -171,7 +174,7 @@ private:
};
template <class T, class A>
-class SourceFunctionPaintPropertyBinder : public PaintPropertyBinder<T, T, PossiblyEvaluatedPropertyValue<T>, A> {
+class SourceFunctionPaintPropertyBinder final : public PaintPropertyBinder<T, T, PossiblyEvaluatedPropertyValue<T>, A> {
public:
using BaseAttributeType = A;
using BaseAttributeValue = typename A::Value;
@@ -184,8 +187,9 @@ public:
defaultValue(std::move(defaultValue_)) {
}
void setPatternParameters(const optional<ImagePosition>&, const optional<ImagePosition>&, CrossfadeParameters&) override {};
- void populateVertexVector(const GeometryTileFeature& feature, std::size_t length, const ImagePositions&, const optional<PatternDependency>&) override {
- auto evaluated = expression.evaluate(feature, defaultValue);
+ void populateVertexVector(const GeometryTileFeature& feature, std::size_t length, const ImagePositions&, const optional<PatternDependency>&, const style::expression::Value& formattedSection) override {
+ using style::expression::EvaluationContext;
+ auto evaluated = expression.evaluate(EvaluationContext(&feature).withFormattedSection(&formattedSection), defaultValue);
this->statistics.add(evaluated);
auto value = attributeValue(evaluated);
for (std::size_t i = vertexVector.vertexSize(); i < length; ++i) {
@@ -226,7 +230,7 @@ private:
};
template <class T, class A>
-class CompositeFunctionPaintPropertyBinder : public PaintPropertyBinder<T, T, PossiblyEvaluatedPropertyValue<T>, A> {
+class CompositeFunctionPaintPropertyBinder final : public PaintPropertyBinder<T, T, PossiblyEvaluatedPropertyValue<T>, A> {
public:
using AttributeType = ZoomInterpolatedAttributeType<A>;
@@ -239,8 +243,12 @@ public:
zoomRange({zoom, zoom + 1}) {
}
void setPatternParameters(const optional<ImagePosition>&, const optional<ImagePosition>&, CrossfadeParameters&) override {};
- void populateVertexVector(const GeometryTileFeature& feature, std::size_t length, const ImagePositions&, const optional<PatternDependency>&) override {
- Range<T> range = expression.evaluate(zoomRange, feature, defaultValue);
+ void populateVertexVector(const GeometryTileFeature& feature, std::size_t length, const ImagePositions&, const optional<PatternDependency>&, const style::expression::Value& formattedSection) override {
+ using style::expression::EvaluationContext;
+ Range<T> range = {
+ expression.evaluate(EvaluationContext(zoomRange.min, &feature).withFormattedSection(&formattedSection), defaultValue),
+ expression.evaluate(EvaluationContext(zoomRange.max, &feature).withFormattedSection(&formattedSection), defaultValue),
+ };
this->statistics.add(range.min);
this->statistics.add(range.max);
AttributeValue value = zoomInterpolatedAttributeValue(
@@ -289,7 +297,7 @@ private:
};
template <class T, class A1, class A2>
-class CompositeCrossFadedPaintPropertyBinder : public PaintPropertyBinder<T, std::array<uint16_t, 4>, PossiblyEvaluatedPropertyValue<Faded<T>>, A1, A2> {
+class CompositeCrossFadedPaintPropertyBinder final : public PaintPropertyBinder<T, std::array<uint16_t, 4>, PossiblyEvaluatedPropertyValue<Faded<T>>, A1, A2> {
public:
using AttributeType = ZoomInterpolatedAttributeType<A1>;
using AttributeType2 = ZoomInterpolatedAttributeType<A2>;
@@ -313,7 +321,7 @@ public:
crossfade = crossfade_;
};
- void populateVertexVector(const GeometryTileFeature&, std::size_t length, const ImagePositions& patternPositions, const optional<PatternDependency>& patternDependencies) override {
+ void populateVertexVector(const GeometryTileFeature&, std::size_t length, const ImagePositions& patternPositions, const optional<PatternDependency>& patternDependencies, const style::expression::Value&) override {
if (patternDependencies->mid.empty()) {
// Unlike other propperties with expressions that evaluate to null, the default value for `*-pattern` properties is an empty
@@ -475,9 +483,9 @@ public:
PaintPropertyBinders(PaintPropertyBinders&&) = default;
PaintPropertyBinders(const PaintPropertyBinders&) = delete;
- void populateVertexVectors(const GeometryTileFeature& feature, std::size_t length, const ImagePositions& patternPositions, const optional<PatternDependency>& patternDependencies) {
+ void populateVertexVectors(const GeometryTileFeature& feature, std::size_t length, const ImagePositions& patternPositions, const optional<PatternDependency>& patternDependencies, const style::expression::Value& formattedSection = {}) {
util::ignore({
- (binders.template get<Ps>()->populateVertexVector(feature, length, patternPositions, patternDependencies), 0)...
+ (binders.template get<Ps>()->populateVertexVector(feature, length, patternPositions, patternDependencies, formattedSection), 0)...
});
}