From 648f64535a4d1621310296be6a361866bd8f6845 Mon Sep 17 00:00:00 2001 From: Andrii Kurdiumov Date: Tue, 24 Jan 2023 20:11:37 +0600 Subject: [PATCH] Introduce AOT friendly version of ToLogFont and FromLogFont These methods used by WinForms Closes #70358 --- .../ref/System.Drawing.Common.netcoreapp.cs | 7 ++ .../src/System/Drawing/Font.cs | 75 +++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/src/libraries/System.Drawing.Common/ref/System.Drawing.Common.netcoreapp.cs b/src/libraries/System.Drawing.Common/ref/System.Drawing.Common.netcoreapp.cs index 389223c06e17dc..1ed2302cdc519f 100644 --- a/src/libraries/System.Drawing.Common/ref/System.Drawing.Common.netcoreapp.cs +++ b/src/libraries/System.Drawing.Common/ref/System.Drawing.Common.netcoreapp.cs @@ -26,6 +26,13 @@ public void FillPie(System.Drawing.Brush brush, System.Drawing.RectangleF rect, [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] public void GetContextInfo(out PointF offset, out Region? clip) { throw null; } } + public sealed partial class Font + { + public void ToLogFont(ref T logFont, Graphics graphics) where T: unmanaged { throw null; } + public static Font FromLogFont(in T logFont) where T: unmanaged { throw null; } + public static Font FromLogFont(in T logFont, IntPtr hdc) where T: unmanaged { throw null; } + public void ToLogFont(ref T logFont) where T: unmanaged { throw null; } + } } namespace System.Drawing.Drawing2D { diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Font.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Font.cs index a008f77a3c5c1a..ddd6a697ae5e8a 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Font.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Font.cs @@ -291,6 +291,29 @@ public unsafe void ToLogFont(object logFont, Graphics graphics) } } + /// + /// Update the given LOGFONT with data from given graphics. + /// + /// A structure to populate with LOGFONT data. + /// Graphics object which provide information about font. + public unsafe void ToLogFont(ref T logFont, Graphics graphics) + where T: unmanaged + { + ArgumentNullException.ThrowIfNull(logFont); + + if (sizeof(T) != sizeof(Interop.User32.LOGFONT)) + { + // If we don't actually have an object that is LOGFONT in size, trying to pass + // it to GDI+ is likely to cause an AV. + throw new ArgumentException(null, nameof(logFont)); + } + + fixed (T* pLogFont = &logFont) + { + *(Interop.User32.LOGFONT*)pLogFont = ToLogFontInternal(graphics); + } + } + private unsafe Interop.User32.LOGFONT ToLogFontInternal(Graphics graphics) { ArgumentNullException.ThrowIfNull(graphics); @@ -551,6 +574,20 @@ public static Font FromLogFont(object lf) } } + /// + /// Creates a from the given LOGFONT using the screen device context. + /// + /// A structure holding LOGFONT data. + /// The newly created . + public static Font FromLogFont(in T logFont) + where T: unmanaged + { + using (ScreenDC dc = ScreenDC.Create()) + { + return FromLogFont(in logFont, dc); + } + } + internal static Font FromLogFont(ref Interop.User32.LOGFONT logFont) { using (ScreenDC dc = ScreenDC.Create()) @@ -616,6 +653,30 @@ public static unsafe Font FromLogFont(object lf, IntPtr hdc) return FromLogFontInternal(ref logFont, hdc); } + /// + /// Creates a from the given LOGFONT using the given device context. + /// + /// A structure holding LOGFONT data. + /// Handle to a device context (HDC). + /// The newly created . + public static unsafe Font FromLogFont(in T logFont, IntPtr hdc) + where T: unmanaged + { + ArgumentNullException.ThrowIfNull(logFont); + + if (sizeof(T) != sizeof(Interop.User32.LOGFONT)) + { + // If we don't actually have an object that is LOGFONT in size, trying to pass + // it to GDI+ is likely to cause an AV. + throw new ArgumentException(null, nameof(logFont)); + } + + fixed (T* pLogFont = &logFont) + { + return FromLogFontInternal(ref *(Interop.User32.LOGFONT*)pLogFont, hdc); + } + } + /// /// Creates a from the specified handle to a device context (HDC). /// @@ -681,6 +742,20 @@ public void ToLogFont(object logFont) } } + /// + /// Update the given LOGFONT with data from the screen device context. + /// + /// A structure to populate with LOGFONT data. + public void ToLogFont(ref T logFont) + where T: unmanaged + { + using (ScreenDC dc = ScreenDC.Create()) + using (Graphics graphics = Graphics.FromHdcInternal(dc)) + { + ToLogFont(ref logFont, graphics); + } + } + /// /// Returns a handle to this . ///