using System; using System.Collections.Generic; using System.Text; using System.ComponentModel; using System.Web.UI.WebControls; namespace Svg { /// /// Represents a unit in an Scalable Vector Graphics document. /// [TypeConverter(typeof(SvgUnitConverter))] public struct SvgUnit { private SvgUnitType _type; private float _value; private bool _isEmpty; private float? _deviceValue; /// /// Gets and empty . /// public static readonly SvgUnit Empty = new SvgUnit(); /// /// Gets a value to determine whether the unit is empty. /// public bool IsEmpty { get { return this._isEmpty; } } /// /// Gets the value of the unit. /// public float Value { get { return this._value; } } /// /// Gets the of unit. /// public SvgUnitType Type { get { return this._type; } } /// /// Converts the current unit to one that can be used at render time. /// /// The representation of the current unit in a device value (usually pixels). public float ToDeviceValue() { return this.ToDeviceValue(null); } /// /// Converts the current unit to one that can be used at render time. /// /// The representation of the current unit in a device value (usually pixels). public float ToDeviceValue(ISvgStylable styleOwner) { return this.ToDeviceValue(styleOwner, false); } /// /// Converts the current unit to one that can be used at render time. /// /// The representation of the current unit in a device value (usually pixels). public float ToDeviceValue(ISvgStylable styleOwner, bool vertical) { // If it's already been calculated if (this._deviceValue.HasValue) { return this._deviceValue.Value; } if (this._value == 0.0f) { this._deviceValue = 0.0f; return this._deviceValue.Value; } // http://www.w3.org/TR/CSS21/syndata.html#values // http://www.w3.org/TR/SVG11/coords.html#Units const float cmInInch = 2.54f; int ppi = SvgDocument.PPI; switch (this.Type) { case SvgUnitType.Centimeter: _deviceValue = (float)((this.Value / cmInInch) * ppi); break; case SvgUnitType.Inch: _deviceValue = this.Value * ppi; break; case SvgUnitType.Millimeter: _deviceValue = (float)((this.Value / 10) / cmInInch) * ppi; break; case SvgUnitType.Pica: _deviceValue = ((this.Value * 12) / 72) * ppi; break; case SvgUnitType.Point: _deviceValue = (this.Value / 72) * ppi; break; case SvgUnitType.Pixel: _deviceValue = this.Value; break; case SvgUnitType.User: _deviceValue = this.Value; break; case SvgUnitType.Percentage: // Can't calculate if there is no style owner if (styleOwner == null) { _deviceValue = this.Value; } // TODO : Support height percentages System.Drawing.RectangleF size = styleOwner.Bounds; _deviceValue = (((vertical) ? size.Height : size.Width) / 100) * this.Value; break; default: _deviceValue = this.Value; break; } return this._deviceValue.Value; } /// /// Converts the current unit to a percentage, if applicable. /// /// An of type . public SvgUnit ToPercentage() { switch (this.Type) { case SvgUnitType.Percentage: return this; case SvgUnitType.User: return new SvgUnit(SvgUnitType.Percentage, this.Value * 100); default: throw new NotImplementedException(); break; } return this; } /// /// Indicates whether this instance and a specified object are equal. /// /// Another object to compare to. /// /// true if and this instance are the same type and represent the same value; otherwise, false. /// public override bool Equals(object obj) { if (obj == null) { return false; } if (!(obj.GetType() == typeof(SvgUnit))) { return false; } SvgUnit unit = (SvgUnit)obj; return (unit.Value == this.Value && unit.Type == this.Type); } /// /// Returns the fully qualified type name of this instance. /// /// /// A containing a fully qualified type name. /// public override string ToString() { string type = string.Empty; switch (this.Type) { case SvgUnitType.Pixel: type = "px"; break; case SvgUnitType.Point: type = "pt"; break; case SvgUnitType.Inch: type = "in"; break; case SvgUnitType.Centimeter: type = "cm"; break; case SvgUnitType.Millimeter: type = "mm"; break; case SvgUnitType.Percentage: type = "%"; break; case SvgUnitType.Em: type = "em"; break; } return string.Concat(this.Value.ToString(), type); } /// /// Performs an implicit conversion from to . /// /// The value. /// The result of the conversion. public static implicit operator float(SvgUnit value) { return value.ToDeviceValue(); } /// /// Performs an implicit conversion from to . /// /// The value. /// The result of the conversion. public static implicit operator SvgUnit(float value) { return new SvgUnit(value); } /// /// Initializes a new instance of the struct. /// /// The type. /// The value. public SvgUnit(SvgUnitType type, float value) { this._type = type; this._value = value; this._isEmpty = (this._value == 0.0f); this._deviceValue = null; } /// /// Initializes a new instance of the struct. /// /// The value. public SvgUnit(float value) { this._value = value; this._type = SvgUnitType.User; this._isEmpty = (this._value == 0.0f); this._deviceValue = null; } } /// /// Defines the various types of unit an can be. /// public enum SvgUnitType { /// /// Indicates that the unit is in pixels. /// Pixel, /// /// Indicates that the unit is equal to the pt size of the current font. /// Em, /// /// Indicates that the unit is a percentage. /// Percentage, /// /// Indicates that the unit has no unit identifier and is a value in the current user coordinate system. /// User, /// /// Indicates the the unit is in inches. /// Inch, /// /// Indicates that the unit is in centimeters. /// Centimeter, /// /// Indicates that the unit is in millimeters. /// Millimeter, /// /// Indicates that the unit is in picas. /// Pica, /// /// Indicates that the unit is in points, the smallest unit of measure, being a subdivision of the larger . There are 12 points in the . /// Point } }