diff --git a/include/mbgl/text/types.hpp b/include/mbgl/text/types.hpp index 9a9284b58..027df6d63 100644 --- a/include/mbgl/text/types.hpp +++ b/include/mbgl/text/types.hpp @@ -6,6 +6,8 @@ #include #include +#include + namespace mbgl { typedef vec2 CollisionPoint; @@ -35,21 +37,14 @@ struct CollisionRect { // These are the glyph boxes that we want to have placed. struct GlyphBox { explicit GlyphBox() {} - explicit GlyphBox(const CollisionRect &bbox, const CollisionRect &box, - float minScale) - : bbox(bbox), box(box), minScale(minScale) {} + explicit GlyphBox(const CollisionRect &box, float minScale) : box(box), minScale(minScale) {} explicit GlyphBox(const CollisionRect &box, float minScale, float maxScale, - const CollisionAnchor &anchor, bool rotate) - : anchor(anchor), - box(box), - rotate(rotate), - minScale(minScale), - maxScale(maxScale) {} + const CollisionAnchor &anchor) + : anchor(anchor), box(box), minScale(minScale), maxScale(maxScale) {} CollisionAnchor anchor; - CollisionRect bbox; CollisionRect box; - bool rotate = false; + boost::optional hBox; float minScale = 0.0f; float maxScale = std::numeric_limits::infinity(); }; @@ -81,9 +76,8 @@ typedef std::vector PlacedGlyphs; // These are the placed boxes contained in the rtree. struct PlacementBox { CollisionAnchor anchor; - CollisionRect bbox; CollisionRect box; - bool rotate = false; + boost::optional hBox; PlacementRange placementRange = {{0.0f, 0.0f}}; float placementScale = 0.0f; float maxScale = std::numeric_limits::infinity(); diff --git a/src/text/collision.cpp b/src/text/collision.cpp index 54b47e438..a54373f56 100644 --- a/src/text/collision.cpp +++ b/src/text/collision.cpp @@ -37,20 +37,16 @@ Collision::Collision() : cTree(new Tree()), hTree(new Tree()) { // Hack to prevent cross-tile labels insert( {{GlyphBox{ - CollisionRect{CollisionPoint{0, 0}, CollisionPoint{0, m * 8}}, CollisionRect{CollisionPoint{0, 0}, CollisionPoint{0, m * 8}}, 0}, GlyphBox{ - CollisionRect{CollisionPoint{0, 0}, CollisionPoint{m * 8, 0}}, CollisionRect{CollisionPoint{0, 0}, CollisionPoint{m * 8, 0}}, 0}}}, CollisionAnchor(0, 0), 1, {{M_PI * 2, 0}}, false, 2); insert({{GlyphBox{ - CollisionRect{CollisionPoint{-m * 8, 0}, CollisionPoint{0, 0}}, CollisionRect{CollisionPoint{-m * 8, 0}, CollisionPoint{0, 0}}, 0}, GlyphBox{ - CollisionRect{CollisionPoint{0, -m * 8}, CollisionPoint{0, 0}}, CollisionRect{CollisionPoint{0, -m * 8}, CollisionPoint{0, 0}}, 0}}}, CollisionAnchor{m, m}, 1, {{M_PI * 2, 0}}, false, 2); @@ -61,7 +57,6 @@ GlyphBox getMergedGlyphs(const GlyphBoxes &boxes, bool horizontal, GlyphBox mergedGlyphs; const float inf = std::numeric_limits::infinity(); mergedGlyphs.box = CollisionRect{{inf, inf}, {-inf, -inf}}; - mergedGlyphs.rotate = horizontal; mergedGlyphs.anchor = anchor; CollisionRect &box = mergedGlyphs.box; @@ -102,6 +97,7 @@ PlacementProperty Collision::place(const GlyphBoxes &boxes, // Calculate bboxes for all the glyphs for (GlyphBox &glyph : glyphs) { + // for all horizontal labels, calculate bbox covering all rotated positions if (horizontal) { const CollisionRect &box = glyph.box; float x12 = box.tl.x * box.tl.x, y12 = box.tl.y * box.tl.y, @@ -109,9 +105,7 @@ PlacementProperty Collision::place(const GlyphBoxes &boxes, diag = std::sqrt( util::max(x12 + y12, x12 + y22, x22 + y12, x22 + y22)); - glyph.bbox = CollisionRect{{-diag, -diag}, {diag, diag}}; - } else { - glyph.bbox = glyph.box; + glyph.hBox = CollisionRect{{-diag, -diag}, {diag, diag}}; } } @@ -140,8 +134,8 @@ float Collision::getPlacementScale(const GlyphBoxes &glyphs, float maxPlacementScale, float pad) { for (const GlyphBox &glyph : glyphs) { - const CollisionRect &bbox = glyph.bbox; const CollisionRect &box = glyph.box; + const CollisionRect &bbox = glyph.hBox ? glyph.hBox.get() : glyph.box; const CollisionAnchor &anchor = glyph.anchor; if (anchor.x < 0 || anchor.x > 4096 || anchor.y < 0 || @@ -238,7 +232,7 @@ PlacementRange Collision::getPlacementRange(const GlyphBoxes &glyphs, PlacementRange placementRange = {{2.0f * M_PI, 0}}; for (const GlyphBox &glyph : glyphs) { - const CollisionRect &bbox = glyph.bbox; + const CollisionRect &bbox = glyph.hBox ? glyph.hBox.get() : glyph.box; const CollisionAnchor &anchor = glyph.anchor; float minPlacedX = anchor.x + bbox.tl.x / placementScale; @@ -261,15 +255,16 @@ PlacementRange Collision::getPlacementRange(const GlyphBoxes &glyphs, for (const PlacementValue &value : blocking) { const Box &s = std::get<0>(value); const PlacementBox &b = std::get<1>(value); + const CollisionRect &bbox2 = b.hBox ? b.hBox.get() : b.box; float x1, x2, y1, y2, intersectX, intersectY; // Adjust and compare bboxes to see if the glyphs might intersect if (placementScale > b.placementScale) { - x1 = b.anchor.x + b.bbox.tl.x / placementScale; - y1 = b.anchor.y + b.bbox.tl.y / placementScale; - x2 = b.anchor.x + b.bbox.br.x / placementScale; - y2 = b.anchor.y + b.bbox.br.y / placementScale; + x1 = b.anchor.x + bbox2.tl.x / placementScale; + y1 = b.anchor.y + bbox2.tl.y / placementScale; + x2 = b.anchor.x + bbox2.br.x / placementScale; + y2 = b.anchor.y + bbox2.br.y / placementScale; intersectX = x1 < maxPlacedX && x2 > minPlacedX; intersectY = y1 < maxPlacedY && y2 > minPlacedY; } else { @@ -310,8 +305,8 @@ void Collision::insert(const GlyphBoxes &glyphs, const CollisionAnchor &anchor, result.reserve(glyphs.size()); for (const GlyphBox &glyph : glyphs) { - const CollisionRect &bbox = glyph.bbox; const CollisionRect &box = glyph.box; + const CollisionRect &bbox = glyph.hBox ? glyph.hBox.get() : glyph.box; float minScale = std::fmax(placementScale, glyph.minScale); @@ -323,8 +318,9 @@ void Collision::insert(const GlyphBoxes &glyphs, const CollisionAnchor &anchor, PlacementBox placement; placement.anchor = anchor; placement.box = box; - placement.bbox = bbox; - placement.rotate = horizontal; + if (glyph.hBox) { + placement.hBox = bbox; + } placement.placementRange = placementRange; placement.placementScale = minScale; placement.maxScale = glyph.maxScale; diff --git a/src/text/placement.cpp b/src/text/placement.cpp index 82c45b4e0..ae5bf46bf 100644 --- a/src/text/placement.cpp +++ b/src/text/placement.cpp @@ -228,8 +228,8 @@ void getGlyphs(PlacedGlyphs &glyphs, GlyphBoxes &boxes, // Prevent label from extending past the end of the line util::max(instance.minScale, anchor.scale), instance.maxScale, - instance.anchor, - horizontal}; + instance.anchor + }; // Remember the glyph for later insertion. glyphs.emplace_back(PlacedGlyph{ diff --git a/src/text/rotation_range.cpp b/src/text/rotation_range.cpp index 943253a3d..2596cf1bb 100644 --- a/src/text/rotation_range.cpp +++ b/src/text/rotation_range.cpp @@ -239,14 +239,14 @@ CollisionRange rotationRange(const GlyphBox &inserting, static_cast((b.anchor.y - a.anchor.y) * scale)}; // Generate a list of collision interval - if (a.rotate && b.rotate) { + if (a.hBox && b.hBox) { collisions = rotatingRotatingCollisions(a.box, b.box, relativeAnchor); - } else if (a.rotate) { + } else if (a.hBox) { const CollisionRect box { b.box.tl.x + relativeAnchor.x, b.box.tl.y + relativeAnchor.y, b.box.br.x + relativeAnchor.x, b.box.br.y + relativeAnchor.y}; collisions = rotatingFixedCollisions(a.box, box); - } else if (b.rotate) { + } else if (b.hBox) { const CollisionRect box { a.box.tl.x - relativeAnchor.x, a.box.tl.y - relativeAnchor.y, a.box.br.x - relativeAnchor.x, a.box.br.y - relativeAnchor.y};