From 760dc3a59974d5c5b7c6c6aae7f750474c0fb68e Mon Sep 17 00:00:00 2001 From: Mikhail Pozdnyakov Date: Fri, 22 Mar 2019 20:49:38 +0200 Subject: [core] Single line optimization for variable label placement --- platform/node/test/ignores.json | 4 ++-- src/mbgl/layout/symbol_instance.cpp | 27 ++++++++++++++++------- src/mbgl/layout/symbol_instance.hpp | 5 ++++- src/mbgl/layout/symbol_layout.cpp | 33 ++++++++++++++++++----------- src/mbgl/renderer/buckets/symbol_bucket.cpp | 4 ++-- src/mbgl/style/conversion/constant.cpp | 5 ----- src/mbgl/text/placement.cpp | 4 ++-- src/mbgl/text/shaping.cpp | 1 - 8 files changed, 50 insertions(+), 33 deletions(-) diff --git a/platform/node/test/ignores.json b/platform/node/test/ignores.json index 11dff4d716..060f4935a6 100644 --- a/platform/node/test/ignores.json +++ b/platform/node/test/ignores.json @@ -149,8 +149,8 @@ "render-tests/symbol-sort-key/text-expression": "https://github.com/mapbox/mapbox-gl-native/issues/14028", "render-tests/symbol-sort-key/text-placement": "https://github.com/mapbox/mapbox-gl-native/issues/14028", "render-tests/fill-opacity/opaque-fill-over-symbol-layer": "skip - port https://github.com/mapbox/mapbox-gl-js/pull/7612", - "render-tests/text-variable-anchor/pitched-rotated-debug": "skip - fails on gl-native due to worse accuracy at collision detection (float vs double) - needs issue", - "render-tests/text-variable-anchor/rotated-offset": "skip - fails on gl-native due to worse accuracy at collision detection (float vs double) - needs issue", + "render-tests/text-variable-anchor/pitched-rotated-debug": "https://github.com/mapbox/mapbox-gl-native/issues/14211", + "render-tests/text-variable-anchor/rotated-offset": "https://github.com/mapbox/mapbox-gl-native/issues/14211", "render-tests/text-variable-anchor/remember-last-placement": "skip - fails on gl-native, as symbol index is not functional at static map mode - needs issue", "render-tests/geojson/clustered-properties": "https://github.com/mapbox/mapbox-gl-native/issues/14043", "render-tests/remove-feature-state/composite-expression": "https://github.com/mapbox/mapbox-gl-native/issues/12413", diff --git a/src/mbgl/layout/symbol_instance.cpp b/src/mbgl/layout/symbol_instance.cpp index fddaaf7c2d..0197df1066 100644 --- a/src/mbgl/layout/symbol_instance.cpp +++ b/src/mbgl/layout/symbol_instance.cpp @@ -54,26 +54,37 @@ SymbolInstance::SymbolInstance(Anchor& anchor_, iconOffset(iconOffset_), key(key_), textBoxScale(textBoxScale_), - radialTextOffset(radialTextOffset_) { + radialTextOffset(radialTextOffset_), + singleLine(shapedTextOrientations.singleLine) { // Create the quads used for rendering the icon and glyphs. if (shapedIcon) { iconQuad = getIconQuad(*shapedIcon, layout, layoutTextSize, shapedTextOrientations.horizontal); } - - if (shapedTextOrientations.right) { + + bool singleLineInitialized = false; + const auto initHorizontalGlyphQuads = [&] (SymbolQuads& quads, const Shaping& shaping) { writingModes |= WritingModeType::Horizontal; - rightJustifiedGlyphQuads = getGlyphQuads(shapedTextOrientations.right, textOffset, layout, textPlacement, positions); + if (!singleLine) { + quads = getGlyphQuads(shaping, textOffset, layout, textPlacement, positions); + return; + } + if (!singleLineInitialized) { + rightJustifiedGlyphQuads = getGlyphQuads(shaping, textOffset, layout, textPlacement, positions); + singleLineInitialized = true; + } + }; + + if (shapedTextOrientations.right) { + initHorizontalGlyphQuads(rightJustifiedGlyphQuads, shapedTextOrientations.right); } if (shapedTextOrientations.center) { - writingModes |= WritingModeType::Horizontal; - centerJustifiedGlyphQuads = getGlyphQuads(shapedTextOrientations.center, textOffset, layout, textPlacement, positions); + initHorizontalGlyphQuads(centerJustifiedGlyphQuads, shapedTextOrientations.center); } if (shapedTextOrientations.left) { - writingModes |= WritingModeType::Horizontal; - leftJustifiedGlyphQuads = getGlyphQuads(shapedTextOrientations.left, textOffset, layout, textPlacement, positions); + initHorizontalGlyphQuads(leftJustifiedGlyphQuads, shapedTextOrientations.left); } if (shapedTextOrientations.vertical) { diff --git a/src/mbgl/layout/symbol_instance.hpp b/src/mbgl/layout/symbol_instance.hpp index 44d81ae1e5..5169b16adb 100644 --- a/src/mbgl/layout/symbol_instance.hpp +++ b/src/mbgl/layout/symbol_instance.hpp @@ -18,6 +18,7 @@ struct ShapedTextOrientations { Shaping& right = horizontal; Shaping center; Shaping left; + bool singleLine = false; }; class SymbolInstance { @@ -45,14 +46,15 @@ public: float radialTextOffset); optional getDefaultHorizontalPlacedTextIndex() const; - Anchor anchor; GeometryCoordinates line; bool hasText; bool hasIcon; + // Note: When singleLine == true, only `rightJustifiedGlyphQuads` is populated. SymbolQuads rightJustifiedGlyphQuads; SymbolQuads centerJustifiedGlyphQuads; SymbolQuads leftJustifiedGlyphQuads; + SymbolQuads verticalGlyphQuads; optional iconQuad; @@ -72,6 +74,7 @@ public: optional placedIconIndex; float textBoxScale; float radialTextOffset; + bool singleLine; uint32_t crossTileID = 0; }; diff --git a/src/mbgl/layout/symbol_layout.cpp b/src/mbgl/layout/symbol_layout.cpp index f691d406f1..d1c50d7773 100644 --- a/src/mbgl/layout/symbol_layout.cpp +++ b/src/mbgl/layout/symbol_layout.cpp @@ -312,7 +312,6 @@ void SymbolLayout::prepareSymbols(const GlyphMap& glyphMap, const GlyphPositions justifications.push_back(getAnchorJustification(anchor)); } } - for (TextJustifyType justification: justifications) { Shaping& shapingForJustification = shapingForTextJustifyType(shapedTextOrientations, justification); if (shapingForJustification) { @@ -323,8 +322,11 @@ void SymbolLayout::prepareSymbols(const GlyphMap& glyphMap, const GlyphPositions Shaping shaping = applyShaping(*feature.formattedText, WritingModeType::Horizontal, SymbolAnchorType::Center, justification); if (shaping) { shapingForJustification = std::move(shaping); + if (shaping.lineCount == 1u) { + shapedTextOrientations.singleLine = true; + break; + } } - // TODO: use 'singleLine' optimization. } } else { if (textJustify == TextJustifyType::Auto) { @@ -547,9 +549,9 @@ void SymbolLayout::createBucket(const ImagePositions&, std::unique_ptr(layout, layerPaintProperties, textSize, iconSize, zoom, sdfIcons, iconsNeedLinear, sortFeaturesByY, bucketLeaderID, std::move(symbolInstances), tilePixelRatio); for (SymbolInstance &symbolInstance : bucket->symbolInstances) { - const bool hasText = symbolInstance.hasText; const bool hasIcon = symbolInstance.hasIcon; + const bool singleLine = symbolInstance.singleLine; const auto& feature = features.at(symbolInstance.layoutFeatureIndex); @@ -557,16 +559,23 @@ void SymbolLayout::createBucket(const ImagePositions&, std::unique_ptr lastAddedSection; - if (!symbolInstance.rightJustifiedGlyphQuads.empty()) { - lastAddedSection = addSymbolGlyphQuads(*bucket, symbolInstance, feature, symbolInstance.writingModes, symbolInstance.placedRightTextIndex, symbolInstance.rightJustifiedGlyphQuads, lastAddedSection); - } - if (!symbolInstance.centerJustifiedGlyphQuads.empty()) { - lastAddedSection = addSymbolGlyphQuads(*bucket, symbolInstance, feature, symbolInstance.writingModes, symbolInstance.placedCenterTextIndex, symbolInstance.centerJustifiedGlyphQuads, lastAddedSection); - } - if (!symbolInstance.leftJustifiedGlyphQuads.empty()) { - lastAddedSection = addSymbolGlyphQuads(*bucket, symbolInstance, feature, symbolInstance.writingModes, symbolInstance.placedLeftTextIndex, symbolInstance.leftJustifiedGlyphQuads, lastAddedSection); + if (singleLine) { + optional placedTextIndex; + lastAddedSection = addSymbolGlyphQuads(*bucket, symbolInstance, feature, symbolInstance.writingModes, placedTextIndex, symbolInstance.rightJustifiedGlyphQuads, lastAddedSection); + symbolInstance.placedRightTextIndex = placedTextIndex; + symbolInstance.placedCenterTextIndex = placedTextIndex; + symbolInstance.placedLeftTextIndex = placedTextIndex; + } else { + if (!symbolInstance.rightJustifiedGlyphQuads.empty()) { + lastAddedSection = addSymbolGlyphQuads(*bucket, symbolInstance, feature, symbolInstance.writingModes, symbolInstance.placedRightTextIndex, symbolInstance.rightJustifiedGlyphQuads, lastAddedSection); + } + if (!symbolInstance.centerJustifiedGlyphQuads.empty()) { + lastAddedSection = addSymbolGlyphQuads(*bucket, symbolInstance, feature, symbolInstance.writingModes, symbolInstance.placedCenterTextIndex, symbolInstance.centerJustifiedGlyphQuads, lastAddedSection); + } + if (!symbolInstance.leftJustifiedGlyphQuads.empty()) { + lastAddedSection = addSymbolGlyphQuads(*bucket, symbolInstance, feature, symbolInstance.writingModes, symbolInstance.placedLeftTextIndex, symbolInstance.leftJustifiedGlyphQuads, lastAddedSection); + } } - if (symbolInstance.writingModes & WritingModeType::Vertical) { lastAddedSection = addSymbolGlyphQuads(*bucket, symbolInstance, feature, WritingModeType::Vertical, symbolInstance.placedVerticalTextIndex, symbolInstance.verticalGlyphQuads, lastAddedSection); } diff --git a/src/mbgl/renderer/buckets/symbol_bucket.cpp b/src/mbgl/renderer/buckets/symbol_bucket.cpp index 38342b44ee..68f683c8d6 100644 --- a/src/mbgl/renderer/buckets/symbol_bucket.cpp +++ b/src/mbgl/renderer/buckets/symbol_bucket.cpp @@ -224,11 +224,11 @@ void SymbolBucket::sortFeatures(const float angle) { addPlacedSymbol(text.triangles, text.placedSymbols[*symbolInstance.placedRightTextIndex]); } - if (symbolInstance.placedCenterTextIndex) { + if (symbolInstance.placedCenterTextIndex && !symbolInstance.singleLine) { addPlacedSymbol(text.triangles, text.placedSymbols[*symbolInstance.placedCenterTextIndex]); } - if (symbolInstance.placedLeftTextIndex) { + if (symbolInstance.placedLeftTextIndex && !symbolInstance.singleLine) { addPlacedSymbol(text.triangles, text.placedSymbols[*symbolInstance.placedLeftTextIndex]); } diff --git a/src/mbgl/style/conversion/constant.cpp b/src/mbgl/style/conversion/constant.cpp index 1942779aaa..0fcaab433b 100644 --- a/src/mbgl/style/conversion/constant.cpp +++ b/src/mbgl/style/conversion/constant.cpp @@ -147,11 +147,6 @@ optional> Converter>::operator()(const Con return result; } - -namespace { - -} // namespace - optional> Converter>::operator()(const Convertible& value, Error& error) const { if (!isArray(value)) { error.message = "value must be an array"; diff --git a/src/mbgl/text/placement.cpp b/src/mbgl/text/placement.cpp index 9d0fcf7b32..f6c4ac1eb6 100644 --- a/src/mbgl/text/placement.cpp +++ b/src/mbgl/text/placement.cpp @@ -464,14 +464,14 @@ void Placement::updateBucketOpacities(SymbolBucket& bucket, std::set& PlacedSymbol& placed = bucket.text.placedSymbols[*symbolInstance.placedRightTextIndex]; placed.hidden = opacityState.isHidden(); } - if (symbolInstance.placedCenterTextIndex) { + if (symbolInstance.placedCenterTextIndex && !symbolInstance.singleLine) { for (size_t i = 0; i < symbolInstance.centerJustifiedGlyphQuads.size() * 4; i++) { bucket.text.opacityVertices.emplace_back(opacityVertex); } PlacedSymbol& placed = bucket.text.placedSymbols[*symbolInstance.placedCenterTextIndex]; placed.hidden = opacityState.isHidden(); } - if (symbolInstance.placedLeftTextIndex) { + if (symbolInstance.placedLeftTextIndex && !symbolInstance.singleLine) { for (size_t i = 0; i < symbolInstance.leftJustifiedGlyphQuads.size() * 4; i++) { bucket.text.opacityVertices.emplace_back(opacityVertex); } diff --git a/src/mbgl/text/shaping.cpp b/src/mbgl/text/shaping.cpp index 348c2ddccc..ba21b97389 100644 --- a/src/mbgl/text/shaping.cpp +++ b/src/mbgl/text/shaping.cpp @@ -363,7 +363,6 @@ const Shaping getShaping(const TaggedString& formattedString, const style::TextJustifyType textJustify, const float spacing, const Point& translate, - //const float verticalHeight, const WritingModeType writingMode, BiDi& bidi, const GlyphMap& glyphs) { -- cgit v1.2.1