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
namespace {
std::string format(AssEntryGroup group, bool ssa) {
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;
@ -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 "";
return nullptr;
}
struct Writer {
TextFileWriter file;
bool ssa;
bool ssa = false;
AssEntryGroup group = AssEntryGroup::INFO;
Writer(std::ostream &ostr) : file(ostr) {
file.WriteLineToFile("[Script Info]");
}
Writer(agi::fs::path const& filename, std::string const& encoding)
: file(filename, encoding)
, ssa(agi::fs::HasExtension(filename, "ssa"))
@ -108,7 +112,8 @@ struct Writer {
file.WriteLineToFile("");
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();
}
@ -135,9 +140,7 @@ struct Writer {
// the inline_string encoding grew the data by more than uuencoding would
// so base64 encode it instead
line += "u"; // marker for uuencoding
encoded_data = 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;
line += agi::ass::UUEncode(edi.second.second, false);
} else {
line += "e"; // marker for inline_string encoding (escaping)
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 {
Writer writer(filename, encoding);
writer.Write(src->Info);
writer.Write(src->Styles);
writer.Write(src->Attachments);
writer.Write(src->Events);
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 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 "compat.h"
#include "include/aegisub/subtitles_provider.h"
#include "subtitle_format_ass.h"
#include "video_frame.h"
#include <libaegisub/background_runner.h>
@ -50,6 +51,7 @@
#include <atomic>
#include <boost/gil/gil_all.hpp>
#include <boost/interprocess/streams/vectorstream.hpp>
#include <boost/range/algorithm_ext/push_back.hpp>
#include <memory>
#include <mutex>
@ -153,33 +155,13 @@ LibassSubtitlesProvider::~LibassSubtitlesProvider() {
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) {
Writer writer;
writer.data.reserve(0x4000);
writer.Write(subs->Info);
writer.Write(subs->Styles);
writer.Write(subs->Events);
boost::interprocess::basic_ovectorstream<std::vector<char>> ostr;
ostr.reserve(0x4000);
AssSubtitleFormat::WriteToStream(subs, ostr);
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.";
}

View file

@ -32,7 +32,7 @@
TextFileWriter::TextFileWriter(agi::fs::path const& filename, std::string encoding)
: file(new agi::io::Save(filename, true))
, conv()
, ostr(file->Get())
{
if (encoding.empty())
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() {
// 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)
#ifdef _WIN32
line += "\r\n";
@ -62,5 +66,5 @@ void TextFileWriter::WriteLineToFile(std::string&& line, bool addLineBreak) {
if (conv)
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 {
std::unique_ptr<agi::io::Save> file;
std::unique_ptr<agi::charset::IconvWrapper> conv;
std::ostream &ostr;
public:
TextFileWriter(agi::fs::path const& filename, std::string encoding="");
TextFileWriter(std::ostream &ostr);
~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);
};