代码之家  ›  专栏  ›  技术社区  ›  AndrewS

将字体保存到磁盘,然后实例化字体的glyphtypeface引发异常。为什么?

  •  5
  • AndrewS  · 技术社区  · 14 年前

    我正在处理WPF标志符号和文档,并在.NET 4框架中遇到了一个空引用异常。

    我提取真正的字体并将其保存到磁盘上作为.ttf文件,然后尝试基于字体创建字形。我第一次将字体保存到磁盘上并根据字体实例化glyphtypeface时 之后 从同一个文件夹中的另一个字体创建glyphtypeface时,我得到一个空引用异常。

    假设我有字体A和B。B尚未保存到磁盘(A可能已保存到磁盘,也可能未保存到磁盘;这似乎无关紧要):

    1)将b保存到与a相同的文件夹中的磁盘,
    2)使用字体A创建字形字体,
    3)使用字体B=异常创建glyphtypeface。

    Null reference exception at:  
    at MS.Internal.FontCache.FontFaceLayoutInfo.IntMap.TryGetValue(Int32 key, UInt16& value)  
    at MS.Internal.FontCache.FontFaceLayoutInfo..ctor(Font font)  
    at System.Windows.Media.GlyphTypeface.Initialize(Uri typefaceSource, StyleSimulations styleSimulations)  
    at System.Windows.Media.GlyphTypeface..ctor(Uri typefaceSource)
    

    如果我重新启动应用程序并再次运行它(字体B已经在磁盘上),步骤3不会引发异常。

    将字体保存到磁盘的代码只是从二进制流中写入一个节,然后释放文件:

    if (!File.Exists(filename))
    {
        using (FileStream fs = File.Create(filename, length))
        {
            fs.Write(m_data, m_index, length);
            fs.Close();
        }
    }
    

    有什么想法吗?我不想把每种字体都放在自己的文件夹里…

    谢谢你抽出时间。

    5 回复  |  直到 12 年前
        1
  •  2
  •   AndrewS    14 年前

    我最终使用了将每个字体保存到自己的文件夹(使用文件夹名称的字体名称)的解决方法。例外情况消失了,所以我想我们可以把它归结为.NET中的一个bug。

        2
  •  2
  •   Martin Liversage    12 年前

    这个臭虫一直让我发疯,但我想我对现在的情况有了更好的了解。

    为了测试,我使用了以下XAML:

    <Page
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
      <Glyphs
        FontUri="C:\Users\Public\Desktop\A.ttf"
        FontRenderingEmSize="100"
        Fill="Black"
        UnicodeString="Test"/>
    </Page>
    

    使用 XamlPadX 在.NET 2运行时上运行的应用程序,无论字体放在哪里,我都能可靠地呈现XAML。

    使用 Kaxaml 在.NET 4运行时上运行的应用程序,根据我在文件系统中放置字体的位置,XAML通常无法呈现。通过移动字体文件并重命名,我试图发现允许的模式。然而,很难看到一种模式。

    例如,在下面的路径中存储字体将呈现字形:

    C:\Users\Public\Desktop\A.ttf - OK
    

    将其重命名为 A.ttf B.ttf 将引发异常:

    C:\Users\Public\Desktop\B.ttf - throws exception
    

    更改扩展名也会引发异常:

    C:\Users\Public\Desktop\A.odttf - throws exception
    

    重命名部分路径有时会造成严重破坏,但我看不到任何模式。最初,我使用了临时路径,获得异常会导致这个问题和关于不使用该路径的答案。但是,稍后,只要文件名是 A.TTF 而不是 B.TTF 因此,避免临时路径并不是一个确定的解决方案。

    在我使用自己的WPF应用程序进行测试的过程中, B.TTF 文件名突然开始工作。但是,我必须重新启动Kaxaml应用程序,然后它才会接受 B.TTF 文件名。同时,在这一点上 A.odttf 文件名仍在引发异常。

    我的建议是使用类似kaxaml的应用程序,或者创建一个小的wpf应用程序来测试哪些字体文件名是可接受的,然后使用它们。但是,我担心这个bug的本质是这样的,“好”字体文件名可能在以后的某个时间点变为“坏”。只有时间才会显现。

        3
  •  1
  •   Cheetah    12 年前

    我(和一个同事)终于发现了我们的特殊问题:不要将字体文件保存到 %TEMP% . 出于某种原因,将字体保存到其他文件夹可以使其工作(对我们而言),并将其保存到其中的任何位置 %温度% 使它破裂。

        4
  •  1
  •   bluish dmajkic    12 年前

    根据 XamlToys Doesn't work on framework 4.0??? ,问题出在部分字体的文件扩展名中。

    当我重命名保存到.ttf的.oftf文件时,一切都会重新工作。但还不知道为什么会这样。在.NET 4.0中似乎是新的。

        5
  •  0
  •   whybird    14 年前

    我的解决方法是简单地将<glyphs>替换为equavalent<textblock>s。在我的例子中,两个像素的布局差异不是问题。

    正如您所指出的那样,在我的例子中,.NET 3.5中也不是问题,而是出现在.NET 4.0中。