Recursively scan font tags in subtitles.
authorCarl Hetherington <cth@carlh.net>
Tue, 21 Aug 2012 15:00:16 +0000 (16:00 +0100)
committerCarl Hetherington <cth@carlh.net>
Tue, 21 Aug 2012 15:00:16 +0000 (16:00 +0100)
src/subtitle_asset.cc
src/subtitle_asset.h
src/xml.cc
src/xml.h
test/tests.cc

index 8f0c48abb69b254f7106d0102d99196b5d096061..be0368562a3ccafffd9b9e411280d020db2bb063 100644 (file)
@@ -35,38 +35,79 @@ SubtitleAsset::SubtitleAsset (string directory, string xml)
        ignore_node ("LoadFont");
 
        list<shared_ptr<FontNode> > font_nodes = sub_nodes<FontNode> ("Font");
-       list<shared_ptr<LoadFontNode> > load_font_nodes = sub_nodes<LoadFontNode> ("LoadFont");
+       _load_font_nodes = sub_nodes<LoadFontNode> ("LoadFont");
 
        /* Now make Subtitle objects to represent the raw XML nodes
           in a sane way.
        */
 
+       list<shared_ptr<FontNode> > current_font_nodes;
        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
-                                                       )
+               examine_font_node (*i, current_font_nodes);
+       }
+}
+
+void
+SubtitleAsset::examine_font_node (shared_ptr<FontNode> font_node, list<shared_ptr<FontNode> >& current_font_nodes)
+{
+       current_font_nodes.push_back (font_node);
+       
+       for (list<shared_ptr<SubtitleNode> >::iterator j = font_node->subtitle_nodes.begin(); j != font_node->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 (id_from_font_nodes (current_font_nodes)),
+                                               size_from_font_nodes (current_font_nodes),
+                                               (*j)->in,
+                                               (*j)->out,
+                                               (*k)->v_position,
+                                               (*k)->text
                                                )
-                                       );
-                       }
+                                       )
+                               );
                }
        }
+
+       for (list<shared_ptr<FontNode> >::iterator j = font_node->font_nodes.begin(); j != font_node->font_nodes.end(); ++j) {
+               examine_font_node (*j, current_font_nodes);
+       }
+
+       current_font_nodes.pop_back ();
+}
+
+string
+SubtitleAsset::id_from_font_nodes (list<shared_ptr<FontNode> > const & font_nodes) const
+{
+       for (list<shared_ptr<FontNode> >::const_reverse_iterator i = font_nodes.rbegin(); i != font_nodes.rend(); ++i) {
+               if (!(*i)->id.empty ()) {
+                       return (*i)->id;
+               }
+       }
+
+       return "";
+}
+
+int
+SubtitleAsset::size_from_font_nodes (list<shared_ptr<FontNode> > const & font_nodes) const
+{
+       for (list<shared_ptr<FontNode> >::const_reverse_iterator i = font_nodes.rbegin(); i != font_nodes.rend(); ++i) {
+               if ((*i)->size != 0) {
+                       return (*i)->size;
+               }
+       }
+
+       return 0;
+
 }
 
 FontNode::FontNode (xmlpp::Node const * node)
        : XMLNode (node)
 {
        id = string_attribute ("Id");
-       size = int64_attribute ("Size");
+       size = optional_int64_attribute ("Size");
        subtitle_nodes = sub_nodes<SubtitleNode> ("Subtitle");
+       font_nodes = sub_nodes<FontNode> ("Font");
 }
 
 LoadFontNode::LoadFontNode (xmlpp::Node const * node)
@@ -106,14 +147,14 @@ SubtitleAsset::subtitles_at (Time t) const
 }
 
 std::string
-SubtitleAsset::font_id_to_name (string id, list<shared_ptr<LoadFontNode> > const & load_font_nodes) const
+SubtitleAsset::font_id_to_name (string id) const
 {
-       list<shared_ptr<LoadFontNode> >::const_iterator i = load_font_nodes.begin();
-       while (i != load_font_nodes.end() && (*i)->id != id) {
+       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 ()) {
+       if (i == _load_font_nodes.end ()) {
                return "";
        }
 
index 038ff1fa98b4fcf96316683948901d639a8b81e9..6a04bed3e44e4006ea385b35cf946e659d14c999 100644 (file)
@@ -55,6 +55,7 @@ public:
        int size;
        
        std::list<boost::shared_ptr<SubtitleNode> > subtitle_nodes;
+       std::list<boost::shared_ptr<FontNode> > font_nodes;
 };
 
 class LoadFontNode : public XMLNode
@@ -128,12 +129,16 @@ public:
        std::list<boost::shared_ptr<Subtitle> > subtitles_at (Time t) const;
 
 private:
-       std::string font_id_to_name (std::string id, std::list<boost::shared_ptr<LoadFontNode> > const & load_font_nodes) const;
+       std::string font_id_to_name (std::string id) const;
+       void examine_font_node (boost::shared_ptr<FontNode> font_node, std::list<boost::shared_ptr<FontNode> >& current_font_nodes);
+       std::string id_from_font_nodes (std::list<boost::shared_ptr<FontNode> > const & font_nodes) const;
+       int size_from_font_nodes (std::list<boost::shared_ptr<FontNode> > const & font_nodes) const;
        
        std::string _subtitle_id;
        std::string _movie_title;
        int64_t _reel_number;
        std::string _language;
+       std::list<boost::shared_ptr<LoadFontNode> > _load_font_nodes;
 
        std::list<boost::shared_ptr<Subtitle> > _subtitles;
 };
index 0f0d2d4764f3ed965e1e8eb55b880ce0f77cf524..08a43ea938d9c01f8c3ff06ee5b6969c42ac885b 100644 (file)
@@ -163,6 +163,17 @@ XMLNode::int64_attribute (string name)
        return lexical_cast<int64_t> (string_attribute (name));
 }
 
+int64_t
+XMLNode::optional_int64_attribute (string name)
+{
+       string const s = string_attribute (name);
+       if (s.empty ()) {
+               return 0;
+       }
+       
+       return lexical_cast<int64_t> (s);
+}
+
 void
 XMLNode::done ()
 {
index d7f6ad36c6bf202695c56bbb04dafe255d993e22..5ff5f614e4d239d9a1ca6a016e4795bacc94e4b5 100644 (file)
--- a/src/xml.h
+++ b/src/xml.h
@@ -38,6 +38,7 @@ protected:
        float float_attribute (std::string);
        std::string string_attribute (std::string);
        int64_t int64_attribute (std::string);
+       int64_t optional_int64_attribute (std::string);
 
        std::string content ();
 
index 3d56c3e7f5302cbb6c62242d7cb8f4cb950efc53..486db0bd09a2107a92641cbf7f9dd5a930c82cdf 100644 (file)
@@ -115,41 +115,6 @@ BOOST_AUTO_TEST_CASE (subtitles)
        libdcp::SubtitleAsset subs ("test/ref", "subs.xml");
 
        BOOST_CHECK_EQUAL (subs.language(), "French");
-//     BOOST_CHECK_EQUAL (subs.font_nodes().size(), 1);
-//     BOOST_CHECK_EQUAL (subs.font_nodes().front()->subtitle_nodes.size(), 4);
-
-#if 0  
-       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)->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)->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)->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)->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");
-#endif 
 
        list<shared_ptr<libdcp::Subtitle> > s = subs.subtitles_at (libdcp::Time (0, 0, 6, 1));
        BOOST_CHECK_EQUAL (s.size(), 1);
@@ -159,6 +124,21 @@ BOOST_AUTO_TEST_CASE (subtitles)
        BOOST_CHECK_EQUAL (s.front()->out(), libdcp::Time (0, 0, 7, 115));
        BOOST_CHECK_EQUAL (s.front()->font(), "Arial");
        BOOST_CHECK_EQUAL (s.front()->size_in_pixels(1080), 53);
+
+       s = subs.subtitles_at (libdcp::Time (0, 0, 7, 190));
+       BOOST_CHECK_EQUAL (s.size(), 2);
+       BOOST_CHECK_EQUAL (s.front()->text(), "My corset was H.M. The Queen's");
+       BOOST_CHECK_EQUAL (s.front()->v_position(), 21);
+       BOOST_CHECK_EQUAL (s.front()->in(), libdcp::Time (0, 0, 7, 177));
+       BOOST_CHECK_EQUAL (s.front()->out(), libdcp::Time (0, 0, 11, 31));
+       BOOST_CHECK_EQUAL (s.front()->font(), "Arial");
+       BOOST_CHECK_EQUAL (s.front()->size_in_pixels(1080), 53);
+       BOOST_CHECK_EQUAL (s.back()->text(), "My large wonderbra");
+       BOOST_CHECK_EQUAL (s.back()->v_position(), 15);
+       BOOST_CHECK_EQUAL (s.back()->in(), libdcp::Time (0, 0, 7, 177));
+       BOOST_CHECK_EQUAL (s.back()->out(), libdcp::Time (0, 0, 11, 31));
+       BOOST_CHECK_EQUAL (s.back()->font(), "Arial");
+       BOOST_CHECK_EQUAL (s.back()->size_in_pixels(1080), 53);
        
        s = subs.subtitles_at (libdcp::Time (0, 0, 11, 95));
        BOOST_CHECK_EQUAL (s.size(), 1);