From 759dfe8bf630b30173880551db70f54c43697b98 Mon Sep 17 00:00:00 2001 From: zmiao Date: Wed, 12 Feb 2020 12:28:05 +0200 Subject: [core] Support [within expression] with layout property --- include/mbgl/style/property_expression.hpp | 33 +++++++++++++ metrics/ignores/platform-all.json | 3 +- src/mbgl/layout/pattern_layout.hpp | 30 ++++++++---- src/mbgl/layout/symbol_layout.cpp | 57 ++++++++++++---------- src/mbgl/layout/symbol_layout.hpp | 1 + src/mbgl/renderer/buckets/fill_bucket.cpp | 2 +- src/mbgl/renderer/buckets/line_bucket.cpp | 8 +-- src/mbgl/renderer/buckets/line_bucket.hpp | 2 +- .../renderer/possibly_evaluated_property_value.hpp | 14 +++++- src/mbgl/style/properties.hpp | 37 ++++++++++++++ 10 files changed, 142 insertions(+), 45 deletions(-) diff --git a/include/mbgl/style/property_expression.hpp b/include/mbgl/style/property_expression.hpp index 7439ac9ca1..8502bfefbd 100644 --- a/include/mbgl/style/property_expression.hpp +++ b/include/mbgl/style/property_expression.hpp @@ -73,6 +73,20 @@ public: finalDefaultValue); } + T evaluate(const GeometryTileFeature& feature, const CanonicalTileID& canonical, T finalDefaultValue) const { + return evaluate(expression::EvaluationContext(&feature).withCanonicalTileID(&canonical), finalDefaultValue); + } + + T evaluate(const GeometryTileFeature& feature, + const std::set& availableImages, + const CanonicalTileID& canonical, + T finalDefaultValue) const { + return evaluate(expression::EvaluationContext(&feature) + .withAvailableImages(&availableImages) + .withCanonicalTileID(&canonical), + finalDefaultValue); + } + T evaluate(float zoom, const GeometryTileFeature& feature, T finalDefaultValue) const { return evaluate(expression::EvaluationContext(zoom, &feature), finalDefaultValue); } @@ -85,6 +99,25 @@ public: finalDefaultValue); } + T evaluate(float zoom, + const GeometryTileFeature& feature, + const std::set& availableImages, + const CanonicalTileID& canonical, + T finalDefaultValue) const { + return evaluate(expression::EvaluationContext(zoom, &feature) + .withAvailableImages(&availableImages) + .withCanonicalTileID(&canonical), + finalDefaultValue); + } + + T evaluate(float zoom, + const GeometryTileFeature& feature, + const CanonicalTileID& canonical, + T finalDefaultValue) const { + return evaluate(expression::EvaluationContext(zoom, &feature).withCanonicalTileID(&canonical), + finalDefaultValue); + } + T evaluate(float zoom, const GeometryTileFeature& feature, const FeatureState& state, T finalDefaultValue) const { assert(!isFeatureConstant()); return evaluate(expression::EvaluationContext(zoom, &feature, &state), finalDefaultValue); diff --git a/metrics/ignores/platform-all.json b/metrics/ignores/platform-all.json index f27941a3b6..e9ee792f37 100644 --- a/metrics/ignores/platform-all.json +++ b/metrics/ignores/platform-all.json @@ -132,6 +132,5 @@ "render-tests/text-variable-anchor/left-top-right-buttom-offset-tile-map-mode":"https://github.com/mapbox/mapbox-gl-js/pull/9202", "render-tests/line-pattern/with-dasharray":"https://github.com/mapbox/mapbox-gl-js/pull/9189", "render-tests/symbol-sort-key/placement-tile-boundary-right-then-left": "https://github.com/mapbox/mapbox-gl-js/pull/9054", - "render-tests/line-dasharray/zero-length-gap":"https://github.com/mapbox/mapbox-gl-js/pull/9246", - "render-tests/within/layout-text": "TODO: Fix by enabling `within` expreesion with layout property" + "render-tests/line-dasharray/zero-length-gap":"https://github.com/mapbox/mapbox-gl-js/pull/9246" } diff --git a/src/mbgl/layout/pattern_layout.hpp b/src/mbgl/layout/pattern_layout.hpp index 81ff3996db..8d612d2589 100644 --- a/src/mbgl/layout/pattern_layout.hpp +++ b/src/mbgl/layout/pattern_layout.hpp @@ -45,7 +45,8 @@ struct PatternFeatureInserter { std::unique_ptr feature, PatternLayerMap patternDependencyMap, float /*zoom*/, - const PropertiesType&) { + const PropertiesType&, + const CanonicalTileID&) { features.emplace_back(index, std::move(feature), std::move(patternDependencyMap)); } }; @@ -58,9 +59,10 @@ struct PatternFeatureInserter { std::unique_ptr feature, PatternLayerMap patternDependencyMap, float zoom, - const PropertiesType& properties) { + const PropertiesType& properties, + const CanonicalTileID& canonical) { const auto& sortKeyProperty = properties.template get(); - float sortKey = sortKeyProperty.evaluate(*feature, zoom, SortKeyPropertyType::defaultValue()); + float sortKey = sortKeyProperty.evaluate(*feature, zoom, canonical, SortKeyPropertyType::defaultValue()); PatternFeature patternFeature{index, std::move(feature), std::move(patternDependencyMap), sortKey}; const auto lowerBound = std::lower_bound(features.cbegin(), features.cend(), patternFeature); features.insert(lowerBound, std::move(patternFeature)); @@ -127,12 +129,17 @@ public: const auto min = patternProperty.evaluate(*feature, zoom - 1, layoutParameters.availableImages, + parameters.tileID.canonical, + PatternPropertyType::defaultValue()); + const auto mid = patternProperty.evaluate(*feature, + zoom, + layoutParameters.availableImages, + parameters.tileID.canonical, PatternPropertyType::defaultValue()); - const auto mid = patternProperty.evaluate( - *feature, zoom, layoutParameters.availableImages, PatternPropertyType::defaultValue()); const auto max = patternProperty.evaluate(*feature, zoom + 1, layoutParameters.availableImages, + parameters.tileID.canonical, PatternPropertyType::defaultValue()); layoutParameters.imageDependencies.emplace(min.to.id(), ImageType::Pattern); @@ -145,14 +152,17 @@ public: } } - PatternFeatureInserter::insert( - features, i, std::move(feature), std::move(patternDependencyMap), zoom, layout); + PatternFeatureInserter::insert(features, + i, + std::move(feature), + std::move(patternDependencyMap), + zoom, + layout, + parameters.tileID.canonical); } }; - bool hasDependencies() const override { - return hasPattern; - } + bool hasDependencies() const override { return hasPattern; } void createBucket(const ImagePositions& patternPositions, std::unique_ptr& featureIndex, diff --git a/src/mbgl/layout/symbol_layout.cpp b/src/mbgl/layout/symbol_layout.cpp index e954a26a50..63ce223574 100644 --- a/src/mbgl/layout/symbol_layout.cpp +++ b/src/mbgl/layout/symbol_layout.cpp @@ -86,6 +86,7 @@ SymbolLayout::SymbolLayout(const BucketParameters& parameters, sourceLayer(std::move(sourceLayer_)), overscaling(parameters.tileID.overscaleFactor()), zoom(parameters.tileID.overscaledZ), + canonicalID(parameters.tileID.canonical), mode(parameters.mode), pixelRatio(parameters.pixelRatio), tileSize(util::tileSize * overscaling), @@ -141,9 +142,9 @@ SymbolLayout::SymbolLayout(const BucketParameters& parameters, ft.index = i; if (hasText) { - auto formatted = layout->evaluate(zoom, ft, layoutParameters.availableImages); - auto textTransform = layout->evaluate(zoom, ft); - FontStack baseFontStack = layout->evaluate(zoom, ft); + auto formatted = layout->evaluate(zoom, ft, layoutParameters.availableImages, canonicalID); + auto textTransform = layout->evaluate(zoom, ft, canonicalID); + FontStack baseFontStack = layout->evaluate(zoom, ft, canonicalID); ft.formattedText = TaggedString(); for (const auto & section : formatted.sections) { @@ -188,13 +189,13 @@ SymbolLayout::SymbolLayout(const BucketParameters& parameters, } if (hasIcon) { - ft.icon = layout->evaluate(zoom, ft, layoutParameters.availableImages); + ft.icon = layout->evaluate(zoom, ft, layoutParameters.availableImages, canonicalID); layoutParameters.imageDependencies.emplace(ft.icon->id(), ImageType::Icon); } if (ft.formattedText || ft.icon) { if (sortFeaturesByKey) { - ft.sortKey = layout->evaluate(zoom, ft); + ft.sortKey = layout->evaluate(zoom, ft, canonicalID); const auto lowerBound = std::lower_bound(features.begin(), features.end(), ft); features.insert(lowerBound, std::move(ft)); } else { @@ -355,14 +356,16 @@ void SymbolLayout::prepareSymbols(const GlyphMap& glyphMap, ShapedTextOrientations shapedTextOrientations; optional shapedIcon; std::array textOffset{{0.0f, 0.0f}}; - const float layoutTextSize = layout->evaluate(zoom + 1, feature); - const float layoutTextSizeAtBucketZoomLevel = layout->evaluate(zoom, feature); - const float layoutIconSize = layout->evaluate(zoom + 1, feature); + const float layoutTextSize = layout->evaluate(zoom + 1, feature, canonicalID); + const float layoutTextSizeAtBucketZoomLevel = layout->evaluate(zoom, feature, canonicalID); + const float layoutIconSize = layout->evaluate(zoom + 1, feature, canonicalID); // if feature has text, shape the text if (feature.formattedText && layoutTextSize > 0.0f) { const float lineHeight = layout->get() * util::ONE_EM; - const float spacing = util::i18n::allowsLetterSpacing(feature.formattedText->rawText()) ? layout->evaluate(zoom, feature) * util::ONE_EM : 0.0f; + const float spacing = util::i18n::allowsLetterSpacing(feature.formattedText->rawText()) + ? layout->evaluate(zoom, feature, canonicalID) * util::ONE_EM + : 0.0f; auto applyShaping = [&](const TaggedString& formattedText, WritingModeType writingMode, @@ -371,7 +374,7 @@ void SymbolLayout::prepareSymbols(const GlyphMap& glyphMap, const Shaping result = getShaping( /* string */ formattedText, /* maxWidth: ems */ - isPointPlacement ? layout->evaluate(zoom, feature) * util::ONE_EM : 0.0f, + isPointPlacement ? layout->evaluate(zoom, feature, canonicalID) * util::ONE_EM : 0.0f, /* ems */ lineHeight, textAnchor, textJustify, @@ -389,22 +392,24 @@ void SymbolLayout::prepareSymbols(const GlyphMap& glyphMap, return result; }; - const std::vector variableTextAnchor = layout->evaluate(zoom, feature); - const SymbolAnchorType textAnchor = layout->evaluate(zoom, feature); + const std::vector variableTextAnchor = + layout->evaluate(zoom, feature, canonicalID); + const SymbolAnchorType textAnchor = layout->evaluate(zoom, feature, canonicalID); if (variableTextAnchor.empty()) { // Layers with variable anchors use the `text-radial-offset` property and the [x, y] offset vector // is calculated at placement time instead of layout time - const float radialOffset = layout->evaluate(zoom, feature); + const float radialOffset = layout->evaluate(zoom, feature, canonicalID); if (radialOffset > 0.0f) { // The style spec says don't use `text-offset` and `text-radial-offset` together // but doesn't actually specify what happens if you use both. We go with the radial offset. textOffset = evaluateRadialOffset(textAnchor, radialOffset * util::ONE_EM); } else { - textOffset = {{layout->evaluate(zoom, feature)[0] * util::ONE_EM, - layout->evaluate(zoom, feature)[1] * util::ONE_EM}}; + textOffset = {{layout->evaluate(zoom, feature, canonicalID)[0] * util::ONE_EM, + layout->evaluate(zoom, feature, canonicalID)[1] * util::ONE_EM}}; } } - TextJustifyType textJustify = textAlongLine ? TextJustifyType::Center : layout->evaluate(zoom, feature); + TextJustifyType textJustify = + textAlongLine ? TextJustifyType::Center : layout->evaluate(zoom, feature, canonicalID); const auto addVerticalShapingForPointLabelIfNeeded = [&] { if (allowVerticalPlacement && feature.formattedText->allowsVerticalWritingMode()) { @@ -474,8 +479,8 @@ void SymbolLayout::prepareSymbols(const GlyphMap& glyphMap, if (image != imageMap.end()) { iconType = SymbolContent::IconRGBA; shapedIcon = PositionedIcon::shapeIcon(imagePositions.at(feature.icon->id()), - layout->evaluate(zoom, feature), - layout->evaluate(zoom, feature)); + layout->evaluate(zoom, feature, canonicalID), + layout->evaluate(zoom, feature, canonicalID)); if (image->second->sdf) { iconType = SymbolContent::IconSDF; } @@ -520,13 +525,13 @@ void SymbolLayout::addFeature(const std::size_t layoutFeatureIndex, const float minScale = 0.5f; const float glyphSize = 24.0f; - const std::array iconOffset = layout->evaluate(zoom, feature); + const std::array iconOffset = layout->evaluate(zoom, feature, canonicalID); // To reduce the number of labels that jump around when zooming we need // to use a text-size value that is the same for all zoom levels. // This calculates text-size at a high zoom level so that all tiles can // use the same value when calculating anchor positions. - const float textMaxSize = layout->evaluate(18, feature); + const float textMaxSize = layout->evaluate(18, feature, canonicalID); const float fontScale = layoutTextSize / glyphSize; const float textBoxScale = tilePixelRatio * fontScale; @@ -536,15 +541,15 @@ void SymbolLayout::addFeature(const std::size_t layoutFeatureIndex, const float textPadding = layout->get() * tilePixelRatio; const float iconPadding = layout->get() * tilePixelRatio; const float textMaxAngle = layout->get() * util::DEG2RAD; - const float iconRotation = layout->evaluate(zoom, feature); - const float textRotation = layout->evaluate(zoom, feature); + const float iconRotation = layout->evaluate(zoom, feature, canonicalID); + const float textRotation = layout->evaluate(zoom, feature, canonicalID); std::array variableTextOffset; if (!textRadialOffset.isUndefined()) { - variableTextOffset = {{layout->evaluate(zoom, feature) * util::ONE_EM, - INVALID_OFFSET_VALUE}}; + variableTextOffset = { + {layout->evaluate(zoom, feature, canonicalID) * util::ONE_EM, INVALID_OFFSET_VALUE}}; } else { - variableTextOffset = {{layout->evaluate(zoom, feature)[0] * util::ONE_EM, - layout->evaluate(zoom, feature)[1] * util::ONE_EM}}; + variableTextOffset = {{layout->evaluate(zoom, feature, canonicalID)[0] * util::ONE_EM, + layout->evaluate(zoom, feature, canonicalID)[1] * util::ONE_EM}}; } const SymbolPlacementType textPlacement = layout->get() != AlignmentType::Map diff --git a/src/mbgl/layout/symbol_layout.hpp b/src/mbgl/layout/symbol_layout.hpp index 740a69df9e..a1c0b86fd9 100644 --- a/src/mbgl/layout/symbol_layout.hpp +++ b/src/mbgl/layout/symbol_layout.hpp @@ -115,6 +115,7 @@ private: const std::unique_ptr sourceLayer; const float overscaling; const float zoom; + const CanonicalTileID canonicalID; const MapMode mode; const float pixelRatio; diff --git a/src/mbgl/renderer/buckets/fill_bucket.cpp b/src/mbgl/renderer/buckets/fill_bucket.cpp index 73c2530241..f42dc59579 100644 --- a/src/mbgl/renderer/buckets/fill_bucket.cpp +++ b/src/mbgl/renderer/buckets/fill_bucket.cpp @@ -115,7 +115,7 @@ void FillBucket::addFeature(const GeometryTileFeature& feature, for (auto& pair : paintPropertyBinders) { const auto it = patternDependencies.find(pair.first); - if (it != patternDependencies.end()){ + if (it != patternDependencies.end()) { pair.second.populateVertexVectors( feature, vertices.elements(), index, patternPositions, it->second, canonical); } else { diff --git a/src/mbgl/renderer/buckets/line_bucket.cpp b/src/mbgl/renderer/buckets/line_bucket.cpp index fdb110bc9d..55593aaa66 100644 --- a/src/mbgl/renderer/buckets/line_bucket.cpp +++ b/src/mbgl/renderer/buckets/line_bucket.cpp @@ -34,7 +34,7 @@ void LineBucket::addFeature(const GeometryTileFeature& feature, std::size_t index, const CanonicalTileID& canonical) { for (auto& line : geometryCollection) { - addGeometry(line, feature); + addGeometry(line, feature, canonical); } for (auto& pair : paintPropertyBinders) { @@ -97,7 +97,9 @@ private: double total; }; -void LineBucket::addGeometry(const GeometryCoordinates& coordinates, const GeometryTileFeature& feature) { +void LineBucket::addGeometry(const GeometryCoordinates& coordinates, + const GeometryTileFeature& feature, + const CanonicalTileID& canonical) { const FeatureType type = feature.getType(); const std::size_t len = [&coordinates] { std::size_t l = coordinates.size(); @@ -137,7 +139,7 @@ void LineBucket::addGeometry(const GeometryCoordinates& coordinates, const Geome *numericValue(clip_start_it->second), *numericValue(clip_end_it->second), total_length}; } - const LineJoinType joinType = layout.evaluate(zoom, feature); + const LineJoinType joinType = layout.evaluate(zoom, feature, canonical); const float miterLimit = joinType == LineJoinType::Bevel ? 1.05f : float(layout.get()); diff --git a/src/mbgl/renderer/buckets/line_bucket.hpp b/src/mbgl/renderer/buckets/line_bucket.hpp index a3821d108b..111c16b348 100644 --- a/src/mbgl/renderer/buckets/line_bucket.hpp +++ b/src/mbgl/renderer/buckets/line_bucket.hpp @@ -52,7 +52,7 @@ public: std::map paintPropertyBinders; private: - void addGeometry(const GeometryCoordinates&, const GeometryTileFeature&); + void addGeometry(const GeometryCoordinates&, const GeometryTileFeature&, const CanonicalTileID&); struct TriangleElement { TriangleElement(uint16_t a_, uint16_t b_, uint16_t c_) : a(a_), b(b_), c(c_) {} diff --git a/src/mbgl/renderer/possibly_evaluated_property_value.hpp b/src/mbgl/renderer/possibly_evaluated_property_value.hpp index 5e412855a4..466e042cbc 100644 --- a/src/mbgl/renderer/possibly_evaluated_property_value.hpp +++ b/src/mbgl/renderer/possibly_evaluated_property_value.hpp @@ -50,6 +50,14 @@ public: ); } + template + T evaluate(const Feature& feature, float zoom, const CanonicalTileID& canonical, T defaultValue) const { + return this->match([&](const T& constant_) { return constant_; }, + [&](const style::PropertyExpression& expression) { + return expression.evaluate(zoom, feature, canonical, defaultValue); + }); + } + template T evaluate(const Feature& feature, float zoom, const FeatureState& featureState, T defaultValue) const { return this->match([&](const T& constant_) { return constant_; }, @@ -96,13 +104,15 @@ public: Faded evaluate(const Feature& feature, float zoom, const std::set& availableImages, + const CanonicalTileID& canonical, T defaultValue) const { return this->match( [&] (const Faded& constant_) { return constant_; }, [&] (const style::PropertyExpression& expression) { if (!expression.isZoomConstant()) { - const T min = expression.evaluate(floor(zoom), feature, availableImages, defaultValue); - const T max = expression.evaluate(floor(zoom) + 1, feature, availableImages, defaultValue); + const T min = expression.evaluate(floor(zoom), feature, availableImages, canonical, defaultValue); + const T max = + expression.evaluate(floor(zoom) + 1, feature, availableImages, canonical, defaultValue); return Faded {min, max}; } else { const T evaluated = expression.evaluate(feature, availableImages, defaultValue); diff --git a/src/mbgl/style/properties.hpp b/src/mbgl/style/properties.hpp index 2fab53ad12..39b6672734 100644 --- a/src/mbgl/style/properties.hpp +++ b/src/mbgl/style/properties.hpp @@ -168,6 +168,11 @@ public: return t; } + template + static T evaluate(float, const GeometryTileFeature&, const CanonicalTileID&, const T& t, const T&) { + return t; + } + template static T evaluate(float z, const GeometryTileFeature& feature, @@ -193,6 +198,30 @@ public: [&](const PropertyExpression& t) { return t.evaluate(z, feature, availableImages, defaultValue); }); } + template + static T evaluate(float z, + const GeometryTileFeature& feature, + const PossiblyEvaluatedPropertyValue& v, + const T& defaultValue, + const std::set& availableImages, + const CanonicalTileID& canonical) { + return v.match([&](const T& t) { return t; }, + [&](const PropertyExpression& t) { + return t.evaluate(z, feature, availableImages, canonical, defaultValue); + }); + } + + template + static T evaluate(float z, + const GeometryTileFeature& feature, + const CanonicalTileID& canonical, + const PossiblyEvaluatedPropertyValue& v, + const T& defaultValue) { + return v.match( + [&](const T& t) { return t; }, + [&](const PropertyExpression& t) { return t.evaluate(z, feature, canonical, defaultValue); }); + } + template static T evaluate(float z, const GeometryTileFeature& feature, const FeatureState& state, const PossiblyEvaluatedPropertyValue& v, const T& defaultValue) { @@ -220,6 +249,14 @@ public: return evaluate(z, feature, this->template get

(), P::defaultValue(), availableImages); } + template + auto evaluate(float z, + const GeometryTileFeature& feature, + const std::set& availableImages, + const CanonicalTileID& canonical) const { + return evaluate(z, feature, this->template get

(), P::defaultValue(), availableImages, canonical); + } + Evaluated evaluate(float z, const GeometryTileFeature& feature) const { return Evaluated { evaluate(z, feature)... -- cgit v1.2.1