context: //
  // System.Drawing.FontConverter.cs
  //
  // Authors:
  //	Dennis Hayes (dennish@Raytek.com)
  //	Gonzalo Paniagua Javier (gonzalo@ximian.com)
  //	Ravindra (rkumar@novell.com)
  //
  // Copyright (C) 2002,2003 Ximian, Inc.  http://www.ximian.com
  //
  // Copyright (C) 2004-2006 Novell, Inc (http://www.novell.com)
  //
  // Permission is hereby granted, free of charge, to any person obtaining
  // a copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to
  // permit persons to whom the Software is furnished to do so, subject to
  // the following conditions:
  // 
  // The above copyright notice and this permission notice shall be
  // included in all copies or substantial portions of the Software.
  // 
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  //
  
  using System;
  using System.Text;
  using System.Collections;
  using System.ComponentModel;
  using System.Globalization;
  using System.Drawing.Text;
  using System.ComponentModel.Design.Serialization;
  using System.Reflection;
  
  namespace System.Drawing
  {
  	public class FontConverter : TypeConverter
  	{
  		public FontConverter ()
  		{
  		}
  		~FontConverter ()
  		{
  			// required to match API definition
  		}	
  		public override bool CanConvertFrom (ITypeDescriptorContext context, Type sourceType)
  		{
  			if (sourceType == typeof (string))
  				return true;
  
  			return base.CanConvertFrom (context, sourceType);
  		}
  
  		public override bool CanConvertTo (ITypeDescriptorContext context, Type destinationType)
  		{
  			if (destinationType == typeof (String))
  				return true;
  
  			if (destinationType == typeof (InstanceDescriptor))
  				return true;
  
  			return base.CanConvertTo (context, destinationType);
  		}
  
  		public override object ConvertTo (ITypeDescriptorContext context,
  			CultureInfo culture,
  			object value,
  			Type destinationType)
  		{
  			if ((destinationType == typeof (string)) && (value is Font)) {
  				Font font = (Font) value;
  				StringBuilder sb = new StringBuilder ();
  				sb.Append (font.Name).Append (culture.TextInfo.ListSeparator[0] + " ");
  				sb.Append (font.Size);
  
  				switch (font.Unit) {
  					// MS throws ArgumentException, if unit is set 
  					// to GraphicsUnit.Display
  					// Don't know what to append for GraphicsUnit.Display
  				case GraphicsUnit.Display:
  					sb.Append ("display"); break;
  
  				case GraphicsUnit.Document:
  					sb.Append ("doc"); break;
  
  				case GraphicsUnit.Point:
  					sb.Append ("pt"); break;
  
  				case GraphicsUnit.Inch:
  					sb.Append ("in"); break;
  
  				case GraphicsUnit.Millimeter:
  					sb.Append ("mm"); break;
  
  				case GraphicsUnit.Pixel:
  					sb.Append ("px"); break;
  
  				case GraphicsUnit.World:
  					sb.Append ("world"); break;
  				}
  
  				if (font.Style != FontStyle.Regular)
  					sb.Append (culture.TextInfo.ListSeparator[0] + " style=").Append (font.Style);
  
  				return sb.ToString ();
  			}
  
  			if ((destinationType == typeof (InstanceDescriptor)) && (value is Font)) {
  				Font font = (Font) value;
  				ConstructorInfo met = typeof(Font).GetConstructor (new Type[] {typeof(string), typeof(float), typeof(FontStyle), typeof(GraphicsUnit)});
  				object[] args = new object[4];
  				args [0] = font.Name;
  				args [1] = font.Size;
  				args [2] = font.Style;
  				args [3] = font.Unit;
  				return new InstanceDescriptor (met, args);
  			}
  			
  			return base.ConvertTo (context, culture, value, destinationType);
  		}
  
  		public override object ConvertFrom (ITypeDescriptorContext context, CultureInfo culture, object value)
  		{
  			FontStyle	f_style;
  			float		f_size;
  			GraphicsUnit	f_unit;
  			string		font;
  			string		units;
  			string[]	fields;
  
  			if (! (value is string)) {
  				return base.ConvertFrom (context, culture, value);
  			}
  
  			font = (string)value;
  			font = font.Trim ();
  
  			if (font.Length == 0) {
  				return null;
  			}
  
  			if (culture == null) {
  				culture = CultureInfo.CurrentCulture;
  			}
  
  			// Format is FontFamily, size[<units>[, style=1,2,3]]
  			// This is a bit tricky since the comma can be used for styles and fields
  			fields = font.Split(new char[] {culture.TextInfo.ListSeparator[0]});
  			if (fields.Length < 1) {
  				throw new ArgumentException("Failed to parse font format");
  			}
  
  			font = fields[0];
  			f_size = 8f;
  			units = "px";
  			f_unit = GraphicsUnit.Pixel;
  			if (fields.Length > 1) {	// We have a size
  				for (int i = 0; i < fields[1].Length; i++) {
  					if (Char.IsLetter(fields[1][i])) {
  						f_size = (float)TypeDescriptor.GetConverter(typeof(float)).ConvertFromString(context, culture, fields[1].Substring(0, i));
  						units = fields[1].Substring(i);
  						break;
  					}
  				}
  				if (units == "display") {
  					f_unit = GraphicsUnit.Display;
  				} else if (units == "doc") {
  					f_unit = GraphicsUnit.Document;
  				} else if (units == "pt") {
  					f_unit = GraphicsUnit.Point;
  				} else if (units == "in") {
  					f_unit = GraphicsUnit.Inch;
  				} else if (units == "mm") {
  					f_unit = GraphicsUnit.Millimeter;
  				} else if (units == "px") {
  					f_unit = GraphicsUnit.Pixel;
  				} else if (units == "world") {
  					f_unit = GraphicsUnit.World;
  				}
  			}
  
  			f_style = FontStyle.Regular;
  			if (fields.Length > 2) {	// We have style
  				string		compare;
  
  				for (int i = 2; i < fields.Length; i++) {
  					compare = fields[i];
  
  					if (compare.IndexOf("Regular") != -1) {
  						f_style |= FontStyle.Regular;
  					}
  					if (compare.IndexOf("Bold") != -1) {
  						f_style |= FontStyle.Bold;
  					}
  					if (compare.IndexOf("Italic") != -1) {
  						f_style |= FontStyle.Italic;
  					}
  					if (compare.IndexOf("Strikeout") != -1) {
  						f_style |= FontStyle.Strikeout;
  					}
  					if (compare.IndexOf("Underline") != -1) {
  						f_style |= FontStyle.Underline;
  					}
  				}
  			}
  
  			return new Font (font, f_size, f_style, f_unit);
  		}
  
  		public override object CreateInstance (ITypeDescriptorContext context, IDictionary propertyValues)
  		{
  			Object value;
  			byte charSet = 1;
  			float size = 8;
  			String name = null;
  			bool vertical = false;
  			FontStyle style = FontStyle.Regular;
  			FontFamily fontFamily = null;
  			GraphicsUnit unit = GraphicsUnit.Point;
  
  			if ((value = propertyValues ["GdiCharSet"]) != null)
  				charSet = (byte) value;
  
  			if ((value = propertyValues ["Size"]) != null)
  				size = (float) value;
  
  			if ((value = propertyValues ["Unit"]) != null)
  				unit = (GraphicsUnit) value;
  
  			if ((value = propertyValues ["Name"]) != null)
  
gt: 				name = (String) value;