@@ -210,20 +210,20 @@ private void UpdateVisualOpacityMask(AttachedShadowElementContext context)
210210 return ;
211211 }
212212
213- // Create a rounded rectangle Visual with a thick outline and no fill, then use a VisualSurface of it as an opacity mask for the shadow.
214- // This will have the effect of clipping the inner content of the shadow, so that the casting element is not covered by the shadow,
215- // while the shadow is still rendered outside of the element. Similar to what takes place in GetVisualClip,
216- // except here we use a brush to mask content instead of a pure geometric clip.
217- var shapeVisual = context . GetResource ( OpacityMaskShapeVisualResourceKey ) ??
213+ // Create ShapeVisual, and CompositionSpriteShape with geometry, these will provide the visuals for the opacity mask.
214+ ShapeVisual shapeVisual = context . GetResource ( OpacityMaskShapeVisualResourceKey ) ??
218215 context . AddResource ( OpacityMaskShapeVisualResourceKey , context . Compositor . CreateShapeVisual ( ) ) ;
219216
220- CompositionRoundedRectangleGeometry geom = context . GetResource ( OpacityMaskGeometryResourceKey ) ??
217+ CompositionRoundedRectangleGeometry geometry = context . GetResource ( OpacityMaskGeometryResourceKey ) ??
221218 context . AddResource ( OpacityMaskGeometryResourceKey , context . Compositor . CreateRoundedRectangleGeometry ( ) ) ;
222219 CompositionSpriteShape shape = context . GetResource ( OpacityMaskSpriteShapeResourceKey ) ??
223- context . AddResource ( OpacityMaskSpriteShapeResourceKey , context . Compositor . CreateSpriteShape ( geom ) ) ;
220+ context . AddResource ( OpacityMaskSpriteShapeResourceKey , context . Compositor . CreateSpriteShape ( geometry ) ) ;
224221
225- geom . Offset = new Vector2 ( MaxBlurRadius / 2 ) ;
226- geom . CornerRadius = new Vector2 ( ( MaxBlurRadius / 2 ) + ( float ) CornerRadius ) ;
222+ // Set the attributes of the geometry, and add the CompositionSpriteShape to the ShapeVisual.
223+ // The geometry will have a thick outline and no fill, meaning that when used as a mask,
224+ // the shadow will only be rendered on the outer area covered by the outline, clipping out its inner portion.
225+ geometry . Offset = new Vector2 ( MaxBlurRadius / 2 ) ;
226+ geometry . CornerRadius = new Vector2 ( ( MaxBlurRadius / 2 ) + ( float ) CornerRadius ) ;
227227 shape . StrokeThickness = MaxBlurRadius ;
228228 shape . StrokeBrush = shape . StrokeBrush ?? context . Compositor . CreateColorBrush ( Colors . Black ) ;
229229
@@ -232,42 +232,57 @@ private void UpdateVisualOpacityMask(AttachedShadowElementContext context)
232232 shapeVisual . Shapes . Add ( shape ) ;
233233 }
234234
235- var visualSurface = context . GetResource ( OpacityMaskShapeVisualSurfaceResourceKey ) ??
235+ // Create CompositionVisualSurface using the ShapeVisual as the source visual.
236+ CompositionVisualSurface visualSurface = context . GetResource ( OpacityMaskShapeVisualSurfaceResourceKey ) ??
236237 context . AddResource ( OpacityMaskShapeVisualSurfaceResourceKey , context . Compositor . CreateVisualSurface ( ) ) ;
237238 visualSurface . SourceVisual = shapeVisual ;
238239
239- geom . Size = new Vector2 ( ( float ) context . Element . ActualWidth , ( float ) context . Element . ActualHeight ) + new Vector2 ( MaxBlurRadius ) ;
240+ geometry . Size = new Vector2 ( ( float ) context . Element . ActualWidth , ( float ) context . Element . ActualHeight ) + new Vector2 ( MaxBlurRadius ) ;
240241 shapeVisual . Size = visualSurface . SourceSize = new Vector2 ( ( float ) context . Element . ActualWidth , ( float ) context . Element . ActualHeight ) + new Vector2 ( MaxBlurRadius * 2 ) ;
241242
242- var surfaceBrush = context . GetResource ( OpacityMaskShapeVisualSurfaceBrushResourceKey ) ??
243+ // Create a CompositionSurfaceBrush using the CompositionVisualSurface as the source, this essentially converts the ShapeVisual into a brush.
244+ // This brush can then be used as a mask.
245+ CompositionSurfaceBrush opacityMask = context . GetResource ( OpacityMaskShapeVisualSurfaceBrushResourceKey ) ??
243246 context . AddResource ( OpacityMaskShapeVisualSurfaceBrushResourceKey , context . Compositor . CreateSurfaceBrush ( ) ) ;
244- surfaceBrush . Surface = visualSurface ;
247+ opacityMask . Surface = visualSurface ;
245248 }
246249
247250 /// <inheritdoc/>
248251 protected override void SetElementChildVisual ( AttachedShadowElementContext context )
249252 {
250- if ( context . TryGetResource ( OpacityMaskShapeVisualSurfaceBrushResourceKey , out var opacityMask ) )
253+ if ( context . TryGetResource ( OpacityMaskShapeVisualSurfaceBrushResourceKey , out CompositionSurfaceBrush opacityMask ) )
251254 {
252- var visualSurface = context . GetResource ( OpacityMaskVisualSurfaceResourceKey ) ??
255+ // If the resource for OpacityMaskShapeVisualSurfaceBrushResourceKey exists it means this.InnerContentClipMode == CompositionVisualSurface,
256+ // which means we need to take some steps to set up an opacity mask.
257+
258+ // Create a CompositionVisualSurface, and use the SpriteVisual containing the shadow as the source.
259+ CompositionVisualSurface shadowVisualSurface = context . GetResource ( OpacityMaskVisualSurfaceResourceKey ) ??
253260 context . AddResource ( OpacityMaskVisualSurfaceResourceKey , context . Compositor . CreateVisualSurface ( ) ) ;
254- visualSurface . SourceVisual = context . SpriteVisual ;
261+ shadowVisualSurface . SourceVisual = context . SpriteVisual ;
255262 context . SpriteVisual . RelativeSizeAdjustment = Vector2 . Zero ;
256263 context . SpriteVisual . Size = new Vector2 ( ( float ) context . Element . ActualWidth , ( float ) context . Element . ActualHeight ) ;
257- visualSurface . SourceOffset = new Vector2 ( - MaxBlurRadius ) ;
258- visualSurface . SourceSize = new Vector2 ( ( float ) context . Element . ActualWidth , ( float ) context . Element . ActualHeight ) + new Vector2 ( MaxBlurRadius * 2 ) ;
259264
260- var surfaceBrush = context . GetResource ( OpacityMaskSurfaceBrushResourceKey ) ??
265+ // Adjust the offset and size of the CompositionVisualSurface to accommodate the thick outline of the shape created in UpdateVisualOpacityMask().
266+ shadowVisualSurface . SourceOffset = new Vector2 ( - MaxBlurRadius ) ;
267+ shadowVisualSurface . SourceSize = new Vector2 ( ( float ) context . Element . ActualWidth , ( float ) context . Element . ActualHeight ) + new Vector2 ( MaxBlurRadius * 2 ) ;
268+
269+ // Create a CompositionSurfaceBrush from the CompositionVisualSurface. This allows us to render the shadow in a brush.
270+ CompositionSurfaceBrush shadowSurfaceBrush = context . GetResource ( OpacityMaskSurfaceBrushResourceKey ) ??
261271 context . AddResource ( OpacityMaskSurfaceBrushResourceKey , context . Compositor . CreateSurfaceBrush ( ) ) ;
262- surfaceBrush . Surface = visualSurface ;
263- surfaceBrush . Stretch = CompositionStretch . None ;
272+ shadowSurfaceBrush . Surface = shadowVisualSurface ;
273+ shadowSurfaceBrush . Stretch = CompositionStretch . None ;
264274
275+ // Create a CompositionMaskBrush, using the CompositionSurfaceBrush of the shadow as the source,
276+ // and the CompositionSurfaceBrush created in UpdateVisualOpacityMask() as the mask.
277+ // This creates a brush that renders the shadow with its inner portion clipped out.
265278 CompositionMaskBrush maskBrush = context . GetResource ( OpacityMaskBrushResourceKey ) ??
266279 context . AddResource ( OpacityMaskBrushResourceKey , context . Compositor . CreateMaskBrush ( ) ) ;
267- maskBrush . Source = surfaceBrush ;
280+ maskBrush . Source = shadowSurfaceBrush ;
268281 maskBrush . Mask = opacityMask ;
269282
270- var visual = context . GetResource ( OpacityMaskVisualResourceKey ) ??
283+ // Create a SpriteVisual and set its brush to the CompositionMaskBrush created in the previous step,
284+ // then set it as the child of the element in the context.
285+ SpriteVisual visual = context . GetResource ( OpacityMaskVisualResourceKey ) ??
271286 context . AddResource ( OpacityMaskVisualResourceKey , context . Compositor . CreateSpriteVisual ( ) ) ;
272287 visual . RelativeSizeAdjustment = Vector2 . One ;
273288 visual . Offset = new Vector3 ( - MaxBlurRadius , - MaxBlurRadius , 0 ) ;
@@ -288,21 +303,21 @@ protected override void SetElementChildVisual(AttachedShadowElementContext conte
288303 /// <inheritdoc />
289304 protected internal override void OnSizeChanged ( AttachedShadowElementContext context , Size newSize , Size previousSize )
290305 {
291- var sizeAsVec2 = newSize . ToVector2 ( ) ;
306+ Vector2 sizeAsVec2 = newSize . ToVector2 ( ) ;
292307
293- var geometry = context . GetResource ( RoundedRectangleGeometryResourceKey ) ;
308+ CompositionRoundedRectangleGeometry geometry = context . GetResource ( RoundedRectangleGeometryResourceKey ) ;
294309 if ( geometry != null )
295310 {
296311 geometry . Size = sizeAsVec2 ;
297312 }
298313
299- var visualSurface = context . GetResource ( VisualSurfaceResourceKey ) ;
314+ CompositionVisualSurface visualSurface = context . GetResource ( VisualSurfaceResourceKey ) ;
300315 if ( geometry != null )
301316 {
302317 visualSurface . SourceSize = sizeAsVec2 ;
303318 }
304319
305- var shapeVisual = context . GetResource ( ShapeVisualResourceKey ) ;
320+ ShapeVisual shapeVisual = context . GetResource ( ShapeVisualResourceKey ) ;
306321 if ( geometry != null )
307322 {
308323 shapeVisual . Size = sizeAsVec2 ;
0 commit comments