[vlc-devel] [PATCH 2/4] freetype: font fallback for Linux
Salah-Eddin Shaban
salshaaban at gmail.com
Thu Oct 22 13:53:48 CEST 2015
---
modules/text_renderer/freetype.c | 4 +-
modules/text_renderer/platform_fonts.c | 217 +++++++++++++++++++++++++--------
modules/text_renderer/platform_fonts.h | 7 +-
modules/text_renderer/text_layout.c | 5 +
4 files changed, 178 insertions(+), 55 deletions(-)
diff --git a/modules/text_renderer/freetype.c b/modules/text_renderer/freetype.c
index 95b045e..61b3ec5 100644
--- a/modules/text_renderer/freetype.c
+++ b/modules/text_renderer/freetype.c
@@ -1259,7 +1259,9 @@ static int Create( vlc_object_t *p_this )
goto error;
#ifdef HAVE_FONTCONFIG
- p_sys->pf_select = FontConfig_Select;
+ p_sys->pf_select = Generic_Select;
+ p_sys->pf_get_family = FontConfig_GetFamily;
+ p_sys->pf_get_fallbacks = FontConfig_GetFallbacks;
FontConfig_BuildCache( p_filter );
#elif defined( __APPLE__ )
#if !TARGET_OS_IPHONE
diff --git a/modules/text_renderer/platform_fonts.c b/modules/text_renderer/platform_fonts.c
index 1195272..93ccdf1 100644
--- a/modules/text_renderer/platform_fonts.c
+++ b/modules/text_renderer/platform_fonts.c
@@ -461,73 +461,190 @@ void FontConfig_BuildCache( filter_t *p_filter )
msg_Dbg( p_filter, "Took %ld microseconds", (long)((t2 - t1)) );
}
-/***
- * \brief Selects a font matching family, bold, italic provided
- ***/
-char* FontConfig_Select( filter_t *p_filter, const char* family,
- bool b_bold, bool b_italic,
- int *i_idx, uni_char_t codepoint )
+const vlc_family_t *FontConfig_GetFamily( filter_t *p_filter, const char *psz_family )
{
- FcResult result = FcResultMatch;
- FcPattern *pat, *p_pat;
- FcChar8* val_s;
- FcBool val_b;
- char *ret = NULL;
- FcConfig* config = NULL;
- VLC_UNUSED(p_filter);
- VLC_UNUSED(codepoint);
+ filter_sys_t *p_sys = p_filter->p_sys;
- /* Create a pattern and fills it */
- pat = FcPatternCreate();
- if (!pat) return NULL;
+ char *psz_lc = ToLower( psz_family );
- /* */
- FcPatternAddString( pat, FC_FAMILY, (const FcChar8*)family );
- 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 );
+ if( unlikely( !psz_lc ) )
+ return NULL;
- /* */
- FcDefaultSubstitute( pat );
- if( !FcConfigSubstitute( config, pat, FcMatchPattern ) )
+ vlc_family_t *p_family =
+ vlc_dictionary_value_for_key( &p_sys->family_map, psz_lc );
+
+ if( p_family != kVLCDictionaryNotFound )
{
- FcPatternDestroy( pat );
- return NULL;
+ free( psz_lc );
+ return p_family;
}
- /* Find the best font for the pattern, destroy the pattern */
- p_pat = FcFontMatch( config, pat, &result );
- FcPatternDestroy( pat );
- if( !p_pat || result == FcResultNoMatch ) return NULL;
+ p_family = NewFamily( p_filter, psz_lc, &p_sys->p_families,
+ &p_sys->family_map, psz_lc );
+
+ free( psz_lc );
+ if( !p_family )
+ return NULL;
+
+ bool b_bold, b_italic;
- /* Check the new pattern */
- if( ( FcResultMatch != FcPatternGetBool( p_pat, FC_OUTLINE, 0, &val_b ) )
- || ( val_b != FcTrue ) )
+ for( int i = 0; i < 4; ++i )
{
+ switch( i )
+ {
+ case 0:
+ b_bold = false;
+ b_italic = false;
+ break;
+ case 1:
+ b_bold = true;
+ b_italic = false;
+ break;
+ case 2:
+ b_bold = false;
+ b_italic = true;
+ break;
+ case 3:
+ b_bold = true;
+ b_italic = true;
+ break;
+ }
+
+ int i_index = 0;
+ FcResult result = FcResultMatch;
+ FcPattern *pat, *p_pat;
+ FcChar8* val_s;
+ FcBool val_b;
+ char *psz_fontfile = NULL;
+ FcConfig* config = NULL;
+
+ /* Create a pattern and fill it */
+ pat = FcPatternCreate();
+ if (!pat) continue;
+
+ /* */
+ FcPatternAddString( pat, FC_FAMILY, (const FcChar8*) psz_family );
+ 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;
+
+ /* Check the new pattern */
+ if( ( FcResultMatch != FcPatternGetBool( p_pat, FC_OUTLINE, 0, &val_b ) )
+ || ( val_b != FcTrue ) )
+ {
+ FcPatternDestroy( p_pat );
+ continue;
+ }
+ if( FcResultMatch != FcPatternGetInteger( p_pat, FC_INDEX, 0, &i_index ) )
+ {
+ i_index = 0;
+ }
+
+ if( FcResultMatch != FcPatternGetString( p_pat, FC_FAMILY, 0, &val_s ) )
+ {
+ FcPatternDestroy( p_pat );
+ continue;
+ }
+
+ if( FcResultMatch == FcPatternGetString( p_pat, FC_FILE, 0, &val_s ) )
+ psz_fontfile = strdup( (const char*)val_s );
+
FcPatternDestroy( p_pat );
- return NULL;
+
+ if( !psz_fontfile )
+ continue;
+
+ NewFont( psz_fontfile, i_index, b_bold, b_italic, p_family );
}
- if( FcResultMatch != FcPatternGetInteger( p_pat, FC_INDEX, 0, i_idx ) )
+
+ return p_family;
+}
+
+vlc_family_t *FontConfig_GetFallbacks( filter_t *p_filter, const char *psz_family,
+ uni_char_t codepoint )
+{
+
+ VLC_UNUSED( codepoint );
+
+ vlc_family_t *p_family = NULL;
+ filter_sys_t *p_sys = p_filter->p_sys;
+
+ char *psz_lc = ToLower( psz_family );
+
+ if( unlikely( !psz_lc ) )
+ return NULL;
+
+ p_family = vlc_dictionary_value_for_key( &p_sys->fallback_map, psz_lc );
+
+ if( p_family != kVLCDictionaryNotFound )
{
- *i_idx = 0;
+ free( psz_lc );
+ return p_family;
}
-
- if( FcResultMatch != FcPatternGetString( p_pat, FC_FAMILY, 0, &val_s ) )
+ else
+ p_family = NULL;
+
+ const char *psz_last_name = "";
+ FcPattern *p_pattern = FcPatternCreate();
+ FcValue family;
+ family.type = FcTypeString;
+ family.u.s = ( const FcChar8* ) psz_family;
+ FcPatternAdd( p_pattern, FC_FAMILY, family, FcFalse );
+ if( FcConfigSubstitute( NULL, p_pattern, FcMatchPattern ) == FcTrue )
{
- FcPatternDestroy( p_pat );
- return NULL;
+ FcDefaultSubstitute( p_pattern );
+ FcResult result;
+ FcFontSet* p_font_set = FcFontSort( NULL, p_pattern, FcTrue, NULL, &result );
+ if( p_font_set )
+ {
+ for( int i = 0; i < p_font_set->nfont; ++i )
+ {
+ char* psz_name = NULL;
+ FcPatternGetString( p_font_set->fonts[i],
+ FC_FAMILY, 0, ( FcChar8** )( &psz_name ) );
+
+ /* Avoid duplicate family names */
+ if( strcasecmp( psz_last_name, psz_name ) )
+ {
+ vlc_family_t *p_temp = NewFamily( p_filter, psz_name,
+ &p_family, NULL, NULL );
+
+ if( unlikely( !p_temp ) )
+ {
+ FcFontSetDestroy( p_font_set );
+ FcPatternDestroy( p_pattern );
+ if( p_family )
+ FreeFamilies( p_family, NULL );
+ free( psz_lc );
+ return NULL;
+ }
+
+ psz_last_name = p_temp->psz_name;
+ }
+ }
+ FcFontSetDestroy( p_font_set );
+ }
}
+ FcPatternDestroy( p_pattern );
- /* if( strcasecmp((const char*)val_s, family ) != 0 )
- msg_Warn( p_filter, "fontconfig: selected font family is not"
- "the requested one: '%s' != '%s'\n",
- (const char*)val_s, family ); */
-
- if( FcResultMatch == FcPatternGetString( p_pat, FC_FILE, 0, &val_s ) )
- ret = strdup( (const char*)val_s );
+ if( p_family )
+ vlc_dictionary_insert( &p_sys->fallback_map, psz_lc, p_family );
- FcPatternDestroy( p_pat );
- return ret;
+ free( psz_lc );
+ return p_family;
}
#endif
diff --git a/modules/text_renderer/platform_fonts.h b/modules/text_renderer/platform_fonts.h
index ce788ec..9748ce4 100644
--- a/modules/text_renderer/platform_fonts.h
+++ b/modules/text_renderer/platform_fonts.h
@@ -120,13 +120,12 @@ struct vlc_family_t
#define FB_NAME "fallback"
#ifdef HAVE_FONTCONFIG
-char* FontConfig_Select( filter_t *p_filter, const char* family,
- bool b_bold, bool b_italic,
- int *i_idx, uni_char_t codepoint );
+const vlc_family_t *FontConfig_GetFamily( filter_t *p_filter, const char *psz_family );
+vlc_family_t *FontConfig_GetFallbacks( filter_t *p_filter, const char *psz_family,
+ uni_char_t codepoint );
void FontConfig_BuildCache( filter_t *p_filter );
#endif
-
#if defined( _WIN32 ) && !VLC_WINSTORE_APP
char* Win32_Select( filter_t *p_filter, const char* family,
bool b_bold, bool b_italic,
diff --git a/modules/text_renderer/text_layout.c b/modules/text_renderer/text_layout.c
index a3386f9..bd6a62e 100644
--- a/modules/text_renderer/text_layout.c
+++ b/modules/text_renderer/text_layout.c
@@ -58,6 +58,11 @@
#include "text_layout.h"
#include "freetype.h"
+/* FontConfig */
+#ifdef HAVE_FONTCONFIG
+# define HAVE_FONT_FALLBACK
+#endif
+
/*
* Within a paragraph, run_desc_t represents a run of characters
* having the same font face, size, and style, Unicode script
--
1.9.1
More information about the vlc-devel
mailing list