1

我在将字体从资源加载到 PrivateFontCollection 时遇到了一些困难。

当我开始这个时,我成功地从文件中加载了字体,但是我希望将字体嵌入到我的项目中(因此用户端的文件混乱更少,应用程序运行时的 IO 也更少)。

下面的代码将加载字体,获取正确的名称,并允许缩放,但是没有一个字符正确显示。

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 中。

我在 SO 上查看了一些“解决方案”,但是它们已经过时了,并且 Visual Studio 2013 中不再提供部分或全部命令/访问器(文章解决方案来自 4-5 年前)。一些示例“解决方案”以及为什么它们不起作用:

解决方案 #1 - 这不起作用,因为字体的访问器字符串返回 null。就我而言,访问器是MyProject.Properties.Resources.fontawesome_webfont

解决方案 #2 - 此解决方案最接近,但再次用于访问资源的方法不再有效。我上面的代码实现了一个收获版本,去掉了将 byte[] 数组传递到内存然后从内存加载的核心概念。由于在我的情况下,资源的 get{} 属性已经返回了一个 byte[] 数组,因此无需将其“转换”为字节数组,因此我(似乎)能够安全地删除该部分代码更新它以使用较新的访问器。

无论哪种情况,我都想要一个解决这个问题的方法,它允许我将嵌入资源中的字体文件加载到 PrivateFontCollection 中。

4

1 回答 1

3

AddMemoryFont的评论部分说:

要使用内存字体,控件上的文本必须使用 GDI+ 呈现。使用SetCompatibleTextRenderingDefault方法,传递true, 来设置应用程序上的 GDI+ 呈现,或者通过将控件的UseCompatibleTextRendering属性设置为单个控件来设置 GDI+ 呈现true。某些控件无法使用 GDI+ 呈现。

我在本地重现了您的问题,并通过将您的使用示例更改为:

label1.Font = Foo.FontAwesome;
label1.Text = Foo.glass;
label1.UseCompatibleTextRendering = true;

这将打开该标签的 GDI+ 渲染,允许添加的字体AddMemoryFont正确渲染。

于 2015-10-13T00:17:32.177 回答