Browse Source

Fix bounds clipping.

scenegraph-after-breakage
Steven Kirk 10 years ago
parent
commit
6b6474bc8d
  1. 18
      src/Avalonia.Visuals/Rendering/SceneGraph/SceneBuilder.cs
  2. 49
      tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/SceneBuilderTests.cs
  3. 16
      tests/Avalonia.Visuals.UnitTests/VisualTree/VisualExtensionsTests_GetVisualsAt.cs

18
src/Avalonia.Visuals/Rendering/SceneGraph/SceneBuilder.cs

@ -20,7 +20,7 @@ namespace Avalonia.Rendering.SceneGraph
using (var impl = new DeferredDrawingContextImpl())
using (var context = new DrawingContext(impl))
{
Update(context, scene, (VisualNode)scene.Root, true);
Update(context, scene, (VisualNode)scene.Root, scene.Root.Visual.Bounds, true);
}
}
@ -58,12 +58,15 @@ namespace Avalonia.Rendering.SceneGraph
using (var impl = new DeferredDrawingContextImpl(dirty))
using (var context = new DrawingContext(impl))
{
var clip = scene.Root.Visual.Bounds;
if (node.Parent != null)
{
context.PushPostTransform(node.Parent.Transform);
clip = node.Parent.ClipBounds;
}
Update(context, scene, (VisualNode)node, recurse);
Update(context, scene, (VisualNode)node, clip, recurse);
}
return true;
@ -120,7 +123,7 @@ namespace Avalonia.Rendering.SceneGraph
return (VisualNode)node;
}
private static void Update(DrawingContext context, Scene scene, VisualNode node, bool forceRecurse)
private static void Update(DrawingContext context, Scene scene, VisualNode node, Rect clip, bool forceRecurse)
{
var visual = node.Visual;
var opacity = visual.Opacity;
@ -153,12 +156,17 @@ namespace Avalonia.Rendering.SceneGraph
node.Transform != contextImpl.Transform;
node.Transform = contextImpl.Transform;
node.ClipBounds = bounds * node.Transform;
node.ClipBounds = (bounds * node.Transform).Intersect(clip);
node.ClipToBounds = clipToBounds;
node.GeometryClip = visual.Clip;
node.Opacity = opacity;
node.OpacityMask = visual.OpacityMask;
if (node.ClipToBounds)
{
clip = clip.Intersect(node.ClipBounds);
}
visual.Render(context);
if (forceRecurse)
@ -166,7 +174,7 @@ namespace Avalonia.Rendering.SceneGraph
foreach (var child in visual.VisualChildren.OrderBy(x => x, ZIndexComparer.Instance))
{
var childNode = scene.FindNode(child) ?? CreateNode(scene, child, node);
Update(context, scene, (VisualNode)childNode, forceRecurse);
Update(context, scene, (VisualNode)childNode, clip, forceRecurse);
}
node.SubTreeUpdated = true;

49
tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/SceneBuilderTests.cs

@ -98,6 +98,55 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
}
}
[Fact]
public void ClipBounds_Should_Be_Intersection_With_Parent_ClipBounds()
{
using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{
Border border;
var tree = new TestRoot
{
Width = 200,
Height = 300,
Child = new Canvas
{
ClipToBounds = true,
Width = 100,
Height = 100,
HorizontalAlignment = HorizontalAlignment.Left,
VerticalAlignment = VerticalAlignment.Top,
Children =
{
(border = new Border
{
Background = Brushes.AliceBlue,
Width = 100,
Height = 100,
[Canvas.LeftProperty] = 50,
[Canvas.TopProperty] = 50,
})
}
}
};
tree.Measure(Size.Infinity);
tree.Arrange(new Rect(tree.DesiredSize));
var scene = new Scene(tree);
SceneBuilder.UpdateAll(scene);
var borderNode = scene.FindNode(border);
Assert.Equal(new Rect(50, 50, 50, 50), borderNode.ClipBounds);
// Initial ClipBounds are correct, make sure they're still correct after updating border.
scene = scene.Clone();
Assert.True(SceneBuilder.Update(scene, border));
borderNode = scene.FindNode(border);
Assert.Equal(new Rect(50, 50, 50, 50), borderNode.ClipBounds);
}
}
[Fact]
public void Should_Respect_ZIndex()
{

16
tests/Avalonia.Visuals.UnitTests/VisualTree/VisualExtensionsTests_GetVisualsAt.cs

@ -171,8 +171,8 @@ namespace Avalonia.Visuals.UnitTests.VisualTree
}
};
container.Measure(Size.Infinity);
container.Arrange(new Rect(container.DesiredSize));
root.Measure(Size.Infinity);
root.Arrange(new Rect(container.DesiredSize));
var result = container.GetVisualsAt(new Point(100, 100));
@ -224,8 +224,8 @@ namespace Avalonia.Visuals.UnitTests.VisualTree
}
};
container.Measure(Size.Infinity);
container.Arrange(new Rect(container.DesiredSize));
root.Measure(Size.Infinity);
root.Arrange(new Rect(container.DesiredSize));
var result = container.GetVisualsAt(new Point(100, 100));
@ -319,8 +319,8 @@ namespace Avalonia.Visuals.UnitTests.VisualTree
}
};
container.Measure(Size.Infinity);
container.Arrange(new Rect(container.DesiredSize));
root.Measure(Size.Infinity);
root.Arrange(new Rect(container.DesiredSize));
var result = container.GetVisualsAt(new Point(50, 50));
@ -391,8 +391,8 @@ namespace Avalonia.Visuals.UnitTests.VisualTree
scroll.UpdateChild();
container.Measure(Size.Infinity);
container.Arrange(new Rect(container.DesiredSize));
root.Measure(Size.Infinity);
root.Arrange(new Rect(container.DesiredSize));
var result = container.GetVisualsAt(new Point(50, 150)).First();

Loading…
Cancel
Save