From e011861eafd55ace9fe478b28f8a04dcbf6a037d Mon Sep 17 00:00:00 2001 From: Benedikt Stebner Date: Thu, 27 Mar 2025 09:35:20 +0100 Subject: [PATCH] Fix TextWrapping in combination with TextEndOfLine runs (#18523) --- .../Media/TextFormatting/TextFormatterImpl.cs | 14 ++++++++--- .../Media/TextFormatting/TextLayoutTests.cs | 24 +++++++++++++++++++ 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/src/Avalonia.Base/Media/TextFormatting/TextFormatterImpl.cs b/src/Avalonia.Base/Media/TextFormatting/TextFormatterImpl.cs index 8e2325fb14..edf7576c3c 100644 --- a/src/Avalonia.Base/Media/TextFormatting/TextFormatterImpl.cs +++ b/src/Avalonia.Base/Media/TextFormatting/TextFormatterImpl.cs @@ -574,10 +574,11 @@ namespace Avalonia.Media.TextFormatting { var measuredLength = 0; var currentWidth = 0.0; + var runIndex = 0; - for (var i = 0; i < textRuns.Count; ++i) + for (; runIndex < textRuns.Count; ++runIndex) { - var currentRun = textRuns[i]; + var currentRun = textRuns[runIndex]; switch (currentRun) { @@ -630,7 +631,14 @@ namespace Avalonia.Media.TextFormatting runLength = clusterLength; } - return measuredLength + runLength; + measuredLength += runLength; + + if (runIndex < textRuns.Count - 1 && runLength == currentRun.Length && textRuns[runIndex + 1] is TextEndOfLine endOfLine) + { + measuredLength += endOfLine.Length; + } + + return measuredLength; } currentWidth += clusterWidth; diff --git a/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLayoutTests.cs b/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLayoutTests.cs index 0113973ab6..5440d980ab 100644 --- a/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLayoutTests.cs +++ b/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLayoutTests.cs @@ -1160,6 +1160,30 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting } } + [Fact] + public void Should_Wrap_With_LineEnd() + { + using (Start()) + { + var defaultProperties = + new GenericTextRunProperties(Typeface.Default, 72, foregroundBrush: Brushes.Black); + + var paragraphProperties = new GenericTextParagraphProperties(defaultProperties, textWrap: TextWrapping.Wrap); + + var textLayout = new TextLayout(new SingleBufferTextSource("01", defaultProperties, true), paragraphProperties, maxWidth: 36); + + Assert.Equal(2, textLayout.TextLines.Count); + + var lastLine = textLayout.TextLines.Last(); + + Assert.Equal(2, lastLine.TextRuns.Count); + + var lastRun = lastLine.TextRuns.Last(); + + Assert.IsAssignableFrom(lastRun); + } + } + private static IDisposable Start() { var disposable = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface