diff --git a/build/Aegisub/Aegisub.vcxproj b/build/Aegisub/Aegisub.vcxproj
index b8c742bf5..1b543cae7 100644
--- a/build/Aegisub/Aegisub.vcxproj
+++ b/build/Aegisub/Aegisub.vcxproj
@@ -212,6 +212,7 @@
+
@@ -404,6 +405,7 @@
+
diff --git a/build/Aegisub/Aegisub.vcxproj.filters b/build/Aegisub/Aegisub.vcxproj.filters
index 9fc3e3d32..64750b2fd 100644
--- a/build/Aegisub/Aegisub.vcxproj.filters
+++ b/build/Aegisub/Aegisub.vcxproj.filters
@@ -618,6 +618,9 @@
Main UI\Grid
+
+ Subtitle formats
+
@@ -1169,13 +1172,12 @@
Main UI\Grid
+
+ Subtitle formats
+
-
- Resources
-
-
- Resources
-
+
+
diff --git a/src/Makefile b/src/Makefile
index 1195d03f3..3cfde47f0 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -223,6 +223,7 @@ SRC += \
subtitle_format_microdvd.cpp \
subtitle_format_mkv.cpp \
subtitle_format_srt.cpp \
+ subtitle_format_ssa.cpp \
subtitle_format_transtation.cpp \
subtitle_format_ttxt.cpp \
subtitle_format_txt.cpp \
diff --git a/src/ass_attachment.h b/src/ass_attachment.h
index 2a7efe249..4f42b4085 100644
--- a/src/ass_attachment.h
+++ b/src/ass_attachment.h
@@ -47,7 +47,6 @@ public:
std::string GetFileName(bool raw=false) const;
std::string const& GetEntryData() const { return entry_data; }
- std::string const& GetSSAText() const { return entry_data; }
AssEntryGroup Group() const override { return group; }
AssAttachment(AssAttachment const& rgt);
diff --git a/src/ass_dialogue.cpp b/src/ass_dialogue.cpp
index 80378172c..14e2d2d25 100644
--- a/src/ass_dialogue.cpp
+++ b/src/ass_dialogue.cpp
@@ -163,14 +163,11 @@ void append_unsafe_str(std::string &out, std::string const& str) {
out += ',';
}
-std::string AssDialogue::GetData(bool ssa) const {
+std::string AssDialogue::GetEntryData() const {
std::string str = Comment ? "Comment: " : "Dialogue: ";
str.reserve(51 + Style.get().size() + Actor.get().size() + Effect.get().size() + Text.get().size());
- if (ssa)
- append_str(str, "Marked=0");
- else
- append_int(str, Layer);
+ append_int(str, Layer);
append_str(str, Start.GetAssFormated());
append_str(str, End.GetAssFormated());
append_unsafe_str(str, Style);
diff --git a/src/ass_dialogue.h b/src/ass_dialogue.h
index e9273255c..996586a50 100644
--- a/src/ass_dialogue.h
+++ b/src/ass_dialogue.h
@@ -153,8 +153,6 @@ struct AssDialogueBase {
};
class AssDialogue final : public AssEntry, public AssDialogueBase, public AssEntryListHook {
- std::string GetData(bool ssa) const;
-
/// @brief Parse raw ASS data into everything else
/// @param data ASS line
void Parse(std::string const& data);
@@ -172,10 +170,8 @@ public:
/// Update the text of the line from parsed blocks
void UpdateText(std::vector>& blocks);
- std::string GetEntryData() const { return GetData(false); }
+ std::string GetEntryData() const;
- /// Get the line as SSA rather than ASS
- std::string GetSSAText() const { return GetData(true); }
/// Does this line collide with the passed line?
bool CollidesWith(const AssDialogue *target) const;
diff --git a/src/ass_entry.cpp b/src/ass_entry.cpp
index bdf486b0f..9befe02fe 100644
--- a/src/ass_entry.cpp
+++ b/src/ass_entry.cpp
@@ -21,7 +21,7 @@
#include "ass_entry.h"
-std::string const& AssEntry::GroupHeader(bool ssa) const {
+std::string const& AssEntry::GroupHeader() const {
static std::string ass_headers[] = {
"[Script Info]",
"[V4+ Styles]",
@@ -31,16 +31,5 @@ std::string const& AssEntry::GroupHeader(bool ssa) const {
"[Aegisub Extradata]",
""
};
-
- static std::string ssa_headers[] = {
- "[Script Info]",
- "[V4 Styles]",
- "[Fonts]",
- "[Graphics]",
- "[Events]",
- "[Aegisub Extradata]",
- ""
- };
-
- return (ssa ? ssa_headers : ass_headers)[(int)Group()];
+ return ass_headers[(int)Group()];
}
diff --git a/src/ass_entry.h b/src/ass_entry.h
index f830e0d92..f1f6b3f4c 100644
--- a/src/ass_entry.h
+++ b/src/ass_entry.h
@@ -57,5 +57,5 @@ public:
virtual AssEntryGroup Group() const=0;
/// ASS or SSA Section header for this entry's group
- std::string const& GroupHeader(bool ssa=false) const;
+ std::string const& GroupHeader() const;
};
diff --git a/src/ass_file.cpp b/src/ass_file.cpp
index 2e6a8b712..966e9cc19 100644
--- a/src/ass_file.cpp
+++ b/src/ass_file.cpp
@@ -25,6 +25,7 @@
#include
#include
+#include
#include
#include
diff --git a/src/ass_info.h b/src/ass_info.h
index 3f491e8f7..af6463d78 100644
--- a/src/ass_info.h
+++ b/src/ass_info.h
@@ -16,8 +16,6 @@
#include "ass_entry.h"
-#include
-
class AssInfo final : public AssEntry {
std::string key;
std::string value;
@@ -28,7 +26,6 @@ public:
AssEntryGroup Group() const override { return AssEntryGroup::INFO; }
std::string GetEntryData() const { return key + ": " + value; }
- std::string GetSSAText() const { return boost::iequals(key, "scripttype: v4.00+") ? "ScriptType: v4.00" : GetEntryData(); }
std::string Key() const { return key; }
std::string Value() const { return value; }
diff --git a/src/ass_style.cpp b/src/ass_style.cpp
index a7c6282e9..21efc713f 100644
--- a/src/ass_style.cpp
+++ b/src/ass_style.cpp
@@ -191,17 +191,6 @@ void AssStyle::UpdateData() {
% Margin[0] % Margin[1] % Margin[2] % encoding);
}
-std::string AssStyle::GetSSAText() const {
- return str(boost::format("Style: %s,%s,%g,%s,%s,0,%s,%d,%d,%d,%g,%g,%d,%d,%d,%d,0,%i")
- % name % font % fontsize
- % primary.GetSsaFormatted()
- % secondary.GetSsaFormatted()
- % shadow.GetSsaFormatted()
- % (bold? -1 : 0) % (italic ? -1 : 0)
- % borderstyle % outline_w % shadow_w % AssToSsa(alignment)
- % Margin[0] % Margin[1] % Margin[2] % encoding);
-}
-
void AssStyle::GetEncodings(wxArrayString &encodingStrings) {
encodingStrings.Clear();
encodingStrings.Add(wxString("0 - ") + _("ANSI"));
diff --git a/src/ass_style.h b/src/ass_style.h
index 432db702a..4ce0fccdd 100644
--- a/src/ass_style.h
+++ b/src/ass_style.h
@@ -78,7 +78,6 @@ public:
AssStyle(std::string const& data, int version=1);
std::string const& GetEntryData() const { return data; }
- std::string GetSSAText() const ;
AssEntryGroup Group() const override { return AssEntryGroup::STYLE; }
/// Convert an ASS alignment to the equivalent SSA alignment
diff --git a/src/auto4_lua.cpp b/src/auto4_lua.cpp
index 0116b933c..98960bea9 100644
--- a/src/auto4_lua.cpp
+++ b/src/auto4_lua.cpp
@@ -60,11 +60,11 @@
#include
#include
#include
+#include
#include
#include
#include
#include
-#include
#include
#include
#include
diff --git a/src/subtitle_format_ass.cpp b/src/subtitle_format_ass.cpp
index e5261193a..494041676 100644
--- a/src/subtitle_format_ass.cpp
+++ b/src/subtitle_format_ass.cpp
@@ -32,19 +32,6 @@
DEFINE_SIMPLE_EXCEPTION(AssParseError, SubtitleFormatParseError, "subtitle_io/parse/ass")
-AssSubtitleFormat::AssSubtitleFormat()
-: SubtitleFormat("Advanced Substation Alpha")
-{
-}
-
-std::vector AssSubtitleFormat::GetReadWildcards() const {
- return {"ass", "ssa"};
-}
-
-std::vector AssSubtitleFormat::GetWriteWildcards() const {
- return {"ass", "ssa"};
-}
-
void AssSubtitleFormat::ReadFile(AssFile *target, agi::fs::path const& filename, agi::vfr::Framerate const& fps, std::string const& encoding) const {
TextFileReader file(filename, encoding);
int version = !agi::fs::HasExtension(filename, "ssa");
@@ -68,27 +55,16 @@ void AssSubtitleFormat::ReadFile(AssFile *target, agi::fs::path const& filename,
#endif
namespace {
-const char *format(AssEntryGroup group, bool ssa) {
- if (group == AssEntryGroup::DIALOGUE) {
- if (ssa)
- return "Format: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text" LINEBREAK;
- else
- return "Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text" LINEBREAK;
- }
-
- if (group == AssEntryGroup::STYLE) {
- if (ssa)
- return "Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, TertiaryColour, BackColour, Bold, Italic, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, AlphaLevel, Encoding" LINEBREAK;
- else
- return "Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding" LINEBREAK;
- }
-
+const char *format(AssEntryGroup group) {
+ if (group == AssEntryGroup::DIALOGUE)
+ return "Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text" LINEBREAK;
+ if (group == AssEntryGroup::STYLE)
+ return "Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding" LINEBREAK;
return nullptr;
}
struct Writer {
TextFileWriter file;
- bool ssa = false;
AssEntryGroup group = AssEntryGroup::INFO;
Writer(std::ostream &ostr) : file(ostr) {
@@ -97,7 +73,6 @@ struct Writer {
Writer(agi::fs::path const& filename, std::string const& encoding)
: file(filename, encoding)
- , ssa(agi::fs::HasExtension(filename, "ssa"))
{
file.WriteLineToFile("[Script Info]");
file.WriteLineToFile(std::string("; Script generated by Aegisub ") + GetAegisubLongVersionString());
@@ -111,14 +86,14 @@ struct Writer {
// Add a blank line between each group
file.WriteLineToFile("");
- file.WriteLineToFile(line.GroupHeader(ssa));
- if (const char *str = format(line.Group(), ssa))
+ file.WriteLineToFile(line.GroupHeader());
+ if (const char *str = format(line.Group()))
file.WriteLineToFile(str, false);
group = line.Group();
}
- file.WriteLineToFile(ssa ? line.GetSSAText() : line.GetEntryData());
+ file.WriteLineToFile(line.GetEntryData());
}
}
diff --git a/src/subtitle_format_ass.h b/src/subtitle_format_ass.h
index 3071276d8..10d47dc38 100644
--- a/src/subtitle_format_ass.h
+++ b/src/subtitle_format_ass.h
@@ -1,47 +1,29 @@
-// Copyright (c) 2006, Rodrigo Braz Monteiro
-// All rights reserved.
+// Copyright (c) 2014, Thomas Goyne
//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
+// Permission to use, copy, modify, and distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
//
-// * Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-// * Neither the name of the Aegisub Group nor the names of its contributors
-// may be used to endorse or promote products derived from this software
-// without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-// POSSIBILITY OF SUCH DAMAGE.
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
//
// Aegisub Project http://www.aegisub.org/
-/// @file subtitle_format_ass.h
-/// @see subtitle_format_ass.cpp
-/// @ingroup subtitle_io
-///
-
#include "subtitle_format.h"
class AssSubtitleFormat final : public SubtitleFormat {
public:
- AssSubtitleFormat();
+ AssSubtitleFormat() : SubtitleFormat("Advanced SubStation Alpha") { }
- std::vector GetReadWildcards() const override;
- std::vector GetWriteWildcards() const override;
+ std::vector GetReadWildcards() const override { return {"ass", "ssa"}; }
+ std::vector GetWriteWildcards() const override { return {"ass"}; }
- // Naturally the ASS subtitle format can save all Ass files
+ // Naturally the ASS subtitle format can save all ASS files
bool CanSave(const AssFile*) const override { return true; }
void ReadFile(AssFile *target, agi::fs::path const& filename, agi::vfr::Framerate const& fps, std::string const& forceEncoding) const override;
diff --git a/src/subtitle_format_ssa.cpp b/src/subtitle_format_ssa.cpp
new file mode 100644
index 000000000..1cd790377
--- /dev/null
+++ b/src/subtitle_format_ssa.cpp
@@ -0,0 +1,93 @@
+// Copyright (c) 2014, Thomas Goyne
+//
+// Permission to use, copy, modify, and distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+// Aegisub Project http://www.aegisub.org/
+
+#include "subtitle_format_ssa.h"
+
+#include "ass_attachment.h"
+#include "ass_dialogue.h"
+#include "ass_info.h"
+#include "ass_file.h"
+#include "ass_style.h"
+#include "text_file_writer.h"
+#include "version.h"
+
+#include
+
+#include
+#include
+#include
+
+namespace {
+std::string replace_commas(std::string str) {
+ boost::replace_all(str, ",", ";");
+ return str;
+}
+
+std::string strip_newlines(std::string str) {
+ boost::replace_all(str, "\n", "");
+ boost::replace_all(str, "\r", "");
+ return str;
+}
+}
+
+void SsaSubtitleFormat::WriteFile(const AssFile *src, agi::fs::path const& filename, agi::vfr::Framerate const&, std::string const& encoding) const {
+ TextFileWriter file(filename, encoding);
+
+ file.WriteLineToFile("[Script Info]");
+ file.WriteLineToFile(std::string("; Script generated by Aegisub ") + GetAegisubLongVersionString());
+ file.WriteLineToFile("; http://www.aegisub.org/");
+ for (auto const& line : src->Info)
+ file.WriteLineToFile(boost::iequals(line.Key(), "scripttype") ? "ScriptType: v4.00" : line.GetEntryData());
+
+ file.WriteLineToFile("");
+ file.WriteLineToFile("[V4 Styles]");
+ file.WriteLineToFile("Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, TertiaryColour, BackColour, Bold, Italic, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, AlphaLevel, Encoding");
+ for (auto const& line : src->Styles)
+ file.WriteLineToFile(str(boost::format("Style: %s,%s,%g,%s,%s,0,%s,%d,%d,%d,%g,%g,%d,%d,%d,%d,0,%i")
+ % line.name % line.font % line.fontsize
+ % line.primary.GetSsaFormatted()
+ % line.secondary.GetSsaFormatted()
+ % line.shadow.GetSsaFormatted()
+ % (line.bold? -1 : 0) % (line.italic ? -1 : 0)
+ % line.borderstyle % line.outline_w % line.shadow_w % AssStyle::AssToSsa(line.alignment)
+ % line.Margin[0] % line.Margin[1] % line.Margin[2] % line.encoding));
+
+ file.WriteLineToFile("");
+ file.WriteLineToFile("[Fonts]");
+ for (auto const& line : src->Attachments) {
+ if (line.Group() == AssEntryGroup::FONT)
+ file.WriteLineToFile(line.GetEntryData());
+ }
+
+ file.WriteLineToFile("");
+ file.WriteLineToFile("[Graphics]");
+ for (auto const& line : src->Attachments) {
+ if (line.Group() == AssEntryGroup::GRAPHIC)
+ file.WriteLineToFile(line.GetEntryData());
+ }
+
+ file.WriteLineToFile("");
+ file.WriteLineToFile("[Events]");
+ file.WriteLineToFile("Format: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text");
+ for (auto const& line : src->Events)
+ file.WriteLineToFile(str(boost::format("%s: Marked=0,%s,%s,%s,%s,%d,%d,%d,%s,%s")
+ % (line.Comment ? "Comment" : "Dialogue")
+ % line.Start.GetAssFormated() % line.End.GetAssFormated()
+ % replace_commas(line.Style) % replace_commas(line.Actor)
+ % line.Margin[0] % line.Margin[1] % line.Margin[2]
+ % replace_commas(line.Effect)
+ % strip_newlines(line.Text)));
+}
diff --git a/src/subtitle_format_ssa.h b/src/subtitle_format_ssa.h
new file mode 100644
index 000000000..66ba45d03
--- /dev/null
+++ b/src/subtitle_format_ssa.h
@@ -0,0 +1,26 @@
+// Copyright (c) 2014, Thomas Goyne
+//
+// Permission to use, copy, modify, and distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+// Aegisub Project http://www.aegisub.org/
+
+#include "subtitle_format.h"
+
+class SsaSubtitleFormat final : public SubtitleFormat {
+public:
+ SsaSubtitleFormat() : SubtitleFormat("SubStation Alpha") { }
+ std::vector GetWriteWildcards() const override { return {"ssa"}; }
+ /// @todo Not actually true
+ bool CanSave(const AssFile*) const override { return true; }
+ void WriteFile(const AssFile *src, agi::fs::path const& filename, agi::vfr::Framerate const& fps, std::string const& encoding) const override;
+};
\ No newline at end of file