如何正确处理PrivateFontCollection?

时间:2016-01-05 20:35:15

标签: c# interop unmanaged unmanaged-memory

我正在使用PrivateFontCollection在我的网络服务器上安装上传的字体。下面的代码有效,但在第二次上传字体时,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);
            }
        }
    }

2 个答案:

答案 0 :(得分:2)

PrivateFontCollection是一个非常有缺陷的类,你必须非常小心地使用它。您现有代码中的一个非常严重的错误是Marshal.FreeCoTaskMem()调用。您需要确保调用此函数,直到 代码停止使用您从该系列创建的任何字体对象为止。如果不这样做会导致随机字形损坏,如果运气好,您只会获得AccessViolationException。基本问题是字体将继续使用您使用AllocCoTaskMem()分配的内存,它完全不知道内存不再有效。重新使用内存时会发生损坏。

此外,虽然该类具有AddMemoryFont()方法,但它没有相应的RemoveMemoryFont()方法。清理的唯一方法是调用PrivateFontCollection.Dispose()。这将删除集合中所有字体。使用与上一段相同的规定,只有在确定不再使用任何Font对象时,才能调用Dispose()。过早调用会导致异常。

非常尴尬的行为,只有真正安全的使用PFC的方法是在应用程序的生命周期中保持它。当然,在网络应用程序中非常痛苦。

您可以假设添加的字体是FontFamily []数组中的 last 。不是第一个,因为你已经实现了它。

答案 1 :(得分:1)

根据AddFontMemResourceEx function

  

要删除已安装的字体,请调用RemoveFontMemResourceEx。   但是,当进程消失时,系统将卸载字体   即使进程没有调用RemoveFontMemResource。

但是,我不认为你这样做。这可能是原因。

相关问题