[vlc-devel] [PATCH 06/19] ttml codec: add tag style parsing support
Stanislas Plessia
stplessia at gmail.com
Wed Aug 31 12:19:10 CEST 2016
ParseTTMLStyle is now able to parse any type of tag according
to its name and to create a style according to its attributes
---
modules/codec/substtml.c | 115 ++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 100 insertions(+), 15 deletions(-)
diff --git a/modules/codec/substtml.c b/modules/codec/substtml.c
index 1534f95..c471e8a 100644
--- a/modules/codec/substtml.c
+++ b/modules/codec/substtml.c
@@ -99,6 +99,13 @@ static void MergeTTMLStyle( ttml_style_t *p_dst, const ttml_style_t *p_src)
p_dst->i_margin_percent_v = p_src->i_margin_percent_v;
}
+static void CleanupStyle( ttml_style_t* p_ttml_style )
+{
+ text_style_Delete( p_ttml_style->font_style );
+ free( p_ttml_style->psz_styleid );
+ free( p_ttml_style );
+}
+
static ttml_style_t *FindTextStyle( decoder_t *p_dec, const char *psz_style )
{
decoder_sys_t *p_sys = p_dec->p_sys;
@@ -157,7 +164,7 @@ static text_style_t* CurrentStyle( style_stack_t* p_stack )
return text_style_Duplicate( p_stack->p_style->font_style );
}
-static void ParseTTMLStyle( decoder_t *p_dec, xml_reader_t* p_reader )
+static ttml_style_t* ParseTTMLStyle( decoder_t *p_dec, xml_reader_t* p_reader, const char* psz_node_name )
{
decoder_sys_t* p_sys = p_dec->p_sys;
ttml_style_t *p_ttml_style = NULL;
@@ -171,22 +178,95 @@ static void ParseTTMLStyle( decoder_t *p_dec, xml_reader_t* p_reader )
if( unlikely( !p_ttml_style->font_style ) )
{
free( p_ttml_style );
- return ;
+ return NULL;
}
const char *attr, *val;
while( (attr = xml_ReaderNextAttr( p_reader, &val ) ) )
{
- if ( !strcasecmp( attr, "style" ) )
+ /* searching previous styles for inheritence */
+ if( !strcasecmp( attr, "style" ) || !strcasecmp( attr, "region" ) )
{
- for( size_t i = 0; i < p_sys->i_styles; i++ )
+ if( !strcasecmp( psz_node_name, "style" ) || !strcasecmp( psz_node_name, "tt:style" ) ||
+ !strcasecmp( psz_node_name, "region" ) || !strcasecmp( psz_node_name, "tt:region" ) )
+ {
+ for( size_t i = 0; i < p_sys->i_styles; i++ )
+ {
+ if( !strcasecmp( p_sys->pp_styles[i]->psz_styleid, val ) )
+ {
+ p_base_style = p_sys->pp_styles[i];
+ break;
+ }
+ }
+ }
+ /*
+ * In p nodes, style attribute has this format :
+ * style="style1 style2 style3" where style1 and style2 are
+ * style applied on the parents of p in that order.
+ *
+ * In span node, we can apply several styles in the same order than
+ * in p nodes with the same inheritance order.
+ *
+ * In order to preserve this style predominance, we merge the styles
+ * in the from right to left ( the right one being predominant ) .
+ */
+ else if( !strcasecmp( psz_node_name, "p" ) || !strcasecmp( psz_node_name, "tt:p" ) ||
+ !strcasecmp( psz_node_name, "span" ) || !strcasecmp( psz_node_name, "tt:span" ) )
{
- if( !strcasecmp( p_sys->pp_styles[i]->psz_styleid, val ) )
+ char *tmp;
+ char *value = strdup( val );
+ if( unlikely( value == NULL ) )
+ return NULL;
+
+ char *token = strtok_r( value , " ", &tmp );
+ ttml_style_t* p_style = FindTextStyle( p_dec, token );
+ while( p_style == NULL )
{
- p_base_style = p_sys->pp_styles[i];
+ msg_Warn( p_dec, "Style \"%s\" not found", token );
+ token = strtok_r( NULL, " ", &tmp);
+ if( token == NULL )
+ {
+ free( value );
+ break;
+ }
+ p_style = FindTextStyle( p_dec, token );
+ }
+
+ while( ( token = strtok_r( NULL, " ", &tmp) ) != NULL )
+ {
+ ttml_style_t* p_next_style = FindTextStyle( p_dec, token );
+ while( p_next_style == NULL )
+ {
+ msg_Warn( p_dec, "Style \"%s\" not found", token );
+ token = strtok_r( NULL, " ", &tmp);
+ if( token == NULL )
+ {
+ free( value );
+ break;
+ }
+ p_next_style = FindTextStyle( p_dec, token );
+ }
+ MergeTTMLStyle( p_next_style, p_style );
+ CleanupStyle( p_style );
+ p_style = p_next_style;
+ }
+ MergeTTMLStyle( p_style, p_ttml_style );
+ free( value );
+ CleanupStyle( p_ttml_style );
+ p_ttml_style = p_style;
+ }
+ else
+ {
+ ttml_style_t* p_style = FindTextStyle( p_dec, val );
+ if( p_style == NULL )
+ {
+ msg_Warn( p_dec, "Style \"%s\" not found", val );
break;
}
+ MergeTTMLStyle( p_style , p_ttml_style );
+ CleanupStyle( p_ttml_style );
+ p_ttml_style = p_style;
}
}
else if ( !strcasecmp( "xml:id", attr ) )
@@ -199,7 +279,13 @@ static void ParseTTMLStyle( decoder_t *p_dec, xml_reader_t* p_reader )
free( p_ttml_style->font_style->psz_fontname );
p_ttml_style->font_style->psz_fontname = strdup( val );
}
- else if ( !strcasecmp( "tts:fontSize", attr ) )
+ else if( !strcasecmp( "tts:opacity", attr ) )
+ {
+ p_ttml_style->font_style->i_background_alpha = atoi( val );
+ p_ttml_style->font_style->i_font_alpha = atoi( val );
+ p_ttml_style->font_style->i_features |= STYLE_HAS_BACKGROUND_ALPHA | STYLE_HAS_FONT_ALPHA;
+ }
+ else if( !strcasecmp( "tts:fontSize", attr ) )
{
char* psz_end = NULL;
float size = strtof( val, &psz_end );
@@ -330,17 +416,16 @@ static void ParseTTMLStyle( decoder_t *p_dec, xml_reader_t* p_reader )
}
if ( p_base_style != NULL )
{
- text_style_Merge( p_ttml_style->font_style, p_base_style->font_style, false );
+ MergeTTMLStyle( p_ttml_style, p_base_style );
+ CleanupStyle( p_base_style );
}
if ( p_ttml_style->psz_styleid == NULL )
{
- free( p_ttml_style->font_style->psz_fontname );
- free( p_ttml_style );
- return ;
+ CleanupStyle( p_ttml_style );
+ CleanupStyle( p_base_style );
+ return NULL;
}
-
- TAB_APPEND( p_sys->i_styles, p_sys->pp_styles, p_ttml_style );
- return ;
+ return p_ttml_style;
}
static void ParseTTMLStyles( decoder_t* p_dec )
@@ -369,7 +454,7 @@ static void ParseTTMLStyles( decoder_t* p_dec )
i_type = xml_ReaderNextNode( p_reader, &psz_name );
while ( i_type != XML_READER_ENDELEM || ( strcasecmp( psz_name, "styling" ) && strcasecmp( psz_name, "tt:styling" ) ) )
{
- ParseTTMLStyle( p_dec, p_reader );
+ ParseTTMLStyle( p_dec, p_reader, psz_name );
i_type = xml_ReaderNextNode( p_reader, &psz_name );
}
}
--
2.7.4
More information about the vlc-devel
mailing list