mirror of
https://github.com/SubtitleEdit/subtitleedit.git
synced 2024-11-23 11:42:36 +01:00
1839 lines
86 KiB
C#
1839 lines
86 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.Globalization;
|
|
using System.Linq;
|
|
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)
|
|
borderStyle = "3";
|
|
|
|
string boldStyle = "0"; // 0=regular
|
|
if (Configuration.Settings.SubtitleSettings.SsaFontBold)
|
|
boldStyle = "-1";
|
|
|
|
var ssa = Configuration.Settings.SubtitleSettings;
|
|
return "Style: Default," + ssa.SsaFontName + "," +
|
|
(int)ssa.SsaFontSize + "," +
|
|
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";
|
|
}
|
|
}
|
|
|
|
public static string DefaultHeader
|
|
{
|
|
get
|
|
{
|
|
SubtitleFormat format = new AdvancedSubStationAlpha();
|
|
var sub = new Subtitle();
|
|
string text = format.ToText(sub, string.Empty);
|
|
var lines = text.SplitToLines();
|
|
format.LoadSubtitle(sub, lines, string.Empty);
|
|
return sub.Header;
|
|
}
|
|
}
|
|
|
|
public override string Extension => ".ass";
|
|
|
|
public const string NameOfFormat = "Advanced Sub Station Alpha";
|
|
|
|
public override string Name => NameOfFormat;
|
|
|
|
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))
|
|
subtitle.Header = subtitle.Header.Replace("[V4 Styles]", "[V4+ Styles]");
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public const string HeaderNoStyles = @"[Script Info]
|
|
; 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
|
|
{1}
|
|
|
|
[Events]
|
|
Format: Layer, Start, End, Style, Actor, MarginL, MarginR, MarginV, Effect, Text";
|
|
|
|
public override string ToText(Subtitle subtitle, string title)
|
|
{
|
|
bool fromTtml = false;
|
|
string header = @"[Script Info]
|
|
; 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
|
|
" + DefaultStyle + @"
|
|
|
|
[Events]
|
|
Format: Layer, Start, End, Style, Actor, MarginL, MarginR, MarginV, Effect, Text";
|
|
|
|
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());
|
|
sb.AppendLine("Format: Layer, Start, End, Style, Actor, MarginL, MarginR, MarginV, Effect, Text");
|
|
styles = GetStylesFromHeader(subtitle.Header);
|
|
}
|
|
else if (!string.IsNullOrEmpty(subtitle.Header) && subtitle.Header.Contains("[V4 Styles]"))
|
|
{
|
|
LoadStylesFromSubstationAlpha(subtitle, title, header, HeaderNoStyles, sb);
|
|
}
|
|
else if (subtitle.Header != null && subtitle.Header.Contains("http://www.w3.org/ns/ttml"))
|
|
{
|
|
LoadStylesFromTimedText10(subtitle, title, header, HeaderNoStyles, sb);
|
|
fromTtml = true;
|
|
isValidAssHeader = !string.IsNullOrEmpty(subtitle.Header) && subtitle.Header.Contains("[V4+ Styles]");
|
|
if (isValidAssHeader)
|
|
{
|
|
styles = GetStylesFromHeader(subtitle.Header);
|
|
}
|
|
}
|
|
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);
|
|
}
|
|
}
|
|
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))
|
|
style = p.Extra;
|
|
if (fromTtml && !string.IsNullOrEmpty(p.Style) && isValidAssHeader && styles.Contains(p.Style))
|
|
style = p.Style;
|
|
|
|
string actor = "";
|
|
if (!string.IsNullOrEmpty(p.Actor))
|
|
actor = p.Actor;
|
|
|
|
string marginL = "0";
|
|
if (!string.IsNullOrEmpty(p.MarginL) && Utilities.IsInteger(p.MarginL))
|
|
marginL = p.MarginL;
|
|
string marginR = "0";
|
|
if (!string.IsNullOrEmpty(p.MarginR) && Utilities.IsInteger(p.MarginR))
|
|
marginR = p.MarginR;
|
|
string marginV = "0";
|
|
if (!string.IsNullOrEmpty(p.MarginV) && Utilities.IsInteger(p.MarginV))
|
|
marginV = p.MarginV;
|
|
|
|
string effect = "";
|
|
if (!string.IsNullOrEmpty(p.Effect))
|
|
effect = p.Effect;
|
|
|
|
if (p.IsComment)
|
|
sb.AppendLine(string.Format(commentWriteFormat, start, end, FormatText(p), style, actor, marginL, marginR, marginV, effect, p.Layer));
|
|
else
|
|
sb.AppendLine(string.Format(paragraphWriteFormat, start, end, FormatText(p), style, actor, marginL, marginR, marginV, effect, p.Layer));
|
|
}
|
|
|
|
if (!string.IsNullOrEmpty(subtitle.Footer) && (subtitle.Footer.Contains("[Fonts]" + Environment.NewLine) || subtitle.Footer.Contains("[Graphics]" + Environment.NewLine)))
|
|
{
|
|
sb.AppendLine();
|
|
sb.AppendLine(subtitle.Footer);
|
|
}
|
|
return sb.ToString().Trim();
|
|
}
|
|
|
|
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);
|
|
if (ssaStyle != null)
|
|
{
|
|
string bold = "0";
|
|
if (ssaStyle.Bold)
|
|
bold = "-1";
|
|
string italic = "0";
|
|
if (ssaStyle.Italic)
|
|
italic = "-1";
|
|
string underline = "0";
|
|
if (ssaStyle.Underline)
|
|
underline = "-1";
|
|
|
|
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;
|
|
}
|
|
|
|
ttStyles.AppendLine(string.Format(styleFormat, ssaStyle.Name, ssaStyle.FontName, ssaStyle.FontSize, GetSsaColorString(ssaStyle.Primary), GetSsaColorString(ssaStyle.Secondary),
|
|
GetSsaColorString(ssaStyle.Outline), GetSsaColorString(ssaStyle.Background), bold, italic, underline, ssaStyle.BorderStyle, ssaStyle.OutlineWidth, ssaStyle.ShadowWidth,
|
|
newAlignment, ssaStyle.MarginLeft, ssaStyle.MarginRight, ssaStyle.MarginVertical));
|
|
styleFound = true;
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
// ignored
|
|
}
|
|
}
|
|
|
|
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));
|
|
}
|
|
}
|
|
|
|
public static void LoadStylesFromTimedText10(Subtitle subtitle, string title, string header, string headerNoStyles, StringBuilder sb)
|
|
{
|
|
foreach (Paragraph p in subtitle.Paragraphs)
|
|
{
|
|
p.Effect = null;
|
|
}
|
|
|
|
try
|
|
{
|
|
var lines = subtitle.Header.SplitToLines();
|
|
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);
|
|
int styleCount = 0;
|
|
var ttStyles = new StringBuilder();
|
|
var styleNames = new List<string>();
|
|
foreach (XmlNode node in head.SelectNodes("//ttml:style", nsmgr))
|
|
{
|
|
string name = null;
|
|
if (node.Attributes["xml:id"] != null)
|
|
name = node.Attributes["xml:id"].Value;
|
|
else if (node.Attributes["id"] != null)
|
|
name = node.Attributes["id"].Value;
|
|
if (name != null)
|
|
{
|
|
styleCount++;
|
|
|
|
string fontFamily = "Arial";
|
|
if (node.Attributes["tts:fontFamily"] != null)
|
|
fontFamily = node.Attributes["tts:fontFamily"].Value;
|
|
|
|
string fontWeight = "normal";
|
|
if (node.Attributes["tts:fontWeight"] != null)
|
|
fontWeight = node.Attributes["tts:fontWeight"].Value;
|
|
|
|
string fontStyle = "normal";
|
|
if (node.Attributes["tts:fontStyle"] != null)
|
|
fontStyle = node.Attributes["tts:fontStyle"].Value;
|
|
|
|
string color = "#ffffff";
|
|
if (node.Attributes["tts:color"] != null)
|
|
color = node.Attributes["tts:color"].Value.Trim();
|
|
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)
|
|
fontSize = node.Attributes["tts:fontSize"].Value.Replace("px", string.Empty).Replace("em", string.Empty);
|
|
int fSize;
|
|
if (!int.TryParse(fontSize, out fSize))
|
|
fSize = 20;
|
|
|
|
string italic = "0";
|
|
if (fontStyle == "italic")
|
|
italic = "-1";
|
|
|
|
string bold = "0";
|
|
if (fontWeight == "bold")
|
|
bold = "-1";
|
|
|
|
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))
|
|
paragraph.Extra = "Default";
|
|
}
|
|
}
|
|
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 void LoadStylesFromTimedTextTimedDraft2006Oct(Subtitle subtitle, string title, string header, string headerNoStyles, StringBuilder sb)
|
|
{
|
|
foreach (Paragraph p in subtitle.Paragraphs)
|
|
{
|
|
p.Effect = null;
|
|
}
|
|
|
|
try
|
|
{
|
|
var lines = subtitle.Header.SplitToLines();
|
|
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)
|
|
name = node.Attributes["xml:id"].Value;
|
|
else if (node.Attributes["id"] != null)
|
|
name = node.Attributes["id"].Value;
|
|
if (name != null)
|
|
{
|
|
styleCount++;
|
|
|
|
string fontFamily = "Arial";
|
|
if (node.Attributes["tts:fontFamily"] != null)
|
|
fontFamily = node.Attributes["tts:fontFamily"].Value;
|
|
|
|
string fontWeight = "normal";
|
|
if (node.Attributes["tts:fontWeight"] != null)
|
|
fontWeight = node.Attributes["tts:fontWeight"].Value;
|
|
|
|
string fontStyle = "normal";
|
|
if (node.Attributes["tts:fontStyle"] != null)
|
|
fontStyle = node.Attributes["tts:fontStyle"].Value;
|
|
|
|
string color = "#ffffff";
|
|
if (node.Attributes["tts:color"] != null)
|
|
color = node.Attributes["tts:color"].Value.Trim();
|
|
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)
|
|
fontSize = node.Attributes["tts:fontSize"].Value.Replace("px", string.Empty).Replace("em", string.Empty);
|
|
int fSize;
|
|
if (!int.TryParse(fontSize, out fSize))
|
|
fSize = 20;
|
|
|
|
string italic = "0";
|
|
if (fontStyle == "italic")
|
|
italic = "-1";
|
|
|
|
string bold = "0";
|
|
if (fontWeight == "bold")
|
|
bold = "-1";
|
|
|
|
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))
|
|
paragraph.Extra = "Default";
|
|
}
|
|
}
|
|
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)
|
|
headerLines = DefaultStyle;
|
|
|
|
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;
|
|
}
|
|
|
|
foreach (string line in headerLines.SplitToLines())
|
|
{
|
|
if (line.StartsWith("style:", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
int end = line.IndexOf(',');
|
|
if (end > 0)
|
|
list.Add(line.Substring(6, end - 6).Trim());
|
|
}
|
|
}
|
|
return list;
|
|
}
|
|
|
|
public static string FormatText(Paragraph p)
|
|
{
|
|
string text = p.Text.Replace(Environment.NewLine, "\\N");
|
|
|
|
if (!text.Contains('<'))
|
|
return text;
|
|
|
|
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)
|
|
{
|
|
int start = text.IndexOf("<font ", StringComparison.Ordinal);
|
|
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);
|
|
if (indexOfEndFont < text.Length)
|
|
{
|
|
if (fontTag.Contains(" size="))
|
|
{
|
|
text = text.Insert(indexOfEndFont, "{\\fs}");
|
|
}
|
|
if (fontTag.Contains(" face="))
|
|
{
|
|
text = text.Insert(indexOfEndFont, "{\\fn}");
|
|
}
|
|
if (fontTag.Contains(" color="))
|
|
{
|
|
text = text.Insert(indexOfEndFont, "{\\c}");
|
|
}
|
|
}
|
|
}
|
|
|
|
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++;
|
|
}
|
|
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");
|
|
}
|
|
return text;
|
|
}
|
|
|
|
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);
|
|
|
|
int fontEnd = fontTag.IndexOfAny(new[] { '"', '\'' }, fontStart + tag.Length);
|
|
if (fontEnd < 0)
|
|
fontEnd = fontTag.IndexOfAny(new[] { ' ', '>' }, fontStart + tag.Length);
|
|
|
|
if (fontEnd > 0)
|
|
{
|
|
string subTag = fontTag.Substring(fontStart + tag.Length, fontEnd - (fontStart + tag.Length));
|
|
if (tag.Contains("color"))
|
|
{
|
|
Color c;
|
|
try
|
|
{
|
|
c = ColorTranslator.FromHtml(subTag);
|
|
}
|
|
catch
|
|
{
|
|
c = Color.White;
|
|
}
|
|
subTag = (c.B.ToString("X2") + c.G.ToString("X2") + c.R.ToString("X2")).ToLowerInvariant(); // use bbggrr
|
|
}
|
|
fontTag = fontTag.Remove(fontStart, fontEnd - fontStart + 1);
|
|
if (start < text.Length)
|
|
text = text.Insert(start, @"{\" + ssaTagName + subTag + endSsaTag);
|
|
}
|
|
}
|
|
return fontTag;
|
|
}
|
|
|
|
public static string GetFormattedText(string text)
|
|
{
|
|
text = text.Replace("\\N", Environment.NewLine).Replace("\\n", Environment.NewLine);
|
|
|
|
var tooComplex = ContainsUnsupportedTags(text);
|
|
|
|
if (!tooComplex)
|
|
{
|
|
for (int i = 0; i < 10; i++) // just look ten times...
|
|
{
|
|
bool italic;
|
|
if (text.Contains(@"{\fn"))
|
|
{
|
|
int start = text.IndexOf(@"{\fn", StringComparison.Ordinal);
|
|
int end = text.IndexOf('}', start);
|
|
if (end > 0 && !text.Substring(start).StartsWith("{\\fn}", StringComparison.Ordinal))
|
|
{
|
|
string fontName = text.Substring(start + 4, end - (start + 4));
|
|
string extraTags = string.Empty;
|
|
string unknownTags;
|
|
CheckAndAddSubTags(ref fontName, ref extraTags, out unknownTags, out italic);
|
|
text = text.Remove(start, end - start + 1);
|
|
if (italic)
|
|
text = text.Insert(start, "<font face=\"" + fontName + "\"" + extraTags + ">" + unknownTags + "<i>");
|
|
else
|
|
text = text.Insert(start, "<font face=\"" + fontName + "\"" + extraTags + ">" + unknownTags);
|
|
|
|
int indexOfEndTag = text.IndexOf("{\\fn}", start, StringComparison.Ordinal);
|
|
if (indexOfEndTag > 0)
|
|
{
|
|
text = text.Remove(indexOfEndTag, "{\\fn}".Length).Insert(indexOfEndTag, "</font>");
|
|
}
|
|
else
|
|
{
|
|
int indexOfNextTag1 = text.IndexOf("{\\fn", 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>";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (text.Contains(@"{\fs"))
|
|
{
|
|
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;
|
|
string unknownTags;
|
|
CheckAndAddSubTags(ref fontSize, ref extraTags, out unknownTags, out italic);
|
|
if (Utilities.IsInteger(fontSize))
|
|
{
|
|
text = text.Remove(start, end - start + 1);
|
|
if (italic)
|
|
text = text.Insert(start, "<font size=\"" + fontSize + "\"" + extraTags + ">" + unknownTags + "<i>");
|
|
else
|
|
text = text.Insert(start, "<font size=\"" + fontSize + "\"" + extraTags + ">" + unknownTags);
|
|
|
|
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>";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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;
|
|
string unknownTags;
|
|
CheckAndAddSubTags(ref color, ref extraTags, out unknownTags, out italic);
|
|
|
|
color = color.RemoveChar('&').TrimStart('H');
|
|
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);
|
|
color = color.ToLower();
|
|
|
|
text = text.Remove(start, end - start + 1);
|
|
if (italic)
|
|
text = text.Insert(start, "<font color=\"" + color + "\"" + extraTags + ">" + unknownTags + "<i>");
|
|
else
|
|
text = text.Insert(start, "<font color=\"" + color + "\"" + extraTags + ">" + unknownTags);
|
|
int indexOfEndTag = text.IndexOf("{\\c}", start, StringComparison.Ordinal);
|
|
int indexOfNextColorTag = text.IndexOf("{\\c&", start, StringComparison.Ordinal);
|
|
if (indexOfNextColorTag > 0 && (indexOfNextColorTag < indexOfEndTag || indexOfEndTag == -1))
|
|
text = text.Insert(indexOfNextColorTag, "</font>");
|
|
else if (indexOfEndTag > 0)
|
|
text = text.Remove(indexOfEndTag, "{\\c}".Length).Insert(indexOfEndTag, "</font>");
|
|
else
|
|
text += "</font>";
|
|
}
|
|
}
|
|
|
|
if (text.Contains(@"{\1c")) // "1" specifices primary color
|
|
{
|
|
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;
|
|
string unknownTags;
|
|
CheckAndAddSubTags(ref color, ref extraTags, out unknownTags, out italic);
|
|
|
|
color = color.RemoveChar('&').TrimStart('H');
|
|
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);
|
|
color = color.ToLower();
|
|
|
|
text = text.Remove(start, end - start + 1);
|
|
if (italic)
|
|
text = text.Insert(start, "<font color=\"" + color + "\"" + extraTags + ">" + unknownTags + "<i>");
|
|
else
|
|
text = text.Insert(start, "<font color=\"" + color + "\"" + extraTags + ">" + unknownTags);
|
|
text += "</font>";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
text = text.Replace(@"{\i1}", "<i>");
|
|
text = text.Replace(@"{\i0}", "</i>");
|
|
text = text.Replace(@"{\i}", "</i>");
|
|
if (Utilities.CountTagInText(text, "<i>") > Utilities.CountTagInText(text, "</i>"))
|
|
text += "</i>";
|
|
|
|
text = text.Replace(@"{\u1}", "<u>");
|
|
text = text.Replace(@"{\u0}", "</u>");
|
|
text = text.Replace(@"{\u}", "</u>");
|
|
if (Utilities.CountTagInText(text, "<u>") > Utilities.CountTagInText(text, "</u>"))
|
|
text += "</u>";
|
|
|
|
text = text.Replace(@"{\b1}", "<b>");
|
|
text = text.Replace(@"{\b0}", "</b>");
|
|
text = text.Replace(@"{\b}", "</b>");
|
|
if (Utilities.CountTagInText(text, "<b>") > Utilities.CountTagInText(text, "</b>"))
|
|
text += "</b>";
|
|
|
|
return text;
|
|
}
|
|
|
|
private static bool ContainsUnsupportedTags(string text)
|
|
{
|
|
if (string.IsNullOrEmpty(text) || !text.Contains("{\\", StringComparison.OrdinalIgnoreCase))
|
|
return false;
|
|
|
|
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))
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private static void CheckAndAddSubTags(ref string tagName, ref string extraTags, out string unknownTags, out bool italic)
|
|
{
|
|
italic = false;
|
|
unknownTags = string.Empty;
|
|
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);
|
|
color = color.RemoveChar('&').TrimStart('H');
|
|
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);
|
|
color = color.ToLower();
|
|
|
|
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('\\');
|
|
var unknowntag = rest.Substring(0, indexOfSPlit);
|
|
unknownTags += "\\" + unknowntag;
|
|
rest = rest.Substring(indexOfSPlit).TrimStart('\\');
|
|
}
|
|
else if (!string.IsNullOrEmpty(rest))
|
|
{
|
|
unknownTags += "\\" + rest;
|
|
rest = string.Empty;
|
|
}
|
|
}
|
|
}
|
|
if (!string.IsNullOrEmpty(unknownTags))
|
|
unknownTags = "{" + unknownTags + "}";
|
|
}
|
|
|
|
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;
|
|
int indexActor = 4;
|
|
int indexName = -1; // convert "Name" to "Actor" (if no "Actor") - "Name" is from SSA ?
|
|
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++;
|
|
if (!eventsStarted && !fontsStarted && !graphicsStarted &&
|
|
!line.Trim().Equals("[fonts]", StringComparison.InvariantCultureIgnoreCase) &&
|
|
!line.Trim().Equals("[graphics]", StringComparison.InvariantCultureIgnoreCase))
|
|
header.AppendLine(line);
|
|
|
|
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))
|
|
{
|
|
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]");
|
|
}
|
|
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)
|
|
{
|
|
string s = line.Trim().ToLower();
|
|
if (line.Length > 10 && s.StartsWith("format:", StringComparison.Ordinal))
|
|
{
|
|
indexLayer = -1;
|
|
indexStart = -1;
|
|
indexEnd = -1;
|
|
indexStyle = -1;
|
|
indexActor = -1;
|
|
indexName = -1;
|
|
indexMarginL = -1;
|
|
indexMarginR = -1;
|
|
indexMarginV = -1;
|
|
indexEffect = -1;
|
|
indexText = -1;
|
|
|
|
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))
|
|
indexStart = i;
|
|
else if (formatTrimmed.Equals("end", StringComparison.Ordinal))
|
|
indexEnd = i;
|
|
else if (formatTrimmed.Equals("text", StringComparison.Ordinal))
|
|
indexText = i;
|
|
else if (formatTrimmed.Equals("style", StringComparison.Ordinal))
|
|
indexStyle = i;
|
|
else if (formatTrimmed.Equals("actor", StringComparison.Ordinal))
|
|
indexActor = i;
|
|
else if (formatTrimmed.Equals("name", StringComparison.Ordinal))
|
|
indexName = i;
|
|
else if (formatTrimmed.Equals("marginl", StringComparison.Ordinal))
|
|
indexMarginL = i;
|
|
else if (formatTrimmed.Equals("marginr", StringComparison.Ordinal))
|
|
indexMarginR = i;
|
|
else if (formatTrimmed.Equals("marginv", StringComparison.Ordinal))
|
|
indexMarginV = i;
|
|
else if (formatTrimmed.Equals("effect", StringComparison.Ordinal))
|
|
indexEffect = i;
|
|
else if (formatTrimmed.Equals("layer", StringComparison.Ordinal))
|
|
indexLayer = i;
|
|
}
|
|
}
|
|
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))
|
|
splittedLine = line.Remove(0, 7).Split(',');
|
|
else if (s.StartsWith("dialogue:", StringComparison.Ordinal))
|
|
splittedLine = line.Remove(0, 9).Split(',');
|
|
else
|
|
splittedLine = line.Split(',');
|
|
|
|
for (int i = 0; i < splittedLine.Length; i++)
|
|
{
|
|
if (i == indexStart)
|
|
start = splittedLine[i].Trim();
|
|
else if (i == indexEnd)
|
|
end = splittedLine[i].Trim();
|
|
else if (i == indexStyle)
|
|
style = splittedLine[i].Trim();
|
|
else if (i == indexActor)
|
|
actor = splittedLine[i].Trim();
|
|
else if (i == indexName && indexActor == -1)
|
|
actor = splittedLine[i].Trim();
|
|
else if (i == indexMarginL)
|
|
marginL = splittedLine[i].Trim();
|
|
else if (i == indexMarginR)
|
|
marginR = splittedLine[i].Trim();
|
|
else if (i == indexMarginV)
|
|
marginV = splittedLine[i].Trim();
|
|
else if (i == indexEffect)
|
|
effect = splittedLine[i].Trim();
|
|
else if (i == indexLayer)
|
|
int.TryParse(splittedLine[i].Replace("Comment:", string.Empty).Trim(), out layer);
|
|
else if (i == indexText)
|
|
text = splittedLine[i];
|
|
else if (i > indexText)
|
|
text += "," + splittedLine[i];
|
|
}
|
|
|
|
try
|
|
{
|
|
var p = new Paragraph
|
|
{
|
|
StartTime = GetTimeCodeFromString(start),
|
|
EndTime = GetTimeCodeFromString(end),
|
|
Text = GetFormattedText(text)
|
|
};
|
|
|
|
if (!string.IsNullOrEmpty(style))
|
|
p.Extra = style;
|
|
if (!string.IsNullOrEmpty(actor))
|
|
p.Actor = actor;
|
|
if (!string.IsNullOrEmpty(marginL))
|
|
p.MarginL = marginL;
|
|
if (!string.IsNullOrEmpty(marginR))
|
|
p.MarginR = marginR;
|
|
if (!string.IsNullOrEmpty(marginV))
|
|
p.MarginV = marginV;
|
|
if (!string.IsNullOrEmpty(effect))
|
|
p.Effect = effect;
|
|
p.Layer = layer;
|
|
p.IsComment = s.StartsWith("comment:", StringComparison.Ordinal);
|
|
subtitle.Paragraphs.Add(p);
|
|
}
|
|
catch
|
|
{
|
|
_errorCount++;
|
|
if (errors.Length < 2000)
|
|
errors.AppendLine(string.Format(Configuration.Settings.Language.Main.LineNumberXErrorReadingTimeCodeFromSourceLineY, lineNumber, line));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (header.Length > 0)
|
|
subtitle.Header = header.ToString();
|
|
if (footer.Length > 0)
|
|
subtitle.Footer = footer.ToString().Trim();
|
|
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]),
|
|
int.Parse(timeCode[1]),
|
|
int.Parse(timeCode[2]),
|
|
int.Parse(timeCode[3]) * 10);
|
|
}
|
|
|
|
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(");
|
|
s = RemoveTag(s, "iclip(");
|
|
s = RemoveTag(s, "pbo(");
|
|
s = RemoveTag(s, "bord");
|
|
s = RemoveTag(s, "pos");
|
|
|
|
// 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) ||
|
|
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, 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)
|
|
s = s.Remove(indexOfTag, endIndex1 - indexOfTag);
|
|
}
|
|
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)
|
|
s = s.Insert(1, "0");
|
|
}
|
|
|
|
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)
|
|
{
|
|
int alpha;
|
|
if (int.TryParse(s.Substring(1, 2), NumberStyles.HexNumber, null, out alpha))
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
int number;
|
|
if (int.TryParse(f, out number))
|
|
{
|
|
Color temp = Color.FromArgb(number);
|
|
return Color.FromArgb(255, temp.B, temp.G, temp.R);
|
|
}
|
|
return defaultColor;
|
|
}
|
|
|
|
public static string GetSsaColorString(Color c)
|
|
{
|
|
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)
|
|
}
|
|
|
|
public static string CheckForErrors(string header)
|
|
{
|
|
if (string.IsNullOrEmpty(header))
|
|
return string.Empty;
|
|
|
|
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())
|
|
{
|
|
string s = line.Trim().ToLower();
|
|
if (s.StartsWith("format:", StringComparison.Ordinal))
|
|
{
|
|
if (line.Length > 10)
|
|
{
|
|
var format = line.Substring(8).ToLower().Split(',');
|
|
styleCount = format.Length;
|
|
for (int i = 0; i < format.Length; i++)
|
|
{
|
|
string f = format[i].Trim();
|
|
if (f == "name")
|
|
nameIndex = i;
|
|
else if (f == "fontname")
|
|
fontNameIndex = i;
|
|
else if (f == "fontsize")
|
|
fontsizeIndex = i;
|
|
else if (f == "primarycolour")
|
|
primaryColourIndex = i;
|
|
else if (f == "secondarycolour")
|
|
secondaryColourIndex = i;
|
|
else if (f == "outlinecolour")
|
|
outlineColourIndex = i;
|
|
else if (f == "backcolour")
|
|
backColourIndex = i;
|
|
else if (f == "bold")
|
|
boldIndex = i;
|
|
else if (f == "italic")
|
|
italicIndex = i;
|
|
else if (f == "underline")
|
|
underlineIndex = i;
|
|
else if (f == "outline")
|
|
outlineIndex = i;
|
|
else if (f == "shadow")
|
|
shadowIndex = i;
|
|
else if (f == "alignment")
|
|
alignmentIndex = i;
|
|
else if (f == "marginl")
|
|
marginLIndex = i;
|
|
else if (f == "marginr")
|
|
marginRIndex = i;
|
|
else if (f == "marginv")
|
|
marginVIndex = i;
|
|
else if (f == "borderstyle")
|
|
borderStyleIndex = i;
|
|
}
|
|
}
|
|
}
|
|
else if (s.RemoveChar(' ').StartsWith("style:", StringComparison.Ordinal))
|
|
{
|
|
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++)
|
|
{
|
|
string f = format[i].Trim().ToLower();
|
|
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)
|
|
{
|
|
int number;
|
|
if (!int.TryParse(f, out number) || f.StartsWith('-'))
|
|
{
|
|
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)
|
|
{
|
|
float number;
|
|
if (!float.TryParse(f, out number) || f.StartsWith('-'))
|
|
{
|
|
sb.AppendLine("'Outline' (width) incorrect: " + rawLine);
|
|
sb.AppendLine();
|
|
}
|
|
}
|
|
else if (i == shadowIndex)
|
|
{
|
|
float number;
|
|
if (!float.TryParse(f, out number) || f.StartsWith('-'))
|
|
{
|
|
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)
|
|
{
|
|
int number;
|
|
if (!int.TryParse(f, out number) || f.StartsWith('-'))
|
|
{
|
|
sb.AppendLine("'MarginL' incorrect: " + rawLine);
|
|
sb.AppendLine();
|
|
}
|
|
}
|
|
else if (i == marginRIndex)
|
|
{
|
|
int number;
|
|
if (!int.TryParse(f, out number) || f.StartsWith('-'))
|
|
{
|
|
sb.AppendLine("'MarginR' incorrect: " + rawLine);
|
|
sb.AppendLine();
|
|
}
|
|
}
|
|
else if (i == marginVIndex)
|
|
{
|
|
int number;
|
|
if (!int.TryParse(f, out number) || f.StartsWith('-'))
|
|
{
|
|
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>
|
|
public static string AddSsaStyle(SsaStyle style, string header)
|
|
{
|
|
if (string.IsNullOrEmpty(header))
|
|
header = DefaultHeader;
|
|
|
|
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))
|
|
stylesStarted = true;
|
|
if (line.StartsWith("format:", StringComparison.OrdinalIgnoreCase))
|
|
styleFormat = line;
|
|
if (!line.StartsWith("Style: " + style.Name + ",", StringComparison.Ordinal)) // overwrite existing style
|
|
sb.AppendLine(line);
|
|
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)
|
|
header = DefaultHeader;
|
|
|
|
foreach (string line in header.SplitToLines())
|
|
{
|
|
string s = line.Trim().ToLower();
|
|
if (s.StartsWith("format:", StringComparison.Ordinal))
|
|
{
|
|
if (line.Length > 10)
|
|
{
|
|
var format = line.ToLower().Substring(8).Split(',');
|
|
for (int i = 0; i < format.Length; i++)
|
|
{
|
|
string f = format[i].Trim().ToLower();
|
|
if (f == "name")
|
|
nameIndex = i;
|
|
else if (f == "fontname")
|
|
fontNameIndex = i;
|
|
else if (f == "fontsize")
|
|
fontsizeIndex = i;
|
|
else if (f == "primarycolour")
|
|
primaryColourIndex = i;
|
|
else if (f == "secondarycolour")
|
|
secondaryColourIndex = i;
|
|
else if (f == "tertiarycolour")
|
|
tertiaryColourIndex = i;
|
|
else if (f == "outlinecolour")
|
|
outlineColourIndex = i;
|
|
else if (f == "backcolour")
|
|
backColourIndex = i;
|
|
else if (f == "bold")
|
|
boldIndex = i;
|
|
else if (f == "italic")
|
|
italicIndex = i;
|
|
else if (f == "underline")
|
|
underlineIndex = i;
|
|
else if (f == "outline")
|
|
outlineIndex = i;
|
|
else if (f == "shadow")
|
|
shadowIndex = i;
|
|
else if (f == "alignment")
|
|
alignmentIndex = i;
|
|
else if (f == "marginl")
|
|
marginLIndex = i;
|
|
else if (f == "marginr")
|
|
marginRIndex = i;
|
|
else if (f == "marginv")
|
|
marginVIndex = i;
|
|
else if (f == "borderstyle")
|
|
borderStyleIndex = i;
|
|
}
|
|
}
|
|
}
|
|
else if (s.RemoveChar(' ').StartsWith("style:", StringComparison.Ordinal))
|
|
{
|
|
if (line.Length > 10)
|
|
{
|
|
style.RawLine = line;
|
|
var format = line.Substring(6).Split(',');
|
|
for (int i = 0; i < format.Length; i++)
|
|
{
|
|
string f = format[i].Trim().ToLower();
|
|
if (i == nameIndex)
|
|
{
|
|
style.Name = format[i].Trim();
|
|
}
|
|
else if (i == fontNameIndex)
|
|
{
|
|
style.FontName = f;
|
|
}
|
|
else if (i == fontsizeIndex)
|
|
{
|
|
int number;
|
|
if (int.TryParse(f, out number))
|
|
style.FontSize = number;
|
|
}
|
|
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)
|
|
{
|
|
style.Bold = f == "-1" || f == "1";
|
|
}
|
|
else if (i == italicIndex)
|
|
{
|
|
style.Italic = f == "-1" || f == "1";
|
|
}
|
|
else if (i == underlineIndex)
|
|
{
|
|
style.Underline = f == "-1" || f == "1";
|
|
}
|
|
else if (i == outlineIndex)
|
|
{
|
|
decimal number;
|
|
if (decimal.TryParse(f, out number))
|
|
style.OutlineWidth = number;
|
|
}
|
|
else if (i == shadowIndex)
|
|
{
|
|
decimal number;
|
|
if (decimal.TryParse(f, out number))
|
|
style.ShadowWidth = number;
|
|
}
|
|
else if (i == alignmentIndex)
|
|
{
|
|
style.Alignment = f;
|
|
}
|
|
else if (i == marginLIndex)
|
|
{
|
|
int number;
|
|
if (int.TryParse(f, out number))
|
|
style.MarginLeft = number;
|
|
}
|
|
else if (i == marginRIndex)
|
|
{
|
|
int number;
|
|
if (int.TryParse(f, out number))
|
|
style.MarginRight = number;
|
|
}
|
|
else if (i == marginVIndex)
|
|
{
|
|
int number;
|
|
if (int.TryParse(f, out number))
|
|
style.MarginVertical = number;
|
|
}
|
|
else if (i == borderStyleIndex)
|
|
{
|
|
style.BorderStyle = f;
|
|
}
|
|
}
|
|
}
|
|
if (styleName != null && style.Name != null && (styleName.Equals(style.Name, StringComparison.OrdinalIgnoreCase) ||
|
|
styleName.Equals("*Default", StringComparison.OrdinalIgnoreCase) && style.Name.Equals("Default", StringComparison.OrdinalIgnoreCase)))
|
|
{
|
|
style.LoadedFromHeader = true;
|
|
return style;
|
|
}
|
|
}
|
|
}
|
|
return new SsaStyle { Name = styleName };
|
|
}
|
|
|
|
public override bool HasStyleSupport => true;
|
|
}
|
|
} |