ignore_node ("LoadFont");
- _fonts = sub_nodes<Font> ("Font");
+ _font_nodes = sub_nodes<FontNode> ("Font");
+ list<shared_ptr<LoadFontNode> > load_font_nodes = sub_nodes<LoadFontNode> ("LoadFont");
+
+ /* Now make Subtitle objects to represent the raw XML nodes
+ in a sane way.
+ */
+
+ for (list<shared_ptr<FontNode> >::iterator i = _font_nodes.begin(); i != _font_nodes.end(); ++i) {
+ for (list<shared_ptr<SubtitleNode> >::iterator j = (*i)->subtitle_nodes.begin(); j != (*i)->subtitle_nodes.end(); ++j) {
+ for (list<shared_ptr<TextNode> >::iterator k = (*j)->text_nodes.begin(); k != (*j)->text_nodes.end(); ++k) {
+ _subtitles.push_back (
+ shared_ptr<Subtitle> (
+ new Subtitle (
+ font_id_to_name ((*i)->id, load_font_nodes),
+ (*i)->size,
+ (*j)->in,
+ (*j)->out,
+ (*k)->v_position,
+ (*k)->text
+ )
+ )
+ );
+ }
+ }
+ }
+}
+
+FontNode::FontNode (xmlpp::Node const * node)
+ : XMLNode (node)
+{
+ id = string_attribute ("Id");
+ size = int64_attribute ("Size");
+ subtitle_nodes = sub_nodes<SubtitleNode> ("Subtitle");
}
-Font::Font (xmlpp::Node const * node)
+LoadFontNode::LoadFontNode (xmlpp::Node const * node)
: XMLNode (node)
{
- _subtitles = sub_nodes<Subtitle> ("Subtitle");
+ id = string_attribute ("Id");
+ uri = string_attribute ("URI");
}
+
-Subtitle::Subtitle (xmlpp::Node const * node)
+SubtitleNode::SubtitleNode (xmlpp::Node const * node)
: XMLNode (node)
{
- _in = time_attribute ("TimeIn");
- _out = time_attribute ("TimeOut");
- _texts = sub_nodes<Text> ("Text");
+ in = time_attribute ("TimeIn");
+ out = time_attribute ("TimeOut");
+ text_nodes = sub_nodes<TextNode> ("Text");
}
-Text::Text (xmlpp::Node const * node)
+TextNode::TextNode (xmlpp::Node const * node)
: XMLNode (node)
{
- _text = content ();
- _v_position = float_attribute ("VPosition");
+ text = content ();
+ v_position = float_attribute ("VPosition");
}
-list<shared_ptr<Text> >
+list<shared_ptr<Subtitle> >
SubtitleAsset::subtitles_at (Time t) const
{
- for (list<shared_ptr<Font> >::const_iterator i = _fonts.begin(); i != _fonts.end(); ++i) {
- list<shared_ptr<Text> > s = (*i)->subtitles_at (t);
- if (!s.empty ()) {
- return s;
+ list<shared_ptr<Subtitle> > s;
+ for (list<shared_ptr<Subtitle> >::const_iterator i = _subtitles.begin(); i != _subtitles.end(); ++i) {
+ if ((*i)->in() <= t && t <= (*i)->out ()) {
+ s.push_back (*i);
}
}
- return list<shared_ptr<Text> > ();
+ return s;
}
-list<shared_ptr<Text> >
-Font::subtitles_at (Time t) const
+std::string
+SubtitleAsset::font_id_to_name (string id, list<shared_ptr<LoadFontNode> > const & load_font_nodes) const
{
- for (list<shared_ptr<Subtitle> >::const_iterator i = _subtitles.begin(); i != _subtitles.end(); ++i) {
- if ((*i)->in() <= t && t <= (*i)->out()) {
- return (*i)->texts ();
- }
+ list<shared_ptr<LoadFontNode> >::const_iterator i = load_font_nodes.begin();
+ while (i != load_font_nodes.end() && (*i)->id != id) {
+ ++i;
+ }
+
+ if (i == load_font_nodes.end ()) {
+ return "";
+ }
+
+ if ((*i)->uri == "arial.ttf") {
+ return "Arial";
}
- return list<shared_ptr<Text> > ();
+ return "";
+}
+
+Subtitle::Subtitle (
+ std::string font,
+ int size,
+ Time in,
+ Time out,
+ float v_position,
+ std::string text
+ )
+ : _font (font)
+ , _size (size)
+ , _in (in)
+ , _out (out)
+ , _v_position (v_position)
+ , _text (text)
+{
+
+}
+
+int
+Subtitle::size_in_pixels (int screen_height) const
+{
+ /* Size in the subtitle file is given in points as if the screen
+ height is 11 inches, so a 72pt font would be 1/11th of the screen
+ height.
+ */
+
+ return _size * screen_height / (11 * 72);
}
namespace libdcp
{
-class Text : public XMLNode
+class TextNode : public XMLNode
{
public:
- Text () {}
- Text (xmlpp::Node const * node);
+ TextNode () {}
+ TextNode (xmlpp::Node const * node);
- float v_position () const {
- return _v_position;
- }
+ float v_position;
+ std::string text;
+};
- std::string text () const {
- return _text;
- }
+class SubtitleNode : public XMLNode
+{
+public:
+ SubtitleNode () {}
+ SubtitleNode (xmlpp::Node const * node);
-private:
- float _v_position;
- std::string _text;
+ Time in;
+ Time out;
+ std::list<boost::shared_ptr<TextNode> > text_nodes;
+};
+
+class FontNode : public XMLNode
+{
+public:
+ FontNode () {}
+ FontNode (xmlpp::Node const * node);
+
+ std::string id;
+ int size;
+
+ std::list<boost::shared_ptr<SubtitleNode> > subtitle_nodes;
+};
+
+class LoadFontNode : public XMLNode
+{
+public:
+ LoadFontNode () {}
+ LoadFontNode (xmlpp::Node const * node);
+
+ std::string id;
+ std::string uri;
};
-class Subtitle : public XMLNode
+class Subtitle
{
public:
- Subtitle () {}
- Subtitle (xmlpp::Node const * node);
+ Subtitle (
+ std::string font,
+ int size,
+ Time in,
+ Time out,
+ float v_position,
+ std::string text
+ );
+
+ std::string font () const {
+ return _font;
+ }
Time in () const {
return _in;
return _out;
}
- std::list<boost::shared_ptr<Text> > const & texts () const {
- return _texts;
+ std::string text () const {
+ return _text;
+ }
+
+ float v_position () const {
+ return _v_position;
}
+ int size_in_pixels (int screen_height) const;
+
private:
- std::list<boost::shared_ptr<Text> > _texts;
+ std::string _font;
+ int _size;
Time _in;
Time _out;
+ float _v_position;
+ std::string _text;
};
-class Font : public XMLNode
-{
-public:
- Font () {}
- Font (xmlpp::Node const * node);
-
- std::list<boost::shared_ptr<Subtitle> > const & subtitles () const {
- return _subtitles;
- }
-
- std::list<boost::shared_ptr<Text> > subtitles_at (Time t) const;
-
-private:
- std::list<boost::shared_ptr<Subtitle> > _subtitles;
-};
-
class SubtitleAsset : public Asset, public XMLFile
{
public:
void write_to_cpl (std::ostream&) const {}
virtual std::list<std::string> equals (boost::shared_ptr<const Asset>, EqualityOptions) const {
+ /* XXX */
return std::list<std::string> ();
}
return _language;
}
- std::list<boost::shared_ptr<Text> > subtitles_at (Time t) const;
+ std::list<boost::shared_ptr<Subtitle> > subtitles_at (Time t) const;
- std::list<boost::shared_ptr<Font> > const & fonts () const {
- return _fonts;
+ std::list<boost::shared_ptr<FontNode> > font_nodes () const {
+ return _font_nodes;
}
private:
+ std::string font_id_to_name (std::string id, std::list<boost::shared_ptr<LoadFontNode> > const & load_font_nodes) const;
+
std::string _subtitle_id;
std::string _movie_title;
int64_t _reel_number;
std::string _language;
- std::list<boost::shared_ptr<Font> > _fonts;
+ std::list<boost::shared_ptr<FontNode> > _font_nodes;
+
+ std::list<boost::shared_ptr<Subtitle> > _subtitles;
};
}
libdcp::SubtitleAsset subs ("test/ref", "subs.xml");
BOOST_CHECK_EQUAL (subs.language(), "French");
- BOOST_CHECK_EQUAL (subs.fonts().size(), 1);
- BOOST_CHECK_EQUAL (subs.fonts().front()->subtitles().size(), 4);
+ BOOST_CHECK_EQUAL (subs.font_nodes().size(), 1);
+ BOOST_CHECK_EQUAL (subs.font_nodes().front()->subtitle_nodes.size(), 4);
- list<shared_ptr<libdcp::Subtitle> >::const_iterator i = subs.fonts().front()->subtitles().begin ();
+ list<shared_ptr<libdcp::SubtitleNode> >::const_iterator i = subs.font_nodes().front()->subtitle_nodes.begin ();
- BOOST_CHECK_EQUAL ((*i)->in(), libdcp::Time (0, 0, 5, 198));
- BOOST_CHECK_EQUAL ((*i)->out(), libdcp::Time (0, 0, 7, 115));
- BOOST_CHECK_EQUAL ((*i)->texts().size(), 1);
- BOOST_CHECK_EQUAL ((*i)->texts().front()->v_position(), 15);
- BOOST_CHECK_EQUAL ((*i)->texts().front()->text(), "My jacket was Idi Amin's");
+ BOOST_CHECK_EQUAL ((*i)->in, libdcp::Time (0, 0, 5, 198));
+ BOOST_CHECK_EQUAL ((*i)->out, libdcp::Time (0, 0, 7, 115));
+ BOOST_CHECK_EQUAL ((*i)->text_nodes.size(), 1);
+ BOOST_CHECK_EQUAL ((*i)->text_nodes.front()->v_position, 15);
+ BOOST_CHECK_EQUAL ((*i)->text_nodes.front()->text, "My jacket was Idi Amin's");
++i;
- BOOST_CHECK_EQUAL ((*i)->in(), libdcp::Time (0, 0, 7, 177));
- BOOST_CHECK_EQUAL ((*i)->out(), libdcp::Time (0, 0, 11, 31));
- BOOST_CHECK_EQUAL ((*i)->texts().size(), 2);
- BOOST_CHECK_EQUAL ((*i)->texts().front()->v_position(), 21);
- BOOST_CHECK_EQUAL ((*i)->texts().front()->text(), "My corset was H.M. The Queen's");
- BOOST_CHECK_EQUAL ((*i)->texts().back()->v_position(), 15);
- BOOST_CHECK_EQUAL ((*i)->texts().back()->text(), "My large wonderbra");
+ BOOST_CHECK_EQUAL ((*i)->in, libdcp::Time (0, 0, 7, 177));
+ BOOST_CHECK_EQUAL ((*i)->out, libdcp::Time (0, 0, 11, 31));
+ BOOST_CHECK_EQUAL ((*i)->text_nodes.size(), 2);
+ BOOST_CHECK_EQUAL ((*i)->text_nodes.front()->v_position, 21);
+ BOOST_CHECK_EQUAL ((*i)->text_nodes.front()->text, "My corset was H.M. The Queen's");
+ BOOST_CHECK_EQUAL ((*i)->text_nodes.back()->v_position, 15);
+ BOOST_CHECK_EQUAL ((*i)->text_nodes.back()->text, "My large wonderbra");
++i;
- BOOST_CHECK_EQUAL ((*i)->in(), libdcp::Time (0, 0, 11, 94));
- BOOST_CHECK_EQUAL ((*i)->out(), libdcp::Time (0, 0, 13, 63));
- BOOST_CHECK_EQUAL ((*i)->texts().size(), 1);
- BOOST_CHECK_EQUAL ((*i)->texts().front()->v_position(), 15);
- BOOST_CHECK_EQUAL ((*i)->texts().front()->text(), "Once belonged to the Shah");
+ BOOST_CHECK_EQUAL ((*i)->in, libdcp::Time (0, 0, 11, 94));
+ BOOST_CHECK_EQUAL ((*i)->out, libdcp::Time (0, 0, 13, 63));
+ BOOST_CHECK_EQUAL ((*i)->text_nodes.size(), 1);
+ BOOST_CHECK_EQUAL ((*i)->text_nodes.front()->v_position, 15);
+ BOOST_CHECK_EQUAL ((*i)->text_nodes.front()->text, "Once belonged to the Shah");
++i;
- BOOST_CHECK_EQUAL ((*i)->in(), libdcp::Time (0, 0, 13, 104));
- BOOST_CHECK_EQUAL ((*i)->out(), libdcp::Time (0, 0, 15, 177));
- BOOST_CHECK_EQUAL ((*i)->texts().size(), 1);
- BOOST_CHECK_EQUAL ((*i)->texts().front()->v_position(), 15);
- BOOST_CHECK_EQUAL ((*i)->texts().front()->text(), "And these are Roy Hattersley's jeans");
-
- BOOST_CHECK_EQUAL (subs.subtitles_at (libdcp::Time (0, 0, 14, 042)).size(), 1);
- BOOST_CHECK_EQUAL (subs.subtitles_at (libdcp::Time (0, 0, 14, 042)).front()->text(), "And these are Roy Hattersley's jeans");
+ BOOST_CHECK_EQUAL ((*i)->in, libdcp::Time (0, 0, 13, 104));
+ BOOST_CHECK_EQUAL ((*i)->out, libdcp::Time (0, 0, 15, 177));
+ BOOST_CHECK_EQUAL ((*i)->text_nodes.size(), 1);
+ BOOST_CHECK_EQUAL ((*i)->text_nodes.front()->v_position, 15);
+ BOOST_CHECK_EQUAL ((*i)->text_nodes.front()->text, "And these are Roy Hattersley's jeans");
+
+ BOOST_CHECK_EQUAL (subs.subtitles_at (libdcp::Time (0, 0, 14, 42)).size(), 1);
+ shared_ptr<libdcp::Subtitle> s = subs.subtitles_at (libdcp::Time (0, 0, 14, 42)).front ();
+ BOOST_CHECK_EQUAL (s->text(), "And these are Roy Hattersley's jeans");
+ BOOST_CHECK_EQUAL (s->v_position(), 15);
+ BOOST_CHECK_EQUAL (s->in(), libdcp::Time (0, 0, 13, 104));
+ BOOST_CHECK_EQUAL (s->out(), libdcp::Time (0, 0, 15, 177));
+ BOOST_CHECK_EQUAL (s->font(), "Arial");
+ BOOST_CHECK_EQUAL (s->size_in_pixels(1080), 53);
}
BOOST_AUTO_TEST_CASE (dcp_time)