【发布时间】:2019-12-19 07:11:38
【问题描述】:
我尝试使用 WinAPI 将字体渲染为位图,但无法达到所需的字体大小。
这是字体的初始化方式:
HDC dc = ::CreateCompatibleDC(NULL);
::SetMapMode(dc, MM_TEXT);
::SetTextAlign(dc, TA_LEFT | TA_TOP | TA_UPDATECP);
int size_in_pixels = 18;
HFONT font = ::CreateFontA(-size_in_pixels, ..., "Arial");
::SelectObject(dc, font);
::TEXTMETRICW tm = { 0 };
GetTextMetricsW(dc, &tm);
但之后我在GetGlyphOutlineW 和GetTextMetricsW 中都得到了不正确的值,这不是我作为参数传递的大小
我知道它的期望值是逻辑单位,但在 MM_TEXT 中,1 单位应该是 1 像素,不是吗?
我希望 CreateFontA 在传递负值时接受点大小(例如这里的 https://i.stack.imgur.com/tEt8J.png),但实际上这是错误的。
我尝试了暴力破解值,并找出了一些尺寸的合适参数:
18px = -19; 36px = -39; 73px = -78;
我也试过微软提供的公式:
nHeight = -MulDiv(PointSize, GetDeviceCaps(hDC, LOGPIXELSY), 72);
但这也给了我一个错误的结果,如果测量它,渲染的文本(使用GetGlyphOutlineW)会更大(例如,'j' 的高度应该具有我通过的确切大小)
来自GetTextMetricsW 的指标也是错误的,例如tmAscent。我知道在 Windows 上它包括内部领先,但即使从 tmAscent 中减去 tmInternalLeading 它仍然不正确。
顺便说一句,GetCharABCWidthsW 中的值是正确的,因此 a+b+c 是以像素为单位的字形宽度(而文档中说它应该是逻辑单位)。
另外我应该说一下 DPI,通常我在 Windows 10 的设置中使用 125%,但我什至尝试使用 100%,有趣的是 ::GetDeviceCaps(dc, LOGPIXELSY) 不会随着我使用的比例而改变,它总是 96
下面是 CreateFontA(-128, ...) 的示例,其中包含最终图集和指标:
rendered atlas
问题 #1:我应该怎么做才能传递所需的点大小(以像素为单位)并接收具有正确大小的字形(以像素为单位)?
问题 #2:所有这些函数都使用了哪些奇怪的单位?
【问题讨论】:
标签: c++ winapi fonts rendering