diff --git a/include/llmr/text/collision.hpp b/include/llmr/text/collision.hpp index ef4899c26..c9dafdd38 100644 --- a/include/llmr/text/collision.hpp +++ b/include/llmr/text/collision.hpp @@ -11,7 +11,7 @@ public: Collision(); ~Collision(); - PlacementProperty place(const PlacedGlyphs &boxes, + PlacementProperty place(const GlyphBoxes &boxes, const CollisionAnchor &anchor, float minPlacementScale, float maxPlacementScale, float padding, bool horizontal, bool alwaysVisible); diff --git a/src/text/collision.cpp b/src/text/collision.cpp index d1488cb29..0da50f280 100644 --- a/src/text/collision.cpp +++ b/src/text/collision.cpp @@ -53,7 +53,7 @@ Collision::Collision() : cTree(new Tree()), hTree(new Tree()) { CollisionAnchor{m, m}, 1, {{M_PI * 2, 0}}, false, 2); } -GlyphBox getMergedGlyphs(const PlacedGlyphs &placed_glyphs, bool horizontal, +GlyphBox getMergedGlyphs(const GlyphBoxes &boxes, bool horizontal, const CollisionAnchor &anchor) { GlyphBox mergedGlyphs; const float inf = std::numeric_limits::infinity(); @@ -62,28 +62,28 @@ GlyphBox getMergedGlyphs(const PlacedGlyphs &placed_glyphs, bool horizontal, mergedGlyphs.anchor = anchor; CollisionRect &box = mergedGlyphs.box; - for (const PlacedGlyph &placed_glyph : placed_glyphs) { - const CollisionRect &gbox = placed_glyph.glyphBox.box; + for (const GlyphBox &glyph : boxes) { + const CollisionRect &gbox = glyph.box; box.tl.x = util::min(box.tl.x, gbox.tl.x); box.tl.y = util::min(box.tl.y, gbox.tl.y); box.br.x = util::max(box.br.x, gbox.br.x); box.br.y = util::max(box.br.y, gbox.br.y); mergedGlyphs.minScale = - util::max(mergedGlyphs.minScale, placed_glyph.glyphBox.minScale); + util::max(mergedGlyphs.minScale, glyph.minScale); } return mergedGlyphs; } -PlacementProperty Collision::place(const PlacedGlyphs &placed_glyphs, +PlacementProperty Collision::place(const GlyphBoxes &boxes, const CollisionAnchor &anchor, float minPlacementScale, float maxPlacementScale, float padding, bool horizontal, bool alwaysVisible) { float minScale = std::numeric_limits::infinity(); - for (const PlacedGlyph &placed_glyph : placed_glyphs) { - minScale = util::min(minScale, placed_glyph.glyphBox.minScale); + for (const GlyphBox &glyphBox : boxes) { + minScale = util::min(minScale, glyphBox.minScale); } minPlacementScale = util::max(minPlacementScale, minScale); @@ -92,11 +92,9 @@ PlacementProperty Collision::place(const PlacedGlyphs &placed_glyphs, // for horizontal labels. GlyphBoxes glyphs; if (horizontal) { - glyphs.push_back(getMergedGlyphs(placed_glyphs, horizontal, anchor)); + glyphs.push_back(getMergedGlyphs(boxes, horizontal, anchor)); } else { - for (const PlacedGlyph &placed_glyph : placed_glyphs) { - glyphs.push_back(placed_glyph.glyphBox); - } + glyphs = boxes; } // Calculate bboxes for all the glyphs diff --git a/src/text/placement.cpp b/src/text/placement.cpp index 237fd05d7..dbf7286e5 100644 --- a/src/text/placement.cpp +++ b/src/text/placement.cpp @@ -72,6 +72,14 @@ struct GlyphInstance { const float angle = 0.0f; }; +struct GlyphsAndBoxes { + explicit GlyphsAndBoxes(const PlacedGlyphs &glyphs, const GlyphBoxes &boxes) + : glyphs(glyphs), boxes(boxes) {} + + const PlacedGlyphs glyphs; + const GlyphBoxes boxes; +}; + typedef std::vector GlyphInstances; void getSegmentGlyphs(std::back_insert_iterator glyphs, @@ -145,7 +153,7 @@ void getSegmentGlyphs(std::back_insert_iterator glyphs, } } -PlacedGlyphs getGlyphs(Anchor &anchor, float advance, const Shaping &shaping, +GlyphsAndBoxes getGlyphs(Anchor &anchor, float advance, const Shaping &shaping, const IndexedFaces &faces, float fontScale, bool horizontal, const std::vector &line, float maxAngleDelta, float rotate) { @@ -163,6 +171,7 @@ PlacedGlyphs getGlyphs(Anchor &anchor, float advance, const Shaping &shaping, // } PlacedGlyphs glyphs; + GlyphBoxes boxes; const uint32_t buffer = 3; @@ -235,23 +244,28 @@ PlacedGlyphs getGlyphs(Anchor &anchor, float advance, const Shaping &shaping, fontScale * util::max(tl.y, tr.y, bl.y, br.y)}; } + GlyphBox glyphBox = GlyphBox{ + box, + // Prevent label from extending past the end of the line + util::max(instance.minScale, anchor.scale), + instance.maxScale, + instance.anchor, + horizontal}; + // Remember the glyph for later insertion. glyphs.emplace_back(PlacedGlyph{ tl, tr, bl, br, glyph.rect, static_cast( - std::fmod((anchor.angle + rotate + instance.offset + 2 * M_PI), - (2 * M_PI))), - GlyphBox{box, instance.minScale, instance.maxScale, - instance.anchor, horizontal}}); + std::fmod((anchor.angle + rotate + instance.offset + 2 * M_PI), (2 * M_PI))), + glyphBox}); + + if (instance.offset == 0.0f) { + boxes.emplace_back(glyphBox); + } } } - // Prevent label from extending past the end of the line - for (PlacedGlyph &g : glyphs) { - g.glyphBox.minScale = util::max(g.glyphBox.minScale, anchor.scale); - } - - return glyphs; + return GlyphsAndBoxes{glyphs, boxes}; } void Placement::addFeature(TextBucket& bucket, @@ -289,14 +303,14 @@ void Placement::addFeature(TextBucket& bucket, } for (Anchor anchor : anchors) { - PlacedGlyphs glyphs = + GlyphsAndBoxes glyphsAndBoxes = getGlyphs(anchor, advance, shaping, faces, fontScale, horizontal, line, maxAngleDelta, rotate); PlacementProperty place = - collision.place(glyphs, anchor, anchor.scale, maxPlacementScale, + collision.place(glyphsAndBoxes.boxes, anchor, anchor.scale, maxPlacementScale, padding, horizontal, info.alwaysVisible); if (place) { - bucket.addGlyphs(glyphs, place.zoom, place.rotationRange, + bucket.addGlyphs(glyphsAndBoxes.glyphs, place.zoom, place.rotationRange, zoom - zOffset); } }