summaryrefslogtreecommitdiff
path: root/src/mbgl/text/placement.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mbgl/text/placement.cpp')
-rw-r--r--src/mbgl/text/placement.cpp60
1 files changed, 40 insertions, 20 deletions
diff --git a/src/mbgl/text/placement.cpp b/src/mbgl/text/placement.cpp
index 4ad911212d..f7d13dcb26 100644
--- a/src/mbgl/text/placement.cpp
+++ b/src/mbgl/text/placement.cpp
@@ -98,7 +98,7 @@ Point<float> calculateVariableLayoutOffset(style::SymbolAnchorType anchor, float
} // namespace
void Placement::placeBucket(
- SymbolBucket& bucket,
+ const SymbolBucket& bucket,
const BucketPlacementParameters& params,
std::set<uint32_t>& seenCrossTileIDs) {
const auto& layout = *bucket.layout;
@@ -157,10 +157,13 @@ 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 hasCollisionCircleData = bucket.hasCollisionCircleData();
const bool zOrderByViewportY = layout.get<style::SymbolZOrder>() == style::SymbolZOrderType::ViewportY;
+ std::vector<ProjectedCollisionBox> textBoxes;
+ std::vector<ProjectedCollisionBox> iconBoxes;
- auto placeSymbol = [&] (SymbolInstance& symbolInstance) {
+ auto placeSymbol = [&] (const SymbolInstance& symbolInstance) {
if (seenCrossTileIDs.count(symbolInstance.crossTileID) != 0u) return;
if (renderTile.holdForFade()) {
@@ -169,14 +172,16 @@ void Placement::placeBucket(
placements.emplace(symbolInstance.crossTileID, JointPlacement(false, false, false));
return;
}
+ textBoxes.clear();
+ iconBoxes.clear();
bool placeText = false;
bool placeIcon = false;
bool offscreen = true;
optional<size_t> horizontalTextIndex = symbolInstance.getDefaultHorizontalPlacedTextIndex();
if (horizontalTextIndex) {
- CollisionFeature& textCollisionFeature = symbolInstance.textCollisionFeature;
- PlacedSymbol& placedSymbol = bucket.text.placedSymbols.at(*horizontalTextIndex);
+ const CollisionFeature& textCollisionFeature = symbolInstance.textCollisionFeature;
+ const PlacedSymbol& placedSymbol = bucket.text.placedSymbols.at(*horizontalTextIndex);
const float fontSize = evaluateSizeForFeature(partiallyEvaluatedTextSize, placedSymbol);
if (variableTextAnchors.empty()) {
auto placed = collisionIndex.placeFeature(textCollisionFeature, {},
@@ -184,7 +189,7 @@ void Placement::placeBucket(
placedSymbol, scale, fontSize,
layout.get<style::TextAllowOverlap>(),
pitchWithMap,
- params.showCollisionBoxes, avoidEdges, collisionGroup.second);
+ params.showCollisionBoxes, avoidEdges, collisionGroup.second, textBoxes);
placeText = placed.first;
offscreen &= placed.second;
} else if (!textCollisionFeature.alongLine && !textCollisionFeature.boxes.empty()) {
@@ -227,7 +232,7 @@ void Placement::placeBucket(
placedSymbol, scale, fontSize,
layout.get<style::TextAllowOverlap>(),
pitchWithMap,
- params.showCollisionBoxes, avoidEdges, collisionGroup.second);
+ params.showCollisionBoxes, avoidEdges, collisionGroup.second, textBoxes);
if (placed.first) {
assert(symbolInstance.crossTileID != 0u);
@@ -253,12 +258,12 @@ void Placement::placeBucket(
textBoxScale,
prevAnchor
}));
- markUsedJustification(bucket, anchor, symbolInstance);
placeText = placed.first;
offscreen &= placed.second;
break;
}
+ textBoxes.clear();
}
// If we didn't get placed, we still need to copy our position from the last placement for
@@ -267,14 +272,13 @@ void Placement::placeBucket(
auto prevOffset = prevPlacement->variableOffsets.find(symbolInstance.crossTileID);
if (prevOffset != prevPlacement->variableOffsets.end()) {
variableOffsets[symbolInstance.crossTileID] = prevOffset->second;
- markUsedJustification(bucket, prevOffset->second.anchor, symbolInstance);
}
}
}
}
if (symbolInstance.placedIconIndex) {
- PlacedSymbol& placedSymbol = bucket.icon.placedSymbols.at(*symbolInstance.placedIconIndex);
+ const PlacedSymbol& placedSymbol = bucket.icon.placedSymbols.at(*symbolInstance.placedIconIndex);
const float fontSize = evaluateSizeForFeature(partiallyEvaluatedIconSize, placedSymbol);
auto placed = collisionIndex.placeFeature(symbolInstance.iconCollisionFeature, {},
@@ -282,7 +286,7 @@ void Placement::placeBucket(
placedSymbol, scale, fontSize,
layout.get<style::IconAllowOverlap>(),
pitchWithMap,
- params.showCollisionBoxes, avoidEdges, collisionGroup.second);
+ params.showCollisionBoxes, avoidEdges, collisionGroup.second, iconBoxes);
placeIcon = placed.first;
offscreen &= placed.second;
}
@@ -300,11 +304,20 @@ void Placement::placeBucket(
}
if (placeText) {
- collisionIndex.insertFeature(symbolInstance.textCollisionFeature, layout.get<style::TextIgnorePlacement>(), bucket.bucketInstanceId, collisionGroup.first);
+ collisionIndex.insertFeature(symbolInstance.textCollisionFeature, textBoxes, layout.get<style::TextIgnorePlacement>(), bucket.bucketInstanceId, collisionGroup.first);
}
if (placeIcon) {
- collisionIndex.insertFeature(symbolInstance.iconCollisionFeature, layout.get<style::IconIgnorePlacement>(), bucket.bucketInstanceId, collisionGroup.first);
+ collisionIndex.insertFeature(symbolInstance.iconCollisionFeature, iconBoxes, layout.get<style::IconIgnorePlacement>(), bucket.bucketInstanceId, collisionGroup.first);
+ }
+
+ if (hasCollisionCircleData) {
+ if (symbolInstance.iconCollisionFeature.alongLine && !iconBoxes.empty()) {
+ collisionCircles[&symbolInstance.iconCollisionFeature] = iconBoxes;
+ }
+ if (symbolInstance.textCollisionFeature.alongLine && !textBoxes.empty()) {
+ collisionCircles[&symbolInstance.textCollisionFeature] = textBoxes;
+ }
}
assert(symbolInstance.crossTileID != 0);
@@ -326,7 +339,7 @@ void Placement::placeBucket(
placeSymbol(*it);
}
} else {
- for (SymbolInstance& symbol : bucket.symbolInstances) {
+ for (const SymbolInstance& symbol : bucket.symbolInstances) {
placeSymbol(symbol);
}
}
@@ -407,7 +420,7 @@ Point<float> calculateVariableRenderShift(style::SymbolAnchorType anchor, float
}
} // namespace
-bool Placement::updateBucketDynamicVertices(SymbolBucket& bucket, const TransformState& state, const RenderTile& tile) {
+bool Placement::updateBucketDynamicVertices(SymbolBucket& bucket, const TransformState& state, const RenderTile& tile) const {
using namespace style;
const auto& layout = *bucket.layout;
const bool alongLine = layout.get<SymbolPlacement>() != SymbolPlacementType::Point;
@@ -569,9 +582,9 @@ void Placement::updateBucketOpacities(SymbolBucket& bucket, const TransformState
bucket.text.opacityVertices.extend(textOpacityVerticesSize, opacityVertex);
- auto prevOffset = variableOffsets.find(symbolInstance.crossTileID);
- if (prevOffset != variableOffsets.end()) {
- markUsedJustification(bucket, prevOffset->second.anchor, symbolInstance);
+ auto offset = variableOffsets.find(symbolInstance.crossTileID);
+ if (offset != variableOffsets.end()) {
+ markUsedJustification(bucket, offset->second.anchor, symbolInstance);
}
}
if (symbolInstance.hasIcon) {
@@ -627,9 +640,16 @@ void Placement::updateBucketOpacities(SymbolBucket& bucket, const TransformState
if (!feature.alongLine) {
return;
}
- for (const CollisionBox& box : feature.boxes) {
- const auto& dynamicVertex = CollisionBoxProgram::dynamicVertex(placed, !box.projected.isCircle(), {});
- bucket.collisionCircle->dynamicVertices.extend(4, dynamicVertex);
+ auto circles = collisionCircles.find(&feature);
+ if (circles != collisionCircles.end()) {
+ for (const auto& circle : circles->second) {
+ const auto& dynamicVertex = CollisionBoxProgram::dynamicVertex(placed, !circle.isCircle(), {});
+ bucket.collisionCircle->dynamicVertices.extend(4, dynamicVertex);
+ }
+ } else {
+ // This feature was not placed, because it was not loaded or from a fading tile. Apply default values.
+ static const auto dynamicVertex = CollisionBoxProgram::dynamicVertex(placed, false /*not used*/, {});
+ bucket.collisionCircle->dynamicVertices.extend(4 * feature.boxes.size(), dynamicVertex);
}
};