From 006f820aea6c4c6d5ee4462fbbef8eb70d82ce5e Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Thu, 11 Oct 2012 18:45:54 -0700 Subject: [PATCH] Move ass parsing logic from AssFile to ASSSubtitleFormat --- aegisub/src/ass_file.cpp | 139 +++------------------------- aegisub/src/ass_file.h | 5 - aegisub/src/mkv_wrap.cpp | 5 +- aegisub/src/subtitle_format_ass.cpp | 121 +++++++++++++++++++++++- aegisub/src/subtitle_format_ass.h | 4 + 5 files changed, 136 insertions(+), 138 deletions(-) diff --git a/aegisub/src/ass_file.cpp b/aegisub/src/ass_file.cpp index 64ccc5860..d7ef3d5df 100644 --- a/aegisub/src/ass_file.cpp +++ b/aegisub/src/ass_file.cpp @@ -230,121 +230,6 @@ bool AssFile::CanSave() const { return writer && writer->CanSave(this); } -void AssFile::AddLine(wxString data, int *version, AssAttachment **attach) { - // Is this line an attachment filename? - bool isFilename = data.StartsWith("fontname: ") || data.StartsWith("filename: "); - - // If there's an attachment in progress, deal with it first as an - // attachment data line can appear to be other things - if (*attach) { - // Check if it's valid data - bool validData = data.size() > 0 && data.size() <= 80; - for (size_t i = 0; i < data.size(); ++i) { - if (data[i] < 33 || data[i] >= 97) { - validData = false; - break; - } - } - - // Data is over, add attachment to the file - if (!validData || isFilename) { - (*attach)->Finish(); - Line.push_back(*attach); - *attach = NULL; - } - else { - // Insert data - (*attach)->AddData(data); - - // Done building - if (data.Length() < 80) { - (*attach)->Finish(); - Line.push_back(*attach); - *attach = NULL; - return; - } - } - } - - if (data.empty()) return; - - // Section header - if (data[0] == '[' && data.Last() == ']') { - // Ugly hacks to allow intermixed v4 and v4+ style sections - wxString low = data.Lower(); - if (low == "[v4 styles]") { - data = "[V4+ Styles]"; - *version = 0; - } - else if (low == "[v4+ styles]") { - data = "[V4+ Styles]"; - *version = 1; - } - - Line.push_back(new AssEntry(data, data)); - return; - } - - // If the first nonblank line isn't a header pretend it starts with [Script Info] - if (Line.empty()) - Line.push_back(new AssEntry("[Script Info]", "[Script Info]")); - - wxString group = Line.back()->group; - wxString lowGroup = group.Lower(); - - // Attachment - if (lowGroup == "[fonts]" || lowGroup == "[graphics]") { - if (isFilename) { - *attach = new AssAttachment(data.Mid(10), group); - } - } - // Dialogue - else if (lowGroup == "[events]") { - if (data.StartsWith("Dialogue:") || data.StartsWith("Comment:")) - Line.push_back(new AssDialogue(data)); - else if (data.StartsWith("Format:")) - Line.push_back(new AssEntry("Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text", group)); - } - // Style - else if (lowGroup == "[v4+ styles]") { - if (data.StartsWith("Style:")) - Line.push_back(new AssStyle(data, *version)); - else if (data.StartsWith("Format:")) - Line.push_back(new AssEntry("Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding", group)); - } - // Script info - else if (lowGroup == "[script info]") { - // Comment - if (data.StartsWith(";")) { - // Skip stupid comments added by other programs - // Of course, we'll add our own in place later... ;) - return; - } - - if (data.StartsWith("ScriptType:")) { - wxString versionString = data.Mid(11).Trim(true).Trim(false).Lower(); - int trueVersion; - if (versionString == "v4.00") - trueVersion = 0; - else if (versionString == "v4.00+") - trueVersion = 1; - else - throw "Unknown SSA file format version"; - if (trueVersion != *version) { - wxLogMessage("Warning: File has the wrong extension."); - *version = trueVersion; - } - } - - // Everything - Line.push_back(new AssEntry(data, group)); - } - // Unrecognized group - else { - Line.push_back(new AssEntry(data, group)); - } -} - void AssFile::Clear() { background_delete_clear(Line); @@ -359,24 +244,22 @@ void AssFile::LoadDefault(bool defline) { Clear(); // Write headers - AssAttachment *attach = 0; - int version = 1; - AddLine("[Script Info]", &version, &attach); - AddLine("Title: Default Aegisub file", &version, &attach); - AddLine("ScriptType: v4.00+", &version, &attach); - AddLine("WrapStyle: 0", &version, &attach); - AddLine("ScaledBorderAndShadow: yes", &version, &attach); - AddLine("Collisions: Normal", &version, &attach); + Line.push_back(new AssEntry("[Script Info]", "[Script Info]")); + Line.push_back(new AssEntry("Title: Default Aegisub file", "[Script Info]")); + Line.push_back(new AssEntry("ScriptType: v4.00+", "[Script Info]")); + Line.push_back(new AssEntry("WrapStyle: 0", "[Script Info]")); + Line.push_back(new AssEntry("ScaledBorderAndShadow: yes", "[Script Info]")); + Line.push_back(new AssEntry("Collisions: Normal", "[Script Info]")); if (!OPT_GET("Subtitle/Default Resolution/Auto")->GetBool()) { - AddLine(wxString::Format("PlayResX: %" PRId64, OPT_GET("Subtitle/Default Resolution/Width")->GetInt()), &version, &attach); - AddLine(wxString::Format("PlayResY: %" PRId64, OPT_GET("Subtitle/Default Resolution/Height")->GetInt()), &version, &attach); + Line.push_back(new AssEntry(wxString::Format("PlayResX: %" PRId64, OPT_GET("Subtitle/Default Resolution/Width")->GetInt()), "[Script Info]")); + Line.push_back(new AssEntry(wxString::Format("PlayResY: %" PRId64, OPT_GET("Subtitle/Default Resolution/Height")->GetInt()), "[Script Info]")); } - AddLine("YCbCr Matrix: None", &version, &attach); + Line.push_back(new AssEntry("YCbCr Matrix: None", "[Script Info]")); InsertStyle(new AssStyle); - AddLine("[Events]", &version, &attach); - AddLine("Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text", &version, &attach); + Line.push_back(new AssEntry("[Events]", "[Events]")); + Line.push_back(new AssEntry("Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text", "[Events]")); if (defline) Line.push_back(new AssDialogue); diff --git a/aegisub/src/ass_file.h b/aegisub/src/ass_file.h index 54e630ee1..83af367c5 100644 --- a/aegisub/src/ass_file.h +++ b/aegisub/src/ass_file.h @@ -163,11 +163,6 @@ public: void SetScriptInfo(wxString const& key, wxString const& value); // Add a ";" comment in the [Script Info] section void AddComment(wxString comment); - /// @brief Add a line to the file - /// @param data Full text of ASS line - /// @param[in,out] version ASS version the line was parsed as - /// @param[in,out] attach Accumulator for attachment parsing - void AddLine(wxString data, int *version, AssAttachment **attach); /// Type of changes made in a commit enum CommitType { diff --git a/aegisub/src/mkv_wrap.cpp b/aegisub/src/mkv_wrap.cpp index 8e4f1bd31..a82101d70 100644 --- a/aegisub/src/mkv_wrap.cpp +++ b/aegisub/src/mkv_wrap.cpp @@ -56,6 +56,7 @@ #include "compat.h" #include "dialog_progress.h" #include "MatroskaParser.h" +#include "subtitle_format_ass.h" class MkvStdIO : public InputStream { public: @@ -137,7 +138,7 @@ static void read_subtitles(agi::ProgressSink *ps, MatroskaFile *file, MkvStdIO * int version = ssa; AssAttachment *attach = 0; for (std::map::iterator it = subList.begin(); it != subList.end(); ++it) { - target->AddLine(it->second, &version, &attach); + ASSSubtitleFormat::AddLine(target, it->second, &version, &attach); } } @@ -208,7 +209,7 @@ void MatroskaWrapper::GetSubtitles(wxString const& filename, AssFile *target) { AssAttachment *attach = 0; wxStringTokenizer token(privString, "\r\n", wxTOKEN_STRTOK); while (token.HasMoreTokens()) - target->AddLine(token.GetNextToken(), &version, &attach); + ASSSubtitleFormat::AddLine(target, token.GetNextToken(), &version, &attach); } // Load default if it's SRT else { diff --git a/aegisub/src/subtitle_format_ass.cpp b/aegisub/src/subtitle_format_ass.cpp index 2f6c9bead..7b7a46ebf 100644 --- a/aegisub/src/subtitle_format_ass.cpp +++ b/aegisub/src/subtitle_format_ass.cpp @@ -38,8 +38,10 @@ #include "subtitle_format_ass.h" +#include "ass_attachment.h" #include "ass_dialogue.h" #include "ass_file.h" +#include "ass_style.h" #include "compat.h" #include "text_file_reader.h" #include "text_file_writer.h" @@ -66,8 +68,6 @@ wxArrayString ASSSubtitleFormat::GetWriteWildcards() const { } void ASSSubtitleFormat::ReadFile(AssFile *target, wxString const& filename, wxString const& encoding) const { - using namespace std; - target->Clear(); TextFileReader file(filename, encoding); @@ -77,7 +77,7 @@ void ASSSubtitleFormat::ReadFile(AssFile *target, wxString const& filename, wxSt while (file.HasMoreLines()) { wxString line = file.ReadLineFromFile(); try { - target->AddLine(line, &version, &attach); + AddLine(target, line, &version, &attach); } catch (const char *err) { target->Clear(); @@ -101,3 +101,118 @@ void ASSSubtitleFormat::WriteFile(const AssFile *src, wxString const& filename, file.WriteLineToFile(ssa ? (*cur)->GetSSAText() : (*cur)->GetEntryData(), true); } } + +void ASSSubtitleFormat::AddLine(AssFile *target, wxString data, int *version, AssAttachment **attach) { + // Is this line an attachment filename? + bool isFilename = data.StartsWith("fontname: ") || data.StartsWith("filename: "); + + // If there's an attachment in progress, deal with it first as an + // attachment data line can appear to be other things + if (*attach) { + // Check if it's valid data + bool validData = data.size() > 0 && data.size() <= 80; + for (size_t i = 0; i < data.size(); ++i) { + if (data[i] < 33 || data[i] >= 97) { + validData = false; + break; + } + } + + // Data is over, add attachment to the file + if (!validData || isFilename) { + (*attach)->Finish(); + target->Line.push_back(*attach); + *attach = NULL; + } + else { + // Insert data + (*attach)->AddData(data); + + // Done building + if (data.Length() < 80) { + (*attach)->Finish(); + target->Line.push_back(*attach); + *attach = NULL; + return; + } + } + } + + if (data.empty()) return; + + // Section header + if (data[0] == '[' && data.Last() == ']') { + // Ugly hacks to allow intermixed v4 and v4+ style sections + wxString low = data.Lower(); + if (low == "[v4 styles]") { + data = "[V4+ Styles]"; + *version = 0; + } + else if (low == "[v4+ styles]") { + data = "[V4+ Styles]"; + *version = 1; + } + + target->Line.push_back(new AssEntry(data, data)); + return; + } + + // If the first nonblank line isn't a header pretend it starts with [Script Info] + if (target->Line.empty()) + target->Line.push_back(new AssEntry("[Script Info]", "[Script Info]")); + + wxString group = target->Line.back()->group; + wxString lowGroup = group.Lower(); + + // Attachment + if (lowGroup == "[fonts]" || lowGroup == "[graphics]") { + if (isFilename) { + *attach = new AssAttachment(data.Mid(10), group); + } + } + // Dialogue + else if (lowGroup == "[events]") { + if (data.StartsWith("Dialogue:") || data.StartsWith("Comment:")) + target->Line.push_back(new AssDialogue(data)); + else if (data.StartsWith("Format:")) + target->Line.push_back(new AssEntry("Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text", group)); + } + // Style + else if (lowGroup == "[v4+ styles]") { + if (data.StartsWith("Style:")) + target->Line.push_back(new AssStyle(data, *version)); + else if (data.StartsWith("Format:")) + target->Line.push_back(new AssEntry("Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding", group)); + } + // Script info + else if (lowGroup == "[script info]") { + // Comment + if (data.StartsWith(";")) { + // Skip stupid comments added by other programs + // Of course, we'll add our own in place later... ;) + return; + } + + if (data.StartsWith("ScriptType:")) { + wxString versionString = data.Mid(11).Trim(true).Trim(false).Lower(); + int trueVersion; + if (versionString == "v4.00") + trueVersion = 0; + else if (versionString == "v4.00+") + trueVersion = 1; + else + throw "Unknown SSA file format version"; + if (trueVersion != *version) { + wxLogMessage("Warning: File has the wrong extension."); + *version = trueVersion; + } + } + + // Everything + target->Line.push_back(new AssEntry(data, group)); + } + // Unrecognized group + else { + target->Line.push_back(new AssEntry(data, group)); + } +} diff --git a/aegisub/src/subtitle_format_ass.h b/aegisub/src/subtitle_format_ass.h index ca62c30fc..19959c728 100644 --- a/aegisub/src/subtitle_format_ass.h +++ b/aegisub/src/subtitle_format_ass.h @@ -36,6 +36,8 @@ #include "subtitle_format.h" +class AssAttachment; + /// DOCME /// @class ASSSubtitleFormat /// @brief DOCME @@ -53,4 +55,6 @@ public: void ReadFile(AssFile *target, wxString const& filename, wxString const& forceEncoding) const; void WriteFile(const AssFile *src, wxString const& filename, wxString const& encoding) const; + + static void AddLine(AssFile *target, wxString data, int *version, AssAttachment **attach); };