上篇文章使用pango在windows中渲染文字的一些细节(1)大致描述了pangov1.45.3中存在的的稍嫌不足之处,本文尝试去解决这些问题。
一、为pango提供SurrogateFallback(替换性备选字体)支持
1、第一步,实现windows系统读取SurrogateFallback的代码
read_windows_surrogate_fallback是在pango的read_windows_fallbacks()中使用,实现时直接传入line_buffer变量,并将当前字体的“替换性备选字体”追加进line_buffer变量中。
static void
read_windows_surrogate_fallback(GString* line_buffer, const wchar_t* fontname)
{
HKEY hKey;
LSTATUS status;
wchar_t szPath[261];
swprintf_s(szPath, 261, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\LanguagePack\\SurrogateFallback\\%s", fontname);
status = RegOpenKeyExW(HKEY_LOCAL_MACHINE, szPath, 0, KEY_READ, &hKey);
if (status != ERROR_SUCCESS)
{
swprintf_s(szPath, 261, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\LanguagePack\\SurrogateFallback");
status = RegOpenKeyExW(HKEY_LOCAL_MACHINE, szPath, 0, KEY_READ, &hKey);
}
if (status != ERROR_SUCCESS)
return;
// Unicode当前规范包含从0x00000-0xfffff总共16个平面(panel)
for (int i = 2; i < 16; i++)
{
wchar_t szPanel[16];
DWORD dwSize;
swprintf_s(szPanel, 16, L"Plane%d", i);
dwSize = sizeof(szPath) / sizeof(szPath[0]);
status = RegGetValueW(hKey, NULL, szPanel, RRF_RT_REG_SZ, NULL, szPath, &dwSize);
if (status == ERROR_SUCCESS)
{
gchar* sutf8 = g_utf16_to_utf8(szPath, -1, NULL, NULL, NULL);
g_string_append_printf(line_buffer, ",%s", sutf8);
g_free(sutf8);
}
}
RegCloseKey(hKey);
}
2、第二步,在pango的read_windows_fallbacks函数中增加SurrogateFallback支持
static void
read_windows_fallbacks (GHashTable *ht_aliases)
{
...
for (value_index = 0; status != ERROR_NO_MORE_ITEMS; value_index++)
{
...
status = RegEnumValueW (hkey, value_index, name, &name_length,
NULL, NULL, NULL, NULL);
...
utf8_name = g_utf16_to_utf8 (name, -1, NULL, NULL, NULL);
...
g_string_append_printf (line_buffer,
"\"%s\" = \"%s",
utf8_name,
utf8_name);
...
// 优先加入SurrogateFallback(替换性备选字体)
read_windows_surrogate_fallback(line_buffer, name);
3、显示效果对比
下图是在windows11(10.0.22000.184)中选用MingLiU字体的显示效果对比。
第一行的pango渲染没有使用SurrogateFallback(替换性备选字体)支持,可以看见数字、英文、及汉字𩽾的显示均与MingLiU字体整体风格不符,尤其是汉字𩽾。
