@@ -16,6 +16,7 @@ public abstract class LayerEffect
1616 private readonly GraphicsOptions ? writeBackOptions ;
1717 private readonly Point writeBackOffset ;
1818 private readonly Action < IImageProcessingContext > operation ;
19+ private readonly int reach ;
1920
2021 /// <summary>
2122 /// Initializes a new instance of the <see cref="LayerEffect"/> class.
@@ -39,25 +40,33 @@ protected LayerEffect(LayerEffect fallbackEffect)
3940 this . writeBackOptions = fallbackEffect . WriteBackOptions ;
4041 this . writeBackOffset = fallbackEffect . WriteBackOffset ;
4142 this . operation = fallbackEffect . CreateOperation ( ) ;
43+ this . reach = fallbackEffect . Reach ;
4244 }
4345
46+ /// <summary>
47+ /// Gets the distance, in pixels, the effect can push content beyond its source region. Layer
48+ /// and processing bounds are expanded by this reach so the effect output is not cut off.
49+ /// Effects constructed over a fallback inherit the fallback's reach.
50+ /// </summary>
51+ public virtual int Reach => this . reach ;
52+
4453 /// <summary>
4554 /// Gets a value indicating whether the effect leaves the layer content unchanged, in which
4655 /// case its application is skipped entirely.
4756 /// </summary>
48- internal virtual bool IsPassThrough => this . isPassThrough ;
57+ public virtual bool IsPassThrough => this . isPassThrough ;
4958
5059 /// <summary>
5160 /// Gets the graphics options used to composite the processed pixels back onto the layer, or
5261 /// <see langword="null"/> to replace the processed region outright.
5362 /// </summary>
54- internal virtual GraphicsOptions ? WriteBackOptions => this . writeBackOptions ;
63+ public virtual GraphicsOptions ? WriteBackOptions => this . writeBackOptions ;
5564
5665 /// <summary>
5766 /// Gets the offset, in pixels, at which the processed pixels are written back relative to the
5867 /// region they were read from.
5968 /// </summary>
60- internal virtual Point WriteBackOffset => this . writeBackOffset ;
69+ public virtual Point WriteBackOffset => this . writeBackOffset ;
6170
6271 /// <summary>
6372 /// Creates the image-processing operation that transforms the layer snapshot into the effect
@@ -89,13 +98,16 @@ public BlurLayerEffect(float sigma)
8998 public float Sigma { get ; }
9099
91100 /// <inheritdoc/>
92- internal override bool IsPassThrough => this . Sigma == 0 ;
101+ public override int Reach => ( int ) MathF . Ceiling ( this . Sigma * 3F ) + 1 ;
93102
94103 /// <inheritdoc/>
95- internal override GraphicsOptions ? WriteBackOptions => null ;
104+ public override bool IsPassThrough => this . Sigma == 0 ;
96105
97106 /// <inheritdoc/>
98- internal override Point WriteBackOffset => default ;
107+ public override GraphicsOptions ? WriteBackOptions => null ;
108+
109+ /// <inheritdoc/>
110+ public override Point WriteBackOffset => default ;
99111}
100112
101113/// <summary>
@@ -138,11 +150,15 @@ public DropShadowLayerEffect(Point offset, float sigma, Color color)
138150 public Color Color { get ; }
139151
140152 /// <inheritdoc/>
141- internal override GraphicsOptions ? WriteBackOptions
153+ public override int Reach
154+ => ( int ) MathF . Ceiling ( this . Sigma * 3F ) + Math . Max ( Math . Abs ( this . Offset . X ) , Math . Abs ( this . Offset . Y ) ) + 1 ;
155+
156+ /// <inheritdoc/>
157+ public override GraphicsOptions ? WriteBackOptions
142158 => new ( ) { AlphaCompositionMode = PixelAlphaCompositionMode . DestOver } ;
143159
144160 /// <inheritdoc/>
145- internal override Point WriteBackOffset => this . Offset ;
161+ public override Point WriteBackOffset => this . Offset ;
146162
147163 /// <summary>
148164 /// Creates the CPU drop-shadow operation for the supplied effect values.
@@ -207,11 +223,14 @@ public GlowLayerEffect(float sigma, Color color)
207223 public Color Color { get ; }
208224
209225 /// <inheritdoc/>
210- internal override GraphicsOptions ? WriteBackOptions
226+ public override int Reach => ( int ) MathF . Ceiling ( this . Sigma * 3F ) + 1 ;
227+
228+ /// <inheritdoc/>
229+ public override GraphicsOptions ? WriteBackOptions
211230 => new ( ) { AlphaCompositionMode = PixelAlphaCompositionMode . DestOver } ;
212231
213232 /// <inheritdoc/>
214- internal override Point WriteBackOffset => default ;
233+ public override Point WriteBackOffset => default ;
215234
216235 /// <summary>
217236 /// Creates the CPU glow operation for the supplied effect values.
@@ -284,11 +303,15 @@ public InnerShadowLayerEffect(Point offset, float sigma, Color color)
284303 public Color Color { get ; }
285304
286305 /// <inheritdoc/>
287- internal override GraphicsOptions ? WriteBackOptions
306+ public override int Reach
307+ => ( int ) MathF . Ceiling ( this . Sigma * 3F ) + Math . Max ( Math . Abs ( this . Offset . X ) , Math . Abs ( this . Offset . Y ) ) + 1 ;
308+
309+ /// <inheritdoc/>
310+ public override GraphicsOptions ? WriteBackOptions
288311 => new ( ) { AlphaCompositionMode = PixelAlphaCompositionMode . SrcAtop } ;
289312
290313 /// <inheritdoc/>
291- internal override Point WriteBackOffset => this . Offset ;
314+ public override Point WriteBackOffset => this . Offset ;
292315
293316 /// <summary>
294317 /// Creates the CPU inner-shadow operation for the supplied effect values.
@@ -343,11 +366,14 @@ public ColorMatrixLayerEffect(ColorMatrix matrix)
343366 public ColorMatrix Matrix { get ; }
344367
345368 /// <inheritdoc/>
346- internal override GraphicsOptions ? WriteBackOptions => null ;
369+ public override int Reach => 0 ;
370+
371+ /// <inheritdoc/>
372+ public override GraphicsOptions ? WriteBackOptions => null ;
347373
348374 /// <inheritdoc/>
349- internal override Point WriteBackOffset => default ;
375+ public override Point WriteBackOffset => default ;
350376
351377 /// <inheritdoc/>
352- internal override bool IsPassThrough => this . Matrix == ColorMatrix . Identity ;
378+ public override bool IsPassThrough => this . Matrix == ColorMatrix . Identity ;
353379}
0 commit comments