@@ -68,91 +68,96 @@ SymbolQuads getGlyphQuads(const Shaping& shapedText,
6868
6969 SymbolQuads quads;
7070
71- for (const PositionedGlyph &positionedGlyph: shapedText.positionedGlyphs ) {
72- auto fontPositions = positions.find (positionedGlyph.font );
73- if (fontPositions == positions.end ())
74- continue ;
75-
76- auto positionsIt = fontPositions->second .glyphPositionMap .find (positionedGlyph.glyph );
77- if (positionsIt == fontPositions->second .glyphPositionMap .end ()) {
78- continue ;
71+ if (shapedText.lineCount == 0 ) return quads;
72+ const float lineHeight = (std::fabs (shapedText.bottom ) + std::fabs (shapedText.top )) / shapedText.lineCount ;
73+ for (const auto & positionedGlyphs : shapedText.positionedGlyphs ) {
74+ const float currentHeight = lineHeight * positionedGlyphs.first ;
75+ for (const PositionedGlyph& positionedGlyph : positionedGlyphs.second ) {
76+ auto fontPositions = positions.find (positionedGlyph.font );
77+ if (fontPositions == positions.end ()) continue ;
78+
79+ auto positionsIt = fontPositions->second .glyphPositionMap .find (positionedGlyph.glyph );
80+ if (positionsIt == fontPositions->second .glyphPositionMap .end ()) {
81+ continue ;
82+ }
83+
84+ const GlyphPosition& glyph = positionsIt->second ;
85+ const Rect<uint16_t >& rect = glyph.rect ;
86+
87+ // The rects have an additional buffer that is not included in their size;
88+ const float glyphPadding = 1 .0f ;
89+ const float rectBuffer = 3 .0f + glyphPadding;
90+
91+ const float halfAdvance = glyph.metrics .advance * positionedGlyph.scale / 2.0 ;
92+
93+ const Point<float > glyphOffset =
94+ alongLine ? Point<float >{positionedGlyph.x + halfAdvance, positionedGlyph.y } : Point<float >{0 .0f , 0 .0f };
95+
96+ Point<float > builtInOffset = alongLine ? Point<float >{0 .0f , 0 .0f }
97+ : Point<float >{positionedGlyph.x + halfAdvance + textOffset[0 ],
98+ positionedGlyph.y + textOffset[1 ]};
99+
100+ Point<float > verticalizedLabelOffset = {0 .0f , 0 .0f };
101+ const bool rotateVerticalGlyph = (alongLine || allowVerticalPlacement) && positionedGlyph.vertical ;
102+ if (rotateVerticalGlyph) {
103+ // Vertical POI labels, that are rotated 90deg CW and whose glyphs must preserve upright orientation
104+ // need to be rotated 90deg CCW. After quad is rotated, it is translated to the original built-in
105+ // offset.
106+ verticalizedLabelOffset = builtInOffset;
107+ builtInOffset = {0 .0f , 0 .0f };
108+ }
109+
110+ const float x1 = (glyph.metrics .left - rectBuffer) * positionedGlyph.scale - halfAdvance + builtInOffset.x ;
111+ const float y1 = (-glyph.metrics .top - rectBuffer) * positionedGlyph.scale + builtInOffset.y ;
112+ const float x2 = x1 + rect.w * positionedGlyph.scale ;
113+ const float y2 = y1 + rect.h * positionedGlyph.scale ;
114+
115+ Point<float > tl{x1, y1};
116+ Point<float > tr{x2, y1};
117+ Point<float > bl{x1, y2};
118+ Point<float > br{x2, y2};
119+
120+ if (rotateVerticalGlyph) {
121+ // Vertical-supporting glyphs are laid out in 24x24 point boxes (1 square em)
122+ // In horizontal orientation, the y values for glyphs are below the midline.
123+ // If the glyph's baseline is applicable, we take the relative y offset of the
124+ // glyph, which needs to erase out current line height that added to the glyphs.
125+ // Otherwise, we use a "yOffset" of -17 to pull them up to the middle.
126+ // By rotating counter-clockwise around the point at the center of the left
127+ // edge of a 24x24 layout box centered below the midline, we align the center
128+ // of the glyphs with the horizontal midline, so the yOffset is no longer
129+ // necessary, but we also pull the glyph to the left along the x axis.
130+ // The y coordinate includes baseline yOffset, therefore, needs to be accounted
131+ // for when glyph is rotated and translated.
132+ const float yShift = (shapedText.hasBaseline ? (positionedGlyph.y - currentHeight) : Shaping::yOffset);
133+ const Point<float > center{-halfAdvance, halfAdvance - yShift};
134+ const float verticalRotation = -M_PI_2;
135+
136+ // xHalfWidhtOffsetcorrection is a difference between full-width and half-width
137+ // advance, should be 0 for full-width glyphs and will pull up half-width glyphs.
138+ const float xHalfWidhtOffsetcorrection = util::ONE_EM / 2 - halfAdvance;
139+ const Point<float > xOffsetCorrection{5 .0f - yShift - xHalfWidhtOffsetcorrection, 0 .0f };
140+
141+ tl = util::rotate (tl - center, verticalRotation) + center + xOffsetCorrection + verticalizedLabelOffset;
142+ tr = util::rotate (tr - center, verticalRotation) + center + xOffsetCorrection + verticalizedLabelOffset;
143+ bl = util::rotate (bl - center, verticalRotation) + center + xOffsetCorrection + verticalizedLabelOffset;
144+ br = util::rotate (br - center, verticalRotation) + center + xOffsetCorrection + verticalizedLabelOffset;
145+ }
146+
147+ if (textRotate) {
148+ // Compute the transformation matrix.
149+ float angle_sin = std::sin (textRotate);
150+ float angle_cos = std::cos (textRotate);
151+ std::array<float , 4 > matrix = {{angle_cos, -angle_sin, angle_sin, angle_cos}};
152+
153+ tl = util::matrixMultiply (matrix, tl);
154+ tr = util::matrixMultiply (matrix, tr);
155+ bl = util::matrixMultiply (matrix, bl);
156+ br = util::matrixMultiply (matrix, br);
157+ }
158+
159+ quads.emplace_back (tl, tr, bl, br, rect, shapedText.writingMode , glyphOffset, positionedGlyph.sectionIndex );
79160 }
80-
81- const GlyphPosition& glyph = positionsIt->second ;
82- const Rect<uint16_t >& rect = glyph.rect ;
83-
84- // The rects have an additional buffer that is not included in their size;
85- const float glyphPadding = 1 .0f ;
86- const float rectBuffer = 3 .0f + glyphPadding;
87-
88- const float halfAdvance = glyph.metrics .advance * positionedGlyph.scale / 2.0 ;
89-
90- const Point<float > glyphOffset = alongLine ?
91- Point<float >{ positionedGlyph.x + halfAdvance, positionedGlyph.y } :
92- Point<float >{ 0 .0f , 0 .0f };
93-
94- Point<float > builtInOffset = alongLine ?
95- Point<float >{ 0 .0f , 0 .0f } :
96- Point<float >{ positionedGlyph.x + halfAdvance + textOffset[0 ], positionedGlyph.y + textOffset[1 ] };
97-
98- Point<float > verticalizedLabelOffset = { 0 .0f , 0 .0f };
99- const bool rotateVerticalGlyph = (alongLine || allowVerticalPlacement) && positionedGlyph.vertical ;
100- if (rotateVerticalGlyph) {
101- // Vertical POI labels, that are rotated 90deg CW and whose glyphs must preserve upright orientation
102- // need to be rotated 90deg CCW. After quad is rotated, it is translated to the original built-in offset.
103- verticalizedLabelOffset = builtInOffset;
104- builtInOffset = { 0 .0f , 0 .0f };
105- }
106-
107- const float x1 = (glyph.metrics .left - rectBuffer) * positionedGlyph.scale - halfAdvance + builtInOffset.x ;
108- const float y1 = (-glyph.metrics .top - rectBuffer) * positionedGlyph.scale + builtInOffset.y ;
109- const float x2 = x1 + rect.w * positionedGlyph.scale ;
110- const float y2 = y1 + rect.h * positionedGlyph.scale ;
111-
112- Point<float > tl{x1, y1};
113- Point<float > tr{x2, y1};
114- Point<float > bl{x1, y2};
115- Point<float > br{x2, y2};
116-
117- if (rotateVerticalGlyph) {
118- // Vertical-supporting glyphs are laid out in 24x24 point boxes (1 square em)
119- // In horizontal orientation, the y values for glyphs are below the midline.
120- // If the glyph's baseline is applicable, we take the y value of the glyph.
121- // Otherwise, we use a "yOffset" of -17 to pull them up to the middle.
122- // By rotating counter-clockwise around the point at the center of the left
123- // edge of a 24x24 layout box centered below the midline, we align the center
124- // of the glyphs with the horizontal midline, so the yOffset is no longer
125- // necessary, but we also pull the glyph to the left along the x axis.
126- // The y coordinate includes baseline yOffset, therefore, needs to be accounted
127- // for when glyph is rotated and translated.
128- const float yShift = (shapedText.hasBaseline ? positionedGlyph.y : Shaping::yOffset);
129- const Point<float > center{-halfAdvance, halfAdvance - yShift};
130- const float verticalRotation = -M_PI_2;
131-
132- // xHalfWidhtOffsetcorrection is a difference between full-width and half-width
133- // advance, should be 0 for full-width glyphs and will pull up half-width glyphs.
134- const float xHalfWidhtOffsetcorrection = util::ONE_EM / 2 - halfAdvance;
135- const Point<float > xOffsetCorrection{5 .0f - yShift - xHalfWidhtOffsetcorrection, 0 .0f };
136-
137- tl = util::rotate (tl - center, verticalRotation) + center + xOffsetCorrection + verticalizedLabelOffset;
138- tr = util::rotate (tr - center, verticalRotation) + center + xOffsetCorrection + verticalizedLabelOffset;
139- bl = util::rotate (bl - center, verticalRotation) + center + xOffsetCorrection + verticalizedLabelOffset;
140- br = util::rotate (br - center, verticalRotation) + center + xOffsetCorrection + verticalizedLabelOffset;
141- }
142-
143- if (textRotate) {
144- // Compute the transformation matrix.
145- float angle_sin = std::sin (textRotate);
146- float angle_cos = std::cos (textRotate);
147- std::array<float , 4 > matrix = {{angle_cos, -angle_sin, angle_sin, angle_cos}};
148-
149- tl = util::matrixMultiply (matrix, tl);
150- tr = util::matrixMultiply (matrix, tr);
151- bl = util::matrixMultiply (matrix, bl);
152- br = util::matrixMultiply (matrix, br);
153- }
154-
155- quads.emplace_back (tl, tr, bl, br, rect, shapedText.writingMode , glyphOffset, positionedGlyph.sectionIndex );
156161 }
157162
158163 return quads;
0 commit comments