From 56e6f7d5b2d752684c732dc725551c54485865b7 Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Fri, 25 Nov 2011 19:28:19 +0000 Subject: [PATCH] Move ASS -> SRT tag conversion to the SRT subtitle format from AssDialogue Originally committed to SVN as r5911. --- aegisub/src/ass_dialogue.cpp | 97 ------------------------ aegisub/src/ass_dialogue.h | 2 - aegisub/src/subtitle_format.cpp | 19 +++-- aegisub/src/subtitle_format.h | 9 ++- aegisub/src/subtitle_format_encore.cpp | 3 +- aegisub/src/subtitle_format_microdvd.cpp | 3 +- aegisub/src/subtitle_format_srt.cpp | 59 +++++++++++--- aegisub/src/subtitle_format_srt.h | 1 + aegisub/src/subtitle_format_ttxt.cpp | 3 +- 9 files changed, 73 insertions(+), 123 deletions(-) diff --git a/aegisub/src/ass_dialogue.cpp b/aegisub/src/ass_dialogue.cpp index a7742f056..a52b55f9f 100644 --- a/aegisub/src/ass_dialogue.cpp +++ b/aegisub/src/ass_dialogue.cpp @@ -360,103 +360,6 @@ void AssDialogue::StripTag (wxString tagName) { Text = final; } -void AssDialogue::ConvertTagsToSRT () { - using std::list; - using std::vector; - AssDialogueBlockOverride* curBlock; - AssDialogueBlockPlain *curPlain; - AssOverrideTag* curTag; - wxString final = ""; - bool isItalic=false,isBold=false,isUnder=false,isStrike=false; - bool temp; - - // Iterate through blocks - ParseASSTags(); - for (size_t i=0;i(Blocks.at(i)); - if (curBlock) { - // Iterate through overrides - for (size_t j=0;jTags.size();j++) { - curTag = curBlock->Tags.at(j); - if (curTag->IsValid()) { - // Italics - if (curTag->Name == "\\i") { - temp = curTag->Params.at(0)->Get(); - if (temp && !isItalic) { - isItalic = true; - final += ""; - } - if (!temp && isItalic) { - isItalic = false; - final += ""; - } - } - - // Underline - if (curTag->Name == "\\u") { - temp = curTag->Params.at(0)->Get(); - if (temp && !isUnder) { - isUnder = true; - final += ""; - } - if (!temp && isUnder) { - isUnder = false; - final += ""; - } - } - - // Strikeout - if (curTag->Name == "\\s") { - temp = curTag->Params.at(0)->Get(); - if (temp && !isStrike) { - isStrike = true; - final += ""; - } - if (!temp && isStrike) { - isStrike = false; - final += ""; - } - } - - // Bold - if (curTag->Name == "\\b") { - temp = curTag->Params.at(0)->Get(); - if (temp && !isBold) { - isBold = true; - final += ""; - } - if (!temp && isBold) { - isBold = false; - final += ""; - } - } - } - } - } - - // Plain text - else { - curPlain = dynamic_cast(Blocks.at(i)); - if (curPlain) { - final += curPlain->GetText(); - } - } - } - - // Ensure all tags are closed - if (isBold) - final += ""; - if (isItalic) - final += ""; - if (isUnder) - final += ""; - if (isStrike) - final += ""; - - Text = final; - ClearBlocks(); -} - void AssDialogue::UpdateText () { if (Blocks.empty()) return; Text.clear(); diff --git a/aegisub/src/ass_dialogue.h b/aegisub/src/ass_dialogue.h index 717c83c2b..8213a24f4 100644 --- a/aegisub/src/ass_dialogue.h +++ b/aegisub/src/ass_dialogue.h @@ -204,8 +204,6 @@ public: /// @param callback The callback function to call per tag parameter /// @param userData User data to pass to callback function void ProcessParameters(AssDialogueBlockOverride::ProcessParametersCallback callback,void *userData=NULL); - /// Convert ASS tags to SRT tags - void ConvertTagsToSRT(); /// Strip all ASS tags from the text void StripTags(); /// Strip a specific ASS tag from the text diff --git a/aegisub/src/subtitle_format.cpp b/aegisub/src/subtitle_format.cpp index 311fbdce0..5f8e1d3c7 100644 --- a/aegisub/src/subtitle_format.cpp +++ b/aegisub/src/subtitle_format.cpp @@ -199,19 +199,22 @@ void SubtitleFormat::SortLines() { AssFile::Sort(*Line); } -void SubtitleFormat::ConvertTags(int format, const wxString &lineEnd, bool mergeLineBreaks) { +void SubtitleFormat::StripTags() { for (std::list::iterator cur = Line->begin(); cur != Line->end(); ++cur) { if (AssDialogue *current = dynamic_cast(*cur)) { - // Strip tags - if (format == 1) current->StripTags(); - else if (format == 2) current->ConvertTagsToSRT(); + current->StripTags(); + } + } +} - // Replace line breaks +void SubtitleFormat::ConvertNewlines(wxString const& newline, bool mergeLineBreaks) { + for (std::list::iterator cur = Line->begin(); cur != Line->end(); ++cur) { + if (AssDialogue *current = dynamic_cast(*cur)) { current->Text.Replace("\\h", " "); - current->Text.Replace("\\n", lineEnd); - current->Text.Replace("\\N", lineEnd); + current->Text.Replace("\\n", newline); + current->Text.Replace("\\N", newline); if (mergeLineBreaks) { - while (current->Text.Replace(lineEnd+lineEnd, lineEnd)); + while (current->Text.Replace(newline+newline, newline)); } } } diff --git a/aegisub/src/subtitle_format.h b/aegisub/src/subtitle_format.h index de9641d78..8fe157983 100644 --- a/aegisub/src/subtitle_format.h +++ b/aegisub/src/subtitle_format.h @@ -82,11 +82,12 @@ protected: void ClearCopy(); /// Sort the lines by start time void SortLines(); - /// Strip tags or convert them to SRT - /// @param format 1: strip tags 2: SRT - /// @param lineEnd Newline character(s) + /// Strip override tags + void StripTags(); + /// Convert newlines to the specified character(s) + /// @param lineEnd newline character(s) /// @param mergeLineBreaks Should multiple consecutive line breaks be merged into one? - void ConvertTags(int format, const wxString &lineEnd, bool mergeLineBreaks=true); + void ConvertNewlines(wxString const& newline, bool mergeLineBreaks = true); /// Remove All commented and empty lines void StripComments(); /// Remove everything but the dialogue lines diff --git a/aegisub/src/subtitle_format_encore.cpp b/aegisub/src/subtitle_format_encore.cpp index 9c118c7ed..22e374b5b 100644 --- a/aegisub/src/subtitle_format_encore.cpp +++ b/aegisub/src/subtitle_format_encore.cpp @@ -64,7 +64,8 @@ void EncoreSubtitleFormat::WriteFile(wxString const& filename, wxString const& e StripComments(); RecombineOverlaps(); MergeIdentical(); - ConvertTags(1, "\r\n"); + StripTags(); + ConvertNewlines("\r\n"); // Write lines int i = 0; diff --git a/aegisub/src/subtitle_format_microdvd.cpp b/aegisub/src/subtitle_format_microdvd.cpp index 74528e100..2c3c4819c 100644 --- a/aegisub/src/subtitle_format_microdvd.cpp +++ b/aegisub/src/subtitle_format_microdvd.cpp @@ -149,7 +149,8 @@ void MicroDVDSubtitleFormat::WriteFile(wxString const& filename, wxString const& StripComments(); RecombineOverlaps(); MergeIdentical(); - ConvertTags(1, "|"); + StripTags(); + ConvertNewlines("|"); TextFileWriter file(filename, encoding); diff --git a/aegisub/src/subtitle_format_srt.cpp b/aegisub/src/subtitle_format_srt.cpp index 1153c8f86..e4f27228e 100644 --- a/aegisub/src/subtitle_format_srt.cpp +++ b/aegisub/src/subtitle_format_srt.cpp @@ -42,6 +42,7 @@ #include "ass_dialogue.h" #include "ass_file.h" +#include "ass_override.h" #include "ass_style.h" #include "colorspace.h" #include "compat.h" @@ -519,26 +520,66 @@ void SRTSubtitleFormat::WriteFile(wxString const& filename, wxString const& enco CreateCopy(); SortLines(); StripComments(); - // Tags must be converted in two passes - // First ASS style overrides are converted to SRT but linebreaks are kept - ConvertTags(2,"\\N",false); - // Then we can recombine overlaps, this requires ASS style linebreaks RecombineOverlaps(); MergeIdentical(); - // And finally convert linebreaks - ConvertTags(0,"\r\n",false); - // Otherwise unclosed overrides might affect lines they shouldn't, see bug #809 for example + ConvertNewlines("\r\n", false); // Write lines int i=1; - for (std::list::iterator cur=Line->begin();cur!=Line->end();cur++) { + for (std::list::iterator cur = Line->begin(); cur != Line->end(); ++cur) { if (AssDialogue *current = dynamic_cast(*cur)) { file.WriteLineToFile(wxString::Format("%d", i++)); file.WriteLineToFile(WriteSRTTime(current->Start) + " --> " + WriteSRTTime(current->End)); - file.WriteLineToFile(current->Text); + file.WriteLineToFile(ConvertTags(current)); file.WriteLineToFile(""); } } ClearCopy(); } + +wxString SRTSubtitleFormat::ConvertTags(AssDialogue *diag) { + wxString final; + std::map tag_states; + tag_states['i'] = false; + tag_states['b'] = false; + tag_states['u'] = false; + tag_states['s'] = false; + + diag->ParseASSTags(); + + for (size_t i = 0; i < diag->Blocks.size(); ++i) { + if (AssDialogueBlockOverride* block = dynamic_cast(diag->Blocks[i])) { + // Iterate through overrides + for (size_t j = 0; j < block->Tags.size(); j++) { + AssOverrideTag *tag = block->Tags[j]; + if (tag->IsValid()) { + std::map::iterator it = tag_states.find(tag->Name[1]); + if (it != tag_states.end()) { + bool temp = tag->Params[0]->Get(); + if (temp && !it->second) + final += wxString::Format("<%c>", it->first); + if (!temp && it->second) + final += wxString::Format("", it->first); + it->second = temp; + } + } + } + } + // Plain text + else if (AssDialogueBlockPlain *plain = dynamic_cast(diag->Blocks[i])) { + final += plain->GetText(); + } + } + + // Ensure all tags are closed + // Otherwise unclosed overrides might affect lines they shouldn't, see bug #809 for example + for (std::map::iterator it = tag_states.begin(); it != tag_states.end(); ++it) { + if (it->second) + final += wxString::Format("", it->first); + } + + diag->ClearBlocks(); + + return final; +} diff --git a/aegisub/src/subtitle_format_srt.h b/aegisub/src/subtitle_format_srt.h index 4ed9ad2da..c7c1f13ae 100644 --- a/aegisub/src/subtitle_format_srt.h +++ b/aegisub/src/subtitle_format_srt.h @@ -42,6 +42,7 @@ /// /// DOCME class SRTSubtitleFormat : public SubtitleFormat { + wxString ConvertTags(AssDialogue *diag); public: SRTSubtitleFormat(); wxArrayString GetReadWildcards() const; diff --git a/aegisub/src/subtitle_format_ttxt.cpp b/aegisub/src/subtitle_format_ttxt.cpp index 363ce763d..08733e49a 100644 --- a/aegisub/src/subtitle_format_ttxt.cpp +++ b/aegisub/src/subtitle_format_ttxt.cpp @@ -282,7 +282,8 @@ void TTXTSubtitleFormat::ConvertToTTXT () { StripComments(); RecombineOverlaps(); MergeIdentical(); - ConvertTags(1, "\r\n"); + StripTags(); + ConvertNewlines("\r\n"); // Find last line AssTime lastTime;