[vlc-commits] freetype: implement GDI font linking fallback

2020-08-24 Thread Francois Cartegnie
vlc | branch: master | Francois Cartegnie  | 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), name, LF_FACESIZE );
+
+EnumFontFamiliesEx( hDC, , (FONTENUMPROC), 
(LPARAM), 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,  )))
+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, ,
+   NULL,  )) )
+{
+free( psz_buffer );
+RegCloseKey( fontLinkKey );
+return VLC_EGENERIC;
+}
+
+WCHAR* linkedFonts = (WCHAR*) malloc(linkedFontsBufferSize);
+
+if ( linkedFonts &&
+ SUCCEEDED(RegQueryValueEx( fontLinkKey, psz_buffer, 0, ,
+   (BYTE*)linkedFonts,  
) )
+&& 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, [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;
 inti_ret = VLC_EGENERIC;
 
 p_fallbacks = vlc_dictionary_value_for_key( >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, _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;
- 

[vlc-commits] freetype: implement GDI font linking fallback

2020-08-24 Thread Francois Cartegnie
vlc | branch: master | Francois Cartegnie  | Fri Aug 21 
00:10:34 2020 +0200| [a813845992587fbeaa434156d5b0d568e885bc48] | committer: 
Francois Cartegnie

freetype: implement GDI font linking fallback

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=a813845992587fbeaa434156d5b0d568e885bc48
---

 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), name, LF_FACESIZE );
+
+EnumFontFamiliesEx( hDC, , (FONTENUMPROC), 
(LPARAM), 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,  )))
+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, ,
+   NULL,  )) )
+{
+free( psz_buffer );
+RegCloseKey( fontLinkKey );
+return VLC_EGENERIC;
+}
+
+WCHAR* linkedFonts = (WCHAR*) malloc(linkedFontsBufferSize);
+
+if ( linkedFonts &&
+ SUCCEEDED(RegQueryValueEx( fontLinkKey, psz_buffer, 0, ,
+   (BYTE*)linkedFonts,  
) )
+&& 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, [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;
 inti_ret = VLC_EGENERIC;
 
 p_fallbacks = vlc_dictionary_value_for_key( >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, _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;
-