mirror of
https://github.com/SubtitleEdit/subtitleedit.git
synced 2024-10-27 22:42:38 +01:00
Added "Advanced Sub Station Alpha" as a separate format (no longer treated as ssa)
git-svn-id: https://subtitleedit.googlecode.com/svn/trunk@484 99eadd0c-20b8-1223-b5c4-2a2b2df33de2
This commit is contained in:
parent
67d8e4602c
commit
dcff9b7324
@ -28,6 +28,8 @@ namespace Nikse.SubtitleEdit.Logic
|
||||
|
||||
public bool Forced { get; set; }
|
||||
|
||||
public string Extra { get; set; }
|
||||
|
||||
public Paragraph()
|
||||
{
|
||||
StartTime = new TimeCode(TimeSpan.FromSeconds(0));
|
||||
|
345
src/Logic/SubtitleFormats/AdvancedSubStationAlpha.cs
Normal file
345
src/Logic/SubtitleFormats/AdvancedSubStationAlpha.cs
Normal file
@ -0,0 +1,345 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Nikse.SubtitleEdit.Logic.SubtitleFormats
|
||||
{
|
||||
class AdvancedSubStationAlpha : SubtitleFormat
|
||||
{
|
||||
public override string Extension
|
||||
{
|
||||
get { return ".ass"; }
|
||||
}
|
||||
|
||||
public override string Name
|
||||
{
|
||||
get { return "Advanced Sub Station Alpha"; }
|
||||
}
|
||||
|
||||
public override bool HasLineNumber
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public override bool IsTimeBased
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
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 (!all.Contains("[V4+ Styles]"))
|
||||
return false;
|
||||
|
||||
LoadSubtitle(subtitle, lines, fileName);
|
||||
return subtitle.Paragraphs.Count > _errorCount;
|
||||
}
|
||||
|
||||
public override string ToText(Subtitle subtitle, string title)
|
||||
{
|
||||
const 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
|
||||
Style: Default,Tahoma,25,&H00FFFFFF,&HF0000000,&H001509AE,&H32270EA8,-1,0,0,0,100,100,0,0.00,1,2,1,2,30,30,10,1
|
||||
|
||||
[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: Marked=0,{0},{1},{3},NTP,0000,0000,0000,,{2}";
|
||||
|
||||
var sb = new StringBuilder();
|
||||
System.Drawing.Color fontColor = System.Drawing.Color.FromArgb(Configuration.Settings.SsaStyle.FontColorArgb);
|
||||
bool isValidAssHeader =!string.IsNullOrEmpty(subtitle.Header) && subtitle.Header.Contains("[V4+ Styles]");
|
||||
List<string> 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
|
||||
{
|
||||
sb.AppendLine(string.Format(header,
|
||||
title,
|
||||
Configuration.Settings.SsaStyle.FontName,
|
||||
(int)Configuration.Settings.SsaStyle.FontSize,
|
||||
System.Drawing.ColorTranslator.ToWin32(fontColor)));
|
||||
}
|
||||
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;
|
||||
sb.AppendLine(string.Format(paragraphWriteFormat, start, end, FormatText(p), style));
|
||||
}
|
||||
return sb.ToString().Trim();
|
||||
}
|
||||
|
||||
public static List<string> GetStylesFromHeader(string headerLines)
|
||||
{
|
||||
List<string> list = new List<string>();
|
||||
foreach (string line in headerLines.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
if (line.StartsWith("Style:"))
|
||||
{
|
||||
int end = line.IndexOf(",");
|
||||
if (end > 0)
|
||||
list.Add(line.Substring(6, end - 6).Trim());
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private static string FormatText(Paragraph p)
|
||||
{
|
||||
string text = p.Text.Replace(Environment.NewLine, "\\N");
|
||||
text = text.Replace("<i>", @"{\i1}");
|
||||
text = text.Replace("</i>", @"{\i0}");
|
||||
text = text.Replace("<u>", @"{\u1}");
|
||||
text = text.Replace("</u>", @"{\u0}");
|
||||
text = text.Replace("<b>", @"{\b1}");
|
||||
text = text.Replace("</b>", @"{\b0}");
|
||||
if (text.Contains("<font "))
|
||||
{
|
||||
int start = text.IndexOf(@"<font ");
|
||||
int end = text.IndexOf('>', start);
|
||||
if (end > 0)
|
||||
{
|
||||
string fontTag = text.Substring(start + 4, end - (start + 4));
|
||||
text = text.Remove(start, end - start + 1);
|
||||
text = text.Replace("</font>", string.Empty);
|
||||
|
||||
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, "color=\"", "\"", "c&H", "&}");
|
||||
fontTag = FormatTag(ref text, start, fontTag, "color='", "'", "c&H", "&}");
|
||||
}
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
private static string FormatTag(ref string text, int start, string fontTag, string tag, string endSign, string ssaTagName, string endSsaTag)
|
||||
{
|
||||
if (fontTag.Contains(tag))
|
||||
{
|
||||
int fontStart = fontTag.IndexOf(tag);
|
||||
int fontEnd = fontTag.IndexOf(endSign, fontStart + tag.Length);
|
||||
if (fontEnd > 0)
|
||||
{
|
||||
string subTag = fontTag.Substring(fontStart + tag.Length, fontEnd - (fontStart + tag.Length));
|
||||
if (tag.Contains("color"))
|
||||
subTag = subTag.Replace("#", string.Empty);
|
||||
fontTag = fontTag.Remove(fontStart, fontEnd - fontStart + 1);
|
||||
text = text.Insert(start, @"{\" + ssaTagName + subTag + endSsaTag);
|
||||
}
|
||||
}
|
||||
return fontTag;
|
||||
}
|
||||
|
||||
private static string GetFormattedText(string text)
|
||||
{
|
||||
text = text.Replace("\\N", Environment.NewLine).Replace("\\n", Environment.NewLine);
|
||||
|
||||
text = text.Replace(@"{\i1}", "<i>");
|
||||
text = text.Replace(@"{\i0}", "</i>");
|
||||
if (Utilities.CountTagInText(text, "<i>") > Utilities.CountTagInText(text, "</i>"))
|
||||
text += "</i>";
|
||||
|
||||
text = text.Replace(@"{\u1}", "<u>");
|
||||
text = text.Replace(@"{\u0}", "</u>");
|
||||
if (Utilities.CountTagInText(text, "<u>") > Utilities.CountTagInText(text, "</u>"))
|
||||
text += "</u>";
|
||||
|
||||
text = text.Replace(@"{\b1}", "<b>");
|
||||
text = text.Replace(@"{\b0}", "</b>");
|
||||
if (Utilities.CountTagInText(text, "<b>") > Utilities.CountTagInText(text, "</b>"))
|
||||
text += "</b>";
|
||||
|
||||
for (int i = 0; i < 5; i++) // just look five times...
|
||||
{
|
||||
if (text.Contains(@"{\fn"))
|
||||
{
|
||||
int start = text.IndexOf(@"{\fn");
|
||||
int end = text.IndexOf('}', start);
|
||||
if (end > 0)
|
||||
{
|
||||
string fontName = text.Substring(start + 4, end - (start + 4));
|
||||
text = text.Remove(start, end - start + 1);
|
||||
text = text.Insert(start, "<font name=\"" + fontName + "\">");
|
||||
text += "</font>";
|
||||
}
|
||||
}
|
||||
|
||||
if (text.Contains(@"{\fs"))
|
||||
{
|
||||
int start = text.IndexOf(@"{\fs");
|
||||
int end = text.IndexOf('}', start);
|
||||
if (end > 0)
|
||||
{
|
||||
string fontSize = text.Substring(start + 4, end - (start + 4));
|
||||
if (Utilities.IsInteger(fontSize))
|
||||
{
|
||||
text = text.Remove(start, end - start + 1);
|
||||
text = text.Insert(start, "<font size=\"" + fontSize + "\">");
|
||||
text += "</font>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (text.Contains(@"{\c"))
|
||||
{
|
||||
int start = text.IndexOf(@"{\c");
|
||||
int end = text.IndexOf('}', start);
|
||||
if (end > 0)
|
||||
{
|
||||
string color = text.Substring(start + 4, end - (start + 4));
|
||||
color = color.Replace("&", string.Empty).TrimStart('H');
|
||||
text = text.Remove(start, end - start + 1);
|
||||
text = text.Insert(start, "<font color=\"" + color + "\">");
|
||||
text += "</font>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
public override void LoadSubtitle(Subtitle subtitle, List<string> lines, string fileName)
|
||||
{
|
||||
_errorCount = 0;
|
||||
bool eventsStarted = false;
|
||||
subtitle.Paragraphs.Clear();
|
||||
string[] format = "Layer, Start, End, Style, Actor, MarginL, MarginR, MarginV, Effect, Text".Split(',');
|
||||
int indexStart = 1;
|
||||
int indexEnd = 2;
|
||||
int indexStyle = 3;
|
||||
int indexText = 9;
|
||||
|
||||
var header = new StringBuilder();
|
||||
foreach (string line in lines)
|
||||
{
|
||||
if (!eventsStarted)
|
||||
header.AppendLine(line);
|
||||
|
||||
if (line.Trim().ToLower() == "[events]")
|
||||
{
|
||||
eventsStarted = true;
|
||||
}
|
||||
else if (eventsStarted)
|
||||
{
|
||||
string s = line.Trim().ToLower();
|
||||
if (s.StartsWith("format:"))
|
||||
{
|
||||
if (line.Length > 10)
|
||||
{
|
||||
format = line.ToLower().Substring(8).Split(',');
|
||||
for (int i = 0; i < format.Length; i++)
|
||||
{
|
||||
if (format[i].Trim().ToLower() == "start")
|
||||
indexStart = i;
|
||||
else if (format[i].Trim().ToLower() == "end")
|
||||
indexEnd = i;
|
||||
else if (format[i].Trim().ToLower() == "text")
|
||||
indexText = i;
|
||||
else if (format[i].Trim().ToLower() == "style")
|
||||
indexStyle = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string text = string.Empty;
|
||||
string start = string.Empty;
|
||||
string end = string.Empty;
|
||||
string style = string.Empty;
|
||||
|
||||
string[] splittedLine;
|
||||
|
||||
if (s.StartsWith("dialogue:"))
|
||||
splittedLine = line.Substring(10).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 == indexText)
|
||||
text = splittedLine[i];
|
||||
else if (i > indexText)
|
||||
text += "," + splittedLine[i];
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var p = new Paragraph();
|
||||
|
||||
p.StartTime = GetTimeCodeFromString(start);
|
||||
p.EndTime = GetTimeCodeFromString(end);
|
||||
p.Text = GetFormattedText(text);
|
||||
if (!string.IsNullOrEmpty(style))
|
||||
p.Extra = style;
|
||||
subtitle.Paragraphs.Add(p);
|
||||
}
|
||||
catch
|
||||
{
|
||||
_errorCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (header.Length > 0)
|
||||
subtitle.Header = header.ToString();
|
||||
subtitle.Renumber(1);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
foreach (Paragraph p in subtitle.Paragraphs)
|
||||
{
|
||||
int indexOfBegin = p.Text.IndexOf("{");
|
||||
while (indexOfBegin >= 0 && p.Text.IndexOf("}") > indexOfBegin)
|
||||
{
|
||||
int indexOfEnd = p.Text.IndexOf("}");
|
||||
p.Text = p.Text.Remove(indexOfBegin, (indexOfEnd - indexOfBegin) + 1);
|
||||
|
||||
indexOfBegin = p.Text.IndexOf("{");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Nikse.SubtitleEdit.Forms;
|
||||
|
||||
namespace Nikse.SubtitleEdit.Logic.SubtitleFormats
|
||||
{
|
||||
@ -52,21 +51,34 @@ Style: Default,{1},{2},{3},65535,65535,-2147483640,-1,0,1,3,0,2,30,30,30,0,0
|
||||
Format: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text";
|
||||
|
||||
const string timeCodeFormat = "{0}:{1:00}:{2:00}.{3:00}"; // h:mm:ss.cc
|
||||
const string paragraphWriteFormat = "Dialogue: Marked=0,{0},{1},Default,NTP,0000,0000,0000,!Effect,{2}";
|
||||
const string paragraphWriteFormat = "Dialogue: Marked=0,{0},{1},{3},NTP,0000,0000,0000,!Effect,{2}";
|
||||
|
||||
var sb = new StringBuilder();
|
||||
System.Drawing.Color fontColor = System.Drawing.Color.FromArgb(Configuration.Settings.SsaStyle.FontColorArgb);
|
||||
sb.AppendLine(string.Format(header,
|
||||
title,
|
||||
Configuration.Settings.SsaStyle.FontName,
|
||||
(int)Configuration.Settings.SsaStyle.FontSize,
|
||||
System.Drawing.ColorTranslator.ToWin32(fontColor)));
|
||||
|
||||
bool isValidAssHeader =!string.IsNullOrEmpty(subtitle.Header) && subtitle.Header.Contains("[V4+ Styles]");
|
||||
List<string> 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 = AdvancedSubStationAlpha.GetStylesFromHeader(subtitle.Header);
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.AppendLine(string.Format(header,
|
||||
title,
|
||||
Configuration.Settings.SsaStyle.FontName,
|
||||
(int)Configuration.Settings.SsaStyle.FontSize,
|
||||
System.Drawing.ColorTranslator.ToWin32(fontColor)));
|
||||
}
|
||||
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);
|
||||
sb.AppendLine(string.Format(paragraphWriteFormat, start, end, FormatText(p)));
|
||||
string style = "Default";
|
||||
if (!string.IsNullOrEmpty(p.Extra) && isValidAssHeader && styles.Contains(p.Extra))
|
||||
style = p.Extra;
|
||||
sb.AppendLine(string.Format(paragraphWriteFormat, start, end, FormatText(p), style));
|
||||
}
|
||||
return sb.ToString().Trim();
|
||||
}
|
||||
@ -197,10 +209,15 @@ Format: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
|
||||
string[] format = "Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text".Split(',');
|
||||
int indexStart = 1;
|
||||
int indexEnd = 2;
|
||||
int indexText = 9;
|
||||
int indexStyle = 3;
|
||||
int indexText = 9;
|
||||
|
||||
var header = new StringBuilder();
|
||||
foreach (string line in lines)
|
||||
{
|
||||
if (!eventsStarted)
|
||||
header.AppendLine(line);
|
||||
|
||||
if (line.Trim().ToLower() == "[events]")
|
||||
{
|
||||
eventsStarted = true;
|
||||
@ -221,6 +238,8 @@ Format: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
|
||||
indexEnd = i;
|
||||
else if (format[i].Trim().ToLower() == "text")
|
||||
indexText = i;
|
||||
else if (format[i].Trim().ToLower() == "style")
|
||||
indexStyle = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -229,6 +248,7 @@ Format: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
|
||||
string text = string.Empty;
|
||||
string start = string.Empty;
|
||||
string end = string.Empty;
|
||||
string style = string.Empty;
|
||||
|
||||
string[] splittedLine;
|
||||
|
||||
@ -256,6 +276,8 @@ Format: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
|
||||
p.StartTime = GetTimeCodeFromString(start);
|
||||
p.EndTime = GetTimeCodeFromString(end);
|
||||
p.Text = GetFormattedText(text);
|
||||
if (!string.IsNullOrEmpty(style))
|
||||
p.Extra = style;
|
||||
subtitle.Paragraphs.Add(p);
|
||||
}
|
||||
catch
|
||||
@ -265,6 +287,8 @@ Format: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
|
||||
}
|
||||
}
|
||||
}
|
||||
if (header.Length > 0)
|
||||
subtitle.Header = header.ToString();
|
||||
subtitle.Renumber(1);
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@ namespace Nikse.SubtitleEdit.Logic.SubtitleFormats
|
||||
new AdobeEncore(),
|
||||
new AdobeEncoreTab(),
|
||||
new AdobeEncoreWithLineNumbers(),
|
||||
new AdvancedSubStationAlpha(),
|
||||
new AQTitle(),
|
||||
new Captionate(),
|
||||
new CaraokeXml(),
|
||||
|
@ -537,6 +537,7 @@
|
||||
<Compile Include="Logic\SubtitleFormats\AdobeEncore.cs" />
|
||||
<Compile Include="Logic\SubtitleFormats\AdobeEncoreTabs.cs" />
|
||||
<Compile Include="Logic\SubtitleFormats\AdobeEncoreWithLineNumbers.cs" />
|
||||
<Compile Include="Logic\SubtitleFormats\AdvancedSubStationAlpha.cs" />
|
||||
<Compile Include="Logic\SubtitleFormats\AQTitle.cs" />
|
||||
<Compile Include="Logic\SubtitleFormats\BdnXml.cs" />
|
||||
<Compile Include="Logic\SubtitleFormats\Captionate.cs" />
|
||||
|
Loading…
Reference in New Issue
Block a user