[ShadowContainer] CornerRadius performance issue (#790)

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>
This commit is contained in:
Rafael Rosa 2023-09-14 16:44:08 -03:00 коммит произвёл GitHub
Родитель a0a15f56d1
Коммит 50eed7754b
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
3 изменённых файлов: 126 добавлений и 18 удалений

Просмотреть файл

@ -1,7 +1,7 @@
jobs:
- job: iOS_UITests
displayName: 'Run iOS UI Tests'
timeoutInMinutes: 90
timeoutInMinutes: 120
variables:
CI_Build: true
SourceLinkEnabled: false

Просмотреть файл

@ -29,6 +29,10 @@ using Microsoft.UI.Xaml;
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
{
@ -36,43 +40,107 @@ namespace Uno.Toolkit.RuntimeTests.Tests
[RunsOnUIThread]
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
{
Content = new Border { Height = 200, Width = 200, Background = new SolidColorBrush(Colors.Green) }
};
var shadowContainer = new ShadowContainer
{
Content = greenBorder
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) }
};
shadowContainer.Shadows.Add(new UI.Shadow
{
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);
}
[TestMethod]
@ -110,7 +178,6 @@ namespace Uno.Toolkit.RuntimeTests.Tests
await renderer.AssertColorAt(Colors.Green, 75, 225);
}
#if !(__ANDROID__ || __IOS__)
[TestMethod]
[DataRow(10, 10, false)]
[DataRow(10, 10, true)]
@ -174,6 +241,45 @@ namespace Uno.Toolkit.RuntimeTests.Tests
}
#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()
{

Просмотреть файл

@ -272,10 +272,12 @@ public partial class ShadowContainer
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);