Skip to content

Commit

Permalink
perf(android): Adjust clipping computation performance
Browse files Browse the repository at this point in the history
  • Loading branch information
jeromelaban committed Sep 3, 2021
1 parent a234799 commit 6b3f2eb
Showing 1 changed file with 52 additions and 25 deletions.
77 changes: 52 additions & 25 deletions src/Uno.UI/UI/Xaml/UIElement.Android.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,29 +22,55 @@ namespace Windows.UI.Xaml
public partial class UIElement : BindableView
{
/// <summary>
/// Returns true if this element has children and they are all native (non-UIElements), false if it has no children or if at
/// least one is a UIElement.
/// Keeps the count of native children (non-UIElements), for clipping purpoess.
/// </summary>
private bool AreChildrenNativeViewsOnly
private int _nativeChildrenCount;
private bool _nativeClipChildren;

private Rect _previousClip = Rect.Empty;

private void ComputeAreChildrenNativeViewsOnly()
{
get
var nativeClipChildren = (this as IShadowChildrenProvider).ChildrenShadow.Count == _nativeChildrenCount;

if (_nativeClipChildren != nativeClipChildren)
{
var shadow = (this as IShadowChildrenProvider).ChildrenShadow;
if (shadow.Count == 0)
{
return false;
}
_nativeClipChildren = nativeClipChildren;

foreach (var child in shadow)
{
if (child is UIElement)
{
return false;
}
}
// Non-UIElements typically expect to be clipped, and display incorrectly otherwise
// This won't work when UIElements and non-UIElements are mixed in the same Panel,
// but it should cover most cases in practice, and anyway should be superceded when
// IFrameworkElement will be removed.
SetClipChildren(FeatureConfiguration.UIElement.AlwaysClipNativeChildren ? _nativeClipChildren : false);
}
}

return true;
protected override void OnLocalViewRemoved(View view)
{
base.OnLocalViewRemoved(view);

if (!(view is UIElement))
{
_nativeChildrenCount--;
}

ComputeAreChildrenNativeViewsOnly();
}

/// <summary>
/// Invoked when a child view has been added.
/// </summary>
/// <param name="view">The view being removed</param>
protected override void OnChildViewAdded(View view)
{
base.OnChildViewAdded(view);

if(!(view is UIElement))
{
_nativeChildrenCount++;
}

ComputeAreChildrenNativeViewsOnly();
}

public UIElement()
Expand All @@ -54,7 +80,6 @@ public UIElement()
InitializePointers();
}


/// <summary>
/// Determines if InvalidateMeasure has been called
/// </summary>
Expand All @@ -67,18 +92,20 @@ public UIElement()

partial void ApplyNativeClip(Rect rect)
{
// Non-UIElements typically expect to be clipped, and display incorrectly otherwise
// This won't work when UIElements and non-UIElements are mixed in the same Panel,
// but it should cover most cases in practice, and anyway should be superceded when
// IFrameworkElement will be removed.
SetClipChildren(FeatureConfiguration.UIElement.AlwaysClipNativeChildren ? AreChildrenNativeViewsOnly : false);

if (rect.IsEmpty)
{
ViewCompat.SetClipBounds(this, null);
if (_previousClip != rect)
{
_previousClip = rect;

ViewCompat.SetClipBounds(this, null);
}

return;
}

_previousClip = rect;

var physicalRect = rect.LogicalToPhysicalPixels();
if (FrameRoundingAdjustment is { } fra)
{
Expand Down

0 comments on commit 6b3f2eb

Please sign in to comment.