Проблема создания PrivateFontCollection из ресурсов

Я использовал этот код в течение нескольких месяцев, и он работал как шарм. Недавно мне добавили этот код в систему контроля версий в TFS, и он больше не работает должным образом. Единственными изменениями были изменения некоторых пространств имен в соответствии с нашими рекомендациями по продукту. Цель состоит в том, чтобы создать 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));                    //******************************************************//

Что вдруг начало происходить, так это то, что все шрифты не загружаются в словарь. Насколько я могу сказать при отладке, ресурсы в порядке. Он проходит через все ресурсы шрифта правильно. Однако когда дело доходит до s_FontCollection.AddMemoryFont это начинает пропускать некоторые. Я пытался понять, как читать Status вернуть значение из метода ( как отмечено здесь), но не может заставить это работать. Я честно не изменил никакой другой код, связанный с этим.

Действительно странная часть - это проблема во время исполнения. Я могу запустить одну и ту же сборку несколько раз и получить разные результаты в отношении доступных шрифтов.

1 ответ

Решение

Оказывается, проблема заключалась в том, что файл ttf испортился при добавлении в систему контроля версий. Что касается обсуждения выше, освобождение памяти с помощью FreeCoTaskMem() работает нормально (как это всегда делалось ранее), потому что требуется только временно получить байты в памяти, чтобы можно было использовать AddFontFromMem() - что является самым простым способом внедрения данные в пфц. Удаление ошибочного шрифта полностью решило проблему.

Другие вопросы по тегам