Browse Source

Fixed round rect regression in compositing renderer

pull/9543/head
Nikita Tsukanov 3 years ago
parent
commit
e895c91367
  1. 6
      src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionVisual.cs
  2. 7
      src/Avalonia.Base/Visual.cs
  3. 14
      src/Avalonia.Controls/Border.cs
  4. 76
      src/Avalonia.Controls/BorderVisual.cs

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

@ -48,7 +48,7 @@ namespace Avalonia.Rendering.Composition.Server
if (Opacity != 1)
canvas.PushOpacity(Opacity);
var boundsRect = new Rect(new Size(Size.X, Size.Y));
if(ClipToBounds)
if (ClipToBounds && !HandlesClipToBounds)
canvas.PushClip(Root!.SnapToDevicePixels(boundsRect));
if (Clip != null)
canvas.PushGeometryClip(Clip);
@ -65,11 +65,13 @@ namespace Avalonia.Rendering.Composition.Server
canvas.PopOpacityMask();
if (Clip != null)
canvas.PopGeometryClip();
if (ClipToBounds)
if (ClipToBounds && !HandlesClipToBounds)
canvas.PopClip();
if(Opacity != 1)
canvas.PopOpacity();
}
protected virtual bool HandlesClipToBounds => false;
private ReadbackData _readback0, _readback1, _readback2;

7
src/Avalonia.Base/Visual.cs

@ -452,12 +452,15 @@ namespace Avalonia
}
}
private protected virtual CompositionDrawListVisual CreateCompositionVisual(Compositor compositor)
=> new CompositionDrawListVisual(compositor,
new ServerCompositionDrawListVisual(compositor.Server, this), this);
internal CompositionVisual AttachToCompositor(Compositor compositor)
{
if (CompositionVisual == null || CompositionVisual.Compositor != compositor)
{
CompositionVisual = new CompositionDrawListVisual(compositor,
new ServerCompositionDrawListVisual(compositor.Server, this), this);
CompositionVisual = CreateCompositionVisual(compositor);
}
return CompositionVisual;

14
src/Avalonia.Controls/Border.cs

@ -4,6 +4,7 @@ using Avalonia.Controls.Shapes;
using Avalonia.Controls.Utils;
using Avalonia.Layout;
using Avalonia.Media;
using Avalonia.Rendering.Composition;
using Avalonia.Utilities;
using Avalonia.VisualTree;
@ -73,6 +74,7 @@ namespace Avalonia.Controls
private readonly BorderRenderHelper _borderRenderHelper = new BorderRenderHelper();
private Thickness? _layoutThickness;
private double _scale;
private CompositionBorderVisual? _borderVisual;
/// <summary>
/// Initializes static members of the <see cref="Border"/> class.
@ -101,6 +103,10 @@ namespace Avalonia.Controls
case nameof(BorderThickness):
_layoutThickness = null;
break;
case nameof(CornerRadius):
if (_borderVisual != null)
_borderVisual.CornerRadius = CornerRadius;
break;
}
}
@ -245,6 +251,14 @@ namespace Avalonia.Controls
return LayoutHelper.ArrangeChild(Child, finalSize, Padding, BorderThickness);
}
private protected override CompositionDrawListVisual CreateCompositionVisual(Compositor compositor)
{
return _borderVisual = new CompositionBorderVisual(compositor, this)
{
CornerRadius = CornerRadius
};
}
public CornerRadius ClipToBoundsRadius => CornerRadius;
}
}

76
src/Avalonia.Controls/BorderVisual.cs

@ -0,0 +1,76 @@
using System;
using Avalonia.Rendering.Composition;
using Avalonia.Rendering.Composition.Server;
using Avalonia.Rendering.Composition.Transport;
using Avalonia.Rendering.SceneGraph;
namespace Avalonia.Controls;
class CompositionBorderVisual : CompositionDrawListVisual
{
private CornerRadius _cornerRadius;
private bool _cornerRadiusChanged;
public CompositionBorderVisual(Compositor compositor, Visual visual) : base(compositor,
new ServerBorderVisual(compositor.Server, visual), visual)
{
}
public CornerRadius CornerRadius
{
get => _cornerRadius;
set
{
if (_cornerRadius != value)
{
_cornerRadiusChanged = true;
_cornerRadius = value;
RegisterForSerialization();
}
}
}
private protected override void SerializeChangesCore(BatchStreamWriter writer)
{
base.SerializeChangesCore(writer);
writer.Write(_cornerRadiusChanged);
if (_cornerRadiusChanged)
writer.Write(_cornerRadius);
}
class ServerBorderVisual : ServerCompositionDrawListVisual
{
private CornerRadius _cornerRadius;
public ServerBorderVisual(ServerCompositor compositor, Visual v) : base(compositor, v)
{
}
protected override void RenderCore(CompositorDrawingContextProxy canvas, Rect currentTransformedClip)
{
if (ClipToBounds)
{
var clipRect = Root!.SnapToDevicePixels(new Rect(new Size(Size.X, Size.Y)));
if (_cornerRadius.IsEmpty)
canvas.PushClip(clipRect);
else
canvas.PushClip(new RoundedRect(clipRect, _cornerRadius));
}
base.RenderCore(canvas, currentTransformedClip);
if(ClipToBounds)
canvas.PopClip();
}
protected override void DeserializeChangesCore(BatchStreamReader reader, TimeSpan commitedAt)
{
base.DeserializeChangesCore(reader, commitedAt);
if (reader.Read<bool>())
_cornerRadius = reader.Read<CornerRadius>();
}
protected override bool HandlesClipToBounds => true;
}
}
Loading…
Cancel
Save