Skip to content

Commit 3cb9931

Browse files
authored
Merge pull request #12734 from Gillibald/feature/pushPopRenderOptions
Introduce DrawingContext Push/PopRenderOptions
2 parents 1c667f8 + 68e68df commit 3cb9931

File tree

10 files changed

+121
-1
lines changed

10 files changed

+121
-1
lines changed

src/Avalonia.Base/Media/DrawingContext.cs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,8 @@ public enum PushedStateType
283283
Opacity,
284284
Clip,
285285
GeometryClip,
286-
OpacityMask
286+
OpacityMask,
287+
RenderOptions
287288
}
288289

289290
public RestoreState(DrawingContext context, PushedStateType type)
@@ -308,6 +309,8 @@ public void Dispose()
308309
_context.PopGeometryClipCore();
309310
else if (_type == PushedStateType.OpacityMask)
310311
_context.PopOpacityMaskCore();
312+
else if (_type == PushedStateType.RenderOptions)
313+
_context.PopRenderOptionsCore();
311314
}
312315
}
313316

@@ -400,6 +403,20 @@ public PushedState PushTransform(Matrix matrix)
400403
return new PushedState(this);
401404
}
402405

406+
/// <summary>
407+
/// Pushes render options.
408+
/// </summary>
409+
/// <param name="renderOptions">The render options.</param>
410+
/// <returns>A disposable to undo the render options.</returns>
411+
public PushedState PushRenderOptions(RenderOptions renderOptions)
412+
{
413+
PushRenderOptionsCore(renderOptions);
414+
_states ??= StateStackPool.Get();
415+
_states.Push(new RestoreState(this, RestoreState.PushedStateType.RenderOptions));
416+
return new PushedState(this);
417+
}
418+
protected abstract void PushRenderOptionsCore(RenderOptions renderOptions);
419+
403420
[Obsolete("Use PushTransform"), EditorBrowsable(EditorBrowsableState.Never)]
404421
public PushedState PushPreTransform(Matrix matrix) => PushTransform(matrix);
405422
[Obsolete("Use PushTransform"), EditorBrowsable(EditorBrowsableState.Never)]
@@ -415,6 +432,7 @@ public PushedState PushTransform(Matrix matrix)
415432
protected abstract void PopOpacityCore();
416433
protected abstract void PopOpacityMaskCore();
417434
protected abstract void PopTransformCore();
435+
protected abstract void PopRenderOptionsCore();
418436

419437
private static bool PenIsVisible(IPen? pen)
420438
{

src/Avalonia.Base/Media/DrawingGroup.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ public IBrush? OpacityMask
5353
set => SetValue(OpacityMaskProperty, value);
5454
}
5555

56+
internal RenderOptions? RenderOptions { get; set; }
57+
5658
/// <summary>
5759
/// Gets or sets the collection that contains the child geometries.
5860
/// </summary>
@@ -75,6 +77,7 @@ internal override void DrawCore(DrawingContext context)
7577
using (context.PushOpacity(Opacity))
7678
using (ClipGeometry != null ? context.PushGeometryClip(ClipGeometry) : default)
7779
using (OpacityMask != null ? context.PushOpacityMask(OpacityMask, bounds) : default)
80+
using (RenderOptions != null ? context.PushRenderOptions(RenderOptions.Value) : default)
7881
{
7982
foreach (var drawing in Children)
8083
{
@@ -313,6 +316,15 @@ protected override void PushTransformCore(Matrix matrix)
313316
drawingGroup.Transform = new MatrixTransform(matrix);
314317
}
315318

319+
protected override void PushRenderOptionsCore(RenderOptions renderOptions)
320+
{
321+
// Instantiate a new drawing group and set it as the _currentDrawingGroup
322+
var drawingGroup = PushNewDrawingGroup();
323+
324+
// Set the render options on the new DrawingGroup
325+
drawingGroup.RenderOptions = renderOptions;
326+
}
327+
316328
protected override void PopClipCore() => Pop();
317329

318330
protected override void PopGeometryClipCore() => Pop();
@@ -323,6 +335,8 @@ protected override void PushTransformCore(Matrix matrix)
323335

324336
protected override void PopTransformCore() => Pop();
325337

338+
protected override void PopRenderOptionsCore() => Pop();
339+
326340
/// <summary>
327341
/// Creates a new DrawingGroup for a Push* call by setting the
328342
/// _currentDrawingGroup to a newly instantiated DrawingGroup,

src/Avalonia.Base/Media/PlatformDrawingContext.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ protected override void PushTransformCore(Matrix matrix)
9090
_impl.Transform = matrix * current;
9191
}
9292

93+
protected override void PushRenderOptionsCore(RenderOptions renderOptions) => _impl.PushRenderOptions(renderOptions);
94+
9395
protected override void PopClipCore() => _impl.PopClip();
9496

9597
protected override void PopGeometryClipCore() => _impl.PopGeometryClip();
@@ -102,6 +104,8 @@ protected override void PopTransformCore() =>
102104
_impl.Transform =
103105
(_transforms ?? throw new ObjectDisposedException(nameof(PlatformDrawingContext))).Pop();
104106

107+
protected override void PopRenderOptionsCore() => _impl.PopRenderOptions();
108+
105109
protected override void DisposeCore()
106110
{
107111
if (_ownsImpl)

src/Avalonia.Base/Platform/IDrawingContextImpl.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,17 @@ void DrawRectangle(IBrush? brush, IPen? pen, RoundedRect rect,
160160
/// </summary>
161161
void PopGeometryClip();
162162

163+
/// <summary>
164+
/// Pushes render options.
165+
/// </summary>
166+
/// <param name="renderOptions">The render options.</param>
167+
void PushRenderOptions(RenderOptions renderOptions);
168+
169+
/// <summary>
170+
/// Pops the latest render options.
171+
/// </summary>
172+
void PopRenderOptions();
173+
163174
/// <summary>
164175
/// Attempts to get an optional feature from the drawing context implementation.
165176
/// </summary>

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,3 +211,18 @@ public void Collect(IRenderDataServerResourcesCollector collector)
211211
public abstract Rect? Bounds { get; }
212212
public abstract bool HitTest(Point p);
213213
}
214+
215+
class RenderDataRenderOptionsNode : RenderDataPushNode
216+
{
217+
public RenderOptions RenderOptions { get; set; }
218+
219+
public override void Push(ref RenderDataNodeRenderContext context)
220+
{
221+
context.Context.PushRenderOptions(RenderOptions);
222+
}
223+
224+
public override void Pop(ref RenderDataNodeRenderContext context)
225+
{
226+
context.Context.PopRenderOptions();
227+
}
228+
}

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,12 @@ protected override void PushTransformCore(Matrix matrix)
259259
});
260260
}
261261

262+
protected override void PushRenderOptionsCore(RenderOptions renderOptions) => Push(new RenderDataRenderOptionsNode()
263+
{
264+
RenderOptions = renderOptions
265+
});
266+
267+
262268
protected override void PopClipCore() => Pop<RenderDataClipNode>();
263269

264270
protected override void PopGeometryClipCore() => Pop<RenderDataGeometryClipNode>();
@@ -269,6 +275,8 @@ protected override void PushTransformCore(Matrix matrix)
269275

270276
protected override void PopTransformCore() => Pop<RenderDataPushMatrixNode>();
271277

278+
protected override void PopRenderOptionsCore() => Pop<RenderDataRenderOptionsNode>();
279+
272280
internal override void DrawBitmap(IRef<IBitmapImpl>? source, double opacity, Rect sourceRect, Rect destRect)
273281
{
274282
if (source == null || sourceRect.IsEmpty() || destRect.IsEmpty())

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,11 @@ public void PushOpacityMask(IBrush mask, Rect bounds)
122122
_impl.PushOpacityMask(mask, bounds);
123123
}
124124

125+
public void PushRenderOptions(RenderOptions renderOptions)
126+
{
127+
_impl.PushRenderOptions(renderOptions);
128+
}
129+
125130
public void PopOpacityMask()
126131
{
127132
_impl.PopOpacityMask();
@@ -137,6 +142,11 @@ public void PopGeometryClip()
137142
_impl.PopGeometryClip();
138143
}
139144

145+
public void PopRenderOptions()
146+
{
147+
_impl.PopRenderOptions();
148+
}
149+
140150
public object? GetFeature(Type t) => _impl.GetFeature(t);
141151

142152

src/Headless/Avalonia.Headless/HeadlessPlatformRenderInterface.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,16 @@ public void PushClip(RoundedRect clip)
542542
{
543543

544544
}
545+
546+
public void PushRenderOptions(RenderOptions renderOptions)
547+
{
548+
549+
}
550+
551+
public void PopRenderOptions()
552+
{
553+
554+
}
545555
}
546556

547557
private class HeadlessRenderTarget : IRenderTarget

src/Skia/Avalonia.Skia/DrawingContextImpl.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ internal partial class DrawingContextImpl : IDrawingContextImpl,
2323
private readonly Vector _dpi;
2424
private readonly Stack<PaintWrapper> _maskStack = new();
2525
private readonly Stack<double> _opacityStack = new();
26+
private readonly Stack<RenderOptions> _renderOptionsStack = new();
2627
private readonly Matrix? _postTransform;
2728
private double _currentOpacity = 1.0f;
2829
private readonly bool _disableSubpixelTextRendering;
@@ -634,6 +635,21 @@ public void PopOpacity()
634635
_currentOpacity = _opacityStack.Pop();
635636
}
636637

638+
/// <inheritdoc />
639+
public void PushRenderOptions(RenderOptions renderOptions)
640+
{
641+
CheckLease();
642+
643+
_renderOptionsStack.Push(RenderOptions);
644+
645+
RenderOptions = RenderOptions.MergeWith(renderOptions);
646+
}
647+
648+
public void PopRenderOptions()
649+
{
650+
RenderOptions = _renderOptionsStack.Pop();
651+
}
652+
637653
/// <inheritdoc />
638654
public virtual void Dispose()
639655
{

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ internal class DrawingContextImpl : IDrawingContextImpl
2424
private readonly SharpDX.DXGI.SwapChain1 _swapChain;
2525
private readonly Action _finishedCallback;
2626

27+
private readonly Stack<RenderOptions> _renderOptionsStack = new();
28+
2729
/// <summary>
2830
/// Initializes a new instance of the <see cref="DrawingContextImpl"/> class.
2931
/// </summary>
@@ -488,6 +490,18 @@ public void PopOpacity()
488490
PopLayer();
489491
}
490492

493+
public void PushRenderOptions(RenderOptions renderOptions)
494+
{
495+
_renderOptionsStack.Push(RenderOptions);
496+
497+
RenderOptions = RenderOptions.MergeWith(renderOptions);
498+
}
499+
500+
public void PopRenderOptions()
501+
{
502+
RenderOptions = _renderOptionsStack.Pop();
503+
}
504+
491505
private void PopLayer()
492506
{
493507
var layer = _layers.Pop();

0 commit comments

Comments
 (0)