[vlc-commits] freetype: implement GDI font linking fallback
Francois Cartegnie
git at videolan.org
Mon Aug 24 17:39:42 CEST 2020
vlc | branch: master | Francois Cartegnie <fcvlcdev at 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 )
More information about the vlc-commits
mailing list