X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fmisc%2Ffreetype.c;h=0f68c946fcbf2caa21b0f451a6afe1099bd484ad;hb=37a4eca2752150fbcdd0b760a55a6b29557f1ec8;hp=f716b99bdd9aa5fd9d953923d75c30ade4abbfcf;hpb=cdc8bcd3e5ed868589e16e5014246a4ccc3b512e;p=vlc diff --git a/modules/misc/freetype.c b/modules/misc/freetype.c index f716b99bdd..0f68c946fc 100644 --- a/modules/misc/freetype.c +++ b/modules/misc/freetype.c @@ -33,33 +33,38 @@ #include #include -#include -#include -#include #include #include #include #include +#include +#include +#include #include -#include #include +#include #include FT_FREETYPE_H #include FT_GLYPH_H #define FT_FLOOR(X) ((X & -64) >> 6) #define FT_CEIL(X) (((X + 63) & -64) >> 6) -#define FT_MulFix(v, s) (((v)*(s))>>16) +#ifndef FT_MulFix + #define FT_MulFix(v, s) (((v)*(s))>>16) +#endif #ifdef __APPLE__ -#define DEFAULT_FONT "/System/Library/Fonts/LucidaGrande.dfont" -#define FC_DEFAULT_FONT "Lucida Grande" +#define DEFAULT_FONT "/Library/Fonts/Arial Black.ttf" +#define FC_DEFAULT_FONT "Arial Black" #elif defined( SYS_BEOS ) #define DEFAULT_FONT "/boot/beos/etc/fonts/ttfonts/Swiss721.ttf" #define FC_DEFAULT_FONT "Swiss" #elif defined( WIN32 ) #define DEFAULT_FONT "" /* Default font found at run-time */ #define FC_DEFAULT_FONT "Arial" +#elif defined( HAVE_MAEMO ) +#define DEFAULT_FONT "/usr/share/fonts/nokia/nosnb.ttf" +#define FC_DEFAULT_FONT "Nokia Sans Bold" #else #define DEFAULT_FONT "/usr/share/fonts/truetype/freefont/FreeSerifBold.ttf" #define FC_DEFAULT_FONT "Serif Bold" @@ -71,6 +76,8 @@ #ifdef HAVE_FONTCONFIG #include +#undef DEFAULT_FONT +#define DEFAULT_FONT FC_DEFAULT_FONT #endif #include @@ -82,7 +89,13 @@ static int Create ( vlc_object_t * ); static void Destroy( vlc_object_t * ); #define FONT_TEXT N_("Font") -#define FONT_LONGTEXT N_("Filename for the font you want to use") + +#ifdef HAVE_FONTCONFIG +#define FONT_LONGTEXT N_("Font family for the font you want to use") +#else +#define FONT_LONGTEXT N_("Font file for the font you want to use") +#endif + #define FONTSIZE_TEXT N_("Font size in pixels") #define FONTSIZE_LONGTEXT N_("This is the default size of the fonts " \ "that will be rendered on the video. " \ @@ -100,7 +113,7 @@ static void Destroy( vlc_object_t * ); #define FONTSIZER_TEXT N_("Relative font size") #define FONTSIZER_LONGTEXT N_("This is the relative default size of the " \ "fonts that will be rendered on the video. If absolute font size is set, "\ - "relative size will be overriden." ) + "relative size will be overridden." ) static const int pi_sizes[] = { 20, 18, 16, 12, 6 }; static const char *const ppsz_sizes_text[] = { @@ -129,40 +142,40 @@ static const char *const ppsz_color_descriptions[] = { 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( N_("Text renderer")); - set_description( N_("Freetype2 font renderer") ); - set_category( CAT_VIDEO ); - set_subcategory( SUBCAT_VIDEO_SUBPIC ); +vlc_module_begin () + 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, - false ); + add_font( "freetype-font", DEFAULT_FONT, NULL, FONT_TEXT, FONT_LONGTEXT, + false ) add_integer( "freetype-fontsize", 0, NULL, FONTSIZE_TEXT, - FONTSIZE_LONGTEXT, 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, 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, false ); - change_integer_list( pi_color_values, ppsz_color_descriptions, NULL ); + COLOR_LONGTEXT, false ) + change_integer_list( pi_color_values, ppsz_color_descriptions, NULL ) add_integer( "freetype-rel-fontsize", 16, NULL, FONTSIZER_TEXT, - FONTSIZER_LONGTEXT, false ); - change_integer_list( pi_sizes, ppsz_sizes_text, NULL ); + FONTSIZER_LONGTEXT, false ) + change_integer_list( pi_sizes, ppsz_sizes_text, NULL ) add_integer( "freetype-effect", 2, NULL, EFFECT_TEXT, - EFFECT_LONGTEXT, false ); - change_integer_list( pi_effects, ppsz_effects_text, NULL ); + EFFECT_LONGTEXT, false ) + change_integer_list( pi_effects, ppsz_effects_text, NULL ) - add_bool( "freetype-yuvp", 0, NULL, YUVP_TEXT, - YUVP_LONGTEXT, true ); - set_capability( "text renderer", 100 ); - add_shortcut( "text" ); - set_callbacks( Create, Destroy ); -vlc_module_end(); + add_bool( "freetype-yuvp", false, NULL, YUVP_TEXT, + YUVP_LONGTEXT, true ) + set_capability( "text renderer", 100 ) + add_shortcut( "text" ) + set_callbacks( Create, Destroy ) +vlc_module_end () @@ -204,7 +217,7 @@ struct line_desc_t uint8_t *p_fg_bg_ratio; /* 0x00=100% FG --> 0x7F=100% BG */ bool b_new_color_mode; /** underline information -- only supplied if text should be underlined */ - uint16_t *pi_underline_offset; + int *pi_underline_offset; uint16_t *pi_underline_thickness; int i_height; @@ -216,17 +229,6 @@ struct line_desc_t }; static line_desc_t *NewLine( int ); -typedef struct font_stack_t font_stack_t; -struct font_stack_t -{ - char *psz_name; - int i_size; - uint32_t i_color; /* ARGB */ - uint32_t i_karaoke_bg_color; /* ARGB */ - - font_stack_t *p_next; -}; - typedef struct { int i_font_size; @@ -235,6 +237,7 @@ typedef struct bool b_italic; bool b_bold; bool b_underline; + bool b_through; char *psz_fontname; } ft_style_t; @@ -242,16 +245,6 @@ 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 vlc_object_t *FontBuilderAttach( filter_t *p_filter, vlc_mutex_t **pp_lock ); -static void FontBuilderDetach( filter_t *p_filter, vlc_object_t *p_fontbuilder ); -static void* FontBuilderThread( vlc_object_t *p_this); -static void FontBuilderDestructor( vlc_object_t *p_this ); -static void FontBuilderGetFcConfig( filter_t *p_filter, vlc_object_t *p_fontbuilder ); -static int FontBuilderDone( vlc_object_t*, const char *, vlc_value_t, vlc_value_t, - void* ); -#endif - /***************************************************************************** * filter_sys_t: freetype local data ***************************************************************************** @@ -271,17 +264,21 @@ struct filter_sys_t int i_default_font_size; int i_display_height; #ifdef HAVE_FONTCONFIG - vlc_mutex_t *p_fontconfig_lock; - bool b_fontconfig_ok; - FcConfig *p_fontconfig; + char* psz_fontfamily; + xml_reader_t *p_xml; #endif input_attachment_t **pp_font_attachments; int i_font_attachments; - vlc_object_t *p_fontbuilder; }; +#define UCHAR uint32_t +#define TR_DEFAULT_FONT p_sys->psz_fontfamily +#define TR_FONT_STYLE_PTR ft_style_t * + +#include "text_renderer.h" + /***************************************************************************** * Create: allocates osd-text video thread output method ***************************************************************************** @@ -291,73 +288,161 @@ 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; + char *psz_fontfile=NULL; + char *psz_fontfamily=NULL; + int i_error,fontindex; + +#ifdef HAVE_FONTCONFIG + FcPattern *fontpattern = NULL, *fontmatch = NULL; + /* Initialise result to Match, as fontconfig doesnt + * really set this other than some error-cases */ + FcResult fontresult = FcResultMatch; +#endif + /* Allocate structure */ p_filter->p_sys = p_sys = malloc( sizeof( filter_sys_t ) ); if( !p_sys ) return VLC_ENOMEM; +#ifdef HAVE_FONTCONFIG + p_sys->psz_fontfamily = NULL; + p_sys->p_xml = NULL; +#endif p_sys->p_face = 0; p_sys->p_library = 0; p_sys->i_font_size = 0; p_sys->i_display_height = 0; - var_Create( p_filter, "freetype-font", - VLC_VAR_STRING | VLC_VAR_DOINHERIT ); - var_Create( p_filter, "freetype-fontsize", - VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); var_Create( p_filter, "freetype-rel-fontsize", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); - var_Create( p_filter, "freetype-opacity", - VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); - var_Create( p_filter, "freetype-effect", - VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); - var_Get( p_filter, "freetype-opacity", &val ); - p_sys->i_font_opacity = __MAX( __MIN( val.i_int, 255 ), 0 ); - var_Create( p_filter, "freetype-color", - VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); - var_Get( p_filter, "freetype-color", &val ); - p_sys->i_font_color = __MAX( __MIN( val.i_int, 0xFFFFFF ), 0 ); - p_sys->i_effect = var_GetInteger( p_filter, "freetype-effect" ); - - /* Look what method was requested */ - var_Get( p_filter, "freetype-font", &val ); - psz_fontfile = val.psz_string; - if( !psz_fontfile || !*psz_fontfile ) + + psz_fontfamily = var_CreateGetString( p_filter, "freetype-font" ); + p_sys->i_default_font_size = var_CreateGetInteger( p_filter, "freetype-fontsize" ); + p_sys->i_effect = var_CreateGetInteger( p_filter, "freetype-effect" ); + p_sys->i_font_opacity = var_CreateGetInteger( p_filter,"freetype-opacity" ); + p_sys->i_font_opacity = __MAX( __MIN( p_sys->i_font_opacity, 255 ), 0 ); + p_sys->i_font_color = var_CreateGetInteger( p_filter, "freetype-color" ); + p_sys->i_font_color = __MAX( __MIN( p_sys->i_font_color , 0xFFFFFF ), 0 ); + + fontindex=0; + if( !psz_fontfamily || !*psz_fontfamily ) { - free( psz_fontfile ); - psz_fontfile = (char *)malloc( PATH_MAX + 1 ); - if( !psz_fontfile ) + free( psz_fontfamily ); +#ifdef HAVE_FONTCONFIG + psz_fontfamily=strdup( DEFAULT_FONT ); +#else + psz_fontfamily = (char *)malloc( PATH_MAX + 1 ); + if( !psz_fontfamily ) goto error; +# ifdef WIN32 + GetWindowsDirectory( psz_fontfamily , PATH_MAX + 1 ); + strcat( psz_fontfamily, "\\fonts\\arial.ttf" ); +# else + strcpy( psz_fontfamily, DEFAULT_FONT ); +# endif + msg_Err( p_filter,"User didn't specify fontfile, using %s", psz_fontfamily); +#endif + } + +#ifdef HAVE_FONTCONFIG + msg_Dbg( p_filter, "Building font databases."); + mtime_t t1, t2; + t1 = mdate(); + #ifdef WIN32 - GetWindowsDirectory( psz_fontfile, PATH_MAX + 1 ); - strcat( psz_fontfile, "\\fonts\\arial.ttf" ); -#elif defined(__APPLE__) - strcpy( psz_fontfile, DEFAULT_FONT ); -#else - msg_Err( p_filter, "user didn't specify a font" ); - goto error; + dialog_progress_bar_t *p_dialog = NULL; + FcConfig *fcConfig = FcInitLoadConfig(); + + p_dialog = dialog_ProgressCreate( p_filter, + _("Building font cache"), + _("Please wait while your font cache is rebuilt.\n" + "This should take less than a few minutes."), NULL ); + +/* if( p_dialog ) + dialog_ProgressSet( p_dialog, NULL, 0.5 ); */ + + FcConfigBuildFonts( fcConfig ); + t2 = mdate(); + msg_Dbg( p_filter, "Took %ld microseconds", (long)((t2 - t1)) ); + + if( p_dialog ) + { +// dialog_ProgressSet( p_dialog, NULL, 1.0 ); + dialog_ProgressDestroy( p_dialog ); + p_dialog = NULL; + } #endif + /* Lets find some fontfile from freetype-font variable family */ + char *psz_fontsize; + if( asprintf( &psz_fontsize, "%d", p_sys->i_default_font_size ) == -1 ) + goto error; + + fontpattern = FcPatternCreate(); + if( !fontpattern ) + { + msg_Err( p_filter, "Creating fontpattern failed"); + goto error; } + FcPatternAddString( fontpattern, FC_FAMILY, psz_fontfamily); + FcPatternAddString( fontpattern, FC_SIZE, psz_fontsize ); + free( psz_fontsize ); + + if( FcConfigSubstitute( NULL, fontpattern, FcMatchPattern ) == FcFalse ) + { + msg_Err( p_filter, "FontSubstitute failed"); + goto error; + } + FcDefaultSubstitute( fontpattern ); + + /* testing fontresult here doesn't do any good really, but maybe it will + * in future as fontconfig code doesn't set it in all cases and just + * returns NULL or doesn't set to to Match on all Match cases.*/ + fontmatch = FcFontMatch( NULL, fontpattern, &fontresult ); + if( !fontmatch || fontresult == FcResultNoMatch ) + { + msg_Err( p_filter, "Fontmatching failed"); + goto error; + } + + FcPatternGetString( fontmatch, FC_FILE, 0, &psz_fontfile); + FcPatternGetInteger( fontmatch, FC_INDEX, 0, &fontindex ); + if( !psz_fontfile ) + { + msg_Err( p_filter, "Failed to get fontfile"); + goto error; + } + + msg_Dbg( p_filter, "Using %s as font from file %s", psz_fontfamily, + psz_fontfile ? psz_fontfile : "(null)" ); + p_sys->psz_fontfamily = strdup( psz_fontfamily ); + +#else + + psz_fontfile = psz_fontfamily; + +#endif + i_error = FT_Init_FreeType( &p_sys->p_library ); if( i_error ) { msg_Err( p_filter, "couldn't initialize freetype" ); goto error; } + i_error = FT_New_Face( p_sys->p_library, psz_fontfile ? psz_fontfile : "", - 0, &p_sys->p_face ); + fontindex, &p_sys->p_face ); + if( i_error == FT_Err_Unknown_File_Format ) { - msg_Err( p_filter, "file %s have unknown format", psz_fontfile ); + msg_Err( p_filter, "file %s have unknown format", + psz_fontfile ? psz_fontfile : "(null)" ); goto error; } else if( i_error ) { - msg_Err( p_filter, "failed to load font file %s", psz_fontfile ); + msg_Err( p_filter, "failed to load font file %s", + psz_fontfile ? psz_fontfile : "(null)" ); goto error; } @@ -368,19 +453,10 @@ static int Create( vlc_object_t *p_this ) goto error; } -#ifdef HAVE_FONTCONFIG - p_sys->b_fontconfig_ok = false; - p_sys->p_fontconfig = NULL; - p_sys->p_fontbuilder = FontBuilderAttach( p_filter, &p_sys->p_fontconfig_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; - free( psz_fontfile ); p_sys->pp_font_attachments = NULL; p_sys->i_font_attachments = 0; @@ -388,18 +464,31 @@ static int Create( vlc_object_t *p_this ) p_filter->pf_render_text = RenderText; #ifdef HAVE_FONTCONFIG p_filter->pf_render_html = RenderHtml; + FcPatternDestroy( fontmatch ); + FcPatternDestroy( fontpattern ); #else p_filter->pf_render_html = NULL; #endif + free( psz_fontfamily ); LoadFontsFromAttachments( p_filter ); return VLC_SUCCESS; - error: +error: +#ifdef HAVE_FONTCONFIG + if( fontmatch ) FcPatternDestroy( fontmatch ); + if( fontpattern ) FcPatternDestroy( fontpattern ); + +#ifdef WIN32 + if( p_dialog ) + dialog_ProgressDestroy( p_dialog ); +#endif +#endif + if( p_sys->p_face ) FT_Done_Face( p_sys->p_face ); if( p_sys->p_library ) FT_Done_FreeType( p_sys->p_library ); - free( psz_fontfile ); + free( psz_fontfamily ); free( p_sys ); return VLC_EGENERIC; } @@ -425,7 +514,8 @@ static void Destroy( vlc_object_t *p_this ) } #ifdef HAVE_FONTCONFIG - FontBuilderDetach( p_filter, p_sys->p_fontbuilder ); + if( p_sys->p_xml ) xml_ReaderDelete( p_sys->p_xml ); + free( p_sys->psz_fontfamily ); #endif /* FcFini asserts calling the subfunction FcCacheFini() @@ -437,156 +527,6 @@ static void Destroy( vlc_object_t *p_this ) free( p_sys ); } -#ifdef HAVE_FONTCONFIG -static vlc_object_t *FontBuilderAttach( filter_t *p_filter, vlc_mutex_t **pp_lock ) -{ - /* Check for an existing Fontbuilder thread */ - vlc_mutex_t *p_lock = var_AcquireMutex( "fontbuilder" ); - 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( p_lock ); - *pp_lock = p_lock; - return p_fontbuilder; -} -static void FontBuilderDetach( filter_t *p_filter, vlc_object_t *p_fontbuilder ) -{ - vlc_mutex_t *lock = var_AcquireMutex( "fontbuilder" ); - 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( 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( lock ); - } - vlc_object_release( p_fontbuilder ); - } - vlc_mutex_unlock( 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_t *p_lock = var_AcquireMutex( "fontbuilder" ); - p_this->p_private = p_fontconfig; - vlc_mutex_unlock( p_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_t *p_lock = var_AcquireMutex( "fontbuilder" ); - - FontBuilderGetFcConfig( p_filter, p_this ); - - vlc_mutex_unlock( p_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 @@ -594,44 +534,26 @@ static int FontBuilderDone( vlc_object_t *p_this, const char *psz_var, 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 ) + if( filter_GetInputAttachments( p_filter, &pp_attachments, &i_attachments_cnt ) ) 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; + if( !p_sys->pp_font_attachments ) + return VLC_ENOMEM; - for( k = 0; k < i_attachments_cnt; k++ ) + for( int 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 ) { - 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 ); - } + p_sys->pp_font_attachments[ p_sys->i_font_attachments++ ] = p_attach; } else { @@ -640,9 +562,7 @@ static int LoadFontsFromAttachments( filter_t *p_filter ) } free( pp_attachments ); - vlc_object_release(p_input); - - return rv; + return VLC_SUCCESS; } /***************************************************************************** @@ -653,6 +573,7 @@ static int LoadFontsFromAttachments( filter_t *p_filter ) static int Render( filter_t *p_filter, subpicture_region_t *p_region, line_desc_t *p_line, int i_width, int i_height ) { + VLC_UNUSED(p_filter); static const uint8_t pi_gamma[16] = {0x00, 0x52, 0x84, 0x96, 0xb8, 0xca, 0xdc, 0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; @@ -662,12 +583,10 @@ static int Render( filter_t *p_filter, subpicture_region_t *p_region, int i, x, y, i_pitch; uint8_t i_y; /* YUV values, derived from incoming RGB */ int8_t i_u, i_v; - subpicture_region_t *p_region_tmp; /* Create a new subpicture region */ memset( &fmt, 0, sizeof(video_format_t) ); - fmt.i_chroma = VLC_FOURCC('Y','U','V','P'); - fmt.i_aspect = 0; + fmt.i_chroma = VLC_CODEC_YUVP; fmt.i_width = fmt.i_visible_width = i_width + 4; fmt.i_height = fmt.i_visible_height = i_height + 4; if( p_region->fmt.i_visible_width > 0 ) @@ -675,16 +594,13 @@ static int Render( filter_t *p_filter, subpicture_region_t *p_region, if( p_region->fmt.i_visible_height > 0 ) fmt.i_visible_height = p_region->fmt.i_visible_height; fmt.i_x_offset = fmt.i_y_offset = 0; - p_region_tmp = spu_CreateRegion( p_filter, &fmt ); - if( !p_region_tmp ) - { - msg_Err( p_filter, "cannot allocate SPU region" ); - return VLC_EGENERIC; - } - p_region->fmt = p_region_tmp->fmt; - p_region->picture = p_region_tmp->picture; - free( p_region_tmp ); + assert( !p_region->p_picture ); + p_region->p_picture = picture_NewFromFormat( &fmt ); + if( !p_region->p_picture ) + return VLC_EGENERIC; + fmt.p_palette = p_region->fmt.p_palette ? p_region->fmt.p_palette : malloc(sizeof(*fmt.p_palette)); + p_region->fmt = fmt; /* Calculate text color components */ i_y = (uint8_t)(( 66 * p_line->i_red + 129 * p_line->i_green + @@ -715,8 +631,8 @@ static int Render( filter_t *p_filter, subpicture_region_t *p_region, (int)fmt.p_palette->palette[i][3] * (255 - p_line->i_alpha) / 255; } - p_dst = p_region->picture.Y_PIXELS; - i_pitch = p_region->picture.Y_PITCH; + p_dst = p_region->p_picture->Y_PIXELS; + i_pitch = p_region->p_picture->Y_PITCH; /* Initialize the region pixels */ memset( p_dst, 0, i_pitch * p_region->fmt.i_height ); @@ -768,21 +684,21 @@ static int Render( filter_t *p_filter, subpicture_region_t *p_region, /* Outlining (find something better than nearest neighbour filtering ?) */ if( 1 ) { - uint8_t *p_dst = p_region->picture.Y_PIXELS; + uint8_t *p_dst = p_region->p_picture->Y_PIXELS; uint8_t *p_top = p_dst; /* Use 1st line as a cache */ uint8_t left, current; for( y = 1; y < (int)fmt.i_height - 1; y++ ) { if( y > 1 ) memcpy( p_top, p_dst, fmt.i_width ); - p_dst += p_region->picture.Y_PITCH; + p_dst += p_region->p_picture->Y_PITCH; left = 0; for( x = 1; x < (int)fmt.i_width - 1; x++ ) { current = p_dst[x]; p_dst[x] = ( 8 * (int)p_dst[x] + left + p_dst[x+1] + p_top[x -1]+ p_top[x] + p_top[x+1] + - p_dst[x -1 + p_region->picture.Y_PITCH ] + p_dst[x + p_region->picture.Y_PITCH] + p_dst[x + 1 + p_region->picture.Y_PITCH]) / 16; + p_dst[x -1 + p_region->p_picture->Y_PITCH ] + p_dst[x + p_region->p_picture->Y_PITCH] + p_dst[x + 1 + p_region->p_picture->Y_PITCH]) / 16; left = current; } } @@ -803,11 +719,11 @@ static void UnderlineGlyphYUVA( int i_line_thickness, int i_line_offset, bool b_ int i_pitch; uint8_t *p_dst_y,*p_dst_u,*p_dst_v,*p_dst_a; - p_dst_y = p_region->picture.Y_PIXELS; - p_dst_u = p_region->picture.U_PIXELS; - p_dst_v = p_region->picture.V_PIXELS; - p_dst_a = p_region->picture.A_PIXELS; - i_pitch = p_region->picture.A_PITCH; + p_dst_y = p_region->p_picture->Y_PIXELS; + p_dst_u = p_region->p_picture->U_PIXELS; + p_dst_v = p_region->p_picture->V_PIXELS; + p_dst_a = p_region->p_picture->A_PIXELS; + i_pitch = p_region->p_picture->A_PITCH; int i_offset = ( p_this_glyph_pos->y + i_glyph_tmax + i_line_offset + 3 ) * i_pitch + p_this_glyph_pos->x + p_this_glyph->left + 3 + i_align_offset; @@ -826,8 +742,9 @@ static void UnderlineGlyphYUVA( int i_line_thickness, int i_line_offset, bool b_ bool b_ok = true; /* break the underline around the tails of any glyphs which cross it */ + /* Strikethrough doesn't get broken */ for( z = x - i_line_thickness; - z < x + i_line_thickness && b_ok; + z < x + i_line_thickness && b_ok && (i_line_offset >= 0); z++ ) { if( p_next_glyph && ( z >= i_extra ) ) @@ -866,8 +783,8 @@ static void UnderlineGlyphYUVA( int i_line_thickness, int i_line_offset, bool b_ static void DrawBlack( line_desc_t *p_line, int i_width, subpicture_region_t *p_region, int xoffset, int yoffset ) { - uint8_t *p_dst = p_region->picture.A_PIXELS; - int i_pitch = p_region->picture.A_PITCH; + uint8_t *p_dst = p_region->p_picture->A_PIXELS; + int i_pitch = p_region->p_picture->A_PITCH; int x,y; for( ; p_line != NULL; p_line = p_line->p_next ) @@ -930,15 +847,13 @@ static int RenderYUVA( filter_t *p_filter, subpicture_region_t *p_region, video_format_t fmt; int i, x, y, i_pitch, i_alpha; uint8_t i_y, i_u, i_v; /* YUV values, derived from incoming RGB */ - subpicture_region_t *p_region_tmp; if( i_width == 0 || i_height == 0 ) return VLC_SUCCESS; /* Create a new subpicture region */ memset( &fmt, 0, sizeof(video_format_t) ); - fmt.i_chroma = VLC_FOURCC('Y','U','V','A'); - fmt.i_aspect = 0; + fmt.i_chroma = VLC_CODEC_YUVA; fmt.i_width = fmt.i_visible_width = i_width + 6; fmt.i_height = fmt.i_visible_height = i_height + 6; if( p_region->fmt.i_visible_width > 0 ) @@ -946,16 +861,11 @@ static int RenderYUVA( filter_t *p_filter, subpicture_region_t *p_region, if( p_region->fmt.i_visible_height > 0 ) fmt.i_visible_height = p_region->fmt.i_visible_height; fmt.i_x_offset = fmt.i_y_offset = 0; - p_region_tmp = spu_CreateRegion( p_filter, &fmt ); - if( !p_region_tmp ) - { - msg_Err( p_filter, "cannot allocate SPU region" ); - return VLC_EGENERIC; - } - p_region->fmt = p_region_tmp->fmt; - p_region->picture = p_region_tmp->picture; - free( p_region_tmp ); + p_region->p_picture = picture_NewFromFormat( &fmt ); + if( !p_region->p_picture ) + return VLC_EGENERIC; + p_region->fmt = fmt; /* Calculate text color components */ YUVFromRGB( (p_line->i_red << 16) | @@ -964,11 +874,11 @@ static int RenderYUVA( filter_t *p_filter, subpicture_region_t *p_region, &i_y, &i_u, &i_v); i_alpha = p_line->i_alpha; - p_dst_y = p_region->picture.Y_PIXELS; - p_dst_u = p_region->picture.U_PIXELS; - p_dst_v = p_region->picture.V_PIXELS; - p_dst_a = p_region->picture.A_PIXELS; - i_pitch = p_region->picture.A_PITCH; + p_dst_y = p_region->p_picture->Y_PIXELS; + p_dst_u = p_region->p_picture->U_PIXELS; + p_dst_v = p_region->p_picture->V_PIXELS; + p_dst_a = p_region->p_picture->A_PIXELS; + i_pitch = p_region->p_picture->A_PITCH; /* Initialize the region pixels */ if( p_filter->p_sys->i_effect != EFFECT_BACKGROUND ) @@ -1219,7 +1129,7 @@ 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 ) { i_char = psz_unicode[pos]; if (i_char != '\r' && i_char != '\n') @@ -1311,12 +1221,16 @@ static int RenderText( filter_t *p_filter, subpicture_region_t *p_region_out, } p_line->p_glyph_pos[ i ].x = i_pen_x; p_line->p_glyph_pos[ i ].y = i_pen_y; - i_error = FT_Load_Glyph( face, i_glyph_index, FT_LOAD_DEFAULT ); + i_error = FT_Load_Glyph( face, i_glyph_index, FT_LOAD_NO_BITMAP | FT_LOAD_DEFAULT ); if( i_error ) { - msg_Err( p_filter, "unable to render text FT_Load_Glyph returned" - " %d", i_error ); - goto error; + i_error = FT_Load_Glyph( face, i_glyph_index, FT_LOAD_DEFAULT ); + if( i_error ) + { + msg_Err( p_filter, "unable to render text FT_Load_Glyph returned" + " %d", i_error ); + goto error; + } } i_error = FT_Get_Glyph( glyph, &tmp_glyph ); if( i_error ) @@ -1400,7 +1314,7 @@ static int RenderText( filter_t *p_filter, subpicture_region_t *p_region_out, p_region_out->i_x = p_region_in->i_x; p_region_out->i_y = p_region_in->i_y; - if( config_GetInt( p_filter, "freetype-yuvp" ) ) + if( var_InheritBool( p_filter, "freetype-yuvp" ) ) Render( p_filter, p_region_out, p_lines, result.x, result.y ); else RenderYUVA( p_filter, p_region_out, p_lines, result.x, result.y ); @@ -1418,7 +1332,7 @@ static int RenderText( filter_t *p_filter, subpicture_region_t *p_region_out, #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, bool b_bold, - bool b_italic, bool b_uline ) + bool b_italic, bool b_uline, bool b_through ) { ft_style_t *p_style = malloc( sizeof( ft_style_t )); @@ -1430,6 +1344,7 @@ static ft_style_t *CreateStyle( char *psz_fontname, int i_font_size, p_style->b_italic = b_italic; p_style->b_bold = b_bold; p_style->b_underline = b_uline; + p_style->b_through = b_through; p_style->psz_fontname = strdup( psz_fontname ); } @@ -1455,6 +1370,7 @@ static bool StyleEquals( ft_style_t *s1, ft_style_t *s2 ) if(( s1->i_font_size == s2->i_font_size ) && ( s1->i_font_color == s2->i_font_color ) && ( s1->b_italic == s2->b_italic ) && + ( s1->b_through == s2->b_through ) && ( s1->b_bold == s2->b_bold ) && ( s1->b_underline == s2->b_underline ) && ( !strcmp( s1->psz_fontname, s2->psz_fontname ))) @@ -1464,94 +1380,6 @@ static bool StyleEquals( ft_style_t *s1, ft_style_t *s2 ) return false; } -static int PushFont( font_stack_t **p_font, const char *psz_name, int i_size, - uint32_t i_color, uint32_t i_karaoke_bg_color ) -{ - font_stack_t *p_new; - - if( !p_font ) - return VLC_EGENERIC; - - p_new = malloc( sizeof( font_stack_t ) ); - if( ! p_new ) - return VLC_ENOMEM; - - p_new->p_next = NULL; - - if( psz_name ) - p_new->psz_name = strdup( psz_name ); - else - p_new->psz_name = NULL; - - p_new->i_size = i_size; - p_new->i_color = i_color; - p_new->i_karaoke_bg_color = i_karaoke_bg_color; - - if( !*p_font ) - { - *p_font = p_new; - } - else - { - font_stack_t *p_last; - - for( p_last = *p_font; - p_last->p_next; - p_last = p_last->p_next ) - ; - - p_last->p_next = p_new; - } - return VLC_SUCCESS; -} - -static int PopFont( font_stack_t **p_font ) -{ - font_stack_t *p_last, *p_next_to_last; - - if( !p_font || !*p_font ) - return VLC_EGENERIC; - - p_next_to_last = NULL; - for( p_last = *p_font; - p_last->p_next; - p_last = p_last->p_next ) - { - p_next_to_last = p_last; - } - - if( p_next_to_last ) - p_next_to_last->p_next = NULL; - else - *p_font = NULL; - - free( p_last->psz_name ); - free( p_last ); - - return VLC_SUCCESS; -} - -static int PeekFont( font_stack_t **p_font, char **psz_name, int *i_size, - uint32_t *i_color, uint32_t *i_karaoke_bg_color ) -{ - font_stack_t *p_last; - - if( !p_font || !*p_font ) - return VLC_EGENERIC; - - for( p_last=*p_font; - p_last->p_next; - p_last=p_last->p_next ) - ; - - *psz_name = p_last->psz_name; - *i_size = p_last->i_size; - *i_color = p_last->i_color; - *i_karaoke_bg_color = p_last->i_karaoke_bg_color; - - return VLC_SUCCESS; -} - static void IconvText( filter_t *p_filter, const char *psz_string, uint32_t *i_string_length, uint32_t **ppsz_unicode ) { @@ -1609,7 +1437,7 @@ 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, bool b_bold, bool b_italic, - bool b_uline ) + bool b_uline, bool b_through ) { ft_style_t *p_style = NULL; @@ -1622,13 +1450,14 @@ static ft_style_t *GetStyleFromFontStack( filter_sys_t *p_sys, &i_font_color, &i_karaoke_bg_color )) { p_style = CreateStyle( psz_fontname, i_font_size, i_font_color, - i_karaoke_bg_color, b_bold, b_italic, b_uline ); + i_karaoke_bg_color, b_bold, b_italic, b_uline, b_through ); } return p_style; } static int RenderTag( filter_t *p_filter, FT_Face p_face, int i_font_color, - bool b_uline, int i_karaoke_bgcolor, + bool b_uline, bool b_through, bool b_bold, + bool b_italic, 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 ) @@ -1682,14 +1511,28 @@ static int RenderTag( filter_t *p_filter, FT_Face p_face, int i_font_color, p_line->p_glyph_pos[ i ].x = *pi_pen_x; p_line->p_glyph_pos[ i ].y = i_pen_y; - i_error = FT_Load_Glyph( p_face, i_glyph_index, FT_LOAD_DEFAULT ); + i_error = FT_Load_Glyph( p_face, i_glyph_index, FT_LOAD_NO_BITMAP | FT_LOAD_DEFAULT ); if( i_error ) { - msg_Err( p_filter, - "unable to render text FT_Load_Glyph returned %d", i_error ); - p_line->pp_glyphs[ i ] = NULL; - return VLC_EGENERIC; + i_error = FT_Load_Glyph( p_face, i_glyph_index, FT_LOAD_DEFAULT ); + if( i_error ) + { + msg_Err( p_filter, + "unable to render text FT_Load_Glyph returned %d", i_error ); + p_line->pp_glyphs[ i ] = NULL; + return VLC_EGENERIC; + } } + + /* Do synthetic styling now that Freetype supports it; + * ie. if the font we have loaded is NOT already in the + * style that the tags want, then switch it on; if they + * are then don't. */ + if (b_bold && !( p_face->style_flags & FT_STYLE_FLAG_BOLD )) + FT_GlyphSlot_Embolden( p_face->glyph ); + if (b_italic && !( p_face->style_flags & FT_STYLE_FLAG_ITALIC )) + FT_GlyphSlot_Oblique( p_face->glyph ); + i_error = FT_Get_Glyph( p_face->glyph, &tmp_glyph ); if( i_error ) { @@ -1705,7 +1548,7 @@ static int RenderTag( filter_t *p_filter, FT_Face p_face, int i_font_color, FT_Done_Glyph( tmp_glyph ); continue; } - if( b_uline ) + if( b_uline || b_through ) { float aOffset = FT_FLOOR(FT_MulFix(p_face->underline_position, p_face->size->metrics.y_scale)); @@ -1716,7 +1559,19 @@ static int RenderTag( filter_t *p_filter, FT_Face p_face, int i_font_color, ( aOffset < 0 ) ? -aOffset : aOffset; p_line->pi_underline_thickness[ i ] = ( aSize < 0 ) ? -aSize : aSize; + if (b_through) + { + /* Move the baseline to make it strikethrough instead of + * underline. That means that strikethrough takes precedence + */ + float aDescent = FT_FLOOR(FT_MulFix(p_face->descender*2, + p_face->size->metrics.y_scale)); + + p_line->pi_underline_offset[ i ] -= + ( aDescent < 0 ) ? -aDescent : aDescent; + } } + p_line->pp_glyphs[ i ] = (FT_BitmapGlyph)tmp_glyph; p_line->p_fg_rgb[ i ] = i_font_color & 0x00ffffff; p_line->p_bg_rgb[ i ] = i_karaoke_bgcolor & 0x00ffffff; @@ -1726,10 +1581,9 @@ static int RenderTag( filter_t *p_filter, FT_Face p_face, int i_font_color, glyph_size.xMin + ((FT_BitmapGlyph)tmp_glyph)->left; if( line.xMax > (int)p_filter->fmt_out.video.i_visible_width - 20 ) { - while( --i > *pi_start ) - { + for( ; i >= *pi_start; i-- ) FT_Done_Glyph( (FT_Glyph)p_line->pp_glyphs[ i ] ); - } + i = *pi_start; while( psz_unicode > psz_unicode_start && *psz_unicode != ' ' ) { @@ -1753,8 +1607,6 @@ static int RenderTag( filter_t *p_filter, FT_Face p_face, int i_font_color, p_result->x = __MAX( p_result->x, line.xMax ); p_result->y = __MAX( p_result->y, __MAX( p_line->i_height, i_yMax - i_yMin ) ); - - *pi_start = i; return VLC_SUCCESS; } else @@ -1805,273 +1657,6 @@ static int RenderTag( filter_t *p_filter, FT_Face p_face, int i_font_color, return VLC_SUCCESS; } -static const struct { - const char *psz_name; - uint32_t i_value; -} p_html_colors[] = { - /* Official html colors */ - { "Aqua", 0x00FFFF }, - { "Black", 0x000000 }, - { "Blue", 0x0000FF }, - { "Fuchsia", 0xFF00FF }, - { "Gray", 0x808080 }, - { "Green", 0x008000 }, - { "Lime", 0x00FF00 }, - { "Maroon", 0x800000 }, - { "Navy", 0x000080 }, - { "Olive", 0x808000 }, - { "Purple", 0x800080 }, - { "Red", 0xFF0000 }, - { "Silver", 0xC0C0C0 }, - { "Teal", 0x008080 }, - { "White", 0xFFFFFF }, - { "Yellow", 0xFFFF00 }, - - /* Common ones */ - { "AliceBlue", 0xF0F8FF }, - { "AntiqueWhite", 0xFAEBD7 }, - { "Aqua", 0x00FFFF }, - { "Aquamarine", 0x7FFFD4 }, - { "Azure", 0xF0FFFF }, - { "Beige", 0xF5F5DC }, - { "Bisque", 0xFFE4C4 }, - { "Black", 0x000000 }, - { "BlanchedAlmond", 0xFFEBCD }, - { "Blue", 0x0000FF }, - { "BlueViolet", 0x8A2BE2 }, - { "Brown", 0xA52A2A }, - { "BurlyWood", 0xDEB887 }, - { "CadetBlue", 0x5F9EA0 }, - { "Chartreuse", 0x7FFF00 }, - { "Chocolate", 0xD2691E }, - { "Coral", 0xFF7F50 }, - { "CornflowerBlue", 0x6495ED }, - { "Cornsilk", 0xFFF8DC }, - { "Crimson", 0xDC143C }, - { "Cyan", 0x00FFFF }, - { "DarkBlue", 0x00008B }, - { "DarkCyan", 0x008B8B }, - { "DarkGoldenRod", 0xB8860B }, - { "DarkGray", 0xA9A9A9 }, - { "DarkGrey", 0xA9A9A9 }, - { "DarkGreen", 0x006400 }, - { "DarkKhaki", 0xBDB76B }, - { "DarkMagenta", 0x8B008B }, - { "DarkOliveGreen", 0x556B2F }, - { "Darkorange", 0xFF8C00 }, - { "DarkOrchid", 0x9932CC }, - { "DarkRed", 0x8B0000 }, - { "DarkSalmon", 0xE9967A }, - { "DarkSeaGreen", 0x8FBC8F }, - { "DarkSlateBlue", 0x483D8B }, - { "DarkSlateGray", 0x2F4F4F }, - { "DarkSlateGrey", 0x2F4F4F }, - { "DarkTurquoise", 0x00CED1 }, - { "DarkViolet", 0x9400D3 }, - { "DeepPink", 0xFF1493 }, - { "DeepSkyBlue", 0x00BFFF }, - { "DimGray", 0x696969 }, - { "DimGrey", 0x696969 }, - { "DodgerBlue", 0x1E90FF }, - { "FireBrick", 0xB22222 }, - { "FloralWhite", 0xFFFAF0 }, - { "ForestGreen", 0x228B22 }, - { "Fuchsia", 0xFF00FF }, - { "Gainsboro", 0xDCDCDC }, - { "GhostWhite", 0xF8F8FF }, - { "Gold", 0xFFD700 }, - { "GoldenRod", 0xDAA520 }, - { "Gray", 0x808080 }, - { "Grey", 0x808080 }, - { "Green", 0x008000 }, - { "GreenYellow", 0xADFF2F }, - { "HoneyDew", 0xF0FFF0 }, - { "HotPink", 0xFF69B4 }, - { "IndianRed", 0xCD5C5C }, - { "Indigo", 0x4B0082 }, - { "Ivory", 0xFFFFF0 }, - { "Khaki", 0xF0E68C }, - { "Lavender", 0xE6E6FA }, - { "LavenderBlush", 0xFFF0F5 }, - { "LawnGreen", 0x7CFC00 }, - { "LemonChiffon", 0xFFFACD }, - { "LightBlue", 0xADD8E6 }, - { "LightCoral", 0xF08080 }, - { "LightCyan", 0xE0FFFF }, - { "LightGoldenRodYellow", 0xFAFAD2 }, - { "LightGray", 0xD3D3D3 }, - { "LightGrey", 0xD3D3D3 }, - { "LightGreen", 0x90EE90 }, - { "LightPink", 0xFFB6C1 }, - { "LightSalmon", 0xFFA07A }, - { "LightSeaGreen", 0x20B2AA }, - { "LightSkyBlue", 0x87CEFA }, - { "LightSlateGray", 0x778899 }, - { "LightSlateGrey", 0x778899 }, - { "LightSteelBlue", 0xB0C4DE }, - { "LightYellow", 0xFFFFE0 }, - { "Lime", 0x00FF00 }, - { "LimeGreen", 0x32CD32 }, - { "Linen", 0xFAF0E6 }, - { "Magenta", 0xFF00FF }, - { "Maroon", 0x800000 }, - { "MediumAquaMarine", 0x66CDAA }, - { "MediumBlue", 0x0000CD }, - { "MediumOrchid", 0xBA55D3 }, - { "MediumPurple", 0x9370D8 }, - { "MediumSeaGreen", 0x3CB371 }, - { "MediumSlateBlue", 0x7B68EE }, - { "MediumSpringGreen", 0x00FA9A }, - { "MediumTurquoise", 0x48D1CC }, - { "MediumVioletRed", 0xC71585 }, - { "MidnightBlue", 0x191970 }, - { "MintCream", 0xF5FFFA }, - { "MistyRose", 0xFFE4E1 }, - { "Moccasin", 0xFFE4B5 }, - { "NavajoWhite", 0xFFDEAD }, - { "Navy", 0x000080 }, - { "OldLace", 0xFDF5E6 }, - { "Olive", 0x808000 }, - { "OliveDrab", 0x6B8E23 }, - { "Orange", 0xFFA500 }, - { "OrangeRed", 0xFF4500 }, - { "Orchid", 0xDA70D6 }, - { "PaleGoldenRod", 0xEEE8AA }, - { "PaleGreen", 0x98FB98 }, - { "PaleTurquoise", 0xAFEEEE }, - { "PaleVioletRed", 0xD87093 }, - { "PapayaWhip", 0xFFEFD5 }, - { "PeachPuff", 0xFFDAB9 }, - { "Peru", 0xCD853F }, - { "Pink", 0xFFC0CB }, - { "Plum", 0xDDA0DD }, - { "PowderBlue", 0xB0E0E6 }, - { "Purple", 0x800080 }, - { "Red", 0xFF0000 }, - { "RosyBrown", 0xBC8F8F }, - { "RoyalBlue", 0x4169E1 }, - { "SaddleBrown", 0x8B4513 }, - { "Salmon", 0xFA8072 }, - { "SandyBrown", 0xF4A460 }, - { "SeaGreen", 0x2E8B57 }, - { "SeaShell", 0xFFF5EE }, - { "Sienna", 0xA0522D }, - { "Silver", 0xC0C0C0 }, - { "SkyBlue", 0x87CEEB }, - { "SlateBlue", 0x6A5ACD }, - { "SlateGray", 0x708090 }, - { "SlateGrey", 0x708090 }, - { "Snow", 0xFFFAFA }, - { "SpringGreen", 0x00FF7F }, - { "SteelBlue", 0x4682B4 }, - { "Tan", 0xD2B48C }, - { "Teal", 0x008080 }, - { "Thistle", 0xD8BFD8 }, - { "Tomato", 0xFF6347 }, - { "Turquoise", 0x40E0D0 }, - { "Violet", 0xEE82EE }, - { "Wheat", 0xF5DEB3 }, - { "White", 0xFFFFFF }, - { "WhiteSmoke", 0xF5F5F5 }, - { "Yellow", 0xFFFF00 }, - { "YellowGreen", 0x9ACD32 }, - - { NULL, 0 } -}; - -static int HandleFontAttributes( xml_reader_t *p_xml_reader, - font_stack_t **p_fonts, int i_scale ) -{ - int rv; - char *psz_fontname = NULL; - uint32_t i_font_color = 0xffffff; - int i_font_alpha = 0; - uint32_t i_karaoke_bg_color = 0x00ffffff; - int i_font_size = 24; - - /* Default all attributes to the top font in the stack -- in case not - * all attributes are specified in the sub-font - */ - if( VLC_SUCCESS == PeekFont( p_fonts, - &psz_fontname, - &i_font_size, - &i_font_color, - &i_karaoke_bg_color )) - { - psz_fontname = strdup( psz_fontname ); - i_font_size = i_font_size * 1000 / i_scale; - } - i_font_alpha = (i_font_color >> 24) & 0xff; - i_font_color &= 0x00ffffff; - - while ( xml_ReaderNextAttr( p_xml_reader ) == VLC_SUCCESS ) - { - char *psz_name = xml_ReaderName( p_xml_reader ); - char *psz_value = xml_ReaderValue( p_xml_reader ); - - if( psz_name && psz_value ) - { - if( !strcasecmp( "face", psz_name ) ) - { - free( psz_fontname ); - psz_fontname = strdup( psz_value ); - } - else if( !strcasecmp( "size", psz_name ) ) - { - if( ( *psz_value == '+' ) || ( *psz_value == '-' ) ) - { - int i_value = atoi( psz_value ); - - if( ( i_value >= -5 ) && ( i_value <= 5 ) ) - i_font_size += ( i_value * i_font_size ) / 10; - else if( i_value < -5 ) - i_font_size = - i_value; - else if( i_value > 5 ) - i_font_size = i_value; - } - else - i_font_size = atoi( psz_value ); - } - else if( !strcasecmp( "color", psz_name ) ) - { - if( psz_value[0] == '#' ) - { - i_font_color = strtol( psz_value + 1, NULL, 16 ); - i_font_color &= 0x00ffffff; - } - else - { - for( int i = 0; p_html_colors[i].psz_name != NULL; i++ ) - { - if( !strncasecmp( psz_value, p_html_colors[i].psz_name, strlen(p_html_colors[i].psz_name) ) ) - { - i_font_color = p_html_colors[i].i_value; - break; - } - } - } - } - else if( !strcasecmp( "alpha", psz_name ) && - ( psz_value[0] == '#' ) ) - { - i_font_alpha = strtol( psz_value + 1, NULL, 16 ); - i_font_alpha &= 0xff; - } - } - free( psz_name ); - free( psz_value ); - } - rv = PushFont( p_fonts, - psz_fontname, - i_font_size * i_scale / 1000, - (i_font_color & 0xffffff) | ((i_font_alpha & 0xff) << 24), - i_karaoke_bg_color ); - - free( psz_fontname ); - - return rv; -} - static void SetupLine( filter_t *p_filter, const char *psz_text_in, uint32_t **psz_text_out, uint32_t *pi_runs, uint32_t **ppi_run_lengths, ft_style_t ***ppp_styles, @@ -2086,15 +1671,16 @@ static void SetupLine( filter_t *p_filter, const char *psz_text_in, { (*pi_runs)++; + /* XXX this logic looks somewhat broken */ + if( *ppp_styles ) { - *ppp_styles = (ft_style_t **) - realloc( *ppp_styles, *pi_runs * sizeof( ft_style_t * ) ); + *ppp_styles = realloc_or_free( *ppp_styles, + *pi_runs * sizeof( ft_style_t * ) ); } else if( *pi_runs == 1 ) { - *ppp_styles = (ft_style_t **) - malloc( *pi_runs * sizeof( ft_style_t * ) ); + *ppp_styles = malloc( *pi_runs * sizeof( ft_style_t * ) ); } /* We have just malloc'ed this memory successfully - @@ -2105,10 +1691,12 @@ static void SetupLine( filter_t *p_filter, const char *psz_text_in, p_style = NULL; } + /* XXX more iffy logic */ + if( *ppi_run_lengths ) { - *ppi_run_lengths = (uint32_t *) - realloc( *ppi_run_lengths, *pi_runs * sizeof( uint32_t ) ); + *ppi_run_lengths = realloc_or_free( *ppi_run_lengths, + *pi_runs * sizeof( uint32_t ) ); } else if( *pi_runs == 1 ) { @@ -2128,254 +1716,6 @@ static void SetupLine( filter_t *p_filter, const char *psz_text_in, if( p_style ) DeleteStyle( p_style ); } -static void SetKaraokeLen( uint32_t i_runs, uint32_t *pi_run_lengths, - uint32_t i_k_runs, uint32_t *pi_k_run_lengths ) -{ - /* Karaoke tags _PRECEDE_ the text they specify a duration - * for, therefore we are working out the length for the - * previous tag, and first time through we have nothing - */ - if( pi_k_run_lengths ) - { - int i_chars = 0; - uint32_t i; - - /* Work out how many characters are presently in the string - */ - for( i = 0; i < i_runs; i++ ) - i_chars += pi_run_lengths[ i ]; - - /* Subtract away those we've already allocated to other - * karaoke tags - */ - for( i = 0; i < i_k_runs; i++ ) - i_chars -= pi_k_run_lengths[ i ]; - - pi_k_run_lengths[ i_k_runs - 1 ] = i_chars; - } -} - -static void SetupKaraoke( xml_reader_t *p_xml_reader, uint32_t *pi_k_runs, - uint32_t **ppi_k_run_lengths, - uint32_t **ppi_k_durations ) -{ - while ( xml_ReaderNextAttr( p_xml_reader ) == VLC_SUCCESS ) - { - char *psz_name = xml_ReaderName( p_xml_reader ); - char *psz_value = xml_ReaderValue( p_xml_reader ); - - if( psz_name && psz_value && - !strcasecmp( "t", psz_name ) ) - { - if( ppi_k_durations && ppi_k_run_lengths ) - { - (*pi_k_runs)++; - - if( *ppi_k_durations ) - { - *ppi_k_durations = (uint32_t *) - realloc( *ppi_k_durations, - *pi_k_runs * sizeof( uint32_t ) ); - } - else if( *pi_k_runs == 1 ) - { - *ppi_k_durations = (uint32_t *) - malloc( *pi_k_runs * sizeof( uint32_t ) ); - } - - if( *ppi_k_run_lengths ) - { - *ppi_k_run_lengths = (uint32_t *) - realloc( *ppi_k_run_lengths, - *pi_k_runs * sizeof( uint32_t ) ); - } - else if( *pi_k_runs == 1 ) - { - *ppi_k_run_lengths = (uint32_t *) - malloc( *pi_k_runs * sizeof( uint32_t ) ); - } - 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; - } - } - free( psz_name ); - free( psz_value ); - } -} - -static int ProcessNodes( filter_t *p_filter, - xml_reader_t *p_xml_reader, - text_style_t *p_font_style, - uint32_t *psz_text, - int *pi_len, - - uint32_t *pi_runs, - uint32_t **ppi_run_lengths, - ft_style_t ***ppp_styles, - - bool b_karaoke, - uint32_t *pi_k_runs, - uint32_t **ppi_k_run_lengths, - uint32_t **ppi_k_durations ) -{ - int rv = VLC_SUCCESS; - filter_sys_t *p_sys = p_filter->p_sys; - uint32_t *psz_text_orig = psz_text; - font_stack_t *p_fonts = NULL; - vlc_value_t val; - int i_scale = 1000; - - char *psz_node = NULL; - - 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, - p_font_style->psz_fontname, - p_font_style->i_font_size * i_scale / 1000, - (p_font_style->i_font_color & 0xffffff) | - ((p_font_style->i_font_alpha & 0xff) << 24), - (p_font_style->i_karaoke_background_color & 0xffffff) | - ((p_font_style->i_karaoke_background_alpha & 0xff) << 24)); - - if( p_font_style->i_style_flags & STYLE_BOLD ) - b_bold = true; - if( p_font_style->i_style_flags & STYLE_ITALIC ) - b_italic = true; - if( p_font_style->i_style_flags & STYLE_UNDERLINE ) - b_uline = true; - } - else - { - rv = PushFont( &p_fonts, - FC_DEFAULT_FONT, - p_sys->i_font_size, - 0x00ffffff, - 0x00ffffff ); - } - if( rv != VLC_SUCCESS ) - return rv; - - while ( ( xml_ReaderRead( p_xml_reader ) == 1 ) ) - { - switch ( xml_ReaderNodeType( p_xml_reader ) ) - { - case XML_READER_NONE: - break; - case XML_READER_ENDELEM: - psz_node = xml_ReaderName( p_xml_reader ); - - if( psz_node ) - { - if( !strcasecmp( "font", psz_node ) ) - PopFont( &p_fonts ); - else if( !strcasecmp( "b", psz_node ) ) - b_bold = false; - else if( !strcasecmp( "i", psz_node ) ) - b_italic = false; - else if( !strcasecmp( "u", psz_node ) ) - b_uline = false; - - free( psz_node ); - } - break; - case XML_READER_STARTELEM: - psz_node = xml_ReaderName( p_xml_reader ); - if( psz_node ) - { - if( !strcasecmp( "font", psz_node ) ) - rv = HandleFontAttributes( p_xml_reader, &p_fonts, i_scale ); - else if( !strcasecmp( "b", psz_node ) ) - b_bold = true; - else if( !strcasecmp( "i", psz_node ) ) - b_italic = true; - else if( !strcasecmp( "u", psz_node ) ) - b_uline = true; - else if( !strcasecmp( "br", psz_node ) ) - { - SetupLine( p_filter, "\n", &psz_text, - pi_runs, ppi_run_lengths, ppp_styles, - GetStyleFromFontStack( p_sys, - &p_fonts, - b_bold, - b_italic, - b_uline ) ); - } - else if( !strcasecmp( "k", psz_node ) ) - { - /* Only valid in karaoke */ - if( b_karaoke ) - { - if( *pi_k_runs > 0 ) - { - SetKaraokeLen( *pi_runs, *ppi_run_lengths, - *pi_k_runs, *ppi_k_run_lengths ); - } - SetupKaraoke( p_xml_reader, pi_k_runs, - ppi_k_run_lengths, ppi_k_durations ); - } - } - - free( psz_node ); - } - break; - case XML_READER_TEXT: - psz_node = xml_ReaderValue( p_xml_reader ); - if( psz_node ) - { - /* Turn any multiple-whitespaces into single spaces */ - char *s = strpbrk( psz_node, "\t\r\n " ); - while( s ) - { - int i_whitespace = strspn( s, "\t\r\n " ); - - if( i_whitespace > 1 ) - memmove( &s[1], - &s[i_whitespace], - strlen( s ) - i_whitespace + 1 ); - *s++ = ' '; - - s = strpbrk( s, "\t\r\n " ); - } - SetupLine( p_filter, psz_node, &psz_text, - pi_runs, ppi_run_lengths, ppp_styles, - GetStyleFromFontStack( p_sys, - &p_fonts, - b_bold, - b_italic, - b_uline ) ); - free( psz_node ); - } - break; - } - if( rv != VLC_SUCCESS ) - { - psz_text = psz_text_orig; - break; - } - } - if( b_karaoke ) - { - SetKaraokeLen( *pi_runs, *ppi_run_lengths, - *pi_k_runs, *ppi_k_run_lengths ); - } - - *pi_len = psz_text - psz_text_orig; - - while( VLC_SUCCESS == PopFont( &p_fonts ) ); - - return rv; -} - static int CheckForEmbeddedFont( filter_sys_t *p_sys, FT_Face *pp_face, ft_style_t *p_style ) { int k; @@ -2640,19 +1980,11 @@ static int ProcessLines( filter_t *p_filter, { char *psz_fontfile = NULL; - vlc_mutex_lock( p_sys->p_fontconfig_lock ); - if( p_sys->b_fontconfig_ok ) - { - /* FIXME Is there really a race condition between FontConfig_Select with default fontconfig(NULL) - * and FcConfigBuildFonts ? If not it would be better to remove the check on b_fontconfig_ok */ - 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->p_fontconfig_lock ); - + psz_fontfile = FontConfig_Select( NULL, + p_style->psz_fontname, + p_style->b_bold, + p_style->b_italic, + &i_idx ); if( psz_fontfile && ! *psz_fontfile ) { msg_Warn( p_filter, "Fontconfig was unable to find a font: \"%s\" %s" @@ -2759,6 +2091,9 @@ static int ProcessLines( filter_t *p_filter, if( RenderTag( p_filter, p_face ? p_face : p_sys->p_face, p_style->i_font_color, p_style->b_underline, + p_style->b_through, + p_style->b_bold, + p_style->b_italic, p_style->i_karaoke_bg_color, p_line, psz_unicode, &i_pen_x, i_pen_y, &i_posn, &tmp_result ) != VLC_SUCCESS ) @@ -2855,8 +2190,6 @@ static int RenderHtml( filter_t *p_filter, subpicture_region_t *p_region_out, { int rv = VLC_SUCCESS; stream_t *p_sub = NULL; - xml_t *p_xml = NULL; - xml_reader_t *p_xml_reader = NULL; if( !p_region_in || !p_region_in->psz_html ) return VLC_EGENERIC; @@ -2868,114 +2201,106 @@ static int RenderHtml( filter_t *p_filter, subpicture_region_t *p_region_out, (uint8_t *) p_region_in->psz_html, strlen( p_region_in->psz_html ), true ); - if( p_sub ) + if( unlikely(p_sub == NULL) ) + return VLC_SUCCESS; + + xml_reader_t *p_xml_reader = p_filter->p_sys->p_xml; + bool b_karaoke = false; + + if( !p_xml_reader ) + p_xml_reader = xml_ReaderCreate( p_filter, p_sub ); + else + p_xml_reader = xml_ReaderReset( p_xml_reader, p_sub ); + + p_filter->p_sys->p_xml = p_xml_reader; + if( p_xml_reader ) { - p_xml = xml_Create( p_filter ); - if( p_xml ) + /* Look for Root Node */ + if( xml_ReaderRead( p_xml_reader ) == 1 ) { - bool b_karaoke = false; + char *psz_node = xml_ReaderName( p_xml_reader ); - p_xml_reader = xml_ReaderCreate( p_xml, p_sub ); - if( p_xml_reader ) + if( !strcasecmp( "karaoke", psz_node ) ) { - /* Look for Root Node */ - if( xml_ReaderRead( p_xml_reader ) == 1 ) - { - char *psz_node = xml_ReaderName( p_xml_reader ); - - if( !strcasecmp( "karaoke", psz_node ) ) - { - /* 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", true ); - b_karaoke = true; - } - else if( !strcasecmp( "text", psz_node ) ) - { - 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; - } - - free( psz_node ); - } + /* 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", true ); + b_karaoke = true; } - - if( p_xml_reader ) + else if( !strcasecmp( "text", psz_node ) ) { - uint32_t *psz_text; - int i_len = 0; - uint32_t i_runs = 0; - uint32_t i_k_runs = 0; - uint32_t *pi_run_lengths = NULL; - uint32_t *pi_k_run_lengths = NULL; - uint32_t *pi_k_durations = NULL; - ft_style_t **pp_styles = NULL; - FT_Vector result; - line_desc_t *p_lines = NULL; - - psz_text = (uint32_t *)malloc( strlen( p_region_in->psz_html ) * - sizeof( uint32_t ) ); - if( psz_text ) - { - uint32_t k; + b_karaoke = false; + } + else + { + /* Only text and karaoke tags are supported */ + msg_Dbg( p_filter, "Unsupported top-level tag '%s' ignored.", psz_node ); + p_filter->p_sys->p_xml = xml_ReaderReset( p_xml_reader, NULL ); + p_xml_reader = NULL; + rv = VLC_EGENERIC; + } - rv = ProcessNodes( p_filter, p_xml_reader, - p_region_in->p_style, psz_text, &i_len, - &i_runs, &pi_run_lengths, &pp_styles, - b_karaoke, &i_k_runs, &pi_k_run_lengths, - &pi_k_durations ); + free( psz_node ); + } + } - p_region_out->i_x = p_region_in->i_x; - p_region_out->i_y = p_region_in->i_y; + if( p_xml_reader ) + { + uint32_t *psz_text; + int i_len = 0; + uint32_t i_runs = 0; + uint32_t i_k_runs = 0; + uint32_t *pi_run_lengths = NULL; + uint32_t *pi_k_run_lengths = NULL; + uint32_t *pi_k_durations = NULL; + ft_style_t **pp_styles = NULL; + FT_Vector result; + line_desc_t *p_lines = NULL; - if(( rv == VLC_SUCCESS ) && ( i_len > 0 )) - { - rv = ProcessLines( p_filter, psz_text, i_len, i_runs, - pi_run_lengths, pp_styles, &p_lines, &result, - b_karaoke, i_k_runs, pi_k_run_lengths, - pi_k_durations ); - } + psz_text = (uint32_t *)malloc( strlen( p_region_in->psz_html ) * + sizeof( uint32_t ) ); + if( psz_text ) + { + rv = ProcessNodes( p_filter, p_xml_reader, + p_region_in->p_style, psz_text, &i_len, + &i_runs, &pi_run_lengths, &pp_styles, + b_karaoke, &i_k_runs, &pi_k_run_lengths, + &pi_k_durations ); - for( k=0; ki_x = p_region_in->i_x; + p_region_out->i_y = p_region_in->i_y; - /* Don't attempt to render text that couldn't be layed out - * properly. - */ - if(( rv == VLC_SUCCESS ) && ( i_len > 0 )) - { - if( config_GetInt( p_filter, "freetype-yuvp" ) ) - { - Render( p_filter, p_region_out, p_lines, - result.x, result.y ); - } - else - { - RenderYUVA( p_filter, p_region_out, p_lines, - result.x, result.y ); - } - } - } - FreeLines( p_lines ); + if(( rv == VLC_SUCCESS ) && ( i_len > 0 )) + { + rv = ProcessLines( p_filter, psz_text, i_len, i_runs, + pi_run_lengths, pp_styles, &p_lines, + &result, b_karaoke, i_k_runs, + pi_k_run_lengths, pi_k_durations ); + } - xml_ReaderDelete( p_xml, p_xml_reader ); + for( uint_fast32_t k=0; k 0 )) + { + if( var_InheritBool( p_filter, "freetype-yuvp" ) ) + Render( p_filter, p_region_out, p_lines, + result.x, result.y ); + else + RenderYUVA( p_filter, p_region_out, p_lines, + result.x, result.y ); } - xml_Delete( p_xml ); } - stream_Delete( p_sub ); + p_filter->p_sys->p_xml = xml_ReaderReset( p_xml_reader, NULL ); + FreeLines( p_lines ); } - + stream_Delete( p_sub ); return rv; } @@ -3040,6 +2365,34 @@ static char* FontConfig_Select( FcConfig* priv, const char* family, FcPatternDestroy( p_pat ); return strdup( (const char*)val_s ); } +#else + +static void SetupLine( filter_t *p_filter, const char *psz_text_in, + uint32_t **psz_text_out, uint32_t *pi_runs, + uint32_t **ppi_run_lengths, ft_style_t ***ppp_styles, + ft_style_t *p_style ) +{ + VLC_UNUSED(p_filter); + VLC_UNUSED(psz_text_in); + VLC_UNUSED(psz_text_out); + VLC_UNUSED(pi_runs); + VLC_UNUSED(ppi_run_lengths); + VLC_UNUSED(ppp_styles); + VLC_UNUSED(p_style); +} + +static ft_style_t *GetStyleFromFontStack( filter_sys_t *p_sys, + font_stack_t **p_fonts, bool b_bold, bool b_italic, + bool b_uline, bool b_through ) +{ + VLC_UNUSED(p_sys); + VLC_UNUSED(p_fonts); + VLC_UNUSED(b_bold); + VLC_UNUSED(b_italic); + VLC_UNUSED(b_uline); + VLC_UNUSED(b_through); + return NULL; +} #endif static void FreeLine( line_desc_t *p_line ) @@ -3086,7 +2439,7 @@ static line_desc_t *NewLine( int i_count ) p_line->p_fg_rgb = malloc( sizeof( uint32_t ) * ( i_count + 1 ) ); p_line->p_bg_rgb = malloc( sizeof( uint32_t ) * ( i_count + 1 ) ); p_line->p_fg_bg_ratio = calloc( i_count + 1, sizeof( uint8_t ) ); - p_line->pi_underline_offset = calloc( i_count + 1, sizeof( uint16_t ) ); + p_line->pi_underline_offset = calloc( i_count + 1, sizeof( int ) ); p_line->pi_underline_thickness = calloc( i_count + 1, sizeof( uint16_t ) ); if( ( p_line->pp_glyphs == NULL ) || ( p_line->p_glyph_pos == NULL ) ||