Added support for multiple languages in TimedText + fixed bug regarding some cc formats in batch-convert

git-svn-id: https://subtitleedit.googlecode.com/svn/trunk@2169 99eadd0c-20b8-1223-b5c4-2a2b2df33de2
This commit is contained in:
niksedk 2013-11-07 16:01:15 +00:00
parent f3fe83761e
commit fbb4ad523c
9 changed files with 311 additions and 134 deletions

View File

@ -8,6 +8,7 @@
* OCR max. error% is now saved for bluray - thx Zoltán
* More default values for ASS/SSA
* Added split long lines to "Batch convert" - thx menes
* Added support for multiple languages in TimedText / DFXP - thx Laszlo
* FIXED:
* F11 (Set start time) sometimes kept duration - thx Rinus/Quetsbeek
* Cavana 890 now works with Hebrew again - thx Yaniv
@ -15,6 +16,8 @@
* Fix regarding italics in remove text for HI - thx cipry15
* Now allows html tags in SAMI - thx estima
* Now possible to choose en-GB spell check in OCR window - thx Paul
* "Insert sub after current line" no longer inserts before cur line
* Batch convert now works with more cc formats
3.3.9 (19th October 2013)

View File

@ -434,6 +434,7 @@
this.imageListPlayRate = new System.Windows.Forms.ImageList(this.components);
this.timerTextUndo = new System.Windows.Forms.Timer(this.components);
this.timerAlternateTextUndo = new System.Windows.Forms.Timer(this.components);
this.toolStripMenuItemSetLanguage = new System.Windows.Forms.ToolStripMenuItem();
this.statusStrip1.SuspendLayout();
this.toolStrip1.SuspendLayout();
this.menuStrip1.SuspendLayout();
@ -2090,6 +2091,7 @@
this.contextMenuStripListview.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.setStylesForSelectedLinesToolStripMenuItem,
this.toolStripMenuItemAssStyles,
this.toolStripMenuItemSetLanguage,
this.toolStripMenuItemWebVTT,
this.toolStripMenuItemDelete,
this.toolStripMenuItemInsertBefore,
@ -2128,7 +2130,7 @@
this.changeCasingForSelectedLinesToolStripMenuItem,
this.toolStripMenuItemSaveSelectedLines});
this.contextMenuStripListview.Name = "contextMenuStripListview";
this.contextMenuStripListview.Size = new System.Drawing.Size(285, 782);
this.contextMenuStripListview.Size = new System.Drawing.Size(285, 826);
this.contextMenuStripListview.Opening += new System.ComponentModel.CancelEventHandler(this.ContextMenuStripListviewOpening);
//
// setStylesForSelectedLinesToolStripMenuItem
@ -2983,7 +2985,7 @@
this.timeUpDownVideoPosition.Margin = new System.Windows.Forms.Padding(4);
this.timeUpDownVideoPosition.Mode = Nikse.SubtitleEdit.Controls.TimeUpDown.TimeMode.HHMMSSMS;
this.timeUpDownVideoPosition.Name = "timeUpDownVideoPosition";
this.timeUpDownVideoPosition.Size = new System.Drawing.Size(92, 25);
this.timeUpDownVideoPosition.Size = new System.Drawing.Size(96, 25);
this.timeUpDownVideoPosition.TabIndex = 12;
//
// buttonGotoSub
@ -3428,7 +3430,7 @@
this.timeUpDownVideoPositionAdjust.Margin = new System.Windows.Forms.Padding(4);
this.timeUpDownVideoPositionAdjust.Mode = Nikse.SubtitleEdit.Controls.TimeUpDown.TimeMode.HHMMSSMS;
this.timeUpDownVideoPositionAdjust.Name = "timeUpDownVideoPositionAdjust";
this.timeUpDownVideoPositionAdjust.Size = new System.Drawing.Size(92, 25);
this.timeUpDownVideoPositionAdjust.Size = new System.Drawing.Size(96, 25);
this.timeUpDownVideoPositionAdjust.TabIndex = 13;
//
// ShowSubtitleTimer
@ -4074,7 +4076,7 @@
this.timeUpDownStartTime.Margin = new System.Windows.Forms.Padding(4);
this.timeUpDownStartTime.Mode = Nikse.SubtitleEdit.Controls.TimeUpDown.TimeMode.HHMMSSMS;
this.timeUpDownStartTime.Name = "timeUpDownStartTime";
this.timeUpDownStartTime.Size = new System.Drawing.Size(92, 25);
this.timeUpDownStartTime.Size = new System.Drawing.Size(96, 25);
this.timeUpDownStartTime.TabIndex = 0;
//
// numericUpDownDuration
@ -4269,6 +4271,12 @@
this.timerAlternateTextUndo.Interval = 700;
this.timerAlternateTextUndo.Tick += new System.EventHandler(this.TimerAlternateTextUndoTick);
//
// toolStripMenuItemSetLanguage
//
this.toolStripMenuItemSetLanguage.Name = "toolStripMenuItemSetLanguage";
this.toolStripMenuItemSetLanguage.Size = new System.Drawing.Size(284, 22);
this.toolStripMenuItemSetLanguage.Text = "Timed text - set language";
//
// Main
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@ -4753,6 +4761,7 @@
private System.Windows.Forms.ToolStripMenuItem descendingToolStripMenuItem;
private System.Windows.Forms.ToolStripSeparator toolStripSeparatorExportCustomText;
private System.Windows.Forms.ToolStripMenuItem exportCustomTextFormatToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem toolStripMenuItemSetLanguage;
}
}

View File

@ -807,7 +807,7 @@ namespace Nikse.SubtitleEdit.Forms
var cheetahCaption = new CheetahCaption();
if (cheetahCaption.IsMine(null, fileName))
{
cheetahCaption.LoadSubtitle(_subtitle, null, fileName);
cheetahCaption.LoadSubtitle(sub, null, fileName);
format = cheetahCaption;
}
}
@ -816,7 +816,7 @@ namespace Nikse.SubtitleEdit.Forms
var capMakerPlus = new CapMakerPlus();
if (capMakerPlus.IsMine(null, fileName))
{
capMakerPlus.LoadSubtitle(_subtitle, null, fileName);
capMakerPlus.LoadSubtitle(sub, null, fileName);
format = capMakerPlus;
}
}
@ -825,7 +825,7 @@ namespace Nikse.SubtitleEdit.Forms
var captionate = new Captionate();
if (captionate.IsMine(null, fileName))
{
captionate.LoadSubtitle(_subtitle, null, fileName);
captionate.LoadSubtitle(sub, null, fileName);
format = captionate;
}
}
@ -834,7 +834,7 @@ namespace Nikse.SubtitleEdit.Forms
var ultech130 = new Ultech130();
if (ultech130.IsMine(null, fileName))
{
ultech130.LoadSubtitle(_subtitle, null, fileName);
ultech130.LoadSubtitle(sub, null, fileName);
format = ultech130;
}
}
@ -843,7 +843,7 @@ namespace Nikse.SubtitleEdit.Forms
var nciCaption = new NciCaption();
if (nciCaption.IsMine(null, fileName))
{
nciCaption.LoadSubtitle(_subtitle, null, fileName);
nciCaption.LoadSubtitle(sub, null, fileName);
format = nciCaption;
}
}
@ -852,7 +852,7 @@ namespace Nikse.SubtitleEdit.Forms
var tsb4 = new TSB4();
if (tsb4.IsMine(null, fileName))
{
tsb4.LoadSubtitle(_subtitle, null, fileName);
tsb4.LoadSubtitle(sub, null, fileName);
format = tsb4;
}
}
@ -861,7 +861,7 @@ namespace Nikse.SubtitleEdit.Forms
var avidStl = new AvidStl();
if (avidStl.IsMine(null, fileName))
{
avidStl.LoadSubtitle(_subtitle, null, fileName);
avidStl.LoadSubtitle(sub, null, fileName);
format = avidStl;
}
}
@ -3408,13 +3408,17 @@ namespace Nikse.SubtitleEdit.Forms
styles = Sami.GetStylesFromHeader(_subtitle.Header);
else if (format.Name == "Nuendo")
styles = GetNuendoStyles();
foreach (Paragraph p in _subtitle.Paragraphs)
{
if (string.IsNullOrEmpty(p.Extra) && styles.Count > 0)
p.Extra = styles[0];
}
if (format.GetType() == typeof(Sami) || format.GetType() == typeof(SamiModern))
SubtitleListview1.ShowExtraColumn(Configuration.Settings.Language.General.Class);
else if (format.GetType() == typeof(TimedText10) || format.GetType() == typeof(ItunesTimedText))
SubtitleListview1.ShowExtraColumn("Style / Language");
else if (format.Name == "Nuendo")
SubtitleListview1.ShowExtraColumn("Character"); //TODO: Put in language xml file
else
@ -5548,6 +5552,7 @@ namespace Nikse.SubtitleEdit.Forms
{
var format = GetCurrentSubtitleFormat();
var formatType = format.GetType();
toolStripMenuItemSetLanguage.Visible = false;
if ((formatType == typeof(AdvancedSubStationAlpha) || formatType == typeof(SubStationAlpha)) && SubtitleListview1.SelectedItems.Count > 0)
{
toolStripMenuItemWebVTT.Visible = false;
@ -5583,6 +5588,35 @@ namespace Nikse.SubtitleEdit.Forms
setStylesForSelectedLinesToolStripMenuItem.Visible = styles.Count >= 1;
toolStripMenuItemAssStyles.Visible = true;
setStylesForSelectedLinesToolStripMenuItem.Text = _language.Menu.ContextMenu.TimedTextSetStyle;
// languages
var languages = TimedText10.GetUsedLanguages(_subtitle);
toolStripMenuItemSetLanguage.DropDownItems.Clear();
if (!string.IsNullOrEmpty(_language.Menu.ContextMenu.AdvancedSubStationAlphaStyles)) // TODO: remove if in 3.4
toolStripMenuItemSetLanguage.Text = _language.Menu.ContextMenu.AdvancedSubStationAlphaStyles;
toolStripMenuItemSetLanguage.Visible = true;
if (languages.Count > 0)
{
foreach (string language in languages)
{
toolStripMenuItemSetLanguage.DropDownItems.Add(language, null, AddLanguageClick);
}
toolStripMenuItemSetLanguage.DropDownItems.Add("-");
}
toolStripMenuItemSetLanguage.DropDownItems.Add("New");
var newItem = (ToolStripMenuItem) toolStripMenuItemSetLanguage.DropDownItems[toolStripMenuItemSetLanguage.DropDownItems.Count - 1];
var moreLanguages = new List<string>();
foreach (System.Globalization.CultureInfo x in System.Globalization.CultureInfo.GetCultures(System.Globalization.CultureTypes.NeutralCultures))
{
if (!languages.Contains(x.TwoLetterISOLanguageName.ToLower()) && !languages.Contains(x.TwoLetterISOLanguageName.ToLower()))
moreLanguages.Add(x.TwoLetterISOLanguageName.ToLower());
}
moreLanguages.Sort();
foreach (string language in moreLanguages)
{
newItem.DropDownItems.Add(language, null, AddLanguageClick);
}
}
else if ((formatType == typeof(Sami) || formatType == typeof(SamiModern)) && SubtitleListview1.SelectedItems.Count > 0)
{
@ -5728,10 +5762,40 @@ namespace Nikse.SubtitleEdit.Forms
if (!string.IsNullOrEmpty(style))
{
MakeHistoryForUndo("Set style: " + style);
var format = GetCurrentSubtitleFormat();
var formatType = format.GetType();
if ((formatType == typeof(TimedText10) || formatType == typeof(ItunesTimedText)))
{
foreach (int index in SubtitleListview1.SelectedIndices)
{
_subtitle.Paragraphs[index].Style = style;
_subtitle.Paragraphs[index].Extra = TimedText10.SetExtra(_subtitle.Paragraphs[index]);
SubtitleListview1.SetExtraText(index, _subtitle.Paragraphs[index].Extra, SubtitleListview1.ForeColor);
}
}
else
{
foreach (int index in SubtitleListview1.SelectedIndices)
{
_subtitle.Paragraphs[index].Extra = style;
SubtitleListview1.SetExtraText(index, style, SubtitleListview1.ForeColor);
}
}
}
}
void AddLanguageClick(object sender, EventArgs e)
{
string lang = (sender as ToolStripItem).Text;
if (!string.IsNullOrEmpty(lang))
{
MakeHistoryForUndo("Set language: " + lang);
foreach (int index in SubtitleListview1.SelectedIndices)
{
_subtitle.Paragraphs[index].Extra = style;
SubtitleListview1.SetExtraText(index, style, SubtitleListview1.ForeColor);
_subtitle.Paragraphs[index].Language = lang;
_subtitle.Paragraphs[index].Extra = TimedText10.SetExtra(_subtitle.Paragraphs[index]);
SubtitleListview1.SetExtraText(index, _subtitle.Paragraphs[index].Extra, SubtitleListview1.ForeColor);
}
}
}
@ -6056,7 +6120,15 @@ namespace Nikse.SubtitleEdit.Forms
var newParagraph = new Paragraph();
if (useExtraForStyle)
{
newParagraph.Extra = style;
if (format.GetType() == typeof(TimedText10) || format.GetType() == typeof(ItunesTimedText))
{
if (styles.Count > 0)
newParagraph.Style = style;
newParagraph.Extra = TimedText10.SetExtra(newParagraph);
}
}
Paragraph prev = _subtitle.GetParagraphOrDefault(firstSelectedIndex - 1);
Paragraph next = _subtitle.GetParagraphOrDefault(firstSelectedIndex);
@ -6149,7 +6221,16 @@ namespace Nikse.SubtitleEdit.Forms
var newParagraph = new Paragraph();
if (useExtraForStyle)
{
newParagraph.Extra = style;
if (format.GetType() == typeof(TimedText10) || format.GetType() == typeof(ItunesTimedText))
{
if (styles.Count > 0)
newParagraph.Style = style;
newParagraph.Extra = TimedText10.SetExtra(newParagraph);
}
}
Paragraph prev = _subtitle.GetParagraphOrDefault(firstSelectedIndex - 1);
Paragraph next = _subtitle.GetParagraphOrDefault(firstSelectedIndex);
if (prev != null)
@ -15612,7 +15693,7 @@ namespace Nikse.SubtitleEdit.Forms
if (Configuration.Settings.General.RemoveBlankLinesWhenOpening)
subtitle.RemoveEmptyLines();
int index = FirstSelectedIndex;
int index = FirstSelectedIndex + 1;
if (index < 0)
index = 0;
foreach (Paragraph p in subtitle.Paragraphs)

View File

@ -690,7 +690,7 @@
AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj0yLjAuMC4w
LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAD2
CAAAAk1TRnQBSQFMAgEBAgEAAXgBIAF4ASABEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo
CAAAAk1TRnQBSQFMAgEBAgEAAYgBIAGIASABEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo
AwABQAMAARADAAEBAQABCAYAAQQYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA
AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5
AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA

View File

@ -1257,6 +1257,7 @@ namespace Nikse.SubtitleEdit.Logic
SubStationAlphaStyles = "Sub Station Alpha styles...",
TimedTextStyles = "Timed Text styles...",
TimedTextSetStyle = "Timed Text - set style",
TimedTextSetLanguage = "Timed Text - set language",
SamiSetStyle = "Sami - set class",
Cut = "Cut",
Copy = "Copy",

View File

@ -1140,6 +1140,7 @@
public string AdvancedSubStationAlphaStyles { get; set; }
public string TimedTextSetStyle { get; set; }
public string TimedTextStyles { get; set; }
public string TimedTextSetLanguage { get; set; }
public string SamiSetStyle { get; set; }
public string Cut { get; set; }
public string Copy { get; set; }

View File

@ -40,6 +40,10 @@ namespace Nikse.SubtitleEdit.Logic
public string ID { get; set; }
public string Language { get; set; }
public string Style { get; set; }
public Paragraph()
{
StartTime = new TimeCode(TimeSpan.FromSeconds(0));
@ -71,6 +75,8 @@ namespace Nikse.SubtitleEdit.Logic
Effect = paragraph.Effect;
Layer = paragraph.Layer;
ID = paragraph.ID;
Language = paragraph.Language;
Style = paragraph.Style;
}
public Paragraph(int startFrame, int endFrame, string text)

View File

@ -198,19 +198,19 @@ namespace Nikse.SubtitleEdit.Logic.SubtitleFormats
if (text.StartsWith("{\\an") && text.Length > 6 && text[5] == '}')
text = text.Remove(0, 6);
if (subtitle.Header != null && p.Extra != null && GetStylesFromHeader(subtitle.Header).Contains(p.Extra))
if (subtitle.Header != null && p.Style != null && GetStylesFromHeader(subtitle.Header).Contains(p.Style))
{
if (p.Extra != defaultStyle)
if (p.Style != defaultStyle)
{
XmlAttribute styleAttr = xml.CreateAttribute("style");
styleAttr.InnerText = p.Extra;
styleAttr.InnerText = p.Style;
paragraph.Attributes.Append(styleAttr);
}
}
else if (!string.IsNullOrEmpty(p.Extra))
else if (!string.IsNullOrEmpty(p.Style))
{
XmlAttribute styleP = xml.CreateAttribute("style");
styleP.InnerText = p.Extra;
styleP.InnerText = p.Style;
paragraph.Attributes.Append(styleP);
}

View File

@ -205,135 +205,174 @@ namespace Nikse.SubtitleEdit.Logic.SubtitleFormats
if (body.Attributes["style"] != null)
defaultStyle = body.Attributes["style"].InnerText;
//XmlNode titleNode = xml.DocumentElement.SelectSingleNode("//ttml:head", nsmgr).FirstChild.FirstChild;
//titleNode.InnerText = title;
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);
foreach (Paragraph p in subtitle.Paragraphs)
var languages = GetUsedLanguages(subtitle);
if (languages.Count > 0)
{
XmlNode paragraph = xml.CreateElement("p", "http://www.w3.org/ns/ttml");
string text = p.Text;
bool first = true;
foreach (string line in text.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries))
foreach (Paragraph p in subtitle.Paragraphs)
{
if (!first)
if (p.Language == null)
{
XmlNode br = xml.CreateElement("br", "http://www.w3.org/ns/ttml");
paragraph.AppendChild(br);
}
System.Collections.Generic.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>"))
{
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;
}
else if (line.Substring(i).StartsWith("<b>"))
{
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 "))
{
int endIndex = line.Substring(i + 1).IndexOf(">");
if (endIndex > 0)
{
skipCount = endIndex + 1;
string fontContent = line.Substring(i, skipCount);
if (fontContent.Contains(" color="))
{
string[] arr = fontContent.Substring(fontContent.IndexOf(" color=") + 7).Trim().Split(" ".ToCharArray(), 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>") || line.Substring(i).StartsWith("</b>") || line.Substring(i).StartsWith("</font>"))
{
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>"))
skipCount = 6;
else
skipCount = 3;
}
else
{
currentStyle.InnerText = currentStyle.InnerText + line.Substring(i, 1);
}
}
first = false;
}
XmlAttribute start = xml.CreateAttribute("begin");
start.InnerText = ConvertToTimeString(p.StartTime);
paragraph.Attributes.Append(start);
XmlAttribute id = xml.CreateAttribute("id");
id.InnerText = "p" + no.ToString();
paragraph.Attributes.Append(id);
XmlAttribute end = xml.CreateAttribute("end");
end.InnerText = ConvertToTimeString(p.EndTime);
paragraph.Attributes.Append(end);
if (subtitle.Header != null && p.Extra != null && headerStyles.Contains(p.Extra))
{
if (p.Extra != defaultStyle)
{
XmlAttribute styleAttr = xml.CreateAttribute("style");
styleAttr.InnerText = p.Extra;
paragraph.Attributes.Append(styleAttr);
XmlNode paragraph = MakeParagraph(subtitle, xml, defaultStyle, no, headerStyles, p);
div.AppendChild(paragraph);
no++;
}
}
var divParentNode = div.ParentNode;
if (div.ChildNodes.Count == 0)
divParentNode.RemoveChild(div);
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);
foreach (Paragraph p in subtitle.Paragraphs)
{
if (p.Language == language)
{
XmlNode paragraph = MakeParagraph(subtitle, xml, defaultStyle, no, headerStyles, p);
div.AppendChild(paragraph);
no++;
}
}
}
}
else
{
foreach (Paragraph p in subtitle.Paragraphs)
{
XmlNode paragraph = MakeParagraph(subtitle, xml, defaultStyle, no, headerStyles, p);
div.AppendChild(paragraph);
no++;
}
}
return ToUtf8XmlString(xml).Replace(" xmlns=\"\"", string.Empty).Replace(" xmlns:tts=\"http://www.w3.org/ns/10/ttml#style\">", ">");
}
private static XmlNode MakeParagraph(Subtitle subtitle, XmlDocument xml, string defaultStyle, int no, List<string> headerStyles, Paragraph p)
{
XmlNode paragraph = xml.CreateElement("p", "http://www.w3.org/ns/ttml");
string text = p.Text;
bool first = true;
foreach (string line in text.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries))
{
if (!first)
{
XmlNode br = xml.CreateElement("br", "http://www.w3.org/ns/ttml");
paragraph.AppendChild(br);
}
System.Collections.Generic.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>"))
{
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;
}
else if (line.Substring(i).StartsWith("<b>"))
{
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 "))
{
int endIndex = line.Substring(i + 1).IndexOf(">");
if (endIndex > 0)
{
skipCount = endIndex + 1;
string fontContent = line.Substring(i, skipCount);
if (fontContent.Contains(" color="))
{
string[] arr = fontContent.Substring(fontContent.IndexOf(" color=") + 7).Trim().Split(" ".ToCharArray(), 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>") || line.Substring(i).StartsWith("</b>") || line.Substring(i).StartsWith("</font>"))
{
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>"))
skipCount = 6;
else
skipCount = 3;
}
else
{
currentStyle.InnerText = currentStyle.InnerText + line.Substring(i, 1);
}
}
first = false;
}
XmlAttribute start = xml.CreateAttribute("begin");
start.InnerText = ConvertToTimeString(p.StartTime);
paragraph.Attributes.Append(start);
XmlAttribute id = xml.CreateAttribute("id");
id.InnerText = "p" + no.ToString();
paragraph.Attributes.Append(id);
XmlAttribute end = xml.CreateAttribute("end");
end.InnerText = ConvertToTimeString(p.EndTime);
paragraph.Attributes.Append(end);
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);
}
}
return paragraph;
}
public override void LoadSubtitle(Subtitle subtitle, List<string> lines, string fileName)
{
_errorCount = 0;
@ -437,9 +476,9 @@ namespace Nikse.SubtitleEdit.Logic.SubtitleFormats
startSeconds = endCode.TotalSeconds;
var p = new Paragraph(startCode, endCode, pText.ToString().Replace(" ", " ").Replace(" ", " "));
p.Extra = defaultStyle;
p.Style = defaultStyle;
if (node.Attributes["style"] != null)
p.Extra = node.Attributes["style"].InnerText;
p.Style = node.Attributes["style"].InnerText;
if (node.Attributes["region"] != null)
{
@ -448,6 +487,17 @@ namespace Nikse.SubtitleEdit.Logic.SubtitleFormats
p.Text = "{\\an8}" + p.Text;
}
// check language
if (node.ParentNode.Name == "div")
{
if (node.ParentNode.Attributes["xml:lang"] != null)
p.Language = node.ParentNode.Attributes["xml:lang"].InnerText;
else if (node.ParentNode.Attributes["lang"] != null)
p.Language = node.ParentNode.Attributes["lang"].InnerText;
}
p.Extra = SetExtra(p);
subtitle.Paragraphs.Add(p);
}
catch (Exception ex)
@ -459,6 +509,17 @@ namespace Nikse.SubtitleEdit.Logic.SubtitleFormats
subtitle.Renumber(1);
}
public static string SetExtra(Paragraph p)
{
string style = p.Style;
if (string.IsNullOrEmpty(style))
style = "-";
string lang = p.Language;
if (string.IsNullOrEmpty(lang))
lang = "-";
return string.Format("{0} / {1}", style, lang);
}
private static void ReadSpan(StringBuilder pText, XmlNode innerNode)
{
bool italic = false;
@ -608,6 +669,21 @@ namespace Nikse.SubtitleEdit.Logic.SubtitleFormats
return list;
}
public static List<string> GetUsedLanguages(Subtitle subtitle)
{
var list = new List<string>();
foreach (Paragraph p in subtitle.Paragraphs)
{
if (p.Language != null)
{
string l = p.Language.ToLower().Trim();
if (!list.Contains(l))
list.Add(l);
}
}
return list;
}
}
}