// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. using System; using SixLabors.ImageSharp.PixelFormats; using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// /// A radial gradient brush, defined by center point and radius. /// public sealed class RadialGradientBrush : GradientBrush { private readonly PointF 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( PointF center, float radius, GradientRepetitionMode repetitionMode, params ColorStop[] colorStops) : base(repetitionMode, colorStops) { this.center = center; this.radius = radius; } /// public override BrushApplicator CreateApplicator( Configuration configuration, GraphicsOptions options, ImageFrame source, RectangleF region) => new RadialGradientBrushApplicator( configuration, options, source, this.center, this.radius, this.ColorStops, this.RepetitionMode); /// private sealed class RadialGradientBrushApplicator : GradientBrushApplicator where TPixel : struct, IPixel { private readonly PointF center; private readonly float radius; /// /// Initializes a new instance of the class. /// /// The configuration instance to use when performing operations. /// The graphics options. /// The target image. /// Center point of the gradient. /// Radius of the gradient. /// Definition of colors. /// How the colors are repeated beyond the first gradient. public RadialGradientBrushApplicator( Configuration configuration, GraphicsOptions options, ImageFrame target, PointF center, float radius, ColorStop[] colorStops, GradientRepetitionMode repetitionMode) : base(configuration, options, target, colorStops, repetitionMode) { this.center = center; this.radius = radius; } /// /// 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(float x, float y) { // TODO: Can this not use Vector2 distance? float distance = MathF.Sqrt(MathF.Pow(this.center.X - x, 2) + MathF.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); } } } }