gpt4 book ai didi

windows - 获取 DrawText [Ex] 解释的 GDI HFONT 行高

转载 作者:行者123 更新时间:2023-12-05 02:01:57 25 4
gpt4 key购买 nike

我想知道哪些指标用于计算正确的行高(2 个相邻文本行基线之间的垂直距离)。 “正确”应任意定义为“无论 DrawTextW 做什么”。

The accepted answer here似乎遵循图表提供的内容in this MSDN article说:

TEXTMETRICW.tmHeight + TEXTMETRICW.tmExternalLeading;

但这似乎不正确。使用 2 段文本进行一些测试,每段文本由 2 行组成:

// RECT rc is more than large enough to fit any text
int HeightChinese = DrawTextW(hdc, L"中\r\n文", -1, &rc, 0);
int HeightLatin = DrawTextW(hdc, L"Latin,\r\nlatin!", -1, &rc, 0);

预期的返回值应该是2 * <SomethingUnknown> .

一个观察结果是 DrawTextW 的返回值将始终匹配 RECT输出如果 DT_CALCRECT用于我机器上的所有字体。所以我假设使用 DT_CALCRECT使用 DrawTextW 的返回值不提供任何附加值.

对于我机器上的所有字体,这些都是正确的:

  • HeightChinese == HeightLatin
  • LOGFONTW.lfHeight == TEXTMETRICW.tmHeight (1).

对于我机器上的大多数字体,这是正确的:

  • HeightXxx == 2 * TEXTMETRICW.tmHeight

这已经与另一个问题中提供的公式相矛盾(TEXTMETRICW.tmExternalLeading 不起作用)。

例如,“宋体”与 LOGFONTW.lfHeight = 36会有TEXTMETRICW.tmExternalLeading = 1 , 和 HeightXxx == 72 (不是 74)。截屏和测量像素点的线距也是72(看来返回值是可信的)。

同时,“Segoe UI”与LOGFONTW.lHeight = 43会有TEXTMETRICW.tmExternalLeading = 0 , 和 HeightXxx == 84 (不是 86)。

这是我系统上所有异常字体的列表:

"FontName" -- "DrawText return value" vs "2 * TEXTMETRICW.tmHeight"

Ebrima -- 84 vs 86
Leelawadee UI -- 84 vs 86
Leelawadee UI Semilight -- 84 vs 86
Lucida Sans Unicode -- 96 vs 98
Malgun Gothic -- 84 vs 86
Malgun Gothic Semilight -- 84 vs 86
Microsoft Tai Le -- 80 vs 82
Microsoft YaHei -- 82 vs 84
Microsoft YaHei UI Light -- 82 vs 84
MS Gothic -- 66 vs 64
MS UI Gothic -- 66 vs 64
MS PGothic -- 66 vs 64
Nirmala UI -- 84 vs 86
Nirmala UI Semilight -- 84 vs 86
Palatino Linotype -- 84 vs 86
Segoe UI -- 84 vs 86
Segoe UI Black -- 84 vs 86
Segoe UI Historic -- 84 vs 86
Segoe UI Light -- 84 vs 86
Segoe UI Semibold -- 84 vs 86
Segoe UI Semilight -- 84 vs 86
Segoe UI Symbol -- 84 vs 86
SimSun -- 66 vs 64
NSimSun -- 66 vs 64
SimSun-ExtB -- 66 vs 64
Verdana -- 76 vs 78
Webdings -- 62 vs 64
Yu Gothic UI -- 84 vs 86
Yu Gothic UI Semibold -- 84 vs 86
Yu Gothic UI Light -- 84 vs 86
Yu Gothic UI Semilight -- 84 vs 86
MS Mincho -- 66 vs 64
MS PMincho -- 66 vs 64
Ubuntu Mono -- 62 vs 64

有时返回值比计算值大2,有时比计算值小2。

我查看了 TEXTMETRICW 中的其他值,我还查看了可用的额外数据 int OUTLINETEXTMETRICW ,但我找不到任何可以解释观察结果的模式。

那么,计算行高的正确指标是什么?我知道我可以调用 DrawTextWDT_CALCRECT获取此值,但我想了解此信息的来源(以及字体设计师如何以可预测的方式控制它)。

Here is a gist with a complete Windows application that demonstrates this .所有有趣的东西都在 WM_PAINT 中.搜索 @EDIT对于一些有趣的代码开关和断点。 在发布此问题时,我的 GitHub 帐户已被标记,Gist 暂时不可用。希望这件事能尽快解决。

(1) 我正在使用 EnumFontFamiliesEx枚举所有字体,它恰好提供了LOGFONTW具有的结构lfHeight值。这意味着我使用的是单元格高度,而不是字符高度。虽然 字符高度 是更典型的指定字体高度的方式,但这在这里有点无关紧要,单元格高度 恰好等于 TEXTMETRICW.tmHeight。 ,但字符高度不是。计算的相关值为TEXTMETRICW.tmHeight ,而不是 LOGFONTW.lfHeight .

最佳答案

正如 Jonathan Potter 指出的那样,公式 TEXTMETRICW.tmHeight 应该 是正确的,如果设置了 DT_EXTERNALLEADING 标志,那么它是TEXTMETRICW.tmHeight + TEXTMETRICW.tmExternalLeading

我用 Ghidra 对 DrawTextExW 进行了逆向工程,数字有时不对的原因不是 DrawTextExW 本身。 DrawTextExW 内部使用了一个DT_InitDrawTextInfo,它又使用了GetTextMetricsW 并根据上述公式计算行高。

但是,请考虑使用此代码来探测所有字体:

LOGFONTW Probe = {};
Probe.lfCharSet = DEFAULT_CHARSET;
EnumFontFamiliesExW(hdc, &Probe, InitializeFontInfo_EnumFontFamiliesCallback, NULL, 0);

static int CALLBACK InitializeFontInfo_EnumFontFamiliesCallback(const LOGFONTW *LogFont, const TEXTMETRICW *TextMetric, DWORD FontType, LPARAM lParam)
{
FONT_INFO tmp = {};
tmp.LogFont = *LogFont;
tmp.TextMetric = *TextMetric;
FontInfo.push_back(tmp);
return 1;
}

这里以Segoe UI字体为例,LogFont->lfHeight将为43。

因此,TextMetric->tmHeight 也将为 43,您会认为这在某种程度上是有意义的。

但是:

如果您继续将此 LogFont 选择到 HDC 中,然后使用 GetTextMetricsW,如下所示:

HFONT Font = CreateFontIndirectW(LogFont);
SelectObject(hdc, Font);
TEXTMETRICW TextMetric = {};
GetTextMetricsW(hdc, &TextMetric);

然后 TextMetric->tmHeight == 42 即使 LogFont->lfHeight == 43

换句话说,为 EnumFontFamiliesExW 回调提供的 TEXTMETRICW 参数的值不可信。尽管您可能会争辩说错误出在其他地方,并且选择 LogFont->lfHeight == 43 字体实际上也应该产生 TextMetric->tmHeight == 43 文本规范,但我想这要求太多了。我的猜测是其中某处正在进行浮点转换,并且偶尔会对某些数字产生舍入误差。

关于windows - 获取 DrawText [Ex] 解释的 GDI HFONT 行高,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66186989/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com