committed by
GitHub
45 changed files with 482 additions and 239 deletions
@ -1,13 +0,0 @@ |
|||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|||
<PropertyGroup> |
|||
<ApiContractPackageVersion>0.10.0</ApiContractPackageVersion> |
|||
<NugetPackageName Condition="'$(PackageId)' != ''">$(PackageId)</NugetPackageName> |
|||
<NugetPackageName Condition="'$(PackageId)' == ''">Avalonia</NugetPackageName> |
|||
<RunApiCompat Condition="'$(TargetFramework)' == 'net6.0'">false</RunApiCompat> |
|||
</PropertyGroup> |
|||
<ItemGroup> |
|||
<PackageDownload Include="$(NugetPackageName)" Version="[$(ApiContractPackageVersion)]" /> |
|||
<PackageReference Include="Microsoft.DotNet.ApiCompat" Version="5.0.0-beta.20372.2" PrivateAssets="All" /> |
|||
<ResolvedMatchingContract Include="$(NuGetPackageRoot)\$(NugetPackageName.ToLowerInvariant())\$(ApiContractPackageVersion)\lib\$(TargetFramework)\$(AssemblyName).dll" /> |
|||
</ItemGroup> |
|||
</Project> |
|||
@ -1,31 +0,0 @@ |
|||
using System; |
|||
using Avalonia.Media; |
|||
using Avalonia.Utilities; |
|||
|
|||
namespace Avalonia.Rendering.SceneGraph; |
|||
|
|||
internal static class GeometryBoundsHelper |
|||
{ |
|||
/// <summary>
|
|||
/// Calculates the bounds of a given geometry with respect to the pens <see cref="IPen.LineCap"/>
|
|||
/// </summary>
|
|||
/// <param name="originalBounds">The calculated bounds without <see cref="IPen.LineCap"/>s</param>
|
|||
/// <param name="pen">The pen with information about the <see cref="IPen.LineCap"/>s</param>
|
|||
/// <returns></returns>
|
|||
public static Rect CalculateBoundsWithLineCaps(this Rect originalBounds, IPen? pen) |
|||
{ |
|||
if (pen is null || MathUtilities.IsZero(pen.Thickness)) return originalBounds; |
|||
|
|||
switch (pen.LineCap) |
|||
{ |
|||
case PenLineCap.Flat: |
|||
return originalBounds; |
|||
case PenLineCap.Round: |
|||
return originalBounds.Inflate(pen.Thickness / 2); |
|||
case PenLineCap.Square: |
|||
return originalBounds.Inflate(pen.Thickness); |
|||
default: |
|||
throw new ArgumentOutOfRangeException(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,68 @@ |
|||
using Avalonia.Controls; |
|||
using Avalonia.Media; |
|||
using Xunit; |
|||
|
|||
namespace Avalonia.Base.UnitTests.Rendering; |
|||
/// <summary>
|
|||
/// Test class that verifies how clipping influences rendering in the compositor
|
|||
/// </summary>
|
|||
public class CompositorInvalidationClippingTests : CompositorTestsBase |
|||
{ |
|||
[Fact] |
|||
// Test case: When the ClipToBounds is false, all visuals should be rendered
|
|||
public void Siblings_Should_Be_Rendered_On_Invalidate_Without_ClipToBounds() |
|||
{ |
|||
AssertRenderedVisuals(clipToBounds: false, clipGeometry: false, expectedRenderedVisualsCount: 4); |
|||
} |
|||
|
|||
[Fact] |
|||
// Test case: When the ClipToBounds is true, only visuals within the clipped boundary should be rendered
|
|||
public void Siblings_Should_Not_Be_Rendered_On_Invalidate_With_ClipToBounds() |
|||
{ |
|||
AssertRenderedVisuals(clipToBounds: true, clipGeometry: false, expectedRenderedVisualsCount: 3); |
|||
} |
|||
|
|||
[Fact] |
|||
// Test case: When the Clip is used, only visuals within the clip geometry should be rendered
|
|||
public void Siblings_Should_Not_Be_Rendered_On_Invalidate_With_Clip() |
|||
{ |
|||
AssertRenderedVisuals(clipToBounds: false, clipGeometry: true, expectedRenderedVisualsCount: 3); |
|||
} |
|||
|
|||
private void AssertRenderedVisuals(bool clipToBounds, bool clipGeometry, int expectedRenderedVisualsCount) |
|||
{ |
|||
using (var s = new CompositorCanvas()) |
|||
{ |
|||
//#1 visual is top level
|
|||
//#2 visual is s.Canvas
|
|||
|
|||
//#3 visual is border1
|
|||
s.Canvas.Children.Add(new Border() |
|||
{ |
|||
[Canvas.LeftProperty] = 0, [Canvas.TopProperty] = 0, |
|||
Width = 20, Height = 10, |
|||
Background = Brushes.Red, |
|||
ClipToBounds = clipToBounds, |
|||
Clip = clipGeometry ? new RectangleGeometry(new Rect(new Size(20, 10))) : null |
|||
}); |
|||
|
|||
//#4 visual is border2
|
|||
s.Canvas.Children.Add(new Border() |
|||
{ |
|||
[Canvas.LeftProperty] = 30, [Canvas.TopProperty] = 50, |
|||
Width = 20, Height = 10, |
|||
Background = Brushes.Red, |
|||
ClipToBounds = clipToBounds, |
|||
Clip = clipGeometry ? new RectangleGeometry(new Rect(new Size(20, 10))) : null |
|||
}); |
|||
s.RunJobs(); |
|||
s.Events.Reset(); |
|||
|
|||
//invalidate border1
|
|||
s.Canvas.Children[0].IsVisible = false; |
|||
s.RunJobs(); |
|||
|
|||
s.AssertRenderedVisuals(expectedRenderedVisualsCount); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,43 @@ |
|||
using System; |
|||
using Avalonia.Controls.Shapes; |
|||
using Avalonia.Layout; |
|||
using Avalonia.Media; |
|||
using Avalonia.Platform; |
|||
using Avalonia.Rendering; |
|||
using Avalonia.UnitTests; |
|||
using Xunit; |
|||
|
|||
namespace Avalonia.Skia.UnitTests |
|||
{ |
|||
public class RenderBoundsTests |
|||
{ |
|||
[Theory, |
|||
InlineData("M10 20 L 20 10 L 30 20", PenLineCap.Round, PenLineJoin.Miter, 2, 10, |
|||
8.585786819458008, 8.585786819458008, 22.828428268432617, 12.828428268432617), |
|||
InlineData("M10 10 L 20 10", PenLineCap.Round, PenLineJoin.Miter,2, 10, |
|||
9,9,12,2), |
|||
InlineData("M10 10 L 20 15 L 10 20", PenLineCap.Flat, PenLineJoin.Miter, 2, 20, |
|||
9.552786827087402, 9.105572700500488, 12.683281898498535, 11.788853645324707) |
|||
|
|||
] |
|||
public void RenderBoundsAreCorrectlyCalculated(string path, PenLineCap cap, PenLineJoin join, double thickness, double miterLimit, double x, double y, double width, double height) |
|||
{ |
|||
using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface |
|||
.With(renderInterface: new PlatformRenderInterface()))) |
|||
{ |
|||
var geo = PathGeometry.Parse(path); |
|||
var pen = new Pen(Brushes.Black, thickness, null, cap, join, miterLimit); |
|||
var bounds = geo.GetRenderBounds(pen); |
|||
var tolerance = 0.001; |
|||
if ( |
|||
Math.Abs(bounds.X - x) > tolerance |
|||
|| Math.Abs(bounds.Y - y) > tolerance |
|||
|| Math.Abs(bounds.Width - width) > tolerance |
|||
|| Math.Abs(bounds.Height - height) > tolerance) |
|||
Assert.Fail($"Expected {x}:{y}:{width}:{height}, got {bounds}"); |
|||
|
|||
Assert.Equal(new Rect(x, y, width, height), bounds); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue