diff options
author | Alexander Shalamov <alexander.shalamov@mapbox.com> | 2019-03-04 09:37:22 +0200 |
---|---|---|
committer | Alexander Shalamov <alexander.shalamov@mapbox.com> | 2019-03-04 10:20:50 +0200 |
commit | 39dcc92f2a1e8ab20bba312f474d34f818be248e (patch) | |
tree | ea388cc5a8dabe0df702b9bcac962729f0f01d8f | |
parent | 3bfdb110646f33953fe7c44a6f4db7cdbb540d6a (diff) | |
download | qtlocation-mapboxgl-39dcc92f2a1e8ab20bba312f474d34f818be248e.tar.gz |
[core] Populate symbol layer paint properties for text sections
-rw-r--r-- | src/mbgl/layout/symbol_layout.cpp | 126 | ||||
-rw-r--r-- | src/mbgl/layout/symbol_layout.hpp | 18 | ||||
-rw-r--r-- | src/mbgl/renderer/buckets/symbol_bucket.hpp | 15 | ||||
-rw-r--r-- | src/mbgl/renderer/paint_property_binder.hpp | 38 |
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)... }); } |