summaryrefslogtreecommitdiff
path: root/src/interop_subtitle_asset.cc
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2015-06-04 16:48:08 +0100
committerCarl Hetherington <cth@carlh.net>2015-06-05 14:34:43 +0100
commit6c55e8d2c3b0129a19fc40dca344219021ad12ef (patch)
treecf9c3244ed55fb1fa8db89ca87923f3b7a6d35a1 /src/interop_subtitle_asset.cc
parent2105caa32a12236d5b70a0cf8b9ac62fcf7f574e (diff)
Rename some stuff Content -> Asset.
Diffstat (limited to 'src/interop_subtitle_asset.cc')
-rw-r--r--src/interop_subtitle_asset.cc239
1 files changed, 239 insertions, 0 deletions
diff --git a/src/interop_subtitle_asset.cc b/src/interop_subtitle_asset.cc
new file mode 100644
index 00000000..a6bdfcaf
--- /dev/null
+++ b/src/interop_subtitle_asset.cc
@@ -0,0 +1,239 @@
+/*
+ Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "interop_subtitle_asset.h"
+#include "interop_load_font_node.h"
+#include "xml.h"
+#include "raw_convert.h"
+#include "font_node.h"
+#include <libxml++/libxml++.h>
+#include <boost/foreach.hpp>
+#include <cmath>
+
+using std::list;
+using std::string;
+using std::cout;
+using boost::shared_ptr;
+using boost::optional;
+using boost::dynamic_pointer_cast;
+using namespace dcp;
+
+InteropSubtitleAsset::InteropSubtitleAsset (boost::filesystem::path file)
+ : SubtitleAsset (file)
+{
+ shared_ptr<cxml::Document> xml (new cxml::Document ("DCSubtitle"));
+ xml->read_file (file);
+ _id = xml->string_child ("SubtitleID");
+
+ _movie_title = xml->string_child ("MovieTitle");
+ _load_font_nodes = type_children<dcp::InteropLoadFontNode> (xml, "LoadFont");
+
+ list<cxml::NodePtr> f = xml->node_children ("Font");
+ list<shared_ptr<dcp::FontNode> > font_nodes;
+ BOOST_FOREACH (cxml::NodePtr& i, f) {
+ font_nodes.push_back (shared_ptr<FontNode> (new FontNode (i, 250)));
+ }
+
+ parse_common (xml, font_nodes);
+}
+
+InteropSubtitleAsset::InteropSubtitleAsset (string movie_title, string language)
+ : _movie_title (movie_title)
+{
+ _language = language;
+}
+
+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();
+ }
+};
+
+Glib::ustring
+InteropSubtitleAsset::xml_as_string () const
+{
+ xmlpp::Document doc;
+ xmlpp::Element* root = doc.create_root_node ("DCSubtitle");
+ root->set_attribute ("Version", "1.0");
+
+ root->add_child("SubtitleID")->add_child_text (_id);
+ root->add_child("MovieTitle")->add_child_text (_movie_title);
+ root->add_child("ReelNumber")->add_child_text (raw_convert<string> (_reel_number));
+ root->add_child("Language")->add_child_text (_language);
+
+ for (list<shared_ptr<InteropLoadFontNode> >::const_iterator i = _load_font_nodes.begin(); i != _load_font_nodes.end(); ++i) {
+ xmlpp::Element* load_font = root->add_child("LoadFont");
+ load_font->set_attribute ("Id", (*i)->id);
+ load_font->set_attribute ("URI", (*i)->uri);
+ }
+
+ 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");
+ 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");
+ subtitle_element->set_attribute ("SpotNumber", raw_convert<string> (spot_number++));
+ subtitle_element->set_attribute ("TimeIn", i->in().as_string());
+ subtitle_element->set_attribute ("TimeOut", i->out().as_string());
+ subtitle_element->set_attribute ("FadeUpTime", raw_convert<string> (i->fade_up_time().as_editable_units(250)));
+ subtitle_element->set_attribute ("FadeDownTime", raw_convert<string> (i->fade_down_time().as_editable_units(250)));
+
+ 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");
+ 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());
+ }
+
+ return doc.write_to_string_formatted ("UTF-8");
+}
+
+void
+InteropSubtitleAsset::add_font (string id, string uri)
+{
+ _load_font_nodes.push_back (shared_ptr<InteropLoadFontNode> (new InteropLoadFontNode (id, uri)));
+}
+
+bool
+InteropSubtitleAsset::equals (shared_ptr<const Asset> other_asset, EqualityOptions options, NoteHandler note) const
+{
+ if (!SubtitleAsset::equals (other_asset, options, note)) {
+ return false;
+ }
+
+ shared_ptr<const InteropSubtitleAsset> other = dynamic_pointer_cast<const InteropSubtitleAsset> (other_asset);
+ if (!other) {
+ return false;
+ }
+
+ list<shared_ptr<InteropLoadFontNode> >::const_iterator i = _load_font_nodes.begin ();
+ list<shared_ptr<InteropLoadFontNode> >::const_iterator j = other->_load_font_nodes.begin ();
+
+ while (i != _load_font_nodes.end ()) {
+ if (j == other->_load_font_nodes.end ()) {
+ note (DCP_ERROR, "<LoadFont> nodes differ");
+ return false;
+ }
+
+ if (**i != **j) {
+ note (DCP_ERROR, "<LoadFont> nodes differ");
+ return false;
+ }
+
+ ++i;
+ ++j;
+ }
+
+ if (_movie_title != other->_movie_title) {
+ note (DCP_ERROR, "Subtitle movie titles differ");
+ return false;
+ }
+
+ return true;
+}
+
+list<shared_ptr<LoadFontNode> >
+InteropSubtitleAsset::load_font_nodes () const
+{
+ list<shared_ptr<LoadFontNode> > lf;
+ copy (_load_font_nodes.begin(), _load_font_nodes.end(), back_inserter (lf));
+ return lf;
+}