// // Copyright (c) James Jackson-South and contributors. // Licensed under the Apache License, Version 2.0. // namespace ImageSharp.Drawing.Brushes { using System; using System.Numerics; using Processors; /// /// Provides an implementation of a pattern brush for painting patterns. /// /// /// The patterns that are used to create a custom pattern brush are made up of a repeating matrix of flags, /// where each flag denotes whether to draw the foreground color or the background color. /// so to create a new bool[,] with your flags /// /// For example if you wanted to create a diagonal line that repeat every 4 pixels you would use a pattern like so /// 1000 /// 0100 /// 0010 /// 0001 /// /// /// or you want a horizontal stripe which is 3 pixels apart you would use a pattern like /// 1 /// 0 /// 0 /// /// Warning when use array initializer across multiple lines the bools look inverted i.e. /// new bool[,]{ /// {true, false, false}, /// {false,true, false} /// } /// would be /// 10 /// 01 /// 00 /// /// The pixel format. public class PatternBrush : IBrush where TColor : struct, IPackedPixel, IEquatable { /// /// The pattern. /// private readonly TColor[][] pattern; /// /// The stride width. /// private readonly int stride; /// /// Initializes a new instance of the class. /// /// Color of the fore. /// Color of the back. /// The pattern. public PatternBrush(TColor foreColor, TColor backColor, bool[,] pattern) { this.stride = pattern.GetLength(1); // Convert the multidimension array into a jagged one. int height = pattern.GetLength(0); this.pattern = new TColor[height][]; for (int x = 0; x < height; x++) { this.pattern[x] = new TColor[this.stride]; for (int y = 0; y < this.stride; y++) { if (pattern[x, y]) { this.pattern[x][y] = foreColor; } else { this.pattern[x][y] = backColor; } } } } /// /// Initializes a new instance of the class. /// /// The brush. internal PatternBrush(PatternBrush brush) { this.pattern = brush.pattern; this.stride = brush.stride; } /// public BrushApplicator CreateApplicator(PixelAccessor sourcePixels, RectangleF region) { return new PatternBrushApplicator(this.pattern, this.stride); } /// /// The pattern brush applicator. /// private class PatternBrushApplicator : BrushApplicator { /// /// The patter x-length. /// private readonly int xLength; /// /// The stride width. /// private readonly int stride; /// /// The pattern. /// private readonly TColor[][] pattern; /// /// Initializes a new instance of the class. /// /// The pattern. /// The stride. public PatternBrushApplicator(TColor[][] pattern, int stride) { this.pattern = pattern; this.xLength = pattern.Length; this.stride = stride; } /// /// Gets the color for a single pixel. /// /// The point. /// /// The color /// public override TColor GetColor(Vector2 point) { int x = (int)point.X % this.xLength; int y = (int)point.Y % this.stride; return this.pattern[x][y]; } /// public override void Dispose() { // noop } } } }