@ -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 |