gdi32: Move the font cache out of freetype.c.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
a84c60ed2a
commit
19d13d0004
|
@ -44,6 +44,7 @@
|
|||
WINE_DEFAULT_DEBUG_CHANNEL(font);
|
||||
|
||||
static HKEY wine_fonts_key;
|
||||
static HKEY wine_fonts_cache_key;
|
||||
|
||||
struct font_physdev
|
||||
{
|
||||
|
@ -64,6 +65,8 @@ static UINT font_smoothing = GGO_BITMAP;
|
|||
static UINT subpixel_orientation = GGO_GRAY4_BITMAP;
|
||||
static BOOL antialias_fakes = TRUE;
|
||||
|
||||
static void remove_face_from_cache( struct gdi_font_face *face );
|
||||
|
||||
/* Device -> World size conversion */
|
||||
|
||||
/* Performs a device to world transformation on the specified width (which
|
||||
|
@ -769,6 +772,287 @@ struct gdi_font_face *create_face( const WCHAR *style, const WCHAR *fullname, co
|
|||
return face;
|
||||
}
|
||||
|
||||
void release_face( struct gdi_font_face *face )
|
||||
{
|
||||
if (--face->refcount) return;
|
||||
if (face->family)
|
||||
{
|
||||
if (face->flags & ADDFONT_ADD_TO_CACHE) remove_face_from_cache( face );
|
||||
list_remove( &face->entry );
|
||||
release_family( face->family );
|
||||
}
|
||||
HeapFree( GetProcessHeap(), 0, face->file );
|
||||
HeapFree( GetProcessHeap(), 0, face->style_name );
|
||||
HeapFree( GetProcessHeap(), 0, face->full_name );
|
||||
HeapFree( GetProcessHeap(), 0, face->cached_enum_data );
|
||||
HeapFree( GetProcessHeap(), 0, face );
|
||||
}
|
||||
|
||||
static inline BOOL faces_equal( const struct gdi_font_face *f1, const struct gdi_font_face *f2 )
|
||||
{
|
||||
if (strcmpiW( f1->full_name, f2->full_name )) return FALSE;
|
||||
if (f1->scalable) return TRUE;
|
||||
if (f1->size.y_ppem != f2->size.y_ppem) return FALSE;
|
||||
return !memcmp( &f1->fs, &f2->fs, sizeof(f1->fs) );
|
||||
}
|
||||
|
||||
static inline int style_order( const struct gdi_font_face *face )
|
||||
{
|
||||
switch (face->ntmFlags & (NTM_REGULAR | NTM_BOLD | NTM_ITALIC))
|
||||
{
|
||||
case NTM_REGULAR:
|
||||
return 0;
|
||||
case NTM_BOLD:
|
||||
return 1;
|
||||
case NTM_ITALIC:
|
||||
return 2;
|
||||
case NTM_BOLD | NTM_ITALIC:
|
||||
return 3;
|
||||
default:
|
||||
WARN( "Don't know how to order face %s with flags 0x%08x\n",
|
||||
debugstr_w(face->full_name), face->ntmFlags );
|
||||
return 9999;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL insert_face_in_family_list( struct gdi_font_face *face, struct gdi_font_family *family )
|
||||
{
|
||||
struct gdi_font_face *cursor;
|
||||
|
||||
LIST_FOR_EACH_ENTRY( cursor, &family->faces, struct gdi_font_face, entry )
|
||||
{
|
||||
if (faces_equal( face, cursor ))
|
||||
{
|
||||
TRACE( "Already loaded face %s in family %s, original version %x, new version %x\n",
|
||||
debugstr_w(face->full_name), debugstr_w(family->family_name),
|
||||
cursor->version, face->version );
|
||||
|
||||
if (face->file && !strcmpiW( face->file, cursor->file ))
|
||||
{
|
||||
cursor->refcount++;
|
||||
TRACE("Font %s already in list, refcount now %d\n",
|
||||
debugstr_w(face->file), cursor->refcount);
|
||||
return FALSE;
|
||||
}
|
||||
if (face->version <= cursor->version)
|
||||
{
|
||||
TRACE("Original font %s is newer so skipping %s\n",
|
||||
debugstr_w(cursor->file), debugstr_w(face->file));
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE("Replacing original %s with %s\n",
|
||||
debugstr_w(cursor->file), debugstr_w(face->file));
|
||||
list_add_before( &cursor->entry, &face->entry );
|
||||
face->family = family;
|
||||
family->refcount++;
|
||||
face->refcount++;
|
||||
release_face( cursor );
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
if (style_order( face ) < style_order( cursor )) break;
|
||||
}
|
||||
|
||||
TRACE( "Adding face %s in family %s from %s\n", debugstr_w(face->full_name),
|
||||
debugstr_w(family->family_name), debugstr_w(face->file) );
|
||||
list_add_before( &cursor->entry, &face->entry );
|
||||
face->family = family;
|
||||
family->refcount++;
|
||||
face->refcount++;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* font cache */
|
||||
|
||||
struct cached_face
|
||||
{
|
||||
DWORD index;
|
||||
DWORD flags;
|
||||
DWORD ntmflags;
|
||||
DWORD version;
|
||||
struct bitmap_font_size size;
|
||||
FONTSIGNATURE fs;
|
||||
WCHAR full_name[1];
|
||||
/* WCHAR file_name[]; */
|
||||
};
|
||||
|
||||
static void load_face_from_cache( HKEY hkey_family, struct gdi_font_family *family,
|
||||
void *buffer, DWORD buffer_size, BOOL scalable )
|
||||
{
|
||||
DWORD type, size, needed, index = 0;
|
||||
struct gdi_font_face *face;
|
||||
HKEY hkey_strike;
|
||||
WCHAR name[256];
|
||||
struct cached_face *cached = (struct cached_face *)buffer;
|
||||
|
||||
size = sizeof(name);
|
||||
needed = buffer_size - sizeof(DWORD);
|
||||
while (!RegEnumValueW( hkey_family, index++, name, &size, NULL, &type, buffer, &needed ))
|
||||
{
|
||||
if (type == REG_BINARY && needed > sizeof(*cached))
|
||||
{
|
||||
((DWORD *)buffer)[needed / sizeof(DWORD)] = 0;
|
||||
|
||||
face = create_face( name, cached->full_name, cached->full_name + strlenW(cached->full_name) + 1,
|
||||
cached->index, cached->fs, cached->ntmflags, cached->version,
|
||||
cached->flags, scalable ? NULL : &cached->size );
|
||||
if (!scalable)
|
||||
TRACE("Adding bitmap size h %d w %d size %d x_ppem %d y_ppem %d\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]);
|
||||
|
||||
insert_face_in_family_list( face, family );
|
||||
release_face( face );
|
||||
}
|
||||
size = sizeof(name);
|
||||
needed = buffer_size - sizeof(DWORD);
|
||||
}
|
||||
|
||||
/* load bitmap strikes */
|
||||
|
||||
index = 0;
|
||||
needed = buffer_size;
|
||||
while (!RegEnumKeyExW( hkey_family, index++, buffer, &needed, NULL, NULL, NULL, NULL ))
|
||||
{
|
||||
if (!RegOpenKeyExW( hkey_family, buffer, 0, KEY_ALL_ACCESS, &hkey_strike ))
|
||||
{
|
||||
load_face_from_cache( hkey_strike, family, buffer, buffer_size, FALSE );
|
||||
RegCloseKey( hkey_strike );
|
||||
}
|
||||
needed = buffer_size;
|
||||
}
|
||||
}
|
||||
|
||||
/* move vertical fonts after their horizontal counterpart */
|
||||
/* assumes that font_list is already sorted by family name */
|
||||
static void reorder_vertical_fonts(void)
|
||||
{
|
||||
struct gdi_font_family *family, *next, *vert_family;
|
||||
struct list *ptr, *vptr;
|
||||
struct list vertical_families = LIST_INIT( vertical_families );
|
||||
|
||||
LIST_FOR_EACH_ENTRY_SAFE( family, next, &font_list, struct gdi_font_family, entry )
|
||||
{
|
||||
if (family->family_name[0] != '@') continue;
|
||||
list_remove( &family->entry );
|
||||
list_add_tail( &vertical_families, &family->entry );
|
||||
}
|
||||
|
||||
ptr = list_head( &font_list );
|
||||
vptr = list_head( &vertical_families );
|
||||
while (ptr && vptr)
|
||||
{
|
||||
family = LIST_ENTRY( ptr, struct gdi_font_family, entry );
|
||||
vert_family = LIST_ENTRY( vptr, struct gdi_font_family, entry );
|
||||
if (strcmpiW( family->family_name, vert_family->family_name + 1 ) > 0)
|
||||
{
|
||||
list_remove( vptr );
|
||||
list_add_before( ptr, vptr );
|
||||
vptr = list_head( &vertical_families );
|
||||
}
|
||||
else ptr = list_next( &font_list, ptr );
|
||||
}
|
||||
list_move_tail( &font_list, &vertical_families );
|
||||
}
|
||||
|
||||
static void load_font_list_from_cache(void)
|
||||
{
|
||||
DWORD size, family_index = 0;
|
||||
struct gdi_font_family *family;
|
||||
HKEY hkey_family;
|
||||
WCHAR buffer[4096], second_name[LF_FACESIZE];
|
||||
|
||||
size = sizeof(buffer);
|
||||
while (!RegEnumKeyExW( wine_fonts_cache_key, family_index++, buffer, &size, NULL, NULL, NULL, NULL ))
|
||||
{
|
||||
RegOpenKeyExW( wine_fonts_cache_key, buffer, 0, KEY_ALL_ACCESS, &hkey_family );
|
||||
TRACE("opened family key %s\n", debugstr_w(buffer));
|
||||
size = sizeof(second_name);
|
||||
if (RegQueryValueExW( hkey_family, NULL, NULL, NULL, (BYTE *)second_name, &size ))
|
||||
second_name[0] = 0;
|
||||
|
||||
family = create_family( buffer, second_name );
|
||||
|
||||
load_face_from_cache( hkey_family, family, buffer, sizeof(buffer), TRUE );
|
||||
|
||||
RegCloseKey( hkey_family );
|
||||
release_family( family );
|
||||
size = sizeof(buffer);
|
||||
}
|
||||
|
||||
reorder_vertical_fonts();
|
||||
}
|
||||
|
||||
void add_face_to_cache( struct gdi_font_face *face )
|
||||
{
|
||||
HKEY hkey_family, hkey_face;
|
||||
DWORD len, buffer[1024];
|
||||
struct cached_face *cached = (struct cached_face *)buffer;
|
||||
|
||||
if (RegCreateKeyExW( wine_fonts_cache_key, face->family->family_name, 0, NULL, REG_OPTION_VOLATILE,
|
||||
KEY_ALL_ACCESS, NULL, &hkey_family, NULL ))
|
||||
return;
|
||||
|
||||
if (face->family->second_name[0])
|
||||
RegSetValueExW( hkey_family, NULL, 0, REG_SZ, (BYTE *)face->family->second_name,
|
||||
(strlenW( face->family->second_name ) + 1) * sizeof(WCHAR) );
|
||||
|
||||
if (!face->scalable)
|
||||
{
|
||||
static const WCHAR fmtW[] = {'%','d',0};
|
||||
WCHAR name[10];
|
||||
|
||||
sprintfW( name, fmtW, face->size.y_ppem );
|
||||
RegCreateKeyExW( hkey_family, name, 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS,
|
||||
NULL, &hkey_face, NULL);
|
||||
}
|
||||
else hkey_face = hkey_family;
|
||||
|
||||
memset( cached, 0, sizeof(*cached) );
|
||||
cached->index = face->face_index;
|
||||
cached->flags = face->flags;
|
||||
cached->ntmflags = face->ntmFlags;
|
||||
cached->version = face->version;
|
||||
cached->fs = face->fs;
|
||||
if (!face->scalable) cached->size = face->size;
|
||||
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 );
|
||||
}
|
||||
|
||||
static void remove_face_from_cache( struct gdi_font_face *face )
|
||||
{
|
||||
HKEY hkey_family;
|
||||
|
||||
if (RegOpenKeyExW( wine_fonts_cache_key, face->family->family_name, 0, KEY_ALL_ACCESS, &hkey_family ))
|
||||
return;
|
||||
|
||||
if (!face->scalable)
|
||||
{
|
||||
static const WCHAR fmtW[] = {'%','d',0};
|
||||
WCHAR name[10];
|
||||
sprintfW( name, fmtW, face->size.y_ppem );
|
||||
RegDeleteKeyW( hkey_family, name );
|
||||
}
|
||||
else RegDeleteValueW( hkey_family, face->style_name );
|
||||
|
||||
RegCloseKey( hkey_family );
|
||||
}
|
||||
|
||||
/* font links */
|
||||
|
||||
static struct list font_links = LIST_INIT(font_links);
|
||||
|
@ -3240,6 +3524,7 @@ void font_init(void)
|
|||
{
|
||||
static const WCHAR mutex_nameW[] = {'_','_','W','I','N','E','_','F','O','N','T','_','M','U','T','E','X','_','_',0};
|
||||
HANDLE mutex;
|
||||
DWORD disposition;
|
||||
|
||||
if (RegCreateKeyExA( HKEY_CURRENT_USER, "Software\\Wine\\Fonts", 0, NULL, 0,
|
||||
KEY_ALL_ACCESS, NULL, &wine_fonts_key, NULL ))
|
||||
|
@ -3251,7 +3536,13 @@ void font_init(void)
|
|||
|
||||
if (!(mutex = CreateMutexW( NULL, FALSE, mutex_nameW ))) return;
|
||||
WaitForSingleObject( mutex, INFINITE );
|
||||
font_funcs->load_fonts();
|
||||
|
||||
RegCreateKeyExA( wine_fonts_key, "Cache", 0, NULL, REG_OPTION_VOLATILE,
|
||||
KEY_ALL_ACCESS, NULL, &wine_fonts_cache_key, &disposition );
|
||||
|
||||
if (disposition == REG_CREATED_NEW_KEY) font_funcs->load_fonts();
|
||||
else load_font_list_from_cache();
|
||||
|
||||
ReleaseMutex( mutex );
|
||||
|
||||
reorder_font_list();
|
||||
|
|
|
@ -265,12 +265,6 @@ static const WCHAR external_fonts_reg_key[] = {'S','o','f','t','w','a','r','e','
|
|||
|
||||
static const WCHAR SymbolW[] = {'S','y','m','b','o','l','\0'};
|
||||
|
||||
/* Registry font cache key and value names */
|
||||
static const WCHAR wine_fonts_key[] = {'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\',
|
||||
'F','o','n','t','s',0};
|
||||
static const WCHAR wine_fonts_cache_key[] = {'C','a','c','h','e',0};
|
||||
|
||||
|
||||
struct font_mapping
|
||||
{
|
||||
struct list entry;
|
||||
|
@ -284,11 +278,9 @@ struct font_mapping
|
|||
static struct list mappings_list = LIST_INIT( mappings_list );
|
||||
|
||||
static UINT default_aa_flags;
|
||||
static HKEY hkey_font_cache;
|
||||
|
||||
static BOOL CDECL freetype_set_outline_text_metrics( struct gdi_font *font );
|
||||
static BOOL CDECL freetype_set_bitmap_text_metrics( struct gdi_font *font );
|
||||
static void remove_face_from_cache( Face *face );
|
||||
|
||||
/****************************************
|
||||
* Notes on .fon files
|
||||
|
@ -884,311 +876,6 @@ static WCHAR *ft_face_get_full_name( FT_Face ft_face, LANGID langid )
|
|||
return full_name;
|
||||
}
|
||||
|
||||
static inline BOOL faces_equal( const Face *f1, const Face *f2 )
|
||||
{
|
||||
if (strcmpiW( f1->full_name, f2->full_name )) return FALSE;
|
||||
if (f1->scalable) return TRUE;
|
||||
if (f1->size.y_ppem != f2->size.y_ppem) return FALSE;
|
||||
return !memcmp( &f1->fs, &f2->fs, sizeof(f1->fs) );
|
||||
}
|
||||
|
||||
static void release_face( Face *face )
|
||||
{
|
||||
if (--face->refcount) return;
|
||||
if (face->family)
|
||||
{
|
||||
if (face->flags & ADDFONT_ADD_TO_CACHE) remove_face_from_cache( face );
|
||||
list_remove( &face->entry );
|
||||
release_family( face->family );
|
||||
}
|
||||
HeapFree( GetProcessHeap(), 0, face->file );
|
||||
HeapFree( GetProcessHeap(), 0, face->style_name );
|
||||
HeapFree( GetProcessHeap(), 0, face->full_name );
|
||||
HeapFree( GetProcessHeap(), 0, face->cached_enum_data );
|
||||
HeapFree( GetProcessHeap(), 0, face );
|
||||
}
|
||||
|
||||
static inline int style_order(const Face *face)
|
||||
{
|
||||
switch (face->ntmFlags & (NTM_REGULAR | NTM_BOLD | NTM_ITALIC))
|
||||
{
|
||||
case NTM_REGULAR:
|
||||
return 0;
|
||||
case NTM_BOLD:
|
||||
return 1;
|
||||
case NTM_ITALIC:
|
||||
return 2;
|
||||
case NTM_BOLD | NTM_ITALIC:
|
||||
return 3;
|
||||
default:
|
||||
WARN( "Don't know how to order face %s with flags 0x%08x\n", debugstr_w(face->full_name), face->ntmFlags );
|
||||
return 9999;
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL insert_face_in_family_list( Face *face, Family *family )
|
||||
{
|
||||
Face *cursor;
|
||||
|
||||
LIST_FOR_EACH_ENTRY( cursor, &family->faces, Face, entry )
|
||||
{
|
||||
if (faces_equal( face, cursor ))
|
||||
{
|
||||
TRACE( "Already loaded face %s in family %s, original version %x, new version %x\n",
|
||||
debugstr_w(face->full_name), debugstr_w(family->family_name),
|
||||
cursor->version, face->version );
|
||||
|
||||
if (face->file && !strcmpiW( face->file, cursor->file ))
|
||||
{
|
||||
cursor->refcount++;
|
||||
TRACE("Font %s already in list, refcount now %d\n",
|
||||
debugstr_w(face->file), cursor->refcount);
|
||||
return FALSE;
|
||||
}
|
||||
if (face->version <= cursor->version)
|
||||
{
|
||||
TRACE("Original font %s is newer so skipping %s\n",
|
||||
debugstr_w(cursor->file), debugstr_w(face->file));
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE("Replacing original %s with %s\n",
|
||||
debugstr_w(cursor->file), debugstr_w(face->file));
|
||||
list_add_before( &cursor->entry, &face->entry );
|
||||
face->family = family;
|
||||
family->refcount++;
|
||||
face->refcount++;
|
||||
release_face( cursor );
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (style_order( face ) < style_order( cursor )) break;
|
||||
}
|
||||
|
||||
TRACE( "Adding face %s in family %s from %s\n", debugstr_w(face->full_name),
|
||||
debugstr_w(family->family_name), debugstr_w(face->file) );
|
||||
list_add_before( &cursor->entry, &face->entry );
|
||||
face->family = family;
|
||||
family->refcount++;
|
||||
face->refcount++;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
struct cached_face
|
||||
{
|
||||
DWORD index;
|
||||
DWORD flags;
|
||||
DWORD ntmflags;
|
||||
DWORD version;
|
||||
struct bitmap_font_size size;
|
||||
FONTSIGNATURE fs;
|
||||
WCHAR full_name[1];
|
||||
/* WCHAR file_name[]; */
|
||||
};
|
||||
|
||||
static void load_face(HKEY hkey_family, Family *family, void *buffer, DWORD buffer_size, BOOL scalable)
|
||||
{
|
||||
DWORD type, size, needed, index = 0;
|
||||
Face *face;
|
||||
HKEY hkey_strike;
|
||||
WCHAR name[256];
|
||||
struct cached_face *cached = (struct cached_face *)buffer;
|
||||
|
||||
size = sizeof(name);
|
||||
needed = buffer_size - sizeof(DWORD);
|
||||
while (!RegEnumValueW( hkey_family, index++, name, &size, NULL, &type, buffer, &needed ))
|
||||
{
|
||||
if (type == REG_BINARY && needed > sizeof(*cached))
|
||||
{
|
||||
((DWORD *)buffer)[needed / sizeof(DWORD)] = 0;
|
||||
|
||||
face = create_face( name, cached->full_name, cached->full_name + strlenW(cached->full_name) + 1,
|
||||
cached->index, cached->fs, cached->ntmflags, cached->version,
|
||||
cached->flags, scalable ? NULL : &cached->size );
|
||||
if (!scalable)
|
||||
TRACE("Adding bitmap size h %d w %d size %d x_ppem %d y_ppem %d\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 );
|
||||
}
|
||||
size = sizeof(name);
|
||||
needed = buffer_size - sizeof(DWORD);
|
||||
}
|
||||
|
||||
/* load bitmap strikes */
|
||||
|
||||
index = 0;
|
||||
needed = buffer_size;
|
||||
while (!RegEnumKeyExW(hkey_family, index++, buffer, &needed, NULL, NULL, NULL, NULL))
|
||||
{
|
||||
if (!RegOpenKeyExW(hkey_family, buffer, 0, KEY_ALL_ACCESS, &hkey_strike))
|
||||
{
|
||||
load_face(hkey_strike, family, buffer, buffer_size, FALSE);
|
||||
RegCloseKey(hkey_strike);
|
||||
}
|
||||
needed = buffer_size;
|
||||
}
|
||||
}
|
||||
|
||||
/* move vertical fonts after their horizontal counterpart */
|
||||
/* assumes that font_list is already sorted by family name */
|
||||
static void reorder_vertical_fonts(void)
|
||||
{
|
||||
Family *family, *next, *vert_family;
|
||||
struct list *ptr, *vptr;
|
||||
struct list vertical_families = LIST_INIT( vertical_families );
|
||||
|
||||
LIST_FOR_EACH_ENTRY_SAFE( family, next, &font_list, Family, entry )
|
||||
{
|
||||
if (family->family_name[0] != '@') continue;
|
||||
list_remove( &family->entry );
|
||||
list_add_tail( &vertical_families, &family->entry );
|
||||
}
|
||||
|
||||
ptr = list_head( &font_list );
|
||||
vptr = list_head( &vertical_families );
|
||||
while (ptr && vptr)
|
||||
{
|
||||
family = LIST_ENTRY( ptr, Family, entry );
|
||||
vert_family = LIST_ENTRY( vptr, Family, entry );
|
||||
if (strcmpiW( family->family_name, vert_family->family_name + 1 ) > 0)
|
||||
{
|
||||
list_remove( vptr );
|
||||
list_add_before( ptr, vptr );
|
||||
vptr = list_head( &vertical_families );
|
||||
}
|
||||
else ptr = list_next( &font_list, ptr );
|
||||
}
|
||||
list_move_tail( &font_list, &vertical_families );
|
||||
}
|
||||
|
||||
static void load_font_list_from_cache(HKEY hkey_font_cache)
|
||||
{
|
||||
DWORD size, family_index = 0;
|
||||
Family *family;
|
||||
HKEY hkey_family;
|
||||
WCHAR buffer[4096];
|
||||
|
||||
size = sizeof(buffer);
|
||||
while (!RegEnumKeyExW(hkey_font_cache, family_index++, buffer, &size, NULL, NULL, NULL, NULL))
|
||||
{
|
||||
WCHAR *second_name = NULL;
|
||||
WCHAR *family_name = strdupW( buffer );
|
||||
|
||||
RegOpenKeyExW(hkey_font_cache, family_name, 0, KEY_ALL_ACCESS, &hkey_family);
|
||||
TRACE("opened family key %s\n", debugstr_w(family_name));
|
||||
size = sizeof(buffer);
|
||||
if (!RegQueryValueExW( hkey_family, NULL, NULL, NULL, (BYTE *)buffer, &size ))
|
||||
second_name = strdupW( buffer );
|
||||
|
||||
family = create_family( family_name, second_name );
|
||||
|
||||
load_face(hkey_family, family, buffer, sizeof(buffer), TRUE);
|
||||
|
||||
HeapFree( GetProcessHeap(), 0, family_name );
|
||||
HeapFree( GetProcessHeap(), 0, second_name );
|
||||
|
||||
RegCloseKey(hkey_family);
|
||||
release_family( family );
|
||||
size = sizeof(buffer);
|
||||
}
|
||||
|
||||
reorder_vertical_fonts();
|
||||
}
|
||||
|
||||
static LONG create_font_cache_key(HKEY *hkey, DWORD *disposition)
|
||||
{
|
||||
LONG ret;
|
||||
HKEY hkey_wine_fonts;
|
||||
|
||||
/* We don't want to create the fonts key as volatile, so open this first */
|
||||
ret = RegCreateKeyExW(HKEY_CURRENT_USER, wine_fonts_key, 0, NULL, 0,
|
||||
KEY_ALL_ACCESS, NULL, &hkey_wine_fonts, NULL);
|
||||
if(ret != ERROR_SUCCESS)
|
||||
{
|
||||
WARN("Can't create %s\n", debugstr_w(wine_fonts_key));
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = RegCreateKeyExW(hkey_wine_fonts, wine_fonts_cache_key, 0, NULL, REG_OPTION_VOLATILE,
|
||||
KEY_ALL_ACCESS, NULL, hkey, disposition);
|
||||
RegCloseKey(hkey_wine_fonts);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void add_face_to_cache(Face *face)
|
||||
{
|
||||
HKEY hkey_family, hkey_face;
|
||||
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,
|
||||
KEY_ALL_ACCESS, NULL, &hkey_family, NULL );
|
||||
if (face->family->second_name[0])
|
||||
RegSetValueExW( hkey_family, NULL, 0, REG_SZ, (BYTE *)face->family->second_name,
|
||||
(strlenW( face->family->second_name ) + 1) * sizeof(WCHAR) );
|
||||
|
||||
if (!face->scalable)
|
||||
{
|
||||
static const WCHAR fmtW[] = {'%','d',0};
|
||||
WCHAR name[10];
|
||||
|
||||
sprintfW( name, fmtW, face->size.y_ppem );
|
||||
RegCreateKeyExW( hkey_family, name, 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS,
|
||||
NULL, &hkey_face, NULL);
|
||||
}
|
||||
else hkey_face = hkey_family;
|
||||
|
||||
memset( cached, 0, sizeof(*cached) );
|
||||
cached->index = face->face_index;
|
||||
cached->flags = face->flags;
|
||||
cached->ntmflags = face->ntmFlags;
|
||||
cached->version = face->version;
|
||||
cached->fs = face->fs;
|
||||
if (!face->scalable) cached->size = face->size;
|
||||
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);
|
||||
}
|
||||
|
||||
static void remove_face_from_cache( Face *face )
|
||||
{
|
||||
HKEY hkey_family;
|
||||
|
||||
RegOpenKeyExW( hkey_font_cache, face->family->family_name, 0, KEY_ALL_ACCESS, &hkey_family );
|
||||
|
||||
if (face->scalable)
|
||||
{
|
||||
RegDeleteValueW( hkey_family, face->style_name );
|
||||
}
|
||||
else
|
||||
{
|
||||
static const WCHAR fmtW[] = {'%','d',0};
|
||||
WCHAR name[10];
|
||||
sprintfW( name, fmtW, face->size.y_ppem );
|
||||
RegDeleteKeyW( hkey_family, name );
|
||||
}
|
||||
RegCloseKey(hkey_family);
|
||||
}
|
||||
|
||||
static WCHAR *get_vertical_name( WCHAR *name )
|
||||
{
|
||||
SIZE_T length;
|
||||
|
@ -2149,7 +1836,10 @@ sym_not_found:
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static void init_font_list(void)
|
||||
/*************************************************************
|
||||
* freetype_load_fonts
|
||||
*/
|
||||
static void CDECL freetype_load_fonts(void)
|
||||
{
|
||||
delete_external_font_keys();
|
||||
load_system_bitmap_fonts();
|
||||
|
@ -2163,24 +1853,8 @@ static void init_font_list(void)
|
|||
#elif defined(__ANDROID__)
|
||||
ReadFontDir("/system/fonts", TRUE);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
* freetype_load_fonts
|
||||
*/
|
||||
static void CDECL freetype_load_fonts(void)
|
||||
{
|
||||
DWORD disposition;
|
||||
|
||||
create_font_cache_key(&hkey_font_cache, &disposition);
|
||||
|
||||
if(disposition == REG_CREATED_NEW_KEY)
|
||||
init_font_list();
|
||||
else
|
||||
load_font_list_from_cache(hkey_font_cache);
|
||||
|
||||
if(disposition == REG_CREATED_NEW_KEY)
|
||||
update_reg_entries();
|
||||
update_reg_entries();
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
|
|
|
@ -463,6 +463,9 @@ extern struct gdi_font_family *find_family_from_any_name( const WCHAR *name ) DE
|
|||
extern struct gdi_font_face *create_face( const WCHAR *style, const WCHAR *fullname, const WCHAR *file,
|
||||
UINT index, FONTSIGNATURE fs, DWORD ntmflags,
|
||||
DWORD version, DWORD flags, const struct bitmap_font_size *size ) DECLSPEC_HIDDEN;
|
||||
extern void release_face( struct gdi_font_face *face ) DECLSPEC_HIDDEN;
|
||||
extern BOOL insert_face_in_family_list( struct gdi_font_face *face, struct gdi_font_family *family ) DECLSPEC_HIDDEN;
|
||||
extern void add_face_to_cache( struct gdi_font_face *face ) DECLSPEC_HIDDEN;
|
||||
|
||||
extern struct gdi_font_link *find_gdi_font_link( const WCHAR *name ) DECLSPEC_HIDDEN;
|
||||
extern struct gdi_font_family *find_family_from_font_links( const WCHAR *name, const WCHAR *subst,
|
||||
|
|
Loading…
Reference in New Issue