我正在使用PrivateFontCollection在我的Web服务器上安装上载的字体。下面的代码有效,但是在第二次上载字体时,PrivateFontCollection引用了第一个上载字体。因此,某些事情没有得到正确处理。有人发现我在做什么错吗?
var fontName = string.Empty;
using (var ms = new MemoryStream(fontBytes))
{
// used to store our font and make it available in our app
using (var pfc = new PrivateFontCollection())
{
//create memory pointer
IntPtr data = Marshal.AllocCoTaskMem((int)ms.Length);
try
{
//copy the bytes to the unsafe memory block
Marshal.Copy(fontBytes, 0, data, (int)ms.Length);
// We HAVE to do this to register the font to the system (Weird .NET bug !)
uint cFonts = 0;
AddFontMemResourceEx(data, (uint)fontBytes.Length, IntPtr.Zero, ref cFonts);
//pass the font to the font collection
pfc.AddMemoryFont(data, (int)ms.Length);
var fontWithMime = "data:application/x-font-truetype;charset=utf-8;base64," + cleanFontData;
fontName = pfc.Families[0].Name;
//db work here
}
finally
{
ms.Close();
Marshal.FreeCoTaskMem(data);
}
}
}
最佳答案
PrivateFontCollection是一个非常有缺陷的类,您必须非常小心地使用它。现有代码中一个非常严重的错误是Marshal.FreeCoTaskMem()调用。您必须确保在代码停止使用从族中创建的任何Font对象之后,才调用此函数。否则,将导致随机字形损坏,只有在您幸运的情况下,您才会获得AccessViolationException。潜在的问题是字体将继续使用通过AllocCoTaskMem()分配的内存,这完全不知道该内存不再有效。重新使用内存时会发生损坏。
此外,尽管该类具有AddMemoryFont()方法,但没有相应的RemoveMemoryFont()方法。清除的唯一方法是调用PrivateFontCollection.Dispose()。这将删除集合中的所有字体。按照与上一段相同的规定,只有在确定不再使用任何Font对象时,才可以调用Dispose()。太早调用它不会导致异常。
非常尴尬的行为,使用PFC的唯一真正安全的方法是在应用程序的生命周期内一直使用它。当然,在Web应用程序中非常痛苦。
您可以假定添加的字体是FontFamily []数组中的最后一个字体。现在实现的不是第一个。