24

我有一个包含字体文件 (.ttf) 内容的 MemoryStream,我希望能够从该流创建一个 FontFamily WPF 对象,而无需将流的内容写入磁盘。我知道使用 System.Drawing.FontFamily 可以做到这一点,但我不知道如何使用 System.Windows.Media.FontFamily 来做到这一点。

注意:我只有流,所以我不能将它打包为应用程序中的资源,并且由于磁盘权限问题,将无法将字体文件写入磁盘以作为“内容”参考

更新:

API 文档描述了如何使用应用程序资源,尽管我不清楚这是程序集中的嵌入式资源还是磁盘上的文件。

当您引用作为应用程序一部分打包的字体时,您可以使用基本 URI 值。例如,基本 URI 值可以是“pack://application”URI,它允许您引用打包为应用程序资源的字体。下面的代码示例显示由基本 URI 值和相对 URI 值组成的字体引用。

4

2 回答 2

2

这里有一个类似的问题,其中包含通过将 System.Drawing.FontFamily 转换为 WPF 字体系列的假设解决方案,所有这些都在内存中,没有任何文件 IO:

public static void Load(MemoryStream stream)
{
    byte[] streamData = new byte[stream.Length];
    stream.Read(streamData, 0, streamData.Length);
    IntPtr data = Marshal.AllocCoTaskMem(streamData.Length); // Very important.
    Marshal.Copy(streamData, 0, data, streamData.Length);
    PrivateFontCollection pfc = new PrivateFontCollection();
    pfc.AddMemoryFont(data, streamData.Length);
    MemoryFonts.Add(pfc); // Your own collection of fonts here.
    Marshal.FreeCoTaskMem(data); // Very important.
}

public static System.Windows.Media.FontFamily LoadFont(int fontId)
{
    if (!Exists(fontId))
    {
        return null;
    }
    /*
    NOTE:
    This is basically how you convert a System.Drawing.FontFamily to System.Windows.Media.FontFamily, using PrivateFontCollection.
    */
    return new System.Windows.Media.FontFamily(MemoryFonts[fontId].Families[0].Name);
}

这似乎使用System.Drawing.PrivateFontCollection( ^ ) 添加从 aSystem.Drawing.Font创建的 a MemoryStream,然后使用该Families[0].Name字体的 传递给System.Windows.Media.FontFamily构造函数。我假设姓氏将是 PrivateFontCollection 中该字体实例的 URI,但您可能必须尝试一下。

于 2021-01-11T06:41:22.243 回答
1

我能想到的最好方法是将 oldFont 保存到临时目录,然后使用接受 uri 的 newFont 构造函数立即加载它。

于 2011-09-07T15:12:08.217 回答