简体   繁体   English

从资源创建PrivateFontCollection的问题

[英]Issue Creating PrivateFontCollection from Resources

I've been running this same code for months and it's worked like a charm. 我已经运行了相同的代码几个月,它的工作就像一个魅力。 Recently, I've had this code added to source control in TFS and it's no longer working properly. 最近,我已经将此代码添加到TFS的源代码管理中,并且不再正常工作。 The only changes were to modify some namespaces to meet our product guidelines. 唯一的更改是修改了一些名称空间,以满足我们的产品准则。 The purpose is to create a pfc out of fonts that are embedded as resources in the file - the reason being that the executable is to be portable and not rely on anything aside from appropriate an .NET version being installed. 目的是从作为资源嵌入文件中的字体创建pfc ,原因是可执行文件具有可移植性,除了安装适当的.NET版本外,不依赖任何内容。

    public static Dictionary<string, object> FontDict = new Dictionary<string, object>();

    public static PrivateFontCollection s_FontCollection = new PrivateFontCollection();
    public static Font staticFont;

    public static FontFamily[] FontFamilies
    {
        get
        {
            if (s_FontCollection.Families.Length == 0)
                LoadFonts();

            return s_FontCollection.Families;
        }
    }

    public static Font GetFont(string family, float size)
    {
        foreach (FontFamily font in FontFamilies)
        {
            if (font.Name.ToLower().Equals(family.ToLower()))
            {
                Font ret = new Font(font, size);
                //return (Font)ret.Clone();
                return ret;
            }
        }

        return null;
    }

    public static void LoadFonts()
    {
        if (Assembly.GetEntryAssembly() == null || Assembly.GetEntryAssembly().GetManifestResourceNames() == null)
            return;

        foreach (string resource in Assembly.GetEntryAssembly().GetManifestResourceNames())
        {
            // Load TTF files from your Fonts resource folder.
            if (resource.Contains(".Fonts.") && resource.ToLower().EndsWith(".ttf"))
            {
                using (Stream stream = Assembly.GetEntryAssembly().GetManifestResourceStream(resource))
                {
                    try
                    {
                        // create an unsafe memory block for the font data
                        System.IntPtr data = Marshal.AllocCoTaskMem((int)stream.Length);

                        // create a buffer to read in to
                        byte[] fontdata = new byte[stream.Length];

                        // read the font data from the resource
                        stream.Read(fontdata, 0, (int)stream.Length);

                        // copy the bytes to the unsafe memory block
                        Marshal.Copy(fontdata, 0, data, (int)stream.Length);

                        // pass the font to the font collection
                        s_FontCollection.AddMemoryFont(data, (int)stream.Length);

                        // close the resource stream
                        stream.Close();

                        // free up the unsafe memory
                        Marshal.FreeCoTaskMem(data);
                    }
                    catch
                    {

                    }
                }
            }
        }

        FontDict.Clear();
        FontDict.Add("SYS",    new Font("Arial", 20));
        FontDict.Add("SYSs",   new Font("Arial", 14));
        FontDict.Add("MICR",   GetFont("MICR", 18));                    // Preferred MICR font
        FontDict.Add("SIG",    GetFont("PWSignaturetwo", 30));
        FontDict.Add("HAND1l", GetFont("Daniel", 22));
        FontDict.Add("HAND2l", GetFont("Jenna Sue", 32));
        FontDict.Add("HAND3l", GetFont("Honey Script", 30));
        FontDict.Add("HAND4l", GetFont("Confessions", 42));
        FontDict.Add("HAND5l", GetFont("Soljik-Dambaek", 26));
        FontDict.Add("HAND6l", GetFont("Billy's Hand Thin", 38));
        FontDict.Add("HAND7l", GetFont("Daisy Script", 34));
        FontDict.Add("HAND8l", GetFont("Fineliner SCript", 34));
        FontDict.Add("HAND9l", GetFont("Graphe", 20));
        FontDict.Add("HAND1s", GetFont("Daniel", 16));
        FontDict.Add("HAND2s", GetFont("Jenna Sue", 26));
        FontDict.Add("HAND3s", GetFont("Honey Script", 24));
        FontDict.Add("HAND4s", GetFont("Confessions", 30));
        FontDict.Add("HAND5s", GetFont("Soljik-Dambaek", 20));
        FontDict.Add("HAND6s", GetFont("Billy's Hand Thin", 26));
        FontDict.Add("HAND7s", GetFont("Daisy Script", 26));
        FontDict.Add("HAND8s", GetFont("Fineliner Script", 26));
        FontDict.Add("HAND9s", GetFont("Graphe", 14));
        FontDict.Add("HACKs",  GetFont("Hack", 10));                    //******************************************************//
        FontDict.Add("HACKm",  GetFont("Hack", 12));                    //    Preferred fixed-width font for non-check data     //
        FontDict.Add("HACKl",  GetFont("Hack", 16));                    //******************************************************//

What suddenly has started happening is that all fonts don't get loaded to the dictionary. 突然开始发生的事情是所有字体都没有加载到字典中。 As far as I can tell while debugging, the resources are fine. 据我在调试时所知道的,资源很好。 It loops through all of the font resources correctly. 它将正确循环所有字体资源。 However, when it gets to s_FontCollection.AddMemoryFont it starts skipping some. 但是,当到达s_FontCollection.AddMemoryFont它将开始跳过一些内容。 I was trying to figure out how to read the Status return value from the method ( as noted here ) but can't seem to make that work. 我试图弄清楚如何从方法中读取Status返回值( 如此处所述 ),但似乎无法实现。 I've honestly changed no other code related to this. 老实说,我没有更改与此相关的其他代码。

The really odd part is it's an issue at the time of execution. 真正奇怪的是,这是执行时的问题。 I can run the same build multiple times and end up with different results regarding what fonts are available. 我可以多次运行相同的版本,最后在可用字体方面得到不同的结果。

Turns out the issue was a ttf file that went corrupt when it was added to source control. 原来问题是ttf文件在添加到源代码管理后损坏了。 As to the discussion above, deallocating the memory via FreeCoTaskMem() works fine (as it always did previously) because it's only needed temporarily to get the bytes to memory so that AddFontFromMem() can be utilized - which is the easiest way to get embedded data into the pfc. 对于上面的讨论,通过FreeCoTaskMem()释放内存工作正常(就像以前一样),因为只需要临时将字节获取到内存中,以便可以利用AddFontFromMem()-这是最简单的嵌入式方法数据存入pfc。 Removing the errant font resolved the issue entirely. 删除错误的字体可以完全解决此问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM