public void DcinemaSmpteColorAndItalic() { var target = new DCinemaSmpte2010(); var subtitle = new Subtitle(); subtitle.Paragraphs.Add(new Paragraph("<font color=\"#ff0000\"><i>Red</i></font>", 1000, 5000)); string text = target.ToText(subtitle, "title"); Assert.IsTrue(text.Contains("<dcst:Font Italic=\"yes\" Color=\"FFFF0000\">Red</dcst:Font>")); }
public void DcinemaSmpteItalic() { var target = new DCinemaSmpte2010(); var subtitle = new Subtitle(); subtitle.Paragraphs.Add(new Paragraph("<i>Italic</i>", 1000, 5000)); string text = target.ToText(subtitle, "title"); Assert.IsTrue(text.Contains("<dcst:Font Italic=\"yes\">Italic</dcst:Font>")); }
public override string ToText(Subtitle subtitle, string title) { Errors = null; var ss = Configuration.Settings.SubtitleSettings; if (!string.IsNullOrEmpty(ss.CurrentDCinemaEditRate)) { string[] temp = ss.CurrentDCinemaEditRate.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); double d1, d2; if (temp.Length == 2 && double.TryParse(temp[0], out d1) && double.TryParse(temp[1], out d2)) { _frameRate = d1 / d2; } } string xmlStructure = "<dcst:SubtitleReel xmlns:dcst=\"http://www.smpte-ra.org/schemas/428-7/2007/DCST\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">" + Environment.NewLine + " <dcst:Id>urn:uuid:7be835a3-cfb4-43d0-bb4b-f0b4c95e962e</dcst:Id>" + Environment.NewLine + " <dcst:ContentTitleText></dcst:ContentTitleText> " + Environment.NewLine + " <dcst:AnnotationText>This is a subtitle file</dcst:AnnotationText>" + Environment.NewLine + " <dcst:IssueDate>2012-06-26T12:33:59.000-00:00</dcst:IssueDate>" + Environment.NewLine + " <dcst:ReelNumber>1</dcst:ReelNumber>" + Environment.NewLine + " <dcst:Language>en</dcst:Language>" + Environment.NewLine + " <dcst:EditRate>25 1</dcst:EditRate>" + Environment.NewLine + " <dcst:TimeCodeRate>25</dcst:TimeCodeRate>" + Environment.NewLine + " <dcst:StartTime>00:00:00:00</dcst:StartTime> " + Environment.NewLine + " <dcst:LoadFont ID=\"theFontId\">urn:uuid:3dec6dc0-39d0-498d-97d0-928d2eb78391</dcst:LoadFont>" + Environment.NewLine + " <dcst:SubtitleList>" + Environment.NewLine + " <dcst:Font ID=\"theFontId\" Size=\"39\" Weight=\"normal\" Color=\"FFFFFFFF\" Effect=\"border\" EffectColor=\"FF000000\">" + Environment.NewLine + " </dcst:Font>" + Environment.NewLine + " </dcst:SubtitleList>" + Environment.NewLine + "</dcst:SubtitleReel>"; var xml = new XmlDocument(); xml.LoadXml(xmlStructure); xml.PreserveWhitespace = true; var nsmgr = new XmlNamespaceManager(xml.NameTable); nsmgr.AddNamespace("dcst", xml.DocumentElement.NamespaceURI); if (string.IsNullOrEmpty(ss.CurrentDCinemaMovieTitle)) { ss.CurrentDCinemaMovieTitle = title; } if (ss.CurrentDCinemaFontSize == 0 || string.IsNullOrEmpty(ss.CurrentDCinemaFontEffect)) { Configuration.Settings.SubtitleSettings.InitializeDCinameSettings(true); } xml.DocumentElement.SelectSingleNode("dcst:ContentTitleText", nsmgr).InnerText = ss.CurrentDCinemaMovieTitle; if (string.IsNullOrEmpty(ss.CurrentDCinemaSubtitleId) || !ss.CurrentDCinemaSubtitleId.StartsWith("urn:uuid:")) { ss.CurrentDCinemaSubtitleId = "urn:uuid:" + Guid.NewGuid(); } xml.DocumentElement.SelectSingleNode("dcst:Id", nsmgr).InnerText = ss.CurrentDCinemaSubtitleId; xml.DocumentElement.SelectSingleNode("dcst:ReelNumber", nsmgr).InnerText = ss.CurrentDCinemaReelNumber; xml.DocumentElement.SelectSingleNode("dcst:IssueDate", nsmgr).InnerText = ss.CurrentDCinemaIssueDate; if (string.IsNullOrEmpty(ss.CurrentDCinemaLanguage)) { ss.CurrentDCinemaLanguage = "en"; } xml.DocumentElement.SelectSingleNode("dcst:Language", nsmgr).InnerText = ss.CurrentDCinemaLanguage; if (ss.CurrentDCinemaEditRate == null && ss.CurrentDCinemaTimeCodeRate == null) { if (Configuration.Settings.General.CurrentFrameRate == 24) { ss.CurrentDCinemaEditRate = "24 1"; ss.CurrentDCinemaTimeCodeRate = "24"; } else { ss.CurrentDCinemaEditRate = "25 1"; ss.CurrentDCinemaTimeCodeRate = "25"; } } xml.DocumentElement.SelectSingleNode("dcst:EditRate", nsmgr).InnerText = ss.CurrentDCinemaEditRate; xml.DocumentElement.SelectSingleNode("dcst:TimeCodeRate", nsmgr).InnerText = ss.CurrentDCinemaTimeCodeRate; if (string.IsNullOrEmpty(ss.CurrentDCinemaStartTime)) { ss.CurrentDCinemaStartTime = "00:00:00:00"; } xml.DocumentElement.SelectSingleNode("dcst:StartTime", nsmgr).InnerText = ss.CurrentDCinemaStartTime; xml.DocumentElement.SelectSingleNode("dcst:LoadFont", nsmgr).InnerText = ss.CurrentDCinemaFontUri; int fontSize = ss.CurrentDCinemaFontSize; string loadedFontId = "Font1"; if (!string.IsNullOrEmpty(ss.CurrentDCinemaFontId)) { loadedFontId = ss.CurrentDCinemaFontId; } xml.DocumentElement.SelectSingleNode("dcst:LoadFont", nsmgr).Attributes["ID"].Value = loadedFontId; xml.DocumentElement.SelectSingleNode("dcst:SubtitleList/dcst:Font", nsmgr).Attributes["Size"].Value = fontSize.ToString(); xml.DocumentElement.SelectSingleNode("dcst:SubtitleList/dcst:Font", nsmgr).Attributes["Color"].Value = "FF" + Utilities.ColorToHex(ss.CurrentDCinemaFontColor).TrimStart('#').ToUpperInvariant(); xml.DocumentElement.SelectSingleNode("dcst:SubtitleList/dcst:Font", nsmgr).Attributes["ID"].Value = loadedFontId; xml.DocumentElement.SelectSingleNode("dcst:SubtitleList/dcst:Font", nsmgr).Attributes["Effect"].Value = ss.CurrentDCinemaFontEffect; xml.DocumentElement.SelectSingleNode("dcst:SubtitleList/dcst:Font", nsmgr).Attributes["EffectColor"].Value = "FF" + Utilities.ColorToHex(ss.CurrentDCinemaFontEffectColor).TrimStart('#').ToUpperInvariant(); XmlNode mainListFont = xml.DocumentElement.SelectSingleNode("dcst:SubtitleList/dcst:Font", nsmgr); int no = 0; foreach (Paragraph p in subtitle.Paragraphs) { if (p.Text != null) { XmlNode subNode = xml.CreateElement("dcst:Subtitle", "dcst"); XmlAttribute id = xml.CreateAttribute("SpotNumber"); id.InnerText = (no + 1).ToString(); subNode.Attributes.Append(id); XmlAttribute fadeUpTime = xml.CreateAttribute("FadeUpTime"); fadeUpTime.InnerText = "00:00:00:00"; subNode.Attributes.Append(fadeUpTime); XmlAttribute fadeDownTime = xml.CreateAttribute("FadeDownTime"); fadeDownTime.InnerText = "00:00:00:00"; subNode.Attributes.Append(fadeDownTime); XmlAttribute start = xml.CreateAttribute("TimeIn"); start.InnerText = ConvertToTimeString(p.StartTime); subNode.Attributes.Append(start); XmlAttribute 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 = 1 + lines.Count * 7; 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; Stack <string> fontColors = new Stack <string>(); foreach (string line in lines) { XmlNode textNode = xml.CreateElement("dcst:Text", "dcst"); XmlAttribute vPosition = xml.CreateAttribute("Vposition"); vPosition.InnerText = vPos.ToString(); textNode.Attributes.Append(vPosition); XmlAttribute vAlign = xml.CreateAttribute("Valign"); if (alignVTop) { vAlign.InnerText = "top"; } else if (alignVCenter) { vAlign.InnerText = "center"; } else { vAlign.InnerText = "bottom"; } textNode.Attributes.Append(vAlign); textNode.Attributes.Append(vAlign); XmlAttribute hAlign = xml.CreateAttribute("Halign"); if (alignLeft) { hAlign.InnerText = "left"; } else if (alignRight) { hAlign.InnerText = "right"; } else { hAlign.InnerText = "center"; } textNode.Attributes.Append(hAlign); XmlAttribute direction = xml.CreateAttribute("Direction"); direction.InnerText = "ltr"; 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>")) { 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>")) { if (txt.Length > 0) { XmlNode fontNode = xml.CreateElement("dcst:Font", "dcst"); XmlAttribute italic = xml.CreateAttribute("Italic"); italic.InnerText = "yes"; fontNode.Attributes.Append(italic); if (line.Length > i + 5 && line.Substring(i + 4).StartsWith("</font>")) { XmlAttribute 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=") && 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('#').ToUpperInvariant().PadLeft(8, 'F'); } fontColors.Push(c); fontNo++; i = endOfFont; } else if (fontNo > 0 && line.Substring(i).StartsWith("</font>")) { if (txt.Length > 0) { XmlNode fontNode = xml.CreateElement("dcst:Font", "dcst"); XmlAttribute fontColor = xml.CreateAttribute("Color"); fontColor.InnerText = fontColors.Pop(); fontNode.Attributes.Append(fontColor); if (line.Length > i + 9 && line.Substring(i + 7).StartsWith("</i>")) { XmlAttribute italic = xml.CreateAttribute("Italic"); italic.InnerText = "yes"; fontNode.Attributes.Append(italic); isItalic = false; i += 4; } 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) { XmlNode fontNode = xml.CreateElement("dcst:Font", "dcst"); XmlAttribute fontColor = xml.CreateAttribute("Color"); fontColor.InnerText = fontColors.Peek(); fontNode.Attributes.Append(fontColor); if (isItalic) { XmlAttribute italic = xml.CreateAttribute("Italic"); italic.InnerText = "yes"; fontNode.Attributes.Append(italic); } fontNode.InnerText = HtmlUtil.RemoveHtmlTags(txt.ToString()); html.Append(fontNode.OuterXml); } else if (html.Length > 0 && html.ToString().StartsWith("<dcst:Font ")) { XmlDocument temp = new XmlDocument(); temp.LoadXml("<root>" + html.ToString().Replace("dcst:Font", "Font") + "</root>"); XmlNode fontNode = xml.CreateElement("dcst:Font"); fontNode.InnerXml = temp.DocumentElement.SelectSingleNode("Font").InnerXml; foreach (XmlAttribute a in temp.DocumentElement.SelectSingleNode("Font").Attributes) { XmlAttribute newA = xml.CreateAttribute(a.Name); newA.InnerText = a.InnerText; fontNode.Attributes.Append(newA); } XmlAttribute fontColor = xml.CreateAttribute("Color"); fontColor.InnerText = fontColors.Peek(); fontNode.Attributes.Append(fontColor); html.Clear(); html.Append(fontNode.OuterXml); } } else if (isItalic) { if (txt.Length > 0) { XmlNode fontNode = xml.CreateElement("dcst:Font", "dcst"); XmlAttribute italic = xml.CreateAttribute("Italic"); italic.InnerText = "yes"; fontNode.Attributes.Append(italic); fontNode.InnerText = HtmlUtil.RemoveHtmlTags(line); 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; } } if (subNode.InnerXml.Length == 0) { // Empty text is just one space XmlNode textNode = xml.CreateElement("dcst:Text", "dcst"); textNode.InnerXml = " "; subNode.AppendChild(textNode); XmlAttribute vPosition = xml.CreateAttribute("Vposition"); vPosition.InnerText = vPos.ToString(); textNode.Attributes.Append(vPosition); XmlAttribute vAlign = xml.CreateAttribute("Valign"); vAlign.InnerText = "bottom"; textNode.Attributes.Append(vAlign); } mainListFont.AppendChild(subNode); no++; } } string result = ToUtf8XmlString(xml).Replace("encoding=\"utf-8\"", "encoding=\"UTF-8\"").Replace(" xmlns:dcst=\"dcst\"", string.Empty); const string res = "Nikse.SubtitleEdit.Resources.SMPTE-428-7-2007-DCST.xsd.gz"; System.Reflection.Assembly asm = System.Reflection.Assembly.GetExecutingAssembly(); Stream strm = asm.GetManifestResourceStream(res); if (strm != null) { try { var xmld = new XmlDocument(); var rdr = new StreamReader(strm); var zip = new GZipStream(rdr.BaseStream, CompressionMode.Decompress); xmld.LoadXml(result); using (var xr = XmlReader.Create(zip)) { xmld.Schemas.Add(null, xr); xmld.Validate(ValidationCallBack); } } catch (Exception exception) { Errors = "Error validating xml via SMPTE - 428 - 7 - 2007 - DCST.xsd: " + exception.Message; } } return(DCinemaSmpte2010.FixDcsTextSameLine(result)); }
private string ConvertToTimeString(TimeCode time) { return($"{time.Hours:00}:{time.Minutes:00}:{time.Seconds:00}:{DCinemaSmpte2010.MsToFramesMaxFrameRate(time.Milliseconds, _frameRate):00}"); }
private string ConvertToTimeString(TimeCode time) { return(string.Format("{0:00}:{1:00}:{2:00}:{3:00}", time.Hours, time.Minutes, time.Seconds, DCinemaSmpte2010.MsToFramesMaxFrameRate(time.Milliseconds, _frameRate))); }