text_style_t *text_style_Duplicate( const text_style_t *p_src ) { if( !p_src ) return NULL; text_style_t *p_dst = calloc( 1, sizeof(*p_dst) ); if( p_dst ) text_style_Copy( p_dst, p_src ); return p_dst; }
static void ParseUSFHeaderTags( decoder_t *p_dec, xml_reader_t *p_xml_reader ) { decoder_sys_t *p_sys = p_dec->p_sys; const char *node; ssa_style_t *p_ssa_style = NULL; int i_style_level = 0; int i_metadata_level = 0; int type; while( (type = xml_ReaderNextNode( p_xml_reader, &node )) > 0 ) { switch( type ) { case XML_READER_ENDELEM: switch (i_style_level) { case 0: if( !strcasecmp( "metadata", node ) && (i_metadata_level == 1) ) i_metadata_level--; break; case 1: if( !strcasecmp( "styles", node ) ) i_style_level--; break; case 2: if( !strcasecmp( "style", node ) ) { TAB_APPEND( p_sys->i_ssa_styles, p_sys->pp_ssa_styles, p_ssa_style ); p_ssa_style = NULL; i_style_level--; } break; } break; case XML_READER_STARTELEM: if( !strcasecmp( "metadata", node ) && (i_style_level == 0) ) i_metadata_level++; else if( !strcasecmp( "resolution", node ) && ( i_metadata_level == 1) ) { const char *attr, *val; while( (attr = xml_ReaderNextAttr( p_xml_reader, &val )) ) { if( !strcasecmp( "x", attr ) ) p_sys->i_original_width = atoi( val ); else if( !strcasecmp( "y", attr ) ) p_sys->i_original_height = atoi( val ); } } else if( !strcasecmp( "styles", node ) && (i_style_level == 0) ) { i_style_level++; } else if( !strcasecmp( "style", node ) && (i_style_level == 1) ) { i_style_level++; p_ssa_style = calloc( 1, sizeof(ssa_style_t) ); if( unlikely(!p_ssa_style) ) return; p_ssa_style->p_style = text_style_Create( STYLE_NO_DEFAULTS ); if( unlikely(!p_ssa_style->p_style) ) { free(p_ssa_style); return; } /* 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 * Default in the XML */ for( int i = 0; i < p_sys->i_ssa_styles; i++ ) { if( !strcasecmp( p_sys->pp_ssa_styles[i]->psz_stylename, "Default" ) ) { ssa_style_t *p_default_style = p_sys->pp_ssa_styles[i]; 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->p_style, p_default_style->p_style ); p_ssa_style->psz_stylename = NULL; } } const char *attr, *val; while( (attr = xml_ReaderNextAttr( p_xml_reader, &val )) ) { if( !strcasecmp( "name", attr ) ) { free( p_ssa_style->psz_stylename ); p_ssa_style->psz_stylename = strdup( val ); } } } else if( !strcasecmp( "fontstyle", node ) && (i_style_level == 2) ) { const char *attr, *val; while( (attr = xml_ReaderNextAttr( p_xml_reader, &val )) ) { if( !strcasecmp( "face", attr ) ) { free( p_ssa_style->p_style->psz_fontname ); p_ssa_style->p_style->psz_fontname = strdup( val ); } else if( !strcasecmp( "size", attr ) ) { if( ( *val == '+' ) || ( *val == '-' ) ) { int i_value = atoi( val ); if( ( i_value >= -5 ) && ( i_value <= 5 ) ) 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->p_style->i_font_size = - i_value; else if( i_value > 5 ) p_ssa_style->p_style->i_font_size = i_value; } else p_ssa_style->p_style->i_font_size = atoi( val ); } else if( !strcasecmp( "italic", attr ) ) { if( !strcasecmp( "yes", val )) p_ssa_style->p_style->i_style_flags |= STYLE_ITALIC; else 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->p_style->i_style_flags |= STYLE_BOLD; else 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->p_style->i_style_flags |= STYLE_UNDERLINE; else 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->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 ) ) { if( *val == '#' ) { unsigned long col = strtol(val+1, NULL, 16); 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->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->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; } }
static void ParseUSFHeaderTags( decoder_t *p_dec, xml_reader_t *p_xml_reader ) { decoder_sys_t *p_sys = p_dec->p_sys; char *psz_node; ssa_style_t *p_ssa_style = NULL; int i_style_level = 0; int i_metadata_level = 0; while ( xml_ReaderRead( p_xml_reader ) == 1 ) { switch ( xml_ReaderNodeType( p_xml_reader ) ) { case XML_READER_TEXT: case XML_READER_NONE: break; case XML_READER_ENDELEM: psz_node = xml_ReaderName( p_xml_reader ); if( !psz_node ) break; switch (i_style_level) { case 0: if( !strcasecmp( "metadata", psz_node ) && (i_metadata_level == 1) ) { i_metadata_level--; } break; case 1: if( !strcasecmp( "styles", psz_node ) ) { i_style_level--; } break; case 2: if( !strcasecmp( "style", psz_node ) ) { TAB_APPEND( p_sys->i_ssa_styles, p_sys->pp_ssa_styles, p_ssa_style ); p_ssa_style = NULL; i_style_level--; } break; } free( psz_node ); break; case XML_READER_STARTELEM: psz_node = xml_ReaderName( p_xml_reader ); if( !psz_node ) break; if( !strcasecmp( "metadata", psz_node ) && (i_style_level == 0) ) { i_metadata_level++; } else if( !strcasecmp( "resolution", psz_node ) && ( i_metadata_level == 1) ) { while ( xml_ReaderNextAttr( p_xml_reader ) == VLC_SUCCESS ) { char *psz_name = xml_ReaderName ( p_xml_reader ); char *psz_value = xml_ReaderValue ( p_xml_reader ); if( psz_name && psz_value ) { if( !strcasecmp( "x", psz_name ) ) p_sys->i_original_width = atoi( psz_value ); else if( !strcasecmp( "y", psz_name ) ) p_sys->i_original_height = atoi( psz_value ); } free( psz_name ); free( psz_value ); } } else if( !strcasecmp( "styles", psz_node ) && (i_style_level == 0) ) { i_style_level++; } else if( !strcasecmp( "style", psz_node ) && (i_style_level == 1) ) { i_style_level++; p_ssa_style = calloc( 1, sizeof(ssa_style_t) ); if( !p_ssa_style ) { free( psz_node ); return; } /* 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 * Default in the XML */ int i; for( i = 0; i < p_sys->i_ssa_styles; i++ ) { if( !strcasecmp( p_sys->pp_ssa_styles[i]->psz_stylename, "Default" ) ) { ssa_style_t *p_default_style = p_sys->pp_ssa_styles[i]; 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 ); p_ssa_style->psz_stylename = NULL; } } while ( xml_ReaderNextAttr( p_xml_reader ) == VLC_SUCCESS ) { char *psz_name = xml_ReaderName ( p_xml_reader ); char *psz_value = xml_ReaderValue ( p_xml_reader ); if( psz_name && psz_value ) { if( !strcasecmp( "name", psz_name ) ) p_ssa_style->psz_stylename = strdup( psz_value ); } free( psz_name ); free( psz_value ); } } else if( !strcasecmp( "fontstyle", psz_node ) && (i_style_level == 2) ) { while ( xml_ReaderNextAttr( p_xml_reader ) == VLC_SUCCESS ) { char *psz_name = xml_ReaderName ( p_xml_reader ); char *psz_value = xml_ReaderValue ( p_xml_reader ); if( psz_name && psz_value ) { if( !strcasecmp( "face", psz_name ) ) { free( p_ssa_style->font_style.psz_fontname ); p_ssa_style->font_style.psz_fontname = strdup( psz_value ); } else if( !strcasecmp( "size", psz_name ) ) { if( ( *psz_value == '+' ) || ( *psz_value == '-' ) ) { int i_value = atoi( psz_value ); 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; else if( i_value < -5 ) p_ssa_style->font_style.i_font_size = - i_value; else if( i_value > 5 ) p_ssa_style->font_style.i_font_size = i_value; } else p_ssa_style->font_style.i_font_size = atoi( psz_value ); } else if( !strcasecmp( "italic", psz_name ) ) { if( !strcasecmp( "yes", psz_value )) p_ssa_style->font_style.i_style_flags |= STYLE_ITALIC; else p_ssa_style->font_style.i_style_flags &= ~STYLE_ITALIC; } else if( !strcasecmp( "weight", psz_name ) ) { if( !strcasecmp( "bold", psz_value )) p_ssa_style->font_style.i_style_flags |= STYLE_BOLD; else p_ssa_style->font_style.i_style_flags &= ~STYLE_BOLD; } else if( !strcasecmp( "underline", psz_name ) ) { if( !strcasecmp( "yes", psz_value )) p_ssa_style->font_style.i_style_flags |= STYLE_UNDERLINE; else p_ssa_style->font_style.i_style_flags &= ~STYLE_UNDERLINE; } else if( !strcasecmp( "color", psz_name ) ) { if( *psz_value == '#' ) { unsigned long col = strtol(psz_value+1, NULL, 16); p_ssa_style->font_style.i_font_color = (col & 0x00ffffff); p_ssa_style->font_style.i_font_alpha = (col >> 24) & 0xff; } } else if( !strcasecmp( "outline-color", psz_name ) ) { if( *psz_value == '#' ) { unsigned long col = strtol(psz_value+1, NULL, 16); p_ssa_style->font_style.i_outline_color = (col & 0x00ffffff); p_ssa_style->font_style.i_outline_alpha = (col >> 24) & 0xff; } } else if( !strcasecmp( "outline-level", psz_name ) ) { p_ssa_style->font_style.i_outline_width = atoi( psz_value ); } else if( !strcasecmp( "shadow-color", psz_name ) ) { if( *psz_value == '#' ) { unsigned long col = strtol(psz_value+1, NULL, 16); p_ssa_style->font_style.i_shadow_color = (col & 0x00ffffff); p_ssa_style->font_style.i_shadow_alpha = (col >> 24) & 0xff; } } else if( !strcasecmp( "shadow-level", psz_name ) )