2015-12-31 14:08:05 +01:00
using System ;
using System.Collections.Generic ;
using System.Drawing ;
using System.Globalization ;
2017-07-27 13:31:54 +02:00
using System.Linq ;
2015-12-31 14:08:05 +01:00
using System.Text ;
using System.Xml ;
namespace Nikse.SubtitleEdit.Core.SubtitleFormats
{
public class AdvancedSubStationAlpha : SubtitleFormat
{
public string Errors { get ; private set ; }
public static string DefaultStyle
{
get
{
string borderStyle = "1" ; // 1=normal, 3=opaque box
if ( Configuration . Settings . SubtitleSettings . SsaOpaqueBox )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
borderStyle = "3" ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
string boldStyle = "0" ; // 0=regular
if ( Configuration . Settings . SubtitleSettings . SsaFontBold )
2019-01-19 14:40:37 +01:00
{
2016-06-25 11:28:27 +02:00
boldStyle = "-1" ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
var ssa = Configuration . Settings . SubtitleSettings ;
return "Style: Default," + ssa . SsaFontName + "," +
2019-10-20 13:30:34 +02:00
ssa . SsaFontSize . ToString ( CultureInfo . InvariantCulture ) + "," +
2017-09-13 20:34:40 +02:00
GetSsaColorString ( Color . FromArgb ( ssa . SsaFontColorArgb ) ) + "," +
"&H0300FFFF,&H00000000,&H02000000," + boldStyle + ",0,0,0,100,100,0,0," + borderStyle + "," + ssa . SsaOutline . ToString ( CultureInfo . InvariantCulture ) + "," +
Configuration . Settings . SubtitleSettings . SsaShadow . ToString ( CultureInfo . InvariantCulture ) + ",2," + ssa . SsaMarginLeft + "," + ssa . SsaMarginRight + "," + ssa . SsaMarginTopBottom + ",1" ;
2015-12-31 14:08:05 +01:00
}
}
public static string DefaultHeader
{
get
{
SubtitleFormat format = new AdvancedSubStationAlpha ( ) ;
var sub = new Subtitle ( ) ;
string text = format . ToText ( sub , string . Empty ) ;
2017-11-26 17:35:00 +01:00
var lines = text . SplitToLines ( ) ;
2015-12-31 14:08:05 +01:00
format . LoadSubtitle ( sub , lines , string . Empty ) ;
return sub . Header ;
}
}
2017-07-27 13:31:54 +02:00
public override string Extension = > ".ass" ;
2015-12-31 14:08:05 +01:00
public const string NameOfFormat = "Advanced Sub Station Alpha" ;
2017-07-27 13:31:54 +02:00
public override string Name = > NameOfFormat ;
2015-12-31 14:08:05 +01:00
public override bool IsMine ( List < string > lines , string fileName )
{
var subtitle = new Subtitle ( ) ;
var sb = new StringBuilder ( ) ;
lines . ForEach ( line = > sb . AppendLine ( line ) ) ;
string all = sb . ToString ( ) ;
if ( ! string . IsNullOrEmpty ( fileName ) & & fileName . EndsWith ( ".ass" , StringComparison . OrdinalIgnoreCase ) & & ! all . Contains ( "[V4 Styles]" ) )
{
}
else if ( ! all . Contains ( "dialog:" , StringComparison . OrdinalIgnoreCase ) & & ! all . Contains ( "dialogue:" , StringComparison . OrdinalIgnoreCase ) )
{
return false ;
}
else if ( ! all . Contains ( "[V4+ Styles]" ) & & new SubStationAlpha ( ) . IsMine ( lines , fileName ) )
{
return false ;
}
LoadSubtitle ( subtitle , lines , fileName ) ;
Errors = null ;
if ( subtitle . Paragraphs . Count > _errorCount )
{
if ( ! string . IsNullOrEmpty ( subtitle . Header ) )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
subtitle . Header = subtitle . Header . Replace ( "[V4 Styles]" , "[V4+ Styles]" ) ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
return true ;
}
return false ;
}
2016-06-01 20:59:22 +02:00
public const string HeaderNoStyles = @ "[Script Info]
2015-12-31 14:08:05 +01:00
; This is an Advanced Sub Station Alpha v4 + script .
Title : { 0 }
ScriptType : v4 . 00 +
Collisions : Normal
PlayDepth : 0
[V4+ Styles]
Format : Name , Fontname , Fontsize , PrimaryColour , SecondaryColour , OutlineColour , BackColour , Bold , Italic , Underline , StrikeOut , ScaleX , ScaleY , Spacing , Angle , BorderStyle , Outline , Shadow , Alignment , MarginL , MarginR , MarginV , Encoding
2016-06-01 20:59:22 +02:00
{ 1 }
2015-12-31 14:08:05 +01:00
[Events]
2019-08-21 15:54:18 +02:00
Format : Layer , Start , End , Style , Name , MarginL , MarginR , MarginV , Effect , Text ";
2015-12-31 14:08:05 +01:00
2016-06-01 20:59:22 +02:00
public override string ToText ( Subtitle subtitle , string title )
{
bool fromTtml = false ;
string header = @ "[Script Info]
2015-12-31 14:08:05 +01:00
; This is an Advanced Sub Station Alpha v4 + script .
Title : { 0 }
ScriptType : v4 . 00 +
Collisions : Normal
PlayDepth : 0
[V4+ Styles]
Format : Name , Fontname , Fontsize , PrimaryColour , SecondaryColour , OutlineColour , BackColour , Bold , Italic , Underline , StrikeOut , ScaleX , ScaleY , Spacing , Angle , BorderStyle , Outline , Shadow , Alignment , MarginL , MarginR , MarginV , Encoding
2016-06-01 20:59:22 +02:00
" + DefaultStyle + @"
2015-12-31 14:08:05 +01:00
[Events]
2019-08-21 15:54:18 +02:00
Format : Layer , Start , End , Style , Name , MarginL , MarginR , MarginV , Effect , Text ";
2015-12-31 14:08:05 +01:00
const string timeCodeFormat = "{0}:{1:00}:{2:00}.{3:00}" ; // h:mm:ss.cc
const string paragraphWriteFormat = "Dialogue: {9},{0},{1},{3},{4},{5},{6},{7},{8},{2}" ;
const string commentWriteFormat = "Comment: {9},{0},{1},{3},{4},{5},{6},{7},{8},{2}" ;
var sb = new StringBuilder ( ) ;
bool isValidAssHeader = ! string . IsNullOrEmpty ( subtitle . Header ) & & subtitle . Header . Contains ( "[V4+ Styles]" ) ;
var styles = new List < string > ( ) ;
if ( isValidAssHeader )
{
sb . AppendLine ( subtitle . Header . Trim ( ) ) ;
2019-08-21 15:54:18 +02:00
sb . AppendLine ( "Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text" ) ;
2015-12-31 14:08:05 +01:00
styles = GetStylesFromHeader ( subtitle . Header ) ;
}
else if ( ! string . IsNullOrEmpty ( subtitle . Header ) & & subtitle . Header . Contains ( "[V4 Styles]" ) )
{
2016-06-01 20:59:22 +02:00
LoadStylesFromSubstationAlpha ( subtitle , title , header , HeaderNoStyles , sb ) ;
2015-12-31 14:08:05 +01:00
}
else if ( subtitle . Header ! = null & & subtitle . Header . Contains ( "http://www.w3.org/ns/ttml" ) )
{
2016-06-01 20:59:22 +02:00
LoadStylesFromTimedText10 ( subtitle , title , header , HeaderNoStyles , sb ) ;
fromTtml = true ;
isValidAssHeader = ! string . IsNullOrEmpty ( subtitle . Header ) & & subtitle . Header . Contains ( "[V4+ Styles]" ) ;
if ( isValidAssHeader )
{
styles = GetStylesFromHeader ( subtitle . Header ) ;
}
2015-12-31 14:08:05 +01:00
}
2017-07-27 13:31:54 +02:00
else if ( subtitle . Header ! = null & & subtitle . Header . Contains ( "http://www.w3.org/2006/10/ttaf1" ) )
{
LoadStylesFromTimedTextTimedDraft2006Oct ( subtitle , title , header , HeaderNoStyles , sb ) ;
fromTtml = true ;
isValidAssHeader = ! string . IsNullOrEmpty ( subtitle . Header ) & & subtitle . Header . Contains ( "[V4+ Styles]" ) ;
if ( isValidAssHeader )
{
styles = GetStylesFromHeader ( subtitle . Header ) ;
}
}
2015-12-31 14:08:05 +01:00
else
{
sb . AppendLine ( string . Format ( header , title ) ) ;
}
foreach ( Paragraph p in subtitle . Paragraphs )
{
string start = string . Format ( timeCodeFormat , p . StartTime . Hours , p . StartTime . Minutes , p . StartTime . Seconds , p . StartTime . Milliseconds / 10 ) ;
string end = string . Format ( timeCodeFormat , p . EndTime . Hours , p . EndTime . Minutes , p . EndTime . Seconds , p . EndTime . Milliseconds / 10 ) ;
string style = "Default" ;
if ( ! string . IsNullOrEmpty ( p . Extra ) & & isValidAssHeader & & styles . Contains ( p . Extra ) )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
style = p . Extra ;
2019-01-19 14:40:37 +01:00
}
2016-06-01 20:59:22 +02:00
if ( fromTtml & & ! string . IsNullOrEmpty ( p . Style ) & & isValidAssHeader & & styles . Contains ( p . Style ) )
2019-01-19 14:40:37 +01:00
{
2016-06-01 20:59:22 +02:00
style = p . Style ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
string actor = "" ;
if ( ! string . IsNullOrEmpty ( p . Actor ) )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
actor = p . Actor ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
string marginL = "0" ;
if ( ! string . IsNullOrEmpty ( p . MarginL ) & & Utilities . IsInteger ( p . MarginL ) )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
marginL = p . MarginL ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
string marginR = "0" ;
if ( ! string . IsNullOrEmpty ( p . MarginR ) & & Utilities . IsInteger ( p . MarginR ) )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
marginR = p . MarginR ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
string marginV = "0" ;
if ( ! string . IsNullOrEmpty ( p . MarginV ) & & Utilities . IsInteger ( p . MarginV ) )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
marginV = p . MarginV ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
string effect = "" ;
if ( ! string . IsNullOrEmpty ( p . Effect ) )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
effect = p . Effect ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
if ( p . IsComment )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
sb . AppendLine ( string . Format ( commentWriteFormat , start , end , FormatText ( p ) , style , actor , marginL , marginR , marginV , effect , p . Layer ) ) ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
sb . AppendLine ( string . Format ( paragraphWriteFormat , start , end , FormatText ( p ) , style , actor , marginL , marginR , marginV , effect , p . Layer ) ) ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
}
if ( ! string . IsNullOrEmpty ( subtitle . Footer ) & & ( subtitle . Footer . Contains ( "[Fonts]" + Environment . NewLine ) | | subtitle . Footer . Contains ( "[Graphics]" + Environment . NewLine ) ) )
{
sb . AppendLine ( ) ;
sb . AppendLine ( subtitle . Footer ) ;
}
2019-08-21 15:54:18 +02:00
return sb . ToString ( ) . Trim ( ) + Environment . NewLine ;
2015-12-31 14:08:05 +01:00
}
private static void LoadStylesFromSubstationAlpha ( Subtitle subtitle , string title , string header , string headerNoStyles , StringBuilder sb )
{
try
{
bool styleFound = false ;
var ttStyles = new StringBuilder ( ) ;
// Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
const string styleFormat = "Style: {0},{1},{2},{3},{4},{5},{6},{7},{8},{9},0,100,100,0,0,{10},{11},{12},{13},{14},{15},{16},1" ;
foreach ( string styleName in GetStylesFromHeader ( subtitle . Header ) )
{
try
{
var ssaStyle = GetSsaStyle ( styleName , subtitle . Header ) ;
2018-08-29 19:21:31 +02:00
2018-03-12 17:02:08 +01:00
string bold = "0" ;
if ( ssaStyle . Bold )
2019-01-19 14:40:37 +01:00
{
2018-03-12 17:02:08 +01:00
bold = "-1" ;
2019-01-19 14:40:37 +01:00
}
2018-03-12 17:02:08 +01:00
string italic = "0" ;
if ( ssaStyle . Italic )
2019-01-19 14:40:37 +01:00
{
2018-03-12 17:02:08 +01:00
italic = "-1" ;
2019-01-19 14:40:37 +01:00
}
2018-03-12 17:02:08 +01:00
string underline = "0" ;
if ( ssaStyle . Underline )
2019-01-19 14:40:37 +01:00
{
2018-03-12 17:02:08 +01:00
underline = "-1" ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
2018-03-12 17:02:08 +01:00
string newAlignment = "2" ;
switch ( ssaStyle . Alignment )
{
case "1" :
newAlignment = "1" ;
break ;
case "3" :
newAlignment = "3" ;
break ;
case "9" :
newAlignment = "4" ;
break ;
case "10" :
newAlignment = "5" ;
break ;
case "11" :
newAlignment = "6" ;
break ;
case "5" :
newAlignment = "7" ;
break ;
case "6" :
newAlignment = "8" ;
break ;
case "7" :
newAlignment = "9" ;
break ;
2015-12-31 14:08:05 +01:00
}
2018-03-12 17:02:08 +01:00
ttStyles . AppendLine ( string . Format ( styleFormat , ssaStyle . Name , ssaStyle . FontName , ssaStyle . FontSize , GetSsaColorString ( ssaStyle . Primary ) , GetSsaColorString ( ssaStyle . Secondary ) ,
2018-04-29 10:11:44 +02:00
GetSsaColorString ( ssaStyle . Outline ) , GetSsaColorString ( ssaStyle . Background ) , bold , italic , underline , ssaStyle . BorderStyle , ssaStyle . OutlineWidth . ToString ( CultureInfo . InvariantCulture ) , ssaStyle . ShadowWidth . ToString ( CultureInfo . InvariantCulture ) ,
2018-03-12 17:02:08 +01:00
newAlignment , ssaStyle . MarginLeft , ssaStyle . MarginRight , ssaStyle . MarginVertical ) ) ;
styleFound = true ;
2018-08-29 19:21:31 +02:00
2015-12-31 14:08:05 +01:00
}
catch
{
2017-07-27 13:31:54 +02:00
// ignored
2015-12-31 14:08:05 +01:00
}
}
if ( styleFound )
{
sb . AppendLine ( string . Format ( headerNoStyles , title , ttStyles ) ) ;
subtitle . Header = sb . ToString ( ) ;
}
else
{
sb . AppendLine ( string . Format ( header , title ) ) ;
}
}
catch
{
sb . AppendLine ( string . Format ( header , title ) ) ;
}
}
2016-06-01 20:59:22 +02:00
public static void LoadStylesFromTimedText10 ( Subtitle subtitle , string title , string header , string headerNoStyles , StringBuilder sb )
2015-12-31 14:08:05 +01:00
{
2016-04-17 13:08:26 +02:00
foreach ( Paragraph p in subtitle . Paragraphs )
{
p . Effect = null ;
}
2015-12-31 14:08:05 +01:00
try
{
2017-11-26 19:14:58 +01:00
var lines = subtitle . Header . SplitToLines ( ) ;
2015-12-31 14:08:05 +01:00
var tt = new TimedText10 ( ) ;
var sub = new Subtitle ( ) ;
tt . LoadSubtitle ( sub , lines , string . Empty ) ;
var xml = new XmlDocument ( ) ;
xml . LoadXml ( subtitle . Header ) ;
var nsmgr = new XmlNamespaceManager ( xml . NameTable ) ;
nsmgr . AddNamespace ( "ttml" , "http://www.w3.org/ns/ttml" ) ;
XmlNode head = xml . DocumentElement . SelectSingleNode ( "ttml:head" , nsmgr ) ;
2017-07-27 13:31:54 +02:00
int styleCount = 0 ;
2015-12-31 14:08:05 +01:00
var ttStyles = new StringBuilder ( ) ;
2017-07-27 13:31:54 +02:00
var styleNames = new List < string > ( ) ;
2015-12-31 14:08:05 +01:00
foreach ( XmlNode node in head . SelectNodes ( "//ttml:style" , nsmgr ) )
{
string name = null ;
if ( node . Attributes [ "xml:id" ] ! = null )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
name = node . Attributes [ "xml:id" ] . Value ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( node . Attributes [ "id" ] ! = null )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
name = node . Attributes [ "id" ] . Value ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
if ( name ! = null )
{
2017-07-27 13:31:54 +02:00
styleCount + + ;
string fontFamily = "Arial" ;
2019-03-13 17:50:50 +01:00
if ( node . Attributes [ "tts:fontFamily" ] ? . Value ! = null )
2019-01-19 14:40:37 +01:00
{
2017-07-27 13:31:54 +02:00
fontFamily = node . Attributes [ "tts:fontFamily" ] . Value ;
2019-03-13 17:50:50 +01:00
if ( fontFamily . Contains ( "," ) )
{
fontFamily = fontFamily . Split ( ',' ) [ 0 ] ;
}
2019-01-19 14:40:37 +01:00
}
2017-07-27 13:31:54 +02:00
string fontWeight = "normal" ;
if ( node . Attributes [ "tts:fontWeight" ] ! = null )
2019-01-19 14:40:37 +01:00
{
2017-07-27 13:31:54 +02:00
fontWeight = node . Attributes [ "tts:fontWeight" ] . Value ;
2019-01-19 14:40:37 +01:00
}
2017-07-27 13:31:54 +02:00
string fontStyle = "normal" ;
if ( node . Attributes [ "tts:fontStyle" ] ! = null )
2019-01-19 14:40:37 +01:00
{
2017-07-27 13:31:54 +02:00
fontStyle = node . Attributes [ "tts:fontStyle" ] . Value ;
2019-01-19 14:40:37 +01:00
}
2017-07-27 13:31:54 +02:00
string color = "#ffffff" ;
if ( node . Attributes [ "tts:color" ] ! = null )
2019-01-19 14:40:37 +01:00
{
2017-07-27 13:31:54 +02:00
color = node . Attributes [ "tts:color" ] . Value . Trim ( ) ;
2019-01-19 14:40:37 +01:00
}
2017-07-27 13:31:54 +02:00
Color c = Color . White ;
try
{
if ( color . StartsWith ( "rgb(" , StringComparison . Ordinal ) )
{
string [ ] arr = color . Remove ( 0 , 4 ) . TrimEnd ( ')' ) . Split ( new [ ] { ',' } , StringSplitOptions . RemoveEmptyEntries ) ;
c = Color . FromArgb ( int . Parse ( arr [ 0 ] ) , int . Parse ( arr [ 1 ] ) , int . Parse ( arr [ 2 ] ) ) ;
}
else
{
c = ColorTranslator . FromHtml ( color ) ;
}
}
catch
{
// ignored
}
string fontSize = "20" ;
if ( node . Attributes [ "tts:fontSize" ] ! = null )
2019-01-19 14:40:37 +01:00
{
2017-07-27 13:31:54 +02:00
fontSize = node . Attributes [ "tts:fontSize" ] . Value . Replace ( "px" , string . Empty ) . Replace ( "em" , string . Empty ) ;
2019-01-19 14:40:37 +01:00
}
2019-10-20 13:30:34 +02:00
if ( ! float . TryParse ( fontSize , NumberStyles . AllowDecimalPoint , CultureInfo . InvariantCulture , out var fSize ) )
2019-01-19 14:40:37 +01:00
{
2017-07-27 13:31:54 +02:00
fSize = 20 ;
2019-01-19 14:40:37 +01:00
}
2017-07-27 13:31:54 +02:00
string italic = "0" ;
if ( fontStyle = = "italic" )
2019-01-19 14:40:37 +01:00
{
2017-07-27 13:31:54 +02:00
italic = "-1" ;
2019-01-19 14:40:37 +01:00
}
2017-07-27 13:31:54 +02:00
string bold = "0" ;
if ( fontWeight = = "bold" )
2019-01-19 14:40:37 +01:00
{
2017-07-27 13:31:54 +02:00
bold = "-1" ;
2019-01-19 14:40:37 +01:00
}
2017-07-27 13:31:54 +02:00
const string styleFormat = "Style: {0},{1},{2},{3},&H0300FFFF,&H00000000,&H02000000,{4},{5},0,0,100,100,0,0,1,2,2,2,10,10,10,1" ;
ttStyles . AppendLine ( string . Format ( styleFormat , name , fontFamily , fSize , GetSsaColorString ( c ) , bold , italic ) ) ;
styleNames . Add ( name ) ;
}
}
if ( styleCount > 0 )
{
if ( ! styleNames . Contains ( "Default" ) & & ! styleNames . Contains ( "default" ) & & subtitle . Paragraphs . Any ( pa = > string . IsNullOrEmpty ( pa . Extra ) ) )
{
ttStyles = new StringBuilder ( DefaultStyle + Environment . NewLine + ttStyles ) ;
foreach ( var paragraph in subtitle . Paragraphs )
{
if ( string . IsNullOrEmpty ( paragraph . Extra ) )
2019-01-19 14:40:37 +01:00
{
2017-07-27 13:31:54 +02:00
paragraph . Extra = "Default" ;
2019-01-19 14:40:37 +01:00
}
2017-07-27 13:31:54 +02:00
}
}
sb . AppendLine ( string . Format ( headerNoStyles , title , ttStyles ) ) ;
subtitle . Header = sb . ToString ( ) ;
}
else
{
sb . AppendLine ( string . Format ( header , title ) ) ;
}
// Set correct style on paragraphs
foreach ( Paragraph p in subtitle . Paragraphs )
{
if ( p . Extra ! = null & & p . Extra . Contains ( '/' ) )
{
p . Extra = p . Extra . Split ( '/' ) [ 0 ] . Trim ( ) ;
}
}
}
catch
{
sb . AppendLine ( string . Format ( header , title ) ) ;
}
}
2017-09-05 16:46:37 +02:00
2017-07-27 13:31:54 +02:00
public static void LoadStylesFromTimedTextTimedDraft2006Oct ( Subtitle subtitle , string title , string header , string headerNoStyles , StringBuilder sb )
{
foreach ( Paragraph p in subtitle . Paragraphs )
{
p . Effect = null ;
}
try
{
2017-11-26 19:14:58 +01:00
var lines = subtitle . Header . SplitToLines ( ) ;
2017-07-27 13:31:54 +02:00
var sb2 = new StringBuilder ( ) ;
lines . ForEach ( line = > sb2 . AppendLine ( line ) ) ;
var xml = new XmlDocument { XmlResolver = null } ;
xml . LoadXml ( sb2 . ToString ( ) . Replace ( " & " , " & " ) . Replace ( "Q&A" , "Q&A" ) . RemoveControlCharactersButWhiteSpace ( ) . Trim ( ) ) ;
subtitle . Header = xml . OuterXml ;
var nsmgr = new XmlNamespaceManager ( xml . NameTable ) ;
nsmgr . AddNamespace ( "ttaf1" , xml . DocumentElement . NamespaceURI ) ;
int styleCount = 0 ;
var ttStyles = new StringBuilder ( ) ;
var styleNames = new List < string > ( ) ;
foreach ( XmlNode node in xml . DocumentElement . SelectNodes ( "//ttaf1:style" , nsmgr ) )
{
string name = null ;
if ( node . Attributes [ "xml:id" ] ! = null )
2019-01-19 14:40:37 +01:00
{
2017-07-27 13:31:54 +02:00
name = node . Attributes [ "xml:id" ] . Value ;
2019-01-19 14:40:37 +01:00
}
2017-07-27 13:31:54 +02:00
else if ( node . Attributes [ "id" ] ! = null )
2019-01-19 14:40:37 +01:00
{
2017-07-27 13:31:54 +02:00
name = node . Attributes [ "id" ] . Value ;
2019-01-19 14:40:37 +01:00
}
2017-07-27 13:31:54 +02:00
if ( name ! = null )
{
styleCount + + ;
2015-12-31 14:08:05 +01:00
string fontFamily = "Arial" ;
2019-03-13 17:50:50 +01:00
if ( node . Attributes [ "tts:fontFamily" ] ? . Value ! = null )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
fontFamily = node . Attributes [ "tts:fontFamily" ] . Value ;
2019-03-13 17:50:50 +01:00
if ( fontFamily . Contains ( "," ) )
{
fontFamily = fontFamily . Split ( ',' ) [ 0 ] ;
}
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
string fontWeight = "normal" ;
if ( node . Attributes [ "tts:fontWeight" ] ! = null )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
fontWeight = node . Attributes [ "tts:fontWeight" ] . Value ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
string fontStyle = "normal" ;
if ( node . Attributes [ "tts:fontStyle" ] ! = null )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
fontStyle = node . Attributes [ "tts:fontStyle" ] . Value ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
string color = "#ffffff" ;
if ( node . Attributes [ "tts:color" ] ! = null )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
color = node . Attributes [ "tts:color" ] . Value . Trim ( ) ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
Color c = Color . White ;
try
{
if ( color . StartsWith ( "rgb(" , StringComparison . Ordinal ) )
{
string [ ] arr = color . Remove ( 0 , 4 ) . TrimEnd ( ')' ) . Split ( new [ ] { ',' } , StringSplitOptions . RemoveEmptyEntries ) ;
c = Color . FromArgb ( int . Parse ( arr [ 0 ] ) , int . Parse ( arr [ 1 ] ) , int . Parse ( arr [ 2 ] ) ) ;
}
else
{
c = ColorTranslator . FromHtml ( color ) ;
}
}
catch
{
2017-07-27 13:31:54 +02:00
// ignored
2015-12-31 14:08:05 +01:00
}
string fontSize = "20" ;
if ( node . Attributes [ "tts:fontSize" ] ! = null )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
fontSize = node . Attributes [ "tts:fontSize" ] . Value . Replace ( "px" , string . Empty ) . Replace ( "em" , string . Empty ) ;
2019-01-19 14:40:37 +01:00
}
2019-10-20 13:30:34 +02:00
if ( ! float . TryParse ( fontSize , NumberStyles . AllowDecimalPoint , CultureInfo . InvariantCulture , out var fSize ) )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
fSize = 20 ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
string italic = "0" ;
if ( fontStyle = = "italic" )
2019-01-19 14:40:37 +01:00
{
2016-06-25 11:28:27 +02:00
italic = "-1" ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
string bold = "0" ;
if ( fontWeight = = "bold" )
2019-01-19 14:40:37 +01:00
{
2016-06-25 11:28:27 +02:00
bold = "-1" ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
const string styleFormat = "Style: {0},{1},{2},{3},&H0300FFFF,&H00000000,&H02000000,{4},{5},0,0,100,100,0,0,1,2,2,2,10,10,10,1" ;
ttStyles . AppendLine ( string . Format ( styleFormat , name , fontFamily , fSize , GetSsaColorString ( c ) , bold , italic ) ) ;
2017-07-27 13:31:54 +02:00
styleNames . Add ( name ) ;
2015-12-31 14:08:05 +01:00
}
}
2017-07-27 13:31:54 +02:00
if ( styleCount > 0 )
2015-12-31 14:08:05 +01:00
{
2017-07-27 13:31:54 +02:00
if ( ! styleNames . Contains ( "Default" ) & & ! styleNames . Contains ( "default" ) & & subtitle . Paragraphs . Any ( pa = > string . IsNullOrEmpty ( pa . Extra ) ) )
{
ttStyles = new StringBuilder ( DefaultStyle + Environment . NewLine + ttStyles ) ;
foreach ( var paragraph in subtitle . Paragraphs )
{
if ( string . IsNullOrEmpty ( paragraph . Extra ) )
2019-01-19 14:40:37 +01:00
{
2017-07-27 13:31:54 +02:00
paragraph . Extra = "Default" ;
2019-01-19 14:40:37 +01:00
}
2017-07-27 13:31:54 +02:00
}
}
2015-12-31 14:08:05 +01:00
sb . AppendLine ( string . Format ( headerNoStyles , title , ttStyles ) ) ;
subtitle . Header = sb . ToString ( ) ;
}
else
{
sb . AppendLine ( string . Format ( header , title ) ) ;
}
// Set correct style on paragraphs
foreach ( Paragraph p in subtitle . Paragraphs )
{
if ( p . Extra ! = null & & p . Extra . Contains ( '/' ) )
{
p . Extra = p . Extra . Split ( '/' ) [ 0 ] . Trim ( ) ;
}
}
}
catch
{
sb . AppendLine ( string . Format ( header , title ) ) ;
}
}
public static List < string > GetStylesFromHeader ( string headerLines )
{
var list = new List < string > ( ) ;
if ( headerLines = = null )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
headerLines = DefaultStyle ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
2016-06-01 20:59:22 +02:00
if ( headerLines . Contains ( "http://www.w3.org/ns/ttml" ) )
{
var subtitle = new Subtitle { Header = headerLines } ;
LoadStylesFromTimedText10 ( subtitle , string . Empty , headerLines , HeaderNoStyles , new StringBuilder ( ) ) ;
headerLines = subtitle . Header ;
}
2015-12-31 14:08:05 +01:00
foreach ( string line in headerLines . SplitToLines ( ) )
{
if ( line . StartsWith ( "style:" , StringComparison . OrdinalIgnoreCase ) )
{
int end = line . IndexOf ( ',' ) ;
if ( end > 0 )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
list . Add ( line . Substring ( 6 , end - 6 ) . Trim ( ) ) ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
}
}
return list ;
}
public static string FormatText ( Paragraph p )
{
string text = p . Text . Replace ( Environment . NewLine , "\\N" ) ;
2017-09-05 18:07:05 +02:00
if ( ! text . Contains ( '<' ) )
2019-01-19 14:40:37 +01:00
{
2017-09-05 18:07:05 +02:00
return text ;
2019-01-19 14:40:37 +01:00
}
2017-09-05 18:07:05 +02:00
2015-12-31 14:08:05 +01:00
text = text . Replace ( "<i>" , @"{\i1}" ) ;
text = text . Replace ( "</i>" , @"{\i0}" ) ;
text = text . Replace ( "</i>" , @"{\i}" ) ;
text = text . Replace ( "<u>" , @"{\u1}" ) ;
text = text . Replace ( "</u>" , @"{\u0}" ) ;
text = text . Replace ( "</u>" , @"{\u}" ) ;
text = text . Replace ( "<b>" , @"{\b1}" ) ;
text = text . Replace ( "</b>" , @"{\b0}" ) ;
text = text . Replace ( "</b>" , @"{\b}" ) ;
int count = 0 ;
while ( text . Contains ( "<font " ) & & count < 10 )
{
2016-08-10 04:40:15 +02:00
int start = text . IndexOf ( "<font " , StringComparison . Ordinal ) ;
2015-12-31 14:08:05 +01:00
int end = text . IndexOf ( '>' , start ) ;
if ( end > 0 )
{
string fontTag = text . Substring ( start + 5 , end - ( start + 4 ) ) ;
text = text . Remove ( start , end - start + 1 ) ;
int indexOfEndFont = text . IndexOf ( "</font>" , start , StringComparison . Ordinal ) ;
if ( indexOfEndFont > 0 )
{
text = text . Remove ( indexOfEndFont , 7 ) ;
2017-02-27 19:22:02 +01:00
if ( indexOfEndFont < text . Length )
2016-01-28 19:04:28 +01:00
{
if ( fontTag . Contains ( " size=" ) )
{
text = text . Insert ( indexOfEndFont , "{\\fs}" ) ;
}
if ( fontTag . Contains ( " face=" ) )
{
text = text . Insert ( indexOfEndFont , "{\\fn}" ) ;
}
2017-02-27 19:22:02 +01:00
if ( fontTag . Contains ( " color=" ) )
{
text = text . Insert ( indexOfEndFont , "{\\c}" ) ;
}
2016-01-28 19:04:28 +01:00
}
2015-12-31 14:08:05 +01:00
}
fontTag = FormatTag ( ref text , start , fontTag , "face=\"" , "fn" , "}" ) ;
fontTag = FormatTag ( ref text , start , fontTag , "face='" , "fn" , "}" ) ;
fontTag = FormatTag ( ref text , start , fontTag , "face=" , "fn" , "}" ) ;
fontTag = FormatTag ( ref text , start , fontTag , "size=\"" , "fs" , "}" ) ;
fontTag = FormatTag ( ref text , start , fontTag , "size='" , "fs" , "}" ) ;
fontTag = FormatTag ( ref text , start , fontTag , "size=" , "fs" , "}" ) ;
fontTag = FormatTag ( ref text , start , fontTag , "color=\"" , "c&H" , "&}" ) ;
fontTag = FormatTag ( ref text , start , fontTag , "color='" , "c&H" , "&}" ) ;
FormatTag ( ref text , start , fontTag , "color=" , "c&H" , "&}" ) ;
}
count + + ;
}
2016-01-28 19:04:28 +01:00
text = text . Replace ( "{\\c}" , "@___@@" ) . Replace ( "}{" , string . Empty ) . Replace ( "@___@@" , "{\\c}" ) . Replace ( "{\\c}{\\c&" , "{\\c&" ) ;
while ( text . EndsWith ( "{\\c}" , StringComparison . Ordinal ) )
{
text = text . Remove ( text . Length - 4 ) ;
}
while ( text . Contains ( "\\fs\\fs" , StringComparison . Ordinal ) )
{
text = text . Replace ( "\\fs\\fs" , "\\fs" ) ;
}
while ( text . Contains ( "\\fn\\fn" , StringComparison . Ordinal ) )
{
text = text . Replace ( "\\fn\\fn" , "\\fn" ) ;
}
while ( text . Contains ( "\\c\\c&H" , StringComparison . Ordinal ) )
{
text = text . Replace ( "\\c\\c&H" , "\\c&H" ) ;
2016-02-08 20:38:51 +01:00
}
2016-01-28 19:04:28 +01:00
return text ;
2015-12-31 14:08:05 +01:00
}
private static string FormatTag ( ref string text , int start , string fontTag , string tag , string ssaTagName , string endSsaTag )
{
if ( fontTag . Contains ( tag ) )
{
int fontStart = fontTag . IndexOf ( tag , StringComparison . Ordinal ) ;
2017-07-04 16:57:31 +02:00
int fontEnd = fontTag . IndexOfAny ( new [ ] { '"' , '\'' } , fontStart + tag . Length ) ;
if ( fontEnd < 0 )
2019-01-19 14:40:37 +01:00
{
2017-07-04 16:57:31 +02:00
fontEnd = fontTag . IndexOfAny ( new [ ] { ' ' , '>' } , fontStart + tag . Length ) ;
2019-01-19 14:40:37 +01:00
}
2017-07-04 16:57:31 +02:00
2015-12-31 14:08:05 +01:00
if ( fontEnd > 0 )
{
string subTag = fontTag . Substring ( fontStart + tag . Length , fontEnd - ( fontStart + tag . Length ) ) ;
if ( tag . Contains ( "color" ) )
{
2017-03-05 20:03:24 +01:00
Color c ;
try
{
c = ColorTranslator . FromHtml ( subTag ) ;
}
catch
{
c = Color . White ;
2017-03-06 19:16:50 +01:00
}
2017-03-05 20:16:58 +01:00
subTag = ( c . B . ToString ( "X2" ) + c . G . ToString ( "X2" ) + c . R . ToString ( "X2" ) ) . ToLowerInvariant ( ) ; // use bbggrr
2015-12-31 14:08:05 +01:00
}
fontTag = fontTag . Remove ( fontStart , fontEnd - fontStart + 1 ) ;
if ( start < text . Length )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
text = text . Insert ( start , @"{\" + ssaTagName + subTag + endSsaTag ) ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
}
}
return fontTag ;
}
2019-01-26 12:11:57 +01:00
public static string GetFormattedText ( string input )
2015-12-31 14:08:05 +01:00
{
2019-01-26 12:11:57 +01:00
var text = input . Replace ( "\\N" , Environment . NewLine ) . Replace ( "\\n" , Environment . NewLine ) ;
2015-12-31 14:08:05 +01:00
2017-09-05 16:46:37 +02:00
var tooComplex = ContainsUnsupportedTags ( text ) ;
2015-12-31 14:08:05 +01:00
2017-09-05 16:46:37 +02:00
if ( ! tooComplex )
{
for ( int i = 0 ; i < 10 ; i + + ) // just look ten times...
2015-12-31 14:08:05 +01:00
{
2017-09-05 16:46:37 +02:00
bool italic ;
if ( text . Contains ( @"{\fn" ) )
2015-12-31 14:08:05 +01:00
{
2017-09-05 16:46:37 +02:00
int start = text . IndexOf ( @"{\fn" , StringComparison . Ordinal ) ;
int end = text . IndexOf ( '}' , start ) ;
if ( end > 0 & & ! text . Substring ( start ) . StartsWith ( "{\\fn}" , StringComparison . Ordinal ) )
2015-12-31 14:08:05 +01:00
{
2017-09-05 16:46:37 +02:00
string fontName = text . Substring ( start + 4 , end - ( start + 4 ) ) ;
string extraTags = string . Empty ;
2019-01-26 12:11:57 +01:00
CheckAndAddSubTags ( ref fontName , ref extraTags , out var unknownTags , out italic ) ;
2015-12-31 14:08:05 +01:00
text = text . Remove ( start , end - start + 1 ) ;
if ( italic )
2019-01-19 14:40:37 +01:00
{
2017-09-05 16:46:37 +02:00
text = text . Insert ( start , "<font face=\"" + fontName + "\"" + extraTags + ">" + unknownTags + "<i>" ) ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else
2019-01-19 14:40:37 +01:00
{
2017-09-05 16:46:37 +02:00
text = text . Insert ( start , "<font face=\"" + fontName + "\"" + extraTags + ">" + unknownTags ) ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
2017-09-05 16:46:37 +02:00
int indexOfEndTag = text . IndexOf ( "{\\fn}" , start , StringComparison . Ordinal ) ;
2015-12-31 14:08:05 +01:00
if ( indexOfEndTag > 0 )
2016-01-28 19:04:28 +01:00
{
2017-09-05 16:46:37 +02:00
text = text . Remove ( indexOfEndTag , "{\\fn}" . Length ) . Insert ( indexOfEndTag , "</font>" ) ;
2016-01-28 19:04:28 +01:00
}
2015-12-31 14:08:05 +01:00
else
2016-01-28 19:04:28 +01:00
{
2017-09-05 16:46:37 +02:00
int indexOfNextTag1 = text . IndexOf ( "{\\fn" , start , StringComparison . Ordinal ) ;
2016-01-28 19:04:28 +01:00
int indexOfNextTag2 = text . IndexOf ( "{\\c}" , start , StringComparison . Ordinal ) ;
if ( indexOfNextTag1 > 0 )
{
text = text . Insert ( indexOfNextTag1 , "</font>" ) ;
}
else if ( indexOfNextTag2 > 0 & & text . IndexOf ( "{\\" , start , StringComparison . Ordinal ) > = indexOfNextTag2 )
{
text = text . Insert ( indexOfNextTag2 , "</font>" ) ;
}
else
{
text + = "</font>" ;
}
}
2015-12-31 14:08:05 +01:00
}
}
2017-09-05 16:46:37 +02:00
if ( text . Contains ( @"{\fs" ) )
2015-12-31 14:08:05 +01:00
{
2017-09-05 16:46:37 +02:00
int start = text . IndexOf ( @"{\fs" , StringComparison . Ordinal ) ;
int end = text . IndexOf ( '}' , start ) ;
if ( end > 0 & & ! text . Substring ( start ) . StartsWith ( "{\\fs}" , StringComparison . Ordinal ) )
{
string fontSize = text . Substring ( start + 4 , end - ( start + 4 ) ) ;
string extraTags = string . Empty ;
2019-01-26 12:11:57 +01:00
CheckAndAddSubTags ( ref fontSize , ref extraTags , out var unknownTags , out italic ) ;
2019-10-20 13:30:34 +02:00
if ( float . TryParse ( fontSize , NumberStyles . AllowDecimalPoint , CultureInfo . InvariantCulture , out _ ) )
2017-09-05 16:46:37 +02:00
{
text = text . Remove ( start , end - start + 1 ) ;
if ( italic )
2019-01-19 14:40:37 +01:00
{
2017-09-05 16:46:37 +02:00
text = text . Insert ( start , "<font size=\"" + fontSize + "\"" + extraTags + ">" + unknownTags + "<i>" ) ;
2019-01-19 14:40:37 +01:00
}
2017-09-05 16:46:37 +02:00
else
2019-01-19 14:40:37 +01:00
{
2017-09-05 16:46:37 +02:00
text = text . Insert ( start , "<font size=\"" + fontSize + "\"" + extraTags + ">" + unknownTags ) ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
2017-09-05 16:46:37 +02:00
int indexOfEndTag = text . IndexOf ( "{\\fs}" , start , StringComparison . Ordinal ) ;
if ( indexOfEndTag > 0 )
{
text = text . Remove ( indexOfEndTag , "{\\fs}" . Length ) . Insert ( indexOfEndTag , "</font>" ) ;
}
else
{
int indexOfNextTag1 = text . IndexOf ( "{\\fs" , start , StringComparison . Ordinal ) ;
int indexOfNextTag2 = text . IndexOf ( "{\\c}" , start , StringComparison . Ordinal ) ;
if ( indexOfNextTag1 > 0 )
{
text = text . Insert ( indexOfNextTag1 , "</font>" ) ;
}
else if ( indexOfNextTag2 > 0 & & text . IndexOf ( "{\\" , start , StringComparison . Ordinal ) > = indexOfNextTag2 )
{
text = text . Insert ( indexOfNextTag2 , "</font>" ) ;
}
else
{
text + = "</font>" ;
}
}
}
}
}
2015-12-31 14:08:05 +01:00
2017-09-05 16:46:37 +02:00
if ( text . Contains ( @"{\c" ) )
{
int start = text . IndexOf ( @"{\c" , StringComparison . Ordinal ) ;
int end = text . IndexOf ( '}' , start ) ;
if ( end > 0 & & ! text . Substring ( start ) . StartsWith ( "{\\c}" , StringComparison . Ordinal ) & & ! text . Substring ( start ) . StartsWith ( "{\\clip" , StringComparison . Ordinal ) )
{
string color = text . Substring ( start + 4 , end - ( start + 4 ) ) ;
string extraTags = string . Empty ;
2019-01-26 12:11:57 +01:00
CheckAndAddSubTags ( ref color , ref extraTags , out var unknownTags , out italic ) ;
2015-12-31 14:08:05 +01:00
2017-12-10 22:18:13 +01:00
color = color . RemoveChar ( '&' ) . TrimStart ( 'H' ) ;
2017-09-05 16:46:37 +02:00
color = color . PadLeft ( 6 , '0' ) ;
// switch to rrggbb from bbggrr
color = "#" + color . Remove ( color . Length - 6 ) + color . Substring ( color . Length - 2 , 2 ) + color . Substring ( color . Length - 4 , 2 ) + color . Substring ( color . Length - 6 , 2 ) ;
2019-01-21 09:53:15 +01:00
color = color . ToLowerInvariant ( ) ;
2017-09-05 16:46:37 +02:00
text = text . Remove ( start , end - start + 1 ) ;
if ( italic )
2019-01-19 14:40:37 +01:00
{
2017-09-05 16:46:37 +02:00
text = text . Insert ( start , "<font color=\"" + color + "\"" + extraTags + ">" + unknownTags + "<i>" ) ;
2019-01-19 14:40:37 +01:00
}
2017-09-05 16:46:37 +02:00
else
2019-01-19 14:40:37 +01:00
{
2017-09-05 16:46:37 +02:00
text = text . Insert ( start , "<font color=\"" + color + "\"" + extraTags + ">" + unknownTags ) ;
2019-01-19 14:40:37 +01:00
}
2017-09-05 16:46:37 +02:00
int indexOfEndTag = text . IndexOf ( "{\\c}" , start , StringComparison . Ordinal ) ;
int indexOfNextColorTag = text . IndexOf ( "{\\c&" , start , StringComparison . Ordinal ) ;
if ( indexOfNextColorTag > 0 & & ( indexOfNextColorTag < indexOfEndTag | | indexOfEndTag = = - 1 ) )
2019-01-19 14:40:37 +01:00
{
2017-09-05 16:46:37 +02:00
text = text . Insert ( indexOfNextColorTag , "</font>" ) ;
2019-01-19 14:40:37 +01:00
}
2017-09-05 16:46:37 +02:00
else if ( indexOfEndTag > 0 )
2019-01-19 14:40:37 +01:00
{
2017-09-05 16:46:37 +02:00
text = text . Remove ( indexOfEndTag , "{\\c}" . Length ) . Insert ( indexOfEndTag , "</font>" ) ;
2019-01-19 14:40:37 +01:00
}
2017-09-05 16:46:37 +02:00
else
2019-01-19 14:40:37 +01:00
{
2017-09-05 16:46:37 +02:00
text + = "</font>" ;
2019-01-19 14:40:37 +01:00
}
2017-09-05 16:46:37 +02:00
}
2015-12-31 14:08:05 +01:00
}
2017-09-05 16:46:37 +02:00
if ( text . Contains ( @"{\1c" ) ) // "1" specifices primary color
2015-12-31 14:08:05 +01:00
{
2017-09-05 16:46:37 +02:00
int start = text . IndexOf ( @"{\1c" , StringComparison . Ordinal ) ;
int end = text . IndexOf ( '}' , start ) ;
if ( end > 0 & & ! text . Substring ( start ) . StartsWith ( "{\\1c}" , StringComparison . Ordinal ) )
{
string color = text . Substring ( start + 5 , end - ( start + 5 ) ) ;
string extraTags = string . Empty ;
2019-01-26 12:11:57 +01:00
CheckAndAddSubTags ( ref color , ref extraTags , out var unknownTags , out italic ) ;
2015-12-31 14:08:05 +01:00
2017-12-10 22:18:13 +01:00
color = color . RemoveChar ( '&' ) . TrimStart ( 'H' ) ;
2017-09-05 16:46:37 +02:00
color = color . PadLeft ( 6 , '0' ) ;
2015-12-31 14:08:05 +01:00
2017-09-05 16:46:37 +02:00
// switch to rrggbb from bbggrr
color = "#" + color . Remove ( color . Length - 6 ) + color . Substring ( color . Length - 2 , 2 ) + color . Substring ( color . Length - 4 , 2 ) + color . Substring ( color . Length - 6 , 2 ) ;
2019-01-21 09:53:15 +01:00
color = color . ToLowerInvariant ( ) ;
2015-12-31 14:08:05 +01:00
2017-09-05 16:46:37 +02:00
text = text . Remove ( start , end - start + 1 ) ;
if ( italic )
2019-01-19 14:40:37 +01:00
{
2017-09-05 16:46:37 +02:00
text = text . Insert ( start , "<font color=\"" + color + "\"" + extraTags + ">" + unknownTags + "<i>" ) ;
2019-01-19 14:40:37 +01:00
}
2017-09-05 16:46:37 +02:00
else
2019-01-19 14:40:37 +01:00
{
2017-09-05 16:46:37 +02:00
text = text . Insert ( start , "<font color=\"" + color + "\"" + extraTags + ">" + unknownTags ) ;
2019-01-19 14:40:37 +01:00
}
2017-09-05 16:46:37 +02:00
text + = "</font>" ;
}
2015-12-31 14:08:05 +01:00
}
}
}
text = text . Replace ( @"{\i1}" , "<i>" ) ;
text = text . Replace ( @"{\i0}" , "</i>" ) ;
text = text . Replace ( @"{\i}" , "</i>" ) ;
if ( Utilities . CountTagInText ( text , "<i>" ) > Utilities . CountTagInText ( text , "</i>" ) )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
text + = "</i>" ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
text = text . Replace ( @"{\u1}" , "<u>" ) ;
text = text . Replace ( @"{\u0}" , "</u>" ) ;
text = text . Replace ( @"{\u}" , "</u>" ) ;
if ( Utilities . CountTagInText ( text , "<u>" ) > Utilities . CountTagInText ( text , "</u>" ) )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
text + = "</u>" ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
text = text . Replace ( @"{\b1}" , "<b>" ) ;
text = text . Replace ( @"{\b0}" , "</b>" ) ;
text = text . Replace ( @"{\b}" , "</b>" ) ;
if ( Utilities . CountTagInText ( text , "<b>" ) > Utilities . CountTagInText ( text , "</b>" ) )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
text + = "</b>" ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
return text ;
}
2017-09-05 16:46:37 +02:00
private static bool ContainsUnsupportedTags ( string text )
{
if ( string . IsNullOrEmpty ( text ) | | ! text . Contains ( "{\\" , StringComparison . OrdinalIgnoreCase ) )
2019-01-19 14:40:37 +01:00
{
2017-09-05 16:46:37 +02:00
return false ;
2019-01-19 14:40:37 +01:00
}
2017-09-05 16:46:37 +02:00
var unsupportedTags = new List < string >
{
"\\alpha" ,
"\\be0" ,
"\\be1" ,
"\\bord" ,
"\\blur" ,
"\\clip" ,
"\\fad" ,
"\\fa" ,
"\\fade" ,
"\\fscx" ,
"\\fscy" ,
"\\fr" ,
"\\iclip" ,
"\\k" ,
"\\K" ,
"\\kf" ,
"\\ko" ,
"\\move" ,
"\\org" ,
"\\p" ,
"\\pos" ,
"\\s0" ,
"\\s1" ,
"\\t(" ,
"\\xbord" ,
"\\ybord" ,
"\\xshad" ,
"\\yshad"
} ;
foreach ( var unsupportedTag in unsupportedTags )
{
if ( text . Contains ( unsupportedTag , StringComparison . Ordinal ) )
2019-01-19 14:40:37 +01:00
{
2017-09-05 16:46:37 +02:00
return true ;
2019-01-19 14:40:37 +01:00
}
2017-09-05 16:46:37 +02:00
}
return false ;
}
2016-07-16 19:44:20 +02:00
private static void CheckAndAddSubTags ( ref string tagName , ref string extraTags , out string unknownTags , out bool italic )
2015-12-31 14:08:05 +01:00
{
italic = false ;
2016-07-16 19:44:20 +02:00
unknownTags = string . Empty ;
2015-12-31 14:08:05 +01:00
int indexOfSPlit = tagName . IndexOf ( '\\' ) ;
if ( indexOfSPlit > 0 )
{
string rest = tagName . Substring ( indexOfSPlit ) . TrimStart ( '\\' ) ;
tagName = tagName . Remove ( indexOfSPlit ) ;
for ( int i = 0 ; i < 10 ; i + + )
{
if ( rest . StartsWith ( "fs" , StringComparison . Ordinal ) & & rest . Length > 2 )
{
indexOfSPlit = rest . IndexOf ( '\\' ) ;
string fontSize = rest ;
if ( indexOfSPlit > 0 )
{
fontSize = rest . Substring ( 0 , indexOfSPlit ) ;
rest = rest . Substring ( indexOfSPlit ) . TrimStart ( '\\' ) ;
}
else
{
rest = string . Empty ;
}
extraTags + = " size=\"" + fontSize . Substring ( 2 ) + "\"" ;
}
else if ( rest . StartsWith ( "fn" , StringComparison . Ordinal ) & & rest . Length > 2 )
{
indexOfSPlit = rest . IndexOf ( '\\' ) ;
string fontName = rest ;
if ( indexOfSPlit > 0 )
{
fontName = rest . Substring ( 0 , indexOfSPlit ) ;
rest = rest . Substring ( indexOfSPlit ) . TrimStart ( '\\' ) ;
}
else
{
rest = string . Empty ;
}
extraTags + = " face=\"" + fontName . Substring ( 2 ) + "\"" ;
}
else if ( rest . StartsWith ( 'c' ) & & rest . Length > 2 )
{
indexOfSPlit = rest . IndexOf ( '\\' ) ;
string fontColor = rest ;
if ( indexOfSPlit > 0 )
{
fontColor = rest . Substring ( 0 , indexOfSPlit ) ;
rest = rest . Substring ( indexOfSPlit ) . TrimStart ( '\\' ) ;
}
else
{
rest = string . Empty ;
}
string color = fontColor . Substring ( 2 ) ;
2017-12-10 22:18:13 +01:00
color = color . RemoveChar ( '&' ) . TrimStart ( 'H' ) ;
2015-12-31 14:08:05 +01:00
color = color . PadLeft ( 6 , '0' ) ;
// switch to rrggbb from bbggrr
color = "#" + color . Remove ( color . Length - 6 ) + color . Substring ( color . Length - 2 , 2 ) + color . Substring ( color . Length - 4 , 2 ) + color . Substring ( color . Length - 6 , 2 ) ;
2019-01-21 09:53:15 +01:00
color = color . ToLowerInvariant ( ) ;
2015-12-31 14:08:05 +01:00
extraTags + = " color=\"" + color + "\"" ;
}
else if ( rest . StartsWith ( "i1" , StringComparison . Ordinal ) & & rest . Length > 1 )
{
indexOfSPlit = rest . IndexOf ( '\\' ) ;
italic = true ;
if ( indexOfSPlit > 0 )
{
rest = rest . Substring ( indexOfSPlit ) . TrimStart ( '\\' ) ;
}
else
{
rest = string . Empty ;
}
}
else if ( rest . Length > 0 & & rest . Contains ( "\\" ) )
{
indexOfSPlit = rest . IndexOf ( '\\' ) ;
2016-07-16 19:44:20 +02:00
var unknowntag = rest . Substring ( 0 , indexOfSPlit ) ;
unknownTags + = "\\" + unknowntag ;
2015-12-31 14:08:05 +01:00
rest = rest . Substring ( indexOfSPlit ) . TrimStart ( '\\' ) ;
}
2016-07-16 19:44:20 +02:00
else if ( ! string . IsNullOrEmpty ( rest ) )
{
unknownTags + = "\\" + rest ;
rest = string . Empty ;
}
2015-12-31 14:08:05 +01:00
}
}
2016-07-16 19:44:20 +02:00
if ( ! string . IsNullOrEmpty ( unknownTags ) )
2019-01-19 14:40:37 +01:00
{
2016-07-16 19:44:20 +02:00
unknownTags = "{" + unknownTags + "}" ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
}
public override void LoadSubtitle ( Subtitle subtitle , List < string > lines , string fileName )
{
_errorCount = 0 ;
Errors = null ;
bool eventsStarted = false ;
bool fontsStarted = false ;
bool graphicsStarted = false ;
subtitle . Paragraphs . Clear ( ) ;
// Layer, Start, End, Style, Actor, MarginL, MarginR, MarginV, Effect, Text
int indexLayer = 0 ;
int indexStart = 1 ;
int indexEnd = 2 ;
int indexStyle = 3 ;
2019-08-21 15:54:18 +02:00
int indexActor = - 1 ; // convert "Actor" to "Nam" (if no "Name")
int indexName = 4 ;
2015-12-31 14:08:05 +01:00
int indexMarginL = 5 ;
int indexMarginR = 6 ;
int indexMarginV = 7 ;
int indexEffect = 8 ;
int indexText = 9 ;
var errors = new StringBuilder ( ) ;
int lineNumber = 0 ;
var header = new StringBuilder ( ) ;
var footer = new StringBuilder ( ) ;
foreach ( string line in lines )
{
lineNumber + + ;
2017-09-13 20:34:40 +02:00
if ( ! eventsStarted & & ! fontsStarted & & ! graphicsStarted & &
! line . Trim ( ) . Equals ( "[fonts]" , StringComparison . InvariantCultureIgnoreCase ) & &
! line . Trim ( ) . Equals ( "[graphics]" , StringComparison . InvariantCultureIgnoreCase ) )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
header . AppendLine ( line ) ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
if ( string . IsNullOrWhiteSpace ( line ) | | line . TrimStart ( ) . StartsWith ( ';' ) )
{
// skip empty and comment lines
}
else if ( line . TrimStart ( ) . StartsWith ( "dialog:" , StringComparison . OrdinalIgnoreCase ) | | line . TrimStart ( ) . StartsWith ( "dialogue:" , StringComparison . OrdinalIgnoreCase ) ) // fix faulty font tags...
{
eventsStarted = true ;
fontsStarted = false ;
graphicsStarted = false ;
}
if ( line . Trim ( ) . Equals ( "[events]" , StringComparison . OrdinalIgnoreCase ) )
{
2017-09-13 20:34:40 +02:00
if ( header . ToString ( ) . IndexOf ( Environment . NewLine + "[events]" , StringComparison . OrdinalIgnoreCase ) < 0 )
{
var h = header . ToString ( ) . TrimEnd ( ) ;
header . Clear ( ) ;
header . AppendLine ( h ) ;
header . AppendLine ( ) ;
header . AppendLine ( "[Events]" ) ;
}
2015-12-31 14:08:05 +01:00
eventsStarted = true ;
fontsStarted = false ;
graphicsStarted = false ;
}
else if ( line . Trim ( ) . Equals ( "[fonts]" , StringComparison . OrdinalIgnoreCase ) )
{
eventsStarted = false ;
fontsStarted = true ;
graphicsStarted = false ;
footer . AppendLine ( ) ;
footer . AppendLine ( "[Fonts]" ) ;
}
else if ( line . Trim ( ) . Equals ( "[graphics]" , StringComparison . OrdinalIgnoreCase ) )
{
eventsStarted = false ;
fontsStarted = false ;
graphicsStarted = true ;
footer . AppendLine ( ) ;
footer . AppendLine ( "[Graphics]" ) ;
}
else if ( fontsStarted )
{
footer . AppendLine ( line ) ;
}
else if ( graphicsStarted )
{
footer . AppendLine ( line ) ;
}
else if ( eventsStarted )
{
2019-01-21 09:53:15 +01:00
string s = line . Trim ( ) . ToLowerInvariant ( ) ;
2015-12-31 14:08:05 +01:00
if ( line . Length > 10 & & s . StartsWith ( "format:" , StringComparison . Ordinal ) )
{
2017-07-23 10:54:53 +02:00
indexLayer = - 1 ;
indexStart = - 1 ;
indexEnd = - 1 ;
indexStyle = - 1 ;
indexActor = - 1 ;
2017-09-05 16:46:37 +02:00
indexName = - 1 ;
2017-07-23 10:54:53 +02:00
indexMarginL = - 1 ;
indexMarginR = - 1 ;
indexMarginV = - 1 ;
indexEffect = - 1 ;
indexText = - 1 ;
2015-12-31 14:08:05 +01:00
var format = s . Substring ( 8 ) . Split ( ',' ) ;
for ( int i = 0 ; i < format . Length ; i + + )
{
var formatTrimmed = format [ i ] . Trim ( ) ;
if ( formatTrimmed . Equals ( "start" , StringComparison . Ordinal ) )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
indexStart = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( formatTrimmed . Equals ( "end" , StringComparison . Ordinal ) )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
indexEnd = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( formatTrimmed . Equals ( "text" , StringComparison . Ordinal ) )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
indexText = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( formatTrimmed . Equals ( "style" , StringComparison . Ordinal ) )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
indexStyle = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( formatTrimmed . Equals ( "actor" , StringComparison . Ordinal ) )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
indexActor = i ;
2019-01-19 14:40:37 +01:00
}
2017-09-05 16:46:37 +02:00
else if ( formatTrimmed . Equals ( "name" , StringComparison . Ordinal ) )
2019-01-19 14:40:37 +01:00
{
2017-09-05 16:46:37 +02:00
indexName = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( formatTrimmed . Equals ( "marginl" , StringComparison . Ordinal ) )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
indexMarginL = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( formatTrimmed . Equals ( "marginr" , StringComparison . Ordinal ) )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
indexMarginR = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( formatTrimmed . Equals ( "marginv" , StringComparison . Ordinal ) )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
indexMarginV = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( formatTrimmed . Equals ( "effect" , StringComparison . Ordinal ) )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
indexEffect = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( formatTrimmed . Equals ( "layer" , StringComparison . Ordinal ) )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
indexLayer = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
}
}
else if ( ! string . IsNullOrEmpty ( s ) )
{
var text = string . Empty ;
var start = string . Empty ;
var end = string . Empty ;
var style = string . Empty ;
var actor = string . Empty ;
var marginL = string . Empty ;
var marginR = string . Empty ;
var marginV = string . Empty ;
var effect = string . Empty ;
var layer = 0 ;
string [ ] splittedLine ;
if ( s . StartsWith ( "dialog:" , StringComparison . Ordinal ) )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
splittedLine = line . Remove ( 0 , 7 ) . Split ( ',' ) ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( s . StartsWith ( "dialogue:" , StringComparison . Ordinal ) )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
splittedLine = line . Remove ( 0 , 9 ) . Split ( ',' ) ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
splittedLine = line . Split ( ',' ) ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
for ( int i = 0 ; i < splittedLine . Length ; i + + )
{
if ( i = = indexStart )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
start = splittedLine [ i ] . Trim ( ) ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( i = = indexEnd )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
end = splittedLine [ i ] . Trim ( ) ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( i = = indexStyle )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
style = splittedLine [ i ] . Trim ( ) ;
2019-01-19 14:40:37 +01:00
}
2019-08-21 15:54:18 +02:00
else if ( i = = indexActor & & indexName = = - 1 )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
actor = splittedLine [ i ] . Trim ( ) ;
2019-01-19 14:40:37 +01:00
}
2019-08-21 15:54:18 +02:00
else if ( i = = indexName )
2019-01-19 14:40:37 +01:00
{
2017-09-05 16:46:37 +02:00
actor = splittedLine [ i ] . Trim ( ) ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( i = = indexMarginL )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
marginL = splittedLine [ i ] . Trim ( ) ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( i = = indexMarginR )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
marginR = splittedLine [ i ] . Trim ( ) ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( i = = indexMarginV )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
marginV = splittedLine [ i ] . Trim ( ) ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( i = = indexEffect )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
effect = splittedLine [ i ] . Trim ( ) ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( i = = indexLayer )
2019-01-19 14:40:37 +01:00
{
2017-09-13 20:34:40 +02:00
int . TryParse ( splittedLine [ i ] . Replace ( "Comment:" , string . Empty ) . Trim ( ) , out layer ) ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( i = = indexText )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
text = splittedLine [ i ] ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( i > indexText )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
text + = "," + splittedLine [ i ] ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
}
try
{
var p = new Paragraph
{
StartTime = GetTimeCodeFromString ( start ) ,
EndTime = GetTimeCodeFromString ( end ) ,
Text = GetFormattedText ( text )
} ;
if ( ! string . IsNullOrEmpty ( style ) )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
p . Extra = style ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
if ( ! string . IsNullOrEmpty ( actor ) )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
p . Actor = actor ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
if ( ! string . IsNullOrEmpty ( marginL ) )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
p . MarginL = marginL ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
if ( ! string . IsNullOrEmpty ( marginR ) )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
p . MarginR = marginR ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
if ( ! string . IsNullOrEmpty ( marginV ) )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
p . MarginV = marginV ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
if ( ! string . IsNullOrEmpty ( effect ) )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
p . Effect = effect ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
p . Layer = layer ;
p . IsComment = s . StartsWith ( "comment:" , StringComparison . Ordinal ) ;
subtitle . Paragraphs . Add ( p ) ;
}
catch
{
_errorCount + + ;
if ( errors . Length < 2000 )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
errors . AppendLine ( string . Format ( Configuration . Settings . Language . Main . LineNumberXErrorReadingTimeCodeFromSourceLineY , lineNumber , line ) ) ;
2019-01-19 14:40:37 +01:00
}
2019-08-25 13:05:17 +02:00
else if ( subtitle . Paragraphs . Count = = 0 )
{
break ;
}
2015-12-31 14:08:05 +01:00
}
}
}
}
if ( header . Length > 0 )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
subtitle . Header = header . ToString ( ) ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
if ( footer . Length > 0 )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
subtitle . Footer = footer . ToString ( ) . Trim ( ) ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
subtitle . Renumber ( ) ;
Errors = errors . ToString ( ) ;
}
private static TimeCode GetTimeCodeFromString ( string time )
{
// h:mm:ss.cc
string [ ] timeCode = time . Split ( ':' , '.' ) ;
return new TimeCode ( int . Parse ( timeCode [ 0 ] ) ,
2017-09-13 20:34:40 +02:00
int . Parse ( timeCode [ 1 ] ) ,
int . Parse ( timeCode [ 2 ] ) ,
int . Parse ( timeCode [ 3 ] ) * 10 ) ;
2015-12-31 14:08:05 +01:00
}
public override void RemoveNativeFormatting ( Subtitle subtitle , SubtitleFormat newFormat )
{
if ( newFormat ! = null & & newFormat . Name = = SubStationAlpha . NameOfFormat )
{
foreach ( Paragraph p in subtitle . Paragraphs )
{
string s = p . Text ;
if ( s . Contains ( '{' ) & & s . Contains ( '}' ) )
{
s = s . Replace ( @"\u0" , string . Empty ) ;
s = s . Replace ( @"\u1" , string . Empty ) ;
s = s . Replace ( @"\s0" , string . Empty ) ;
s = s . Replace ( @"\s1" , string . Empty ) ;
s = s . Replace ( @"\be0" , string . Empty ) ;
s = s . Replace ( @"\be1" , string . Empty ) ;
s = RemoveTag ( s , "shad" ) ;
s = RemoveTag ( s , "fsc" ) ;
s = RemoveTag ( s , "fsp" ) ;
s = RemoveTag ( s , "fr" ) ;
s = RemoveTag ( s , "t(" ) ;
s = RemoveTag ( s , "move(" ) ;
s = RemoveTag ( s , "Position(" ) ;
s = RemoveTag ( s , "org(" ) ;
s = RemoveTag ( s , "fade(" ) ;
s = RemoveTag ( s , "fad(" ) ;
s = RemoveTag ( s , "clip(" ) ;
2017-09-05 16:46:37 +02:00
s = RemoveTag ( s , "iclip(" ) ;
2015-12-31 14:08:05 +01:00
s = RemoveTag ( s , "pbo(" ) ;
2017-09-05 16:46:37 +02:00
s = RemoveTag ( s , "bord" ) ;
s = RemoveTag ( s , "pos" ) ;
2015-12-31 14:08:05 +01:00
// TODO: Alignment tags
s = s . Replace ( "{}" , string . Empty ) ;
p . Text = s ;
}
}
}
else
{
foreach ( Paragraph p in subtitle . Paragraphs )
{
int indexOfBegin = p . Text . IndexOf ( '{' ) ;
string pre = string . Empty ;
while ( indexOfBegin > = 0 & & p . Text . IndexOf ( '}' ) > indexOfBegin )
{
string s = p . Text . Substring ( indexOfBegin ) ;
if ( s . StartsWith ( "{\\an1}" , StringComparison . Ordinal ) | |
s . StartsWith ( "{\\an2}" , StringComparison . Ordinal ) | |
s . StartsWith ( "{\\an3}" , StringComparison . Ordinal ) | |
s . StartsWith ( "{\\an4}" , StringComparison . Ordinal ) | |
s . StartsWith ( "{\\an5}" , StringComparison . Ordinal ) | |
s . StartsWith ( "{\\an6}" , StringComparison . Ordinal ) | |
s . StartsWith ( "{\\an7}" , StringComparison . Ordinal ) | |
s . StartsWith ( "{\\an8}" , StringComparison . Ordinal ) | |
s . StartsWith ( "{\\an9}" , StringComparison . Ordinal ) )
{
pre = s . Substring ( 0 , 6 ) ;
}
else if ( s . StartsWith ( "{\\an1\\" , StringComparison . Ordinal ) | |
2017-09-13 20:34:40 +02:00
s . StartsWith ( "{\\an2\\" , StringComparison . Ordinal ) | |
s . StartsWith ( "{\\an3\\" , StringComparison . Ordinal ) | |
s . StartsWith ( "{\\an4\\" , StringComparison . Ordinal ) | |
s . StartsWith ( "{\\an5\\" , StringComparison . Ordinal ) | |
s . StartsWith ( "{\\an6\\" , StringComparison . Ordinal ) | |
s . StartsWith ( "{\\an7\\" , StringComparison . Ordinal ) | |
s . StartsWith ( "{\\an8\\" , StringComparison . Ordinal ) | |
s . StartsWith ( "{\\an9\\" , StringComparison . Ordinal ) )
2015-12-31 14:08:05 +01:00
{
pre = s . Substring ( 0 , 5 ) + "}" ;
}
int indexOfEnd = p . Text . IndexOf ( '}' ) ;
p . Text = p . Text . Remove ( indexOfBegin , ( indexOfEnd - indexOfBegin ) + 1 ) ;
indexOfBegin = p . Text . IndexOf ( '{' ) ;
}
p . Text = pre + p . Text ;
}
}
}
private static string RemoveTag ( string s , string tag )
{
int indexOfTag = s . IndexOf ( @"\" + tag , StringComparison . Ordinal ) ;
if ( indexOfTag > 0 )
{
var endIndex1 = s . IndexOf ( '\\' , indexOfTag + 1 ) ;
var endIndex2 = s . IndexOf ( '}' , indexOfTag + 1 ) ;
endIndex1 = Math . Min ( endIndex1 , endIndex2 ) ;
if ( endIndex1 > 0 )
2019-01-19 14:40:37 +01:00
{
2019-01-29 21:33:20 +01:00
return s . Remove ( indexOfTag , endIndex1 - indexOfTag ) ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
}
return s ;
}
/// <summary>
/// BGR color like this: &HBBGGRR& (where BB, GG, and RR are hex values in uppercase)
/// </summary>
/// <param name="f">Input string</param>
/// <param name="defaultColor">Default color</param>
/// <returns>Input string as color, or default color if problems</returns>
public static Color GetSsaColor ( string f , Color defaultColor )
{
//Red = &H0000FF&
//Green = &H00FF00&
//Blue = &HFF0000&
//White = &HFFFFFF&
//Black = &H000000&
string s = f . Trim ( ) . Trim ( '&' ) ;
if ( s . StartsWith ( 'h' ) & & s . Length < 7 )
{
while ( s . Length < 7 )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
s = s . Insert ( 1 , "0" ) ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
}
if ( s . StartsWith ( 'h' ) & & s . Length = = 7 )
{
s = s . Substring ( 1 ) ;
string hexColor = "#" + s . Substring ( 4 , 2 ) + s . Substring ( 2 , 2 ) + s . Substring ( 0 , 2 ) ;
try
{
return ColorTranslator . FromHtml ( hexColor ) ;
}
catch
{
return defaultColor ;
}
}
if ( s . StartsWith ( 'h' ) & & s . Length = = 9 )
{
2019-01-26 12:11:57 +01:00
if ( int . TryParse ( s . Substring ( 1 , 2 ) , NumberStyles . HexNumber , null , out var alpha ) )
2015-12-31 14:08:05 +01:00
{
alpha = 255 - alpha ; // ASS stores alpha in reverse (0=full itentity and 255=fully transparent)
}
else
{
alpha = 255 ; // full color
}
s = s . Substring ( 3 ) ;
string hexColor = "#" + s . Substring ( 4 , 2 ) + s . Substring ( 2 , 2 ) + s . Substring ( 0 , 2 ) ;
try
{
var c = ColorTranslator . FromHtml ( hexColor ) ;
return Color . FromArgb ( alpha , c ) ;
}
catch
{
return defaultColor ;
}
}
2019-01-26 12:11:57 +01:00
if ( int . TryParse ( f , out var number ) )
2015-12-31 14:08:05 +01:00
{
2019-01-26 12:11:57 +01:00
var temp = Color . FromArgb ( number ) ;
2015-12-31 14:08:05 +01:00
return Color . FromArgb ( 255 , temp . B , temp . G , temp . R ) ;
}
return defaultColor ;
}
public static string GetSsaColorString ( Color c )
{
2017-07-27 13:31:54 +02:00
return $"&H{255 - c.A:X2}{c.B:X2}{c.G:X2}{c.R:X2}" ; // ASS stores alpha in reverse (0=full itentity and 255=fully transparent)
2015-12-31 14:08:05 +01:00
}
public static string CheckForErrors ( string header )
{
if ( string . IsNullOrEmpty ( header ) )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
return string . Empty ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
var sb = new StringBuilder ( ) ;
int styleCount = - 1 ;
int nameIndex = - 1 ;
int fontNameIndex = - 1 ;
int fontsizeIndex = - 1 ;
int primaryColourIndex = - 1 ;
int secondaryColourIndex = - 1 ;
int outlineColourIndex = - 1 ;
int backColourIndex = - 1 ;
int boldIndex = - 1 ;
int italicIndex = - 1 ;
int underlineIndex = - 1 ;
int outlineIndex = - 1 ;
int shadowIndex = - 1 ;
int alignmentIndex = - 1 ;
int marginLIndex = - 1 ;
int marginRIndex = - 1 ;
int marginVIndex = - 1 ;
int borderStyleIndex = - 1 ;
foreach ( string line in header . SplitToLines ( ) )
{
2019-01-21 09:53:15 +01:00
string s = line . Trim ( ) . ToLowerInvariant ( ) ;
2015-12-31 14:08:05 +01:00
if ( s . StartsWith ( "format:" , StringComparison . Ordinal ) )
{
if ( line . Length > 10 )
{
2019-01-21 09:53:15 +01:00
var format = line . Substring ( 8 ) . ToLowerInvariant ( ) . Split ( ',' ) ;
2015-12-31 14:08:05 +01:00
styleCount = format . Length ;
for ( int i = 0 ; i < format . Length ; i + + )
{
string f = format [ i ] . Trim ( ) ;
if ( f = = "name" )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
nameIndex = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( f = = "fontname" )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
fontNameIndex = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( f = = "fontsize" )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
fontsizeIndex = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( f = = "primarycolour" )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
primaryColourIndex = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( f = = "secondarycolour" )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
secondaryColourIndex = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( f = = "outlinecolour" )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
outlineColourIndex = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( f = = "backcolour" )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
backColourIndex = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( f = = "bold" )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
boldIndex = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( f = = "italic" )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
italicIndex = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( f = = "underline" )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
underlineIndex = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( f = = "outline" )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
outlineIndex = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( f = = "shadow" )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
shadowIndex = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( f = = "alignment" )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
alignmentIndex = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( f = = "marginl" )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
marginLIndex = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( f = = "marginr" )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
marginRIndex = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( f = = "marginv" )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
marginVIndex = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( f = = "borderstyle" )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
borderStyleIndex = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
}
}
}
2017-12-10 22:18:13 +01:00
else if ( s . RemoveChar ( ' ' ) . StartsWith ( "style:" , StringComparison . Ordinal ) )
2015-12-31 14:08:05 +01:00
{
if ( line . Length > 10 )
{
string rawLine = line ;
var format = line . Substring ( 6 ) . Split ( ',' ) ;
if ( format . Length ! = styleCount )
{
sb . AppendLine ( "Number of expected Style elements do not match number of Format elements: " + rawLine ) ;
sb . AppendLine ( ) ;
}
else
{
Color dummyColor = Color . FromArgb ( 9 , 14 , 16 , 26 ) ;
for ( int i = 0 ; i < format . Length ; i + + )
{
2019-01-21 09:53:15 +01:00
string f = format [ i ] . Trim ( ) . ToLowerInvariant ( ) ;
2015-12-31 14:08:05 +01:00
if ( i = = nameIndex )
{
if ( f . Length = = 0 )
{
sb . AppendLine ( "'Name' is empty: " + rawLine ) ;
sb . AppendLine ( ) ;
}
}
else if ( i = = fontNameIndex )
{
if ( f . Length = = 0 )
{
sb . AppendLine ( "'Fontname' is empty: " + rawLine ) ;
sb . AppendLine ( ) ;
}
}
else if ( i = = fontsizeIndex )
{
2019-10-20 13:30:34 +02:00
if ( ! float . TryParse ( f , NumberStyles . AllowDecimalPoint , CultureInfo . InvariantCulture , out _ ) | | f . StartsWith ( '-' ) )
2015-12-31 14:08:05 +01:00
{
sb . AppendLine ( "'Fontsize' incorrect: " + rawLine ) ;
sb . AppendLine ( ) ;
}
}
else if ( i = = primaryColourIndex )
{
if ( GetSsaColor ( f , dummyColor ) = = dummyColor | | f = = "&h" )
{
sb . AppendLine ( "'PrimaryColour' incorrect: " + rawLine ) ;
sb . AppendLine ( ) ;
}
}
else if ( i = = secondaryColourIndex )
{
if ( GetSsaColor ( f , dummyColor ) = = dummyColor )
{
sb . AppendLine ( "'SecondaryColour' incorrect: " + rawLine ) ;
sb . AppendLine ( ) ;
}
}
else if ( i = = outlineColourIndex )
{
if ( GetSsaColor ( f , dummyColor ) = = dummyColor )
{
sb . AppendLine ( "'OutlineColour' incorrect: " + rawLine ) ;
sb . AppendLine ( ) ;
}
}
else if ( i = = backColourIndex )
{
if ( GetSsaColor ( f , dummyColor ) = = dummyColor )
{
sb . AppendLine ( "'BackColour' incorrect: " + rawLine ) ;
sb . AppendLine ( ) ;
}
}
else if ( i = = boldIndex )
{
if ( Utilities . AllLetters . Contains ( f ) )
{
sb . AppendLine ( "'Bold' incorrect: " + rawLine ) ;
sb . AppendLine ( ) ;
}
}
else if ( i = = italicIndex )
{
if ( Utilities . AllLetters . Contains ( f ) )
{
sb . AppendLine ( "'Italic' incorrect: " + rawLine ) ;
sb . AppendLine ( ) ;
}
}
else if ( i = = underlineIndex )
{
if ( Utilities . AllLetters . Contains ( f ) )
{
sb . AppendLine ( "'Underline' incorrect: " + rawLine ) ;
sb . AppendLine ( ) ;
}
}
else if ( i = = outlineIndex )
{
2018-08-29 19:21:31 +02:00
if ( ! float . TryParse ( f , NumberStyles . AllowDecimalPoint , CultureInfo . InvariantCulture , out _ ) | | f . StartsWith ( '-' ) )
2015-12-31 14:08:05 +01:00
{
sb . AppendLine ( "'Outline' (width) incorrect: " + rawLine ) ;
sb . AppendLine ( ) ;
}
}
else if ( i = = shadowIndex )
{
2018-08-29 19:21:31 +02:00
if ( ! float . TryParse ( f , NumberStyles . AllowDecimalPoint , CultureInfo . InvariantCulture , out _ ) | | f . StartsWith ( '-' ) )
2015-12-31 14:08:05 +01:00
{
sb . AppendLine ( "'Shadow' (width) incorrect: " + rawLine ) ;
sb . AppendLine ( ) ;
}
}
else if ( i = = alignmentIndex )
{
if ( ! "101123456789 " . Contains ( f ) )
{
sb . AppendLine ( "'Alignment' incorrect: " + rawLine ) ;
sb . AppendLine ( ) ;
}
}
else if ( i = = marginLIndex )
{
2018-08-29 19:21:31 +02:00
if ( ! int . TryParse ( f , out _ ) | | f . StartsWith ( '-' ) )
2015-12-31 14:08:05 +01:00
{
sb . AppendLine ( "'MarginL' incorrect: " + rawLine ) ;
sb . AppendLine ( ) ;
}
}
else if ( i = = marginRIndex )
{
2018-08-29 19:21:31 +02:00
if ( ! int . TryParse ( f , out _ ) | | f . StartsWith ( '-' ) )
2015-12-31 14:08:05 +01:00
{
sb . AppendLine ( "'MarginR' incorrect: " + rawLine ) ;
sb . AppendLine ( ) ;
}
}
else if ( i = = marginVIndex )
{
2018-08-29 19:21:31 +02:00
if ( ! int . TryParse ( f , out _ ) | | f . StartsWith ( '-' ) )
2015-12-31 14:08:05 +01:00
{
sb . AppendLine ( "'MarginV' incorrect: " + rawLine ) ;
sb . AppendLine ( ) ;
}
}
else if ( i = = borderStyleIndex )
{
if ( f . Length ! = 0 & & ! "123" . Contains ( f ) )
{
sb . AppendLine ( "'BorderStyle' incorrect: " + rawLine ) ;
sb . AppendLine ( ) ;
}
}
}
}
}
}
}
return sb . ToString ( ) ;
}
/// <summary>
/// Add new style to ASS header
/// </summary>
/// <returns>Header with new style</returns>
2019-01-29 21:33:20 +01:00
public static string AddSsaStyle ( SsaStyle style , string inputHeader )
2015-12-31 14:08:05 +01:00
{
2019-01-29 21:33:20 +01:00
var header = inputHeader ;
2015-12-31 14:08:05 +01:00
if ( string . IsNullOrEmpty ( header ) )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
header = DefaultHeader ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
var sb = new StringBuilder ( ) ;
bool stylesStarted = false ;
bool styleAdded = false ;
string styleFormat = "Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding" ;
foreach ( string line in header . SplitToLines ( ) )
{
if ( line . Equals ( "[V4+ Styles]" , StringComparison . OrdinalIgnoreCase ) | | line . Equals ( "[V4 Styles]" , StringComparison . OrdinalIgnoreCase ) )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
stylesStarted = true ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
if ( line . StartsWith ( "format:" , StringComparison . OrdinalIgnoreCase ) )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
styleFormat = line ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
if ( ! line . StartsWith ( "Style: " + style . Name + "," , StringComparison . Ordinal ) ) // overwrite existing style
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
sb . AppendLine ( line ) ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
if ( ! styleAdded & & stylesStarted & & line . TrimStart ( ) . StartsWith ( "style:" , StringComparison . OrdinalIgnoreCase ) )
{
sb . AppendLine ( style . ToRawAss ( styleFormat ) ) ;
styleAdded = true ;
}
}
return sb . ToString ( ) ;
}
public static SsaStyle GetSsaStyle ( string styleName , string header )
{
var style = new SsaStyle { Name = styleName } ;
int nameIndex = - 1 ;
int fontNameIndex = - 1 ;
int fontsizeIndex = - 1 ;
int primaryColourIndex = - 1 ;
int secondaryColourIndex = - 1 ;
int tertiaryColourIndex = - 1 ;
int outlineColourIndex = - 1 ;
int backColourIndex = - 1 ;
int boldIndex = - 1 ;
int italicIndex = - 1 ;
int underlineIndex = - 1 ;
int outlineIndex = - 1 ;
int shadowIndex = - 1 ;
int alignmentIndex = - 1 ;
int marginLIndex = - 1 ;
int marginRIndex = - 1 ;
int marginVIndex = - 1 ;
int borderStyleIndex = - 1 ;
if ( header = = null )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
header = DefaultHeader ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
foreach ( string line in header . SplitToLines ( ) )
{
2019-01-21 09:53:15 +01:00
string s = line . Trim ( ) . ToLowerInvariant ( ) ;
2015-12-31 14:08:05 +01:00
if ( s . StartsWith ( "format:" , StringComparison . Ordinal ) )
{
if ( line . Length > 10 )
{
2019-01-21 09:53:15 +01:00
var format = line . ToLowerInvariant ( ) . Substring ( 8 ) . Split ( ',' ) ;
2015-12-31 14:08:05 +01:00
for ( int i = 0 ; i < format . Length ; i + + )
{
2019-01-21 09:53:15 +01:00
string f = format [ i ] . Trim ( ) . ToLowerInvariant ( ) ;
2015-12-31 14:08:05 +01:00
if ( f = = "name" )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
nameIndex = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( f = = "fontname" )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
fontNameIndex = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( f = = "fontsize" )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
fontsizeIndex = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( f = = "primarycolour" )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
primaryColourIndex = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( f = = "secondarycolour" )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
secondaryColourIndex = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( f = = "tertiarycolour" )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
tertiaryColourIndex = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( f = = "outlinecolour" )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
outlineColourIndex = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( f = = "backcolour" )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
backColourIndex = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( f = = "bold" )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
boldIndex = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( f = = "italic" )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
italicIndex = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( f = = "underline" )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
underlineIndex = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( f = = "outline" )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
outlineIndex = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( f = = "shadow" )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
shadowIndex = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( f = = "alignment" )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
alignmentIndex = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( f = = "marginl" )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
marginLIndex = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( f = = "marginr" )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
marginRIndex = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( f = = "marginv" )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
marginVIndex = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
else if ( f = = "borderstyle" )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
borderStyleIndex = i ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
}
}
}
2017-12-10 22:18:13 +01:00
else if ( s . RemoveChar ( ' ' ) . StartsWith ( "style:" , StringComparison . Ordinal ) )
2015-12-31 14:08:05 +01:00
{
if ( line . Length > 10 )
{
style . RawLine = line ;
var format = line . Substring ( 6 ) . Split ( ',' ) ;
for ( int i = 0 ; i < format . Length ; i + + )
{
2019-01-21 09:53:15 +01:00
string f = format [ i ] . Trim ( ) . ToLowerInvariant ( ) ;
2015-12-31 14:08:05 +01:00
if ( i = = nameIndex )
{
style . Name = format [ i ] . Trim ( ) ;
}
else if ( i = = fontNameIndex )
{
style . FontName = f ;
}
else if ( i = = fontsizeIndex )
{
2019-10-20 13:30:34 +02:00
if ( float . TryParse ( f , NumberStyles . AllowDecimalPoint , CultureInfo . InvariantCulture , out var fOut ) )
2019-01-19 14:40:37 +01:00
{
2019-10-20 13:30:34 +02:00
style . FontSize = fOut ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
}
else if ( i = = primaryColourIndex )
{
style . Primary = GetSsaColor ( f , Color . White ) ;
}
else if ( i = = secondaryColourIndex )
{
style . Secondary = GetSsaColor ( f , Color . Yellow ) ;
}
else if ( i = = tertiaryColourIndex )
{
style . Tertiary = GetSsaColor ( f , Color . Yellow ) ;
}
else if ( i = = outlineColourIndex )
{
style . Outline = GetSsaColor ( f , Color . Black ) ;
}
else if ( i = = backColourIndex )
{
style . Background = GetSsaColor ( f , Color . Black ) ;
}
else if ( i = = boldIndex )
{
2016-06-25 11:28:27 +02:00
style . Bold = f = = "-1" | | f = = "1" ;
2015-12-31 14:08:05 +01:00
}
else if ( i = = italicIndex )
{
2016-06-25 11:28:27 +02:00
style . Italic = f = = "-1" | | f = = "1" ;
2015-12-31 14:08:05 +01:00
}
else if ( i = = underlineIndex )
{
2016-08-10 04:40:15 +02:00
style . Underline = f = = "-1" | | f = = "1" ;
2015-12-31 14:08:05 +01:00
}
else if ( i = = outlineIndex )
{
2019-01-26 12:11:57 +01:00
if ( decimal . TryParse ( f , NumberStyles . AllowDecimalPoint , CultureInfo . InvariantCulture , out var number ) )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
style . OutlineWidth = number ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
}
else if ( i = = shadowIndex )
{
2019-01-26 12:11:57 +01:00
if ( decimal . TryParse ( f , NumberStyles . AllowDecimalPoint , CultureInfo . InvariantCulture , out var number ) )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
style . ShadowWidth = number ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
}
else if ( i = = alignmentIndex )
{
style . Alignment = f ;
}
else if ( i = = marginLIndex )
{
2019-01-26 12:11:57 +01:00
if ( int . TryParse ( f , out var number ) )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
style . MarginLeft = number ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
}
else if ( i = = marginRIndex )
{
2019-01-26 12:11:57 +01:00
if ( int . TryParse ( f , out var number ) )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
style . MarginRight = number ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
}
else if ( i = = marginVIndex )
{
2019-01-26 12:11:57 +01:00
if ( int . TryParse ( f , out var number ) )
2019-01-19 14:40:37 +01:00
{
2015-12-31 14:08:05 +01:00
style . MarginVertical = number ;
2019-01-19 14:40:37 +01:00
}
2015-12-31 14:08:05 +01:00
}
else if ( i = = borderStyleIndex )
{
style . BorderStyle = f ;
}
}
}
2016-07-08 21:36:25 +02:00
if ( styleName ! = null & & style . Name ! = null & & ( styleName . Equals ( style . Name , StringComparison . OrdinalIgnoreCase ) | |
2018-08-29 19:21:31 +02:00
styleName . Equals ( "*Default" , StringComparison . OrdinalIgnoreCase ) & &
2018-03-07 08:10:26 +01:00
style . Name . Equals ( "Default" , StringComparison . OrdinalIgnoreCase ) ) )
2015-12-31 14:08:05 +01:00
{
style . LoadedFromHeader = true ;
return style ;
}
}
}
return new SsaStyle { Name = styleName } ;
}
2017-07-27 13:31:54 +02:00
public override bool HasStyleSupport = > true ;
2015-12-31 14:08:05 +01:00
}
2017-09-13 20:34:40 +02:00
}