summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2014-05-29 11:57:08 +0100
committerCarl Hetherington <cth@carlh.net>2014-05-29 11:57:08 +0100
commitaebf2cb7812c8f593b85182611b587e6014aefc6 (patch)
treec954ebc0cf39263b6c051e159f48e177cafae310 /src
parent8b1958988ca234f51ec99385d81b95c1f0f092af (diff)
Re-work Subtitle class; remove STL text writer.
Diffstat (limited to 'src')
-rw-r--r--src/dcp_reader.cc55
-rw-r--r--src/dcp_reader.h10
-rw-r--r--src/stl_binary_reader.cc47
-rw-r--r--src/stl_binary_writer.cc134
-rw-r--r--src/stl_binary_writer.h (renamed from src/convert_time.h)27
-rw-r--r--src/stl_text_reader.cc54
-rw-r--r--src/stl_text_reader.h6
-rw-r--r--src/stl_text_writer.cc84
-rw-r--r--src/stl_text_writer.h26
-rw-r--r--src/subtitle.cc76
-rw-r--r--src/subtitle.h90
-rw-r--r--src/time_pair.cc (renamed from src/convert_time.cc)35
-rw-r--r--src/wscript6
13 files changed, 380 insertions, 270 deletions
diff --git a/src/dcp_reader.cc b/src/dcp_reader.cc
index 4c3384e..bd5c183 100644
--- a/src/dcp_reader.cc
+++ b/src/dcp_reader.cc
@@ -207,6 +207,13 @@ public:
string uri;
};
+struct DCPReader::ParseState {
+ list<shared_ptr<DCPFont> > font_nodes;
+ list<shared_ptr<DCPText> > text_nodes;
+ list<shared_ptr<DCPSubtitle> > subtitle_nodes;
+ boost::optional<Subtitle> subtitle;
+};
+
}
/** @param s A string.
@@ -263,6 +270,10 @@ DCPReader::DCPReader (istream& in)
ParseState parse_state;
examine_font_nodes (xml, font_nodes, parse_state);
+ if (parse_state.subtitle && !parse_state.subtitle.get().blocks.empty ()) {
+ _subs.push_back (parse_state.subtitle.get ());
+ }
+
_subs.sort ();
}
@@ -308,7 +319,7 @@ DCPReader::examine_text_nodes (
}
void
-DCPReader::maybe_add_subtitle (string text, ParseState const & parse_state)
+DCPReader::maybe_add_subtitle (string text, ParseState& parse_state)
{
if (empty_or_white_space (text)) {
return;
@@ -325,19 +336,31 @@ DCPReader::maybe_add_subtitle (string text, ParseState const & parse_state)
DCPText effective_text (*parse_state.text_nodes.back ());
DCPSubtitle effective_subtitle (*parse_state.subtitle_nodes.back ());
- Subtitle s;
- s.text = text;
- s.font = font_id_to_name (effective_font.id);
- s.font_size.proportional = float (effective_font.size) / (72 * 11);
- s.vertical_position.proportional = float (effective_text.v_position) / 100;
- s.vertical_position.reference = effective_text.v_align;
- s.effect = effective_font.effect;
- s.effect_colour = effective_font.effect_colour;
- s.colour = effective_font.colour.get ();
- s.italic = effective_font.italic.get ();
- s.from.metric = effective_subtitle.in;
- s.to.metric = effective_subtitle.out;
- s.fade_up = effective_subtitle.fade_up_time;
- s.fade_down = effective_subtitle.fade_down_time;
- _subs.push_back (s);
+ Subtitle proposed_subtitle;
+ proposed_subtitle.vertical_position.proportional = float (effective_text.v_position) / 100;
+ proposed_subtitle.vertical_position.reference = effective_text.v_align;
+ proposed_subtitle.from.set_metric (effective_subtitle.in);
+ proposed_subtitle.to.set_metric (effective_subtitle.out);
+ proposed_subtitle.fade_up = effective_subtitle.fade_up_time;
+ proposed_subtitle.fade_down = effective_subtitle.fade_down_time;
+
+ if (!parse_state.subtitle || !parse_state.subtitle.get().same_metadata (proposed_subtitle)) {
+ /* We need a new Subtitle */
+ if (parse_state.subtitle && !parse_state.subtitle.get().blocks.empty ()) {
+ /* Push the old one */
+ _subs.push_back (parse_state.subtitle.get ());
+ }
+ parse_state.subtitle = proposed_subtitle;
+ }
+
+ Block block;
+ block.text = text;
+ block.font = font_id_to_name (effective_font.id);
+ block.font_size.set_proportional (float (effective_font.size) / (72 * 11));
+ block.effect = effective_font.effect;
+ block.effect_colour = effective_font.effect_colour;
+ block.colour = effective_font.colour.get ();
+ block.italic = effective_font.italic.get ();
+
+ parse_state.subtitle.get().blocks.push_back (block);
}
diff --git a/src/dcp_reader.h b/src/dcp_reader.h
index 51ada1a..aa8df7f 100644
--- a/src/dcp_reader.h
+++ b/src/dcp_reader.h
@@ -37,14 +37,10 @@ public:
DCPReader (std::istream &);
private:
-
- struct ParseState {
- std::list<boost::shared_ptr<DCPFont> > font_nodes;
- std::list<boost::shared_ptr<DCPText> > text_nodes;
- std::list<boost::shared_ptr<DCPSubtitle> > subtitle_nodes;
- };
- void maybe_add_subtitle (std::string text, ParseState const & parse_state);
+ struct ParseState;
+
+ void maybe_add_subtitle (std::string text, ParseState& parse_state);
void examine_font_nodes (
boost::shared_ptr<const cxml::Node> xml,
diff --git a/src/stl_binary_reader.cc b/src/stl_binary_reader.cc
index 0d97e2e..ebcee1b 100644
--- a/src/stl_binary_reader.cc
+++ b/src/stl_binary_reader.cc
@@ -26,11 +26,13 @@
#include "compose.hpp"
using std::map;
+using std::vector;
using std::cout;
using std::string;
using std::istream;
using boost::lexical_cast;
using boost::algorithm::replace_all;
+using boost::is_any_of;
using boost::locale::conv::utf_to_utf;
using namespace sub;
@@ -120,7 +122,6 @@ STLBinaryReader::STLBinaryReader (istream& in)
editor_contact_details = get_string (341, 32);
for (int i = 0; i < tti_blocks; ++i) {
- Subtitle sub;
in.read ((char *) _buffer, 128);
if (in.gcount() != 128) {
@@ -131,26 +132,32 @@ STLBinaryReader::STLBinaryReader (istream& in)
continue;
}
- sub.from.frame = get_timecode (5);
- sub.to.frame = get_timecode (9);
- sub.line = get_int (13, 1);
-
- /* XXX: justification, effects */
-
- string s = get_string (16, 112);
-
- /* 8Ah is a new line */
- replace_all (s, "\x8a", "\n");
-
- /* 8Fh is unused space, so trim the string to the first instance of that */
- size_t unused = s.find_first_of ('\x8f');
- if (unused != string::npos) {
- s = s.substr (0, unused);
+ string const whole = get_string (16, 112);
+
+ /* Split the text up into lines (8Ah is a new line) */
+ vector<string> lines;
+ split (lines, whole, is_any_of ("\x8a"));
+
+ for (size_t i = 0; i < lines.size(); ++i) {
+ Subtitle sub;
+ sub.from.set_frame (get_timecode (5));
+ sub.to.set_frame (get_timecode (9));
+ sub.vertical_position.line = get_int (13, 1) + i;
+
+ /* XXX: justification, effects */
+
+ /* 8Fh is unused space, so trim the string to the first instance of that */
+ size_t unused = lines[i].find_first_of ('\x8f');
+ if (unused != string::npos) {
+ lines[i] = lines[i].substr (0, unused);
+ }
+
+ Block block;
+ block.text = utf_to_utf<char> (iso6937_to_utf16 (lines[i].c_str()));
+ sub.blocks.push_back (block);
+
+ _subs.push_back (sub);
}
-
- sub.text = utf_to_utf<char> (iso6937_to_utf16 (s.c_str()));
-
- _subs.push_back (sub);
}
}
diff --git a/src/stl_binary_writer.cc b/src/stl_binary_writer.cc
new file mode 100644
index 0000000..34e4d73
--- /dev/null
+++ b/src/stl_binary_writer.cc
@@ -0,0 +1,134 @@
+/*
+ Copyright (C) 2014 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 <list>
+#include <cmath>
+#include <fstream>
+#include "stl_binary_writer.h"
+#include "compose.hpp"
+
+using std::list;
+using std::ofstream;
+using std::string;
+using namespace sub;
+
+static void
+put_string (char* p, string s)
+{
+ memcpy (p, s.c_str (), s.length ());
+}
+
+static void
+put_string (char* p, int n, string s)
+{
+ memcpy (p, s.c_str (), s.length ());
+ memset (p + s.length(), ' ', s.length () - n);
+}
+
+/** @param language ISO 3-character country code for the language of the subtitles */
+void
+sub::write_stl_binary (
+ list<Subtitle> subtitles,
+ float frames_per_second,
+ string language,
+ string original_programme_title,
+ string original_episode_title,
+ string translated_programme_title,
+ string translated_episode_title,
+ string translator_name,
+ string translator_contact_details,
+ string creation_date,
+ string revision_date,
+ int revision_number,
+ string country_of_origin,
+ string publisher,
+ string editor_name,
+ string editor_contact_details,
+ boost::filesystem::path file_name
+ )
+{
+ assert (language.size() == 3);
+ assert (original_programme_title.size() <= 32);
+ assert (original_episode_title.size() <= 32);
+ assert (translated_programme_title.size() <= 32);
+ assert (translated_episode_title.size() <= 32);
+ assert (translator_name.size() <= 32);
+ assert (translator_contact_details.size() <= 32);
+ assert (creation_date.size() == 6);
+ assert (revision_date.size() == 6);
+ assert (revision_number <= 99);
+ assert (country_of_origin.size() == 3);
+ assert (publisher.size() <= 32);
+ assert (editor_name.size() <= 32);
+ assert (editor_contact_details.size() <= 32);
+
+ char* buffer = new char[1024];
+ ofstream output (file_name.string().c_str ());
+
+ /* Code page: 850 */
+ put_string (buffer + 0, "850");
+ /* Disk format code */
+ put_string (buffer + 3, String::compose ("STL%1.01", rint (frames_per_second)));
+ /* Display standard code: open subtitling */
+ put_string (buffer + 11, "0");
+ /* Character code table: Latin (ISO 6937) */
+ put_string (buffer + 12, "00");
+ put_string (buffer + 14, language);
+ put_string (buffer + 16, 32, original_programme_title);
+ put_string (buffer + 48, 32, original_episode_title);
+ put_string (buffer + 80, 32, translated_programme_title);
+ put_string (buffer + 112, 32, translated_episode_title);
+ put_string (buffer + 144, 32, translator_name);
+ put_string (buffer + 176, 32, translator_contact_details);
+ /* Subtitle list reference code */
+ put_string (buffer + 208, "0000000000000000");
+ put_string (buffer + 224, creation_date);
+ put_string (buffer + 230, revision_date);
+ put_string (buffer + 236, String::compose ("%02d", revision_number));
+ /* TTI blocks */
+ put_string (buffer + 238, String::compose ("%05d", subtitles.size ()));
+ /* Total number of subtitles */
+ put_string (buffer + 243, String::compose ("%05d", subtitles.size ()));
+ /* Total number of subtitle groups */
+ put_string (buffer + 248, "000");
+ /* Maximum number of displayable characters in any text row */
+ /* XXX */
+ put_string (buffer + 251, "99");
+ /* Maximum number of displayable rows */
+ /* XXX */
+ put_string (buffer + 253, "99");
+ /* Time code status */
+ put_string (buffer + 255, "1");
+ /* Start-of-programme time code */
+ put_string (buffer + 256, "00000000");
+ /* First-in-cue time code */
+ put_string (buffer + 264, "00000000");
+ /* Total number of disks */
+ put_string (buffer + 272, "1");
+ /* Disk sequence number */
+ put_string (buffer + 273, "1");
+ put_string (buffer + 274, country_of_origin);
+ put_string (buffer + 277, publisher);
+ put_string (buffer + 309, editor_name);
+ put_string (buffer + 341, editor_contact_details);
+
+ output.write (buffer, 1024);
+
+ delete[] buffer;
+}
diff --git a/src/convert_time.h b/src/stl_binary_writer.h
index 92ec737..7dbf5a5 100644
--- a/src/convert_time.h
+++ b/src/stl_binary_writer.h
@@ -17,12 +17,31 @@
*/
-#include "metric_time.h"
-#include "frame_time.h"
+#include <string>
+#include <boost/filesystem.hpp>
namespace sub {
-FrameTime metric_to_frame (MetricTime, float frames_per_second);
-MetricTime frame_to_metric (FrameTime, float frames_per_second);
+class Subtitle;
+
+extern void write_stl_binary (
+ std::list<Subtitle> subtitles,
+ float frames_per_second,
+ std::string language,
+ std::string original_programme_title,
+ std::string original_episode_title,
+ std::string translated_programme_title,
+ std::string translated_episode_title,
+ std::string translator_name,
+ std::string translator_contact_details,
+ std::string creation_date,
+ std::string revision_date,
+ int revision_number,
+ std::string country_of_origin,
+ std::string publisher,
+ std::string editor_name,
+ std::string editor_contact_details,
+ boost::filesystem::path file_name
+ );
}
diff --git a/src/stl_text_reader.cc b/src/stl_text_reader.cc
index f9e9b65..0b4141c 100644
--- a/src/stl_text_reader.cc
+++ b/src/stl_text_reader.cc
@@ -38,6 +38,8 @@ using namespace sub;
STLTextReader::STLTextReader (istream& in)
{
+ _subtitle.vertical_position.line = 0;
+
while (in.good ()) {
string line;
getline (in, line);
@@ -91,38 +93,37 @@ STLTextReader::STLTextReader (istream& in)
continue;
}
- _current.from.frame = from.get ();
- _current.to.frame = to.get ();
+ _subtitle.from.set_frame (from.get ());
+ _subtitle.to.set_frame (to.get ());
/* Parse ^B/^I/^U */
string text = line.substr (divider[1] + 1);
for (size_t i = 0; i < text.length(); ++i) {
if (text[i] == '|') {
- maybe_push ();
- _current.line++;
+ maybe_push_subtitle ();
+ _subtitle.vertical_position.line = _subtitle.vertical_position.line.get() + 1;
} else if (text[i] == '^') {
- maybe_push ();
+ maybe_push_block ();
if ((i + 1) < text.length()) {
switch (text[i + 1]) {
case 'B':
- _current.bold = !_current.bold;
+ _block.bold = !_block.bold;
break;
case 'I':
- _current.italic = !_current.italic;
+ _block.italic = !_block.italic;
break;
case 'U':
- _current.underline = !_current.underline;
+ _block.underline = !_block.underline;
break;
}
}
++i;
} else {
- _current.text += text[i];
+ _block.text += text[i];
}
}
- maybe_push ();
- _current.line = 0;
+ maybe_push_subtitle ();
}
}
}
@@ -144,24 +145,37 @@ void
STLTextReader::set (string name, string value)
{
if (name == "$FontName") {
- _current.font = value;
+ _block.font = value;
} else if (name == "$Bold") {
- _current.bold = value == "True";
+ _block.bold = value == "True";
} else if (name == "$Italic") {
- _current.italic = value == "True";
+ _block.italic = value == "True";
} else if (name == "$Underlined") {
- _current.underline = value == "True";
+ _block.underline = value == "True";
} else if (name == "$FontSize") {
- _current.font_size.points = lexical_cast<int> (value);
+ _block.font_size.set_points (lexical_cast<int> (value));
+ }
+}
+
+void
+STLTextReader::maybe_push_subtitle ()
+{
+ maybe_push_block ();
+
+ if (!_subtitle.blocks.empty ()) {
+ _subs.push_back (_subtitle);
+ _subtitle.blocks.clear ();
+ _subtitle.vertical_position.line = 0;
}
}
void
-STLTextReader::maybe_push ()
+STLTextReader::maybe_push_block ()
{
- if (!_current.text.empty ()) {
- _subs.push_back (_current);
- _current.text.clear ();
+ if (!_block.text.empty ()) {
+ _subtitle.blocks.push_back (_block);
+ _block.text.clear ();
}
}
+
diff --git a/src/stl_text_reader.h b/src/stl_text_reader.h
index c48a8e5..e6a550a 100644
--- a/src/stl_text_reader.h
+++ b/src/stl_text_reader.h
@@ -29,10 +29,12 @@ public:
private:
void set (std::string name, std::string value);
- void maybe_push ();
+ void maybe_push_subtitle ();
+ void maybe_push_block ();
boost::optional<FrameTime> time (std::string t) const;
- Subtitle _current;
+ Subtitle _subtitle;
+ Block _block;
};
}
diff --git a/src/stl_text_writer.cc b/src/stl_text_writer.cc
deleted file mode 100644
index 6a8601d..0000000
--- a/src/stl_text_writer.cc
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- Copyright (C) 2014 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 "stl_text_writer.h"
-#include <boost/optional.hpp>
-
-using std::list;
-using std::ostream;
-using std::string;
-using boost::optional;
-using namespace sub;
-
-void
-sub::write_stl_text (list<Subtitle> subtitles, int screen_height_in_points, float frames_per_second, ostream& out)
-{
- optional<string> font;
- optional<int> font_size;
- bool bold = false;
- bool italic = false;
- bool underline = false;
- int line = 0;
- optional<FrameTime> from;
- optional<FrameTime> to;
-
- for (list<Subtitle>::const_iterator i = subtitles.begin(); i != subtitles.end(); ++i) {
- bool started_new = false;
- if (!font || font.get() != i->font) {
- out << "\n$FontName = " << i->font;
- font = i->font;
- started_new = true;
- }
- if (!font_size || font_size.get() != i->font_size_points (screen_height_in_points)) {
- out << "\n$FontSize = " << i->font_size_points (screen_height_in_points);
- font_size = i->font_size_points (screen_height_in_points);
- started_new = true;
- }
- string text;
- if (bold != i->bold) {
- text += "^B";
- bold = i->bold;
- }
- if (italic != i->italic) {
- text += "^I";
- italic = i->italic;
- }
- if (underline != i->underline) {
- text += "^U";
- underline = i->underline;
- }
-
- text += i->text;
-
- if (from && from.get() == i->from_frame(frames_per_second) && to && to.get() == i->to_frame(frames_per_second) && !started_new) {
- for (int j = line; j < i->line; ++j) {
- out << "|";
- }
- out << text;
- line = i->line;
- } else {
- out << "\n" << i->from_frame(frames_per_second).timecode() << "," << i->to_frame(frames_per_second).timecode() << "," << text;
- from = i->from_frame (frames_per_second);
- to = i->to_frame (frames_per_second);
- line = 0;
- }
- }
-
- out << "\n";
-}
diff --git a/src/stl_text_writer.h b/src/stl_text_writer.h
deleted file mode 100644
index d44696f..0000000
--- a/src/stl_text_writer.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- Copyright (C) 2014 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.h"
-
-namespace sub {
-
-extern void write_stl_text (std::list<Subtitle> subtitles, int screen_height_in_points, float frames_per_second, std::ostream &);
-
-}
diff --git a/src/subtitle.cc b/src/subtitle.cc
index 6d3360f..5eb5784 100644
--- a/src/subtitle.cc
+++ b/src/subtitle.cc
@@ -18,81 +18,65 @@
*/
#include "subtitle.h"
-#include "convert_time.h"
-using std::list;
using namespace sub;
bool
sub::operator< (Subtitle const & a, Subtitle const & b)
{
- if (a.from.frame && b.from.frame) {
- return a.from.frame.get() < b.from.frame.get();
+ if (a.from.frame() && b.from.frame()) {
+ return a.from.frame().get() < b.from.frame().get();
}
- if (a.from.metric && b.from.metric) {
- return a.from.metric.get() < b.from.metric.get();
+ if (a.from.metric() && b.from.metric()) {
+ return a.from.metric().get() < b.from.metric().get();
}
assert (false);
}
-FrameTime
-Subtitle::from_frame (float frames_per_second) const
-{
- if (from.frame) {
- return from.frame.get ();
- }
-
- return metric_to_frame (from.metric.get(), frames_per_second);
-}
-FrameTime
-Subtitle::to_frame (float frames_per_second) const
+float
+Block::FontSize::proportional (int screen_height_in_points) const
{
- if (to.frame) {
- return to.frame.get ();
+ if (_proportional) {
+ return _proportional.get ();
}
- return metric_to_frame (to.metric.get(), frames_per_second);
+ return float (_points.get ()) / screen_height_in_points;
}
-MetricTime
-Subtitle::from_metric (float frames_per_second) const
+int
+Block::FontSize::points (int screen_height_in_points) const
{
- if (from.metric) {
- return from.metric.get ();
+ if (_points) {
+ return _points.get ();
}
- return frame_to_metric (from.frame.get(), frames_per_second);
+ return _proportional.get() * screen_height_in_points;
}
-MetricTime
-Subtitle::to_metric (float frames_per_second) const
+bool
+Subtitle::same_metadata (Subtitle const & other) const
{
- if (to.metric) {
- return to.metric.get ();
- }
-
- return frame_to_metric (to.frame.get(), frames_per_second);
+ return (
+ vertical_position == other.vertical_position &&
+ from == other.from &&
+ to == other.to &&
+ fade_up == other.fade_up &&
+ fade_down == other.fade_down
+ );
}
-float
-Subtitle::font_size_proportional (int screen_height_in_points) const
+bool
+Subtitle::VerticalPosition::operator== (Subtitle::VerticalPosition const & other) const
{
- if (font_size.proportional) {
- return font_size.proportional.get ();
+ if (proportional && reference && other.proportional && other.reference) {
+ return proportional.get() == other.proportional.get() && reference.get() == other.reference.get();
+ } else if (line && other.line) {
+ return line.get() == other.line.get();
}
- return float (font_size.points.get ()) / screen_height_in_points;
+ return false;
}
-int
-Subtitle::font_size_points (int screen_height_in_points) const
-{
- if (font_size.points) {
- return font_size.points.get ();
- }
-
- return font_size.proportional.get() * screen_height_in_points;
-}
diff --git a/src/subtitle.h b/src/subtitle.h
index fc08ac7..ca73b4b 100644
--- a/src/subtitle.h
+++ b/src/subtitle.h
@@ -25,46 +25,58 @@
#include "colour.h"
#include "vertical_reference.h"
#include "effect.h"
+#include "time_pair.h"
#include <boost/optional.hpp>
#include <string>
#include <list>
namespace sub {
-class Subtitle
+/** A piece of text with a single font, style, size etc. */
+class Block
{
public:
- Subtitle ()
+ Block ()
: colour (1, 1, 1)
, bold (false)
, italic (false)
, underline (false)
- , line (0)
{}
-
+
/** Subtitle text in UTF-8 */
std::string text;
std::string font;
/** font size */
- struct {
+ class FontSize {
+ public:
+ void set_proportional (float p) {
+ _proportional = p;
+ }
+
+ void set_points (int p) {
+ _points = p;
+ }
+
+ boost::optional<float> proportional () const {
+ return _proportional;
+ }
+
+ boost::optional<int> points () const {
+ return _points;
+ }
+
+ float proportional (int screen_height_in_points) const;
+ int points (int screen_height_in_points) const;
+
+ private:
/** as a proportion of screen height */
- boost::optional<float> proportional;
+ boost::optional<float> _proportional;
/** in points */
- boost::optional<int> points;
+ boost::optional<int> _points;
+
} font_size;
- float font_size_proportional (int screen_height_in_points) const;
- int font_size_points (int screen_height_in_points) const;
-
- /** vertical position of the baseline of the text */
- struct {
- /** as a proportion of screen height offset from some reference point */
- boost::optional<float> proportional;
- /** reference position for proportional */
- boost::optional<VerticalReference> reference;
- } vertical_position;
-
boost::optional<Effect> effect;
boost::optional<Colour> effect_colour;
@@ -72,28 +84,40 @@ public:
bool bold; ///< true to use a bold version of font
bool italic; ///< true to use an italic version of font
bool underline; ///< true to underline
- int line; ///< line number, starting from 0
+};
- /** from time */
- struct {
- boost::optional<FrameTime> frame;
- boost::optional<MetricTime> metric;
- } from;
+/** A line of text which starts and stops at specific times */
+class Subtitle
+{
+public:
+ Subtitle ()
+ {}
- FrameTime from_frame (float frames_per_second) const;
- MetricTime from_metric (float frames_per_second) const;
+ /** vertical position of the baseline of the text */
+ struct VerticalPosition {
- /** to time */
- struct {
- boost::optional<FrameTime> frame;
- boost::optional<MetricTime> metric;
- } to;
+ /** as a proportion of screen height offset from some reference point */
+ boost::optional<float> proportional;
+ /** reference position for proportional */
+ boost::optional<VerticalReference> reference;
+ /** line number from the top of the screen */
+ boost::optional<int> line;
+
+ bool operator== (VerticalPosition const & other) const;
+
+ } vertical_position;
- FrameTime to_frame (float frames_per_second) const;
- MetricTime to_metric (float frames_per_second) const;
+ /** from time */
+ TimePair from;
+ /** to time */
+ TimePair to;
boost::optional<MetricTime> fade_up;
boost::optional<MetricTime> fade_down;
+
+ std::list<Block> blocks;
+
+ bool same_metadata (Subtitle const &) const;
};
bool operator< (Subtitle const & a, Subtitle const & b);
diff --git a/src/convert_time.cc b/src/time_pair.cc
index 3ae165b..186d54c 100644
--- a/src/convert_time.cc
+++ b/src/time_pair.cc
@@ -17,21 +17,40 @@
*/
-#include "metric_time.h"
-#include "frame_time.h"
-#include "convert_time.h"
+#include "time_pair.h"
-using std::cout;
using namespace sub;
FrameTime
-sub::metric_to_frame (MetricTime t, float frames_per_second)
+TimePair::frame (float frames_per_second) const
{
- return FrameTime (t.hours(), t.minutes(), t.seconds(), t.milliseconds() * frames_per_second / 1000);
+ if (_frame) {
+ return _frame.get ();
+ }
+
+ MetricTime const m = _metric.get ();
+ return FrameTime (m.hours(), m.minutes(), m.seconds(), m.milliseconds() * frames_per_second / 1000);
}
MetricTime
-sub::frame_to_metric (FrameTime t, float frames_per_second)
+TimePair::metric (float frames_per_second) const
+{
+ if (_metric) {
+ return _metric.get ();
+ }
+
+ FrameTime const f = _frame.get ();
+ return MetricTime (f.hours(), f.minutes(), f.seconds(), f.frames() * 1000 / frames_per_second);
+}
+
+bool
+TimePair::operator== (TimePair const & other) const
{
- return MetricTime (t.hours(), t.minutes(), t.seconds(), t.frames() * 1000 / frames_per_second);
+ if (_metric && other._metric) {
+ return _metric.get() == other._metric.get();
+ } else if (_frame && other._frame) {
+ return _frame.get() == other._frame.get();
+ }
+
+ return false;
}
diff --git a/src/wscript b/src/wscript
index c2bdd64..dd04aa9 100644
--- a/src/wscript
+++ b/src/wscript
@@ -12,7 +12,6 @@ def build(bld):
obj.export_includes = ['.']
obj.source = """
colour.cc
- convert_time.cc
dcp_reader.cc
effect.cc
frame_time.cc
@@ -23,22 +22,21 @@ def build(bld):
reader_factory.cc
stl_binary_reader.cc
stl_text_reader.cc
- stl_text_writer.cc
+ time_pair.cc
subtitle.cc
vertical_reference.cc
"""
headers = """
colour.h
- convert_time.h
dcp_reader.h
effect.h
frame_time.h
metric_time.h
reader.h
stl_text_reader.h
- stl_text_writer.h
subtitle.h
+ time_pair.h
vertical_reference.h
"""