Commit f2e43bd7 authored by Hugo Beauzée-Luyssen's avatar Hugo Beauzée-Luyssen Committed by Jean-Baptiste Kempf

Subtitle renderers: Merge RenderText & RenderHTML

The current workflow is often parsing a subtitle format, then convert it
in a common HTML and then push it to the renderer as HTML. The renderer
will reparse the HTML and try to render it. Of course, that means that
only one renderer can do that correctly, and so we bloat the freetype
renderer as much as we can.
It also means that we have 2 render callbacks for subtitles, one for
normal text and one for styled text, and we sometimes reparse the HTML
to remove the tags, for the first.

We now only use a text_segment, with new segments at every style change;
an unique render function and the renderer can decide to honor or not
the style.

It's a big commit, so regressions can arise, but it was tested for most
common cases.
parent b8ce6743
......@@ -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;
......
......@@ -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 */
......
......@@ -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;
......
......@@ -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 );
......
......@@ -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;
}
......
......@@ -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, "<text>%s</text>", 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;
}
......
......@@ -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, "<br/>", 5 ) == 0 )
*psz_text++ = '\n';
psz_subtitle += strcspn( psz_subtitle, ">" );
}
else if( *psz_subtitle == '&' )
{
if( !strncasecmp( psz_subtitle, "&lt;", 4 ))
{
*psz_text++ = '<';
psz_subtitle += strcspn( psz_subtitle, ";" );
}
else if( !strncasecmp( psz_subtitle, "&gt;", 4 ))
{
*psz_text++ = '>';
psz_subtitle += strcspn( psz_subtitle, ";" );
}
else if( !strncasecmp( psz_subtitle, "&amp;", 5 ))
{
*psz_text++ = '&';
psz_subtitle += strcspn( psz_subtitle, ";" );
}
else if( !strncasecmp( psz_subtitle, "&quot;", 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
......
......@@ -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<i_len; i++ )
if ( (*ppsz_src)[i] == '\n' )
i_nlcount++;
if ( !i_nlcount ) return;
char *psz_dst = malloc( i_len + 1 + (i_nlcount * 4) );
char *ptr = psz_dst;
for ( unsigned i=0; i<i_len; i++ )
{
if ( (*ppsz_src)[i] == '\n' )
{
strcpy( ptr, "<br/>" );
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 ) ? "<u>" : "",
( p_styles->i_style_flags & STYLE_BOLD ) ? "<b>" : "",
( p_styles->i_style_flags & STYLE_ITALIC ) ? "<i>" : "",
psz_encoded,
( p_styles->i_style_flags & STYLE_ITALIC ) ? "</i>" : "",
( p_styles->i_style_flags & STYLE_BOLD ) ? "</b>" : "",
( p_styles->i_style_flags & STYLE_UNDERLINE ) ? "</u>" : ""
);
if ( i_return < 0 ) psz_subtext = NULL;
if ( psz_color || psz_fontsize )
{
i_return = asprintf( &psz_text, "<font%s%s>%s</font>",
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, "<text>%s</text>", 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);
}
......
......@@ -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;
}
......
......@@ -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 );
......
......@@ -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, "<text ", 6 )) ||
( !strncasecmp( psz_subtitle, "<text>", 6 )))
{
psz_end = strcasestr( psz_subtitle, "</text>" );
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, "<karaoke ", 9 )) ||
if(( !strncasecmp( psz_subtitle, "<karaoke ", 9 )) ||
( !strncasecmp( psz_subtitle, "<karaoke>", 9 )))
{
psz_end = strcasestr( psz_subtitle, "</karaoke>" );
......@@ -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;
......
......@@ -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;
......
......@@ -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 )
{