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;
}
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 () {
if (Blocks.empty()) return;
Text.clear();

View File

@ -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

View File

@ -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<AssEntry*>::iterator cur = Line->begin(); cur != Line->end(); ++cur) {
if (AssDialogue *current = dynamic_cast<AssDialogue*>(*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<AssEntry*>::iterator cur = Line->begin(); cur != Line->end(); ++cur) {
if (AssDialogue *current = dynamic_cast<AssDialogue*>(*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));
}
}
}

View File

@ -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

View File

@ -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;

View File

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

View File

@ -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<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)) {
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<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
class SRTSubtitleFormat : public SubtitleFormat {
wxString ConvertTags(AssDialogue *diag);
public:
SRTSubtitleFormat();
wxArrayString GetReadWildcards() const;

View File

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