diff options
| author | Carl Hetherington <cth@carlh.net> | 2017-01-11 10:24:22 +0000 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2017-01-11 10:24:22 +0000 |
| commit | 3d236df4bbe1e7e8a8c8c4c467c9b9178ace00f1 (patch) | |
| tree | fe158d7e4323010c3659d94e3f56363e07999be2 /src | |
| parent | becc88e69211c07b1fdcd6572084d43728116ee2 (diff) | |
Forward-port STL binary writer from master, pulling in horizontal position stuff.
Diffstat (limited to 'src')
| -rw-r--r-- | src/raw_subtitle.h | 3 | ||||
| -rw-r--r-- | src/stl_binary_reader.cc | 15 | ||||
| -rw-r--r-- | src/stl_binary_writer.cc | 213 | ||||
| -rw-r--r-- | src/subtitle.cc | 3 | ||||
| -rw-r--r-- | src/subtitle.h | 7 |
5 files changed, 150 insertions, 91 deletions
diff --git a/src/raw_subtitle.h b/src/raw_subtitle.h index 2a202c1..965ca93 100644 --- a/src/raw_subtitle.h +++ b/src/raw_subtitle.h @@ -26,6 +26,7 @@ #include "effect.h" #include "font_size.h" #include "vertical_position.h" +#include "horizontal_position.h" #include <boost/optional.hpp> #include <string> #include <list> @@ -60,6 +61,8 @@ public: bool italic; ///< true to use an italic version of font bool underline; ///< true to underline + HorizontalPosition horizontal_position; + /** vertical position of the baseline of the text */ VerticalPosition vertical_position; diff --git a/src/stl_binary_reader.cc b/src/stl_binary_reader.cc index 8d7befb..0c24a14 100644 --- a/src/stl_binary_reader.cc +++ b/src/stl_binary_reader.cc @@ -110,6 +110,21 @@ STLBinaryReader::STLBinaryReader (istream& in) sub.italic = italic; sub.underline = underline; + /* XXX: not sure what to do with JC = 0, "unchanged presentation" */ + int const h = get_int (14, 1); + switch (h) { + case 0: + case 2: + sub.horizontal_position = CENTRE; + break; + case 1: + sub.horizontal_position = LEFT; + break; + case 3: + sub.horizontal_position = RIGHT; + break; + } + /* Loop over characters */ string text; for (size_t j = 0; j < lines[i].size(); ++j) { diff --git a/src/stl_binary_writer.cc b/src/stl_binary_writer.cc index 9f2057a..7ae7509 100644 --- a/src/stl_binary_writer.cc +++ b/src/stl_binary_writer.cc @@ -43,6 +43,7 @@ using std::setfill; using std::max; using std::cout; using boost::locale::conv::utf_to_utf; +using boost::optional; using namespace sub; /** Arbitrary number which to divide the screen into rows; e.g. @@ -89,6 +90,44 @@ put_int_as_int (char* p, int v, unsigned int n) } } +static int +vertical_position (sub::Line const & line) +{ + int vp = 0; + if (line.vertical_position.proportional) { + switch (line.vertical_position.reference.get_value_or (TOP_OF_SCREEN)) { + case TOP_OF_SCREEN: + vp = rint (line.vertical_position.proportional.get() * ROWS); + break; + case CENTRE_OF_SCREEN: + vp = rint (line.vertical_position.proportional.get() * ROWS + (ROWS / 2.0)); + break; + case BOTTOM_OF_SCREEN: + vp = rint (ROWS - (line.vertical_position.proportional.get() * ROWS)); + break; + default: + break; + } + } else if (line.vertical_position.line) { + float const prop = float (line.vertical_position.line.get()) / line.vertical_position.lines.get (); + switch (line.vertical_position.reference.get_value_or (TOP_OF_SCREEN)) { + case TOP_OF_SCREEN: + vp = prop * ROWS; + break; + case CENTRE_OF_SCREEN: + vp = (prop + 0.5) * ROWS; + break; + case BOTTOM_OF_SCREEN: + vp = (1 - prop) * ROWS; + break; + default: + break; + } + } + + return vp; +} + /** @param language ISO 3-character country code for the language of the subtitles */ void sub::write_stl_binary ( @@ -130,10 +169,9 @@ sub::write_stl_binary ( ofstream output (file_name.string().c_str ()); STLBinaryTables tables; - /* Find the longest subtitle in characters and the number of lines */ + /* Find the longest subtitle in characters */ int longest = 0; - int lines = 0; for (list<Subtitle>::const_iterator i = subtitles.begin(); i != subtitles.end(); ++i) { for (list<Line>::const_iterator j = i->lines.begin(); j != i->lines.end(); ++j) { @@ -142,7 +180,6 @@ sub::write_stl_binary ( t += k->text.size (); } longest = max (longest, t); - ++lines; } } @@ -167,9 +204,9 @@ sub::write_stl_binary ( put_string (buffer + 230, revision_date); put_int_as_string (buffer + 236, revision_number, 2); /* TTI blocks */ - put_int_as_string (buffer + 238, lines, 5); + put_int_as_string (buffer + 238, subtitles.size(), 5); /* Total number of subtitles */ - put_int_as_string (buffer + 243, lines, 5); + put_int_as_string (buffer + 243, subtitles.size(), 5); /* Total number of subtitle groups */ put_string (buffer + 248, "001"); /* Maximum number of displayable characters in any text row */ @@ -194,74 +231,76 @@ sub::write_stl_binary ( output.write (buffer, 1024); for (list<Subtitle>::const_iterator i = subtitles.begin(); i != subtitles.end(); ++i) { - int N = 0; + + /* Find the top vertical position of this subtitle */ + optional<int> top; for (list<Line>::const_iterator j = i->lines.begin(); j != i->lines.end(); ++j) { + int const vp = vertical_position (*j); + if (!top || vp < top.get ()) { + top = vp; + } + } - memset (buffer, 0, 1024); - - /* Subtitle group number */ - put_int_as_int (buffer + 0, 1, 1); - /* Subtitle number */ - put_int_as_int (buffer + 1, N, 2); - /* Extension block number. Use 0xff here to indicate that it is the last TTI - block in this subtitle "set", as we only ever use one. - */ - put_int_as_int (buffer + 3, 255, 1); - /* Cumulative status */ - put_int_as_int (buffer + 4, tables.cumulative_status_enum_to_file (CUMULATIVE_STATUS_NOT_CUMULATIVE), 1); - /* Time code in */ - put_int_as_int (buffer + 5, i->from.hours (), 1); - put_int_as_int (buffer + 6, i->from.minutes (), 1); - put_int_as_int (buffer + 7, i->from.seconds (), 1); - put_int_as_int (buffer + 8, i->from.frames_at (sub::Rational (frames_per_second * 1000, 1000)), 1); - /* Time code out */ - put_int_as_int (buffer + 9, i->to.hours (), 1); - put_int_as_int (buffer + 10, i->to.minutes (), 1); - put_int_as_int (buffer + 11, i->to.seconds (), 1); - put_int_as_int (buffer + 12, i->to.frames_at (sub::Rational (frames_per_second * 1000, 1000)), 1); - /* Vertical position */ - int vp = 0; - if (j->vertical_position.proportional) { - switch (j->vertical_position.reference.get_value_or (TOP_OF_SCREEN)) { - case TOP_OF_SCREEN: - vp = rint (j->vertical_position.proportional.get() * ROWS); - break; - case CENTRE_OF_SCREEN: - vp = rint (j->vertical_position.proportional.get() * ROWS + (ROWS / 2.0)); - break; - case BOTTOM_OF_SCREEN: - vp = rint (ROWS - (j->vertical_position.proportional.get() * ROWS)); - break; - default: - break; - } - } else if (j->vertical_position.line) { - float const prop = float (j->vertical_position.line.get()) / j->vertical_position.lines.get (); - switch (j->vertical_position.reference.get_value_or (TOP_OF_SCREEN)) { - case TOP_OF_SCREEN: - vp = prop * ROWS; - break; - case CENTRE_OF_SCREEN: - vp = (prop + 0.5) * ROWS; - break; - case BOTTOM_OF_SCREEN: - vp = (1 - prop) * ROWS; - break; - default: - break; + memset (buffer, 0, 1024); + + /* Subtitle group number */ + put_int_as_int (buffer + 0, 1, 1); + /* Subtitle number */ + put_int_as_int (buffer + 1, 0, 2); + /* Extension block number. Use 0xff here to indicate that it is the last TTI + block in this subtitle "set", as we only ever use one. + */ + put_int_as_int (buffer + 3, 255, 1); + /* Cumulative status */ + put_int_as_int (buffer + 4, tables.cumulative_status_enum_to_file (CUMULATIVE_STATUS_NOT_CUMULATIVE), 1); + /* Time code in */ + put_int_as_int (buffer + 5, i->from.hours(), 1); + put_int_as_int (buffer + 6, i->from.minutes(), 1); + put_int_as_int (buffer + 7, i->from.seconds(), 1); + put_int_as_int (buffer + 8, i->from.frames_at(sub::Rational (frames_per_second * 1000, 1000)), 1); + /* Time code out */ + put_int_as_int (buffer + 9, i->to.hours(), 1); + put_int_as_int (buffer + 10, i->to.minutes(), 1); + put_int_as_int (buffer + 11, i->to.seconds(), 1); + put_int_as_int (buffer + 12, i->to.frames_at(sub::Rational (frames_per_second * 1000, 1000)), 1); + /* Vertical position */ + put_int_as_int (buffer + 13, top.get(), 1); + + /* Justification code */ + /* XXX: this assumes the first line has the right value */ + switch (i->lines.front().horizontal_position) { + case LEFT: + put_int_as_int (buffer + 14, tables.justification_enum_to_file (JUSTIFICATION_LEFT), 1); + break; + case CENTRE: + put_int_as_int (buffer + 14, tables.justification_enum_to_file (JUSTIFICATION_CENTRE), 1); + break; + case RIGHT: + put_int_as_int (buffer + 14, tables.justification_enum_to_file (JUSTIFICATION_RIGHT), 1); + break; + } + + /* Comment flag */ + put_int_as_int (buffer + 15, tables.comment_enum_to_file (COMMENT_NO), 1); + + /* Text */ + string text; + bool italic = false; + bool underline = false; + optional<int> last_vp; + + for (list<Line>::const_iterator j = i->lines.begin(); j != i->lines.end(); ++j) { + + /* CR/LF down to this line */ + int const vp = vertical_position (*j); + + if (last_vp) { + for (int i = last_vp.get(); i < vp; ++i) { + text += "\x8A"; } } - put_int_as_int (buffer + 13, vp, 1); - /* Justification code */ - /* XXX */ - put_int_as_int (buffer + 14, tables.justification_enum_to_file (JUSTIFICATION_NONE), 1); - /* Comment flag */ - put_int_as_int (buffer + 15, tables.comment_enum_to_file (COMMENT_NO), 1); - - /* Text */ - string text; - bool italic = false; - bool underline = false; + + last_vp = vp; for (list<Block>::const_iterator k = j->blocks.begin(); k != j->blocks.end(); ++k) { if (k->underline && !underline) { @@ -281,32 +320,28 @@ sub::write_stl_binary ( text += utf16_to_iso6937 (utf_to_utf<wchar_t> (k->text)); } + } - /* Turn italic/underline off before the end of this subtitle */ - - if (underline) { - text += "\x83"; - } - - if (italic) { - text += "\x81"; - } - - text += "\x8A"; + /* Turn italic/underline off before the end of this subtitle */ - if (text.length() > 111) { - text = text.substr (111); - } + if (underline) { + text += "\x83"; + } - while (text.length() < 112) { - text += "\x8F"; - } + if (italic) { + text += "\x81"; + } - put_string (buffer + 16, text); - output.write (buffer, 128); + if (text.length() > 111) { + text = text.substr (111); + } - ++N; + while (text.length() < 112) { + text += "\x8F"; } + + put_string (buffer + 16, text); + output.write (buffer, 128); } delete[] buffer; diff --git a/src/subtitle.cc b/src/subtitle.cc index 663c161..c146480 100644 --- a/src/subtitle.cc +++ b/src/subtitle.cc @@ -37,7 +37,8 @@ Subtitle::same_metadata (RawSubtitle s) const } Line::Line (RawSubtitle s) - : vertical_position (s.vertical_position) + : horizontal_position (s.horizontal_position) + , vertical_position (s.vertical_position) { blocks.push_back (Block (s)); } diff --git a/src/subtitle.h b/src/subtitle.h index 2d22dac..af9ac33 100644 --- a/src/subtitle.h +++ b/src/subtitle.h @@ -25,6 +25,7 @@ #include "effect.h" #include "font_size.h" #include "vertical_position.h" +#include "horizontal_position.h" #include "raw_subtitle.h" #include <boost/optional.hpp> #include <string> @@ -74,11 +75,15 @@ public: class Line { public: - Line () {} + Line () + : horizontal_position (CENTRE) + {} /** Construct a Line taking any relevant information from a RawSubtitle */ Line (RawSubtitle s); + HorizontalPosition horizontal_position; + /** vertical position of the baseline of the text */ VerticalPosition vertical_position; |
