Skip to content

Commit

Permalink
[ShadowContainer] CornerRadius performance issue (#790)
Browse files Browse the repository at this point in the history
Co-authored-by: Xiaotian Gu <xiaoyao312@gmail.com>
Co-authored-by: Rafael Rosa <rafaelmendesrosa@gmail.com>
Co-authored-by: Jérôme Laban <jlaban@gmail.com>
(cherry picked from commit 50eed77)

# Conflicts:
#	build/workflow/stage-uitests-ios.yml
  • Loading branch information
rafael-rosa-knowcode authored and mergify[bot] committed Sep 14, 2023
1 parent 5b0064b commit c35a74d
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 15 deletions.
4 changes: 4 additions & 0 deletions build/workflow/stage-uitests-ios.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,14 @@

- job: iOS_UITests
displayName: 'Run iOS UI Tests'
<<<<<<< HEAD
dependsOn:
- iOS_Build_For_Tests
- Toolkit_UITests_Build
timeoutInMinutes: 90
=======
timeoutInMinutes: 120
>>>>>>> 50eed77 ([ShadowContainer] CornerRadius performance issue (#790))
variables:
CI_Build: true
SourceLinkEnabled: false
Expand Down
129 changes: 118 additions & 11 deletions src/Uno.Toolkit.RuntimeTests/Tests/ShadowContainerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@
using Microsoft.UI.Xaml.Media.Imaging;
using Windows.UI.ViewManagement;
using FluentAssertions;
using SkiaSharp;
using SkiaSharp.Views.Windows;
using System.Drawing;
using Windows.Globalization.DateTimeFormatting;

namespace Uno.Toolkit.RuntimeTests.Tests
{
Expand All @@ -36,43 +40,107 @@ namespace Uno.Toolkit.RuntimeTests.Tests
#endif
internal partial class ShadowContainerTests
{

#if !(__ANDROID__ || __IOS__)

[TestMethod]
public async Task Displays_Content()
[DataRow(10, 10, false, 0)]
[DataRow(-10, -10, false, 0)]
[DataRow(10, 10, true, 0)]
[DataRow(-10, -10, true, 0)]
[DataRow(10, 10, false, 100)]
[DataRow(-10, -10, false, 100)]
[DataRow(10, 10, true, 100)]
[DataRow(-10, -10, true, 100)]
public async Task ShadowsCornerRadius_Content(int offsetX, int offsetY, bool inner, double bottomRightCorner)
{
if (!ImageAssertHelper.IsScreenshotSupported())
{
Assert.Inconclusive(); // System.NotImplementedException: RenderTargetBitmap is not supported on this platform.;
}

var greenBorder = new ShadowContainer
var shadowContainer = new ShadowContainer
{
Content = new Border { Height = 200, Width = 200, Background = new SolidColorBrush(Colors.Green) }
HorizontalAlignment = HorizontalAlignment.Left,
VerticalAlignment = VerticalAlignment.Top,
Background = new SolidColorBrush(Colors.Green),
Content = new Border { Height = 200, Width = 200, CornerRadius = new CornerRadius(0, 0, bottomRightCorner, 0) }
};

var shadowContainer = new ShadowContainer
shadowContainer.Shadows.Add(new UI.Shadow
{
Content = greenBorder
};
Color = Colors.Red,
OffsetX = offsetX,
OffsetY = offsetY,
IsInner = inner,
Opacity = 1,
});

var stackPanel = new StackPanel
{
Width = 220,
Height = 220,
Padding = new Thickness(10),
Background = new SolidColorBrush(Colors.Yellow),
HorizontalAlignment = HorizontalAlignment.Center,
Children =
{
new Border { Height = 200, Width = 200, Background = new SolidColorBrush(Colors.Red) },
shadowContainer,
new Border { Height = 200, Width = 200, Background = new SolidColorBrush(Colors.Red) },
}
};

var absOffsetX = Math.Abs(offsetX);
var absOffsetY = Math.Abs(offsetY);
var canvasMargin = absOffsetX + absOffsetY;
UnitTestsUIContentHelper.Content = stackPanel;

await UnitTestsUIContentHelper.WaitForIdle();
await UnitTestsUIContentHelper.WaitForLoaded(stackPanel);
await Task.Yield();

//Validate current structure.
var grid = shadowContainer.GetChildren().First() as Grid;
var canvas = grid?.GetChildren().First() as Canvas;
var skXamlCanvas = canvas?.GetChildren().First() as SKXamlCanvas;
var contentPresenter = grid?.GetChildren().Skip(1).First() as ContentPresenter;
var border = contentPresenter?.GetChildren().First() as Border;

//Validate element measurements
Assert.AreEqual(grid?.ActualWidth, canvas?.ActualWidth);
Assert.AreEqual(canvas?.ActualWidth, border?.ActualWidth);
Assert.AreEqual(skXamlCanvas?.ActualWidth, border?.ActualWidth + canvasMargin);

//Validate point colors
var renderer = await stackPanel.TakeScreenshot();
await renderer.AssertColorAt(Colors.Green, 100, 300);

//Set 4 coners positions to be validated
var leftX = inner ? absOffsetX + 1 : 1;
var rightX = (int)((stackPanel?.ActualWidth ?? 0) - (inner ? absOffsetX + 1 : 1));
var topY = inner ? absOffsetY + 1 : 1;
var bottomY = (int)((stackPanel?.ActualHeight ?? 0) - (inner ? absOffsetX + 1 : 1));


var topLeftColor =
inner
? (offsetX < 0 ? Colors.Green : Colors.Red)
: (offsetX < 0 ? Colors.Red : Colors.Yellow);
await renderer.AssertColorAt(topLeftColor, leftX, topY);

//TopRight
var topRightColor = inner ? Colors.Red : Colors.Yellow;
await renderer.AssertColorAt(topRightColor, rightX, topY);

//BottomRight and CornerCurve
//Case we have RightCorner the Bottom will always be Yellow
var bottomRightColor =
bottomRightCorner > 50
? Colors.Yellow
: offsetX < 0
? inner ? Colors.Red : Colors.Yellow
: inner ? Colors.Green : Colors.Red;
await renderer.AssertColorAt(bottomRightColor, rightX, bottomY);

//BottomLeft
await renderer.AssertColorAt(Colors.Yellow, leftX, bottomY);

}

#if !(__ANDROID__ || __IOS__)
Expand Down Expand Up @@ -174,6 +242,45 @@ public async Task Outer_Shadows(int offsetX, int offsetY, bool inner)
}
#endif

[TestMethod]
public async Task Displays_Content()
{
if (!ImageAssertHelper.IsScreenshotSupported())
{
Assert.Inconclusive(); // System.NotImplementedException: RenderTargetBitmap is not supported on this platform.;
}

var greenBorder = new ShadowContainer
{
Content = new Border { Height = 200, Width = 200, Background = new SolidColorBrush(Colors.Green) }
};

var shadowContainer = new ShadowContainer
{
Content = greenBorder
};

var stackPanel = new StackPanel
{
Background = new SolidColorBrush(Colors.Yellow),
HorizontalAlignment = HorizontalAlignment.Center,
Children =
{
new Border { Height = 200, Width = 200, Background = new SolidColorBrush(Colors.Red) },
shadowContainer,
new Border { Height = 200, Width = 200, Background = new SolidColorBrush(Colors.Red) },
}
};

UnitTestsUIContentHelper.Content = stackPanel;

await UnitTestsUIContentHelper.WaitForIdle();
await UnitTestsUIContentHelper.WaitForLoaded(stackPanel);

var renderer = await stackPanel.TakeScreenshot();
await renderer.AssertColorAt(Colors.Green, 100, 300);
}

[TestMethod]
public async Task ShadowContainer_ReLayoutsAfterChangeInSize()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -272,10 +272,12 @@ private record CornerRadiusRectShadowShapeContext(double Width, double Height, C
protected override SKRoundRect GetContentShape(ShadowPaintState state)
{
var rect = new SKRect(0, 0, (float)Width * state.PixelRatio, (float)Height * state.PixelRatio);
var radii = new[] { CornerRadius.TopLeft, CornerRadius.TopRight, CornerRadius.BottomRight, CornerRadius.BottomLeft }
.Select(x => (float)x * state.PixelRatio)
.Select(x => new SKPoint(x, x))
.ToArray();
var radii = new SKPoint[] {
new SKPoint((float)CornerRadius.TopLeft * state.PixelRatio, (float)CornerRadius.TopLeft * state.PixelRatio),
new SKPoint((float)CornerRadius.TopRight * state.PixelRatio, (float)CornerRadius.TopRight * state.PixelRatio),
new SKPoint((float)CornerRadius.BottomRight * state.PixelRatio,(float)CornerRadius.BottomRight * state.PixelRatio),
new SKPoint((float)CornerRadius.BottomLeft * state.PixelRatio, (float)CornerRadius.BottomLeft * state.PixelRatio)
};
var shape = new SKRoundRect();
shape.SetRectRadii(rect, radii);

Expand Down

0 comments on commit c35a74d

Please sign in to comment.