[vlc-commits] freetype: change callbacks and use fallback lists
Francois Cartegnie
git at videolan.org
Mon Aug 24 17:38:58 CEST 2020
vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Wed Aug 5 11:20:04 2020 +0200| [9d0d3c19692147102c0ee3eef5fb6b6986b3eb35] | committer: Francois Cartegnie
freetype: change callbacks and use fallback lists
Makes use of explicit fallback to make a single
call to fontconfig.
Callbacks now returns error code
as we should be able to cache misses
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=9d0d3c19692147102c0ee3eef5fb6b6986b3eb35
---
modules/text_renderer/freetype/fonts/android.c | 27 ++--
modules/text_renderer/freetype/fonts/backends.h | 48 ++++--
modules/text_renderer/freetype/fonts/darwin.c | 29 +++-
modules/text_renderer/freetype/fonts/dwrite.cpp | 34 ++--
modules/text_renderer/freetype/fonts/fontconfig.c | 94 +++++++----
modules/text_renderer/freetype/fonts/win32.c | 36 +++--
modules/text_renderer/freetype/freetype.h | 1 -
modules/text_renderer/freetype/ftcache.c | 5 +-
modules/text_renderer/freetype/lru.c | 28 +++-
modules/text_renderer/freetype/lru.h | 8 +-
modules/text_renderer/freetype/platform_fonts.c | 183 +++++++++++++++-------
modules/text_renderer/freetype/platform_fonts.h | 14 +-
12 files changed, 347 insertions(+), 160 deletions(-)
diff --git a/modules/text_renderer/freetype/fonts/android.c b/modules/text_renderer/freetype/fonts/android.c
index a68949519f..d1651ed083 100644
--- a/modules/text_renderer/freetype/fonts/android.c
+++ b/modules/text_renderer/freetype/fonts/android.c
@@ -426,27 +426,24 @@ int Android_Prepare( vlc_font_select_t *fs )
return VLC_SUCCESS;
}
-const vlc_family_t *Android_GetFamily( vlc_font_select_t *fs, const char *psz_lcname )
+int Android_GetFamily( vlc_font_select_t *fs, const char *psz_lcname,
+ const vlc_family_t **pp_result )
{
- vlc_family_t *p_family =
- vlc_dictionary_value_for_key( &fs->family_map, psz_lcname );
+ *pp_result = vlc_dictionary_value_for_key( &fs->family_map, psz_lcname );
+ if( *pp_result == kVLCDictionaryNotFound )
+ *pp_result = NULL;
- if( p_family == kVLCDictionaryNotFound )
- return NULL;
-
- return p_family;
+ return VLC_SUCCESS;
}
-vlc_family_t *Android_GetFallbacks( vlc_font_select_t *fs, const char *psz_lcname,
- uni_char_t codepoint )
+int Android_GetFallbacks( vlc_font_select_t *fs, const char *psz_lcname,
+ uni_char_t codepoint, vlc_family_t **pp_result )
{
VLC_UNUSED( codepoint );
- vlc_family_t *p_fallbacks =
- vlc_dictionary_value_for_key( &fs->fallback_map, psz_lcname );
+ *pp_result = vlc_dictionary_value_for_key( &fs->fallback_map, psz_lcname );
+ if( *pp_result == kVLCDictionaryNotFound )
+ *pp_result = NULL;
- if( p_fallbacks == kVLCDictionaryNotFound )
- return NULL;
-
- return p_fallbacks;
+ return VLC_SUCCESS;
}
diff --git a/modules/text_renderer/freetype/fonts/backends.h b/modules/text_renderer/freetype/fonts/backends.h
index 88058b0449..abfc1b1ca5 100644
--- a/modules/text_renderer/freetype/fonts/backends.h
+++ b/modules/text_renderer/freetype/fonts/backends.h
@@ -21,21 +21,32 @@
extern "C" {
#endif
+#include "../lru.h"
+
struct vlc_font_select_t
{
vlc_object_t *p_obj;
filter_t *p_filter;
- const vlc_family_t * (*pf_get_family) ( vlc_font_select_t *, const char *psz_family );
+ /* If the callbacks return VLC_SUCCESS, this means the result is valid
+ (can still be no match/NULL), and if not, this is a temp error. */
+ int (*pf_select_family) ( vlc_font_select_t *, const char *psz_family,
+ const vlc_family_t ** );
+ int (*pf_select_among_families)( vlc_font_select_t *, const fontfamilies_t *,
+ const vlc_family_t ** );
- vlc_family_t * (*pf_get_fallbacks) ( vlc_font_select_t *, const char *psz_family,
- uni_char_t codepoint );
+ int (*pf_get_fallbacks) ( vlc_font_select_t *, const char *psz_family,
+ uni_char_t codepoint, vlc_family_t ** );
+ int (*pf_get_fallbacks_among_families) ( vlc_font_select_t *, const fontfamilies_t *,
+ uni_char_t codepoint, vlc_family_t ** );
/**
* This is the master family list. It owns the lists of vlc_font_t's
* and should be freed using FreeFamiliesAndFonts()
*/
vlc_family_t *p_families;
+ /* We need to limit caching of lookups as we do not control the names */
+ vlc_lru *families_lookup_lru;
/**
* This maps a family name to a vlc_family_t within the master list
@@ -60,37 +71,40 @@ struct vlc_font_select_t
* PLATFORM SPECIFIC SELECTORS
**/
#ifdef HAVE_FONTCONFIG
-vlc_family_t *FontConfig_GetFallbacks( vlc_font_select_t *, const char *psz_family,
- uni_char_t codepoint );
-const vlc_family_t *FontConfig_GetFamily( vlc_font_select_t *, const char *psz_family );
+int FontConfig_GetFallbacksAmongFamilies( vlc_font_select_t *, const fontfamilies_t *,
+ uni_char_t codepoint, vlc_family_t **pp_result );
+int FontConfig_GetFamily( vlc_font_select_t *, const char *psz_family, const vlc_family_t ** );
+int FontConfig_SelectAmongFamilies( vlc_font_select_t *fs, const fontfamilies_t *families,
+ const vlc_family_t **pp_result );
int FontConfig_Prepare( vlc_font_select_t * );
void FontConfig_Unprepare( vlc_font_select_t * );
#endif /* FONTCONFIG */
#if defined( _WIN32 )
-const vlc_family_t *DWrite_GetFamily( vlc_font_select_t *, const char *psz_family );
-vlc_family_t *DWrite_GetFallbacks( vlc_font_select_t *, const char *psz_family,
- uni_char_t codepoint );
+int DWrite_GetFamily( vlc_font_select_t *, const char *psz_family, const vlc_family_t ** );
+int DWrite_GetFallbacks( vlc_font_select_t *, const char *psz_family,
+ uni_char_t codepoint, vlc_family_t ** );
int InitDWrite( vlc_font_select_t * );
int ReleaseDWrite( vlc_font_select_t * );
int DWrite_GetFontStream( vlc_font_select_t *, int i_index, FT_Stream *pp_stream );
#if !VLC_WINSTORE_APP
-vlc_family_t *Win32_GetFallbacks( vlc_font_select_t *, const char *psz_family,
- uni_char_t codepoint );
+int Win32_GetFallbacks( vlc_font_select_t *, const char *psz_family,
+ uni_char_t codepoint, vlc_family_t ** );
-const vlc_family_t *Win32_GetFamily( vlc_font_select_t *, const char *psz_family );
+int Win32_GetFamily( vlc_font_select_t *, const char *psz_family, const vlc_family_t ** );
#endif /* !VLC_WINSTORE_APP */
#endif /* _WIN32 */
#ifdef __APPLE__
-vlc_family_t *CoreText_GetFallbacks(vlc_font_select_t *, const char *psz_family, uni_char_t codepoint);
-const vlc_family_t *CoreText_GetFamily(vlc_font_select_t *, const char *psz_family);
+int CoreText_GetFallbacks(vlc_font_select_t *, const char *psz_family,
+ uni_char_t codepoint, vlc_family_t **);
+int CoreText_GetFamily(vlc_font_select_t *, const char *psz_family, const vlc_family_t **);
#endif /* __APPLE__ */
#ifdef __ANDROID__
-const vlc_family_t *Android_GetFamily( vlc_font_select_t *, const char *psz_family );
-vlc_family_t *Android_GetFallbacks( vlc_font_select_t *, const char *psz_family,
- uni_char_t codepoint );
+int Android_GetFamily( vlc_font_select_t *, const char *psz_family, const vlc_family_t ** );
+int Android_GetFallbacks( vlc_font_select_t *, const char *psz_family,
+ uni_char_t codepoint, vlc_family_t ** );
int Android_Prepare( vlc_font_select_t * );
#endif /* __ANDROID__ */
diff --git a/modules/text_renderer/freetype/fonts/darwin.c b/modules/text_renderer/freetype/fonts/darwin.c
index 6816192be5..08a9f1c88d 100644
--- a/modules/text_renderer/freetype/fonts/darwin.c
+++ b/modules/text_renderer/freetype/fonts/darwin.c
@@ -159,10 +159,13 @@ static CFComparisonResult SortCTFontMatchResults(CTFontDescriptorRef desc1,
return kCFCompareGreaterThan;
}
-const vlc_family_t *CoreText_GetFamily(vlc_font_select_t *fs, const char *psz_lcname)
+int CoreText_GetFamily(vlc_font_select_t *fs, const char *psz_lcname,
+ const vlc_family_t **pp_result)
{
+ int i_ret = VLC_EGENERIC;
+
if (unlikely(psz_lcname == NULL)) {
- return NULL;
+ return VLC_EGENERIC;
}
psz_lcname = CoreText_TranslateGenericFamily(psz_lcname);
@@ -170,7 +173,8 @@ const vlc_family_t *CoreText_GetFamily(vlc_font_select_t *fs, const char *psz_lc
/* let's double check if we have parsed this family already */
vlc_family_t *p_family = vlc_dictionary_value_for_key(&fs->family_map, psz_lcname);
if (p_family) {
- return p_family;
+ *pp_result = p_family;
+ return VLC_SUCCESS;
}
CTFontCollectionRef coreTextFontCollection = NULL;
@@ -239,6 +243,8 @@ const vlc_family_t *CoreText_GetFamily(vlc_font_select_t *fs, const char *psz_lc
addNewFontToFamily(fs, iter, path, p_family);
}
+ i_ret = VLC_SUCCESS;
+
end:
if (matchedFontDescriptions != NULL) {
CFRelease(matchedFontDescriptions);
@@ -255,13 +261,16 @@ end:
CFRelease(coreTextFontDescriptorsArray);
CFRelease(familyName);
- return p_family;
+ *pp_result = p_family;
+ return i_ret;
}
-vlc_family_t *CoreText_GetFallbacks(vlc_font_select_t *fs, const char *psz_lcname, uni_char_t codepoint)
+int CoreText_GetFallbacks(vlc_font_select_t *fs, const char *psz_lcname,
+ uni_char_t codepoint, vlc_family_t **pp_result)
{
+ int i_ret = VLC_EGENERIC;
if (unlikely(psz_lcname == NULL)) {
- return NULL;
+ return VLC_EGENERIC;
}
psz_lcname = CoreText_TranslateGenericFamily(psz_lcname);
@@ -299,6 +308,7 @@ vlc_family_t *CoreText_GetFallbacks(vlc_font_select_t *fs, const char *psz_lcnam
p_family = vlc_dictionary_value_for_key(&fs->family_map, psz_lc_fallback);
if (p_family) {
+ i_ret = VLC_SUCCESS;
goto done;
}
@@ -313,11 +323,14 @@ vlc_family_t *CoreText_GetFallbacks(vlc_font_select_t *fs, const char *psz_lcnam
/* check if the path is empty, which can happen in rare circumstances */
if (psz_fontPath == NULL || *psz_fontPath == '\0') {
+ i_ret = VLC_SUCCESS;
goto done;
}
addNewFontToFamily(fs, fallbackFontDescriptor, strdup(psz_fontPath), p_family);
+ i_ret = VLC_SUCCESS;
+
done:
CFRelease(familyName);
CFRelease(font);
@@ -331,5 +344,7 @@ done:
CFRelease(postScriptFallbackFontname);
if (fallbackFontDescriptor != NULL)
CFRelease(fallbackFontDescriptor);
- return p_family;
+
+ *pp_result = p_family;
+ return i_ret;
}
diff --git a/modules/text_renderer/freetype/fonts/dwrite.cpp b/modules/text_renderer/freetype/fonts/dwrite.cpp
index 12216f7d92..0d7092e604 100644
--- a/modules/text_renderer/freetype/fonts/dwrite.cpp
+++ b/modules/text_renderer/freetype/fonts/dwrite.cpp
@@ -571,7 +571,8 @@ static void DWrite_ParseFamily( vlc_font_select_t *fs, IDWriteFontFamily *p_dw_f
}
}
-extern "C" const vlc_family_t *DWrite_GetFamily( vlc_font_select_t *fs, const char *psz_lcname )
+extern "C" int DWrite_GetFamily( vlc_font_select_t *fs, const char *psz_lcname,
+ const vlc_family_t **pp_result )
{
dw_sys_t *p_dw_sys = ( dw_sys_t * ) fs->p_dw_sys;
ComPtr< IDWriteFontFamily > p_dw_family;
@@ -583,13 +584,16 @@ extern "C" const vlc_family_t *DWrite_GetFamily( vlc_font_select_t *fs, const ch
( vlc_family_t * ) vlc_dictionary_value_for_key( &fs->family_map, psz_lcname );
if( p_family )
- return p_family;
+ {
+ *pp_result = p_family;
+ return VLC_SUCCESS;
+ }
p_family = NewFamily( fs, psz_lcname, &fs->p_families,
&fs->family_map, psz_lcname );
if( unlikely( !p_family ) )
- return NULL;
+ return VLC_EGENERIC;
msg_Dbg( fs->p_obj, "DWrite_GetFamily(): family name: %s", psz_lcname );
@@ -674,7 +678,8 @@ extern "C" const vlc_family_t *DWrite_GetFamily( vlc_font_select_t *fs, const ch
done:
free( pwsz_family );
- return p_family;
+ *pp_result = p_family;
+ return VLC_SUCCESS;
}
static char *DWrite_Fallback( vlc_font_select_t *fs, const char *psz_lcname,
@@ -750,12 +755,13 @@ done:
return psz_result;
}
-extern "C" vlc_family_t *DWrite_GetFallbacks( vlc_font_select_t *fs, const char *psz_lcname,
- uni_char_t codepoint )
+extern "C" int DWrite_GetFallbacks( vlc_font_select_t *fs, const char *psz_lcname,
+ uni_char_t codepoint, vlc_family_t **pp_result )
{
vlc_family_t *p_family = NULL;
vlc_family_t *p_fallbacks = NULL;
char *psz_fallback = NULL;
+ int i_ret = VLC_EGENERIC;
p_fallbacks = ( vlc_family_t * ) vlc_dictionary_value_for_key( &fs->fallback_map, psz_lcname );
@@ -775,12 +781,16 @@ extern "C" vlc_family_t *DWrite_GetFallbacks( vlc_font_select_t *fs, const char
if( !psz_fallback )
goto done;
- const vlc_family_t *p_fallback = DWrite_GetFamily( fs, psz_fallback );
- if( !p_fallback || !p_fallback->p_fonts )
+ const vlc_family_t *p_fallback = NULL;
+ if( DWrite_GetFamily( fs, psz_fallback, &p_fallback ) != VLC_SUCCESS )
goto done;
- if( !CheckFace( fs, p_fallback->p_fonts, codepoint ) )
+ if( !p_fallback || !p_fallback->p_fonts ||
+ !CheckFace( fs, p_fallback->p_fonts, codepoint ) )
+ {
+ i_ret = VLC_SUCCESS;
goto done;
+ }
p_family = NewFamily( fs, psz_fallback, NULL, NULL, NULL );
@@ -796,7 +806,11 @@ extern "C" vlc_family_t *DWrite_GetFallbacks( vlc_font_select_t *fs, const char
psz_lcname, p_family );
}
+ i_ret = VLC_SUCCESS;
+
done:
free( psz_fallback );
- return p_family;
+
+ *pp_result = p_family;
+ return i_ret;
}
diff --git a/modules/text_renderer/freetype/fonts/fontconfig.c b/modules/text_renderer/freetype/fonts/fontconfig.c
index 265f3ef9a9..fff08913f2 100644
--- a/modules/text_renderer/freetype/fonts/fontconfig.c
+++ b/modules/text_renderer/freetype/fonts/fontconfig.c
@@ -106,16 +106,10 @@ void FontConfig_Unprepare( vlc_font_select_t *fs )
vlc_mutex_unlock( &lock );
}
-const vlc_family_t *FontConfig_GetFamily( vlc_font_select_t *fs, const char *psz_lcname )
+int FontConfig_SelectAmongFamilies( vlc_font_select_t *fs, const fontfamilies_t *families,
+ const vlc_family_t **pp_result )
{
- vlc_family_t *p_family = vlc_dictionary_value_for_key( &fs->family_map, psz_lcname );
- if( p_family != kVLCDictionaryNotFound )
- return p_family;
-
- p_family = NewFamily( fs, psz_lcname, &fs->p_families,
- &fs->family_map, psz_lcname );
- if( !p_family )
- return NULL;
+ vlc_family_t *p_family = NULL;
for( int i = 0; i < 4; ++i ) /* Iterate through FC_{SLANT,WEIGHT} combos */
{
@@ -134,7 +128,9 @@ const vlc_family_t *FontConfig_GetFamily( vlc_font_select_t *fs, const char *psz
if (!pat) continue;
/* */
- FcPatternAddString( pat, FC_FAMILY, (const FcChar8*) psz_lcname );
+ const char *psz_lcname;
+ vlc_vector_foreach( psz_lcname, &families->vec )
+ FcPatternAddString( pat, FC_FAMILY, (const FcChar8*) psz_lcname );
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 );
@@ -152,25 +148,43 @@ const vlc_family_t *FontConfig_GetFamily( vlc_font_select_t *fs, const char *psz
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 ) )
+ if( FcResultMatch != FcPatternGetString( p_pat, FC_FAMILY, 0, &val_s ) )
{
FcPatternDestroy( p_pat );
continue;
}
- if( FcResultMatch != FcPatternGetInteger( p_pat, FC_INDEX, 0, &i_index ) )
+ if( !p_family )
{
- i_index = 0;
+ char *psz_fnlc = LowercaseDup((const char *)val_s);
+ 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( pat );
+ return VLC_ENOMEM;
+ }
+ }
+ free(psz_fnlc);
}
- if( FcResultMatch != FcPatternGetString( p_pat, FC_FAMILY, 0, &val_s ) )
+ /* 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_FILE, 0, &val_s ) )
psz_fontfile = strdup( (const char*)val_s );
@@ -182,28 +196,47 @@ const vlc_family_t *FontConfig_GetFamily( vlc_font_select_t *fs, const char *psz
NewFont( psz_fontfile, i_index, b_bold, b_italic, p_family );
}
- return p_family;
+ *pp_result = p_family;
+ return VLC_SUCCESS;
+}
+
+int FontConfig_GetFamily( vlc_font_select_t *fs, const char *psz_lcname,
+ const vlc_family_t **pp_result )
+{
+ fontfamilies_t families;
+ families.psz_key = psz_lcname;
+ vlc_vector_init( &families.vec );
+ vlc_vector_push( &families.vec, (char *) psz_lcname );
+ int ret = FontConfig_SelectAmongFamilies( fs, &families, pp_result );
+ vlc_vector_clear( &families.vec );
+ return ret;
}
-vlc_family_t *FontConfig_GetFallbacks( vlc_font_select_t *fs, const char *psz_lcname,
- uni_char_t codepoint )
+int FontConfig_GetFallbacksAmongFamilies( vlc_font_select_t *fs, const fontfamilies_t *families,
+ uni_char_t codepoint, vlc_family_t **pp_result )
{
VLC_UNUSED( codepoint );
+ vlc_family_t *p_family = NULL;
- vlc_family_t *p_family =
- vlc_dictionary_value_for_key( &fs->fallback_map, psz_lcname );
+ p_family = vlc_dictionary_value_for_key( &fs->fallback_map, families->psz_key );
if( p_family != kVLCDictionaryNotFound )
- return p_family;
+ {
+ *pp_result = p_family;
+ return VLC_SUCCESS;
+ }
else
p_family = NULL;
-
const char *psz_last_name = "";
+
FcPattern *p_pattern = FcPatternCreate();
- FcValue family;
- family.type = FcTypeString;
- family.u.s = ( const FcChar8* ) psz_lcname;
- FcPatternAdd( p_pattern, FC_FAMILY, family, FcFalse );
+ if (!p_pattern)
+ return VLC_EGENERIC;
+
+ const char *psz_lcname;
+ vlc_vector_foreach( psz_lcname, &families->vec )
+ FcPatternAddString( p_pattern, FC_FAMILY, (const FcChar8*) psz_lcname );
+
if( FcConfigSubstitute( config, p_pattern, FcMatchPattern ) == FcTrue )
{
FcDefaultSubstitute( p_pattern );
@@ -229,7 +262,7 @@ vlc_family_t *FontConfig_GetFallbacks( vlc_font_select_t *fs, const char *psz_lc
FcPatternDestroy( p_pattern );
if( p_family )
FreeFamilies( p_family, NULL );
- return NULL;
+ return VLC_EGENERIC;
}
psz_last_name = p_temp->psz_name;
@@ -241,7 +274,8 @@ vlc_family_t *FontConfig_GetFallbacks( vlc_font_select_t *fs, const char *psz_lc
FcPatternDestroy( p_pattern );
if( p_family )
- vlc_dictionary_insert( &fs->fallback_map, psz_lcname, p_family );
+ vlc_dictionary_insert( &fs->fallback_map, families->psz_key, p_family );
- return p_family;
+ *pp_result = p_family;
+ return VLC_SUCCESS;
}
diff --git a/modules/text_renderer/freetype/fonts/win32.c b/modules/text_renderer/freetype/fonts/win32.c
index 00866595c7..39e58b7cfc 100644
--- a/modules/text_renderer/freetype/fonts/win32.c
+++ b/modules/text_renderer/freetype/fonts/win32.c
@@ -392,19 +392,22 @@ static int CALLBACK EnumFontCallback(const ENUMLOGFONTEX *lpelfe, const NEWTEXTM
return 1;
}
-const vlc_family_t *Win32_GetFamily( vlc_font_select_t *fs, const char *psz_lcname )
+int Win32_GetFamily( vlc_font_select_t *fs, const char *psz_lcname, const vlc_family_t **pp_result )
{
vlc_family_t *p_family =
vlc_dictionary_value_for_key( &fs->family_map, psz_lcname );
if( p_family )
- return p_family;
+ {
+ *pp_result = p_family;
+ return VLC_SUCCESS;
+ }
p_family = NewFamily( fs, psz_lcname, &fs->p_families,
&fs->family_map, psz_lcname );
if( unlikely( !p_family ) )
- return NULL;
+ return VLC_EGENERIC;
LOGFONT lf;
lf.lfCharSet = DEFAULT_CHARSET;
@@ -421,7 +424,8 @@ const vlc_family_t *Win32_GetFamily( vlc_font_select_t *fs, const char *psz_lcna
EnumFontFamiliesEx(hDC, &lf, (FONTENUMPROC)&EnumFontCallback, (LPARAM)&ctx, 0);
ReleaseDC(NULL, hDC);
- return p_family;
+ *pp_result = p_family;
+ return VLC_SUCCESS;
}
static int CALLBACK MetaFileEnumProc( HDC hdc, HANDLETABLE* table,
@@ -516,12 +520,13 @@ error:
return NULL;
}
-vlc_family_t *Win32_GetFallbacks( vlc_font_select_t *fs, const char *psz_lcname,
- uni_char_t codepoint )
+int Win32_GetFallbacks( vlc_font_select_t *fs, const char *psz_lcname,
+ uni_char_t codepoint, vlc_family_t **pp_result )
{
vlc_family_t *p_family = NULL;
vlc_family_t *p_fallbacks = NULL;
char *psz_uniscribe = NULL;
+ int i_ret = VLC_EGENERIC;
p_fallbacks = vlc_dictionary_value_for_key( &fs->fallback_map, psz_lcname );
@@ -537,16 +542,22 @@ vlc_family_t *Win32_GetFallbacks( vlc_font_select_t *fs, const char *psz_lcname,
if( !p_family )
{
psz_uniscribe = UniscribeFallback( psz_lcname, codepoint );
-
if( !psz_uniscribe )
+ {
+ i_ret = VLC_SUCCESS;
goto done;
+ }
- const vlc_family_t *p_uniscribe = Win32_GetFamily( fs, psz_uniscribe );
- if( !p_uniscribe || !p_uniscribe->p_fonts )
+ const vlc_family_t *p_uniscribe = NULL;
+ if( Win32_GetFamily( fs, psz_uniscribe, &p_uniscribe ) != VLC_SUCCESS )
goto done;
- if( !CheckFace( fs, p_uniscribe->p_fonts, codepoint ) )
+ if( !p_uniscribe || !p_uniscribe->p_fonts ||
+ !CheckFace( fs, p_uniscribe->p_fonts, codepoint ) )
+ {
+ i_ret = VLC_SUCCESS;
goto done;
+ }
p_family = NewFamily( fs, psz_uniscribe, NULL, NULL, NULL );
@@ -562,9 +573,12 @@ vlc_family_t *Win32_GetFallbacks( vlc_font_select_t *fs, const char *psz_lcname,
psz_lcname, p_family );
}
+ i_ret = VLC_SUCCESS;
+
done:
free( psz_uniscribe );
- return p_family;
+ *pp_result = p_family;
+ return i_ret;
}
char * MakeFilePath( vlc_font_select_t *fs, const char *psz_filename )
diff --git a/modules/text_renderer/freetype/freetype.h b/modules/text_renderer/freetype/freetype.h
index aff536b8e1..7d3e9784a8 100644
--- a/modules/text_renderer/freetype/freetype.h
+++ b/modules/text_renderer/freetype/freetype.h
@@ -87,7 +87,6 @@ typedef struct vlc_font_select_t vlc_font_select_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/ftcache.c b/modules/text_renderer/freetype/ftcache.c
index b4a0268392..f475c3c58e 100644
--- a/modules/text_renderer/freetype/ftcache.c
+++ b/modules/text_renderer/freetype/ftcache.c
@@ -175,9 +175,10 @@ static FT_Error RequestFace( FTC_FaceID face_id, FT_Library library,
return 0;
}
-static void LRUGlyphRefRelease( void *v )
+static void LRUGlyphRefRelease( void *priv, void *v )
{
vlc_ftcache_custom_glyph_ref_t ref = (vlc_ftcache_custom_glyph_ref_t) v;
+ VLC_UNUSED(priv);
assert(ref->refcount);
if( --ref->refcount == 0 )
{
@@ -219,7 +220,7 @@ vlc_ftcache_t * vlc_ftcache_New( vlc_object_t *obj, FT_Library p_library,
/* Dictionnaries for fonts */
vlc_dictionary_init( &ftcache->face_ids, 50 );
- ftcache->glyphs_lrucache = vlc_lru_New( 128, LRUGlyphRefRelease );
+ ftcache->glyphs_lrucache = vlc_lru_New( 128, LRUGlyphRefRelease, ftcache );
if(!ftcache->glyphs_lrucache ||
FTC_Manager_New( p_library, 4, 8, maxkb << 10,
diff --git a/modules/text_renderer/freetype/lru.c b/modules/text_renderer/freetype/lru.c
index 316a584755..226fd0510c 100644
--- a/modules/text_renderer/freetype/lru.c
+++ b/modules/text_renderer/freetype/lru.c
@@ -34,7 +34,8 @@ struct vlc_lru_entry
struct vlc_lru
{
- void (*releaseValue)(void *);
+ void (*releaseValue)(void *, void *);
+ void *priv;
unsigned max;
vlc_dictionary_t dict;
struct vlc_list list;
@@ -46,15 +47,18 @@ static void vlc_lru_releaseentry( void *value, void *priv )
struct vlc_lru_entry *entry = value;
struct vlc_lru *lru = priv;
free(entry->psz_key);
- lru->releaseValue(entry->value);
+ if( lru->releaseValue )
+ lru->releaseValue( lru->priv, entry->value );
free(entry);
}
-vlc_lru * vlc_lru_New( unsigned max, void(*releaseValue)(void *) )
+vlc_lru * vlc_lru_New( unsigned max,
+ void(*releaseValue)(void *, void *), void *priv )
{
vlc_lru *lru = malloc(sizeof(*lru));
if( lru )
{
+ lru->priv = priv;
lru->max = max;
vlc_dictionary_init( &lru->dict, max );
vlc_list_init( &lru->list );
@@ -70,6 +74,11 @@ void vlc_lru_Release( vlc_lru *lru )
free( lru );
}
+bool vlc_lru_HasKey( vlc_lru *lru, const char *psz_key )
+{
+ return vlc_dictionary_has_key( &lru->dict, psz_key );
+}
+
void * vlc_lru_Get( vlc_lru *lru, const char *psz_key )
{
struct vlc_lru_entry *entry = vlc_dictionary_value_for_key( &lru->dict, psz_key );
@@ -94,13 +103,13 @@ void vlc_lru_Insert( vlc_lru *lru, const char *psz_key, void *value )
struct vlc_lru_entry *entry = calloc(1, sizeof(*entry));
if(!entry)
{
- lru->releaseValue(value);
+ lru->releaseValue(lru->priv, value);
return;
}
entry->psz_key = strdup( psz_key );
if(!entry->psz_key)
{
- lru->releaseValue(value);
+ lru->releaseValue(lru->priv, value);
free(entry);
return;
}
@@ -121,3 +130,12 @@ void vlc_lru_Insert( vlc_lru *lru, const char *psz_key, void *value )
vlc_lru_releaseentry(toremove, lru);
}
}
+
+void vlc_lru_Apply( vlc_lru *lru,
+ void(*func)(void *, const char *, void *),
+ void *priv )
+{
+ struct vlc_lru_entry *entry;
+ vlc_list_foreach( entry, &lru->list, node )
+ func( priv, entry->psz_key, entry->value );
+}
diff --git a/modules/text_renderer/freetype/lru.h b/modules/text_renderer/freetype/lru.h
index 3dcb72b66c..eb5ff3b1d6 100644
--- a/modules/text_renderer/freetype/lru.h
+++ b/modules/text_renderer/freetype/lru.h
@@ -26,12 +26,18 @@ extern "C" {
typedef struct vlc_lru vlc_lru;
-vlc_lru * vlc_lru_New( unsigned max, void(*releaseValue)(void *) );
+vlc_lru * vlc_lru_New( unsigned max,
+ void(*releaseValue)(void *, void *), void * );
void vlc_lru_Release( vlc_lru *lru );
+bool vlc_lru_HasKey( vlc_lru *lru, const char *psz_key );
void * vlc_lru_Get( vlc_lru *lru, const char *psz_key );
void vlc_lru_Insert( vlc_lru *lru, const char *psz_key, void *value );
+void vlc_lru_Apply( vlc_lru *lru,
+ void(*func)(void *, const char *, void *),
+ void * );
+
#ifdef __cplusplus
}
#endif
diff --git a/modules/text_renderer/freetype/platform_fonts.c b/modules/text_renderer/freetype/platform_fonts.c
index a74aa4a882..67446f280f 100644
--- a/modules/text_renderer/freetype/platform_fonts.c
+++ b/modules/text_renderer/freetype/platform_fonts.c
@@ -158,7 +158,7 @@ vlc_family_t *SearchFallbacks( vlc_font_select_t *fs, vlc_family_t *p_fallbacks,
{
if( !p_fallback->p_fonts )
{
- const vlc_family_t *p_temp = FontSelectGetFamily( fs, p_fallback->psz_name );
+ const vlc_family_t *p_temp = FontSelectFamily( fs, p_fallback->psz_name );
if( !p_temp || !p_temp->p_fonts )
continue;
p_fallback->p_fonts = p_temp->p_fonts;
@@ -396,7 +396,7 @@ vlc_family_t *InitDefaultList( vlc_font_select_t *fs, const char *const *ppsz_de
if( !psz_lc )
continue;
- const vlc_family_t *p_family = FontSelectGetFamily( fs, psz_lc );
+ const vlc_family_t *p_family = FontSelectFamily( fs, psz_lc );
if( p_family )
{
vlc_family_t *p_temp =
@@ -458,6 +458,14 @@ static void DumpFamily( vlc_object_t *p_obj, const vlc_family_t *p_family,
}
}
+static void DumpLRUElement( void *priv, const char *key, void *val )
+{
+ vlc_object_t *p_obj = priv;
+ vlc_family_t *p_family = val;
+ msg_Dbg( p_obj, "Key: %s", key );
+ DumpFamily( p_obj, p_family, false, -1 );
+}
+
static void DumpDictionary( vlc_object_t *p_obj, const vlc_dictionary_t *p_dict,
bool b_dump_fonts, int i_max_families )
{
@@ -488,10 +496,14 @@ void DumpFamilies( vlc_font_select_t *fs )
msg_Dbg( p_obj, "family_map" );
msg_Dbg( p_obj, "-----------------" );
DumpDictionary( p_obj, &fs->family_map, false, 1 );
+ msg_Dbg( p_obj, "-----------------" );
+ msg_Dbg( p_obj, "families_lookup_lru" );
+ msg_Dbg( p_obj, "-----------------" );
+ vlc_lru_Apply( fs->families_lookup_lru, DumpLRUElement, p_obj );
msg_Dbg( p_obj, "-------------------" );
msg_Dbg( p_obj, "fallback_map" );
msg_Dbg( p_obj, "-------------------" );
- DumpDictionary( p_obj, &fs->fallback_map, true, -1 );
+ DumpDictionary( p_obj, &fs->fallback_map, false, -1 );
}
#endif
@@ -575,7 +587,7 @@ static void AddSingleFamily( const char *psz_start,
{
char *psz = strndup( psz_start, psz_end - psz_start );
if( psz )
- vlc_vector_push( families, psz );
+ vlc_vector_push( &families->vec, psz );
}
}
@@ -612,9 +624,8 @@ static char* SelectFontWithFamilyFallback( vlc_font_select_t *fs,
* Try regular face of the same family first.
* It usually has the best coverage.
*/
- vlc_vector_foreach( psz_lcname, families )
+ vlc_vector_foreach( psz_lcname, &families->vec )
{
- assert(IsLowercase(psz_lcname));
Debug( fs->p_obj, "Looking for family \"%s\"", psz_lcname );
p_fallbacks = vlc_dictionary_value_for_key( &fs->fallback_map,
@@ -627,18 +638,19 @@ static char* SelectFontWithFamilyFallback( vlc_font_select_t *fs,
break;
}
- p_family = FontSelectGetFamily( fs, psz_lcname );
- if( p_family && p_family->p_fonts )
+ p_family = NULL;
+ }
+
+ p_family = FontSelectAmongFamilies( fs, families );
+ if( p_family )
+ {
+ if( p_family->p_fonts &&
+ CheckFace( fs, p_family->p_fonts, codepoint ) )
{
- if( CheckFace( fs, p_family->p_fonts, codepoint ) )
- {
- Debug( fs->p_obj, "Found family \"%s\" for codepoint %x",
- psz_lcname, codepoint );
- break;
- }
+ Debug( fs->p_obj, "Found family \"%s\" for codepoint %x",
+ psz_lcname, codepoint );
}
-
- p_family = NULL;
+ else p_family = NULL;
}
/* Try font attachments if not available locally */
@@ -661,21 +673,18 @@ static char* SelectFontWithFamilyFallback( vlc_font_select_t *fs,
/* Try system fallbacks */
if( !p_family )
{
- vlc_vector_foreach( psz_lcname, families )
+ p_fallbacks = FontFallbacksAmongFamilies( fs, families, codepoint );
+ if( p_fallbacks )
{
- Debug( fs->p_obj, "Looking for family \"%s\" in system fallbacks cp %x", psz_lcname, codepoint );
- p_fallbacks = FontSelectGetFallbacks( fs, psz_lcname, codepoint );
- if( p_fallbacks )
+ Debug( fs->p_obj, "Looking for families \"%s\" in system fallbacks cp %x",
+ families->psz_key, codepoint );
+ p_family = SearchFallbacks( fs, p_fallbacks, codepoint );
+ if( p_family && p_family->p_fonts )
{
- p_family = SearchFallbacks( fs, p_fallbacks, codepoint );
- if( p_family && p_family->p_fonts )
- {
- Debug( fs->p_obj, "Selected family \"%s\" in system fallbacks",
- p_family->psz_name );
- break;
- }
+ Debug( fs->p_obj, "Selected family \"%s\" in system fallbacks",
+ p_family->psz_name );
}
- p_family = NULL;
+ else p_family = NULL;
}
}
@@ -701,7 +710,7 @@ static char* SelectFontWithFamilyFallback( vlc_font_select_t *fs,
{
Debug( fs->p_obj, "Looking for DEFAULT_FAMILY \"%s\" as a last resort", DEFAULT_FAMILY );
char *lc = LowercaseDup(DEFAULT_FAMILY);
- p_family = FontSelectGetFamily( fs, lc );
+ p_family = FontSelectFamily( fs, lc );
free(lc);
}
@@ -731,11 +740,12 @@ SelectAndLoadFace( filter_t *p_filter, const text_style_t *p_style, uni_char_t c
psz_fontname = psz_alloc;
fontfamilies_t families;
- vlc_vector_init( &families );
+ families.psz_key = psz_fontname;
+ vlc_vector_init( &families.vec );
SplitIntoSingleFamily( psz_fontname, &families );
- if( families.size == 0 )
+ if( families.vec.size == 0 )
{
- vlc_vector_clear( &families );
+ vlc_vector_clear( &families.vec );
free(psz_alloc);
return NULL;
}
@@ -768,9 +778,9 @@ SelectAndLoadFace( filter_t *p_filter, const text_style_t *p_style, uni_char_t c
}
char *psz_temp;
- vlc_vector_foreach( psz_temp, &families )
+ vlc_vector_foreach( psz_temp, &families.vec )
free( psz_temp );
- vlc_vector_clear( &families );
+ vlc_vector_clear( &families.vec );
free( psz_fontfile );
free(psz_alloc);
@@ -778,8 +788,8 @@ SelectAndLoadFace( filter_t *p_filter, const text_style_t *p_style, uni_char_t c
}
#ifndef HAVE_GET_FONT_BY_FAMILY_NAME
-static const vlc_family_t * StaticMap_GetFamily( vlc_font_select_t *fs,
- const char *psz_lcname )
+static int StaticMap_GetFamily( vlc_font_select_t *fs, const char *psz_lcname,
+ vlc_family_t **pp_result )
{
filter_t *p_filter = fs->p_filter;
filter_sys_t *p_sys = p_filter->p_sys;
@@ -787,7 +797,10 @@ static const vlc_family_t * StaticMap_GetFamily( vlc_font_select_t *fs,
vlc_family_t *p_family =
vlc_dictionary_value_for_key( &fs->family_map, psz_lcname );
if( p_family )
- return p_family;
+ {
+ *pp_result = p_family;
+ return VLC_SUCCESS;
+ }
const char *psz_file = NULL;
if( !strcasecmp( psz_lcname, DEFAULT_FAMILY ) )
@@ -802,20 +815,24 @@ static const vlc_family_t * StaticMap_GetFamily( vlc_font_select_t *fs,
}
if( !psz_file )
- return NULL;
+ {
+ *pp_result = NULL;
+ return VLC_SUCCESS;
+ }
/* Create new entry */
p_family = NewFamily( fs, psz_lcname, &fs->p_families,
&fs->family_map, psz_lcname );
if( unlikely( !p_family ) )
- return NULL;
+ return VLC_EGENERIC;
char *psz_font_file = MakeFilePath( fs, psz_file );
if( psz_font_file )
NewFont( psz_font_file, 0, false, false, p_family );
- return p_family;
+ *pp_result = p_family;
+ return VLC_SUCCESS;
}
#endif
@@ -851,25 +868,30 @@ vlc_font_select_t * FontSelectNew( filter_t *p_filter )
fs->p_obj = VLC_OBJECT(p_filter);
/* Dictionnaries for families */
- vlc_dictionary_init( &fs->family_map, 50 );
- vlc_dictionary_init( &fs->fallback_map, 20 );
+ vlc_dictionary_init( &fs->family_map, 53 );
+ vlc_dictionary_init( &fs->fallback_map, 23 );
+
+ fs->families_lookup_lru = vlc_lru_New( 23, NULL, NULL );
+ if( !fs->families_lookup_lru )
+ goto error;
#ifdef HAVE_FONTCONFIG
- fs->pf_get_family = FontConfig_GetFamily;
- fs->pf_get_fallbacks = FontConfig_GetFallbacks;
+ fs->pf_select_family = FontConfig_GetFamily;
+ fs->pf_select_among_families = FontConfig_SelectAmongFamilies;
+ fs->pf_get_fallbacks_among_families = FontConfig_GetFallbacksAmongFamilies;
if( FontConfig_Prepare( fs ) )
{
- fs->pf_get_family = NULL;
+ fs->pf_select_family = NULL;
goto error;
}
#elif defined( __APPLE__ )
- fs->pf_get_family = CoreText_GetFamily;
+ fs->pf_select_family = CoreText_GetFamily;
fs->pf_get_fallbacks = CoreText_GetFallbacks;
#elif defined( _WIN32 )
if( InitDWrite( fs ) == VLC_SUCCESS )
{
- fs->pf_get_family = DWrite_GetFamily;
+ fs->pf_select_family = DWrite_GetFamily;
fs->pf_get_fallbacks = DWrite_GetFallbacks;
}
else
@@ -881,20 +903,20 @@ vlc_font_select_t * FontSelectNew( filter_t *p_filter )
msg_Warn( p_filter, "DirectWrite initialization failed. Falling back to GDI/Uniscribe" );
const char *const ppsz_default[] =
{ "tahoma", "fangsong", "simhei", "kaiti" };
- fs->pf_get_family = Win32_GetFamily;
+ fs->pf_select_family = Win32_GetFamily;
fs->pf_get_fallbacks = Win32_GetFallbacks;
if( InitDefaultList( fs, ppsz_default, ARRAY_SIZE(ppsz_default) ) == NULL )
goto error;
#endif
}
#elif defined( __ANDROID__ )
- fs->pf_get_family = Android_GetFamily;
+ fs->pf_select_family = Android_GetFamily;
fs->pf_get_fallbacks = Android_GetFallbacks;
if( Android_Prepare( fs ) == VLC_ENOMEM )
goto error;
#else
- fs->pf_get_family = StaticMap_GetFamily;
+ fs->pf_select_family = StaticMap_GetFamily;
fs->pf_get_fallbacks = NULL;
/* The default static fonts are also fallback fonts */
const char *const ppsz_default[] =
@@ -913,14 +935,17 @@ error:
void FontSelectDelete( vlc_font_select_t *fs )
{
#ifdef HAVE_FONTCONFIG
- if( fs->pf_get_family == FontConfig_GetFamily )
+ if( fs->pf_select_family == FontConfig_GetFamily )
FontConfig_Unprepare( fs );
#elif defined( _WIN32 )
- if( fs->pf_get_family == DWrite_GetFamily )
+ if( fs->pf_select_family == DWrite_GetFamily )
ReleaseDWrite( fs );
#endif
+ if( fs->families_lookup_lru )
+ vlc_lru_Release( fs->families_lookup_lru );
+
/* Dicts */
vlc_dictionary_clear( &fs->fallback_map, FreeFamilies, fs );
vlc_dictionary_clear( &fs->family_map, NULL, NULL );
@@ -930,13 +955,57 @@ void FontSelectDelete( vlc_font_select_t *fs )
free( fs );
}
-const vlc_family_t * FontSelectGetFamily( vlc_font_select_t *fs, const char *psz_lcname )
+const vlc_family_t * FontSelectFamily( vlc_font_select_t *fs, const char *psz_lcname )
{
- return fs->pf_get_family ? fs->pf_get_family( fs, psz_lcname ) : NULL;
+ const vlc_family_t *p_family = NULL;
+ if( fs->pf_select_family )
+ fs->pf_select_family( fs, psz_lcname, &p_family );
+ return p_family;
+}
+
+const vlc_family_t * FontSelectAmongFamilies( vlc_font_select_t *fs, const fontfamilies_t *families )
+{
+ /* We return empty NULL matches, so we check if key exists, not value */
+ if( vlc_lru_HasKey( fs->families_lookup_lru, families->psz_key ) )
+ return vlc_lru_Get( fs->families_lookup_lru, families->psz_key );
+
+ const vlc_family_t *p_family = NULL;
+ if( fs->pf_select_among_families )
+ {
+ if( fs->pf_select_among_families( fs, families, &p_family ) != VLC_SUCCESS )
+ p_family = NULL;
+ }
+ else if( fs->pf_select_family )
+ {
+ const char *psz_name;
+ vlc_vector_foreach( psz_name, &families->vec )
+ {
+ fs->pf_select_family( fs, psz_name, &p_family );
+ if( p_family )
+ break;
+ }
+ }
+ vlc_lru_Insert( fs->families_lookup_lru, families->psz_key, (void *) p_family );
+ return p_family;
}
-vlc_family_t * FontSelectGetFallbacks( vlc_font_select_t *fs, const char *psz_family,
- uni_char_t codepoint )
+vlc_family_t * FontFallbacksAmongFamilies( vlc_font_select_t *fs, const fontfamilies_t *families,
+ uni_char_t codepoint )
{
- return fs->pf_get_fallbacks ? fs->pf_get_fallbacks( fs, psz_family, codepoint ) : NULL;
+ vlc_family_t *p_res = NULL;
+ if ( fs->pf_get_fallbacks_among_families )
+ {
+ fs->pf_get_fallbacks_among_families( fs, families, codepoint, &p_res );
+ }
+ else if( fs->pf_get_fallbacks )
+ {
+ const char *psz_name;
+ vlc_vector_foreach( psz_name, &families->vec )
+ {
+ fs->pf_get_fallbacks( fs, psz_name, codepoint, &p_res );
+ if( p_res )
+ break;
+ }
+ }
+ return p_res;
}
diff --git a/modules/text_renderer/freetype/platform_fonts.h b/modules/text_renderer/freetype/platform_fonts.h
index 3ab71f9268..3d93ad0d59 100644
--- a/modules/text_renderer/freetype/platform_fonts.h
+++ b/modules/text_renderer/freetype/platform_fonts.h
@@ -155,6 +155,12 @@ struct vlc_family_t
vlc_font_t *p_fonts; /**< fonts matching this family */
};
+typedef struct
+{
+ const char *psz_key;
+ struct VLC_VECTOR(char *) vec;
+} fontfamilies_t;
+
#define FB_LIST_ATTACHMENTS "attachments"
#define FB_LIST_DEFAULT "default"
#define FB_NAME "fallback"
@@ -166,18 +172,18 @@ void FontSelectDelete( vlc_font_select_t * );
* Get a pointer to the vlc_family_t in the master list that matches \p psz_family.
* Add this family to the list if it hasn't been added yet.
*/
-const vlc_family_t * FontSelectGetFamily( vlc_font_select_t *, const char *psz_family );
+const vlc_family_t * FontSelectFamily( vlc_font_select_t *, const char *psz_family );
+const vlc_family_t * FontSelectAmongFamilies( vlc_font_select_t *, const fontfamilies_t * );
/**
- * Get the fallback list for \p psz_family from the system and cache
+ * Get the fallback list for \p fontfamilies_t from the system and cache
* it in \ref fallback_map.
* On Windows fallback lists are populated progressively as required
* using Uniscribe, so we need the codepoint here.
*/
-vlc_family_t * FontSelectGetFallbacks( vlc_font_select_t *, const char *psz_family,
+vlc_family_t * FontFallbacksAmongFamilies( vlc_font_select_t *, const fontfamilies_t *,
uni_char_t codepoint );
-
/* ******************
* Family and fonts *
********************/
More information about the vlc-commits
mailing list