diff --git a/src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs b/src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs index 3264d5e88a..935347ed85 100644 --- a/src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs +++ b/src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs @@ -698,7 +698,7 @@ namespace Avalonia.Media.TextFormatting i = lastRunIndex; //Possible overlap at runs of different direction - if (directionalWidth == 0) + if (directionalWidth == 0 && i < _textRuns.Length - 1) { //In case a run only contains a linebreak we don't want to skip it. if (currentRun is ShapedTextRun shaped) @@ -844,7 +844,7 @@ namespace Avalonia.Media.TextFormatting i = firstRunIndex; //Possible overlap at runs of different direction - if (directionalWidth == 0) + if (directionalWidth == 0 && i > 0) { //In case a run only contains a linebreak we don't want to skip it. if (currentRun is ShapedTextRun shaped) @@ -860,8 +860,8 @@ namespace Avalonia.Media.TextFormatting } } - TextBounds? textBounds = null; int coveredLength; + TextBounds? textBounds; switch (currentDirection) { @@ -942,6 +942,13 @@ namespace Avalonia.Media.TextFormatting new TextRunBounds( new Rect(startX, 0, drawableTextRun.Size.Width, Height), currentPosition, currentRun.Length, currentRun)); } + else + { + //Add potential TextEndOfParagraph + textRunBounds.Add( + new TextRunBounds( + new Rect(endX, 0, 0, Height), currentPosition, currentRun.Length, currentRun)); + } currentPosition += currentRun.Length; @@ -1007,6 +1014,13 @@ namespace Avalonia.Media.TextFormatting endX += drawableTextRun.Size.Width; } + else + { + //Add potential TextEndOfParagraph + textRunBounds.Add( + new TextRunBounds( + new Rect(endX, 0, 0, Height), currentPosition, currentRun.Length, currentRun)); + } currentPosition += currentRun.Length; diff --git a/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLineTests.cs b/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLineTests.cs index d605ecbfda..1a39dd5223 100644 --- a/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLineTests.cs +++ b/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLineTests.cs @@ -1021,6 +1021,33 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting } } + [Fact] + public void Should_GetTextBounds_With_EndOfParagraph() + { + var text = "abc"; + + using (Start()) + { + var defaultProperties = new GenericTextRunProperties(Typeface.Default); + var textSource = new SingleBufferTextSource(text, defaultProperties, true); + + var formatter = new TextFormatterImpl(); + + var textLine = + formatter.FormatLine(textSource, 0, double.PositiveInfinity, + new GenericTextParagraphProperties(FlowDirection.LeftToRight, TextAlignment.Left, + true, true, defaultProperties, TextWrapping.NoWrap, 0, 0, 0)); + + var textBounds = textLine.GetTextBounds(3, 1); + + Assert.Equal(1, textBounds.Count); + + var firstBounds = textBounds.First(); + + Assert.True(firstBounds.TextRunBounds.Count > 0); + } + } + private class FixedRunsTextSource : ITextSource { private readonly IReadOnlyList _textRuns;