Browse Source
Fixes for #8092: - Always round sizes up, not to the nearest pixel, thereby ensuring that `DesiredSize`s don't get rounded down where possible. - Apply rounding to `Padding` and `BorderThickness` in measure pass as well as arrange pass, to ensure that `DesiredSize` takes this rounding into account.pull/8146/head
15 changed files with 414 additions and 56 deletions
@ -0,0 +1,140 @@ |
|||
using Avalonia.Controls; |
|||
using Avalonia.Layout; |
|||
using Avalonia.UnitTests; |
|||
using Xunit; |
|||
using Xunit.Sdk; |
|||
|
|||
namespace Avalonia.Base.UnitTests.Layout |
|||
{ |
|||
public class LayoutableTests_LayoutRounding |
|||
{ |
|||
[Theory] |
|||
[InlineData(100, 100)] |
|||
[InlineData(101, 101.33333333333333)] |
|||
[InlineData(103, 103.33333333333333)] |
|||
public void Measure_Adjusts_DesiredSize_Upwards_When_Constraint_Allows(double desiredSize, double expectedSize) |
|||
{ |
|||
var target = new TestLayoutable(new Size(desiredSize, desiredSize)); |
|||
var root = CreateRoot(1.5, target); |
|||
|
|||
root.LayoutManager.ExecuteInitialLayoutPass(); |
|||
|
|||
Assert.Equal(new Size(expectedSize, expectedSize), target.DesiredSize); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Measure_Constrains_Adjusted_DesiredSize_To_Constraint() |
|||
{ |
|||
var target = new TestLayoutable(new Size(101, 101)); |
|||
var root = CreateRoot(1.5, target, constraint: new Size(101, 101)); |
|||
|
|||
root.LayoutManager.ExecuteInitialLayoutPass(); |
|||
|
|||
// Desired width/height with layout rounding is 101.3333 but constraint is 101,101 so
|
|||
// layout rounding should be ignored.
|
|||
Assert.Equal(new Size(101, 101), target.DesiredSize); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Measure_Adjusts_DesiredSize_Upwards_When_Margin_Present() |
|||
{ |
|||
var target = new TestLayoutable(new Size(101, 101), margin: 1); |
|||
var root = CreateRoot(1.5, target); |
|||
|
|||
root.LayoutManager.ExecuteInitialLayoutPass(); |
|||
|
|||
// - 1 pixel margin is rounded up to 1.3333; for both sides it is 2.6666
|
|||
// - Size of 101 gets rounded up to 101.3333
|
|||
// - Final size = 101.3333 + 2.6666 = 104
|
|||
AssertEqual(new Size(104, 104), target.DesiredSize); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Arrange_Adjusts_Bounds_Upwards_With_Margin() |
|||
{ |
|||
var target = new TestLayoutable(new Size(101, 101), margin: 1); |
|||
var root = CreateRoot(1.5, target); |
|||
|
|||
root.LayoutManager.ExecuteInitialLayoutPass(); |
|||
|
|||
// - 1 pixel margin is rounded up to 1.3333
|
|||
// - Size of 101 gets rounded up to 101.3333
|
|||
AssertEqual(new Point(1.3333333333333333, 1.3333333333333333), target.Bounds.Position); |
|||
AssertEqual(new Size(101.33333333333333, 101.33333333333333), target.Bounds.Size); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(16, 6, 5.333333333333333)] |
|||
[InlineData(18, 10, 4)] |
|||
public void Arranges_Center_Alignment_Correctly_With_Fractional_Scaling( |
|||
double containerWidth, |
|||
double childWidth, |
|||
double expectedX) |
|||
{ |
|||
Border target; |
|||
var root = new TestRoot |
|||
{ |
|||
LayoutScaling = 1.5, |
|||
UseLayoutRounding = true, |
|||
Child = new Decorator |
|||
{ |
|||
Width = containerWidth, |
|||
Height = 100, |
|||
Child = target = new Border |
|||
{ |
|||
Width = childWidth, |
|||
HorizontalAlignment = HorizontalAlignment.Center, |
|||
} |
|||
} |
|||
}; |
|||
|
|||
root.Measure(new Size(100, 100)); |
|||
root.Arrange(new Rect(target.DesiredSize)); |
|||
|
|||
Assert.Equal(new Rect(expectedX, 0, childWidth, 100), target.Bounds); |
|||
} |
|||
|
|||
private static TestRoot CreateRoot( |
|||
double scaling, |
|||
Control child, |
|||
Size? constraint = null) |
|||
{ |
|||
return new TestRoot |
|||
{ |
|||
LayoutScaling = scaling, |
|||
UseLayoutRounding = true, |
|||
Child = child, |
|||
ClientSize = constraint ?? new Size(1000, 1000), |
|||
}; |
|||
} |
|||
|
|||
private static void AssertEqual(Point expected, Point actual) |
|||
{ |
|||
if (!expected.NearlyEquals(actual)) |
|||
{ |
|||
throw new EqualException(expected, actual); |
|||
} |
|||
} |
|||
|
|||
private static void AssertEqual(Size expected, Size actual) |
|||
{ |
|||
if (!expected.NearlyEquals(actual)) |
|||
{ |
|||
throw new EqualException(expected, actual); |
|||
} |
|||
} |
|||
|
|||
private class TestLayoutable : Control |
|||
{ |
|||
private Size _desiredSize; |
|||
|
|||
public TestLayoutable(Size desiredSize, double margin = 0) |
|||
{ |
|||
_desiredSize = desiredSize; |
|||
Margin = new Thickness(margin); |
|||
} |
|||
|
|||
protected override Size MeasureOverride(Size availableSize) => _desiredSize; |
|||
} |
|||
} |
|||
} |
|||
|
Before Width: | Height: | Size: 752 B After Width: | Height: | Size: 767 B |
|
Before Width: | Height: | Size: 557 B After Width: | Height: | Size: 532 B |
Loading…
Reference in new issue