diff options
Diffstat (limited to 'src/mbgl')
-rw-r--r-- | src/mbgl/layout/symbol_layout.cpp | 19 | ||||
-rw-r--r-- | src/mbgl/text/quads.cpp | 28 | ||||
-rw-r--r-- | src/mbgl/text/shaping.cpp | 62 | ||||
-rw-r--r-- | src/mbgl/text/shaping.hpp | 8 |
4 files changed, 72 insertions, 45 deletions
diff --git a/src/mbgl/layout/symbol_layout.cpp b/src/mbgl/layout/symbol_layout.cpp index 81d1d9a5b6..d0227c36c5 100644 --- a/src/mbgl/layout/symbol_layout.cpp +++ b/src/mbgl/layout/symbol_layout.cpp @@ -121,7 +121,7 @@ SymbolLayout::SymbolLayout(const BucketParameters& parameters, allowVerticalPlacement = allowVerticalPlacement || placementMode == style::TextWritingModeType::Vertical; return !seen.insert(placementMode).second; }); - modes.erase(end, modes.end()); + modes.erase(end, modes.end()); placementModes = std::move(modes); } @@ -525,21 +525,22 @@ void SymbolLayout::addFeature(const std::size_t layoutFeatureIndex, const float textRepeatDistance = symbolSpacing / 2; const auto evaluatedLayoutProperties = layout->evaluate(zoom, feature); IndexedSubfeature indexedFeature(feature.index, sourceLayer->getName(), bucketLeaderID, symbolInstances.size()); - const bool hasIconTextFit = evaluatedLayoutProperties.get<style::IconTextFit>() != IconTextFitType::None; + const auto iconTextFit = evaluatedLayoutProperties.get<style::IconTextFit>(); // Adjust shaped icon size when icon-text-fit is used. optional<PositionedIcon> verticallyShapedIcon; - if (shapedIcon && hasIconTextFit) { + if (shapedIcon && iconTextFit != IconTextFitType::None) { // Create vertically shaped icon for vertical writing mode if needed. if (allowVerticalPlacement && shapedTextOrientations.vertical) { verticallyShapedIcon = shapedIcon; - verticallyShapedIcon->fitIconToText(evaluatedLayoutProperties, - shapedTextOrientations.vertical, - layoutTextSize); + verticallyShapedIcon->fitIconToText( + shapedTextOrientations.vertical, iconTextFit, layout->get<IconTextFitPadding>(), iconOffset, fontScale); + } + const auto shapedText = getDefaultHorizontalShaping(shapedTextOrientations); + if (shapedText) { + shapedIcon->fitIconToText( + shapedText, iconTextFit, layout->get<IconTextFitPadding>(), iconOffset, fontScale); } - shapedIcon->fitIconToText(evaluatedLayoutProperties, - getDefaultHorizontalShaping(shapedTextOrientations), - layoutTextSize); } auto addSymbolInstance = [&] (Anchor& anchor, std::shared_ptr<SymbolInstanceSharedData> sharedData) { diff --git a/src/mbgl/text/quads.cpp b/src/mbgl/text/quads.cpp index 281c5d99de..a94bfee336 100644 --- a/src/mbgl/text/quads.cpp +++ b/src/mbgl/text/quads.cpp @@ -20,12 +20,28 @@ SymbolQuad getIconQuad(const PositionedIcon& shapedIcon, // If you have a 10px icon that isn't perfectly aligned to the pixel grid it will cover 11 actual // pixels. The quad needs to be padded to account for this, otherwise they'll look slightly clipped // on one edge in some cases. - const float border = 1.0; - - float top = shapedIcon.top() - border / image.pixelRatio; - float left = shapedIcon.left() - border / image.pixelRatio; - float bottom = shapedIcon.bottom() + border / image.pixelRatio; - float right = shapedIcon.right() + border / image.pixelRatio; + constexpr const float border = 1.0f; + + // Expand the box to respect the 1 pixel border in the atlas image. We're using `image.paddedRect - border` + // instead of image.displaySize because we only pad with one pixel for retina images as well, and the + // displaySize uses the logical dimensions, not the physical pixel dimensions. + // Unlike the JavaScript version, we're _not_ including the padding in the texture rect, so the + // logic "dimension * padded / non-padded - dimension" is swapped. + const float iconWidth = shapedIcon.right() - shapedIcon.left(); + const float expandX = (iconWidth * (static_cast<float>(image.textureRect.w) + 2.0f * border) / + static_cast<float>(image.textureRect.w) - + iconWidth) / + 2.0f; + const float left = shapedIcon.left() - expandX; + const float right = shapedIcon.right() + expandX; + + const float iconHeight = shapedIcon.bottom() - shapedIcon.top(); + const float expandY = (iconHeight * (static_cast<float>(image.textureRect.h) + 2.0f * border) / + static_cast<float>(image.textureRect.h) - + iconHeight) / + 2.0f; + const float top = shapedIcon.top() - expandY; + const float bottom = shapedIcon.bottom() + expandY; Point<float> tl{left, top}; Point<float> tr{right, top}; diff --git a/src/mbgl/text/shaping.cpp b/src/mbgl/text/shaping.cpp index 4ae9d0cf20..8eb885af5d 100644 --- a/src/mbgl/text/shaping.cpp +++ b/src/mbgl/text/shaping.cpp @@ -83,33 +83,41 @@ PositionedIcon PositionedIcon::shapeIcon(const ImagePosition& image, return PositionedIcon { image, top, bottom, left, right, iconRotation }; } -void PositionedIcon::fitIconToText(const style::SymbolLayoutProperties::Evaluated& layout, - const Shaping& shapedText, - float layoutTextSize) { - using namespace style; - assert(layout.get<IconTextFit>() != IconTextFitType::None); - if (shapedText) { - auto iconWidth = _right - _left; - auto iconHeight = _bottom - _top; - auto size = layoutTextSize / 24.0f; - auto textLeft = shapedText.left * size; - auto textRight = shapedText.right * size; - auto textTop = shapedText.top * size; - auto textBottom = shapedText.bottom * size; - auto textWidth = textRight - textLeft; - auto textHeight = textBottom - textTop; - auto padT = layout.get<IconTextFitPadding>()[0]; - auto padR = layout.get<IconTextFitPadding>()[1]; - auto padB = layout.get<IconTextFitPadding>()[2]; - auto padL = layout.get<IconTextFitPadding>()[3]; - auto offsetY = layout.get<IconTextFit>() == IconTextFitType::Width ? (textHeight - iconHeight) * 0.5 : 0; - auto offsetX = layout.get<IconTextFit>() == IconTextFitType::Height ? (textWidth - iconWidth) * 0.5 : 0; - auto width = layout.get<IconTextFit>() == IconTextFitType::Width || layout.get<IconTextFit>() == IconTextFitType::Both ? textWidth : iconWidth; - auto height = layout.get<IconTextFit>() == IconTextFitType::Height || layout.get<IconTextFit>() == IconTextFitType::Both ? textHeight : iconHeight; - _left = textLeft + offsetX - padL; - _top = textTop + offsetY - padT; - _right = textLeft + offsetX + padR + width; - _bottom = textTop + offsetY + padB + height; +void PositionedIcon::fitIconToText(const Shaping& shapedText, + const style::IconTextFitType textFit, + const std::array<float, 4>& padding, + const std::array<float, 2>& iconOffset, + const float fontScale) { + assert(textFit != style::IconTextFitType::None); + assert(shapedText); + + // We don't respect the icon-anchor, because icon-text-fit is set. Instead, + // the icon will be centered on the text, then stretched in the given + // dimensions. + + const float textLeft = shapedText.left * fontScale; + const float textRight = shapedText.right * fontScale; + + if (textFit == style::IconTextFitType::Width || textFit == style::IconTextFitType::Both) { + // Stretched horizontally to the text width + _left = iconOffset[0] + textLeft - padding[3]; + _right = iconOffset[0] + textRight + padding[1]; + } else { + // Centered on the text + _left = iconOffset[0] + (textLeft + textRight - image().displaySize()[0]) / 2.0f; + _right = _left + image().displaySize()[0]; + } + + const float textTop = shapedText.top * fontScale; + const float textBottom = shapedText.bottom * fontScale; + if (textFit == style::IconTextFitType::Height || textFit == style::IconTextFitType::Both) { + // Stretched vertically to the text height + _top = iconOffset[1] + textTop - padding[0]; + _bottom = iconOffset[1] + textBottom + padding[2]; + } else { + // Centered on the text + _top = iconOffset[1] + (textTop + textBottom - image().displaySize()[1]) / 2.0f; + _bottom = _top + image().displaySize()[1]; } } diff --git a/src/mbgl/text/shaping.hpp b/src/mbgl/text/shaping.hpp index 28730e9db9..6ed1b5cb0e 100644 --- a/src/mbgl/text/shaping.hpp +++ b/src/mbgl/text/shaping.hpp @@ -45,9 +45,11 @@ public: // Updates shaped icon's bounds based on shaped text's bounds and provided // layout properties. - void fitIconToText(const style::SymbolLayoutProperties::Evaluated& layout, - const Shaping& shapedText, - float layoutTextSize); + void fitIconToText(const Shaping& shapedText, + const style::IconTextFitType textFit, + const std::array<float, 4>& padding, + const std::array<float, 2>& iconOffset, + const float fontScale); const ImagePosition& image() const { return _image; } float top() const { return _top; } |