Fix ssa to assa style issue - thx Alain :)

This commit is contained in:
niksedk 2023-01-17 19:11:14 +01:00
parent f37c82d713
commit 6e556022a0
5 changed files with 305 additions and 104 deletions

View File

@ -318,5 +318,163 @@ namespace Nikse.SubtitleEdit.Core.Common
var s = sb.ToString().Trim();
return s.Substring(0, s.Length - 1);
}
public static SsaStyle FromRawSsa(string header, string styleLine)
{
var result = new SsaStyle();
var styleArray = styleLine.Split(',');
var format = GetSsaFormatList(header);
if (styleArray.Length != format.Length)
{
return result;
}
for (var i = 0; i < format.Length; i++)
{
var f = format[i].Trim();
var v = styleArray[i].Trim();
if (f == "name")
{
result.Name = v;
}
else if (f == "fontname")
{
result.FontName = v;
}
else if (f == "fontsize")
{
if (decimal.TryParse(v, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var d))
{
result.FontSize = d;
}
}
else if (f == "primarycolour")
{
result.Primary = AdvancedSubStationAlpha.GetSsaColor(v, Color.White);
}
else if (f == "secondarycolour")
{
result.Secondary = AdvancedSubStationAlpha.GetSsaColor(v, Color.Yellow);
}
else if (f == "tertiarycolour")
{
result.Tertiary = AdvancedSubStationAlpha.GetSsaColor(v, Color.Yellow);
}
else if (f == "backcolour")
{
result.Outline = AdvancedSubStationAlpha.GetSsaColor(v, Color.Black);
}
else if (f == "bold")
{
result.Bold = v != "0";
}
else if (f == "italic")
{
result.Italic = v != "0";
}
else if (f == "outline")
{
if (decimal.TryParse(f, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var number))
{
result.OutlineWidth = number;
}
}
else if (f == "shadow")
{
if (decimal.TryParse(f, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var number))
{
result.ShadowWidth = number;
}
}
else if (f == "marginl")
{
if (int.TryParse(f, out var number))
{
result.MarginLeft = number;
}
}
else if (f == "marginr")
{
if (int.TryParse(f, out var number))
{
result.MarginRight = number;
}
}
else if (f == "marginv")
{
if (int.TryParse(f, out var number))
{
result.MarginVertical = number;
}
}
else if (f == "borderstyle")
{
result.BorderStyle = v;
}
else if (f == "alignment")
{
switch (v)
{
case "1":
result.Alignment = "1"; // bottom left
break;
case "2":
result.Alignment = "2"; // bottom center
break;
case "3":
result.Alignment = "3"; // bottom right
break;
case "9":
result.Alignment = "4"; // middle left
break;
case "10":
result.Alignment = "5"; // middle center
break;
case "11":
result.Alignment = "6"; // middle right
break;
case "5":
result.Alignment = "7"; // top left
break;
case "6":
result.Alignment = "8"; // top center
break;
case "7":
result.Alignment = "9"; // top right
break;
default:
result.Alignment = "2";
break;
}
}
}
return result;
}
private static string[] GetSsaFormatList(string header)
{
if (string.IsNullOrEmpty(header))
{
header = SubStationAlpha.DefaultHeader;
}
foreach (var line in header.SplitToLines())
{
var s = line.Trim().ToLowerInvariant();
if (s.StartsWith("format:"))
{
s = s.Remove(0, "format:".Length).TrimStart().Replace(" ", string.Empty);
return s.Split(',');
}
}
return "Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, TertiaryColour, BackColour, Bold, Italic, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, AlphaLevel, Encoding"
.Replace(" ", string.Empty)
.ToLowerInvariant()
.Split();
}
}
}

View File

@ -94,7 +94,7 @@ namespace Nikse.SubtitleEdit.Core.SubtitleFormats
public static string HeaderNoStyles = @"[Script Info]
; This is an Advanced Sub Station Alpha v4+ script.
Title: {0}
ScriptType: v4.00+" +
ScriptType: v4.00+" +
(Configuration.Settings.SubtitleSettings.AssaShowPlayDepth ? Environment.NewLine + "PlayDepth: 0" : string.Empty) +
(Configuration.Settings.SubtitleSettings.AssaShowScaledBorderAndShadow ? Environment.NewLine + "ScaledBorderAndShadow: Yes" : string.Empty) +
@"
@ -180,7 +180,7 @@ Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text"
style = p.Style;
}
var actor = "";
var actor = string.Empty;
if (!string.IsNullOrEmpty(p.Actor))
{
actor = p.Actor;
@ -204,7 +204,7 @@ Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text"
marginV = p.MarginV;
}
var effect = "";
var effect = string.Empty;
if (!string.IsNullOrEmpty(p.Effect))
{
effect = p.Effect;
@ -246,12 +246,12 @@ Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text"
public static string GetHeaderAndStylesFromSubStationAlpha(string header)
{
var scriptInfo = string.Empty;
header = FixScriptType(header);
if (header != null &&
header.Contains("[Script Info]") &&
header.Contains("ScriptType: v4.00") &&
!header.Contains("ScriptType: v4.00+"))
{
header = FixScriptType(header);
var sb = new StringBuilder();
var scriptInfoOn = false;
foreach (var line in header.SplitToLines())
@ -266,6 +266,12 @@ Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text"
scriptInfoOn = true;
}
if (line.Length > 10 && line.TrimStart().StartsWith("format:", StringComparison.OrdinalIgnoreCase))
{
var s = line.Trim().Remove(0, 7);
var arr = line.Split(',');
}
if (scriptInfoOn)
{
if (line.StartsWith("ScriptType:", StringComparison.OrdinalIgnoreCase))
@ -282,21 +288,28 @@ Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text"
}
}
}
scriptInfo = sb.ToString();
}
else
{
header = FixScriptType(header);
}
var style = GetStyle(header);
if (string.IsNullOrEmpty(scriptInfo) || string.IsNullOrEmpty(style))
var stylesContent = GetStyleContentFromHeader(header);
if (string.IsNullOrEmpty(scriptInfo) || stylesContent.Count == 0)
{
return DefaultHeader;
}
return string.Format($@"{scriptInfo.Trim() + Environment.NewLine}
[V4+ Styles]
{SsaStyle.DefaultAssStyleFormat}
{style.Trim() + Environment.NewLine}
[Events]");
var styles = new List<SsaStyle>();
foreach (var styleAsString in stylesContent)
{
styles.Add(SsaStyle.FromRawSsa(header, styleAsString));
}
header = GetHeaderAndStylesFromAdvancedSubStationAlpha(header, styles);
return header;
}
public static string GetHeaderAndStylesFromAdvancedSubStationAlpha(string header, List<SsaStyle> styles)
@ -919,6 +932,37 @@ Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text"
return list;
}
public static List<string> GetStyleContentFromHeader(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 (var line in headerLines.SplitToLines())
{
if (line.StartsWith("style:", StringComparison.OrdinalIgnoreCase))
{
var end = line.IndexOf(',');
if (end > 0)
{
list.Add(line.Remove(0, 6).Trim());
}
}
}
return list;
}
public static string FormatText(string input)
{
var text = input;
@ -2396,46 +2440,46 @@ Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text"
{
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 strikOutIndex = -1;
int outlineIndex = -1;
int shadowIndex = -1;
int alignmentIndex = -1;
int marginLIndex = -1;
int marginRIndex = -1;
int marginVIndex = -1;
int scaleXIndex = -1;
int scaleYIndex = -1;
int spacingIndex = -1;
int angleIndex = -1;
int borderStyleIndex = -1;
var nameIndex = -1;
var fontNameIndex = -1;
var fontSizeIndex = -1;
var primaryColourIndex = -1;
var secondaryColourIndex = -1;
var tertiaryColourIndex = -1;
var outlineColourIndex = -1;
var backColourIndex = -1;
var boldIndex = -1;
var italicIndex = -1;
var underlineIndex = -1;
var strikeOutIndex = -1;
var outlineIndex = -1;
var shadowIndex = -1;
var alignmentIndex = -1;
var marginLIndex = -1;
var marginRIndex = -1;
var marginVIndex = -1;
var scaleXIndex = -1;
var scaleYIndex = -1;
var spacingIndex = -1;
var angleIndex = -1;
var borderStyleIndex = -1;
if (header == null)
{
header = DefaultHeader;
}
foreach (string line in header.SplitToLines())
foreach (var line in header.SplitToLines())
{
string s = line.Trim().ToLowerInvariant();
var s = line.Trim().ToLowerInvariant();
if (s.StartsWith("format:", StringComparison.Ordinal))
{
if (line.Length > 10)
{
var format = line.ToLowerInvariant().Substring(8).Split(',');
for (int i = 0; i < format.Length; i++)
for (var i = 0; i < format.Length; i++)
{
string f = format[i].Trim().ToLowerInvariant();
var f = format[i].Trim().ToLowerInvariant();
if (f == "name")
{
nameIndex = i;
@ -2446,7 +2490,7 @@ Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text"
}
else if (f == "fontsize")
{
fontsizeIndex = i;
fontSizeIndex = i;
}
else if (f == "primarycolour")
{
@ -2482,7 +2526,7 @@ Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text"
}
else if (f == "strikeout")
{
strikOutIndex = i;
strikeOutIndex = i;
}
else if (f == "outline")
{
@ -2537,9 +2581,9 @@ Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text"
{
style.RawLine = line;
var format = line.Substring(6).Split(',');
for (int i = 0; i < format.Length; i++)
for (var i = 0; i < format.Length; i++)
{
string f = format[i].Trim();
var f = format[i].Trim();
if (i == nameIndex)
{
style.Name = format[i].Trim();
@ -2548,7 +2592,7 @@ Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text"
{
style.FontName = f;
}
else if (i == fontsizeIndex)
else if (i == fontSizeIndex)
{
if (decimal.TryParse(f, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var fOut))
{
@ -2587,7 +2631,7 @@ Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text"
{
style.Underline = f == "-1" || f == "1";
}
else if (i == strikOutIndex)
else if (i == strikeOutIndex)
{
style.Strikeout = f == "-1" || f == "1";
}

View File

@ -143,13 +143,13 @@ Format: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
marginR = p.MarginR.PadLeft(4, '0');
}
string marginV = "0000";
var marginV = "0000";
if (!string.IsNullOrEmpty(p.MarginV) && Utilities.IsInteger(p.MarginV))
{
marginV = p.MarginV.PadLeft(4, '0');
}
string effect = "";
var effect = string.Empty;
if (!string.IsNullOrEmpty(p.Effect))
{
effect = p.Effect;
@ -210,25 +210,25 @@ Format: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
private static string GetStyle(string header)
{
var ttStyles = new StringBuilder();
foreach (string styleName in AdvancedSubStationAlpha.GetStylesFromHeader(header))
foreach (var styleName in AdvancedSubStationAlpha.GetStylesFromHeader(header))
{
try
{
var ssaStyle = AdvancedSubStationAlpha.GetSsaStyle(styleName, header);
string bold = "0";
var bold = "0";
if (ssaStyle.Bold)
{
bold = "-1";
}
string italic = "0";
var italic = "0";
if (ssaStyle.Italic)
{
italic = "-1";
}
string newAlignment = "2";
var newAlignment = "2";
switch (ssaStyle.Alignment)
{
case "1":
@ -306,25 +306,25 @@ Format: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
{
stylexmlCount++;
string fontFamily = "Arial";
var fontFamily = "Arial";
if (node.Attributes["tts:fontFamily"] != null)
{
fontFamily = node.Attributes["tts:fontFamily"].Value;
}
string fontWeight = "normal";
var fontWeight = "normal";
if (node.Attributes["tts:fontWeight"] != null)
{
fontWeight = node.Attributes["tts:fontWeight"].Value;
}
string fontStyle = "normal";
var fontStyle = "normal";
if (node.Attributes["tts:fontStyle"] != null)
{
fontStyle = node.Attributes["tts:fontStyle"].Value;
}
string color = "#ffffff";
var color = "#ffffff";
if (node.Attributes["tts:color"] != null)
{
color = node.Attributes["tts:color"].Value.Trim();
@ -335,7 +335,7 @@ Format: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
{
if (color.StartsWith("rgb(", StringComparison.Ordinal))
{
string[] arr = color.Remove(0, 4).TrimEnd(')').Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
var 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
@ -348,7 +348,7 @@ Format: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
c = Color.White;
}
string fontSize = "20";
var fontSize = "20";
if (node.Attributes["tts:fontSize"] != null)
{
fontSize = node.Attributes["tts:fontSize"].Value.Replace("px", string.Empty).Replace("em", string.Empty);
@ -385,29 +385,29 @@ Format: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
{
_errorCount = 0;
Errors = null;
bool eventsStarted = false;
var eventsStarted = false;
var fontsStarted = false;
var graphicsStarted = false;
subtitle.Paragraphs.Clear();
// "Marked", " Start", " End", " Style", " Name", " MarginL", " MarginR", " MarginV", " Effect", " Text"
int indexLayer = 0;
int indexStart = 1;
int indexEnd = 2;
int indexStyle = 3;
var indexLayer = 0;
var indexStart = 1;
var indexEnd = 2;
var indexStyle = 3;
const int indexName = 4;
int indexMarginL = 5;
int indexMarginR = 6;
int indexMarginV = 7;
int indexEffect = 8;
int indexText = 9;
var indexMarginL = 5;
var indexMarginR = 6;
var indexMarginV = 7;
var indexEffect = 8;
var indexText = 9;
var errors = new StringBuilder();
int lineNumber = 0;
var lineNumber = 0;
var header = new StringBuilder();
var footer = new StringBuilder();
for (int i1 = 0; i1 < lines.Count; i1++)
for (var i1 = 0; i1 < lines.Count; i1++)
{
string line = lines[i1];
var line = lines[i1];
lineNumber++;
if (!eventsStarted)
{
@ -442,11 +442,11 @@ Format: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
}
else if (eventsStarted && !string.IsNullOrWhiteSpace(line))
{
string s = line.Trim().ToLowerInvariant();
var s = line.Trim().ToLowerInvariant();
if (line.Length > 10 && s.StartsWith("format:", StringComparison.Ordinal))
{
var format = s.Substring(8).Split(',');
for (int i = 0; i < format.Length; i++)
for (var i = 0; i < format.Length; i++)
{
var formatTrimmed = format[i].Trim();
if (formatTrimmed.Equals("layer", StringComparison.Ordinal))
@ -532,7 +532,7 @@ Format: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
splitLine = line.Split(',');
}
for (int i = 0; i < splitLine.Length; i++)
for (var i = 0; i < splitLine.Length; i++)
{
if (i == indexStart)
{
@ -656,7 +656,7 @@ Format: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
private static TimeCode GetTimeCodeFromString(string time)
{
// h:mm:ss.cc
string[] timeCode = time.Split(':', '.');
var timeCode = time.Split(':', '.');
return new TimeCode(int.Parse(timeCode[0]),
int.Parse(timeCode[1]),
int.Parse(timeCode[2]),
@ -671,13 +671,13 @@ Format: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
}
else
{
foreach (Paragraph p in subtitle.Paragraphs)
foreach (var p in subtitle.Paragraphs)
{
int indexOfBegin = p.Text.IndexOf('{');
string pre = string.Empty;
var indexOfBegin = p.Text.IndexOf('{');
var pre = string.Empty;
while (indexOfBegin >= 0 && p.Text.IndexOf('}') > indexOfBegin)
{
string s = p.Text.Substring(indexOfBegin);
var s = p.Text.Substring(indexOfBegin);
if (s.StartsWith("{\\an1}", StringComparison.Ordinal) ||
s.StartsWith("{\\an2}", StringComparison.Ordinal) ||
s.StartsWith("{\\an3}", StringComparison.Ordinal) ||
@ -731,11 +731,13 @@ Format: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
{
pre = "{\\an9}";
}
int indexOfEnd = p.Text.IndexOf('}');
var indexOfEnd = p.Text.IndexOf('}');
p.Text = p.Text.Remove(indexOfBegin, (indexOfEnd - indexOfBegin) + 1);
indexOfBegin = p.Text.IndexOf('{');
}
p.Text = pre + p.Text;
}
}
@ -796,5 +798,18 @@ Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, TertiaryColour
{style.Trim() + Environment.NewLine}
[Events]");
}
public static string DefaultHeader
{
get
{
var format = new SubStationAlpha();
var sub = new Subtitle();
var text = format.ToText(sub, string.Empty);
var lines = text.SplitToLines();
format.LoadSubtitle(sub, lines, string.Empty);
return sub.Header;
}
}
}
}

View File

@ -500,7 +500,10 @@ namespace Nikse.SubtitleEdit.Controls
}
}
subtitle.Header = MpvPreviewStyleHeader;
if (subtitle.Header == null || !(subtitle.Header.Contains("[V4+ Styles]") && uiFormat.Name == SubStationAlpha.NameOfFormat))
{
subtitle.Header = MpvPreviewStyleHeader;
}
if (oldSub.Header != null && oldSub.Header.Length > 20 && oldSub.Header.Substring(3, 3) == "STL")
{

View File

@ -328,7 +328,7 @@ namespace Nikse.SubtitleEdit.Forms.Styles
}
}
private List<string> GetFontNames(byte[] fontBytes)
private static List<string> GetFontNames(byte[] fontBytes)
{
var privateFontCollection = new PrivateFontCollection();
var handle = GCHandle.Alloc(fontBytes, GCHandleType.Pinned);
@ -572,25 +572,6 @@ namespace Nikse.SubtitleEdit.Forms.Styles
}
}
private static string FixDuplicateStyleName(string newStyleName, List<SsaStyle> existingStyles)
{
if (existingStyles.All(p => p.Name != newStyleName))
{
return newStyleName;
}
for (int i = 1; i < int.MaxValue; i++)
{
var name = $"{newStyleName}_{i}";
if (existingStyles.All(p => p.Name != name))
{
return name;
}
}
return Guid.NewGuid().ToString();
}
public static void AddStyle(ListView lv, SsaStyle ssaStyle, Subtitle subtitle, bool isSubstationAlpha)
{
AddStyle(lv, ssaStyle, subtitle, isSubstationAlpha, lv.Items.Count);
@ -848,7 +829,7 @@ namespace Nikse.SubtitleEdit.Forms.Styles
return sb.ToString();
}
private void UpdateSelectedIndices(ListView listview, int startingIndex = -1, int numberOfSelectedItems = 1)
private static void UpdateSelectedIndices(ListView listview, int startingIndex = -1, int numberOfSelectedItems = 1)
{
if (numberOfSelectedItems == 0)
{
@ -866,7 +847,7 @@ namespace Nikse.SubtitleEdit.Forms.Styles
}
listview.SelectedItems.Clear();
for (int i = 0; i < numberOfSelectedItems; i++)
for (var i = 0; i < numberOfSelectedItems; i++)
{
listview.Items[startingIndex - i].Selected = true;
listview.Items[startingIndex - i].EnsureVisible();
@ -880,11 +861,11 @@ namespace Nikse.SubtitleEdit.Forms.Styles
if (listViewStyles.SelectedItems.Count == 1)
{
string styleName = listViewStyles.SelectedItems[0].Text;
var styleName = listViewStyles.SelectedItems[0].Text;
_startName = styleName;
_editedName = null;
_oldSsaName = styleName;
SsaStyle style = GetSsaStyleFile(styleName);
var style = GetSsaStyleFile(styleName);
SetControlsFromStyle(style);
_doUpdate = true;
groupBoxProperties.Enabled = true;