using PaintDotNet.Measurement.Enum; using System; using System.ComponentModel; using System.Drawing; using System.Drawing.Drawing2D; using System.Runtime.Serialization; namespace PaintDotNet.Measurement.ObjInfo { /// /// Carries information about the subset of Pen configuration details that we support. /// Does not carry color information. /// [Serializable] public sealed class PenInfo : ICloneable, ISerializable { public const DashStyle DefaultDashStyle = DashStyle.Solid; public const LineCap2 DefaultLineCap = LineCap2.Flat; public const float DefaultCapScale = 1.0f; public const float MinCapScale = 1.0f; public const float MaxCapScale = 5.0f; private DashStyle dashStyle; public DashStyle DashStyle { get { return this.dashStyle; } set { this.dashStyle = value; } } private float width; public float Width { get { return this.width; } set { this.width = value; } } private LineCap2 startCap; public LineCap2 StartCap { get { return this.startCap; } set { this.startCap = value; } } private LineCap2 endCap; public LineCap2 EndCap { get { return this.endCap; } set { this.endCap = value; } } private float capScale; private float CapScale { get { return Utility.Clamp(this.capScale, MinCapScale, MaxCapScale); } set { this.capScale = value; } } public static bool operator ==(PenInfo lhs, PenInfo rhs) { return ( lhs.dashStyle == rhs.dashStyle && lhs.width == rhs.width && lhs.startCap == rhs.startCap && lhs.endCap == rhs.endCap && lhs.capScale == rhs.capScale); } public static bool operator !=(PenInfo lhs, PenInfo rhs) { return !(lhs == rhs); } public override bool Equals(object obj) { PenInfo rhs = obj as PenInfo; if (rhs == null) { return false; } return this == rhs; } public override int GetHashCode() { return this.dashStyle.GetHashCode() ^ this.width.GetHashCode() ^ this.startCap.GetHashCode() ^ this.endCap.GetHashCode() ^ this.capScale.GetHashCode(); } private void LineCapToLineCap2(LineCap2 cap2, out LineCap capResult, out CustomLineCap customCapResult) { switch (cap2) { case LineCap2.Flat: capResult = LineCap.Flat; customCapResult = null; break; case LineCap2.Arrow: capResult = LineCap.ArrowAnchor; customCapResult = new AdjustableArrowCap(5.0f * this.capScale, 5.0f * this.capScale, false); break; case LineCap2.ArrowFilled: capResult = LineCap.ArrowAnchor; customCapResult = new AdjustableArrowCap(5.0f * this.capScale, 5.0f * this.capScale, true); break; case LineCap2.Rounded: capResult = LineCap.Round; customCapResult = null; break; default: throw new InvalidEnumArgumentException(); } } public Pen CreatePen(BrushInfo brushInfo, Color foreColor, Color backColor) { Pen pen; if (brushInfo.BrushType == BrushType.None) { pen = new Pen(foreColor, width); } else { pen = new Pen(brushInfo.CreateBrush(foreColor, backColor), width); } LineCap startLineCap; CustomLineCap startCustomLineCap; LineCapToLineCap2(this.startCap, out startLineCap, out startCustomLineCap); if (startCustomLineCap != null) { pen.CustomStartCap = startCustomLineCap; } else { pen.StartCap = startLineCap; } LineCap endLineCap; CustomLineCap endCustomLineCap; LineCapToLineCap2(this.endCap, out endLineCap, out endCustomLineCap); if (endCustomLineCap != null) { pen.CustomEndCap = endCustomLineCap; } else { pen.EndCap = endLineCap; } pen.DashStyle = this.dashStyle; return pen; } public PenInfo(DashStyle dashStyle, float width, LineCap2 startCap, LineCap2 endCap, float capScale) { this.dashStyle = dashStyle; this.width = width; this.capScale = capScale; this.startCap = startCap; this.endCap = endCap; } private PenInfo(SerializationInfo info, StreamingContext context) { this.dashStyle = (DashStyle)info.GetValue("dashStyle", typeof(DashStyle)); this.width = info.GetSingle("width"); // Save the caps as integers because we want to change the "LineCap2" name. // Just not feeling very creative right now I guess. try { this.startCap = (LineCap2)info.GetInt32("startCap"); } catch (SerializationException) { this.startCap = DefaultLineCap; } try { this.endCap = (LineCap2)info.GetInt32("endCap"); } catch (SerializationException) { this.endCap = DefaultLineCap; } try { float loadedCapScale = info.GetSingle("capScale"); this.capScale = Utility.Clamp(loadedCapScale, MinCapScale, MaxCapScale); } catch (SerializationException) { this.capScale = DefaultCapScale; } } public PenInfo Clone() { return new PenInfo(this.dashStyle, this.width, this.startCap, this.endCap, this.capScale); } object ICloneable.Clone() { return Clone(); } public void GetObjectData(SerializationInfo info, StreamingContext context) { info.AddValue("dashStyle", this.dashStyle); info.AddValue("width", this.width); info.AddValue("startCap", (int)this.startCap); info.AddValue("endCap", (int)this.endCap); info.AddValue("capScale", this.capScale); } } }