Some refactoring and bug fixing to subtitle format stuff, and improved saving of srt, ttxt and microdvd.

Originally committed to SVN as r1259.
This commit is contained in:
Rodrigo Braz Monteiro 2007-06-19 03:34:53 +00:00
parent 0aaedd7b49
commit 708622cc63
8 changed files with 112 additions and 146 deletions

View file

@ -38,6 +38,7 @@
// Includes
#include <fstream>
#include <wx/tokenzr.h>
#include <wx/regex.h>
#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<AssDialogueBlock*>::iterator next;
for (vector<AssDialogueBlock*>::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(""));
}

View file

@ -314,3 +314,83 @@ double SubtitleFormat::AskForFPS() {
// fubar
return 0.0;
}
//////////////
// Sort lines
void SubtitleFormat::SortLines() {
Line->sort(LessByPointedToValue<AssEntry>());
}
////////////////
// Convert tags
void SubtitleFormat::ConvertTags(int format,wxString lineEnd) {
using std::list;
list<AssEntry*>::iterator next;
for (list<AssEntry*>::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<AssEntry*>::iterator next;
list<AssEntry*>::iterator prev = Line->end();
AssDialogue *previous = NULL;
// Loop through each line
for (list<AssEntry*>::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);
}
}
}

View file

@ -64,8 +64,12 @@ private:
protected:
std::list<AssEntry*> *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);

View file

@ -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();
}

View file

@ -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<AssEntry*>::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<AssEntry>());
list<AssEntry*>::iterator next;
list<AssEntry*>::iterator prev = Line->end();
// Process lines
bool notfirst = false;
for (list<AssEntry*>::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);
}
}
}

View file

@ -50,10 +50,6 @@ class AssDialogue;
/////////////////////
// SRT reader/writer
class SRTSubtitleFormat : public SubtitleFormat {
private:
void ConvertToSRT();
void DialogueToSRT(AssDialogue *current,std::list<AssEntry*>::iterator prev);
public:
wxString GetName();
wxArrayString GetReadWildcards();

View file

@ -316,68 +316,21 @@ void TTXTSubtitleFormat::WriteLine(wxXmlNode *root, AssDialogue *line) {
}
///////////////////////
// Convert line to TTXT
void TTXTSubtitleFormat::DialogueToTTXT(AssDialogue *current,std::list<AssEntry*>::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<AssEntry>());
// Prepare processing
list<AssEntry*>::iterator next;
list<AssEntry*>::iterator prev = Line->end();
// Find last line
AssTime lastTime;
// Process lines
bool notfirst = false;
for (list<AssEntry*>::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<AssEntry*>::reverse_iterator cur=Line->rbegin();cur!=Line->rend();cur++) {
AssDialogue *prev = AssEntry::GetAsDialogue(*cur);
if (prev) {
lastTime = prev->End;
break;
}
}

View file

@ -59,7 +59,6 @@ private:
void WriteLine(wxXmlNode *root,AssDialogue *line);
void ConvertToTTXT();
void DialogueToTTXT(AssDialogue *current,std::list<AssEntry*>::iterator prev);
public:
wxString GetName();