#include <boost/bind.hpp>
#include <boost/foreach.hpp>
#include <sstream>
+#include <iostream>
#include <vector>
using std::string;
using std::vector;
using std::map;
using std::cout;
+using std::list;
using boost::optional;
using boost::function;
using namespace boost::algorithm;
);
}
+/** @param base RawSubtitle filled in with any required common values.
+ * @param line SSA line string.
+ * @return List of RawSubtitles to represent line with vertical reference TOP_OF_SUBTITLE.
+ */
+list<RawSubtitle>
+SSAReader::parse_line (RawSubtitle base, string line)
+{
+ enum {
+ TEXT,
+ STYLE,
+ BACKSLASH
+ } state = TEXT;
+
+ list<RawSubtitle> subs;
+ RawSubtitle current = base;
+ string style;
+
+ current.vertical_position.line = 0;
+ /* XXX: arbitrary */
+ current.vertical_position.lines = 32;
+ current.vertical_position.reference = TOP_OF_SUBTITLE;
+
+ for (size_t i = 0; i < line.length(); ++i) {
+ char const c = line[i];
+ switch (state) {
+ case TEXT:
+ if (c == '{') {
+ state = STYLE;
+ } else if (c == '\\') {
+ state = BACKSLASH;
+ } else if (c != '\r' && c != '\n') {
+ current.text += c;
+ }
+ break;
+ case STYLE:
+ if (c == '}') {
+ if (!current.text.empty ()) {
+ subs.push_back (current);
+ current.text = "";
+ }
+ if (style == "i1") {
+ current.italic = true;
+ } else if (style == "i0") {
+ current.italic = false;
+ }
+ style = "";
+ state = TEXT;
+ } else {
+ style += c;
+ }
+ break;
+ case BACKSLASH:
+ if ((c == 'n' || c == 'N') && !current.text.empty ()) {
+ subs.push_back (current);
+ current.text = "";
+ current.vertical_position.line = current.vertical_position.line.get() + 1;
+ }
+ state = TEXT;
+ break;
+ }
+ }
+
+ if (!current.text.empty ()) {
+ subs.push_back (current);
+ }
+
+ return subs;
+}
+
void
SSAReader::read (function<optional<string> ()> get_line)
{
}
trim (*line);
+ remove_unicode_bom (line);
if (starts_with (*line, ";") || line->empty ()) {
continue;
vector<string> event;
split (event, body, is_any_of (","));
+ /* There may be commas in the subtitle part; reassemble any extra parts
+ from when we just split it.
+ */
+ while (event.size() > event_format.size()) {
+ string const ex = event.back ();
+ event.pop_back ();
+ event.back() += "," + ex;
+ }
+
SUB_ASSERT (!event.empty());
SUB_ASSERT (event_format.size() == event.size());
sub.bold = style.bold;
sub.italic = style.italic;
sub.effect = style.effect;
+
+ /* XXX: arbitrary */
+ sub.vertical_position.lines = 32;
+ sub.vertical_position.reference = TOP_OF_SUBTITLE;
+ sub.vertical_position.line = 0;
+
} else if (event_format[i] == "Text") {
- sub.text = event[i];
+ BOOST_FOREACH (sub::RawSubtitle j, parse_line (sub, event[i])) {
+ _subs.push_back (j);
+ }
}
}
-
- _subs.push_back (sub);
}
}