2

I'm struggling to figure out to to create rounded corners of content using Composition API. This is where I'm at, any help would be much appreciated:

void CreateRoundedCorners(Vector2 cornerRadius, CompositionSurfaceBrush imageSourceBrush, SpriteVisual targetVisual)
{
    CompositionRoundedRectangleGeometry roundedRectangle = _compositor.CreateRoundedRectangleGeometry();
    roundedRectangle.Size = new Vector2(;
    roundedRectangle.CornerRadius = cornerRadius;

    CompositionSpriteShape spriteShape = _compositor.CreateSpriteShape(roundedRectangle);
    spriteShape.FillBrush = _compositor.CreateColorBrush(Colors.Black);
    spriteShape.CenterPoint = new Vector2(_imageSize.X / 2, _imageSize.Y / 2);

    ShapeVisual spriteShapeVisual = _compositor.CreateShapeVisual();
    spriteShapeVisual.Size = _imageSize;
    spriteShapeVisual.Shapes.Add(spriteShape);

    CompositionMaskBrush maskBrush = _compositor.CreateMaskBrush();
    maskBrush.Source = imageSourceBrush;
    maskBrush.Mask = null; // How do I get the rectangle shape in here?

    targetVisual.Brush = maskBrush;
}
Sean O'Neil
  • 1,222
  • 12
  • 22

2 Answers2

2

I have figured out a solution. Creating a CompositionVisualSurface, adding the ShapeVisual to it, and creating a CompositionSurfaceBrush from that to use as the Mask source.

void CreateRoundedCorners(Vector2 cornerRadius, CompositionBrush imageSourceBrush, SpriteVisual targetVisual)
{
    CompositionRoundedRectangleGeometry roundedRectangle =_compositor.CreateRoundedRectangleGeometry();
    roundedRectangle.Size = _imageSize;
    roundedRectangle.CornerRadius = cornerRadius;

    CompositionSpriteShape spriteShape = _compositor.CreateSpriteShape(roundedRectangle);
    spriteShape.FillBrush = _compositor.CreateColorBrush(Colors.Black);
    spriteShape.CenterPoint = new Vector2(_imageSize.X / 2, _imageSize.Y / 2);

    ShapeVisual spriteShapeVisual = _compositor.CreateShapeVisual();
    spriteShapeVisual.BorderMode = CompositionBorderMode.Soft;
    spriteShapeVisual.Size = _imageSize;
    spriteShapeVisual.Shapes.Add(spriteShape);

    CompositionVisualSurface surface = _compositor.CreateVisualSurface();
    surface.SourceSize = _imageSize;
    surface.SourceVisual = spriteShapeVisual;

    CompositionMaskBrush maskBrush = _compositor.CreateMaskBrush();
    maskBrush.Source = imageSourceBrush;
    maskBrush.Mask = _compositor.CreateSurfaceBrush(surface);

    targetVisual.Brush = maskBrush;
}

EDIT: A mask can also be obtained from a Shape but only if it's already in the visual tree:

Windows.UI.Xaml.Shapes.Shape rect = new Rectangle();
CompositionBrush mask = rect.GetAlphaMask();
Sean O'Neil
  • 1,222
  • 12
  • 22
0

UWP Composition API: Rounded Corners?

For your requirement, you could use SetElementChildVisual method to add the CompositionRoundedRectangleGeometry to current page.

For example:

private void Page_Loaded(object sender, RoutedEventArgs e)
{
    var visual = ElementCompositionPreview.GetElementVisual(this);
    var compositor = visual.Compositor;
  
    CompositionRoundedRectangleGeometry roundedRectangle = compositor.CreateRoundedRectangleGeometry();
    roundedRectangle.Size = new Vector2(200, 200);
    roundedRectangle.CornerRadius = new Vector2(30,30);

    CompositionSpriteShape spriteShape = compositor.CreateSpriteShape(roundedRectangle);
    spriteShape.FillBrush = compositor.CreateColorBrush(Colors.Blue);
    spriteShape.CenterPoint = new Vector2(100, 100);

    ShapeVisual spriteShapeVisual = compositor.CreateShapeVisual();
    spriteShapeVisual.Size = new Vector2(200, 200); 
    
    spriteShapeVisual.Shapes.Clear();
    spriteShapeVisual.Shapes.Add(spriteShape);
  
    ElementCompositionPreview.SetElementChildVisual(this, spriteShapeVisual);
}
Nico Zhu
  • 32,367
  • 2
  • 15
  • 36
  • Thanks for the response but that just paints a blue rectangle with rounded corners. I'm trying to get rounded corners on any type of CompositionBrush including loaded image or video. The idea was to use the rectangle shape as an opacity mask. – Sean O'Neil Nov 19 '20 at 06:19
  • Why not use `CornerRadius` to set the control corner radius directly ? – Nico Zhu Nov 19 '20 at 06:22
  • Yes that does seem to work if the Grid is loaded first, but this will be problematic performance-wise for me and I'm pretty certain drop shadows will not have rounded corners doing it that way. – Sean O'Neil Nov 19 '20 at 06:53
  • Ok, I found you have posted yourself answer, if your solution works, you could mark it by self – Nico Zhu Nov 19 '20 at 06:56
  • So my solution does work, but unfortunately the corners are not very smooth. They're a bit jagged. Corners are smoother when setting the CornerRadius in the Grid as you suggested. But as I suspected, doing it that way means I can't use DropShadow. The shadow is actually cut off. This is a bit of a dilemma, I wonder why the rastered Composition shape would create a more jagged mask. – Sean O'Neil Nov 19 '20 at 07:08
  • 1
    Solved it. Changed ShapeVisual.BorderMode to 'Soft' and now it looks just like the XAML CornerRadius. Thanks for your help I wouldn't have noticed that otherwise. – Sean O'Neil Nov 19 '20 at 07:22