mirror of https://github.com/odrling/Aegisub
Move ass parsing logic from AssFile to ASSSubtitleFormat
This commit is contained in:
parent
682c7d5371
commit
006f820aea
|
@ -230,121 +230,6 @@ bool AssFile::CanSave() const {
|
||||||
return writer && writer->CanSave(this);
|
return writer && writer->CanSave(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssFile::AddLine(wxString data, int *version, AssAttachment **attach) {
|
|
||||||
// Is this line an attachment filename?
|
|
||||||
bool isFilename = data.StartsWith("fontname: ") || data.StartsWith("filename: ");
|
|
||||||
|
|
||||||
// If there's an attachment in progress, deal with it first as an
|
|
||||||
// attachment data line can appear to be other things
|
|
||||||
if (*attach) {
|
|
||||||
// Check if it's valid data
|
|
||||||
bool validData = data.size() > 0 && data.size() <= 80;
|
|
||||||
for (size_t i = 0; i < data.size(); ++i) {
|
|
||||||
if (data[i] < 33 || data[i] >= 97) {
|
|
||||||
validData = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Data is over, add attachment to the file
|
|
||||||
if (!validData || isFilename) {
|
|
||||||
(*attach)->Finish();
|
|
||||||
Line.push_back(*attach);
|
|
||||||
*attach = NULL;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Insert data
|
|
||||||
(*attach)->AddData(data);
|
|
||||||
|
|
||||||
// Done building
|
|
||||||
if (data.Length() < 80) {
|
|
||||||
(*attach)->Finish();
|
|
||||||
Line.push_back(*attach);
|
|
||||||
*attach = NULL;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.empty()) return;
|
|
||||||
|
|
||||||
// Section header
|
|
||||||
if (data[0] == '[' && data.Last() == ']') {
|
|
||||||
// Ugly hacks to allow intermixed v4 and v4+ style sections
|
|
||||||
wxString low = data.Lower();
|
|
||||||
if (low == "[v4 styles]") {
|
|
||||||
data = "[V4+ Styles]";
|
|
||||||
*version = 0;
|
|
||||||
}
|
|
||||||
else if (low == "[v4+ styles]") {
|
|
||||||
data = "[V4+ Styles]";
|
|
||||||
*version = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
Line.push_back(new AssEntry(data, data));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the first nonblank line isn't a header pretend it starts with [Script Info]
|
|
||||||
if (Line.empty())
|
|
||||||
Line.push_back(new AssEntry("[Script Info]", "[Script Info]"));
|
|
||||||
|
|
||||||
wxString group = Line.back()->group;
|
|
||||||
wxString lowGroup = group.Lower();
|
|
||||||
|
|
||||||
// Attachment
|
|
||||||
if (lowGroup == "[fonts]" || lowGroup == "[graphics]") {
|
|
||||||
if (isFilename) {
|
|
||||||
*attach = new AssAttachment(data.Mid(10), group);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Dialogue
|
|
||||||
else if (lowGroup == "[events]") {
|
|
||||||
if (data.StartsWith("Dialogue:") || data.StartsWith("Comment:"))
|
|
||||||
Line.push_back(new AssDialogue(data));
|
|
||||||
else if (data.StartsWith("Format:"))
|
|
||||||
Line.push_back(new AssEntry("Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text", group));
|
|
||||||
}
|
|
||||||
// Style
|
|
||||||
else if (lowGroup == "[v4+ styles]") {
|
|
||||||
if (data.StartsWith("Style:"))
|
|
||||||
Line.push_back(new AssStyle(data, *version));
|
|
||||||
else if (data.StartsWith("Format:"))
|
|
||||||
Line.push_back(new AssEntry("Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding", group));
|
|
||||||
}
|
|
||||||
// Script info
|
|
||||||
else if (lowGroup == "[script info]") {
|
|
||||||
// Comment
|
|
||||||
if (data.StartsWith(";")) {
|
|
||||||
// Skip stupid comments added by other programs
|
|
||||||
// Of course, we'll add our own in place later... ;)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.StartsWith("ScriptType:")) {
|
|
||||||
wxString versionString = data.Mid(11).Trim(true).Trim(false).Lower();
|
|
||||||
int trueVersion;
|
|
||||||
if (versionString == "v4.00")
|
|
||||||
trueVersion = 0;
|
|
||||||
else if (versionString == "v4.00+")
|
|
||||||
trueVersion = 1;
|
|
||||||
else
|
|
||||||
throw "Unknown SSA file format version";
|
|
||||||
if (trueVersion != *version) {
|
|
||||||
wxLogMessage("Warning: File has the wrong extension.");
|
|
||||||
*version = trueVersion;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Everything
|
|
||||||
Line.push_back(new AssEntry(data, group));
|
|
||||||
}
|
|
||||||
// Unrecognized group
|
|
||||||
else {
|
|
||||||
Line.push_back(new AssEntry(data, group));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AssFile::Clear() {
|
void AssFile::Clear() {
|
||||||
background_delete_clear(Line);
|
background_delete_clear(Line);
|
||||||
|
|
||||||
|
@ -359,24 +244,22 @@ void AssFile::LoadDefault(bool defline) {
|
||||||
Clear();
|
Clear();
|
||||||
|
|
||||||
// Write headers
|
// Write headers
|
||||||
AssAttachment *attach = 0;
|
Line.push_back(new AssEntry("[Script Info]", "[Script Info]"));
|
||||||
int version = 1;
|
Line.push_back(new AssEntry("Title: Default Aegisub file", "[Script Info]"));
|
||||||
AddLine("[Script Info]", &version, &attach);
|
Line.push_back(new AssEntry("ScriptType: v4.00+", "[Script Info]"));
|
||||||
AddLine("Title: Default Aegisub file", &version, &attach);
|
Line.push_back(new AssEntry("WrapStyle: 0", "[Script Info]"));
|
||||||
AddLine("ScriptType: v4.00+", &version, &attach);
|
Line.push_back(new AssEntry("ScaledBorderAndShadow: yes", "[Script Info]"));
|
||||||
AddLine("WrapStyle: 0", &version, &attach);
|
Line.push_back(new AssEntry("Collisions: Normal", "[Script Info]"));
|
||||||
AddLine("ScaledBorderAndShadow: yes", &version, &attach);
|
|
||||||
AddLine("Collisions: Normal", &version, &attach);
|
|
||||||
if (!OPT_GET("Subtitle/Default Resolution/Auto")->GetBool()) {
|
if (!OPT_GET("Subtitle/Default Resolution/Auto")->GetBool()) {
|
||||||
AddLine(wxString::Format("PlayResX: %" PRId64, OPT_GET("Subtitle/Default Resolution/Width")->GetInt()), &version, &attach);
|
Line.push_back(new AssEntry(wxString::Format("PlayResX: %" PRId64, OPT_GET("Subtitle/Default Resolution/Width")->GetInt()), "[Script Info]"));
|
||||||
AddLine(wxString::Format("PlayResY: %" PRId64, OPT_GET("Subtitle/Default Resolution/Height")->GetInt()), &version, &attach);
|
Line.push_back(new AssEntry(wxString::Format("PlayResY: %" PRId64, OPT_GET("Subtitle/Default Resolution/Height")->GetInt()), "[Script Info]"));
|
||||||
}
|
}
|
||||||
AddLine("YCbCr Matrix: None", &version, &attach);
|
Line.push_back(new AssEntry("YCbCr Matrix: None", "[Script Info]"));
|
||||||
|
|
||||||
InsertStyle(new AssStyle);
|
InsertStyle(new AssStyle);
|
||||||
|
|
||||||
AddLine("[Events]", &version, &attach);
|
Line.push_back(new AssEntry("[Events]", "[Events]"));
|
||||||
AddLine("Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text", &version, &attach);
|
Line.push_back(new AssEntry("Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text", "[Events]"));
|
||||||
|
|
||||||
if (defline)
|
if (defline)
|
||||||
Line.push_back(new AssDialogue);
|
Line.push_back(new AssDialogue);
|
||||||
|
|
|
@ -163,11 +163,6 @@ public:
|
||||||
void SetScriptInfo(wxString const& key, wxString const& value);
|
void SetScriptInfo(wxString const& key, wxString const& value);
|
||||||
// Add a ";" comment in the [Script Info] section
|
// Add a ";" comment in the [Script Info] section
|
||||||
void AddComment(wxString comment);
|
void AddComment(wxString comment);
|
||||||
/// @brief Add a line to the file
|
|
||||||
/// @param data Full text of ASS line
|
|
||||||
/// @param[in,out] version ASS version the line was parsed as
|
|
||||||
/// @param[in,out] attach Accumulator for attachment parsing
|
|
||||||
void AddLine(wxString data, int *version, AssAttachment **attach);
|
|
||||||
|
|
||||||
/// Type of changes made in a commit
|
/// Type of changes made in a commit
|
||||||
enum CommitType {
|
enum CommitType {
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
#include "dialog_progress.h"
|
#include "dialog_progress.h"
|
||||||
#include "MatroskaParser.h"
|
#include "MatroskaParser.h"
|
||||||
|
#include "subtitle_format_ass.h"
|
||||||
|
|
||||||
class MkvStdIO : public InputStream {
|
class MkvStdIO : public InputStream {
|
||||||
public:
|
public:
|
||||||
|
@ -137,7 +138,7 @@ static void read_subtitles(agi::ProgressSink *ps, MatroskaFile *file, MkvStdIO *
|
||||||
int version = ssa;
|
int version = ssa;
|
||||||
AssAttachment *attach = 0;
|
AssAttachment *attach = 0;
|
||||||
for (std::map<int, wxString>::iterator it = subList.begin(); it != subList.end(); ++it) {
|
for (std::map<int, wxString>::iterator it = subList.begin(); it != subList.end(); ++it) {
|
||||||
target->AddLine(it->second, &version, &attach);
|
ASSSubtitleFormat::AddLine(target, it->second, &version, &attach);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,7 +209,7 @@ void MatroskaWrapper::GetSubtitles(wxString const& filename, AssFile *target) {
|
||||||
AssAttachment *attach = 0;
|
AssAttachment *attach = 0;
|
||||||
wxStringTokenizer token(privString, "\r\n", wxTOKEN_STRTOK);
|
wxStringTokenizer token(privString, "\r\n", wxTOKEN_STRTOK);
|
||||||
while (token.HasMoreTokens())
|
while (token.HasMoreTokens())
|
||||||
target->AddLine(token.GetNextToken(), &version, &attach);
|
ASSSubtitleFormat::AddLine(target, token.GetNextToken(), &version, &attach);
|
||||||
}
|
}
|
||||||
// Load default if it's SRT
|
// Load default if it's SRT
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -38,8 +38,10 @@
|
||||||
|
|
||||||
#include "subtitle_format_ass.h"
|
#include "subtitle_format_ass.h"
|
||||||
|
|
||||||
|
#include "ass_attachment.h"
|
||||||
#include "ass_dialogue.h"
|
#include "ass_dialogue.h"
|
||||||
#include "ass_file.h"
|
#include "ass_file.h"
|
||||||
|
#include "ass_style.h"
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
#include "text_file_reader.h"
|
#include "text_file_reader.h"
|
||||||
#include "text_file_writer.h"
|
#include "text_file_writer.h"
|
||||||
|
@ -66,8 +68,6 @@ wxArrayString ASSSubtitleFormat::GetWriteWildcards() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASSSubtitleFormat::ReadFile(AssFile *target, wxString const& filename, wxString const& encoding) const {
|
void ASSSubtitleFormat::ReadFile(AssFile *target, wxString const& filename, wxString const& encoding) const {
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
target->Clear();
|
target->Clear();
|
||||||
|
|
||||||
TextFileReader file(filename, encoding);
|
TextFileReader file(filename, encoding);
|
||||||
|
@ -77,7 +77,7 @@ void ASSSubtitleFormat::ReadFile(AssFile *target, wxString const& filename, wxSt
|
||||||
while (file.HasMoreLines()) {
|
while (file.HasMoreLines()) {
|
||||||
wxString line = file.ReadLineFromFile();
|
wxString line = file.ReadLineFromFile();
|
||||||
try {
|
try {
|
||||||
target->AddLine(line, &version, &attach);
|
AddLine(target, line, &version, &attach);
|
||||||
}
|
}
|
||||||
catch (const char *err) {
|
catch (const char *err) {
|
||||||
target->Clear();
|
target->Clear();
|
||||||
|
@ -101,3 +101,118 @@ void ASSSubtitleFormat::WriteFile(const AssFile *src, wxString const& filename,
|
||||||
file.WriteLineToFile(ssa ? (*cur)->GetSSAText() : (*cur)->GetEntryData(), true);
|
file.WriteLineToFile(ssa ? (*cur)->GetSSAText() : (*cur)->GetEntryData(), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ASSSubtitleFormat::AddLine(AssFile *target, wxString data, int *version, AssAttachment **attach) {
|
||||||
|
// Is this line an attachment filename?
|
||||||
|
bool isFilename = data.StartsWith("fontname: ") || data.StartsWith("filename: ");
|
||||||
|
|
||||||
|
// If there's an attachment in progress, deal with it first as an
|
||||||
|
// attachment data line can appear to be other things
|
||||||
|
if (*attach) {
|
||||||
|
// Check if it's valid data
|
||||||
|
bool validData = data.size() > 0 && data.size() <= 80;
|
||||||
|
for (size_t i = 0; i < data.size(); ++i) {
|
||||||
|
if (data[i] < 33 || data[i] >= 97) {
|
||||||
|
validData = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Data is over, add attachment to the file
|
||||||
|
if (!validData || isFilename) {
|
||||||
|
(*attach)->Finish();
|
||||||
|
target->Line.push_back(*attach);
|
||||||
|
*attach = NULL;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Insert data
|
||||||
|
(*attach)->AddData(data);
|
||||||
|
|
||||||
|
// Done building
|
||||||
|
if (data.Length() < 80) {
|
||||||
|
(*attach)->Finish();
|
||||||
|
target->Line.push_back(*attach);
|
||||||
|
*attach = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.empty()) return;
|
||||||
|
|
||||||
|
// Section header
|
||||||
|
if (data[0] == '[' && data.Last() == ']') {
|
||||||
|
// Ugly hacks to allow intermixed v4 and v4+ style sections
|
||||||
|
wxString low = data.Lower();
|
||||||
|
if (low == "[v4 styles]") {
|
||||||
|
data = "[V4+ Styles]";
|
||||||
|
*version = 0;
|
||||||
|
}
|
||||||
|
else if (low == "[v4+ styles]") {
|
||||||
|
data = "[V4+ Styles]";
|
||||||
|
*version = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
target->Line.push_back(new AssEntry(data, data));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the first nonblank line isn't a header pretend it starts with [Script Info]
|
||||||
|
if (target->Line.empty())
|
||||||
|
target->Line.push_back(new AssEntry("[Script Info]", "[Script Info]"));
|
||||||
|
|
||||||
|
wxString group = target->Line.back()->group;
|
||||||
|
wxString lowGroup = group.Lower();
|
||||||
|
|
||||||
|
// Attachment
|
||||||
|
if (lowGroup == "[fonts]" || lowGroup == "[graphics]") {
|
||||||
|
if (isFilename) {
|
||||||
|
*attach = new AssAttachment(data.Mid(10), group);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Dialogue
|
||||||
|
else if (lowGroup == "[events]") {
|
||||||
|
if (data.StartsWith("Dialogue:") || data.StartsWith("Comment:"))
|
||||||
|
target->Line.push_back(new AssDialogue(data));
|
||||||
|
else if (data.StartsWith("Format:"))
|
||||||
|
target->Line.push_back(new AssEntry("Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text", group));
|
||||||
|
}
|
||||||
|
// Style
|
||||||
|
else if (lowGroup == "[v4+ styles]") {
|
||||||
|
if (data.StartsWith("Style:"))
|
||||||
|
target->Line.push_back(new AssStyle(data, *version));
|
||||||
|
else if (data.StartsWith("Format:"))
|
||||||
|
target->Line.push_back(new AssEntry("Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding", group));
|
||||||
|
}
|
||||||
|
// Script info
|
||||||
|
else if (lowGroup == "[script info]") {
|
||||||
|
// Comment
|
||||||
|
if (data.StartsWith(";")) {
|
||||||
|
// Skip stupid comments added by other programs
|
||||||
|
// Of course, we'll add our own in place later... ;)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.StartsWith("ScriptType:")) {
|
||||||
|
wxString versionString = data.Mid(11).Trim(true).Trim(false).Lower();
|
||||||
|
int trueVersion;
|
||||||
|
if (versionString == "v4.00")
|
||||||
|
trueVersion = 0;
|
||||||
|
else if (versionString == "v4.00+")
|
||||||
|
trueVersion = 1;
|
||||||
|
else
|
||||||
|
throw "Unknown SSA file format version";
|
||||||
|
if (trueVersion != *version) {
|
||||||
|
wxLogMessage("Warning: File has the wrong extension.");
|
||||||
|
*version = trueVersion;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Everything
|
||||||
|
target->Line.push_back(new AssEntry(data, group));
|
||||||
|
}
|
||||||
|
// Unrecognized group
|
||||||
|
else {
|
||||||
|
target->Line.push_back(new AssEntry(data, group));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -36,6 +36,8 @@
|
||||||
|
|
||||||
#include "subtitle_format.h"
|
#include "subtitle_format.h"
|
||||||
|
|
||||||
|
class AssAttachment;
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
/// @class ASSSubtitleFormat
|
/// @class ASSSubtitleFormat
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
|
@ -53,4 +55,6 @@ public:
|
||||||
|
|
||||||
void ReadFile(AssFile *target, wxString const& filename, wxString const& forceEncoding) const;
|
void ReadFile(AssFile *target, wxString const& filename, wxString const& forceEncoding) const;
|
||||||
void WriteFile(const AssFile *src, wxString const& filename, wxString const& encoding) const;
|
void WriteFile(const AssFile *src, wxString const& filename, wxString const& encoding) const;
|
||||||
|
|
||||||
|
static void AddLine(AssFile *target, wxString data, int *version, AssAttachment **attach);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue