From e9fc538b529a9c3a1695b90108b7323272d50302 Mon Sep 17 00:00:00 2001 From: Bernie Purcell Date: Tue, 21 Aug 2007 07:49:24 +0000 Subject: [PATCH] Changes to get styled subtitles working with Windows --- configure.ac | 3 + extras/contrib/src/Distributions/win32.mak | 2 +- extras/contrib/src/Makefile | 28 ++++ extras/contrib/src/Patches/fontconfig.patch | 173 ++++++++++++++++++++ extras/contrib/src/packages.mak | 2 + modules/misc/freetype.c | 105 ++++++++++-- 6 files changed, 297 insertions(+), 16 deletions(-) create mode 100644 extras/contrib/src/Patches/fontconfig.patch diff --git a/configure.ac b/configure.ac index ee732a860b..ca709c8c4c 100644 --- a/configure.ac +++ b/configure.ac @@ -4133,6 +4133,9 @@ then VLC_ADD_PLUGINS([freetype]) VLC_ADD_CFLAGS([freetype],[`${FREETYPE_CONFIG} --cflags`]) VLC_ADD_LDFLAGS([freetype],[`${FREETYPE_CONFIG} --libs`]) + if test "${SYS}" = "mingw32"; then + VLC_ADD_LDFLAGS([freetype],[-lxml2])] + fi AC_CHECK_HEADERS(fontconfig/fontconfig.h, [VLC_ADD_CFLAGS([freetype],[-DHAVE_FONTCONFIG]) VLC_ADD_LDFLAGS([freetype],[-lfontconfig])]) diff --git a/extras/contrib/src/Distributions/win32.mak b/extras/contrib/src/Distributions/win32.mak index 836e64f53e..0efa421d48 100644 --- a/extras/contrib/src/Distributions/win32.mak +++ b/extras/contrib/src/Distributions/win32.mak @@ -6,6 +6,6 @@ all: .iconv .intl .freetype .fribidi .zlib \ .png .gpg-error .gcrypt .gnutls .mpcdec \ .dvdnav .dvbpsi .wxwidgets .qt4 .dirac .SDL_image \ .dx_headers .dshow_headers .gecko-win32 .unicows .dca \ - .lua .tag \ + .lua .tag .fontconfig \ .aclocal # .daap .cddb .cdio .vcdimager .portaudio diff --git a/extras/contrib/src/Makefile b/extras/contrib/src/Makefile index 4e1a0f769f..07222731c3 100644 --- a/extras/contrib/src/Makefile +++ b/extras/contrib/src/Makefile @@ -430,6 +430,34 @@ CLEAN_FILE += .iconv CLEAN_PKG += libiconv DISTCLEAN_PKG += libiconv-$(LIBICONV_VERSION).tar.gz +# *************************************************************************** +# fontconfig +# *************************************************************************** + +fontconfig-$(FONTCONFIG_VERSION).tar.gz: + $(WGET) $(FONTCONFIG_URL) + +fontconfig: fontconfig-$(FONTCONFIG_VERSION).tar.gz + $(EXTRACT_GZ) + patch -p0 < Patches/fontconfig.patch + +.fontconfig: fontconfig +ifdef HAVE_WIN32 + ifdef HAVE_CYGWIN + (cd $<; ./configure --target=$(HOST) --disable-pic --disable-shared --with-cache-dir=WINDOWSTEMPDIR --with-arch=i686 --prefix=$(PREFIX) && make && make install) + else + (cd $<; $(HOSTCC) ./configure $(HOSTCONF) --with-cache-dir=WINDOWSTEMPDIR --with-arch=i686 --prefix=$(PREFIX) && make && make install) + endif +else + (cd $<; $(HOSTCC) ./configure $(HOSTCONF) --prefix=$(PREFIX) && make && make install) +endif + $(INSTALL_NAME) + touch $@ + +CLEAN_FILE += .fontconfig +CLEAN_PKG += fontconfig +DISTCLEAN_PKG += fontconfig-$(FONTCONFIG_VERSION).tar.gz + # *************************************************************************** # freetype2 # *************************************************************************** diff --git a/extras/contrib/src/Patches/fontconfig.patch b/extras/contrib/src/Patches/fontconfig.patch new file mode 100644 index 0000000000..cc1a030765 --- /dev/null +++ b/extras/contrib/src/Patches/fontconfig.patch @@ -0,0 +1,173 @@ +--- fontconfig/src/Makefile.am Mon Sep 18 07:06:41 2006 ++++ fontconfig/src/Makefile.am Sat Aug 18 20:48:45 2007 +*************** +*** 31,35 **** + + install-libtool-import-lib: +- $(INSTALL) .libs/libfontconfig.dll.a $(DESTDIR)$(libdir) + $(INSTALL) fontconfig.def $(DESTDIR)$(libdir)/fontconfig.def + +--- 31,34 ---- +--- fontconfig/src/Makefile.in Sun Dec 3 10:27:33 2006 ++++ fontconfig/src/Makefile.in Sat Aug 18 20:53:40 2007 +*************** +*** 614,618 **** + + @OS_WIN32_TRUE@install-libtool-import-lib: +- @OS_WIN32_TRUE@ $(INSTALL) .libs/libfontconfig.dll.a $(DESTDIR)$(libdir) + @OS_WIN32_TRUE@ $(INSTALL) fontconfig.def $(DESTDIR)$(libdir)/fontconfig.def + +--- 614,617 ---- +--- fontconfig/src/fcinit.c Sun Dec 3 07:10:30 2006 ++++ fontconfig/src/fcinit.c Sun Aug 19 00:52:07 2007 +*************** +*** 26,32 **** +--- 26,94 ---- + #include + ++ #ifdef _WIN32 ++ #define STRICT ++ #include ++ #undef STRICT ++ ++ static char *IsWindowsDir(char *p_dir_in, char **p_dir_out) ++ { ++ *p_dir_out = NULL; ++ ++ if( ! strcmp( p_dir_in, "WINDOWSFONTDIR" )) ++ { ++ int rc; ++ ++ *p_dir_out = malloc( 1000 ); ++ if( !*p_dir_out ) ++ { ++ fprintf( stderr, "Fontconfig error: out of memory" ); ++ return p_dir_in; ++ } ++ rc = GetWindowsDirectory( *p_dir_out, 800 ); ++ if( rc == 0 || rc > 800 ) ++ { ++ fprintf( stderr, "Fontconfig error: GetWindowsDirectory failed" ); ++ free( *p_dir_out ); ++ *p_dir_out = NULL; ++ ++ return p_dir_in; ++ } ++ if( *p_dir_out[ strlen( *p_dir_out ) - 1 ] != '\\' ) ++ strcat( *p_dir_out, "\\" ); ++ strcat( *p_dir_out, "fonts" ); ++ ++ return *p_dir_out; ++ } ++ else if( ! strcmp( p_dir_in, "WINDOWSTEMPDIR" )) ++ { ++ int rc; ++ ++ *p_dir_out = malloc( 1000 ); ++ if( !*p_dir_out ) ++ { ++ fprintf( stderr, "Fontconfig error: out of memory" ); ++ return p_dir_in; ++ } ++ rc = GetTempPath( 800, *p_dir_out ); ++ if( rc == 0 || rc > 800 ) ++ { ++ fprintf( stderr, "Fontconfig error: GetTempPath failed" ); ++ free( *p_dir_out ); ++ *p_dir_out = NULL; ++ ++ return p_dir_in; ++ } ++ return *p_dir_out; ++ } ++ return p_dir_in; ++ } ++ #else ++ #define IsWindowsDir(A, B) A ++ #endif ++ + static FcConfig * + FcInitFallbackConfig (void) + { ++ char *p_dir_out = NULL; + FcConfig *config; + +*************** +*** 34,40 **** + if (!config) + goto bail0; +! if (!FcConfigAddDir (config, (FcChar8 *) FC_DEFAULT_FONTS)) + goto bail1; +! if (!FcConfigAddCacheDir (config, (FcChar8 *) FC_CACHEDIR)) + goto bail1; + return config; +--- 96,106 ---- + if (!config) + goto bail0; +! if (!FcConfigAddDir (config, (FcChar8 *) IsWindowsDir(FC_DEFAULT_FONTS, &p_dir_out))) + goto bail1; +! if (p_dir_out) +! free(p_dir_out); +! p_dir_out = NULL; +! +! if (!FcConfigAddCacheDir (config, (FcChar8 *) IsWindowsDir(FC_CACHEDIR, &p_dir_out))) + goto bail1; + return config; +*************** +*** 43,46 **** +--- 109,114 ---- + FcConfigDestroy (config); + bail0: ++ if (p_dir_out) ++ free(p_dir_out); + return 0; + } +*************** +*** 73,84 **** + if (config->cacheDirs && config->cacheDirs->num == 0) + { + fprintf (stderr, + "Fontconfig warning: no elements found. Check configuration.\n"); + fprintf (stderr, + "Fontconfig warning: adding %s\n", +! FC_CACHEDIR); + fprintf (stderr, + "Fontconfig warning: adding ~/.fontconfig\n"); +! if (!FcConfigAddCacheDir (config, (FcChar8 *) FC_CACHEDIR) || + !FcConfigAddCacheDir (config, (FcChar8 *) "~/.fontconfig")) + { +--- 141,158 ---- + if (config->cacheDirs && config->cacheDirs->num == 0) + { ++ char *p_dir_out = NULL; ++ + fprintf (stderr, + "Fontconfig warning: no elements found. Check configuration.\n"); + fprintf (stderr, + "Fontconfig warning: adding %s\n", +! IsWindowsDir(FC_CACHEDIR, &p_dir_out)); + fprintf (stderr, + "Fontconfig warning: adding ~/.fontconfig\n"); +! if (p_dir_out) +! free(p_dir_out); +! p_dir_out = NULL; +! +! if (!FcConfigAddCacheDir (config, (FcChar8 *) IsWindowsDir(FC_CACHEDIR, &p_dir_out)) || + !FcConfigAddCacheDir (config, (FcChar8 *) "~/.fontconfig")) + { +*************** +*** 86,91 **** +--- 160,172 ---- + "Fontconfig error: out of memory"); + FcConfigDestroy (config); ++ ++ if (p_dir_out) ++ free(p_dir_out); ++ p_dir_out = NULL; ++ + return FcInitFallbackConfig (); + } ++ if (p_dir_out) ++ free(p_dir_out); + } + diff --git a/extras/contrib/src/packages.mak b/extras/contrib/src/packages.mak index 30c228b215..aa1c3bb7a2 100644 --- a/extras/contrib/src/packages.mak +++ b/extras/contrib/src/packages.mak @@ -42,6 +42,8 @@ LIBICONV_VERSION=1.9.2 LIBICONV_URL=$(GNU)/libiconv/libiconv-$(LIBICONV_VERSION).tar.gz GETTEXT_VERSION=0.16.1 GETTEXT_URL=$(GNU)/gettext/gettext-$(GETTEXT_VERSION).tar.gz +FONTCONFIG_VERSION=2.4.2 +FONTCONFIG_URL=http://fontconfig.org/release/fontconfig-$(FONTCONFIG_VERSION).tar.gz FREETYPE2_VERSION=2.3.5 FREETYPE2_URL=$(SF)/freetype/freetype-$(FREETYPE2_VERSION).tar.gz FRIBIDI_VERSION=0.10.4 diff --git a/modules/misc/freetype.c b/modules/misc/freetype.c index 1b5fe8aefb..64b22b1aae 100644 --- a/modules/misc/freetype.c +++ b/modules/misc/freetype.c @@ -1,3 +1,4 @@ +#include /***************************************************************************** * freetype.c : Put text on the video, using freetype2 ***************************************************************************** @@ -238,6 +239,7 @@ typedef struct static int Render( filter_t *, subpicture_region_t *, line_desc_t *, int, int); static void FreeLines( line_desc_t * ); static void FreeLine( line_desc_t * ); +static void FontBuilder( vlc_object_t *p_this); /***************************************************************************** * filter_sys_t: freetype local data @@ -259,6 +261,8 @@ struct filter_sys_t int i_display_height; #ifdef HAVE_FONTCONFIG FcConfig *p_fontconfig; + vlc_bool_t b_fontconfig_ok; + vlc_mutex_t fontconfig_lock; #endif input_attachment_t **pp_font_attachments; @@ -332,10 +336,36 @@ static int Create( vlc_object_t *p_this ) } #ifdef HAVE_FONTCONFIG - if( FcInit() ) - p_sys->p_fontconfig = FcConfigGetCurrent(); + vlc_mutex_init( p_filter, &p_sys->fontconfig_lock ); + p_sys->b_fontconfig_ok = VLC_FALSE; + + p_sys->p_fontconfig = FcInitLoadConfig(); + + if( p_sys->p_fontconfig ) + { + /* Normally this doesn't take very long, but an initial build of + * the fontconfig database or the addition of a lot of new fonts + * can cause it to take several minutes for a large number of fonts. + * Even a small number can take several seconds - much longer than + * we can afford to block, so we build the list in the background + * and if it succeeds we allow fontconfig to be used. + */ + if( vlc_thread_create( p_filter, "fontlist builder", FontBuilder, + VLC_THREAD_PRIORITY_LOW, VLC_FALSE ) ) + { + /* Don't destroy the fontconfig object - we won't be able to do + * italics or bold or change the font face, but we will still + * be able to do underline and change the font size. + */ + msg_Warn( p_filter, "fontconfig database builder thread can't " + "be launched. Font styling support will be limited." ); + }; + } else - p_sys->p_fontconfig = NULL; + { + msg_Warn( p_filter, "Couldn't initialise Fontconfig. " + "Font styling won't be available." ); + } #endif i_error = FT_Init_FreeType( &p_sys->p_library ); if( i_error ) @@ -376,10 +406,11 @@ static int Create( vlc_object_t *p_this ) p_filter->pf_render_text = RenderText; #ifdef HAVE_FONTCONFIG - p_filter->pf_render_html = RenderHtml; -#else - p_filter->pf_render_html = NULL; + if( p_sys->p_fontconfig ) + p_filter->pf_render_html = RenderHtml; + else #endif + p_filter->pf_render_html = NULL; LoadFontsFromAttachments( p_filter ); @@ -416,8 +447,13 @@ static void Destroy( vlc_object_t *p_this ) } #ifdef HAVE_FONTCONFIG - FcConfigDestroy( p_sys->p_fontconfig ); - p_sys->p_fontconfig = NULL; + vlc_mutex_destroy( &p_sys->fontconfig_lock ); + + if( p_sys->p_fontconfig ) + { + FcConfigDestroy( p_sys->p_fontconfig ); + p_sys->p_fontconfig = NULL; + } /* FcFini asserts calling the subfunction FcCacheFini() * even if no other library functions have been made since FcInit(), * so don't call it. */ @@ -427,6 +463,38 @@ static void Destroy( vlc_object_t *p_this ) free( p_sys ); } +static void FontBuilder( vlc_object_t *p_this) +{ + filter_t *p_filter = (filter_t*)p_this; + filter_sys_t *p_sys = p_filter->p_sys; + time_t t1, t2; + + /* Find the session to announce */ + vlc_mutex_lock( &p_sys->fontconfig_lock ); + + msg_Dbg( p_filter, "Building font database..." ); + time(&t1); + if(! FcConfigBuildFonts( p_sys->p_fontconfig )) + { + /* Don't destroy the fontconfig object - we won't be able to do + * italics or bold or change the font face, but we will still + * be able to do underline and change the font size. + */ + msg_Err( p_filter, "fontconfig database can't be built. " + "Font styling won't be available" ); + } + time(&t2); + + msg_Dbg( p_filter, "Finished building font database." ); + if( t1 > 0 && t2 > 0 ) + msg_Dbg( p_filter, "Took %ld seconds", t2 - t1 ); + + FcConfigSetCurrent( p_sys->p_fontconfig ); + p_sys->b_fontconfig_ok = VLC_TRUE; + + vlc_mutex_unlock( &p_sys->fontconfig_lock ); +} + /***************************************************************************** * Make any TTF/OTF fonts present in the attachments of the media file * and store them for later use by the FreeType Engine @@ -2281,17 +2349,24 @@ static int ProcessLines( filter_t *p_filter, /* Look for a match amongst our attachments first */ CheckForEmbeddedFont( p_sys, &p_face, p_style ); - if( ! p_face ) + if( ! p_face && p_sys->b_fontconfig_ok ) { - char *psz_fontfile = FontConfig_Select( p_sys->p_fontconfig, - p_style->psz_fontname, - p_style->b_bold, - p_style->b_italic, - &i_idx ); + char *psz_fontfile; + + vlc_mutex_lock( &p_sys->fontconfig_lock ); + + psz_fontfile = FontConfig_Select( p_sys->p_fontconfig, + p_style->psz_fontname, + p_style->b_bold, + p_style->b_italic, + &i_idx ); + + vlc_mutex_unlock( &p_sys->fontconfig_lock ); + if( psz_fontfile ) { if( FT_New_Face( p_sys->p_library, - psz_fontfile ? psz_fontfile : "", i_idx, &p_face ) ) + psz_fontfile, i_idx, &p_face ) ) { free( psz_fontfile ); free( pp_char_styles );