// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. using System; using SixLabors.ImageSharp.Advanced.Unsafe; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Drawing.Brushes.Processors { /// /// primitive that converts a point in to a color for discovering the fill color based on an implementation /// /// The pixel format. /// public abstract class BrushApplicator : IDisposable // disposable will be required if/when there is an ImageBrush where TPixel : struct, IPixel { /// /// Initializes a new instance of the class. /// /// The target. /// The options. internal BrushApplicator(ImageBase target, GraphicsOptions options) { this.Target = target; this.Options = options; this.Blender = PixelOperations.Instance.GetPixelBlender(options.BlenderMode); } /// /// Gets the blendder /// internal PixelBlender Blender { get; } /// /// Gets the destinaion /// protected ImageBase Target { get; } /// /// Gets the blend percentage /// protected GraphicsOptions Options { get; private set; } /// /// Gets the color for a single pixel. /// /// The x cordinate. /// The y cordinate. /// The a that should be applied to the pixel. internal abstract TPixel this[int x, int y] { get; } /// public abstract void Dispose(); /// /// Applies the opactiy weighting for each pixel in a scanline to the target based on the pattern contained in the brush. /// /// The a collection of opacity values between 0 and 1 to be merged with the brushed color value before being applied to the target. /// The x position in the target pixel space that the start of the scanline data corresponds to. /// The y position in the target pixel space that whole scanline corresponds to. /// scanlineBuffer will be > scanlineWidth but provide and offset in case we want to share a larger buffer across runs. internal virtual void Apply(Span scanline, int x, int y) { using (var amountBuffer = new Buffer(scanline.Length)) using (var overlay = new Buffer(scanline.Length)) { for (int i = 0; i < scanline.Length; i++) { if (this.Options.BlendPercentage < 1) { amountBuffer[i] = scanline[i] * this.Options.BlendPercentage; } overlay[i] = this[x + i, y]; } Span destinationRow = this.Target.GetPixelRowSpan(x).Slice(y, scanline.Length); this.Blender.Blend(destinationRow, destinationRow, overlay, amountBuffer); } } } }