vlc | branch: master | Francois Cartegnie <fcvlc...@free.fr> | Fri Aug 21 00:10:34 2020 +0200| [db28beebd7d93cbf69003440570f008ac6ec88cd] | committer: Francois Cartegnie
freetype: implement GDI font linking fallback > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=db28beebd7d93cbf69003440570f008ac6ec88cd --- modules/text_renderer/freetype/fonts/backends.h | 1 + modules/text_renderer/freetype/fonts/win32.c | 115 +++++++++++++++++++++--- modules/text_renderer/freetype/platform_fonts.c | 8 ++ 3 files changed, 114 insertions(+), 10 deletions(-) diff --git a/modules/text_renderer/freetype/fonts/backends.h b/modules/text_renderer/freetype/fonts/backends.h index abfc1b1ca5..6730ba46a4 100644 --- a/modules/text_renderer/freetype/fonts/backends.h +++ b/modules/text_renderer/freetype/fonts/backends.h @@ -64,6 +64,7 @@ struct vlc_font_select_t #if defined( _WIN32 ) void *p_dw_sys; + vlc_dictionary_t fontlinking_map; #endif }; diff --git a/modules/text_renderer/freetype/fonts/win32.c b/modules/text_renderer/freetype/fonts/win32.c index 8b5f22c67c..17cc85371b 100644 --- a/modules/text_renderer/freetype/fonts/win32.c +++ b/modules/text_renderer/freetype/fonts/win32.c @@ -59,6 +59,7 @@ #if !VLC_WINSTORE_APP #define FONT_DIR_NT TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts") +#define FONT_LINKING_NT TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontLink\\SystemLink") static inline void AppendFamily( vlc_family_t **pp_list, vlc_family_t *p_family ) { @@ -396,6 +397,82 @@ static int CALLBACK EnumFontCallback(const ENUMLOGFONTEX *lpelfe, const NEWTEXTM return 1; } +static void FillLinkedFontsForFamily( vlc_font_select_t *fs, + LPTSTR name, vlc_family_t *p_family ) +{ + HDC hDC = GetDC( NULL ); + if( !hDC ) + return; + + struct enumFontCallbackContext ctx; + ctx.fs = fs; + ctx.p_family = p_family; + ctx.prevFullName[0] = 0; + + LOGFONT lf = { 0 }; + lf.lfCharSet = DEFAULT_CHARSET; + wcsncpy( (LPTSTR)&lf.lfFaceName, name, LF_FACESIZE ); + + EnumFontFamiliesEx( hDC, &lf, (FONTENUMPROC)&EnumFontCallback, (LPARAM)&ctx, 0 ); + ReleaseDC( NULL, hDC ); +} + +static int AddLinkedFonts( vlc_font_select_t *fs, const char *psz_family, + vlc_family_t *p_family ) +{ + HKEY fontLinkKey; + if (FAILED(RegOpenKeyEx( HKEY_LOCAL_MACHINE, FONT_LINKING_NT, + 0, KEY_READ, &fontLinkKey ))) + return VLC_EGENERIC; + + LPTSTR psz_buffer = ToWide( psz_family ); + if( !psz_buffer ) + { + RegCloseKey( fontLinkKey ); + return VLC_EGENERIC; + } + + DWORD linkedFontsBufferSize = 0; + DWORD lpType; + if( FAILED(RegQueryValueEx( fontLinkKey, psz_buffer, 0, &lpType, + NULL, &linkedFontsBufferSize )) ) + { + free( psz_buffer ); + RegCloseKey( fontLinkKey ); + return VLC_EGENERIC; + } + + WCHAR* linkedFonts = (WCHAR*) malloc(linkedFontsBufferSize); + + if ( linkedFonts && + SUCCEEDED(RegQueryValueEx( fontLinkKey, psz_buffer, 0, &lpType, + (BYTE*)linkedFonts, &linkedFontsBufferSize ) ) + && lpType == REG_MULTI_SZ) + { + DWORD start = 0; + for( DWORD i=0; i < linkedFontsBufferSize / sizeof(WCHAR); i++ ) + { + if( linkedFonts[i] == 0 && i > start ) + { + for( DWORD j=start + 1; j < i; j++ ) + { + if( linkedFonts[j] != ',' ) + continue; + FillLinkedFontsForFamily( fs, &linkedFonts[j + 1], p_family ); + break; + } + start = i + 1; + } + } + } + + free(psz_buffer); + free(linkedFonts); + RegCloseKey(fontLinkKey); + + return VLC_SUCCESS; +} + int Win32_GetFamily( vlc_font_select_t *fs, const char *psz_lcname, const vlc_family_t **pp_result ) { vlc_family_t *p_family = @@ -531,6 +608,7 @@ int Win32_GetFallbacks( vlc_font_select_t *fs, const char *psz_lcname, vlc_family_t *p_family = NULL; vlc_family_t *p_fallbacks = NULL; char *psz_uniscribe = NULL; + char *psz_linkname = NULL; int i_ret = VLC_EGENERIC; p_fallbacks = vlc_dictionary_value_for_key( &fs->fallback_map, psz_lcname ); @@ -553,23 +631,39 @@ int Win32_GetFallbacks( vlc_font_select_t *fs, const char *psz_lcname, goto done; } - const vlc_family_t *p_uniscribe = NULL; - if( Win32_GetFamily( fs, psz_uniscribe, &p_uniscribe ) != VLC_SUCCESS ) - goto done; - - if( !p_uniscribe || !p_uniscribe->p_fonts || - !CheckFace( fs, p_uniscribe->p_fonts, codepoint ) ) + /* Search for existing listing inserted from a different + * codepoint in fallbacks (and that means the fallback will not work) */ + for( vlc_family_t *p = p_fallbacks; p; p = p->p_next ) { - i_ret = VLC_SUCCESS; - goto done; + if( !strcasecmp( p->psz_name, psz_uniscribe ) ) + { + i_ret = VLC_SUCCESS; + goto done; + } } + /* Load the replied font, but might still can't provide codepoint + * as it could rely on font linking */ + const vlc_family_t *p_uniscribe = NULL; + if( Win32_GetFamily( fs, psz_uniscribe, &p_uniscribe ) != VLC_SUCCESS || + p_uniscribe == NULL ) + goto done; + + /* Create entry for the replied font */ p_family = NewFamily( fs, psz_uniscribe, NULL, NULL, NULL ); + if( !p_family ) + goto done; - if( unlikely( !p_family ) ) + if( asprintf( &psz_linkname, "\xF0\x9F\x94\x97%s", psz_uniscribe ) < 0 ) goto done; - p_family->p_fonts = p_uniscribe->p_fonts; + vlc_family_t *withlinked = NewFamily( fs, psz_linkname, NULL, NULL, NULL ); + if( withlinked ) + { + p_family->p_next = withlinked; + AddLinkedFonts( fs, psz_uniscribe, withlinked ); + vlc_dictionary_insert( &fs->fontlinking_map, psz_linkname, withlinked ); + } if( p_fallbacks ) AppendFamily( &p_fallbacks, p_family ); @@ -581,6 +675,7 @@ int Win32_GetFallbacks( vlc_font_select_t *fs, const char *psz_lcname, i_ret = VLC_SUCCESS; done: + free( psz_linkname ); free( psz_uniscribe ); *pp_result = p_family; return i_ret; diff --git a/modules/text_renderer/freetype/platform_fonts.c b/modules/text_renderer/freetype/platform_fonts.c index cab256f9d8..180de9dd5e 100644 --- a/modules/text_renderer/freetype/platform_fonts.c +++ b/modules/text_renderer/freetype/platform_fonts.c @@ -500,6 +500,12 @@ void DumpFamilies( vlc_font_select_t *fs ) msg_Dbg( p_obj, "fallback_map" ); msg_Dbg( p_obj, "-------------------" ); DumpDictionary( p_obj, &fs->fallback_map, false, -1 ); +# ifdef _WIN32 + msg_Dbg( p_obj, "-------------------" ); + msg_Dbg( p_obj, "fontlinking_map" ); + msg_Dbg( p_obj, "-------------------" ); + DumpDictionary( p_obj, &fs->fontlinking_map, true, 1 ); +# endif } #endif @@ -888,6 +894,7 @@ vlc_font_select_t * FontSelectNew( filter_t *p_filter ) fs->pf_select_family = CoreText_GetFamily; fs->pf_get_fallbacks = CoreText_GetFallbacks; #elif defined( _WIN32 ) + vlc_dictionary_init( &fs->fontlinking_map, 20 ); if( InitDWrite( fs ) == VLC_SUCCESS ) { fs->pf_select_family = DWrite_GetFamily; @@ -940,6 +947,7 @@ void FontSelectDelete( vlc_font_select_t *fs ) #elif defined( _WIN32 ) if( fs->pf_select_family == DWrite_GetFamily ) ReleaseDWrite( fs ); + vlc_dictionary_clear( &fs->fontlinking_map, FreeFamilies, fs ); #endif if( fs->families_lookup_lru ) _______________________________________________ vlc-commits mailing list vlc-commits@videolan.org https://mailman.videolan.org/listinfo/vlc-commits