The System.Drawing.Font.ToLogFont method seems to work well in a Windows environment. Using it in a Linux environment produces runtime errors. I've prepared a sample console application which illustrates the issue.
Unhandled exception. System.ArgumentException: Value does not fall within the expected range. (Parameter 'logFont')
at System.Drawing.Font.ToLogFont(Object logFont, Graphics graphics)
at System.Drawing.Font.ToLogFont(Object logFont)
at TestFonts.Program.Main(String[] args) in /home/hwfbcisod/Desktop/TestFontsNew/Program.cs:line 27
```C#
using System;
using System.Drawing;
using System.Runtime.InteropServices;
namespace TestFonts
{
class Program
{
static void Main()
{
var font = new Font(new FontFamily("Arial"), 20, FontStyle.Bold);
var logFont = new LOGFONT();
font.ToLogFont(logFont);
Console.WriteLine(logFont.lfHeight);
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
private class LOGFONT
{
public int lfHeight;
public int lfWidth;
public int lfEscapement;
public int lfOrientation;
public int lfWeight;
public byte lfItalic;
public byte lfUnderline;
public byte lfStrikeOut;
public byte lfCharSet;
public byte lfOutPrecision;
public byte lfClipPrecision;
public byte lfQuality;
public byte lfPitchAndFamily;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string lfFaceName;
}
}
}
### NuGet Packages
[System.Drawing.Common](https://www.nuget.org/packages/System.Drawing.Common/)
## Configuration
### .NET Info
.NET SDK (reflecting any global.json):V
Version: 5.0.100
Commit: 5044b93829
Runtime Environment:
OS Name: ubuntu
OS Version: 18.04
OS Platform: Linux
RID: ubuntu.18.04-x64
Base Path: /usr/share/dotnet/sdk/5.0.100/
Host (useful for support):
Version: 5.0.0
Commit: cf258a14b7
.NET SDKs installed:
5.0.100 [/usr/share/dotnet/sdk]
.NET runtimes installed:
Microsoft.AspNetCore.App 5.0.0 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.NETCore.App 5.0.0 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
### OS Info
Distributor ID: Ubuntu
Description: Ubuntu 18.04.3 LTS
Release: 18.04
Codename: bionic
```
Note: The Ubuntu distribution is running in a VM. Reproduced on both a local Hyper-V instance and on an Azure VM.
The above problems occur both in .NET Core 3.1 and .NET Core 5. I haven't tested with other versions.
Tagging subscribers to this area: @safern, @tannergooding, @jeffhandley The System.Drawing.Font.ToLogFont method seems to work well in a Windows environment. Using it in a Linux environment produces runtime errors. I've prepared a sample console application which illustrates the issue. ```C# namespace TestFonts } .NET SDK (reflecting any global.json):V Runtime Environment: Host (useful for support): .NET SDKs installed: .NET runtimes installed: Distributor ID: Ubuntu Note: The Ubuntu distribution is running in a VM. Reproduced on both a local Hyper-V instance and on an Azure VM. The above problems occur both in .NET Core 3.1 and .NET Core 5. I have't tested with other versions.
See info in area-owners.md if you want to be subscribed.
Issue Details
Description:
Description
Exceptions
Unhandled exception. System.ArgumentException: Value does not fall within the expected range. (Parameter 'logFont')
at System.Drawing.Font.ToLogFont(Object logFont, Graphics graphics)
at System.Drawing.Font.ToLogFont(Object logFont)
at TestFonts.Program.Main(String[] args) in /home/hwfbcisod/Desktop/TestFontsNew/Program.cs:line 27
Source Code
using System;
using System.Drawing;
using System.Runtime.InteropServices;
{
class Program
{
static void Main()
{
var font = new Font(new FontFamily("Arial"), 20, FontStyle.Bold);
var logFont = new LOGFONT();
font.ToLogFont(logFont);
Console.WriteLine(logFont.lfHeight);
} [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
private class LOGFONT
{
public int lfHeight;
public int lfWidth;
public int lfEscapement;
public int lfOrientation;
public int lfWeight;
public byte lfItalic;
public byte lfUnderline;
public byte lfStrikeOut;
public byte lfCharSet;
public byte lfOutPrecision;
public byte lfClipPrecision;
public byte lfQuality;
public byte lfPitchAndFamily;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string lfFaceName;
}
}
### NuGet Packages
[System.Drawing.Common](https://www.nuget.org/packages/System.Drawing.Common/)
## Configuration
### .NET Info
Version: 5.0.100
Commit: 5044b93829
OS Name: ubuntu
OS Version: 18.04
OS Platform: Linux
RID: ubuntu.18.04-x64
Base Path: /usr/share/dotnet/sdk/5.0.100/
Version: 5.0.0
Commit: cf258a14b7
5.0.100 [/usr/share/dotnet/sdk]
Microsoft.AspNetCore.App 5.0.0 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.NETCore.App 5.0.0 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
```OS Info
Description: Ubuntu 18.04.3 LTS
Release: 18.04
Codename: bionicRegression?
Author:
hwfbcisod
Assignees:
-
Labels:
area-System.Drawing, untriaged
Milestone:
-
The size check is failing because size of LOGFONT type is different than the one defined by runtime: https://github.com/dotnet/runtime/blob/6cb16e12fd912c28f2ab4577414b4a2d8b321a28/src/libraries/Common/src/Interop/Windows/User32/Interop.LOGFONT.cs#L12
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
- private class LOGFONT
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ private unsafe struct LOGFONT
{
public int lfHeight;
public int lfWidth;
public int lfEscapement;
public int lfOrientation;
public int lfWeight;
public byte lfItalic;
public byte lfUnderline;
public byte lfStrikeOut;
public byte lfCharSet;
public byte lfOutPrecision;
public byte lfClipPrecision;
public byte lfQuality;
public byte lfPitchAndFamily;
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
- public string lfFaceName;
+ private fixed char _lfFaceName[32];
+ public string lfFaceName
+ {
+ get { fixed (char* c = _lfFaceName) { return new string(c); } }
+ }
+ }
build as dotnet build -p:AllowUnsafeBlocks=True and finally dotnet run.
Thanks, @am11 that seems accurate.
@hwfbcisod please confirm if that fixes your issue 馃槃
Thank you, @am11.
@safern Yes, that seems to work. At least it does on my Hyper-V VM.
Great. Thanks for confirming @hwfbcisod. Please let us know if we can help further. I'm closing the issue based on the conversation above.
@am11 Do you have an idea why example described in issue works on Windows and fails in Linux ?
If you search over internet one of the first sites describing LOGFONT is pinvoke.net and it gives you wrong signature.
Maybe we need a better documentation for this .
@TrayanZapryanov, the official docs of ToLogFont https://docs.microsoft.com/en-us/dotnet/api/system.drawing.font.tologfont?view=dotnet-plat-ext-5.0 points to this definition of win32 struct https://docs.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-logfonta.
In the pinvoke.net documentation you mentioned, we only need to change CharSet.Auto to CharSet.Unicode, because CharSet.Auto on Unix-y system is UTF8 in .NET and Unicode on Windows: https://docs.microsoft.com/en-us/dotnet/standard/native-interop/charset. (always better to explicitly specify the encoding, rather than relying on default behavior in such cases).
Most helpful comment
The size check is failing because size of
LOGFONTtype is different than the one defined by runtime: https://github.com/dotnet/runtime/blob/6cb16e12fd912c28f2ab4577414b4a2d8b321a28/src/libraries/Common/src/Interop/Windows/User32/Interop.LOGFONT.cs#L12build as
dotnet build -p:AllowUnsafeBlocks=Trueand finallydotnet run.