Extract duplicated ASS writing code from libass provider

This commit is contained in:
Thomas Goyne 2014-04-29 09:02:59 -07:00
parent b24e2c33e0
commit 31af9c575f
5 changed files with 34 additions and 37 deletions

View file

@ -68,7 +68,7 @@ void AssSubtitleFormat::ReadFile(AssFile *target, agi::fs::path const& filename,
#endif #endif
namespace { namespace {
std::string format(AssEntryGroup group, bool ssa) { const char *format(AssEntryGroup group, bool ssa) {
if (group == AssEntryGroup::DIALOGUE) { if (group == AssEntryGroup::DIALOGUE) {
if (ssa) if (ssa)
return "Format: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text" LINEBREAK; return "Format: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text" LINEBREAK;
@ -83,14 +83,18 @@ std::string format(AssEntryGroup group, bool ssa) {
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 "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 ""; return nullptr;
} }
struct Writer { struct Writer {
TextFileWriter file; TextFileWriter file;
bool ssa; bool ssa = false;
AssEntryGroup group = AssEntryGroup::INFO; AssEntryGroup group = AssEntryGroup::INFO;
Writer(std::ostream &ostr) : file(ostr) {
file.WriteLineToFile("[Script Info]");
}
Writer(agi::fs::path const& filename, std::string const& encoding) Writer(agi::fs::path const& filename, std::string const& encoding)
: file(filename, encoding) : file(filename, encoding)
, ssa(agi::fs::HasExtension(filename, "ssa")) , ssa(agi::fs::HasExtension(filename, "ssa"))
@ -108,7 +112,8 @@ struct Writer {
file.WriteLineToFile(""); file.WriteLineToFile("");
file.WriteLineToFile(line.GroupHeader(ssa)); file.WriteLineToFile(line.GroupHeader(ssa));
file.WriteLineToFile(format(line.Group(), ssa), false); if (const char *str = format(line.Group(), ssa))
file.WriteLineToFile(str, false);
group = line.Group(); group = line.Group();
} }
@ -135,9 +140,7 @@ struct Writer {
// the inline_string encoding grew the data by more than uuencoding would // the inline_string encoding grew the data by more than uuencoding would
// so base64 encode it instead // so base64 encode it instead
line += "u"; // marker for uuencoding line += "u"; // marker for uuencoding
encoded_data = agi::ass::UUEncode(edi.second.second, false); line += agi::ass::UUEncode(edi.second.second, false);
printf("did uuencoding, original size=%lu, encoded size=%lu\n", edi.second.second.size(), encoded_data.size());
line += encoded_data;
} else { } else {
line += "e"; // marker for inline_string encoding (escaping) line += "e"; // marker for inline_string encoding (escaping)
line += encoded_data; line += encoded_data;
@ -150,10 +153,16 @@ struct Writer {
void AssSubtitleFormat::WriteFile(const AssFile *src, agi::fs::path const& filename, agi::vfr::Framerate const& fps, std::string const& encoding) const { void AssSubtitleFormat::WriteFile(const AssFile *src, agi::fs::path const& filename, agi::vfr::Framerate const& fps, std::string const& encoding) const {
Writer writer(filename, encoding); Writer writer(filename, encoding);
writer.Write(src->Info); writer.Write(src->Info);
writer.Write(src->Styles); writer.Write(src->Styles);
writer.Write(src->Attachments); writer.Write(src->Attachments);
writer.Write(src->Events); writer.Write(src->Events);
writer.WriteExtradata(src->Extradata); writer.WriteExtradata(src->Extradata);
} }
void AssSubtitleFormat::WriteToStream(const AssFile *src, std::ostream &ostr) {
Writer writer(ostr);
writer.Write(src->Info);
writer.Write(src->Styles);
writer.Write(src->Events);
}

View file

@ -46,4 +46,5 @@ public:
void ReadFile(AssFile *target, agi::fs::path const& filename, agi::vfr::Framerate const& fps, std::string const& forceEncoding) const override; void ReadFile(AssFile *target, agi::fs::path const& filename, agi::vfr::Framerate const& fps, std::string const& forceEncoding) const override;
void WriteFile(const AssFile *src, agi::fs::path const& filename, agi::vfr::Framerate const& fps, std::string const& encoding) const override; void WriteFile(const AssFile *src, agi::fs::path const& filename, agi::vfr::Framerate const& fps, std::string const& encoding) const override;
static void WriteToStream(const AssFile *src, std::ostream &ostr);
}; };

View file

@ -40,6 +40,7 @@
#include "ass_style.h" #include "ass_style.h"
#include "compat.h" #include "compat.h"
#include "include/aegisub/subtitles_provider.h" #include "include/aegisub/subtitles_provider.h"
#include "subtitle_format_ass.h"
#include "video_frame.h" #include "video_frame.h"
#include <libaegisub/background_runner.h> #include <libaegisub/background_runner.h>
@ -50,6 +51,7 @@
#include <atomic> #include <atomic>
#include <boost/gil/gil_all.hpp> #include <boost/gil/gil_all.hpp>
#include <boost/interprocess/streams/vectorstream.hpp>
#include <boost/range/algorithm_ext/push_back.hpp> #include <boost/range/algorithm_ext/push_back.hpp>
#include <memory> #include <memory>
#include <mutex> #include <mutex>
@ -153,33 +155,13 @@ LibassSubtitlesProvider::~LibassSubtitlesProvider() {
if (ass_track) ass_free_track(ass_track); if (ass_track) ass_free_track(ass_track);
} }
struct Writer {
std::vector<char> data;
AssEntryGroup group = AssEntryGroup::GROUP_MAX;
template<typename T>
void Write(T const& list) {
for (auto const& line : list) {
if (group != line.Group()) {
group = line.Group();
boost::push_back(data, line.GroupHeader() + "\r\n");
}
boost::push_back(data, line.GetEntryData() + "\r\n");
}
}
};
void LibassSubtitlesProvider::LoadSubtitles(AssFile *subs) { void LibassSubtitlesProvider::LoadSubtitles(AssFile *subs) {
Writer writer; boost::interprocess::basic_ovectorstream<std::vector<char>> ostr;
ostr.reserve(0x4000);
writer.data.reserve(0x4000); AssSubtitleFormat::WriteToStream(subs, ostr);
writer.Write(subs->Info);
writer.Write(subs->Styles);
writer.Write(subs->Events);
if (ass_track) ass_free_track(ass_track); if (ass_track) ass_free_track(ass_track);
ass_track = ass_read_memory(library, &writer.data[0], writer.data.size(), nullptr); ass_track = ass_read_memory(library, const_cast<char *>(ostr.vector().data()), ostr.vector().size(), nullptr);
if (!ass_track) throw "libass failed to load subtitles."; if (!ass_track) throw "libass failed to load subtitles.";
} }

View file

@ -32,7 +32,7 @@
TextFileWriter::TextFileWriter(agi::fs::path const& filename, std::string encoding) TextFileWriter::TextFileWriter(agi::fs::path const& filename, std::string encoding)
: file(new agi::io::Save(filename, true)) : file(new agi::io::Save(filename, true))
, conv() , ostr(file->Get())
{ {
if (encoding.empty()) if (encoding.empty())
encoding = OPT_GET("App/Save Charset")->GetString(); encoding = OPT_GET("App/Save Charset")->GetString();
@ -48,11 +48,15 @@ TextFileWriter::TextFileWriter(agi::fs::path const& filename, std::string encodi
} }
} }
TextFileWriter::TextFileWriter(std::ostream &ostr) : ostr(ostr) {
WriteLineToFile("\xEF\xBB\xBF", false);
}
TextFileWriter::~TextFileWriter() { TextFileWriter::~TextFileWriter() {
// Explicit empty destructor required with a unique_ptr to an incomplete class // Explicit empty destructor required with a unique_ptr to an incomplete class
} }
void TextFileWriter::WriteLineToFile(std::string&& line, bool addLineBreak) { void TextFileWriter::WriteLineToFile(std::string line, bool addLineBreak) {
if (addLineBreak) if (addLineBreak)
#ifdef _WIN32 #ifdef _WIN32
line += "\r\n"; line += "\r\n";
@ -62,5 +66,5 @@ void TextFileWriter::WriteLineToFile(std::string&& line, bool addLineBreak) {
if (conv) if (conv)
line = conv->Convert(line); line = conv->Convert(line);
file->Get().write(line.data(), line.size()); ostr.write(line.data(), line.size());
} }

View file

@ -32,11 +32,12 @@ namespace agi {
class TextFileWriter { class TextFileWriter {
std::unique_ptr<agi::io::Save> file; std::unique_ptr<agi::io::Save> file;
std::unique_ptr<agi::charset::IconvWrapper> conv; std::unique_ptr<agi::charset::IconvWrapper> conv;
std::ostream &ostr;
public: public:
TextFileWriter(agi::fs::path const& filename, std::string encoding=""); TextFileWriter(agi::fs::path const& filename, std::string encoding="");
TextFileWriter(std::ostream &ostr);
~TextFileWriter(); ~TextFileWriter();
void WriteLineToFile(std::string const& line, bool addLineBreak=true) { WriteLineToFile(std::string(line), addLineBreak); } void WriteLineToFile(std::string line, bool addLineBreak=true);
void WriteLineToFile(std::string&& line, bool addLineBreak=true);
}; };