using System;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Processing.Drawing.Brushes.GradientBrushes
{
///
/// A Circular Gradient Brush, defined by center point and radius.
///
/// The pixel format.
public sealed class RadialGradientBrush : GradientBrushBase
where TPixel : struct, IPixel
{
private readonly Point center;
private readonly float radius;
///
/// The center of the circular gradient and 0 for the color stops.
/// The radius of the circular gradient and 1 for the color stops.
/// Defines how the colors in the gradient are repeated.
/// the color stops as defined in base class.
public RadialGradientBrush(
Point center,
float radius,
GradientRepetitionMode repetitionMode,
params ColorStop[] colorStops)
: base(repetitionMode, colorStops)
{
this.center = center;
this.radius = radius;
}
///
public override BrushApplicator CreateApplicator(
ImageFrame source,
RectangleF region,
GraphicsOptions options) =>
new RadialGradientBrushApplicator(
source,
options,
this.center,
this.radius,
this.ColorStops,
this.RepetitionMode);
///
private sealed class RadialGradientBrushApplicator : GradientBrushApplicatorBase
{
private readonly Point center;
private readonly float radius;
///
/// Initializes a new instance of the class.
///
/// The target image
/// The options.
/// Center point of the gradient.
/// Radius of the gradient.
/// Definition of colors.
/// How the colors are repeated beyond the first gradient.
public RadialGradientBrushApplicator(
ImageFrame target,
GraphicsOptions options,
Point center,
float radius,
ColorStop[] colorStops,
GradientRepetitionMode repetitionMode)
: base(target, options, colorStops, repetitionMode)
{
this.center = center;
this.radius = radius;
}
///
public override void Dispose()
{
}
///
/// As this is a circular gradient, the position on the gradient is based on
/// the distance of the point to the center.
///
/// The X coordinate of the target pixel.
/// The Y coordinate of the target pixel.
/// the position on the color gradient.
protected override float PositionOnGradient(int x, int y)
{
float distance = (float)Math.Sqrt(Math.Pow(this.center.X - x, 2) + Math.Pow(this.center.Y - y, 2));
return distance / this.radius;
}
internal override void Apply(Span scanline, int x, int y)
{
// TODO: each row is symmetric across center, so we can calculate half of it and mirror it to improve performance.
base.Apply(scanline, x, y);
}
}
}
}