[vlc-commits] freetype: handle explicit font family fallback

Francois Cartegnie git at videolan.org
Tue Jul 21 16:07:15 CEST 2020


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Mon Jun 29 15:10:44 2020 +0200| [465bd111f1c9cdf53f4b8188676768981ba9d7fc] | committer: Francois Cartegnie

freetype: handle explicit font family fallback

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

 modules/text_renderer/freetype/freetype.h       |   2 +
 modules/text_renderer/freetype/platform_fonts.c | 143 ++++++++++++++++++++----
 2 files changed, 123 insertions(+), 22 deletions(-)

diff --git a/modules/text_renderer/freetype/freetype.h b/modules/text_renderer/freetype/freetype.h
index f1a7dbbc53..0e9eaa1860 100644
--- a/modules/text_renderer/freetype/freetype.h
+++ b/modules/text_renderer/freetype/freetype.h
@@ -40,6 +40,7 @@
 
 #include <vlc_text_style.h>                             /* text_style_t */
 #include <vlc_arrays.h>                                 /* vlc_dictionary_t */
+#include <vlc_vector.h>
 
 #include <ft2build.h>
 #include FT_FREETYPE_H
@@ -71,6 +72,7 @@ typedef uint32_t uni_char_t;
  * This structure is part of the video output thread descriptor.
  * It describes the freetype specific properties of an output thread.
  *****************************************************************************/
+typedef struct VLC_VECTOR(char *) fontfamilies_t;
 typedef struct vlc_family_t vlc_family_t;
 typedef struct
 {
diff --git a/modules/text_renderer/freetype/platform_fonts.c b/modules/text_renderer/freetype/platform_fonts.c
index 5051b0edc0..bead63e900 100644
--- a/modules/text_renderer/freetype/platform_fonts.c
+++ b/modules/text_renderer/freetype/platform_fonts.c
@@ -218,6 +218,21 @@ vlc_family_t *SearchFallbacks( filter_t *p_filter, vlc_family_t *p_fallbacks,
     return p_family;
 }
 
+static vlc_family_t *SearchFontByFamilyName( filter_t *p_filter,
+                                             vlc_family_t *p_list,
+                                             const char *psz_familyname,
+                                             uni_char_t codepoint )
+{
+    for( vlc_family_t *p = p_list; p; p = p->p_next )
+    {
+        if( !strcasecmp( p->psz_name, psz_familyname ) &&
+            p->p_fonts &&
+            GetFace( p_filter, p->p_fonts, codepoint ) )
+            return p;
+    }
+    return NULL;
+}
+
 static inline void AppendFont( vlc_font_t **pp_list, vlc_font_t *p_font )
 {
     while( *pp_list )
@@ -471,9 +486,56 @@ int ConvertToLiveSize( filter_t *p_filter, const text_style_t *p_style )
     return i_font_size;
 }
 
-static char * SelectFontWithFamilyFallback( filter_t *p_filter, const char *psz_name,
-                      const text_style_t *p_style,
-                      int *pi_idx, uni_char_t codepoint )
+static void TrimWhiteSpace( const char **pp, const char **ppend )
+{
+    for( ; *pp < *ppend ; ++(*pp) )
+        if( **pp != ' ' && **pp != '\t' )
+            break;
+    for( ; *ppend > *pp ; --(*ppend) )
+        if( *((*ppend)- 1) != ' ' && *((*ppend)- 1) != '\t' )
+            break;
+}
+
+static void AddSingleFamily( const char *psz_start,
+                             const char *psz_end,
+                             fontfamilies_t *families )
+{
+    TrimWhiteSpace( &psz_start, &psz_end );
+    /* basic unquote */
+    if( psz_end > psz_start &&
+        *psz_start == '"' && psz_end[-1] == '"' )
+    {
+        ++psz_start;
+        --psz_end;
+    }
+    if( psz_end > psz_start )
+    {
+        char *psz = strndup( psz_start, psz_end - psz_start );
+        if( psz )
+            vlc_vector_push( families, psz );
+    }
+}
+
+static void SplitIntoSingleFamily( const char *psz_spec, fontfamilies_t *families )
+{
+    if( !psz_spec )
+        return;
+
+    char *dup = strdup( psz_spec );
+    char *p_savetpr;
+    for ( const char *psz = strtok_r( dup, ",", &p_savetpr );
+          psz != NULL;
+          psz = strtok_r( NULL, ",", &p_savetpr ) )
+    {
+        AddSingleFamily( psz, psz + strlen( psz ), families );
+    }
+    free( dup );
+}
+
+static char* SelectFontWithFamilyFallback( filter_t *p_filter,
+                                    const fontfamilies_t *families,
+                                    const text_style_t *p_style,
+                                    int *pi_idx, uni_char_t codepoint )
 {
     filter_sys_t *p_sys = p_filter->p_sys;
 
@@ -484,18 +546,34 @@ static char * SelectFontWithFamilyFallback( filter_t *p_filter, const char *psz_
     if( codepoint )
     {
         vlc_family_t *p_fallbacks;
+        const char *psz_name;
         /*
          * Try regular face of the same family first.
          * It usually has the best coverage.
          */
-        p_family = p_sys->pf_get_family( p_filter, psz_name );
-        if( p_family && p_family->p_fonts &&
-            !GetFace( p_filter, p_temp->p_fonts, codepoint ) )
+        vlc_vector_foreach( psz_name, families )
         {
+            p_fallbacks = vlc_dictionary_value_for_key( &p_sys->fallback_map,
+                                                        FB_LIST_ATTACHMENTS );
+            if( p_fallbacks )
+            {
+                p_family = SearchFontByFamilyName( p_filter, p_fallbacks,
+                                                   psz_name, codepoint );
+                if( p_family )
+                    break;
+            }
+
+            p_family = p_sys->pf_get_family( p_filter, psz_name );
+            if( p_family && p_family->p_fonts &&
+                GetFace( p_filter, p_family->p_fonts, codepoint ) )
+            {
+                break;
+            }
+
             p_family = NULL;
         }
 
-        /* Try font attachments */
+        /* Try font attachments if not available locally */
         if( !p_family )
         {
             p_fallbacks = vlc_dictionary_value_for_key( &p_sys->fallback_map,
@@ -505,12 +583,19 @@ static char * SelectFontWithFamilyFallback( filter_t *p_filter, const char *psz_
         }
 
         /* Try system fallbacks */
-        if( p_sys->pf_get_fallbacks )
-        if( !p_family )
+        if( !p_family && p_sys->pf_get_fallbacks )
         {
-            p_fallbacks = p_sys->pf_get_fallbacks( p_filter, psz_name, codepoint );
-            if( p_fallbacks )
-                p_family = SearchFallbacks( p_filter, p_fallbacks, codepoint );
+            vlc_vector_foreach( psz_name, families )
+            {
+                p_fallbacks = p_sys->pf_get_fallbacks( p_filter, psz_name, codepoint );
+                if( p_fallbacks )
+                {
+                    p_family = SearchFallbacks( p_filter, p_fallbacks, codepoint );
+                    if( p_family && p_family->p_fonts )
+                        break;
+                }
+                p_family = NULL;
+            }
         }
 
         /* Try the default fallback list, if any */
@@ -543,25 +628,39 @@ static char * SelectFontWithFamilyFallback( filter_t *p_filter, const char *psz_
 FT_Face SelectAndLoadFace( filter_t *p_filter, const text_style_t *p_style,
                            uni_char_t codepoint )
 {
-    const char *psz_family = (p_style->i_style_flags & STYLE_MONOSPACED)
-                           ? p_style->psz_monofontname : p_style->psz_fontname;
+    const char *psz_fontname = (p_style->i_style_flags & STYLE_MONOSPACED)
+                               ? p_style->psz_monofontname : p_style->psz_fontname;
+
+    fontfamilies_t families;
+    vlc_vector_init( &families );
+    SplitIntoSingleFamily( psz_fontname, &families );
+    if( families.size == 0 )
+    {
+        vlc_vector_clear( &families );
+        return NULL;
+    }
+
     FT_Face p_face = NULL;
-    int  i_idx = 0;
 
+    int  i_idx = 0;
     char *psz_fontfile =
-            SelectFontWithFamilyFallback( p_filter, psz_family, p_style,
+            SelectFontWithFamilyFallback( p_filter, &families, p_style,
                                           &i_idx, codepoint );
-    if( !psz_fontfile || *psz_fontfile == '\0' )
+    if( psz_fontfile && *psz_fontfile != '\0' )
+    {
+        p_face = LoadFace( p_filter, psz_fontfile, i_idx, p_style );
+    }
+    else
     {
         msg_Warn( p_filter,
                   "SelectAndLoadFace: no font found for family: %s, codepoint: 0x%x",
-                  psz_family, codepoint );
-        goto end;
+                  psz_fontname, codepoint );
     }
 
-    p_face = LoadFace( p_filter, psz_fontfile, i_idx, p_style );
-
-end:
+    char *psz_temp;
+    vlc_vector_foreach( psz_temp, &families )
+        free( psz_temp );
+    vlc_vector_clear( &families );
     free( psz_fontfile );
     return p_face;
 }



More information about the vlc-commits mailing list