上篇文章使用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字体整体风格不符,尤其是汉字𩽾。