从资源创建 PrivateFontCollection 的问题
Issue Creating PrivateFontCollection from Resources
几个月来我一直在使用相同的代码 运行,它的效果非常好。最近,我将这段代码添加到 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
时,它开始跳过一些。我试图弄清楚如何从方法 (as noted here) 中读取 Status
return 值,但似乎无法实现。老实说,我没有更改与此相关的其他代码。
真正奇怪的是它是执行时的一个问题。我可以 运行 多次相同的构建并最终得到关于可用字体的不同结果。
原来问题是一个 ttf 文件在添加到源代码管理时损坏了。至于上面的讨论,通过 FreeCoTaskMem() 释放内存工作正常(就像以前一样),因为它只需要暂时将字节获取到内存,以便可以使用 AddFontFromMem() - 这是最简单的嵌入方式数据进入 pfc。删除错误字体完全解决了这个问题。
几个月来我一直在使用相同的代码 运行,它的效果非常好。最近,我将这段代码添加到 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
时,它开始跳过一些。我试图弄清楚如何从方法 (as noted here) 中读取 Status
return 值,但似乎无法实现。老实说,我没有更改与此相关的其他代码。
真正奇怪的是它是执行时的一个问题。我可以 运行 多次相同的构建并最终得到关于可用字体的不同结果。
原来问题是一个 ttf 文件在添加到源代码管理时损坏了。至于上面的讨论,通过 FreeCoTaskMem() 释放内存工作正常(就像以前一样),因为它只需要暂时将字节获取到内存,以便可以使用 AddFontFromMem() - 这是最简单的嵌入方式数据进入 pfc。删除错误字体完全解决了这个问题。