将资源中的字体加载到 PrivateFontCollection 会导致损坏重新发布
Loading a font from resources into PrivateFontCollection results in corruption repost
我在将字体从资源加载到 PrivateFontCollection 时遇到一些困难。
当我开始这个时,我成功地从一个文件中加载了字体,但是我希望将字体嵌入到我的项目中(这样用户端的文件混乱就会少一些,同时 IO 也会少一些)申请是 运行).
以下代码将加载字体、获取正确的名称并允许缩放,但是 none 的字符会正确显示。
static class Foo {
public static string FontAwesomeTTF { get; set; }
public static Font FontAwesome { get; set; }
public static float Size { get; set; }
public static FontStyle Style { get; set; }
private static PrivateFontCollection pfc { get; set; }
static Foo() {
// This was set when loading from a file.
// FontAwesomeTTF = "fontawesome-webfont.ttf";
Style = FontStyle.Regular;
Size = 20;
if ( pfc==null ) {
pfc=new PrivateFontCollection();
if ( FontAwesomeTTF==null ) {
var fontBytes=Properties.Resources.fontawesome_webfont;
var fontData=Marshal.AllocCoTaskMem( fontBytes.Length );
Marshal.Copy( fontBytes, 0, fontData, fontBytes.Length );
pfc.AddMemoryFont( fontData, fontBytes.Length );
Marshal.FreeCoTaskMem( fontData );
} else {
pfc.AddFontFile( FontAwesomeTTF );
}
}
FontAwesome = new Font(pfc.Families[0], Size, Style);
}
private static string UnicodeToChar( string hex ) {
int code=int.Parse( hex, System.Globalization.NumberStyles.HexNumber );
string unicodeString=char.ConvertFromUtf32( code );
return unicodeString;
}
public static string glass { get { return UnicodeToChar("f000"); } }
}
用法示例:
label1.Font = Foo.FontAwesome;
label1.Text = Foo.glass;
这是从内存加载的样子:
这是从文件加载的样子:
我在嵌入式资源和基于文件的测试中都使用了当前的 FontAwesome TTF 文件。似乎当嵌入的东西在翻译中或从嵌入加载时丢失或加扰。我需要帮助才能完成这项工作,以便我可以将字体从嵌入式资源加载到 PrivateFontCollection。
有一些 'solutions' 我在 SO 上看过,但是它们已经过时了,commands/accessors 中的一些或全部在 Visual Studio 2013 年不再可用(文章解决方案是4-5 年前)。一些示例 'solutions' 以及为什么它们不起作用:
Solution #1 - 这不能用作字体 returns null 的访问器字符串。在我的例子中,访问器是 MyProject.Properties.Resources.fontawesome_webfont
Solution #2 - 此解决方案最接近,但用于访问资源的方法同样不再有效。我上面的代码实现了一个收获版本,去掉了将 byte[] 数组传递到内存然后从内存加载的核心概念。由于在我的例子中资源的 get{} 属性 returns 已经是一个 byte[] 数组,所以没有必要 'convert' 它进入字节数组,因此我(看似)通过更新代码以使用较新的访问器,能够安全地删除该部分代码。
无论哪种情况,我都想要一个解决此问题的方法,允许我将字体文件从嵌入式资源加载到 PrivateFontCollection。
AddMemoryFont
's remarks section 说:
To use the memory font, text on a control must be rendered with GDI+. Use the SetCompatibleTextRenderingDefault
method, passing true
, to set GDI+ rendering on the application, or on individual controls by setting the control's UseCompatibleTextRendering
property to true
. Some controls cannot be rendered with GDI+.
我在本地重现了您的问题,并将您的使用示例更改为:
label1.Font = Foo.FontAwesome;
label1.Text = Foo.glass;
label1.UseCompatibleTextRendering = true;
这会为该标签打开 GDI+ 渲染,允许添加 AddMemoryFont
的字体正确渲染。
我在将字体从资源加载到 PrivateFontCollection 时遇到一些困难。
当我开始这个时,我成功地从一个文件中加载了字体,但是我希望将字体嵌入到我的项目中(这样用户端的文件混乱就会少一些,同时 IO 也会少一些)申请是 运行).
以下代码将加载字体、获取正确的名称并允许缩放,但是 none 的字符会正确显示。
static class Foo {
public static string FontAwesomeTTF { get; set; }
public static Font FontAwesome { get; set; }
public static float Size { get; set; }
public static FontStyle Style { get; set; }
private static PrivateFontCollection pfc { get; set; }
static Foo() {
// This was set when loading from a file.
// FontAwesomeTTF = "fontawesome-webfont.ttf";
Style = FontStyle.Regular;
Size = 20;
if ( pfc==null ) {
pfc=new PrivateFontCollection();
if ( FontAwesomeTTF==null ) {
var fontBytes=Properties.Resources.fontawesome_webfont;
var fontData=Marshal.AllocCoTaskMem( fontBytes.Length );
Marshal.Copy( fontBytes, 0, fontData, fontBytes.Length );
pfc.AddMemoryFont( fontData, fontBytes.Length );
Marshal.FreeCoTaskMem( fontData );
} else {
pfc.AddFontFile( FontAwesomeTTF );
}
}
FontAwesome = new Font(pfc.Families[0], Size, Style);
}
private static string UnicodeToChar( string hex ) {
int code=int.Parse( hex, System.Globalization.NumberStyles.HexNumber );
string unicodeString=char.ConvertFromUtf32( code );
return unicodeString;
}
public static string glass { get { return UnicodeToChar("f000"); } }
}
用法示例:
label1.Font = Foo.FontAwesome;
label1.Text = Foo.glass;
这是从内存加载的样子:
这是从文件加载的样子:
我在嵌入式资源和基于文件的测试中都使用了当前的 FontAwesome TTF 文件。似乎当嵌入的东西在翻译中或从嵌入加载时丢失或加扰。我需要帮助才能完成这项工作,以便我可以将字体从嵌入式资源加载到 PrivateFontCollection。
有一些 'solutions' 我在 SO 上看过,但是它们已经过时了,commands/accessors 中的一些或全部在 Visual Studio 2013 年不再可用(文章解决方案是4-5 年前)。一些示例 'solutions' 以及为什么它们不起作用:
Solution #1 - 这不能用作字体 returns null 的访问器字符串。在我的例子中,访问器是 MyProject.Properties.Resources.fontawesome_webfont
Solution #2 - 此解决方案最接近,但用于访问资源的方法同样不再有效。我上面的代码实现了一个收获版本,去掉了将 byte[] 数组传递到内存然后从内存加载的核心概念。由于在我的例子中资源的 get{} 属性 returns 已经是一个 byte[] 数组,所以没有必要 'convert' 它进入字节数组,因此我(看似)通过更新代码以使用较新的访问器,能够安全地删除该部分代码。
无论哪种情况,我都想要一个解决此问题的方法,允许我将字体文件从嵌入式资源加载到 PrivateFontCollection。
AddMemoryFont
's remarks section 说:
To use the memory font, text on a control must be rendered with GDI+. Use the
SetCompatibleTextRenderingDefault
method, passingtrue
, to set GDI+ rendering on the application, or on individual controls by setting the control'sUseCompatibleTextRendering
property totrue
. Some controls cannot be rendered with GDI+.
我在本地重现了您的问题,并将您的使用示例更改为:
label1.Font = Foo.FontAwesome;
label1.Text = Foo.glass;
label1.UseCompatibleTextRendering = true;
这会为该标签打开 GDI+ 渲染,允许添加 AddMemoryFont
的字体正确渲染。