private void FillStyles() { listViewStyles.Columns[listViewStyles.Columns.Count - 1].Width = -2; var styles = new List <string>(); var formatType = _format.GetType(); if (formatType == typeof(AdvancedSubStationAlpha) || formatType == typeof(SubStationAlpha)) { styles = AdvancedSubStationAlpha.GetStylesFromHeader(_subtitle.Header); } else if (formatType == typeof(TimedText10) || formatType == typeof(ItunesTimedText)) { styles = TimedText10.GetStylesFromHeader(_subtitle.Header); } else if (formatType == typeof(Sami) || formatType == typeof(SamiModern)) { styles = _subtitle.Header == null?Sami.GetStylesFromSubtitle(_subtitle) : Sami.GetStylesFromHeader(_subtitle.Header); } listViewStyles.Items.Clear(); foreach (var style in styles.OrderBy(p => p)) { listViewStyles.Items.Add(style); } }
private void FillStyles() { listViewStyles.AutoSizeLastColumn(); var styles = new List <string>(); var formatType = _format.GetType(); if (formatType == typeof(AdvancedSubStationAlpha) || formatType == typeof(SubStationAlpha)) { styles = AdvancedSubStationAlpha.GetStylesFromHeader(_subtitle.Header); } else if (formatType == typeof(TimedText10) || formatType == typeof(ItunesTimedText)) { styles = TimedText10.GetStylesFromHeader(_subtitle.Header); } else if (formatType == typeof(Sami) || formatType == typeof(SamiModern)) { styles = _subtitle.Header == null?Sami.GetStylesFromSubtitle(_subtitle) : Sami.GetStylesFromHeader(_subtitle.Header); } _loading = true; listViewStyles.Items.Clear(); listViewStyles.Items.AddRange(styles.OrderBy(p => p).Select(p => new ListViewItem { Text = p }).ToArray()); _loading = false; }
public SubStationAlphaStylesExport(string header, bool isSubStationAlpha, SubtitleFormat format) { InitializeComponent(); UiUtil.FixFonts(this); _header = header; _isSubStationAlpha = isSubStationAlpha; _format = format; var styles = AdvancedSubStationAlpha.GetStylesFromHeader(_header); listViewExportStyles.Columns[0].Width = listViewExportStyles.Width - 20; foreach (var style in styles) { listViewExportStyles.Items.Add(new ListViewItem(style) { Checked = true }); } Text = LanguageSettings.Current.SubStationAlphaStyles.Export; labelStyles.Text = LanguageSettings.Current.SubStationAlphaStyles.Styles; toolStripMenuItemInverseSelection.Text = LanguageSettings.Current.Main.Menu.Edit.InverseSelection; toolStripMenuItemSelectAll.Text = LanguageSettings.Current.Main.Menu.ContextMenu.SelectAll; buttonOK.Text = LanguageSettings.Current.General.Ok; buttonCancel.Text = LanguageSettings.Current.General.Cancel; }
private void FillStyles() { listViewStyles.AutoSizeLastColumn(); var styles = AdvancedSubStationAlpha.GetStylesFromHeader(_subtitle.Header); var oldLoading = _loading; _loading = true; listViewStyles.Items.Clear(); listViewStyles.Items.AddRange(styles.OrderBy(p => p).Select(p => new ListViewItem { Text = p }).ToArray()); _loading = oldLoading; }
private void InitializeListView() { var styles = AdvancedSubStationAlpha.GetStylesFromHeader(_subtitle.Header); listViewStyles.Items.Clear(); foreach (string style in styles) { SsaStyle ssaStyle = AdvancedSubStationAlpha.GetSsaStyle(style, _subtitle.Header); SubStationAlphaStyles.AddStyle(listViewStyles, ssaStyle, _subtitle, _isSubStationAlpha); } if (listViewStyles.Items.Count > 0) { listViewStyles.Items[0].Selected = true; } }
public static string SubStationAlphaHeaderToTimedText(Subtitle subtitle) { var x = new XmlDocument(); x.LoadXml(new TimedText10().ToText(new Subtitle(), "tt")); // load default xml var xnsmgr = new XmlNamespaceManager(x.NameTable); xnsmgr.AddNamespace("ttml", "http://www.w3.org/ns/ttml"); var styleHead = x.DocumentElement.SelectSingleNode("ttml:head", xnsmgr); styleHead.SelectSingleNode("ttml:styling", xnsmgr).RemoveAll(); foreach (string styleName in AdvancedSubStationAlpha.GetStylesFromHeader(subtitle.Header)) { try { var ssaStyle = AdvancedSubStationAlpha.GetSsaStyle(styleName, subtitle.Header); if (ssaStyle != null) { string fontStyle = "normal"; if (ssaStyle.Italic) { fontStyle = "italic"; } string fontWeight = "normal"; if (ssaStyle.Bold) { fontWeight = "bold"; } AddStyleToXml(x, styleHead, xnsmgr, ssaStyle.Name, ssaStyle.FontName, fontWeight, fontStyle, Utilities.ColorToHex(ssaStyle.Primary), ssaStyle.FontSize.ToString(CultureInfo.InvariantCulture)); } } catch { // ignored } } return(x.OuterXml); }
public SubStationAlphaStylesExport(string header, bool isSubStationAlpha, SubtitleFormat format) { InitializeComponent(); _header = header; _isSubStationAlpha = isSubStationAlpha; _format = format; _styles = AdvancedSubStationAlpha.GetStylesFromHeader(_header); listViewExportStyles.Columns[0].Width = listViewExportStyles.Width - 20; foreach (var style in _styles) { listViewExportStyles.Items.Add(new ListViewItem(style) { Checked = true }); } Text = Configuration.Settings.Language.SubStationAlphaStyles.Export; labelStyles.Text = Configuration.Settings.Language.SubStationAlphaStyles.Styles; buttonOK.Text = Configuration.Settings.Language.General.Ok; buttonCancel.Text = Configuration.Settings.Language.General.Cancel; }
public override string ToText(Subtitle subtitle, string title) { const string header = @"[Script Info] ; This is a Sub Station Alpha v4 script. Title: {0} ScriptType: v4.00 Collisions: Normal PlayDepth: 0 [V4 Styles] Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, TertiaryColour, BackColour, Bold, Italic, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, AlphaLevel, Encoding Style: Default,{1},{2},{3},65535,65535,-2147483640,-1,0,1,{4},{5},2,10,10,10,0,1 [Events] Format: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text"; const string headerNoStyles = @"[Script Info] ; This is a Sub Station Alpha v4 script. Title: {0} ScriptType: v4.00 Collisions: Normal PlayDepth: 0 [V4 Styles] Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, TertiaryColour, BackColour, Bold, Italic, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, AlphaLevel, Encoding {1} [Events] 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={4},{0},{1},{3},{5},0000,0000,0000,{6},{2}"; const string commentWriteFormat = "Comment: Marked={4},{0},{1},{3},{5},0000,0000,0000,{6},{2}"; var sb = new StringBuilder(); Color fontColor = Color.White; bool isValidAssHeader = !string.IsNullOrEmpty(subtitle.Header) && subtitle.Header.Contains("[V4 Styles]"); var styles = new List <string>(); if (isValidAssHeader) { sb.AppendLine(subtitle.Header.Trim()); const string formatLine = "Format: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text"; if (!subtitle.Header.Contains(formatLine)) { sb.AppendLine(formatLine); } styles = AdvancedSubStationAlpha.GetStylesFromHeader(subtitle.Header); } else if (!string.IsNullOrEmpty(subtitle.Header) && subtitle.Header.Contains("[V4+ Styles]")) { LoadStylesFromAdvancedSubstationAlpha(subtitle, title, subtitle.Header, headerNoStyles, sb); } else { sb.AppendLine(string.Format(header, title, "Arial", 20, ColorTranslator.ToWin32(fontColor), 2, 1 )); } 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"; string actor = "NTP"; if (!string.IsNullOrEmpty(p.Actor)) { actor = p.Actor; } string effect = ""; if (!string.IsNullOrEmpty(p.Effect)) { effect = p.Effect; } if (!string.IsNullOrEmpty(p.Extra) && isValidAssHeader && styles.Contains(p.Extra)) { style = p.Extra; } if (style == "Default") { style = "*Default"; } if (p.IsComment) { sb.AppendLine(string.Format(commentWriteFormat, start, end, AdvancedSubStationAlpha.FormatText(p), style, p.Layer, actor, effect)); } else { sb.AppendLine(string.Format(paragraphWriteFormat, start, end, AdvancedSubStationAlpha.FormatText(p), style, p.Layer, actor, effect)); } } return(sb.ToString().Trim()); }
private static void LoadStylesFromAdvancedSubstationAlpha(Subtitle subtitle, string title, string header, string headerNoStyles, StringBuilder sb) { try { bool styleFound = false; var ttStyles = new StringBuilder(); foreach (string styleName in AdvancedSubStationAlpha.GetStylesFromHeader(subtitle.Header)) { try { var ssaStyle = AdvancedSubStationAlpha.GetSsaStyle(styleName, subtitle.Header); if (ssaStyle != null) { string bold = "-1"; if (ssaStyle.Bold) { bold = "1"; } string italic = "0"; if (ssaStyle.Italic) { italic = "1"; } string newAlignment = "2"; switch (ssaStyle.Alignment) { case "1": newAlignment = "1"; break; case "3": newAlignment = "3"; break; case "4": newAlignment = "9"; break; case "5": newAlignment = "10"; break; case "6": newAlignment = "11"; break; case "7": newAlignment = "5"; break; case "8": newAlignment = "6"; break; case "9": newAlignment = "7"; break; } //Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, TertiaryColour, BackColour, Bold, Italic, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, AlphaLevel, Encoding const string styleFormat = "Style: {0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12},{13},{14},{15},0,1"; // N FN FS PC SC TC BC Bo It BS O Sh Ali ML MR MV A Encoding ttStyles.AppendLine(string.Format(styleFormat, ssaStyle.Name, ssaStyle.FontName, ssaStyle.FontSize, ssaStyle.Primary.ToArgb(), ssaStyle.Secondary.ToArgb(), ssaStyle.Outline.ToArgb(), ssaStyle.Background.ToArgb(), bold, italic, ssaStyle.BorderStyle, ssaStyle.OutlineWidth, ssaStyle.ShadowWidth, newAlignment, ssaStyle.MarginLeft, ssaStyle.MarginRight, ssaStyle.MarginVertical)); styleFound = true; } } catch { } } 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 override string ToText(Subtitle subtitle, string title) { XmlNode styleHead = null; bool convertedFromSubStationAlpha = false; if (subtitle.Header != null) { try { var x = new XmlDocument(); x.LoadXml(subtitle.Header); var xnsmgr = new XmlNamespaceManager(x.NameTable); xnsmgr.AddNamespace("ttml", "http://www.w3.org/ns/ttml"); styleHead = x.DocumentElement.SelectSingleNode("ttml:head", xnsmgr); } catch { styleHead = null; } if (styleHead == null && (subtitle.Header.Contains("[V4+ Styles]") || subtitle.Header.Contains("[V4 Styles]"))) { var x = new XmlDocument(); x.LoadXml(new ItunesTimedText().ToText(new Subtitle(), "tt")); // load default xml var xnsmgr = new XmlNamespaceManager(x.NameTable); xnsmgr.AddNamespace("ttml", "http://www.w3.org/ns/ttml"); styleHead = x.DocumentElement.SelectSingleNode("ttml:head", xnsmgr); styleHead.SelectSingleNode("ttml:styling", xnsmgr).RemoveAll(); foreach (string styleName in AdvancedSubStationAlpha.GetStylesFromHeader(subtitle.Header)) { try { var ssaStyle = AdvancedSubStationAlpha.GetSsaStyle(styleName, subtitle.Header); string fontStyle = "normal"; if (ssaStyle.Italic) { fontStyle = "italic"; } string fontWeight = "normal"; if (ssaStyle.Bold) { fontWeight = "bold"; } AddStyleToXml(x, styleHead, xnsmgr, ssaStyle.Name, ssaStyle.FontName, fontWeight, fontStyle, Utilities.ColorToHex(ssaStyle.Primary), ssaStyle.FontSize.ToString()); convertedFromSubStationAlpha = true; } catch { // ignored } } subtitle.Header = x.OuterXml; // save new xml with styles in header } } var xml = new XmlDocument { XmlResolver = null }; var nsmgr = new XmlNamespaceManager(xml.NameTable); nsmgr.AddNamespace("ttml", "http://www.w3.org/ns/ttml"); nsmgr.AddNamespace("ttp", "http://www.w3.org/ns/10/ttml#parameter"); nsmgr.AddNamespace("tts", "http://www.w3.org/ns/ttml#styling"); nsmgr.AddNamespace("ttm", "http://www.w3.org/ns/10/ttml#metadata"); string frameRate = ((int)Math.Round(Configuration.Settings.General.CurrentFrameRate)).ToString(); string frameRateMultiplier = "999 1000"; if (Configuration.Settings.General.CurrentFrameRate % 1.0 < 0.01) { frameRateMultiplier = "1 1"; } string dropMode = "nonDrop"; if (Math.Abs(Configuration.Settings.General.CurrentFrameRate - 29.97) < 0.01) { dropMode = "dropNTSC"; } const string language = "en-US"; string xmlStructure = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>" + Environment.NewLine + "<tt xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://www.w3.org/ns/ttml\" xmlns:tt=\"http://www.w3.org/ns/ttml\" xmlns:tts=\"http://www.w3.org/ns/ttml#styling\" xmlns:ttp=\"http://www.w3.org/ns/ttml#parameter\" xml:lang=\"" + language + "\" ttp:timeBase=\"smpte\" ttp:frameRate=\"" + frameRate + "\" ttp:frameRateMultiplier=\"" + frameRateMultiplier + "\" ttp:dropMode=\"" + dropMode + "\">" + Environment.NewLine + " <head>" + Environment.NewLine + " <styling>" + Environment.NewLine + " <style tts:fontSize=\"100%\" tts:color=\"white\" tts:fontStyle=\"normal\" tts:fontWeight=\"normal\" tts:fontFamily=\"sansSerif\" xml:id=\"normal\"/>" + Environment.NewLine + " <style tts:fontSize=\"100%\" tts:color=\"white\" tts:fontStyle=\"normal\" tts:fontWeight=\"bold\" tts:fontFamily=\"sansSerif\" xml:id=\"bold\"/>" + Environment.NewLine + " <style tts:fontSize=\"100%\" tts:color=\"white\" tts:fontStyle=\"italic\" tts:fontWeight=\"normal\" tts:fontFamily=\"sansSerif\" xml:id=\"italic\"/>" + Environment.NewLine + " </styling>" + Environment.NewLine + " <layout>" + Environment.NewLine + " <region xml:id=\"top\" tts:origin=\"0% 0%\" tts:extent=\"100% 15%\" tts:textAlign=\"center\" tts:displayAlign=\"before\"/>" + Environment.NewLine + " <region xml:id=\"bottom\" tts:origin=\"0% 85%\" tts:extent=\"100% 15%\" tts:textAlign=\"center\" tts:displayAlign=\"after\"/>" + Environment.NewLine + " </layout>" + Environment.NewLine + " </head>" + Environment.NewLine + " <body>" + Environment.NewLine + " <div />" + Environment.NewLine + " </body>" + Environment.NewLine + "</tt>"; if (styleHead == null) { xml.LoadXml(xmlStructure); } else { try { xml.LoadXml(subtitle.Header); XmlNode divNode = xml.DocumentElement.SelectSingleNode("//ttml:body", nsmgr).SelectSingleNode("ttml:div", nsmgr); if (divNode == null) { divNode = xml.DocumentElement.SelectSingleNode("//ttml:body", nsmgr).FirstChild; } if (divNode != null) { var lst = new List <XmlNode>(); foreach (XmlNode child in divNode.ChildNodes) { lst.Add(child); } foreach (XmlNode child in lst) { divNode.RemoveChild(child); } } else { xml.LoadXml(xmlStructure); } } catch { xml.LoadXml(xmlStructure); } } XmlNode body = xml.DocumentElement.SelectSingleNode("ttml:body", nsmgr); string defaultStyle = Guid.NewGuid().ToString(); if (body.Attributes["style"] != null) { defaultStyle = body.Attributes["style"].InnerText; } XmlNode div = xml.DocumentElement.SelectSingleNode("//ttml:body", nsmgr).SelectSingleNode("ttml:div", nsmgr); if (div == null) { div = xml.DocumentElement.SelectSingleNode("//ttml:body", nsmgr).FirstChild; } bool hasBottomRegion = false; bool hasTopRegion = false; foreach (XmlNode node in xml.DocumentElement.SelectNodes("//ttml:head/ttml:layout/ttml:region", nsmgr)) { string id = null; if (node.Attributes["xml:id"] != null) { id = node.Attributes["xml:id"].Value; } else if (node.Attributes["id"] != null) { id = node.Attributes["id"].Value; } if (id != null && id == "bottom") { hasBottomRegion = true; } if (id != null && id == "top") { hasTopRegion = true; } } var headerStyles = GetStylesFromHeader(subtitle.Header); foreach (Paragraph p in subtitle.Paragraphs) { XmlNode paragraph = xml.CreateElement("p", "http://www.w3.org/ns/ttml"); string text = p.Text; XmlAttribute regionP = xml.CreateAttribute("region"); if (text.StartsWith("{\\an7}", StringComparison.Ordinal) || text.StartsWith("{\\an8}", StringComparison.Ordinal) || text.StartsWith("{\\an9}", StringComparison.Ordinal)) { if (hasTopRegion) { regionP.InnerText = "top"; paragraph.Attributes.Append(regionP); } } else if (hasBottomRegion) { regionP.InnerText = "bottom"; paragraph.Attributes.Append(regionP); } if (text.StartsWith("{\\an", StringComparison.Ordinal) && text.Length > 6 && text[5] == '}') { text = text.Remove(0, 6); } if (convertedFromSubStationAlpha) { if (string.IsNullOrEmpty(p.Style)) { p.Style = p.Extra; } } if (subtitle.Header != null && p.Style != null && headerStyles.Contains(p.Style)) { if (p.Style != defaultStyle) { XmlAttribute styleAttr = xml.CreateAttribute("style"); styleAttr.InnerText = p.Style; paragraph.Attributes.Append(styleAttr); } } else if (!string.IsNullOrEmpty(p.Style)) { XmlAttribute styleP = xml.CreateAttribute("style"); styleP.InnerText = p.Style; paragraph.Attributes.Append(styleP); } bool first = true; bool italicOn = false; foreach (string line in text.SplitToLines()) { if (!first) { XmlNode br = xml.CreateElement("br", "http://www.w3.org/ns/ttml"); paragraph.AppendChild(br); } Stack <XmlNode> styles = new Stack <XmlNode>(); XmlNode currentStyle = xml.CreateTextNode(string.Empty); paragraph.AppendChild(currentStyle); int skipCount = 0; for (int i = 0; i < line.Length; i++) { if (skipCount > 0) { skipCount--; } else if (line.Substring(i).StartsWith("<i>", StringComparison.OrdinalIgnoreCase)) { styles.Push(currentStyle); currentStyle = xml.CreateNode(XmlNodeType.Element, "span", null); paragraph.AppendChild(currentStyle); XmlAttribute attr = xml.CreateAttribute("tts:fontStyle", "http://www.w3.org/ns/ttml#styling"); attr.InnerText = "italic"; currentStyle.Attributes.Append(attr); skipCount = 2; italicOn = true; } else if (line.Substring(i).StartsWith("<b>", StringComparison.OrdinalIgnoreCase)) { currentStyle = xml.CreateNode(XmlNodeType.Element, "span", null); paragraph.AppendChild(currentStyle); XmlAttribute attr = xml.CreateAttribute("tts:fontWeight", "http://www.w3.org/ns/ttml#styling"); attr.InnerText = "bold"; currentStyle.Attributes.Append(attr); skipCount = 2; } else if (line.Substring(i).StartsWith("<font ", StringComparison.OrdinalIgnoreCase)) { int endIndex = line.Substring(i + 1).IndexOf('>'); if (endIndex > 0) { skipCount = endIndex + 1; string fontContent = line.Substring(i, skipCount); if (fontContent.Contains(" color=", StringComparison.OrdinalIgnoreCase)) { var arr = fontContent.Substring(fontContent.IndexOf(" color=", StringComparison.OrdinalIgnoreCase) + 7).Trim().Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (arr.Length > 0) { string fontColor = arr[0].Trim('\'').Trim('"').Trim('\''); currentStyle = xml.CreateNode(XmlNodeType.Element, "span", null); paragraph.AppendChild(currentStyle); XmlAttribute attr = xml.CreateAttribute("tts:color", "http://www.w3.org/ns/ttml#styling"); attr.InnerText = fontColor; currentStyle.Attributes.Append(attr); } } } else { skipCount = line.Length; } } else if (line.Substring(i).StartsWith("</i>", StringComparison.OrdinalIgnoreCase) || line.Substring(i).StartsWith("</b>", StringComparison.OrdinalIgnoreCase) || line.Substring(i).StartsWith("</font>", StringComparison.OrdinalIgnoreCase)) { currentStyle = xml.CreateTextNode(string.Empty); if (styles.Count > 0) { currentStyle = styles.Pop().CloneNode(true); currentStyle.InnerText = string.Empty; } paragraph.AppendChild(currentStyle); if (line.Substring(i).StartsWith("</font>", StringComparison.OrdinalIgnoreCase)) { skipCount = 6; } else { skipCount = 3; } italicOn = false; } else { if (i == 0 && italicOn && !line.Substring(i).StartsWith("<i>", StringComparison.OrdinalIgnoreCase)) { styles.Push(currentStyle); currentStyle = xml.CreateNode(XmlNodeType.Element, "span", null); paragraph.AppendChild(currentStyle); XmlAttribute attr = xml.CreateAttribute("tts:fontStyle", "http://www.w3.org/ns/ttml#styling"); attr.InnerText = "italic"; currentStyle.Attributes.Append(attr); } currentStyle.InnerText += line[i]; } } first = false; } XmlAttribute start = xml.CreateAttribute("begin"); start.InnerText = ConvertToTimeString(p.StartTime); paragraph.Attributes.Append(start); XmlAttribute end = xml.CreateAttribute("end"); end.InnerText = ConvertToTimeString(p.EndTime); paragraph.Attributes.Append(end); div.AppendChild(paragraph); } string xmlString = ToUtf8XmlString(xml).Replace(" xmlns=\"\"", string.Empty).Replace("<br />", "<br/>"); if (subtitle.Header == null) { subtitle.Header = xmlString; } return(xmlString); }
public override string ToText(Subtitle subtitle, string title) { XmlNode styleHead = null; if (subtitle.Header != null) { try { var x = new XmlDocument(); x.LoadXml(subtitle.Header); var xnsmgr = new XmlNamespaceManager(x.NameTable); xnsmgr.AddNamespace("ttml", "http://www.w3.org/ns/ttml"); styleHead = x.DocumentElement.SelectSingleNode("ttml:head", xnsmgr); } catch { } if (styleHead == null && (subtitle.Header.Contains("[V4+ Styles]") || subtitle.Header.Contains("[V4 Styles]"))) { var x = new XmlDocument(); x.LoadXml(new TimedText10().ToText(new Subtitle(), "tt")); // load default xml var xnsmgr = new XmlNamespaceManager(x.NameTable); xnsmgr.AddNamespace("ttml", "http://www.w3.org/ns/ttml"); styleHead = x.DocumentElement.SelectSingleNode("ttml:head", xnsmgr); styleHead.SelectSingleNode("ttml:styling", xnsmgr).RemoveAll(); foreach (string styleName in AdvancedSubStationAlpha.GetStylesFromHeader(subtitle.Header)) { try { var ssaStyle = AdvancedSubStationAlpha.GetSsaStyle(styleName, subtitle.Header); if (ssaStyle != null) { string fontStyle = "normal"; if (ssaStyle.Italic) { fontStyle = "italic"; } string fontWeight = "normal"; if (ssaStyle.Bold) { fontWeight = "bold"; } AddStyleToXml(x, styleHead, xnsmgr, ssaStyle.Name, ssaStyle.FontName, fontWeight, fontStyle, Utilities.ColorToHex(ssaStyle.Primary), ssaStyle.FontSize.ToString(CultureInfo.InvariantCulture)); } } catch { } } subtitle.Header = x.OuterXml; // save new xml with styles in header } } var xml = new XmlDocument(); var nsmgr = new XmlNamespaceManager(xml.NameTable); nsmgr.AddNamespace("ttml", "http://www.w3.org/ns/ttml"); nsmgr.AddNamespace("ttp", "http://www.w3.org/ns/10/ttml#parameter"); nsmgr.AddNamespace("tts", "http://www.w3.org/ns/10/ttml#style"); nsmgr.AddNamespace("ttm", "http://www.w3.org/ns/10/ttml#metadata"); string xmlStructure = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>" + Environment.NewLine + "<tt xmlns=\"http://www.w3.org/ns/ttml\" xmlns:ttp=\"http://www.w3.org/ns/ttml#parameter\" ttp:timeBase=\"media\" xmlns:tts=\"http://www.w3.org/ns/ttml#style\" xml:lang=\"en\" xmlns:ttm=\"http://www.w3.org/ns/ttml#metadata\">" + Environment.NewLine + " <head>" + Environment.NewLine + " <metadata>" + Environment.NewLine + " <ttm:title></ttm:title>" + Environment.NewLine + " </metadata>" + Environment.NewLine + " <styling>" + Environment.NewLine + " <style id=\"s0\" tts:backgroundColor=\"black\" tts:fontStyle=\"normal\" tts:fontSize=\"16\" tts:fontFamily=\"sansSerif\" tts:color=\"white\" />" + Environment.NewLine + " </styling>" + Environment.NewLine + " </head>" + Environment.NewLine + " <body style=\"s0\">" + Environment.NewLine + " <div />" + Environment.NewLine + " </body>" + Environment.NewLine + "</tt>"; if (styleHead == null) { xml.LoadXml(xmlStructure); } else { xml.LoadXml(subtitle.Header); XmlNode bodyNode = xml.DocumentElement.SelectSingleNode("//ttml:body", nsmgr); XmlNode divNode = bodyNode.SelectSingleNode("ttml:div", nsmgr); if (divNode == null) { divNode = xml.DocumentElement.SelectSingleNode("//ttml:body", nsmgr).FirstChild; } if (divNode != null) { // Remove all but first div int innerNodeCount = 0; var innerNodeList = new List <XmlNode>(); foreach (XmlNode innerNode in bodyNode.SelectNodes("ttml:div", nsmgr)) { if (innerNodeCount > 0) { innerNodeList.Add(innerNode); } innerNodeCount++; } foreach (XmlNode child in innerNodeList) { bodyNode.RemoveChild(child); } var lst = new List <XmlNode>(); foreach (XmlNode child in divNode.ChildNodes) { lst.Add(child); } foreach (XmlNode child in lst) { divNode.RemoveChild(child); } } else { xml.LoadXml(xmlStructure); } } XmlNode body = xml.DocumentElement.SelectSingleNode("ttml:body", nsmgr); string defaultStyle = Guid.NewGuid().ToString(); if (body.Attributes["style"] != null) { defaultStyle = body.Attributes["style"].InnerText; } XmlNode div = xml.DocumentElement.SelectSingleNode("//ttml:body", nsmgr).SelectSingleNode("ttml:div", nsmgr); if (div == null) { div = xml.DocumentElement.SelectSingleNode("//ttml:body", nsmgr).FirstChild; } int no = 0; var headerStyles = GetStylesFromHeader(subtitle.Header); var regions = GetRegionsFromHeader(subtitle.Header); var languages = GetUsedLanguages(subtitle); if (languages.Count > 0) { var divParentNode = div.ParentNode; foreach (Paragraph p in subtitle.Paragraphs) { if (p.Language == null) { if (p.NewSection) { div = xml.CreateElement("div", "http://www.w3.org/ns/ttml"); divParentNode.AppendChild(div); } XmlNode paragraph = MakeParagraph(subtitle, xml, defaultStyle, no, headerStyles, regions, p); div.AppendChild(paragraph); no++; } } foreach (string language in languages) { div = xml.CreateElement("div", "http://www.w3.org/ns/ttml"); XmlAttribute attr = xml.CreateAttribute("xml:lang", "http://www.w3.org/XML/1998/namespace"); attr.Value = language; div.Attributes.Append(attr); divParentNode.AppendChild(div); bool firstParagraph = true; foreach (Paragraph p in subtitle.Paragraphs) { if (p.Language == language) { if (p.NewSection && !firstParagraph) { div = xml.CreateElement("div", "http://www.w3.org/ns/ttml"); attr = xml.CreateAttribute("xml:lang", "http://www.w3.org/XML/1998/namespace"); attr.Value = language; div.Attributes.Append(attr); divParentNode.AppendChild(div); } firstParagraph = false; XmlNode paragraph = MakeParagraph(subtitle, xml, defaultStyle, no, headerStyles, regions, p); div.AppendChild(paragraph); no++; } } } if (divParentNode != null && divParentNode.HasChildNodes && !divParentNode.FirstChild.HasChildNodes) { divParentNode.RemoveChild(divParentNode.FirstChild); } } else { var divParentNode = div.ParentNode; foreach (Paragraph p in subtitle.Paragraphs) { if (p.NewSection) { div = xml.CreateElement("div", "http://www.w3.org/ns/ttml"); divParentNode.AppendChild(div); } XmlNode paragraph = MakeParagraph(subtitle, xml, defaultStyle, no, headerStyles, regions, p); div.AppendChild(paragraph); no++; } if (divParentNode != null && divParentNode.HasChildNodes && !divParentNode.FirstChild.HasChildNodes) { divParentNode.RemoveChild(divParentNode.FirstChild); } } return(ToUtf8XmlString(xml).Replace(" xmlns=\"\"", string.Empty).Replace(" xmlns:tts=\"http://www.w3.org/ns/10/ttml#style\">", ">")); }
private static string GetStyle(string header) { var ttStyles = new StringBuilder(); foreach (string styleName in AdvancedSubStationAlpha.GetStylesFromHeader(header)) { try { var ssaStyle = AdvancedSubStationAlpha.GetSsaStyle(styleName, header); string bold = "0"; if (ssaStyle.Bold) { bold = "-1"; } string italic = "0"; if (ssaStyle.Italic) { italic = "-1"; } string newAlignment = "2"; switch (ssaStyle.Alignment) { case "1": newAlignment = "1"; break; case "3": newAlignment = "3"; break; case "4": newAlignment = "9"; break; case "5": newAlignment = "10"; break; case "6": newAlignment = "11"; break; case "7": newAlignment = "5"; break; case "8": newAlignment = "6"; break; case "9": newAlignment = "7"; break; } //Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, TertiaryColour, BackColour, Bold, Italic, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, AlphaLevel, Encoding const string styleFormat = "Style: {0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12},{13},{14},{15},0,1"; // N FN FS PC SC TC BC Bo It BS O Sh Ali ML MR MV A Encoding ttStyles.AppendLine(string.Format(styleFormat, ssaStyle.Name, ssaStyle.FontName, ssaStyle.FontSize, ssaStyle.Primary.ToArgb(), ssaStyle.Secondary.ToArgb(), ssaStyle.Outline.ToArgb(), ssaStyle.Background.ToArgb(), bold, italic, ssaStyle.BorderStyle, ssaStyle.OutlineWidth.ToString(CultureInfo.InvariantCulture), ssaStyle.ShadowWidth.ToString(CultureInfo.InvariantCulture), newAlignment, ssaStyle.MarginLeft, ssaStyle.MarginRight, ssaStyle.MarginVertical)); } catch { // ignored } } return(ttStyles.ToString()); }
public override string ToText(Subtitle subtitle, string title) { var convertedFromSubStationAlpha = false; if (subtitle.Header != null) { XmlNode styleHead = null; try { var x = new XmlDocument(); x.LoadXml(subtitle.Header); var xnsmgr = new XmlNamespaceManager(x.NameTable); xnsmgr.AddNamespace("ttml", "http://www.w3.org/ns/ttml"); if (x.DocumentElement != null) { styleHead = x.DocumentElement.SelectSingleNode("ttml:head", xnsmgr); } } catch { styleHead = null; } if (styleHead == null && (subtitle.Header.Contains("[V4+ Styles]") || subtitle.Header.Contains("[V4 Styles]"))) { var x = new XmlDocument(); x.LoadXml(new ItunesTimedText().ToText(new Subtitle(), "tt")); // load default xml var xnsmgr = new XmlNamespaceManager(x.NameTable); xnsmgr.AddNamespace("ttml", "http://www.w3.org/ns/ttml"); if (x.DocumentElement != null) { styleHead = x.DocumentElement.SelectSingleNode("ttml:head", xnsmgr); styleHead.SelectSingleNode("ttml:styling", xnsmgr).RemoveAll(); foreach (var styleName in AdvancedSubStationAlpha.GetStylesFromHeader(subtitle.Header)) { try { var ssaStyle = AdvancedSubStationAlpha.GetSsaStyle(styleName, subtitle.Header); var fontStyle = "normal"; if (ssaStyle.Italic) { fontStyle = "italic"; } var fontWeight = "normal"; if (ssaStyle.Bold) { fontWeight = "bold"; } AddStyleToXml(x, styleHead, xnsmgr, ssaStyle.Name, ssaStyle.FontName, fontWeight, fontStyle, Utilities.ColorToHex(ssaStyle.Primary), ssaStyle.FontSize.ToString()); convertedFromSubStationAlpha = true; } catch { // ignored } } } subtitle.Header = x.OuterXml; // save new xml with styles in header } } var xml = new XmlDocument { XmlResolver = null }; var nsmgr = new XmlNamespaceManager(xml.NameTable); nsmgr.AddNamespace("ttml", "http://www.w3.org/ns/ttml"); nsmgr.AddNamespace("ttp", "http://www.w3.org/ns/10/ttml#parameter"); nsmgr.AddNamespace("tts", "http://www.w3.org/ns/10/ttml#style"); nsmgr.AddNamespace("ttm", "http://www.w3.org/ns/10/ttml#metadata"); const string xmlStructure = @"<?xml version='1.0' encoding='utf-8'?> <tt xmlns='http://www.w3.org/ns/ttml' xmlns:ttm='http://www.w3.org/ns/ttml#metadata' xmlns:tts='http://www.w3.org/ns/ttml#styling' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xml:lang='en'> <head> <metadata> <ttm:title>Netflix Subtitle</ttm:title> </metadata> <styling> <style tts:fontStyle='normal' tts:fontWeight='normal' xml:id='s1' tts:color='white' tts:fontFamily='Arial' tts:fontSize='100%'></style> </styling> <layout> <region tts:extent='80% 40%' tts:origin='10% 10%' tts:displayAlign='before' tts:textAlign='center' xml:id='topCenter' /> <region tts:extent='80% 40%' tts:origin='10% 50%' tts:displayAlign='after' tts:textAlign='center' xml:id='bottomCenter' /> </layout> </head> <body> <div style='s1' xml:id='d1'></div> </body> </tt>"; xml.LoadXml(xmlStructure); if (!string.IsNullOrWhiteSpace(title)) { var headNode = xml.DocumentElement.SelectSingleNode("//ttml:head", nsmgr); var metadataNode = headNode?.SelectSingleNode("ttml:metadata", nsmgr); var titleNode = metadataNode?.FirstChild; if (titleNode != null) { titleNode.InnerText = "Netflix Subtitle for " + title; } } var div = xml.DocumentElement.SelectSingleNode("//ttml:body", nsmgr).SelectSingleNode("ttml:div", nsmgr); var hasBottomCenterRegion = false; var hasTopCenterRegion = false; foreach (XmlNode node in xml.DocumentElement.SelectNodes("//ttml:head/ttml:layout/ttml:region", nsmgr)) { string id = null; if (node.Attributes["xml:id"] != null) { id = node.Attributes["xml:id"].Value; } else if (node.Attributes["id"] != null) { id = node.Attributes["id"].Value; } if (id != null && id == "bottomCenter") { hasBottomCenterRegion = true; } if (id != null && id == "topCenter") { hasTopCenterRegion = true; } } var no = 0; foreach (var p in subtitle.Paragraphs) { XmlNode paragraph = xml.CreateElement("p", "http://www.w3.org/ns/ttml"); var text = p.Text; XmlAttribute pid = xml.CreateAttribute("xml:id"); pid.InnerText = "p" + ++no; paragraph.Attributes.Append(pid); XmlAttribute start = xml.CreateAttribute("begin"); start.InnerText = string.Format(CultureInfo.InvariantCulture, "{0:00}:{1:00}:{2:00}.{3:000}", p.StartTime.Hours, p.StartTime.Minutes, p.StartTime.Seconds, p.StartTime.Milliseconds); paragraph.Attributes.Append(start); XmlAttribute end = xml.CreateAttribute("end"); end.InnerText = string.Format(CultureInfo.InvariantCulture, "{0:00}:{1:00}:{2:00}.{3:000}", p.EndTime.Hours, p.EndTime.Minutes, p.EndTime.Seconds, p.EndTime.Milliseconds); paragraph.Attributes.Append(end); XmlAttribute regionP = xml.CreateAttribute("region"); if (text.StartsWith("{\\an7}", StringComparison.Ordinal) || text.StartsWith("{\\an8}", StringComparison.Ordinal) || text.StartsWith("{\\an9}", StringComparison.Ordinal)) { if (hasTopCenterRegion) { regionP.InnerText = "topCenter"; paragraph.Attributes.Append(regionP); } } else if (hasBottomCenterRegion) { regionP.InnerText = "bottomCenter"; paragraph.Attributes.Append(regionP); } if (text.StartsWith("{\\an", StringComparison.Ordinal) && text.Length > 6 && text[5] == '}') { text = text.Remove(0, 6); } if (convertedFromSubStationAlpha) { if (string.IsNullOrEmpty(p.Style)) { p.Style = p.Extra; } } var first = true; var italicOn = false; var boldOn = false; var fontColors = new Stack <string>(); foreach (var line in text.SplitToLines()) { if (!first) { XmlNode br = xml.CreateElement("br", "http://www.w3.org/ns/ttml"); paragraph.AppendChild(br); } var styles = new Stack <XmlNode>(); XmlNode currentStyle = xml.CreateTextNode(string.Empty); paragraph.AppendChild(currentStyle); var skipCount = 0; for (var i = 0; i < line.Length; i++) { if (skipCount > 0) { skipCount--; } else if (line.Substring(i).StartsWith("<i>", StringComparison.OrdinalIgnoreCase)) { styles.Push(currentStyle); currentStyle = xml.CreateNode(XmlNodeType.Element, "span", null); paragraph.AppendChild(currentStyle); XmlAttribute attr = xml.CreateAttribute("tts:fontStyle", "http://www.w3.org/ns/10/ttml#style"); attr.InnerText = "italic"; currentStyle.Attributes.Append(attr); skipCount = 2; italicOn = true; } else if (line.Substring(i).StartsWith("<b>", StringComparison.OrdinalIgnoreCase)) { currentStyle = xml.CreateNode(XmlNodeType.Element, "span", null); paragraph.AppendChild(currentStyle); XmlAttribute attr = xml.CreateAttribute("tts:fontWeight", "http://www.w3.org/ns/10/ttml#style"); attr.InnerText = "bold"; currentStyle.Attributes.Append(attr); skipCount = 2; boldOn = true; } else if (line.Substring(i).StartsWith("<font ", StringComparison.OrdinalIgnoreCase)) { var fontColorAdded = false; var endIndex = line.Substring(i + 1).IndexOf('>'); if (endIndex > 0) { skipCount = endIndex + 1; var fontContent = line.Substring(i, skipCount); if (fontContent.Contains(" color=", StringComparison.OrdinalIgnoreCase)) { var arr = fontContent.Substring(fontContent.IndexOf(" color=", StringComparison.Ordinal) + 7).Trim().Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (arr.Length > 0) { var fontColor = arr[0].Trim('\'').Trim('"').Trim('\''); currentStyle = xml.CreateNode(XmlNodeType.Element, "span", null); paragraph.AppendChild(currentStyle); XmlAttribute attr = xml.CreateAttribute("tts:color", "http://www.w3.org/ns/10/ttml#style"); attr.InnerText = fontColor; currentStyle.Attributes.Append(attr); fontColors.Push(fontColor); fontColorAdded = true; } } } else { skipCount = line.Length; } if (!fontColorAdded) { fontColors.Push(string.Empty); } } else if (line.Substring(i).StartsWith("</font>", StringComparison.OrdinalIgnoreCase)) { fontColors.Pop(); skipCount = 6; currentStyle = xml.CreateTextNode(string.Empty); if (styles.Count > 0) { currentStyle = styles.Pop().CloneNode(true); currentStyle.InnerText = string.Empty; } if (styles.Count == 0) { currentStyle = xml.CreateTextNode(string.Empty); paragraph.AppendChild(currentStyle); } } else if (line.Substring(i).StartsWith("</i>", StringComparison.OrdinalIgnoreCase) || line.Substring(i).StartsWith("</b>", StringComparison.OrdinalIgnoreCase) || line.Substring(i).StartsWith("</font>", StringComparison.OrdinalIgnoreCase)) { currentStyle = xml.CreateTextNode(string.Empty); if (styles.Count > 0) { currentStyle = styles.Pop().CloneNode(true); currentStyle.InnerText = string.Empty; } paragraph.AppendChild(currentStyle); if (line.Substring(i).StartsWith("</font>", StringComparison.OrdinalIgnoreCase)) { skipCount = 6; fontColors.Pop(); } else { skipCount = 3; } italicOn = false; } else { if (i == 0 && italicOn && !line.Substring(i).StartsWith("<i>", StringComparison.OrdinalIgnoreCase)) { styles.Push(currentStyle); currentStyle = xml.CreateNode(XmlNodeType.Element, "span", null); paragraph.AppendChild(currentStyle); XmlAttribute attr = xml.CreateAttribute("tts:fontStyle", "http://www.w3.org/ns/10/ttml#style"); attr.InnerText = "italic"; currentStyle.Attributes.Append(attr); } else if (i == 0 && boldOn && !line.Substring(i).StartsWith("<b>", StringComparison.OrdinalIgnoreCase)) { styles.Push(currentStyle); currentStyle = xml.CreateNode(XmlNodeType.Element, "span", null); paragraph.AppendChild(currentStyle); XmlAttribute attr = xml.CreateAttribute("tts:fontWeight", "http://www.w3.org/ns/10/ttml#style"); attr.InnerText = "bold"; currentStyle.Attributes.Append(attr); } else if (i == 0 && fontColors.Count > 0 && !line.Substring(i).StartsWith("<font ", StringComparison.OrdinalIgnoreCase)) { var fontColor = fontColors.Peek(); if (!string.IsNullOrEmpty(fontColor)) { styles.Push(currentStyle); currentStyle = xml.CreateNode(XmlNodeType.Element, "span", null); paragraph.AppendChild(currentStyle); XmlAttribute attr = xml.CreateAttribute("tts:color", "http://www.w3.org/ns/10/ttml#style"); attr.InnerText = fontColor; currentStyle.Attributes.Append(attr); } } currentStyle.InnerText += line[i]; } } first = false; } div.AppendChild(paragraph); } var xmlString = ToUtf8XmlString(xml).Replace(" xmlns=\"\"", string.Empty).Replace(" xmlns:tts=\"http://www.w3.org/ns/10/ttml#style\">", ">").Replace("<br />", "<br/>"); if (subtitle.Header == null) { subtitle.Header = xmlString; } return(xmlString); }
public override string ToText(Subtitle subtitle, string title) { const string header = @"[Script Info] ; This is a Sub Station Alpha v4 script. Title: {0} ScriptType: v4.00 Collisions: Normal PlayDepth: 0 [V4 Styles] Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, TertiaryColour, BackColour, Bold, Italic, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, AlphaLevel, Encoding Style: Default,{1},{2},{3},65535,65535,-2147483640,{9},0,1,{4},{5},2,{6},{7},{8},0,1 [Events] 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={4},{0},{1},{3},{5},{6},{7},{8},{9},{2}"; const string commentWriteFormat = "Comment: Marked={4},{0},{1},{3},{5},{6},{7},{8},{9},{2}"; var sb = new StringBuilder(); var isValidSsaHeader = !string.IsNullOrEmpty(subtitle.Header) && subtitle.Header.Contains("[V4 Styles]"); var styles = new List <string>(); if (isValidSsaHeader) { sb.AppendLine(subtitle.Header.Trim()); const string formatLine = "Format: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text"; if (!subtitle.Header.Contains(formatLine)) { sb.AppendLine(formatLine); } styles = AdvancedSubStationAlpha.GetStylesFromHeader(subtitle.Header); } else if (!string.IsNullOrEmpty(subtitle.Header) && subtitle.Header.Contains("[V4+ Styles]")) { LoadStylesFromAdvancedSubstationAlpha(subtitle, title, subtitle.Header, HeaderNoStyles, sb); isValidSsaHeader = true; styles = AdvancedSubStationAlpha.GetStylesFromHeader(subtitle.Header); } else if (subtitle.Header != null && subtitle.Header.Contains("http://www.w3.org/ns/ttml")) { LoadStylesFromTimedText10(subtitle, title, header, HeaderNoStyles, sb); } else { SsaStyle style = null; var storageCategories = Configuration.Settings.SubtitleSettings.AssaStyleStorageCategories; if (storageCategories != null && storageCategories.Count > 0 && storageCategories.Exists(x => x.IsDefault)) { var defaultStyle = storageCategories.FirstOrDefault(x => x.IsDefault)?.Styles.FirstOrDefault(x => x.Name.ToLowerInvariant() == "default"); style = defaultStyle ?? storageCategories.FirstOrDefault(x => x.IsDefault)?.Styles[0]; } style = style ?? new SsaStyle(); var boldStyle = "0"; // 0=regular if (style.Bold) { boldStyle = "-1"; // -1 = true, 0 is false } sb.AppendLine(string.Format(header, title, style.FontName, style.FontSize, ColorTranslator.ToWin32(style.Primary), style.OutlineWidth, style.ShadowWidth, style.MarginLeft, style.MarginRight, style.MarginVertical, boldStyle )); } foreach (var p in subtitle.Paragraphs) { var start = string.Format(timeCodeFormat, p.StartTime.Hours, p.StartTime.Minutes, p.StartTime.Seconds, p.StartTime.Milliseconds / 10); var end = string.Format(timeCodeFormat, p.EndTime.Hours, p.EndTime.Minutes, p.EndTime.Seconds, p.EndTime.Milliseconds / 10); var style = "Default"; var actor = "NTP"; if (!string.IsNullOrEmpty(p.Actor)) { actor = p.Actor; } var marginL = "0000"; if (!string.IsNullOrEmpty(p.MarginL) && Utilities.IsInteger(p.MarginL)) { marginL = p.MarginL.PadLeft(4, '0'); } var marginR = "0000"; if (!string.IsNullOrEmpty(p.MarginR) && Utilities.IsInteger(p.MarginR)) { marginR = p.MarginR.PadLeft(4, '0'); } string marginV = "0000"; if (!string.IsNullOrEmpty(p.MarginV) && Utilities.IsInteger(p.MarginV)) { marginV = p.MarginV.PadLeft(4, '0'); } string effect = ""; if (!string.IsNullOrEmpty(p.Effect)) { effect = p.Effect; } if (!string.IsNullOrEmpty(p.Extra) && isValidSsaHeader && styles.Contains(p.Extra)) { style = p.Extra; } if (style == "Default") { style = "*Default"; } var text = p.Text.Replace(Environment.NewLine, "\\N"); if (p.IsComment) { sb.AppendLine(string.Format(commentWriteFormat, start, end, AdvancedSubStationAlpha.FormatText(text), style, p.Layer, actor, marginL, marginR, marginV, effect)); } else { sb.AppendLine(string.Format(paragraphWriteFormat, start, end, AdvancedSubStationAlpha.FormatText(text), style, p.Layer, actor, marginL, marginR, marginV, effect)); } } if (!string.IsNullOrEmpty(subtitle.Footer) && (subtitle.Footer.Contains("[Fonts]" + Environment.NewLine) || subtitle.Footer.Contains("[Graphics]" + Environment.NewLine) || subtitle.Footer.Contains("[Aegisub Extradata]" + Environment.NewLine))) { sb.AppendLine(); sb.AppendLine(subtitle.Footer); } return(sb.ToString().Trim() + Environment.NewLine); }
public override string ToText(Subtitle subtitle, string title) { bool convertedFromSubStationAlpha = false; if (subtitle.Header != null) { XmlNode styleHead = null; try { var x = new XmlDocument(); x.LoadXml(subtitle.Header); var xnsmgr = new XmlNamespaceManager(x.NameTable); xnsmgr.AddNamespace("ttml", "http://www.w3.org/ns/ttml"); if (x.DocumentElement != null) { styleHead = x.DocumentElement.SelectSingleNode("ttml:head", xnsmgr); } } catch { styleHead = null; } if (styleHead == null && (subtitle.Header.Contains("[V4+ Styles]") || subtitle.Header.Contains("[V4 Styles]"))) { var x = new XmlDocument(); x.LoadXml(new ItunesTimedText().ToText(new Subtitle(), "tt")); // load default xml var xnsmgr = new XmlNamespaceManager(x.NameTable); xnsmgr.AddNamespace("ttml", "http://www.w3.org/ns/ttml"); if (x.DocumentElement != null) { styleHead = x.DocumentElement.SelectSingleNode("ttml:head", xnsmgr); styleHead.SelectSingleNode("ttml:styling", xnsmgr).RemoveAll(); foreach (string styleName in AdvancedSubStationAlpha.GetStylesFromHeader(subtitle.Header)) { try { var ssaStyle = AdvancedSubStationAlpha.GetSsaStyle(styleName, subtitle.Header); string fontStyle = "normal"; if (ssaStyle.Italic) { fontStyle = "italic"; } string fontWeight = "normal"; if (ssaStyle.Bold) { fontWeight = "bold"; } AddStyleToXml(x, styleHead, xnsmgr, ssaStyle.Name, ssaStyle.FontName, fontWeight, fontStyle, Utilities.ColorToHex(ssaStyle.Primary), ssaStyle.FontSize.ToString()); convertedFromSubStationAlpha = true; } catch { // ignored } } } subtitle.Header = x.OuterXml; // save new xml with styles in header } } var xml = new XmlDocument { XmlResolver = null }; var nsmgr = new XmlNamespaceManager(xml.NameTable); foreach (var ns in NameSpaces) { nsmgr.AddNamespace(ns.Prefix, ns.Url); } string xmlStructure = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>" + Environment.NewLine + "<tt " + BuildRootElementAttributes() + ">" + Environment.NewLine + " <head>" + Environment.NewLine + " <metadata>" + Environment.NewLine + " <ttm:title>" + title + "</ttm:title>" + Environment.NewLine + " <ttm:desc>Automatically generated by Subtitle Edit</ttm:desc>" + Environment.NewLine + " </metadata>" + Environment.NewLine + " <styling>" + Environment.NewLine + " <style tts:fontStyle=\"normal\" tts:fontWeight=\"normal\" xml:id=\"s1\" tts:color=\"white\" tts:fontFamily=\"Arial\" tts:fontSize=\"100%\"></style>" + Environment.NewLine + " </styling>" + Environment.NewLine + " <layout>" + Environment.NewLine + " <region tts:extent=\"80% 40%\" tts:origin=\"10% 10%\" tts:displayAlign=\"before\" tts:textAlign=\"center\" xml:id=\"topCenter\" />" + Environment.NewLine + " <region tts:extent=\"80% 40%\" tts:origin=\"10% 50%\" tts:displayAlign=\"after\" tts:textAlign=\"center\" xml:id=\"bottomCenter\" />" + Environment.NewLine + " </layout>" + Environment.NewLine + " </head>" + Environment.NewLine + " <body>" + Environment.NewLine + " <div style=\"s1\" xml:id=\"d1\"></div>" + Environment.NewLine + " </body>" + Environment.NewLine + "</tt>"; xml.LoadXml(xmlStructure); var div = xml.DocumentElement.SelectSingleNode("//ttml:body", nsmgr).SelectSingleNode("ttml:div", nsmgr); bool hasBottomCenterRegion = false; bool hasTopCenterRegion = false; foreach (XmlNode node in xml.DocumentElement.SelectNodes("//ttml:head/ttml:layout/ttml:region", nsmgr)) { string id = null; if (node.Attributes["xml:id"] != null) { id = node.Attributes["xml:id"].Value; } else if (node.Attributes["id"] != null) { id = node.Attributes["id"].Value; } if (id != null && id == "bottomCenter") { hasBottomCenterRegion = true; } if (id != null && id == "topCenter") { hasTopCenterRegion = true; } } var relevantParagraphs = subtitle.Paragraphs; if (RemoveInformationalParagraph) { relevantParagraphs.RemoveAll(p => p.StartFrame == 0); } int no = 0; foreach (var p in relevantParagraphs) { XmlNode paragraph = xml.CreateElement("p", "http://www.w3.org/ns/ttml"); string text = p.Text; XmlAttribute pid = xml.CreateAttribute("xml:id"); pid.InnerText = "p" + ++no; paragraph.Attributes.Append(pid); XmlAttribute start = xml.CreateAttribute("begin"); start.InnerText = ConvertToTimeString(p.StartTime); paragraph.Attributes.Append(start); XmlAttribute end = xml.CreateAttribute("end"); end.InnerText = ConvertToTimeString(p.EndTime); paragraph.Attributes.Append(end); XmlAttribute regionP = xml.CreateAttribute("region"); if (text.StartsWith("{\\an7}", StringComparison.Ordinal) || text.StartsWith("{\\an8}", StringComparison.Ordinal) || text.StartsWith("{\\an9}", StringComparison.Ordinal)) { if (hasTopCenterRegion) { regionP.InnerText = "topCenter"; paragraph.Attributes.Append(regionP); } } else if (hasBottomCenterRegion) { regionP.InnerText = "bottomCenter"; paragraph.Attributes.Append(regionP); } if (text.StartsWith("{\\an", StringComparison.Ordinal) && text.Length > 6 && text[5] == '}') { text = text.Remove(0, 6); } if (convertedFromSubStationAlpha) { if (string.IsNullOrEmpty(p.Style)) { p.Style = p.Extra; } } bool first = true; bool italicOn = false; foreach (string line in text.SplitToLines()) { if (!first) { XmlNode br = xml.CreateElement("br", "http://www.w3.org/ns/ttml"); paragraph.AppendChild(br); } var styles = new Stack <XmlNode>(); XmlNode currentStyle = xml.CreateTextNode(string.Empty); paragraph.AppendChild(currentStyle); int skipCount = 0; for (int i = 0; i < line.Length; i++) { if (skipCount > 0) { skipCount--; } else if (line.Substring(i).StartsWith("<i>", StringComparison.Ordinal)) { styles.Push(currentStyle); currentStyle = xml.CreateNode(XmlNodeType.Element, "span", null); paragraph.AppendChild(currentStyle); XmlAttribute attr = xml.CreateAttribute("tts:fontStyle", "http://www.w3.org/ns/10/ttml#style"); attr.InnerText = "italic"; currentStyle.Attributes.Append(attr); skipCount = 2; italicOn = true; } else if (line.Substring(i).StartsWith("<b>", StringComparison.Ordinal)) { currentStyle = xml.CreateNode(XmlNodeType.Element, "span", null); paragraph.AppendChild(currentStyle); XmlAttribute attr = xml.CreateAttribute("tts:fontWeight", "http://www.w3.org/ns/10/ttml#style"); attr.InnerText = "bold"; currentStyle.Attributes.Append(attr); skipCount = 2; } else if (line.Substring(i).StartsWith("<font ", StringComparison.Ordinal)) { int endIndex = line.Substring(i + 1).IndexOf('>'); if (endIndex > 0) { skipCount = endIndex + 1; string fontContent = line.Substring(i, skipCount); if (fontContent.Contains(" color=")) { var arr = fontContent.Substring(fontContent.IndexOf(" color=", StringComparison.Ordinal) + 7).Trim().Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (arr.Length > 0) { string fontColor = arr[0].Trim('\'').Trim('"').Trim('\''); currentStyle = xml.CreateNode(XmlNodeType.Element, "span", null); paragraph.AppendChild(currentStyle); XmlAttribute attr = xml.CreateAttribute("tts:color", "http://www.w3.org/ns/10/ttml#style"); attr.InnerText = fontColor; currentStyle.Attributes.Append(attr); } } } else { skipCount = line.Length; } } else if (line.Substring(i).StartsWith("</i>", StringComparison.Ordinal) || line.Substring(i).StartsWith("</b>", StringComparison.Ordinal) || line.Substring(i).StartsWith("</font>", StringComparison.Ordinal)) { currentStyle = xml.CreateTextNode(string.Empty); if (styles.Count > 0) { currentStyle = styles.Pop().CloneNode(true); currentStyle.InnerText = string.Empty; } paragraph.AppendChild(currentStyle); if (line.Substring(i).StartsWith("</font>", StringComparison.Ordinal)) { skipCount = 6; } else { skipCount = 3; } italicOn = false; } else { if (i == 0 && italicOn && !(line.Substring(i).StartsWith("<i>", StringComparison.Ordinal))) { styles.Push(currentStyle); currentStyle = xml.CreateNode(XmlNodeType.Element, "span", null); paragraph.AppendChild(currentStyle); XmlAttribute attr = xml.CreateAttribute("tts:fontStyle", "http://www.w3.org/ns/10/ttml#style"); attr.InnerText = "italic"; currentStyle.Attributes.Append(attr); } currentStyle.InnerText = currentStyle.InnerText + line[i]; } } first = false; } div.AppendChild(paragraph); } string xmlString = ToUtf8XmlString(xml).Replace(" xmlns=\"\"", string.Empty).Replace(" xmlns:tts=\"http://www.w3.org/ns/10/ttml#style\">", ">").Replace("<br />", "<br/>"); if (subtitle.Header == null) { subtitle.Header = xmlString; } return(xmlString); }
private void SortAndLoad() { JoinedFormat = new SubRip(); // default subtitle format string header = null; SubtitleFormat lastFormat = null; var subtitles = new List <Subtitle>(); for (int k = 0; k < _fileNamesToJoin.Count; k++) { var fileName = _fileNamesToJoin[k]; try { var sub = new Subtitle(); SubtitleFormat format = null; if (fileName.EndsWith(".ismt", StringComparison.InvariantCultureIgnoreCase) || fileName.EndsWith(".mp4", StringComparison.InvariantCultureIgnoreCase) || fileName.EndsWith(".m4v", StringComparison.InvariantCultureIgnoreCase) || fileName.EndsWith(".3gp", StringComparison.InvariantCultureIgnoreCase)) { format = new IsmtDfxp(); if (format.IsMine(null, fileName)) { var s = new Subtitle(); format.LoadSubtitle(s, null, fileName); if (s.Paragraphs.Count > 0) { lastFormat = format; } } } var lines = FileUtil.ReadAllLinesShared(fileName, LanguageAutoDetect.GetEncodingFromFile(fileName)); if (lastFormat != null && lastFormat.IsMine(lines, fileName)) { format = lastFormat; format.LoadSubtitle(sub, lines, fileName); } if (sub.Paragraphs.Count == 0 || format == null) { format = sub.LoadSubtitle(fileName, out _, null); } if (format == null && lines.Count > 0 && lines.Count < 10 && lines[0].Trim() == "WEBVTT") { format = new WebVTT(); // empty WebVTT } if (format == null) { foreach (var binaryFormat in SubtitleFormat.GetBinaryFormats(true)) { if (binaryFormat.IsMine(null, fileName)) { binaryFormat.LoadSubtitle(sub, null, fileName); format = binaryFormat; break; } } } if (format == null) { foreach (var f in SubtitleFormat.GetTextOtherFormats()) { if (f.IsMine(lines, fileName)) { f.LoadSubtitle(sub, lines, fileName); format = f; break; } } } if (format == null) { Revert(k, LanguageSettings.Current.UnknownSubtitle.Title + Environment.NewLine + fileName); break; } if (sub.Header != null) { if (format.Name == AdvancedSubStationAlpha.NameOfFormat && header != null) { var oldPlayResX = AdvancedSubStationAlpha.GetTagFromHeader("PlayResX", "[Script Info]", header); var oldPlayResY = AdvancedSubStationAlpha.GetTagFromHeader("PlayResY", "[Script Info]", header); var newPlayResX = AdvancedSubStationAlpha.GetTagFromHeader("PlayResX", "[Script Info]", sub.Header); var newPlayResY = AdvancedSubStationAlpha.GetTagFromHeader("PlayResY", "[Script Info]", sub.Header); var stylesInHeader = AdvancedSubStationAlpha.GetStylesFromHeader(header); var styles = new List <SsaStyle>(); foreach (var styleName in stylesInHeader) { styles.Add(AdvancedSubStationAlpha.GetSsaStyle(styleName, header)); } foreach (var newStyle in AdvancedSubStationAlpha.GetStylesFromHeader(sub.Header)) { if (stylesInHeader.Any(p => p == newStyle)) { var styleToBeRenamed = AdvancedSubStationAlpha.GetSsaStyle(newStyle, sub.Header); var newName = styleToBeRenamed.Name + "_" + Guid.NewGuid(); foreach (var p in sub.Paragraphs.Where(p => p.Extra == styleToBeRenamed.Name)) { p.Extra = newName; } styleToBeRenamed.Name = newName; styles.Add(styleToBeRenamed); } else { styles.Add(AdvancedSubStationAlpha.GetSsaStyle(newStyle, sub.Header)); } } header = AdvancedSubStationAlpha.GetHeaderAndStylesFromAdvancedSubStationAlpha(header, styles); if (!string.IsNullOrEmpty(oldPlayResX) && string.IsNullOrEmpty(newPlayResX)) { header = AdvancedSubStationAlpha.AddTagToHeader("PlayResX", oldPlayResX, "[Script Info]", header); } if (!string.IsNullOrEmpty(oldPlayResY) && string.IsNullOrEmpty(newPlayResY)) { header = AdvancedSubStationAlpha.AddTagToHeader("PlayResY", oldPlayResY, "[Script Info]", header); } } else { header = sub.Header; } } lastFormat = lastFormat == null || lastFormat.FriendlyName == format.FriendlyName ? format : new SubRip(); subtitles.Add(sub); } catch (Exception exception) { Revert(k, exception.Message); return; } } JoinedFormat = lastFormat; if (!radioButtonJoinAddTime.Checked) { for (int outer = 0; outer < subtitles.Count; outer++) { for (int inner = 1; inner < subtitles.Count; inner++) { var a = subtitles[inner - 1]; var b = subtitles[inner]; if (a.Paragraphs.Count > 0 && b.Paragraphs.Count > 0 && a.Paragraphs[0].StartTime.TotalMilliseconds > b.Paragraphs[0].StartTime.TotalMilliseconds) { var t1 = _fileNamesToJoin[inner - 1]; _fileNamesToJoin[inner - 1] = _fileNamesToJoin[inner]; _fileNamesToJoin[inner] = t1; var t2 = subtitles[inner - 1]; subtitles[inner - 1] = subtitles[inner]; subtitles[inner] = t2; } } } } listViewParts.BeginUpdate(); listViewParts.Items.Clear(); int i = 0; foreach (var fileName in _fileNamesToJoin) { var sub = subtitles[i]; var lvi = new ListViewItem($"{sub.Paragraphs.Count:#,###,###}"); if (sub.Paragraphs.Count > 0) { lvi.SubItems.Add(sub.Paragraphs[0].StartTime.ToString()); lvi.SubItems.Add(sub.Paragraphs[sub.Paragraphs.Count - 1].StartTime.ToString()); } else { lvi.SubItems.Add("-"); lvi.SubItems.Add("-"); } lvi.SubItems.Add(fileName); listViewParts.Items.Add(lvi); i++; } listViewParts.EndUpdate(); JoinedSubtitle = new Subtitle(); if (JoinedFormat != null && JoinedFormat.FriendlyName != SubRip.NameOfFormat) { JoinedSubtitle.Header = header; } var addTime = radioButtonJoinAddTime.Checked; foreach (var sub in subtitles) { double addMs = 0; if (addTime && JoinedSubtitle.Paragraphs.Count > 0) { addMs = JoinedSubtitle.Paragraphs.Last().EndTime.TotalMilliseconds + Convert.ToDouble(numericUpDownAddMs.Value); } foreach (var p in sub.Paragraphs) { p.StartTime.TotalMilliseconds += addMs; p.EndTime.TotalMilliseconds += addMs; JoinedSubtitle.Paragraphs.Add(p); } } JoinedSubtitle.Renumber(); labelTotalLines.Text = string.Format(LanguageSettings.Current.JoinSubtitles.TotalNumberOfLinesX, JoinedSubtitle.Paragraphs.Count); }
public override string ToText(Subtitle subtitle, string title) { bool convertedFromSubStationAlpha = false; if (subtitle.Header != null) { XmlNode styleHead = null; try { var x = new XmlDocument(); x.LoadXml(subtitle.Header); var xnsmgr = new XmlNamespaceManager(x.NameTable); xnsmgr.AddNamespace("ttml", "http://www.w3.org/ns/ttml"); if (x.DocumentElement != null) { styleHead = x.DocumentElement.SelectSingleNode("ttml:head", xnsmgr); } } catch { styleHead = null; } if (styleHead == null && (subtitle.Header.Contains("[V4+ Styles]") || subtitle.Header.Contains("[V4 Styles]"))) { var x = new XmlDocument(); x.LoadXml(new ItunesTimedText().ToText(new Subtitle(), "tt")); // load default xml var xnsmgr = new XmlNamespaceManager(x.NameTable); xnsmgr.AddNamespace("ttml", "http://www.w3.org/ns/ttml"); if (x.DocumentElement != null) { styleHead = x.DocumentElement.SelectSingleNode("ttml:head", xnsmgr); styleHead.SelectSingleNode("ttml:styling", xnsmgr).RemoveAll(); foreach (string styleName in AdvancedSubStationAlpha.GetStylesFromHeader(subtitle.Header)) { try { var ssaStyle = AdvancedSubStationAlpha.GetSsaStyle(styleName, subtitle.Header); string fontStyle = "normal"; if (ssaStyle.Italic) { fontStyle = "italic"; } string fontWeight = "normal"; if (ssaStyle.Bold) { fontWeight = "bold"; } AddStyleToXml(x, styleHead, xnsmgr, ssaStyle.Name, ssaStyle.FontName, fontWeight, fontStyle, Utilities.ColorToHex(ssaStyle.Primary), ssaStyle.FontSize.ToString()); convertedFromSubStationAlpha = true; } catch { // ignored } } } subtitle.Header = x.OuterXml; // save new xml with styles in header } } var xml = new XmlDocument { XmlResolver = null }; var nsmgr = new XmlNamespaceManager(xml.NameTable); nsmgr.AddNamespace("ttml", "http://www.w3.org/ns/ttml"); nsmgr.AddNamespace("ttp", "http://www.w3.org/ns/10/ttml#parameter"); nsmgr.AddNamespace("tts", "http://www.w3.org/ns/10/ttml#style"); nsmgr.AddNamespace("ttm", "http://www.w3.org/ns/10/ttml#metadata"); nsmgr.AddNamespace("ttm", "http://www.w3.org/ns/10/ttml#metadata"); nsmgr.AddNamespace("smpte", "http://www.smpte-ra.org/schemas/2052-1/2010/smpte-tt"); nsmgr.AddNamespace("m608", "http://www.smpte-ra.org/schemas/2052-1/2010/smpte-tt#cea608"); const string xmlStructure = @"<?xml version='1.0' encoding='utf-8'?> <tt xml:lang='[LANG]' xmlns='http://www.w3.org/ns/ttml' xmlns:tts='http://www.w3.org/ns/ttml#styling' xmlns:ttm='http://www.w3.org/ns/ttml#metadata' xmlns:ttp='http://www.w3.org/ns/ttml#parameter' ttp:timeBase='media' ttp:frameRate='24' ttp:frameRateMultiplier='1000 1001' xmlns:smpte='http://www.smpte-ra.org/schemas/2052-1/2010/smpte-tt' xmlns:m608='http://www.smpte-ra.org/schemas/2052-1/2010/smpte-tt#cea608'> <head> <metadata> <ttm:title>SMPTE-TT 2052 subtitle</ttm:title> <ttm:desc>SMPTE Timed Text document created by Subtitle Edit</ttm:desc> <smpte:information xmlns:m608='http://www.smpte-ra.org/schemas/2052-1/2010/smpte-tt#cea608' origin='http://www.smpte-ra.org/schemas/2052-1/2010/smpte-tt#cea608' mode='Preserved' m608:channel='CC1' m608:programName='Demo' m608:captionService='F1C1CC'/> </metadata> <styling> <style xml:id='basic' tts:color='white' tts:fontFamily='Arial' tts:backgroundColor='transparent' tts:fontSize='21' tts:fontWeight='normal' tts:fontStyle='normal' /> </styling> <layout> <region xml:id='bottom' tts:backgroundColor='transparent' tts:showBackground='whenActive' tts:origin='80% 80%' tts:extent='80% 80%' tts:displayAlign='after' /> </layout> </head> <body> <div></div> </body> </tt>"; var languageCode = LanguageAutoDetect.AutoDetectGoogleLanguage(subtitle); xml.LoadXml(xmlStructure.Replace("[LANG]", languageCode)); if (!string.IsNullOrWhiteSpace(title)) { var headNode = xml.DocumentElement.SelectSingleNode("//ttml:head", nsmgr); var metadataNode = headNode?.SelectSingleNode("ttml:metadata", nsmgr); var titleNode = metadataNode?.FirstChild; if (titleNode != null) { titleNode.InnerText = title; } } var div = xml.DocumentElement.SelectSingleNode("//ttml:body", nsmgr).SelectSingleNode("ttml:div", nsmgr); bool hasBottomCenterRegion = false; bool hasTopCenterRegion = false; foreach (XmlNode node in xml.DocumentElement.SelectNodes("//ttml:head/ttml:layout/ttml:region", nsmgr)) { string id = null; if (node.Attributes["xml:id"] != null) { id = node.Attributes["xml:id"].Value; } else if (node.Attributes["id"] != null) { id = node.Attributes["id"].Value; } if (id != null && id == "bottom") { hasBottomCenterRegion = true; } if (id != null && id == "topCenter") { hasTopCenterRegion = true; } } foreach (var p in subtitle.Paragraphs) { XmlNode paragraph = xml.CreateElement("p", "http://www.w3.org/ns/ttml"); string text = p.Text; XmlAttribute start = xml.CreateAttribute("begin"); start.InnerText = string.Format(CultureInfo.InvariantCulture, "{0:00}:{1:00}:{2:00}:{3:00}", p.StartTime.Hours, p.StartTime.Minutes, p.StartTime.Seconds, MillisecondsToFramesMaxFrameRate(p.StartTime.Milliseconds)); paragraph.Attributes.Append(start); XmlAttribute end = xml.CreateAttribute("end"); end.InnerText = string.Format(CultureInfo.InvariantCulture, "{0:00}:{1:00}:{2:00}:{3:00}", p.EndTime.Hours, p.EndTime.Minutes, p.EndTime.Seconds, MillisecondsToFramesMaxFrameRate(p.EndTime.Milliseconds)); paragraph.Attributes.Append(end); XmlAttribute style = xml.CreateAttribute("style"); style.InnerText = "basic"; paragraph.Attributes.Append(style); XmlAttribute regionP = xml.CreateAttribute("region"); if (text.StartsWith("{\\an7}", StringComparison.Ordinal) || text.StartsWith("{\\an8}", StringComparison.Ordinal) || text.StartsWith("{\\an9}", StringComparison.Ordinal)) { if (hasTopCenterRegion) { regionP.InnerText = "top"; paragraph.Attributes.Append(regionP); } } else if (hasBottomCenterRegion) { regionP.InnerText = "bottom"; paragraph.Attributes.Append(regionP); } if (text.StartsWith("{\\an", StringComparison.Ordinal) && text.Length > 6 && text[5] == '}') { text = text.Remove(0, 6); } XmlAttribute styleAttribute = xml.CreateAttribute("style"); styleAttribute.InnerText = "basic"; paragraph.Attributes.Append(styleAttribute); if (convertedFromSubStationAlpha) { if (string.IsNullOrEmpty(p.Style)) { p.Style = p.Extra; } } bool first = true; bool italicOn = false; foreach (string line in text.SplitToLines()) { if (!first) { XmlNode br = xml.CreateElement("br", "http://www.w3.org/ns/ttml"); paragraph.AppendChild(br); } var styles = new Stack <XmlNode>(); XmlNode currentStyle = xml.CreateTextNode(string.Empty); paragraph.AppendChild(currentStyle); int skipCount = 0; for (int i = 0; i < line.Length; i++) { if (skipCount > 0) { skipCount--; } else if (line.Substring(i).StartsWith("<i>", StringComparison.Ordinal)) { styles.Push(currentStyle); currentStyle = xml.CreateNode(XmlNodeType.Element, "span", null); paragraph.AppendChild(currentStyle); XmlAttribute attr = xml.CreateAttribute("tts:fontStyle", "http://www.w3.org/ns/10/ttml#style"); attr.InnerText = "italic"; currentStyle.Attributes.Append(attr); skipCount = 2; italicOn = true; } else if (line.Substring(i).StartsWith("<b>", StringComparison.Ordinal)) { currentStyle = xml.CreateNode(XmlNodeType.Element, "span", null); paragraph.AppendChild(currentStyle); XmlAttribute attr = xml.CreateAttribute("tts:fontWeight", "http://www.w3.org/ns/10/ttml#style"); attr.InnerText = "bold"; currentStyle.Attributes.Append(attr); skipCount = 2; } else if (line.Substring(i).StartsWith("<font ", StringComparison.Ordinal)) { int endIndex = line.Substring(i + 1).IndexOf('>'); if (endIndex > 0) { skipCount = endIndex + 1; string fontContent = line.Substring(i, skipCount); if (fontContent.Contains(" color=")) { var arr = fontContent.Substring(fontContent.IndexOf(" color=", StringComparison.Ordinal) + 7).Trim().Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (arr.Length > 0) { string fontColor = arr[0].Trim('\'').Trim('"').Trim('\''); currentStyle = xml.CreateNode(XmlNodeType.Element, "span", null); paragraph.AppendChild(currentStyle); XmlAttribute attr = xml.CreateAttribute("tts:color", "http://www.w3.org/ns/10/ttml#style"); attr.InnerText = fontColor; currentStyle.Attributes.Append(attr); } } } else { skipCount = line.Length; } } else if (line.Substring(i).StartsWith("</i>", StringComparison.Ordinal) || line.Substring(i).StartsWith("</b>", StringComparison.Ordinal) || line.Substring(i).StartsWith("</font>", StringComparison.Ordinal)) { currentStyle = xml.CreateTextNode(string.Empty); if (styles.Count > 0) { currentStyle = styles.Pop().CloneNode(true); currentStyle.InnerText = string.Empty; } paragraph.AppendChild(currentStyle); if (line.Substring(i).StartsWith("</font>", StringComparison.Ordinal)) { skipCount = 6; } else { skipCount = 3; } italicOn = false; } else { if (i == 0 && italicOn && !(line.Substring(i).StartsWith("<i>", StringComparison.Ordinal))) { styles.Push(currentStyle); currentStyle = xml.CreateNode(XmlNodeType.Element, "span", null); paragraph.AppendChild(currentStyle); XmlAttribute attr = xml.CreateAttribute("tts:fontStyle", "http://www.w3.org/ns/10/ttml#style"); attr.InnerText = "italic"; currentStyle.Attributes.Append(attr); } currentStyle.InnerText = currentStyle.InnerText + line[i]; } } first = false; } div.AppendChild(paragraph); } string xmlString = ToUtf8XmlString(xml).Replace(" xmlns=\"\"", string.Empty).Replace(" xmlns:tts=\"http://www.w3.org/ns/10/ttml#style\">", ">").Replace("<br />", "<br/>"); if (subtitle.Header == null) { subtitle.Header = xmlString; } return(xmlString); }
public override string ToText(Subtitle subtitle, string title) { const string header = @"[Script Info] ; This is a Sub Station Alpha v4 script. Title: {0} ScriptType: v4.00 Collisions: Normal PlayDepth: 0 [V4 Styles] Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, TertiaryColour, BackColour, Bold, Italic, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, AlphaLevel, Encoding Style: Default,{1},{2},{3},65535,65535,-2147483640,{9},0,1,{4},{5},2,{6},{7},{8},0,1 [Events] Format: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text"; const string headerNoStyles = @"[Script Info] ; This is a Sub Station Alpha v4 script. Title: {0} ScriptType: v4.00 Collisions: Normal PlayDepth: 0 [V4 Styles] Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, TertiaryColour, BackColour, Bold, Italic, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, AlphaLevel, Encoding {1} [Events] 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={4},{0},{1},{3},{5},{6},{7},{8},{9},{2}"; const string commentWriteFormat = "Comment: Marked={4},{0},{1},{3},{5},{6},{7},{8},{9},{2}"; var sb = new StringBuilder(); Color fontColor = Color.FromArgb(Configuration.Settings.SubtitleSettings.SsaFontColorArgb); bool isValidAssHeader = !string.IsNullOrEmpty(subtitle.Header) && subtitle.Header.Contains("[V4 Styles]"); var styles = new List <string>(); if (isValidAssHeader) { sb.AppendLine(subtitle.Header.Trim()); const string formatLine = "Format: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text"; if (!subtitle.Header.Contains(formatLine)) { sb.AppendLine(formatLine); } styles = AdvancedSubStationAlpha.GetStylesFromHeader(subtitle.Header); } else if (!string.IsNullOrEmpty(subtitle.Header) && subtitle.Header.Contains("[V4+ Styles]")) { LoadStylesFromAdvancedSubstationAlpha(subtitle, title, subtitle.Header, headerNoStyles, sb); isValidAssHeader = true; styles = AdvancedSubStationAlpha.GetStylesFromHeader(subtitle.Header); } else if (subtitle.Header != null && subtitle.Header.Contains("http://www.w3.org/ns/ttml")) { LoadStylesFromTimedText10(subtitle, title, header, headerNoStyles, sb); } else { var ssa = Configuration.Settings.SubtitleSettings; string boldStyle = "0"; // 0=regular if (ssa.SsaFontBold) { boldStyle = "-1"; // -1 = true, 0 is false } sb.AppendLine(string.Format(header, title, ssa.SsaFontName, (int)ssa.SsaFontSize, ColorTranslator.ToWin32(fontColor), ssa.SsaOutline, ssa.SsaShadow, ssa.SsaMarginLeft, ssa.SsaMarginRight, ssa.SsaMarginTopBottom, boldStyle )); } 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"; string actor = "NTP"; if (!string.IsNullOrEmpty(p.Actor)) { actor = p.Actor; } string marginL = "0000"; if (!string.IsNullOrEmpty(p.MarginL) && Utilities.IsInteger(p.MarginL)) { marginL = p.MarginL.PadLeft(4, '0'); } string marginR = "0000"; if (!string.IsNullOrEmpty(p.MarginR) && Utilities.IsInteger(p.MarginR)) { marginR = p.MarginR.PadLeft(4, '0'); } string marginV = "0000"; if (!string.IsNullOrEmpty(p.MarginV) && Utilities.IsInteger(p.MarginV)) { marginV = p.MarginV.PadLeft(4, '0'); } string effect = ""; if (!string.IsNullOrEmpty(p.Effect)) { effect = p.Effect; } if (!string.IsNullOrEmpty(p.Extra) && isValidAssHeader && styles.Contains(p.Extra)) { style = p.Extra; } if (style == "Default") { style = "*Default"; } if (p.IsComment) { sb.AppendLine(string.Format(commentWriteFormat, start, end, AdvancedSubStationAlpha.FormatText(p), style, p.Layer, actor, marginL, marginR, marginV, effect)); } else { sb.AppendLine(string.Format(paragraphWriteFormat, start, end, AdvancedSubStationAlpha.FormatText(p), style, p.Layer, actor, marginL, marginR, marginV, effect)); } } return(sb.ToString().Trim()); }