diff --git a/include/vlc_filter.h b/include/vlc_filter.h index dfb4b6ab8a..f2edd805e8 100644 --- a/include/vlc_filter.h +++ b/include/vlc_filter.h @@ -136,15 +136,11 @@ struct filter_t struct { - int (*pf_text) ( filter_t *, subpicture_region_t *, - subpicture_region_t *, - const vlc_fourcc_t * ); - int (*pf_html) ( filter_t *, subpicture_region_t *, + int (*pf_render) ( filter_t *, subpicture_region_t *, subpicture_region_t *, const vlc_fourcc_t * ); } render; -#define pf_render_text u.render.pf_text -#define pf_render_html u.render.pf_html +#define pf_render u.render.pf_render } u; diff --git a/include/vlc_subpicture.h b/include/vlc_subpicture.h index 52696c8a4f..a5f827a4c2 100644 --- a/include/vlc_subpicture.h +++ b/include/vlc_subpicture.h @@ -65,8 +65,6 @@ struct subpicture_region_t int i_alpha; /**< transparency */ text_segment_t *p_text; /**< subtitle text, made of a list of segments */ - char *psz_html; /**< HTML version of subtitle (NULL = use psz_text) */ - text_style_t *p_style; /**< a description of the text style formatting */ bool b_renderbg; /**< render black background under text */ subpicture_region_t *p_next; /**< next region in the list */ diff --git a/modules/codec/arib/aribsub.c b/modules/codec/arib/aribsub.c index a23d71400d..d22a474f48 100644 --- a/modules/codec/arib/aribsub.c +++ b/modules/codec/arib/aribsub.c @@ -298,7 +298,6 @@ static subpicture_t *render( decoder_t *p_dec, arib_parser_t *p_parser, p_region->psz_text = strdup( psz_text ); free( psz_text ); - p_region->psz_html = NULL; p_region->psz_fontname = NULL; p_region->i_font_color = p_buf_region->i_foreground_color; p_region->i_planewidth = p_buf_region->i_planewidth; diff --git a/modules/codec/arib/substext.h b/modules/codec/arib/substext.h index e787b7bf79..24d3fdafb6 100644 --- a/modules/codec/arib/substext.h +++ b/modules/codec/arib/substext.h @@ -23,7 +23,6 @@ typedef struct arib_text_region_s { char *psz_text; - char *psz_html; char *psz_fontname; int i_font_color; @@ -97,9 +96,7 @@ static void SubpictureTextUpdate(subpicture_t *subpic, return; } - if( p_region->psz_text ) - r->p_text = text_segment_New( p_region->psz_text ); - r->psz_html = p_region->psz_html ? strdup(p_region->psz_html) : NULL; + r->p_text = text_segment_New( p_region->psz_text ); r->i_align = SUBPICTURE_ALIGN_LEFT | SUBPICTURE_ALIGN_TOP; subpic->i_original_picture_width = p_region->i_planewidth; @@ -107,16 +104,16 @@ static void SubpictureTextUpdate(subpicture_t *subpic, r->i_x = p_region->i_charleft - (p_region->i_fontwidth + p_region->i_horint / 2) + p_region->i_charleft_adj; r->i_y = p_region->i_charbottom - (p_region->i_fontheight + p_region->i_verint / 2) + p_region->i_charbottom_adj; - r->p_style = text_style_New(); - r->p_style->psz_fontname = p_region->psz_fontname ? strdup( p_region->psz_fontname ) : NULL; - r->p_style->i_font_size = p_region->i_fontheight; - r->p_style->i_font_color = p_region->i_font_color; - r->p_style->i_style_flags = 0; + r->p_text->style = text_style_New(); + r->p_text->style->psz_fontname = p_region->psz_fontname ? strdup( p_region->psz_fontname ) : NULL; + r->p_text->style->i_font_size = p_region->i_fontheight; + r->p_text->style->i_font_color = p_region->i_font_color; + r->p_text->style->i_style_flags = 0; if( p_region->i_fontwidth < p_region->i_fontheight ) { - r->p_style->i_style_flags |= STYLE_HALFWIDTH; + r->p_text->style->i_style_flags |= STYLE_HALFWIDTH; } - r->p_style->i_spacing = p_region->i_horint; + r->p_text->style->i_spacing = p_region->i_horint; } } static void SubpictureTextDestroy(subpicture_t *subpic) @@ -127,7 +124,6 @@ static void SubpictureTextDestroy(subpicture_t *subpic) for( p_region = sys->p_region; p_region; p_region = p_region_next ) { free( p_region->psz_text ); - free( p_region->psz_html ); free( p_region->psz_fontname ); p_region_next = p_region->p_next; free( p_region ); diff --git a/modules/codec/cc.c b/modules/codec/cc.c index db279cc67c..e6cec745be 100644 --- a/modules/codec/cc.c +++ b/modules/codec/cc.c @@ -296,7 +296,7 @@ static block_t *Pop( decoder_t *p_dec ) return p_block; } -static subpicture_t *Subtitle( decoder_t *p_dec, char *psz_subtitle, char *psz_html, mtime_t i_pts ) +static subpicture_t *Subtitle( decoder_t *p_dec, char *psz_subtitle, mtime_t i_pts ) { //decoder_sys_t *p_sys = p_dec->p_sys; subpicture_t *p_spu = NULL; @@ -306,20 +306,16 @@ static subpicture_t *Subtitle( decoder_t *p_dec, char *psz_subtitle, char *psz_h { msg_Warn( p_dec, "subtitle without a date" ); free( psz_subtitle ); - free( psz_html ); return NULL; } EnsureUTF8( psz_subtitle ); - if( psz_html ) - EnsureUTF8( psz_html ); /* Create the subpicture unit */ p_spu = decoder_NewSubpictureText( p_dec ); if( !p_spu ) { free( psz_subtitle ); - free( psz_html ); return NULL; } p_spu->i_start = i_pts; @@ -332,11 +328,12 @@ static subpicture_t *Subtitle( decoder_t *p_dec, char *psz_subtitle, char *psz_h /* The "leavetext" alignment is a special mode where the subpicture region itself gets aligned, but the text inside it does not */ p_spu_sys->align = SUBPICTURE_ALIGN_LEAVETEXT; - p_spu_sys->text = psz_subtitle; - p_spu_sys->html = psz_html; + p_spu_sys->p_segments = text_segment_New( psz_subtitle ); p_spu_sys->i_font_height_percent = 5; p_spu_sys->renderbg = true; + free( psz_subtitle ); + return p_spu; } @@ -362,9 +359,8 @@ static subpicture_t *Convert( decoder_t *p_dec, block_t *p_block ) if( b_changed ) { - char *psz_subtitle = Eia608Text( &p_sys->eia608, false ); char *psz_html = Eia608Text( &p_sys->eia608, true ); - return Subtitle( p_dec, psz_subtitle, psz_html, i_pts ); + return Subtitle( p_dec, psz_html, i_pts ); } return NULL; } diff --git a/modules/codec/kate.c b/modules/codec/kate.c index 8a9aad2ca5..73c5bce4a4 100644 --- a/modules/codec/kate.c +++ b/modules/codec/kate.c @@ -702,20 +702,13 @@ static void SetupText( decoder_t *p_dec, subpicture_t *p_spu, const kate_event * switch( ev->text_markup_type ) { case kate_markup_none: - p_spu->p_region->p_text = text_segment_New( ev->text ); /* no leak, this actually gets killed by the core */ - break; case kate_markup_simple: if( p_sys->b_formatted ) - { - /* the HTML renderer expects a top level text tag pair */ - char *buffer = NULL; - if( asprintf( &buffer, "%s", ev->text ) >= 0 ) - { - p_spu->p_region->psz_html = buffer; - } - break; - } - /* if not formatted, we fall through */ +// p_spu->p_region->p_text = ParseSubtitles(&p_spu->p_region->i_align, ev->text ); + ;//FIXME + else + p_spu->p_region->p_text = text_segment_New( ev->text ); /* no leak, this actually gets killed by the core */ + break; default: /* we don't know about this one, so remove markup and display as text */ { @@ -723,6 +716,7 @@ static void SetupText( decoder_t *p_dec, subpicture_t *p_spu, const kate_event * size_t len0 = strlen( copy ) + 1; kate_text_remove_markup( ev->text_encoding, copy, &len0 ); p_spu->p_region->p_text = text_segment_New( copy ); + free( copy ); } break; } diff --git a/modules/codec/subsdec.c b/modules/codec/subsdec.c index 1b4276e299..5eb7d01560 100644 --- a/modules/codec/subsdec.c +++ b/modules/codec/subsdec.c @@ -461,80 +461,15 @@ static subpicture_t *ParseText( decoder_t *p_dec, block_t *p_block ) subpicture_updater_sys_t *p_spu_sys = p_spu->updater.p_sys; p_spu_sys->align = SUBPICTURE_ALIGN_BOTTOM | p_sys->i_align; - p_spu_sys->text = StripTags( psz_subtitle ); - if( var_InheritBool( p_dec, "subsdec-formatted" ) ) - p_spu_sys->html = CreateHtmlSubtitle( &p_spu_sys->align, psz_subtitle ); + char* psz_sub = CreateHtmlSubtitle( &p_spu_sys->align, psz_subtitle ); + p_spu_sys->p_segments = text_segment_New( psz_sub ); - free( psz_subtitle ); + //FIXME: Remove the variable? + //if( var_InheritBool( p_dec, "subsdec-formatted" ) ) - return p_spu; -} - -/* Function now handles tags with attribute values, and tries - * to deal with &' commands too. It no longer modifies the string - * in place, so that the original text can be reused - */ -static char *StripTags( char *psz_subtitle ) -{ - char *psz_text_start; - char *psz_text; + free( psz_sub ); - psz_text = psz_text_start = malloc( strlen( psz_subtitle ) + 1 ); - if( !psz_text_start ) - return NULL; - - while( *psz_subtitle ) - { - if( *psz_subtitle == '<' ) - { - if( strncasecmp( psz_subtitle, "
", 5 ) == 0 ) - *psz_text++ = '\n'; - - psz_subtitle += strcspn( psz_subtitle, ">" ); - } - else if( *psz_subtitle == '&' ) - { - if( !strncasecmp( psz_subtitle, "<", 4 )) - { - *psz_text++ = '<'; - psz_subtitle += strcspn( psz_subtitle, ";" ); - } - else if( !strncasecmp( psz_subtitle, ">", 4 )) - { - *psz_text++ = '>'; - psz_subtitle += strcspn( psz_subtitle, ";" ); - } - else if( !strncasecmp( psz_subtitle, "&", 5 )) - { - *psz_text++ = '&'; - psz_subtitle += strcspn( psz_subtitle, ";" ); - } - else if( !strncasecmp( psz_subtitle, """, 6 )) - { - *psz_text++ = '\"'; - psz_subtitle += strcspn( psz_subtitle, ";" ); - } - else - { - /* Assume it is just a normal ampersand */ - *psz_text++ = '&'; - } - } - else - { - *psz_text++ = *psz_subtitle; - } - - /* Security fix: Account for the case where input ends early */ - if( *psz_subtitle == '\0' ) break; - - psz_subtitle++; - } - *psz_text = '\0'; - char *psz = realloc( psz_text_start, strlen( psz_text_start ) + 1 ); - if( psz ) psz_text_start = psz; - - return psz_text_start; + return p_spu; } /* Try to respect any style tags present in the subtitle string. The main diff --git a/modules/codec/substext.h b/modules/codec/substext.h index 9f5b35c5be..f7aeb2e083 100644 --- a/modules/codec/substext.h +++ b/modules/codec/substext.h @@ -8,9 +8,7 @@ typedef struct } subpicture_updater_sys_option_t; struct subpicture_updater_sys_t { - char *text; - char *html; - text_segment_t *p_htmlsegments; + text_segment_t *p_segments; int align; int x; @@ -32,116 +30,6 @@ struct subpicture_updater_sys_t { int16_t i_drop_shadow_alpha; }; -static void MakeHtmlNewLines( char **ppsz_src ) -{ - unsigned int i_nlcount = 0; - unsigned i_len = strlen( *ppsz_src ); - if ( i_len == 0 ) return; - for ( unsigned i=0; i" ); - ptr += 5; - } else { - *ptr++ = (*ppsz_src)[i]; - } - } - *ptr = 0; - free( *ppsz_src ); - *ppsz_src = psz_dst; -} - -static void HtmlAppend( char **ppsz_dst, const char *psz_src, - const text_style_t *p_styles, const float f_scale ) -{ - if ( !ppsz_dst ) return; - int i_return; - char *psz_subtext = NULL; - char *psz_text = NULL; - char *psz_fontsize = NULL; - char *psz_color = NULL; - char *psz_encoded = convert_xml_special_chars( psz_src ); - if ( !psz_encoded ) return; - - MakeHtmlNewLines( &psz_encoded ); - - if ( p_styles->i_font_alpha > 0 ) //ARGB - { - i_return = asprintf( &psz_color, " color=\"#%6x\"", - p_styles->i_font_color & 0x00FFFFFF ); - if ( i_return < 0 ) psz_color = NULL; - } - - if ( p_styles->i_font_size > 0 && f_scale > 0 ) - { - i_return = asprintf( &psz_fontsize, " size=\"%u\"", - (unsigned) (f_scale * p_styles->i_font_size) ); - if ( i_return < 0 ) psz_fontsize = NULL; - } - - i_return = asprintf( &psz_subtext, "%s%s%s%s%s%s%s", - ( p_styles->i_style_flags & STYLE_UNDERLINE ) ? "" : "", - ( p_styles->i_style_flags & STYLE_BOLD ) ? "" : "", - ( p_styles->i_style_flags & STYLE_ITALIC ) ? "" : "", - psz_encoded, - ( p_styles->i_style_flags & STYLE_ITALIC ) ? "" : "", - ( p_styles->i_style_flags & STYLE_BOLD ) ? "" : "", - ( p_styles->i_style_flags & STYLE_UNDERLINE ) ? "" : "" - ); - if ( i_return < 0 ) psz_subtext = NULL; - - if ( psz_color || psz_fontsize ) - { - i_return = asprintf( &psz_text, "%s", - psz_color ? psz_color : "", - psz_fontsize ? psz_fontsize : "", - psz_subtext ); - if ( i_return < 0 ) psz_text = NULL; - free( psz_subtext ); - } - else - { - psz_text = psz_subtext; - } - - free( psz_fontsize ); - free( psz_color ); - - if ( *ppsz_dst ) - { - char *psz_dst = *ppsz_dst; - i_return = asprintf( ppsz_dst, "%s%s", psz_dst, psz_text ); - if ( i_return < 0 ) ppsz_dst = NULL; - free( psz_dst ); - free( psz_text ); - } - else - *ppsz_dst = psz_text; -} - -static char *SegmentsToHtml( text_segment_t *p_head, const float f_scale ) -{ - char *psz_dst = NULL; - char *psz_ret = NULL; - while( p_head ) - { - HtmlAppend( &psz_dst, p_head->psz_text, p_head->style, f_scale ); - p_head = p_head->p_next; - } - int i_ret = asprintf( &psz_ret, "%s", psz_dst ); - if ( i_ret < 0 ) psz_ret = NULL; - free( psz_dst ); - return psz_ret; -} - static int SubpictureTextValidate(subpicture_t *subpic, bool has_src_changed, const video_format_t *fmt_src, bool has_dst_changed, const video_format_t *fmt_dst, @@ -164,6 +52,7 @@ static int SubpictureTextValidate(subpicture_t *subpic, } return VLC_EGENERIC; } + static void SubpictureTextUpdate(subpicture_t *subpic, const video_format_t *fmt_src, const video_format_t *fmt_dst, @@ -187,14 +76,7 @@ static void SubpictureTextUpdate(subpicture_t *subpic, if (!r) return; - r->p_text = sys->text ? text_segment_New( sys->text ): NULL; - if ( sys->p_htmlsegments ) - r->psz_html = SegmentsToHtml( sys->p_htmlsegments, - (float) fmt_dst->i_height / fmt_src->i_height ); - else if ( sys->html ) - r->psz_html = strdup(sys->html); - else - r->psz_html = NULL; + r->p_text = sys->p_segments; r->i_align = sys->align; r->b_renderbg = sys->renderbg; if (!sys->is_fixed) { @@ -224,47 +106,43 @@ static void SubpictureTextUpdate(subpicture_t *subpic, sys->font_color.b_set || sys->background_color.b_set ) { - r->p_style = text_style_New(); - if (!r->p_style) return; - - if (sys->i_font_height_abs_to_src) - sys->i_font_height_percent = sys->i_font_height_abs_to_src * 100 / - fmt_src->i_visible_height; - - if (sys->i_font_height_percent) + //FIXME: Is this used for something else than tx3g? + for ( text_segment_t* p_segment = sys->p_segments; p_segment; p_segment = p_segment->p_next ) { - r->p_style->i_font_size = sys->i_font_height_percent * - subpic->i_original_picture_height / 100; - r->p_style->i_font_color = 0xffffff; - r->p_style->i_font_alpha = 0xff; + text_style_t* p_style = p_segment->style; + + if (sys->i_font_height_abs_to_src) + sys->i_font_height_percent = sys->i_font_height_abs_to_src * 100 / + fmt_src->i_visible_height; + + if (sys->i_font_height_percent) + { + p_style->i_font_size = sys->i_font_height_percent * + subpic->i_original_picture_height / 100; + p_style->i_font_color = 0xffffff; + p_style->i_font_alpha = 0xff; + } + + if (sys->style_flags.b_set) + p_style->i_style_flags = sys->style_flags.i_value; + if (sys->font_color.b_set) + p_style->i_font_color = sys->font_color.i_value; + if (sys->background_color.b_set) + p_style->i_background_color = sys->background_color.i_value; + if (sys->i_alpha) + p_style->i_font_alpha = sys->i_alpha; + if (sys->i_drop_shadow) + p_style->i_shadow_width = sys->i_drop_shadow; + if (sys->i_drop_shadow_alpha) + p_style->i_shadow_alpha = sys->i_drop_shadow_alpha; } - - if (sys->style_flags.b_set) - r->p_style->i_style_flags = sys->style_flags.i_value; - if (sys->font_color.b_set) - r->p_style->i_font_color = sys->font_color.i_value; - if (sys->background_color.b_set) - r->p_style->i_background_color = sys->background_color.i_value; - if (sys->i_alpha) - r->p_style->i_font_alpha = sys->i_alpha; - if (sys->i_drop_shadow) - r->p_style->i_shadow_width = sys->i_drop_shadow; - if (sys->i_drop_shadow_alpha) - r->p_style->i_shadow_alpha = sys->i_drop_shadow_alpha; } } static void SubpictureTextDestroy(subpicture_t *subpic) { subpicture_updater_sys_t *sys = subpic->updater.p_sys; - free(sys->text); - free(sys->html); - while( sys->p_htmlsegments ) - { - text_segment_t *p_segment = sys->p_htmlsegments; - sys->p_htmlsegments = p_segment->p_next; - text_segment_Delete( p_segment ); - } + text_segment_ChainDelete( sys->p_segments ); free(sys); } diff --git a/modules/codec/substtml.c b/modules/codec/substtml.c index e4c80a6614..4515353d7a 100644 --- a/modules/codec/substtml.c +++ b/modules/codec/substtml.c @@ -102,7 +102,8 @@ static subpicture_t *ParseText( decoder_t *p_dec, block_t *p_block ) subpicture_updater_sys_t *p_spu_sys = p_spu->updater.p_sys; p_spu_sys->align = SUBPICTURE_ALIGN_BOTTOM | p_sys->i_align; - p_spu_sys->text = psz_subtitle; + p_spu_sys->p_segments = text_segment_New( psz_subtitle ); + free( psz_subtitle ); return p_spu; } diff --git a/modules/codec/substx3g.c b/modules/codec/substx3g.c index c33be0b642..bba46ca828 100644 --- a/modules/codec/substx3g.c +++ b/modules/codec/substx3g.c @@ -379,8 +379,7 @@ static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block ) p_spu->b_absolute = false; p_spu_sys->align = SUBPICTURE_ALIGN_BOTTOM; - p_spu_sys->text = psz_subtitle; - p_spu_sys->p_htmlsegments = p_segment; + p_spu_sys->p_segments = p_segment; block_Release( p_block ); diff --git a/modules/codec/subsusf.c b/modules/codec/subsusf.c index 113b2d9cb7..be9f2beb2a 100644 --- a/modules/codec/subsusf.c +++ b/modules/codec/subsusf.c @@ -429,14 +429,7 @@ static subpicture_region_t *CreateTextRegion( decoder_t *p_dec, { ssa_style_t *p_ssa_style = NULL; - p_text_region->psz_html = strndup( psz_subtitle, i_len ); - if( ! p_text_region->psz_html ) - { - subpicture_region_Delete( p_text_region ); - return NULL; - } - - p_ssa_style = ParseStyle( p_sys, p_text_region->psz_html ); + p_ssa_style = ParseStyle( p_sys, psz_subtitle ); if( !p_ssa_style ) { int i; @@ -452,7 +445,6 @@ static subpicture_region_t *CreateTextRegion( decoder_t *p_dec, { msg_Dbg( p_dec, "style is: %s", p_ssa_style->psz_stylename ); - p_text_region->p_style = text_style_Duplicate( &p_ssa_style->font_style ); p_text_region->i_align = p_ssa_style->i_align; /* TODO: Setup % based offsets properly, without adversely affecting @@ -464,13 +456,14 @@ static subpicture_region_t *CreateTextRegion( decoder_t *p_dec, */ p_text_region->i_x = p_ssa_style->i_margin_h; p_text_region->i_y = p_ssa_style->i_margin_v; - + p_text_region->p_text = text_segment_NewInheritStyle( &p_ssa_style->font_style ); } else { p_text_region->i_align = SUBPICTURE_ALIGN_BOTTOM | i_sys_align; p_text_region->i_x = i_sys_align ? 20 : 0; p_text_region->i_y = 10; + p_text_region->p_text = text_segment_New( NULL ); } /* Look for position arguments which may override the style-based * defaults. @@ -825,45 +818,8 @@ static subpicture_region_t *ParseUSFString( decoder_t *p_dec, { char *psz_end = NULL; - if(( !strncasecmp( psz_subtitle, "", 6 ))) - { - psz_end = strcasestr( psz_subtitle, "" ); - - if( psz_end ) - { - subpicture_region_t *p_text_region; - - psz_end += strcspn( psz_end, ">" ) + 1; - p_text_region = CreateTextRegion( p_dec, - psz_subtitle, - psz_end - psz_subtitle, - p_sys->i_align ); - - if( p_text_region ) - { - p_text_region->p_text = text_segment_New( CreatePlainText( p_text_region->psz_html ) ); - - if( ! var_CreateGetBool( p_dec, "subsdec-formatted" ) ) - { - free( p_text_region->psz_html ); - p_text_region->psz_html = NULL; - } - } - - if( !p_region_first ) - { - p_region_first = p_region_upto = p_text_region; - } - else if( p_text_region ) - { - p_region_upto->p_next = p_text_region; - p_region_upto = p_region_upto->p_next; - } - } - } - else if(( !strncasecmp( psz_subtitle, "", 9 ))) { psz_end = strcasestr( psz_subtitle, "" ); @@ -879,14 +835,6 @@ static subpicture_region_t *ParseUSFString( decoder_t *p_dec, psz_end - psz_subtitle, p_sys->i_align ); - if( p_text_region ) - { - if( ! var_CreateGetBool( p_dec, "subsdec-formatted" ) ) - { - free( p_text_region->psz_html ); - p_text_region->psz_html = NULL; - } - } if( !p_region_first ) { p_region_first = p_region_upto = p_text_region; @@ -941,9 +889,6 @@ static subpicture_region_t *ParseUSFString( decoder_t *p_dec, SetupPositions( p_image_region, psz_subtitle ); p_image_region->p_next = NULL; - p_image_region->p_text = NULL; - p_image_region->psz_html = NULL; - } if( !p_region_first ) { @@ -955,6 +900,33 @@ static subpicture_region_t *ParseUSFString( decoder_t *p_dec, p_region_upto = p_region_upto->p_next; } } + else + { + subpicture_region_t *p_text_region; + + psz_end += strcspn( psz_end, ">" ) + 1; + + p_text_region = CreateTextRegion( p_dec, + psz_subtitle, + psz_end - psz_subtitle, + p_sys->i_align ); + + if( p_text_region ) + { + free( p_text_region->p_text->psz_text ); + p_text_region->p_text->psz_text = CreatePlainText( psz_subtitle ); + } + + if( !p_region_first ) + { + p_region_first = p_region_upto = p_text_region; + } + else if( p_text_region ) + { + p_region_upto->p_next = p_text_region; + p_region_upto = p_region_upto->p_next; + } + } if( psz_end ) psz_subtitle = psz_end - 1; diff --git a/modules/codec/zvbi.c b/modules/codec/zvbi.c index 59152e9c75..c87a7cf3d4 100644 --- a/modules/codec/zvbi.c +++ b/modules/codec/zvbi.c @@ -384,7 +384,7 @@ static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block ) if( !p_spu ) goto error; subpicture_updater_sys_t *p_spu_sys = p_spu->updater.p_sys; - p_spu_sys->text = strdup(""); + p_spu_sys->p_segments = text_segment_New(""); p_sys->b_update = true; p_sys->i_last_page = i_wanted_page; @@ -441,7 +441,7 @@ static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block ) offset++; subpicture_updater_sys_t *p_spu_sys = p_spu->updater.p_sys; - p_spu_sys->text = strdup( &p_text[offset] ); + p_spu_sys->p_segments = text_segment_New( &p_text[offset] ); p_spu_sys->align = i_align; p_spu_sys->i_font_height_percent = 5; diff --git a/modules/text_renderer/freetype.c b/modules/text_renderer/freetype.c index 0c97b237ea..bc975af4b6 100644 --- a/modules/text_renderer/freetype.c +++ b/modules/text_renderer/freetype.c @@ -913,28 +913,22 @@ static xml_reader_t *GetXMLReader( filter_t *p_filter, stream_t *p_sub ) * needed glyphs into memory. It is used as pf_add_string callback in * the vout method by this module */ -static int RenderCommon( filter_t *p_filter, subpicture_region_t *p_region_out, - subpicture_region_t *p_region_in, bool b_html, +static int Render( filter_t *p_filter, subpicture_region_t *p_region_out, + subpicture_region_t *p_region_in, const vlc_fourcc_t *p_chroma_list ) { filter_sys_t *p_sys = p_filter->p_sys; if( !p_region_in ) return VLC_EGENERIC; - if( b_html && !p_region_in->psz_html ) - return VLC_EGENERIC; - if( !b_html && !p_region_in->p_text && !p_region_in->p_text->psz_text ) - return VLC_EGENERIC; - const size_t i_text_max = strlen( b_html ? p_region_in->psz_html - : p_region_in->p_text->psz_text ); + text_style_t **pp_styles = NULL; + size_t i_text_length = 0; + + uni_char_t *psz_text = SegmentsToTextAndStyles( p_region_in->p_text, &i_text_length, &pp_styles ); - uni_char_t *psz_text = calloc( i_text_max, sizeof( *psz_text ) ); - text_style_t **pp_styles = calloc( i_text_max, sizeof( *pp_styles ) ); if( !psz_text || !pp_styles ) { - free( psz_text ); - free( pp_styles ); return VLC_EGENERIC; } @@ -943,113 +937,15 @@ static int RenderCommon( filter_t *p_filter, subpicture_region_t *p_region_out, /* */ int rv = VLC_SUCCESS; - int i_text_length = 0; FT_BBox bbox; int i_max_face_height; line_desc_t *p_lines = NULL; uint32_t *pi_k_durations = NULL; - if( b_html ) - { - stream_t *p_sub = stream_MemoryNew( VLC_OBJECT(p_filter), - (uint8_t *) p_region_in->psz_html, - strlen( p_region_in->psz_html ), - true ); - if( unlikely(p_sub == NULL) ) - { - free( psz_text ); - free( pp_styles ); - return VLC_SUCCESS; - } - - xml_reader_t *p_xml_reader = GetXMLReader( p_filter, p_sub ); - - if( !p_xml_reader ) - rv = VLC_EGENERIC; - - if( !rv ) - { - /* Look for Root Node */ - const char *node; - - if( xml_ReaderNextNode( p_xml_reader, &node ) == XML_READER_STARTELEM ) - { - if( strcasecmp( "karaoke", node ) == 0 ) - { - pi_k_durations = calloc( i_text_max, sizeof( *pi_k_durations ) ); - } - else if( strcasecmp( "text", node ) != 0 ) - { - /* Only text and karaoke tags are supported */ - msg_Dbg( p_filter, "Unsupported top-level tag <%s> ignored.", - node ); - rv = VLC_EGENERIC; - } - } - else - { - msg_Err( p_filter, "Malformed HTML subtitle" ); - rv = VLC_EGENERIC; - } - } - if( !rv ) - { - rv = ProcessNodes( p_filter, - psz_text, pp_styles, pi_k_durations, &i_text_length, - p_xml_reader, p_region_in->p_style, &p_filter->p_sys->style ); - } - - if( p_xml_reader ) - p_filter->p_sys->p_xml = xml_ReaderReset( p_xml_reader, NULL ); - - stream_Delete( p_sub ); - } - else - { - text_style_t *p_style; - if( p_region_in->p_style ) - { - p_style = CreateStyle( p_region_in->p_style->psz_fontname ? p_region_in->p_style->psz_fontname - : p_sys->style.psz_fontname, - p_region_in->p_style->i_font_size > 0 ? p_region_in->p_style->i_font_size - : p_sys->style.i_font_size, - (p_region_in->p_style->i_font_color & 0xffffff) | - ((p_region_in->p_style->i_font_alpha & 0xff) << 24), - 0x00ffffff, - p_region_in->p_style->i_style_flags & (STYLE_BOLD | - STYLE_ITALIC | - STYLE_UNDERLINE | - STYLE_STRIKEOUT | - STYLE_HALFWIDTH) ); - p_style->i_spacing = p_region_in->p_style->i_spacing; - } - else - { - uint32_t i_font_color = var_InheritInteger( p_filter, "freetype-color" ); - i_font_color = VLC_CLIP( i_font_color, 0, 0xFFFFFF ); - p_style = CreateStyle( p_sys->style.psz_fontname, - p_sys->style.i_font_size, - (i_font_color & 0xffffff) | - ((p_sys->style.i_font_alpha & 0xff) << 24), - 0x00ffffff, 0); - } - if( p_sys->style.i_style_flags & STYLE_BOLD ) - p_style->i_style_flags |= STYLE_BOLD; - - i_text_length = SetupText( p_filter, - psz_text, - pp_styles, - NULL, - p_region_in->p_text->psz_text, p_style, 0 ); - } - - if( !rv && i_text_length > 0 ) - { - rv = LayoutText( p_filter, - &p_lines, &bbox, &i_max_face_height, - psz_text, pp_styles, pi_k_durations, i_text_length ); - } + rv = LayoutText( p_filter, + &p_lines, &bbox, &i_max_face_height, + psz_text, pp_styles, pi_k_durations, i_text_length ); p_region_out->i_x = p_region_in->i_x; p_region_out->i_y = p_region_in->i_y; @@ -1107,7 +1003,7 @@ static int RenderCommon( filter_t *p_filter, subpicture_region_t *p_region_out, FreeLines( p_lines ); free( psz_text ); - for( int i = 0; i < i_text_length; i++ ) + for( size_t i = 0; i < i_text_length; i++ ) { if( pp_styles[i] && ( i + 1 == i_text_length || pp_styles[i] != pp_styles[i + 1] ) ) text_style_Delete( pp_styles[i] ); @@ -1118,20 +1014,6 @@ static int RenderCommon( filter_t *p_filter, subpicture_region_t *p_region_out, return rv; } -static int RenderText( filter_t *p_filter, subpicture_region_t *p_region_out, - subpicture_region_t *p_region_in, - const vlc_fourcc_t *p_chroma_list ) -{ - return RenderCommon( p_filter, p_region_out, p_region_in, false, p_chroma_list ); -} - -static int RenderHtml( filter_t *p_filter, subpicture_region_t *p_region_out, - subpicture_region_t *p_region_in, - const vlc_fourcc_t *p_chroma_list ) -{ - return RenderCommon( p_filter, p_region_out, p_region_in, true, p_chroma_list ); -} - /***************************************************************************** * Create: allocates osd-text video thread output method ***************************************************************************** @@ -1316,8 +1198,7 @@ static int Create( vlc_object_t *p_this ) p_sys->pp_font_attachments = NULL; p_sys->i_font_attachments = 0; - p_filter->pf_render_text = RenderText; - p_filter->pf_render_html = RenderHtml; + p_filter->pf_render = Render; LoadFontsFromAttachments( p_filter ); diff --git a/modules/text_renderer/svg.c b/modules/text_renderer/svg.c index 00580db83f..15717d4194 100644 --- a/modules/text_renderer/svg.c +++ b/modules/text_renderer/svg.c @@ -134,8 +134,7 @@ static int Create( vlc_object_t *p_this ) p_sys->i_width = p_filter->fmt_out.video.i_width; p_sys->i_height = p_filter->fmt_out.video.i_height; - p_filter->pf_render_text = RenderText; - p_filter->pf_render_html = NULL; + p_filter->pf_render = RenderText; p_filter->p_sys = p_sys; /* MUST call this before any RSVG funcs */ @@ -436,6 +435,8 @@ static int RenderText( filter_t *p_filter, subpicture_region_t *p_region_out, /* Sanity check */ if( !p_region_in || !p_region_out ) return VLC_EGENERIC; if( !p_region_in->p_text ) return VLC_EGENERIC; + //FIXME: What should we do when there's more than a single segment? + //Is this refused at codec level? psz_string = p_region_in->p_text->psz_text; if( !psz_string || !*psz_string ) return VLC_EGENERIC; diff --git a/modules/text_renderer/tdummy.c b/modules/text_renderer/tdummy.c index 80b7f5da34..38c1b80758 100644 --- a/modules/text_renderer/tdummy.c +++ b/modules/text_renderer/tdummy.c @@ -51,7 +51,6 @@ static int RenderText( filter_t *p_filter, subpicture_region_t *p_region_out, static int OpenRenderer( vlc_object_t *p_this ) { filter_t *p_filter = (filter_t *)p_this; - p_filter->pf_render_text = RenderText; - p_filter->pf_render_html = NULL; + p_filter->pf_render = RenderText; return VLC_SUCCESS; } diff --git a/modules/text_renderer/text_layout.c b/modules/text_renderer/text_layout.c index bb6019ba2e..1156184dae 100644 --- a/modules/text_renderer/text_layout.c +++ b/modules/text_renderer/text_layout.c @@ -34,6 +34,7 @@ #endif #include +#include #include #include @@ -207,7 +208,7 @@ static void BBoxEnlarge( FT_BBox *p_max, const FT_BBox *p ) static paragraph_t *NewParagraph( filter_t *p_filter, int i_size, - uni_char_t *p_code_points, + const uni_char_t *p_code_points, text_style_t **pp_styles, uint32_t *pi_k_dates, int i_runs_size ) @@ -458,11 +459,14 @@ static int ItemizeParagraph( filter_t *p_filter, paragraph_t *p_paragraph ) || last_script != p_paragraph->p_scripts[ i ] || last_level != p_paragraph->p_levels[ i ] #endif - || p_last_style->i_font_size != p_paragraph->pp_styles[ i ]->i_font_size - || ( ( p_last_style->i_style_flags - ^ p_paragraph->pp_styles[ i ]->i_style_flags ) - & STYLE_HALFWIDTH ) - ||!FaceStyleEquals( p_last_style, p_paragraph->pp_styles[ i ] ) ) + || ( p_paragraph->pp_styles[ i ] != NULL && ( + p_last_style->i_font_size != p_paragraph->pp_styles[ i ]->i_font_size + || ( ( p_last_style->i_style_flags + ^ p_paragraph->pp_styles[ i ]->i_style_flags ) + & STYLE_HALFWIDTH ) + ||!FaceStyleEquals( p_last_style, p_paragraph->pp_styles[ i ] ) ) + ) + ) { int i_ret = AddRun( p_filter, p_paragraph, i_last_run_start, i, 0 ); if( i_ret ) @@ -1203,7 +1207,7 @@ error: int LayoutText( filter_t *p_filter, line_desc_t **pp_lines, FT_BBox *p_bbox, int *pi_max_face_height, - uni_char_t *psz_text, text_style_t **pp_styles, + const uni_char_t *psz_text, text_style_t **pp_styles, uint32_t *pi_k_dates, int i_len ) { line_desc_t *p_first_line = 0; @@ -1311,3 +1315,49 @@ error: if( p_paragraph ) FreeParagraph( p_paragraph ); return VLC_EGENERIC; } + +uni_char_t* SegmentsToTextAndStyles(const text_segment_t *p_segment, size_t *pi_string_length, text_style_t ***ppp_styles) +{ + text_style_t **pp_styles = NULL; + uni_char_t *psz_uni = NULL; + size_t i_size = 0; + for ( const text_segment_t *s = p_segment; s != NULL; s = s->p_next ) + { + //FIXME: This is missing a space in between segments. + if ( !s->psz_text ) + continue; + size_t i_string_bytes = 0; + uni_char_t *psz_tmp = ToCharset( FREETYPE_TO_UCS, s->psz_text, &i_string_bytes ); + if ( !psz_tmp ) + { + free( psz_uni ); + free( pp_styles ); + return NULL; + } + uni_char_t *psz_realloc = realloc(psz_uni, i_size + i_string_bytes); + if ( unlikely( !psz_realloc ) ) + { + free( pp_styles ); + free( psz_uni ); + free( psz_tmp ); + return NULL; + } + psz_uni = psz_realloc; + memcpy( psz_uni + i_size, psz_tmp, i_string_bytes ); + free( psz_tmp ); + text_style_t **pp_styles_realloc = realloc( pp_styles, i_size + i_string_bytes); + if ( unlikely( !pp_styles_realloc ) ) + { + free( pp_styles ); + free( psz_uni ); + return NULL; + } + pp_styles = pp_styles_realloc; + for ( size_t i = i_size; i < (i_size + i_string_bytes) / sizeof(*psz_uni); i++ ) + pp_styles[i] = s->style; + i_size += i_string_bytes; + } + *pi_string_length = i_size / sizeof( *psz_uni ); + *ppp_styles = pp_styles; + return psz_uni; +} diff --git a/modules/text_renderer/text_layout.h b/modules/text_renderer/text_layout.h index e5b60b973c..d9a159e07c 100644 --- a/modules/text_renderer/text_layout.h +++ b/modules/text_renderer/text_layout.h @@ -51,7 +51,9 @@ struct line_desc_t void FreeLines( line_desc_t *p_lines ); line_desc_t *NewLine( int i_count ); -int LayoutText( filter_t *p_filter, line_desc_t **pp_lines, +int LayoutText(filter_t *p_filter, line_desc_t **pp_lines, FT_BBox *p_bbox, int *pi_max_face_height, - uni_char_t *psz_text, text_style_t **pp_styles, + const uni_char_t *psz_text, text_style_t **pp_styles, uint32_t *pi_k_dates, int i_len ); + +uni_char_t *SegmentsToTextAndStyles(const text_segment_t *p_segment, size_t *pi_string_length, text_style_t ***ppp_styles ); diff --git a/modules/text_renderer/win32text.c b/modules/text_renderer/win32text.c index 3b044279bf..7e28cfe1df 100644 --- a/modules/text_renderer/win32text.c +++ b/modules/text_renderer/win32text.c @@ -184,8 +184,7 @@ static int Create( vlc_object_t *p_this ) if( SetFont( p_filter, 0 ) != VLC_SUCCESS ) goto error; free( psz_fontfile ); - p_filter->pf_render_text = RenderText; - p_filter->pf_render_html = NULL; + p_filter->pf_render = RenderText; return VLC_SUCCESS; error: @@ -324,11 +323,11 @@ static int RenderText( filter_t *p_filter, subpicture_region_t *p_region_out, return VLC_EGENERIC; } - if( p_region_in->p_style ) + if( p_region_in->p_text->style ) { - i_font_color = VLC_CLIP( p_region_in->p_style->i_font_color, 0, 0xFFFFFF ); - i_font_alpha = VLC_CLIP( p_region_in->p_style->i_font_alpha, 0, 255 ); - i_font_size = VLC_CLIP( p_region_in->p_style->i_font_size, 0, 255 ); + i_font_color = VLC_CLIP( p_region_in->p_text->style->i_font_color, 0, 0xFFFFFF ); + i_font_alpha = VLC_CLIP( p_region_in->p_text->style->i_font_alpha, 0, 255 ); + i_font_size = VLC_CLIP( p_region_in->p_text->style->i_font_size, 0, 255 ); } else { diff --git a/modules/video_filter/dynamicoverlay/dynamicoverlay.c b/modules/video_filter/dynamicoverlay/dynamicoverlay.c index 2dd34b8e1d..56e80c4617 100644 --- a/modules/video_filter/dynamicoverlay/dynamicoverlay.c +++ b/modules/video_filter/dynamicoverlay/dynamicoverlay.c @@ -365,7 +365,7 @@ static subpicture_t *Filter( filter_t *p_filter, mtime_t date ) if( p_overlay->format.i_chroma == VLC_CODEC_TEXT ) { p_region->p_text = text_segment_New( p_overlay->data.p_text ); - p_region->p_style = text_style_Duplicate( p_overlay->p_fontstyle ); + p_region->p_text->style = text_style_Duplicate( p_overlay->p_fontstyle ); } else { diff --git a/modules/video_filter/marq.c b/modules/video_filter/marq.c index d35234bfa8..e69cd96ee3 100644 --- a/modules/video_filter/marq.c +++ b/modules/video_filter/marq.c @@ -330,7 +330,9 @@ static subpicture_t *Filter( filter_t *p_filter, mtime_t date ) p_spu->p_region->i_x = p_sys->i_xoff; p_spu->p_region->i_y = p_sys->i_yoff; - p_spu->p_region->p_style = text_style_Duplicate( p_sys->p_style ); + //FIXME: Provide a way to force a default style to a list of segments +#warning Missing style + //p_spu->p_region->p_style = text_style_Duplicate( p_sys->p_style ); out: vlc_mutex_unlock( &p_sys->lock ); diff --git a/modules/video_filter/rss.c b/modules/video_filter/rss.c index d7d85128ce..865ab55c96 100644 --- a/modules/video_filter/rss.c +++ b/modules/video_filter/rss.c @@ -500,7 +500,9 @@ static subpicture_t *Filter( filter_t *p_filter, mtime_t date ) p_spu->p_region->i_x = p_sys->i_xoff; p_spu->p_region->i_y = p_sys->i_yoff; - p_spu->p_region->p_style = text_style_Duplicate( p_sys->p_style ); + //FIXME: Provide a way to force a default style to a list of segments +#warning Missing style +// p_spu->p_region->p_style = text_style_Duplicate( p_sys->p_style ); if( p_feed->p_pic ) { diff --git a/modules/video_filter/subsdelay.c b/modules/video_filter/subsdelay.c index 808df39fda..8d3299abec 100644 --- a/modules/video_filter/subsdelay.c +++ b/modules/video_filter/subsdelay.c @@ -216,7 +216,7 @@ static int SubsdelayCalculateAlpha( filter_t *p_filter, int i_overlapping, int i static int SubsdelayGetTextRank( char *psz_text ); -static bool SubsdelayIsTextEmpty( char *psz_text ); +static bool SubsdelayIsTextEmpty( const text_segment_t* p_segment ); /***************************************************************************** * Subpicture functions @@ -1052,8 +1052,8 @@ static void SubpicLocalUpdate( subpicture_t* p_subpic, mtime_t i_ts ) if( p_entry->b_check_empty && p_subpic->p_region ) { - if( SubsdelayIsTextEmpty( p_subpic->p_region->psz_html ) || - SubsdelayIsTextEmpty( p_subpic->p_region->p_text->psz_text ) ) + //FIXME: What if there is more than one segment? + if( SubsdelayIsTextEmpty( p_subpic->p_region->p_text ) ) { /* remove empty subtitle */ @@ -1116,8 +1116,7 @@ static void SubpicLocalUpdate( subpicture_t* p_subpic, mtime_t i_ts ) *****************************************************************************/ static bool SubpicIsEmpty( subpicture_t* p_subpic ) { - return ( p_subpic->p_region && ( SubsdelayIsTextEmpty( p_subpic->p_region->psz_html ) || - SubsdelayIsTextEmpty( p_subpic->p_region->p_text->psz_text ) ) ); + return ( p_subpic->p_region && ( SubsdelayIsTextEmpty( p_subpic->p_region->p_text ) ) ); } /***************************************************************************** @@ -1180,17 +1179,10 @@ static int64_t SubsdelayEstimateDelay( filter_t *p_filter, subsdelay_heap_entry_ if( i_mode == SUBSDELAY_MODE_RELATIVE_SOURCE_CONTENT ) { - if( p_entry->p_subpic && p_entry->p_subpic->p_region && ( p_entry->p_subpic->p_region->p_text->psz_text - || p_entry->p_subpic->p_region->psz_html ) ) + if( p_entry->p_subpic && p_entry->p_subpic->p_region && ( p_entry->p_subpic->p_region->p_text ) ) { - if( p_entry->p_subpic->p_region->p_text->psz_text ) - { - i_rank = SubsdelayGetTextRank( p_entry->p_subpic->p_region->p_text->psz_text ); - } - else - { - i_rank = SubsdelayGetTextRank( p_entry->p_subpic->p_region->psz_html ); - } + //FIXME: We only use a single segment here + i_rank = SubsdelayGetTextRank( p_entry->p_subpic->p_region->p_text->psz_text ); return ( i_rank * INT_FACTOR_TO_RANK_FACTOR( i_factor ) ); } @@ -1341,13 +1333,18 @@ static int SubsdelayGetTextRank( char *psz_text ) /***************************************************************************** * SubsdelayIsTextEmpty: Check if the text contains spaces only *****************************************************************************/ -static bool SubsdelayIsTextEmpty( char *psz_text ) +static bool SubsdelayIsTextEmpty( const text_segment_t *p_segment ) { - if( !psz_text ) + while ( p_segment ) { - return false; + if ( strlen( p_segment->psz_text ) > 0 ) + { + size_t offset = strspn( p_segment->psz_text, " " ); + if ( p_segment->psz_text[offset] ) + return false; + } + p_segment = p_segment->p_next; } - psz_text += strspn( psz_text, " " ); - return !( *psz_text ); + return true; } diff --git a/src/misc/subpicture.c b/src/misc/subpicture.c index 6e74b0d9b0..19db482c09 100644 --- a/src/misc/subpicture.c +++ b/src/misc/subpicture.c @@ -249,9 +249,6 @@ void subpicture_region_Delete( subpicture_region_t *p_region ) free( p_region->fmt.p_palette ); text_segment_ChainDelete( p_region->p_text ); - free( p_region->psz_html ); - if( p_region->p_style ) - text_style_Delete( p_region->p_style ); free( p_region ); } @@ -305,12 +302,6 @@ subpicture_region_t* subpicture_region_Copy( subpicture_region_t *p_region_src ) p_region_dst->i_alpha = p_region_src->i_alpha; p_region_dst->p_text = text_segment_Copy( p_region_src->p_text ); - p_region_dst->psz_html = p_region_src->psz_html ? strdup(p_region_src->psz_html) : NULL; - if (p_region_src->p_style != NULL) { - p_region_dst->p_style = text_style_New(); - p_region_dst->p_style = text_style_Copy(p_region_dst->p_style, - p_region_src->p_style); - } //Palette is already copied by subpicture_region_New, we just have to duplicate p_pixels for (int i = 0; i < p_region_src->p_picture->i_planes; i++) diff --git a/src/video_output/video_epg.c b/src/video_output/video_epg.c index d580d5d7ae..6cb8bf8f7e 100644 --- a/src/video_output/video_epg.c +++ b/src/video_output/video_epg.c @@ -114,16 +114,28 @@ static subpicture_region_t * vout_OSDEpgText(const char *text, /* Set subpicture parameters */ region->p_text = text_segment_New(text); + if ( unlikely( !region->p_text ) ) + { + subpicture_region_Delete( region ); + return NULL; + } region->i_align = 0; region->i_x = x; region->i_y = y; /* Set text style */ - region->p_style = text_style_New(); - if (region->p_style) { - region->p_style->i_font_size = size; - region->p_style->i_font_color = color; - region->p_style->i_font_alpha = 0; + text_style_t *p_style = text_style_New(); + if ( unlikely( !p_style ) ) + { + text_segment_Delete( region->p_text ); + subpicture_region_Delete( region ); + return NULL; + } + region->p_text->style = p_style; + if (p_style) { + p_style->i_font_size = size; + p_style->i_font_color = color; + p_style->i_font_alpha = 0; } return region; diff --git a/src/video_output/vout_subpictures.c b/src/video_output/vout_subpictures.c index 44303a127d..196038a617 100644 --- a/src/video_output/vout_subpictures.c +++ b/src/video_output/vout_subpictures.c @@ -275,10 +275,8 @@ static void SpuRenderText(spu_t *spu, bool *rerender_text, var_SetInteger(text, "spu-elapsed", elapsed_time); var_SetBool(text, "text-rerender", false); - if (text->pf_render_html && region->psz_html) - text->pf_render_html(text, region, region, chroma_list); - else if (text->pf_render_text) - text->pf_render_text(text, region, region, chroma_list); + if ( region->p_text ) + text->pf_render(text, region, region, chroma_list); *rerender_text = var_GetBool(text, "text-rerender"); }