I embedded a .ttf font file ("Amatic Bold", specifically) in my resources and I'm using this code below to get the Font. I tried the code fom this post: How do I Embed a font with my C# application? (using Visual Studio 2005)
This is my implementation:
static public Font GetCustomFont (byte[] fontData, float size, FontStyle style)
{
if (_fontCollection == null) _fontCollection = new PrivateFontCollection();
IntPtr fontPtr = System.Runtime.InteropServices.Marshal.AllocCoTaskMem(fontData.Length);
System.Runtime.InteropServices.Marshal.Copy(fontData, 0, fontPtr, fontData.Length);
_fontCollection.AddMemoryFont(fontPtr, fontData.Length);
System.Runtime.InteropServices.Marshal.FreeCoTaskMem(fontPtr);
return new Font(_fontCollection.Families[0], size, style);
}
Im using it like that:
Font font = GetCustomFont(Properties.MainResources.Amatic_Bold, 25, System.Drawing.FontStyle.Bold);
The font should look like:

The problem is the font is loading but not correctly showing when used; it looks like an "Arial" or other standard font instead of what it should be. If I install the font in Windows, it works (I suppose is obvious...)
I searched for an existing answer but could'nt find my exact problem...
Any help will be appreciated. Thanks in advance.
Well, then... I think I got it!
I'll explain what I've "discovered" (whether it can be obvious or not):
First: Application.SetCompatibleTextRenderingDefault must be set to true for Memory fonts to be rendered in the controls.
(Also Control.UseCompatibleTextRendering can be used)
It's perfectly specified in Microsoft documentation but I've missed that :-(
Second: PrivateFontCollection.Families return an array of added fonts, but.. Surprise! It's alphabetically ordered!
No matter what's the order you add the fonts or the method you use (AddMemoryFont/AddFontFile), you'll get it alphabetically ordered!
So if you're adding more than one font and then trying to get the last font you've added, you'll probably getting the wrong one.
Third: I've also tried doing FreeCoTaskMem() after adding the font in the collection or doing it on form closing. Both were working for me!
I don't know the exact implications of this...
This is my final code:
//This list is used to properly dispose PrivateFontCollection after usage
static private List<PrivateFontCollection> _fontCollections;
[STAThread]
private static void Main(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(true); //Mandatory in order to have Memory fonts rendered in the controls.
//Dispose all used PrivateFontCollections when exiting
Application.ApplicationExit += delegate {
if (_fontCollections != null) {
foreach (var fc in _fontCollections) if (fc != null) fc.Dispose();
_fontCollections = null;
}
};
Application.Run(new frmMain());
}
void frmMain_Load(object sender, EventArgs e)
{
Font font1 = GetCustomFont(Properties.Resources.Amatic_Bold, 25, FontStyle.Bold);
//or...
Font font1 = GetCustomFont("Amatic-Bold.ttf", 25, FontStyle.Bold);
labelTestFont1.Font = font1;
Font font2 = GetCustomFont(Properties.Resources.<font_resource>, 25, FontStyle.Bold);
//or...
Font font2 = GetCustomFont("<font_filename>", 25, FontStyle.Bold);
labelTestFont2.Font = font2;
//...
}
static public Font GetCustomFont (byte[] fontData, float size, FontStyle style)
{
if (_fontCollections == null) _fontCollections = new List<PrivateFontCollection>();
PrivateFontCollection fontCol = new PrivateFontCollection();
IntPtr fontPtr = Marshal.AllocCoTaskMem(fontData.Length);
Marshal.Copy(fontData, 0, fontPtr, fontData.Length);
fontCol.AddMemoryFont(fontPtr, fontData.Length);
Marshal.FreeCoTaskMem(fontPtr); //<-- It works!
_fontCollections.Add (fontCol);
return new Font(fontCol.Families[0], size, style);
}
static public Font GetCustomFont (string fontFile, float size, FontStyle style)
{
if (_fontCollections == null) _fontCollections = new List<PrivateFontCollection>();
PrivateFontCollection fontCol = new PrivateFontCollection();
fontCol.AddFontFile (fontFile);
_fontCollections.Add (fontCol);
return new Font(fontCol.Families[0], size, style);
}
As you can see, I've decided to create an exclusive PrivateFontCollection for each font, then store it to a List for a final disposal on application end.
This was tested in 3 different PC's (both with Windows 7, 32 and 64 bits) and 3 different .ttf fonts.
An example of the result:

I don't know if my approach is good enough, but I expect it could be useful for others!
One more detail: Unlike what I expected, AddMemoryFont is slower then AddFontFile (21ms vs. 15 ms)
Again, thanks to all comments!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With