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); } } } }