public void Save(string fileName, Subtitle subtitle) { using (var fs = new FileStream(fileName, FileMode.Create, FileAccess.Write)) { int russianCount = 0; char[] logoGrams = { '的', '是', '啊', '吧', '好', '吧', '亲', '爱', '的', '早', '上' }; char[] russianChars = { 'я', 'д', 'й', 'л', 'щ', 'ж', 'ц', 'ф', 'ы' }; foreach (Paragraph p in subtitle.Paragraphs) { if (p.Text.Contains(logoGrams)) { _languageIdLine1 = LanguageIdChineseSimplified; _languageIdLine2 = LanguageIdChineseSimplified; break; } if (p.Text.Contains(russianChars)) { russianCount++; if (russianCount > 10) { _languageIdLine1 = LanguageIdRussian; _languageIdLine2 = LanguageIdRussian; // or 0x09? break; } } } if (Configuration.Settings.SubtitleSettings.CurrentCavena89LanguageId > 0) { _languageIdLine1 = Configuration.Settings.SubtitleSettings.CurrentCavena89LanguageId; _languageIdLine2 = Configuration.Settings.SubtitleSettings.CurrentCavena89LanguageId; } else { var language = LanguageAutoDetect.AutoDetectGoogleLanguage(subtitle); switch (language) { case "he": _languageIdLine1 = LanguageIdHebrew; _languageIdLine2 = LanguageIdHebrew; // or 0x09 break; case "ru": _languageIdLine1 = LanguageIdRussian; _languageIdLine2 = LanguageIdRussian; // or 0x09? break; case "zh": _languageIdLine1 = LanguageIdChineseSimplified; _languageIdLine2 = LanguageIdChineseSimplified; break; case "da": _languageIdLine1 = LanguageIdDanish; _languageIdLine2 = LanguageIdDanish; break; } } // prompt??? //if (Configuration.Settings.SubtitleSettings.CurrentCavena890LanguageIdLine1 >= 0) // _languageIdLine1 = Configuration.Settings.SubtitleSettings.CurrentCavena890LanguageIdLine1; //if (Configuration.Settings.SubtitleSettings.CurrentCavena890LanguageIdLine2 >= 0) // _languageIdLine2 = Configuration.Settings.SubtitleSettings.CurrentCavena890LanguageIdLine2; // write file header (some fields are known, some are not...) fs.WriteByte(0); // ? fs.WriteByte(0); // ? // tape number (20 bytes) for (int i = 0; i < 20; i++) { fs.WriteByte(0); } // ? for (int i = 0; i < 18; i++) { fs.WriteByte(0); } // translated programme title (28 bytes) string title = Path.GetFileNameWithoutExtension(fileName) ?? string.Empty; if (title.Length > 28) { title = title.Substring(0, 28); } if (!string.IsNullOrWhiteSpace(Configuration.Settings.SubtitleSettings.CurrentCavena89Title) && Configuration.Settings.SubtitleSettings.CurrentCavena89Title.Length <= 28) { title = Configuration.Settings.SubtitleSettings.CurrentCavena89Title; } var buffer = Encoding.ASCII.GetBytes(title); fs.Write(buffer, 0, buffer.Length); for (int i = 0; i < 28 - buffer.Length; i++) { fs.WriteByte(0); } // translator (28 bytes) if (!string.IsNullOrWhiteSpace(Configuration.Settings.SubtitleSettings.CurrentCavena890Translator) && Configuration.Settings.SubtitleSettings.CurrentCavena890Translator.Length <= 28) { buffer = Encoding.ASCII.GetBytes(Configuration.Settings.SubtitleSettings.CurrentCavena890Translator); fs.Write(buffer, 0, buffer.Length); for (int i = 0; i < 28 - buffer.Length; i++) { fs.WriteByte(0); } } else { for (int i = 0; i < 28; i++) { fs.WriteByte(0); } } // ? for (int i = 0; i < 9; i++) { fs.WriteByte(0); } // translated episode title (11 bytes) for (int i = 0; i < 11; i++) { fs.WriteByte(0); } // ? for (int i = 0; i < 18; i++) { fs.WriteByte(0); } // ? + language codes buffer = new byte[] { 0xA0, 0x05, 0x04, 0x03, 0x06, 0x06, 0x08, 0x90, 0x00, 0x00, 0x00, 0x00, (byte)_languageIdLine1, (byte)_languageIdLine2 }; fs.Write(buffer, 0, buffer.Length); // comments (24 bytes) buffer = Encoding.ASCII.GetBytes(""); if (!string.IsNullOrWhiteSpace(Configuration.Settings.SubtitleSettings.CurrentCavena89Comment) && Configuration.Settings.SubtitleSettings.CurrentCavena89Comment.Length <= 24) { buffer = Encoding.ASCII.GetBytes(Configuration.Settings.SubtitleSettings.CurrentCavena89Comment); } fs.Write(buffer, 0, buffer.Length); for (int i = 0; i < 24 - buffer.Length; i++) { fs.WriteByte(0); } // ?? buffer = new byte[] { 0x08, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00 }; fs.Write(buffer, 0, buffer.Length); // number of subtitles fs.WriteByte((byte)(subtitle.Paragraphs.Count % 256)); fs.WriteByte((byte)(subtitle.Paragraphs.Count / 256)); // write font - prefix with binary zeroes buffer = GetFontBytesFromLanguageId(_languageIdLine1); // also TBX308VFONTL.V for english... for (int i = 0; i < 14 - buffer.Length; i++) { fs.WriteByte(0); } fs.Write(buffer, 0, buffer.Length); // ? for (int i = 0; i < 13; i++) { fs.WriteByte(0); } // number of subtitles again fs.WriteByte((byte)(subtitle.Paragraphs.Count % 256)); fs.WriteByte((byte)(subtitle.Paragraphs.Count / 256)); // number of subtitles again again fs.WriteByte((byte)(subtitle.Paragraphs.Count % 256)); fs.WriteByte((byte)(subtitle.Paragraphs.Count / 256)); // ? for (int i = 0; i < 6; i++) { fs.WriteByte(0); } // original programme title (28 chars) if (!string.IsNullOrWhiteSpace(Configuration.Settings.SubtitleSettings.CurrentCavena890riginalTitle) && Configuration.Settings.SubtitleSettings.CurrentCavena890riginalTitle.Length <= 28) { buffer = Encoding.ASCII.GetBytes(Configuration.Settings.SubtitleSettings.CurrentCavena890riginalTitle); fs.Write(buffer, 0, buffer.Length); for (int i = 0; i < 28 - buffer.Length; i++) { fs.WriteByte(0); } } else { for (int i = 0; i < 28; i++) { fs.WriteByte(0); } } // write font (use same font id from line 1) buffer = GetFontBytesFromLanguageId(_languageIdLine1); fs.Write(buffer, 0, buffer.Length); // ? fs.WriteByte(0x3d); fs.WriteByte(0x8d); // start of message time string startOfMessage = "10:00:00:00"; if (Configuration.Settings.SubtitleSettings.Cavena890StartOfMessage != null && Configuration.Settings.SubtitleSettings.Cavena890StartOfMessage.Length == startOfMessage.Length) { startOfMessage = Configuration.Settings.SubtitleSettings.Cavena890StartOfMessage; } buffer = Encoding.ASCII.GetBytes(startOfMessage); fs.Write(buffer, 0, buffer.Length); buffer = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x54, 0x44 }; fs.Write(buffer, 0, buffer.Length); for (int i = 0; i < 92; i++) { fs.WriteByte(0); } // paragraphs int number = 16; foreach (Paragraph p in subtitle.Paragraphs) { // number fs.WriteByte((byte)(number / 256)); fs.WriteByte((byte)(number % 256)); WriteTime(fs, p.StartTime); WriteTime(fs, p.EndTime); if (p.Text.StartsWith("{\\an1}")) { fs.WriteByte(0x50); // left } else if (p.Text.StartsWith("{\\an3}")) { fs.WriteByte(0x52); // left } else { fs.WriteByte(0x54); // center } buffer = new byte[] { 0, 0, 0, 0, 0, 0, 0 }; // 0x16 }; -- the last two bytes might be something with vertical alignment... fs.Write(buffer, 0, buffer.Length); bool hasBox = Utilities.RemoveSsaTags(p.Text).StartsWith("<box>"); var text = p.Text.Replace("<box>", string.Empty).Replace("</box>", string.Empty); text = HtmlUtil.RemoveOpenCloseTags(Utilities.RemoveSsaTags(text), HtmlUtil.TagBold, HtmlUtil.TagFont, HtmlUtil.TagBold); WriteText(fs, text, p == subtitle.Paragraphs[subtitle.Paragraphs.Count - 1], _languageIdLine1, hasBox); number += 16; } } }
public void Fix(Subtitle subtitle, IFixCallbacks callbacks) { var language = Configuration.Settings.Language.FixCommonErrors; string fixAction = language.UnneededPeriod; int removedCount = 0; for (int i = 0; i < subtitle.Paragraphs.Count; i++) { var p = subtitle.Paragraphs[i]; if (callbacks.AllowFix(p, fixAction)) { // Returns processed text. string procText = RemoveDotAfterPunctuation(p.Text); while (procText.Contains("....", StringComparison.Ordinal)) { procText = procText.Replace("....", "..."); } while (procText.Contains("……", StringComparison.Ordinal)) { procText = procText.Replace("……", "…"); } while (procText.Contains(".…", StringComparison.Ordinal)) { procText = procText.Replace(".…", "…"); } while (procText.Contains("….", StringComparison.Ordinal)) { procText = procText.Replace("….", "…"); } var l = callbacks.Language; if (procText.Contains('.') && LanguageAutoDetect.IsLanguageWithoutPeriods(l)) { var sb = new StringBuilder(); foreach (var line in procText.SplitToLines()) { var s = line; if (s.EndsWith('.') && !s.EndsWith("..", StringComparison.Ordinal)) { s = s.TrimEnd('.'); } else if (s.EndsWith(".</i>", StringComparison.Ordinal) && !s.EndsWith("..</i>", StringComparison.Ordinal)) { s = s.Remove(s.Length - 5, 1); } sb.AppendLine(s); } procText = sb.ToString().TrimEnd(); } int diff = p.Text.Length - procText.Length; if (diff > 0) { // Calculate total removed dots. removedCount += diff; callbacks.AddFixToListView(p, fixAction, p.Text, procText); p.Text = procText; } } } callbacks.UpdateFixStatus(removedCount, language.RemoveUnneededPeriods, string.Format(language.XUnneededPeriodsRemoved, removedCount)); }
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(CultureInfo.InvariantCulture)); 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"); var 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='10% 55%' tts:extent='80% 80%' tts:displayAlign='after' /> <region xml:id='top' tts:backgroundColor='transparent' tts:showBackground='whenActive' tts:origin='10% 10%' tts:extent='80% 80%' tts:displayAlign='before' /> </layout> </head> <body> <div></div> </body> </tt>"; string frameRate = ((int)Math.Round(Configuration.Settings.General.CurrentFrameRate)).ToString(); string frameRateMultiplier = "1000 1001"; if (Configuration.Settings.General.CurrentFrameRate % 1.0 < 0.01) { frameRateMultiplier = "1 1"; } xmlStructure = xmlStructure.Replace("frameRate='24'", $"frameRate='{frameRate}'"); xmlStructure = xmlStructure.Replace("frameRateMultiplier='1000 1001'", $"frameRateMultiplier='{frameRateMultiplier}'"); 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" || id == "top")) { 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 textAlign = xml.CreateAttribute("textAlign"); textAlign.InnerText = "center"; paragraph.Attributes.Append(textAlign); 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 Utilities.RemoveSsaTags(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); }
internal void Initialize(Subtitle subtitle, string title, bool googleTranslate, Encoding encoding) { if (title != null) { Text = title; } _googleTranslate = googleTranslate; if (!_googleTranslate) { linkLabelPoweredByGoogleTranslate.Text = Configuration.Settings.Language.GoogleTranslate.PoweredByMicrosoftTranslate; } labelPleaseWait.Visible = false; progressBar1.Visible = false; _subtitle = subtitle; _translatedSubtitle = new Subtitle(subtitle); string defaultFromLanguage = LanguageAutoDetect.AutoDetectGoogleLanguage(encoding); // Guess language via encoding if (string.IsNullOrEmpty(defaultFromLanguage)) { defaultFromLanguage = LanguageAutoDetect.AutoDetectGoogleLanguage(subtitle); // Guess language based on subtitle contents } FillComboWithLanguages(comboBoxFrom); int i = 0; foreach (ComboBoxItem item in comboBoxFrom.Items) { if (item.Value == defaultFromLanguage) { comboBoxFrom.SelectedIndex = i; break; } i++; } FillComboWithLanguages(comboBoxTo); i = 0; string uiCultureTargetLanguage = Configuration.Settings.Tools.GoogleTranslateLastTargetLanguage; if (uiCultureTargetLanguage == defaultFromLanguage) { foreach (string s in Utilities.GetDictionaryLanguages()) { string temp = s.Replace("[", string.Empty).Replace("]", string.Empty); if (temp.Length > 4) { temp = temp.Substring(temp.Length - 5, 2).ToLower(); if (temp != uiCultureTargetLanguage) { uiCultureTargetLanguage = temp; break; } } } } comboBoxTo.SelectedIndex = 0; foreach (ComboBoxItem item in comboBoxTo.Items) { if (item.Value == uiCultureTargetLanguage) { comboBoxTo.SelectedIndex = i; break; } i++; } subtitleListViewFrom.Fill(subtitle); GoogleTranslate_Resize(null, null); _googleApiNotWorking = !Configuration.Settings.Tools.UseGooleApiPaidService; // google has closed their free api service :( }
public override string ToText(Subtitle subtitle, string title) { string languageEnglishName; try { string languageShortName = LanguageAutoDetect.AutoDetectGoogleLanguage(subtitle); var ci = CultureInfo.CreateSpecificCulture(languageShortName); languageEnglishName = ci.EnglishName; int indexOfStartP = languageEnglishName.IndexOf('('); if (indexOfStartP > 1) { languageEnglishName = languageEnglishName.Remove(indexOfStartP).Trim(); } } catch { languageEnglishName = "English"; } string hex = Guid.NewGuid().ToString().Replace("-", string.Empty); hex = hex.Insert(8, "-").Insert(13, "-").Insert(18, "-").Insert(23, "-"); string xmlStructure = "<DCSubtitle Version=\"1.0\">" + Environment.NewLine + " <SubtitleID>" + hex.ToLower() + "</SubtitleID>" + Environment.NewLine + " <MovieTitle></MovieTitle>" + Environment.NewLine + " <ReelNumber>1</ReelNumber>" + Environment.NewLine + " <Language>" + languageEnglishName + "</Language>" + Environment.NewLine + " <LoadFont URI=\"" + Configuration.Settings.SubtitleSettings.DCinemaFontFile + "\" Id=\"Font1\"/>" + Environment.NewLine + " <Font Id=\"Font1\" Color=\"FFFFFFFF\" Effect=\"border\" EffectColor=\"FF000000\" Italic=\"no\" Underlined=\"no\" Script=\"normal\" Size=\"42\">" + Environment.NewLine + " </Font>" + Environment.NewLine + "</DCSubtitle>"; var xml = new XmlDocument(); xml.LoadXml(xmlStructure); xml.PreserveWhitespace = true; var ss = Configuration.Settings.SubtitleSettings; string loadedFontId = "Font1"; if (!string.IsNullOrEmpty(ss.CurrentDCinemaFontId)) { loadedFontId = ss.CurrentDCinemaFontId; } if (string.IsNullOrEmpty(ss.CurrentDCinemaMovieTitle)) { ss.CurrentDCinemaMovieTitle = title; } if (ss.CurrentDCinemaFontSize == 0 || string.IsNullOrEmpty(ss.CurrentDCinemaFontEffect)) { Configuration.Settings.SubtitleSettings.InitializeDCinameSettings(true); } xml.DocumentElement.SelectSingleNode("MovieTitle").InnerText = ss.CurrentDCinemaMovieTitle; xml.DocumentElement.SelectSingleNode("SubtitleID").InnerText = ss.CurrentDCinemaSubtitleId.Replace("urn:uuid:", string.Empty); xml.DocumentElement.SelectSingleNode("ReelNumber").InnerText = ss.CurrentDCinemaReelNumber; xml.DocumentElement.SelectSingleNode("Language").InnerText = ss.CurrentDCinemaLanguage; xml.DocumentElement.SelectSingleNode("LoadFont").Attributes["URI"].InnerText = ss.CurrentDCinemaFontUri; xml.DocumentElement.SelectSingleNode("LoadFont").Attributes["Id"].InnerText = loadedFontId; int fontSize = ss.CurrentDCinemaFontSize; xml.DocumentElement.SelectSingleNode("Font").Attributes["Id"].InnerText = loadedFontId; xml.DocumentElement.SelectSingleNode("Font").Attributes["Color"].InnerText = "FF" + Utilities.ColorToHex(ss.CurrentDCinemaFontColor).TrimStart('#').ToUpper(); xml.DocumentElement.SelectSingleNode("Font").Attributes["Effect"].InnerText = ss.CurrentDCinemaFontEffect; xml.DocumentElement.SelectSingleNode("Font").Attributes["EffectColor"].InnerText = "FF" + Utilities.ColorToHex(ss.CurrentDCinemaFontEffectColor).TrimStart('#').ToUpper(); xml.DocumentElement.SelectSingleNode("Font").Attributes["Size"].InnerText = ss.CurrentDCinemaFontSize.ToString(); var mainListFont = xml.DocumentElement.SelectSingleNode("Font"); int no = 0; foreach (Paragraph p in subtitle.Paragraphs) { if (!string.IsNullOrEmpty(p.Text)) { var subNode = xml.CreateElement("Subtitle"); var id = xml.CreateAttribute("SpotNumber"); id.InnerText = (no + 1).ToString(); subNode.Attributes.Append(id); var fadeUpTime = xml.CreateAttribute("FadeUpTime"); fadeUpTime.InnerText = Configuration.Settings.SubtitleSettings.DCinemaFadeUpTime.ToString(); subNode.Attributes.Append(fadeUpTime); var fadeDownTime = xml.CreateAttribute("FadeDownTime"); fadeDownTime.InnerText = Configuration.Settings.SubtitleSettings.DCinemaFadeDownTime.ToString(); subNode.Attributes.Append(fadeDownTime); var start = xml.CreateAttribute("TimeIn"); start.InnerText = ConvertToTimeString(p.StartTime); subNode.Attributes.Append(start); var end = xml.CreateAttribute("TimeOut"); end.InnerText = ConvertToTimeString(p.EndTime); subNode.Attributes.Append(end); bool alignLeft = p.Text.StartsWith("{\\a1}", StringComparison.Ordinal) || p.Text.StartsWith("{\\a5}", StringComparison.Ordinal) || p.Text.StartsWith("{\\a9}", StringComparison.Ordinal) || // sub station alpha p.Text.StartsWith("{\\an1}", StringComparison.Ordinal) || p.Text.StartsWith("{\\an4}", StringComparison.Ordinal) || p.Text.StartsWith("{\\an7}", StringComparison.Ordinal); // advanced sub station alpha bool alignRight = p.Text.StartsWith("{\\a3}", StringComparison.Ordinal) || p.Text.StartsWith("{\\a7}", StringComparison.Ordinal) || p.Text.StartsWith("{\\a11}", StringComparison.Ordinal) || // sub station alpha p.Text.StartsWith("{\\an3}", StringComparison.Ordinal) || p.Text.StartsWith("{\\an6}", StringComparison.Ordinal) || p.Text.StartsWith("{\\an9}", StringComparison.Ordinal); // advanced sub station alpha bool alignVTop = p.Text.StartsWith("{\\a5}", StringComparison.Ordinal) || p.Text.StartsWith("{\\a6}", StringComparison.Ordinal) || p.Text.StartsWith("{\\a7}", StringComparison.Ordinal) || // sub station alpha p.Text.StartsWith("{\\an7}", StringComparison.Ordinal) || p.Text.StartsWith("{\\an8}", StringComparison.Ordinal) || p.Text.StartsWith("{\\an9}", StringComparison.Ordinal); // advanced sub station alpha bool alignVCenter = p.Text.StartsWith("{\\a9}", StringComparison.Ordinal) || p.Text.StartsWith("{\\a10}", StringComparison.Ordinal) || p.Text.StartsWith("{\\a11}", StringComparison.Ordinal) || // sub station alpha p.Text.StartsWith("{\\an4}", StringComparison.Ordinal) || p.Text.StartsWith("{\\an5}", StringComparison.Ordinal) || p.Text.StartsWith("{\\an6}", StringComparison.Ordinal); // advanced sub station alpha string text = Utilities.RemoveSsaTags(p.Text); var lines = text.SplitToLines(); int vPos; int vPosFactor = (int)Math.Round(fontSize / 7.4); if (alignVTop) { vPos = Configuration.Settings.SubtitleSettings.DCinemaBottomMargin; // Bottom margin is normally 8 } else if (alignVCenter) { vPos = (int)Math.Round((lines.Count * vPosFactor * -1) / 2.0); } else { vPos = (lines.Count * vPosFactor) - vPosFactor + Configuration.Settings.SubtitleSettings.DCinemaBottomMargin; // Bottom margin is normally 8 } bool isItalic = false; int fontNo = 0; var fontColors = new Stack <string>(); foreach (string line in lines) { var textNode = xml.CreateElement("Text"); var vPosition = xml.CreateAttribute("VPosition"); vPosition.InnerText = vPos.ToString(); textNode.Attributes.Append(vPosition); if (Math.Abs(Configuration.Settings.SubtitleSettings.DCinemaZPosition) > 0.01) { var zPosition = xml.CreateAttribute("ZPosition"); zPosition.InnerText = string.Format(CultureInfo.InvariantCulture, "{0:0.00}", Configuration.Settings.SubtitleSettings.DCinemaZPosition); textNode.Attributes.Append(zPosition); } var vAlign = xml.CreateAttribute("VAlign"); if (alignVTop) { vAlign.InnerText = "top"; } else if (alignVCenter) { vAlign.InnerText = "center"; } else { vAlign.InnerText = "bottom"; } textNode.Attributes.Append(vAlign); var hAlign = xml.CreateAttribute("HAlign"); if (alignLeft) { hAlign.InnerText = "left"; } else if (alignRight) { hAlign.InnerText = "right"; } else { hAlign.InnerText = "center"; } textNode.Attributes.Append(hAlign); var direction = xml.CreateAttribute("Direction"); direction.InnerText = "horizontal"; textNode.Attributes.Append(direction); int i = 0; var txt = new StringBuilder(); var html = new StringBuilder(); XmlNode nodeTemp = xml.CreateElement("temp"); while (i < line.Length) { if (!isItalic && line.Substring(i).StartsWith("<i>", StringComparison.Ordinal)) { if (txt.Length > 0) { nodeTemp.InnerText = txt.ToString(); html.Append(nodeTemp.InnerXml); txt.Clear(); } isItalic = true; i += 2; } else if (isItalic && line.Substring(i).StartsWith("</i>", StringComparison.Ordinal)) { if (txt.Length > 0) { var fontNode = xml.CreateElement("Font"); var italic = xml.CreateAttribute("Italic"); italic.InnerText = "yes"; fontNode.Attributes.Append(italic); if (!string.IsNullOrEmpty(ss.CurrentDCinemaFontEffect)) { var fontEffect = xml.CreateAttribute("Effect"); fontEffect.InnerText = ss.CurrentDCinemaFontEffect; fontNode.Attributes.Append(fontEffect); } if (line.Length > i + 5 && line.Substring(i + 4).StartsWith("</font>", StringComparison.Ordinal)) { var fontColor = xml.CreateAttribute("Color"); fontColor.InnerText = fontColors.Pop(); fontNode.Attributes.Append(fontColor); fontNo--; i += 7; } fontNode.InnerText = HtmlUtil.RemoveHtmlTags(txt.ToString()); html.Append(fontNode.OuterXml); txt.Clear(); } isItalic = false; i += 3; } else if (line.Substring(i).StartsWith("<font color=", StringComparison.Ordinal) && line.Substring(i + 3).Contains('>')) { int endOfFont = line.IndexOf('>', i); if (txt.Length > 0) { nodeTemp.InnerText = txt.ToString(); html.Append(nodeTemp.InnerXml); txt.Clear(); } string c = line.Substring(i + 12, endOfFont - (i + 12)); c = c.Trim('"').Trim('\'').Trim(); if (c.StartsWith('#')) { c = c.TrimStart('#').ToUpper().PadLeft(8, 'F'); } fontColors.Push(c); fontNo++; i += endOfFont - i; } else if (fontNo > 0 && line.Substring(i).StartsWith("</font>", StringComparison.Ordinal)) { if (txt.Length > 0) { var fontNode = xml.CreateElement("Font"); var fontColor = xml.CreateAttribute("Color"); fontColor.InnerText = fontColors.Pop(); fontNode.Attributes.Append(fontColor); if (line.Length > i + 9 && line.Substring(i + 7).StartsWith("</i>", StringComparison.Ordinal)) { var italic = xml.CreateAttribute("Italic"); italic.InnerText = "yes"; fontNode.Attributes.Append(italic); isItalic = false; i += 4; } if (!string.IsNullOrEmpty(ss.CurrentDCinemaFontEffect)) { var fontEffect = xml.CreateAttribute("Effect"); fontEffect.InnerText = ss.CurrentDCinemaFontEffect; fontNode.Attributes.Append(fontEffect); } fontNode.InnerText = HtmlUtil.RemoveHtmlTags(txt.ToString()); html.Append(fontNode.OuterXml); txt.Clear(); } fontNo--; i += 6; } else { txt.Append(line[i]); } i++; } if (fontNo > 0) { if (txt.Length > 0) { var fontNode = xml.CreateElement("Font"); var fontColor = xml.CreateAttribute("Color"); fontColor.InnerText = fontColors.Peek(); fontNode.Attributes.Append(fontColor); if (isItalic) { var italic = xml.CreateAttribute("Italic"); italic.InnerText = "yes"; fontNode.Attributes.Append(italic); } if (!string.IsNullOrEmpty(ss.CurrentDCinemaFontEffect)) { var fontEffect = xml.CreateAttribute("Effect"); fontEffect.InnerText = ss.CurrentDCinemaFontEffect; fontNode.Attributes.Append(fontEffect); } fontNode.InnerText = HtmlUtil.RemoveHtmlTags(txt.ToString()); html.Append(fontNode.OuterXml); } else if (html.Length > 0 && html.ToString().StartsWith("<Font ", StringComparison.Ordinal)) { var temp = new XmlDocument(); temp.LoadXml("<root>" + html + "</root>"); var fontNode = xml.CreateElement("Font"); fontNode.InnerXml = temp.DocumentElement.SelectSingleNode("Font").InnerXml; foreach (XmlAttribute a in temp.DocumentElement.SelectSingleNode("Font").Attributes) { var newA = xml.CreateAttribute(a.Name); newA.InnerText = a.InnerText; fontNode.Attributes.Append(newA); } var fontColor = xml.CreateAttribute("Color"); fontColor.InnerText = fontColors.Peek(); fontNode.Attributes.Append(fontColor); if (!string.IsNullOrEmpty(ss.CurrentDCinemaFontEffect)) { var fontEffect = xml.CreateAttribute("Effect"); fontEffect.InnerText = ss.CurrentDCinemaFontEffect; fontNode.Attributes.Append(fontEffect); } html.Clear(); html.Append(fontNode.OuterXml); } } else if (isItalic) { if (txt.Length > 0) { var fontNode = xml.CreateElement("Font"); var italic = xml.CreateAttribute("Italic"); italic.InnerText = "yes"; fontNode.Attributes.Append(italic); if (!string.IsNullOrEmpty(ss.CurrentDCinemaFontEffect)) { var fontEffect = xml.CreateAttribute("Effect"); fontEffect.InnerText = ss.CurrentDCinemaFontEffect; fontNode.Attributes.Append(fontEffect); } fontNode.InnerText = HtmlUtil.RemoveHtmlTags(txt.ToString()); html.Append(fontNode.OuterXml); } } else { if (txt.Length > 0) { nodeTemp.InnerText = txt.ToString(); html.Append(nodeTemp.InnerXml); } } textNode.InnerXml = html.ToString(); subNode.AppendChild(textNode); if (alignVTop) { vPos += vPosFactor; } else { vPos -= vPosFactor; } } mainListFont.AppendChild(subNode); no++; } } string s = ToUtf8XmlString(xml).Replace("encoding=\"utf-8\"", "encoding=\"UTF-8\""); while (s.Contains("</Font> ") || s.Contains(" <Font ") || s.Contains(Environment.NewLine + "<Font ") || s.Contains("</Font>" + Environment.NewLine)) { while (s.Contains(" Font")) { s = s.Replace(" <Font ", " <Font "); } while (s.Contains("\tFont")) { s = s.Replace("\t<Font ", " <Font "); } s = s.Replace("</Font> ", "</Font> "); s = s.Replace(" <Font ", " <Font "); s = s.Replace("\r\n<Font ", "<Font "); s = s.Replace("\r\n <Font ", "<Font "); s = s.Replace(Environment.NewLine + "<Font ", "<Font "); s = s.Replace(Environment.NewLine + " <Font ", "<Font "); s = s.Replace("</Font>\r\n", "</Font>"); s = s.Replace("</Font>" + Environment.NewLine, "</Font>"); s = s.Replace("><", "> <"); s = s.Replace("</Font> </Text>", "</Font></Text>"); s = s.Replace("horizontal\"> <Font", "horizontal\"><Font"); } return(s); }
public static string FixHyphensAdd(Subtitle subtitle, int i, string language) { Paragraph p = subtitle.Paragraphs[i]; string text = p.Text; var textCache = HtmlUtil.RemoveHtmlTags(text.TrimStart(), true); if (textCache.StartsWith('-') || textCache.Contains(Environment.NewLine + "-")) { Paragraph prev = subtitle.GetParagraphOrDefault(i - 1); if (prev == null || !HtmlUtil.RemoveHtmlTags(prev.Text).TrimEnd().EndsWith('-') || HtmlUtil.RemoveHtmlTags(prev.Text).TrimEnd().EndsWith("--", StringComparison.Ordinal)) { var lines = textCache.SplitToLines(); int startHyphenCount = lines.Count(line => line.TrimStart().StartsWith('-')); int totalSpaceHyphen = Utilities.CountTagInText(text, " -"); if (startHyphenCount == 1 && totalSpaceHyphen == 0) { var parts = textCache.SplitToLines(); if (parts.Count == 2 && !string.IsNullOrWhiteSpace(parts[0])) { var part0 = parts[0].TrimEnd().Trim('"'); bool doAdd = "!?.".Contains(part0[part0.Length - 1]) || LanguageAutoDetect.IsLanguageWithoutPeriods(language); if (parts[0].TrimStart().StartsWith('-') && parts[1].Contains(':') && doAdd || parts[1].TrimStart().StartsWith('-') && parts[0].Contains(':') && doAdd) { doAdd = false; } if (doAdd) { int idx = text.IndexOf('-'); int newLineIdx = text.IndexOf(Environment.NewLine, StringComparison.Ordinal); bool addSecondLine = idx < newLineIdx; if (addSecondLine && idx > 0 && char.IsLetter(text[idx - 1])) { addSecondLine = false; } if (addSecondLine) { // add dash in second line. var originalParts = text.SplitToLines(); if (originalParts[1].LineStartsWithHtmlTag(true)) { originalParts[1] = originalParts[1].Substring(0, 3) + "- " + originalParts[1].Remove(0, 3).TrimEnd(); } else if (originalParts[1].StartsWith("{\\an", StringComparison.Ordinal) && originalParts[1].Length > 6 && originalParts[1][5] == '}') { originalParts[1] = originalParts[1].Insert(6, "- "); } else { originalParts[1] = "- " + originalParts[1].Trim(); } text = originalParts[0] + Environment.NewLine + originalParts[1]; } else { // add dash in first line. if (text.LineStartsWithHtmlTag(true)) { text = text.Substring(0, 3) + "- " + text.Remove(0, 3).TrimEnd(); } else if (text.StartsWith("{\\an", StringComparison.Ordinal) && text.Length > 6 && text[5] == '}') { text = text.Insert(6, "- "); } else { text = "- " + text.Trim(); } } } } } // - Shut it off. -Get the f**k<br/>out of here, Darryl. if (totalSpaceHyphen == 1 && startHyphenCount == 1) { var idx = text.IndexOf(" -", StringComparison.Ordinal); if (idx > 1 && ".?!".Contains(text[idx - 1]) && idx + 2 < text.Length) { var firstLine = text.Substring(0, idx).Replace(Environment.NewLine, " ").Trim(); var secondLine = text.Substring(idx + 1).Insert(1, " ").Replace(Environment.NewLine, " ").Trim(); text = firstLine + Environment.NewLine + secondLine; } } } } return(text); }
public Subtitle MergeShortLinesInSubtitle(Subtitle subtitle, List <int> mergedIndexes, out int numberOfMerges, double maxMillisecondsBetweenLines, int maxCharacters, bool clearFixes) { listViewFixes.ItemChecked -= listViewFixes_ItemChecked; if (clearFixes) { listViewFixes.Items.Clear(); } numberOfMerges = 0; string language = LanguageAutoDetect.AutoDetectGoogleLanguage(subtitle); var mergedSubtitle = new Subtitle(); bool lastMerged = false; Paragraph p = null; var lineNumbers = new StringBuilder(); bool onlyContinuousLines = checkBoxOnlyContinuationLines.Checked; for (int i = 1; i < subtitle.Paragraphs.Count; i++) { if (!lastMerged) { p = new Paragraph(subtitle.GetParagraphOrDefault(i - 1)); mergedSubtitle.Paragraphs.Add(p); } Paragraph next = subtitle.GetParagraphOrDefault(i); if (next != null) { if (Utilities.QualifiesForMerge(p, next, maxMillisecondsBetweenLines, maxCharacters, onlyContinuousLines) && IsFixAllowed(p)) { if (MergeShortLinesUtils.GetStartTag(p.Text) == MergeShortLinesUtils.GetStartTag(next.Text) && MergeShortLinesUtils.GetEndTag(p.Text) == MergeShortLinesUtils.GetEndTag(next.Text)) { string s1 = p.Text.Trim(); s1 = s1.Substring(0, s1.Length - MergeShortLinesUtils.GetEndTag(s1).Length); string s2 = next.Text.Trim(); s2 = s2.Substring(MergeShortLinesUtils.GetStartTag(s2).Length); p.Text = Utilities.AutoBreakLine(s1 + Environment.NewLine + s2, language); } else { p.Text = Utilities.AutoBreakLine(p.Text + Environment.NewLine + next.Text, language); } p.EndTime = next.EndTime; if (lastMerged) { lineNumbers.Append(next.Number); lineNumbers.Append(','); } else { lineNumbers.Append(p.Number); lineNumbers.Append(','); lineNumbers.Append(next.Number); lineNumbers.Append(','); } lastMerged = true; numberOfMerges++; if (!mergedIndexes.Contains(i)) { mergedIndexes.Add(i); } if (!mergedIndexes.Contains(i - 1)) { mergedIndexes.Add(i - 1); } } else { lastMerged = false; } } else { lastMerged = false; } if (!lastMerged && lineNumbers.Length > 0 && clearFixes) { AddToListView(p, lineNumbers.ToString(), p.Text); lineNumbers.Clear(); } } if (!lastMerged) { mergedSubtitle.Paragraphs.Add(new Paragraph(subtitle.GetParagraphOrDefault(subtitle.Paragraphs.Count - 1))); } listViewFixes.ItemChecked += listViewFixes_ItemChecked; return(mergedSubtitle); }
public Subtitle SplitLongLinesInSubtitle(Subtitle subtitle, List <int> splittedIndexes, List <int> autoBreakedIndexes, out int numberOfSplits, int totalLineMaxCharacters, int singleLineMaxCharacters, bool clearFixes) { listViewFixes.ItemChecked -= listViewFixes_ItemChecked; if (clearFixes) { listViewFixes.Items.Clear(); } numberOfSplits = 0; string language = LanguageAutoDetect.AutoDetectGoogleLanguage(subtitle); var splittedSubtitle = new Subtitle(); string[] expectedPunctuations = { ". -", "! -", "? -" }; for (int i = 0; i < subtitle.Paragraphs.Count; i++) { bool added = false; var p = subtitle.Paragraphs[i]; if (p != null && p.Text != null) { if (SplitLongLinesHelper.QualifiesForSplit(p.Text, singleLineMaxCharacters, totalLineMaxCharacters) && IsFixAllowed(p)) { string oldText = HtmlUtil.RemoveHtmlTags(p.Text); bool isDialog = false; string dialogText = string.Empty; if (p.Text.Contains('-')) { dialogText = Utilities.AutoBreakLine(p.Text, 5, 1, language); var tempText = p.Text.Replace(Environment.NewLine, " ").Replace(" ", " "); if (Utilities.CountTagInText(tempText, '-') == 2 && (p.Text.StartsWith('-') || p.Text.StartsWith("<i>-", StringComparison.Ordinal))) { int idx = tempText.IndexOfAny(expectedPunctuations, StringComparison.Ordinal); if (idx > 1) { dialogText = tempText.Remove(idx + 1, 1).Insert(idx + 1, Environment.NewLine); } } var arr = dialogText.SplitToLines(); if (arr.Length == 2 && (arr[0].StartsWith('-') || arr[0].StartsWith("<i>-", StringComparison.Ordinal)) && (arr[1].StartsWith('-') || arr[1].StartsWith("<i>-", StringComparison.Ordinal))) { isDialog = true; } } if (!isDialog && !SplitLongLinesHelper.QualifiesForSplit(Utilities.AutoBreakLine(p.Text, language), singleLineMaxCharacters, totalLineMaxCharacters)) { var newParagraph = new Paragraph(p) { Text = Utilities.AutoBreakLine(p.Text, language) }; if (clearFixes) { AddToListView(p, (splittedSubtitle.Paragraphs.Count + 1).ToString(CultureInfo.InvariantCulture), oldText); } autoBreakedIndexes.Add(splittedSubtitle.Paragraphs.Count); splittedSubtitle.Paragraphs.Add(newParagraph); added = true; numberOfSplits++; } else { string text = Utilities.AutoBreakLine(p.Text, language); if (isDialog) { text = dialogText; } if (isDialog || text.Contains(Environment.NewLine)) { var arr = text.SplitToLines(); if (arr.Length == 2) { int spacing1 = Configuration.Settings.General.MinimumMillisecondsBetweenLines / 2; int spacing2 = Configuration.Settings.General.MinimumMillisecondsBetweenLines / 2; if (Configuration.Settings.General.MinimumMillisecondsBetweenLines % 2 == 1) { spacing2++; } var newParagraph1 = new Paragraph(p); var newParagraph2 = new Paragraph(p); newParagraph1.Text = Utilities.AutoBreakLine(arr[0], language); double middle = p.StartTime.TotalMilliseconds + (p.Duration.TotalMilliseconds / 2); if (!string.IsNullOrWhiteSpace(oldText)) { var startFactor = (double)HtmlUtil.RemoveHtmlTags(newParagraph1.Text).Length / oldText.Length; if (startFactor < 0.25) { startFactor = 0.25; } if (startFactor > 0.75) { startFactor = 0.75; } middle = p.StartTime.TotalMilliseconds + (p.Duration.TotalMilliseconds * startFactor); } newParagraph1.EndTime.TotalMilliseconds = middle - spacing1; newParagraph2.Text = Utilities.AutoBreakLine(arr[1], language); newParagraph2.StartTime.TotalMilliseconds = newParagraph1.EndTime.TotalMilliseconds + spacing2; if (clearFixes) { AddToListView(p, (splittedSubtitle.Paragraphs.Count + 1).ToString(CultureInfo.InvariantCulture), oldText); } splittedIndexes.Add(splittedSubtitle.Paragraphs.Count); splittedIndexes.Add(splittedSubtitle.Paragraphs.Count + 1); string p1 = HtmlUtil.RemoveHtmlTags(newParagraph1.Text).TrimEnd(); if (p1.EndsWith('.') || p1.EndsWith('!') || p1.EndsWith('?') || p1.EndsWith(':') || p1.EndsWith(')') || p1.EndsWith(']') || p1.EndsWith('♪')) { if (newParagraph1.Text.StartsWith('-') && newParagraph2.Text.StartsWith('-')) { newParagraph1.Text = newParagraph1.Text.Remove(0, 1).Trim(); newParagraph2.Text = newParagraph2.Text.Remove(0, 1).Trim(); } else if (newParagraph1.Text.StartsWith("<i>-", StringComparison.Ordinal) && newParagraph2.Text.StartsWith('-')) { newParagraph1.Text = newParagraph1.Text.Remove(3, 1).Trim(); if (newParagraph1.Text.StartsWith("<i> ", StringComparison.Ordinal)) { newParagraph1.Text = newParagraph1.Text.Remove(3, 1).Trim(); } newParagraph2.Text = newParagraph2.Text.Remove(0, 1).Trim(); } } else { bool endsWithComma = newParagraph1.Text.EndsWith(',') || newParagraph1.Text.EndsWith(",</i>", StringComparison.Ordinal); string post = string.Empty; if (newParagraph1.Text.EndsWith("</i>", StringComparison.Ordinal)) { post = "</i>"; newParagraph1.Text = newParagraph1.Text.Remove(newParagraph1.Text.Length - post.Length); } if (endsWithComma) { newParagraph1.Text += post; } else { newParagraph1.Text += comboBoxLineContinuationEnd.Text.TrimEnd() + post; } string pre = string.Empty; if (newParagraph2.Text.StartsWith("<i>", StringComparison.Ordinal)) { pre = "<i>"; newParagraph2.Text = newParagraph2.Text.Remove(0, pre.Length); } if (endsWithComma) { newParagraph2.Text = pre + newParagraph2.Text; } else { newParagraph2.Text = pre + comboBoxLineContinuationBegin.Text + newParagraph2.Text; } } var italicStart1 = newParagraph1.Text.IndexOf("<i>", StringComparison.Ordinal); if (italicStart1 >= 0 && italicStart1 < 10 && newParagraph1.Text.IndexOf("</i>", StringComparison.Ordinal) < 0 && newParagraph2.Text.Contains("</i>") && newParagraph2.Text.IndexOf("<i>", StringComparison.Ordinal) < 0) { newParagraph1.Text += "</i>"; newParagraph2.Text = "<i>" + newParagraph2.Text; } splittedSubtitle.Paragraphs.Add(newParagraph1); splittedSubtitle.Paragraphs.Add(newParagraph2); added = true; numberOfSplits++; } } } } if (!added) { splittedSubtitle.Paragraphs.Add(new Paragraph(p)); } } } listViewFixes.ItemChecked += listViewFixes_ItemChecked; splittedSubtitle.Renumber(); return(splittedSubtitle); }
public static Subtitle SplitLongLinesInSubtitle(Subtitle subtitle, int totalLineMaxCharacters, int singleLineMaxCharacters) { var splittedIndexes = new List <int>(); var autoBreakedIndexes = new List <int>(); var splittedSubtitle = new Subtitle(subtitle); splittedSubtitle.Paragraphs.Clear(); string language = LanguageAutoDetect.AutoDetectGoogleLanguage(subtitle); for (int i = 0; i < subtitle.Paragraphs.Count; i++) { bool added = false; var p = subtitle.GetParagraphOrDefault(i); if (p?.Text != null) { if (QualifiesForSplit(p.Text, singleLineMaxCharacters, totalLineMaxCharacters)) { var text = Utilities.AutoBreakLine(p.Text, language); if (!QualifiesForSplit(text, singleLineMaxCharacters, totalLineMaxCharacters)) { var newParagraph = new Paragraph(p) { Text = text }; autoBreakedIndexes.Add(splittedSubtitle.Paragraphs.Count); splittedSubtitle.Paragraphs.Add(newParagraph); added = true; } else { if (text.Contains(Environment.NewLine)) { var arr = text.SplitToLines(); if (arr.Count == 2) { var minMsBtwnLnBy2 = Configuration.Settings.General.MinimumMillisecondsBetweenLines / 2; int spacing1 = minMsBtwnLnBy2; int spacing2 = minMsBtwnLnBy2; if (Configuration.Settings.General.MinimumMillisecondsBetweenLines % 2 == 1) { spacing2++; } double duration = p.Duration.TotalMilliseconds / 2.0; var newParagraph1 = new Paragraph(p); var newParagraph2 = new Paragraph(p); newParagraph1.Text = Utilities.AutoBreakLine(arr[0], language); newParagraph1.EndTime.TotalMilliseconds = p.StartTime.TotalMilliseconds + duration - spacing1; newParagraph2.Text = Utilities.AutoBreakLine(arr[1], language); newParagraph2.StartTime.TotalMilliseconds = newParagraph1.EndTime.TotalMilliseconds + spacing2; splittedIndexes.Add(splittedSubtitle.Paragraphs.Count); splittedIndexes.Add(splittedSubtitle.Paragraphs.Count + 1); string p1 = HtmlUtil.RemoveHtmlTags(newParagraph1.Text); var len = p1.Length - 1; if (p1.Length > 0 && (p1[len] == '.' || p1[len] == '!' || p1[len] == '?' || p1[len] == ':' || p1[len] == ')' || p1[len] == ']' || p1[len] == '♪')) { if (newParagraph1.Text.StartsWith('-') && newParagraph2.Text.StartsWith('-')) { newParagraph1.Text = newParagraph1.Text.Remove(0, 1).Trim(); newParagraph2.Text = newParagraph2.Text.Remove(0, 1).Trim(); } else if (newParagraph1.Text.StartsWith("<i>-", StringComparison.Ordinal) && newParagraph2.Text.StartsWith('-')) { newParagraph1.Text = newParagraph1.Text.Remove(3, 1).Trim(); if (newParagraph1.Text.StartsWith("<i> ", StringComparison.Ordinal)) { newParagraph1.Text = newParagraph1.Text.Remove(3, 1).Trim(); } newParagraph2.Text = newParagraph2.Text.Remove(0, 1).Trim(); } } else { if (newParagraph1.Text.EndsWith("</i>", StringComparison.Ordinal)) { const string post = "</i>"; newParagraph1.Text = newParagraph1.Text.Remove(newParagraph1.Text.Length - post.Length); } if (newParagraph2.Text.StartsWith("<i>", StringComparison.Ordinal)) { const string pre = "<i>"; newParagraph2.Text = newParagraph2.Text.Remove(0, pre.Length); } } var indexOfItalicOpen1 = newParagraph1.Text.IndexOf("<i>", StringComparison.Ordinal); if (indexOfItalicOpen1 >= 0 && indexOfItalicOpen1 < 10 && newParagraph1.Text.IndexOf("</i>", StringComparison.Ordinal) < 0 && newParagraph2.Text.Contains("</i>") && newParagraph2.Text.IndexOf("<i>", StringComparison.Ordinal) < 0) { newParagraph1.Text += "</i>"; newParagraph2.Text = "<i>" + newParagraph2.Text; } splittedSubtitle.Paragraphs.Add(newParagraph1); splittedSubtitle.Paragraphs.Add(newParagraph2); added = true; } } } } } if (!added) { splittedSubtitle.Paragraphs.Add(new Paragraph(p)); } } splittedSubtitle.Renumber(); return(splittedSubtitle); }
private void ButtonExportClick(object sender, EventArgs e) { using (var saveFileDialog = new SaveFileDialog { Title = LanguageSettings.Current.General.OpenSubtitle, FileName = "translate.docx", Filter = "Word docx files|*.docx", }) { if (saveFileDialog.ShowDialog() != DialogResult.OK) { return; } Subtitle = new Subtitle(SubtitleOriginal, false); _skipIndices = new Dictionary <int, int>(); var texts = new List <string>(); var mergeCount = 0; var autoMerge = checkBoxAutoMerge.Checked; var language = LanguageAutoDetect.AutoDetectGoogleLanguage(Subtitle); using (var document = DocX.Create(saveFileDialog.FileName)) { for (var index = 0; index < Subtitle.Paragraphs.Count; index++) { if (mergeCount > 0) { mergeCount--; continue; } var subtitleParagraph = Subtitle.Paragraphs[index]; var text = subtitleParagraph.Text; if (autoMerge) { if (MergeWithThreeNext(Subtitle, index, language)) { mergeCount = 3; _skipIndices.Add(index, mergeCount); text = Utilities.RemoveLineBreaks(text + Environment.NewLine + Subtitle.Paragraphs[index + 1].Text + Environment.NewLine + Subtitle.Paragraphs[index + 2].Text); } else if (MergeWithTwoNext(Subtitle, index, language)) { mergeCount = 2; _skipIndices.Add(index, mergeCount); text = Utilities.RemoveLineBreaks(text + Environment.NewLine + Subtitle.Paragraphs[index + 1].Text + Environment.NewLine + Subtitle.Paragraphs[index + 2].Text); } else if (MergeWithNext(Subtitle, index, language)) { mergeCount = 1; _skipIndices.Add(index, mergeCount); text = Utilities.RemoveLineBreaks(text + Environment.NewLine + Subtitle.Paragraphs[index + 1].Text); } } texts.Add(text); } var table = document.AddTable(texts.Count, 1); table.AutoFit = AutoFit.Window; for (var index = 0; index < texts.Count; index++) { var text = texts[index]; table.Rows[index].Cells[0].InsertParagraph(text); } var p = document.InsertParagraph(string.Empty); p.Alignment = Alignment.both; p.InsertTableAfterSelf(table); document.Save(); } } }
private void ButtonOkClick(object sender, EventArgs e) { if (string.IsNullOrWhiteSpace(textBoxAddName.Text)) { return; } NewName = textBoxAddName.Text.RemoveControlCharacters().Trim(); string languageName = null; _language = Configuration.Settings.Language.Main; if (!string.IsNullOrEmpty(Configuration.Settings.General.SpellCheckLanguage)) { languageName = Configuration.Settings.General.SpellCheckLanguage; } else { List <string> list = Utilities.GetDictionaryLanguages(); if (list.Count > 0) { string name = list[0]; int start = name.LastIndexOf('['); int end = name.LastIndexOf(']'); if (start > 0 && end > start) { start++; name = name.Substring(start, end - start); languageName = name; } else { MessageBox.Show(string.Format(_language.InvalidLanguageNameX, name)); return; } } } languageName = LanguageAutoDetect.AutoDetectLanguageName(languageName, _subtitle); if (comboBoxDictionaries.Items.Count > 0) { string name = comboBoxDictionaries.SelectedItem.ToString(); int start = name.LastIndexOf('['); int end = name.LastIndexOf(']'); if (start >= 0 && end > start) { start++; name = name.Substring(start, end - start); languageName = name; } } if (string.IsNullOrEmpty(languageName)) { languageName = "en_US"; } var namesList = new NamesList(Configuration.DictionariesFolder, languageName, Configuration.Settings.WordLists.UseOnlineNamesEtc, Configuration.Settings.WordLists.NamesEtcUrl); if (namesList.Add(textBoxAddName.Text)) { DialogResult = DialogResult.OK; } else { DialogResult = DialogResult.Cancel; } }
private void ButtonImportClick(object sender, EventArgs e) { using (var openFileDialog1 = new OpenFileDialog()) { openFileDialog1.Title = LanguageSettings.Current.General.OpenSubtitle; openFileDialog1.FileName = string.Empty; openFileDialog1.Filter = "Word docx files|*.docx"; openFileDialog1.FileName = string.Empty; var result = openFileDialog1.ShowDialog(this); if (result != DialogResult.OK) { return; } try { using (var document = DocX.Load(openFileDialog1.FileName)) { var table = document.Tables.FirstOrDefault(); if (table == null) { return; } var splitLines = table.Rows.Count + _skipIndices.Count == Subtitle.Paragraphs.Count; if (!splitLines && table.Rows.Count != Subtitle.Paragraphs.Count) { var res = MessageBox.Show($"Table rows ({table.Rows.Count} + {_skipIndices.Count}) does not match subtitle count ({Subtitle.Paragraphs.Count})" + Environment.NewLine + "Continue?", "Subtitel Edit", MessageBoxButtons.YesNoCancel); if (res != DialogResult.Yes) { return; } } var language = LanguageAutoDetect.AutoDetectGoogleLanguage(Subtitle); var count = 0; foreach (var tableRow in table.Rows) { var p = Subtitle.GetParagraphOrDefault(count); if (p != null) { p.Text = string.Empty; foreach (var paragraph in tableRow.Cells[0].Paragraphs) { p.Text = (p.Text + Environment.NewLine + paragraph.Text).Trim(); } var text = string.Join(Environment.NewLine, p.Text.SplitToLines()); if (_skipIndices.TryGetValue(count, out var splitCount)) { var lines = SplitResult(text, splitCount, language); while (lines.Count < splitCount) { lines.Add(string.Empty); } foreach (var line in lines) { p = Subtitle.GetParagraphOrDefault(count); p.Text = line; count++; } continue; } p.Text = text; } count++; } } DialogResult = DialogResult.OK; } catch (Exception exception) { MessageBox.Show(exception.Message); } } }
public static bool IsPlainText(string fileName) { var fileInfo = new FileInfo(fileName); if (fileInfo.Length < 20) { return(false); // too short to be plain text } if (fileInfo.Length > 5000000) { return(false); // too large to be plain text } var enc = LanguageAutoDetect.GetEncodingFromFile(fileName); var s = ReadAllTextShared(fileName, enc); int numberCount = 0; int letterCount = 0; int len = s.Length; for (int i = 0; i < len; i++) { var ch = s[i]; if (char.IsLetter(ch) || " -,.!?[]()\r\n".Contains(ch)) { letterCount++; } else if (char.IsControl(ch) && ch != '\t') // binary found { return(false); } else if (CharUtils.IsDigit(ch)) { numberCount++; } } if (len < 100) { return(numberCount < 5 && letterCount > 20); } var numberPatternMatches = new Regex(@"\d+[.:,; -]\d+").Matches(s); if (numberPatternMatches.Count > 30) { return(false); // looks like time codes } var largeBlocksOfLargeNumbers = new Regex(@"\d{3,8}").Matches(s); if (largeBlocksOfLargeNumbers.Count > 30) { return(false); // looks like time codes } if (len < 1000 && largeBlocksOfLargeNumbers.Count > 10) { return(false); // looks like time codes } var partsWithMoreThan100CharsOfNonNumbers = new Regex(@"[^\d]{150,100000}").Matches(s); if (partsWithMoreThan100CharsOfNonNumbers.Count > 10) { return(true); // looks like text } var numberThreshold = len * 0.015 + 25; var letterThreshold = len * 0.8; return(numberCount < numberThreshold && letterCount > letterThreshold); }
public override string ToText(Subtitle subtitle, string title) { var language = LanguageAutoDetect.AutoDetectGoogleLanguage(subtitle); var sb = new StringBuilder(); var header = @" { 'SubtitleLanguages': [ { 'IsForced': false, 'ClassName': '[LANGUAGE_CODE]', 'Name': '[LANGUAGE_ENGLISH]', 'NativeName': '[LANGUAGE_NATIVE]', 'SubtitleItems': [" .Replace('\'', '"') .Replace("[LANGUAGE_CODE]", language); try { var ci = new CultureInfo(language); header = header.Replace("[LANGUAGE_ENGLISH]", ci.EnglishName); header = header.Replace("[LANGUAGE_NATIVE]", ci.NativeName); } catch { header = header.Replace("[LANGUAGE_ENGLISH]", "unknown"); header = header.Replace("[LANGUAGE_NATIVE]", "unknown"); } sb.AppendLine(header); for (int i = 0; i < subtitle.Paragraphs.Count; i++) { if (i > 0) { sb.AppendLine("\t\t,"); } sb.AppendLine("\t\t{"); sb.AppendLine("\t\t\t\"TextLines\": ["); Paragraph p = subtitle.Paragraphs[i]; var lines = p.Text.SplitToLines(); for (int j = 0; j < lines.Count; j++) { sb.Append("\t\t\t"); sb.Append('"'); sb.Append(Json.EncodeJsonText(lines[j])); sb.Append('"'); if (j < lines.Count - 1) { sb.Append(','); } sb.AppendLine(); } sb.AppendLine("\t\t\t],"); sb.AppendLine($"\t\t\t\"ClassName\": \"{language}\", "); sb.AppendLine($"\t\t\t\"ShowTime\": {p.StartTime.TotalMilliseconds}, "); sb.AppendLine($"\t\t\t\"HideTime\": {p.EndTime.TotalMilliseconds}"); sb.AppendLine("\t\t}"); } sb.Append(@" ], 'ReturnCode': { 'Id': 1, 'Code': 'SUCCESS' } } ] }").Replace('\'', '"'); return(sb.ToString().Trim()); }
public Cavena890SaveOptions(Subtitle subtitle, string subtitleFileName) { UiUtil.PreInitialize(this); InitializeComponent(); UiUtil.FixFonts(this); buttonCancel.Text = LanguageSettings.Current.General.Cancel; buttonOK.Text = LanguageSettings.Current.General.Ok; timeUpDownStartTime.ForceHHMMSSFF(); timeUpDownStartTime.TimeCode = new TimeCode(TimeCode.ParseHHMMSSFFToMilliseconds(Configuration.Settings.SubtitleSettings.Cavena890StartOfMessage)); textBoxTranslatedTitle.Text = Configuration.Settings.SubtitleSettings.CurrentCavena89Title; textBoxOriginalTitle.Text = Configuration.Settings.SubtitleSettings.CurrentCavena890riginalTitle; textBoxTranslator.Text = Configuration.Settings.SubtitleSettings.CurrentCavena890Translator; textBoxComment.Text = Configuration.Settings.SubtitleSettings.CurrentCavena89Comment; if (string.IsNullOrWhiteSpace(textBoxComment.Text)) { textBoxComment.Text = "Made with Subtitle Edit"; } if (string.IsNullOrWhiteSpace(Configuration.Settings.SubtitleSettings.CurrentCavena89Title)) { string title = Path.GetFileNameWithoutExtension(subtitleFileName) ?? string.Empty; if (title.Length > 28) { title = title.Substring(0, 28); } textBoxTranslatedTitle.Text = title; } var language = LanguageAutoDetect.AutoDetectGoogleLanguage(subtitle); switch (language) { case "he": Configuration.Settings.SubtitleSettings.CurrentCavena89LanguageId = Cavena890.LanguageIdHebrew; comboBoxLanguage.SelectedIndex = 5; break; case "ru": Configuration.Settings.SubtitleSettings.CurrentCavena89LanguageId = Cavena890.LanguageIdRussian; comboBoxLanguage.SelectedIndex = 6; break; case "ro": Configuration.Settings.SubtitleSettings.CurrentCavena89LanguageId = Cavena890.LanguageIdRomanian; comboBoxLanguage.SelectedIndex = 7; break; case "zh": Configuration.Settings.SubtitleSettings.CurrentCavena89LanguageId = Cavena890.LanguageIdChineseSimplified; comboBoxLanguage.SelectedIndex = 2; break; case "da": Configuration.Settings.SubtitleSettings.CurrentCavena89LanguageId = Cavena890.LanguageIdDanish; comboBoxLanguage.SelectedIndex = 1; break; default: Configuration.Settings.SubtitleSettings.CurrentCavena89LanguageId = Cavena890.LanguageIdEnglish; comboBoxLanguage.SelectedIndex = 4; break; } }
public void Save(string fileName, Subtitle subtitle) { using (var fs = new FileStream(fileName, FileMode.Create, FileAccess.Write)) { int russianCount = 0; foreach (Paragraph p in subtitle.Paragraphs) { if (p.Text.Contains(new[] { '的', '是', '啊', '吧', '好', '吧', '亲', '爱', '的', '早', '上' })) { _languageIdLine1 = LanguageIdChineseSimplified; _languageIdLine2 = LanguageIdChineseSimplified; break; } if (p.Text.Contains(new[] { 'я', 'д', 'й', 'л', 'щ', 'ж', 'ц', 'ф', 'ы' })) { russianCount++; if (russianCount > 10) { _languageIdLine1 = LanguageIdRussian; _languageIdLine2 = LanguageIdRussian; // or 0x09? break; } } } var language = LanguageAutoDetect.AutoDetectGoogleLanguage(subtitle); if (language == "he") // Hebrew { _languageIdLine1 = LanguageIdHebrew; _languageIdLine2 = LanguageIdHebrew; // or 0x09 } else if (language == "ru") { _languageIdLine1 = LanguageIdRussian; _languageIdLine2 = LanguageIdRussian; // or 0x09? } else if (language == "zh") { _languageIdLine1 = LanguageIdChineseSimplified; _languageIdLine2 = LanguageIdChineseSimplified; } else if (language == "da") { _languageIdLine1 = LanguageIdDanish; _languageIdLine2 = LanguageIdDanish; } // prompt??? //if (Configuration.Settings.SubtitleSettings.CurrentCavena890LanguageIdLine1 >= 0) // _languageIdLine1 = Configuration.Settings.SubtitleSettings.CurrentCavena890LanguageIdLine1; //if (Configuration.Settings.SubtitleSettings.CurrentCavena890LanguageIdLine2 >= 0) // _languageIdLine2 = Configuration.Settings.SubtitleSettings.CurrentCavena890LanguageIdLine2; // write file header (some fields are known, some are not...) fs.WriteByte(0); // ? fs.WriteByte(0); // ? // tape number (20 bytes) for (int i = 0; i < 20; i++) { fs.WriteByte(0); } // ? for (int i = 0; i < 18; i++) { fs.WriteByte(0); } // translated programme title (28 bytes) string title = Path.GetFileNameWithoutExtension(fileName) ?? string.Empty; if (title.Length > 28) { title = title.Substring(0, 28); } var buffer = Encoding.ASCII.GetBytes(title); fs.Write(buffer, 0, buffer.Length); for (int i = 0; i < 28 - buffer.Length; i++) { fs.WriteByte(0); } // translator (28 bytes) for (int i = 0; i < 28; i++) { fs.WriteByte(0); } // ? for (int i = 0; i < 9; i++) { fs.WriteByte(0); } // translated episode title (11 bytes) for (int i = 0; i < 11; i++) { fs.WriteByte(0); } // ? for (int i = 0; i < 18; i++) { fs.WriteByte(0); } // ? + language codes buffer = new byte[] { 0xA0, 0x05, 0x04, 0x03, 0x06, 0x06, 0x08, 0x90, 0x00, 0x00, 0x00, 0x00, (byte)_languageIdLine1, (byte)_languageIdLine2 }; fs.Write(buffer, 0, buffer.Length); // comments (24 bytes) buffer = Encoding.ASCII.GetBytes("Made with Subtitle Edit"); fs.Write(buffer, 0, buffer.Length); for (int i = 0; i < 24 - buffer.Length; i++) { fs.WriteByte(0); } // ?? buffer = new byte[] { 0x08, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00 }; fs.Write(buffer, 0, buffer.Length); // number of subtitles fs.WriteByte((byte)(subtitle.Paragraphs.Count % 256)); fs.WriteByte((byte)(subtitle.Paragraphs.Count / 256)); // write font - prefix with binary zeroes buffer = GetFontBytesFromLanguageId(_languageIdLine1); // also TBX308VFONTL.V for english... for (int i = 0; i < 14 - buffer.Length; i++) { fs.WriteByte(0); } fs.Write(buffer, 0, buffer.Length); // ? for (int i = 0; i < 13; i++) { fs.WriteByte(0); } // some language codes again? if (_languageIdLine1 == LanguageIdHebrew || _languageIdLine2 == LanguageIdHebrew) { buffer = new byte[] { 0x64, 0x02, 0x64, 0x02 }; } else if (_languageIdLine1 == LanguageIdRussian || _languageIdLine2 == LanguageIdRussian) { buffer = new byte[] { 0xce, 0x00, 0xce, 0x00 }; } else { buffer = new byte[] { 0x37, 0x00, 0x37, 0x00 }; // seen in English files } fs.Write(buffer, 0, buffer.Length); // ? for (int i = 0; i < 6; i++) { fs.WriteByte(0); } // original programme title (28 chars) for (int i = 0; i < 28; i++) { fs.WriteByte(0); } // write font (use same font id from line 1) buffer = GetFontBytesFromLanguageId(_languageIdLine1); fs.Write(buffer, 0, buffer.Length); buffer = new byte[] { 0x3d, 0x8d, 0x31, 0x30, 0x3A, 0x30, 0x30, 0x3A, 0x30, 0x30, 0x3A, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x54, 0x44 }; fs.Write(buffer, 0, buffer.Length); for (int i = 0; i < 92; i++) { fs.WriteByte(0); } // paragraphs int number = 16; foreach (Paragraph p in subtitle.Paragraphs) { // number fs.WriteByte((byte)(number / 256)); fs.WriteByte((byte)(number % 256)); WriteTime(fs, p.StartTime); WriteTime(fs, p.EndTime); if (p.Text.StartsWith("{\\an1}")) { fs.WriteByte(0x50); // left } else if (p.Text.StartsWith("{\\an3}")) { fs.WriteByte(0x52); // left } else { fs.WriteByte(0x54); // center } buffer = new byte[] { 0, 0, 0, 0, 0, 0, 0 }; // 0x16 }; -- the last two bytes might be something with vertical alignment... fs.Write(buffer, 0, buffer.Length); WriteText(fs, p.Text, p == subtitle.Paragraphs[subtitle.Paragraphs.Count - 1], _languageIdLine1); number += 16; } } }
public override string ToText(Subtitle subtitle, string title) { string threeLetterLanguage; string languageDisplay; try { var ci = new CultureInfo(LanguageAutoDetect.AutoDetectGoogleLanguage(subtitle)); threeLetterLanguage = ci.GetThreeLetterIsoLanguageName(); languageDisplay = ci.EnglishName; } catch { threeLetterLanguage = "eng"; languageDisplay = "English"; } string xmlStructure = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + Environment.NewLine + "<esub-xf xmlns=\"" + NameSpaceUri + "\" framerate=\"" + Configuration.Settings.General.CurrentFrameRate.ToString(CultureInfo.InvariantCulture) + "\" timebase=\"smpte\">" + Environment.NewLine + " <subtitlelist language=\"" + threeLetterLanguage + "\" langname=\"" + languageDisplay + "\" type=\"translation\">" + Environment.NewLine + " </subtitlelist>" + Environment.NewLine + "</esub-xf>"; var xml = new XmlDocument { XmlResolver = null }; xml.LoadXml(xmlStructure); var ns = new XmlNamespaceManager(xml.NameTable); ns.AddNamespace("esub-xf", NameSpaceUri); var subtitleList = xml.DocumentElement.SelectSingleNode("//esub-xf:subtitlelist", ns); foreach (var p in subtitle.Paragraphs) { var text = p.Text; var paragraph = xml.CreateElement("subtitle", NameSpaceUri); var start = xml.CreateAttribute("display"); start.InnerText = p.StartTime.ToHHMMSSFF(); paragraph.Attributes.Append(start); var end = xml.CreateAttribute("clear"); end.InnerText = p.EndTime.ToHHMMSSFF(); paragraph.Attributes.Append(end); var hRegion = xml.CreateElement("hregion", NameSpaceUri); if (text.StartsWith("{\\an7}") || p.Text.StartsWith("{\\an8}") || p.Text.StartsWith("{\\an9}")) { var vpos = xml.CreateAttribute("vposition"); vpos.Value = "top"; hRegion.Attributes.Append(vpos); } paragraph.AppendChild(hRegion); text = Utilities.RemoveSsaTags(text); if (text.Contains("<i>", StringComparison.OrdinalIgnoreCase) || text.Contains("<b>", StringComparison.OrdinalIgnoreCase) || text.Contains("<font", StringComparison.OrdinalIgnoreCase)) { GenerateLineWithSpan(text, xml, hRegion); } else { foreach (var line in text.SplitToLines()) { var lineNode = xml.CreateElement("line", NameSpaceUri); hRegion.AppendChild(lineNode); lineNode.InnerText = line; } } subtitleList.AppendChild(paragraph); } return(ToUtf8XmlString(xml)); }
internal static bool BatchConvertSave(string toFormat, string offset, Encoding targetEncoding, string outputFolder, int count, ref int converted, ref int errors, IList <SubtitleFormat> formats, string fileName, Subtitle sub, SubtitleFormat format, bool overwrite, string pacCodePage, double?targetFrameRate, bool removeTextForHi, bool fixCommonErrors, bool redoCasing) { double oldFrameRate = Configuration.Settings.General.CurrentFrameRate; try { // adjust offset if (!string.IsNullOrEmpty(offset) && (offset.StartsWith("/offset:", StringComparison.Ordinal) || offset.StartsWith("offset:", StringComparison.Ordinal))) { string[] parts = offset.Split(new[] { ':' }, StringSplitOptions.RemoveEmptyEntries); if (parts.Length == 5) { try { var ts = new TimeSpan(0, int.Parse(parts[1].TrimStart('-')), int.Parse(parts[2]), int.Parse(parts[3]), int.Parse(parts[4])); if (parts[1].StartsWith('-')) { sub.AddTimeToAllParagraphs(ts.Negate()); } else { sub.AddTimeToAllParagraphs(ts); } } catch { Console.Write(" (unable to read offset " + offset + ")"); } } } // adjust frame rate if (targetFrameRate.HasValue) { sub.ChangeFrameRate(Configuration.Settings.General.CurrentFrameRate, targetFrameRate.Value); Configuration.Settings.General.CurrentFrameRate = targetFrameRate.Value; } if (removeTextForHi) { var hiSettings = new Core.Forms.RemoveTextForHISettings(); var hiLib = new Core.Forms.RemoveTextForHI(hiSettings); foreach (var p in sub.Paragraphs) { p.Text = hiLib.RemoveTextFromHearImpaired(p.Text); } } if (fixCommonErrors) { using (var fce = new FixCommonErrors { BatchMode = true }) { for (int i = 0; i < 3; i++) { fce.RunBatch(sub, format, targetEncoding, Configuration.Settings.Tools.BatchConvertLanguage); sub = fce.FixedSubtitle; } } } if (redoCasing) { using (var changeCasing = new ChangeCasing()) { changeCasing.FixCasing(sub, LanguageAutoDetect.AutoDetectGoogleLanguage(sub)); } using (var changeCasingNames = new ChangeCasingNames()) { changeCasingNames.Initialize(sub); changeCasingNames.FixCasing(); } } bool targetFormatFound = false; string outputFileName; foreach (SubtitleFormat sf in formats) { if (sf.IsTextBased && (sf.Name.Replace(" ", string.Empty).Equals(toFormat, StringComparison.OrdinalIgnoreCase) || sf.Name.Replace(" ", string.Empty).Equals(toFormat.Replace(" ", string.Empty), StringComparison.OrdinalIgnoreCase))) { targetFormatFound = true; sf.BatchMode = true; outputFileName = FormatOutputFileNameForBatchConvert(fileName, sf.Extension, outputFolder, overwrite); Console.Write("{0}: {1} -> {2}...", count, Path.GetFileName(fileName), outputFileName); if (sf.IsFrameBased && !sub.WasLoadedWithFrameNumbers) { sub.CalculateFrameNumbersFromTimeCodesNoCheck(Configuration.Settings.General.CurrentFrameRate); } else if (sf.IsTimeBased && sub.WasLoadedWithFrameNumbers) { sub.CalculateTimeCodesFromFrameNumbers(Configuration.Settings.General.CurrentFrameRate); } if ((sf.GetType() == typeof(WebVTT) || sf.GetType() == typeof(WebVTTFileWithLineNumber))) { targetEncoding = Encoding.UTF8; } if (sf.GetType() == typeof(ItunesTimedText) || sf.GetType() == typeof(ScenaristClosedCaptions) || sf.GetType() == typeof(ScenaristClosedCaptionsDropFrame)) { Encoding outputEnc = new UTF8Encoding(false); // create encoding with no BOM using (var file = new StreamWriter(outputFileName, false, outputEnc)) // open file with encoding { file.Write(sub.ToText(sf)); } // save and close it } else if (targetEncoding == Encoding.UTF8 && (format.GetType() == typeof(TmpegEncAW5) || format.GetType() == typeof(TmpegEncXml))) { Encoding outputEnc = new UTF8Encoding(false); // create encoding with no BOM using (var file = new StreamWriter(outputFileName, false, outputEnc)) // open file with encoding { file.Write(sub.ToText(sf)); } // save and close it } else { try { File.WriteAllText(outputFileName, sub.ToText(sf), targetEncoding); } catch (Exception ex) { Console.WriteLine(ex.Message); errors++; return(false); } } if (format.GetType() == typeof(Sami) || format.GetType() == typeof(SamiModern)) { var sami = (Sami)format; foreach (string className in Sami.GetStylesFromHeader(sub.Header)) { var newSub = new Subtitle(); foreach (Paragraph p in sub.Paragraphs) { if (p.Extra != null && p.Extra.Trim().Equals(className.Trim(), StringComparison.OrdinalIgnoreCase)) { newSub.Paragraphs.Add(p); } } if (newSub.Paragraphs.Count > 0 && newSub.Paragraphs.Count < sub.Paragraphs.Count) { string s = fileName; if (s.LastIndexOf('.') > 0) { s = s.Insert(s.LastIndexOf('.'), "_" + className); } else { s += "_" + className + format.Extension; } outputFileName = FormatOutputFileNameForBatchConvert(s, sf.Extension, outputFolder, overwrite); File.WriteAllText(outputFileName, newSub.ToText(sf), targetEncoding); } } } Console.WriteLine(" done."); break; } } if (!targetFormatFound) { var ebu = new Ebu(); if (ebu.Name.Replace(" ", string.Empty).Equals(toFormat.Replace(" ", string.Empty), StringComparison.OrdinalIgnoreCase)) { targetFormatFound = true; outputFileName = FormatOutputFileNameForBatchConvert(fileName, ebu.Extension, outputFolder, overwrite); Console.Write("{0}: {1} -> {2}...", count, Path.GetFileName(fileName), outputFileName); Ebu.Save(outputFileName, sub, true); Console.WriteLine(" done."); } } if (!targetFormatFound) { var pac = new Pac(); if (pac.Name.Replace(" ", string.Empty).Equals(toFormat, StringComparison.OrdinalIgnoreCase) || toFormat.Equals("pac", StringComparison.OrdinalIgnoreCase) || toFormat.Equals(".pac", StringComparison.OrdinalIgnoreCase)) { pac.BatchMode = true; int codePage; if (!string.IsNullOrEmpty(pacCodePage) && int.TryParse(pacCodePage, out codePage)) { pac.CodePage = codePage; } targetFormatFound = true; outputFileName = FormatOutputFileNameForBatchConvert(fileName, pac.Extension, outputFolder, overwrite); Console.Write("{0}: {1} -> {2}...", count, Path.GetFileName(fileName), outputFileName); pac.Save(outputFileName, sub); Console.WriteLine(" done."); } } if (!targetFormatFound) { var cavena890 = new Cavena890(); if (cavena890.Name.Replace(" ", string.Empty).Equals(toFormat, StringComparison.OrdinalIgnoreCase)) { targetFormatFound = true; outputFileName = FormatOutputFileNameForBatchConvert(fileName, cavena890.Extension, outputFolder, overwrite); Console.Write("{0}: {1} -> {2}...", count, Path.GetFileName(fileName), outputFileName); cavena890.Save(outputFileName, sub); Console.WriteLine(" done."); } } if (!targetFormatFound) { var cheetahCaption = new CheetahCaption(); if (cheetahCaption.Name.Replace(" ", string.Empty).Equals(toFormat, StringComparison.OrdinalIgnoreCase)) { targetFormatFound = true; outputFileName = FormatOutputFileNameForBatchConvert(fileName, cheetahCaption.Extension, outputFolder, overwrite); Console.Write("{0}: {1} -> {2}...", count, Path.GetFileName(fileName), outputFileName); CheetahCaption.Save(outputFileName, sub); Console.WriteLine(" done."); } } if (!targetFormatFound) { var ayato = new Ayato(); if (ayato.Name.Replace(" ", string.Empty).Equals(toFormat, StringComparison.OrdinalIgnoreCase)) { targetFormatFound = true; outputFileName = FormatOutputFileNameForBatchConvert(fileName, ayato.Extension, outputFolder, overwrite); Console.Write("{0}: {1} -> {2}...", count, Path.GetFileName(fileName), outputFileName); ayato.Save(outputFileName, null, sub); Console.WriteLine(" done."); } } if (!targetFormatFound) { var capMakerPlus = new CapMakerPlus(); if (capMakerPlus.Name.Replace(" ", string.Empty).Equals(toFormat, StringComparison.OrdinalIgnoreCase)) { targetFormatFound = true; outputFileName = FormatOutputFileNameForBatchConvert(fileName, capMakerPlus.Extension, outputFolder, overwrite); Console.Write("{0}: {1} -> {2}...", count, Path.GetFileName(fileName), outputFileName); CapMakerPlus.Save(outputFileName, sub); Console.WriteLine(" done."); } } if (!targetFormatFound) { if (Configuration.Settings.Language.BatchConvert.PlainText == toFormat || Configuration.Settings.Language.BatchConvert.PlainText.Replace(" ", string.Empty).Equals(toFormat.Replace(" ", string.Empty), StringComparison.OrdinalIgnoreCase)) { targetFormatFound = true; outputFileName = FormatOutputFileNameForBatchConvert(fileName, ".txt", outputFolder, overwrite); Console.Write("{0}: {1} -> {2}...", count, Path.GetFileName(fileName), outputFileName); File.WriteAllText(outputFileName, ExportText.GeneratePlainText(sub, false, false, false, false, false, false, string.Empty, true, false, true, true, false), targetEncoding); Console.WriteLine(" done."); } } if (!targetFormatFound) { if (string.Compare(BatchConvert.BluRaySubtitle, toFormat, StringComparison.OrdinalIgnoreCase) == 0 || string.Compare(BatchConvert.BluRaySubtitle.Replace(" ", string.Empty), toFormat, StringComparison.OrdinalIgnoreCase) == 0) { targetFormatFound = true; outputFileName = FormatOutputFileNameForBatchConvert(fileName, ".sup", outputFolder, overwrite); Console.Write("{0}: {1} -> {2}...", count, Path.GetFileName(fileName), outputFileName); using (var form = new ExportPngXml()) { form.Initialize(sub, format, "BLURAYSUP", fileName, null, null); var binarySubtitleFile = new FileStream(outputFileName, FileMode.Create); int width = 1920; int height = 1080; var parts = Configuration.Settings.Tools.ExportBluRayVideoResolution.Split('x'); if (parts.Length == 2 && Utilities.IsInteger(parts[0]) && Utilities.IsInteger(parts[1])) { width = int.Parse(parts[0]); height = int.Parse(parts[1]); } for (int index = 0; index < sub.Paragraphs.Count; index++) { var mp = form.MakeMakeBitmapParameter(index, width, height); mp.LineJoin = Configuration.Settings.Tools.ExportPenLineJoin; mp.Bitmap = ExportPngXml.GenerateImageFromTextWithStyle(mp); ExportPngXml.MakeBluRaySupImage(mp); binarySubtitleFile.Write(mp.Buffer, 0, mp.Buffer.Length); } binarySubtitleFile.Close(); } Console.WriteLine(" done."); } else if (string.Compare(BatchConvert.VobSubSubtitle, toFormat, StringComparison.OrdinalIgnoreCase) == 0 || string.Compare(BatchConvert.VobSubSubtitle.Replace(" ", string.Empty), toFormat, StringComparison.OrdinalIgnoreCase) == 0) { targetFormatFound = true; outputFileName = FormatOutputFileNameForBatchConvert(fileName, ".sub", outputFolder, overwrite); Console.Write("{0}: {1} -> {2}...", count, Path.GetFileName(fileName), outputFileName); using (var form = new ExportPngXml()) { form.Initialize(sub, format, "VOBSUB", fileName, null, null); int width = 720; int height = 576; var parts = Configuration.Settings.Tools.ExportVobSubVideoResolution.Split('x'); if (parts.Length == 2 && Utilities.IsInteger(parts[0]) && Utilities.IsInteger(parts[1])) { width = int.Parse(parts[0]); height = int.Parse(parts[1]); } var cfg = Configuration.Settings.Tools; var languageIndex = IfoParser.ArrayOfLanguageCode.IndexOf(LanguageAutoDetect.AutoDetectGoogleLanguageOrNull(sub)); if (languageIndex < 0) { languageIndex = IfoParser.ArrayOfLanguageCode.IndexOf("en"); } using (var vobSubWriter = new VobSubWriter(outputFileName, width, height, cfg.ExportBottomMargin, cfg.ExportBottomMargin, 32, cfg.ExportFontColor, cfg.ExportBorderColor, !cfg.ExportVobAntiAliasingWithTransparency, IfoParser.ArrayOfLanguage[languageIndex], IfoParser.ArrayOfLanguageCode[languageIndex])) { for (int index = 0; index < sub.Paragraphs.Count; index++) { var mp = form.MakeMakeBitmapParameter(index, width, height); mp.LineJoin = Configuration.Settings.Tools.ExportPenLineJoin; mp.Bitmap = ExportPngXml.GenerateImageFromTextWithStyle(mp); vobSubWriter.WriteParagraph(mp.P, mp.Bitmap, mp.Alignment); } vobSubWriter.WriteIdxFile(); } } Console.WriteLine(" done."); } } if (!targetFormatFound) { Console.WriteLine("{0}: {1} - target format '{2}' not found!", count, fileName, toFormat); errors++; return(false); } converted++; return(true); } finally { Configuration.Settings.General.CurrentFrameRate = oldFrameRate; } }
internal void Initialize(Subtitle subtitle, Subtitle target, string title, bool googleTranslate, Encoding encoding) { if (title != null) { Text = title; } _googleTranslate = googleTranslate; if (!_googleTranslate) { _translator = new MicrosoftTranslator(Configuration.Settings.Tools.MicrosoftTranslatorApiKey); linkLabelPoweredByGoogleTranslate.Text = Configuration.Settings.Language.GoogleTranslate.PoweredByMicrosoftTranslate; } labelPleaseWait.Visible = false; progressBar1.Visible = false; _subtitle = subtitle; if (target != null) { TranslatedSubtitle = new Subtitle(target); subtitleListViewTo.Fill(TranslatedSubtitle); } else { TranslatedSubtitle = new Subtitle(subtitle); foreach (var paragraph in TranslatedSubtitle.Paragraphs) { paragraph.Text = string.Empty; } } string defaultFromLanguage = LanguageAutoDetect.AutoDetectGoogleLanguage(encoding); // Guess language via encoding if (string.IsNullOrEmpty(defaultFromLanguage)) { defaultFromLanguage = LanguageAutoDetect.AutoDetectGoogleLanguage(subtitle); // Guess language based on subtitle contents } if (defaultFromLanguage == "he") { defaultFromLanguage = "iw"; } FillComboWithLanguages(comboBoxFrom); int i = 0; foreach (ComboBoxItem item in comboBoxFrom.Items) { if (item.Value == defaultFromLanguage) { comboBoxFrom.SelectedIndex = i; break; } i++; } var installedLanguages = new List<InputLanguage>(); foreach (InputLanguage language in InputLanguage.InstalledInputLanguages) { installedLanguages.Add(language); } FillComboWithLanguages(comboBoxTo); i = 0; string uiCultureTargetLanguage = Configuration.Settings.Tools.GoogleTranslateLastTargetLanguage; if (uiCultureTargetLanguage == defaultFromLanguage) { foreach (string s in Utilities.GetDictionaryLanguages()) { string temp = s.Replace("[", string.Empty).Replace("]", string.Empty); if (temp.Length > 4) { temp = temp.Substring(temp.Length - 5, 2).ToLowerInvariant(); if (temp != defaultFromLanguage && installedLanguages.Any(p => p.Culture.TwoLetterISOLanguageName.Contains(temp))) { uiCultureTargetLanguage = temp; break; } } } } if (uiCultureTargetLanguage == defaultFromLanguage) { foreach (InputLanguage language in installedLanguages) { if (language.Culture.TwoLetterISOLanguageName != defaultFromLanguage) { uiCultureTargetLanguage = language.Culture.TwoLetterISOLanguageName; break; } } } if (uiCultureTargetLanguage == defaultFromLanguage && defaultFromLanguage == "en") { uiCultureTargetLanguage = "es"; } if (uiCultureTargetLanguage == defaultFromLanguage) { uiCultureTargetLanguage = "en"; } comboBoxTo.SelectedIndex = 0; foreach (ComboBoxItem item in comboBoxTo.Items) { if (item.Value == uiCultureTargetLanguage) { comboBoxTo.SelectedIndex = i; break; } i++; } subtitleListViewFrom.Fill(subtitle); GoogleTranslate_Resize(null, null); _formattingTypes = new FormattingType[_subtitle.Paragraphs.Count]; _autoSplit = new bool[_subtitle.Paragraphs.Count]; }
private void FindAllNames() { string language = LanguageAutoDetect.AutoDetectLanguageName("en_US", _subtitle); if (string.IsNullOrEmpty(language)) { language = "en_US"; } var namesList = new NamesList(Configuration.DictionariesFolder, language, Configuration.Settings.WordLists.UseOnlineNamesEtc, Configuration.Settings.WordLists.NamesEtcUrl); // Will contains both one word names and multi names var namesEtcList = namesList.GetAllNames(); if (language.StartsWith("en", StringComparison.Ordinal)) { namesEtcList.Remove("Black"); namesEtcList.Remove("Bill"); namesEtcList.Remove("Long"); namesEtcList.Remove("Don"); } var sb = new StringBuilder(); foreach (Paragraph p in _subtitle.Paragraphs) { sb.AppendLine(p.Text); } string text = HtmlUtil.RemoveHtmlTags(sb.ToString()); string textToLower = text.ToLower(); listViewNames.BeginUpdate(); foreach (string name in namesEtcList) { int startIndex = textToLower.IndexOf(name.ToLower(), StringComparison.Ordinal); if (startIndex >= 0) { while (startIndex >= 0 && startIndex < text.Length && textToLower.Substring(startIndex).Contains(name.ToLower()) && name.Length > 1 && name != name.ToLower()) { bool startOk = (startIndex == 0) || (text[startIndex - 1] == ' ') || (text[startIndex - 1] == '-') || (text[startIndex - 1] == '"') || (text[startIndex - 1] == '\'') || (text[startIndex - 1] == '>') || (Environment.NewLine.EndsWith(text[startIndex - 1].ToString(CultureInfo.InvariantCulture))); if (startOk) { int end = startIndex + name.Length; bool endOk = end <= text.Length; if (endOk) { endOk = end == text.Length || ExpectedEndChars.Contains(text[end]); } if (endOk && text.Substring(startIndex, name.Length) != name) // do not add names where casing already is correct { if (!_usedNames.Contains(name)) { _usedNames.Add(name); AddToListViewNames(name); break; // break while } } } startIndex = textToLower.IndexOf(name.ToLower(), startIndex + 2, StringComparison.Ordinal); } } } listViewNames.EndUpdate(); groupBoxNames.Text = string.Format(Configuration.Settings.Language.ChangeCasingNames.NamesFoundInSubtitleX, listViewNames.Items.Count); }
public Idx(string fileName) : this(FileUtil.ReadAllLinesShared(fileName, LanguageAutoDetect.GetEncodingFromFile(fileName)).ToList()) { }
private static Encoding DetectAnsiEncoding(string fileName) { fileName = Path.Combine(Directory.GetCurrentDirectory(), fileName); return(LanguageAutoDetect.DetectAnsiEncoding(FileUtil.ReadAllBytesShared(fileName))); }
private void SortAndLoad() { JoinedFormat = new SubRip(); // default subtitle format string header = null; SubtitleFormat lastFormat = null; var subtitles = new List <Subtitle>(); for (var 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) { sub.Header = sub.Header.Replace("*Default", "Default"); foreach (var subParagraph in sub.Paragraphs) { if (subParagraph.Extra == "*Default") { subParagraph.Extra = "Default"; } } } 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)) { if (IsStyleDifferent(newStyle, sub, header)) { 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); }
private bool LoadSingleFile(string fileName, Form parentForm) { groupBoxSplitting.Enabled = true; textBoxText.Enabled = true; Format = null; string ext = string.Empty; var extension = Path.GetExtension(fileName); if (extension != null) { ext = extension.ToLowerInvariant(); } var fd = new FinalDraftTemplate2(); var list = new List <string>(FileUtil.ReadAllLinesShared(fileName, LanguageAutoDetect.GetEncodingFromFile(fileName))); bool isFinalDraft = fd.IsMine(list, fileName); if (ext == ".astx") { LoadAdobeStory(fileName); } else if (isFinalDraft) { return(LoadFinalDraftTemplate(fileName, parentForm ?? this)); } else if (ext == ".tx3g" && new Tx3GTextOnly().IsMine(null, fileName)) { LoadTx3G(fileName); } else if (ext == ".rtf" && FileUtil.IsRtf(fileName)) { LoadRtf(fileName); } else { LoadTextFile(fileName); } return(true); }
private void VerifyDragDrop(ListView listView, DragEventArgs e) { var files = e.Data.GetData(DataFormats.FileDrop) as string[]; if (files == null) { return; } if (files.Length > 1) { MessageBox.Show(Configuration.Settings.Language.Main.DropOnlyOneFile, string.Empty, MessageBoxButtons.OK, MessageBoxIcon.Error); return; } string filePath = files[0]; if (FileUtil.IsDirectory(filePath)) { MessageBox.Show(Configuration.Settings.Language.Main.ErrorDirectoryDropNotAllowed, string.Empty, MessageBoxButtons.OK, MessageBoxIcon.Error); return; } var listExt = new List <string>(); foreach (var s in UiUtil.SubtitleExtensionFilter.Value.Split(new[] { '*' }, StringSplitOptions.RemoveEmptyEntries)) { if (s.EndsWith(';')) { listExt.Add(s.Trim(';')); } } if (!listExt.Contains(Path.GetExtension(filePath))) { return; } if (FileUtil.IsVobSub(filePath) || FileUtil.IsBluRaySup(filePath)) { MessageBox.Show(Configuration.Settings.Language.CompareSubtitles.CannotCompareWithImageBasedSubtitles); return; } Encoding encoding; if (listView.Name == "subtitleListView1") { _subtitle1 = new Subtitle(); _subtitle1.LoadSubtitle(filePath, out encoding, null); subtitleListView1.Fill(_subtitle1); subtitleListView1.SelectIndexAndEnsureVisible(0); subtitleListView2.SelectIndexAndEnsureVisible(0); labelSubtitle1.Text = filePath; _language1 = LanguageAutoDetect.AutoDetectGoogleLanguage(_subtitle1); if (_subtitle1.Paragraphs.Count > 0) { CompareSubtitles(); } } else { _subtitle2 = new Subtitle(); _subtitle2.LoadSubtitle(filePath, out encoding, null); subtitleListView2.Fill(_subtitle2); subtitleListView1.SelectIndexAndEnsureVisible(0); subtitleListView2.SelectIndexAndEnsureVisible(0); labelSubtitle2.Text = filePath; if (_subtitle2.Paragraphs.Count > 0) { CompareSubtitles(); } } }
public override string ToText(Subtitle subtitle, string title) { var language = LanguageAutoDetect.AutoDetectGoogleLanguage(subtitle); var ci = CultureInfo.GetCultureInfo(language); language = CultureInfo.CreateSpecificCulture(ci.Name).Name; string languageTag = $"{language.Replace("-", string.Empty).ToUpperInvariant()}CC"; string languageName = ci.EnglishName; string languageStyle = $".{languageTag} [ name: {languageName}; lang: {language.Replace("_", "-")} ; SAMIType: CC ; ]"; languageStyle = languageStyle.Replace("[", "{").Replace("]", "}"); string header = @"<SAMI> <HEAD> <TITLE>_TITLE_</TITLE> <SAMIParam> Metrics {time:ms;} Spec {MSFT:1.0;} </SAMIParam> <STYLE TYPE=""text/css""> <!-- P { font-family: Arial; font-weight: normal; color: white; background-color: black; text-align: center; } _LANGUAGE-STYLE_ --> </STYLE> </HEAD> <BODY> <-- Open play menu, choose Captions and Subtiles, On if available --> <-- Open tools menu, Security, Show local captions when present -->"; bool useExtra = false; if (!string.IsNullOrEmpty(subtitle.Header) && subtitle.Header.StartsWith("<style", StringComparison.OrdinalIgnoreCase)) { useExtra = true; header = @"<SAMI> <HEAD> <TITLE>_TITLE_</TITLE> <SAMIParam> Metrics {time:ms;} Spec {MSFT:1.0;} </SAMIParam> " + subtitle.Header.Trim() + @" </HEAD> <BODY> <-- Open play menu, choose Captions and Subtiles, On if available --> <-- Open tools menu, Security, Show local captions when present -->"; } // Example text (start numbers are milliseconds) //<SYNC Start=65264><P>Let's go! //<SYNC Start=66697><P><BR> string paragraphWriteFormat = @"<SYNC Start={0}><P Class={3}>{2}" + Environment.NewLine + @"<SYNC Start={1}><P Class={3}> "; string paragraphWriteFormatOpen = @"<SYNC Start={0}><P Class={2}>{1}"; if (Name == new SamiModern().Name) { paragraphWriteFormat = "<SYNC Start=\"{0}\"><P Class=\"{3}\">{2}</P></SYNC>" + Environment.NewLine + "<SYNC Start=\"{1}\"><P Class=\"{3}\"> </P></SYNC>"; paragraphWriteFormatOpen = "<SYNC Start=\"{0}\"><P Class=\"{2}\">{1}</P></SYNC>"; } else if (Name == new SamiYouTube().Name) { paragraphWriteFormat = "<SYNC Start=\"{0}\"><P Class=\"{3}\">{2}</P></SYNC>" + Environment.NewLine + "<SYNC Start=\"{1}\"><P Class=\"{3}\"></P></SYNC>"; paragraphWriteFormatOpen = "<SYNC Start=\"{0}\"><P Class=\"{2}\">{1}</P></SYNC>"; } int count = 1; var sb = new StringBuilder(); sb.AppendLine(header.Replace("_TITLE_", title).Replace("_LANGUAGE-STYLE_", languageStyle)); var totalLine = new StringBuilder(); var partialLine = new StringBuilder(); foreach (Paragraph p in subtitle.Paragraphs) { Paragraph next = subtitle.GetParagraphOrDefault(count); string text = p.Text; if (text.Contains('<') && text.Contains('>')) { bool tagOn = false; for (int i = 0; i < text.Length; i++) { string t = text.Substring(i); if (t.StartsWith('<') && (t.StartsWith("<font", StringComparison.Ordinal) || t.StartsWith("<div", StringComparison.Ordinal) || t.StartsWith("<i", StringComparison.Ordinal) || t.StartsWith("<b", StringComparison.Ordinal) || t.StartsWith("<s", StringComparison.Ordinal) || t.StartsWith("</", StringComparison.Ordinal))) { totalLine.Append(EncodeText(partialLine.ToString())); partialLine.Clear(); tagOn = true; totalLine.Append('<'); } else if (t.StartsWith('>') && tagOn) { tagOn = false; totalLine.Append('>'); } else if (!tagOn) { partialLine.Append(text[i]); } else { totalLine.Append(text[i]); } } totalLine.Append(EncodeText(partialLine.ToString())); text = totalLine.ToString(); totalLine.Clear(); partialLine.Clear(); } else { text = EncodeText(text); } if (Name == new SamiModern().Name) { text = text.Replace(Environment.NewLine, "<br />"); } else { text = text.Replace(Environment.NewLine, "<br>"); } string currentClass = languageTag; if (useExtra && !string.IsNullOrEmpty(p.Extra)) { currentClass = p.Extra; } var startMs = (long)(Math.Round(p.StartTime.TotalMilliseconds)); var endMs = (long)(Math.Round(p.EndTime.TotalMilliseconds)); if (next != null && Math.Abs(((long)Math.Round(next.StartTime.TotalMilliseconds)) - endMs) < 1) { sb.AppendLine(string.Format(paragraphWriteFormatOpen, startMs, text, currentClass)); } else { sb.AppendLine(string.Format(paragraphWriteFormat, startMs, endMs, text, currentClass)); } count++; } sb.AppendLine("</BODY>"); sb.AppendLine("</SAMI>"); return(sb.ToString().Trim()); }
private void buttonOK_Click(object sender, EventArgs e) { buttonOK.Enabled = false; using (var saveDialog = new SaveFileDialog { FileName = string.Empty, Filter = "MP4|*.mp4|Matroska|*.mkv|WebM|*.webm" }) { if (saveDialog.ShowDialog(this) != DialogResult.OK) { return; } VideoFileName = saveDialog.FileName; } if (File.Exists(VideoFileName)) { File.Delete(VideoFileName); } if (numericUpDownFontSize.Visible) { var fontSize = (int)numericUpDownFontSize.Value; var style = AdvancedSubStationAlpha.GetSsaStyle("Default", _assaSubtitle.Header); style.FontSize = fontSize; var styleLine = style.ToRawAss(); _assaSubtitle.Header = AdvancedSubStationAlpha.AddTagToHeader("Style", styleLine, "[V4+ Styles]", _assaSubtitle.Header); } if (Configuration.Settings.General.RightToLeftMode && LanguageAutoDetect.CouldBeRightToLeftLanguage(_assaSubtitle)) { for (var index = 0; index < _assaSubtitle.Paragraphs.Count; index++) { var paragraph = _assaSubtitle.Paragraphs[index]; if (LanguageAutoDetect.ContainsRightToLeftLetter(paragraph.Text)) { paragraph.Text = Utilities.FixRtlViaUnicodeChars(paragraph.Text); } } } SubtitleFormat format = new AdvancedSubStationAlpha(); var assaTempFileName = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString() + ".ass"); File.WriteAllText(assaTempFileName, format.ToText(_assaSubtitle, null)); progressBar1.Style = ProgressBarStyle.Marquee; progressBar1.Visible = true; labelPleaseWait.Visible = true; var process = VideoPreviewGenerator.GenerateHardcodedVideoFile( _inputVideoFileName, assaTempFileName, VideoFileName); process.Start(); while (!process.HasExited) { System.Threading.Thread.Sleep(100); Application.DoEvents(); if (_abort) { process.Kill(); } } progressBar1.Visible = false; labelPleaseWait.Visible = false; try { File.Delete(assaTempFileName); } catch { // ignore } DialogResult = _abort ? DialogResult.Cancel : DialogResult.OK; }
public GenerateVideoWithHardSubs(Subtitle assaSubtitle, string inputVideoFileName, VideoInfo videoInfo, int?fontSize) { UiUtil.PreInitialize(this); InitializeComponent(); UiUtil.FixFonts(this); _loading = true; _videoInfo = videoInfo; Text = LanguageSettings.Current.GenerateVideoWithBurnedInSubs.Title; _assaSubtitle = new Subtitle(assaSubtitle); _inputVideoFileName = inputVideoFileName; buttonOK.Text = LanguageSettings.Current.Watermark.Generate; labelPleaseWait.Text = LanguageSettings.Current.General.PleaseWait; labelResolution.Text = LanguageSettings.Current.SubStationAlphaProperties.Resolution; labelPreviewPleaseWait.Text = LanguageSettings.Current.General.PleaseWait; labelFontSize.Text = LanguageSettings.Current.ExportPngXml.FontSize; labelSubtitleFont.Text = LanguageSettings.Current.ExportPngXml.FontFamily; buttonCancel.Text = LanguageSettings.Current.General.Cancel; labelAudioEnc.Text = LanguageSettings.Current.GenerateVideoWithBurnedInSubs.Encoding; labelVideoEncoding.Text = LanguageSettings.Current.GenerateVideoWithBurnedInSubs.Encoding; labelAudioBitRate.Text = LanguageSettings.Current.GenerateVideoWithBurnedInSubs.BitRate; labelAudioSampleRate.Text = LanguageSettings.Current.GenerateVideoWithBurnedInSubs.SampleRate; checkBoxMakeStereo.Text = LanguageSettings.Current.GenerateVideoWithBurnedInSubs.Stereo; labelCRF.Text = LanguageSettings.Current.GenerateVideoWithBurnedInSubs.Crf; labelPreset.Text = LanguageSettings.Current.GenerateVideoWithBurnedInSubs.Preset; labelTune.Text = LanguageSettings.Current.GenerateVideoWithBurnedInSubs.TuneFor; buttonPreview.Text = LanguageSettings.Current.General.Preview; checkBoxRightToLeft.Text = LanguageSettings.Current.Settings.FixRTLViaUnicodeChars; checkBoxAlignRight.Text = LanguageSettings.Current.GenerateVideoWithBurnedInSubs.AlignRight; checkBoxBox.Text = LanguageSettings.Current.SubStationAlphaStyles.OpaqueBox; progressBar1.Visible = false; labelPleaseWait.Visible = false; labelPreviewPleaseWait.Visible = false; labelProgress.Text = string.Empty; labelFileName.Text = string.Empty; labelPass.Text = string.Empty; comboBoxVideoEncoding.SelectedIndex = 0; comboBoxCrf.SelectedIndex = 6; comboBoxAudioEnc.SelectedIndex = 0; comboBoxAudioSampleRate.SelectedIndex = 1; comboBoxTune.SelectedIndex = 0; comboBoxAudioBitRate.Text = "128k"; checkBoxTargetFileSize_CheckedChanged(null, null); checkBoxTargetFileSize.Text = LanguageSettings.Current.GenerateVideoWithBurnedInSubs.TargetFileSize; labelFileSize.Text = LanguageSettings.Current.GenerateVideoWithBurnedInSubs.FileSizeMb; numericUpDownTargetFileSize.Left = labelFileSize.Left + labelFileSize.Width + 5; linkLabelHelp.Text = LanguageSettings.Current.Main.Menu.Help.Title; groupBoxSettings.Text = LanguageSettings.Current.Settings.Title; groupBoxVideo.Text = LanguageSettings.Current.Main.Menu.Video.Title; groupBoxAudio.Text = LanguageSettings.Current.GenerateVideoWithBurnedInSubs.Audio; comboBoxVideoEncoding.Text = Configuration.Settings.Tools.GenVideoEncoding; comboBoxCrf.Text = Configuration.Settings.Tools.GenVideoCrf; comboBoxTune.Text = Configuration.Settings.Tools.GenVideoTune; comboBoxAudioEnc.Text = Configuration.Settings.Tools.GenVideoAudioEncoding; comboBoxAudioSampleRate.Text = Configuration.Settings.Tools.GenVideoAudioSampleRate; checkBoxMakeStereo.Checked = Configuration.Settings.Tools.GenVideoAudioForceStereo; checkBoxTargetFileSize.Checked = Configuration.Settings.Tools.GenVideoTargetFileSize; checkBoxBox.Checked = Configuration.Settings.Tools.GenVideoNonAssaBox; checkBoxAlignRight.Checked = Configuration.Settings.Tools.GenVideoNonAssaAlignRight; checkBoxRightToLeft.Checked = Configuration.Settings.Tools.GenVideoNonAssaAlignRight; numericUpDownWidth.Value = _videoInfo.Width; numericUpDownHeight.Value = _videoInfo.Height; var left = Math.Max(Math.Max(labelResolution.Left + labelResolution.Width, labelFontSize.Left + labelFontSize.Width), labelSubtitleFont.Left + labelSubtitleFont.Width) + 5; numericUpDownFontSize.Left = left; comboBoxSubtitleFont.Left = left; numericUpDownWidth.Left = left; labelX.Left = numericUpDownWidth.Left + numericUpDownWidth.Width + 3; numericUpDownHeight.Left = labelX.Left + labelX.Width + 3; buttonVideoChooseStandardRes.Left = numericUpDownHeight.Left + numericUpDownHeight.Width + 9; labelInfo.Text = LanguageSettings.Current.GenerateVideoWithBurnedInSubs.InfoAssaOff; checkBoxRightToLeft.Left = left; checkBoxAlignRight.Left = left; checkBoxBox.Left = left; var audioLeft = Math.Max(Math.Max(labelAudioEnc.Left + labelAudioEnc.Width, labelAudioSampleRate.Left + labelAudioSampleRate.Width), labelAudioBitRate.Left + labelAudioBitRate.Width) + 5; comboBoxAudioEnc.Left = audioLeft; checkBoxMakeStereo.Left = audioLeft; comboBoxAudioSampleRate.Left = audioLeft; comboBoxAudioBitRate.Left = audioLeft; linkLabelHelp.Left = Width - linkLabelHelp.Width - 30; _isAssa = !fontSize.HasValue; if (fontSize.HasValue) { if (fontSize.Value < numericUpDownFontSize.Minimum) { numericUpDownFontSize.Value = numericUpDownFontSize.Minimum; } else if (fontSize.Value > numericUpDownFontSize.Maximum) { numericUpDownFontSize.Value = numericUpDownFontSize.Maximum; } else { numericUpDownFontSize.Value = fontSize.Value; } checkBoxRightToLeft.Checked = Configuration.Settings.General.RightToLeftMode && LanguageAutoDetect.CouldBeRightToLeftLanguage(_assaSubtitle); } else { numericUpDownFontSize.Enabled = false; labelFontSize.Enabled = false; labelSubtitleFont.Enabled = false; comboBoxSubtitleFont.Enabled = false; checkBoxRightToLeft.Left = checkBoxTargetFileSize.Left; checkBoxAlignRight.Enabled = false; checkBoxBox.Enabled = false; labelInfo.Text = LanguageSettings.Current.GenerateVideoWithBurnedInSubs.InfoAssaOn; } var initialFont = Configuration.Settings.Tools.ExportBluRayFontName; if (string.IsNullOrEmpty(initialFont)) { initialFont = UiUtil.GetDefaultFont().Name; } foreach (var x in FontFamily.Families) { if (x.IsStyleAvailable(FontStyle.Regular) || x.IsStyleAvailable(FontStyle.Bold)) { comboBoxSubtitleFont.Items.Add(x.Name); if (x.Name.Equals(initialFont, StringComparison.OrdinalIgnoreCase)) { comboBoxSubtitleFont.SelectedIndex = comboBoxSubtitleFont.Items.Count - 1; } } } if (comboBoxSubtitleFont.SelectedIndex < 0 && comboBoxSubtitleFont.Items.Count > 0) { comboBoxSubtitleFont.SelectedIndex = 0; } checkBoxRightToLeft.Checked = Configuration.Settings.General.RightToLeftMode && LanguageAutoDetect.CouldBeRightToLeftLanguage(_assaSubtitle); textBoxLog.Visible = false; }
private void ButtonOpenSubtitle1Click(object sender, EventArgs e) { openFileDialog1.FileName = string.Empty; if (openFileDialog1.ShowDialog() == DialogResult.OK) { if (FileUtil.IsVobSub(openFileDialog1.FileName) || FileUtil.IsBluRaySup(openFileDialog1.FileName)) { MessageBox.Show(Configuration.Settings.Language.CompareSubtitles.CannotCompareWithImageBasedSubtitles); return; } _subtitle1 = new Subtitle(); Encoding encoding; var format = _subtitle1.LoadSubtitle(openFileDialog1.FileName, out encoding, null); if (format == null) { var pac = new Pac(); if (pac.IsMine(null, openFileDialog1.FileName)) { pac.BatchMode = true; pac.LoadSubtitle(_subtitle1, null, openFileDialog1.FileName); format = pac; } } if (format == null) { var cavena890 = new Cavena890(); if (cavena890.IsMine(null, openFileDialog1.FileName)) { cavena890.LoadSubtitle(_subtitle1, null, openFileDialog1.FileName); } } if (format == null) { var spt = new Spt(); if (spt.IsMine(null, openFileDialog1.FileName)) { spt.LoadSubtitle(_subtitle1, null, openFileDialog1.FileName); } } if (format == null) { var cheetahCaption = new CheetahCaption(); if (cheetahCaption.IsMine(null, openFileDialog1.FileName)) { cheetahCaption.LoadSubtitle(_subtitle1, null, openFileDialog1.FileName); } } if (format == null) { var chk = new Chk(); if (chk.IsMine(null, openFileDialog1.FileName)) { chk.LoadSubtitle(_subtitle1, null, openFileDialog1.FileName); } } if (format == null) { var asc = new TimeLineAscii(); if (asc.IsMine(null, openFileDialog1.FileName)) { asc.LoadSubtitle(_subtitle1, null, openFileDialog1.FileName); } } if (format == null) { var asc = new TimeLineFootageAscii(); if (asc.IsMine(null, openFileDialog1.FileName)) { asc.LoadSubtitle(_subtitle1, null, openFileDialog1.FileName); } } subtitleListView1.Fill(_subtitle1); subtitleListView1.SelectIndexAndEnsureVisible(0); subtitleListView2.SelectIndexAndEnsureVisible(0); labelSubtitle1.Text = openFileDialog1.FileName; _language1 = LanguageAutoDetect.AutoDetectGoogleLanguage(_subtitle1); if (_subtitle1.Paragraphs.Count > 0 && _subtitle2?.Paragraphs.Count > 0) { CompareSubtitles(); } } }
public static Subtitle SplitLongLinesInSubtitle(Subtitle subtitle, int totalLineMaxCharacters, int singleLineMaxCharacters) { var splittedSubtitle = new Subtitle(subtitle); var language = LanguageAutoDetect.AutoDetectGoogleLanguage(subtitle); // calculate gaps var halfMinGaps = Configuration.Settings.General.MinimumMillisecondsBetweenLines / 2.0; var halfMinGapsMood = halfMinGaps + Configuration.Settings.General.MinimumMillisecondsBetweenLines % 2; const int FirstLine = 0; const int SecondLine = 1; for (int i = splittedSubtitle.Paragraphs.Count - 1; i >= 0; i--) { var oldParagraph = splittedSubtitle.Paragraphs[i]; // don't split into two paragraph if it can be balanced var text = oldParagraph.Text; var noHtmlLines = HtmlUtil.RemoveHtmlTags(text, true).SplitToLines(); bool autoBreak = true; if (noHtmlLines.Count == 2 && noHtmlLines[0].Length <= totalLineMaxCharacters && noHtmlLines[1].Length < totalLineMaxCharacters && (noHtmlLines[0].EndsWith('.') || noHtmlLines[0].EndsWith('!') || noHtmlLines[0].EndsWith('?') || noHtmlLines[0].EndsWith('؟'))) { autoBreak = false; } if (autoBreak) { text = Utilities.AutoBreakLine(oldParagraph.Text, language, true); } if (noHtmlLines.Count == 1 && text.SplitToLines().Count <= 2 && noHtmlLines[0].Length > singleLineMaxCharacters && !QualifiesForSplit(text, singleLineMaxCharacters, totalLineMaxCharacters)) { oldParagraph.Text = text; continue; } if (!QualifiesForSplit(text, singleLineMaxCharacters, totalLineMaxCharacters)) { continue; } // continue if paragraph doesn't contain exactly two lines var lines = text.SplitToLines(); if (lines.Count > 2) { continue; // ignore 3+ lines } // calculate milliseconds per char var millisecondsPerChar = oldParagraph.Duration.TotalMilliseconds / (HtmlUtil.RemoveHtmlTags(text, true).Length - Environment.NewLine.Length); oldParagraph.Text = lines[FirstLine]; // use optimal time to adjust duration oldParagraph.EndTime.TotalMilliseconds = oldParagraph.StartTime.TotalMilliseconds + millisecondsPerChar * HtmlUtil.RemoveHtmlTags(oldParagraph.Text, true).Length - halfMinGaps; // build second paragraph var newParagraph = new Paragraph(oldParagraph) { Text = lines[SecondLine] }; newParagraph.StartTime.TotalMilliseconds = oldParagraph.EndTime.TotalMilliseconds + halfMinGapsMood; newParagraph.EndTime.TotalMilliseconds = newParagraph.StartTime.TotalMilliseconds + millisecondsPerChar * HtmlUtil.RemoveHtmlTags(newParagraph.Text, true).Length; // only remove dash (if dialog) if first line is fully closed and "Split removes dashes" is true if (Configuration.Settings.General.SplitRemovesDashes && IsTextClosed(oldParagraph.Text)) { RemoveInvalidDash(oldParagraph, newParagraph); } // handle invalid tags if (oldParagraph.Text.Contains('<')) { oldParagraph.Text = HtmlUtil.FixInvalidItalicTags(oldParagraph.Text); } if (newParagraph.Text.Contains('<')) { newParagraph.Text = HtmlUtil.FixInvalidItalicTags(newParagraph.Text); } oldParagraph.Text = Utilities.AutoBreakLine(oldParagraph.Text, language); newParagraph.Text = Utilities.AutoBreakLine(newParagraph.Text, language); // insert new paragraph after the current/old one splittedSubtitle.Paragraphs.Insert(i + 1, newParagraph); } splittedSubtitle.Renumber(); return(splittedSubtitle); }