Commit 782de7d7 authored by François Cartegnie's avatar François Cartegnie 🤞

text_style: use inheritance

Renderer should have final decision of the styles to apply.
Rendered forced styles are applied over text-segments
ones, then renderer defaults (text-style's ones).

Also adds proportional font size.
Fixes all style inheritance and font sizing hacks in region
sys.

Final fixed font size is only computed at update time, if
not set to fixed size by decoder.
parent e7e451fb
......@@ -121,6 +121,59 @@ typedef enum
EIA608_STATUS_DISPLAY = EIA608_STATUS_CAPTION_CLEARED | EIA608_STATUS_CAPTION_ENDED,
} eia608_status_t;
static const struct {
eia608_color_t i_color;
eia608_font_t i_font;
int i_column;
} pac2_attribs[]= {
{ EIA608_COLOR_WHITE, EIA608_FONT_REGULAR, 0 },
{ EIA608_COLOR_WHITE, EIA608_FONT_UNDERLINE, 0 },
{ EIA608_COLOR_GREEN, EIA608_FONT_REGULAR, 0 },
{ EIA608_COLOR_GREEN, EIA608_FONT_UNDERLINE, 0 },
{ EIA608_COLOR_BLUE, EIA608_FONT_REGULAR, 0 },
{ EIA608_COLOR_BLUE, EIA608_FONT_UNDERLINE, 0 },
{ EIA608_COLOR_CYAN, EIA608_FONT_REGULAR, 0 },
{ EIA608_COLOR_CYAN, EIA608_FONT_UNDERLINE, 0 },
{ EIA608_COLOR_RED, EIA608_FONT_REGULAR, 0 },
{ EIA608_COLOR_RED, EIA608_FONT_UNDERLINE, 0 },
{ EIA608_COLOR_YELLOW, EIA608_FONT_REGULAR, 0 },
{ EIA608_COLOR_YELLOW, EIA608_FONT_UNDERLINE, 0 },
{ EIA608_COLOR_MAGENTA, EIA608_FONT_REGULAR, 0 },
{ EIA608_COLOR_MAGENTA, EIA608_FONT_UNDERLINE, 0 },
{ EIA608_COLOR_WHITE, EIA608_FONT_ITALICS, 0 },
{ EIA608_COLOR_WHITE, EIA608_FONT_UNDERLINE_ITALICS, 0 },
{ EIA608_COLOR_WHITE, EIA608_FONT_REGULAR, 0 },
{ EIA608_COLOR_WHITE, EIA608_FONT_UNDERLINE, 0 },
{ EIA608_COLOR_WHITE, EIA608_FONT_REGULAR, 4 },
{ EIA608_COLOR_WHITE, EIA608_FONT_UNDERLINE, 4 },
{ EIA608_COLOR_WHITE, EIA608_FONT_REGULAR, 8 },
{ EIA608_COLOR_WHITE, EIA608_FONT_UNDERLINE, 8 },
{ EIA608_COLOR_WHITE, EIA608_FONT_REGULAR, 12 },
{ EIA608_COLOR_WHITE, EIA608_FONT_UNDERLINE, 12 },
{ EIA608_COLOR_WHITE, EIA608_FONT_REGULAR, 16 },
{ EIA608_COLOR_WHITE, EIA608_FONT_UNDERLINE, 16 },
{ EIA608_COLOR_WHITE, EIA608_FONT_REGULAR, 20 },
{ EIA608_COLOR_WHITE, EIA608_FONT_UNDERLINE, 20 },
{ EIA608_COLOR_WHITE, EIA608_FONT_REGULAR, 24 },
{ EIA608_COLOR_WHITE, EIA608_FONT_UNDERLINE, 24 },
{ EIA608_COLOR_WHITE, EIA608_FONT_REGULAR, 28 },
{ EIA608_COLOR_WHITE, EIA608_FONT_UNDERLINE, 28 } ,
};
#define EIA608_COLOR_DEFAULT EIA608_COLOR_WHITE
static const int rgi_eia608_colors[] = {
0xffffff, // white
0x00ff00, // green
0x0000ff, // blue
0x00ffff, // cyan
0xff0000, // red
0xffff00, // yellow
0xff00ff, // magenta
0xffffff, // user defined XXX we use white
};
typedef struct
{
/* Current channel (used to reject packet without channel information) */
......@@ -371,8 +424,12 @@ static subpicture_t *Subtitle( decoder_t *p_dec, text_segment_t *p_segments, mti
region itself gets aligned, but the text inside it does not */
p_spu_sys->align = SUBPICTURE_ALIGN_LEAVETEXT;
p_spu_sys->p_segments = p_segments;
p_spu_sys->i_font_height_percent = 5;
p_spu_sys->renderbg = p_dec->p_sys->b_opaque;
/* Set style defaults (will be added to segments if none set) */
p_spu_sys->p_default_style->i_style_flags |= STYLE_MONOSPACED;
p_spu_sys->p_default_style->i_font_color = rgi_eia608_colors[EIA608_COLOR_DEFAULT];
p_spu_sys->p_default_style->f_font_relsize = 80.0 / EIA608_SCREEN_ROWS;
p_spu_sys->p_default_style->i_features |= (STYLE_HAS_FONT_COLOR | STYLE_HAS_FLAGS);
return p_spu;
}
......@@ -428,48 +485,6 @@ static subpicture_t *Convert( decoder_t *p_dec, block_t **pp_block )
/*****************************************************************************
*
*****************************************************************************/
static const struct {
eia608_color_t i_color;
eia608_font_t i_font;
int i_column;
} pac2_attribs[]= {
{ EIA608_COLOR_WHITE, EIA608_FONT_REGULAR, 0 },
{ EIA608_COLOR_WHITE, EIA608_FONT_UNDERLINE, 0 },
{ EIA608_COLOR_GREEN, EIA608_FONT_REGULAR, 0 },
{ EIA608_COLOR_GREEN, EIA608_FONT_UNDERLINE, 0 },
{ EIA608_COLOR_BLUE, EIA608_FONT_REGULAR, 0 },
{ EIA608_COLOR_BLUE, EIA608_FONT_UNDERLINE, 0 },
{ EIA608_COLOR_CYAN, EIA608_FONT_REGULAR, 0 },
{ EIA608_COLOR_CYAN, EIA608_FONT_UNDERLINE, 0 },
{ EIA608_COLOR_RED, EIA608_FONT_REGULAR, 0 },
{ EIA608_COLOR_RED, EIA608_FONT_UNDERLINE, 0 },
{ EIA608_COLOR_YELLOW, EIA608_FONT_REGULAR, 0 },
{ EIA608_COLOR_YELLOW, EIA608_FONT_UNDERLINE, 0 },
{ EIA608_COLOR_MAGENTA, EIA608_FONT_REGULAR, 0 },
{ EIA608_COLOR_MAGENTA, EIA608_FONT_UNDERLINE, 0 },
{ EIA608_COLOR_WHITE, EIA608_FONT_ITALICS, 0 },
{ EIA608_COLOR_WHITE, EIA608_FONT_UNDERLINE_ITALICS, 0 },
{ EIA608_COLOR_WHITE, EIA608_FONT_REGULAR, 0 },
{ EIA608_COLOR_WHITE, EIA608_FONT_UNDERLINE, 0 },
{ EIA608_COLOR_WHITE, EIA608_FONT_REGULAR, 4 },
{ EIA608_COLOR_WHITE, EIA608_FONT_UNDERLINE, 4 },
{ EIA608_COLOR_WHITE, EIA608_FONT_REGULAR, 8 },
{ EIA608_COLOR_WHITE, EIA608_FONT_UNDERLINE, 8 },
{ EIA608_COLOR_WHITE, EIA608_FONT_REGULAR, 12 },
{ EIA608_COLOR_WHITE, EIA608_FONT_UNDERLINE, 12 },
{ EIA608_COLOR_WHITE, EIA608_FONT_REGULAR, 16 },
{ EIA608_COLOR_WHITE, EIA608_FONT_UNDERLINE, 16 },
{ EIA608_COLOR_WHITE, EIA608_FONT_REGULAR, 20 },
{ EIA608_COLOR_WHITE, EIA608_FONT_UNDERLINE, 20 },
{ EIA608_COLOR_WHITE, EIA608_FONT_REGULAR, 24 },
{ EIA608_COLOR_WHITE, EIA608_FONT_UNDERLINE, 24 },
{ EIA608_COLOR_WHITE, EIA608_FONT_REGULAR, 28 },
{ EIA608_COLOR_WHITE, EIA608_FONT_UNDERLINE, 28 } ,
};
#define EIA608_COLOR_DEFAULT EIA608_COLOR_WHITE
static void Eia608Cursor( eia608_t *h, int dx )
{
h->cursor.i_column += dx;
......@@ -1004,6 +1019,7 @@ static text_segment_t * Eia608TextLine( struct eia608_screen *screen, int i_row,
text_segment_Delete(p_segment);
return NULL;
}
text_style_Reset( p_segment->style );
/* Ensure we get a monospaced font (required for accurate positioning */
p_segment->style->i_style_flags |= STYLE_MONOSPACED;
......@@ -1046,27 +1062,25 @@ static text_segment_t * Eia608TextLine( struct eia608_screen *screen, int i_row,
text_segment_Delete(p_segment);
return p_segments_head;
}
text_style_Reset( p_segment->style );
p_segment->style->i_style_flags |= STYLE_MONOSPACED;
/* start segment with new style */
if(font & EIA608_FONT_ITALICS)
{
p_segment->style->i_style_flags |= STYLE_ITALIC;
p_segment->style->i_features |= STYLE_HAS_FLAGS;
}
if(font & EIA608_FONT_UNDERLINE)
{
p_segment->style->i_style_flags |= STYLE_UNDERLINE;
p_segment->style->i_features |= STYLE_HAS_FLAGS;
}
if(color != EIA608_COLOR_DEFAULT)
{
static const int rgi_colors[] = {
0xffffff, // white
0x00ff00, // green
0x0000ff, // blue
0x00ffff, // cyan
0xff0000, // red
0xffff00, // yellow
0xff00ff, // magenta
0xffffff, // user defined XXX we use white
};
p_segment->style->i_font_color = rgi_colors[color];
p_segment->style->i_font_color = rgi_eia608_colors[color];
p_segment->style->i_features |= STYLE_HAS_FONT_COLOR;
}
}
......
......@@ -876,9 +876,20 @@ struct style_stack
style_stack_t* p_next;
};
static text_style_t *CreateDefaultStyle()
{
text_style_t *p_style = text_style_New();
if( p_style )
{
text_style_Reset( p_style );
p_style->f_font_relsize = STYLE_DEFAULT_REL_FONT_SIZE;
}
return p_style;
}
static text_style_t* DuplicateAndPushStyle(style_stack_t** pp_stack)
{
text_style_t* p_dup = *pp_stack ? text_style_Duplicate( (*pp_stack)->p_style ) : text_style_New();
text_style_t* p_dup = ( *pp_stack ) ? text_style_Duplicate( (*pp_stack)->p_style ) : CreateDefaultStyle();
if ( unlikely( !p_dup ) )
return NULL;
style_stack_t* p_entry = malloc( sizeof( *p_entry ) );
......@@ -923,7 +934,7 @@ static text_segment_t* NewTextSegmentPopStyle( text_segment_t* p_segment, style_
// We shouldn't have an empty stack since this happens when closing a tag,
// but better be safe than sorry if (/when) we encounter a broken subtitle file.
PopStyle( pp_stack );
text_style_t* p_dup = *pp_stack ? text_style_Duplicate( (*pp_stack)->p_style ) : text_style_New();
text_style_t* p_dup = ( *pp_stack ) ? text_style_Duplicate( (*pp_stack)->p_style ) : CreateDefaultStyle();
p_new->style = p_dup;
p_segment->p_next = p_new;
return p_new;
......@@ -958,21 +969,25 @@ static text_segment_t* ParseSubtitles( int *pi_align, const char *psz_subtitle )
{
p_segment = NewTextSegmentPushStyle( p_segment, &p_stack );
p_segment->style->i_style_flags |= STYLE_BOLD;
p_segment->style->i_features |= STYLE_HAS_FLAGS;
}
else if( !strcasecmp( psz_tagname, "i" ) )
{
p_segment = NewTextSegmentPushStyle( p_segment, &p_stack );
p_segment->style->i_style_flags |= STYLE_ITALIC;
p_segment->style->i_features |= STYLE_HAS_FLAGS;
}
else if( !strcasecmp( psz_tagname, "u" ) )
{
p_segment = NewTextSegmentPushStyle( p_segment, &p_stack );
p_segment->style->i_style_flags |= STYLE_UNDERLINE;
p_segment->style->i_features |= STYLE_HAS_FLAGS;
}
else if( !strcasecmp( psz_tagname, "s" ) )
{
p_segment = NewTextSegmentPushStyle( p_segment, &p_stack );
p_segment->style->i_style_flags |= STYLE_STRIKEOUT;
p_segment->style->i_features |= STYLE_HAS_FLAGS;
}
else if( !strcasecmp( psz_tagname, "font" ) )
{
......@@ -997,18 +1012,23 @@ static text_segment_t* ParseSubtitles( int *pi_align, const char *psz_subtitle )
else if ( !strcasecmp( psz_attribute_name, "size" ) )
{
p_segment->style->i_font_size = atoi( psz_attribute_value );
p_segment->style->f_font_relsize = STYLE_DEFAULT_REL_FONT_SIZE *
STYLE_DEFAULT_FONT_SIZE / p_segment->style->i_font_size;
}
else if ( !strcasecmp( psz_attribute_name, "color" ) )
{
p_segment->style->i_font_color = GetColor( psz_attribute_value );
p_segment->style->i_features |= STYLE_HAS_FONT_COLOR;
}
else if ( !strcasecmp( psz_attribute_name, "outline-color" ) )
{
p_segment->style->i_outline_color = GetColor( psz_attribute_value );
p_segment->style->i_features |= STYLE_HAS_OUTLINE_COLOR;
}
else if ( !strcasecmp( psz_attribute_name, "shadow-color" ) )
{
p_segment->style->i_shadow_color = GetColor( psz_attribute_value );
p_segment->style->i_features |= STYLE_HAS_SHADOW_COLOR;
}
else if ( !strcasecmp( psz_attribute_name, "outline-level" ) )
{
......@@ -1021,10 +1041,12 @@ static text_segment_t* ParseSubtitles( int *pi_align, const char *psz_subtitle )
else if ( !strcasecmp( psz_attribute_name, "back-color" ) )
{
p_segment->style->i_background_color = GetColor( psz_attribute_value );
p_segment->style->i_features |= STYLE_HAS_BACKGROUND_COLOR;
}
else if ( !strcasecmp( psz_attribute_name, "alpha" ) )
{
p_segment->style->i_font_alpha = atoi( psz_attribute_value );
p_segment->style->i_features |= STYLE_HAS_FONT_ALPHA;
}
free( psz_attribute_name );
......@@ -1127,18 +1149,21 @@ static text_segment_t* ParseSubtitles( int *pi_align, const char *psz_subtitle )
{
p_segment = NewTextSegmentPushStyle( p_segment, &p_stack );
p_segment->style->i_style_flags |= STYLE_ITALIC;
p_segment->style->i_features |= STYLE_HAS_FLAGS;
psz_subtitle++;
}
if( psz_subtitle[3] == 'b' )
{
p_segment = NewTextSegmentPushStyle( p_segment, &p_stack );
p_segment->style->i_style_flags |= STYLE_BOLD;
p_segment->style->i_features |= STYLE_HAS_FLAGS;
psz_subtitle++;
}
if( psz_subtitle[3] == 'u' )
{
p_segment = NewTextSegmentPushStyle( p_segment, &p_stack );
p_segment->style->i_style_flags |= STYLE_UNDERLINE;
p_segment->style->i_features |= STYLE_HAS_FLAGS;
psz_subtitle++;
}
psz_subtitle = strchr( psz_subtitle, '}' ) + 1;
......
#include <vlc_strings.h>
#include <vlc_text_style.h>
typedef struct
{
bool b_set;
unsigned int i_value;
} subpicture_updater_sys_option_t;
struct subpicture_updater_sys_t {
text_segment_t *p_segments;
int align;
int x;
int y;
int i_font_height_percent;
int i_font_height_abs_to_src;
bool is_fixed;
int fixed_width;
......@@ -22,12 +14,7 @@ struct subpicture_updater_sys_t {
bool renderbg;
/* styling */
subpicture_updater_sys_option_t style_flags;
subpicture_updater_sys_option_t font_color;
subpicture_updater_sys_option_t background_color;
int16_t i_alpha;
int16_t i_drop_shadow;
int16_t i_drop_shadow_alpha;
text_style_t *p_default_style; /* decoder (full or partial) defaults */
};
static int SubpictureTextValidate(subpicture_t *subpic,
......@@ -101,42 +88,20 @@ static void SubpictureTextUpdate(subpicture_t *subpic,
r->i_y = sys->y * fmt_dst->i_height / sys->fixed_height;
}
if (sys->i_font_height_percent || sys->i_alpha ||
sys->style_flags.b_set ||
sys->font_color.b_set ||
sys->background_color.b_set )
/* Add missing default style, if any, to all segments */
for ( text_segment_t* p_segment = sys->p_segments; p_segment; p_segment = p_segment->p_next )
{
//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 )
/* Add decoder defaults */
if( p_segment->style )
text_style_Merge( p_segment->style, sys->p_default_style, false );
else
p_segment->style = text_style_Duplicate( sys->p_default_style );
/* Update all segments font sizes in pixels, *** metric used by renderers *** */
/* We only do this when a fixed font size isn't set */
if( p_segment->style->f_font_relsize && !p_segment->style->i_font_size )
{
text_style_t* p_style = p_segment->style;
if(!p_style)
continue;
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;
p_segment->style->i_font_size = p_segment->style->f_font_relsize *
subpic->i_original_picture_height / 100;
}
}
}
......@@ -157,8 +122,18 @@ static inline subpicture_t *decoder_NewSubpictureText(decoder_t *decoder)
.pf_destroy = SubpictureTextDestroy,
.p_sys = sys,
};
sys->p_default_style = text_style_New();
if(unlikely(!sys->p_default_style))
{
free(sys);
return NULL;
}
text_style_Reset( sys->p_default_style );
subpicture_t *subpic = decoder_NewSubpicture(decoder, &updater);
if (!subpic)
{
text_style_Delete(sys->p_default_style);
free(sys);
}
return subpic;
}
......@@ -317,14 +317,7 @@ static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block )
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_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_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;
}
p_segment3g->s->style = text_style_Duplicate( p_dec->fmt_in.subs.p_style );
if ( !p_segment3g->s->psz_text )
{
......@@ -367,23 +360,26 @@ static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block )
uint16_t i_end = __MIN( GetWBE(p_buf + 2), i_psz_bytelength - 1 );
text_style_t style;
memset( &style, 0, sizeof(text_style_t) );
text_style_Reset( &style );
style.i_style_flags = ConvertFlags( p_buf[6] );
style.i_font_size = p_buf[7];
style.f_font_relsize = p_buf[7] * 5 / 100; /* in % units of 0.05 height */
style.i_font_color = GetDWBE(p_buf+8) >> 8;// RGBA -> RGB
style.i_font_alpha = GetDWBE(p_buf+8) & 0xFF;
style.i_features = STYLE_HAS_FONT_COLOR | STYLE_HAS_FONT_ALPHA;
ApplySegmentStyle( &p_segment3g, i_start, i_end, &style );
if ( i_nbrecords == 1 )
{
if ( p_buf[6] )
{
p_spu_sys->style_flags.i_value = ConvertFlags( p_buf[6] );
p_spu_sys->style_flags.b_set = true;
if( (p_spu_sys->p_default_style->i_style_flags = ConvertFlags( p_buf[6] )) )
p_spu_sys->p_default_style->i_features |= STYLE_HAS_FLAGS;
}
p_spu_sys->i_font_height_abs_to_src = p_buf[7];
p_spu_sys->font_color.i_value = GetDWBE(p_buf+8) >> 8;// RGBA -> ARGB
p_spu_sys->font_color.i_value |= (GetDWBE(p_buf+8) & 0xFF) << 24;
p_spu_sys->font_color.b_set = true;
p_spu_sys->p_default_style->f_font_relsize = p_buf[7] * 5 / 100;
p_spu_sys->p_default_style->i_font_color = GetDWBE(p_buf+8) >> 8;// RGBA -> ARGB
p_spu_sys->p_default_style->i_font_alpha = (GetDWBE(p_buf+8) & 0xFF) << 24;
p_spu_sys->p_default_style->i_features |= (STYLE_HAS_FONT_COLOR | STYLE_HAS_FONT_ALPHA);
}
p_buf += 12;
......@@ -392,12 +388,13 @@ static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block )
case VLC_FOURCC('d','r','p','o'):
if ( (size_t)(p_buf - p_block->p_buffer) < 4 ) break;
p_spu_sys->i_drop_shadow = __MAX( GetWBE(p_buf), GetWBE(p_buf+2) );
p_spu_sys->p_default_style->i_shadow_width = __MAX( GetWBE(p_buf), GetWBE(p_buf+2) );
break;
case VLC_FOURCC('d','r','p','t'):
if ( (size_t)(p_buf - p_block->p_buffer) < 2 ) break;
p_spu_sys->i_drop_shadow_alpha = GetWBE(p_buf);
p_spu_sys->p_default_style->i_shadow_alpha = GetWBE(p_buf);
p_spu_sys->p_default_style->i_features |= STYLE_HAS_SHADOW_ALPHA;
break;
default:
......
......@@ -73,7 +73,7 @@ typedef struct
typedef struct
{
char * psz_stylename; /* The name of the style, no comma's allowed */
text_style_t font_style;
text_style_t * p_style;
int i_align;
int i_margin_h;
int i_margin_v;
......@@ -184,8 +184,7 @@ static void CloseDecoder( vlc_object_t *p_this )
continue;
free( p_sys->pp_ssa_styles[i]->psz_stylename );
//FIXME: Make font_style a pointer and use text_style_* functions
free( p_sys->pp_ssa_styles[i]->font_style.psz_fontname );
text_style_Delete( p_sys->pp_ssa_styles[i]->p_style );
free( p_sys->pp_ssa_styles[i] );
}
TAB_CLEAN( p_sys->i_ssa_styles, p_sys->pp_ssa_styles );
......@@ -417,6 +416,7 @@ static subpicture_region_t *CreateTextRegion( decoder_t *p_dec,
decoder_sys_t *p_sys = p_dec->p_sys;
subpicture_region_t *p_text_region;
video_format_t fmt;
VLC_UNUSED( i_len );
/* Create a new subpicture region */
memset( &fmt, 0, sizeof(video_format_t) );
......@@ -456,7 +456,7 @@ 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 );
p_text_region->p_text = text_segment_NewInheritStyle( p_ssa_style->p_style );
}
else
{
......@@ -616,6 +616,13 @@ static void ParseUSFHeaderTags( decoder_t *p_dec, xml_reader_t *p_xml_reader )
p_ssa_style = calloc( 1, sizeof(ssa_style_t) );
if( unlikely(!p_ssa_style) )
return;
p_ssa_style->p_style = text_style_New();
if( unlikely(!p_ssa_style->p_style) )
{
free(p_ssa_style);
return;
}
text_style_Reset( p_ssa_style->p_style );
/* All styles are supposed to default to Default, and then
* one or more settings are over-ridden.
* At the moment this only effects styles defined AFTER
......@@ -630,7 +637,7 @@ static void ParseUSFHeaderTags( decoder_t *p_dec, xml_reader_t *p_xml_reader )
memcpy( p_ssa_style, p_default_style, sizeof( ssa_style_t ) );
//FIXME: Make font_style a pointer. Actually we double copy some data here,
// we use text_style_Copy to avoid copying psz_fontname, though .
text_style_Copy( &p_ssa_style->font_style, &p_default_style->font_style );
text_style_Copy( p_ssa_style->p_style, p_default_style->p_style );
p_ssa_style->psz_stylename = NULL;
}
}
......@@ -652,8 +659,8 @@ static void ParseUSFHeaderTags( decoder_t *p_dec, xml_reader_t *p_xml_reader )
{
if( !strcasecmp( "face", attr ) )
{
free( p_ssa_style->font_style.psz_fontname );
p_ssa_style->font_style.psz_fontname = strdup( val );
free( p_ssa_style->p_style->psz_fontname );
p_ssa_style->p_style->psz_fontname = strdup( val );
}
else if( !strcasecmp( "size", attr ) )
{
......@@ -662,44 +669,49 @@ static void ParseUSFHeaderTags( decoder_t *p_dec, xml_reader_t *p_xml_reader )
int i_value = atoi( val );
if( ( i_value >= -5 ) && ( i_value <= 5 ) )
p_ssa_style->font_style.i_font_size +=
( i_value * p_ssa_style->font_style.i_font_size ) / 10;
p_ssa_style->p_style->i_font_size +=
( i_value * p_ssa_style->p_style->i_font_size ) / 10;
else if( i_value < -5 )
p_ssa_style->font_style.i_font_size = - i_value;
p_ssa_style->p_style->i_font_size = - i_value;
else if( i_value > 5 )
p_ssa_style->font_style.i_font_size = i_value;
p_ssa_style->p_style->i_font_size = i_value;
}
else
p_ssa_style->font_style.i_font_size = atoi( val );
p_ssa_style->p_style->i_font_size = atoi( val );
}
else if( !strcasecmp( "italic", attr ) )
{
if( !strcasecmp( "yes", val ))
p_ssa_style->font_style.i_style_flags |= STYLE_ITALIC;
p_ssa_style->p_style->i_style_flags |= STYLE_ITALIC;
else
p_ssa_style->font_style.i_style_flags &= ~STYLE_ITALIC;
p_ssa_style->p_style->i_style_flags &= ~STYLE_ITALIC;
p_ssa_style->p_style->i_features |= STYLE_HAS_FLAGS;
}
else if( !strcasecmp( "weight", attr ) )
{
if( !strcasecmp( "bold", val ))
p_ssa_style->font_style.i_style_flags |= STYLE_BOLD;
p_ssa_style->p_style->i_style_flags |= STYLE_BOLD;
else
p_ssa_style->font_style.i_style_flags &= ~STYLE_BOLD;
p_ssa_style->p_style->i_style_flags &= ~STYLE_BOLD;
p_ssa_style->p_style->i_features |= STYLE_HAS_FLAGS;
}
else if( !strcasecmp( "underline", attr ) )
{
if( !strcasecmp( "yes", val ))
p_ssa_style->font_style.i_style_flags |= STYLE_UNDERLINE;
p_ssa_style->p_style->i_style_flags |= STYLE_UNDERLINE;
else
p_ssa_style->font_style.i_style_flags &= ~STYLE_UNDERLINE;
p_ssa_style->p_style->i_style_flags &= ~STYLE_UNDERLINE;
p_ssa_style->p_style->i_features |= STYLE_HAS_FLAGS;
}
else if( !strcasecmp( "color", attr ) )
{
if( *val == '#' )
{
unsigned long col = strtol(val+1, NULL, 16);
p_ssa_style->font_style.i_font_color = (col & 0x00ffffff);
p_ssa_style->font_style.i_font_alpha = (col >> 24) & 0xff;
p_ssa_style->p_style->i_font_color = (col & 0x00ffffff);
p_ssa_style->p_style->i_font_alpha = (col >> 24) & 0xff;
p_ssa_style->p_style->i_features |= STYLE_HAS_FONT_COLOR
| STYLE_HAS_FONT_ALPHA;
}
}
else if( !strcasecmp( "outline-color", attr ) )
......@@ -707,39 +719,45 @@ static void ParseUSFHeaderTags( decoder_t *p_dec, xml_reader_t *p_xml_reader )
if( *val == '#' )
{
unsigned long col = strtol(val+1, NULL, 16);
p_ssa_style->font_style.i_outline_color = (col & 0x00ffffff);
p_ssa_style->font_style.i_outline_alpha = (col >> 24) & 0xff;
p_ssa_style->p_style->i_outline_color = (col & 0x00ffffff);
p_ssa_style->p_style->i_outline_alpha = (col >> 24) & 0xff;
p_ssa_style->p_style->i_features |= STYLE_HAS_OUTLINE_COLOR
| STYLE_HAS_OUTLINE_ALPHA;
}
}
else if( !strcasecmp( "outline-level", attr ) )
{
p_ssa_style->font_style.i_outline_width = atoi( val );
p_ssa_style->p_style->i_outline_width = atoi( val );
}
else if( !strcasecmp( "shadow-color", attr ) )
{
if( *val == '#' )
{
unsigned long col = strtol(val+1, NULL, 16);
p_ssa_style->font_style.i_shadow_color = (col & 0x00ffffff);
p_ssa_style->font_style.i_shadow_alpha = (col >> 24) & 0xff;
p_ssa_style->p_style->i_shadow_color = (col & 0x00ffffff);
p_ssa_style->p_style->i_shadow_alpha = (col >> 24) & 0xff;
p_ssa_style->p_style->i_features |= STYLE_HAS_SHADOW_COLOR
| STYLE_HAS_SHADOW_ALPHA;
}
}
else if( !strcasecmp( "shadow-level", attr ) )
{
p_ssa_style->font_style.i_shadow_width = atoi( val );
p_ssa_style->p_style->i_shadow_width = atoi( val );
}
else if( !strcasecmp( "back-color", attr ) )
{
if( *val == '#' )
{
unsigned long col = strtol(val+1, NULL, 16);
p_ssa_style->font_style.i_karaoke_background_color = (col & 0x00ffffff);
p_ssa_style->font_style.i_karaoke_background_alpha = (col >> 24) & 0xff;
p_ssa_style->p_style->i_karaoke_background_color = (col & 0x00ffffff);
p_ssa_style->p_style->i_karaoke_background_alpha = (col >> 24) & 0xff;
p_ssa_style->p_style->i_features |= STYLE_HAS_K_BACKGROUND_COLOR
| STYLE_HAS_K_BACKGROUND_ALPHA;
}
}
else if( !strcasecmp( "spacing", attr ) )
{
p_ssa_style->font_style.i_spacing = atoi( val );
p_ssa_style->p_style->i_spacing = atoi( val );
}
}
}
......
......@@ -444,7 +444,6 @@ static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block )
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;
p_spu_sys->renderbg = b_opaque;
#ifdef ZVBI_DEBUG
......
......@@ -789,12 +789,16 @@ int SetupSpuES( demux_t *p_demux, mp4_track_t *p_track, MP4_Box_t *p_sample )
text_style_t *p_style = text_style_New();
if ( p_style )
{
if ( p_text->i_font_size ) /* !WARN: % in absolute storage */
p_style->i_font_size = p_text->i_font_size;
text_style_Reset( p_style );
if ( p_text->i_font_size ) /* !WARN: in % of 5% height */
{
p_style->f_font_relsize = p_text->i_font_size * 5 / 100;
}
if ( p_text->i_font_color )
{
p_style->i_font_color = p_text->i_font_color >> 8;
p_style->i_font_alpha = p_text->i_font_color & 0xFF;
p_style->i_features |= (STYLE_HAS_FONT_ALPHA | STYLE_HAS_FONT_COLOR);
}
if ( p_text->i_background_color[3] >> 8 )
{
......@@ -802,6 +806,7 @@ int SetupSpuES( demux_t *p_demux, mp4_track_t *p_track, MP4_Box_t *p_sample )
p_style->i_background_color |= p_text->i_background_color[1] >> 8;
p_style->i_background_color |= p_text->i_background_color[2] >> 8;
p_style->i_background_alpha = p_text->i_background_color[3] >> 8;
p_style->i_features |= (STYLE_HAS_BACKGROUND_ALPHA | STYLE_HAS_BACKGROUND_COLOR);
}
}
p_track->fmt.subs.p_style = p_style;
......
......@@ -192,8 +192,17 @@ static int CreateFilter( vlc_object_t *p_this )
if( p_sys == NULL )
return VLC_ENOMEM;
vlc_mutex_init( &p_sys->lock );
p_sys->p_style = text_style_New();
if(likely(p_sys->p_style))
{
text_style_Reset( p_sys->p_style );
}
else
{
free(p_sys);
return VLC_ENOMEM;
}
vlc_mutex_init( &p_sys->lock );
config_ChainParse( p_filter, CFG_PREFIX, ppsz_filter_options,
p_filter->p_cfg );
......@@ -216,7 +225,9 @@ static int CreateFilter( vlc_object_t *p_this )
p_sys->p_style->i_font_alpha = var_CreateGetIntegerCommand( p_filter,
"marq-opacity" );
var_AddCallback( p_filter, "marq-opacity", MarqueeCallback, p_sys );
p_sys->p_style->i_features |= STYLE_HAS_FONT_ALPHA;
CREATE_VAR( p_style->i_font_color, Integer, "marq-color" );
p_sys->p_style->i_features |= STYLE_HAS_FONT_COLOR;
CREATE_VAR( p_style->i_font_size, Integer, "marq-size" );
/* Misc init */
......@@ -330,9 +341,7 @@ 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;
//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 );
p_spu->p_region->p_text->style = text_style_Duplicate( p_sys->p_style );