Support shadow in subtitles (#911).
authorCarl Hetherington <cth@carlh.net>
Fri, 8 Jul 2016 00:30:39 +0000 (01:30 +0100)
committerCarl Hetherington <cth@carlh.net>
Fri, 8 Jul 2016 00:48:50 +0000 (01:48 +0100)
ChangeLog
src/lib/film.cc
src/lib/player.cc
src/lib/subtitle_content.cc
src/lib/subtitle_content.h
src/lib/subtitle_decoder.cc
src/wx/text_subtitle_appearance_dialog.cc
src/wx/text_subtitle_appearance_dialog.h

index 4a28623fa378fc84e843dc9cebcd7bf3160d0f04..55be07de3212d01a4dbbe59b4a7e9b32da25b5ab 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,7 @@
 2016-07-08  Carl Hetherington  <cth@carlh.net>
 
+       * Support shadow in subtitles (#911).
+
        * Version 2.9.0 released.
 
 2016-07-07  Carl Hetherington  <cth@carlh.net>
index 3cd3f0f21e7ec5c4e9546569b142a8b21155740b..313170c21ba8d6ae1e2a0edc025e15504a493f7f 100644 (file)
@@ -114,8 +114,10 @@ using boost::is_any_of;
  * are present.
  * 34 -> 35
  * VideoFrameType in VideoContent is a string rather than an integer.
+ * 35 -> 36
+ * EffectColour rather than OutlineColour in Subtitle.
  */
-int const Film::current_state_version = 35;
+int const Film::current_state_version = 36;
 
 /** Construct a Film object in a given directory.
  *
index f8bfb527beb48b63c1494c194c6877053cd3a817..db62cbcc8dec6f417b05558f25724353324c7563 100644 (file)
@@ -172,7 +172,8 @@ Player::playlist_content_changed (weak_ptr<Content> w, int property, bool freque
                property == DCPContentProperty::CAN_BE_PLAYED ||
                property == SubtitleContentProperty::COLOUR ||
                property == SubtitleContentProperty::OUTLINE ||
-               property == SubtitleContentProperty::OUTLINE_COLOUR ||
+               property == SubtitleContentProperty::SHADOW ||
+               property == SubtitleContentProperty::EFFECT_COLOUR ||
                property == FFmpegContentProperty::SUBTITLE_STREAM ||
                property == VideoContentProperty::COLOUR_CONVERSION
                ) {
index fcc825026da8d69ebb6ac3829d83f262b27253ac..2376aac6898a286e42ebc44b9815ba326acc7b70 100644 (file)
@@ -49,8 +49,9 @@ int const SubtitleContentProperty::LANGUAGE = 506;
 int const SubtitleContentProperty::FONTS = 507;
 int const SubtitleContentProperty::COLOUR = 508;
 int const SubtitleContentProperty::OUTLINE = 509;
-int const SubtitleContentProperty::OUTLINE_COLOUR = 510;
-int const SubtitleContentProperty::LINE_SPACING = 511;
+int const SubtitleContentProperty::SHADOW = 510;
+int const SubtitleContentProperty::EFFECT_COLOUR = 511;
+int const SubtitleContentProperty::LINE_SPACING = 512;
 
 SubtitleContent::SubtitleContent (Content* parent)
        : ContentPart (parent)
@@ -62,7 +63,8 @@ SubtitleContent::SubtitleContent (Content* parent)
        , _y_scale (1)
        , _colour (255, 255, 255)
        , _outline (false)
-       , _outline_colour (0, 0, 0)
+       , _shadow (false)
+       , _effect_colour (0, 0, 0)
        , _line_spacing (1)
 {
 
@@ -103,11 +105,7 @@ SubtitleContent::SubtitleContent (Content* parent, cxml::ConstNodePtr node, int
                node->optional_number_child<int>("Blue").get_value_or(255)
                )
        , _outline (node->optional_bool_child("Outline").get_value_or(false))
-       , _outline_colour (
-               node->optional_number_child<int>("OutlineRed").get_value_or(255),
-               node->optional_number_child<int>("OutlineGreen").get_value_or(255),
-               node->optional_number_child<int>("OutlineBlue").get_value_or(255)
-               )
+       , _shadow (node->optional_bool_child("Shadow").get_value_or(false))
        , _line_spacing (node->optional_number_child<double>("LineSpacing").get_value_or (1))
 {
        if (version >= 32) {
@@ -129,6 +127,20 @@ SubtitleContent::SubtitleContent (Content* parent, cxml::ConstNodePtr node, int
                _x_scale = _y_scale = node->number_child<double> ("SubtitleScale");
        }
 
+       if (version >= 36) {
+               _effect_colour = dcp::Colour (
+                       node->optional_number_child<int>("EffectRed").get_value_or(255),
+                       node->optional_number_child<int>("EffectGreen").get_value_or(255),
+                       node->optional_number_child<int>("EffectBlue").get_value_or(255)
+                       );
+       } else {
+               _effect_colour = dcp::Colour (
+                       node->optional_number_child<int>("OutlineRed").get_value_or(255),
+                       node->optional_number_child<int>("OutlineGreen").get_value_or(255),
+                       node->optional_number_child<int>("OutlineBlue").get_value_or(255)
+                       );
+       }
+
        _language = node->optional_string_child ("SubtitleLanguage").get_value_or ("");
 
        list<cxml::NodePtr> fonts = node->node_children ("Font");
@@ -223,9 +235,10 @@ SubtitleContent::as_xml (xmlpp::Node* root) const
        root->add_child("Green")->add_child_text (raw_convert<string> (_colour.g));
        root->add_child("Blue")->add_child_text (raw_convert<string> (_colour.b));
        root->add_child("Outline")->add_child_text (raw_convert<string> (_outline));
-       root->add_child("OutlineRed")->add_child_text (raw_convert<string> (_outline_colour.r));
-       root->add_child("OutlineGreen")->add_child_text (raw_convert<string> (_outline_colour.g));
-       root->add_child("OutlineBlue")->add_child_text (raw_convert<string> (_outline_colour.b));
+       root->add_child("Shadow")->add_child_text (raw_convert<string> (_shadow));
+       root->add_child("EffectRed")->add_child_text (raw_convert<string> (_effect_colour.r));
+       root->add_child("EffectGreen")->add_child_text (raw_convert<string> (_effect_colour.g));
+       root->add_child("EffectBlue")->add_child_text (raw_convert<string> (_effect_colour.b));
        root->add_child("LineSpacing")->add_child_text (raw_convert<string> (_line_spacing));
 
        for (list<shared_ptr<Font> >::const_iterator i = _fonts.begin(); i != _fonts.end(); ++i) {
@@ -299,9 +312,15 @@ SubtitleContent::set_outline (bool o)
 }
 
 void
-SubtitleContent::set_outline_colour (dcp::Colour colour)
+SubtitleContent::set_shadow (bool s)
+{
+       maybe_set (_shadow, s, SubtitleContentProperty::SHADOW);
+}
+
+void
+SubtitleContent::set_effect_colour (dcp::Colour colour)
 {
-       maybe_set (_outline_colour, colour, SubtitleContentProperty::OUTLINE_COLOUR);
+       maybe_set (_effect_colour, colour, SubtitleContentProperty::EFFECT_COLOUR);
 }
 
 void
index 6665f563af4a0496ce9826f17dda7fad80b2b9c5..c8492b91a32359c3eea8262cb00a3e32d516ba90 100644 (file)
@@ -41,7 +41,8 @@ public:
        static int const FONTS;
        static int const COLOUR;
        static int const OUTLINE;
-       static int const OUTLINE_COLOUR;
+       static int const SHADOW;
+       static int const EFFECT_COLOUR;
        static int const LINE_SPACING;
 };
 
@@ -124,11 +125,18 @@ public:
                return _outline;
        }
 
-       void set_outline_colour (dcp::Colour);
+       void set_shadow (bool);
 
-       dcp::Colour outline_colour () const {
+       bool shadow () const {
                boost::mutex::scoped_lock lm (_mutex);
-               return _outline_colour;
+               return _shadow;
+       }
+
+       void set_effect_colour (dcp::Colour);
+
+       dcp::Colour effect_colour () const {
+               boost::mutex::scoped_lock lm (_mutex);
+               return _effect_colour;
        }
 
        void set_line_spacing (double s);
@@ -168,7 +176,8 @@ private:
        std::list<boost::shared_ptr<Font> > _fonts;
        dcp::Colour _colour;
        bool _outline;
-       dcp::Colour _outline_colour;
+       bool _shadow;
+       dcp::Colour _effect_colour;
        std::list<boost::signals2::connection> _font_connections;
        /** scaling factor for line spacing; 1 is "standard", < 1 is closer together, > 1 is further apart */
        double _line_spacing;
index 09f7a67004884fa4a006d3b44b037b6b4dd8bf19..b31b4873ff1a5ef756d26edb0121f38db03d9b09 100644 (file)
@@ -218,6 +218,13 @@ 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),
@@ -236,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)
                                        )
index 30402a63f3502e26c1735198fa8663171126a99f..a826cbc6689f0705ab2d932595726bfa5811444e 100644 (file)
@@ -34,20 +34,29 @@ TextSubtitleAppearanceDialog::TextSubtitleAppearanceDialog (wxWindow* parent, sh
        _colour = new wxColourPickerCtrl (this, wxID_ANY);
        add (_colour);
 
-       _outline = new wxCheckBox (this, wxID_ANY, _("Outline"));
+       wxRadioButton* no_effect = new wxRadioButton (this, wxID_ANY, _("No effect"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP);
+       add (no_effect);
+       add_spacer ();
+
+       _outline = new wxRadioButton (this, wxID_ANY, _("Outline"));
        add (_outline);
        add_spacer ();
 
-       add (_("Outline colour"), true);
-       _outline_colour = new wxColourPickerCtrl (this, wxID_ANY);
-       add (_outline_colour);
+       _shadow = new wxRadioButton (this, wxID_ANY, _("Shadow"));
+       add (_shadow);
+       add_spacer ();
+
+       add (_("Outline / shadow colour"), true);
+       _effect_colour = new wxColourPickerCtrl (this, wxID_ANY);
+       add (_effect_colour);
 
        layout ();
 
        _colour->SetColour (wxColour (_content->colour().r, _content->colour().g, _content->colour().b));
        _outline->SetValue (_content->outline ());
-       _outline_colour->SetColour (
-               wxColour (_content->outline_colour().r, _content->outline_colour().g, _content->outline_colour().b)
+       _shadow->SetValue (_content->shadow ());
+       _effect_colour->SetColour (
+               wxColour (_content->effect_colour().r, _content->effect_colour().g, _content->effect_colour().b)
                );
 }
 
@@ -57,6 +66,7 @@ TextSubtitleAppearanceDialog::apply ()
        wxColour const c = _colour->GetColour ();
        _content->set_colour (dcp::Colour (c.Red(), c.Green(), c.Blue()));
        _content->set_outline (_outline->GetValue ());
-       wxColour const oc = _outline_colour->GetColour ();
-       _content->set_outline_colour (dcp::Colour (oc.Red(), oc.Green(), oc.Blue()));
+       _content->set_shadow (_shadow->GetValue ());
+       wxColour const ec = _effect_colour->GetColour ();
+       _content->set_effect_colour (dcp::Colour (ec.Red(), ec.Green(), ec.Blue()));
 }
index feecae543128b90b9f56f2f1e675c0adf2d36201..c67ec8756bafe0d1d55fe8b3154e1d962301a135 100644 (file)
@@ -21,7 +21,7 @@
 #include "table_dialog.h"
 #include <boost/shared_ptr.hpp>
 
-class wxCheckBox;
+class wxRadioButton;
 class wxColourPickerCtrl;
 class SubtitleContent;
 
@@ -34,8 +34,9 @@ public:
 
 private:
        wxColourPickerCtrl* _colour;
-       wxCheckBox* _outline;
-       wxColourPickerCtrl* _outline_colour;
+       wxRadioButton* _outline;
+       wxRadioButton* _shadow;
+       wxColourPickerCtrl* _effect_colour;
 
        boost::shared_ptr<SubtitleContent> _content;
 };