Move ASS -> SRT tag conversion to the SRT subtitle format from AssDialogue

Originally committed to SVN as r5911.
This commit is contained in:
Thomas Goyne 2011-11-25 19:28:19 +00:00
parent 0992a839cc
commit 56e6f7d5b2
9 changed files with 73 additions and 123 deletions

View file

@ -360,103 +360,6 @@ void AssDialogue::StripTag (wxString tagName) {
Text = final; 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.size();i++) {
curBlock = dynamic_cast<AssDialogueBlockOverride*>(Blocks.at(i));
if (curBlock) {
// Iterate through overrides
for (size_t j=0;j<curBlock->Tags.size();j++) {
curTag = curBlock->Tags.at(j);
if (curTag->IsValid()) {
// Italics
if (curTag->Name == "\\i") {
temp = curTag->Params.at(0)->Get<bool>();
if (temp && !isItalic) {
isItalic = true;
final += "<i>";
}
if (!temp && isItalic) {
isItalic = false;
final += "</i>";
}
}
// Underline
if (curTag->Name == "\\u") {
temp = curTag->Params.at(0)->Get<bool>();
if (temp && !isUnder) {
isUnder = true;
final += "<u>";
}
if (!temp && isUnder) {
isUnder = false;
final += "</u>";
}
}
// Strikeout
if (curTag->Name == "\\s") {
temp = curTag->Params.at(0)->Get<bool>();
if (temp && !isStrike) {
isStrike = true;
final += "<s>";
}
if (!temp && isStrike) {
isStrike = false;
final += "</s>";
}
}
// Bold
if (curTag->Name == "\\b") {
temp = curTag->Params.at(0)->Get<bool>();
if (temp && !isBold) {
isBold = true;
final += "<b>";
}
if (!temp && isBold) {
isBold = false;
final += "</b>";
}
}
}
}
}
// Plain text
else {
curPlain = dynamic_cast<AssDialogueBlockPlain*>(Blocks.at(i));
if (curPlain) {
final += curPlain->GetText();
}
}
}
// Ensure all tags are closed
if (isBold)
final += "</b>";
if (isItalic)
final += "</i>";
if (isUnder)
final += "</u>";
if (isStrike)
final += "</s>";
Text = final;
ClearBlocks();
}
void AssDialogue::UpdateText () { void AssDialogue::UpdateText () {
if (Blocks.empty()) return; if (Blocks.empty()) return;
Text.clear(); Text.clear();

View file

@ -204,8 +204,6 @@ public:
/// @param callback The callback function to call per tag parameter /// @param callback The callback function to call per tag parameter
/// @param userData User data to pass to callback function /// @param userData User data to pass to callback function
void ProcessParameters(AssDialogueBlockOverride::ProcessParametersCallback callback,void *userData=NULL); void ProcessParameters(AssDialogueBlockOverride::ProcessParametersCallback callback,void *userData=NULL);
/// Convert ASS tags to SRT tags
void ConvertTagsToSRT();
/// Strip all ASS tags from the text /// Strip all ASS tags from the text
void StripTags(); void StripTags();
/// Strip a specific ASS tag from the text /// Strip a specific ASS tag from the text

View file

@ -199,19 +199,22 @@ void SubtitleFormat::SortLines() {
AssFile::Sort(*Line); AssFile::Sort(*Line);
} }
void SubtitleFormat::ConvertTags(int format, const wxString &lineEnd, bool mergeLineBreaks) { void SubtitleFormat::StripTags() {
for (std::list<AssEntry*>::iterator cur = Line->begin(); cur != Line->end(); ++cur) { for (std::list<AssEntry*>::iterator cur = Line->begin(); cur != Line->end(); ++cur) {
if (AssDialogue *current = dynamic_cast<AssDialogue*>(*cur)) { if (AssDialogue *current = dynamic_cast<AssDialogue*>(*cur)) {
// Strip tags current->StripTags();
if (format == 1) current->StripTags(); }
else if (format == 2) current->ConvertTagsToSRT(); }
}
// Replace line breaks void SubtitleFormat::ConvertNewlines(wxString const& newline, bool mergeLineBreaks) {
for (std::list<AssEntry*>::iterator cur = Line->begin(); cur != Line->end(); ++cur) {
if (AssDialogue *current = dynamic_cast<AssDialogue*>(*cur)) {
current->Text.Replace("\\h", " "); current->Text.Replace("\\h", " ");
current->Text.Replace("\\n", lineEnd); current->Text.Replace("\\n", newline);
current->Text.Replace("\\N", lineEnd); current->Text.Replace("\\N", newline);
if (mergeLineBreaks) { if (mergeLineBreaks) {
while (current->Text.Replace(lineEnd+lineEnd, lineEnd)); while (current->Text.Replace(newline+newline, newline));
} }
} }
} }

View file

@ -82,11 +82,12 @@ protected:
void ClearCopy(); void ClearCopy();
/// Sort the lines by start time /// Sort the lines by start time
void SortLines(); void SortLines();
/// Strip tags or convert them to SRT /// Strip override tags
/// @param format 1: strip tags 2: SRT void StripTags();
/// @param lineEnd Newline character(s) /// Convert newlines to the specified character(s)
/// @param lineEnd newline character(s)
/// @param mergeLineBreaks Should multiple consecutive line breaks be merged into one? /// @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 /// Remove All commented and empty lines
void StripComments(); void StripComments();
/// Remove everything but the dialogue lines /// Remove everything but the dialogue lines

View file

@ -64,7 +64,8 @@ void EncoreSubtitleFormat::WriteFile(wxString const& filename, wxString const& e
StripComments(); StripComments();
RecombineOverlaps(); RecombineOverlaps();
MergeIdentical(); MergeIdentical();
ConvertTags(1, "\r\n"); StripTags();
ConvertNewlines("\r\n");
// Write lines // Write lines
int i = 0; int i = 0;

View file

@ -149,7 +149,8 @@ void MicroDVDSubtitleFormat::WriteFile(wxString const& filename, wxString const&
StripComments(); StripComments();
RecombineOverlaps(); RecombineOverlaps();
MergeIdentical(); MergeIdentical();
ConvertTags(1, "|"); StripTags();
ConvertNewlines("|");
TextFileWriter file(filename, encoding); TextFileWriter file(filename, encoding);

View file

@ -42,6 +42,7 @@
#include "ass_dialogue.h" #include "ass_dialogue.h"
#include "ass_file.h" #include "ass_file.h"
#include "ass_override.h"
#include "ass_style.h" #include "ass_style.h"
#include "colorspace.h" #include "colorspace.h"
#include "compat.h" #include "compat.h"
@ -519,26 +520,66 @@ void SRTSubtitleFormat::WriteFile(wxString const& filename, wxString const& enco
CreateCopy(); CreateCopy();
SortLines(); SortLines();
StripComments(); 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(); RecombineOverlaps();
MergeIdentical(); MergeIdentical();
// And finally convert linebreaks ConvertNewlines("\r\n", false);
ConvertTags(0,"\r\n",false);
// Otherwise unclosed overrides might affect lines they shouldn't, see bug #809 for example
// Write lines // Write lines
int i=1; int i=1;
for (std::list<AssEntry*>::iterator cur=Line->begin();cur!=Line->end();cur++) { for (std::list<AssEntry*>::iterator cur = Line->begin(); cur != Line->end(); ++cur) {
if (AssDialogue *current = dynamic_cast<AssDialogue*>(*cur)) { if (AssDialogue *current = dynamic_cast<AssDialogue*>(*cur)) {
file.WriteLineToFile(wxString::Format("%d", i++)); file.WriteLineToFile(wxString::Format("%d", i++));
file.WriteLineToFile(WriteSRTTime(current->Start) + " --> " + WriteSRTTime(current->End)); file.WriteLineToFile(WriteSRTTime(current->Start) + " --> " + WriteSRTTime(current->End));
file.WriteLineToFile(current->Text); file.WriteLineToFile(ConvertTags(current));
file.WriteLineToFile(""); file.WriteLineToFile("");
} }
} }
ClearCopy(); ClearCopy();
} }
wxString SRTSubtitleFormat::ConvertTags(AssDialogue *diag) {
wxString final;
std::map<char, bool> 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<AssDialogueBlockOverride*>(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<char, bool>::iterator it = tag_states.find(tag->Name[1]);
if (it != tag_states.end()) {
bool temp = tag->Params[0]->Get<bool>();
if (temp && !it->second)
final += wxString::Format("<%c>", it->first);
if (!temp && it->second)
final += wxString::Format("</%c>", it->first);
it->second = temp;
}
}
}
}
// Plain text
else if (AssDialogueBlockPlain *plain = dynamic_cast<AssDialogueBlockPlain*>(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<char, bool>::iterator it = tag_states.begin(); it != tag_states.end(); ++it) {
if (it->second)
final += wxString::Format("</%c>", it->first);
}
diag->ClearBlocks();
return final;
}

View file

@ -42,6 +42,7 @@
/// ///
/// DOCME /// DOCME
class SRTSubtitleFormat : public SubtitleFormat { class SRTSubtitleFormat : public SubtitleFormat {
wxString ConvertTags(AssDialogue *diag);
public: public:
SRTSubtitleFormat(); SRTSubtitleFormat();
wxArrayString GetReadWildcards() const; wxArrayString GetReadWildcards() const;

View file

@ -282,7 +282,8 @@ void TTXTSubtitleFormat::ConvertToTTXT () {
StripComments(); StripComments();
RecombineOverlaps(); RecombineOverlaps();
MergeIdentical(); MergeIdentical();
ConvertTags(1, "\r\n"); StripTags();
ConvertNewlines("\r\n");
// Find last line // Find last line
AssTime lastTime; AssTime lastTime;