From b0a9bc81744440404d68bcbdc8bda925a8a64597 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Wed, 14 Jan 2015 09:05:13 +0000 Subject: Fix subtitle parser to cope with Hello this is some italic text. The data structures are unable to cope, so hack it to use Pango markup in those cases (formatting changes during a line). --- src/subtitle_asset.cc | 110 +++++++++++++++++++++++--------------------------- src/subtitle_asset.h | 16 ++------ 2 files changed, 54 insertions(+), 72 deletions(-) (limited to 'src') diff --git a/src/subtitle_asset.cc b/src/subtitle_asset.cc index cc95d1a5..e5ef9cd2 100644 --- a/src/subtitle_asset.cc +++ b/src/subtitle_asset.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Carl Hetherington + Copyright (C) 2012-2015 Carl Hetherington 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 @@ -127,76 +127,50 @@ SubtitleAsset::read_xml (shared_ptr xml, bool smpte) tcr = xml->optional_number_child ("TimeCodeRate"); } - xml->ignore_child ("LoadFont"); - - list > font_nodes; - list f = xml->node_children ("Font"); - for (list::iterator i = f.begin(); i != f.end(); ++i) { - font_nodes.push_back (shared_ptr (new parse::Font (*i, tcr))); - } - _load_font_nodes = type_children (xml, "LoadFont"); /* Now make Subtitle objects to represent the raw XML nodes in a sane way. */ - shared_ptr subtitle_list = xml->optional_node_child ("SubtitleList"); - if (subtitle_list) { - list > font; - list f = subtitle_list->node_children ("Font"); - for (list::iterator i = f.begin(); i != f.end(); ++i) { - font_nodes.push_back (shared_ptr (new parse::Font (*i, tcr))); - } - } - ParseState parse_state; - examine_font_nodes (xml, font_nodes, parse_state); + parse_node (xml->node(), parse_state, tcr); } void -SubtitleAsset::examine_font_nodes ( - shared_ptr xml, - list > const & font_nodes, - ParseState& parse_state - ) +SubtitleAsset::parse_node (xmlpp::Node* node, ParseState& parse_state, optional tcr) { - for (list >::const_iterator i = font_nodes.begin(); i != font_nodes.end(); ++i) { - - parse_state.font_nodes.push_back (*i); - maybe_add_subtitle ((*i)->text, parse_state); - - for (list >::iterator j = (*i)->subtitle_nodes.begin(); j != (*i)->subtitle_nodes.end(); ++j) { - parse_state.subtitle_nodes.push_back (*j); - examine_text_nodes (xml, (*j)->text_nodes, parse_state); - examine_font_nodes (xml, (*j)->font_nodes, parse_state); - parse_state.subtitle_nodes.pop_back (); + xmlpp::Node::NodeList children = node->get_children (); + for (xmlpp::Node::NodeList::const_iterator i = children.begin(); i != children.end(); ++i) { + xmlpp::ContentNode* c = dynamic_cast (*i); + if (c) { + maybe_add_subtitle (c->get_content (), parse_state); } - - examine_font_nodes (xml, (*i)->font_nodes, parse_state); - examine_text_nodes (xml, (*i)->text_nodes, parse_state); - - parse_state.font_nodes.pop_back (); - } -} -void -SubtitleAsset::examine_text_nodes ( - shared_ptr xml, - list > const & text_nodes, - ParseState& parse_state - ) -{ - for (list >::const_iterator i = text_nodes.begin(); i != text_nodes.end(); ++i) { - parse_state.text_nodes.push_back (*i); - maybe_add_subtitle ((*i)->text, parse_state); - examine_font_nodes (xml, (*i)->font_nodes, parse_state); - parse_state.text_nodes.pop_back (); + xmlpp::Element* e = dynamic_cast (*i); + if (e) { + cxml::ConstNodePtr n (new cxml::Node (e)); + if (n->name() == "Font") { + parse_state.font_nodes.push_back (shared_ptr (new parse::Font (n, tcr))); + parse_node (e, parse_state, tcr); + parse_state.font_nodes.pop_back (); + } else if (n->name() == "Text") { + parse_state.text_nodes.push_back (shared_ptr (new parse::Text (n, tcr))); + parse_node (e, parse_state, tcr); + parse_state.text_nodes.pop_back (); + } else if (n->name() == "Subtitle") { + parse_state.subtitle_nodes.push_back (shared_ptr (new parse::Subtitle (n, tcr))); + parse_node (e, parse_state, tcr); + parse_state.subtitle_nodes.pop_back (); + } else if (n->name() == "SubtitleList") { + parse_node (e, parse_state, tcr); + } + } } } void -SubtitleAsset::maybe_add_subtitle (string text, ParseState const & parse_state) +SubtitleAsset::maybe_add_subtitle (string text, ParseState& parse_state) { if (empty_or_white_space (text)) { return; @@ -213,8 +187,18 @@ SubtitleAsset::maybe_add_subtitle (string text, ParseState const & parse_state) libdcp::parse::Text effective_text (*parse_state.text_nodes.back ()); libdcp::parse::Subtitle effective_subtitle (*parse_state.subtitle_nodes.back ()); - _subtitles.push_back ( - shared_ptr ( + cout << "Maybe add " << text << "\n"; + + shared_ptr c = parse_state.current; + if (!c || + effective_subtitle.in != c->in() || + effective_subtitle.out != c->out() || + effective_text.v_position != c->v_position() || + effective_text.v_align != c->v_align()) { + + cout << "(reset)\n"; + + parse_state.current.reset ( new Subtitle ( font_id_to_name (effective_font.id), effective_font.italic.get(), @@ -224,14 +208,22 @@ SubtitleAsset::maybe_add_subtitle (string text, ParseState const & parse_state) effective_subtitle.out, effective_text.v_position, effective_text.v_align, - text, + "", effective_font.effect ? effective_font.effect.get() : NONE, effective_font.effect_color.get(), effective_subtitle.fade_up_time, effective_subtitle.fade_down_time ) - ) - ); + ); + + _subtitles.push_back (parse_state.current); + } + + if (effective_font.italic.get()) { + parse_state.current->set_text (parse_state.current->text() + "" + text + ""); + } else { + parse_state.current->set_text (parse_state.current->text() + text); + } } list > diff --git a/src/subtitle_asset.h b/src/subtitle_asset.h index d7976bef..a5014307 100644 --- a/src/subtitle_asset.h +++ b/src/subtitle_asset.h @@ -180,21 +180,11 @@ private: std::list > font_nodes; std::list > text_nodes; std::list > subtitle_nodes; + boost::shared_ptr current; }; - void maybe_add_subtitle (std::string text, ParseState const & parse_state); - - void examine_font_nodes ( - boost::shared_ptr xml, - std::list > const & font_nodes, - ParseState& parse_state - ); - - void examine_text_nodes ( - boost::shared_ptr xml, - std::list > const & text_nodes, - ParseState& parse_state - ); + void parse_node (xmlpp::Node* node, ParseState& parse_state, boost::optional tcr); + void maybe_add_subtitle (std::string text, ParseState& parse_state); boost::optional _movie_title; /* strangely, this is sometimes a string */ -- cgit v1.2.3