forked from unoplatform/uno
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request unoplatform#15332 from unoplatform/dev/mazi/border…
…layer-unstatic refactor: Simplify `BorderLayerRenderer` on Skia
- Loading branch information
Showing
36 changed files
with
443 additions
and
250 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
17 changes: 17 additions & 0 deletions
17
src/Uno.UI/UI/Xaml/Controls/Border/Border.IBorderInfoProvider.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
using Uno.UI.Xaml.Controls; | ||
using Microsoft.UI.Xaml.Media; | ||
|
||
namespace Microsoft.UI.Xaml.Controls; | ||
|
||
partial class Border : IBorderInfoProvider | ||
{ | ||
Brush IBorderInfoProvider.Background => Background; | ||
|
||
BackgroundSizing IBorderInfoProvider.BackgroundSizing => BackgroundSizing; | ||
|
||
Brush IBorderInfoProvider.BorderBrush => BorderBrush; | ||
|
||
Thickness IBorderInfoProvider.BorderThickness => BorderThickness; | ||
|
||
CornerRadius IBorderInfoProvider.CornerRadius => CornerRadius; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
97 changes: 33 additions & 64 deletions
97
src/Uno.UI/UI/Xaml/Controls/Border/BorderLayerRenderer.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,84 +1,53 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Text; | ||
using Windows.Foundation; | ||
#if __SKIA__ | ||
using System; | ||
using Microsoft.UI.Xaml; | ||
using Uno.UI; | ||
using Uno.Disposables; | ||
|
||
namespace Microsoft.UI.Xaml.Shapes; | ||
namespace Uno.UI.Xaml.Controls; | ||
|
||
/// <summary> | ||
/// Provides Border and Background rendering capabilities to a UI element. | ||
/// </summary> | ||
internal partial class BorderLayerRenderer | ||
{ | ||
/* The border is defined by the inner and outer rounded-rectangles. | ||
* Each rounded rectangle is composed of 4x lines and 4x 90' arcs. | ||
* ╭─────╮ | ||
* │A 2 B│ | ||
* │1 3│ | ||
* │D 4 C│ | ||
* ╰─────╯ | ||
* Three factors determine the border: BorderThickness, CornerRadius, and AvailableSize. | ||
* What each part affects: | ||
* - CornerRadius="1A2,2B3,3C4,4D1" | ||
* - BorderThickness="D1A,A2B,B3C,C4D" | ||
* - AvailableSize is used to constrain the radius. | ||
* | ||
* note: technically CornerRadius (together with AvailableSize) also affects the adjacent corner, | ||
* as both points on the same axis will compete for what's available when both add up exceeds | ||
* the available length. (see: h/vRatio in CalculateBorderEllipse) | ||
*/ | ||
private readonly FrameworkElement _owner; | ||
private readonly IBorderInfoProvider _borderInfoProvider; | ||
|
||
public enum Corner { TopLeft, TopRight, BottomRight, BottomLeft } | ||
private BorderLayerState _currentState; | ||
|
||
public static Rect CalculateBorderEllipseBbox(Rect bbox, Corner corner, CornerRadius cr, Thickness bt, bool inner = false) | ||
public BorderLayerRenderer(FrameworkElement owner) | ||
{ | ||
var (cr0, hThickness, vThickness, hComplement, vComplement) = corner switch | ||
_owner = owner ?? throw new ArgumentNullException(nameof(owner)); | ||
if (owner is not IBorderInfoProvider borderInfoProvider) | ||
{ | ||
Corner.TopLeft => (cr.TopLeft, bt.Left, bt.Top, cr.TopRight, cr.BottomLeft), | ||
Corner.TopRight => (cr.TopRight, bt.Right, bt.Top, cr.TopLeft, cr.BottomRight), | ||
Corner.BottomRight => (cr.BottomRight, bt.Right, bt.Bottom, cr.BottomLeft, cr.TopRight), | ||
Corner.BottomLeft => (cr.BottomLeft, bt.Left, bt.Bottom, cr.BottomRight, cr.TopLeft), | ||
throw new InvalidOperationException("BorderLayerRenderer requires an owner which implements IBorderInfoProvider"); | ||
} | ||
|
||
_ => throw new ArgumentOutOfRangeException($"Invalid corner: {corner}"), | ||
}; | ||
_borderInfoProvider = borderInfoProvider; | ||
|
||
// there is still a corner to be painted, albeit not rounded. | ||
if (cr0 == 0) return AlignCorner(bbox, corner, default); | ||
|
||
// The ellipse can only grow up to twice the available length. | ||
// This is further limited by the ratio between the corner-radius | ||
// of that corner and the adjacent corner on the same line. | ||
var hRatio = hComplement == 0 ? 1 : (cr0 / (cr0 + hComplement)); | ||
var vRatio = vComplement == 0 ? 1 : (cr0 / (cr0 + vComplement)); | ||
|
||
// if size is empty here, there is still a corner to be painted, just not rounded. | ||
var size = new Size( | ||
width: Math.Max(0, Math.Min(bbox.Width * 2 * hRatio, cr0 * 2 + (inner ? -hThickness : hThickness))), | ||
height: Math.Max(0, Math.Min(bbox.Height * 2 * vRatio, cr0 * 2 + (inner ? -vThickness : vThickness))) | ||
); | ||
var result = AlignCorner(bbox, corner, size); | ||
|
||
return result; | ||
_owner.Loaded += (s, e) => Update(); | ||
_owner.Unloaded += (s, e) => Clear(); | ||
_owner.LayoutUpdated += (s, e) => Update(); | ||
} | ||
|
||
/// <summary> | ||
/// Arrange a size on the bounding-<paramref name="bbox"/> so that the borders neighboring | ||
/// to the <paramref name="corner"/> are overlapped. | ||
/// Updates the border. | ||
/// </summary> | ||
/// <remarks>The resulting rect can be outside of the bounding-box.</remarks> | ||
private static Rect AlignCorner(Rect bbox, Corner corner, Size size) | ||
internal void Update() | ||
{ | ||
// note: the ellipse can project outside the bounding-box | ||
// because only a quarter needs to be constrained within. | ||
var location = (Point)(corner switch | ||
if (_owner.IsLoaded) | ||
{ | ||
Corner.TopLeft => new(bbox.Left, bbox.Top), | ||
Corner.TopRight => new(bbox.Left + bbox.Width - size.Width, bbox.Top), | ||
Corner.BottomRight => new(bbox.Left + bbox.Width - size.Width, bbox.Top + bbox.Height - size.Height), | ||
Corner.BottomLeft => new(bbox.Left, bbox.Top + bbox.Height - size.Height), | ||
UpdatePlatform(); | ||
} | ||
} | ||
|
||
_ => throw new ArgumentOutOfRangeException($"Invalid corner: {corner}"), | ||
}); | ||
/// <summary> | ||
/// Removes added layers and subscriptions. | ||
/// </summary> | ||
internal void Clear() => ClearPlatform(); | ||
|
||
return new(location, size); | ||
} | ||
partial void UpdatePlatform(); | ||
|
||
partial void ClearPlatform(); | ||
} | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
30 changes: 15 additions & 15 deletions
30
src/Uno.UI/UI/Xaml/Controls/Border/BorderLayerRenderer.reference.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,19 @@ | ||
using Microsoft.UI.Xaml.Controls; | ||
using Microsoft.UI.Xaml; | ||
using Microsoft.UI.Xaml.Controls; | ||
using Microsoft.UI.Xaml.Media; | ||
|
||
namespace Microsoft.UI.Xaml.Shapes | ||
namespace Uno.UI.Xaml.Controls; | ||
|
||
partial class BorderLayerRenderer | ||
{ | ||
partial class BorderLayerRenderer | ||
{ | ||
public void UpdateLayer( | ||
FrameworkElement owner, | ||
Brush background, | ||
BackgroundSizing backgroundSizing, | ||
Thickness borderThickness, | ||
Brush borderBrush, | ||
CornerRadius cornerRadius, | ||
object backgroundImage | ||
) | ||
{ } | ||
} | ||
public void UpdateLayer( | ||
FrameworkElement owner, | ||
Brush background, | ||
BackgroundSizing backgroundSizing, | ||
Thickness borderThickness, | ||
Brush borderBrush, | ||
CornerRadius cornerRadius, | ||
object backgroundImage | ||
) | ||
{ } | ||
} |
Oops, something went wrong.