diff --git a/src/Uno.UI.Composition/Composition/Compositor.cs b/src/Uno.UI.Composition/Composition/Compositor.cs index 3f507be152fd..46b30dc92d67 100644 --- a/src/Uno.UI.Composition/Composition/Compositor.cs +++ b/src/Uno.UI.Composition/Composition/Compositor.cs @@ -1,5 +1,6 @@ #nullable enable +using System.Numerics; using Windows.UI; namespace Windows.UI.Composition @@ -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); @@ -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 }; diff --git a/src/Uno.UI.Composition/Composition/Compositor.skia.cs b/src/Uno.UI.Composition/Composition/Compositor.skia.cs index 5bbe073ad718..9f29042b0ff9 100644 --- a/src/Uno.UI.Composition/Composition/Compositor.skia.cs +++ b/src/Uno.UI.Composition/Composition/Compositor.skia.cs @@ -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) diff --git a/src/Uno.UI.Composition/Composition/RectangleClip.skia.cs b/src/Uno.UI.Composition/Composition/RectangleClip.skia.cs index 64c48bafcb48..b8d080a281e0 100644 --- a/src/Uno.UI.Composition/Composition/RectangleClip.skia.cs +++ b/src/Uno.UI.Composition/Composition/RectangleClip.skia.cs @@ -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; } } diff --git a/src/Uno.UI.Composition/Generated/3.0.0.0/Windows.UI.Composition/Compositor.cs b/src/Uno.UI.Composition/Generated/3.0.0.0/Windows.UI.Composition/Compositor.cs index 8e4b95f80076..b0e1d9b54a1c 100644 --- a/src/Uno.UI.Composition/Generated/3.0.0.0/Windows.UI.Composition/Compositor.cs +++ b/src/Uno.UI.Composition/Generated/3.0.0.0/Windows.UI.Composition/Compositor.cs @@ -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) { diff --git a/src/Uno.UI/UI/Xaml/Controls/Border/BorderLayerRenderer.skia.cs b/src/Uno.UI/UI/Xaml/Controls/Border/BorderLayerRenderer.skia.cs index d76e11615924..b3db479af33a 100644 --- a/src/Uno.UI/UI/Xaml/Controls/Border/BorderLayerRenderer.skia.cs +++ b/src/Uno.UI/UI/Xaml/Controls/Border/BorderLayerRenderer.skia.cs @@ -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(); @@ -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 { @@ -348,7 +343,7 @@ 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) { @@ -356,7 +351,7 @@ private static CompositionPath GetBorderPath(SKPoint[] outerRadii, SKPoint[] inn GetRoundedPath(area.ToSKRect(), outerRadii, geometrySource); GetRoundedPath(insetArea.ToSKRect(), innerRadii, geometrySource); geometrySource.Geometry.FillType = SKPathFillType.EvenOdd; - + return new CompositionPath(geometrySource); } diff --git a/src/Uno.UI/UI/Xaml/NonUniformCornerRadius.cs b/src/Uno.UI/UI/Xaml/NonUniformCornerRadius.cs index cb6f9386e884..3faf3abfe3fa 100644 --- a/src/Uno.UI/UI/Xaml/NonUniformCornerRadius.cs +++ b/src/Uno.UI/UI/Xaml/NonUniformCornerRadius.cs @@ -1,4 +1,5 @@ -using Windows.Foundation; +using System.Numerics; +using Windows.Foundation; namespace Windows.UI.Xaml; @@ -11,15 +12,15 @@ namespace Windows.UI.Xaml; /// Bottom left corner. 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; } diff --git a/src/Uno.UI/UI/Xaml/NonUniformCornerRadius.skia.cs b/src/Uno.UI/UI/Xaml/NonUniformCornerRadius.skia.cs index d1bc31903373..6b34e62ce306 100644 --- a/src/Uno.UI/UI/Xaml/NonUniformCornerRadius.skia.cs +++ b/src/Uno.UI/UI/Xaml/NonUniformCornerRadius.skia.cs @@ -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); } }