// // Copyright (c) James Jackson-South and contributors. // Licensed under the Apache License, Version 2.0. // namespace ImageSharp.Drawing { using System.Buffers; using System.Collections.Immutable; using System.Numerics; using ImageSharp.Drawing.Processors; using SixLabors.Shapes; using Rectangle = ImageSharp.Rectangle; /// /// A drawable mapping between a / and a drawable/fillable region. /// internal class ShapePath : ImageSharp.Drawing.Drawable { /// /// The fillable shape /// private readonly IShape shape; /// /// Initializes a new instance of the class. /// /// The path. public ShapePath(IPath path) : this(ImmutableArray.Create(path)) { this.shape = path.AsShape(); this.Bounds = RectangleF.Ceiling(path.Bounds.Convert()); } /// /// Initializes a new instance of the class. /// /// The shape. public ShapePath(IShape shape) : this(shape.Paths) { this.shape = shape; this.Bounds = RectangleF.Ceiling(shape.Bounds.Convert()); } /// /// Initializes a new instance of the class. /// /// The paths. private ShapePath(ImmutableArray paths) { this.Paths = paths; } /// /// Gets the drawable paths /// /// /// The paths. /// public ImmutableArray Paths { get; } /// public override int MaxIntersections => this.shape.MaxIntersections; /// public override Rectangle Bounds { get; } /// public override int ScanX(int x, float[] buffer, int length, int offset) { Vector2 start = new Vector2(x, this.Bounds.Top - 1); Vector2 end = new Vector2(x, this.Bounds.Bottom + 1); Vector2[] innerbuffer = ArrayPool.Shared.Rent(length); try { int count = this.shape.FindIntersections( start, end, innerbuffer, length, 0); for (int i = 0; i < count; i++) { buffer[i + offset] = innerbuffer[i].Y; } return count; } finally { ArrayPool.Shared.Return(innerbuffer); } } /// public override int ScanY(int y, float[] buffer, int length, int offset) { Vector2 start = new Vector2(float.MinValue, y); Vector2 end = new Vector2(float.MaxValue, y); Vector2[] innerbuffer = ArrayPool.Shared.Rent(length); try { int count = this.shape.FindIntersections( start, end, innerbuffer, length, 0); for (int i = 0; i < count; i++) { buffer[i + offset] = innerbuffer[i].X; } return count; } finally { ArrayPool.Shared.Return(innerbuffer); } } /// public override PointInfo GetPointInfo(int x, int y) { Vector2 point = new Vector2(x, y); SixLabors.Shapes.PointInfo result = default(SixLabors.Shapes.PointInfo); float distance = float.MaxValue; for (int i = 0; i < this.Paths.Length; i++) { SixLabors.Shapes.PointInfo p = this.Paths[i].Distance(point); if (p.DistanceFromPath < distance) { distance = p.DistanceFromPath; result = p; } } return result.Convert(); } } }