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));
        }