位图字体渲染和字距调整

时间:2011-01-03 00:08:27

标签: c# c++ algorithm gdi+ rendering

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

我将通过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

2 个答案:

答案 0 :(得分:2)

KERNINGPAIR的文档似乎非常简单。如果通过wFirstwSecond成员在表格中出现当前字符和后续字符,请将iKernAmount添加到您为下一个字符前进的像素数。

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

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

答案 1 :(得分:0)

一种常见的解决方案是创建一个字母对宽度表。所以字母“Ti”将比MN更接近。这是一个快速制作的表格,并且可以获得成本优异的结果。