是什么导致Calibri在9到14磅之间失去ClearType?

jnm*_*nm2 15 c# fonts gdi+ cleartype opentype

当使用默认的Microsoft Office字体Calibri在9pt和14pt之间指定ClearTypeGridFit时,究竟是什么让GDI +切换到二进制混叠?

这有点令人不安.还有多少其他字体也受到此背后的任何影响以及尺寸的影响?有解决方法吗?(不包括GDI,它没有相同的文本布局功能?)

这是我用来生成图像的代码:

private void Form1_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;

    var height = 0;
    for (var i = 1; i <= 17; i++)
    {
        using (var font = new Font("Calibri", i))
        {
            var text = "ClearTypeGridFit " + i + "pt";
            e.Graphics.DrawString(text, font, SystemBrushes.ControlText, 0, height);
            height += (int)e.Graphics.MeasureString(text, font).Height;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Mik*_*ans 14

Calibri附带一个EBLC表和EBDT表,它告诉文本引擎,对于某些点大小,他们不应该尝试"他们自己的缩放算法",而只是使用直接存储在字体中的位图.

每个字体大小都可以带有自己的列表"以下字形必须以此大小进行位图",称为"打击",因此一个字形可以有多个大小的多个位图(但可能存在间隙,当发生这种情况时,位图需要缩放,事情可能会发生灾难性的错误).

例如,Calibri对点大小为12,13,15,16,17和19进行了攻击,A的示例位图为:

<ebdt_bitmap_format_1 name="A">
  <SmallGlyphMetrics>
    <height value="8"/>
    <width value="7"/>
    <BearingX value="0"/>
    <BearingY value="8"/>
    <Advance value="7"/>
  </SmallGlyphMetrics>
  <rawimagedata>
    10102828 447c8282  
  </rawimagedata>
</ebdt_bitmap_format_1>
Run Code Online (Sandbox Code Playgroud)

该位图由字体大小12 strike引用,并编码为7x8像素位图.由于12是最低值,当我们使用低于12的字体大小时,我们会遇到问题:突然我们必须缩放位图.这只会出现可怕的错误.

如果你看一下像写字板这样的东西,你可以看到微软的Uniscribe引擎(与GDI +一起使用;现代的等价物是Direct2D ,而DirectWrite作为文本引擎)可以很好地缩放这些位图(显示的是5到20的大小),但是即便是微软自己的技术也有明显的局限性.我们看到在字体大小为5,6和7px时,位图非常糟糕,甚至8,10和11看起来有些不稳定:

A尺寸为5到20

放大:

A尺寸为5到20,按比例增加3倍

事情变得更有趣,因为不是每个字形都在每次打击中表示,所以虽然"A"在点大小为12时有位图,但是有一些字形,其中具有显式位图的最低点大小可以是13,或15或16,或者17岁,甚至19岁.

这意味着您有三个问题:

  1. 字体可能"要求"文本引擎使用其位图,而不是尝试按照文本引擎的算法对矢量轮廓进行栅格化,以及
  2. 没有魔术字体大小,高于该大小,所有字符都"很好地"呈现,并且低于该字体,所有字符都呈现为"差".字体可以包含任意数量的"罢工",包含字体编码字形的任何子集,实际上意味着每个字符都有自己的规则,关于文本引擎何时应该从光栅化矢量切换到嵌入位图,以及
  3. 文本引擎完全可以完全自由地完全忽略字体的"需求",并且无论如何都要做自己的事情,并找出哪个引擎确实是什么,尽管我们可以使用互联网,几乎是不可能的.这是任何人似乎没有记录的事情之一.

找出哪些字体可以做到这一点的最简单方法是简单地检查EBDT表的字体 - 如果有的话,这种字体会强制引擎使用位图来表示非常小(有时非常大)的字体.如果你想要这些细节,你可以通过TTX运行字体,然后找到<EBDT>表格开始,看看究竟发生了什么.

不过准备不堪重负.例如,仅Calibri就有超过一千个字形指定的位图.

  • 对于像Calibri这样的专业TTF-OpenType字体,嵌入式位图将比矢量光栅化器可以产生的要好得多(http://www.rastertragedy.com以最令人惊叹的细节解释其原因).因此,优秀的文本引擎将使用它们 - 但并非所有这些都可以.并且,仅仅因为你在Windows上并不意味着你总是使用相同的引擎:GDI +我认为使用Uniscribe,但现代版本的Windows将使用Direct2D和DirectWrite.也就是说,自Windows 95以来我没有为windows编程,因此值得验证. (2认同)