WPF字体:为什么会缺失某些字符?

5
我正在编写一个WPF应用程序,我使用的字体仅在WPF中存在问题 - 在其他任何地方使用它都很好(记事本,写字板等)。 WPF的问题是有时会回退到另一种字体。 通过“有时”我的意思是只有[a-zA-Z]字符似乎正确呈现 - 其他所有内容似乎都呈现为默认的TextBox字体。

是否有人知道WPF对其支持的字体是否有某种限制? 它几乎看起来像是WPF中的错误 - 这种字体在其他地方都很好用。

我尝试使用的字体是“Scramble” TTF字体(http://famousfonts.smackbomb.com/fonts/scrabble.php)。

数字和空格应该被视为空白的Scrabble / Scramble瓷砖,但实际上数字本身出现在我正在使用的文本框中。

我正在使用的代码:

<TextBox Text="Testing testing testing" FontFamily="Fonts/#Scramble" />

有没有其他人也经历过类似的情况?

有什么建议可以分享吗?

谢谢!

5个回答

8

来自MSDN

字体回退

字体回退是指自动替换客户端应用程序选择的字体以外的字体。引起字体回退的两个主要原因如下:

  • 客户端应用程序指定的字体在系统上不存在。
  • 客户端应用程序指定的字体不包含呈现文本所需的字形。

在WPF中,字体回退机制使用默认回退字体系列“全局用户界面”作为替代字体。该字体被定义为复合字体,其文件名为“GlobalUserInterface.CompositeFont”。有关复合字体的更多信息,请参见本主题中的复合字体部分。

WPF字体回退机制取代了以前的Win32字体替换技术。

我猜测这个字体不支持Unicode - 该字体本身是在1996年创建的,并且由于它旨在模拟Scrabble块,我不确定字体作者是否考虑过本地化。

编辑 根据字体文档,该字体支持字母,任何数字都应该呈现为空白块。空格不呈现块。


3
噢,得了吧。肯定有人能给出比这更好的答案……如果我因为从MSDN复制粘贴并且没有完全回答问题就获得奖励,我会感到难为情的…:\ - GalacticCowboy

3
简单来说,在WPF或其他地方,Scramble不使用空白的拼字块作为em空格。您需要另一个字体或其他东西来编辑em / en空格字形(例如Font Creator)。
我使用了另一个字体(x-grid),我知道它有用于空格的特殊字形,并在下面的代码中使用了它们。
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="500">
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition/>
    </Grid.RowDefinitions>
    <TextBlock Grid.Row="0" FontFamily="Scramble" TextAlignment="Center" HorizontalAlignment="Center" FontSize="24" Text="Example Text M M M"/>
    <TextBlock Grid.Row="1" FontFamily="x-grid"  TextAlignment="Center" HorizontalAlignment="Center" FontSize="24" Text="Example Text M M M"/>
</Grid>

生成的窗口看起来像这样。

alt text

抱歉,这与字体回退无关。很抱歉,但我希望这能帮到您。
**更新:**抱歉,刚刚注意到您也提到了数字。在Paint.Net中进行的快速测试显示数字也不会出现在瓷砖中。

我在Word中尝试了一下,最初数字没有显示出来,但如果我返回并特别设置字体格式,则它们会显示出来。但是,这些数字有点古怪。它们在字体预览中也不显示。 - GalacticCowboy
嗯,你设置了什么格式?无论如何,如果它表现得如此不稳定,我会尝试获取更好的字体。 - EightyOne Unite
在我输入数字后,我选择了它们,然后将字体切换到另一个面,再切回Scramble,它们就出现了。 - GalacticCowboy
2
多么奇怪。我刚刚做了同样的事情,只要你输入一个数字,它就会切换回Arial字体。这表明该字体缺少这些字形,使用默认字形代替它们。也许MS Word会在你明确将其格式设置回所选类型时,用所选类型的默认字符替换那些字形。当然,WPF不会这样做。有解决方法,但老实说,如果可以的话,我会修改字体或找到替代品而不是绕过问题。 - EightyOne Unite

2
总的来说,印刷排版和字体是一个相当复杂的话题,我并不是很了解。尽管如此,根据 Windows Presentation Foundation中的印刷排版 和相关的MSDN文档,我已经得出以下结论:
  • 文字是通过文本渲染流程来呈现的(请参见上面的图表)。
  • WPF将OpenType作为TrueType字体格式的扩展来实现。
    • Typography 对象公开了许多OpenType字体的高级特性。
  • 一个重要的低级别文本渲染概念是Glyphs元素,请参见MSDNintroduction
如果您查看所提到的文本渲染管道图,您会注意到,虽然字形是构建块,但它们在最终显示在特定媒介(如屏幕或打印机)之前可能会以各种方式进行处理(过滤/转换/...),例如对LCD屏幕应用ClearType。然而,通常情况下,像管道概念一样,这些变换通常是可选的。

现在,根据您的应用要求,这可能已经得出了一个解决方案。如果您不真正需要TextBox,您也可以只使用Glyphs本身,如下所示:

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:sys="clr-namespace:System;assembly=mscorlib" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
  <Grid>
    <TextBox Text="TextBox: 1234567890" FontFamily="Scramble" FontSize="12" />
    <Glyphs UnicodeString="Glyphs: 1234567890" FontUri="C:\WINDOWS\Fonts\Scramble.TTF" 
            FontRenderingEmSize="12" Fill="Black" OriginX="5" OriginY="32"/>
  </Grid>
</Page>

Glyphs元素按预期渲染数字为空瓷砖,而TextBox元素则不会。请注意,由于Glyphs是低级元素,因此存在几个限制,特别是FontUri / Fill / FontRenderingEmSize都是必需的,即没有像相关的TextBox属性那样的默认值。
考虑到所有这些问题,回到您最初的问题: 我不认为这是WPF的限制(甚至不是错误),而是在WPF UI布局上下文中应用文本呈现要求和默认值的影响。例如,复合(即非低级)TextBox控件将文本格式设置和排版设置应用于其内容(字形),从而便于嵌入字体中的各种字符映射表(可能有很多...); 特殊/简单的字体(如Scramble)可能没有足够或正确的信息,在这种情况下,WPF呈现引擎可能被迫应用字体回退,就像GalacticCowboy已经概述的那样。
如果确实是这种情况,可能有办法覆盖WPF的默认呈现算法(请参见类TextFormatter,即WPF文本引擎),但是很可能需要深入框架来了解TextBox内部发生了什么。然而,在Scramble字体中找到最终缺失或不正确的字符映射可能会更容易一些。这将是完全不同的努力...

2

不要设置FontFamily="Fonts/#Scrambe",直接使用字体名称,不需要加上"Fonts/#":

<TextBox Text="Testing testing testing" FontFamily="Scramble" />

这对我有用。我下载并安装了你提到的字体,它在VS2008的设计视图和运行时中都展示出了完美的字体。


0

我不太熟悉WPF,但我知道微软通常会以不同的方式处理拉丁字符和非拉丁字符。我看到你可以定义一个复合字体,并将特定的Unicode范围映射到字体上。你可以尝试强制整个Unicode范围使用你的字体。链接文本


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接