@@ -628,14 +628,16 @@ private static List<GlyphLayout> LayoutLineVertical(
628628
629629 for ( int k = i ; k < textLine . Count ; k ++ )
630630 {
631- if ( textLine [ k ] . IsTransformed )
631+ TextLine . GlyphLayoutData g = textLine [ k ] ;
632+
633+ if ( g . GraphemeIndex != graphemeIndex )
632634 {
633- currentGraphemeIsTransformed = true ;
634635 break ;
635636 }
636637
637- if ( textLine [ k ] . IsLastInGrapheme )
638+ if ( g . IsTransformed )
638639 {
640+ currentGraphemeIsTransformed = true ;
639641 break ;
640642 }
641643 }
@@ -654,10 +656,15 @@ private static List<GlyphLayout> LayoutLineVertical(
654656 float minX = float . PositiveInfinity ;
655657 float maxX = float . NegativeInfinity ;
656658
657- for ( int k = i ; k < textLine . Count && textLine [ k ] . GraphemeIndex == graphemeIndex ; k ++ )
659+ for ( int k = i ; k < textLine . Count ; k ++ )
658660 {
659661 TextLine . GlyphLayoutData g = textLine [ k ] ;
660662
663+ if ( g . GraphemeIndex != graphemeIndex )
664+ {
665+ break ;
666+ }
667+
661668 foreach ( GlyphMetrics m in g . Metrics )
662669 {
663670 Vector2 s = new Vector2 ( g . PointSize ) / m . ScaleFactor ;
@@ -675,11 +682,6 @@ private static List<GlyphLayout> LayoutLineVertical(
675682 maxX = glyphMaxX ;
676683 }
677684 }
678-
679- if ( g . IsLastInGrapheme )
680- {
681- break ;
682- }
683685 }
684686
685687 float inkWidth = maxX - minX ;
@@ -715,13 +717,22 @@ private static List<GlyphLayout> LayoutLineVertical(
715717 // Offset our in both directions to account for horizontal ink centering and vertical baseline centering.
716718 Vector2 offset = new ( alignX , ( metric . Bounds . Max . Y + metric . TopSideBearing ) * scale . Y ) ;
717719
718- // For transformed glyphs we advance horizontally using the horizontal advance not the line height.
720+ float advanceW = advanceX ;
721+
722+ if ( currentGraphemeIsTransformed && ! isFirstInGrapheme )
723+ {
724+ // For transformed glyphs after the first in the grapheme we advance
725+ // horizontally using the horizontal advance not the line height.
726+ // This gives us the correct total advance across the grapheme.
727+ advanceW = scale . X * metric . AdvanceWidth ;
728+ }
729+
719730 glyphs . Add ( new GlyphLayout (
720731 new Glyph ( metric , data . PointSize ) ,
721732 boxLocation ,
722733 penLocation + new Vector2 ( ( scaledMaxLineHeight - data . ScaledLineHeight ) * .5F , 0 ) ,
723734 offset ,
724- currentGraphemeIsTransformed ? scale . X * metric . AdvanceWidth : advanceX ,
735+ advanceW ,
725736 data . ScaledAdvance + yExtraAdvance ,
726737 GlyphLayoutMode . Vertical ,
727738 i == 0 && j == 0 ,
@@ -1024,7 +1035,7 @@ private static bool DoFontRun(
10241035 charIndex += charsConsumed ;
10251036
10261037 // Get the glyph id for the codepoint and add to the collection.
1027- font . FontMetrics . TryGetGlyphId ( current , next , out ushort glyphId , out skipNextCodePoint ) ;
1038+ _ = font . FontMetrics . TryGetGlyphId ( current , next , out ushort glyphId , out skipNextCodePoint ) ;
10281039 substitutions . AddGlyph ( glyphId , current , ( TextDirection ) bidiRuns [ bidiRunIndex ] . Direction , textRuns [ textRunIndex ] , codePointIndex ) ;
10291040
10301041 codePointIndex ++ ;
@@ -1156,8 +1167,7 @@ private static TextBox BreakLines(
11561167 //
11571168 // Note: Not all glyphs in a font will have a codepoint associated with them. e.g. most compositions, ligatures, etc.
11581169 CodePoint codePoint = codePointEnumerator . Current ;
1159- if ( isSubstituted &&
1160- metrics . Count == 1 )
1170+ if ( isSubstituted && metrics . Count == 1 )
11611171 {
11621172 codePoint = glyph . CodePoint ;
11631173 }
@@ -1302,11 +1312,14 @@ VerticalOrientationType.Rotate or
13021312 }
13031313 }
13041314
1305- bool isLastInGrapheme = graphemeCodePointIndex = = CodePoint . GetCodePointCount ( grapheme ) - 1 ;
1315+ int graphemeCodePointMax = CodePoint . GetCodePointCount ( grapheme ) - 1 ;
13061316
13071317 // For non-decomposed glyphs the length is always 1.
13081318 for ( int i = 0 ; i < decomposedAdvances . Length ; i ++ )
13091319 {
1320+ // Determine if this is the last codepoint in the grapheme.
1321+ bool isLastInGrapheme = graphemeCodePointIndex == graphemeCodePointMax && i == decomposedAdvances . Length - 1 ;
1322+
13101323 float decomposedAdvance = decomposedAdvances [ i ] ;
13111324
13121325 // Work out the scaled metrics for the glyph.
0 commit comments