<PackageReference Include="System.Drawing.Common" Version="10.0.0-preview.1.25080.3" />

Font

Defines a particular format for text, including font face, size, and style attributes. This class cannot be inherited.
using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using System.Drawing.Interop; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using Windows.Win32; using Windows.Win32.Graphics.Gdi; using Windows.Win32.Graphics.GdiPlus; namespace System.Drawing { [Serializable] [NullableContext(1)] [Nullable(0)] [Editor("System.Drawing.Design.FontEditor, System.Drawing.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.Drawing.Design.UITypeEditor, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] [TypeConverter(typeof(FontConverter))] [TypeForwardedFrom("System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] public sealed class Font : MarshalByRefObject, ICloneable, IDisposable, ISerializable { [NonSerialized] [Nullable(0)] private unsafe GpFont* _nativeFont; private float _fontSize; private FontStyle _fontStyle; private FontFamily _fontFamily; private GraphicsUnit _fontUnit; private byte _gdiCharSet = 1; private bool _gdiVerticalFont; private string _systemFontName = string.Empty; [Nullable(2)] private string _originalFontName; public float Size => _fontSize; [Browsable(false)] public FontStyle Style { get { return _fontStyle; } } [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public bool Bold { get { return (Style & FontStyle.Bold) != FontStyle.Regular; } } [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public bool Italic { get { return (Style & FontStyle.Italic) != FontStyle.Regular; } } [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public bool Strikeout { get { return (Style & FontStyle.Strikeout) != FontStyle.Regular; } } [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public bool Underline { get { return (Style & FontStyle.Underline) != FontStyle.Regular; } } [Browsable(false)] public FontFamily FontFamily { get { return _fontFamily; } } [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] [Editor("System.Drawing.Design.FontNameEditor, System.Drawing.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.Drawing.Design.UITypeEditor, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] [TypeConverter(typeof(FontConverter.FontNameConverter))] public string Name { get { return FontFamily.Name; } } [TypeConverter(typeof(FontConverter.FontUnitConverter))] public GraphicsUnit Unit { get { return _fontUnit; } } [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public byte GdiCharSet { get { return _gdiCharSet; } } [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public bool GdiVerticalFont { get { return _gdiVerticalFont; } } [Nullable(2)] [Browsable(false)] public string OriginalFontName { [NullableContext(2)] get { return _originalFontName; } } [Browsable(false)] public string SystemFontName { get { return _systemFontName; } } [Browsable(false)] public bool IsSystemFont { get { return !string.IsNullOrEmpty(_systemFontName); } } [Browsable(false)] public int Height { get { return (int)Math.Ceiling((double)GetHeight()); } } [Nullable(0)] internal unsafe GpFont* NativeFont { [NullableContext(0)] get { return _nativeFont; } } [Browsable(false)] public float SizeInPoints { get { if (Unit != GraphicsUnit.Point) { GetDcScope scope = GetDcScope.ScreenDC; try { using (Graphics graphics = Graphics.FromHdcInternal((IntPtr)ref scope)) { float num = (float)((double)graphics.DpiY / 72); return GetHeight(graphics) * (float)FontFamily.GetEmHeight(Style) / (float)FontFamily.GetLineSpacing(Style) / num; } } finally { scope.Dispose(); } } return Size; } } ~Font() { Dispose(false); } private Font(SerializationInfo info, StreamingContext context) { string string = info.GetString("Name"); FontStyle style = (FontStyle)info.GetValue("Style", typeof(FontStyle)); GraphicsUnit unit = (GraphicsUnit)info.GetValue("Unit", typeof(GraphicsUnit)); float single = info.GetSingle("Size"); Initialize(string, single, style, unit, 1, IsVerticalName(string)); } void ISerializable.GetObjectData(SerializationInfo si, StreamingContext context) { string value = string.IsNullOrEmpty(OriginalFontName) ? Name : OriginalFontName; si.AddValue("Name", value); si.AddValue("Size", Size); si.AddValue("Style", Style); si.AddValue("Unit", Unit); } private static bool IsVerticalName(string familyName) { if (familyName != null && familyName.Length > 0) return familyName[0] == '@'; return false; } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } private unsafe void Dispose(bool disposing) { if (_nativeFont != null) try { PInvokeGdiPlus.GdipDeleteFont(_nativeFont); } catch (Exception ex) when (!ClientUtils.IsCriticalException(ex)) { } finally { _nativeFont = null; } } public unsafe float GetHeight(Graphics graphics) { ArgumentNullException.ThrowIfNull(graphics, "graphics"); if (graphics.NativeGraphics == null) throw new ArgumentException(null, "graphics"); float result = default(float); PInvokeGdiPlus.GdipGetFontHeight(NativeFont, graphics.Pointer(), &result).ThrowIfFailed(); GC.KeepAlive(this); GC.KeepAlive(graphics); return result; } public unsafe float GetHeight(float dpi) { float result = default(float); PInvokeGdiPlus.GdipGetFontHeightGivenDPI(NativeFont, dpi, &result).ThrowIfFailed(); GC.KeepAlive(this); return result; } [NullableContext(2)] public override bool Equals([NotNullWhen(true)] object obj) { if (obj == this) return true; Font font = obj as Font; if (font == null) return false; if (font.FontFamily.Equals(FontFamily) && font.GdiVerticalFont == GdiVerticalFont && font.GdiCharSet == GdiCharSet && font.Style == Style && font.Size == Size) return font.Unit == Unit; return false; } public override int GetHashCode() { return HashCode.Combine(Name, Style, Size, Unit); } public override string ToString() { DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(55, 6); defaultInterpolatedStringHandler.AppendLiteral("["); defaultInterpolatedStringHandler.AppendFormatted(GetType().Name); defaultInterpolatedStringHandler.AppendLiteral(": Name="); defaultInterpolatedStringHandler.AppendFormatted(FontFamily.Name); defaultInterpolatedStringHandler.AppendLiteral(", Size="); defaultInterpolatedStringHandler.AppendFormatted(_fontSize); defaultInterpolatedStringHandler.AppendLiteral(", Units="); defaultInterpolatedStringHandler.AppendFormatted((int)_fontUnit); defaultInterpolatedStringHandler.AppendLiteral(", GdiCharSet="); defaultInterpolatedStringHandler.AppendFormatted(_gdiCharSet); defaultInterpolatedStringHandler.AppendLiteral(", GdiVerticalFont="); defaultInterpolatedStringHandler.AppendFormatted(_gdiVerticalFont); defaultInterpolatedStringHandler.AppendLiteral("]"); return defaultInterpolatedStringHandler.ToStringAndClear(); } internal void SetSystemFontName(string systemFontName) { _systemFontName = systemFontName; } [EditorBrowsable(EditorBrowsableState.Never)] public unsafe void ToLogFont(object logFont, Graphics graphics) { ArgumentNullException.ThrowIfNull(logFont, "logFont"); Type type = logFont.GetType(); int num = sizeof(LOGFONT); if (Marshal.SizeOf(type) != num) throw new ArgumentException(null, "logFont"); ToLogFont(out LOGFONT logFont2, graphics); if (!type.IsValueType) Marshal.PtrToStructure(new IntPtr(&logFont2), logFont); else { GCHandle gCHandle = GCHandle.Alloc(logFont, GCHandleType.Pinned); Buffer.MemoryCopy(&logFont2, (void*)(long)gCHandle.AddrOfPinnedObject(), num, num); gCHandle.Free(); } } public unsafe void ToLogFont(out LOGFONT logFont, Graphics graphics) { ArgumentNullException.ThrowIfNull(graphics, "graphics"); fixed (LOGFONT* logfontW = &logFont) { PInvokeGdiPlus.GdipGetLogFont(NativeFont, graphics.Pointer(), (LOGFONTW*)logfontW).ThrowIfFailed(); GC.KeepAlive(this); GC.KeepAlive(graphics); } if (_gdiVerticalFont) { Span<char> lfFaceName = logFont.lfFaceName; lfFaceName.Slice(0, lfFaceName.Length - 1).CopyTo(lfFaceName.Slice(1, lfFaceName.Length - 1)); lfFaceName[0] = '@'; lfFaceName[lfFaceName.Length - 1] = ''; } if (logFont.lfCharSet == 0) logFont.lfCharSet = _gdiCharSet; } private unsafe void CreateNativeFont() { GpFont* nativeFont = default(GpFont*); Status status = PInvokeGdiPlus.GdipCreateFont(_fontFamily.Pointer(), _fontSize, (int)_fontStyle, (Unit)_fontUnit, &nativeFont); GC.KeepAlive(this); _nativeFont = nativeFont; switch (status) { case Status.Ok: break; case Status.FontStyleNotFound: throw new ArgumentException(System.SR.Format(System.SR.GdiplusFontStyleNotFound, _fontFamily.Name, _fontStyle.ToString())); default: throw status.GetException(); } } public Font(Font prototype, FontStyle newStyle) { _originalFontName = prototype.OriginalFontName; Initialize(prototype.FontFamily, prototype.Size, newStyle, prototype.Unit, 1, false); } public Font(FontFamily family, float emSize, FontStyle style, GraphicsUnit unit) { Initialize(family, emSize, style, unit, 1, false); } public Font(FontFamily family, float emSize, FontStyle style, GraphicsUnit unit, byte gdiCharSet) { Initialize(family, emSize, style, unit, gdiCharSet, false); } public Font(FontFamily family, float emSize, FontStyle style, GraphicsUnit unit, byte gdiCharSet, bool gdiVerticalFont) { Initialize(family, emSize, style, unit, gdiCharSet, gdiVerticalFont); } public Font(string familyName, float emSize, FontStyle style, GraphicsUnit unit, byte gdiCharSet) { Initialize(familyName, emSize, style, unit, gdiCharSet, IsVerticalName(familyName)); } public Font(string familyName, float emSize, FontStyle style, GraphicsUnit unit, byte gdiCharSet, bool gdiVerticalFont) { if (float.IsNaN(emSize) || float.IsInfinity(emSize) || emSize <= 0) throw new ArgumentException(System.SR.Format(System.SR.InvalidBoundArgument, "emSize", emSize, 0, "System.Single.MaxValue"), "emSize"); Initialize(familyName, emSize, style, unit, gdiCharSet, gdiVerticalFont); } public Font(FontFamily family, float emSize, FontStyle style) { Initialize(family, emSize, style, GraphicsUnit.Point, 1, false); } public Font(FontFamily family, float emSize, GraphicsUnit unit) { Initialize(family, emSize, FontStyle.Regular, unit, 1, false); } public Font(FontFamily family, float emSize) { Initialize(family, emSize, FontStyle.Regular, GraphicsUnit.Point, 1, false); } public Font(string familyName, float emSize, FontStyle style, GraphicsUnit unit) { Initialize(familyName, emSize, style, unit, 1, IsVerticalName(familyName)); } public Font(string familyName, float emSize, FontStyle style) { Initialize(familyName, emSize, style, GraphicsUnit.Point, 1, IsVerticalName(familyName)); } public Font(string familyName, float emSize, GraphicsUnit unit) { Initialize(familyName, emSize, FontStyle.Regular, unit, 1, IsVerticalName(familyName)); } public Font(string familyName, float emSize) { Initialize(familyName, emSize, FontStyle.Regular, GraphicsUnit.Point, 1, IsVerticalName(familyName)); } [NullableContext(0)] private unsafe Font(GpFont* nativeFont, byte gdiCharSet, bool gdiVerticalFont) { _nativeFont = nativeFont; GraphicsUnit unit = default(GraphicsUnit); PInvokeGdiPlus.GdipGetFontUnit(_nativeFont, (Unit*)(&unit)).ThrowIfFailed(); float emSize = default(float); PInvokeGdiPlus.GdipGetFontSize(_nativeFont, &emSize).ThrowIfFailed(); FontStyle style = default(FontStyle); PInvokeGdiPlus.GdipGetFontStyle(_nativeFont, (int*)(&style)).ThrowIfFailed(); GpFontFamily* family = default(GpFontFamily*); PInvokeGdiPlus.GdipGetFamily(_nativeFont, &family).ThrowIfFailed(); SetFontFamily(new FontFamily(family, true)); Initialize(_fontFamily, emSize, style, unit, gdiCharSet, gdiVerticalFont); } private void Initialize(string familyName, float emSize, FontStyle style, GraphicsUnit unit, byte gdiCharSet, bool gdiVerticalFont) { _originalFontName = familyName; ReadOnlySpan<char> name = familyName.AsSpan(); if (name.Length > 1 && name[0] == '@') name = name.Slice(1, name.Length - 1); SetFontFamily(new FontFamily(name, true)); Initialize(_fontFamily, emSize, style, unit, gdiCharSet, gdiVerticalFont); } private unsafe void Initialize(FontFamily family, float emSize, FontStyle style, GraphicsUnit unit, byte gdiCharSet, bool gdiVerticalFont) { ArgumentNullException.ThrowIfNull(family, "family"); if (float.IsNaN(emSize) || float.IsInfinity(emSize) || emSize <= 0) throw new ArgumentException(System.SR.Format(System.SR.InvalidBoundArgument, "emSize", emSize, 0, "System.Single.MaxValue"), "emSize"); _fontSize = emSize; _fontStyle = style; _fontUnit = unit; _gdiCharSet = gdiCharSet; _gdiVerticalFont = gdiVerticalFont; if (_fontFamily == null) SetFontFamily(family.Clone()); if (_nativeFont == null) CreateNativeFont(); float fontSize = default(float); Status status = PInvokeGdiPlus.GdipGetFontSize(_nativeFont, &fontSize); _fontSize = fontSize; GC.KeepAlive(this); Gdip.CheckStatus(status); } public static Font FromHfont(IntPtr hfont) { PInvokeCore.GetObject((HGDIOBJ)hfont, out LOGFONT object); GetDcScope scope = GetDcScope.ScreenDC; try { return FromLogFont(ref object, (IntPtr)ref scope); } finally { scope.Dispose(); } } public static Font FromLogFont(object lf) { GetDcScope scope = GetDcScope.ScreenDC; try { return FromLogFont(lf, (IntPtr)ref scope); } finally { scope.Dispose(); } } public static Font FromLogFont([In] [IsReadOnly] ref LOGFONT logFont) { GetDcScope scope = GetDcScope.ScreenDC; try { return FromLogFont(ref logFont, (IntPtr)ref scope); } finally { scope.Dispose(); } } public unsafe static Font FromLogFont([In] [IsReadOnly] ref LOGFONT logFont, IntPtr hdc) { Status status; GpFont* ptr = default(GpFont*); fixed (LOGFONT* logfont = &logFont) { status = PInvokeGdiPlus.GdipCreateFontFromLogfont((HDC)hdc, (LOGFONTW*)logfont, &ptr); } switch (status) { case Status.NotTrueTypeFont: throw new ArgumentException(System.SR.GdiplusNotTrueTypeFont_NoName); default: throw Gdip.StatusException(status); case Status.Ok: if (ptr == null) throw new ArgumentException(System.SR.Format(System.SR.GdiplusNotTrueTypeFont, logFont.AsString())); return new Font(ptr, logFont.lfCharSet, logFont.IsGdiVerticalFont); } } [EditorBrowsable(EditorBrowsableState.Never)] public unsafe static Font FromLogFont(object lf, IntPtr hdc) { ArgumentNullException.ThrowIfNull(lf, "lf"); LOGFONT logFont; if (lf is LOGFONT) { logFont = (LOGFONT)lf; return FromLogFont(ref logFont, hdc); } Type type = lf.GetType(); int num = sizeof(LOGFONT); if (Marshal.SizeOf(type) != num) throw new ArgumentException(null, "lf"); logFont = default(LOGFONT); Marshal.StructureToPtr(lf, new IntPtr(&logFont), false); return FromLogFont(ref logFont, hdc); } public unsafe static Font FromHdc(IntPtr hdc) { GpFont* nativeFont = default(GpFont*); Status status = PInvokeGdiPlus.GdipCreateFontFromDC((HDC)hdc, &nativeFont); switch (status) { case Status.NotTrueTypeFont: throw new ArgumentException(System.SR.GdiplusNotTrueTypeFont_NoName); default: throw Gdip.StatusException(status); case Status.Ok: return new Font(nativeFont, 0, false); } } public unsafe object Clone() { GpFont* nativeFont = default(GpFont*); PInvokeGdiPlus.GdipCloneFont(_nativeFont, &nativeFont).ThrowIfFailed(); GC.KeepAlive(this); return new Font(nativeFont, _gdiCharSet, _gdiVerticalFont); } private void SetFontFamily(FontFamily family) { _fontFamily = family; GC.SuppressFinalize(_fontFamily); } public void ToLogFont(object logFont) { GetDcScope scope = GetDcScope.ScreenDC; try { using (Graphics graphics = Graphics.FromHdcInternal((IntPtr)ref scope)) ToLogFont(logFont, graphics); } finally { scope.Dispose(); } } public void ToLogFont(out LOGFONT logFont) { GetDcScope scope = GetDcScope.ScreenDC; try { using (Graphics graphics = Graphics.FromHdcInternal((IntPtr)ref scope)) ToLogFont(out logFont, graphics); } finally { scope.Dispose(); } } public unsafe IntPtr ToHfont() { GetDcScope scope = GetDcScope.ScreenDC; try { using (Graphics graphics = Graphics.FromHdcInternal((IntPtr)ref scope)) { ToLogFont(out LOGFONT logFont, graphics); HFONT value = PInvokeCore.CreateFontIndirect((LOGFONTW*)(&logFont)); if (value.IsNull) throw new Win32Exception(); return value; } } finally { scope.Dispose(); } } public float GetHeight() { GetDcScope scope = GetDcScope.ScreenDC; try { using (Graphics graphics = Graphics.FromHdcInternal((IntPtr)ref scope)) return GetHeight(graphics); } finally { scope.Dispose(); } } } }