diff --git a/src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs b/src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs index 35ada3c7ee..a518e2ffb8 100644 --- a/src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs +++ b/src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs @@ -536,6 +536,11 @@ namespace Avalonia.Media.TextFormatting endX += currentRun.Size.Width; } + if(currentPosition < firstTextSourceCharacterIndex) + { + startX += currentRun.Size.Width; + } + currentPosition += currentRun.TextSourceLength; break; @@ -590,10 +595,10 @@ namespace Avalonia.Media.TextFormatting public TextLineImpl FinalizeLine() { - BidiReorder(); - _textLineMetrics = CreateLineMetrics(); + BidiReorder(); + return this; } @@ -1068,41 +1073,11 @@ namespace Avalonia.Media.TextFormatting } } - switch (_paragraphProperties.FlowDirection) + if (index == _textRuns.Count - 1) { - case FlowDirection.LeftToRight: - { - if (index == _textRuns.Count - 1) - { - width = widthIncludingWhitespace + textRun.GlyphRun.Metrics.Width; - trailingWhitespaceLength = textRun.GlyphRun.Metrics.TrailingWhitespaceLength; - newLineLength = textRun.GlyphRun.Metrics.NewlineLength; - } - - break; - } - - case FlowDirection.RightToLeft: - { - if (index == _textRuns.Count - 1) - { - var firstRun = _textRuns[0]; - - if (firstRun is ShapedTextCharacters shapedTextCharacters) - { - var offset = shapedTextCharacters.GlyphRun.Metrics.WidthIncludingTrailingWhitespace - - shapedTextCharacters.GlyphRun.Metrics.Width; - - width = widthIncludingWhitespace + - textRun.GlyphRun.Metrics.WidthIncludingTrailingWhitespace - offset; - - trailingWhitespaceLength = shapedTextCharacters.GlyphRun.Metrics.TrailingWhitespaceLength; - newLineLength = shapedTextCharacters.GlyphRun.Metrics.NewlineLength; - } - } - - break; - } + width = widthIncludingWhitespace + textRun.GlyphRun.Metrics.Width; + trailingWhitespaceLength = textRun.GlyphRun.Metrics.TrailingWhitespaceLength; + newLineLength = textRun.GlyphRun.Metrics.NewlineLength; } widthIncludingWhitespace += textRun.GlyphRun.Metrics.WidthIncludingTrailingWhitespace; diff --git a/src/Skia/Avalonia.Skia/TextShaperImpl.cs b/src/Skia/Avalonia.Skia/TextShaperImpl.cs index ebaa247da8..908b0ffa47 100644 --- a/src/Skia/Avalonia.Skia/TextShaperImpl.cs +++ b/src/Skia/Avalonia.Skia/TextShaperImpl.cs @@ -27,7 +27,7 @@ namespace Avalonia.Skia buffer.GuessSegmentProperties(); - buffer.Direction = (bidiLevel & 1) == 0 ? Direction.LeftToRight : Direction.RightToLeft; + buffer.Direction = Direction.LeftToRight; //Always shape LeftToRight buffer.Language = new Language(culture ?? CultureInfo.CurrentCulture); @@ -35,11 +35,6 @@ namespace Avalonia.Skia font.Shape(buffer); - if (buffer.Direction == Direction.RightToLeft) - { - buffer.Reverse(); - } - font.GetScale(out var scaleX, out _); var textScale = fontRenderingEmSize / scaleX; diff --git a/src/Windows/Avalonia.Direct2D1/Media/TextShaperImpl.cs b/src/Windows/Avalonia.Direct2D1/Media/TextShaperImpl.cs index 59027a663f..f4e4b00147 100644 --- a/src/Windows/Avalonia.Direct2D1/Media/TextShaperImpl.cs +++ b/src/Windows/Avalonia.Direct2D1/Media/TextShaperImpl.cs @@ -1,6 +1,5 @@ using System; using System.Globalization; -using Avalonia.Media; using Avalonia.Media.TextFormatting; using Avalonia.Media.TextFormatting.Unicode; using Avalonia.Platform; @@ -11,8 +10,7 @@ using GlyphInfo = HarfBuzzSharp.GlyphInfo; namespace Avalonia.Direct2D1.Media { - -internal class TextShaperImpl : ITextShaperImpl + internal class TextShaperImpl : ITextShaperImpl { public ShapedBuffer ShapeText(ReadOnlySlice text, TextShaperOptions options) { @@ -23,25 +21,20 @@ internal class TextShaperImpl : ITextShaperImpl using (var buffer = new Buffer()) { - buffer.AddUtf16(text.Buffer.Span, text.Start, text.Length); + buffer.AddUtf16(text.Buffer.Span, text.BufferOffset, text.Length); MergeBreakPair(buffer); - + buffer.GuessSegmentProperties(); - buffer.Direction = (bidiLevel & 1) == 0 ? Direction.LeftToRight : Direction.RightToLeft; + buffer.Direction = Direction.LeftToRight; //Always shape LeftToRight - buffer.Language = new Language(culture ?? CultureInfo.CurrentCulture); + buffer.Language = new Language(culture ?? CultureInfo.CurrentCulture); var font = ((GlyphTypefaceImpl)typeface.PlatformImpl).Font; font.Shape(buffer); - if (buffer.Direction == Direction.RightToLeft) - { - buffer.Reverse(); - } - font.GetScale(out var scaleX, out _); var textScale = fontRenderingEmSize / scaleX; @@ -60,13 +53,13 @@ internal class TextShaperImpl : ITextShaperImpl var glyphIndex = (ushort)sourceInfo.Codepoint; - var glyphCluster = (int)sourceInfo.Cluster; + var glyphCluster = (int)(sourceInfo.Cluster); var glyphAdvance = GetGlyphAdvance(glyphPositions, i, textScale); var glyphOffset = GetGlyphOffset(glyphPositions, i, textScale); - if (glyphIndex == 0 && text[glyphCluster] == '\t') + if (glyphIndex == 0 && text.Buffer.Span[glyphCluster] == '\t') { glyphIndex = typeface.GetGlyph(' '); @@ -75,9 +68,7 @@ internal class TextShaperImpl : ITextShaperImpl 4 * typeface.GetGlyphAdvance(glyphIndex) * textScale; } - var targetInfo = - new Avalonia.Media.TextFormatting.GlyphInfo(glyphIndex, glyphCluster, glyphAdvance, - glyphOffset); + var targetInfo = new Avalonia.Media.TextFormatting.GlyphInfo(glyphIndex, glyphCluster, glyphAdvance, glyphOffset); shapedBuffer[i] = targetInfo; } @@ -91,7 +82,7 @@ internal class TextShaperImpl : ITextShaperImpl var length = buffer.Length; var glyphInfos = buffer.GetGlyphInfoSpan(); - + var second = glyphInfos[length - 1]; if (!new Codepoint((int)second.Codepoint).IsBreakChar) @@ -102,7 +93,7 @@ internal class TextShaperImpl : ITextShaperImpl if (length > 1 && glyphInfos[length - 2].Codepoint == '\r' && second.Codepoint == '\n') { var first = glyphInfos[length - 2]; - + first.Codepoint = '\u200C'; second.Codepoint = '\u200C'; second.Cluster = first.Cluster; @@ -113,7 +104,7 @@ internal class TextShaperImpl : ITextShaperImpl { *p = first; } - + fixed (GlyphInfo* p = &glyphInfos[length - 1]) { *p = second; @@ -148,7 +139,7 @@ internal class TextShaperImpl : ITextShaperImpl private static double GetGlyphAdvance(ReadOnlySpan glyphPositions, int index, double textScale) { // Depends on direction of layout - // advanceBuffer[index] = buffer.GlyphPositions[index].YAdvance * textScale; + // glyphPositions[index].YAdvance * textScale; return glyphPositions[index].XAdvance * textScale; } } diff --git a/tests/TestFiles/Direct2D1/Controls/TextBlock/RestrictedHeight_VerticalAlign.expected.png b/tests/TestFiles/Direct2D1/Controls/TextBlock/RestrictedHeight_VerticalAlign.expected.png index edd4dfd263..e8624fa457 100644 Binary files a/tests/TestFiles/Direct2D1/Controls/TextBlock/RestrictedHeight_VerticalAlign.expected.png and b/tests/TestFiles/Direct2D1/Controls/TextBlock/RestrictedHeight_VerticalAlign.expected.png differ diff --git a/tests/TestFiles/Skia/Controls/TextBlock/RestrictedHeight_VerticalAlign.expected.png b/tests/TestFiles/Skia/Controls/TextBlock/RestrictedHeight_VerticalAlign.expected.png index a76c6a5b2a..7bd622050e 100644 Binary files a/tests/TestFiles/Skia/Controls/TextBlock/RestrictedHeight_VerticalAlign.expected.png and b/tests/TestFiles/Skia/Controls/TextBlock/RestrictedHeight_VerticalAlign.expected.png differ