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;
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; }
}
public SvgUnitType Type
{
get { return this._type; }
}
public float ToDeviceValue()
{
return this.ToDeviceValue(null);
}
public float ToDeviceValue(ISvgStylable styleOwner)
{
return this.ToDeviceValue(styleOwner, false);
}
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;
}
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);
}
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);
}
public static implicit operator float(SvgUnit value)
{
return value.ToDeviceValue();
}
public static implicit operator SvgUnit(float value)
{
return new SvgUnit(value);
}
public SvgUnit(SvgUnitType type, float value)
{
this._type = type;
this._value = value;
this._isEmpty = (this._value == 0.0f);
this._deviceValue = null;
}
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
}
}