Commit 3085d9bc authored by Salah-Eddin Shaban's avatar Salah-Eddin Shaban Committed by Jean-Baptiste Kempf

freetype: font fallback for Fontconfig (Linux et al.)

Signed-off-by: default avatarJean-Baptiste Kempf <jb@videolan.org>
parent e8793fde
......@@ -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
......
......@@ -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
......
......@@ -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,
......
......@@ -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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment