Browse Source

Use parent clip rect of the adorned visual

pull/9830/head
Nikita Tsukanov 3 years ago
parent
commit
5a3d9f1574
  1. 19
      src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionVisual.cs
  2. 73
      tests/Avalonia.RenderTests/Controls/AdornerTests.cs
  3. 9
      tests/Avalonia.RenderTests/TestBase.cs
  4. BIN
      tests/TestFiles/Direct2D1/Controls/Adorner/Focus_Adorner_Is_Properly_Clipped.expected.png
  5. BIN
      tests/TestFiles/Skia/Controls/Adorner/Focus_Adorner_Is_Properly_Clipped.expected.png

19
src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionVisual.cs

@ -42,11 +42,18 @@ namespace Avalonia.Rendering.Composition.Server
Root!.RenderedVisuals++;
if (Opacity != 1)
canvas.PushOpacity(Opacity);
if (AdornedVisual != null)
{
canvas.PostTransform = Matrix.Identity;
canvas.Transform = Matrix.Identity;
canvas.PushClip(AdornedVisual._combinedTransformedClipBounds);
}
var transform = GlobalTransformMatrix;
canvas.PostTransform = MatrixUtils.ToMatrix(transform);
canvas.Transform = Matrix.Identity;
if (Opacity != 1)
canvas.PushOpacity(Opacity);
var boundsRect = new Rect(new Size(Size.X, Size.Y));
if (ClipToBounds && !HandlesClipToBounds)
canvas.PushClip(Root!.SnapToDevicePixels(boundsRect));
@ -67,6 +74,8 @@ namespace Avalonia.Rendering.Composition.Server
canvas.PopGeometryClip();
if (ClipToBounds && !HandlesClipToBounds)
canvas.PopClip();
if (AdornedVisual != null)
canvas.PopClip();
if(Opacity != 1)
canvas.PopOpacity();
}
@ -155,8 +164,12 @@ namespace Avalonia.Rendering.Composition.Server
_clipSizeDirty = false;
}
_combinedTransformedClipBounds =
AdornedVisual?._combinedTransformedClipBounds
?? Parent?._combinedTransformedClipBounds
?? new Rect(Root!.Size);
_combinedTransformedClipBounds = Parent?._combinedTransformedClipBounds ?? new Rect(Root!.Size);
if (_transformedClipBounds != null)
_combinedTransformedClipBounds = _combinedTransformedClipBounds.Intersect(_transformedClipBounds.Value);

73
tests/Avalonia.RenderTests/Controls/AdornerTests.cs

@ -0,0 +1,73 @@
using System.Threading.Tasks;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
using Avalonia.Layout;
using Avalonia.Media;
using Xunit;
#if AVALONIA_SKIA
namespace Avalonia.Skia.RenderTests;
#else
namespace Avalonia.Direct2D1.RenderTests.Controls;
#endif
public class AdornerTests : TestBase
{
public AdornerTests()
: base(@"Controls\Adorner")
{
}
[Fact]
public async Task Focus_Adorner_Is_Properly_Clipped()
{
Border adorned;
var tree = new Decorator
{
Child = new VisualLayerManager
{
Child = new Border
{
Background = Brushes.Red,
Padding = new Thickness(10, 50, 10,10),
Child = new Border()
{
Background = Brushes.White,
ClipToBounds = true,
Padding = new Thickness(0, -30, 0, 0),
Child = adorned = new Border
{
Background = Brushes.Green,
VerticalAlignment = VerticalAlignment.Top,
Height = 100,
Width = 50
}
}
}
},
Width = 200,
Height = 200
};
var adorner = new Border
{
BorderThickness = new Thickness(2),
BorderBrush = Brushes.Black
};
var size = new Size(tree.Width, tree.Height);
tree.Measure(size);
tree.Arrange(new Rect(size));
adorned.AttachedToVisualTree += delegate
{
AdornerLayer.SetAdornedElement(adorner, adorned);
AdornerLayer.GetAdornerLayer(adorned)!.Children.Add(adorner);
};
tree.Measure(size);
tree.Arrange(new Rect(size));
await RenderToFile(tree);
CompareImages(skipImmediate: true, skipDeferred: true);
}
}

9
tests/Avalonia.RenderTests/TestBase.cs

@ -156,7 +156,8 @@ namespace Avalonia.Direct2D1.RenderTests
public ILockedFramebuffer Lock() => _bitmap.Lock();
}
protected void CompareImages([CallerMemberName] string testName = "")
protected void CompareImages([CallerMemberName] string testName = "",
bool skipImmediate = false, bool skipDeferred = false, bool skipCompositor = false)
{
var expectedPath = Path.Combine(OutputPath, testName + ".expected.png");
var immediatePath = Path.Combine(OutputPath, testName + ".immediate.out.png");
@ -172,17 +173,17 @@ namespace Avalonia.Direct2D1.RenderTests
var deferredError = CompareImages(deferred, expected);
var compositedError = CompareImages(composited, expected);
if (immediateError > 0.022)
if (immediateError > 0.022 && !skipImmediate)
{
Assert.True(false, immediatePath + ": Error = " + immediateError);
}
if (deferredError > 0.022)
if (deferredError > 0.022 && !skipDeferred)
{
Assert.True(false, deferredPath + ": Error = " + deferredError);
}
if (compositedError > 0.022)
if (compositedError > 0.022 && !skipCompositor)
{
Assert.True(false, compositedPath + ": Error = " + compositedError);
}

BIN
tests/TestFiles/Direct2D1/Controls/Adorner/Focus_Adorner_Is_Properly_Clipped.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 673 B

BIN
tests/TestFiles/Skia/Controls/Adorner/Focus_Adorner_Is_Properly_Clipped.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 673 B

Loading…
Cancel
Save