22baf05498bca403c427ac40e30c178ab610afdf
[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 #if !TARGET_JVM
50                 ~FontConverter ()
51                 {
52                         // required to match API definition
53                 }       
54 #endif
55                 public override bool CanConvertFrom (ITypeDescriptorContext context, Type sourceType)
56                 {
57                         if (sourceType == typeof (string))
58                                 return true;
59
60                         return base.CanConvertFrom (context, sourceType);
61                 }
62
63                 public override bool CanConvertTo (ITypeDescriptorContext context, Type destinationType)
64                 {
65                         if (destinationType == typeof (String))
66                                 return true;
67
68                         if (destinationType == typeof (InstanceDescriptor))
69                                 return true;
70
71                         return base.CanConvertTo (context, destinationType);
72                 }
73
74                 public override object ConvertTo (ITypeDescriptorContext context,
75                         CultureInfo culture,
76                         object value,
77                         Type destinationType)
78                 {
79                         if ((destinationType == typeof (string)) && (value is Font)) {
80                                 Font font = (Font) value;
81                                 StringBuilder sb = new StringBuilder ();
82                                 sb.Append (font.Name).Append (culture.TextInfo.ListSeparator[0] + " ");
83                                 sb.Append (font.Size);
84
85                                 switch (font.Unit) {
86                                         // MS throws ArgumentException, if unit is set 
87                                         // to GraphicsUnit.Display
88                                         // Don't know what to append for GraphicsUnit.Display
89                                 case GraphicsUnit.Display:
90                                         sb.Append ("display"); break;
91
92                                 case GraphicsUnit.Document:
93                                         sb.Append ("doc"); break;
94
95                                 case GraphicsUnit.Point:
96                                         sb.Append ("pt"); break;
97
98                                 case GraphicsUnit.Inch:
99                                         sb.Append ("in"); break;
100
101                                 case GraphicsUnit.Millimeter:
102                                         sb.Append ("mm"); break;
103
104                                 case GraphicsUnit.Pixel:
105                                         sb.Append ("px"); break;
106
107                                 case GraphicsUnit.World:
108                                         sb.Append ("world"); break;
109                                 }
110
111                                 if (font.Style != FontStyle.Regular)
112                                         sb.Append (culture.TextInfo.ListSeparator[0] + " style=").Append (font.Style);
113
114                                 return sb.ToString ();
115                         }
116
117                         if ((destinationType == typeof (InstanceDescriptor)) && (value is Font)) {
118                                 Font font = (Font) value;
119                                 ConstructorInfo met = typeof(Font).GetConstructor (new Type[] {typeof(string), typeof(float), typeof(FontStyle), typeof(GraphicsUnit)});
120                                 object[] args = new object[4];
121                                 args [0] = font.Name;
122                                 args [1] = font.Size;
123                                 args [2] = font.Style;
124                                 args [3] = font.Unit;
125                                 return new InstanceDescriptor (met, args);
126                         }
127                         
128                         return base.ConvertTo (context, culture, value, destinationType);
129                 }
130
131                 public override object ConvertFrom (ITypeDescriptorContext context, CultureInfo culture, object value)
132                 {
133                         FontStyle       f_style;
134                         float           f_size;
135                         GraphicsUnit    f_unit;
136                         string          font;
137                         string          units;
138                         string[]        fields;
139
140                         if (! (value is string)) {
141                                 return base.ConvertFrom (context, culture, value);
142                         }
143
144                         font = (string)value;
145                         font = font.Trim ();
146
147                         if (font.Length == 0) {
148                                 return null;
149                         }
150
151                         if (culture == null) {
152                                 culture = CultureInfo.CurrentCulture;
153                         }
154
155                         // Format is FontFamily, size[<units>[, style=1,2,3]]
156                         // This is a bit tricky since the comma can be used for styles and fields
157                         fields = font.Split(new char[] {culture.TextInfo.ListSeparator[0]});
158                         if (fields.Length < 1) {
159                                 throw new ArgumentException("Failed to parse font format");
160                         }
161
162                         font = fields[0];
163                         f_size = 8f;
164                         units = "px";
165                         f_unit = GraphicsUnit.Pixel;
166                         if (fields.Length > 1) {        // We have a size
167                                 for (int i = 0; i < fields[1].Length; i++) {
168                                         if (Char.IsLetter(fields[1][i])) {
169                                                 f_size = (float)TypeDescriptor.GetConverter(typeof(float)).ConvertFromString(context, culture, fields[1].Substring(0, i));
170                                                 units = fields[1].Substring(i);
171                                                 break;
172                                         }
173                                 }
174                                 if (units == "display") {
175                                         f_unit = GraphicsUnit.Display;
176                                 } else if (units == "doc") {
177                                         f_unit = GraphicsUnit.Document;
178                                 } else if (units == "pt") {
179                                         f_unit = GraphicsUnit.Point;
180                                 } else if (units == "in") {
181                                         f_unit = GraphicsUnit.Inch;
182                                 } else if (units == "mm") {
183                                         f_unit = GraphicsUnit.Millimeter;
184                                 } else if (units == "px") {
185                                         f_unit = GraphicsUnit.Pixel;
186                                 } else if (units == "world") {
187                                         f_unit = GraphicsUnit.World;
188                                 }
189                         }
190
191                         f_style = FontStyle.Regular;
192                         if (fields.Length > 2) {        // We have style
193                                 string          compare;
194
195                                 for (int i = 2; i < fields.Length; i++) {
196                                         compare = fields[i];
197
198                                         if (compare.IndexOf("Regular") != -1) {
199                                                 f_style |= FontStyle.Regular;
200                                         }
201                                         if (compare.IndexOf("Bold") != -1) {
202                                                 f_style |= FontStyle.Bold;
203                                         }
204                                         if (compare.IndexOf("Italic") != -1) {
205                                                 f_style |= FontStyle.Italic;
206                                         }
207                                         if (compare.IndexOf("Strikeout") != -1) {
208                                                 f_style |= FontStyle.Strikeout;
209                                         }
210                                         if (compare.IndexOf("Underline") != -1) {
211                                                 f_style |= FontStyle.Underline;
212                                         }
213                                 }
214                         }
215
216                         return new Font (font, f_size, f_style, f_unit);
217                 }
218
219                 public override object CreateInstance (ITypeDescriptorContext context, IDictionary propertyValues)
220                 {
221                         Object value;
222                         byte charSet = 1;
223                         float size = 8;
224                         String name = null;
225                         bool vertical = false;
226                         FontStyle style = FontStyle.Regular;
227                         FontFamily fontFamily = null;
228                         GraphicsUnit unit = GraphicsUnit.Point;
229
230                         if ((value = propertyValues ["GdiCharSet"]) != null)
231                                 charSet = (byte) value;
232
233                         if ((value = propertyValues ["Size"]) != null)
234                                 size = (float) value;
235
236                         if ((value = propertyValues ["Unit"]) != null)
237                                 unit = (GraphicsUnit) value;
238
239                         if ((value = propertyValues ["Name"]) != null)
240                                 name = (String) value;
241
242                         if ((value = propertyValues ["GdiVerticalFont"]) != null)
243                                 vertical = (bool) value;
244
245                         if ((value = propertyValues ["Bold"]) != null) {
246                                 bool bold = (bool) value;
247                                 if (bold == true)
248                                         style |= FontStyle.Bold;
249                         }
250
251                         if ((value = propertyValues ["Italic"]) != null) {
252                                 bool italic = (bool) value;
253                                 if (italic == true)
254                                         style |= FontStyle.Italic;
255                         }
256
257                         if ((value = propertyValues ["Strikeout"]) != null) {
258                                 bool strike = (bool) value;
259                                 if (strike == true)
260                                         style |= FontStyle.Strikeout;
261                         }
262
263                         if ((value = propertyValues ["Underline"]) != null) {
264                                 bool underline = (bool) value;
265                                 if (underline == true)
266                                         style |= FontStyle.Underline;
267                         }
268
269                         /* ?? Should default font be culture dependent ?? */
270                         if (name == null)
271                                 fontFamily = new FontFamily ("Tahoma");
272                         else {
273                                 name = name.ToLower ();
274                                 FontCollection collection = new InstalledFontCollection ();
275                                 FontFamily [] installedFontList = collection.Families;
276                                 foreach (FontFamily font in installedFontList) {
277                                         if (name == font.Name.ToLower ()) {
278                                                 fontFamily = font;
279                                                 break;
280                                         }
281                                 }
282
283                                 // font family not found in installed fonts
284                                 if (fontFamily == null) {
285                                         collection = new PrivateFontCollection ();
286                                         FontFamily [] privateFontList = collection.Families;
287                                         foreach (FontFamily font in privateFontList) {
288                                                 if (name == font.Name.ToLower ()) {
289                                                         fontFamily = font;
290                                                         break;
291                                                 }
292                                         }
293                                 }
294
295                                 // font family not found in private fonts also
296                                 if (fontFamily == null)
297                                         fontFamily = FontFamily.GenericSansSerif;
298                         }
299
300                         return new Font (fontFamily, size, style, unit, charSet, vertical);
301                 }
302
303                 public override bool GetCreateInstanceSupported (ITypeDescriptorContext context)
304                 {
305                         return true;
306                 }
307
308                 public override PropertyDescriptorCollection GetProperties
309                         (ITypeDescriptorContext context,
310                         object value, Attribute [] attributes)
311                 {
312                         if (value is Font)
313                                 return TypeDescriptor.GetProperties (value, attributes);
314
315                         return base.GetProperties (context, value, attributes);
316                 }
317
318                 public override bool GetPropertiesSupported (ITypeDescriptorContext context)
319                 {
320                         return true;
321                 }
322
323                 public sealed class FontNameConverter : TypeConverter
324 #if NET_2_0
325                 , IDisposable           
326 #endif
327                 {
328                         FontFamily [] fonts;
329                         
330                         public FontNameConverter ()
331                         {
332                                 fonts = FontFamily.Families;
333                         }       
334 #if NET_2_0                     
335                         void IDisposable.Dispose ()
336                         {
337                         }
338 #endif
339                         public override bool CanConvertFrom (ITypeDescriptorContext context, Type sourceType)
340                         {
341                                 if (sourceType == typeof (string))
342                                         return true;
343
344                                 return base.CanConvertFrom (context, sourceType);
345                         }
346
347                         public override object ConvertFrom (ITypeDescriptorContext context, CultureInfo culture, object value)
348                         {
349                                 if (value is string)
350                                         return value;
351                                 return base.ConvertFrom (context, culture, value);
352                         }
353
354                         public override StandardValuesCollection GetStandardValues (ITypeDescriptorContext context)
355                         {
356                                 string [] values = new string [fonts.Length];
357                                 for (int i = fonts.Length; i > 0;){
358                                         i--;
359                                         values [i] = fonts [i].Name;
360                                 }
361                                 
362                                 return new TypeConverter.StandardValuesCollection (values);
363                         }
364
365                         public override bool GetStandardValuesExclusive (ITypeDescriptorContext context)
366                         {
367                                 // We allow other values other than those in the font list.
368                                 return false;
369                         }
370
371                         public override bool GetStandardValuesSupported (ITypeDescriptorContext context)
372                         {
373                                 // Yes, we support picking an element from the list. 
374                                 return true;
375                         }
376                 }
377
378                 public class FontUnitConverter : EnumConverter
379                 {
380                         public FontUnitConverter () : base (typeof (GraphicsUnit)) {}
381                         
382                         public override StandardValuesCollection GetStandardValues (ITypeDescriptorContext context)
383                         {
384                                 return base.GetStandardValues (context);
385                         }
386                                 
387                 }
388         }
389 }