Fixes for separate L/R eye content.
[dcpomatic.git] / src / lib / subtitle_decoder.cc
index d210c578fd712a16517d680b952efe7f4dfc124e..b31b4873ff1a5ef756d26edb0121f38db03d9b09 100644 (file)
@@ -29,6 +29,7 @@
 using std::list;
 using std::cout;
 using std::string;
+using std::min;
 using boost::shared_ptr;
 using boost::optional;
 using boost::function;
@@ -131,6 +132,12 @@ SubtitleDecoder::get_image (ContentTimePeriod period, bool starting, bool accura
 
 void
 SubtitleDecoder::seek (ContentTime, bool)
+{
+       reset ();
+}
+
+void
+SubtitleDecoder::reset ()
 {
        _decoded_text.clear ();
        _decoded_image.clear ();
@@ -141,9 +148,26 @@ SubtitleDecoder::give_text (ContentTimePeriod period, sub::Subtitle const & subt
 {
        /* See if our next subtitle needs to be placed on screen by us */
        bool needs_placement = false;
+       optional<int> bottom_line;
        BOOST_FOREACH (sub::Line i, subtitle.lines) {
                if (!i.vertical_position.reference || i.vertical_position.reference.get() == sub::TOP_OF_SUBTITLE) {
                        needs_placement = true;
+                       DCPOMATIC_ASSERT (i.vertical_position.line);
+                       if (!bottom_line || bottom_line.get() < i.vertical_position.line.get()) {
+                               bottom_line = i.vertical_position.line.get();
+                       }
+               }
+       }
+
+       /* Find the lowest proportional postion */
+       optional<float> lowest_proportional;
+       BOOST_FOREACH (sub::Line i, subtitle.lines) {
+               if (i.vertical_position.proportional) {
+                       if (!lowest_proportional) {
+                               lowest_proportional = i.vertical_position.proportional;
+                       } else {
+                               lowest_proportional = min (lowest_proportional.get(), i.vertical_position.proportional.get());
+                       }
                }
        }
 
@@ -160,15 +184,24 @@ SubtitleDecoder::give_text (ContentTimePeriod period, sub::Subtitle const & subt
                        dcp::VAlign v_align;
                        if (needs_placement) {
                                DCPOMATIC_ASSERT (i.vertical_position.line);
-                               /* This 0.053 is an arbitrary value to lift the bottom sub off the bottom
+                               /* This 1.015 is an arbitrary value to lift the bottom sub off the bottom
                                   of the screen a bit to a pleasing degree.
                                */
-                               v_position = 0.053 + i.vertical_position.line.get() * 1.2 * j.font_size.proportional (72 * 11);
-                               v_align = dcp::VALIGN_BOTTOM;
+                               v_position = 1.015 -
+                                       (1 + bottom_line.get() - i.vertical_position.line.get())
+                                       * 1.2 * content()->line_spacing() * content()->y_scale() * j.font_size.proportional (72 * 11);
+
+                               v_align = dcp::VALIGN_TOP;
                        } else {
                                DCPOMATIC_ASSERT (i.vertical_position.proportional);
                                DCPOMATIC_ASSERT (i.vertical_position.reference);
                                v_position = i.vertical_position.proportional.get();
+
+                               if (lowest_proportional) {
+                                       /* Adjust line spacing */
+                                       v_position = ((v_position - lowest_proportional.get()) * content()->line_spacing()) + lowest_proportional.get();
+                               }
+
                                switch (i.vertical_position.reference.get()) {
                                case sub::TOP_OF_SCREEN:
                                        v_align = dcp::VALIGN_TOP;
@@ -185,11 +218,19 @@ SubtitleDecoder::give_text (ContentTimePeriod period, sub::Subtitle const & subt
                                }
                        }
 
+                       dcp::Effect effect = dcp::NONE;
+                       if (content()->outline()) {
+                               effect = dcp::BORDER;
+                       } else if (content()->shadow()) {
+                               effect = dcp::SHADOW;
+                       }
+
                        out.push_back (
                                dcp::SubtitleString (
                                        string(TEXT_FONT_ID),
                                        j.italic,
                                        j.bold,
+                                       j.underline,
                                        /* force the colour to whatever is configured */
                                        content()->colour(),
                                        j.font_size.points (72 * 11),
@@ -202,8 +243,8 @@ SubtitleDecoder::give_text (ContentTimePeriod period, sub::Subtitle const & subt
                                        v_align,
                                        dcp::DIRECTION_LTR,
                                        j.text,
-                                       content()->outline() ? dcp::BORDER : dcp::NONE,
-                                       content()->outline_colour(),
+                                       effect,
+                                       content()->effect_colour(),
                                        dcp::Time (0, 1000),
                                        dcp::Time (0, 1000)
                                        )