383dee47d52ec23e41000182fccb0f95bce718a6
[mono.git] / mcs / class / System.Drawing / System.Drawing / FontConverter.cs
1 //
2 // System.Drawing.FontConverter.cs
3 //
4 // Authors:
5 //      Dennis Hayes (dennish@Raytek.com)
6 //      Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 //      Ravindra (rkumar@novell.com)
8 //
9 // Copyright (C) 2002,2003 Ximian, Inc.  http://www.ximian.com
10 //
11 // Copyright (C) 2004-2006 Novell, Inc (http://www.novell.com)
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
20 // 
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 // 
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 //
32
33 using System;
34 using System.Text;
35 using System.Collections;
36 using System.ComponentModel;
37 using System.Globalization;
38 using System.Drawing.Text;
39 using System.ComponentModel.Design.Serialization;
40 using System.Reflection;
41
42 namespace System.Drawing
43 {
44         public class FontConverter : TypeConverter
45         {
46                 public FontConverter ()
47                 {
48                 }
49                 ~FontConverter ()
50                 {
51                         // required to match API definition
52                 }       
53                 public override bool CanConvertFrom (ITypeDescriptorContext context, Type sourceType)
54                 {
55                         if (sourceType == typeof (string))
56                                 return true;
57
58                         return base.CanConvertFrom (context, sourceType);
59                 }
60
61                 public override bool CanConvertTo (ITypeDescriptorContext context, Type destinationType)
62                 {
63                         if (destinationType == typeof (String))
64                                 return true;
65
66                         if (destinationType == typeof (InstanceDescriptor))
67                                 return true;
68
69                         return base.CanConvertTo (context, destinationType);
70                 }
71
72                 public override object ConvertTo (ITypeDescriptorContext context,
73                         CultureInfo culture,
74                         object value,
75                         Type destinationType)
76                 {
77                         if ((destinationType == typeof (string)) && (value is Font)) {
78                                 Font font = (Font) value;
79                                 StringBuilder sb = new StringBuilder ();
80                                 sb.Append (font.Name).Append (culture.TextInfo.ListSeparator[0] + " ");
81                                 sb.Append (font.Size);
82
83                                 switch (font.Unit) {
84                                         // MS throws ArgumentException, if unit is set 
85                                         // to GraphicsUnit.Display
86                                         // Don't know what to append for GraphicsUnit.Display
87                                 case GraphicsUnit.Display:
88                                         sb.Append ("display"); break;
89
90                                 case GraphicsUnit.Document:
91                                         sb.Append ("doc"); break;
92
93                                 case GraphicsUnit.Point:
94                                         sb.Append ("pt"); break;
95
96                                 case GraphicsUnit.Inch:
97                                         sb.Append ("in"); break;
98
99                                 case GraphicsUnit.Millimeter:
100                                         sb.Append ("mm"); break;
101
102                                 case GraphicsUnit.Pixel:
103                                         sb.Append ("px"); break;
104
105                                 case GraphicsUnit.World:
106                                         sb.Append ("world"); break;
107                                 }
108
109                                 if (font.Style != FontStyle.Regular)
110                                         sb.Append (culture.TextInfo.ListSeparator[0] + " style=").Append (font.Style);
111
112                                 return sb.ToString ();
113                         }
114
115                         if ((destinationType == typeof (InstanceDescriptor)) && (value is Font)) {
116                                 Font font = (Font) value;
117                                 ConstructorInfo met = typeof(Font).GetConstructor (new Type[] {typeof(string), typeof(float), typeof(FontStyle), typeof(GraphicsUnit)});
118                                 object[] args = new object[4];
119                                 args [0] = font.Name;
120                                 args [1] = font.Size;
121                                 args [2] = font.Style;
122                                 args [3] = font.Unit;
123                                 return new InstanceDescriptor (met, args);
124                         }
125                         
126                         return base.ConvertTo (context, culture, value, destinationType);
127                 }
128
129                 public override object ConvertFrom (ITypeDescriptorContext context, CultureInfo culture, object value)
130                 {
131                         FontStyle       f_style;
132                         float           f_size;
133                         GraphicsUnit    f_unit;
134                         string          font;
135                         string          units;
136                         string[]        fields;
137
138                         if (! (value is string)) {
139                                 return base.ConvertFrom (context, culture, value);
140                         }
141
142                         font = (string)value;
143                         font = font.Trim ();
144
145                         if (font.Length == 0) {
146                                 return null;
147                         }
148
149                         if (culture == null) {
150                                 culture = CultureInfo.CurrentCulture;
151                         }
152
153                         // Format is FontFamily, size[<units>[, style=1,2,3]]
154                         // This is a bit tricky since the comma can be used for styles and fields
155                         fields = font.Split(new char[] {culture.TextInfo.ListSeparator[0]});
156                         if (fields.Length < 1) {
157                                 throw new ArgumentException("Failed to parse font format");
158                         }
159
160                         font = fields[0];
161                         f_size = 8f;
162                         units = "px";
163                         f_unit = GraphicsUnit.Pixel;
164                         if (fields.Length > 1) {        // We have a size
165                                 for (int i = 0; i < fields[1].Length; i++) {
166                                         if (Char.IsLetter(fields[1][i])) {
167                                                 f_size = (float)TypeDescriptor.GetConverter(typeof(float)).ConvertFromString(context, culture, fields[1].Substring(0, i));
168                                                 units = fields[1].Substring(i);
169                                                 break;
170                                         }
171                                 }
172                                 if (units == "display") {
173                                         f_unit = GraphicsUnit.Display;
174                                 } else if (units == "doc") {
175                                         f_unit = GraphicsUnit.Document;
176                                 } else if (units == "pt") {
177                                         f_unit = GraphicsUnit.Point;
178                                 } else if (units == "in") {
179                                         f_unit = GraphicsUnit.Inch;
180                                 } else if (units == "mm") {
181                                         f_unit = GraphicsUnit.Millimeter;
182                                 } else if (units == "px") {
183                                         f_unit = GraphicsUnit.Pixel;
184                                 } else if (units == "world") {
185                                         f_unit = GraphicsUnit.World;
186                                 }
187                         }
188
189                         f_style = FontStyle.Regular;
190                         if (fields.Length > 2) {        // We have style
191                                 string          compare;
192
193                                 for (int i = 2; i < fields.Length; i++) {
194                                         compare = fields[i];
195
196                                         if (compare.IndexOf("Regular") != -1) {
197                                                 f_style |= FontStyle.Regular;
198                                         }
199                                         if (compare.IndexOf("Bold") != -1) {
200                                                 f_style |= FontStyle.Bold;
201                                         }
202                                         if (compare.IndexOf("Italic") != -1) {
203                                                 f_style |= FontStyle.Italic;
204                                         }
205                                         if (compare.IndexOf("Strikeout") != -1) {
206                                                 f_style |= FontStyle.Strikeout;
207                                         }
208                                         if (compare.IndexOf("Underline") != -1) {
209                                                 f_style |= FontStyle.Underline;
210                                         }
211                                 }
212                         }
213
214                         return new Font (font, f_size, f_style, f_unit);
215                 }
216
217                 public override object CreateInstance (ITypeDescriptorContext context, IDictionary propertyValues)
218                 {
219                         Object value;
220                         byte charSet = 1;
221                         float size = 8;
222                         String name = null;
223                         bool vertical = false;
224                         FontStyle style = FontStyle.Regular;
225                         FontFamily fontFamily = null;
226                         GraphicsUnit unit = GraphicsUnit.Point;
227
228                         if ((value = propertyValues ["GdiCharSet"]) != null)
229                                 charSet = (byte) value;
230
231                         if ((value = propertyValues ["Size"]) != null)
232                                 size = (float) value;
233
234                         if ((value = propertyValues ["Unit"]) != null)
235                                 unit = (GraphicsUnit) value;
236
237                         if ((value = propertyValues ["Name"]) != null)
238                                 name = (String) value;
239
240                         if ((value = propertyValues ["GdiVerticalFont"]) != null)
241                                 vertical = (bool) value;
242
243                         if ((value = propertyValues ["Bold"]) != null) {
244                                 bool bold = (bool) value;
245                                 if (bold == true)
246                                         style |= FontStyle.Bold;
247                         }
248
249                         if ((value = propertyValues ["Italic"]) != null) {
250                                 bool italic = (bool) value;
251                                 if (italic == true)
252                                         style |= FontStyle.Italic;
253                         }
254
255                         if ((value = propertyValues ["Strikeout"]) != null) {
256                                 bool strike = (bool) value;
257                                 if (strike == true)
258                                         style |= FontStyle.Strikeout;
259                         }
260
261                         if ((value = propertyValues ["Underline"]) != null) {
262                                 bool underline = (bool) value;
263                                 if (underline == true)
264                                         style |= FontStyle.Underline;
265                         }
266
267                         /* ?? Should default font be culture dependent ?? */
268                         if (name == null)
269                                 fontFamily = new FontFamily ("Tahoma");
270                         else {
271                                 name = name.ToLower ();
272                                 FontCollection collection = new InstalledFontCollection ();
273                                 FontFamily [] installedFontList = collection.Families;
274                                 foreach (FontFamily font in installedFontList) {
275                                         if (name == font.Name.ToLower ()) {
276                                                 fontFamily = font;
277                                                 break;
278                                         }
279                                 }
280
281                                 // font family not found in installed fonts
282                                 if (fontFamily == null) {
283                                         collection = new PrivateFontCollection ();
284                                         FontFamily [] privateFontList = collection.Families;
285                                         foreach (FontFamily font in privateFontList) {
286                                                 if (name == font.Name.ToLower ()) {
287                                                         fontFamily = font;
288                                                         break;
289                                                 }
290                                         }
291                                 }
292
293                                 // font family not found in private fonts also
294                                 if (fontFamily == null)
295                                         fontFamily = FontFamily.GenericSansSerif;
296                         }
297
298                         return new Font (fontFamily, size, style, unit, charSet, vertical);
299                 }
300
301                 public override bool GetCreateInstanceSupported (ITypeDescriptorContext context)
302                 {
303                         return true;
304                 }
305
306                 public override PropertyDescriptorCollection GetProperties
307                         (ITypeDescriptorContext context,
308                         object value, Attribute [] attributes)
309                 {
310                         if (value is Font)
311                                 return TypeDescriptor.GetProperties (value, attributes);
312
313                         return base.GetProperties (context, value, attributes);
314                 }
315
316                 public override bool GetPropertiesSupported (ITypeDescriptorContext context)
317                 {
318                         return true;
319                 }
320
321                 public sealed class FontNameConverter : TypeConverter
322                 , IDisposable           
323                 {
324                         FontFamily [] fonts;
325                         
326                         public FontNameConverter ()
327                         {
328                                 fonts = FontFamily.Families;
329                         }       
330                         void IDisposable.Dispose ()
331                         {
332                         }
333                         public override bool CanConvertFrom (ITypeDescriptorContext context, Type sourceType)
334                         {
335                                 if (sourceType == typeof (string))
336                                         return true;
337
338                                 return base.CanConvertFrom (context, sourceType);
339                         }
340
341                         public override object ConvertFrom (ITypeDescriptorContext context, CultureInfo culture, object value)
342                         {
343                                 if (value is string)
344                                         return value;
345                                 return base.ConvertFrom (context, culture, value);
346                         }
347
348                         public override StandardValuesCollection GetStandardValues (ITypeDescriptorContext context)
349                         {
350                                 string [] values = new string [fonts.Length];
351                                 for (int i = fonts.Length; i > 0;){
352                                         i--;
353                                         values [i] = fonts [i].Name;
354                                 }
355                                 
356                                 return new TypeConverter.StandardValuesCollection (values);
357                         }
358
359                         public override bool GetStandardValuesExclusive (ITypeDescriptorContext context)
360                         {
361                                 // We allow other values other than those in the font list.
362                                 return false;
363                         }
364
365                         public override bool GetStandardValuesSupported (ITypeDescriptorContext context)
366                         {
367                                 // Yes, we support picking an element from the list. 
368                                 return true;
369                         }
370                 }
371
372                 public class FontUnitConverter : EnumConverter
373                 {
374                         public FontUnitConverter () : base (typeof (GraphicsUnit)) {}
375                         
376                         public override StandardValuesCollection GetStandardValues (ITypeDescriptorContext context)
377                         {
378                                 return base.GetStandardValues (context);
379                         }
380                                 
381                 }
382         }
383 }