X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fmisc%2Fquartztext.c;h=db8222ad973d76dba98c4199c1547c8d168dc87d;hb=04aae4db17b7b59c04870677448a0b49262b5f71;hp=379b9069c6e8fe31b3c29538099252c40a08a831;hpb=e3204e44686cfccc0b633b2a76914e6536ceb5c4;p=vlc diff --git a/modules/misc/quartztext.c b/modules/misc/quartztext.c index 379b9069c6..db8222ad97 100644 --- a/modules/misc/quartztext.c +++ b/modules/misc/quartztext.c @@ -4,7 +4,7 @@ * Copyright (C) 2007 the VideoLAN team * $Id$ * - * Authors: Bernie Purcell + * Authors: Bernie Purcell * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,16 +24,20 @@ ////////////////////////////////////////////////////////////////////////////// // Preamble ////////////////////////////////////////////////////////////////////////////// -#include // malloc(), free() -#include + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif #include +#include #include #include #include #include #include #include +#include #include @@ -52,19 +56,22 @@ static int Create ( vlc_object_t * ); static void Destroy( vlc_object_t * ); +static int LoadFontsFromAttachments( filter_t *p_filter ); + static int RenderText( filter_t *, subpicture_region_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 ////////////////////////////////////////////////////////////////////////////// @@ -90,8 +97,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; }; @@ -118,6 +124,9 @@ struct filter_sys_t uint8_t i_font_opacity; int i_font_color; int i_font_size; + + ATSFontContainerRef *p_fonts; + int i_fonts; }; ////////////////////////////////////////////////////////////////////////////// @@ -140,11 +149,16 @@ static int Create( vlc_object_t *p_this ) p_sys->psz_font_name = strdup( DEFAULT_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_size = GetFontSize( p_filter ); p_filter->pf_render_text = RenderText; p_filter->pf_render_html = RenderHtml; + p_sys->p_fonts = NULL; + p_sys->i_fonts = 0; + + LoadFontsFromAttachments( p_filter ); + return VLC_SUCCESS; } @@ -158,60 +172,134 @@ static void Destroy( vlc_object_t *p_this ) filter_t *p_filter = (filter_t *)p_this; filter_sys_t *p_sys = p_filter->p_sys; + if( p_sys->p_fonts ) + { + int k; + + for( k = 0; k < p_sys->i_fonts; k++ ) + { + ATSFontDeactivate( p_sys->p_fonts[k], NULL, kATSOptionFlagsDefault ); + } + + free( p_sys->p_fonts ); + } + free( p_sys->psz_font_name ); free( p_sys ); } +////////////////////////////////////////////////////////////////////////////// +// Make any TTF/OTF fonts present in the attachments of the media file +// available to the Quartz engine for text rendering +////////////////////////////////////////////////////////////////////////////// +static int LoadFontsFromAttachments( filter_t *p_filter ) +{ + filter_sys_t *p_sys = p_filter->p_sys; + input_thread_t *p_input; + input_attachment_t **pp_attachments; + int i_attachments_cnt; + int k; + int rv = VLC_SUCCESS; + + p_input = (input_thread_t *)vlc_object_find( p_filter, VLC_OBJECT_INPUT, FIND_PARENT ); + if( ! p_input ) + return VLC_EGENERIC; + + if( VLC_SUCCESS != input_Control( p_input, INPUT_GET_ATTACHMENTS, &pp_attachments, &i_attachments_cnt )) + { + vlc_object_release(p_input); + return VLC_EGENERIC; + } + + p_sys->i_fonts = 0; + p_sys->p_fonts = malloc( i_attachments_cnt * sizeof( ATSFontContainerRef ) ); + if(! p_sys->p_fonts ) + rv = VLC_ENOMEM; + + for( k = 0; k < i_attachments_cnt; k++ ) + { + input_attachment_t *p_attach = pp_attachments[k]; + + if( p_sys->p_fonts ) + { + 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 ) ) + { + ATSFontContainerRef container; + + if( noErr == ATSFontActivateFromMemory( p_attach->p_data, + p_attach->i_data, + kATSFontContextLocal, + kATSFontFormatUnspecified, + NULL, + kATSOptionFlagsDefault, + &container )) + { + p_sys->p_fonts[ p_sys->i_fonts++ ] = container; + } + } + } + vlc_input_attachment_Delete( p_attach ); + } + free( pp_attachments ); + + vlc_object_release(p_input); + + return rv; +} + #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_4 // 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 ); } } @@ -255,7 +343,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 ); } @@ -269,17 +357,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 { @@ -289,7 +384,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; @@ -298,8 +393,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, @@ -314,8 +410,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; @@ -324,7 +420,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 ); @@ -367,7 +463,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; @@ -375,6 +471,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 ) @@ -384,7 +483,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 ) { @@ -410,7 +508,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; @@ -431,13 +529,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 ) @@ -446,63 +544,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 ) ) { @@ -512,18 +702,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; @@ -532,66 +722,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 ) ) - { - 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; @@ -624,6 +761,21 @@ static void ProcessNodes( filter_t *p_filter, xml_reader_t *p_xml_reader, { uint32_t i_string_length; + // 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 " ); + } + ConvertToUTF16( psz_node, &i_string_length, &psz_text ); psz_text += i_string_length; @@ -652,6 +804,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, @@ -665,42 +819,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; kfmt_out.video.i_height / DEFAULT_REL_FONT_SIZE; +} + 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 ) { @@ -878,19 +1078,22 @@ static int RenderYUVA( filter_t *p_filter, subpicture_region_t *p_region, UniCha int i_width = p_filter->fmt_out.video.i_visible_width; int i_height = p_filter->fmt_out.video.i_visible_height; + int i_text_align = p_region->i_align & 0x3; - if( psz_utf16_str != NULL ) + if( !psz_utf16_str ) { - int i_text_align = 0; + msg_Err( p_filter, "Invalid argument to RenderYUVA" ); + return VLC_EGENERIC; + } - if( p_region->p_style ) - i_text_align = p_region->p_style->i_text_align; - else - i_text_align = p_region->i_align & 0x3; + p_offScreen = Compose( i_text_align, psz_utf16_str, i_text_len, + i_runs, pi_run_lengths, pp_styles, + i_width, i_height, &i_textblock_height ); - p_offScreen = Compose( i_text_align, psz_utf16_str, i_text_len, - i_runs, pi_run_lengths, pp_styles, - i_width, i_height, &i_textblock_height ); + if( !p_offScreen ) + { + msg_Err( p_filter, "No offscreen buffer" ); + return VLC_EGENERIC; } uint8_t *p_dst_y,*p_dst_u,*p_dst_v,*p_dst_a;