diff options
| author | Carl Hetherington <cth@carlh.net> | 2015-06-04 12:25:48 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2015-06-05 15:53:48 +0100 |
| commit | 42a65cba0d8da23c12af52015e66cd9dc0b5a5fa (patch) | |
| tree | ff0a017c49d0975f21a5314d2f77be20f68bd379 /src/subtitle_asset.cc | |
| parent | 943e75e0ac5730714f3823771f127fe78e4cf82b (diff) | |
Initial work on SMPTE subtitles.
Diffstat (limited to 'src/subtitle_asset.cc')
| -rw-r--r-- | src/subtitle_asset.cc | 147 |
1 files changed, 113 insertions, 34 deletions
diff --git a/src/subtitle_asset.cc b/src/subtitle_asset.cc index f1ecc939..1c341de4 100644 --- a/src/subtitle_asset.cc +++ b/src/subtitle_asset.cc @@ -43,14 +43,12 @@ using boost::dynamic_pointer_cast; using namespace dcp; SubtitleAsset::SubtitleAsset () - : _reel_number ("1") { } SubtitleAsset::SubtitleAsset (boost::filesystem::path file) : Asset (file) - , _reel_number ("1") { } @@ -58,13 +56,7 @@ SubtitleAsset::SubtitleAsset (boost::filesystem::path file) void SubtitleAsset::parse_common (shared_ptr<cxml::Document> xml, list<shared_ptr<dcp::FontNode> > font_nodes) { - _reel_number = xml->string_child ("ReelNumber"); - _language = xml->string_child ("Language"); - - /* Now make Subtitle objects to represent the raw XML nodes - in a sane way. - */ - + /* Make Subtitle objects to represent the raw XML nodes in a sane way */ ParseState parse_state; examine_font_nodes (xml, font_nodes, parse_state); } @@ -169,21 +161,6 @@ SubtitleAsset::add (SubtitleString s) _subtitles.push_back (s); } -void -SubtitleAsset::write_xml (boost::filesystem::path p) const -{ - FILE* f = fopen_boost (p, "w"); - if (!f) { - throw FileError ("Could not open file for writing", p, -1); - } - - Glib::ustring const s = xml_as_string (); - fwrite (s.c_str(), 1, s.bytes(), f); - fclose (f); - - _file = p; -} - Time SubtitleAsset::latest_subtitle_out () const { @@ -209,16 +186,6 @@ SubtitleAsset::equals (shared_ptr<const Asset> other_asset, EqualityOptions opti return false; } - if (_reel_number != other->_reel_number) { - note (DCP_ERROR, "subtitle reel numbers differ"); - return false; - } - - if (_language != other->_language) { - note (DCP_ERROR, "subtitle languages differ"); - return false; - } - if (_subtitles != other->_subtitles) { note (DCP_ERROR, "subtitles differ"); return false; @@ -226,3 +193,115 @@ SubtitleAsset::equals (shared_ptr<const Asset> other_asset, EqualityOptions opti return true; } + +struct SubtitleSorter { + bool operator() (SubtitleString const & a, SubtitleString const & b) { + if (a.in() != b.in()) { + return a.in() < b.in(); + } + return a.v_position() < b.v_position(); + } +}; + +void +SubtitleAsset::subtitles_as_xml (xmlpp::Element* root, int time_code_rate, string xmlns) const +{ + list<SubtitleString> sorted = _subtitles; + sorted.sort (SubtitleSorter ()); + + /* XXX: script, underlined, weight not supported */ + + optional<string> font; + bool italic = false; + Colour colour; + int size = 0; + float aspect_adjust = 1.0; + Effect effect = NONE; + Colour effect_colour; + int spot_number = 1; + Time last_in; + Time last_out; + Time last_fade_up_time; + Time last_fade_down_time; + + xmlpp::Element* font_element = 0; + xmlpp::Element* subtitle_element = 0; + + for (list<SubtitleString>::iterator i = sorted.begin(); i != sorted.end(); ++i) { + + /* We will start a new <Font>...</Font> whenever some font property changes. + I suppose we should really make an optimal hierarchy of <Font> tags, but + that seems hard. + */ + + bool const font_changed = + font != i->font() || + italic != i->italic() || + colour != i->colour() || + size != i->size() || + fabs (aspect_adjust - i->aspect_adjust()) > ASPECT_ADJUST_EPSILON || + effect != i->effect() || + effect_colour != i->effect_colour(); + + if (font_changed) { + font = i->font (); + italic = i->italic (); + colour = i->colour (); + size = i->size (); + aspect_adjust = i->aspect_adjust (); + effect = i->effect (); + effect_colour = i->effect_colour (); + } + + if (!font_element || font_changed) { + font_element = root->add_child ("Font", xmlns); + if (font) { + font_element->set_attribute ("Id", font.get ()); + } + font_element->set_attribute ("Italic", italic ? "yes" : "no"); + font_element->set_attribute ("Color", colour.to_argb_string()); + font_element->set_attribute ("Size", raw_convert<string> (size)); + if (fabs (aspect_adjust - 1.0) > ASPECT_ADJUST_EPSILON) { + font_element->set_attribute ("AspectAdjust", raw_convert<string> (aspect_adjust)); + } + font_element->set_attribute ("Effect", effect_to_string (effect)); + font_element->set_attribute ("EffectColor", effect_colour.to_argb_string()); + font_element->set_attribute ("Script", "normal"); + font_element->set_attribute ("Underlined", "no"); + font_element->set_attribute ("Weight", "normal"); + } + + if (!subtitle_element || font_changed || + (last_in != i->in() || + last_out != i->out() || + last_fade_up_time != i->fade_up_time() || + last_fade_down_time != i->fade_down_time() + )) { + + subtitle_element = font_element->add_child ("Subtitle", xmlns); + subtitle_element->set_attribute ("SpotNumber", raw_convert<string> (spot_number++)); + subtitle_element->set_attribute ("TimeIn", i->in().rebase(time_code_rate).as_string()); + subtitle_element->set_attribute ("TimeOut", i->out().rebase(time_code_rate).as_string()); + subtitle_element->set_attribute ("FadeUpTime", raw_convert<string> (i->fade_up_time().as_editable_units(time_code_rate))); + subtitle_element->set_attribute ("FadeDownTime", raw_convert<string> (i->fade_down_time().as_editable_units(time_code_rate))); + + last_in = i->in (); + last_out = i->out (); + last_fade_up_time = i->fade_up_time (); + last_fade_down_time = i->fade_down_time (); + } + + xmlpp::Element* text = subtitle_element->add_child ("Text", xmlns); + if (i->h_align() != HALIGN_CENTER) { + text->set_attribute ("HAlign", halign_to_string (i->h_align ())); + } + if (i->h_position() > ALIGN_EPSILON) { + text->set_attribute ("HPosition", raw_convert<string> (i->h_position() * 100, 6)); + } + text->set_attribute ("VAlign", valign_to_string (i->v_align())); + text->set_attribute ("VPosition", raw_convert<string> (i->v_position() * 100, 6)); + text->add_child_text (i->text()); + } +} + + |
