Skip to content

Commit 9c7f669

Browse files
authored
Merge pull request #22678 from unoplatform/dev/xygu/20260217/skia-rendering-125
fix(skia): improve subpixel clipping and rendering
2 parents 8e56298 + 9494fb3 commit 9c7f669

3 files changed

Lines changed: 13 additions & 5 deletions

File tree

src/Uno.UI.Composition/Composition/CompositionColorBrush.skia.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ public partial class CompositionColorBrush
1010
{
1111
// We don't call SKPaint.Reset() after usage, so make sure
1212
// that only SKPaint.Color is being set
13-
private static readonly SKPaint _tempPaint = new();
13+
private static readonly SKPaint _tempPaint = new() { IsAntialias = true };
1414

1515
internal override void Paint(SKCanvas canvas, float opacity, SKRect bounds)
1616
{

src/Uno.UI.RuntimeTests/Tests/Windows_UI_Composition/Given_ShapeVisual.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,18 +95,25 @@ await UITestHelper.Load(new StackPanel()
9595
await TestServices.WindowHelper.WaitFor(() => imageOpened);
9696

9797
var screenShot1 = await UITestHelper.ScreenShot(border);
98+
var screenShot2 = await UITestHelper.ScreenShot(referenceImage);
9899
// To generate the images
99100
// await screenShot1.Save(filename);
100101

101-
var screenShot2 = await UITestHelper.ScreenShot(referenceImage);
102102
// there can be a very small _bit_ difference when drawing with metal on some platforms
103103
if (OperatingSystem.IsMacOS() || OperatingSystem.IsBrowser() || OperatingSystem.IsIOS() || OperatingSystem.IsAndroid())
104104
{
105105
await ImageAssert.AreSimilarAsync(screenShot1, screenShot2);
106106
}
107107
else
108108
{
109-
await ImageAssert.AreEqualAsync(screenShot1, screenShot2);
109+
// with anti-aliasing in CompositionColorBrush, there can be some minor differences sometimes, but not always
110+
// so here we first check for pixel equality, and only if that fails we check for similarity,
111+
// to avoid the performance cost of the similarity check when not needed.
112+
var pixelEqual = await ImageAssert.AreRenderTargetBitmapsEqualAsync(screenShot1.Bitmap, screenShot2.Bitmap);
113+
if (!pixelEqual)
114+
{
115+
await ImageAssert.AreSimilarAsync(screenShot1, screenShot2);
116+
}
110117
}
111118
}
112119
}

src/Uno.UI/UI/Xaml/FrameworkElement.Layout.crossruntime.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,7 @@ void ArrangeCoreWithTrace(Rect finalRect)
515515
}
516516

517517
private static bool IsLessThanAndNotCloseTo(double a, double b) => a < (b - SIZE_EPSILON);
518+
private static bool IsCloseTo(double a, double b) => Math.Abs(a - b) < SIZE_EPSILON;
518519

519520
private void InnerArrangeCore(Rect finalRect)
520521
{
@@ -576,7 +577,7 @@ private void InnerArrangeCore(Rect finalRect)
576577
if (roundedMarginWidth != marginWidth && arrangeSizeWithoutMargin.Width != unclippedDesiredSize.Width)
577578
{
578579
double arrangeWidthWithoutRoundedMargin = Math.Max(arrangeSize.Width - roundedMarginWidth, 0);
579-
if (arrangeWidthWithoutRoundedMargin == unclippedDesiredSize.Width)
580+
if (IsCloseTo(arrangeWidthWithoutRoundedMargin, unclippedDesiredSize.Width))
580581
{
581582
// The rounding difference between arrangeSizeWithoutMargin.width and unclippedDesiredSize.width
582583
// comes from the horizontal margin. The rounded value of that margin must be used so that this
@@ -597,7 +598,7 @@ private void InnerArrangeCore(Rect finalRect)
597598
if (roundedMarginHeight != marginHeight && arrangeSizeWithoutMargin.Height != unclippedDesiredSize.Height)
598599
{
599600
double arrangeHeightWithoutRoundedMargin = Math.Max(arrangeSize.Height - roundedMarginHeight, 0);
600-
if (arrangeHeightWithoutRoundedMargin == unclippedDesiredSize.Height)
601+
if (IsCloseTo(arrangeHeightWithoutRoundedMargin, unclippedDesiredSize.Height))
601602
{
602603
// The rounding difference between arrangeSizeWithoutMargin.height and unclippedDesiredSize.height
603604
// comes from the vertical margin. The rounded value of that margin must be used so that this

0 commit comments

Comments
 (0)