[winforms] Style
[mono.git] / mcs / class / System.Drawing / System.Drawing / Font.cs
1 //
2 // System.Drawing.Fonts.cs
3 //
4 // Authors:
5 //      Alexandre Pigolkine (pigolkine@gmx.de)
6 //      Miguel de Icaza (miguel@ximian.com)
7 //      Todd Berman (tberman@sevenl.com)
8 //      Jordi Mas i Hernandez (jordi@ximian.com)
9 //      Ravindra (rkumar@novell.com)
10 //
11 // Copyright (C) 2004 Ximian, Inc. (http://www.ximian.com)
12 // Copyright (C) 2004, 2006 Novell, Inc (http://www.novell.com)
13 //
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
21 // 
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
24 // 
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 //
33
34 using System.Runtime.Serialization;
35 using System.Runtime.InteropServices;
36 using System.Security.Permissions;
37 using System.ComponentModel;
38
39 namespace System.Drawing
40 {
41         [Serializable]
42         [ComVisible (true)]
43         [Editor ("System.Drawing.Design.FontEditor, " + Consts.AssemblySystem_Drawing_Design, typeof (System.Drawing.Design.UITypeEditor))]
44         [TypeConverter (typeof (FontConverter))]
45         public sealed class Font : MarshalByRefObject, ISerializable, ICloneable, IDisposable
46         {
47                 private IntPtr  fontObject = IntPtr.Zero;
48 #if NET_2_0             
49                 private string  systemFontName;
50                 private string  originalFontName;
51 #endif          
52                 private float _size;
53                 private object olf;
54
55                 private const byte DefaultCharSet = 1;
56                 private static int CharSetOffset = -1;
57
58                 private void CreateFont (string familyName, float emSize, FontStyle style, GraphicsUnit unit, byte charSet, bool isVertical)
59                 {
60 #if ONLY_1_1
61                         if (familyName == null)
62                                 throw new ArgumentNullException ("familyName");
63 #endif
64 #if NET_2_0
65                         originalFontName = familyName;
66 #endif
67                         FontFamily family;
68                         // NOTE: If family name is null, empty or invalid,
69                         // MS creates Microsoft Sans Serif font.
70                         try {
71                                 family = new FontFamily (familyName);
72                         }
73                         catch (Exception){
74                                 family = FontFamily.GenericSansSerif;
75                         }
76
77                         setProperties (family, emSize, style, unit, charSet, isVertical);           
78                         Status status = GDIPlus.GdipCreateFont (family.NativeObject, emSize,  style, unit, out fontObject);
79                         
80                         if (status == Status.FontStyleNotFound)
81                                 throw new ArgumentException (Locale.GetText ("Style {0} isn't supported by font {1}.", style.ToString (), familyName));
82                                 
83                         GDIPlus.CheckStatus (status);
84                 }
85
86                 private Font (SerializationInfo info, StreamingContext context)
87                 {
88                         string          name;
89                         float           size;
90                         FontStyle       style;
91                         GraphicsUnit    unit;
92
93                         name = (string)info.GetValue("Name", typeof(string));
94                         size = (float)info.GetValue("Size", typeof(float));
95                         style = (FontStyle)info.GetValue("Style", typeof(FontStyle));
96                         unit = (GraphicsUnit)info.GetValue("Unit", typeof(GraphicsUnit));
97  
98                         CreateFont(name, size, style, unit, DefaultCharSet, false);
99                 }
100
101                 void ISerializable.GetObjectData(SerializationInfo si, StreamingContext context)
102                 {
103                         si.AddValue("Name", Name);
104                         si.AddValue ("Size", Size);
105                         si.AddValue ("Style", Style);
106                         si.AddValue ("Unit", Unit);
107                 }
108
109                 ~Font()
110                 {
111                         Dispose ();
112                 }
113
114                 public void Dispose ()
115                 {
116                         if (fontObject != IntPtr.Zero) {
117                                 Status status = GDIPlus.GdipDeleteFont (fontObject);
118                                 fontObject = IntPtr.Zero;
119                                 GC.SuppressFinalize (this);
120                                 // check the status code (throw) at the last step
121                                 GDIPlus.CheckStatus (status);
122                         }
123                 }
124
125                 internal void unitConversion (GraphicsUnit fromUnit, GraphicsUnit toUnit, float nSrc, out float nTrg)
126                 {
127                         float inchs = 0;
128                         nTrg = 0;
129                         
130                         switch (fromUnit) {
131                         case GraphicsUnit.Display:
132                                 inchs = nSrc / 75f;
133                                 break;
134                         case GraphicsUnit.Document:
135                                 inchs = nSrc / 300f;
136                                 break;
137                         case GraphicsUnit.Inch:
138                                 inchs = nSrc;
139                                 break;
140                         case GraphicsUnit.Millimeter:
141                                 inchs = nSrc / 25.4f;
142                                 break;
143                         case GraphicsUnit.Pixel:
144                         case GraphicsUnit.World:
145                                 inchs = nSrc / Graphics.systemDpiX;
146                                 break;
147                         case GraphicsUnit.Point:
148                                 inchs = nSrc / 72f;
149                                 break;
150                         default:
151                                 throw new ArgumentException("Invalid GraphicsUnit");
152                         }
153
154                         switch (toUnit) {
155                         case GraphicsUnit.Display:
156                                 nTrg = inchs * 75;
157                                 break;
158                         case GraphicsUnit.Document:
159                                 nTrg = inchs * 300;
160                                 break;
161                         case GraphicsUnit.Inch:
162                                 nTrg = inchs;
163                                 break;
164                         case GraphicsUnit.Millimeter:
165                                 nTrg = inchs * 25.4f;
166                                 break;
167                         case GraphicsUnit.Pixel:
168                         case GraphicsUnit.World:
169                                 nTrg = inchs * Graphics.systemDpiX;
170                                 break;
171                         case GraphicsUnit.Point:
172                                 nTrg = inchs * 72;
173                                 break;
174                         default:
175                                 throw new ArgumentException("Invalid GraphicsUnit");
176                         }
177                 }
178
179                 internal void setProperties (FontFamily family, float emSize, FontStyle style, GraphicsUnit unit, byte charSet, bool isVertical)
180                 {
181                         _name = family.Name;
182                         _fontFamily = family;                   
183                         _size = emSize;
184
185                         // MS throws ArgumentException, if unit is set to GraphicsUnit.Display
186                         _unit = unit;
187                         _style = style;
188                         _gdiCharSet = charSet;
189                         _gdiVerticalFont = isVertical;
190                         
191                         unitConversion (unit, GraphicsUnit.Point, emSize, out  _sizeInPoints);
192                                                 
193                         _bold = _italic = _strikeout = _underline = false;
194
195                         if ((style & FontStyle.Bold) == FontStyle.Bold)
196                                 _bold = true;
197                                 
198                         if ((style & FontStyle.Italic) == FontStyle.Italic)
199                                _italic = true;
200
201                         if ((style & FontStyle.Strikeout) == FontStyle.Strikeout)
202                                 _strikeout = true;
203
204                         if ((style & FontStyle.Underline) == FontStyle.Underline)
205                                 _underline = true;                  
206                 }
207
208                 public static Font FromHfont (IntPtr hfont)
209                 {
210                         IntPtr                  newObject;
211                         IntPtr                  hdc;                    
212                         FontStyle               newStyle = FontStyle.Regular;
213                         float                   newSize;
214                         LOGFONT                 lf = new LOGFONT ();
215
216                         // Sanity. Should we throw an exception?
217                         if (hfont == IntPtr.Zero) {
218                                 Font result = new Font ("Arial", (float)10.0, FontStyle.Regular);
219                                 return(result);
220                         }
221
222                         if (GDIPlus.RunningOnUnix ()) {
223                                 // If we're on Unix we use our private gdiplus API to avoid Wine 
224                                 // dependencies in S.D
225                                 Status s = GDIPlus.GdipCreateFontFromHfont (hfont, out newObject, ref lf);
226                                 GDIPlus.CheckStatus (s);
227                         } else {
228
229                                 // This needs testing
230                                 // GetDC, SelectObject, ReleaseDC GetTextMetric and
231                                 // GetFontFace are not really GDIPlus, see gdipFunctions.cs
232
233                                 newStyle = FontStyle.Regular;
234
235                                 hdc = GDIPlus.GetDC (IntPtr.Zero);
236                                 try {
237                                         return FromLogFont (lf, hdc);
238                                 }
239                                 finally {
240                                         GDIPlus.ReleaseDC (IntPtr.Zero, hdc);
241                                 }
242                         }
243                         
244                         if (lf.lfItalic != 0) {
245                                 newStyle |= FontStyle.Italic;
246                         }
247
248                         if (lf.lfUnderline != 0) {
249                                 newStyle |= FontStyle.Underline;
250                         }
251
252                         if (lf.lfStrikeOut != 0) {
253                                 newStyle |= FontStyle.Strikeout;
254                         }
255
256                         if (lf.lfWeight > 400) {
257                                 newStyle |= FontStyle.Bold;
258                         }
259
260                         if (lf.lfHeight < 0) {
261                                 newSize = lf.lfHeight * -1;
262                         } else {
263                                 newSize = lf.lfHeight;
264                         }
265
266                         return (new Font (newObject, lf.lfFaceName, newStyle, newSize));
267                 }
268
269                 public IntPtr ToHfont ()
270                 {
271                         if (fontObject == IntPtr.Zero)
272                                 throw new ArgumentException (Locale.GetText ("Object has been disposed."));
273
274                         if (GDIPlus.RunningOnUnix ())
275                                 return fontObject;
276
277                         // win32 specific code
278                         if (olf == null) {
279                                 olf = new LOGFONT ();
280                                 ToLogFont(olf);
281                         }
282                         LOGFONT lf = (LOGFONT)olf;
283                         return GDIPlus.CreateFontIndirect (ref lf);
284                 }
285
286                 internal Font (IntPtr newFontObject, string familyName, FontStyle style, float size)
287                 {
288                         FontFamily fontFamily;                  
289                         
290                         try {
291                                 fontFamily = new FontFamily (familyName);
292                         }
293                         catch (Exception){
294                                 fontFamily = FontFamily.GenericSansSerif;
295                         }
296                         
297                         setProperties (fontFamily, size, style, GraphicsUnit.Pixel, 0, false);
298                         fontObject = newFontObject;
299                 }
300
301                 public Font (Font prototype, FontStyle newStyle)
302                 {
303                         // no null checks, MS throws a NullReferenceException if original is null
304                         setProperties (prototype.FontFamily, prototype.Size, newStyle, prototype.Unit, prototype.GdiCharSet, prototype.GdiVerticalFont);
305                                 
306                         Status status = GDIPlus.GdipCreateFont (_fontFamily.NativeObject, Size, Style, Unit, out fontObject);
307                         GDIPlus.CheckStatus (status);                   
308                 }
309
310                 public Font (FontFamily family, float emSize,  GraphicsUnit unit)
311                         : this (family, emSize, FontStyle.Regular, unit, DefaultCharSet, false)
312                 {
313                 }
314
315                 public Font (string familyName, float emSize,  GraphicsUnit unit)
316                         : this (new FontFamily (familyName), emSize, FontStyle.Regular, unit, DefaultCharSet, false)
317                 {
318                 }
319
320                 public Font (FontFamily family, float emSize)
321                         : this (family, emSize, FontStyle.Regular, GraphicsUnit.Point, DefaultCharSet, false)
322                 {
323                 }
324
325                 public Font (FontFamily family, float emSize, FontStyle style)
326                         : this (family, emSize, style, GraphicsUnit.Point, DefaultCharSet, false)
327                 {
328                 }
329
330                 public Font (FontFamily family, float emSize, FontStyle style, GraphicsUnit unit)
331                         : this (family, emSize, style, unit, DefaultCharSet, false)
332                 {
333                 }
334
335                 public Font (FontFamily family, float emSize, FontStyle style, GraphicsUnit unit, byte gdiCharSet)
336                         : this (family, emSize, style, unit, gdiCharSet, false)
337                 {
338                 }
339
340                 public Font (FontFamily family, float emSize, FontStyle style,
341                                 GraphicsUnit unit, byte gdiCharSet, bool gdiVerticalFont)
342                 {
343                         if (family == null)
344                                 throw new ArgumentNullException ("family");
345
346                         Status status;
347                         setProperties (family, emSize, style, unit, gdiCharSet,  gdiVerticalFont );             
348                         status = GDIPlus.GdipCreateFont (family.NativeObject, emSize,  style,   unit,  out fontObject);
349                         GDIPlus.CheckStatus (status);
350                 }
351
352                 public Font (string familyName, float emSize)
353                         : this (familyName, emSize, FontStyle.Regular, GraphicsUnit.Point, DefaultCharSet, false)
354                 {
355                 }
356
357                 public Font (string familyName, float emSize, FontStyle style)
358                         : this (familyName, emSize, style, GraphicsUnit.Point, DefaultCharSet, false)
359                 {
360                 }
361
362                 public Font (string familyName, float emSize, FontStyle style, GraphicsUnit unit)
363                         : this (familyName, emSize, style, unit, DefaultCharSet, false)
364                 {
365                 }
366
367                 public Font (string familyName, float emSize, FontStyle style, GraphicsUnit unit, byte gdiCharSet)
368                         : this (familyName, emSize, style, unit, gdiCharSet, false)
369                 {
370                 }
371
372                 public Font (string familyName, float emSize, FontStyle style,
373                                 GraphicsUnit unit, byte gdiCharSet, bool  gdiVerticalFont )
374                 {
375                         CreateFont (familyName, emSize, style, unit, gdiCharSet,  gdiVerticalFont );
376                 }
377 #if NET_2_0
378                 internal Font (string familyName, float emSize, string systemName)
379                         : this (familyName, emSize, FontStyle.Regular, GraphicsUnit.Point, DefaultCharSet, false)
380                 {
381                         systemFontName = systemName;
382                 }
383 #endif
384                 public object Clone ()
385                 {
386                         return new Font (this, Style);
387                 }
388
389                 internal IntPtr NativeObject {            
390                         get {
391                                 return fontObject;
392                         }
393                 }
394
395                 private bool _bold;
396
397                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
398                 public bool Bold {
399                         get {
400                                 return _bold;
401                         }
402                 }
403
404                 private FontFamily _fontFamily;
405
406                 [Browsable (false)]
407                 public FontFamily FontFamily {
408                         get {
409                                 return _fontFamily;
410                         }
411                 }
412
413                 private byte _gdiCharSet;
414
415                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
416                 public byte GdiCharSet {
417                         get {
418                                 return _gdiCharSet;
419                         }
420                 }
421
422                 private bool _gdiVerticalFont;
423
424                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
425                 public bool GdiVerticalFont {
426                         get {
427                                 return _gdiVerticalFont;
428                         }
429                 }
430
431                 [Browsable (false)]
432                 public int Height {
433                         get {
434                                 return (int) Math.Ceiling (GetHeight ());
435                         }
436                 }
437
438 #if NET_2_0
439                 [Browsable(false)]
440                 public bool IsSystemFont {
441                         get {
442                                 if (systemFontName == null)
443                                         return false;
444
445                                 return StringComparer.InvariantCulture.Compare (systemFontName, string.Empty) != 0;
446                         }
447                 }
448 #endif
449
450                 private bool _italic;
451
452                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
453                 public bool Italic {
454                         get {
455                                 return _italic;
456                         }
457                 }
458
459                 private string _name;
460
461                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
462                 [Editor ("System.Drawing.Design.FontNameEditor, " + Consts.AssemblySystem_Drawing_Design, typeof (System.Drawing.Design.UITypeEditor))]
463                 [TypeConverter (typeof (FontConverter.FontNameConverter))]
464                 public string Name {
465                         get {
466                                 return _name;
467                         }
468                 }
469                 
470                 public float Size {
471                         get {
472                                 return _size;                   
473                         }
474                 }
475
476                 private float _sizeInPoints;
477
478                 [Browsable (false)]
479                 public float SizeInPoints {
480                         get {
481                                 return _sizeInPoints;
482                         }
483                 }
484
485                 private bool _strikeout;
486
487                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
488                 public bool Strikeout {
489                         get {
490                                 return _strikeout;
491                         }
492                 }
493                 
494                 private FontStyle _style;
495
496                 [Browsable (false)]
497                 public FontStyle Style {
498                         get {
499                                 return _style;
500                         }
501                 }
502
503 #if NET_2_0
504                 [Browsable(false)]
505                 public string SystemFontName {
506                         get {
507                                 return systemFontName;
508                         }
509                 }
510
511                 [Browsable(false)]
512                 public string OriginalFontName {
513                         get {
514                                 return originalFontName;
515                         }
516                 }
517 #endif
518                 private bool _underline;
519
520                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
521                 public bool Underline {
522                         get {
523                                 return _underline;
524                         }
525                 }
526
527                 private GraphicsUnit _unit;
528
529                 [TypeConverter (typeof (FontConverter.FontUnitConverter))]
530                 public GraphicsUnit Unit {
531                         get {
532                                 return _unit;
533                         }
534                 }
535
536                 public override bool Equals (object obj)
537                 {
538                         Font fnt = (obj as Font);
539                         if (fnt == null)
540                                 return false;
541
542                         if (fnt.FontFamily.Equals (FontFamily) && fnt.Size == Size &&
543                             fnt.Style == Style && fnt.Unit == Unit &&
544                             fnt.GdiCharSet == GdiCharSet && 
545                             fnt.GdiVerticalFont == GdiVerticalFont)
546                                 return true;
547                         else
548                                 return false;
549                 }
550
551                 public override int GetHashCode ()
552                 {
553                         return _name.GetHashCode () ^ FontFamily.GetHashCode () ^ _size.GetHashCode () ^ _style.GetHashCode () ^
554                                 _gdiCharSet ^ _gdiVerticalFont.GetHashCode ();
555                 }
556
557                 [MonoTODO ("The hdc parameter has no direct equivalent in libgdiplus.")]
558                 public static Font FromHdc (IntPtr hdc)
559                 {
560                         throw new NotImplementedException ();
561                 }
562
563                 [MonoTODO ("The returned font may not have all it's properties initialized correctly.")]
564                 public static Font FromLogFont (object lf, IntPtr hdc)
565                 {
566                         IntPtr newObject;
567                         LOGFONT o = (LOGFONT)lf;
568                         Status status = GDIPlus.GdipCreateFontFromLogfont (hdc, ref o, out newObject);
569                         GDIPlus.CheckStatus (status);
570                         return new Font (newObject, "Microsoft Sans Serif", FontStyle.Regular, 10);
571                 }
572
573                 public float GetHeight ()
574                 {
575                         return GetHeight (Graphics.systemDpiY);
576                 }
577
578                 public static Font FromLogFont (object lf)
579                 {
580                         if (GDIPlus.RunningOnUnix ())
581                                 return FromLogFont(lf, IntPtr.Zero);
582
583                         // win32 specific code
584                         IntPtr hDC = IntPtr.Zero;
585                         try {
586                                 hDC = GDIPlus.GetDC(IntPtr.Zero);
587                                 return FromLogFont (lf, hDC);
588                         }
589                         finally {
590                                 GDIPlus.ReleaseDC (IntPtr.Zero, hDC);
591                         }
592                 }
593
594                 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
595                 public void ToLogFont (object logFont)
596                 {
597                         if (GDIPlus.RunningOnUnix ()) {
598                                 // Unix - We don't have a window we could associate the DC with
599                                 // so we use an image instead
600                                 using (Bitmap img = new Bitmap (1, 1, Imaging.PixelFormat.Format32bppArgb)) {
601                                         using (Graphics g = Graphics.FromImage (img)) {
602                                                 ToLogFont (logFont, g);
603                                         }
604                                 }
605                         } else {
606                                 // Windows
607                                 IntPtr hDC = GDIPlus.GetDC (IntPtr.Zero);
608                                 try {
609                                         using (Graphics g = Graphics.FromHdc (hDC)) {
610                                                 ToLogFont (logFont, g);
611                                         }
612                                 }
613                                 finally {
614                                         GDIPlus.ReleaseDC (IntPtr.Zero, hDC);
615                                 }
616                         }
617                 }
618
619                 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
620                 public void ToLogFont (object logFont, Graphics graphics)
621                 {
622                         if (graphics == null)
623                                 throw new ArgumentNullException ("graphics");
624
625                         if (logFont == null) {
626 #if NET_2_0
627                                 throw new AccessViolationException ("logFont");
628 #else
629                                 throw new NullReferenceException ("logFont");
630 #endif
631                         }
632
633                         Type st = logFont.GetType ();
634                         if (!st.IsLayoutSequential)
635                                 throw new ArgumentException ("logFont", Locale.GetText ("Layout must be sequential."));
636
637                         // note: there is no exception if 'logFont' isn't big enough
638                         Type lf = typeof (LOGFONT);
639                         int size = Marshal.SizeOf (logFont);
640                         if (size >= Marshal.SizeOf (lf)) {
641                                 Status status;
642                                 IntPtr copy = Marshal.AllocHGlobal (size);
643                                 try {
644                                         Marshal.StructureToPtr (logFont, copy, false);
645
646                                         status = GDIPlus.GdipGetLogFont (NativeObject, graphics.NativeObject, logFont);
647                                         if (status != Status.Ok) {
648                                                 // reset to original values
649                                                 Marshal.PtrToStructure (copy, logFont);
650                                         }
651                                 }
652                                 finally {
653                                         Marshal.FreeHGlobal (copy);
654                                 }
655
656                                 if (CharSetOffset == -1) {
657                                         // not sure why this methods returns an IntPtr since it's an offset
658                                         // anyway there's no issue in downcasting the result into an int32
659                                         CharSetOffset = (int) Marshal.OffsetOf (lf, "lfCharSet");
660                                 }
661
662                                 // note: Marshal.WriteByte(object,*) methods are unimplemented on Mono
663                                 GCHandle gch = GCHandle.Alloc (logFont, GCHandleType.Pinned);
664                                 try {
665                                         IntPtr ptr = gch.AddrOfPinnedObject ();
666                                         // if GDI+ lfCharSet is 0, then we return (S.D.) 1, otherwise the value is unchanged
667                                         if (Marshal.ReadByte (ptr, CharSetOffset) == 0) {
668                                                 // set lfCharSet to 1 
669                                                 Marshal.WriteByte (ptr, CharSetOffset, 1);
670                                         }
671                                 }
672                                 finally {
673                                         gch.Free ();
674                                 }
675
676                                 // now we can throw, if required
677                                 GDIPlus.CheckStatus (status);
678                         }
679                 }
680
681                 public float GetHeight (Graphics graphics)
682                 {
683                         if (graphics == null)
684                                 throw new ArgumentNullException ("graphics");
685
686                         float size;
687                         Status status = GDIPlus.GdipGetFontHeight (fontObject, graphics.NativeObject, out size);
688                         GDIPlus.CheckStatus (status);
689                         return size;
690                 }
691
692                 public float GetHeight (float dpi)
693                 {
694                         float size;
695                         Status status = GDIPlus.GdipGetFontHeightGivenDPI (fontObject, dpi, out size);
696                         GDIPlus.CheckStatus (status);
697                         return size;
698                 }
699
700                 public override String ToString ()
701                 {
702                         return String.Format ("[Font: Name={0}, Size={1}, Units={2}, GdiCharSet={3}, GdiVerticalFont={4}]", _name, Size, (int)_unit, _gdiCharSet, _gdiVerticalFont);
703                 }
704         }
705 }