FontFamily
Defines a group of type faces having a similar basic design and certain variations in styles. This class cannot be inherited.
using System.Diagnostics.CodeAnalysis;
using System.Drawing.Text;
using System.Globalization;
using System.Runtime.CompilerServices;
using Windows.Win32;
using Windows.Win32.Foundation;
using Windows.Win32.Graphics.GdiPlus;
namespace System.Drawing
{
[NullableContext(1)]
[Nullable(0)]
public sealed class FontFamily : MarshalByRefObject, IDisposable
{
private const int NeutralLanguage = 0;
[Nullable(0)]
private unsafe GpFontFamily* _nativeFamily;
private readonly bool _createDefaultOnFail;
[Nullable(0)]
internal unsafe GpFontFamily* NativeFamily {
[NullableContext(0)]
get {
return _nativeFamily;
}
}
private static int CurrentLanguage => CultureInfo.CurrentUICulture.LCID;
public string Name => GetName(CurrentLanguage);
public static FontFamily[] Families => new InstalledFontCollection().Families;
public unsafe static FontFamily GenericSansSerif => new FontFamily(GetGdipGenericSansSerif());
public static FontFamily GenericSerif => new FontFamily(GenericFontFamilies.Serif);
public static FontFamily GenericMonospace => new FontFamily(GenericFontFamilies.Monospace);
[NullableContext(0)]
private unsafe void SetNativeFamily(GpFontFamily* family)
{
_nativeFamily = family;
}
[NullableContext(0)]
internal unsafe FontFamily(GpFontFamily* family)
{
SetNativeFamily(family);
}
internal FontFamily(string name, bool createDefaultOnFail)
{
_createDefaultOnFail = createDefaultOnFail;
CreateFontFamily(name, null);
}
public FontFamily(string name)
{
CreateFontFamily(name, null);
}
public FontFamily(string name, [Nullable(2)] FontCollection fontCollection)
{
CreateFontFamily(name, fontCollection);
}
private unsafe void CreateFontFamily(string name, [Nullable(2)] FontCollection fontCollection)
{
GpFontCollection* fontCollection2 = (GpFontCollection*)(long)((fontCollection == null) ? ((IntPtr)(void*)null) : ((IntPtr)fontCollection._nativeFontCollection));
Status status = Status.Ok;
IntPtr value;
if (name == null)
value = (IntPtr)(void*)null;
else {
ref reference = ref name.GetPinnableReference();
value = (IntPtr)(&reference);
}
GpFontFamily* gdipGenericSansSerif = default(GpFontFamily*);
status = PInvoke.GdipCreateFontFamilyFromName((char*)(long)value, fontCollection2, &gdipGenericSansSerif);
ref reference = ref *(char*)null;
if (status != 0) {
if (_createDefaultOnFail)
gdipGenericSansSerif = GetGdipGenericSansSerif();
else {
switch (status) {
case Status.FontFamilyNotFound:
throw new ArgumentException(System.SR.Format(System.SR.GdiplusFontFamilyNotFound, name));
case Status.NotTrueTypeFont:
throw new ArgumentException(System.SR.Format(System.SR.GdiplusNotTrueTypeFont, name));
}
status.ThrowIfFailed();
}
}
GC.KeepAlive(fontCollection);
SetNativeFamily(gdipGenericSansSerif);
}
public unsafe FontFamily(GenericFontFamilies genericFamily)
{
GpFontFamily* nativeFamily = default(GpFontFamily*);
switch (genericFamily) {
case GenericFontFamilies.Serif:
PInvoke.GdipGetGenericFontFamilySerif(&nativeFamily).ThrowIfFailed();
break;
case GenericFontFamilies.SansSerif:
PInvoke.GdipGetGenericFontFamilySansSerif(&nativeFamily).ThrowIfFailed();
break;
default:
PInvoke.GdipGetGenericFontFamilyMonospace(&nativeFamily).ThrowIfFailed();
break;
}
SetNativeFamily(nativeFamily);
}
~FontFamily()
{
Dispose(false);
}
public override string ToString()
{
DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(9, 2);
defaultInterpolatedStringHandler.AppendLiteral("[");
defaultInterpolatedStringHandler.AppendFormatted(GetType().Name);
defaultInterpolatedStringHandler.AppendLiteral(": Name=");
defaultInterpolatedStringHandler.AppendFormatted(Name);
defaultInterpolatedStringHandler.AppendLiteral("]");
return defaultInterpolatedStringHandler.ToStringAndClear();
}
[NullableContext(2)]
public unsafe override bool Equals([NotNullWhen(true)] object obj)
{
if (obj == this)
return true;
FontFamily fontFamily = obj as FontFamily;
if (fontFamily == null)
return false;
return fontFamily.NativeFamily == NativeFamily;
}
public override int GetHashCode()
{
return GetName(0).GetHashCode();
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private unsafe void Dispose(bool disposing)
{
if (_nativeFamily != null)
try {
PInvoke.GdipDeleteFontFamily(_nativeFamily);
} catch (Exception ex) when (!ClientUtils.IsCriticalException(ex)) {
} finally {
_nativeFamily = null;
}
}
public unsafe string GetName(int language)
{
char* value = stackalloc char[33];
PInvoke.GdipGetFamilyName(NativeFamily, value, (ushort)language).ThrowIfFailed();
return new string(value);
}
[NullableContext(0)]
private unsafe static GpFontFamily* GetGdipGenericSansSerif()
{
GpFontFamily* result = default(GpFontFamily*);
PInvoke.GdipGetGenericFontFamilySansSerif(&result).ThrowIfFailed();
return result;
}
[Obsolete("FontFamily.GetFamilies has been deprecated. Use Families instead.")]
public static FontFamily[] GetFamilies(Graphics graphics)
{
ArgumentNullException.ThrowIfNull(graphics, "graphics");
return new InstalledFontCollection().Families;
}
public unsafe bool IsStyleAvailable(FontStyle style)
{
BOOL value = default(BOOL);
PInvoke.GdipIsStyleAvailable(NativeFamily, (int)style, &value).ThrowIfFailed();
GC.KeepAlive(this);
return value;
}
public unsafe int GetEmHeight(FontStyle style)
{
ushort result = default(ushort);
PInvoke.GdipGetEmHeight(NativeFamily, (int)style, &result).ThrowIfFailed();
GC.KeepAlive(this);
return result;
}
public unsafe int GetCellAscent(FontStyle style)
{
ushort result = default(ushort);
PInvoke.GdipGetCellAscent(NativeFamily, (int)style, &result).ThrowIfFailed();
GC.KeepAlive(this);
return result;
}
public unsafe int GetCellDescent(FontStyle style)
{
ushort result = default(ushort);
PInvoke.GdipGetCellDescent(NativeFamily, (int)style, &result).ThrowIfFailed();
GC.KeepAlive(this);
return result;
}
public unsafe int GetLineSpacing(FontStyle style)
{
ushort result = default(ushort);
PInvoke.GdipGetLineSpacing(NativeFamily, (int)style, &result).ThrowIfFailed();
GC.KeepAlive(this);
return result;
}
}
}