gdi32: Store face data as a single binary value in the registry cache.
This is faster than a bunch of separate string values. Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
14395c8535
commit
b6c099cda6
|
@ -572,20 +572,6 @@ typedef struct tagFontSubst {
|
||||||
static const WCHAR wine_fonts_key[] = {'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\',
|
static const WCHAR wine_fonts_key[] = {'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\',
|
||||||
'F','o','n','t','s',0};
|
'F','o','n','t','s',0};
|
||||||
static const WCHAR wine_fonts_cache_key[] = {'C','a','c','h','e',0};
|
static const WCHAR wine_fonts_cache_key[] = {'C','a','c','h','e',0};
|
||||||
static const WCHAR second_name_value[] = {'S','e','c','o','n','d',' ','N','a','m','e',0};
|
|
||||||
static const WCHAR face_index_value[] = {'I','n','d','e','x',0};
|
|
||||||
static const WCHAR face_ntmflags_value[] = {'N','t','m','f','l','a','g','s',0};
|
|
||||||
static const WCHAR face_version_value[] = {'V','e','r','s','i','o','n',0};
|
|
||||||
static const WCHAR face_height_value[] = {'H','e','i','g','h','t',0};
|
|
||||||
static const WCHAR face_width_value[] = {'W','i','d','t','h',0};
|
|
||||||
static const WCHAR face_size_value[] = {'S','i','z','e',0};
|
|
||||||
static const WCHAR face_x_ppem_value[] = {'X','p','p','e','m',0};
|
|
||||||
static const WCHAR face_y_ppem_value[] = {'Y','p','p','e','m',0};
|
|
||||||
static const WCHAR face_flags_value[] = {'F','l','a','g','s',0};
|
|
||||||
static const WCHAR face_internal_leading_value[] = {'I','n','t','e','r','n','a','l',' ','L','e','a','d','i','n','g',0};
|
|
||||||
static const WCHAR face_font_sig_value[] = {'F','o','n','t',' ','S','i','g','n','a','t','u','r','e',0};
|
|
||||||
static const WCHAR face_file_name_value[] = {'F','i','l','e',' ','N','a','m','e','\0'};
|
|
||||||
static const WCHAR face_full_name_value[] = {'F','u','l','l',' ','N','a','m','e','\0'};
|
|
||||||
|
|
||||||
|
|
||||||
struct font_mapping
|
struct font_mapping
|
||||||
|
@ -1627,115 +1613,86 @@ static Family *create_family( WCHAR *family_name, WCHAR *second_name )
|
||||||
return family;
|
return family;
|
||||||
}
|
}
|
||||||
|
|
||||||
static LONG reg_load_dword(HKEY hkey, const WCHAR *value, DWORD *data)
|
struct cached_face
|
||||||
{
|
{
|
||||||
DWORD type, size = sizeof(DWORD);
|
DWORD index;
|
||||||
|
DWORD flags;
|
||||||
|
DWORD ntmflags;
|
||||||
|
DWORD version;
|
||||||
|
DWORD width;
|
||||||
|
DWORD height;
|
||||||
|
DWORD size;
|
||||||
|
DWORD x_ppem;
|
||||||
|
DWORD y_ppem;
|
||||||
|
DWORD internal_leading;
|
||||||
|
FONTSIGNATURE fs;
|
||||||
|
WCHAR full_name[1];
|
||||||
|
/* WCHAR file_name[]; */
|
||||||
|
};
|
||||||
|
|
||||||
if (RegQueryValueExW(hkey, value, NULL, &type, (BYTE *)data, &size) ||
|
static void load_face(HKEY hkey_family, Family *family, void *buffer, DWORD buffer_size, BOOL scalable)
|
||||||
type != REG_DWORD || size != sizeof(DWORD))
|
|
||||||
{
|
|
||||||
*data = 0;
|
|
||||||
return ERROR_BAD_CONFIGURATION;
|
|
||||||
}
|
|
||||||
return ERROR_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline LONG reg_load_ftlong(HKEY hkey, const WCHAR *value, FT_Long *data)
|
|
||||||
{
|
{
|
||||||
DWORD dw;
|
DWORD type, size, needed, index = 0;
|
||||||
LONG ret = reg_load_dword(hkey, value, &dw);
|
Face *face;
|
||||||
*data = dw;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline LONG reg_load_ftshort(HKEY hkey, const WCHAR *value, FT_Short *data)
|
|
||||||
{
|
|
||||||
DWORD dw;
|
|
||||||
LONG ret = reg_load_dword(hkey, value, &dw);
|
|
||||||
*data = dw;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline LONG reg_save_dword(HKEY hkey, const WCHAR *value, DWORD data)
|
|
||||||
{
|
|
||||||
return RegSetValueExW(hkey, value, 0, REG_DWORD, (BYTE*)&data, sizeof(DWORD));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void load_face(HKEY hkey_face, WCHAR *face_name, Family *family, void *buffer, DWORD buffer_size)
|
|
||||||
{
|
|
||||||
DWORD needed, strike_index = 0;
|
|
||||||
HKEY hkey_strike;
|
HKEY hkey_strike;
|
||||||
|
WCHAR name[256];
|
||||||
|
struct cached_face *cached = (struct cached_face *)buffer;
|
||||||
|
|
||||||
/* If we have a File Name key then this is a real font, not just the parent
|
size = sizeof(name);
|
||||||
key of a bunch of non-scalable strikes */
|
needed = buffer_size - sizeof(DWORD);
|
||||||
needed = buffer_size;
|
while (!RegEnumValueW( hkey_family, index++, name, &size, NULL, &type, buffer, &needed ))
|
||||||
if (RegQueryValueExW(hkey_face, face_file_name_value, NULL, NULL, buffer, &needed) == ERROR_SUCCESS)
|
|
||||||
{
|
{
|
||||||
Face *face;
|
if (type == REG_BINARY && needed > sizeof(*cached))
|
||||||
face = HeapAlloc(GetProcessHeap(), 0, sizeof(*face));
|
|
||||||
face->cached_enum_data = NULL;
|
|
||||||
face->family = NULL;
|
|
||||||
|
|
||||||
face->refcount = 1;
|
|
||||||
face->file = strdupW( buffer );
|
|
||||||
face->style_name = strdupW( face_name );
|
|
||||||
|
|
||||||
needed = buffer_size;
|
|
||||||
if (RegQueryValueExW( hkey_face, face_full_name_value, NULL, NULL, buffer, &needed ) != ERROR_SUCCESS)
|
|
||||||
{
|
{
|
||||||
ERR( "couldn't find full name for %s %s in cache\n", debugstr_w(family->family_name),
|
((DWORD *)buffer)[needed / sizeof(DWORD)] = 0;
|
||||||
debugstr_w(face->style_name) );
|
|
||||||
|
face = HeapAlloc(GetProcessHeap(), 0, sizeof(*face));
|
||||||
|
face->cached_enum_data = NULL;
|
||||||
|
face->family = NULL;
|
||||||
|
face->refcount = 1;
|
||||||
|
face->style_name = strdupW( name );
|
||||||
|
face->face_index = cached->index;
|
||||||
|
face->flags = cached->flags;
|
||||||
|
face->ntmFlags = cached->ntmflags;
|
||||||
|
face->font_version = cached->version;
|
||||||
|
face->size.width = cached->width;
|
||||||
|
face->size.height = cached->height;
|
||||||
|
face->size.size = cached->size;
|
||||||
|
face->size.x_ppem = cached->x_ppem;
|
||||||
|
face->size.y_ppem = cached->y_ppem;
|
||||||
|
face->size.internal_leading = cached->internal_leading;
|
||||||
|
face->fs = cached->fs;
|
||||||
|
face->full_name = strdupW( cached->full_name );
|
||||||
|
face->file = strdupW( cached->full_name + strlenW(cached->full_name) + 1 );
|
||||||
|
face->scalable = scalable;
|
||||||
|
if (!face->scalable)
|
||||||
|
TRACE("Adding bitmap size h %d w %d size %ld x_ppem %ld y_ppem %ld\n",
|
||||||
|
face->size.height, face->size.width, face->size.size >> 6,
|
||||||
|
face->size.x_ppem >> 6, face->size.y_ppem >> 6);
|
||||||
|
|
||||||
|
TRACE("fsCsb = %08x %08x/%08x %08x %08x %08x\n",
|
||||||
|
face->fs.fsCsb[0], face->fs.fsCsb[1],
|
||||||
|
face->fs.fsUsb[0], face->fs.fsUsb[1],
|
||||||
|
face->fs.fsUsb[2], face->fs.fsUsb[3]);
|
||||||
|
|
||||||
|
if (insert_face_in_family_list(face, family))
|
||||||
|
TRACE( "Added face %s to family %s\n", debugstr_w(face->full_name), debugstr_w(family->family_name) );
|
||||||
|
|
||||||
release_face( face );
|
release_face( face );
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
face->full_name = strdupW( buffer );
|
size = sizeof(name);
|
||||||
|
needed = buffer_size - sizeof(DWORD);
|
||||||
reg_load_ftlong(hkey_face, face_index_value, &face->face_index);
|
|
||||||
reg_load_dword(hkey_face, face_ntmflags_value, &face->ntmFlags);
|
|
||||||
reg_load_ftlong(hkey_face, face_version_value, &face->font_version);
|
|
||||||
reg_load_dword(hkey_face, face_flags_value, &face->flags);
|
|
||||||
|
|
||||||
needed = sizeof(face->fs);
|
|
||||||
RegQueryValueExW(hkey_face, face_font_sig_value, NULL, NULL, (BYTE*)&face->fs, &needed);
|
|
||||||
|
|
||||||
if(reg_load_ftshort(hkey_face, face_height_value, &face->size.height) != ERROR_SUCCESS)
|
|
||||||
{
|
|
||||||
face->scalable = TRUE;
|
|
||||||
memset(&face->size, 0, sizeof(face->size));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
face->scalable = FALSE;
|
|
||||||
reg_load_ftshort(hkey_face, face_width_value, &face->size.width);
|
|
||||||
reg_load_ftlong(hkey_face, face_size_value, &face->size.size);
|
|
||||||
reg_load_ftlong(hkey_face, face_x_ppem_value, &face->size.x_ppem);
|
|
||||||
reg_load_ftlong(hkey_face, face_y_ppem_value, &face->size.y_ppem);
|
|
||||||
reg_load_ftshort(hkey_face, face_internal_leading_value, &face->size.internal_leading);
|
|
||||||
|
|
||||||
TRACE("Adding bitmap size h %d w %d size %ld x_ppem %ld y_ppem %ld\n",
|
|
||||||
face->size.height, face->size.width, face->size.size >> 6,
|
|
||||||
face->size.x_ppem >> 6, face->size.y_ppem >> 6);
|
|
||||||
}
|
|
||||||
|
|
||||||
TRACE("fsCsb = %08x %08x/%08x %08x %08x %08x\n",
|
|
||||||
face->fs.fsCsb[0], face->fs.fsCsb[1],
|
|
||||||
face->fs.fsUsb[0], face->fs.fsUsb[1],
|
|
||||||
face->fs.fsUsb[2], face->fs.fsUsb[3]);
|
|
||||||
|
|
||||||
if (insert_face_in_family_list(face, family))
|
|
||||||
TRACE( "Added face %s to family %s\n", debugstr_w(face->full_name), debugstr_w(family->family_name) );
|
|
||||||
|
|
||||||
release_face( face );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* load bitmap strikes */
|
/* load bitmap strikes */
|
||||||
|
|
||||||
|
index = 0;
|
||||||
needed = buffer_size;
|
needed = buffer_size;
|
||||||
while (!RegEnumKeyExW(hkey_face, strike_index++, buffer, &needed, NULL, NULL, NULL, NULL))
|
while (!RegEnumKeyExW(hkey_family, index++, buffer, &needed, NULL, NULL, NULL, NULL))
|
||||||
{
|
{
|
||||||
if (!RegOpenKeyExW(hkey_face, buffer, 0, KEY_ALL_ACCESS, &hkey_strike))
|
if (!RegOpenKeyExW(hkey_family, buffer, 0, KEY_ALL_ACCESS, &hkey_strike))
|
||||||
{
|
{
|
||||||
load_face(hkey_strike, face_name, family, buffer, buffer_size);
|
load_face(hkey_strike, family, buffer, buffer_size, FALSE);
|
||||||
RegCloseKey(hkey_strike);
|
RegCloseKey(hkey_strike);
|
||||||
}
|
}
|
||||||
needed = buffer_size;
|
needed = buffer_size;
|
||||||
|
@ -1786,12 +1743,11 @@ static void load_font_list_from_cache(HKEY hkey_font_cache)
|
||||||
{
|
{
|
||||||
WCHAR *second_name = NULL;
|
WCHAR *second_name = NULL;
|
||||||
WCHAR *family_name = strdupW( buffer );
|
WCHAR *family_name = strdupW( buffer );
|
||||||
DWORD face_index = 0;
|
|
||||||
|
|
||||||
RegOpenKeyExW(hkey_font_cache, family_name, 0, KEY_ALL_ACCESS, &hkey_family);
|
RegOpenKeyExW(hkey_font_cache, family_name, 0, KEY_ALL_ACCESS, &hkey_family);
|
||||||
TRACE("opened family key %s\n", debugstr_w(family_name));
|
TRACE("opened family key %s\n", debugstr_w(family_name));
|
||||||
size = sizeof(buffer);
|
size = sizeof(buffer);
|
||||||
if (!RegQueryValueExW( hkey_family, second_name_value, NULL, NULL, (BYTE *)buffer, &size ))
|
if (!RegQueryValueExW( hkey_family, NULL, NULL, NULL, (BYTE *)buffer, &size ))
|
||||||
second_name = strdupW( buffer );
|
second_name = strdupW( buffer );
|
||||||
|
|
||||||
family = create_family( family_name, second_name );
|
family = create_family( family_name, second_name );
|
||||||
|
@ -1806,20 +1762,7 @@ static void load_font_list_from_cache(HKEY hkey_font_cache)
|
||||||
add_font_subst(&font_subst_list, subst, 0);
|
add_font_subst(&font_subst_list, subst, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
size = sizeof(buffer);
|
load_face(hkey_family, family, buffer, sizeof(buffer), TRUE);
|
||||||
while (!RegEnumKeyExW(hkey_family, face_index++, buffer, &size, NULL, NULL, NULL, NULL))
|
|
||||||
{
|
|
||||||
WCHAR *face_name = strdupW( buffer );
|
|
||||||
HKEY hkey_face;
|
|
||||||
|
|
||||||
if (!RegOpenKeyExW(hkey_family, face_name, 0, KEY_ALL_ACCESS, &hkey_face))
|
|
||||||
{
|
|
||||||
load_face(hkey_face, face_name, family, buffer, sizeof(buffer));
|
|
||||||
RegCloseKey(hkey_face);
|
|
||||||
}
|
|
||||||
HeapFree( GetProcessHeap(), 0, face_name );
|
|
||||||
size = sizeof(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
HeapFree( GetProcessHeap(), 0, family_name );
|
HeapFree( GetProcessHeap(), 0, family_name );
|
||||||
HeapFree( GetProcessHeap(), 0, second_name );
|
HeapFree( GetProcessHeap(), 0, second_name );
|
||||||
|
@ -1855,48 +1798,50 @@ static LONG create_font_cache_key(HKEY *hkey, DWORD *disposition)
|
||||||
static void add_face_to_cache(Face *face)
|
static void add_face_to_cache(Face *face)
|
||||||
{
|
{
|
||||||
HKEY hkey_family, hkey_face;
|
HKEY hkey_family, hkey_face;
|
||||||
WCHAR *face_key_name;
|
DWORD len, buffer[1024];
|
||||||
|
struct cached_face *cached = (struct cached_face *)buffer;
|
||||||
|
|
||||||
RegCreateKeyExW( hkey_font_cache, face->family->family_name, 0, NULL, REG_OPTION_VOLATILE,
|
RegCreateKeyExW( hkey_font_cache, face->family->family_name, 0, NULL, REG_OPTION_VOLATILE,
|
||||||
KEY_ALL_ACCESS, NULL, &hkey_family, NULL );
|
KEY_ALL_ACCESS, NULL, &hkey_family, NULL );
|
||||||
if (face->family->second_name[0])
|
if (face->family->second_name[0])
|
||||||
RegSetValueExW( hkey_family, second_name_value, 0, REG_SZ, (BYTE *)face->family->second_name,
|
RegSetValueExW( hkey_family, NULL, 0, REG_SZ, (BYTE *)face->family->second_name,
|
||||||
(strlenW( face->family->second_name ) + 1) * sizeof(WCHAR) );
|
(strlenW( face->family->second_name ) + 1) * sizeof(WCHAR) );
|
||||||
|
|
||||||
if (face->scalable) face_key_name = face->style_name;
|
if (!face->scalable)
|
||||||
else
|
|
||||||
{
|
{
|
||||||
static const WCHAR fmtW[] = {'%','s','\\','%','d',0};
|
static const WCHAR fmtW[] = {'%','d',0};
|
||||||
face_key_name = HeapAlloc( GetProcessHeap(), 0, (strlenW( face->style_name ) + 10) * sizeof(WCHAR) );
|
WCHAR name[10];
|
||||||
sprintfW( face_key_name, fmtW, face->style_name, face->size.y_ppem );
|
|
||||||
|
sprintfW( name, fmtW, face->size.y_ppem );
|
||||||
|
RegCreateKeyExW( hkey_family, name, 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS,
|
||||||
|
NULL, &hkey_face, NULL);
|
||||||
}
|
}
|
||||||
RegCreateKeyExW(hkey_family, face_key_name, 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL,
|
else hkey_face = hkey_family;
|
||||||
&hkey_face, NULL);
|
|
||||||
if(!face->scalable)
|
|
||||||
HeapFree(GetProcessHeap(), 0, face_key_name);
|
|
||||||
|
|
||||||
RegSetValueExW(hkey_face, face_file_name_value, 0, REG_SZ, (BYTE *)face->file,
|
memset( cached, 0, sizeof(*cached) );
|
||||||
(strlenW(face->file) + 1) * sizeof(WCHAR));
|
cached->index = face->face_index;
|
||||||
RegSetValueExW( hkey_face, face_full_name_value, 0, REG_SZ, (BYTE *)face->full_name,
|
cached->flags = face->flags;
|
||||||
(strlenW( face->full_name ) + 1) * sizeof(WCHAR) );
|
cached->ntmflags = face->ntmFlags;
|
||||||
|
cached->version = face->font_version;
|
||||||
reg_save_dword(hkey_face, face_index_value, face->face_index);
|
cached->fs = face->fs;
|
||||||
reg_save_dword(hkey_face, face_ntmflags_value, face->ntmFlags);
|
if (!face->scalable)
|
||||||
reg_save_dword(hkey_face, face_version_value, face->font_version);
|
|
||||||
if (face->flags) reg_save_dword(hkey_face, face_flags_value, face->flags);
|
|
||||||
|
|
||||||
RegSetValueExW(hkey_face, face_font_sig_value, 0, REG_BINARY, (BYTE*)&face->fs, sizeof(face->fs));
|
|
||||||
|
|
||||||
if(!face->scalable)
|
|
||||||
{
|
{
|
||||||
reg_save_dword(hkey_face, face_height_value, face->size.height);
|
cached->width = face->size.width;
|
||||||
reg_save_dword(hkey_face, face_width_value, face->size.width);
|
cached->height = face->size.height;
|
||||||
reg_save_dword(hkey_face, face_size_value, face->size.size);
|
cached->size = face->size.size;
|
||||||
reg_save_dword(hkey_face, face_x_ppem_value, face->size.x_ppem);
|
cached->x_ppem = face->size.x_ppem;
|
||||||
reg_save_dword(hkey_face, face_y_ppem_value, face->size.y_ppem);
|
cached->y_ppem = face->size.y_ppem;
|
||||||
reg_save_dword(hkey_face, face_internal_leading_value, face->size.internal_leading);
|
cached->internal_leading = face->size.internal_leading;
|
||||||
}
|
}
|
||||||
RegCloseKey(hkey_face);
|
strcpyW( cached->full_name, face->full_name );
|
||||||
|
len = strlenW( face->full_name ) + 1;
|
||||||
|
strcpyW( cached->full_name + len, face->file );
|
||||||
|
len += strlenW( face->file ) + 1;
|
||||||
|
|
||||||
|
RegSetValueExW( hkey_face, face->style_name, 0, REG_BINARY, (BYTE *)cached,
|
||||||
|
offsetof( struct cached_face, full_name[len] ));
|
||||||
|
|
||||||
|
if (hkey_face != hkey_family) RegCloseKey(hkey_face);
|
||||||
RegCloseKey(hkey_family);
|
RegCloseKey(hkey_family);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1908,15 +1853,14 @@ static void remove_face_from_cache( Face *face )
|
||||||
|
|
||||||
if (face->scalable)
|
if (face->scalable)
|
||||||
{
|
{
|
||||||
RegDeleteKeyW( hkey_family, face->style_name );
|
RegDeleteValueW( hkey_family, face->style_name );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
static const WCHAR fmtW[] = {'%','s','\\','%','d',0};
|
static const WCHAR fmtW[] = {'%','d',0};
|
||||||
WCHAR *face_key_name = HeapAlloc( GetProcessHeap(), 0, (strlenW( face->style_name ) + 10) * sizeof(WCHAR) );
|
WCHAR name[10];
|
||||||
sprintfW( face_key_name, fmtW, face->style_name, face->size.y_ppem );
|
sprintfW( name, fmtW, face->size.y_ppem );
|
||||||
RegDeleteKeyW( hkey_family, face_key_name );
|
RegDeleteKeyW( hkey_family, name );
|
||||||
HeapFree(GetProcessHeap(), 0, face_key_name);
|
|
||||||
}
|
}
|
||||||
RegCloseKey(hkey_family);
|
RegCloseKey(hkey_family);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue