forked from mia/Aegisub
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:
parent
0aaedd7b49
commit
708622cc63
8 changed files with 112 additions and 146 deletions
|
@ -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(""));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue