Commit 1fb3dfd8 authored by François Cartegnie's avatar François Cartegnie 🤞
Browse files

vlc_text_style: wrap tx3g specifics in decoder

parent 858e2e65
......@@ -108,8 +108,6 @@ struct text_segment_t {
char *psz_text; /**< text string of the segment */
text_style_t *style; /**< style applied to this segment */
text_segment_t *p_next; /**< next segment */
size_t i_size; //FIXME: substx3g specific
};
/**
......
......@@ -117,14 +117,40 @@ static char * str8indup( const char *psz_string, size_t i_skip, size_t n )
return strndup( psz_string, psz_tmp - psz_string );
}
static void SegmentDoSplit( text_segment_t *p_segment, uint16_t i_start, uint16_t i_end,
text_segment_t **pp_segment_left,
text_segment_t **pp_segment_middle,
text_segment_t **pp_segment_right )
typedef struct tx3g_segment_t tx3g_segment_t;
struct tx3g_segment_t
{
text_segment_t *s;
size_t i_size;
tx3g_segment_t *p_next3g;
};
static tx3g_segment_t * tx3g_segment_New( const char *psz_string )
{
tx3g_segment_t *p_seg = malloc( sizeof(tx3g_segment_t) );
if( p_seg )
{
p_seg->i_size = 0;
p_seg->p_next3g = NULL;
p_seg->s = text_segment_New( psz_string );
if( !p_seg->s )
{
free( p_seg );
p_seg = NULL;
}
}
return p_seg;
}
static void SegmentDoSplit( tx3g_segment_t *p_segment, uint16_t i_start, uint16_t i_end,
tx3g_segment_t **pp_segment_left,
tx3g_segment_t **pp_segment_middle,
tx3g_segment_t **pp_segment_right )
{
text_segment_t *p_segment_left = *pp_segment_left;
text_segment_t *p_segment_right = *pp_segment_right;
text_segment_t *p_segment_middle = *pp_segment_middle;
tx3g_segment_t *p_segment_left = *pp_segment_left;
tx3g_segment_t *p_segment_right = *pp_segment_right;
tx3g_segment_t *p_segment_middle = *pp_segment_middle;
p_segment_left = p_segment_middle = p_segment_right = NULL;
if ( (p_segment->i_size - i_start < 1) || (p_segment->i_size - i_end < 1) )
......@@ -132,33 +158,33 @@ static void SegmentDoSplit( text_segment_t *p_segment, uint16_t i_start, uint16_
if ( i_start > 0 )
{
char* psz_text = str8indup( p_segment->psz_text, 0, i_start );
p_segment_left = text_segment_New( psz_text );
char* psz_text = str8indup( p_segment->s->psz_text, 0, i_start );
p_segment_left = tx3g_segment_New( psz_text );
free( psz_text );
if ( !p_segment_left ) goto error;
p_segment_left->style = text_style_Duplicate( p_segment->style );
p_segment_left->i_size = str8len( p_segment_left->psz_text );
p_segment_left->s->style = text_style_Duplicate( p_segment->s->style );
p_segment_left->i_size = str8len( p_segment_left->s->psz_text );
}
char* psz_text = str8indup( p_segment->psz_text, i_start, i_end - i_start + 1 );
p_segment_middle = text_segment_New( psz_text );
char* psz_text = str8indup( p_segment->s->psz_text, i_start, i_end - i_start + 1 );
p_segment_middle = tx3g_segment_New( psz_text );
free( psz_text );
if ( !p_segment_middle ) goto error;
p_segment_middle->style = text_style_Duplicate( p_segment->style );
p_segment_middle->i_size = str8len( p_segment_middle->psz_text );
p_segment_middle->s->style = text_style_Duplicate( p_segment->s->style );
p_segment_middle->i_size = str8len( p_segment_middle->s->psz_text );
if ( i_end < (p_segment->i_size - 1) )
{
char* psz_text = str8indup( p_segment->psz_text, i_end + 1, p_segment->i_size - i_end - 1 );
p_segment_right = text_segment_New( psz_text );
char* psz_text = str8indup( p_segment->s->psz_text, i_end + 1, p_segment->i_size - i_end - 1 );
p_segment_right = tx3g_segment_New( psz_text );
free( psz_text );
if ( !p_segment_right ) goto error;
p_segment_right->style = text_style_Duplicate( p_segment->style );
p_segment_right->i_size = str8len( p_segment_right->psz_text );
p_segment_right->s->style = text_style_Duplicate( p_segment->s->style );
p_segment_right->i_size = str8len( p_segment_right->s->psz_text );
}
if ( p_segment_left ) p_segment_left->p_next = p_segment_middle;
if ( p_segment_right ) p_segment_middle->p_next = p_segment_right;
if ( p_segment_left ) p_segment_left->p_next3g = p_segment_middle;
if ( p_segment_right ) p_segment_middle->p_next3g = p_segment_right;
*pp_segment_left = p_segment_left;
*pp_segment_middle = p_segment_middle;
......@@ -167,16 +193,19 @@ static void SegmentDoSplit( text_segment_t *p_segment, uint16_t i_start, uint16_
return;
error:
text_segment_Delete( p_segment_left );
text_segment_Delete( p_segment_middle );
text_segment_Delete( p_segment_right );
text_segment_Delete( p_segment_left->s );
free( p_segment_left );
text_segment_Delete( p_segment_middle->s );
free( p_segment_middle );
text_segment_Delete( p_segment_right->s );
free( p_segment_right );
}
static bool SegmentSplit( text_segment_t *p_prev, text_segment_t **pp_segment,
static bool SegmentSplit( tx3g_segment_t *p_prev, tx3g_segment_t **pp_segment,
const uint16_t i_start, const uint16_t i_end,
const text_style_t *p_styles )
{
text_segment_t *p_segment_left = NULL, *p_segment_middle = NULL, *p_segment_right = NULL;
tx3g_segment_t *p_segment_left = NULL, *p_segment_middle = NULL, *p_segment_right = NULL;
if ( (*pp_segment)->i_size == 0 ) return false;
if ( i_start > i_end ) return false;
......@@ -187,36 +216,39 @@ static bool SegmentSplit( text_segment_t *p_prev, text_segment_t **pp_segment,
if ( !p_segment_middle )
{
/* Failed */
text_segment_Delete( p_segment_left );
text_segment_Delete( p_segment_right );
text_segment_Delete( p_segment_left->s );
free( p_segment_left );
text_segment_Delete( p_segment_right->s );
free( p_segment_right );
return false;
}
text_segment_t *p_next = (*pp_segment)->p_next;
text_segment_Delete( *pp_segment );
tx3g_segment_t *p_next3g = (*pp_segment)->p_next3g;
text_segment_Delete( (*pp_segment)->s );
free( *pp_segment );
*pp_segment = ( p_segment_left ) ? p_segment_left : p_segment_middle ;
if ( p_prev ) p_prev->p_next = *pp_segment;
if ( p_prev ) p_prev->p_next3g = *pp_segment;
if ( p_segment_right )
p_segment_right->p_next = p_next;
p_segment_right->p_next3g = p_next3g;
else
p_segment_middle->p_next = p_next;
p_segment_middle->p_next3g = p_next3g;
text_style_Delete( p_segment_middle->style );
p_segment_middle->style = text_style_Duplicate( p_styles );
text_style_Delete( p_segment_middle->s->style );
p_segment_middle->s->style = text_style_Duplicate( p_styles );
return true;
}
/* Creates a new segment using the given style and split existing ones according
to the start & end offsets */
static void ApplySegmentStyle( text_segment_t **pp_segment, const uint16_t i_absstart,
static void ApplySegmentStyle( tx3g_segment_t **pp_segment, const uint16_t i_absstart,
const uint16_t i_absend, const text_style_t *p_styles )
{
/* find the matching segment */
uint16_t i_curstart = 0;
text_segment_t *p_prev = NULL;
text_segment_t *p_cur = *pp_segment;
tx3g_segment_t *p_prev = NULL;
tx3g_segment_t *p_cur = *pp_segment;
while ( p_cur )
{
uint16_t i_curend = i_curstart + p_cur->i_size - 1;
......@@ -233,7 +265,7 @@ static void ApplySegmentStyle( text_segment_t **pp_segment, const uint16_t i_abs
{
i_curstart += p_cur->i_size;
p_prev = p_cur;
p_cur = p_cur->p_next;
p_cur = p_cur->p_next3g;
}
}
}
......@@ -282,21 +314,22 @@ static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block )
for( uint16_t i=0; i < i_psz_bytelength; i++ )
if ( psz_subtitle[i] == '\r' ) psz_subtitle[i] = '\n';
text_segment_t *p_segment = text_segment_New( psz_subtitle );
p_segment->i_size = str8len( psz_subtitle );
tx3g_segment_t *p_segment3g = tx3g_segment_New( psz_subtitle );
p_segment3g->i_size = str8len( psz_subtitle );
if ( p_dec->fmt_in.subs.p_style )
{
p_segment->style = text_style_New();
p_segment->style->i_font_color = p_dec->fmt_in.subs.p_style->i_font_color;
p_segment->style->i_font_alpha = p_dec->fmt_in.subs.p_style->i_font_alpha;
p_segment3g->s->style = text_style_New();
p_segment3g->s->style->i_font_color = p_dec->fmt_in.subs.p_style->i_font_color;
p_segment3g->s->style->i_font_alpha = p_dec->fmt_in.subs.p_style->i_font_alpha;
if ( p_dec->fmt_in.subs.p_style->i_style_flags )
p_segment->style->i_style_flags = p_dec->fmt_in.subs.p_style->i_style_flags;
p_segment->style->i_font_size = p_dec->fmt_in.subs.p_style->i_font_size;
p_segment3g->s->style->i_style_flags = p_dec->fmt_in.subs.p_style->i_style_flags;
p_segment3g->s->style->i_font_size = p_dec->fmt_in.subs.p_style->i_font_size;
}
if ( !p_segment->psz_text )
if ( !p_segment3g->s->psz_text )
{
text_segment_Delete( p_segment );
text_segment_Delete( p_segment3g->s );
free( p_segment3g );
free( psz_subtitle );
return NULL;
}
......@@ -306,7 +339,8 @@ static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block )
if( !p_spu )
{
free( psz_subtitle );
text_segment_Delete( p_segment );
text_segment_Delete( p_segment3g->s );
free( p_segment3g );
return NULL;
}
subpicture_updater_sys_t *p_spu_sys = p_spu->updater.p_sys;
......@@ -337,7 +371,7 @@ static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block )
style.i_font_size = p_buf[7];
style.i_font_color = GetDWBE(p_buf+8) >> 8;// RGBA -> RGB
style.i_font_alpha = GetDWBE(p_buf+8) & 0xFF;
ApplySegmentStyle( &p_segment, i_start, i_end, &style );
ApplySegmentStyle( &p_segment3g, i_start, i_end, &style );
if ( i_nbrecords == 1 )
{
......@@ -379,7 +413,21 @@ 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->p_segments = p_segment;
/* Unwrap */
text_segment_t *p_text_segments = p_segment3g->s;
text_segment_t *p_cur = p_text_segments;
while( p_segment3g )
{
tx3g_segment_t * p_old = p_segment3g;
p_segment3g = p_segment3g->p_next3g;
free( p_old );
if( p_segment3g )
p_cur->p_next = p_segment3g->s;
p_cur = p_cur->p_next;
}
p_spu_sys->p_segments = p_text_segments;
block_Release( p_block );
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment