[vlc-commits] freetype: use FcFontList instead of multiple FcMatch

Francois Cartegnie git at videolan.org
Mon Aug 24 17:38:59 CEST 2020


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Wed Aug  5 16:47:56 2020 +0200| [189cc0f03b32dbb5b423697c4eef7dfd75f23b8b] | committer: Francois Cartegnie

freetype: use FcFontList instead of multiple FcMatch

Better performance listing fonts with the previouly
matched family instead of criterion match

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=189cc0f03b32dbb5b423697c4eef7dfd75f23b8b
---

 modules/text_renderer/freetype/fonts/fontconfig.c | 185 +++++++++++++---------
 modules/text_renderer/freetype/platform_fonts.c   |   2 +-
 2 files changed, 115 insertions(+), 72 deletions(-)

diff --git a/modules/text_renderer/freetype/fonts/fontconfig.c b/modules/text_renderer/freetype/fonts/fontconfig.c
index fff08913f2..93a6253e0e 100644
--- a/modules/text_renderer/freetype/fonts/fontconfig.c
+++ b/modules/text_renderer/freetype/fonts/fontconfig.c
@@ -106,97 +106,140 @@ void FontConfig_Unprepare( vlc_font_select_t *fs )
     vlc_mutex_unlock( &lock );
 }
 
-int FontConfig_SelectAmongFamilies( vlc_font_select_t *fs, const fontfamilies_t *families,
-                                    const vlc_family_t **pp_result )
+static void FontConfig_AddFromFcPattern( FcPattern *p_pat,  vlc_family_t *p_family )
 {
-    vlc_family_t *p_family = NULL;
+    int bold;
+    int italic;
+    FcChar8* val_s;
+    int i_index = 0;
+    char *psz_fontfile = NULL;
+
+    if( FcResultMatch != FcPatternGetInteger( p_pat, FC_INDEX, 0, &i_index ) )
+        i_index = 0;
+
+    if( FcResultMatch != FcPatternGetInteger( p_pat, FC_WEIGHT, 0, &bold ) )
+        bold = FC_WEIGHT_NORMAL;
+    if( bold < FC_WEIGHT_NORMAL )
+        return;
+
+    if( FcResultMatch != FcPatternGetInteger( p_pat, FC_SLANT, 0, &italic ) )
+        italic = FC_SLANT_ROMAN;
+
+    if( FcResultMatch != FcPatternGetString( p_pat, FC_FILE, 0, &val_s ) )
+        return;
+
+    psz_fontfile = strdup( (const char*)val_s );
+    if( psz_fontfile )
+        NewFont( psz_fontfile, i_index,
+                 bold > FC_WEIGHT_NORMAL,
+                 italic != FC_SLANT_ROMAN,
+                 p_family );
+}
+
+static void FontConfig_FillFaces( vlc_family_t *p_family )
+{
+    FcPattern *pat = FcPatternCreate();
+    if ( !pat )
+        return;
 
-    for( int i = 0; i < 4; ++i ) /* Iterate through FC_{SLANT,WEIGHT} combos */
+    FcObjectSet *os = FcObjectSetBuild ( FC_FILE, FC_SLANT, FC_WEIGHT,
+                                         FC_INDEX, FC_WIDTH, (char *) 0 );
+    if( os )
     {
-        bool const b_bold = i & 1;
-        bool const b_italic = i & 2;
-
-        int i_index = 0;
-        FcResult result = FcResultMatch;
-        FcPattern *pat, *p_pat;
-        FcChar8* val_s;
-        FcBool val_b;
-        char *psz_fontfile = NULL;
-
-        /* Create a pattern and fill it */
-        pat = FcPatternCreate();
-        if (!pat) continue;
-
-        /* */
-        const char *psz_lcname;
-        vlc_vector_foreach( psz_lcname, &families->vec )
-            FcPatternAddString( pat, FC_FAMILY, (const FcChar8*) psz_lcname );
+        FcPatternAddString( pat, FC_FAMILY, (const FcChar8 *) p_family->psz_name );
         FcPatternAddBool( pat, FC_OUTLINE, FcTrue );
-        FcPatternAddInteger( pat, FC_SLANT, b_italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN );
-        FcPatternAddInteger( pat, FC_WEIGHT, b_bold ? FC_WEIGHT_EXTRABOLD : FC_WEIGHT_NORMAL );
-
-        /* */
-        FcDefaultSubstitute( pat );
-        if( !FcConfigSubstitute( config, pat, FcMatchPattern ) )
-        {
-            FcPatternDestroy( pat );
-            continue;
-        }
-
-        /* Find the best font for the pattern, destroy the pattern */
-        p_pat = FcFontMatch( config, pat, &result );
-        FcPatternDestroy( pat );
-        if( !p_pat || result == FcResultNoMatch ) continue;
-
-        if( FcResultMatch != FcPatternGetString( p_pat, FC_FAMILY, 0, &val_s ) )
-        {
-            FcPatternDestroy( p_pat );
-            continue;
-        }
 
-        if( !p_family )
+        FcFontSet *fs = FcFontList( 0, pat, os );
+        FcObjectSetDestroy( os );
+        if( fs )
         {
-            char *psz_fnlc = LowercaseDup((const char *)val_s);
-            p_family = vlc_dictionary_value_for_key( &fs->family_map, psz_fnlc );
-            if( p_family == kVLCDictionaryNotFound )
+            for( int pass=0; pass<2 && !p_family->p_fonts; pass++ )
             {
-                p_family = NewFamily( fs, psz_fnlc, &fs->p_families,
-                                      &fs->family_map, psz_fnlc );
-                if( !p_family )
+                for ( int i = 0; i < fs->nfont; i++ )
                 {
-                    free(psz_fnlc);
-                    FcPatternDestroy( pat );
-                    return VLC_ENOMEM;
+                    int i_width = 0;
+                    FcPattern *p_pat = fs->fonts[i];
+
+                    /* we relax the WIDTH condition if we did not get any match */
+                    if( pass == 0 &&
+                        FcResultMatch == FcPatternGetInteger( p_pat, FC_WIDTH, 0, &i_width ) &&
+                        i_width != FC_WIDTH_NORMAL )
+                        continue;
+
+                    FontConfig_AddFromFcPattern( p_pat, p_family );
                 }
             }
-            free(psz_fnlc);
+            FcFontSetDestroy( fs );
         }
+    }
+    FcPatternDestroy( pat );
+}
 
-        /* Check the new pattern */
-        if( ( FcResultMatch != FcPatternGetBool( p_pat, FC_OUTLINE, 0, &val_b ) )
-            || ( val_b != FcTrue ) )
-        {
-            FcPatternDestroy( p_pat );
-            continue;
-        }
+int FontConfig_SelectAmongFamilies( vlc_font_select_t *fs, const fontfamilies_t *families,
+                                    const vlc_family_t **pp_result )
+{
+    FcResult result = FcResultMatch;
+    FcPattern *pat, *p_matchpat;
+    FcChar8* val_s;
 
-        if( FcResultMatch != FcPatternGetInteger( p_pat, FC_INDEX, 0, &i_index ) )
-        {
-            i_index = 0;
-        }
+    /* Create a pattern and fill it */
+    pat = FcPatternCreate();
+    if (!pat)
+        return VLC_EGENERIC;
+
+    /* */
+    const char *psz_lcname;
+    vlc_vector_foreach( psz_lcname, &families->vec )
+        FcPatternAddString( pat, FC_FAMILY, (const FcChar8*) psz_lcname );
+    FcPatternAddBool( pat, FC_OUTLINE, FcTrue );
 
-        if( FcResultMatch == FcPatternGetString( p_pat, FC_FILE, 0, &val_s ) )
-            psz_fontfile = strdup( (const char*)val_s );
+    /* */
+    FcDefaultSubstitute( pat );
+    if( !FcConfigSubstitute( config, pat, FcMatchPattern ) )
+    {
+        FcPatternDestroy( pat );
+        return VLC_EGENERIC;
+    }
 
-        FcPatternDestroy( p_pat );
+    /* Find the best font for the pattern, destroy the pattern */
+    p_matchpat = FcFontMatch( config, pat, &result );
+    if( !p_matchpat )
+        return VLC_EGENERIC;
+    FcPatternDestroy( pat );
+    if( result == FcResultNoMatch )
+    {
+        *pp_result = NULL;
+        return VLC_SUCCESS;
+    }
 
-        if( !psz_fontfile )
-            continue;
+    if( FcResultMatch != FcPatternGetString( p_matchpat, FC_FAMILY, 0, &val_s ) )
+    {
+        FcPatternDestroy( p_matchpat );
+        return VLC_EGENERIC;
+    }
 
-        NewFont( psz_fontfile, i_index, b_bold, b_italic, p_family );
+    char *psz_fnlc = LowercaseDup((const char *)val_s);
+    vlc_family_t *p_family = vlc_dictionary_value_for_key( &fs->family_map, psz_fnlc );
+    if( p_family == kVLCDictionaryNotFound )
+    {
+        p_family = NewFamily( fs, psz_fnlc, &fs->p_families,
+                              &fs->family_map, psz_fnlc );
+        if( !p_family )
+        {
+            free( psz_fnlc );
+            FcPatternDestroy( p_matchpat );
+            return VLC_EGENERIC;
+        }
     }
 
+    free(psz_fnlc);
+    FcPatternDestroy( p_matchpat );
+
+    if( p_family ) /* Populate with fonts */
+        FontConfig_FillFaces( p_family );
+
     *pp_result = p_family;
+
     return VLC_SUCCESS;
 }
 
diff --git a/modules/text_renderer/freetype/platform_fonts.c b/modules/text_renderer/freetype/platform_fonts.c
index 67446f280f..8d601fd142 100644
--- a/modules/text_renderer/freetype/platform_fonts.c
+++ b/modules/text_renderer/freetype/platform_fonts.c
@@ -718,7 +718,7 @@ static char* SelectFontWithFamilyFallback( vlc_font_select_t *fs,
     if( p_family && ( p_font = GetBestFont( fs, p_family, b_bold,
                                             b_italic, codepoint ) ) )
     {
-        Debug( fs->p_obj, "Selected best font file \"%s\"", p_font->psz_fontfile );
+        Debug( fs->p_obj, "Selected best font file \"%s\" %d %d", p_font->psz_fontfile, b_bold, b_italic );
         *pi_idx = p_font->i_index;
         return strdup( p_font->psz_fontfile );
     }



More information about the vlc-commits mailing list