summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2015-11-08 15:00:58 +0000
committerCarl Hetherington <cth@carlh.net>2015-11-08 15:00:58 +0000
commit3b932abd0c7634483911e1d5361e12b2d094ae6f (patch)
treed187652362c0d056222a03538a4812282cda7896 /src
parent7ddba2932f3e577ecde3324a2094037252bdde18 (diff)
Add appearance dialog for SubRip subtitles.
Diffstat (limited to 'src')
-rw-r--r--src/lib/image.cc6
-rw-r--r--src/lib/player.cc5
-rw-r--r--src/lib/subrip_content.cc70
-rw-r--r--src/lib/subrip_content.h33
-rw-r--r--src/lib/subrip_decoder.cc11
-rw-r--r--src/lib/subtitle_decoder.h3
-rw-r--r--src/wx/subtitle_appearance_dialog.cc58
-rw-r--r--src/wx/subtitle_appearance_dialog.h40
-rw-r--r--src/wx/subtitle_panel.cc57
-rw-r--r--src/wx/subtitle_panel.h3
-rw-r--r--src/wx/wscript1
11 files changed, 262 insertions, 25 deletions
diff --git a/src/lib/image.cc b/src/lib/image.cc
index ed029ca2d..6835d0c26 100644
--- a/src/lib/image.cc
+++ b/src/lib/image.cc
@@ -464,10 +464,10 @@ Image::alpha_blend (shared_ptr<const Image> other, Position<int> position)
uint8_t* op = other->data()[0] + oy * other->stride()[0];
for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
float const alpha = float (op[3]) / 255;
- /* Blend high bytes */
- tp[1] = op[0] * alpha + tp[1] * (1 - alpha);
+ /* Blend high bytes; the RGBA in op appears to be BGRA */
+ tp[1] = op[2] * alpha + tp[1] * (1 - alpha);
tp[3] = op[1] * alpha + tp[3] * (1 - alpha);
- tp[5] = op[2] * alpha + tp[5] * (1 - alpha);
+ tp[5] = op[0] * alpha + tp[5] * (1 - alpha);
tp += this_bpp;
op += other_bpp;
diff --git a/src/lib/player.cc b/src/lib/player.cc
index 10e476862..ecf37b576 100644
--- a/src/lib/player.cc
+++ b/src/lib/player.cc
@@ -219,7 +219,10 @@ Player::playlist_content_changed (weak_ptr<Content> w, int property, bool freque
property == ContentProperty::TRIM_END ||
property == ContentProperty::PATH ||
property == VideoContentProperty::VIDEO_FRAME_TYPE ||
- property == DCPContentProperty::CAN_BE_PLAYED
+ property == DCPContentProperty::CAN_BE_PLAYED ||
+ property == SubRipContentProperty::SUBTITLE_COLOUR ||
+ property == SubRipContentProperty::SUBTITLE_OUTLINE ||
+ property == SubRipContentProperty::SUBTITLE_OUTLINE_COLOUR
) {
_have_valid_pieces = false;
diff --git a/src/lib/subrip_content.cc b/src/lib/subrip_content.cc
index 1a7efc117..a6eb07629 100644
--- a/src/lib/subrip_content.cc
+++ b/src/lib/subrip_content.cc
@@ -35,9 +35,16 @@ using boost::lexical_cast;
std::string const SubRipContent::font_id = "font";
+int const SubRipContentProperty::SUBTITLE_COLOUR = 300;
+int const SubRipContentProperty::SUBTITLE_OUTLINE = 301;
+int const SubRipContentProperty::SUBTITLE_OUTLINE_COLOUR = 302;
+
SubRipContent::SubRipContent (shared_ptr<const Film> film, boost::filesystem::path path)
: Content (film, path)
, SubtitleContent (film, path)
+ , _colour (255, 255, 255)
+ , _outline (false)
+ , _outline_colour (0, 0, 0)
{
}
@@ -47,6 +54,17 @@ SubRipContent::SubRipContent (shared_ptr<const Film> film, cxml::ConstNodePtr no
, SubtitleContent (film, node, version)
, _length (node->number_child<ContentTime::Type> ("Length"))
, _frame_rate (node->optional_number_child<double>("SubtitleFrameRate"))
+ , _colour (
+ node->optional_number_child<int>("Red").get_value_or(255),
+ node->optional_number_child<int>("Green").get_value_or(255),
+ 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)
+ )
{
}
@@ -84,6 +102,13 @@ SubRipContent::as_xml (xmlpp::Node* node) const
Content::as_xml (node);
SubtitleContent::as_xml (node);
node->add_child("Length")->add_child_text (raw_convert<string> (_length.get ()));
+ node->add_child("Red")->add_child_text (raw_convert<string> (_colour.r));
+ node->add_child("Green")->add_child_text (raw_convert<string> (_colour.g));
+ node->add_child("Blue")->add_child_text (raw_convert<string> (_colour.b));
+ node->add_child("Outline")->add_child_text (raw_convert<string> (_outline));
+ node->add_child("OutlineRed")->add_child_text (raw_convert<string> (_outline_colour.r));
+ node->add_child("OutlineGreen")->add_child_text (raw_convert<string> (_outline_colour.g));
+ node->add_child("OutlineBlue")->add_child_text (raw_convert<string> (_outline_colour.b));
}
DCPTime
@@ -119,3 +144,48 @@ SubRipContent::subtitle_video_frame_rate () const
*/
return film()->active_frame_rate_change(position()).source;
}
+
+void
+SubRipContent::set_colour (dcp::Colour colour)
+{
+ {
+ boost::mutex::scoped_lock lm (_mutex);
+ if (_colour == colour) {
+ return;
+ }
+
+ _colour = colour;
+ }
+
+ signal_changed (SubRipContentProperty::SUBTITLE_COLOUR);
+}
+
+void
+SubRipContent::set_outline (bool o)
+{
+ {
+ boost::mutex::scoped_lock lm (_mutex);
+ if (_outline == o) {
+ return;
+ }
+
+ _outline = o;
+ }
+
+ signal_changed (SubRipContentProperty::SUBTITLE_OUTLINE);
+}
+
+void
+SubRipContent::set_outline_colour (dcp::Colour colour)
+{
+ {
+ boost::mutex::scoped_lock lm (_mutex);
+ if (_outline_colour == colour) {
+ return;
+ }
+
+ _outline_colour = colour;
+ }
+
+ signal_changed (SubRipContentProperty::SUBTITLE_OUTLINE_COLOUR);
+}
diff --git a/src/lib/subrip_content.h b/src/lib/subrip_content.h
index e05063403..68864f58c 100644
--- a/src/lib/subrip_content.h
+++ b/src/lib/subrip_content.h
@@ -19,6 +19,15 @@
#include "subtitle_content.h"
+class SubRipContentProperty
+{
+public:
+ static int const SUBTITLE_COLOUR;
+ static int const SUBTITLE_OUTLINE;
+ static int const SUBTITLE_OUTLINE_COLOUR;
+};
+
+
class SubRipContent : public SubtitleContent
{
public:
@@ -49,10 +58,34 @@ public:
double subtitle_video_frame_rate () const;
void set_subtitle_video_frame_rate (int r);
+ void set_colour (dcp::Colour);
+
+ dcp::Colour colour () const {
+ boost::mutex::scoped_lock lm (_mutex);
+ return _colour;
+ }
+
+ void set_outline (bool);
+
+ bool outline () const {
+ boost::mutex::scoped_lock lm (_mutex);
+ return _outline;
+ }
+
+ void set_outline_colour (dcp::Colour);
+
+ dcp::Colour outline_colour () const {
+ boost::mutex::scoped_lock lm (_mutex);
+ return _outline_colour;
+ }
+
static std::string const font_id;
private:
ContentTime _length;
/** Video frame rate that this content has been prepared for, if known */
boost::optional<double> _frame_rate;
+ dcp::Colour _colour;
+ bool _outline;
+ dcp::Colour _outline_colour;
};
diff --git a/src/lib/subrip_decoder.cc b/src/lib/subrip_decoder.cc
index 26a7ebcae..0bb543337 100644
--- a/src/lib/subrip_decoder.cc
+++ b/src/lib/subrip_decoder.cc
@@ -28,6 +28,7 @@ using std::string;
using std::cout;
using boost::shared_ptr;
using boost::optional;
+using boost::dynamic_pointer_cast;
SubRipDecoder::SubRipDecoder (shared_ptr<const SubRipContent> content)
: SubtitleDecoder (content)
@@ -57,6 +58,9 @@ SubRipDecoder::pass (PassReason, bool)
/* XXX: we are ignoring positioning specified in the file */
+ shared_ptr<const SubRipContent> content = dynamic_pointer_cast<const SubRipContent> (_subtitle_content);
+ DCPOMATIC_ASSERT (content);
+
list<dcp::SubtitleString> out;
for (list<sub::Line>::const_iterator i = _subtitles[_next].lines.begin(); i != _subtitles[_next].lines.end(); ++i) {
for (list<sub::Block>::const_iterator j = i->blocks.begin(); j != i->blocks.end(); ++j) {
@@ -64,7 +68,8 @@ SubRipDecoder::pass (PassReason, bool)
dcp::SubtitleString (
SubRipContent::font_id,
j->italic,
- dcp::Colour (j->colour.r * 255, j->colour.g * 255, j->colour.b * 255),
+ /* force the colour to whatever is configured */
+ content->colour(),
j->font_size.points (72 * 11),
1.0,
dcp::Time (_subtitles[_next].from.all_as_seconds(), 1000),
@@ -74,8 +79,8 @@ SubRipDecoder::pass (PassReason, bool)
i->vertical_position.line.get() * (1.5 / 22) + 0.8,
dcp::VALIGN_TOP,
j->text,
- dcp::NONE,
- dcp::Colour (255, 255, 255),
+ content->outline() ? dcp::BORDER : dcp::NONE,
+ content->outline_colour(),
dcp::Time (0, 1000),
dcp::Time (0, 1000)
)
diff --git a/src/lib/subtitle_decoder.h b/src/lib/subtitle_decoder.h
index dd9c024e6..ef62d8b88 100644
--- a/src/lib/subtitle_decoder.h
+++ b/src/lib/subtitle_decoder.h
@@ -44,6 +44,7 @@ protected:
std::list<ContentImageSubtitle> _decoded_image_subtitles;
std::list<ContentTextSubtitle> _decoded_text_subtitles;
+ boost::shared_ptr<const SubtitleContent> _subtitle_content;
private:
template <class T>
@@ -54,8 +55,6 @@ private:
*/
virtual std::list<ContentTimePeriod> image_subtitles_during (ContentTimePeriod period, bool starting) const = 0;
virtual std::list<ContentTimePeriod> text_subtitles_during (ContentTimePeriod period, bool starting) const = 0;
-
- boost::shared_ptr<const SubtitleContent> _subtitle_content;
};
#endif
diff --git a/src/wx/subtitle_appearance_dialog.cc b/src/wx/subtitle_appearance_dialog.cc
new file mode 100644
index 000000000..0db55edfe
--- /dev/null
+++ b/src/wx/subtitle_appearance_dialog.cc
@@ -0,0 +1,58 @@
+/*
+ Copyright (C) 2015 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "subtitle_appearance_dialog.h"
+#include "lib/subrip_content.h"
+#include <wx/wx.h>
+#include <wx/clrpicker.h>
+
+using boost::shared_ptr;
+
+SubtitleAppearanceDialog::SubtitleAppearanceDialog (wxWindow* parent, shared_ptr<SubRipContent> content)
+ : TableDialog (parent, _("Subtitle appearance"), 2, 1, true)
+ , _content (content)
+{
+ add (_("Colour"), true);
+ _colour = new wxColourPickerCtrl (this, wxID_ANY);
+ add (_colour);
+
+ _outline = new wxCheckBox (this, wxID_ANY, _("Outline"));
+ add (_outline);
+ add_spacer ();
+
+ add (_("Outline colour"), true);
+ _outline_colour = new wxColourPickerCtrl (this, wxID_ANY);
+ add (_outline_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));
+}
+
+void
+SubtitleAppearanceDialog::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()));
+}
diff --git a/src/wx/subtitle_appearance_dialog.h b/src/wx/subtitle_appearance_dialog.h
new file mode 100644
index 000000000..f4fe307d2
--- /dev/null
+++ b/src/wx/subtitle_appearance_dialog.h
@@ -0,0 +1,40 @@
+/*
+ Copyright (C) 2015 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "table_dialog.h"
+#include <boost/shared_ptr.hpp>
+
+class wxCheckBox;
+class wxColourPickerCtrl;
+class SubRipContent;
+
+class SubtitleAppearanceDialog : public TableDialog
+{
+public:
+ SubtitleAppearanceDialog (wxWindow* parent, boost::shared_ptr<SubRipContent> content);
+
+ void apply ();
+
+private:
+ wxColourPickerCtrl* _colour;
+ wxCheckBox* _outline;
+ wxColourPickerCtrl* _outline_colour;
+
+ boost::shared_ptr<SubRipContent> _content;
+};
diff --git a/src/wx/subtitle_panel.cc b/src/wx/subtitle_panel.cc
index e9de4fccd..74a110349 100644
--- a/src/wx/subtitle_panel.cc
+++ b/src/wx/subtitle_panel.cc
@@ -23,6 +23,7 @@
#include "subtitle_view.h"
#include "content_panel.h"
#include "fonts_dialog.h"
+#include "subtitle_appearance_dialog.h"
#include "lib/ffmpeg_content.h"
#include "lib/subrip_content.h"
#include "lib/ffmpeg_subtitle_stream.h"
@@ -119,6 +120,8 @@ SubtitlePanel::SubtitlePanel (ContentPanel* p)
s->Add (_subtitle_view_button, 1, wxALL, DCPOMATIC_SIZER_GAP);
_fonts_dialog_button = new wxButton (this, wxID_ANY, _("Fonts..."));
s->Add (_fonts_dialog_button, 1, wxALL, DCPOMATIC_SIZER_GAP);
+ _appearance_dialog_button = new wxButton (this, wxID_ANY, _("Appearance..."));
+ s->Add (_appearance_dialog_button, 1, wxALL, DCPOMATIC_SIZER_GAP);
grid->Add (s, wxGBPosition (r, 0), wxGBSpan (1, 2));
++r;
@@ -129,17 +132,18 @@ SubtitlePanel::SubtitlePanel (ContentPanel* p)
_x_scale->SetRange (10, 1000);
_y_scale->SetRange (10, 1000);
- _reference->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&SubtitlePanel::reference_clicked, this));
- _use->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&SubtitlePanel::use_toggled, this));
- _burn->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&SubtitlePanel::burn_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));
- _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));
- _language->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&SubtitlePanel::language_changed, this));
- _stream->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&SubtitlePanel::stream_changed, this));
- _subtitle_view_button->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&SubtitlePanel::subtitle_view_clicked, this));
- _fonts_dialog_button->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&SubtitlePanel::fonts_dialog_clicked, this));
+ _reference->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&SubtitlePanel::reference_clicked, this));
+ _use->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&SubtitlePanel::use_toggled, this));
+ _burn->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&SubtitlePanel::burn_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));
+ _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));
+ _language->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&SubtitlePanel::language_changed, this));
+ _stream->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&SubtitlePanel::stream_changed, this));
+ _subtitle_view_button->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&SubtitlePanel::subtitle_view_clicked, this));
+ _fonts_dialog_button->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&SubtitlePanel::fonts_dialog_clicked, this));
+ _appearance_dialog_button->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&SubtitlePanel::appearance_dialog_clicked, this));
}
void
@@ -229,7 +233,8 @@ SubtitlePanel::setup_sensitivity ()
{
int any_subs = 0;
int ffmpeg_subs = 0;
- int subrip_or_dcp_subs = 0;
+ int subrip_subs = 0;
+ int dcp_subs = 0;
int image_subs = 0;
SubtitleContentList sel = _parent->selected_subtitle ();
BOOST_FOREACH (shared_ptr<SubtitleContent> i, sel) {
@@ -241,8 +246,11 @@ SubtitlePanel::setup_sensitivity ()
++ffmpeg_subs;
++any_subs;
}
- } else if (sc || dsc) {
- ++subrip_or_dcp_subs;
+ } else if (sc) {
+ ++subrip_subs;
+ ++any_subs;
+ } else if (dsc) {
+ ++dcp_subs;
++any_subs;
} else {
++any_subs;
@@ -284,8 +292,9 @@ SubtitlePanel::setup_sensitivity ()
_y_scale->Enable (!reference && any_subs > 0 && use);
_language->Enable (!reference && any_subs > 0 && use);
_stream->Enable (!reference && ffmpeg_subs == 1);
- _subtitle_view_button->Enable (!reference && subrip_or_dcp_subs == 1);
- _fonts_dialog_button->Enable (!reference && subrip_or_dcp_subs == 1);
+ _subtitle_view_button->Enable (!reference && (subrip_subs == 1 || dcp_subs == 1));
+ _fonts_dialog_button->Enable (!reference && (subrip_subs == 1 || dcp_subs == 1));
+ _appearance_dialog_button->Enable (!reference && subrip_subs == 1);
}
void
@@ -425,3 +434,19 @@ SubtitlePanel::reference_clicked ()
d->set_reference_subtitle (_reference->GetValue ());
}
+
+void
+SubtitlePanel::appearance_dialog_clicked ()
+{
+ SubtitleContentList c = _parent->selected_subtitle ();
+ DCPOMATIC_ASSERT (c.size() == 1);
+
+ shared_ptr<SubRipContent> sr = dynamic_pointer_cast<SubRipContent> (c.front ());
+ DCPOMATIC_ASSERT (sr);
+
+ SubtitleAppearanceDialog* d = new SubtitleAppearanceDialog (this, sr);
+ if (d->ShowModal () == wxID_OK) {
+ d->apply ();
+ }
+ d->Destroy ();
+}
diff --git a/src/wx/subtitle_panel.h b/src/wx/subtitle_panel.h
index 7eb9cd27e..e3fd7cd75 100644
--- a/src/wx/subtitle_panel.h
+++ b/src/wx/subtitle_panel.h
@@ -23,6 +23,7 @@ class wxCheckBox;
class wxSpinCtrl;
class SubtitleView;
class FontsDialog;
+class SubtitleAppearanceDialog;
class SubtitlePanel : public ContentSubPanel
{
@@ -45,6 +46,7 @@ private:
void subtitle_view_clicked ();
void fonts_dialog_clicked ();
void reference_clicked ();
+ void appearance_dialog_clicked ();
void setup_sensitivity ();
@@ -61,4 +63,5 @@ private:
SubtitleView* _subtitle_view;
wxButton* _fonts_dialog_button;
FontsDialog* _fonts_dialog;
+ wxButton* _appearance_dialog_button;
};
diff --git a/src/wx/wscript b/src/wx/wscript
index d2bf33cd3..3b61eb5c6 100644
--- a/src/wx/wscript
+++ b/src/wx/wscript
@@ -70,6 +70,7 @@ sources = """
screens_panel.cc
server_dialog.cc
servers_list_dialog.cc
+ subtitle_appearance_dialog.cc
subtitle_panel.cc
subtitle_view.cc
system_font_dialog.cc