diff --git a/src/Avalonia.Visuals/Avalonia.Visuals.csproj b/src/Avalonia.Visuals/Avalonia.Visuals.csproj
index a167cbe753..41e8857e6f 100644
--- a/src/Avalonia.Visuals/Avalonia.Visuals.csproj
+++ b/src/Avalonia.Visuals/Avalonia.Visuals.csproj
@@ -73,10 +73,12 @@
+
+
diff --git a/src/Avalonia.Visuals/Media/IRadialGradientBrush.cs b/src/Avalonia.Visuals/Media/IRadialGradientBrush.cs
new file mode 100644
index 0000000000..a9d902dabe
--- /dev/null
+++ b/src/Avalonia.Visuals/Media/IRadialGradientBrush.cs
@@ -0,0 +1,23 @@
+namespace Avalonia.Media
+{
+ ///
+ /// Paints an area with a radial gradient.
+ ///
+ public interface IRadialGradientBrush : IGradientBrush
+ {
+ ///
+ /// Gets the start point for the gradient.
+ ///
+ RelativePoint Center { get; }
+
+ ///
+ /// Gets the location of the two-dimensional focal point that defines the beginning of the gradient.
+ ///
+ RelativePoint GradientOrigin { get; }
+
+ ///
+ /// Gets the horizontal and vertical radius of the outermost circle of the radial gradient.
+ ///
+ double Radius { get; }
+ }
+}
\ No newline at end of file
diff --git a/src/Avalonia.Visuals/Media/Immutable/ImmutableLinearGradientBrush.cs b/src/Avalonia.Visuals/Media/Immutable/ImmutableLinearGradientBrush.cs
index 985e535b22..b46ee951f7 100644
--- a/src/Avalonia.Visuals/Media/Immutable/ImmutableLinearGradientBrush.cs
+++ b/src/Avalonia.Visuals/Media/Immutable/ImmutableLinearGradientBrush.cs
@@ -12,7 +12,7 @@ namespace Avalonia.Media.Immutable
public class ImmutableLinearGradientBrush : ImmutableGradientBrush, ILinearGradientBrush
{
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
/// The gradient stops.
/// The opacity of the brush.
@@ -32,7 +32,7 @@ namespace Avalonia.Media.Immutable
}
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
/// The brush from which this brush's properties should be copied.
public ImmutableLinearGradientBrush(ILinearGradientBrush source)
diff --git a/src/Avalonia.Visuals/Media/Immutable/ImmutableRadialGradientBrush.cs b/src/Avalonia.Visuals/Media/Immutable/ImmutableRadialGradientBrush.cs
new file mode 100644
index 0000000000..cc2c7b3697
--- /dev/null
+++ b/src/Avalonia.Visuals/Media/Immutable/ImmutableRadialGradientBrush.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Collections.Generic;
+
+namespace Avalonia.Media.Immutable
+{
+ ///
+ /// A brush that draws with a radial gradient.
+ ///
+ public class ImmutableRadialGradientBrush : ImmutableGradientBrush, IRadialGradientBrush
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The gradient stops.
+ /// The opacity of the brush.
+ /// The spread method.
+ /// The start point for the gradient.
+ ///
+ /// The location of the two-dimensional focal point that defines the beginning of the gradient.
+ ///
+ ///
+ /// The horizontal and vertical radius of the outermost circle of the radial gradient.
+ ///
+ public ImmutableRadialGradientBrush(
+ IReadOnlyList gradientStops,
+ double opacity = 1,
+ GradientSpreadMethod spreadMethod = GradientSpreadMethod.Pad,
+ RelativePoint? center = null,
+ RelativePoint? gradientOrigin = null,
+ double radius = 0.5)
+ : base(gradientStops, opacity, spreadMethod)
+ {
+ Center = center ?? RelativePoint.Center;
+ GradientOrigin = gradientOrigin ?? RelativePoint.Center;
+ Radius = radius;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The brush from which this brush's properties should be copied.
+ public ImmutableRadialGradientBrush(IRadialGradientBrush source)
+ : base(source)
+ {
+ Center = source.Center;
+ GradientOrigin = source.GradientOrigin;
+ Radius = source.Radius;
+ }
+
+ ///
+ public RelativePoint Center { get; }
+
+ ///
+ public RelativePoint GradientOrigin { get; }
+
+ ///
+ public double Radius { get; }
+ }
+}
diff --git a/src/Avalonia.Visuals/Media/RadialGradientBrush.cs b/src/Avalonia.Visuals/Media/RadialGradientBrush.cs
index 70657abe88..a78cd86afe 100644
--- a/src/Avalonia.Visuals/Media/RadialGradientBrush.cs
+++ b/src/Avalonia.Visuals/Media/RadialGradientBrush.cs
@@ -1,13 +1,14 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
+using System;
+
namespace Avalonia.Media
{
///
- /// Paints an area with a radial gradient. A focal point defines the beginning of the gradient,
- /// and a circle defines the end point of the gradient.
+ /// Paints an area with a radial gradient.
///
- public sealed class RadialGradientBrush : GradientBrush
+ public sealed class RadialGradientBrush : GradientBrush, IRadialGradientBrush, IMutableBrush
{
///
/// Defines the property.
@@ -54,10 +55,17 @@ namespace Avalonia.Media
///
/// Gets or sets the horizontal and vertical radius of the outermost circle of the radial gradient.
///
+ // TODO: This appears to always be relative so should use a RelativeSize struct or something.
public double Radius
{
get { return GetValue(RadiusProperty); }
set { SetValue(RadiusProperty, value); }
}
+
+ ///
+ IBrush IMutableBrush.ToImmutable()
+ {
+ return new Immutable.ImmutableRadialGradientBrush(this);
+ }
}
}
\ No newline at end of file
diff --git a/src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs b/src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs
index 20b5f54784..623f18ea0c 100644
--- a/src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs
+++ b/src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs
@@ -320,7 +320,7 @@ namespace Avalonia.Direct2D1.Media
{
var solidColorBrush = brush as Avalonia.Media.ISolidColorBrush;
var linearGradientBrush = brush as Avalonia.Media.ILinearGradientBrush;
- var radialGradientBrush = brush as Avalonia.Media.RadialGradientBrush;
+ var radialGradientBrush = brush as Avalonia.Media.IRadialGradientBrush;
var imageBrush = brush as Avalonia.Media.IImageBrush;
var visualBrush = brush as Avalonia.Media.IVisualBrush;
diff --git a/src/Windows/Avalonia.Direct2D1/Media/RadialGradientBrushImpl.cs b/src/Windows/Avalonia.Direct2D1/Media/RadialGradientBrushImpl.cs
index 72779096ff..be972c0173 100644
--- a/src/Windows/Avalonia.Direct2D1/Media/RadialGradientBrushImpl.cs
+++ b/src/Windows/Avalonia.Direct2D1/Media/RadialGradientBrushImpl.cs
@@ -8,7 +8,7 @@ namespace Avalonia.Direct2D1.Media
public class RadialGradientBrushImpl : BrushImpl
{
public RadialGradientBrushImpl(
- Avalonia.Media.RadialGradientBrush brush,
+ Avalonia.Media.IRadialGradientBrush brush,
SharpDX.Direct2D1.RenderTarget target,
Size destinationSize)
{
@@ -24,11 +24,11 @@ namespace Avalonia.Direct2D1.Media
}).ToArray();
var centerPoint = brush.Center.ToPixels(destinationSize);
- var GradientOriginOffset = brush.GradientOrigin.ToPixels(destinationSize);
+ var gradientOrigin = brush.GradientOrigin.ToPixels(destinationSize) - centerPoint;
// Note: Direct2D supports RadiusX and RadiusY but Cairo backend supports only Radius property
- var radiusX = brush.Radius;
- var radiusY = brush.Radius;
+ var radiusX = brush.Radius * destinationSize.Width;
+ var radiusY = brush.Radius * destinationSize.Height;
using (var stops = new SharpDX.Direct2D1.GradientStopCollection(
target,
@@ -40,7 +40,7 @@ namespace Avalonia.Direct2D1.Media
new SharpDX.Direct2D1.RadialGradientBrushProperties
{
Center = centerPoint.ToSharpDX(),
- GradientOriginOffset = GradientOriginOffset.ToSharpDX(),
+ GradientOriginOffset = gradientOrigin.ToSharpDX(),
RadiusX = (float)radiusX,
RadiusY = (float)radiusY
},
diff --git a/tests/Avalonia.RenderTests/Avalonia.Cairo.RenderTests.v3.ncrunchproject b/tests/Avalonia.RenderTests/Avalonia.Cairo.RenderTests.v3.ncrunchproject
index bc70262c50..5c2560547a 100644
--- a/tests/Avalonia.RenderTests/Avalonia.Cairo.RenderTests.v3.ncrunchproject
+++ b/tests/Avalonia.RenderTests/Avalonia.Cairo.RenderTests.v3.ncrunchproject
@@ -70,6 +70,9 @@
Avalonia.Cairo.RenderTests.Media.LinearGradientBrushTests.LinearGradientBrush_RedBlue_Horizontal_Fill
+
+ Avalonia.Cairo.RenderTests.Media.RadialGradientBrushTests.RadialGradientBrush_RedBlue
+
True
diff --git a/tests/Avalonia.RenderTests/Avalonia.RenderTests.projitems b/tests/Avalonia.RenderTests/Avalonia.RenderTests.projitems
index ad3b182bdf..cf86e80d92 100644
--- a/tests/Avalonia.RenderTests/Avalonia.RenderTests.projitems
+++ b/tests/Avalonia.RenderTests/Avalonia.RenderTests.projitems
@@ -10,6 +10,7 @@
+
diff --git a/tests/Avalonia.RenderTests/Media/RadialGradientBrushTests.cs b/tests/Avalonia.RenderTests/Media/RadialGradientBrushTests.cs
new file mode 100644
index 0000000000..af4c17b328
--- /dev/null
+++ b/tests/Avalonia.RenderTests/Media/RadialGradientBrushTests.cs
@@ -0,0 +1,56 @@
+// Copyright (c) The Avalonia Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using Avalonia.Controls;
+using Avalonia.Media;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Xunit;
+
+#if AVALONIA_CAIRO
+namespace Avalonia.Cairo.RenderTests.Media
+#elif AVALONIA_SKIA
+namespace Avalonia.Skia.RenderTests
+#else
+namespace Avalonia.Direct2D1.RenderTests.Media
+#endif
+{
+ public class RadialGradientBrushTests : TestBase
+ {
+ public RadialGradientBrushTests() : base(@"Media\RadialGradientBrush")
+ {
+ }
+
+#if AVALONIA_SKIA_SKIP_FAIL
+ [Fact(Skip = "FIXME")]
+#else
+ [Fact]
+#endif
+ public async Task RadialGradientBrush_RedBlue()
+ {
+ Decorator target = new Decorator
+ {
+ Padding = new Thickness(8),
+ Width = 200,
+ Height = 200,
+ Child = new Border
+ {
+ Background = new RadialGradientBrush
+ {
+ GradientStops =
+ {
+ new GradientStop { Color = Colors.Red, Offset = 0 },
+ new GradientStop { Color = Colors.Blue, Offset = 1 }
+ }
+ }
+ }
+ };
+
+ await RenderToFile(target);
+ CompareImages();
+ }
+ }
+}
diff --git a/tests/TestFiles/Direct2D1/Media/RadialGradientBrush/RadialGradientBrush_RedBlue.expected.png b/tests/TestFiles/Direct2D1/Media/RadialGradientBrush/RadialGradientBrush_RedBlue.expected.png
new file mode 100644
index 0000000000..fce116d98d
Binary files /dev/null and b/tests/TestFiles/Direct2D1/Media/RadialGradientBrush/RadialGradientBrush_RedBlue.expected.png differ