X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fmisc%2Ffreetype.c;h=421c3e943dd085c41d912b9cf8b77f0cc0198fe6;hb=1a112b8a40daf2a86ad1aa310b8eb4fe1255bdce;hp=1b5fe8aefb38360d90dd0384d3ed2e8cc9488b01;hpb=e40d134c69b144327fd1d2001e8b85640f5c7cb9;p=vlc diff --git a/modules/misc/freetype.c b/modules/misc/freetype.c index 1b5fe8aefb..421c3e943d 100644 --- a/modules/misc/freetype.c +++ b/modules/misc/freetype.c @@ -27,11 +27,12 @@ * Preamble *****************************************************************************/ -#ifdef HAVE_LINUX_LIMITS_H -# include +#ifdef HAVE_CONFIG_H +# include "config.h" #endif -#include +#include +#include #include #include #include @@ -41,10 +42,7 @@ #include #include - -#ifdef HAVE_ERRNO_H -# include -#endif +#include #include #include FT_FREETYPE_H @@ -75,6 +73,8 @@ #include #endif +#include + typedef struct line_desc_t line_desc_t; /***************************************************************************** @@ -92,7 +92,9 @@ static int RenderText( filter_t *, subpicture_region_t *, 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 * ); + bool, bool, int * ); +static int BuildDone( vlc_object_t*, const char *, vlc_value_t, vlc_value_t, + void* ); #endif static line_desc_t *NewLine( int ); @@ -125,9 +127,9 @@ static void YUVFromRGB( uint32_t i_argb, "fonts that will be rendered on the video. If absolute font size is set, "\ "relative size will be overriden." ) -static int pi_sizes[] = { 20, 18, 16, 12, 6 }; -static const char *ppsz_sizes_text[] = { N_("Smaller"), N_("Small"), N_("Normal"), - N_("Large"), N_("Larger") }; +static const int pi_sizes[] = { 20, 18, 16, 12, 6 }; +static const char *const ppsz_sizes_text[] = { + N_("Smaller"), N_("Small"), N_("Normal"), N_("Large"), N_("Larger") }; #define YUVP_TEXT N_("Use YUVP renderer") #define YUVP_LONGTEXT N_("This renders the font using \"paletized YUV\". " \ "This option is only needed if you want to encode into DVB subtitles" ) @@ -139,49 +141,49 @@ static const char *ppsz_sizes_text[] = { N_("Smaller"), N_("Small"), N_("Normal" #define EFFECT_OUTLINE 2 #define EFFECT_OUTLINE_FAT 3 -static int pi_effects[] = { 1, 2, 3 }; -static const char *ppsz_effects_text[] = { N_("Background"),N_("Outline"), - N_("Fat Outline") }; -static int pi_color_values[] = { +static int const pi_effects[] = { 1, 2, 3 }; +static const char *const ppsz_effects_text[] = { + N_("Background"),N_("Outline"), N_("Fat Outline") }; +static const int pi_color_values[] = { 0x00000000, 0x00808080, 0x00C0C0C0, 0x00FFFFFF, 0x00800000, 0x00FF0000, 0x00FF00FF, 0x00FFFF00, 0x00808000, 0x00008000, 0x00008080, 0x0000FF00, 0x00800080, 0x00000080, 0x000000FF, 0x0000FFFF }; -static const char *ppsz_color_descriptions[] = { +static const char *const ppsz_color_descriptions[] = { N_("Black"), N_("Gray"), N_("Silver"), N_("White"), N_("Maroon"), N_("Red"), N_("Fuchsia"), N_("Yellow"), N_("Olive"), N_("Green"), N_("Teal"), N_("Lime"), N_("Purple"), N_("Navy"), N_("Blue"), N_("Aqua") }; vlc_module_begin(); - set_shortname( _("Text renderer")); - set_description( _("Freetype2 font renderer") ); + set_shortname( N_("Text renderer")); + set_description( N_("Freetype2 font renderer") ); set_category( CAT_VIDEO ); set_subcategory( SUBCAT_VIDEO_SUBPIC ); add_file( "freetype-font", DEFAULT_FONT, NULL, FONT_TEXT, FONT_LONGTEXT, - VLC_FALSE ); + false ); add_integer( "freetype-fontsize", 0, NULL, FONTSIZE_TEXT, - FONTSIZE_LONGTEXT, VLC_TRUE ); + FONTSIZE_LONGTEXT, true ); /* opacity valid on 0..255, with default 255 = fully opaque */ add_integer_with_range( "freetype-opacity", 255, 0, 255, NULL, - OPACITY_TEXT, OPACITY_LONGTEXT, VLC_TRUE ); + OPACITY_TEXT, OPACITY_LONGTEXT, true ); /* hook to the color values list, with default 0x00ffffff = white */ add_integer( "freetype-color", 0x00FFFFFF, NULL, COLOR_TEXT, - COLOR_LONGTEXT, VLC_FALSE ); + COLOR_LONGTEXT, false ); change_integer_list( pi_color_values, ppsz_color_descriptions, 0 ); add_integer( "freetype-rel-fontsize", 16, NULL, FONTSIZER_TEXT, - FONTSIZER_LONGTEXT, VLC_FALSE ); + FONTSIZER_LONGTEXT, false ); change_integer_list( pi_sizes, ppsz_sizes_text, 0 ); add_integer( "freetype-effect", 2, NULL, EFFECT_TEXT, - EFFECT_LONGTEXT, VLC_FALSE ); + EFFECT_LONGTEXT, false ); change_integer_list( pi_effects, ppsz_effects_text, 0 ); add_bool( "freetype-yuvp", 0, NULL, YUVP_TEXT, - YUVP_LONGTEXT, VLC_TRUE ); + YUVP_LONGTEXT, true ); set_capability( "text renderer", 100 ); add_shortcut( "text" ); set_callbacks( Create, Destroy ); @@ -200,7 +202,7 @@ struct line_desc_t uint32_t *p_fg_rgb; uint32_t *p_bg_rgb; uint8_t *p_fg_bg_ratio; /* 0x00=100% FG --> 0x7F=100% BG */ - vlc_bool_t b_new_color_mode; + bool b_new_color_mode; /** underline information -- only supplied if text should be underlined */ uint16_t *pi_underline_offset; uint16_t *pi_underline_thickness; @@ -229,15 +231,18 @@ typedef struct int i_font_size; uint32_t i_font_color; /* ARGB */ uint32_t i_karaoke_bg_color; /* ARGB */ - vlc_bool_t b_italic; - vlc_bool_t b_bold; - vlc_bool_t b_underline; + bool b_italic; + bool b_bold; + bool b_underline; char *psz_fontname; } ft_style_t; 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 * ); +#ifdef HAVE_FONTCONFIG +static void FontBuilder( vlc_object_t *p_this); +#endif /***************************************************************************** * filter_sys_t: freetype local data @@ -249,7 +254,7 @@ struct filter_sys_t { FT_Library p_library; /* handle to library */ FT_Face p_face; /* handle to face object */ - vlc_bool_t i_use_kerning; + bool i_use_kerning; uint8_t i_font_opacity; int i_font_color; int i_font_size; @@ -259,6 +264,8 @@ struct filter_sys_t int i_display_height; #ifdef HAVE_FONTCONFIG FcConfig *p_fontconfig; + bool b_fontconfig_ok; + vlc_mutex_t fontconfig_lock; #endif input_attachment_t **pp_font_attachments; @@ -272,19 +279,17 @@ 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_object_t *p_fontbuilder; /* Allocate structure */ p_filter->p_sys = p_sys = malloc( sizeof( filter_sys_t ) ); if( !p_sys ) - { - msg_Err( p_filter, "out of memory" ); return VLC_ENOMEM; - } p_sys->p_face = 0; p_sys->p_library = 0; p_sys->i_font_size = 0; @@ -313,13 +318,10 @@ 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 ) - { - msg_Err( p_filter, "out of memory" ); goto error; - } #ifdef WIN32 GetWindowsDirectory( psz_fontfile, PATH_MAX + 1 ); strcat( psz_fontfile, "\\fonts\\arial.ttf" ); @@ -331,12 +333,6 @@ static int Create( vlc_object_t *p_this ) #endif } -#ifdef HAVE_FONTCONFIG - if( FcInit() ) - p_sys->p_fontconfig = FcConfigGetCurrent(); - else - p_sys->p_fontconfig = NULL; -#endif i_error = FT_Init_FreeType( &p_sys->p_library ); if( i_error ) { @@ -363,13 +359,71 @@ static int Create( vlc_object_t *p_this ) goto error; } +#ifdef HAVE_FONTCONFIG + vlc_mutex_init( &p_sys->fontconfig_lock ); + p_sys->b_fontconfig_ok = false; + p_sys->p_fontconfig = NULL; + + /* Check for an existing Fontbuilder thread */ + vlc_mutex_t *lock = var_AcquireMutex( "fontbuilder" ); + p_fontbuilder = vlc_object_find_name( p_filter->p_libvlc, + "fontlist builder", + FIND_CHILD ); + + if( ! p_fontbuilder ) + { + /* 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. + */ + + p_fontbuilder = vlc_object_create( p_filter->p_libvlc, + sizeof(vlc_object_t) ); + if( p_fontbuilder ) + { + p_fontbuilder->psz_object_name = strdup( "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", false ); + var_AddCallback( p_fontbuilder, "build-done", BuildDone, p_sys ); + + if( vlc_thread_create( p_fontbuilder, + "fontlist builder", + FontBuilder, + VLC_THREAD_PRIORITY_LOW, + 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 + { + vlc_object_release( p_fontbuilder ); + } + vlc_mutex_unlock( lock ); + +#endif + p_sys->i_use_kerning = FT_HAS_KERNING( p_sys->p_face ); var_Get( p_filter, "freetype-fontsize", &val ); 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; @@ -388,7 +442,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; } @@ -416,8 +470,23 @@ static void Destroy( vlc_object_t *p_this ) } #ifdef HAVE_FONTCONFIG - FcConfigDestroy( p_sys->p_fontconfig ); - p_sys->p_fontconfig = NULL; + vlc_mutex_t *lock = var_AcquireMutex( "fontbuilder" ); + vlc_object_t *p_fontbuilder = vlc_object_find_name( p_filter->p_libvlc, + "fontlist builder", FIND_CHILD ); + if( p_fontbuilder ) + { + var_DelCallback( p_fontbuilder, "build-done", BuildDone, p_sys ); + vlc_object_release( p_fontbuilder ); + } + vlc_mutex_unlock( lock ); + + 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 +496,48 @@ static void Destroy( vlc_object_t *p_this ) free( p_sys ); } +#ifdef HAVE_FONTCONFIG + +static void FontBuilder( vlc_object_t *p_this ) +{ + FcConfig *p_fontconfig = FcInitLoadConfig(); + vlc_mutex_t *lock; + + vlc_thread_ready( p_this ); + + if( p_fontconfig ) + { + 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_this, "Finished building font database." ); + msg_Dbg( p_this, "Took %ld seconds", (long)((t2 - t1)/1000000) ); + + lock = var_AcquireMutex( "fontbuilder" ); + + var_SetBool( p_this, "build-done", true ); + + FcConfigDestroy( p_fontconfig ); + vlc_mutex_unlock( lock ); + } + vlc_object_detach( p_this ); + vlc_object_release( p_this ); +} + +#endif + /***************************************************************************** * Make any TTF/OTF fonts present in the attachments of the media file * and store them for later use by the FreeType Engine @@ -443,9 +554,12 @@ static int LoadFontsFromAttachments( filter_t *p_filter ) 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 * )); @@ -475,7 +589,9 @@ static int LoadFontsFromAttachments( filter_t *p_filter ) vlc_input_attachment_Delete( p_attach ); } } - free( pp_attachments ); + free( pp_attachments ); + + vlc_object_release(p_input); return rv; } @@ -627,11 +743,11 @@ static int Render( filter_t *p_filter, subpicture_region_t *p_region, return VLC_SUCCESS; } -static void UnderlineGlyphYUVA( int i_line_thickness, int i_line_offset, vlc_bool_t b_ul_next_char, +static void UnderlineGlyphYUVA( int i_line_thickness, int i_line_offset, bool b_ul_next_char, 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; @@ -658,7 +774,7 @@ static void UnderlineGlyphYUVA( int i_line_thickness, int i_line_offset, vlc_boo } for( x = 0; x < i_extra; x++ ) { - vlc_bool_t b_ok = VLC_TRUE; + bool b_ok = true; /* break the underline around the tails of any glyphs which cross it */ for( z = x - i_line_thickness; @@ -672,7 +788,7 @@ static void UnderlineGlyphYUVA( int i_line_thickness, int i_line_offset, vlc_boo if( ( p_next_glyph->bitmap.rows > i_row ) && p_next_glyph->bitmap.buffer[p_next_glyph->bitmap.width * i_row + z-i_extra] ) { - b_ok = VLC_FALSE; + b_ok = false; } } else if ((z > 0 ) && (z < p_this_glyph->bitmap.width)) @@ -682,7 +798,7 @@ static void UnderlineGlyphYUVA( int i_line_thickness, int i_line_offset, vlc_boo if( ( p_this_glyph->bitmap.rows > i_row ) && p_this_glyph->bitmap.buffer[p_this_glyph->bitmap.width * i_row + z] ) { - b_ok = VLC_FALSE; + b_ok = false; } } } @@ -933,7 +1049,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); } } @@ -978,7 +1094,7 @@ static int RenderText( filter_t *p_filter, subpicture_region_t *p_region_out, if( VLC_SUCCESS == var_Get( p_filter, "scale", &val )) i_scale = val.i_int; - + if( p_region_in->p_style ) { i_font_color = __MAX( __MIN( p_region_in->p_style->i_font_color, 0xFFFFFF ), 0 ); @@ -1006,10 +1122,7 @@ static int RenderText( filter_t *p_filter, subpicture_region_t *p_region_out, psz_unicode = psz_unicode_orig = malloc( ( strlen(psz_string) + 1 ) * sizeof(uint32_t) ); if( psz_unicode == NULL ) - { - msg_Err( p_filter, "out of memory" ); goto error; - } #if defined(WORDS_BIGENDIAN) iconv_handle = vlc_iconv_open( "UCS-4BE", "UTF-8" ); #else @@ -1029,15 +1142,16 @@ 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 ); if( i_in_bytes ) { - msg_Warn( p_filter, "failed to convert string to unicode (%s), " - "bytes left %d", strerror(errno), (int)i_in_bytes ); + msg_Warn( p_filter, "failed to convert string to unicode (%m), " + "bytes left %u", (unsigned)i_in_bytes ); goto error; } *(uint32_t*)p_out_buffer = 0; @@ -1047,19 +1161,17 @@ 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 ) - { - msg_Err( p_filter, "out of memory" ); goto error; - } /* 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; @@ -1067,7 +1179,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; @@ -1076,8 +1189,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); } } @@ -1090,10 +1206,7 @@ static int RenderText( filter_t *p_filter, subpicture_region_t *p_region_out, /* Calculate relative glyph positions and a bounding box for the * entire string */ if( !(p_line = NewLine( strlen( psz_string ))) ) - { - msg_Err( p_filter, "out of memory" ); goto error; - } p_lines = p_line; i_pen_x = i_pen_y = 0; i_previous = i = 0; @@ -1114,10 +1227,7 @@ static int RenderText( filter_t *p_filter, subpicture_region_t *p_region_out, { psz_line_start = psz_unicode; if( !(p_next = NewLine( strlen( psz_string ))) ) - { - msg_Err( p_filter, "out of memory" ); goto error; - } p_line->p_next = p_next; p_line->i_width = line.xMax; p_line->i_height = face->size->metrics.height >> 6; @@ -1180,17 +1290,29 @@ static int RenderText( filter_t *p_filter, subpicture_region_t *p_region_out, glyph_size.xMin + ((FT_BitmapGlyph)tmp_glyph)->left; if( line.xMax > (int)p_filter->fmt_out.video.i_visible_width - 20 ) { + FT_Done_Glyph( (FT_Glyph)p_line->pp_glyphs[ i ] ); p_line->pp_glyphs[ i ] = NULL; FreeLine( p_line ); p_line = NewLine( strlen( psz_string )); if( p_prev ) p_prev->p_next = p_line; else p_lines = p_line; + uint32_t *psz_unicode_saved = psz_unicode; while( psz_unicode > psz_line_start && *psz_unicode != ' ' ) { psz_unicode--; } if( psz_unicode == psz_line_start ) + { /* try harder to break that line */ + psz_unicode = psz_unicode_saved; + while( psz_unicode > psz_line_start && + *psz_unicode != '_' && *psz_unicode != '/' && + *psz_unicode != '\\' && *psz_unicode != '.' ) + { + psz_unicode--; + } + } + if( psz_unicode == psz_line_start ) { msg_Warn( p_filter, "unbreakable string" ); goto error; @@ -1234,20 +1356,20 @@ 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; } #ifdef HAVE_FONTCONFIG static ft_style_t *CreateStyle( char *psz_fontname, int i_font_size, - uint32_t i_font_color, uint32_t i_karaoke_bg_color, vlc_bool_t b_bold, - vlc_bool_t b_italic, vlc_bool_t b_uline ) + uint32_t i_font_color, uint32_t i_karaoke_bg_color, bool b_bold, + bool b_italic, bool b_uline ) { ft_style_t *p_style = malloc( sizeof( ft_style_t )); @@ -1269,18 +1391,17 @@ 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 ); } } -static vlc_bool_t StyleEquals( ft_style_t *s1, ft_style_t *s2 ) +static bool StyleEquals( ft_style_t *s1, ft_style_t *s2 ) { if( !s1 || !s2 ) - return VLC_FALSE; + return false; if( s1 == s2 ) - return VLC_TRUE; + return true; if(( s1->i_font_size == s2->i_font_size ) && ( s1->i_font_color == s2->i_font_color ) && @@ -1289,9 +1410,9 @@ static vlc_bool_t StyleEquals( ft_style_t *s1, ft_style_t *s2 ) ( s1->b_underline == s2->b_underline ) && ( !strcmp( s1->psz_fontname, s2->psz_fontname ))) { - return VLC_TRUE; + return true; } - return VLC_FALSE; + return false; } static int PushFont( font_stack_t **p_font, const char *psz_name, int i_size, @@ -1420,8 +1541,8 @@ static void IconvText( filter_t *p_filter, const char *psz_string, if( i_in_bytes ) { - msg_Warn( p_filter, "failed to convert string to unicode (%s), " - "bytes left %d", strerror(errno), (int)i_in_bytes ); + msg_Warn( p_filter, "failed to convert string to unicode (%m), " + "bytes left %u", (unsigned)i_in_bytes ); } else { @@ -1438,8 +1559,8 @@ static void IconvText( filter_t *p_filter, const char *psz_string, } static ft_style_t *GetStyleFromFontStack( filter_sys_t *p_sys, - font_stack_t **p_fonts, vlc_bool_t b_bold, vlc_bool_t b_italic, - vlc_bool_t b_uline ) + font_stack_t **p_fonts, bool b_bold, bool b_italic, + bool b_uline ) { ft_style_t *p_style = NULL; @@ -1458,7 +1579,7 @@ static ft_style_t *GetStyleFromFontStack( filter_sys_t *p_sys, } static int RenderTag( filter_t *p_filter, FT_Face p_face, int i_font_color, - vlc_bool_t b_uline, int i_karaoke_bgcolor, + bool b_uline, int i_karaoke_bgcolor, line_desc_t *p_line, uint32_t *psz_unicode, int *pi_pen_x, int i_pen_y, int *pi_start, FT_Vector *p_result ) @@ -1466,7 +1587,7 @@ static int RenderTag( filter_t *p_filter, FT_Face p_face, int i_font_color, FT_BBox line; int i_yMin, i_yMax; int i; - vlc_bool_t b_first_on_line = VLC_TRUE; + bool b_first_on_line = true; int i_previous = 0; int i_pen_x_start = *pi_pen_x; @@ -1492,7 +1613,7 @@ static int RenderTag( filter_t *p_filter, FT_Face p_face, int i_font_color, i_yMax = line.yMax; if( line.xMax > 0 ) - b_first_on_line = VLC_FALSE; + b_first_on_line = false; while( *psz_unicode && ( *psz_unicode != '\n' ) ) { @@ -1625,9 +1746,8 @@ static int RenderTag( filter_t *p_filter, FT_Face p_face, int i_font_color, { *psz_unicode_start = '\0'; } - else + else if( psz_unicode > psz_unicode_start ) { - psz_unicode++; for( i=0; psz_unicode[ i ]; i++ ) psz_unicode_start[ i ] = psz_unicode[ i ]; psz_unicode_start[ i ] = '\0'; @@ -1670,7 +1790,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 ) ) @@ -1840,13 +1960,13 @@ static void SetupKaraoke( xml_reader_t *p_xml_reader, uint32_t *pi_k_runs, } if( *ppi_k_durations ) (*ppi_k_durations)[ *pi_k_runs - 1 ] = atoi( psz_value ); - + if( *ppi_k_run_lengths ) (*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 ); } } @@ -1860,7 +1980,7 @@ static int ProcessNodes( filter_t *p_filter, uint32_t **ppi_run_lengths, ft_style_t ***ppp_styles, - vlc_bool_t b_karaoke, + bool b_karaoke, uint32_t *pi_k_runs, uint32_t **ppi_k_run_lengths, uint32_t **ppi_k_durations ) @@ -1874,13 +1994,13 @@ static int ProcessNodes( filter_t *p_filter, char *psz_node = NULL; - vlc_bool_t b_italic = VLC_FALSE; - vlc_bool_t b_bold = VLC_FALSE; - vlc_bool_t b_uline = VLC_FALSE; + bool b_italic = false; + bool b_bold = false; + bool b_uline = false; if( VLC_SUCCESS == var_Get( p_filter, "scale", &val )) i_scale = val.i_int; - + if( p_font_style ) { rv = PushFont( &p_fonts, @@ -1892,11 +2012,11 @@ static int ProcessNodes( filter_t *p_filter, ((p_font_style->i_karaoke_background_alpha & 0xff) << 24)); if( p_font_style->i_style_flags & STYLE_BOLD ) - b_bold = VLC_TRUE; + b_bold = true; if( p_font_style->i_style_flags & STYLE_ITALIC ) - b_italic = VLC_TRUE; + b_italic = true; if( p_font_style->i_style_flags & STYLE_UNDERLINE ) - b_uline = VLC_TRUE; + b_uline = true; } else { @@ -1923,11 +2043,11 @@ static int ProcessNodes( filter_t *p_filter, if( !strcasecmp( "font", psz_node ) ) PopFont( &p_fonts ); else if( !strcasecmp( "b", psz_node ) ) - b_bold = VLC_FALSE; + b_bold = false; else if( !strcasecmp( "i", psz_node ) ) - b_italic = VLC_FALSE; + b_italic = false; else if( !strcasecmp( "u", psz_node ) ) - b_uline = VLC_FALSE; + b_uline = false; free( psz_node ); } @@ -1939,11 +2059,11 @@ static int ProcessNodes( filter_t *p_filter, if( !strcasecmp( "font", psz_node ) ) rv = HandleFontAttributes( p_xml_reader, &p_fonts, i_scale ); else if( !strcasecmp( "b", psz_node ) ) - b_bold = VLC_TRUE; + b_bold = true; else if( !strcasecmp( "i", psz_node ) ) - b_italic = VLC_TRUE; + b_italic = true; else if( !strcasecmp( "u", psz_node ) ) - b_uline = VLC_TRUE; + b_uline = true; else if( !strcasecmp( "br", psz_node ) ) { SetupLine( p_filter, "\n", &psz_text, @@ -2038,7 +2158,7 @@ static int CheckForEmbeddedFont( filter_sys_t *p_sys, FT_Face *pp_face, ft_style { if( p_face ) { - vlc_bool_t match = !strcasecmp( p_face->family_name, + bool match = !strcasecmp( p_face->family_name, p_style->psz_fontname ); if( p_face->style_flags & FT_STYLE_FLAG_BOLD ) @@ -2056,7 +2176,7 @@ static int CheckForEmbeddedFont( filter_sys_t *p_sys, FT_Face *pp_face, ft_style *pp_face = p_face; return VLC_SUCCESS; } - + FT_Done_Face( p_face ); } i_font_idx++; @@ -2065,6 +2185,17 @@ static int CheckForEmbeddedFont( filter_sys_t *p_sys, FT_Face *pp_face, ft_style return VLC_EGENERIC; } +static int BuildDone( vlc_object_t *p_this, const char *psz_var, + vlc_value_t oldval, vlc_value_t newval, void *param ) +{ + (void)p_this; + (void)psz_var; + (void)oldval; + ((filter_sys_t*)param)->b_fontconfig_ok = newval.b_bool; + assert( newval.b_bool ); + return VLC_SUCCESS; +} + static int ProcessLines( filter_t *p_filter, uint32_t *psz_text, int i_len, @@ -2073,13 +2204,13 @@ static int ProcessLines( filter_t *p_filter, uint32_t *pi_run_lengths, ft_style_t **pp_styles, line_desc_t **pp_lines, - + FT_Vector *p_result, - vlc_bool_t b_karaoke, + bool b_karaoke, uint32_t i_k_runs, uint32_t *pi_k_run_lengths, - uint32_t *pi_k_durations ) + uint32_t *pi_k_durations ) { filter_sys_t *p_sys = p_filter->p_sys; ft_style_t **pp_char_styles; @@ -2136,13 +2267,12 @@ static int ProcessLines( filter_t *p_filter, ! p_new_positions || ! 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; @@ -2197,7 +2327,7 @@ static int ProcessLines( filter_t *p_filter, int64_t i_duration = 0; int64_t i_start_pos = 0; int64_t i_elapsed = var_GetTime( p_filter, "spu-elapsed" ) / 1000; - + for( k = 0; k< i_k_runs; k++ ) { double fraction = 0.0; @@ -2245,13 +2375,13 @@ static int ProcessLines( filter_t *p_filter, ((p_levels ? (p_levels[ j ] % 2) : 0 ) << 7); } } - + i_last_duration = i_duration; 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; @@ -2281,25 +2411,40 @@ 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 && ! *psz_fontfile ) + { + msg_Warn( p_filter, "Fontconfig was unable to find a font: \"%s\" %s" + " so using default font", p_style->psz_fontname, + ((p_style->b_bold && p_style->b_italic) ? "(Bold,Italic)" : + (p_style->b_bold ? "(Bold)" : + (p_style->b_italic ? "(Italic)" : ""))) ); + free( psz_fontfile ); + psz_fontfile = NULL; + } + 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 ); #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 ); @@ -2325,8 +2470,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 = @@ -2337,15 +2481,13 @@ static int ProcessLines( filter_t *p_filter, malloc( (k - i_prev + 1) * sizeof( uint32_t )); if( !psz_unicode ) { - msg_Err( p_filter, "out of memory" ); if( p_face ) FT_Done_Face( p_face ); free( pp_char_styles ); free( psz_unicode ); #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, @@ -2357,22 +2499,20 @@ static int ProcessLines( filter_t *p_filter, { if( !(p_line = NewLine( i_len - i_prev)) ) { - msg_Err( p_filter, "out of memory" ); if( p_face ) FT_Done_Face( p_face ); free( pp_char_styles ); free( psz_unicode ); #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 -- * (RGB mode has palette constraints on it). We therefore * need to populate the legacy colour fields also. */ - p_line->b_new_color_mode = VLC_TRUE; + p_line->b_new_color_mode = true; p_line->i_alpha = ( p_style->i_font_color & 0xff000000 ) >> 24; p_line->i_red = ( p_style->i_font_color & 0x00ff0000 ) >> 16; p_line->i_green = ( p_style->i_font_color & 0x0000ff00 ) >> 8; @@ -2399,8 +2539,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; } @@ -2411,6 +2550,16 @@ static int ProcessLines( filter_t *p_filter, p_prev = p_line; p_line = NULL; + + if( *psz_unicode == '\n') + { + uint32_t *c_ptr; + + for( c_ptr = psz_unicode; *c_ptr; c_ptr++ ) + { + *c_ptr = *(c_ptr+1); + } + } } } free( psz_unicode ); @@ -2488,13 +2637,13 @@ static int RenderHtml( filter_t *p_filter, subpicture_region_t *p_region_out, p_sub = stream_MemoryNew( VLC_OBJECT(p_filter), (uint8_t *) p_region_in->psz_html, strlen( p_region_in->psz_html ), - VLC_TRUE ); + true ); if( p_sub ) { p_xml = xml_Create( p_filter ); if( p_xml ) { - vlc_bool_t b_karaoke = VLC_FALSE; + bool b_karaoke = false; p_xml_reader = xml_ReaderCreate( p_xml, p_sub ); if( p_xml_reader ) @@ -2509,16 +2658,17 @@ static int RenderHtml( filter_t *p_filter, subpicture_region_t *p_region_out, /* We're going to have to render the text a number * of times to show the progress marker on the text. */ - var_SetBool( p_filter, "text-rerender", VLC_TRUE ); - b_karaoke = VLC_TRUE; + var_SetBool( p_filter, "text-rerender", true ); + b_karaoke = true; } else if( !strcasecmp( "text", psz_node ) ) { - b_karaoke = VLC_FALSE; + b_karaoke = false; } else { /* Only text and karaoke tags are supported */ + msg_Dbg( p_filter, "Unsupported top-level tag '%s' ignored.", psz_node ); xml_ReaderDelete( p_xml, p_xml_reader ); p_xml_reader = NULL; rv = VLC_EGENERIC; @@ -2531,7 +2681,7 @@ static int RenderHtml( filter_t *p_filter, subpicture_region_t *p_region_out, if( p_xml_reader ) { uint32_t *psz_text; - int i_len; + int i_len = 0; uint32_t i_runs = 0; uint32_t i_k_runs = 0; uint32_t *pi_run_lengths = NULL; @@ -2600,7 +2750,7 @@ static int RenderHtml( filter_t *p_filter, subpicture_region_t *p_region_out, } static char* FontConfig_Select( FcConfig* priv, const char* family, - vlc_bool_t b_bold, vlc_bool_t b_italic, int *i_idx ) + bool b_bold, bool b_italic, int *i_idx ) { FcResult result; FcPattern *pat, *p_pat; @@ -2716,19 +2866,18 @@ 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; } p_line->pp_glyphs[0] = NULL; - p_line->b_new_color_mode = VLC_FALSE; + p_line->b_new_color_mode = false; return p_line; }