// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. using System; using System.Buffers; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; using SixLabors.Memory; using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// /// Provides an implementation of a solid brush for painting solid color areas. /// /// The pixel format. public class SolidBrush : IBrush where TPixel : struct, IPixel { /// /// The color to paint. /// private readonly TPixel color; /// /// Initializes a new instance of the class. /// /// The color. public SolidBrush(TPixel color) { this.color = color; } /// /// Gets the color. /// /// /// The color. /// public TPixel Color => this.color; /// public BrushApplicator CreateApplicator(ImageFrame source, RectangleF region, GraphicsOptions options) { return new SolidBrushApplicator(source, this.color, options); } /// /// The solid brush applicator. /// private class SolidBrushApplicator : BrushApplicator { /// /// Initializes a new instance of the class. /// /// The source image. /// The color. /// The options public SolidBrushApplicator(ImageFrame source, TPixel color, GraphicsOptions options) : base(source, options) { this.Colors = source.MemoryAllocator.Allocate(source.Width); this.Colors.GetSpan().Fill(color); } /// /// Gets the colors. /// protected IMemoryOwner Colors { get; } /// /// Gets the color for a single pixel. /// /// The x. /// The y. /// /// The color /// internal override TPixel this[int x, int y] => this.Colors.GetSpan()[x]; /// public override void Dispose() { this.Colors.Dispose(); } /// internal override void Apply(Span scanline, int x, int y) { Span destinationRow = this.Target.GetPixelRowSpan(y).Slice(x, scanline.Length); MemoryAllocator memoryAllocator = this.Target.MemoryAllocator; if (this.Options.BlendPercentage == 1f) { this.Blender.Blend(memoryAllocator, destinationRow, destinationRow, this.Colors.GetSpan(), scanline); } else { using (IMemoryOwner amountBuffer = memoryAllocator.Allocate(scanline.Length)) { Span amountSpan = amountBuffer.GetSpan(); for (int i = 0; i < scanline.Length; i++) { amountSpan[i] = scanline[i] * this.Options.BlendPercentage; } this.Blender.Blend(memoryAllocator, destinationRow, destinationRow, this.Colors.GetSpan(), amountSpan); } } } } } }