Browse Source

fix(text): preserve lines at rounded fractional heights (#21834)

* test(textblock): cover fractional layout rounding

A wrapped TextBlock with a fractional line height must retain every line when its desired height lands exactly on a fractional-scale pixel boundary.

* fix(text): preserve lines at rounded fractional heights

TextLayout treated a floating-point accumulation error as a MaxHeight overflow. Use the established tolerant comparison so a line that exactly fits its rounded layout bounds is retained.

---------

Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
pull/21857/head
Nathan Nguyen 2 months ago
committed by GitHub
parent
commit
480ed54ec7
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 2
      src/Avalonia.Base/Media/TextFormatting/TextLayout.cs
  2. 26
      tests/Avalonia.Controls.UnitTests/TextBlockTests.cs

2
src/Avalonia.Base/Media/TextFormatting/TextLayout.cs

@ -603,7 +603,7 @@ namespace Avalonia.Media.TextFormatting
//Fulfill max height constraint
if (textLines.Count > 0 && !double.IsPositiveInfinity(MaxHeight)
&& Height + textLine.Height > MaxHeight)
&& MathUtilities.GreaterThan(Height + textLine.Height, MaxHeight))
{
if (previousLine?.TextLineBreak != null && _textTrimming != TextTrimming.None)
{

26
tests/Avalonia.Controls.UnitTests/TextBlockTests.cs

@ -536,6 +536,32 @@ namespace Avalonia.Controls.UnitTests
Assert.Equal(new Rect(0, 0, 27.954545454545453, 14.522727272727273), target.Bounds);
}
[Fact]
public void TextBlock_With_Fractional_LineHeight_Should_Not_Cull_Last_Line_At_Fractional_Scaling()
{
using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
var target = new TextBlock
{
Text = "first second third",
FontSize = 16,
LineHeight = 20.8,
TextWrapping = TextWrapping.Wrap,
Width = 50,
HorizontalAlignment = HorizontalAlignment.Left,
VerticalAlignment = VerticalAlignment.Top,
};
var root = new TestRoot(target)
{
LayoutScaling = 1.25,
};
root.Measure(Size.Infinity);
root.Arrange(new Rect(root.DesiredSize));
Assert.Equal(3, target.TextLayout.TextLines.Count);
}
[Fact]
public void TextBlock_With_UseLayoutRounding_False_Should_Not_Round_Padding_In_MeasureOverride()
{

Loading…
Cancel
Save