使用pango在windows中渲染文字的一些细节(2)

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