Rémi Bernon : gdi32: Load font list directly from fontconfig cache.

Alexandre Julliard julliard at winehq.org
Fri Nov 20 14:54:32 CST 2020


Module: wine
Branch: master
Commit: a51d68e35c53f94f2af28ede3b008c5166b8f741
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=a51d68e35c53f94f2af28ede3b008c5166b8f741

Author: Rémi Bernon <rbernon at codeweavers.com>
Date:   Fri Nov 20 10:40:41 2020 +0000

gdi32: Load font list directly from fontconfig cache.

Instead of going through the -slow- font matching.

Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
Signed-off-by: Huw Davies <huw at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/gdi32/freetype.c | 169 +++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 125 insertions(+), 44 deletions(-)

diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c
index 45b5e94d341..7d8bc5f5b05 100644
--- a/dlls/gdi32/freetype.c
+++ b/dlls/gdi32/freetype.c
@@ -190,6 +190,20 @@ MAKE_FUNCPTR(FcPatternDestroy);
 MAKE_FUNCPTR(FcPatternGetBool);
 MAKE_FUNCPTR(FcPatternGetInteger);
 MAKE_FUNCPTR(FcPatternGetString);
+MAKE_FUNCPTR(FcConfigGetFontDirs);
+MAKE_FUNCPTR(FcConfigGetCurrent);
+MAKE_FUNCPTR(FcCacheCopySet);
+MAKE_FUNCPTR(FcCacheNumSubdir);
+MAKE_FUNCPTR(FcCacheSubdir);
+MAKE_FUNCPTR(FcDirCacheRead);
+MAKE_FUNCPTR(FcDirCacheUnload);
+MAKE_FUNCPTR(FcStrListCreate);
+MAKE_FUNCPTR(FcStrListDone);
+MAKE_FUNCPTR(FcStrListNext);
+MAKE_FUNCPTR(FcStrSetAdd);
+MAKE_FUNCPTR(FcStrSetCreate);
+MAKE_FUNCPTR(FcStrSetDestroy);
+MAKE_FUNCPTR(FcStrSetMember);
 #ifndef FC_NAMELANG
 #define FC_NAMELANG "namelang"
 #endif
@@ -1346,6 +1360,51 @@ static FcPattern *create_family_pattern( const char *name )
     return NULL;
 }
 
+static void fontconfig_add_font( FcPattern *pattern, DWORD flags )
+{
+    const char *unix_name, *format;
+    WCHAR *dos_name;
+    FcBool scalable;
+    DWORD aa_flags;
+    int face_index;
+
+    TRACE( "(%p %#x)\n", pattern, flags );
+
+    if (pFcPatternGetString( pattern, FC_FILE, 0, (FcChar8 **)&unix_name ) != FcResultMatch)
+        return;
+
+    if (pFcPatternGetBool( pattern, FC_SCALABLE, 0, &scalable ) != FcResultMatch)
+        scalable = FALSE;
+
+    if (pFcPatternGetString( pattern, FC_FONTFORMAT, 0, (FcChar8 **)&format ) != FcResultMatch)
+    {
+        TRACE( "ignoring unknown font format %s\n", debugstr_a(unix_name) );
+        return;
+    }
+
+    if (!strcmp( format, "Type 1" ))
+    {
+        TRACE( "ignoring Type 1 font %s\n", debugstr_a(unix_name) );
+        return;
+    }
+
+    if (!scalable && !(flags & ADDFONT_ALLOW_BITMAP))
+    {
+        TRACE( "ignoring non-scalable font %s\n", debugstr_a(unix_name) );
+        return;
+    }
+
+    if (!(aa_flags = parse_aa_pattern( pattern ))) aa_flags = default_aa_flags;
+    flags |= ADDFONT_AA_FLAGS(aa_flags);
+
+    if (pFcPatternGetInteger( pattern, FC_INDEX, 0, &face_index ) != FcResultMatch)
+        face_index = 0;
+
+    dos_name = get_dos_file_name( unix_name );
+    add_unix_face( unix_name, dos_name, NULL, 0, face_index, flags, NULL );
+    RtlFreeHeap( GetProcessHeap(), 0, dos_name );
+}
+
 static void init_fontconfig(void)
 {
     void *fc_handle = dlopen(SONAME_LIBFONTCONFIG, RTLD_NOW);
@@ -1369,6 +1428,20 @@ static void init_fontconfig(void)
     LOAD_FUNCPTR(FcPatternGetBool);
     LOAD_FUNCPTR(FcPatternGetInteger);
     LOAD_FUNCPTR(FcPatternGetString);
+    LOAD_FUNCPTR(FcConfigGetFontDirs);
+    LOAD_FUNCPTR(FcConfigGetCurrent);
+    LOAD_FUNCPTR(FcCacheCopySet);
+    LOAD_FUNCPTR(FcCacheNumSubdir);
+    LOAD_FUNCPTR(FcCacheSubdir);
+    LOAD_FUNCPTR(FcDirCacheRead);
+    LOAD_FUNCPTR(FcDirCacheUnload);
+    LOAD_FUNCPTR(FcStrListCreate);
+    LOAD_FUNCPTR(FcStrListDone);
+    LOAD_FUNCPTR(FcStrListNext);
+    LOAD_FUNCPTR(FcStrSetAdd);
+    LOAD_FUNCPTR(FcStrSetCreate);
+    LOAD_FUNCPTR(FcStrSetDestroy);
+    LOAD_FUNCPTR(FcStrSetMember);
 #undef LOAD_FUNCPTR
 
     if (pFcInit())
@@ -1394,61 +1467,69 @@ static void init_fontconfig(void)
     }
 }
 
-static void load_fontconfig_fonts(void)
+static void fontconfig_add_fonts_from_dir_list( FcConfig *config, FcStrList *dir_list, FcStrSet *done_set, DWORD flags )
 {
-    FcPattern *pat;
-    FcFontSet *fontset;
-    const char *format;
+    const FcChar8 *dir;
+    FcFontSet *font_set;
+    FcStrList *subdir_list = NULL;
+    FcStrSet *subdir_set = NULL;
+    FcCache *cache = NULL;
     int i;
-    char *file;
 
-    if (!fontconfig_enabled) return;
-
-    pat = pFcPatternCreate();
-    if (!pat) return;
+    TRACE( "(%p %p %p %#x)\n", config, dir_list, done_set, flags );
 
-    fontset = pFcFontList(NULL, pat, NULL);
-    if (!fontset)
+    while ((dir = pFcStrListNext( dir_list )))
     {
-        pFcPatternDestroy(pat);
-        return;
+        if (pFcStrSetMember( done_set, dir )) continue;
+
+        TRACE( "adding fonts from %s\n", dir );
+        if (!(cache = pFcDirCacheRead( dir, FcFalse, config ))) continue;
+
+        if (!(font_set = pFcCacheCopySet( cache ))) goto done;
+        for (i = 0; i < font_set->nfont; i++)
+            fontconfig_add_font( font_set->fonts[i], flags );
+        pFcFontSetDestroy( font_set );
+        font_set = NULL;
+
+        if (!(subdir_set = pFcStrSetCreate())) goto done;
+        for (i = 0; i < pFcCacheNumSubdir( cache ); i++)
+            pFcStrSetAdd( subdir_set, pFcCacheSubdir( cache, i ) );
+        pFcDirCacheUnload( cache );
+        cache = NULL;
+
+        if (!(subdir_list = pFcStrListCreate( subdir_set ))) goto done;
+        pFcStrSetDestroy( subdir_set );
+        subdir_set = NULL;
+
+        pFcStrSetAdd( done_set, dir );
+        fontconfig_add_fonts_from_dir_list( config, subdir_list, done_set, flags );
+        pFcStrListDone( subdir_list );
+        subdir_list = NULL;
     }
 
-    for(i = 0; i < fontset->nfont; i++) {
-        FcBool scalable;
-        DWORD aa_flags;
-
-        if(pFcPatternGetString(fontset->fonts[i], FC_FILE, 0, (FcChar8**)&file) != FcResultMatch)
-            continue;
-
-        pFcConfigSubstitute( NULL, fontset->fonts[i], FcMatchFont );
-
-        if(pFcPatternGetBool(fontset->fonts[i], FC_SCALABLE, 0, &scalable) == FcResultMatch && !scalable)
-        {
-            TRACE("not scalable\n");
-            continue;
-        }
+done:
+    if (font_set) pFcFontSetDestroy( font_set );
+    if (subdir_list) pFcStrListDone( subdir_list );
+    if (subdir_set) pFcStrSetDestroy( subdir_set );
+    if (cache) pFcDirCacheUnload( cache );
+}
 
-        if (pFcPatternGetString( fontset->fonts[i], FC_FONTFORMAT, 0, (FcChar8 **)&format ) != FcResultMatch)
-        {
-            TRACE( "ignoring unknown font format %s\n", debugstr_a(file) );
-            continue;
-        }
+static void load_fontconfig_fonts( void )
+{
+    FcStrList *dir_list = NULL;
+    FcStrSet *done_set = NULL;
+    FcConfig *config;
 
-        if (!strcmp( format, "Type 1" ))
-        {
-            TRACE( "ignoring Type 1 font %s\n", debugstr_a(file) );
-            continue;
-        }
+    if (!fontconfig_enabled) return;
+    if (!(config = pFcConfigGetCurrent())) goto done;
+    if (!(done_set = pFcStrSetCreate())) goto done;
+    if (!(dir_list = pFcConfigGetFontDirs( config ))) goto done;
 
-        aa_flags = parse_aa_pattern( fontset->fonts[i] );
-        TRACE("fontconfig: %s aa %x\n", file, aa_flags);
+    fontconfig_add_fonts_from_dir_list( config, dir_list, done_set, ADDFONT_EXTERNAL_FONT | ADDFONT_ADD_TO_CACHE );
 
-	AddFontToList( NULL, file, NULL, 0,
-		       ADDFONT_EXTERNAL_FONT | ADDFONT_ADD_TO_CACHE | ADDFONT_AA_FLAGS(aa_flags) );
-    }
-    pFcFontSetDestroy(fontset);
-    pFcPatternDestroy(pat);
+done:
+    if (dir_list) pFcStrListDone( dir_list );
+    if (done_set) pFcStrSetDestroy( done_set );
 }
 
 #elif defined(HAVE_CARBON_CARBON_H)




More information about the wine-cvs mailing list