X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fmisc%2Fquartztext.c;h=d21dfbc37da7f2cd3724a402f3b2c3fdc7989cc7;hb=03967e7ffa33848362d39bccd0af4b32b8c4e7f0;hp=5fa5fd1bd40747fbd1f2b30552ce7d9054d0af09;hpb=7ba52d76b498cf669ce346052bac0a7d28825b66;p=vlc diff --git a/modules/misc/quartztext.c b/modules/misc/quartztext.c index 5fa5fd1bd4..d21dfbc37d 100644 --- a/modules/misc/quartztext.c +++ b/modules/misc/quartztext.c @@ -24,10 +24,13 @@ ////////////////////////////////////////////////////////////////////////////// // Preamble ////////////////////////////////////////////////////////////////////////////// -#include // malloc(), free() -#include -#include +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include #include #include #include @@ -60,14 +63,15 @@ static int RenderText( filter_t *, subpicture_region_t *, static int RenderHtml( filter_t *, subpicture_region_t *, subpicture_region_t * ); +static int GetFontSize( filter_t *p_filter ); static int RenderYUVA( filter_t *p_filter, subpicture_region_t *p_region, UniChar *psz_utfString, uint32_t i_text_len, uint32_t i_runs, uint32_t *pi_run_lengths, ATSUStyle *pp_styles ); static ATSUStyle CreateStyle( char *psz_fontname, int i_font_size, - int i_font_color, int i_font_alpha, - vlc_bool_t b_bold, vlc_bool_t b_italic, - vlc_bool_t b_uline ); + uint32_t i_font_color, + bool b_bold, bool b_italic, + bool b_uline ); ////////////////////////////////////////////////////////////////////////////// // Module descriptor ////////////////////////////////////////////////////////////////////////////// @@ -77,12 +81,46 @@ static ATSUStyle CreateStyle( char *psz_fontname, int i_font_size, // RenderText. This module, unlike Freetype, doesn't provide any options to // override the fallback font selection used when this style information is // absent. +#define FONT_TEXT N_("Font") +#define FONT_LONGTEXT N_("Name for the font you want to use") +#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." ) +#define COLOR_TEXT N_("Text default color") +#define COLOR_LONGTEXT N_("The color of the text that will be rendered on "\ + "the video. This must be an hexadecimal (like HTML colors). The first two "\ + "chars are for red, then green, then blue. #000000 = black, #FF0000 = red,"\ + " #00FF00 = green, #FFFF00 = yellow (red + green), #FFFFFF = white" ) + +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 *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") }; + +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") }; + vlc_module_begin(); - set_shortname( _("Mac Text renderer")); - set_description( _("Quartz font renderer") ); + set_shortname( N_("Mac Text renderer")); + set_description( N_("Quartz font renderer") ); set_category( CAT_VIDEO ); set_subcategory( SUBCAT_VIDEO_SUBPIC ); + add_string( "quartztext-font", DEFAULT_FONT, NULL, FONT_TEXT, FONT_LONGTEXT, + false ); + add_integer( "quartztext-rel-fontsize", DEFAULT_REL_FONT_SIZE, NULL, FONTSIZER_TEXT, + FONTSIZER_LONGTEXT, false ); + change_integer_list( pi_sizes, ppsz_sizes_text, 0 ); + add_integer( "quartztext-color", 0x00FFFFFF, NULL, COLOR_TEXT, + COLOR_LONGTEXT, false ); + change_integer_list( pi_color_values, ppsz_color_descriptions, 0 ); set_capability( "text renderer", 120 ); add_shortcut( "text" ); set_callbacks( Create, Destroy ); @@ -93,8 +131,7 @@ struct font_stack_t { char *psz_name; int i_size; - int i_color; - int i_alpha; + uint32_t i_color; // ARGB font_stack_t *p_next; }; @@ -139,14 +176,11 @@ static int Create( vlc_object_t *p_this ) // 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->psz_font_name = strdup( DEFAULT_FONT ); + p_sys->psz_font_name = var_CreateGetString( p_this, "quartztext-font" ); p_sys->i_font_opacity = 255; - p_sys->i_font_color = DEFAULT_FONT_COLOR; - p_sys->i_font_size = p_filter->fmt_out.video.i_height / DEFAULT_REL_FONT_SIZE; + p_sys->i_font_color = __MAX( __MIN( var_CreateGetInteger( p_this, "quartztext-color" ) , 0xFFFFFF ), 0 ); + p_sys->i_font_size = GetFontSize( p_filter ); p_filter->pf_render_text = RenderText; p_filter->pf_render_html = RenderHtml; @@ -181,8 +215,7 @@ static void Destroy( vlc_object_t *p_this ) free( p_sys->p_fonts ); } - if( p_sys->psz_font_name ) free( p_sys->psz_font_name ); - + free( p_sys->psz_font_name ); free( p_sys ); } @@ -202,9 +235,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_fonts = 0; p_sys->p_fonts = malloc( i_attachments_cnt * sizeof( ATSFontContainerRef ) ); @@ -238,7 +274,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; } @@ -247,52 +285,52 @@ static int LoadFontsFromAttachments( filter_t *p_filter ) // Original version of these functions available on: // http://developer.apple.com/documentation/Carbon/Conceptual/QuickDrawToQuartz2D/tq_color/chapter_4_section_3.html -#define kGenericRGBProfilePathStr "/System/Library/ColorSync/Profiles/Generic RGB Profile.icc" - +#define kGenericRGBProfilePathStr "/System/Library/ColorSync/Profiles/Generic RGB Profile.icc" + static CMProfileRef OpenGenericProfile( void ) { static CMProfileRef cached_rgb_prof = NULL; - + // Create the profile reference only once if( cached_rgb_prof == NULL ) { OSStatus err; CMProfileLocation loc; - + loc.locType = cmPathBasedProfile; strcpy( loc.u.pathLoc.path, kGenericRGBProfilePathStr ); - + err = CMOpenProfile( &cached_rgb_prof, &loc ); - + if( err != noErr ) { cached_rgb_prof = NULL; } } - + if( cached_rgb_prof ) { - // Clone the profile reference so that the caller has + // Clone the profile reference so that the caller has // their own reference, not our cached one. - CMCloneProfileRef( cached_rgb_prof ); + CMCloneProfileRef( cached_rgb_prof ); } - + return cached_rgb_prof; } static CGColorSpaceRef CreateGenericRGBColorSpace( void ) { static CGColorSpaceRef p_generic_rgb_cs = NULL; - + if( p_generic_rgb_cs == NULL ) { CMProfileRef generic_rgb_prof = OpenGenericProfile(); - + if( generic_rgb_prof ) { p_generic_rgb_cs = CGColorSpaceCreateWithPlatformColorSpace( generic_rgb_prof ); - - CMCloseProfile( generic_rgb_prof ); + + CMCloseProfile( generic_rgb_prof ); } } @@ -336,7 +374,7 @@ static void ConvertToUTF16( const char *psz_utf8_str, uint32_t *pi_strlen, UniCh *ppsz_utf16_str = (UniChar *) calloc( i_string_length, sizeof( UniChar ) ); CFStringGetCharacters( p_cfString, CFRangeMake( 0, i_string_length ), *ppsz_utf16_str ); - + CFRelease( p_cfString ); } @@ -350,17 +388,24 @@ static int RenderText( filter_t *p_filter, subpicture_region_t *p_region_out, uint32_t i_string_length; char *psz_string; int i_font_color, i_font_alpha, i_font_size; + vlc_value_t val; + int i_scale = 1000; + + p_sys->i_font_size = GetFontSize( p_filter ); // Sanity check if( !p_region_in || !p_region_out ) return VLC_EGENERIC; psz_string = p_region_in->psz_text; if( !psz_string || !*psz_string ) return VLC_EGENERIC; - + + 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 ); i_font_alpha = __MAX( __MIN( p_region_in->p_style->i_font_alpha, 255 ), 0 ); - i_font_size = __MAX( __MIN( p_region_in->p_style->i_font_size, 255 ), 0 ); + i_font_size = __MAX( __MIN( p_region_in->p_style->i_font_size, 255 ), 0 ) * i_scale / 1000; } else { @@ -370,7 +415,7 @@ static int RenderText( filter_t *p_filter, subpicture_region_t *p_region_out, } if( !i_font_alpha ) i_font_alpha = 255 - p_sys->i_font_opacity; - + ConvertToUTF16( EliminateCRLF( psz_string ), &i_string_length, &psz_utf16_str ); p_region_out->i_x = p_region_in->i_x; @@ -379,8 +424,9 @@ static int RenderText( filter_t *p_filter, subpicture_region_t *p_region_out, if( psz_utf16_str != NULL ) { ATSUStyle p_style = CreateStyle( p_sys->psz_font_name, i_font_size, - i_font_color, i_font_alpha, - VLC_FALSE, VLC_FALSE, VLC_FALSE ); + (i_font_color & 0xffffff) | + ((i_font_alpha & 0xff) << 24), + false, false, false ); if( p_style ) { RenderYUVA( p_filter, p_region_out, psz_utf16_str, i_string_length, @@ -395,8 +441,8 @@ static int RenderText( filter_t *p_filter, subpicture_region_t *p_region_out, } -static ATSUStyle CreateStyle( char *psz_fontname, int i_font_size, int i_font_color, int i_font_alpha, - vlc_bool_t b_bold, vlc_bool_t b_italic, vlc_bool_t b_uline ) +static ATSUStyle CreateStyle( char *psz_fontname, int i_font_size, uint32_t i_font_color, + bool b_bold, bool b_italic, bool b_uline ) { ATSUStyle p_style; OSStatus status; @@ -405,7 +451,7 @@ static ATSUStyle CreateStyle( char *psz_fontname, int i_font_size, int i_font_co float f_red = (float)(( i_font_color & 0x00FF0000 ) >> 16) / 255.0; float f_green = (float)(( i_font_color & 0x0000FF00 ) >> 8) / 255.0; float f_blue = (float)( i_font_color & 0x000000FF ) / 255.0; - float f_alpha = ( 255.0 - (float)i_font_alpha) / 255.0; + float f_alpha = ( 255.0 - (float)(( i_font_color & 0xFF000000 ) >> 24)) / 255.0; ATSUFontID font; Fixed font_size = IntToFixed( i_font_size ); @@ -448,7 +494,7 @@ static ATSUStyle CreateStyle( char *psz_fontname, int i_font_size, int i_font_co } static int PushFont( font_stack_t **p_font, const char *psz_name, int i_size, - int i_color, int i_alpha ) + uint32_t i_color ) { font_stack_t *p_new; @@ -456,6 +502,9 @@ static int PushFont( font_stack_t **p_font, const char *psz_name, int i_size, return VLC_EGENERIC; p_new = malloc( sizeof( font_stack_t ) ); + if( ! p_new ) + return VLC_ENOMEM; + p_new->p_next = NULL; if( psz_name ) @@ -465,7 +514,6 @@ static int PushFont( font_stack_t **p_font, const char *psz_name, int i_size, p_new->i_size = i_size; p_new->i_color = i_color; - p_new->i_alpha = i_alpha; if( !*p_font ) { @@ -491,7 +539,7 @@ static int PopFont( font_stack_t **p_font ) if( !p_font || !*p_font ) return VLC_EGENERIC; - + p_next_to_last = NULL; for( p_last = *p_font; p_last->p_next; @@ -512,13 +560,13 @@ static int PopFont( font_stack_t **p_font ) } static int PeekFont( font_stack_t **p_font, char **psz_name, int *i_size, - int *i_color, int *i_alpha ) + uint32_t *i_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 ) @@ -527,63 +575,155 @@ static int PeekFont( font_stack_t **p_font, char **psz_name, int *i_size, *psz_name = p_last->psz_name; *i_size = p_last->i_size; *i_color = p_last->i_color; - *i_alpha = p_last->i_alpha; return VLC_SUCCESS; } -static ATSUStyle 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 ) +static ATSUStyle GetStyleFromFontStack( filter_sys_t *p_sys, + font_stack_t **p_fonts, bool b_bold, bool b_italic, + bool b_uline ) { ATSUStyle p_style = NULL; - char *psz_fontname = NULL; - int i_font_color = p_sys->i_font_color; - int i_font_alpha = 0; - int i_font_size = p_sys->i_font_size; + char *psz_fontname = NULL; + uint32_t i_font_color = p_sys->i_font_color; + int i_font_size = p_sys->i_font_size; - if( VLC_SUCCESS == PeekFont( p_fonts, &psz_fontname, &i_font_size, &i_font_color, &i_font_alpha ) ) + if( VLC_SUCCESS == PeekFont( p_fonts, &psz_fontname, &i_font_size, + &i_font_color )) { - p_style = CreateStyle( psz_fontname, i_font_size, i_font_color, i_font_alpha, + p_style = CreateStyle( psz_fontname, i_font_size, i_font_color, b_bold, b_italic, b_uline ); } return p_style; } -static void ProcessNodes( filter_t *p_filter, xml_reader_t *p_xml_reader, - text_style_t *p_font_style, UniChar *psz_text, int *pi_len, - uint32_t *pi_runs, uint32_t **ppi_run_lengths, - ATSUStyle **ppp_styles) +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; + 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 )) + { + 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 ) && + ( psz_value[0] == '#' ) ) + { + i_font_color = strtol( psz_value + 1, NULL, 16 ); + i_font_color &= 0x00ffffff; + } + 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) ); + + free( psz_fontname ); + + return rv; +} + +static int ProcessNodes( filter_t *p_filter, + xml_reader_t *p_xml_reader, + text_style_t *p_font_style, + UniChar *psz_text, + int *pi_len, + + uint32_t *pi_runs, + uint32_t **ppi_run_lengths, + ATSUStyle **ppp_styles ) { + int rv = VLC_SUCCESS; filter_sys_t *p_sys = p_filter->p_sys; UniChar *psz_text_orig = psz_text; font_stack_t *p_fonts = NULL; + vlc_value_t val; + int i_scale = 1000; 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 ) { - PushFont( &p_fonts, - p_font_style->psz_fontname, - p_font_style->i_font_size, - p_font_style->i_font_color, - p_font_style->i_font_alpha ); - + 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) ); + 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 { - PushFont( &p_fonts, p_sys->psz_font_name, p_sys->i_font_size, p_sys->i_font_color, 0 ); + rv = PushFont( &p_fonts, + p_sys->psz_font_name, + p_sys->i_font_size, + p_sys->i_font_color ); } + if( rv != VLC_SUCCESS ) + return rv; while ( ( xml_ReaderRead( p_xml_reader ) == 1 ) ) { @@ -593,18 +733,18 @@ static void ProcessNodes( filter_t *p_filter, xml_reader_t *p_xml_reader, 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 = 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 ); } break; @@ -613,78 +753,13 @@ static void ProcessNodes( filter_t *p_filter, xml_reader_t *p_xml_reader, if( psz_node ) { if( !strcasecmp( "font", psz_node ) ) - { - char *psz_fontname = NULL; - int i_font_color = 0xffffff; - int i_font_alpha = 0; - 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_font_alpha )) - { - psz_fontname = strdup( psz_fontname ); - } - - 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 ) ) - { - if( psz_fontname ) 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 ) && - ( psz_value[0] == '#' ) ) - { - i_font_color = strtol( psz_value+1, NULL, 16 ); - i_font_color &= 0x00ffffff; - } - 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 ); - } - } - PushFont( &p_fonts, psz_fontname, i_font_size, i_font_color, i_font_alpha ); - free( psz_fontname ); - } + 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 ) ) { uint32_t i_string_length; @@ -760,6 +835,8 @@ static void ProcessNodes( filter_t *p_filter, xml_reader_t *p_xml_reader, *pi_len = psz_text - psz_text_orig; while( VLC_SUCCESS == PopFont( &p_fonts ) ); + + return rv; } static int RenderHtml( filter_t *p_filter, subpicture_region_t *p_region_out, @@ -773,42 +850,83 @@ static int RenderHtml( filter_t *p_filter, subpicture_region_t *p_region_out, if( !p_region_in || !p_region_in->psz_html ) return VLC_EGENERIC; + /* Reset the default fontsize in case screen metrics have changed */ + p_filter->p_sys->i_font_size = GetFontSize( p_filter ); + 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 ) { + bool b_karaoke = false; + p_xml_reader = xml_ReaderCreate( p_xml, p_sub ); + if( p_xml_reader ) + { + /* 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 */ + xml_ReaderDelete( p_xml, p_xml_reader ); + p_xml_reader = NULL; + rv = VLC_EGENERIC; + } + + free( psz_node ); + } + } + if( p_xml_reader ) { UniChar *psz_text; - int i_len; + int i_len = 0; uint32_t i_runs = 0; uint32_t *pi_run_lengths = NULL; ATSUStyle *pp_styles = NULL; - psz_text = (UniChar *) calloc( strlen( p_region_in->psz_html ), sizeof( UniChar ) ); + psz_text = (UniChar *) malloc( strlen( p_region_in->psz_html ) * + sizeof( UniChar ) ); if( psz_text ) { uint32_t k; - ProcessNodes( p_filter, p_xml_reader, p_region_in->p_style, psz_text, - &i_len, &i_runs, &pi_run_lengths, &pp_styles ); + rv = ProcessNodes( p_filter, p_xml_reader, + p_region_in->p_style, psz_text, &i_len, + &i_runs, &pi_run_lengths, &pp_styles ); p_region_out->i_x = p_region_in->i_x; p_region_out->i_y = p_region_in->i_y; - RenderYUVA( p_filter, p_region_out, psz_text, i_len, i_runs, pi_run_lengths, pp_styles); + if(( rv == VLC_SUCCESS ) && ( i_len > 0 )) + { + RenderYUVA( p_filter, p_region_out, psz_text, i_len, i_runs, + pi_run_lengths, pp_styles); + } for( k=0; k 1.0 ) ? 1.0 : f_thickness )); @@ -978,6 +1096,11 @@ static offscreen_bitmap_t *Compose( int i_text_align, UniChar *psz_utf16_str, ui return p_offScreen; } +static int GetFontSize( filter_t *p_filter ) +{ + return p_filter->fmt_out.video.i_height / __MAX(1, var_CreateGetInteger( p_filter, "quartztext-rel-fontsize" )); +} + static int RenderYUVA( filter_t *p_filter, subpicture_region_t *p_region, UniChar *psz_utf16_str, uint32_t i_text_len, uint32_t i_runs, uint32_t *pi_run_lengths, ATSUStyle *pp_styles ) {