summaryrefslogtreecommitdiff
path: root/src/mbgl/text
diff options
context:
space:
mode:
Diffstat (limited to 'src/mbgl/text')
-rw-r--r--src/mbgl/text/placement.cpp139
-rw-r--r--src/mbgl/text/quads.cpp48
-rw-r--r--src/mbgl/text/quads.hpp4
-rw-r--r--src/mbgl/text/shaping.cpp45
-rw-r--r--src/mbgl/text/shaping.hpp7
5 files changed, 162 insertions, 81 deletions
diff --git a/src/mbgl/text/placement.cpp b/src/mbgl/text/placement.cpp
index 27c4913c63..1428cf7792 100644
--- a/src/mbgl/text/placement.cpp
+++ b/src/mbgl/text/placement.cpp
@@ -157,6 +157,7 @@ void Placement::placeBucket(
std::vector<style::TextVariableAnchorType> variableTextAnchors = layout.get<style::TextVariableAnchor>();
const bool rotateWithMap = layout.get<style::TextRotationAlignment>() == style::AlignmentType::Map;
const bool pitchWithMap = layout.get<style::TextPitchAlignment>() == style::AlignmentType::Map;
+ const bool hasIconTextFit = layout.get<style::IconTextFit>() != style::IconTextFitType::None;
const bool hasCollisionCircleData = bucket.hasCollisionCircleData();
const bool zOrderByViewportY = layout.get<style::SymbolZOrder>() == style::SymbolZOrderType::ViewportY;
@@ -179,7 +180,9 @@ void Placement::placeBucket(
bool placeIcon = false;
bool offscreen = true;
std::pair<bool, bool> placed{ false, false };
- std::pair<bool, bool> placedVertical{ false, false };
+ std::pair<bool, bool> placedVerticalText{ false, false };
+ std::pair<bool, bool> placedVerticalIcon{ false, false };
+ Point<float> shift{0.0f, 0.0f};
optional<size_t> horizontalTextIndex = symbolInstance.getDefaultHorizontalPlacedTextIndex();
if (horizontalTextIndex) {
const PlacedSymbol& placedSymbol = bucket.text.placedSymbols.at(*horizontalTextIndex);
@@ -200,7 +203,7 @@ void Placement::placeBucket(
assert(!bucket.placementModes.empty());
for (auto& placementMode : bucket.placementModes) {
if (placementMode == style::TextWritingModeType::Vertical) {
- placedVertical = placed = placeVerticalFn();
+ placedVerticalText = placed = placeVerticalFn();
} else {
placed = placeHorizontalFn();
}
@@ -280,7 +283,7 @@ void Placement::placeBucket(
for (size_t i = 0u; i < placementAttempts; ++i) {
auto anchor = variableTextAnchors[i % anchorsSize];
const bool allowOverlap = (i >= anchorsSize);
- Point<float> shift = calculateVariableLayoutOffset(anchor, width, height, symbolInstance.radialTextOffset, textBoxScale);
+ shift = calculateVariableLayoutOffset(anchor, width, height, symbolInstance.radialTextOffset, textBoxScale);
if (rotateWithMap) {
float angle = pitchWithMap ? state.getBearing() : -state.getBearing();
shift = util::rotate(shift, angle);
@@ -359,15 +362,28 @@ void Placement::placeBucket(
}
if (symbolInstance.placedIconIndex) {
+ if (!hasIconTextFit || !placeText || variableTextAnchors.empty()) {
+ shift = {0.0f, 0.0f};
+ }
+
const PlacedSymbol& placedSymbol = bucket.icon.placedSymbols.at(*symbolInstance.placedIconIndex);
const float fontSize = evaluateSizeForFeature(partiallyEvaluatedIconSize, placedSymbol);
+ const auto& placeIconFeature = [&] (const CollisionFeature& collisionFeature) {
+ return collisionIndex.placeFeature(collisionFeature, shift,
+ posMatrix, iconLabelPlaneMatrix, pixelRatio,
+ placedSymbol, scale, fontSize,
+ layout.get<style::IconAllowOverlap>(),
+ pitchWithMap,
+ params.showCollisionBoxes, avoidEdges,
+ collisionGroup.second, iconBoxes);
+ };
- auto placedIcon = collisionIndex.placeFeature(symbolInstance.iconCollisionFeature, {},
- posMatrix, iconLabelPlaneMatrix, pixelRatio,
- placedSymbol, scale, fontSize,
- layout.get<style::IconAllowOverlap>(),
- pitchWithMap,
- params.showCollisionBoxes, avoidEdges, collisionGroup.second, iconBoxes);
+ std::pair<bool, bool> placedIcon = {false, false};
+ if (placedVerticalText.first && symbolInstance.verticalIconCollisionFeature) {
+ placedIcon = placedVerticalIcon = placeIconFeature(*symbolInstance.verticalIconCollisionFeature);
+ } else {
+ placedIcon = placeIconFeature(symbolInstance.iconCollisionFeature);
+ }
placeIcon = placedIcon.first;
offscreen &= placedIcon.second;
}
@@ -385,7 +401,7 @@ void Placement::placeBucket(
}
if (placeText) {
- if (placedVertical.first && symbolInstance.verticalTextCollisionFeature) {
+ if (placedVerticalText.first && symbolInstance.verticalTextCollisionFeature) {
collisionIndex.insertFeature(*symbolInstance.verticalTextCollisionFeature, textBoxes, layout.get<style::TextIgnorePlacement>(), bucket.bucketInstanceId, collisionGroup.first);
} else {
collisionIndex.insertFeature(symbolInstance.textCollisionFeature, textBoxes, layout.get<style::TextIgnorePlacement>(), bucket.bucketInstanceId, collisionGroup.first);
@@ -393,7 +409,11 @@ void Placement::placeBucket(
}
if (placeIcon) {
- collisionIndex.insertFeature(symbolInstance.iconCollisionFeature, iconBoxes, layout.get<style::IconIgnorePlacement>(), bucket.bucketInstanceId, collisionGroup.first);
+ if (placedVerticalIcon.first && symbolInstance.verticalIconCollisionFeature) {
+ collisionIndex.insertFeature(*symbolInstance.verticalIconCollisionFeature, iconBoxes, layout.get<style::IconIgnorePlacement>(), bucket.bucketInstanceId, collisionGroup.first);
+ } else {
+ collisionIndex.insertFeature(symbolInstance.iconCollisionFeature, iconBoxes, layout.get<style::IconIgnorePlacement>(), bucket.bucketInstanceId, collisionGroup.first);
+ }
}
if (hasCollisionCircleData) {
@@ -518,6 +538,8 @@ bool Placement::updateBucketDynamicVertices(SymbolBucket& bucket, const Transfor
using namespace style;
const auto& layout = *bucket.layout;
const bool alongLine = layout.get<SymbolPlacement>() != SymbolPlacementType::Point;
+ const bool hasVariableAnchors = !layout.get<TextVariableAnchor>().empty() && bucket.hasTextData();
+ const bool updateTextFitIcon = layout.get<IconTextFit>() != IconTextFitType::None && (bucket.allowVerticalPlacement || hasVariableAnchors) && bucket.hasIconData();
bool result = false;
if (alongLine) {
@@ -538,7 +560,7 @@ bool Placement::updateBucketDynamicVertices(SymbolBucket& bucket, const Transfor
tile, *bucket.textSizeBinder, state);
result = true;
}
- } else if (!layout.get<TextVariableAnchor>().empty() && bucket.hasTextData()) {
+ } else if (hasVariableAnchors) {
bucket.text.dynamicVertices.clear();
bucket.hasVariablePlacement = false;
@@ -548,8 +570,10 @@ bool Placement::updateBucketDynamicVertices(SymbolBucket& bucket, const Transfor
const bool pitchWithMap = layout.get<TextPitchAlignment>() == AlignmentType::Map;
const float pixelsToTileUnits = tile.id.pixelsToTileUnits(1.0, state.getZoom());
const auto labelPlaneMatrix = getLabelPlaneMatrix(tile.matrix, pitchWithMap, rotateWithMap, state, pixelsToTileUnits);
+ std::unordered_map<std::size_t, std::pair<std::size_t, Point<float>>> placedTextShifts;
- for (const PlacedSymbol& symbol : bucket.text.placedSymbols) {
+ for (std::size_t i = 0; i < bucket.text.placedSymbols.size(); ++i) {
+ const PlacedSymbol& symbol = bucket.text.placedSymbols[i];
optional<VariableOffset> variableOffset;
const bool skipOrientation = bucket.allowVerticalPlacement && !symbol.placedOrientation;
if (!symbol.hidden && symbol.crossTileID != 0u && !skipOrientation) {
@@ -598,24 +622,57 @@ bool Placement::updateBucketDynamicVertices(SymbolBucket& bucket, const Transfor
projectedAnchor.first.y + shift.y);
}
- for (std::size_t i = 0; i < symbol.glyphOffsets.size(); ++i) {
+ if (updateTextFitIcon && symbol.placedIconIndex) {
+ placedTextShifts.emplace(*symbol.placedIconIndex,
+ std::pair<std::size_t, Point<float>>{i, shiftedAnchor});
+ }
+
+ for (std::size_t j = 0; j < symbol.glyphOffsets.size(); ++j) {
addDynamicAttributes(shiftedAnchor, symbol.angle, bucket.text.dynamicVertices);
}
}
}
+ if (updateTextFitIcon && bucket.hasVariablePlacement) {
+ bucket.icon.dynamicVertices.clear();
+ for (std::size_t i = 0; i < bucket.icon.placedSymbols.size(); ++i) {
+ const PlacedSymbol& placedIcon = bucket.icon.placedSymbols[i];
+ if (placedIcon.hidden || (!placedIcon.placedOrientation && bucket.allowVerticalPlacement)) {
+ hideGlyphs(placedIcon.glyphOffsets.size(), bucket.icon.dynamicVertices);
+ } else {
+ const auto& pair = placedTextShifts.find(i);
+ if (pair == placedTextShifts.end()) {
+ hideGlyphs(placedIcon.glyphOffsets.size(), bucket.icon.dynamicVertices);
+ } else {
+ for (std::size_t j = 0; j < placedIcon.glyphOffsets.size(); ++j) {
+ addDynamicAttributes(pair->second.second, placedIcon.angle, bucket.icon.dynamicVertices);
+ }
+ }
+ }
+ }
+ }
+
result = true;
} else if (bucket.allowVerticalPlacement && bucket.hasTextData()) {
- bucket.text.dynamicVertices.clear();
- for (const PlacedSymbol& symbol : bucket.text.placedSymbols) {
- if (symbol.hidden || !symbol.placedOrientation) {
- hideGlyphs(symbol.glyphOffsets.size(), bucket.text.dynamicVertices);
- } else {
- for (std::size_t i = 0; i < symbol.glyphOffsets.size(); ++i) {
- addDynamicAttributes(symbol.anchorPoint, symbol.angle, bucket.text.dynamicVertices);
+ const auto updateDynamicVertices = [](SymbolBucket::Buffer& buffer) {
+ buffer.dynamicVertices.clear();
+ for (const PlacedSymbol& symbol : buffer.placedSymbols) {
+ if (symbol.hidden || !symbol.placedOrientation) {
+ hideGlyphs(symbol.glyphOffsets.size(), buffer.dynamicVertices);
+ } else {
+ for (std::size_t j = 0; j < symbol.glyphOffsets.size(); ++j) {
+ addDynamicAttributes(symbol.anchorPoint, symbol.angle, buffer.dynamicVertices);
+ }
}
}
+ };
+
+ updateDynamicVertices(bucket.text);
+ // When text box is rotated, icon-text-fit icon must be rotated as well.
+ if (updateTextFitIcon) {
+ updateDynamicVertices(bucket.icon);
}
+
result = true;
}
@@ -635,6 +692,7 @@ void Placement::updateBucketOpacities(SymbolBucket& bucket, const TransformState
const bool variablePlacement = !bucket.layout->get<style::TextVariableAnchor>().empty();
const bool rotateWithMap = bucket.layout->get<style::TextRotationAlignment>() == style::AlignmentType::Map;
const bool pitchWithMap = bucket.layout->get<style::TextPitchAlignment>() == style::AlignmentType::Map;
+ const bool hasIconTextFit = bucket.layout->get<style::IconTextFit>() != style::IconTextFitType::None;
// If allow-overlap is true, we can show symbols before placement runs on them
// But we have to wait for placement if we potentially depend on a paired icon/text
@@ -703,25 +761,30 @@ void Placement::updateBucketOpacities(SymbolBucket& bucket, const TransformState
}
if (symbolInstance.hasIcon) {
const auto& opacityVertex = SymbolIconProgram::opacityVertex(opacityState.icon.placed, opacityState.icon.opacity);
- bucket.icon.opacityVertices.extend(4, opacityVertex);
if (symbolInstance.placedIconIndex) {
+ bucket.icon.opacityVertices.extend(4, opacityVertex);
bucket.icon.placedSymbols[*symbolInstance.placedIconIndex].hidden = opacityState.isHidden();
}
+
+ if (symbolInstance.placedVerticalIconIndex) {
+ bucket.icon.opacityVertices.extend(4, opacityVertex);
+ bucket.icon.placedSymbols[*symbolInstance.placedVerticalIconIndex].hidden = opacityState.isHidden();
+ }
}
- auto updateCollisionBox = [&](const auto& feature, const bool placed) {
+ auto updateCollisionBox = [&](const auto& feature, const bool placed, const Point<float>& shift) {
if (feature.alongLine) {
return;
}
- const auto& dynamicVertex = CollisionBoxProgram::dynamicVertex(placed, false, {});
+ const auto& dynamicVertex = CollisionBoxProgram::dynamicVertex(placed, false, shift);
bucket.collisionBox->dynamicVertices.extend(feature.boxes.size() * 4, dynamicVertex);
};
auto updateCollisionTextBox = [this, &bucket, &symbolInstance, &state, variablePlacement, rotateWithMap, pitchWithMap](const auto& feature, const bool placed) {
+ Point<float> shift{0.0f, 0.0f};
if (feature.alongLine) {
- return;
+ return shift;
}
- Point<float> shift;
bool used = true;
if (variablePlacement) {
auto foundOffset = variableOffsets.find(symbolInstance.crossTileID);
@@ -748,6 +811,7 @@ void Placement::updateBucketOpacities(SymbolBucket& bucket, const TransformState
}
const auto& dynamicVertex = CollisionBoxProgram::dynamicVertex(placed, !used, shift);
bucket.collisionBox->dynamicVertices.extend(feature.boxes.size() * 4, dynamicVertex);
+ return shift;
};
auto updateCollisionCircles = [&](const auto& feature, const bool placed) {
@@ -768,12 +832,17 @@ void Placement::updateBucketOpacities(SymbolBucket& bucket, const TransformState
};
if (bucket.hasCollisionBoxData()) {
- // TODO: update collision box opacity based on selected text variant (horizontal | vertical).
- updateCollisionTextBox(symbolInstance.textCollisionFeature, opacityState.text.placed);
- if (bucket.allowVerticalPlacement && symbolInstance.verticalTextCollisionFeature) {
- updateCollisionTextBox(*symbolInstance.verticalTextCollisionFeature, opacityState.text.placed);
+ const auto& textShift = updateCollisionTextBox(symbolInstance.textCollisionFeature, opacityState.text.placed);
+ if (bucket.allowVerticalPlacement) {
+ Point<float> verticalTextShift{0.0f, 0.0f};
+ if (symbolInstance.verticalTextCollisionFeature) {
+ verticalTextShift = updateCollisionTextBox(*symbolInstance.verticalTextCollisionFeature, opacityState.text.placed);
+ }
+ if (symbolInstance.verticalIconCollisionFeature) {
+ updateCollisionBox(*symbolInstance.verticalIconCollisionFeature, opacityState.text.placed, hasIconTextFit ? verticalTextShift : Point<float>{0.0f, 0.0f});
+ }
}
- updateCollisionBox(symbolInstance.iconCollisionFeature, opacityState.icon.placed);
+ updateCollisionBox(symbolInstance.iconCollisionFeature, opacityState.icon.placed, hasIconTextFit ? textShift : Point<float>{0.0f, 0.0f});
}
if (bucket.hasCollisionCircleData()) {
updateCollisionCircles(symbolInstance.textCollisionFeature, opacityState.text.placed);
@@ -850,6 +919,14 @@ void Placement::markUsedOrientation(SymbolBucket& bucket, style::TextWritingMode
if (symbolInstance.placedVerticalTextIndex) {
bucket.text.placedSymbols.at(*symbolInstance.placedVerticalTextIndex).placedOrientation = vertical;
}
+
+ if (symbolInstance.placedIconIndex) {
+ bucket.icon.placedSymbols.at(*symbolInstance.placedIconIndex).placedOrientation = horizontal;
+ }
+
+ if (symbolInstance.placedVerticalIconIndex) {
+ bucket.icon.placedSymbols.at(*symbolInstance.placedVerticalIconIndex).placedOrientation = vertical;
+ }
}
float Placement::symbolFadeChange(TimePoint now) const {
diff --git a/src/mbgl/text/quads.cpp b/src/mbgl/text/quads.cpp
index b08c2bc0ba..281c5d99de 100644
--- a/src/mbgl/text/quads.cpp
+++ b/src/mbgl/text/quads.cpp
@@ -14,9 +14,7 @@ namespace mbgl {
using namespace style;
SymbolQuad getIconQuad(const PositionedIcon& shapedIcon,
- const SymbolLayoutProperties::Evaluated& layout,
- const float layoutTextSize,
- const Shaping& shapedText) {
+ WritingModeType writingMode) {
const ImagePosition& image = shapedIcon.image();
// If you have a 10px icon that isn't perfectly aligned to the pixel grid it will cover 11 actual
@@ -28,43 +26,11 @@ SymbolQuad getIconQuad(const PositionedIcon& shapedIcon,
float left = shapedIcon.left() - border / image.pixelRatio;
float bottom = shapedIcon.bottom() + border / image.pixelRatio;
float right = shapedIcon.right() + border / image.pixelRatio;
- Point<float> tl;
- Point<float> tr;
- Point<float> br;
- Point<float> bl;
-
- if (layout.get<IconTextFit>() != IconTextFitType::None && 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;
- tl = {left, top};
- tr = {right, top};
- br = {right, bottom};
- bl = {left, bottom};
- } else {
- tl = {left, top};
- tr = {right, top};
- br = {right, bottom};
- bl = {left, bottom};
- }
+
+ Point<float> tl{left, top};
+ Point<float> tr{right, top};
+ Point<float> br{right, bottom};
+ Point<float> bl{left, bottom};
const float angle = shapedIcon.angle();
@@ -88,7 +54,7 @@ SymbolQuad getIconQuad(const PositionedIcon& shapedIcon,
static_cast<uint16_t>(image.textureRect.h + border * 2)
};
- return SymbolQuad { tl, tr, bl, br, textureRect, shapedText.writingMode, { 0.0f, 0.0f } };
+ return SymbolQuad { tl, tr, bl, br, textureRect, writingMode, { 0.0f, 0.0f } };
}
SymbolQuads getGlyphQuads(const Shaping& shapedText,
diff --git a/src/mbgl/text/quads.hpp b/src/mbgl/text/quads.hpp
index 1ec68189af..145fd2b153 100644
--- a/src/mbgl/text/quads.hpp
+++ b/src/mbgl/text/quads.hpp
@@ -44,9 +44,7 @@ public:
using SymbolQuads = std::vector<SymbolQuad>;
SymbolQuad getIconQuad(const PositionedIcon& shapedIcon,
- const style::SymbolLayoutProperties::Evaluated&,
- const float layoutTextSize,
- const Shaping& shapedText);
+ WritingModeType writingMode);
SymbolQuads getGlyphQuads(const Shaping& shapedText,
const std::array<float, 2> textOffset,
diff --git a/src/mbgl/text/shaping.cpp b/src/mbgl/text/shaping.cpp
index 7bf0e14f80..0cb9ea73a9 100644
--- a/src/mbgl/text/shaping.cpp
+++ b/src/mbgl/text/shaping.cpp
@@ -68,16 +68,49 @@ style::TextJustifyType getAnchorJustification(style::SymbolAnchorType anchor) {
}
}
-PositionedIcon PositionedIcon::shapeIcon(const ImagePosition& image, const std::array<float, 2>& iconOffset, style::SymbolAnchorType iconAnchor, const float iconRotation) {
+PositionedIcon PositionedIcon::shapeIcon(const ImagePosition& image,
+ const std::array<float, 2>& iconOffset,
+ style::SymbolAnchorType iconAnchor,
+ const float iconRotation) {
AnchorAlignment anchorAlign = AnchorAlignment::getAnchorAlignment(iconAnchor);
float dx = iconOffset[0];
float dy = iconOffset[1];
- float x1 = dx - image.displaySize()[0] * anchorAlign.horizontalAlign;
- float x2 = x1 + image.displaySize()[0];
- float y1 = dy - image.displaySize()[1] * anchorAlign.verticalAlign;
- float y2 = y1 + image.displaySize()[1];
+ float left = dx - image.displaySize()[0] * anchorAlign.horizontalAlign;
+ float right = left + image.displaySize()[0];
+ float top = dy - image.displaySize()[1] * anchorAlign.verticalAlign;
+ float bottom = top + image.displaySize()[1];
- return PositionedIcon { image, y1, y2, x1, x2, iconRotation };
+ 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 align(Shaping& shaping,
diff --git a/src/mbgl/text/shaping.hpp b/src/mbgl/text/shaping.hpp
index f3a01e3caf..60a9c718ff 100644
--- a/src/mbgl/text/shaping.hpp
+++ b/src/mbgl/text/shaping.hpp
@@ -4,6 +4,7 @@
#include <mbgl/text/tagged_string.hpp>
#include <mbgl/renderer/image_atlas.hpp>
#include <mbgl/style/types.hpp>
+#include <mbgl/style/layers/symbol_layer_properties.hpp>
namespace mbgl {
@@ -52,6 +53,12 @@ public:
style::SymbolAnchorType iconAnchor,
const float iconRotation);
+ // 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);
+
const ImagePosition& image() const { return _image; }
float top() const { return _top; }
float bottom() const { return _bottom; }