Fonts 呈现字体字符LSB或位置不同

Fonts 呈现字体字符LSB或位置不同,fonts,rendering,directwrite,Fonts,Rendering,Directwrite,在某些情况下,我发现字形的间距不一致 我将DirectWrite与IDWriteFontFace一起使用,并与GetDesignGlyphMetrics一起使用GetGlyphIndexes来获取字形的度量,这样我可以获取每个字形,将其存储为图像,然后使用字形信息(高级、lsb、rsb等)重建整个字符串。我使用WIC位图使用ID2D1RenderTarget.DrawTextLayout渲染每个图示符。虽然我做的99%的测试似乎都有效,但我遇到了不一致的间隔,我不知道是什么原因造成的。也许有人能

在某些情况下,我发现字形的间距不一致

我将DirectWrite与
IDWriteFontFace
一起使用,并与
GetDesignGlyphMetrics
一起使用
GetGlyphIndexes
来获取字形的度量,这样我可以获取每个字形,将其存储为图像,然后使用字形信息(高级、lsb、rsb等)重建整个字符串。我使用WIC位图使用
ID2D1RenderTarget.DrawTextLayout
渲染每个图示符。虽然我做的99%的测试似乎都有效,但我遇到了不一致的间隔,我不知道是什么原因造成的。也许有人能透露一些信息,但我不知道从哪里开始

从我的基本解释来看,字体布局由将字形呈现为lsb+宽度组成,然后放置下一个字符的位置称为前进,前进宽度由lsb、字形宽度和rsb组成


我使用的是Zapfino字体,因为它看起来相当复杂,是测试渲染是否正确的一个很好的指标

下面是一些逐行的渲染比较:

  • 正确渲染:这里有两个不同的字符串:左字符串和右字符串,通过paint.net正确渲染

  • 我的渲染:我包括提前放置(红色)和起始位置(黄色)。 在左边,我们有世界!渲染,和世界!已正确放置,但与正确渲染相比,W和o之间的距离现在太大

    在右边,我们有控制!渲染,并且大多数情况下与paint.net渲染一致

  • 我将两者重叠,以便更好地进行比较。我把世界的左边对齐!所以你可以看到,至少这部分是一致的,它的W是关闭的。右边几乎一样

  • net显示了光标的位置,我假设是前进。你可以看到,提前放置,o就在它上面。但是在右边有o,你可以看到它从前进到o有一段距离。在前面(5)、其他角色旁边或单独渲染o时,它仍然具有该距离。我相信(从外观上看)是LSB在收缩

  • 世界!使用带有光标的paint.net进行渲染。你可以看到o与前进相交。在其他一些例子中,我们遇到了与Wo相同的问题,收缩LSB,但例如在Wi中,字形与前进有适当的距离,就像它自己一样


  • 根据字符缩小LSB或移动字形位置时,这种效果称为什么?如何通过glyph数据检测这种行为?

    我发现了,这是字距调整。我被甩了,因为当我检查字体时,DirectWrite为
    HasKerningPairs
    返回0。然而,我在字体编辑器中打开了字体,可以看到它确实有紧排对。进一步查看文档,它说:

    较新字体可能只有GPO紧排,而不是传统的对表紧排。像Gabriola这样的字体,调整时只返回0。GetKerningPairAdjustments不会将这些GPO条目虚拟化并展平为紧排对。


    他们没有提供任何其他方式来抓住他们,所以这是一条死胡同。无法从DirectWrite中的字体获取这些变量,我觉得这很奇怪,因为内置的TextLayout在内部进行了这些调整。但是,由于DirectWrite提供的API无法解决此问题,因此可以将其标记为已解决和未解决。

    整形自动处理GPO内核,您不需要直接访问值。布局显然要经过整形,用这种方式应用紧排。IDWriteTextLayout1接口允许启用每个范围的对紧排,但这可能仅在没有紧排GPOS功能可用时使用


    基本上,使用普通设计进步和标称图示符进行渲染仅用于演示目的,其他所有内容都应通过成形过程,使用布局API或手动通过GetGlyphs()/GetGlyphPlacements()。

    您一次处理一个字符吗,即,获取每个角色的字形和度量,然后将每个字符绘制到渲染目标?如果是这样,那不是你应该做的。是的,目前我需要分别渲染每个glyph。要做到这一点,我将获取渲染的glyph,并根据glyph和布局度量对它们进行排列。逐个glyph渲染会显著降低功能。例如,您的示例图像显示了一个脚本/书法字体,其中某些字母对之间有连接。字体可能有备用字形,根据相邻字形提供适当的连接笔划。但如果一次处理一个glyph,就不会得到上下文替换。OpenType和DirectWrite确实适合于呈现文本运行。我意识到我将不得不牺牲一些功能。不幸的是,对于我正在使用的用例,我们必须将每个glyph分离到它自己的BGRA数据中,作为OpenGL中的纹理使用。否则,每个文本绘制将被视为单独的纹理/绘制调用,这将使其无法使用。使用这种方法,我们可以在不牺牲性能的情况下进行文本渲染。我一直在寻找方法来扩展它的一些常见功能,比如内核
    TryGetFontTable
    至少可以让我更接近。自己处理GSUB和GPOS表是非常重要的。如果你真的想这么做。您可以使用来获取要处理的原始表。“内置TextLayout在内部进行这些调整”-
    IDWriteTextLayout
    只是将所有GPO工作延迟到
    GetGlyphs()
    调用,因为它对GPO本身一无所知。GPO在
    TextAnalyzer
    中处理的是
    GetGlyphs
    的哪一部分?从外观上看,客户机实现了很多东西。我只是想知道我是不是