]> git.sesse.net Git - vlc/blobdiff - modules/misc/freetype.c
Another bunch of useless test.
[vlc] / modules / misc / freetype.c
index 408a1e86f333f552ebd5e172e0ff56bca88b9d9b..3ba7a4085e90b9a945bb228f5867fbebd3962ab7 100644 (file)
  * Preamble
  *****************************************************************************/
 
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
 #include <vlc/vlc.h>
 #include <vlc_vout.h>
 #include <vlc_osd.h>
 #include <vlc_xml.h>
 #include <vlc_input.h>
 
-#ifdef HAVE_LINUX_LIMITS_H
-#   include <linux/limits.h>
-#endif
-
-#include <time.h>
 #include <math.h>
 #include <errno.h>
 
@@ -91,6 +90,7 @@ static int RenderHtml( filter_t *, subpicture_region_t *,
                        subpicture_region_t * );
 static char *FontConfig_Select( FcConfig *, const char *,
                                 vlc_bool_t, vlc_bool_t, int * );
+static int CheckIfFontBuildComplete( filter_t *p_filter );
 #endif
 static line_desc_t *NewLine( int );
 
@@ -275,11 +275,13 @@ struct filter_sys_t
  *****************************************************************************/
 static int Create( vlc_object_t *p_this )
 {
-    filter_t *p_filter = (filter_t *)p_this;
-    filter_sys_t *p_sys;
-    char *psz_fontfile = NULL;
-    int i_error;
-    vlc_value_t val;
+    filter_t      *p_filter = (filter_t *)p_this;
+    filter_sys_t  *p_sys;
+    char          *psz_fontfile = NULL;
+    int            i_error;
+    vlc_value_t    val;
+    vlc_mutex_t   *lock;
+    vlc_object_t  *p_fontbuilder;
 
     /* Allocate structure */
     p_filter->p_sys = p_sys = malloc( sizeof( filter_sys_t ) );
@@ -316,7 +318,7 @@ static int Create( vlc_object_t *p_this )
     psz_fontfile = val.psz_string;
     if( !psz_fontfile || !*psz_fontfile )
     {
-        if( psz_fontfile ) free( psz_fontfile );
+        free( psz_fontfile );
         psz_fontfile = (char *)malloc( PATH_MAX + 1 );
         if( !psz_fontfile )
         {
@@ -363,34 +365,58 @@ static int Create( vlc_object_t *p_this )
 #ifdef HAVE_FONTCONFIG
     vlc_mutex_init( p_filter, &p_sys->fontconfig_lock );
     p_sys->b_fontconfig_ok = VLC_FALSE;
+    p_sys->p_fontconfig    = NULL;
 
-    p_sys->p_fontconfig = FcInitLoadConfig();
+    /* Check for an existing Fontbuilder thread */
+    lock = var_AcquireMutex( "fontbuilder" );
+    p_fontbuilder = vlc_object_find_name( p_filter->p_libvlc,
+                                          "fontlist builder",
+                                          FIND_CHILD );
 
-    if( p_sys->p_fontconfig )
+    if( ! p_fontbuilder )
     {
-        /* 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.
+        /* Create the FontBuilder 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.
          */
-        if( vlc_thread_create( p_filter, "fontlist builder", FontBuilder,
-                       VLC_THREAD_PRIORITY_LOW, VLC_FALSE ) )
+
+        p_fontbuilder = vlc_object_create( p_filter->p_libvlc,
+                                           VLC_OBJECT_GENERIC );
+        if( p_fontbuilder )
         {
-            /* 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." );
-        };
+            p_fontbuilder->psz_object_name = "fontlist builder";
+            vlc_object_attach( p_fontbuilder, p_filter->p_libvlc );
+
+            var_Create( p_fontbuilder, "build-done", VLC_VAR_BOOL );
+            var_SetBool( p_fontbuilder, "build-done", VLC_FALSE );
+
+            if( vlc_thread_create( p_fontbuilder,
+                                   "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
+        {
+            vlc_object_release( p_fontbuilder );
+        }
     }
     else
     {
-        msg_Warn( p_filter, "Couldn't initialise Fontconfig. "
-                            "Font styling won't be available." );
+        vlc_object_release( p_fontbuilder );
     }
+    vlc_mutex_unlock( lock );
+
 #endif
 
     p_sys->i_use_kerning = FT_HAS_KERNING( p_sys->p_face );
@@ -399,18 +425,17 @@ static int Create( vlc_object_t *p_this )
     p_sys->i_default_font_size = val.i_int;
     if( SetFontSize( p_filter, 0 ) != VLC_SUCCESS ) goto error;
 
-    if( psz_fontfile ) free( psz_fontfile );
+    free( psz_fontfile );
 
     p_sys->pp_font_attachments = NULL;
     p_sys->i_font_attachments = 0;
 
     p_filter->pf_render_text = RenderText;
 #ifdef HAVE_FONTCONFIG
-    if( p_sys->p_fontconfig )
-        p_filter->pf_render_html = RenderHtml;
-    else
+    p_filter->pf_render_html = RenderHtml;
+#else
+    p_filter->pf_render_html = NULL;
 #endif
-        p_filter->pf_render_html = NULL;
 
     LoadFontsFromAttachments( p_filter );
 
@@ -419,7 +444,7 @@ static int Create( vlc_object_t *p_this )
  error:
     if( p_sys->p_face ) FT_Done_Face( p_sys->p_face );
     if( p_sys->p_library ) FT_Done_FreeType( p_sys->p_library );
-    if( psz_fontfile ) free( psz_fontfile );
+    free( psz_fontfile );
     free( p_sys );
     return VLC_EGENERIC;
 }
@@ -447,8 +472,6 @@ static void Destroy( vlc_object_t *p_this )
     }
 
 #ifdef HAVE_FONTCONFIG
-    /* wait for the FontBuilder thread to terminate */
-    vlc_thread_join( p_this );
     vlc_mutex_destroy( &p_sys->fontconfig_lock );
 
     if( p_sys->p_fontconfig )
@@ -469,33 +492,39 @@ static void Destroy( vlc_object_t *p_this )
 
 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;
+    FcConfig      *p_fontconfig = FcInitLoadConfig();
+    vlc_mutex_t   *lock;
 
-    /* Find the session to announce */
-    vlc_mutex_lock( &p_sys->fontconfig_lock );
+    vlc_thread_ready( p_this );
 
-    msg_Dbg( p_filter, "Building font database..." );
-    time(&t1);
-    if(! FcConfigBuildFonts( p_sys->p_fontconfig ))
+    if( 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);
+        mtime_t    t1, t2;
+
+        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_filter, "Finished building font database." );
-    if( t1 > 0 && t2 > 0 )
-        msg_Dbg( p_filter, "Took %ld seconds", t2 - t1 );
+        msg_Dbg( p_this, "Finished building font database." );
+        msg_Dbg( p_this, "Took %ld seconds", (long)((t2 - t1)/1000000) );
 
-    p_sys->b_fontconfig_ok = VLC_TRUE;
+        lock = var_AcquireMutex( "fontbuilder" );
+        var_SetBool( p_this, "build-done", VLC_TRUE );
 
-    vlc_mutex_unlock( &p_sys->fontconfig_lock );
+        FcConfigDestroy( p_fontconfig );
+        vlc_mutex_unlock( lock );
+    }
+    vlc_object_detach( p_this );
+    vlc_object_release( p_this );
 }
 
 #endif
@@ -709,7 +738,7 @@ static void UnderlineGlyphYUVA( int i_line_thickness, int i_line_offset, vlc_boo
                                 FT_BitmapGlyph  p_this_glyph, FT_Vector *p_this_glyph_pos,
                                 FT_BitmapGlyph  p_next_glyph, FT_Vector *p_next_glyph_pos,
                                 int i_glyph_tmax, int i_align_offset,
-                                uint8_t i_y, uint8_t i_u, uint8_t i_v, uint8_t i_alpha,
+                                uint8_t i_y, uint8_t i_u, uint8_t i_v,
                                 subpicture_region_t *p_region)
 {
     int y, x, z;
@@ -1011,7 +1040,7 @@ static int RenderYUVA( filter_t *p_filter, subpicture_region_t *p_region,
                                     p_line->pp_glyphs[i], &(p_line->p_glyph_pos[i]),
                                     p_line->pp_glyphs[i+1], &(p_line->p_glyph_pos[i+1]),
                                     i_glyph_tmax, i_align_offset,
-                                    i_y, i_u, i_v, i_alpha,
+                                    i_y, i_u, i_v,
                                     p_region);
             }
         }
@@ -1107,7 +1136,8 @@ static int RenderText( filter_t *p_filter, subpicture_region_t *p_region_out,
         i_out_bytes = i_in_bytes * sizeof( uint32_t );
         i_out_bytes_left = i_out_bytes;
         p_out_buffer = (char *)psz_unicode;
-        i_ret = vlc_iconv( iconv_handle, (const char**)&p_in_buffer, &i_in_bytes,
+        i_ret = vlc_iconv( iconv_handle, (const char**)&p_in_buffer,
+                           &i_in_bytes,
                            &p_out_buffer, &i_out_bytes_left );
 
         vlc_iconv_close( iconv_handle );
@@ -1125,7 +1155,7 @@ static int RenderText( filter_t *p_filter, subpicture_region_t *p_region_out,
 #if defined(HAVE_FRIBIDI)
     {
         uint32_t *p_fribidi_string;
-        int start_pos, pos = 0;
+        int32_t start_pos, pos = 0;
 
         p_fribidi_string = malloc( (i_string_length + 1) * sizeof(uint32_t) );
         if( !p_fribidi_string )
@@ -1135,9 +1165,10 @@ static int RenderText( filter_t *p_filter, subpicture_region_t *p_region_out,
         }
 
         /* Do bidi conversion line-by-line */
-        while(pos < i_string_length)
+        while( pos < i_string_length )
         {
-            while(pos < i_string_length) {
+            while( pos < i_string_length ) 
+            {
                 i_char = psz_unicode[pos];
                 if (i_char != '\r' && i_char != '\n')
                     break;
@@ -1145,7 +1176,8 @@ static int RenderText( filter_t *p_filter, subpicture_region_t *p_region_out,
                 ++pos;
             }
             start_pos = pos;
-            while(pos < i_string_length) {
+            while( pos < i_string_length )
+            {
                 i_char = psz_unicode[pos];
                 if (i_char == '\r' || i_char == '\n')
                     break;
@@ -1154,8 +1186,11 @@ static int RenderText( filter_t *p_filter, subpicture_region_t *p_region_out,
             if (pos > start_pos)
             {
                 FriBidiCharType base_dir = FRIBIDI_TYPE_LTR;
-                fribidi_log2vis((FriBidiChar*)psz_unicode + start_pos, pos - start_pos,
-                                &base_dir, (FriBidiChar*)p_fribidi_string + start_pos, 0, 0, 0);
+                fribidi_log2vis((FriBidiChar*)psz_unicode + start_pos,
+                                pos - start_pos,
+                                &base_dir,
+                                (FriBidiChar*)p_fribidi_string + start_pos,
+                                0, 0, 0);
             }
         }
 
@@ -1323,12 +1358,12 @@ static int RenderText( filter_t *p_filter, subpicture_region_t *p_region_out,
     else
         RenderYUVA( p_filter, p_region_out, p_lines, result.x, result.y );
 
-    if( psz_unicode_orig ) free( psz_unicode_orig );
+    free( psz_unicode_orig );
     FreeLines( p_lines );
     return VLC_SUCCESS;
 
  error:
-    if( psz_unicode_orig ) free( psz_unicode_orig );
+    free( psz_unicode_orig );
     FreeLines( p_lines );
     return VLC_EGENERIC;
 }
@@ -1358,8 +1393,7 @@ static void DeleteStyle( ft_style_t *p_style )
 {
     if( p_style )
     {
-        if( p_style->psz_fontname )
-            free( p_style->psz_fontname );
+        free( p_style->psz_fontname );
         free( p_style );
     }
 }
@@ -1758,7 +1792,7 @@ static int HandleFontAttributes( xml_reader_t *p_xml_reader,
         {
             if( !strcasecmp( "face", psz_name ) )
             {
-                if( psz_fontname ) free( psz_fontname );
+                free( psz_fontname );
                 psz_fontname = strdup( psz_value );
             }
             else if( !strcasecmp( "size", psz_name ) )
@@ -1933,8 +1967,8 @@ static void SetupKaraoke( xml_reader_t *p_xml_reader, uint32_t *pi_k_runs,
                     (*ppi_k_run_lengths)[ *pi_k_runs - 1 ] = 0;
             }
         }
-        if( psz_name )  free( psz_name );
-        if( psz_value ) free( psz_value );
+        free( psz_name );
+        free( psz_value );
     }
 }
 
@@ -2153,6 +2187,37 @@ static int CheckForEmbeddedFont( filter_sys_t *p_sys, FT_Face *pp_face, ft_style
     return VLC_EGENERIC;
 }
 
+static int CheckIfFontBuildComplete( filter_t *p_filter )
+{
+    filter_sys_t   *p_sys = p_filter->p_sys;
+    vlc_object_t   *p_fb = vlc_object_find_name( p_filter->p_libvlc,
+                                                 "fontlist builder",
+                                                 FIND_CHILD );
+    if( p_fb )
+    {
+        vlc_mutex_t *lock = var_AcquireMutex( "fontbuilder" );
+        vlc_value_t  val;
+
+        if( VLC_SUCCESS == var_Get( p_fb, "build-done", &val ))
+        {
+            p_sys->b_fontconfig_ok = val.b_bool;
+
+            if( p_sys->b_fontconfig_ok )
+            {
+                FcInit();
+                p_sys->p_fontconfig = FcConfigGetCurrent();
+            }
+            else
+                msg_Dbg( p_filter, "Font Build still not complete" );
+        }
+        vlc_mutex_unlock( lock );
+        vlc_object_release( p_fb );
+
+        return VLC_SUCCESS;
+    }
+    return VLC_EGENERIC;
+}
+
 static int ProcessLines( filter_t *p_filter,
                          uint32_t *psz_text,
                          int i_len,
@@ -2225,12 +2290,12 @@ static int ProcessLines( filter_t *p_filter,
             ! p_levels )
         {
             msg_Err( p_filter, "out of memory" );
-            if( p_levels )           free( p_levels );
-            if( p_old_positions )    free( p_old_positions );
-            if( p_new_positions )    free( p_new_positions );
-            if( p_fribidi_string )   free( p_fribidi_string );
-            if( pp_char_styles_new ) free( pp_char_styles_new );
-            if( pi_karaoke_bar )     free( pi_karaoke_bar );
+            free( p_levels );
+            free( p_old_positions );
+            free( p_new_positions );
+            free( p_fribidi_string );
+            free( pp_char_styles_new );
+            free( pi_karaoke_bar );
 
             free( pp_char_styles );
             return VLC_ENOMEM;
@@ -2338,8 +2403,8 @@ static int ProcessLines( filter_t *p_filter,
              i_start_pos += pi_k_run_lengths[ k ];
         }
     }
-    if( p_levels )         free( p_levels );
-    if( p_new_positions )  free( p_new_positions );
+    free( p_levels );
+    free( p_new_positions );
 
     FT_Vector tmp_result;
 
@@ -2369,10 +2434,15 @@ static int ProcessLines( filter_t *p_filter,
             /* Look for a match amongst our attachments first */
             CheckForEmbeddedFont( p_sys, &p_face, p_style );
 
+            if( !p_sys->b_fontconfig_ok )
+            {
+                if( VLC_EGENERIC == CheckIfFontBuildComplete( p_filter ))
+                    msg_Err( p_filter, "Can't find FontBuilder thread!" );
+            }
+
             if( ! p_face && p_sys->b_fontconfig_ok )
             {
                 char *psz_fontfile;
-
                 vlc_mutex_lock( &p_sys->fontconfig_lock );
 
                 psz_fontfile = FontConfig_Select( p_sys->p_fontconfig,
@@ -2380,7 +2450,6 @@ static int ProcessLines( filter_t *p_filter,
                                                   p_style->b_bold,
                                                   p_style->b_italic,
                                                   &i_idx );
-
                 vlc_mutex_unlock( &p_sys->fontconfig_lock );
 
                 if( psz_fontfile && ! *psz_fontfile )
@@ -2404,8 +2473,7 @@ static int ProcessLines( filter_t *p_filter,
 #if defined(HAVE_FRIBIDI)
                         free( psz_text );
 #endif
-                        if( pi_karaoke_bar )
-                            free( pi_karaoke_bar );
+                        free( pi_karaoke_bar );
                         return VLC_EGENERIC;
                     }
                     free( psz_fontfile );
@@ -2431,8 +2499,7 @@ static int ProcessLines( filter_t *p_filter,
 #if defined(HAVE_FRIBIDI)
                 free( psz_text );
 #endif
-                if( pi_karaoke_bar )
-                    free( pi_karaoke_bar );
+                free( pi_karaoke_bar );
                 return VLC_EGENERIC;
             }
             p_sys->i_use_kerning =
@@ -2450,8 +2517,7 @@ static int ProcessLines( filter_t *p_filter,
 #if defined(HAVE_FRIBIDI)
                 free( psz_text );
 #endif
-                if( pi_karaoke_bar )
-                    free( pi_karaoke_bar );
+                free( pi_karaoke_bar );
                 return VLC_ENOMEM;
             }
             memcpy( psz_unicode, psz_text + i_prev,
@@ -2470,8 +2536,7 @@ static int ProcessLines( filter_t *p_filter,
 #if defined(HAVE_FRIBIDI)
                         free( psz_text );
 #endif
-                        if( pi_karaoke_bar )
-                            free( pi_karaoke_bar );
+                        free( pi_karaoke_bar );
                         return VLC_ENOMEM;
                     }
                     /* New Color mode only works in YUVA rendering mode --
@@ -2505,8 +2570,7 @@ static int ProcessLines( filter_t *p_filter,
 #if defined(HAVE_FRIBIDI)
                     free( psz_text );
 #endif
-                    if( pi_karaoke_bar )
-                        free( pi_karaoke_bar );
+                    free( pi_karaoke_bar );
                     return VLC_EGENERIC;
                 }
 
@@ -2833,14 +2897,13 @@ static line_desc_t *NewLine( int i_count )
         ( p_line->pi_underline_offset == NULL ) ||
         ( p_line->pi_underline_thickness == NULL ) )
     {
-        if( p_line->pi_underline_thickness )
-            free( p_line->pi_underline_thickness );
-        if( p_line->pi_underline_offset ) free( p_line->pi_underline_offset );
-        if( p_line->p_fg_rgb ) free( p_line->p_fg_rgb );
-        if( p_line->p_bg_rgb ) free( p_line->p_bg_rgb );
-        if( p_line->p_fg_bg_ratio ) free( p_line->p_fg_bg_ratio );
-        if( p_line->p_glyph_pos ) free( p_line->p_glyph_pos );
-        if( p_line->pp_glyphs ) free( p_line->pp_glyphs );
+        free( p_line->pi_underline_thickness );
+        free( p_line->pi_underline_offset );
+        free( p_line->p_fg_rgb );
+        free( p_line->p_bg_rgb );
+        free( p_line->p_fg_bg_ratio );
+        free( p_line->p_glyph_pos );
+        free( p_line->pp_glyphs );
         free( p_line );
         return NULL;
     }