+ read_xml (path().string());
+}
+
+SubtitleAsset::SubtitleAsset (string directory, string movie_title, string language)
+ : Asset (directory)
+ , _movie_title (movie_title)
+ , _reel_number ("1")
+ , _language (language)
+ , _need_sort (false)
+{
+
+}
+
+void
+SubtitleAsset::read_xml (string xml_file)
+{
+ shared_ptr<cxml::Document> xml (new cxml::Document ("DCSubtitle"));
+ xml->read_file (xml_file);
+
+ _uuid = xml->string_child ("SubtitleID");
+ _movie_title = xml->string_child ("MovieTitle");
+ _reel_number = xml->string_child ("ReelNumber");
+ _language = xml->string_child ("Language");
+
+ xml->ignore_child ("LoadFont");
+
+ list<shared_ptr<libdcp::parse::Font> > font_nodes = type_children<libdcp::parse::Font> (xml, "Font");
+ _load_font_nodes = type_children<libdcp::parse::LoadFont> (xml, "LoadFont");
+
+ /* Now make Subtitle objects to represent the raw XML nodes
+ in a sane way.
+ */
+
+ ParseState parse_state;
+ examine_font_nodes (xml, font_nodes, parse_state);
+}
+
+void
+SubtitleAsset::examine_font_nodes (
+ shared_ptr<const cxml::Node> xml,
+ list<shared_ptr<libdcp::parse::Font> > const & font_nodes,
+ ParseState& parse_state
+ )
+{
+ for (list<shared_ptr<libdcp::parse::Font> >::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<shared_ptr<libdcp::parse::Subtitle> >::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 ();
+ }
+
+ 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<const cxml::Node> xml,
+ list<shared_ptr<libdcp::parse::Text> > const & text_nodes,
+ ParseState& parse_state
+ )
+{
+ for (list<shared_ptr<libdcp::parse::Text> >::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 ();
+ }
+}
+
+void
+SubtitleAsset::maybe_add_subtitle (string text, ParseState const & parse_state)
+{
+ if (empty_or_white_space (text)) {
+ return;
+ }
+
+ if (parse_state.text_nodes.empty() || parse_state.subtitle_nodes.empty ()) {
+ return;
+ }
+
+ assert (!parse_state.text_nodes.empty ());
+ assert (!parse_state.subtitle_nodes.empty ());
+
+ libdcp::parse::Font effective_font (parse_state.font_nodes);
+ 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<Subtitle> (
+ new Subtitle (
+ font_id_to_name (effective_font.id),
+ effective_font.italic.get(),
+ effective_font.color.get(),
+ effective_font.size,
+ effective_subtitle.in,
+ 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
+ )
+ )
+ );
+}
+
+list<shared_ptr<Subtitle> >
+SubtitleAsset::subtitles_at (Time t) const
+{
+ 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 s;
+}
+
+std::string
+SubtitleAsset::font_id_to_name (string id) const
+{
+ list<shared_ptr<libdcp::parse::LoadFont> >::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 "";
+}