C# 从TTF字体流创建GlyphTypeface对象

C# 从TTF字体流创建GlyphTypeface对象,c#,.net,wpf,C#,.net,Wpf,我知道如何通过给定绝对路径,使用磁盘上的字体文件创建GlyphTypeface对象 GlyphTypeface glyphTypeface = new GlyphTypeface(new Uri(@"C:\SomeTrueTypeFont.ttf", UriKind.Absolute)); 我不知道如何使用存储在内存流中的字体文件创建相同的字形字体对象。由于权限等问题,我的应用程序无法将字体流保存到磁盘。如果有人能建议我如何操作,我将不胜感激。我认为这是不可能的。WPF undercove

我知道如何通过给定绝对路径,使用磁盘上的字体文件创建GlyphTypeface对象

  GlyphTypeface glyphTypeface = new GlyphTypeface(new Uri(@"C:\SomeTrueTypeFont.ttf", UriKind.Absolute));

我不知道如何使用存储在内存流中的字体文件创建相同的字形字体对象。由于权限等问题,我的应用程序无法将字体流保存到磁盘。如果有人能建议我如何操作,我将不胜感激。

我认为这是不可能的。WPF undercover使用依赖于物理文件的本机接口。

可以从(的副本)创建

它是以类似的方式完成的

必须将字体流复制到添加到的内存中的。关键的部分是获得传递给的正确信息

以下是内存包的一种可能实现:

sealed class MemoryPackage : IDisposable
{
    private static int packageCounter;

    private readonly Uri packageUri = new Uri("payload://memorypackage" + Interlocked.Increment(ref packageCounter), UriKind.Absolute);
    private readonly Package package = Package.Open(new MemoryStream(), FileMode.Create);
    private int partCounter;

    public MemoryPackage()
    {
        PackageStore.AddPackage(this.packageUri, this.package);
    }

    public Uri CreatePart(Stream stream)
    {
        return this.CreatePart(stream, "application/octet-stream");
    }

    public Uri CreatePart(Stream stream, string contentType)
    {
        var partUri = new Uri("/stream" + (++this.partCounter), UriKind.Relative);

        var part = this.package.CreatePart(partUri, contentType);

        using (var partStream = part.GetStream())
            CopyStream(stream, partStream);

        // Each packUri must be globally unique because WPF might perform some caching based on it.
        return PackUriHelper.Create(this.packageUri, partUri);
    }

    public void DeletePart(Uri packUri)
    {
        this.package.DeletePart(PackUriHelper.GetPartUri(packUri));
    }

    public void Dispose()
    {
        PackageStore.RemovePackage(this.packageUri);
        this.package.Close();
    }

    private static void CopyStream(Stream source, Stream destination)
    {
        const int bufferSize = 4096;

        byte[] buffer = new byte[bufferSize];
        int read;
        while ((read = source.Read(buffer, 0, buffer.Length)) != 0)
            destination.Write(buffer, 0, read);
    }
}
下面是一个示例代码,说明如何使用它从(a的副本)创建:


这是可行的,它实际上修复了我在Glyph字体中看到的两个bug。首先,它修复了GlyphTypeface锁定文件并保持文件句柄打开的事实,从而防止文件被删除。其次,它阻止构造函数抛出null引用异常(),否则在访问文件时会抛出null引用异常(可能与文件路径有关)。这个解决方案令人惊讶,因为它完全不使用文件来回避文件问题。
GlyphTypeface glyphTypeface;

using (var memoryPackage = new MemoryPackage())
{
    using (var fontStream = new MemoryStream(File.ReadAllBytes(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "font"))))
    {
        var typefaceSource = memoryPackage.CreatePart(fontStream);

        glyphTypeface = new GlyphTypeface(typefaceSource);

        memoryPackage.DeletePart(typefaceSource);
    }
}

var familyName = glyphTypeface.FamilyNames[CultureInfo.GetCultureInfo("en-US")];

Console.WriteLine(familyName);