diff --git a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs index f4ebd33c3f5..96f43b554b8 100644 --- a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs +++ b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs @@ -964,34 +964,39 @@ private static void ConfigureGradientBrush(ref PaintWrapper paintWrapper, Rect t (originPoint.Y - centerPoint.Y) * radiusX / radiusY + centerPoint.Y); var origin = originPoint.ToSKPoint(); - - // reverse the order of the stops to match D2D - var reversedColors = new SKColor[stopColors.Length]; - Array.Copy(stopColors, reversedColors, stopColors.Length); - Array.Reverse(reversedColors); + + var endOffset = 0.0; // and then reverse the reference point of the stops var reversedStops = new float[stopOffsets.Length]; for (var i = 0; i < stopOffsets.Length; i++) { - reversedStops[i] = stopOffsets[i]; + var offset = stopOffsets[i]; + + if (endOffset < offset) + { + endOffset = offset; + } + + reversedStops[i] = offset; + if (reversedStops[i] > 0 && reversedStops[i] < 1) { - reversedStops[i] = Math.Abs(1 - stopOffsets[i]); + reversedStops[i] = Math.Abs(1 - offset); } } // compose with a background colour of the final stop to match D2D's behaviour of filling with the final color using (var shader = SKShader.CreateCompose( - SKShader.CreateColor(reversedColors[0]), - transform.HasValue - ? SKShader.CreateTwoPointConicalGradient(center, (float)radiusX, origin, 0, - reversedColors, reversedStops, tileMode, transform.Value.ToSKMatrix()) - : SKShader.CreateTwoPointConicalGradient(center, (float)radiusX, origin, 0, - reversedColors, reversedStops, tileMode) - - ) - ) + SKShader.CreateColor(stopColors[0]), + transform.HasValue + ? SKShader.CreateTwoPointConicalGradient(start, radiusStart, end, radiusEnd, + stopColors, stopOffsets, tileMode, transform.Value.ToSKMatrix()) + : SKShader.CreateTwoPointConicalGradient(start, radiusStart, end, radiusEnd, + stopColors, stopOffsets, tileMode) + + ) + ) { paintWrapper.Paint.Shader = shader; } diff --git a/tests/Avalonia.RenderTests/Media/RadialGradientBrushTests.cs b/tests/Avalonia.RenderTests/Media/RadialGradientBrushTests.cs index c70d5a2c9bf..bffacf4543e 100644 --- a/tests/Avalonia.RenderTests/Media/RadialGradientBrushTests.cs +++ b/tests/Avalonia.RenderTests/Media/RadialGradientBrushTests.cs @@ -19,6 +19,32 @@ public RadialGradientBrushTests() : base(@"Media\RadialGradientBrush") { } + [Fact] + public async Task RadialGradientBrush_Partial_Cover() + { + Decorator target = new Decorator + { + Padding = new Thickness(8), + Width = 200, + Height = 200, + Child = new Border + { + Background = new RadialGradientBrush + { + GradientStops = + { + new GradientStop { Color = Colors.White, Offset = 0 }, + new GradientStop { Color = Color.Parse("#00DD00"), Offset = 0.7 } + }, + GradientOrigin = new RelativePoint(0.7, 0.15, RelativeUnit.Relative) + } + } + }; + + await RenderToFile(target); + CompareImages(); + } + [Fact] public async Task RadialGradientBrush_RedBlue() { diff --git a/tests/TestFiles/Direct2D1/Media/RadialGradientBrush/RadialGradientBrush_Partial_Cover.expected.png b/tests/TestFiles/Direct2D1/Media/RadialGradientBrush/RadialGradientBrush_Partial_Cover.expected.png new file mode 100644 index 00000000000..f36b6360833 Binary files /dev/null and b/tests/TestFiles/Direct2D1/Media/RadialGradientBrush/RadialGradientBrush_Partial_Cover.expected.png differ diff --git a/tests/TestFiles/Skia/Media/RadialGradientBrush/RadialGradientBrush_Partial_Cover.expected.png b/tests/TestFiles/Skia/Media/RadialGradientBrush/RadialGradientBrush_Partial_Cover.expected.png new file mode 100644 index 00000000000..efdf280e669 Binary files /dev/null and b/tests/TestFiles/Skia/Media/RadialGradientBrush/RadialGradientBrush_Partial_Cover.expected.png differ