From 572eb355e4e7034c04bc5e1e6bbed3161d04f2d9 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Tue, 19 Oct 2021 14:47:10 +0200 Subject: [PATCH] Store transform with clip nodes. Clip and geometry clip nodes were not being correctly applied with the current canvas transform from the time of their rendering. Make the nodes store the current canvas transform like the other drawing nodes. Fixes #6359. --- .../Rendering/SceneGraph/ClipNode.cs | 20 +++++++++++++++---- .../SceneGraph/DeferredDrawingContextImpl.cs | 12 +++++------ .../Rendering/SceneGraph/GeometryClipNode.cs | 14 +++++++++++-- 3 files changed, 34 insertions(+), 12 deletions(-) diff --git a/src/Avalonia.Visuals/Rendering/SceneGraph/ClipNode.cs b/src/Avalonia.Visuals/Rendering/SceneGraph/ClipNode.cs index ada04bfefd..90430bed02 100644 --- a/src/Avalonia.Visuals/Rendering/SceneGraph/ClipNode.cs +++ b/src/Avalonia.Visuals/Rendering/SceneGraph/ClipNode.cs @@ -11,19 +11,23 @@ namespace Avalonia.Rendering.SceneGraph /// Initializes a new instance of the class that represents a /// clip push. /// + /// The current transform. /// The clip to push. - public ClipNode(Rect clip) + public ClipNode(Matrix transform, Rect clip) { + Transform = transform; Clip = clip; } - + /// /// Initializes a new instance of the class that represents a /// clip push. /// + /// The current transform. /// The clip to push. - public ClipNode(RoundedRect clip) + public ClipNode(Matrix transform, RoundedRect clip) { + Transform = transform; Clip = clip; } @@ -43,23 +47,31 @@ namespace Avalonia.Rendering.SceneGraph /// public RoundedRect? Clip { get; } + /// + /// Gets the transform with which the node will be drawn. + /// + public Matrix Transform { get; } + /// public bool HitTest(Point p) => false; /// /// Determines if this draw operation equals another. /// + /// The transform of the other draw operation. /// The clip of the other draw operation. /// True if the draw operations are the same, otherwise false. /// /// The properties of the other draw operation are passed in as arguments to prevent /// allocation of a not-yet-constructed draw operation object. /// - public bool Equals(RoundedRect? clip) => Clip == clip; + public bool Equals(Matrix transform, RoundedRect? clip) => Transform == transform && Clip == clip; /// public void Render(IDrawingContextImpl context) { + context.Transform = Transform; + if (Clip.HasValue) { context.PushClip(Clip.Value); diff --git a/src/Avalonia.Visuals/Rendering/SceneGraph/DeferredDrawingContextImpl.cs b/src/Avalonia.Visuals/Rendering/SceneGraph/DeferredDrawingContextImpl.cs index 3594cb59ee..f4039dc0bc 100644 --- a/src/Avalonia.Visuals/Rendering/SceneGraph/DeferredDrawingContextImpl.cs +++ b/src/Avalonia.Visuals/Rendering/SceneGraph/DeferredDrawingContextImpl.cs @@ -303,9 +303,9 @@ namespace Avalonia.Rendering.SceneGraph { var next = NextDrawAs(); - if (next == null || !next.Item.Equals(clip)) + if (next == null || !next.Item.Equals(Transform, clip)) { - Add(new ClipNode(clip)); + Add(new ClipNode(Transform, clip)); } else { @@ -318,9 +318,9 @@ namespace Avalonia.Rendering.SceneGraph { var next = NextDrawAs(); - if (next == null || !next.Item.Equals(clip)) + if (next == null || !next.Item.Equals(Transform, clip)) { - Add(new ClipNode(clip)); + Add(new ClipNode(Transform, clip)); } else { @@ -333,9 +333,9 @@ namespace Avalonia.Rendering.SceneGraph { var next = NextDrawAs(); - if (next == null || !next.Item.Equals(clip)) + if (next == null || !next.Item.Equals(Transform, clip)) { - Add(new GeometryClipNode(clip)); + Add(new GeometryClipNode(Transform, clip)); } else { diff --git a/src/Avalonia.Visuals/Rendering/SceneGraph/GeometryClipNode.cs b/src/Avalonia.Visuals/Rendering/SceneGraph/GeometryClipNode.cs index a2ad83d845..16092d4cbb 100644 --- a/src/Avalonia.Visuals/Rendering/SceneGraph/GeometryClipNode.cs +++ b/src/Avalonia.Visuals/Rendering/SceneGraph/GeometryClipNode.cs @@ -11,9 +11,11 @@ namespace Avalonia.Rendering.SceneGraph /// Initializes a new instance of the class that represents a /// geometry clip push. /// + /// The current transform. /// The clip to push. - public GeometryClipNode(IGeometryImpl clip) + public GeometryClipNode(Matrix transform, IGeometryImpl clip) { + Transform = transform; Clip = clip; } @@ -33,23 +35,31 @@ namespace Avalonia.Rendering.SceneGraph /// public IGeometryImpl Clip { get; } + /// + /// Gets the transform with which the node will be drawn. + /// + public Matrix Transform { get; } + /// public bool HitTest(Point p) => false; /// /// Determines if this draw operation equals another. /// + /// The transform of the other draw operation. /// The clip of the other draw operation. /// True if the draw operations are the same, otherwise false. /// /// The properties of the other draw operation are passed in as arguments to prevent /// allocation of a not-yet-constructed draw operation object. /// - public bool Equals(IGeometryImpl clip) => Clip == clip; + public bool Equals(Matrix transform, IGeometryImpl clip) => Transform == transform && Clip == clip; /// public void Render(IDrawingContextImpl context) { + context.Transform = Transform; + if (Clip != null) { context.PushGeometryClip(Clip);