From 708622cc632d4c89575e787c8b321e3563056992 Mon Sep 17 00:00:00 2001 From: Rodrigo Braz Monteiro Date: Tue, 19 Jun 2007 03:34:53 +0000 Subject: [PATCH] Some refactoring and bug fixing to subtitle format stuff, and improved saving of srt, ttxt and microdvd. Originally committed to SVN as r1259. --- aegisub/ass_dialogue.cpp | 19 ++----- aegisub/subtitle_format.cpp | 80 ++++++++++++++++++++++++++++ aegisub/subtitle_format.h | 4 ++ aegisub/subtitle_format_microdvd.cpp | 13 +++-- aegisub/subtitle_format_srt.cpp | 70 ++---------------------- aegisub/subtitle_format_srt.h | 4 -- aegisub/subtitle_format_ttxt.cpp | 67 ++++------------------- aegisub/subtitle_format_ttxt.h | 1 - 8 files changed, 112 insertions(+), 146 deletions(-) diff --git a/aegisub/ass_dialogue.cpp b/aegisub/ass_dialogue.cpp index c65fcd472..7cff66e05 100644 --- a/aegisub/ass_dialogue.cpp +++ b/aegisub/ass_dialogue.cpp @@ -38,6 +38,7 @@ // Includes #include #include +#include #include "ass_dialogue.h" #include "ass_override.h" #include "vfr.h" @@ -544,22 +545,8 @@ void AssDialogue::ParseASSTags () { ////////////// // Strip tags void AssDialogue::StripTags () { - using std::list; - using std::vector; - ParseASSTags(); - vector::iterator next; - for (vector::iterator cur=Blocks.begin();cur!=Blocks.end();cur=next) { - next = cur; - next++; - // FIXME: doesn't this crash when there's too many override blocks in one line? - if ((*cur)->type == BLOCK_OVERRIDE) { - delete *cur; - Blocks.erase(cur); - } - } - UpdateText(); - UpdateData(); - ClearBlocks(); + static wxRegEx reg(_T("\\{[^\\{]*\\}"),wxRE_ADVANCED); + reg.Replace(&Text,_T("")); } diff --git a/aegisub/subtitle_format.cpp b/aegisub/subtitle_format.cpp index 1cde061c8..afd2da788 100644 --- a/aegisub/subtitle_format.cpp +++ b/aegisub/subtitle_format.cpp @@ -314,3 +314,83 @@ double SubtitleFormat::AskForFPS() { // fubar return 0.0; } + + +////////////// +// Sort lines +void SubtitleFormat::SortLines() { + Line->sort(LessByPointedToValue()); +} + + +//////////////// +// Convert tags +void SubtitleFormat::ConvertTags(int format,wxString lineEnd) { + using std::list; + list::iterator next; + for (list::iterator cur=Line->begin();cur!=Line->end();cur++) { + AssDialogue *current = AssEntry::GetAsDialogue(*cur); + if (current) { + // Strip tags + if (format == 1) current->StripTags(); + else if (format == 2) current->ConvertTagsToSRT(); + + // Replace line breaks + current->Text.Replace(_T("\\h"),_T(" "),true); + current->Text.Replace(_T("\\n"),lineEnd,true); + current->Text.Replace(_T("\\N"),lineEnd,true); + while (current->Text.Replace(lineEnd+lineEnd,lineEnd,true)); + } + } +} + + +//////////////////////////////////////////// +// Merge identical and/or overlapping lines +void SubtitleFormat::Merge(bool identical,bool overlaps,bool stripComments) { + using std::list; + list::iterator next; + list::iterator prev = Line->end(); + AssDialogue *previous = NULL; + + // Loop through each line + for (list::iterator cur=Line->begin();cur!=Line->end();cur=next) { + next = cur; + next++; + + // Dialogue line + AssDialogue *current = AssEntry::GetAsDialogue(*cur); + if (current) { + // Strip comments and empty lines + if ((current->Comment && stripComments) || current->Text.IsEmpty()) { + delete *cur; + Line->erase(cur); + } + + // Proper line + else { + // Check for duplication + if (previous != NULL) { + if (previous->Text == current->Text) { + if (abs(current->Start.GetMS() - previous->End.GetMS()) < 20) { + current->Start = (current->Start < previous->Start ? current->Start : previous->Start); + current->End = (current->End > previous->End ? current->End : previous->End); + delete *prev; + Line->erase(prev); + } + } + } + + // Set as previous + prev = cur; + previous = current; + } + } + + // Other line, delete it + else { + delete *cur; + Line->erase(cur); + } + } +} diff --git a/aegisub/subtitle_format.h b/aegisub/subtitle_format.h index 05d4066b9..d27a68f1f 100644 --- a/aegisub/subtitle_format.h +++ b/aegisub/subtitle_format.h @@ -64,8 +64,12 @@ private: protected: std::list *Line; + void CreateCopy(); void ClearCopy(); + void SortLines(); + void ConvertTags(int format,wxString lineEnd); + void Merge(bool identical,bool overlaps,bool stripComments); void Clear(); void LoadDefault(bool defline=true); diff --git a/aegisub/subtitle_format_microdvd.cpp b/aegisub/subtitle_format_microdvd.cpp index 3150a972c..de65d9b8b 100644 --- a/aegisub/subtitle_format_microdvd.cpp +++ b/aegisub/subtitle_format_microdvd.cpp @@ -175,6 +175,12 @@ void MicroDVDSubtitleFormat::WriteFile(wxString filename,wxString encoding) { else if (fps > 0.0) cfr.SetCFR(fps); else rate = &VFR_Output; + // Convert file + CreateCopy(); + SortLines(); + Merge(true,true,true); + ConvertTags(1,_T("|")); + // Open file TextFileWriter file(filename,encoding); @@ -191,11 +197,12 @@ void MicroDVDSubtitleFormat::WriteFile(wxString filename,wxString encoding) { // Prepare data int start = rate->GetFrameAtTime(current->Start.GetMS(),true); int end = rate->GetFrameAtTime(current->End.GetMS(),false); - wxString text = current->Text; - text.Replace(_T("\\N"),_T("|")); // Write data - file.WriteLineToFile(wxString::Format(_T("{%i}{%i}%s"),start,end,text.c_str())); + file.WriteLineToFile(wxString::Format(_T("{%i}{%i}%s"),start,end,current->Text.c_str())); } } + + // Clean up + ClearCopy(); } diff --git a/aegisub/subtitle_format_srt.cpp b/aegisub/subtitle_format_srt.cpp index 080455ac1..7e4301b5d 100644 --- a/aegisub/subtitle_format_srt.cpp +++ b/aegisub/subtitle_format_srt.cpp @@ -181,7 +181,9 @@ void SRTSubtitleFormat::WriteFile(wxString _filename,wxString encoding) { // Convert to SRT CreateCopy(); - ConvertToSRT(); + SortLines(); + Merge(true,true,true); + ConvertTags(2,_T("\r\n")); // Write lines int i=1; @@ -202,69 +204,7 @@ void SRTSubtitleFormat::WriteFile(wxString _filename,wxString encoding) { } else throw _T("Unexpected line type"); } + + // Clean up ClearCopy(); } - - -/////////////////////// -// Convert line to SRT -void SRTSubtitleFormat::DialogueToSRT(AssDialogue *current,std::list::iterator prev) { - using std::list; - AssDialogue *previous; - if (prev != Line->end()) previous = AssEntry::GetAsDialogue(*prev); - else previous = NULL; - - // Strip ASS tags - current->ConvertTagsToSRT(); - - // Join equal lines - if (previous != NULL) { - if (previous->Text == current->Text) { - if (abs(current->Start.GetMS() - previous->End.GetMS()) < 20) { - current->Start = (current->Start < previous->Start ? current->Start : previous->Start); - current->End = (current->End > previous->End ? current->End : previous->End); - delete *prev; - Line->erase(prev); - } - } - } - - // Fix line breaks - current->Text.Replace(_T("\\n"),_T("\r\n"),true); - current->Text.Replace(_T("\\N"),_T("\r\n"),true); - while (current->Text.Replace(_T("\r\n\r\n"),_T("\r\n"),true)); -} - - -////////////////////////////// -// Converts whole file to SRT -void SRTSubtitleFormat::ConvertToSRT () { - using std::list; - - // Sort lines - Line->sort(LessByPointedToValue()); - - list::iterator next; - list::iterator prev = Line->end(); - - // Process lines - bool notfirst = false; - for (list::iterator cur=Line->begin();cur!=Line->end();cur=next) { - next = cur; - next++; - - // Dialogue line (not comment) - AssDialogue *current = AssEntry::GetAsDialogue(*cur); - if (current && !current->Comment) { - DialogueToSRT(current,prev); - notfirst = true; - prev = cur; - } - - // Other line, delete it - else { - delete *cur; - Line->erase(cur); - } - } -} diff --git a/aegisub/subtitle_format_srt.h b/aegisub/subtitle_format_srt.h index 257b16065..d7c3d2ba4 100644 --- a/aegisub/subtitle_format_srt.h +++ b/aegisub/subtitle_format_srt.h @@ -50,10 +50,6 @@ class AssDialogue; ///////////////////// // SRT reader/writer class SRTSubtitleFormat : public SubtitleFormat { -private: - void ConvertToSRT(); - void DialogueToSRT(AssDialogue *current,std::list::iterator prev); - public: wxString GetName(); wxArrayString GetReadWildcards(); diff --git a/aegisub/subtitle_format_ttxt.cpp b/aegisub/subtitle_format_ttxt.cpp index 0821dfe25..46f5ad2b9 100644 --- a/aegisub/subtitle_format_ttxt.cpp +++ b/aegisub/subtitle_format_ttxt.cpp @@ -316,68 +316,21 @@ void TTXTSubtitleFormat::WriteLine(wxXmlNode *root, AssDialogue *line) { } -/////////////////////// -// Convert line to TTXT -void TTXTSubtitleFormat::DialogueToTTXT(AssDialogue *current,std::list::iterator prev) { - using std::list; - AssDialogue *previous; - if (prev != Line->end()) previous = AssEntry::GetAsDialogue(*prev); - else previous = NULL; - - // Strip ASS tags - current->StripTags(); - - // Join equal lines - if (previous != NULL) { - if (previous->Text == current->Text) { - if (abs(current->Start.GetMS() - previous->End.GetMS()) < 20) { - current->Start = (current->Start < previous->Start ? current->Start : previous->Start); - current->End = (current->End > previous->End ? current->End : previous->End); - delete *prev; - Line->erase(prev); - } - } - } - - // Fix line breaks - current->Text.Replace(_T("\\n"),_T("\r\n"),true); - current->Text.Replace(_T("\\N"),_T("\r\n"),true); - while (current->Text.Replace(_T("\r\n\r\n"),_T("\r\n"),true)); -} - - ////////////////////////////// // Converts whole file to TTXT void TTXTSubtitleFormat::ConvertToTTXT () { - using std::list; + // Convert + SortLines(); + Merge(true,true,true); + ConvertTags(1,_T("\r\n")); - // Sort lines - Line->sort(LessByPointedToValue()); - - // Prepare processing - list::iterator next; - list::iterator prev = Line->end(); + // Find last line AssTime lastTime; - - // Process lines - bool notfirst = false; - for (list::iterator cur=Line->begin();cur!=Line->end();cur=next) { - next = cur; - next++; - - // Dialogue line (not comment) - AssDialogue *current = AssEntry::GetAsDialogue(*cur); - if (current && !current->Comment) { - DialogueToTTXT(current,prev); - notfirst = true; - prev = cur; - lastTime = current->End; - } - - // Other line, delete it - else { - delete *cur; - Line->erase(cur); + for (std::list::reverse_iterator cur=Line->rbegin();cur!=Line->rend();cur++) { + AssDialogue *prev = AssEntry::GetAsDialogue(*cur); + if (prev) { + lastTime = prev->End; + break; } } diff --git a/aegisub/subtitle_format_ttxt.h b/aegisub/subtitle_format_ttxt.h index 67833ceb3..96e414461 100644 --- a/aegisub/subtitle_format_ttxt.h +++ b/aegisub/subtitle_format_ttxt.h @@ -59,7 +59,6 @@ private: void WriteLine(wxXmlNode *root,AssDialogue *line); void ConvertToTTXT(); - void DialogueToTTXT(AssDialogue *current,std::list::iterator prev); public: wxString GetName();