C# 位图字体渲染和紧排
我正在尝试创建位图字体渲染器,但是,我在渲染实际的单个字母位置时遇到问题 我将通过GetCharABCWidthsFloat和GetTextMetricsW获得字体字符信息,但是,我不确定如何正确使用ABC宽度。。。或者我需要更多的信息来做这件事 我不想使用FreeType或任何其他库来实现这一点,我正试图通过C++\Windows提供的标准功能来实现这一点 如果没有字距信息,字母将不会显示正确。例如,看一看“Times new roman”,其中“f”和“t”相邻放置。如果没有正确的字母间距,它们看起来会相距太远。 算法实例---C# 位图字体渲染和紧排,c#,c++,algorithm,gdi+,rendering,C#,C++,Algorithm,Gdi+,Rendering,我正在尝试创建位图字体渲染器,但是,我在渲染实际的单个字母位置时遇到问题 我将通过GetCharABCWidthsFloat和GetTextMetricsW获得字体字符信息,但是,我不确定如何正确使用ABC宽度。。。或者我需要更多的信息来做这件事 我不想使用FreeType或任何其他库来实现这一点,我正试图通过C++\Windows提供的标准功能来实现这一点 如果没有字距信息,字母将不会显示正确。例如,看一看“Times new roman”,其中“f”和“t”相邻放置。如果没有正确的字母间距,
float-letterBottomLeftX=0.0f;
浮动字体高度=1.0f;
浮动字体宽度=1.0f;
浮动刻度=1.0f;
对于(U32 c=0;cgetCharacterInfo(charValue,charInfo);
//float advancedWith=(charInfo.A*scale)+(charInfo.B*scale)+(charInfo.C*scale);
字母宽度=charInfo.B*刻度;
letterHeight=textMetrics.Height*比例;
如果(c==0)
{
letterBottomLeftX=-(charInfo.A*比例);
}
//顶点放置,从LeftX开始
//纹理放置
//索引放置
LeftX+=(charInfo.A+charInfo.B+charInfo.C)*比例;
}
下面是一个示例,您可以注意到字符之间的间距很差。(忽略纹理UV,我将在获得正确的字母位置后修复它)
一种常见的解决方案是创建字母对宽度表。因此,字母“Ti”的位置比MN更接近。这是一个快速制作的表格,并以相当高的成本产生非常好的结果。有关
内核对的文档似乎非常简单。如果当前字符和下一个字符都通过wFirst
和wssecond
成员出现在表中,请将iKernAmount
添加到下一个字符的像素数中
我建议使用GetKerningPairs
的结果创建一个std::map
,以便快速查找。您已经注意到,GetKerningPairs
不会为每个可能的字符组合返回结果。此信息来自字体本身,由字体设计师指示哪些字符对需要调整。这些信息很可能完全丢失,或者丢失对您来说很明显的字符对
在调用这些函数之前,请确保执行SetMapMode(hdc,MM_TEXT)
,因为映射模式会影响结果。是否有方法自动创建此表?它看起来像是一个黑客,只是把值放在那里,而没有查询信息。GetKerningPairs不会返回所有对的信息,即使它们需要特殊放置。我来自嵌入式游戏开发领域。实现这一点的工具是理想的,但众所周知,我们可以通过快捷方式获得结果。大体上,我只是给你一个可行的解决方案的想法。“SetMapMode(hdc,MM_文本)”应该放在哪里?我就是这样做的,我不确定它是否正确使用了它(很抱歉回复太多,这里的格式对回复来说太糟糕了)。HFONT fnt CreateFont(大小,0,0,0,FW_正常,0,0,0,ANSI_字符集,放样精度,剪裁默认精度,校样质量,FF_DONTCARE,“新罗马时代”);int nKerningPairs=GetKerningPairs(dc,0,0);KERNINGPAIR*kerningpairs=新的KERNINGPAIR[nKerningPairs];GetKerningPairs(dc、nKerningPairs、kerningpairs);另外,如果我只想通过GetKerningPairs使用信息,那么我应该为下一个字符提前位置吗?正如你所看到的,我目前正在通过GetABCWidth的B信息推进它。有人编写过位图字体渲染器吗?
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;
}