Browse Source

Merge pull request #12734 from Gillibald/feature/pushPopRenderOptions

Introduce DrawingContext Push/PopRenderOptions
release/11.0.5-rc1
Benedikt Stebner 2 years ago
committed by Steven Kirk
parent
commit
f032a1b68f
  1. 20
      src/Avalonia.Base/Media/DrawingContext.cs
  2. 14
      src/Avalonia.Base/Media/DrawingGroup.cs
  3. 4
      src/Avalonia.Base/Media/PlatformDrawingContext.cs
  4. 11
      src/Avalonia.Base/Platform/IDrawingContextImpl.cs
  5. 15
      src/Avalonia.Base/Rendering/Composition/Drawing/Nodes/RenderDataNodes.cs
  6. 8
      src/Avalonia.Base/Rendering/Composition/Drawing/RenderDataDrawingContext.cs
  7. 10
      src/Avalonia.Base/Rendering/Composition/Server/DrawingContextProxy.cs
  8. 10
      src/Headless/Avalonia.Headless/HeadlessPlatformRenderInterface.cs
  9. 16
      src/Skia/Avalonia.Skia/DrawingContextImpl.cs
  10. 14
      src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs

20
src/Avalonia.Base/Media/DrawingContext.cs

@ -283,7 +283,8 @@ namespace Avalonia.Media
Opacity,
Clip,
GeometryClip,
OpacityMask
OpacityMask,
RenderOptions
}
public RestoreState(DrawingContext context, PushedStateType type)
@ -308,6 +309,8 @@ namespace Avalonia.Media
_context.PopGeometryClipCore();
else if (_type == PushedStateType.OpacityMask)
_context.PopOpacityMaskCore();
else if (_type == PushedStateType.RenderOptions)
_context.PopRenderOptionsCore();
}
}
@ -400,6 +403,20 @@ namespace Avalonia.Media
return new PushedState(this);
}
/// <summary>
/// Pushes render options.
/// </summary>
/// <param name="renderOptions">The render options.</param>
/// <returns>A disposable to undo the render options.</returns>
public PushedState PushRenderOptions(RenderOptions renderOptions)
{
PushRenderOptionsCore(renderOptions);
_states ??= StateStackPool.Get();
_states.Push(new RestoreState(this, RestoreState.PushedStateType.RenderOptions));
return new PushedState(this);
}
protected abstract void PushRenderOptionsCore(RenderOptions renderOptions);
[Obsolete("Use PushTransform"), EditorBrowsable(EditorBrowsableState.Never)]
public PushedState PushPreTransform(Matrix matrix) => PushTransform(matrix);
[Obsolete("Use PushTransform"), EditorBrowsable(EditorBrowsableState.Never)]
@ -415,6 +432,7 @@ namespace Avalonia.Media
protected abstract void PopOpacityCore();
protected abstract void PopOpacityMaskCore();
protected abstract void PopTransformCore();
protected abstract void PopRenderOptionsCore();
private static bool PenIsVisible(IPen? pen)
{

14
src/Avalonia.Base/Media/DrawingGroup.cs

@ -53,6 +53,8 @@ namespace Avalonia.Media
set => SetValue(OpacityMaskProperty, value);
}
internal RenderOptions? RenderOptions { get; set; }
/// <summary>
/// Gets or sets the collection that contains the child geometries.
/// </summary>
@ -75,6 +77,7 @@ namespace Avalonia.Media
using (context.PushOpacity(Opacity))
using (ClipGeometry != null ? context.PushGeometryClip(ClipGeometry) : default)
using (OpacityMask != null ? context.PushOpacityMask(OpacityMask, bounds) : default)
using (RenderOptions != null ? context.PushRenderOptions(RenderOptions.Value) : default)
{
foreach (var drawing in Children)
{
@ -313,6 +316,15 @@ namespace Avalonia.Media
drawingGroup.Transform = new MatrixTransform(matrix);
}
protected override void PushRenderOptionsCore(RenderOptions renderOptions)
{
// Instantiate a new drawing group and set it as the _currentDrawingGroup
var drawingGroup = PushNewDrawingGroup();
// Set the render options on the new DrawingGroup
drawingGroup.RenderOptions = renderOptions;
}
protected override void PopClipCore() => Pop();
protected override void PopGeometryClipCore() => Pop();
@ -323,6 +335,8 @@ namespace Avalonia.Media
protected override void PopTransformCore() => Pop();
protected override void PopRenderOptionsCore() => Pop();
/// <summary>
/// Creates a new DrawingGroup for a Push* call by setting the
/// _currentDrawingGroup to a newly instantiated DrawingGroup,

4
src/Avalonia.Base/Media/PlatformDrawingContext.cs

@ -90,6 +90,8 @@ internal sealed class PlatformDrawingContext : DrawingContext
_impl.Transform = matrix * current;
}
protected override void PushRenderOptionsCore(RenderOptions renderOptions) => _impl.PushRenderOptions(renderOptions);
protected override void PopClipCore() => _impl.PopClip();
protected override void PopGeometryClipCore() => _impl.PopGeometryClip();
@ -102,6 +104,8 @@ internal sealed class PlatformDrawingContext : DrawingContext
_impl.Transform =
(_transforms ?? throw new ObjectDisposedException(nameof(PlatformDrawingContext))).Pop();
protected override void PopRenderOptionsCore() => _impl.PopRenderOptions();
protected override void DisposeCore()
{
if (_ownsImpl)

11
src/Avalonia.Base/Platform/IDrawingContextImpl.cs

@ -160,6 +160,17 @@ namespace Avalonia.Platform
/// </summary>
void PopGeometryClip();
/// <summary>
/// Pushes render options.
/// </summary>
/// <param name="renderOptions">The render options.</param>
void PushRenderOptions(RenderOptions renderOptions);
/// <summary>
/// Pops the latest render options.
/// </summary>
void PopRenderOptions();
/// <summary>
/// Attempts to get an optional feature from the drawing context implementation.
/// </summary>

15
src/Avalonia.Base/Rendering/Composition/Drawing/Nodes/RenderDataNodes.cs

@ -211,3 +211,18 @@ abstract class RenderDataBrushAndPenNode : IRenderDataItemWithServerResources
public abstract Rect? Bounds { get; }
public abstract bool HitTest(Point p);
}
class RenderDataRenderOptionsNode : RenderDataPushNode
{
public RenderOptions RenderOptions { get; set; }
public override void Push(ref RenderDataNodeRenderContext context)
{
context.Context.PushRenderOptions(RenderOptions);
}
public override void Pop(ref RenderDataNodeRenderContext context)
{
context.Context.PopRenderOptions();
}
}

8
src/Avalonia.Base/Rendering/Composition/Drawing/RenderDataDrawingContext.cs

@ -259,6 +259,12 @@ internal class RenderDataDrawingContext : DrawingContext
});
}
protected override void PushRenderOptionsCore(RenderOptions renderOptions) => Push(new RenderDataRenderOptionsNode()
{
RenderOptions = renderOptions
});
protected override void PopClipCore() => Pop<RenderDataClipNode>();
protected override void PopGeometryClipCore() => Pop<RenderDataGeometryClipNode>();
@ -269,6 +275,8 @@ internal class RenderDataDrawingContext : DrawingContext
protected override void PopTransformCore() => Pop<RenderDataPushMatrixNode>();
protected override void PopRenderOptionsCore() => Pop<RenderDataRenderOptionsNode>();
internal override void DrawBitmap(IRef<IBitmapImpl>? source, double opacity, Rect sourceRect, Rect destRect)
{
if (source == null || sourceRect.IsEmpty() || destRect.IsEmpty())

10
src/Avalonia.Base/Rendering/Composition/Server/DrawingContextProxy.cs

@ -122,6 +122,11 @@ internal class CompositorDrawingContextProxy : IDrawingContextImpl,
_impl.PushOpacityMask(mask, bounds);
}
public void PushRenderOptions(RenderOptions renderOptions)
{
_impl.PushRenderOptions(renderOptions);
}
public void PopOpacityMask()
{
_impl.PopOpacityMask();
@ -137,6 +142,11 @@ internal class CompositorDrawingContextProxy : IDrawingContextImpl,
_impl.PopGeometryClip();
}
public void PopRenderOptions()
{
_impl.PopRenderOptions();
}
public object? GetFeature(Type t) => _impl.GetFeature(t);

10
src/Headless/Avalonia.Headless/HeadlessPlatformRenderInterface.cs

@ -542,6 +542,16 @@ namespace Avalonia.Headless
{
}
public void PushRenderOptions(RenderOptions renderOptions)
{
}
public void PopRenderOptions()
{
}
}
private class HeadlessRenderTarget : IRenderTarget

16
src/Skia/Avalonia.Skia/DrawingContextImpl.cs

@ -23,6 +23,7 @@ namespace Avalonia.Skia
private readonly Vector _dpi;
private readonly Stack<PaintWrapper> _maskStack = new();
private readonly Stack<double> _opacityStack = new();
private readonly Stack<RenderOptions> _renderOptionsStack = new();
private readonly Matrix? _postTransform;
private double _currentOpacity = 1.0f;
private readonly bool _disableSubpixelTextRendering;
@ -634,6 +635,21 @@ namespace Avalonia.Skia
_currentOpacity = _opacityStack.Pop();
}
/// <inheritdoc />
public void PushRenderOptions(RenderOptions renderOptions)
{
CheckLease();
_renderOptionsStack.Push(RenderOptions);
RenderOptions = RenderOptions.MergeWith(renderOptions);
}
public void PopRenderOptions()
{
RenderOptions = _renderOptionsStack.Pop();
}
/// <inheritdoc />
public virtual void Dispose()
{

14
src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs

@ -24,6 +24,8 @@ namespace Avalonia.Direct2D1.Media
private readonly SharpDX.DXGI.SwapChain1 _swapChain;
private readonly Action _finishedCallback;
private readonly Stack<RenderOptions> _renderOptionsStack = new();
/// <summary>
/// Initializes a new instance of the <see cref="DrawingContextImpl"/> class.
/// </summary>
@ -488,6 +490,18 @@ namespace Avalonia.Direct2D1.Media
PopLayer();
}
public void PushRenderOptions(RenderOptions renderOptions)
{
_renderOptionsStack.Push(RenderOptions);
RenderOptions = RenderOptions.MergeWith(renderOptions);
}
public void PopRenderOptions()
{
RenderOptions = _renderOptionsStack.Pop();
}
private void PopLayer()
{
var layer = _layers.Pop();

Loading…
Cancel
Save