예제 #1
0
        private Dictionary <string, AssDocumentSection> ReadDocument(string filePath)
        {
            Dictionary <string, AssDocumentSection> sections = new Dictionary <string, AssDocumentSection>();
            AssDocumentSection currentSection = null;

            using (StreamReader reader = new StreamReader(filePath))
            {
                string line;
                while ((line = reader.ReadLine()) != null)
                {
                    if (string.IsNullOrWhiteSpace(line) || line.StartsWith(";"))
                    {
                        continue;
                    }

                    if (line.StartsWith("[") && line.EndsWith("]"))
                    {
                        currentSection = new AssDocumentSection();
                        sections.Add(line.Substring(1, line.Length - 2), currentSection);
                        continue;
                    }

                    Match match = Regex.Match(line, @"(\w+):\s*(.+)");
                    if (!match.Success)
                    {
                        throw new InvalidDataException($"Unrecognized line in .ass: {line}");
                    }

                    if (currentSection == null)
                    {
                        throw new InvalidDataException($"Line {line} is not inside a section");
                    }

                    string        type   = match.Groups[1].Value;
                    List <string> values = match.Groups[2].Value.Split(",", currentSection.Format?.Count);
                    if (type == "Format")
                    {
                        if (currentSection.Format != null)
                        {
                            throw new InvalidDataException("Section has multiple Format items");
                        }

                        currentSection.SetFormat(values.Select(v => v.Trim()).ToList());
                    }
                    else
                    {
                        currentSection.AddItem(type, values);
                    }
                }
            }

            return(sections);
        }
예제 #2
0
        public AssDocument(string filePath, List <AssStyleOptions> styleOptions = null)
        {
            RegisterTagHandlers();

            Dictionary <string, AssDocumentSection> fileSections = ReadDocument(filePath);

            AssDocumentSection infoSection = fileSections["Script Info"];

            VideoDimensions = new Size(infoSection.GetItemInt("PlayResX", 384), infoSection.GetItemInt("PlayResY", 288));

            _styles = fileSections["V4+ Styles"].MapItems("Style", i => new AssStyle(i))
                      .ToDictionary(s => s.Name);

            if (styleOptions != null)
            {
                _styleOptions = styleOptions.ToDictionary(o => o.Name);
            }

            DefaultFontSize = (_styles.GetOrDefault("Default") ?? _styles.First().Value).FontSize;

            foreach (AssDialogue dialogue in fileSections["Events"].MapItems("Dialogue", i => new AssDialogue(i)))
            {
                AssStyle style = GetStyle(dialogue.Style);
                if (style == null)
                {
                    throw new Exception($"Line \"{dialogue.Text}\" refers to style \"{dialogue.Style}\" which doesn't exist.");
                }

                AssStyleOptions options = GetStyleOptions(dialogue.Style);

                List <AssLine> lines = ParseLine(dialogue, style, options);
                Lines.AddRange(lines.SelectMany(ExpandLine));
            }

            EmulateKaraokeForSimultaneousLines();
            foreach (AssLine line in Lines)
            {
                MergeIdenticallyFormattedSections(line);
                line.NormalizeAlpha();
            }
        }
예제 #3
0
 public AssDocumentItem(AssDocumentSection section, string type, List <string> values)
 {
     Section = section;
     Type    = type;
     Values  = values;
 }