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); }
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(); } }
public AssDocumentItem(AssDocumentSection section, string type, List <string> values) { Section = section; Type = type; Values = values; }