diff --git a/src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs b/src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs index 31cddd7bf4..3a4e83663a 100644 --- a/src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs +++ b/src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs @@ -1415,10 +1415,12 @@ namespace Avalonia.Media.TextFormatting } var width = widthIncludingWhitespace; + var isRtl = _paragraphProperties.FlowDirection == FlowDirection.RightToLeft; - for (var i = _textRuns.Length - 1; i >= 0; i--) + for (int i = 0; i < _textRuns.Length; i++) { - var currentRun = _textRuns[i]; + var index = isRtl ? i : _textRuns.Length - 1 - i; + var currentRun = _textRuns[index]; if (currentRun is ShapedTextRun shapedText) { diff --git a/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLineTests.cs b/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLineTests.cs index 27fb7d754b..b690386422 100644 --- a/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLineTests.cs +++ b/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLineTests.cs @@ -1163,6 +1163,57 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting } } + + [Fact] + public void Should_Handle_NewLine_In_RTL_Text() + { + using (Start()) + { + var typeface = Typeface.Default; + + var defaultProperties = new GenericTextRunProperties(typeface); + + var textSource = new SingleBufferTextSource("test\r\n", defaultProperties); + + var formatter = new TextFormatterImpl(); + + var textLine = + formatter.FormatLine(textSource, 0, double.PositiveInfinity, + new GenericTextParagraphProperties(FlowDirection.RightToLeft, TextAlignment.Right, + true, true, defaultProperties, TextWrapping.Wrap, 0, 0, 0)); + + Assert.NotNull(textLine); + + Assert.NotEqual(textLine.NewLineLength, 0); + + } + } + + [Theory] + [InlineData("hello\r\nworld")] + [InlineData("مرحباً\r\nبالعالم")] + [InlineData("hello مرحباً\r\nworld بالعالم")] + [InlineData("مرحباً hello\r\nبالعالم nworld")] + public void Should_Set_NewLineLength_For_CRLF_In_RTL_Text(string text) + { + using (Start()) + { + var typeface = Typeface.Default; + var defaultProperties = new GenericTextRunProperties(typeface); + var textSource = new SingleBufferTextSource(text, defaultProperties); + + var formatter = new TextFormatterImpl(); + + var textLine = + formatter.FormatLine(textSource, 0, double.PositiveInfinity, + new GenericTextParagraphProperties(FlowDirection.RightToLeft, TextAlignment.Right, + true, true, defaultProperties, TextWrapping.Wrap, 0, 0, 0)); + + Assert.NotNull(textLine); + Assert.NotEqual(0, textLine.NewLineLength); + } + } + private class TextHidden : TextRun { public TextHidden(int length)