Allow separate X and Y scale for subtitles.
authorCarl Hetherington <cth@carlh.net>
Fri, 12 Sep 2014 21:45:24 +0000 (22:45 +0100)
committerCarl Hetherington <cth@carlh.net>
Fri, 12 Sep 2014 21:45:24 +0000 (22:45 +0100)
ChangeLog
src/lib/film.cc
src/lib/player.cc
src/lib/subtitle.cc
src/lib/subtitle_content.cc
src/lib/subtitle_content.h
src/wx/subtitle_panel.cc
src/wx/subtitle_panel.h

index 32099c35854b7a25b935d833f097dbb3ec63c318..6803d355c81ec0c61565ce70307403746de54eb0 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2014-09-12  Carl Hetherington  <cth@carlh.net>
+
+       * Allow separate X and Y scale for subtitles (#337).
+
 2014-09-10  Carl Hetherington  <cth@carlh.net>
 
        * Allow DCP names to be created using the ISDCF template and then
index b4d12a062949ffe4a3ca2e49daed3c76a14b60bb..54503ef72c6c7bf5b8c21184fd736d5ba7d949cf 100644 (file)
@@ -91,9 +91,11 @@ using libdcp::raw_convert;
  * 7 -> 8
  * Use <Scale> tag in <VideoContent> rather than <Ratio>.
  * 8 -> 9
- * DCI -> ISDCF
+ * DCI -> ISDCF.
+ * 9 -> 10
+ * Subtitle X and Y scale.
  */
-int const Film::current_state_version = 9;
+int const Film::current_state_version = 10;
 
 /** Construct a Film object in a given directory.
  *
index 2d2977606786097f6b827ec07a8048dd7c90da59..8063d1212971afe2e9bf682a84d253361b902bac 100644 (file)
@@ -497,7 +497,8 @@ Player::content_changed (weak_ptr<Content> w, int property, bool frequent)
        } else if (
                property == SubtitleContentProperty::SUBTITLE_X_OFFSET ||
                property == SubtitleContentProperty::SUBTITLE_Y_OFFSET ||
-               property == SubtitleContentProperty::SUBTITLE_SCALE
+               property == SubtitleContentProperty::SUBTITLE_X_SCALE ||
+               property == SubtitleContentProperty::SUBTITLE_Y_SCALE
                ) {
 
                for (list<Subtitle>::iterator i = _subtitles.begin(); i != _subtitles.end(); ++i) {
index 0d18861c455f69f2d2649730f93d898d0ed66463..03d4ccf2fa5ea57e07311975aa5309ef0dc5751f 100644 (file)
@@ -60,9 +60,9 @@ Subtitle::update (shared_ptr<const Film> film, libdcp::Size video_container_size
        in_rect.x += sc->subtitle_x_offset ();
        in_rect.y += sc->subtitle_y_offset ();
 
-       /* We will scale the subtitle up to fit _video_container_size, and also by the additional subtitle_scale */
-       scaled_size.width = in_rect.width * video_container_size.width * sc->subtitle_scale ();
-       scaled_size.height = in_rect.height * video_container_size.height * sc->subtitle_scale ();
+       /* We will scale the subtitle up to fit _video_container_size, and also by the additional subtitle scale */
+       scaled_size.width = in_rect.width * video_container_size.width * sc->subtitle_x_scale ();
+       scaled_size.height = in_rect.height * video_container_size.height * sc->subtitle_y_scale ();
 
        /* Then we need a corrective translation, consisting of two parts:
         *
@@ -70,14 +70,14 @@ Subtitle::update (shared_ptr<const Film> film, libdcp::Size video_container_size
         *     rect.x * _video_container_size.width and rect.y * _video_container_size.height.
         *
         * 2.  that to shift the origin of the scale by subtitle_scale to the centre of the subtitle; this will be
-        *     (width_before_subtitle_scale * (1 - subtitle_scale) / 2) and
-        *     (height_before_subtitle_scale * (1 - subtitle_scale) / 2).
+        *     (width_before_subtitle_scale * (1 - subtitle_x_scale) / 2) and
+        *     (height_before_subtitle_scale * (1 - subtitle_y_scale) / 2).
         *
         * Combining these two translations gives these expressions.
         */
        
-       _out_position.x = rint (video_container_size.width * (in_rect.x + (in_rect.width * (1 - sc->subtitle_scale ()) / 2)));
-       _out_position.y = rint (video_container_size.height * (in_rect.y + (in_rect.height * (1 - sc->subtitle_scale ()) / 2)));
+       _out_position.x = rint (video_container_size.width * (in_rect.x + (in_rect.width * (1 - sc->subtitle_x_scale ()) / 2)));
+       _out_position.y = rint (video_container_size.height * (in_rect.y + (in_rect.height * (1 - sc->subtitle_y_scale ()) / 2)));
        
        _out_image = _in_image->scale (
                scaled_size,
index 0abb7d491ec57ffff13e2d483fc67e282fd473fb..3702eef4152c484ee3b044804ebdc86aabdaae91 100644 (file)
@@ -33,13 +33,15 @@ using libdcp::raw_convert;
 
 int const SubtitleContentProperty::SUBTITLE_X_OFFSET = 500;
 int const SubtitleContentProperty::SUBTITLE_Y_OFFSET = 501;
-int const SubtitleContentProperty::SUBTITLE_SCALE = 502;
+int const SubtitleContentProperty::SUBTITLE_X_SCALE = 502;
+int const SubtitleContentProperty::SUBTITLE_Y_SCALE = 503;
 
 SubtitleContent::SubtitleContent (shared_ptr<const Film> f, boost::filesystem::path p)
        : Content (f, p)
        , _subtitle_x_offset (0)
        , _subtitle_y_offset (0)
-       , _subtitle_scale (1)
+       , _subtitle_x_scale (1)
+       , _subtitle_y_scale (1)
 {
 
 }
@@ -48,7 +50,8 @@ SubtitleContent::SubtitleContent (shared_ptr<const Film> f, shared_ptr<const cxm
        : Content (f, node)
        , _subtitle_x_offset (0)
        , _subtitle_y_offset (0)
-       , _subtitle_scale (1)
+       , _subtitle_x_scale (1)
+       , _subtitle_y_scale (1)
 {
        if (version >= 7) {
                _subtitle_x_offset = node->number_child<float> ("SubtitleXOffset");
@@ -56,8 +59,13 @@ SubtitleContent::SubtitleContent (shared_ptr<const Film> f, shared_ptr<const cxm
        } else {
                _subtitle_y_offset = node->number_child<float> ("SubtitleOffset");
        }
-       
-       _subtitle_scale = node->number_child<float> ("SubtitleScale");
+
+       if (version >= 10) {
+               _subtitle_x_scale = node->number_child<float> ("SubtitleXScale");
+               _subtitle_y_scale = node->number_child<float> ("SubtitleYScale");
+       } else {
+               _subtitle_x_scale = _subtitle_y_scale = node->number_child<float> ("SubtitleScale");
+       }
 }
 
 SubtitleContent::SubtitleContent (shared_ptr<const Film> f, vector<shared_ptr<Content> > c)
@@ -77,14 +85,19 @@ SubtitleContent::SubtitleContent (shared_ptr<const Film> f, vector<shared_ptr<Co
                        throw JoinError (_("Content to be joined must have the same subtitle Y offset."));
                }
 
-               if (sc->subtitle_scale() != ref->subtitle_scale()) {
-                       throw JoinError (_("Content to be joined must have the same subtitle scale."));
+               if (sc->subtitle_x_scale() != ref->subtitle_x_scale()) {
+                       throw JoinError (_("Content to be joined must have the same subtitle X scale."));
+               }
+
+               if (sc->subtitle_y_scale() != ref->subtitle_y_scale()) {
+                       throw JoinError (_("Content to be joined must have the same subtitle Y scale."));
                }
        }
 
        _subtitle_x_offset = ref->subtitle_x_offset ();
        _subtitle_y_offset = ref->subtitle_y_offset ();
-       _subtitle_scale = ref->subtitle_scale ();
+       _subtitle_x_scale = ref->subtitle_x_scale ();
+       _subtitle_y_scale = ref->subtitle_y_scale ();
 }
 
 void
@@ -92,7 +105,8 @@ SubtitleContent::as_xml (xmlpp::Node* root) const
 {
        root->add_child("SubtitleXOffset")->add_child_text (raw_convert<string> (_subtitle_x_offset));
        root->add_child("SubtitleYOffset")->add_child_text (raw_convert<string> (_subtitle_y_offset));
-       root->add_child("SubtitleScale")->add_child_text (raw_convert<string> (_subtitle_scale));
+       root->add_child("SubtitleXScale")->add_child_text (raw_convert<string> (_subtitle_x_scale));
+       root->add_child("SubtitleYScale")->add_child_text (raw_convert<string> (_subtitle_y_scale));
 }
 
 void
@@ -116,11 +130,21 @@ SubtitleContent::set_subtitle_y_offset (double o)
 }
 
 void
-SubtitleContent::set_subtitle_scale (double s)
+SubtitleContent::set_subtitle_x_scale (double s)
+{
+       {
+               boost::mutex::scoped_lock lm (_mutex);
+               _subtitle_x_scale = s;
+       }
+       signal_changed (SubtitleContentProperty::SUBTITLE_X_SCALE);
+}
+
+void
+SubtitleContent::set_subtitle_y_scale (double s)
 {
        {
                boost::mutex::scoped_lock lm (_mutex);
-               _subtitle_scale = s;
+               _subtitle_y_scale = s;
        }
-       signal_changed (SubtitleContentProperty::SUBTITLE_SCALE);
+       signal_changed (SubtitleContentProperty::SUBTITLE_Y_SCALE);
 }
index 38863768889adb1cbea41dd019afc6fad1517ea0..329368e4432f92ddd698e4f294d8128474bbbbf2 100644 (file)
@@ -27,7 +27,8 @@ class SubtitleContentProperty
 public:
        static int const SUBTITLE_X_OFFSET;
        static int const SUBTITLE_Y_OFFSET;
-       static int const SUBTITLE_SCALE;
+       static int const SUBTITLE_X_SCALE;
+       static int const SUBTITLE_Y_SCALE;
 };
 
 class SubtitleContent : public virtual Content
@@ -41,7 +42,8 @@ public:
 
        void set_subtitle_x_offset (double);
        void set_subtitle_y_offset (double);
-       void set_subtitle_scale (double);
+       void set_subtitle_x_scale (double);
+       void set_subtitle_y_scale (double);
 
        double subtitle_x_offset () const {
                boost::mutex::scoped_lock lm (_mutex);
@@ -53,9 +55,14 @@ public:
                return _subtitle_y_offset;
        }
 
-       double subtitle_scale () const {
+       double subtitle_x_scale () const {
                boost::mutex::scoped_lock lm (_mutex);
-               return _subtitle_scale;
+               return _subtitle_x_scale;
+       }
+
+       double subtitle_y_scale () const {
+               boost::mutex::scoped_lock lm (_mutex);
+               return _subtitle_y_scale;
        }
        
 private:
@@ -69,8 +76,10 @@ private:
         *  +ve is further down the frame, -ve is further up.
         */
        double _subtitle_y_offset;
-       /** scale factor to apply to subtitles */
-       double _subtitle_scale;
+       /** x scale factor to apply to subtitles */
+       double _subtitle_x_scale;
+       /** y scale factor to apply to subtitles */
+       double _subtitle_y_scale;
 };
 
 #endif
index 6470f657d24477ef8e0ec5ef166f7498434defde..7953682fca6fd25f857062b31fee4885a241fdfd 100644 (file)
@@ -59,27 +59,37 @@ SubtitlePanel::SubtitlePanel (FilmEditor* e)
        }
        
        {
-               add_label_to_sizer (grid, this, _("Scale"), true);
+               add_label_to_sizer (grid, this, _("Scale"), true);
                wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
-               _scale = new wxSpinCtrl (this);
-               s->Add (_scale);
+               _x_scale = new wxSpinCtrl (this);
+               s->Add (_x_scale);
                add_label_to_sizer (s, this, _("%"), false);
                grid->Add (s);
        }
 
+       {
+               add_label_to_sizer (grid, this, _("Y Scale"), true);
+               wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
+               _y_scale = new wxSpinCtrl (this);
+               s->Add (_y_scale);
+               add_label_to_sizer (s, this, _("%"), false);
+               grid->Add (s);
+       }
+       
        add_label_to_sizer (grid, this, _("Stream"), true);
        _stream = new wxChoice (this, wxID_ANY);
        grid->Add (_stream, 1, wxEXPAND);
        
        _x_offset->SetRange (-100, 100);
        _y_offset->SetRange (-100, 100);
-       _scale->SetRange (1, 1000);
-       _scale->SetValue (100);
+       _x_scale->SetRange (10, 1000);
+       _y_scale->SetRange (10, 1000);
 
        _with_subtitles->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&SubtitlePanel::with_subtitles_toggled, this));
        _x_offset->Bind       (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&SubtitlePanel::x_offset_changed, this));
        _y_offset->Bind       (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&SubtitlePanel::y_offset_changed, this));
-       _scale->Bind          (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&SubtitlePanel::scale_changed, this));
+       _x_scale->Bind        (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&SubtitlePanel::x_scale_changed, this));
+       _y_scale->Bind        (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&SubtitlePanel::y_scale_changed, this));
        _stream->Bind         (wxEVT_COMMAND_CHOICE_SELECTED,  boost::bind (&SubtitlePanel::stream_changed, this));
 }
 
@@ -134,8 +144,10 @@ SubtitlePanel::film_content_changed (int property)
                checked_set (_x_offset, scs ? (scs->subtitle_x_offset() * 100) : 0);
        } else if (property == SubtitleContentProperty::SUBTITLE_Y_OFFSET) {
                checked_set (_y_offset, scs ? (scs->subtitle_y_offset() * 100) : 0);
-       } else if (property == SubtitleContentProperty::SUBTITLE_SCALE) {
-               checked_set (_scale, scs ? (scs->subtitle_scale() * 100) : 100);
+       } else if (property == SubtitleContentProperty::SUBTITLE_X_SCALE) {
+               checked_set (_x_scale, scs ? int (rint (scs->subtitle_x_scale() * 100)) : 100);
+       } else if (property == SubtitleContentProperty::SUBTITLE_Y_SCALE) {
+               checked_set (_y_scale, scs ? int (rint (scs->subtitle_y_scale() * 100)) : 100);
        }
 }
 
@@ -162,7 +174,8 @@ SubtitlePanel::setup_sensitivity ()
        _with_subtitles->Enable (h);
        _x_offset->Enable (j);
        _y_offset->Enable (j);
-       _scale->Enable (j);
+       _x_scale->Enable (j);
+       _y_scale->Enable (j);
        _stream->Enable (j);
 }
 
@@ -207,11 +220,20 @@ SubtitlePanel::y_offset_changed ()
 }
 
 void
-SubtitlePanel::scale_changed ()
+SubtitlePanel::x_scale_changed ()
+{
+       SubtitleContentList c = _editor->selected_subtitle_content ();
+       if (c.size() == 1) {
+               c.front()->set_subtitle_x_scale (_x_scale->GetValue() / 100.0);
+       }
+}
+
+void
+SubtitlePanel::y_scale_changed ()
 {
        SubtitleContentList c = _editor->selected_subtitle_content ();
        if (c.size() == 1) {
-               c.front()->set_subtitle_scale (_scale->GetValue() / 100.0);
+               c.front()->set_subtitle_y_scale (_y_scale->GetValue() / 100.0);
        }
 }
 
@@ -221,5 +243,6 @@ SubtitlePanel::content_selection_changed ()
        film_content_changed (FFmpegContentProperty::SUBTITLE_STREAMS);
        film_content_changed (SubtitleContentProperty::SUBTITLE_X_OFFSET);
        film_content_changed (SubtitleContentProperty::SUBTITLE_Y_OFFSET);
-       film_content_changed (SubtitleContentProperty::SUBTITLE_SCALE);
+       film_content_changed (SubtitleContentProperty::SUBTITLE_X_SCALE);
+       film_content_changed (SubtitleContentProperty::SUBTITLE_Y_SCALE);
 }
index 20d7c40c2eb1d3eb1add4350a1b1482b3cbfc2a1..7f5d9239d1d477fbad194b2ab6a2a34618466633 100644 (file)
@@ -35,7 +35,8 @@ private:
        void with_subtitles_toggled ();
        void x_offset_changed ();
        void y_offset_changed ();
-       void scale_changed ();
+       void x_scale_changed ();
+       void y_scale_changed ();
        void stream_changed ();
 
        void setup_sensitivity ();
@@ -43,6 +44,7 @@ private:
        wxCheckBox* _with_subtitles;
        wxSpinCtrl* _x_offset;
        wxSpinCtrl* _y_offset;
-       wxSpinCtrl* _scale;
+       wxSpinCtrl* _x_scale;
+       wxSpinCtrl* _y_scale;
        wxChoice* _stream;
 };