public FcpXmlStyle(FcpXmlStyle style) { FontName = style.FontName; FontSize = style.FontSize; FontFace = style.FontFace; FontColor = style.FontColor; Alignment = style.Alignment; Baseline = style.Baseline; Italic = style.Italic; Bold = style.Bold; }
public FinalCutProXml15() { DefaultStyle = new FcpXmlStyle { FontName = "Lucida Sans", FontSize = 36, FontFace = "Regular", FontColor = Color.WhiteSmoke, Alignment = "center", Baseline = 29, Width = 1980, Height = 1024 }; }
public override string ToText(Subtitle subtitle, string title) { string xmlStructure = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" + Environment.NewLine + "<fcpxml version=\"" + FcpXmlVersion + "\">" + Environment.NewLine + " <resources>" + Environment.NewLine + " <format height=\"[HEIGHT]\" width=\"[WIDTH]\" frameDuration=\"" + GetFrameDuration() + "\" id=\"r1\"/>" + Environment.NewLine + " <effect id=\"r2\" uid=\".../Titles.localized/Bumper:Opener.localized/Basic Title.localized/Basic Title.moti\" name=\"Basic Title\"/>" + Environment.NewLine + " </resources>" + Environment.NewLine + " <library location=\"\">" + Environment.NewLine + " <event name=\"Title\">" + Environment.NewLine + " <project name=\"SUBTITLES\">" + Environment.NewLine + " <sequence duration=\"[SEQUENCE_DURATION]s\" format=\"r1\" tcStart=\"0s\" tcFormat=\"" + GetNdfDf() + "\" audioLayout=\"stereo\" audioRate=\"48k\">" + Environment.NewLine + " <spine>" + Environment.NewLine + " </spine>" + Environment.NewLine + " </sequence>" + Environment.NewLine + " </project>" + Environment.NewLine + " </event>" + Environment.NewLine + " </library>" + Environment.NewLine + "</fcpxml>"; var xml = new XmlDocument(); var sequenceDuration = 10; if (subtitle.Paragraphs.Count > 0) { sequenceDuration = (int)Math.Round(subtitle.Paragraphs[subtitle.Paragraphs.Count - 1].EndTime.TotalSeconds); } xml.LoadXml(xmlStructure .Replace("[WIDTH]", DefaultStyle.Width.ToString(CultureInfo.InvariantCulture)) .Replace("[HEIGHT]", DefaultStyle.Height.ToString(CultureInfo.InvariantCulture)) .Replace("[SEQUENCE_DURATION]", sequenceDuration.ToString(CultureInfo.InvariantCulture))) ; XmlNode videoNode = xml.DocumentElement.SelectSingleNode("//project/sequence/spine"); int number = 1; var sbTrimmedTitle = new StringBuilder(); var sb = new StringBuilder(); foreach (Paragraph p in subtitle.Paragraphs) { sbTrimmedTitle.Clear(); sb.Clear(); XmlNode video = xml.CreateElement("video"); foreach (var ch in HtmlUtil.RemoveHtmlTags(p.Text, true)) { if (CharUtils.IsEnglishAlphabet(ch) || char.IsDigit(ch)) { sbTrimmedTitle.Append(ch); } } var styles = new List <FcpXmlStyle> { DefaultStyle }; var text = Utilities.RemoveSsaTags(p.Text).Trim(); var italicIndexesBefore = new Stack <int>(); var boldIndexesBefore = new Stack <int>(); var fontIndexesBefore = new Stack <int>(); var styleTextPairs = new Dictionary <int, string>(); for (int i = 0; i < text.Length; i++) { char ch = text[i]; if (ch != '<') { sb.Append(ch); continue; } string subIText = text.Substring(i); if (subIText.StartsWith("<i>", StringComparison.OrdinalIgnoreCase)) { AddTextAndStyle(styles, sb, styleTextPairs); italicIndexesBefore.Push(styles.Count - 1); var newStyle = new FcpXmlStyle(styles[styles.Count - 1]) { Italic = true }; styles.Add(newStyle); i += 2; } else if (subIText.StartsWith("<b>", StringComparison.OrdinalIgnoreCase)) { AddTextAndStyle(styles, sb, styleTextPairs); boldIndexesBefore.Push(styles.Count - 1); var newStyle = new FcpXmlStyle(styles[styles.Count - 1]) { Bold = true }; styles.Add(newStyle); i += 2; } else if (subIText.StartsWith("<font ", StringComparison.OrdinalIgnoreCase)) { AddTextAndStyle(styles, sb, styleTextPairs); fontIndexesBefore.Push(styles.Count - 1); var s = text.Substring(i); int end = s.IndexOf('>'); if (end > 0) { string f = s.Substring(0, end); var colorStart = f.IndexOf(" color=", StringComparison.OrdinalIgnoreCase); if (colorStart >= 0) { int colorEnd = colorStart + " color=".Length + 1; if (colorEnd < f.Length) { colorEnd = f.IndexOf('"', colorEnd); if (colorEnd > 0 || colorEnd == -1) { if (colorEnd == -1) { s = f.Substring(colorStart); } else { s = f.Substring(colorStart, colorEnd - colorStart); } s = s.Remove(0, " color=".Length); s = s.Trim('"'); s = s.Trim('\''); try { var fontColor = ColorTranslator.FromHtml(s); var newStyle = new FcpXmlStyle(styles[styles.Count - 1]); newStyle.FontColor = fontColor; styles.Add(newStyle); } catch { // just re-add last style styles.Add(new FcpXmlStyle(styles[styles.Count - 1])); } } } } i += end; } else { i += text.Length; } } else if (subIText.StartsWith("</i>", StringComparison.OrdinalIgnoreCase)) { AddTextAndStyle(styles, sb, styleTextPairs); var newStyle = new FcpXmlStyle(styles[styles.Count - 1]); if (italicIndexesBefore.Count > 0) { var beforeIdx = italicIndexesBefore.Pop(); newStyle.Italic = styles[beforeIdx].Italic; } styles.Add(newStyle); i += 3; } else if (subIText.StartsWith("</b>", StringComparison.OrdinalIgnoreCase)) { AddTextAndStyle(styles, sb, styleTextPairs); var newStyle = new FcpXmlStyle(styles[styles.Count - 1]); if (boldIndexesBefore.Count > 0) { var beforeIdx = boldIndexesBefore.Pop(); newStyle.Bold = styles[beforeIdx].Bold; } styles.Add(newStyle); i += 3; } else if (subIText.StartsWith("</font>", StringComparison.OrdinalIgnoreCase)) { AddTextAndStyle(styles, sb, styleTextPairs); var newStyle = new FcpXmlStyle(styles[styles.Count - 1]); if (fontIndexesBefore.Count > 0) { var beforeIdx = fontIndexesBefore.Pop(); newStyle.FontColor = styles[beforeIdx].FontColor; newStyle.FontSize = styles[beforeIdx].FontSize; } styles.Add(newStyle); i += 6; } } AddTextAndStyle(styles, sb, styleTextPairs); WriteCurrentTextSegment(styles, styleTextPairs, video, number++, sbTrimmedTitle.ToString(), xml); XmlNode generatorNode = video.SelectSingleNode("title"); generatorNode.Attributes["offset"].Value = GetFrameTime(p.StartTime); generatorNode.Attributes["duration"].Value = GetFrameTime(p.Duration); generatorNode.Attributes["start"].Value = GetFrameTime(p.StartTime); videoNode.AppendChild(generatorNode); } return(ToUtf8XmlString(xml)); }