+#ifdef HAVE_FONTCONFIG
+static vlc_mutex_t fb_lock = VLC_STATIC_MUTEX;
+
+static vlc_object_t *FontBuilderAttach( filter_t *p_filter )
+{
+ /* Check for an existing Fontbuilder thread */
+ vlc_mutex_lock( &fb_lock );
+ vlc_object_t *p_fontbuilder =
+ vlc_object_find_name( p_filter->p_libvlc,
+ "fontlist builder", FIND_CHILD );
+
+ if( !p_fontbuilder )
+ {
+ /* Create the FontBuilderThread thread as a child of a top-level
+ * object, so that it can survive the destruction of the
+ * freetype object - the fontlist only needs to be built once,
+ * and calling the fontbuild a second time while the first is
+ * still in progress can cause thread instabilities.
+ *
+ * XXX The fontbuilder will be destroy as soon as it is unused.
+ */
+
+ p_fontbuilder = vlc_object_create( p_filter->p_libvlc,
+ sizeof(vlc_object_t) );
+ if( p_fontbuilder )
+ {
+ p_fontbuilder->psz_object_name = strdup( "fontlist builder" );
+ p_fontbuilder->p_private = NULL;
+ vlc_object_set_destructor( p_fontbuilder, FontBuilderDestructor );
+
+ vlc_object_attach( p_fontbuilder, p_filter->p_libvlc );
+
+ var_Create( p_fontbuilder, "build-done", VLC_VAR_BOOL );
+ var_SetBool( p_fontbuilder, "build-done", false );
+
+ if( vlc_thread_create( p_fontbuilder,
+ "fontlist builder",
+ FontBuilderThread,
+ VLC_THREAD_PRIORITY_LOW,
+ false ) )
+ {
+ msg_Warn( p_filter, "fontconfig database builder thread can't "
+ "be launched. Font styling support will be limited." );
+ }
+ }
+ }
+ if( p_fontbuilder )
+ {
+ var_AddCallback( p_fontbuilder, "build-done", FontBuilderDone, p_filter );
+ FontBuilderGetFcConfig( p_filter, p_fontbuilder );
+ }
+ vlc_mutex_unlock( &fb_lock );
+ return p_fontbuilder;
+}
+static void FontBuilderDetach( filter_t *p_filter, vlc_object_t *p_fontbuilder )
+{
+ vlc_mutex_lock( &fb_lock );
+ if( p_fontbuilder )
+ {
+ const bool b_alive = vlc_object_alive( p_fontbuilder );
+
+ var_DelCallback( p_fontbuilder, "build-done", FontBuilderDone, p_filter );
+
+ /* We wait for the thread on the first FontBuilderDetach */
+ if( b_alive )
+ {
+ vlc_object_kill( p_fontbuilder );
+ vlc_mutex_unlock( &fb_lock );
+
+ /* We need to unlock otherwise we may not join (the thread waiting
+ * for the lock). It is safe to unlock as no one else will try a
+ * join and we have a reference on the object) */
+ vlc_thread_join( p_fontbuilder );
+
+ vlc_mutex_lock( &fb_lock );
+ }
+ vlc_object_release( p_fontbuilder );
+ }
+ vlc_mutex_unlock( &fb_lock );
+}
+static void* FontBuilderThread( vlc_object_t *p_this )
+{
+ FcConfig *p_fontconfig = FcInitLoadConfig();
+
+ vlc_thread_ready( p_this );
+
+ if( p_fontconfig )
+ {
+ mtime_t t1, t2;
+ int canc = vlc_savecancel ();
+
+ //msg_Dbg( p_this, "Building font database..." );
+ msg_Dbg( p_this, "Building font database..." );
+ t1 = mdate();
+ if(! FcConfigBuildFonts( 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_this, "fontconfig database can't be built. "
+ "Font styling won't be available" );
+ }
+ t2 = mdate();
+
+ msg_Dbg( p_this, "Finished building font database." );
+ msg_Dbg( p_this, "Took %ld seconds", (long)((t2 - t1)/1000000) );
+
+ vlc_mutex_lock( &fb_lock );
+ p_this->p_private = p_fontconfig;
+ vlc_mutex_unlock( &fb_lock );
+
+ var_SetBool( p_this, "build-done", true );
+ vlc_restorecancel (canc);
+ }
+ return NULL;
+}
+static void FontBuilderGetFcConfig( filter_t *p_filter, vlc_object_t *p_fontbuilder )
+{
+ filter_sys_t *p_sys = p_filter->p_sys;
+
+ p_sys->p_fontconfig = p_fontbuilder->p_private;
+ p_sys->b_fontconfig_ok = p_fontbuilder->p_private != NULL;
+}
+static void FontBuilderDestructor( vlc_object_t *p_this )
+{
+ FcConfig *p_fontconfig = p_this->p_private;
+
+ if( p_fontconfig )
+ FcConfigDestroy( p_fontconfig );
+}
+static int FontBuilderDone( vlc_object_t *p_this, const char *psz_var,
+ vlc_value_t oldval, vlc_value_t newval, void *param )
+{
+ filter_t *p_filter = param;
+
+ if( newval.b_bool )
+ {
+ vlc_mutex_lock( &fb_lock );
+
+ FontBuilderGetFcConfig( p_filter, p_this );
+
+ vlc_mutex_unlock( &fb_lock );
+ }
+
+ VLC_UNUSED(psz_var);
+ VLC_UNUSED(oldval);
+ return VLC_SUCCESS;
+}
+#endif
+
+/*****************************************************************************
+ * Make any TTF/OTF fonts present in the attachments of the media file
+ * and store them for later use by the FreeType Engine
+ *****************************************************************************/
+static int LoadFontsFromAttachments( filter_t *p_filter )
+{
+ filter_sys_t *p_sys = p_filter->p_sys;
+ input_thread_t *p_input;
+ input_attachment_t **pp_attachments;
+ int i_attachments_cnt;
+ int k;
+ int rv = VLC_SUCCESS;
+
+ p_input = (input_thread_t *)vlc_object_find( p_filter, VLC_OBJECT_INPUT, FIND_PARENT );
+ if( ! p_input )
+ return VLC_EGENERIC;
+
+ if( VLC_SUCCESS != input_Control( p_input, INPUT_GET_ATTACHMENTS, &pp_attachments, &i_attachments_cnt ))
+ {
+ vlc_object_release(p_input);
+ return VLC_EGENERIC;
+ }
+
+ p_sys->i_font_attachments = 0;
+ p_sys->pp_font_attachments = malloc( i_attachments_cnt * sizeof( input_attachment_t * ));
+ if(! p_sys->pp_font_attachments )
+ rv = VLC_ENOMEM;
+
+ for( k = 0; k < i_attachments_cnt; k++ )
+ {
+ input_attachment_t *p_attach = pp_attachments[k];
+
+ if( p_sys->pp_font_attachments )
+ {
+ if(( !strcmp( p_attach->psz_mime, "application/x-truetype-font" ) || // TTF
+ !strcmp( p_attach->psz_mime, "application/x-font-otf" ) ) && // OTF
+ ( p_attach->i_data > 0 ) &&
+ ( p_attach->p_data != NULL ) )
+ {
+ p_sys->pp_font_attachments[ p_sys->i_font_attachments++ ] = p_attach;
+ }
+ else
+ {
+ vlc_input_attachment_Delete( p_attach );
+ }
+ }
+ else
+ {
+ vlc_input_attachment_Delete( p_attach );
+ }
+ }
+ free( pp_attachments );
+
+ vlc_object_release(p_input);
+
+ return rv;
+}
+