@ -0,0 +1,55 @@ |
|||||
|
using Avalonia.Media.Immutable; |
||||
|
|
||||
|
namespace Avalonia.Media |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Paints an area with a swept circular gradient.
|
||||
|
/// </summary>
|
||||
|
public sealed class ConicGradientBrush : GradientBrush, IConicGradientBrush |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Defines the <see cref="Center"/> property.
|
||||
|
/// </summary>
|
||||
|
public static readonly StyledProperty<RelativePoint> CenterProperty = |
||||
|
AvaloniaProperty.Register<RadialGradientBrush, RelativePoint>( |
||||
|
nameof(Center), |
||||
|
RelativePoint.Center); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Defines the <see cref="Angle"/> property.
|
||||
|
/// </summary>
|
||||
|
public static readonly StyledProperty<double> AngleProperty = |
||||
|
AvaloniaProperty.Register<RadialGradientBrush, double>( |
||||
|
nameof(Angle), |
||||
|
0); |
||||
|
|
||||
|
static ConicGradientBrush() |
||||
|
{ |
||||
|
AffectsRender<ConicGradientBrush>(CenterProperty, AngleProperty); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets or sets the center point of the gradient.
|
||||
|
/// </summary>
|
||||
|
public RelativePoint Center |
||||
|
{ |
||||
|
get { return GetValue(CenterProperty); } |
||||
|
set { SetValue(CenterProperty, value); } |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets or sets the angle of the start and end of the sweep, measured from above the center point.
|
||||
|
/// </summary>
|
||||
|
public double Angle |
||||
|
{ |
||||
|
get { return GetValue(AngleProperty); } |
||||
|
set { SetValue(AngleProperty, value); } |
||||
|
} |
||||
|
|
||||
|
/// <inheritdoc/>
|
||||
|
public override IBrush ToImmutable() |
||||
|
{ |
||||
|
return new ImmutableConicGradientBrush(this); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,19 @@ |
|||||
|
namespace Avalonia.Media |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Paints an area with a conic gradient.
|
||||
|
/// </summary>
|
||||
|
public interface IConicGradientBrush : IGradientBrush |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Gets the center point for the gradient.
|
||||
|
/// </summary>
|
||||
|
RelativePoint Center { get; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the starting angle for the gradient in degrees, measured from
|
||||
|
/// the point above the center point.
|
||||
|
/// </summary>
|
||||
|
double Angle { get; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,47 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace Avalonia.Media.Immutable |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// A brush that draws with a sweep gradient.
|
||||
|
/// </summary>
|
||||
|
public class ImmutableConicGradientBrush : ImmutableGradientBrush, IConicGradientBrush |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="ImmutableConicGradientBrush"/> class.
|
||||
|
/// </summary>
|
||||
|
/// <param name="gradientStops">The gradient stops.</param>
|
||||
|
/// <param name="opacity">The opacity of the brush.</param>
|
||||
|
/// <param name="spreadMethod">The spread method.</param>
|
||||
|
/// <param name="center">The center point for the gradient.</param>
|
||||
|
/// <param name="angle">The starting angle for the gradient.</param>
|
||||
|
public ImmutableConicGradientBrush( |
||||
|
IReadOnlyList<ImmutableGradientStop> gradientStops, |
||||
|
double opacity = 1, |
||||
|
GradientSpreadMethod spreadMethod = GradientSpreadMethod.Pad, |
||||
|
RelativePoint? center = null, |
||||
|
double angle = 0) |
||||
|
: base(gradientStops, opacity, spreadMethod) |
||||
|
{ |
||||
|
Center = center ?? RelativePoint.Center; |
||||
|
Angle = angle; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="ImmutableConicGradientBrush"/> class.
|
||||
|
/// </summary>
|
||||
|
/// <param name="source">The brush from which this brush's properties should be copied.</param>
|
||||
|
public ImmutableConicGradientBrush(ConicGradientBrush source) |
||||
|
: base(source) |
||||
|
{ |
||||
|
Center = source.Center; |
||||
|
Angle = source.Angle; |
||||
|
} |
||||
|
|
||||
|
/// <inheritdoc/>
|
||||
|
public RelativePoint Center { get; } |
||||
|
|
||||
|
/// <inheritdoc/>
|
||||
|
public double Angle { get; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,178 @@ |
|||||
|
using Avalonia.Controls; |
||||
|
using Avalonia.Media; |
||||
|
using System.Threading.Tasks; |
||||
|
using Xunit; |
||||
|
|
||||
|
#if AVALONIA_SKIA
|
||||
|
namespace Avalonia.Skia.RenderTests |
||||
|
#else
|
||||
|
namespace Avalonia.Direct2D1.RenderTests.Media |
||||
|
#endif
|
||||
|
{ |
||||
|
public class ConicGradientBrushTests : TestBase |
||||
|
{ |
||||
|
public ConicGradientBrushTests() : base(@"Media\ConicGradientBrush") |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task ConicGradientBrush_RedBlue() |
||||
|
{ |
||||
|
Decorator target = new Decorator |
||||
|
{ |
||||
|
Padding = new Thickness(8), |
||||
|
Width = 200, |
||||
|
Height = 200, |
||||
|
Child = new Border |
||||
|
{ |
||||
|
Background = new ConicGradientBrush |
||||
|
{ |
||||
|
GradientStops = |
||||
|
{ |
||||
|
new GradientStop { Color = Colors.Red, Offset = 0 }, |
||||
|
new GradientStop { Color = Colors.Blue, Offset = 1 } |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
await RenderToFile(target); |
||||
|
CompareImages(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task ConicGradientBrush_RedBlue_Rotation() |
||||
|
{ |
||||
|
Decorator target = new Decorator |
||||
|
{ |
||||
|
Padding = new Thickness(8), |
||||
|
Width = 200, |
||||
|
Height = 200, |
||||
|
Child = new Border |
||||
|
{ |
||||
|
Background = new ConicGradientBrush |
||||
|
{ |
||||
|
GradientStops = |
||||
|
{ |
||||
|
new GradientStop { Color = Colors.Red, Offset = 0 }, |
||||
|
new GradientStop { Color = Colors.Blue, Offset = 1 } |
||||
|
}, |
||||
|
Angle = 90 |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
await RenderToFile(target); |
||||
|
CompareImages(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task ConicGradientBrush_RedBlue_Center() |
||||
|
{ |
||||
|
Decorator target = new Decorator |
||||
|
{ |
||||
|
Padding = new Thickness(8), |
||||
|
Width = 200, |
||||
|
Height = 200, |
||||
|
Child = new Border |
||||
|
{ |
||||
|
Background = new ConicGradientBrush |
||||
|
{ |
||||
|
GradientStops = |
||||
|
{ |
||||
|
new GradientStop { Color = Colors.Red, Offset = 0 }, |
||||
|
new GradientStop { Color = Colors.Blue, Offset = 1 } |
||||
|
}, |
||||
|
Center = new RelativePoint(0.25, 0.25, RelativeUnit.Relative) |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
await RenderToFile(target); |
||||
|
CompareImages(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task ConicGradientBrush_RedBlue_Center_and_Rotation() |
||||
|
{ |
||||
|
Decorator target = new Decorator |
||||
|
{ |
||||
|
Padding = new Thickness(8), |
||||
|
Width = 200, |
||||
|
Height = 200, |
||||
|
Child = new Border |
||||
|
{ |
||||
|
Background = new ConicGradientBrush |
||||
|
{ |
||||
|
GradientStops = |
||||
|
{ |
||||
|
new GradientStop { Color = Colors.Red, Offset = 0 }, |
||||
|
new GradientStop { Color = Colors.Blue, Offset = 1 } |
||||
|
}, |
||||
|
Center = new RelativePoint(0.25, 0.25, RelativeUnit.Relative), |
||||
|
Angle = 90 |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
await RenderToFile(target); |
||||
|
CompareImages(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task ConicGradientBrush_RedBlue_SoftEdge() |
||||
|
{ |
||||
|
Decorator target = new Decorator |
||||
|
{ |
||||
|
Padding = new Thickness(8), |
||||
|
Width = 200, |
||||
|
Height = 200, |
||||
|
Child = new Border |
||||
|
{ |
||||
|
Background = new ConicGradientBrush |
||||
|
{ |
||||
|
GradientStops = |
||||
|
{ |
||||
|
new GradientStop { Color = Colors.Red, Offset = 0 }, |
||||
|
new GradientStop { Color = Colors.Blue, Offset = 0.5 }, |
||||
|
new GradientStop { Color = Colors.Red, Offset = 1 }, |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
await RenderToFile(target); |
||||
|
CompareImages(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task ConicGradientBrush_Umbrella() |
||||
|
{ |
||||
|
Decorator target = new Decorator |
||||
|
{ |
||||
|
Padding = new Thickness(8), |
||||
|
Width = 200, |
||||
|
Height = 200, |
||||
|
Child = new Border |
||||
|
{ |
||||
|
Background = new ConicGradientBrush |
||||
|
{ |
||||
|
GradientStops = |
||||
|
{ |
||||
|
new GradientStop { Color = Colors.Red, Offset = 0 }, |
||||
|
new GradientStop { Color = Colors.Yellow, Offset = 0.1667 }, |
||||
|
new GradientStop { Color = Colors.Lime, Offset = 0.3333 }, |
||||
|
new GradientStop { Color = Colors.Aqua, Offset = 0.5000 }, |
||||
|
new GradientStop { Color = Colors.Blue, Offset = 0.6667 }, |
||||
|
new GradientStop { Color = Colors.Magenta, Offset = 0.8333 }, |
||||
|
new GradientStop { Color = Colors.Red, Offset = 1 }, |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
await RenderToFile(target); |
||||
|
CompareImages(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
After Width: | Height: | Size: 601 B |
|
After Width: | Height: | Size: 601 B |
|
After Width: | Height: | Size: 601 B |
|
After Width: | Height: | Size: 601 B |
|
After Width: | Height: | Size: 601 B |
|
After Width: | Height: | Size: 601 B |
|
After Width: | Height: | Size: 7.1 KiB |
|
After Width: | Height: | Size: 6.6 KiB |
|
After Width: | Height: | Size: 6.6 KiB |
|
After Width: | Height: | Size: 7.1 KiB |
|
After Width: | Height: | Size: 8.6 KiB |
|
After Width: | Height: | Size: 11 KiB |