using System; using System.Collections.Generic; using System.Drawing; namespace FastReport.Fonts { #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member public class FastGraphicsPath { public enum PointType : byte { /// /// Indicates that the point is the start of a figure. /// Start = 0x00, /// /// Indicates that the point is one of the two endpoints of a line. /// Connect = 0x01, /// /// Indicates that the point is an endpoint or control point of a cubic Bézier spline. /// Bezier = 0x03, /// /// Masks all bits except for the three low-order bits, which indicate the point type. /// All = 0x07, /// /// Specifies that the point is a marker. /// Marker = 0x20, /// /// Specifies that the point is the last point in a closed subpath (figure). /// Last = 0x80, } private List points = new List(); private List pointTypes = new List(); private bool startNewFigure = false; public byte[] PathTypes { get { byte[] result = new byte[pointTypes.Count]; int i = 0; foreach (PointType type in pointTypes) { result[i] = (byte)type; i++; } return result; } } public PointF[] PathPoints { get { return points.ToArray(); } } private FastFillMode fillMode; public FastFillMode FillMode { get { return fillMode; } set { fillMode = value; } } public int PointCount { get { return points.Count; } } public FastGraphicsPath(FastFillMode fastFillMode /*= FastFillMode.Alternate*/) { FillMode = fastFillMode; } public void AddPath(FastGraphicsPath fastGraphicsPath, bool connect) { if (points.Count == 0) { points.AddRange(fastGraphicsPath.points); pointTypes.AddRange(fastGraphicsPath.pointTypes); } else { int i = -1; foreach (PointF point in fastGraphicsPath.points) { i++; if (connect) { if (points[points.Count - 1] == point) { connect = false; continue; } else { points.Add(point); pointTypes.Add(PointType.Connect); } connect = false; } else { points.Add(point); pointTypes.Add(fastGraphicsPath.pointTypes[i]); } } } } public void Transform(float m00, float m01, float m10, float m11, float v1, float v2) { List points2 = new List(points.Capacity); foreach (PointF point in points) { points2.Add(Transform(point, m00, m01, m10, m11, v1, v2)); } points = points2; } private PointF Transform(PointF point, float m00, float m01, float m10, float m11, float v1, float v2) { return new PointF(point.X * m00 + v1 + point.Y * m10, point.Y * m11 + v2 + point.X * m01); } public void StartFigure() { startNewFigure = true; } public void AddLine(PointF pntStart, PointF pntEnd) { if (startNewFigure || points.Count == 0) { points.Add(pntStart); pointTypes.Add(PointType.Start); } else if (points[points.Count - 1] != pntStart) { points.Add(pntStart); pointTypes.Add(PointType.Connect); } points.Add(pntEnd); pointTypes.Add(PointType.Connect); startNewFigure = false; } public void AddBezier(PointF pntStart, PointF pnt1, PointF pnt2, PointF pntEnd) { if (startNewFigure || points.Count == 0) { points.Add(pntStart); pointTypes.Add(PointType.Start); } else if (points[points.Count - 1] != pntStart) { points.Add(pntStart); pointTypes.Add(PointType.Connect); } points.Add(pnt1); pointTypes.Add(PointType.Bezier); points.Add(pnt2); pointTypes.Add(PointType.Bezier); points.Add(pntEnd); pointTypes.Add(PointType.Bezier); startNewFigure = false; } } }