【发布时间】:2020-09-21 08:07:04
【问题描述】:
在某些情况下,我遇到了字形间距不一致的问题。
我使用 DirectWrite 和 IDWriteFontFace 并使用 GetGlyphIndices 和 GetDesignGlyphMetrics 来获取字形的指标,这样我就可以获取每个字形,将其存储为图像,然后使用字形重建整个字符串信息(提前,LSB,RSB等)。我使用带有 WIC 位图的 ID2D1RenderTarget.DrawTextLayout 渲染每个字形。虽然我所做的 99% 的测试似乎都有效,但我遇到了不一致的间距,我不知道是什么原因造成的。也许有人可以解释一下,但我不知道从哪里开始。
从我的基本解释来看,字体布局是由将字形渲染为 lsb + 宽度组成,然后放置下一个字符的位置称为提前,提前宽度由 lsb、字形宽度、rsb 组成。
我正在使用这种 Zapfino 字体,因为它看起来相当复杂,并且是测试事物是否正确呈现的一个很好的指标。
所以这里逐行进行一些渲染对比:
正确渲染:这里是左右两个不同的字符串,通过paint.net正确渲染
-
我的渲染:我包括提前展示位置(红色)和起始位置(黄色)。 在左边,我们有世界!渲染,和世界!已正确放置,但与正确的渲染相比,W 和 o 之间的距离现在太大了。
在右侧,我们有 Hold!渲染并且大部分与paint.net渲染一致。
我将两者重叠以便更好地进行比较。我对齐orld的左边!所以你可以看到至少那部分是一致的,它是 W 关闭。右侧几乎相同。
Paint.net 显示光标位置在我认为是前进的位置。您可以看到提前放置,o 就在它的顶部。但是右边有o,你可以看到它从advance到o有距离。当在前面 (5)、不同字符旁边或单独渲染 o 时,它仍然具有该距离。我相信(外观方面)似乎是 LSB 缩小了?
天哪!使用带有光标的paint.net 渲染。你可以看到 o 与前进相交。其他一些例子,We 和 Wo 有同样的问题,缩小 LSB,但例如在 Wi 中,字形与前进有适当的距离,就像它自己一样。
根据字符缩小 LSB 或移动字形位置的这种效果称为什么?如何通过字形数据检测此类行为?
【问题讨论】:
-
您是否一次处理一个字符,即获取每个字符的字形和指标,然后将每个字符绘制到渲染目标?如果是这样,那不是你应该做的。
-
是的,目前我需要分别渲染每个字形。为此,我采用渲染的字形并根据字形和布局指标对其进行排列。
-
逐个字形渲染会显着降低功能。例如,您的示例图像显示了一个脚本/书法字体,其中一些字母对之间存在连接。该字体可能具有替代字形,可根据相邻字形提供适当的连接笔划。但是,如果您一次处理一个字形,您将不会获得上下文替换。 OpenType 和 DirectWrite 真正适用于渲染 runs 文本。
-
我意识到我将不得不牺牲一些功能。不幸的是,对于我正在使用的用例,我们必须将每个字形分离成它自己的 BGRA 数据,以便在 OpenGL 中用作纹理。否则,每个文本绘制都将被视为一个单独的纹理/绘制调用,这将使其无法使用。使用这种方法,我们可以在不牺牲性能的情况下进行文本渲染。我一直在寻找方法来扩展它以获得一些常见的功能,例如字距调整。
TryGetFontTable至少应该让我更接近。
标签: fonts rendering directwrite