// // System.Drawing.Fonts.cs // // Authors: // Alexandre Pigolkine (pigolkine@gmx.de) // Miguel de Icaza (miguel@ximian.com) // Todd Berman (tberman@sevenl.com) // Jordi Mas i Hernandez (jordi@ximian.com) // Ravindra (rkumar@novell.com) // // Copyright (C) 2004 Ximian, Inc. (http://www.ximian.com) // // Copyright (C) 2004 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.Runtime.Serialization; using System.Runtime.InteropServices; using System.ComponentModel; namespace System.Drawing { [Serializable] [ComVisible (true)] [Editor ("System.Drawing.Design.FontEditor, " + Consts.AssemblySystem_Drawing_Design, typeof (System.Drawing.Design.UITypeEditor))] [TypeConverter (typeof (FontConverter))] public sealed class Font : MarshalByRefObject, ISerializable, ICloneable, IDisposable { private IntPtr fontObject = IntPtr.Zero; private Font (SerializationInfo info, StreamingContext context) { } void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { } ~Font() { Dispose (); } public void Dispose () { if (fontObject != IntPtr.Zero) { lock (this) { GDIPlus.CheckStatus (GDIPlus.GdipDeleteFont (fontObject)); } GC.SuppressFinalize (this); } } internal void unitConversion (GraphicsUnit fromUnit, GraphicsUnit toUnit, float nSrc, out float nTrg) { float inchs = 0; nTrg = 0; switch (fromUnit) { case GraphicsUnit.Display: inchs = nSrc / 75f; break; case GraphicsUnit.Document: inchs = nSrc / 300f; break; case GraphicsUnit.Inch: inchs = nSrc; break; case GraphicsUnit.Millimeter: inchs = nSrc / 25.4f; break; case GraphicsUnit.Pixel: case GraphicsUnit.World: inchs = nSrc / Graphics.systemDpiX; break; case GraphicsUnit.Point: inchs = nSrc / 72f; break; default: throw new ArgumentException("Invalid GraphicsUnit"); } switch (toUnit) { case GraphicsUnit.Display: nTrg = inchs * 75; break; case GraphicsUnit.Document: nTrg = inchs * 300; break; case GraphicsUnit.Inch: nTrg = inchs; break; case GraphicsUnit.Millimeter: nTrg = inchs * 25.4f; break; case GraphicsUnit.Pixel: case GraphicsUnit.World: nTrg = inchs * Graphics.systemDpiX; break; case GraphicsUnit.Point: nTrg = inchs * 72; break; default: throw new ArgumentException("Invalid GraphicsUnit"); } } internal void setProperties (FontFamily family, float emSize, FontStyle style, GraphicsUnit unit, byte charSet, bool isVertical) { _name = family.Name; _fontFamily = family; _size = emSize; // MS throws ArgumentException, if unit is set to GraphicsUnit.Display _unit = unit; _style = style; _gdiCharSet = charSet; _gdiVerticalFont = isVertical; unitConversion (unit, GraphicsUnit.Point, emSize, out _sizeInPoints); _bold = _italic = _strikeout = _underline = false; if ((style & FontStyle.Bold) == FontStyle.Bold) _bold = true; if ((style & FontStyle.Italic) == FontStyle.Italic) _italic = true; if ((style & FontStyle.Strikeout) == FontStyle.Strikeout) _strikeout = true; if ((style & FontStyle.Underline) == FontStyle.Underline) _underline = true; } public static Font FromHfont (IntPtr Hfont) { OperatingSystem osInfo = Environment.OSVersion; IntPtr newObject; IntPtr hdc; IntPtr oldFont; FontStyle newStyle = FontStyle.Regular; float newSize; LOGFONTA lf = new LOGFONTA (); // Sanity. Should we throw an exception? if (Hfont == IntPtr.Zero) { Font result = new Font ("Arial", (float)10.0, FontStyle.Regular); return(result); } if ((int) osInfo.Platform == 128) { // If we're on Unix we use our private gdiplus API to avoid Wine // dependencies in S.D lock (typeof (Font)) { Status s = GDIPlus.GdipCreateFontFromHfont (Hfont, out newObject, ref lf); GDIPlus.CheckStatus (s); } } else { // This needs testing // GetDC, SelectObject, ReleaseDC GetTextMetric and // GetFontFace are not really GDIPlus, see gdipFunctions.cs newStyle = FontStyle.Regular; lock (typeof (Font)) { hdc = GDIPlus.GetDC (IntPtr.Zero); oldFont = GDIPlus.SelectObject (hdc, Hfont); GDIPlus.CheckStatus (GDIPlus.GdipCreateFontFromDC (hdc, out newObject)); GDIPlus.CheckStatus (GDIPlus.GdipGetLogFontA (newObject, IntPtr.Zero, ref lf)); GDIPlus.SelectObject (hdc, oldFont); GDIPlus.ReleaseDC (hdc); } } if (lf.lfItalic != 0) { newStyle |= FontStyle.Italic; } if (lf.lfUnderline != 0) { newStyle |= FontStyle.Underline; } if (lf.lfStrikeOut != 0) { newStyle |= FontStyle.Strikeout; } if (lf.lfWeight > 400) { newStyle |= FontStyle.Bold; } if (lf.lfHeight < 0) { newSize = lf.lfHeight * -1; } else { newSize = lf.lfHeight; } return (new Font (newObject, lf.lfFaceName, newStyle, newSize)); } public IntPtr ToHfont () { IntPtr Hfont; OperatingSystem osInfo = Environment.OSVersion; // Sanity. Should we throw an exception? if (fontObject == IntPtr.Zero) { return IntPtr.Zero; } if ((int) osInfo.Platform == 128) { // If we're on Unix we use our private gdiplus API GDIPlus.CheckStatus (GDIPlus.GdipGetHfont (fontObject, out Hfont)); } else { // This needs testing, but I don't have a working win32 mono // environment. LOGFONTA lf = new LOGFONTA (); GDIPlus.CheckStatus (GDIPlus.GdipGetLogFontA (fontObject, IntPtr.Zero, ref lf)); Hfont = GDIPlus.CreateFontIndirectA (ref lf); } return Hfont; } internal Font (IntPtr newFontObject, string familyName, FontStyle style, float size) { FontFamily fontFamily = new FontFamily (familyName); setProperties (fontFamily, size, style, GraphicsUnit.Pixel, 0, false); fontObject = newFontObject; } public Font (Font original, FontStyle style) { lock (this) { Status status; setProperties (original.FontFamily, original.Size, style, original.Unit, original.GdiCharSet, original.GdiVerticalFont); status = GDIPlus.GdipCreateFont (_fontFamily.NativeObject, Size, Style, Unit, out fontObject); GDIPlus.CheckStatus (status); } } public Font (FontFamily family, float emSize, GraphicsUnit unit) : this (family, emSize, FontStyle.Regular, unit, (byte)0, false) { } public Font (string familyName, float emSize, GraphicsUnit unit) : this (new FontFamily (familyName), emSize, FontStyle.Regular, unit, (byte)0, false) { } public Font (FontFamily family, float emSize) : this (family, emSize, FontStyle.Regular, GraphicsUnit.Point, (byte)0, false) { } public Font (FontFamily family, float emSize, FontStyle style) : this (family, emSize, style, GraphicsUnit.Point, (byte)0, false) { } public Font (FontFamily family, float emSize, FontStyle style, GraphicsUnit unit) : this (family, emSize, style, unit, (byte)0, false) { } public Font (FontFamily family, float emSize, FontStyle style, GraphicsUnit unit, byte charSet) : this (family, emSize, style, unit, charSet, false) { } public Font (FontFamily family, float emSize, FontStyle style, GraphicsUnit unit, byte charSet, bool isVertical) { lock (this) { Status status; setProperties (family, emSize, style, unit, charSet, isVertical); status = GDIPlus.GdipCreateFont (family.NativeObject, emSize, style, unit, out fontObject); GDIPlus.CheckStatus (status); } } public Font (string familyName, float emSize) : this (familyName, emSize, FontStyle.Regular, GraphicsUnit.Point, (byte)0, false) { } public Font (string familyName, float emSize, FontStyle style) : this (familyName, emSize, style, GraphicsUnit.Point, (byte)0, false) { } public Font (string familyName, float emSize, FontStyle style, GraphicsUnit unit) : this (familyName, emSize, style, unit, (byte)0, false) { } public Font (string familyName, float emSize, FontStyle style, GraphicsUnit unit, byte charSet) : this (familyName, emSize, style, unit, charSet, false) { } public Font (string familyName, float emSize, FontStyle style, GraphicsUnit unit, byte charSet, bool isVertical) { lock (this) { // NOTE: If family name is empty or invalid, MS // creates Microsoft Sans Serif font. MS does not // accept null values for familyName. Status status; FontFamily family = new FontFamily (familyName); setProperties (family, emSize, style, unit, charSet, isVertical); status = GDIPlus.GdipCreateFont (family.NativeObject, emSize, style, unit, out fontObject); GDIPlus.CheckStatus (status); } } public object Clone () { return new Font (this, Style); } internal IntPtr NativeObject { get { return fontObject; } set { fontObject = value; } } private bool _bold; [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] public bool Bold { get { return _bold; } } private FontFamily _fontFamily; [Browsable (false)] public FontFamily FontFamily { get { return _fontFamily; } } private byte _gdiCharSet; [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] public byte GdiCharSet { get { return _gdiCharSet; } } private bool _gdiVerticalFont; [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] public bool GdiVerticalFont { get { return _gdiVerticalFont; } } private int _height; [Browsable (false)] public int Height { get { return _height; } } private bool _italic; [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] public bool Italic { get { return _italic; } } private string _name; [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] [Editor ("System.Drawing.Design.FontNameEditor, " + Consts.AssemblySystem_Drawing_Design, typeof (System.Drawing.Design.UITypeEditor))] [TypeConverter (typeof (FontConverter.FontNameConverter))] public string Name { get { return _name; } } private float _size; public float Size { get { return _size; } } private float _sizeInPoints; [Browsable (false)] public float SizeInPoints { get { return _sizeInPoints; } } private bool _strikeout; [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] public bool Strikeout { get { return _strikeout; } } private FontStyle _style; [Browsable (false)] public FontStyle Style { get { return _style; } } private bool _underline; [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] public bool Underline { get { return _underline; } } private GraphicsUnit _unit; [TypeConverter (typeof (FontConverter.FontUnitConverter))] public GraphicsUnit Unit { get { return _unit; } } public override bool Equals (object obj) { if (! (obj is Font)) return false; Font fnt = (Font) obj; if (fnt.FontFamily == FontFamily && fnt.Size == Size && fnt.Style == Style && fnt.Unit == Unit && fnt.GdiCharSet == GdiCharSet && fnt.GdiVerticalFont == GdiVerticalFont) return true; else return false; } public override int GetHashCode () { return _name.GetHashCode (); } [MonoTODO] public static Font FromHdc (IntPtr hdc) { throw new NotImplementedException (); } [MonoTODO] public static Font FromLogFont (object lf, IntPtr hdc) { throw new NotImplementedException (); } public float GetHeight () { return (float) _height; } [MonoTODO] public static Font FromLogFont (object lf) { throw new NotImplementedException (); } [MonoTODO] public void ToLogFont (object logFont) { throw new NotImplementedException (); } [MonoTODO] public void ToLogFont (object logFont, Graphics graphics) { throw new NotImplementedException (); } [MonoTODO] public float GetHeight (Graphics graphics) { if (Unit == GraphicsUnit.Pixel || Unit == GraphicsUnit.World) return GetHeight (); throw new NotImplementedException (); } [MonoTODO] public float GetHeight (float dpi) { return GetHeight (); } public override String ToString () { return String.Format ("[Font: Name={0}, Size={1}, Style={2}, Units={3}, GdiCharSet={4}, GdiVerticalFont={5}]", _name, _size, _style, _unit, _gdiCharSet, _gdiVerticalFont); } } }