summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnsis Brammanis <brammanis@gmail.com>2017-06-26 12:18:08 -0400
committerAnsis Brammanis <brammanis@gmail.com>2017-06-26 12:18:08 -0400
commitf43b4c0a53271e2d3c70533068fc90d9c82743b6 (patch)
tree4c58deeb5378f341b086202a18a6a32de1c02fda
parenta14db0d12e08845543759da40cde7fc72caf727c (diff)
downloadqtlocation-mapboxgl-f43b4c0a53271e2d3c70533068fc90d9c82743b6.tar.gz
port quad changes
-rw-r--r--src/mbgl/layout/symbol_instance.cpp10
-rw-r--r--src/mbgl/layout/symbol_instance.hpp2
-rw-r--r--src/mbgl/layout/symbol_layout.cpp63
-rw-r--r--src/mbgl/layout/symbol_layout.hpp2
-rw-r--r--src/mbgl/text/quads.cpp303
-rw-r--r--src/mbgl/text/quads.hpp31
6 files changed, 77 insertions, 334 deletions
diff --git a/src/mbgl/layout/symbol_instance.cpp b/src/mbgl/layout/symbol_instance.cpp
index d28da6b43e..0dc6802883 100644
--- a/src/mbgl/layout/symbol_instance.cpp
+++ b/src/mbgl/layout/symbol_instance.cpp
@@ -5,7 +5,7 @@ namespace mbgl {
using namespace style;
-SymbolInstance::SymbolInstance(Anchor& anchor,
+SymbolInstance::SymbolInstance(Anchor& anchor_,
GeometryCoordinates line_,
const std::pair<Shaping, Shaping>& shapedTextOrientations,
optional<PositionedIcon> shapedIcon,
@@ -22,7 +22,7 @@ SymbolInstance::SymbolInstance(Anchor& anchor,
const GlyphPositionMap& positions,
const IndexedSubfeature& indexedFeature,
const std::size_t featureIndex_) :
- point(anchor.point),
+ anchor(anchor_),
line(line_),
index(index_),
hasText(shapedTextOrientations.first || shapedTextOrientations.second),
@@ -36,14 +36,14 @@ SymbolInstance::SymbolInstance(Anchor& anchor,
// Create the quads used for rendering the icon and glyphs.
if (addToBuffers) {
if (shapedIcon) {
- iconQuad = getIconQuad(anchor, *shapedIcon, line_, layout, layoutTextSize, iconPlacement, shapedTextOrientations.first);
+ iconQuad = getIconQuad(*shapedIcon, layout, layoutTextSize, shapedTextOrientations.first);
}
if (shapedTextOrientations.first) {
- auto quads = getGlyphQuads(anchor, shapedTextOrientations.first, textBoxScale, line_, layout, textPlacement, positions);
+ auto quads = getGlyphQuads(shapedTextOrientations.first, layout, textPlacement, positions);
glyphQuads.insert(glyphQuads.end(), quads.begin(), quads.end());
}
if (shapedTextOrientations.second) {
- auto quads = getGlyphQuads(anchor, shapedTextOrientations.second, textBoxScale, line_, layout, textPlacement, positions);
+ auto quads = getGlyphQuads(shapedTextOrientations.second, layout, textPlacement, positions);
glyphQuads.insert(glyphQuads.end(), quads.begin(), quads.end());
}
}
diff --git a/src/mbgl/layout/symbol_instance.hpp b/src/mbgl/layout/symbol_instance.hpp
index 859fa20a02..0eca512271 100644
--- a/src/mbgl/layout/symbol_instance.hpp
+++ b/src/mbgl/layout/symbol_instance.hpp
@@ -30,7 +30,7 @@ public:
const IndexedSubfeature&,
const std::size_t featureIndex);
- Point<float> point;
+ Anchor anchor;
GeometryCoordinates line;
uint32_t index;
bool hasText;
diff --git a/src/mbgl/layout/symbol_layout.cpp b/src/mbgl/layout/symbol_layout.cpp
index d3ed8455a0..6b79ec513a 100644
--- a/src/mbgl/layout/symbol_layout.cpp
+++ b/src/mbgl/layout/symbol_layout.cpp
@@ -454,8 +454,8 @@ std::unique_ptr<SymbolBucket> SymbolLayout::place(CollisionTile& collisionTile)
const float cos = std::cos(collisionTile.config.angle);
std::sort(symbolInstances.begin(), symbolInstances.end(), [sin, cos](SymbolInstance &a, SymbolInstance &b) {
- const int32_t aRotated = sin * a.point.x + cos * a.point.y;
- const int32_t bRotated = sin * b.point.x + cos * b.point.y;
+ const int32_t aRotated = sin * a.anchor.point.x + cos * a.anchor.point.y;
+ const int32_t bRotated = sin * b.anchor.point.x + cos * b.anchor.point.y;
return aRotated != bRotated ?
aRotated < bRotated :
a.index > b.index;
@@ -504,9 +504,9 @@ std::unique_ptr<SymbolBucket> SymbolLayout::place(CollisionTile& collisionTile)
for (const auto& symbol : symbolInstance.glyphQuads) {
addSymbol(
bucket->text, sizeData, symbol, placementZoom,
- keepUpright, textPlacement, collisionTile.config.angle, symbolInstance.writingModes, symbolInstance.point);
+ keepUpright, textPlacement, collisionTile.config.angle, symbolInstance.writingModes, symbolInstance.anchor);
}
- PlacedSymbol placedSymbol(symbolInstance.point, symbolInstance.index, sizeData.min, sizeData.max, 0, 0, placementZoom, false, symbolInstance.line);
+ PlacedSymbol placedSymbol(symbolInstance.anchor.point, symbolInstance.index, sizeData.min, sizeData.max, 0, 0, placementZoom, false, symbolInstance.line);
bucket->text.placedSymbols.emplace_back(std::move(placedSymbol));
}
}
@@ -518,8 +518,8 @@ std::unique_ptr<SymbolBucket> SymbolLayout::place(CollisionTile& collisionTile)
const Range<float> sizeData = bucket->iconSizeBinder->getVertexSizeData(feature);
addSymbol(
bucket->icon, sizeData, *symbolInstance.iconQuad, placementZoom,
- keepUpright, iconPlacement, collisionTile.config.angle, symbolInstance.writingModes, symbolInstance.point);
- PlacedSymbol placedSymbol(symbolInstance.point, symbolInstance.index, sizeData.min, sizeData.max, 0, 0, placementZoom, false, symbolInstance.line);
+ keepUpright, iconPlacement, collisionTile.config.angle, symbolInstance.writingModes, symbolInstance.anchor);
+ PlacedSymbol placedSymbol(symbolInstance.anchor.point, symbolInstance.index, sizeData.min, sizeData.max, 0, 0, placementZoom, false, symbolInstance.line);
bucket->icon.placedSymbols.emplace_back(std::move(placedSymbol));
}
}
@@ -546,7 +546,7 @@ void SymbolLayout::addSymbol(Buffer& buffer,
const style::SymbolPlacementType placement,
const float placementAngle,
const WritingModeType writingModes,
- const Point<float> labelAnchor) {
+ const Anchor& labelAnchor) {
constexpr const uint16_t vertexLength = 4;
const auto &tl = symbol.tl;
@@ -555,30 +555,15 @@ void SymbolLayout::addSymbol(Buffer& buffer,
const auto &br = symbol.br;
const auto &tex = symbol.tex;
- float minZoom = util::max(zoom + util::log2(symbol.minScale), placementZoom);
- float maxZoom = util::min(zoom + util::log2(symbol.maxScale), util::MAX_ZOOM_F);
- const auto &anchorPoint = symbol.anchorPoint;
-
- // drop incorrectly oriented glyphs
- const float a = std::fmod(symbol.anchorAngle + placementAngle + M_PI, M_PI * 2);
- if (writingModes & WritingModeType::Vertical) {
- if (placement == style::SymbolPlacementType::Line && symbol.writingMode == WritingModeType::Vertical) {
- if (keepUpright && placement == style::SymbolPlacementType::Line && (a <= (M_PI * 5 / 4) || a > (M_PI * 7 / 4)))
- return;
- } else if (keepUpright && placement == style::SymbolPlacementType::Line && (a <= (M_PI * 3 / 4) || a > (M_PI * 5 / 4)))
- return;
- } else if (keepUpright && placement == style::SymbolPlacementType::Line &&
- (a <= M_PI / 2 || a > M_PI * 3 / 2)) {
- return;
- }
-
- if (maxZoom <= minZoom)
- return;
+ const float labelAngle = std::fmod((labelAnchor.angle + placementAngle) + 2 * M_PI, 2 * M_PI);
+ const bool inVerticalRange = (
+ (labelAngle > M_PI * 1.0 / 4.0 && labelAngle <= M_PI * 3.0 / 4) ||
+ (labelAngle > M_PI * 5.0 / 4.0 && labelAngle <= M_PI * 7.0 / 4));
+ const bool useVerticalMode = writingModes & WritingModeType::Vertical && inVerticalRange;
- // Lower min zoom so that while fading out the label
- // it can be shown outside of collision-free zoom levels
- if (minZoom == placementZoom) {
- minZoom = 0;
+ if (placement == style::SymbolPlacementType::Line && keepUpright) {
+ // drop incorrectly oriented glyphs
+ if ((symbol.writingMode == WritingModeType::Vertical) != useVerticalMode) return;
}
if (buffer.segments.empty() || buffer.segments.back().vertexLength + vertexLength > std::numeric_limits<uint16_t>::max()) {
@@ -592,12 +577,12 @@ void SymbolLayout::addSymbol(Buffer& buffer,
uint16_t index = segment.vertexLength;
// coordinates (2 triangles)
- buffer.vertices.emplace_back(SymbolLayoutAttributes::vertex(labelAnchor, tl, tex.x, tex.y, sizeData));
- buffer.vertices.emplace_back(SymbolLayoutAttributes::vertex(labelAnchor, tr, tex.x + tex.w, tex.y, sizeData));
- buffer.vertices.emplace_back(SymbolLayoutAttributes::vertex(labelAnchor, bl, tex.x, tex.y + tex.h, sizeData));
- buffer.vertices.emplace_back(SymbolLayoutAttributes::vertex(labelAnchor, br, tex.x + tex.w, tex.y + tex.h, sizeData));
+ buffer.vertices.emplace_back(SymbolLayoutAttributes::vertex(labelAnchor.point, tl, tex.x, tex.y, sizeData));
+ buffer.vertices.emplace_back(SymbolLayoutAttributes::vertex(labelAnchor.point, tr, tex.x + tex.w, tex.y, sizeData));
+ buffer.vertices.emplace_back(SymbolLayoutAttributes::vertex(labelAnchor.point, bl, tex.x, tex.y + tex.h, sizeData));
+ buffer.vertices.emplace_back(SymbolLayoutAttributes::vertex(labelAnchor.point, br, tex.x + tex.w, tex.y + tex.h, sizeData));
- auto dynamicVertex = SymbolDynamicLayoutAttributes::vertex(anchorPoint, 0, placementZoom);
+ auto dynamicVertex = SymbolDynamicLayoutAttributes::vertex(labelAnchor.point, 0, placementZoom);
buffer.dynamicVertices.emplace_back(dynamicVertex);
buffer.dynamicVertices.emplace_back(dynamicVertex);
buffer.dynamicVertices.emplace_back(dynamicVertex);
@@ -648,10 +633,10 @@ void SymbolLayout::addToDebugBuffers(CollisionTile& collisionTile, SymbolBucket&
auto& segment = collisionBox.segments.back();
uint16_t index = segment.vertexLength;
- collisionBox.vertices.emplace_back(CollisionBoxProgram::vertex(anchor, symbolInstance.point, tl, maxZoom, placementZoom));
- collisionBox.vertices.emplace_back(CollisionBoxProgram::vertex(anchor, symbolInstance.point, tr, maxZoom, placementZoom));
- collisionBox.vertices.emplace_back(CollisionBoxProgram::vertex(anchor, symbolInstance.point, br, maxZoom, placementZoom));
- collisionBox.vertices.emplace_back(CollisionBoxProgram::vertex(anchor, symbolInstance.point, bl, maxZoom, placementZoom));
+ collisionBox.vertices.emplace_back(CollisionBoxProgram::vertex(anchor, symbolInstance.anchor.point, tl, maxZoom, placementZoom));
+ collisionBox.vertices.emplace_back(CollisionBoxProgram::vertex(anchor, symbolInstance.anchor.point, tr, maxZoom, placementZoom));
+ collisionBox.vertices.emplace_back(CollisionBoxProgram::vertex(anchor, symbolInstance.anchor.point, br, maxZoom, placementZoom));
+ collisionBox.vertices.emplace_back(CollisionBoxProgram::vertex(anchor, symbolInstance.anchor.point, bl, maxZoom, placementZoom));
collisionBox.lines.emplace_back(index + 0, index + 1);
collisionBox.lines.emplace_back(index + 1, index + 2);
diff --git a/src/mbgl/layout/symbol_layout.hpp b/src/mbgl/layout/symbol_layout.hpp
index 48aa8a321c..37835bad14 100644
--- a/src/mbgl/layout/symbol_layout.hpp
+++ b/src/mbgl/layout/symbol_layout.hpp
@@ -72,7 +72,7 @@ private:
const style::SymbolPlacementType,
const float placementAngle,
WritingModeType writingModes,
- const Point<float> labelAnchor);
+ const Anchor& labelAnchor);
const std::string sourceLayerName;
const std::string bucketName;
diff --git a/src/mbgl/text/quads.cpp b/src/mbgl/text/quads.cpp
index ab10c5a6b7..b2ef063bd6 100644
--- a/src/mbgl/text/quads.cpp
+++ b/src/mbgl/text/quads.cpp
@@ -13,14 +13,9 @@ namespace mbgl {
using namespace style;
-const float globalMinScale = 0.5f; // underscale by 1 zoom level
-
-SymbolQuad getIconQuad(const Anchor& anchor,
- const PositionedIcon& shapedIcon,
- const GeometryCoordinates& line,
+SymbolQuad getIconQuad(const PositionedIcon& shapedIcon,
const SymbolLayoutProperties::Evaluated& layout,
const float layoutTextSize,
- const style::SymbolPlacementType placement,
const Shaping& shapedText) {
const ImagePosition& image = shapedIcon.image();
@@ -71,18 +66,7 @@ SymbolQuad getIconQuad(const Anchor& anchor,
bl = {left, bottom};
}
- float angle = shapedIcon.angle();
- if (placement == style::SymbolPlacementType::Line) {
- assert(static_cast<unsigned int>(anchor.segment) < line.size());
- const GeometryCoordinate &prev= line[anchor.segment];
- if (anchor.point.y == prev.y && anchor.point.x == prev.x &&
- static_cast<unsigned int>(anchor.segment + 1) < line.size()) {
- const GeometryCoordinate &next= line[anchor.segment + 1];
- angle += std::atan2(anchor.point.y - next.y, anchor.point.x - next.x) + M_PI;
- } else {
- angle += std::atan2(anchor.point.y - prev.y, anchor.point.x - prev.x);
- }
- }
+ const float angle = shapedIcon.angle();
if (angle) {
// Compute the transformation matrix.
@@ -104,212 +88,15 @@ SymbolQuad getIconQuad(const Anchor& anchor,
static_cast<uint16_t>(image.textureRect.h + border * 2)
};
- return SymbolQuad { tl, tr, bl, br, textureRect, 0, 0, anchor.point, globalMinScale, std::numeric_limits<float>::infinity(), shapedText.writingMode };
-}
-
-struct GlyphInstance {
- explicit GlyphInstance(Point<float> anchorPoint_) : anchorPoint(std::move(anchorPoint_)) {}
- explicit GlyphInstance(Point<float> anchorPoint_, bool upsideDown_, float minScale_, float maxScale_,
- float angle_)
- : anchorPoint(std::move(anchorPoint_)), upsideDown(upsideDown_), minScale(minScale_), maxScale(maxScale_), angle(angle_) {}
-
- const Point<float> anchorPoint;
- const bool upsideDown = false;
- const float minScale = globalMinScale;
- const float maxScale = std::numeric_limits<float>::infinity();
- const float angle = 0.0f;
-};
-
-using GlyphInstances = std::vector<GlyphInstance>;
-
-struct VirtualSegment {
- Point<float> anchor;
- Point<float> end;
- size_t index;
- float minScale;
- float maxScale;
-};
-
-inline void insertSegmentGlyph(std::back_insert_iterator<GlyphInstances> glyphs,
- const VirtualSegment& virtualSegment,
- const bool glyphIsLogicallyForward,
- const bool upsideDown) {
- float segmentAngle = std::atan2(virtualSegment.end.y - virtualSegment.anchor.y, virtualSegment.end.x - virtualSegment.anchor.x);
- // If !glyphIsLogicallyForward, we're iterating through the segments in reverse logical order as well, so we need to flip the segment angle
- float glyphAngle = glyphIsLogicallyForward ? segmentAngle : segmentAngle + M_PI;
-
- // Insert a glyph rotated at this angle for display in the range from [scale, previous(larger) scale].
- glyphs = GlyphInstance{
- /* anchor */ virtualSegment.anchor,
- /* upsideDown */ upsideDown,
- /* minScale */ virtualSegment.minScale,
- /* maxScale */ virtualSegment.maxScale,
- /* angle */ static_cast<float>(std::fmod((glyphAngle + 2.0 * M_PI), (2.0 * M_PI)))};
-}
-
-/**
- Given the distance along the line from the label anchor to the beginning of the current segment,
- project a "virtual anchor" point at the same distance along the line extending out from this segment.
-
- B <-- beginning of current segment
-* . . . . . . . *--------* E <-- end of current segment
-VA |
- / VA = "virtual segment anchor"
- /
- ---*-----`
- A = label anchor
-
- Distance _along line_ from A to B == straight-line distance from VA to B.
- */
-inline Point<float> getVirtualSegmentAnchor(const Point<float>& segmentBegin, const Point<float>& segmentEnd, float distanceFromAnchorToSegmentBegin) {
- Point<float> segmentDirectionUnitVector = util::normal<float>(segmentBegin, segmentEnd);
- return segmentBegin - (segmentDirectionUnitVector * distanceFromAnchorToSegmentBegin);
+ return SymbolQuad { tl, tr, bl, br, textureRect, shapedText.writingMode, { 0.0f, 0.0f } };
}
-/*
- Given the segment joining `segmentAnchor` and `segmentEnd` and a desired offset
- `glyphDistanceFromAnchor` at which a glyph is to be placed, calculate the minimum
- "scale" at which the glyph will fall on the segment (i.e., not past the end)
-
- "Scale" here refers to the ratio between the *rendered* zoom level and the text-layout
- zoom level, which is 1 + (source tile's zoom level). `glyphDistanceFromAnchor`, although
- passed in units consistent with the text-layout zoom level, is based on text size. So
- when the tile is being rendered at z < text-layout zoom, the glyph's actual distance from
- the anchor is larger relative to the segment's length than at layout time:
-
-
- GLYPH
- z == layout-zoom, scale == 1: segmentAnchor *--------------^-------------* segmentEnd
- z == layout-zoom - 1, scale == 0.5: segmentAnchor *--------------^* segmentEnd
-
- <-------------->
- Anchor-to-glyph distance stays visually fixed,
- so it changes relative to the segment.
-*/
-inline float getMinScaleForSegment(const float glyphDistanceFromAnchor,
- const Point<float>& segmentAnchor,
- const Point<float>& segmentEnd) {
- const auto distanceFromAnchorToEnd = util::dist<float>(segmentAnchor, segmentEnd);
- return glyphDistanceFromAnchor / distanceFromAnchorToEnd;
-}
-
-inline Point<float> getSegmentEnd(const bool glyphIsLogicallyForward,
- const GeometryCoordinates& line,
- const size_t segmentIndex) {
- return convertPoint<float>(glyphIsLogicallyForward ? line[segmentIndex+1] : line[segmentIndex]);
-}
-
-optional<VirtualSegment> getNextVirtualSegment(const VirtualSegment& previousVirtualSegment,
- const GeometryCoordinates& line,
- const float glyphDistanceFromAnchor,
- const bool glyphIsLogicallyForward) {
- auto nextSegmentBegin = previousVirtualSegment.end;
-
- auto end = nextSegmentBegin;
- size_t index = previousVirtualSegment.index;
-
- // skip duplicate nodes
- while (end == nextSegmentBegin) {
- // look ahead by 2 points in the line because the segment index refers to the beginning
- // of the segment, and we need an endpoint too
- if (glyphIsLogicallyForward && (index + 2 < line.size())) {
- index += 1;
- } else if (!glyphIsLogicallyForward && index != 0) {
- index -= 1;
- } else {
- return {};
- }
-
- end = getSegmentEnd(glyphIsLogicallyForward, line, index);
- }
-
- const auto anchor = getVirtualSegmentAnchor(nextSegmentBegin, end,
- util::dist<float>(previousVirtualSegment.anchor,
- previousVirtualSegment.end));
- return VirtualSegment {
- anchor,
- end,
- index,
- getMinScaleForSegment(glyphDistanceFromAnchor, anchor, end),
- previousVirtualSegment.minScale
- };
-}
-
-/*
- Given (1) a glyph positioned relative to an anchor point and (2) a line to follow,
- calculates which segment of the line the glyph will fall on for each possible
- scale range, and for each range produces a "virtual" anchor point and an angle that will
- place the glyph on the right segment and rotated to the correct angle.
-
- Because one glyph quad is made ahead of time for each possible orientation, the
- symbol_sdf shader can quickly handle changing layout as we zoom in and out
-
- If the "keepUpright" property is set, we call getLineGlyphs twice (once upright and
- once "upside down"). This will generate two sets of glyphs following the line in opposite
- directions. Later, SymbolLayout::place will look at the glyphs and based on the placement
- angle determine if their original anchor was "upright" or not -- based on that, it throws
- away one set of glyphs or the other (this work has to be done in the CPU, but it's just a
- filter so it's fast)
- */
-void getLineGlyphs(std::back_insert_iterator<GlyphInstances> glyphs,
- Anchor& anchor,
- float glyphHorizontalOffsetFromAnchor,
- const GeometryCoordinates& line,
- size_t anchorSegment,
- bool upsideDown) {
- assert(line.size() > anchorSegment+1);
-
- // This is true if the glyph is "logically forward" of the anchor point, based on the ordering of line segments
- // The actual angle of the line is irrelevant
- // If "upsideDown" is set, everything is flipped
- const bool glyphIsLogicallyForward = (glyphHorizontalOffsetFromAnchor >= 0) ^ upsideDown;
- const float glyphDistanceFromAnchor = std::fabs(glyphHorizontalOffsetFromAnchor);
-
- const auto initialSegmentEnd = getSegmentEnd(glyphIsLogicallyForward, line, anchorSegment);
- VirtualSegment virtualSegment = {
- anchor.point,
- initialSegmentEnd,
- anchorSegment,
- getMinScaleForSegment(glyphDistanceFromAnchor, anchor.point, initialSegmentEnd),
- std::numeric_limits<float>::infinity()
- };
-
- while (true) {
- insertSegmentGlyph(glyphs,
- virtualSegment,
- glyphIsLogicallyForward,
- upsideDown);
-
- if (virtualSegment.minScale <= anchor.scale) {
- // No need to calculate below the scale where the label starts showing
- return;
- }
-
- optional<VirtualSegment> nextVirtualSegment = getNextVirtualSegment(virtualSegment,
- line,
- glyphDistanceFromAnchor,
- glyphIsLogicallyForward);
- if (!nextVirtualSegment) {
- // There are no more segments, so we can't fit this glyph on the line at a lower scale
- // This implies we can't show the label at all at lower scale, so we update the anchor's min scale
- anchor.scale = virtualSegment.minScale;
- return;
- } else {
- virtualSegment = *nextVirtualSegment;
- }
- }
-
-}
-
-SymbolQuads getGlyphQuads(Anchor& anchor,
- const Shaping& shapedText,
- const float boxScale,
- const GeometryCoordinates& line,
+SymbolQuads getGlyphQuads(const Shaping& shapedText,
const SymbolLayoutProperties::Evaluated& layout,
const style::SymbolPlacementType placement,
const GlyphPositionMap& positions) {
const float textRotate = layout.get<TextRotate>() * util::DEG2RAD;
- const bool keepUpright = layout.get<TextKeepUpright>();
+ const std::array<float, 2> textOffset = layout.get<TextOffset>();
SymbolQuads quads;
@@ -320,67 +107,55 @@ SymbolQuads getGlyphQuads(Anchor& anchor,
const GlyphPosition& glyph = positionsIt->second;
const Rect<uint16_t>& rect = glyph.rect;
- const float centerX = (positionedGlyph.x + glyph.metrics.advance / 2.0f) * boxScale;
-
- GlyphInstances glyphInstances;
- if (placement == style::SymbolPlacementType::Line) {
- getLineGlyphs(std::back_inserter(glyphInstances), anchor, centerX, line, anchor.segment, false);
- if (keepUpright)
- getLineGlyphs(std::back_inserter(glyphInstances), anchor, centerX, line, anchor.segment, true);
- } else {
- glyphInstances.emplace_back(GlyphInstance{anchor.point});
- }
// The rects have an addditional buffer that is not included in their size;
const float glyphPadding = 1.0f;
const float rectBuffer = 3.0f + glyphPadding;
- const float x1 = positionedGlyph.x + glyph.metrics.left - rectBuffer;
- const float y1 = positionedGlyph.y - glyph.metrics.top - rectBuffer;
+ const float halfAdvance = glyph.metrics.advance / 2.0;
+ const bool alongLine = placement == style::SymbolPlacementType::Line;
+
+ const Point<float> glyphOffset = alongLine ?
+ Point<float>{ positionedGlyph.x + halfAdvance, positionedGlyph.y } :
+ Point<float>{ 0.0f, 0.0f };
+
+ const Point<float> builtInOffset = alongLine ?
+ Point<float>{ 0.0f, 0.0f } :
+ Point<float>{ positionedGlyph.x + halfAdvance + textOffset[0], positionedGlyph.y + textOffset[1] };
+
+
+ const float x1 = glyph.metrics.left - rectBuffer - halfAdvance + builtInOffset.x;
+ const float y1 = glyph.metrics.top - rectBuffer + builtInOffset.y;
const float x2 = x1 + rect.w;
const float y2 = y1 + rect.h;
- const Point<float> center{positionedGlyph.x, static_cast<float>(static_cast<float>(glyph.metrics.advance) / 2.0)};
+ const Point<float> center{builtInOffset.x - halfAdvance, static_cast<float>(static_cast<float>(glyph.metrics.advance) / 2.0)};
- Point<float> otl{x1, y1};
- Point<float> otr{x2, y1};
- Point<float> obl{x1, y2};
- Point<float> obr{x2, y2};
+ Point<float> tl{x1, y1};
+ Point<float> tr{x2, y1};
+ Point<float> bl{x1, y2};
+ Point<float> br{x2, y2};
if (positionedGlyph.angle != 0) {
- otl = util::rotate(otl - center, positionedGlyph.angle) + center;
- otr = util::rotate(otr - center, positionedGlyph.angle) + center;
- obl = util::rotate(obl - center, positionedGlyph.angle) + center;
- obr = util::rotate(obr - center, positionedGlyph.angle) + center;
+ tl = util::rotate(tl - center, positionedGlyph.angle) + center;
+ tr = util::rotate(tr - center, positionedGlyph.angle) + center;
+ bl = util::rotate(bl - center, positionedGlyph.angle) + center;
+ br = util::rotate(br - center, positionedGlyph.angle) + center;
}
- for (const GlyphInstance &instance : glyphInstances) {
- Point<float> tl = otl;
- Point<float> tr = otr;
- Point<float> bl = obl;
- Point<float> br = obr;
+ if (textRotate) {
+ // Compute the transformation matrix.
+ float angle_sin = std::sin(textRotate);
+ float angle_cos = std::cos(textRotate);
+ std::array<float, 4> matrix = {{angle_cos, -angle_sin, angle_sin, angle_cos}};
- if (textRotate) {
- // Compute the transformation matrix.
- float angle_sin = std::sin(textRotate);
- float angle_cos = std::cos(textRotate);
- std::array<float, 4> matrix = {{angle_cos, -angle_sin, angle_sin, angle_cos}};
-
- tl = util::matrixMultiply(matrix, tl);
- tr = util::matrixMultiply(matrix, tr);
- bl = util::matrixMultiply(matrix, bl);
- br = util::matrixMultiply(matrix, br);
- }
-
- // Prevent label from extending past the end of the line
- const float glyphMinScale = std::max(instance.minScale, anchor.scale);
-
- // All the glyphs for a label are tagged with either the "right side up" or "upside down" anchor angle,
- // which is used at placement time to determine which set to show
- const float anchorAngle = std::fmod((anchor.angle + (instance.upsideDown ? M_PI : 0.0) + 2 * M_PI), (2 * M_PI));
- const float glyphAngle = std::fmod((instance.angle + (instance.upsideDown ? M_PI : 0.0) + 2 * M_PI), (2 * M_PI));
- quads.emplace_back(tl, tr, bl, br, rect, anchorAngle, glyphAngle, instance.anchorPoint, glyphMinScale, instance.maxScale, shapedText.writingMode);
+ tl = util::matrixMultiply(matrix, tl);
+ tr = util::matrixMultiply(matrix, tr);
+ bl = util::matrixMultiply(matrix, bl);
+ br = util::matrixMultiply(matrix, br);
}
+
+ quads.emplace_back(tl, tr, bl, br, rect, shapedText.writingMode, glyphOffset);
}
return quads;
diff --git a/src/mbgl/text/quads.hpp b/src/mbgl/text/quads.hpp
index b29f6b0ad3..33d003c935 100644
--- a/src/mbgl/text/quads.hpp
+++ b/src/mbgl/text/quads.hpp
@@ -19,50 +19,33 @@ public:
Point<float> bl_,
Point<float> br_,
Rect<uint16_t> tex_,
- float anchorAngle_,
- float glyphAngle_,
- Point<float> anchorPoint_,
- float minScale_,
- float maxScale_,
- WritingModeType writingMode_)
+ WritingModeType writingMode_,
+ Point<float> glyphOffset_)
: tl(std::move(tl_)),
tr(std::move(tr_)),
bl(std::move(bl_)),
br(std::move(br_)),
tex(std::move(tex_)),
- anchorAngle(anchorAngle_),
- glyphAngle(glyphAngle_),
- anchorPoint(std::move(anchorPoint_)),
- minScale(minScale_),
- maxScale(maxScale_),
- writingMode(writingMode_) {}
+ writingMode(writingMode_),
+ glyphOffset(glyphOffset_) {}
Point<float> tl;
Point<float> tr;
Point<float> bl;
Point<float> br;
Rect<uint16_t> tex;
- float anchorAngle, glyphAngle;
- Point<float> anchorPoint;
- float minScale;
- float maxScale;
WritingModeType writingMode;
+ Point<float> glyphOffset;
};
using SymbolQuads = std::vector<SymbolQuad>;
-SymbolQuad getIconQuad(const Anchor& anchor,
- const PositionedIcon& shapedIcon,
- const GeometryCoordinates& line,
+SymbolQuad getIconQuad(const PositionedIcon& shapedIcon,
const style::SymbolLayoutProperties::Evaluated&,
const float layoutTextSize,
- style::SymbolPlacementType placement,
const Shaping& shapedText);
-SymbolQuads getGlyphQuads(Anchor& anchor,
- const Shaping& shapedText,
- const float boxScale,
- const GeometryCoordinates& line,
+SymbolQuads getGlyphQuads(const Shaping& shapedText,
const style::SymbolLayoutProperties::Evaluated&,
style::SymbolPlacementType placement,
const GlyphPositionMap& positions);