位图字体渲染和字距调整

Posted

技术标签:

【中文标题】位图字体渲染和字距调整【英文标题】:Bitmap font rendering and kerning 【发布时间】:2011-01-03 00:08:27 【问题描述】:

我正在尝试创建位图字体渲染器,但是在渲染实际的单个字母位置时遇到问题。

我将通过 GetCharABCWidthsFloat 和 GetTextMetricsW 获取字体字符信息,但是,我不确定如何正确使用 ABC 宽度……还是需要更多信息才能做到这一点?

我不想使用 FreeType 或任何其他库来执行此操作,我正在尝试使用 C++\Windows 提供的标准功能来执行此操作。

没有字距调整信息,字母将不正确。例如,看一下“f”和“t”并排放置的“Times new roman”。如果没有正确的字母间距,它们看起来会相距太远。 算法示例---

float letterBottomLeftX = 0.0f;
float letterHeight = 1.0f;
float letterWidth = 1.0f;

float scale = 1.0f;
for(U32 c = 0; c < numberOfCharacters; ++c)

    fon->GetCharcterInfo(charValue, charInfo);
    //float advancedWith = (charInfo.A * scale) + (charInfo.B * scale) + (charInfo.C * scale);

    letterWidth = charInfo.B * scale;
    letterHeight = textMetrics.Height * scale;

    if(c == 0)
    
        letterBottomLeftX = -(charInfo.A * scale);
    


    // vertex placement, beginning at letterBottomLeftX

    // texture placement

    // index placement

    letterBottomLeftX += (charInfo.A + charInfo.B + charInfo.C) * scale;

这是一个外观示例,您可以注意到字符之间的错误间距。 (忽略纹理 UV,我将在正确放置字母后修复它)。

http://img88.imageshack.us/img88/4015/njpjp2.png

【问题讨论】:

有人写过位图字体渲染器吗? 【参考方案1】:

KERNINGPAIR 的文档看起来很简单。如果当前字符和下一个字符都通过wFirstwSecond 成员出现在表格中,请将iKernAmount 添加到您为下一个字符前进的像素数中。

我建议使用GetKerningPairs 的结果创建一个std::map&lt;std::pair&lt;wchar_t,wchar_t&gt;,int&gt;,以便快速查找。您已经注意到 GetKerningPairs 不会为每个可能的字符组合返回结果。此信息来自字体本身,由字体设计者指示哪些字符对需要调整。这些信息很可能完全丢失,或者丢失了对您来说很明显的字符对。

确保在调用任何这些函数之前执行SetMapMode(hdc,MM_TEXT),因为映射模式会影响结果。

【讨论】:

有趣。 “SetMapMode(hdc,MM_TEXT)”应该放在哪里?我就是这样做的,但我不确定它是否正确使用它(对不起,很多回复,这里的格式对于回复来说很糟糕)。 HFONT fnt CreateFont(size,0,0,0,FW_NORMAL,0,0,0,ANSI_CHARSET,OUT_TT_PRECIS,CLIP_DEFAULT_PRECIS,PROOF_QUALITY,FF_DONTCARE,"Times New Roman"); int nKerningPairs = GetKerningPairs(dc, 0, 0); KERNINGPAIR * kerningpairs = new KERNINGPAIR[nKerningPairs]; GetKerningPairs(dc, nKerningPairs, kerningpairs); 另外,如果我只是想通过 GetKerningPairs 使用信息,那么我应该提前下一个字符的位置吗?如您所见,我目前正在通过 GetABCWidth 的 B 信息推进它。【参考方案2】:

一种常见的解决方案是创建一个字母对宽度表。因此,字母“Ti”会比 MN 更靠近。这是一个快速制作的表格,并且可以在成本上产生不错的结果。

【讨论】:

有没有办法自动创建这个表?只在其中放置值而不以某种方式查询信息似乎是一种黑客行为。 GetKerningPairs 不会返回所有对的信息,即使它们需要特殊放置。 我来自嵌入式游戏开发领域。执行此操作的工具将是理想的,但众所周知,我们可以通过捷径获得结果。大多数情况下,我只是给你一个可行的解决方案的想法。

以上是关于位图字体渲染和字距调整的主要内容,如果未能解决你的问题,请参考以下文章

Qt QFont 字距调整 - 不影响/字距调整字体

ios:自定义字体的字距调整

Text Rendering iOS - 渲染快速变化文本的最高效方式

Android 4.2.1 错误的字距调整(间距)

带有 itext 的 OpenType 字体字距调整

构建用于调整字体中字符的字距和间距的软件[关闭]