diff --git a/src/Avalonia.Base/Media/TextFormatting/TextLayout.cs b/src/Avalonia.Base/Media/TextFormatting/TextLayout.cs
index 39a8ff870e..590d2f2133 100644
--- a/src/Avalonia.Base/Media/TextFormatting/TextLayout.cs
+++ b/src/Avalonia.Base/Media/TextFormatting/TextLayout.cs
@@ -679,20 +679,47 @@ namespace Avalonia.Media.TextFormatting
private void UpdateMetrics(TextLineImpl currentLine, ref bool first)
{
- _metrics.InkBounds = _metrics.InkBounds.Union(new Rect(new Point(0, _metrics.Bounds.Bottom) + currentLine.InkBounds.Position, currentLine.InkBounds.Size));
- _metrics.Bounds = _metrics.Bounds.Union(new Rect(new Point(0, _metrics.Bounds.Bottom) + currentLine.Bounds.Position, currentLine.Bounds.Size));
+ // 1) Offset each line’s bounding rectangles by the total height so far,
+ // so we keep an overall bounding box for the entire text block.
+ var lineTop = _metrics.Height;
- _metrics.MinTextWidth = Math.Max(_metrics.MinTextWidth, currentLine.Bounds.Width);
- _metrics.MinTextWidth = Math.Max(_metrics.MinTextWidth, currentLine.InkBounds.Width);
+ // Offset the line's Bounds
+ var lineBoundsRect = new Rect(
+ currentLine.Bounds.X,
+ lineTop + currentLine.Bounds.Y,
+ currentLine.Bounds.Width,
+ currentLine.Bounds.Height);
- _metrics.Height = _metrics.Bounds.Height;
- _metrics.Width = _metrics.InkBounds.Width;
- _metrics.WidthIncludingTrailingWhitespace = _metrics.Bounds.Width;
- _metrics.Extent = _metrics.InkBounds.Height;
- _metrics.OverhangLeading = Math.Max(0, _metrics.Bounds.Left - _metrics.InkBounds.Left);
- _metrics.OverhangTrailing = Math.Max(0, _metrics.InkBounds.Right - _metrics.Bounds.Right);
- _metrics.OverhangAfter = Math.Max(0, _metrics.InkBounds.Bottom - _metrics.Bounds.Bottom);
+ _metrics.Bounds = _metrics.Bounds.Union(lineBoundsRect);
+ // Offset the line's InkBounds
+ var lineInkRect = new Rect(
+ currentLine.InkBounds.X,
+ lineTop + currentLine.InkBounds.Y,
+ currentLine.InkBounds.Width,
+ currentLine.InkBounds.Height);
+
+ _metrics.InkBounds = _metrics.InkBounds.Union(lineInkRect);
+
+ // 2) Accumulate total layout height by adding the line’s Height.
+ _metrics.Height += currentLine.Height;
+
+ // 3) For the layout’s Width and WidthIncludingTrailingWhitespace,
+ // use the maximum of the line widths rather than the bounding box.
+ _metrics.Width = Math.Max(_metrics.Width, currentLine.Width);
+ _metrics.WidthIncludingTrailingWhitespace = Math.Max(_metrics.WidthIncludingTrailingWhitespace, currentLine.WidthIncludingTrailingWhitespace);
+
+ // 4) Extent is the max black-pixel extent among lines.
+ _metrics.Extent = Math.Max(_metrics.Extent, currentLine.Extent);
+
+ // 5) We can track min-text-width or overhangs similarly if needed.
+ _metrics.MinTextWidth = Math.Max(_metrics.MinTextWidth, currentLine.Width);
+
+ _metrics.OverhangLeading = Math.Max(_metrics.OverhangLeading, currentLine.OverhangLeading);
+ _metrics.OverhangTrailing = Math.Max(_metrics.OverhangTrailing, currentLine.OverhangTrailing);
+ _metrics.OverhangAfter = Math.Max(_metrics.OverhangAfter, currentLine.OverhangAfter);
+
+ // 6) Capture the baseline from the first line.
if (first)
{
_metrics.Baseline = currentLine.Baseline;
diff --git a/tests/Avalonia.Skia.UnitTests/Avalonia.Skia.UnitTests.csproj b/tests/Avalonia.Skia.UnitTests/Avalonia.Skia.UnitTests.csproj
index d006c8c189..d092e3b0b9 100644
--- a/tests/Avalonia.Skia.UnitTests/Avalonia.Skia.UnitTests.csproj
+++ b/tests/Avalonia.Skia.UnitTests/Avalonia.Skia.UnitTests.csproj
@@ -12,8 +12,10 @@
+
+
diff --git a/tests/Avalonia.Skia.UnitTests/Fonts/WinSymbols3.ttf b/tests/Avalonia.Skia.UnitTests/Fonts/WinSymbols3.ttf
new file mode 100644
index 0000000000..4cba3d13a1
Binary files /dev/null and b/tests/Avalonia.Skia.UnitTests/Fonts/WinSymbols3.ttf differ
diff --git a/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLayoutTests.cs b/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLayoutTests.cs
index 3d19efeae9..0113973ab6 100644
--- a/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLayoutTests.cs
+++ b/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLayoutTests.cs
@@ -1147,6 +1147,19 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
}
}
+ [Fact]
+ public void Should_Measure_TextLayoutSymbolWithAndWidthIncludingTrailingWhitespace()
+ {
+ const string symbolsFont = "resm:Avalonia.Skia.UnitTests.Fonts?assembly=Avalonia.Skia.UnitTests#Symbols";
+ using (Start())
+ {
+ var textLayout = new TextLayout("\ue971", new Typeface(symbolsFont), 12.0, Brushes.White);
+
+ Assert.Equal(new Size(12.0, 12.0), new Size(textLayout.Width, textLayout.Height));
+ Assert.Equal(12.0, textLayout.WidthIncludingTrailingWhitespace);
+ }
+ }
+
private static IDisposable Start()
{
var disposable = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface