GetCharacterPlacement(...,GCP_LIGATE)无法在XP上运行

时间:2014-07-31 01:12:50

标签: c++ windows unicode mfc glyph

我想要显示一个卡纳达语的字符(在印度使用)。要正确显示结扎,需要进行结扎。我使用以下MFC代码:

构造

mi_Font.CreateFontW(85, 0, 0, 0, 500, 0, 0, 0, 
                    DEFAULT_CHARSET, 0, 0, 0, 0, L"Tunga");
OnPaint()中的

HDC h_DC = ::GetDC(m_hWnd);
HFONT h_OldFont = (HFONT)::SelectObject(h_DC, mi_Font);

WCHAR u16_Face[100];
::GetTextFace(h_DC, 100, u16_Face);
if (wcscmp(u16_Face, L"Tunga") != 0)
    throw "Invalid font."; // Just assure that the font has been created correctly

WCHAR u16_Glyphs[100] = {0};
GCP_RESULTS k_Results = {0};
k_Results.lStructSize = sizeof(k_Results);
k_Results.lpGlyphs    = u16_Glyphs;
k_Results.nGlyphs     = 100;

const WCHAR* u16_Str = L"\x0C95\x0CCD\x0C95\x0CBE"; // Kannada
int s32_Len = (int)wcslen(u16_Str);

GetCharacterPlacement(h_DC, u16_Str, s32_Len, 0, &k_Results, GCP_LIGATE);

ExtTextOut(h_DC, 0, 0, ETO_GLYPH_INDEX, NULL, u16_Glyphs, k_Results.nGlyphs, NULL);

SelectObject(h_DC, h_OldFont);
::ReleaseDC(m_hWnd, h_DC);

此代码在Windows 7上运行良好。但在Windows XP上,标志GCP_LIGATE无效。 (在Windows 7上,它甚至可以在没有该标志的情况下工作!)

GetCharacterPlacement

为了确保字体不是问题,我将相同的字体文件(Tunga.ttf)复制到两台计算机上。

问题出在GetCharacterPlacement()

在XP上,它返回字形索引66,114,66,101(无结扎)

在Win7上,它返回144,101,180(已连接)

我无法相信Windows XP无法正确显示Kannada,因为Windows 2000中已经引入了GetCharacterPlacement()

当我手动将值输入k_Result时:

u16_Glyphs[0] = 144;
u16_Glyphs[1] = 101;
u16_Glyphs[2] = 180;
k_Results.nGlyphs = 3;

ExtTextOut()在XP上也显示正确的字形。

当我从GetFontLanguageInfo(h_DC)检查返回值时,我在两个操作系统上得到相同的值:0x40000。

是否有人使用此API?

2 个答案:

答案 0 :(得分:0)

我对GetCharacterPlacement()和其他GDI函数进行了更多调查。

除了在Windowx XP上没有正确显示连字这一事实之外,即使在Windows 7上也存在此功能中的严重错误。其中一个是应该包含绘制字符的宽度和高度的返回值是完全错误的对于一些角色。

奇怪的是,Windows正确地绘制了背景颜色(我的截图中的白色),但该功能并不总是返回同一区域。对于170像素宽的一些连字,它返回完全错误的值93。

在某些情况下,可能通过GCP_RESULTS.lpDx请求的Delta-X值可能完全错误,但字形被正确绘制。

最后,当一些字体以斜体绘制时,该函数会返回完全相同的坐标,就好像它是经常绘制的一样,尽管斜体更宽。

我还测试了GetTextExtentPoint32()GetTextExtentPointI()DrawText(...DT_CALCRECT)。它们都返回相同的错误宽度。

实施例: 当您以斜体绘制字符“T”时,所有这些函数都返回35像素的宽度。您可以在下面的屏幕截图中测量自己,真实的是64像素。 35个像素对于常规字符是正确的。斜体样式简直被忽略了。这也适用于Windows 7。

<强>结论: 忘记使用这些功能之一测量字体。它们都是错误的。如果您使用许多字体和语言(例如Telugu o Kannada)进行彻底测试,您会发现它们返回废话的情况。

现在我明白为什么Java虚拟机不使用任何Windows API来绘制文本。如果您研究Java的源代码,您会发现它们直接加载TTF文件并使用自己的代码进行所有计算和绘制。

我在MSDN博客中找到了这个:

GetCharacterPlacement没有考虑字距调整

最近我遇到了同样的错误。 GetCharacterPlacement()在3台PC上返回了错误的结果,在其他4台上返回了正确的值。然后我发现在GetCharacterPlacement()没有按预期工作的所有计算机上,已经安装了东亚语言,并且还没有安装在其他计算机上。我在PC上安装了东亚语言,其中GetCharacterPlacement()工作正常,并在安装后立即停止工作!然后我卸载了东亚语言,代码又开始完美运行了。

enter image description here

答案 1 :(得分:0)

这与我没有直接关系,但我来到这里是因为我在XP上遇到了GetCharacterPlacement问题(我的许多客户仍在使用XP)。

事实证明,在XP中,GCP_RESULTS参数必须在4字节边界上对齐;否则,呼叫失败。在Windows 7中,它不必对齐。

此外,GetLastError()似乎与GetCharacterPlacement调用没有任何关系。

我在上面的例子中意识到它是对齐的。