@@ -15,7 +15,9 @@ public partial class CompositionShadow : Control
1515 public DropShadow DropShadow => _dropShadow ;
1616
1717 public SpriteVisual Visual => _shadowVisual ;
18+ public Compositor compositor ;
1819
20+ private bool _isCustomMask ;
1921 public CompositionBrush Mask
2022 {
2123 get => _dropShadow ? . Mask ;
@@ -24,6 +26,7 @@ public CompositionBrush Mask
2426 if ( _dropShadow != null )
2527 {
2628 _dropShadow . Mask = value ;
29+ _isCustomMask = value != null ; // mark that user provided a mask
2730 }
2831 }
2932 }
@@ -32,7 +35,7 @@ public CompositionShadow()
3235 this . DefaultStyleKey = typeof ( CompositionShadow ) ;
3336 this . SizeChanged += CompositionShadow_SizeChanged ;
3437 this . Loaded += CompositionShadow_Loaded ;
35- var compositor = ElementCompositionPreview . GetElementVisual ( this ) . Compositor ;
38+ compositor = ElementCompositionPreview . GetElementVisual ( this ) . Compositor ;
3639
3740 _shadowVisual = compositor . CreateSpriteVisual ( ) ;
3841 _dropShadow = compositor . CreateDropShadow ( ) ;
@@ -70,7 +73,15 @@ private void CompositionShadow_SizeChanged(object sender, SizeChangedEventArgs e
7073
7174 private void ConfigureShadowVisualForContent ( )
7275 {
73- UpdateShadowMask ( ) ;
76+ if ( IsRounded )
77+ {
78+ UpdateIsRounded ( ) ;
79+ }
80+ else
81+ {
82+ UpdateShadowMask ( ) ;
83+ }
84+
7485 UpdateShadowSize ( ) ;
7586
7687 if ( _dropShadow != null )
@@ -87,25 +98,26 @@ private void UpdateShadowMask()
8798 if ( _dropShadow == null )
8899 return ;
89100
90- if ( Content != null )
101+ // If IsRounded is true, always use rounded mask
102+ if ( IsRounded )
103+ return ; // Mask is already set in UpdateIsRounded
104+
105+ // Only auto-generate mask if user hasn't set a custom mask
106+ if ( ! _isCustomMask && Content != null )
91107 {
92108 CompositionBrush mask = null ;
93109 if ( Content is Image image )
94- {
95110 mask = image . GetAlphaMask ( ) ;
96- }
97111 else if ( Content is Shape shape )
98- {
99112 mask = shape . GetAlphaMask ( ) ;
100- }
101113 else if ( Content is TextBlock textBlock )
102- {
103114 mask = textBlock . GetAlphaMask ( ) ;
104- }
115+
105116 _dropShadow . Mask = mask ;
106117 }
107- else
118+ else if ( ! _isCustomMask )
108119 {
120+ // fallback if Content is null or unsupported
109121 _dropShadow . Mask = null ;
110122 }
111123 }
@@ -156,4 +168,37 @@ private async Task UpdateColorFromImageAsync()
156168 Color = Colors . Black ;
157169 }
158170 }
171+
172+ private void UpdateIsRounded ( )
173+ {
174+ if ( IsRounded )
175+ {
176+ float width = ( float ) this . ActualWidth ;
177+ float height = ( float ) this . ActualHeight ;
178+ float radius = MathF . Min ( width , height ) / 2f ;
179+
180+ var ellipse = compositor . CreateEllipseGeometry ( ) ;
181+ ellipse . Center = new Vector2 ( width / 2f , height / 2f ) ;
182+ ellipse . Radius = new Vector2 ( radius , radius ) ;
183+
184+ var shape = compositor . CreateSpriteShape ( ellipse ) ;
185+ shape . FillBrush = compositor . CreateColorBrush ( Colors . White ) ;
186+
187+ var shapeVisual = compositor . CreateShapeVisual ( ) ;
188+ shapeVisual . Size = new Vector2 ( width , height ) ;
189+ shapeVisual . Shapes . Add ( shape ) ;
190+
191+ var visualSurface = compositor . CreateVisualSurface ( ) ;
192+ visualSurface . SourceVisual = shapeVisual ;
193+ visualSurface . SourceSize = new Vector2 ( width , height ) ;
194+
195+ var maskBrush = compositor . CreateSurfaceBrush ( visualSurface ) ;
196+
197+ _dropShadow . Mask = maskBrush ;
198+ }
199+ else
200+ {
201+ UpdateShadowMask ( ) ;
202+ }
203+ }
159204}
0 commit comments