Don't fill in vertical_position.lines with an arbitrary value.
[libsub.git] / src / ssa_reader.cc
index f3180a7457993e46660e09b4ca9d82c2af830163..c76a78db34d006c4244e40f4d8e7423edfd5fc14 100644 (file)
@@ -26,6 +26,7 @@
 #include <boost/bind.hpp>
 #include <boost/foreach.hpp>
 #include <sstream>
+#include <iostream>
 #include <vector>
 
 using std::string;
@@ -33,6 +34,7 @@ using std::stringstream;
 using std::vector;
 using std::map;
 using std::cout;
+using std::list;
 using boost::optional;
 using boost::function;
 using namespace boost::algorithm;
@@ -136,6 +138,75 @@ SSAReader::parse_time (string t) const
                );
 }
 
+/** @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)
 {
@@ -156,6 +227,7 @@ SSAReader::read (function<optional<string> ()> get_line)
                }
 
                trim (*line);
+               remove_unicode_bom (line);
 
                if (starts_with (*line, ";") || line->empty ()) {
                        continue;
@@ -202,6 +274,15 @@ SSAReader::read (function<optional<string> ()> get_line)
                                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());
 
@@ -223,12 +304,18 @@ SSAReader::read (function<optional<string> ()> get_line)
                                                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);
                        }
                }