简体   繁体   English

渲染字体字符 LSB 或位置不同

[英]Rendering font character LSB or placement varies

I am running into inconsistencies with how glyphs are spaced in some situations.在某些情况下,我遇到了字形间距的不一致。

I am using DirectWrite with a IDWriteFontFace and using the GetGlyphIndices with GetDesignGlyphMetrics to get the metrics of the glyphs so I can take each glyph, store it as an image, then reconstruct the whole string using the glyph information (advance, lsb, rsb, etc).我正在使用带有IDWriteFontFace的 DirectWrite,并使用带有GetDesignGlyphMetricsGetGlyphIndices来获取字形的度量,这样我就可以获取每个字形,将其存储为图像,然后使用字形信息(advance、lsb、rsb 等)重建整个字符串)。 I am rendering each glyph using ID2D1RenderTarget.DrawTextLayout with WIC bitmaps.我使用带有 WIC 位图的ID2D1RenderTarget.DrawTextLayout渲染每个字形。 While 99% of tests I have done seem to work, I am running into inconsistent spacing and I have no idea what is causing it.虽然我所做的 99% 的测试似乎都有效,但我遇到了不一致的间距,我不知道是什么原因造成的。 Maybe someone can shed some light, but I am not sure where to start.也许有人可以阐明一些观点,但我不知道从哪里开始。

From my basic interpretation the font layout is composed of rendering the glyphs as lsb + width, and then the place to put the next character is called the advance and the advance width is composed of lsb, glyph width, rsb.从我的基本解释来看,字体布局由将字形渲染为 lsb + 宽度组成,然后放置下一个字符的位置称为提前,提前宽度由 lsb、字形宽度、rsb 组成。


I am using this Zapfino font, because it seems fairly complex and a good metric to test if things are rendering correctly.我正在使用这种 Zapfino 字体,因为它看起来相当复杂,并且是测试事物是否正确呈现的一个很好的指标。

So here are some rendering comparisons line by line:因此,这里逐行进行一些渲染比较:

  1. correct render: Here are two different strings left and right, correctly rendered through paint.net正确渲染:这是左右两个不同的字符串,通过paint.net正确渲染

  2. my render: I include the advance placements (red) and the starting position (yellow).我的渲染:我包括提前展示位置(红色)和起始 position(黄色)。 On the left, we have World, rendered, and the orld.在左边,我们有 World、rendered 和 orld。 is correctly placed, but the distance between W and o is too large now compared to the correct rendering.已正确放置,但与正确渲染相比,W 和 o 之间的距离现在太大了。

    On the right side we have Hold.在右侧,我们有 Hold。 rendered and for the most part is consistent with the paint.net render.渲染并且大部分与paint.net渲染一致。

  3. I overlap both to give a better idea of comparison.我将两者重叠以更好地进行比较。 I align the left of the orld, so you can see that atleast that part is consistent.我对齐 orld 的左侧,所以你可以看到至少那部分是一致的。 it's the W is off.这是W关闭。 Right side is almost identical.右侧几乎相同。

  4. Paint.net shows the cursor position in what I assume is the advance. Paint.net 显示了 cursor position,我认为这是进步。 You can see that the advance placement, the o is right on top of it.您可以看到提前放置,o 就在它的顶部。 But with o on the right side, you can see it has distance from advance to the o.但是右边有o,你可以看到它从advance到o有距离。 When rendering the o at the front (5), next to a different character, or by itself, it still has that distance.当在前面 (5)、不同字符旁边或单独渲染 o 时,它仍然具有该距离。 I believe (appearance wise) it's the LSB that seems to shrink?我相信(外观明智)似乎是 LSB 缩小了?

  5. orld.奥兰多rendered with paint.net with the cursor.使用 Paint.net 和 cursor 渲染。 You can see the o is intersecting the advance, Some other examples, We has the same problem as Wo, shrunk LSB, but for instance in Wi, the glyph has proper distance from the advance.你可以看到 o 与前进相交,其他一些例子,我们和 Wo 有同样的问题,缩小了 LSB,但是例如在 Wi 中,字形与前进有适当的距离。 like it would be on its own.就像它自己一样。

在此处输入图像描述

What is this effect called where it shrinks the LSB or moves the placement of the glyph depending on characters?根据字符缩小 LSB 或移动字形位置的这种效果称为什么? How can I detect such behavior through glyph data?如何通过字形数据检测此类行为?

Shaping takes care of GPOS kerning automatically, you don't need to access values directly.整形会自动处理 GPOS 字距调整,您无需直接访问值。 Layout goes through shaping obviously, applying kerning this way.布局显然要经过整形,以这种方式应用字距调整。 IDWriteTextLayout1 interface allows enabling pair kerning per range, but that probably only used if no kerning GPOS feature is available. IDWriteTextLayout1 接口允许为每个范围启用对字距调整,但这可能仅在没有可用的字距调整 GPOS 功能时使用。

Basically, rendering with plain design advances and nominal glyphs is only useful for demonstration purposes, everything else should go through shaping process, either with layout API or manually through GetGlyphs()/GetGlyphPlacements().基本上,使用简单的设计改进和标称字形进行渲染仅用于演示目的,其他一切都应通过整形过程 go,使用布局 API 或手动通过 GetGlyphs()/GetGlyphPlacements()。

I figured it out, it is kerning.我想通了,这是字距。 I was thrown off because when I checked the font, DirectWrite returns 0 for HasKerningPairs .我被甩了,因为当我检查字体时, DirectWrite 为HasKerningPairs返回 0 。 However, I opened up the font in a font editor and could see it does have kerning pairs.但是,我在字体编辑器中打开了字体,可以看到它确实有字距调整对。 Further looking at the docs it says:进一步查看它说的文档:

Newer fonts may have only GPOS kerning instead of the legacy pair-table kerning. Such fonts, like Gabriola, will only return 0's for adjustments. GetKerningPairAdjustments doesn't virtualize and flatten these GPOS entries into kerning pairs.

They don't offer any other way to grab them, so this is a dead end.他们没有提供任何其他方式来抓住它们,所以这是一条死胡同。 There is no way to get these variables from the font in DirectWrite, which I find odd because the built in TextLayout makes these adjustments internally.无法从 DirectWrite 中的字体中获取这些变量,我觉得这很奇怪,因为内置的 TextLayout 在内部进行了这些调整。 However, as such there is no solution to this issue with the API provided by DirectWrite, this can be marked solved and unresolved.但是,由于 DirectWrite 提供的 API 没有解决此问题,因此可以标记为已解决和未解决。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM