本文分析wine 加载font的过程。
第一步,update_font_info();
static void update_font_info(void)
{
static const WCHAR logpixels[] = { 'L','o','g','P','i','x','e','l','s',0 };
char buf[40], cpbuf[40];
DWORD len, type;
HKEY hkey = 0;
UINT i, ansi_cp = 0, oem_cp = 0;
DWORD screen_dpi = 96, font_dpi = 0;
BOOL done = FALSE;
if (RegOpenKeyA(HKEY_LOCAL_MACHINE,
"System\\CurrentControlSet\\Hardware Profiles\\Current\\Software\\Fonts",
&hkey) == ERROR_SUCCESS)
{
reg_load_dword(hkey, logpixels, &screen_dpi);
RegCloseKey(hkey);
}
if (RegCreateKeyExA(HKEY_CURRENT_USER, "Software\\Wine\\Fonts", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey, NULL) != ERROR_SUCCESS)
return;
reg_load_dword(hkey, logpixels, &font_dpi);
GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_IDEFAULTANSICODEPAGE|LOCALE_RETURN_NUMBER|LOCALE_NOUSEROVERRIDE,
(WCHAR *)&ansi_cp, sizeof(ansi_cp)/sizeof(WCHAR));
GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_IDEFAULTCODEPAGE|LOCALE_RETURN_NUMBER|LOCALE_NOUSEROVERRIDE,
(WCHAR *)&oem_cp, sizeof(oem_cp)/sizeof(WCHAR));
sprintf( cpbuf, "%u,%u", ansi_cp, oem_cp );
/* Setup Default_Fallback usage for DBCS ANSI codepages */
if (is_dbcs_ansi_cp(ansi_cp))
use_default_fallback = TRUE;
buf[0] = 0;
len = sizeof(buf);
if (RegQueryValueExA(hkey, "Codepages", 0, &type, (BYTE *)buf, &len) == ERROR_SUCCESS && type == REG_SZ)
{
if (!strcmp( buf, cpbuf ) && screen_dpi == font_dpi) /* already set correctly */
{
RegCloseKey(hkey);
return;
}
TRACE("updating registry, codepages/logpixels changed %s/%u -> %u,%u/%u\n",
buf, font_dpi, ansi_cp, oem_cp, screen_dpi);
}
else TRACE("updating registry, codepages/logpixels changed none -> %u,%u/%u\n",
ansi_cp, oem_cp, screen_dpi);
RegSetValueExA(hkey, "Codepages", 0, REG_SZ, (const BYTE *)cpbuf, strlen(cpbuf)+1);
RegSetValueExW(hkey, logpixels, 0, REG_DWORD, (const BYTE *)&screen_dpi, sizeof(screen_dpi));
RegCloseKey(hkey);
for (i = 0; i < sizeof(nls_update_font_list)/sizeof(nls_update_font_list[0]); i++)
{
HKEY hkey;
if (nls_update_font_list[i].ansi_cp == ansi_cp &&
nls_update_font_list[i].oem_cp == oem_cp)
{
hkey = create_config_fonts_registry_key();
RegSetValueExA(hkey, "OEMFONT.FON", 0, REG_SZ, (const BYTE *)nls_update_font_list[i].oem, strlen(nls_update_font_list[i].oem)+1);
RegSetValueExA(hkey, "FIXEDFON.FON", 0, REG_SZ, (const BYTE *)nls_update_font_list[i].fixed, strlen(nls_update_font_list[i].fixed)+1);
RegSetValueExA(hkey, "FONTS.FON", 0, REG_SZ, (const BYTE *)nls_update_font_list[i].system, strlen(nls_update_font_list[i].system)+1);
RegCloseKey(hkey);
hkey = create_fonts_NT_registry_key();
add_font_list(hkey, &nls_update_font_list[i], screen_dpi);
RegCloseKey(hkey);
hkey = create_fonts_9x_registry_key();
add_font_list(hkey, &nls_update_font_list[i], screen_dpi);
RegCloseKey(hkey);
if (!RegCreateKeyA( HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes", &hkey ))
{
RegSetValueExA(hkey, "MS Shell Dlg", 0, REG_SZ, (const BYTE *)nls_update_font_list[i].shelldlg,
strlen(nls_update_font_list[i].shelldlg)+1);
RegSetValueExA(hkey, "Tms Rmn", 0, REG_SZ, (const BYTE *)nls_update_font_list[i].tmsrmn,
strlen(nls_update_font_list[i].tmsrmn)+1);
set_value_key(hkey, "Fixedsys,0", nls_update_font_list[i].fixed_0);
set_value_key(hkey, "System,0", nls_update_font_list[i].system_0);
set_value_key(hkey, "Courier,0", nls_update_font_list[i].courier_0);
set_value_key(hkey, "MS Serif,0", nls_update_font_list[i].serif_0);
set_value_key(hkey, "Small Fonts,0", nls_update_font_list[i].small_0);
set_value_key(hkey, "MS Sans Serif,0", nls_update_font_list[i].sserif_0);
set_value_key(hkey, "Helv,0", nls_update_font_list[i].helv_0);
set_value_key(hkey, "Tms Rmn,0", nls_update_font_list[i].tmsrmn_0);
set_value_key(hkey, nls_update_font_list[i].arial_0.from, nls_update_font_list[i].arial_0.to);
set_value_key(hkey, nls_update_font_list[i].courier_new_0.from, nls_update_font_list[i].courier_new_0.to);
set_value_key(hkey, nls_update_font_list[i].times_new_roman_0.from, nls_update_font_list[i].times_new_roman_0.to);
RegCloseKey(hkey);
}
done = TRUE;
}
else
{
/* Delete the FontSubstitutes from other locales */
if (!RegCreateKeyA( HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes", &hkey ))
{
set_value_key(hkey, nls_update_font_list[i].arial_0.from, NULL);
set_value_key(hkey, nls_update_font_list[i].courier_new_0.from, NULL);
set_value_key(hkey, nls_update_font_list[i].times_new_roman_0.from, NULL);
RegCloseKey(hkey);
}
}
}
if (!done)
FIXME("there is no font defaults for codepages %u,%u\n", ansi_cp, oem_cp);
/* update locale dependent font association info and font system link info in registry.
update only when codepages changed, not logpixels. */
if (strcmp(buf, cpbuf) != 0)
{
update_font_association_info(ansi_cp);
update_font_system_link_info(ansi_cp);
}
}
第二步,init_freetype(),加载"libfreetype.so.6"
第三步,init_fontconfig(),加载"libfontconfig.so.1"
第四步,打开[HKEY_CURRENT_USER\\Software\\Wine\\Fonts]下的字体设置
查询AntialiasFakeBoldOrItalic 即反锯齿,粗体或斜体,设置反锯齿属性
第五步,加载字体
1、如果[HKEY_CURRENT_USER\\Software\\Wine\\Fonts\\Cache] 是新创建的,重新根据Windows\\Fonts 目录来加载所有字体否则根据Cache 键值进行加载
1) 删除[HKEY_CURRENT_USER\\Software\\Wine\\Fonts\\External Fonts] 键值,并将在[HKEY_LOCAL_MECHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts]或[HKEY_LOCAL_MECHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Fonts]的对应信息删掉
2)加载系统字体,即注册表【HKEY_CUDRDRENT_CONFIG\\Software\\Fonts】
3) 加载Windows\\Fonts\\下的字体,wine\fonts\ 下字体,[HKEY_LOCAL_MECHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts]或[HKEY_LOCAL_MECHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Fonts] 记录的字体
4)加载 【HKEY_CURRENT_USER\\Software\\Wine\\Fonts】的字体
2、如果[HKEY_CURRENT_USER\\Software\\Wine\\Fonts\\External Fonts] 键值已经存在,则根据这里面进行加载。
3、加载[HKEY_LOCAL_MECHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes]的字体
4、加载[HKEY_CURRENT_USER\\Software\\Wine\\Fonts\\Replacements]的字体
第六步,根据已加载的字体更新以下注册表键值
[HKEY_LOCAL_MECHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts]的字体
[HKEY_LOCAL_MECHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Fonts]的字体
[HKEY_CURRENT_USER\\Software\\Wine\\Fonts\\External Fonts]的字体
第七步,初始化 SystemLink