Skip to content

Commit

Permalink
feat: Use RectangleClip for rounded corner border
Browse files Browse the repository at this point in the history
  • Loading branch information
MartinZikmund committed Nov 16, 2022
1 parent 35a8e98 commit 0f71961
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 34 deletions.
40 changes: 38 additions & 2 deletions src/Uno.UI.Composition/Composition/Compositor.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#nullable enable

using System.Numerics;
using Windows.UI;

namespace Windows.UI.Composition
Expand Down Expand Up @@ -81,13 +82,47 @@ public InsetClip CreateInsetClip()
=> new InsetClip(this);

public InsetClip CreateInsetClip(float leftInset, float topInset, float rightInset, float bottomInset)
=> new InsetClip(this) {
=> new InsetClip(this)
{
LeftInset = leftInset,
TopInset = topInset,
RightInset = rightInset,
BottomInset = bottomInset
};

public RectangleClip CreateRectangleClip()
=> new RectangleClip(this);

public RectangleClip CreateRectangleClip(float left, float top, float right, float bottom)
=> new RectangleClip(this)
{
Left = left,
Top = top,
Right = right,
Bottom = bottom
};

public RectangleClip CreateRectangleClip(
float left,
float top,
float right,
float bottom,
Vector2 topLeftRadius,
Vector2 topRightRadius,
Vector2 bottomRightRadius,
Vector2 bottomLeftRadius)
=> new RectangleClip(this)
{
Left = left,
Top = top,
Right = right,
Bottom = bottom,
TopLeftRadius = topLeftRadius,
TopRightRadius = topRightRadius,
BottomRightRadius = bottomRightRadius,
BottomLeftRadius = bottomLeftRadius
};

public CompositionLinearGradientBrush CreateLinearGradientBrush()
=> new CompositionLinearGradientBrush(this);

Expand All @@ -98,7 +133,8 @@ public CompositionColorGradientStop CreateColorGradientStop()
=> new CompositionColorGradientStop(this);

public CompositionColorGradientStop CreateColorGradientStop(float offset, Color color)
=> new CompositionColorGradientStop(this) {
=> new CompositionColorGradientStop(this)
{
Offset = offset,
Color = color
};
Expand Down
4 changes: 4 additions & 0 deletions src/Uno.UI.Composition/Composition/Compositor.skia.cs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,10 @@ private static void ApplyClip(SKSurface surface, Visual visual)

surface.Canvas.ClipRect(clipRect, SKClipOperation.Intersect, true);
}
else if (visual.Clip is RectangleClip rectangleClip)
{
surface.Canvas.ClipRoundRect(rectangleClip.SKRoundRect, SKClipOperation.Intersect, true);
}
else if (visual.Clip is CompositionGeometricClip geometricClip)
{
if (geometricClip.Geometry is CompositionPathGeometry cpg)
Expand Down
19 changes: 14 additions & 5 deletions src/Uno.UI.Composition/Composition/RectangleClip.skia.cs
Original file line number Diff line number Diff line change
@@ -1,26 +1,35 @@
#nullable enable

#nullable enable

using SkiaSharp;

namespace Windows.UI.Composition;

partial class RectangleClip
{
private SKRoundRect _skRoundRect;
private SKPoint[] _radii = new SKPoint[4];
private static readonly SKPoint[] _radiiStore = new SKPoint[4];

private SKRoundRect? _skRoundRect;

internal SKRoundRect SKRoundRect => GetRect();

private void GetRect()
private SKRoundRect GetRect()
{
_skRoundRect ??= new SKRoundRect();

_radiiStore[0] = new SKPoint(_topLeftRadius.X, _topLeftRadius.Y);
_radiiStore[1] = new SKPoint(_topRightRadius.X, _topRightRadius.Y);
_radiiStore[2] = new SKPoint(_bottomRightRadius.X, _bottomRightRadius.Y);
_radiiStore[3] = new SKPoint(_bottomLeftRadius.X, _bottomLeftRadius.Y);

_skRoundRect.SetRectRadii(
new SKRect(
Left,
Top,
Right,
Bottom),
_radii);
_radiiStore);
return _skRoundRect;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -413,21 +413,21 @@ public static float MinGlobalPlaybackRate
throw new global::System.NotImplementedException("The member AnimationPropertyInfo Compositor.CreateAnimationPropertyInfo() is not implemented in Uno.");
}
#endif
#if __ANDROID__ || __IOS__ || NET461 || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
#if false
[global::Uno.NotImplemented("__ANDROID__", "__IOS__", "NET461", "__WASM__", "__SKIA__", "__NETSTD_REFERENCE__", "__MACOS__")]
public global::Windows.UI.Composition.RectangleClip CreateRectangleClip()
{
throw new global::System.NotImplementedException("The member RectangleClip Compositor.CreateRectangleClip() is not implemented in Uno.");
}
#endif
#if __ANDROID__ || __IOS__ || NET461 || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
#if false
[global::Uno.NotImplemented("__ANDROID__", "__IOS__", "NET461", "__WASM__", "__SKIA__", "__NETSTD_REFERENCE__", "__MACOS__")]
public global::Windows.UI.Composition.RectangleClip CreateRectangleClip( float left, float top, float right, float bottom)
{
throw new global::System.NotImplementedException("The member RectangleClip Compositor.CreateRectangleClip(float left, float top, float right, float bottom) is not implemented in Uno.");
}
#endif
#if __ANDROID__ || __IOS__ || NET461 || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
#if false
[global::Uno.NotImplemented("__ANDROID__", "__IOS__", "NET461", "__WASM__", "__SKIA__", "__NETSTD_REFERENCE__", "__MACOS__")]
public global::Windows.UI.Composition.RectangleClip CreateRectangleClip( float left, float top, float right, float bottom, global::System.Numerics.Vector2 topLeftRadius, global::System.Numerics.Vector2 topRightRadius, global::System.Numerics.Vector2 bottomRightRadius, global::System.Numerics.Vector2 bottomLeftRadius)
{
Expand Down
17 changes: 6 additions & 11 deletions src/Uno.UI/UI/Xaml/Controls/Border/BorderLayerRenderer.skia.cs
Original file line number Diff line number Diff line change
Expand Up @@ -151,9 +151,6 @@ private static IDisposable InnerCreateLayer(UIElement owner, LayoutState state)
{
var borderPath = GetBorderPath(_outerRadiiStore, _innerRadiiStore, area, adjustedArea);
borderShape.Geometry = compositor.CreatePathGeometry(borderPath);

var outerPath = GetRoundedPath(area.ToSKRect(), _outerRadiiStore);
outerShape.Geometry = compositor.CreatePathGeometry(outerPath);

var borderVisual = compositor.CreateShapeVisual();

Expand All @@ -162,12 +159,10 @@ private static IDisposable InnerCreateLayer(UIElement owner, LayoutState state)

parent.Children.InsertAtTop(borderVisual);
}

owner.ClippingIsSetByCornerRadius = cornerRadius != CornerRadius.None;
if (owner.ClippingIsSetByCornerRadius)
{
parent.Clip = compositor.CreateGeometricClip(outerShape.Geometry);
}

parent.Clip = compositor.CreateRectangleClip(
0, 0, (float)area.Width, (float)area.Height,
fullCornerRadius.Outer.TopLeft, fullCornerRadius.Outer.TopRight, fullCornerRadius.Outer.BottomRight, fullCornerRadius.Outer.BottomLeft);
}
else
{
Expand Down Expand Up @@ -348,15 +343,15 @@ private static SKRoundRect CreateRoundRect(SKRect area, SKPoint[] radii)
var roundRect = new SKRoundRect();
roundRect.SetRectRadii(area, radii);
return roundRect;
}
}

private static CompositionPath GetBorderPath(SKPoint[] outerRadii, SKPoint[] innerRadii, Rect area, Rect insetArea)
{
var geometrySource = new SkiaGeometrySource2D();
GetRoundedPath(area.ToSKRect(), outerRadii, geometrySource);
GetRoundedPath(insetArea.ToSKRect(), innerRadii, geometrySource);
geometrySource.Geometry.FillType = SKPathFillType.EvenOdd;

return new CompositionPath(geometrySource);
}

Expand Down
19 changes: 10 additions & 9 deletions src/Uno.UI/UI/Xaml/NonUniformCornerRadius.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Windows.Foundation;
using System.Numerics;
using Windows.Foundation;

namespace Windows.UI.Xaml;

Expand All @@ -11,15 +12,15 @@ namespace Windows.UI.Xaml;
/// <param name="BottomLeft">Bottom left corner.</param>
internal partial record struct NonUniformCornerRadius
(
Point TopLeft,
Point TopRight,
Point BottomRight,
Point BottomLeft
Vector2 TopLeft,
Vector2 TopRight,
Vector2 BottomRight,
Vector2 BottomLeft
)
{
public bool IsEmpty =>
TopLeft == Point.Zero &&
TopRight == Point.Zero &&
BottomRight == Point.Zero &&
BottomLeft == Point.Zero;
TopLeft == Vector2.Zero &&
TopRight == Vector2.Zero &&
BottomRight == Vector2.Zero &&
BottomLeft == Vector2.Zero;
}
8 changes: 4 additions & 4 deletions src/Uno.UI/UI/Xaml/NonUniformCornerRadius.skia.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ partial record struct NonUniformCornerRadius
{
internal void GetRadii(SKPoint[] radiiStore)
{
radiiStore[0] = new((float)TopLeft.X, (float)TopLeft.Y);
radiiStore[1] = new((float)TopRight.X, (float)TopRight.Y);
radiiStore[2] = new((float)BottomRight.X, (float)BottomRight.Y);
radiiStore[3] = new((float)BottomLeft.X, (float)BottomLeft.Y);
radiiStore[0] = new(TopLeft.X, TopLeft.Y);
radiiStore[1] = new(TopRight.X, TopRight.Y);
radiiStore[2] = new(BottomRight.X, BottomRight.Y);
radiiStore[3] = new(BottomLeft.X, BottomLeft.Y);
}
}

0 comments on commit 0f71961

Please sign in to comment.