Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Windows] Improve performance of ContentPanel.EnsureBorderPath #22346

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
57 changes: 45 additions & 12 deletions src/Core/src/Platform/Windows/ContentPanel.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#nullable enable
using System;
using System;
using System.Numerics;
using Microsoft.Graphics.Canvas;
using Microsoft.Maui.Graphics;
Expand All @@ -8,7 +7,6 @@
using Microsoft.UI.Composition;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Hosting;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Shapes;

namespace Microsoft.Maui.Platform
Expand Down Expand Up @@ -50,38 +48,53 @@ public class ContentPanel : MauiPanel
public ContentPanel()
{
_borderPath = new Path();
EnsureBorderPath();
EnsureBorderPath(containsCheck: false);

SizeChanged += ContentPanelSizeChanged;
}

void ContentPanelSizeChanged(object sender, UI.Xaml.SizeChangedEventArgs e)
void ContentPanelSizeChanged(object sender, SizeChangedEventArgs e)
{
if (_borderPath is null)
{
return;
}

var width = e.NewSize.Width;
var height = e.NewSize.Height;

if (width <= 0 || height <= 0)
{
return;
}

_borderPath.UpdatePath(_borderStroke?.Shape, width, height);
UpdateClip(_borderStroke?.Shape, width, height);
}

internal void EnsureBorderPath()
internal void EnsureBorderPath(bool containsCheck = true)
{
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the main change.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also invoked from

handler.PlatformView.EnsureBorderPath();

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. I believe one cannot use containsCheck = false there though so I did not do it.

If it is not what you meant, please clarify.

if (!Children.Contains(_borderPath))
if (containsCheck)
{
var children = Children;

if (!children.Contains(_borderPath))
{
children.Add(_borderPath);
}
}
else
{
Children.Add(_borderPath);
}
}

public void UpdateBackground(Paint? background)
{
if (_borderPath == null)
if (_borderPath is null)
{
return;
}

_borderPath.UpdateBackground(background);
}
Expand All @@ -95,61 +108,81 @@ public void UpdateBorderShape(IShape borderShape)
internal void UpdateBorderStroke(IBorderStroke borderStroke)
{
if (borderStroke is null)
{
return;
}

_borderStroke = borderStroke;

if (_borderStroke is null)
{
return;
}

UpdateBorder(_borderStroke.Shape);
}

void UpdateBorder(IShape? strokeShape)
{
if (strokeShape is null || _borderPath is null)
{
return;
}

_borderPath.UpdateBorderShape(strokeShape, ActualWidth, ActualHeight);

var width = ActualWidth;
var height = ActualHeight;

if (width <= 0 || height <= 0)
{
return;
}

UpdateClip(strokeShape, width, height);
}

void AddContent(FrameworkElement? content)
{
if (content == null)
if (content is null)
{
return;
}

if (!Children.Contains(_content))
Children.Add(_content);
var children = Children;

if (!children.Contains(_content))
{
children.Add(_content);
}
}

void UpdateClip(IShape? borderShape, double width, double height)
{
if (Content is null)
{
return;
}

if (height <= 0 && width <= 0)
{
return;
}

var clipGeometry = borderShape;

if (clipGeometry is null)
{
return;
}

var visual = ElementCompositionPreview.GetElementVisual(Content);
var compositor = visual.Compositor;

PathF? clipPath;
float strokeThickness = (float)(_borderPath?.StrokeThickness ?? 0);
// The path size should consider the space taken by the border (top and bottom, left and right)
var pathSize = new Graphics.Rect(0, 0, width - strokeThickness * 2, height - strokeThickness * 2);
var pathSize = new Rect(0, 0, width - strokeThickness * 2, height - strokeThickness * 2);

if (clipGeometry is IRoundRectangle roundedRectangle)
{
Expand Down