/*
- Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2018 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
#include "interop_subtitle_asset.h"
#include "interop_load_font_node.h"
+#include "subtitle_asset_internal.h"
#include "xml.h"
#include "raw_convert.h"
#include "util.h"
#include "font_asset.h"
#include "dcp_assert.h"
+#include "subtitle_image.h"
#include <libxml++/libxml++.h>
#include <boost/foreach.hpp>
#include <cmath>
_reel_number = xml->string_child ("ReelNumber");
_language = xml->string_child ("Language");
_movie_title = xml->string_child ("MovieTitle");
- _load_font_nodes = type_children<dcp::InteropLoadFontNode> (xml, "LoadFont");
+ _load_font_nodes = type_children<InteropLoadFontNode> (xml, "LoadFont");
/* Now we need to drop down to xmlpp */
_file = p;
+ /* Image subtitles */
+ int n = 0;
+ BOOST_FOREACH (shared_ptr<dcp::Subtitle> i, _subtitles) {
+ shared_ptr<dcp::SubtitleImage> im = dynamic_pointer_cast<dcp::SubtitleImage> (i);
+ if (im) {
+ im->png_image().write (p.parent_path() / image_subtitle_file (n++));
+ }
+ }
+
+ /* Fonts */
BOOST_FOREACH (shared_ptr<InteropLoadFontNode> i, _load_font_nodes) {
boost::filesystem::path file = p.parent_path() / i->uri;
FILE* f = fopen_boost (file, "wb");
class write_interop_subtitle_test;
class write_interop_subtitle_test2;
+class write_interop_subtitle_test3;
class write_smpte_subtitle_test;
class write_smpte_subtitle_test2;
protected:
friend struct ::write_interop_subtitle_test;
friend struct ::write_interop_subtitle_test2;
+ friend struct ::write_interop_subtitle_test3;
friend struct ::write_smpte_subtitle_test;
friend struct ::write_smpte_subtitle_test2;
_v_position = p;
}
- void set_fade_up_time (dcp::Time t) {
+ void set_fade_up_time (Time t) {
_fade_up_time = t;
}
- void set_fade_down_time (dcp::Time t) {
+ void set_fade_down_time (Time t) {
_fade_down_time = t;
}
}
shared_ptr<SubtitleString> is = dynamic_pointer_cast<SubtitleString>(i);
-
if (is) {
if (!text ||
last_h_align != is->h_align() ||
text->children.push_back (shared_ptr<order::String> (new order::String (text, order::Font (is, standard), is->text())));
}
- /* XXX: image */
+ shared_ptr<SubtitleImage> ii = dynamic_pointer_cast<SubtitleImage>(i);
+ if (ii) {
+ text.reset ();
+ subtitle->children.push_back (
+ shared_ptr<order::Image> (new order::Image (subtitle, ii->png_image(), ii->h_align(), ii->h_position(), ii->v_align(), ii->v_position()))
+ );
+ }
}
/* Pull font changes as high up the hierarchy as we can */
context.time_code_rate = time_code_rate;
context.standard = standard;
context.spot_number = 1;
+ context.image_number = 0;
root->write_xml (xml_root, context);
}
#include "subtitle_asset_internal.h"
#include "subtitle_string.h"
+#include "compose.hpp"
#include <cmath>
using std::string;
}
}
-xmlpp::Element*
-order::Text::as_xml (xmlpp::Element* parent, Context& context) const
+static void
+position_align (xmlpp::Element* e, order::Context& context, HAlign h_align, float h_position, VAlign v_align, float v_position)
{
- xmlpp::Element* e = parent->add_child ("Text", context.xmlns());
-
- if (_h_align != HALIGN_CENTER) {
+ if (h_align != HALIGN_CENTER) {
if (context.standard == SMPTE) {
- e->set_attribute ("Halign", halign_to_string (_h_align));
+ e->set_attribute ("Halign", halign_to_string (h_align));
} else {
- e->set_attribute ("HAlign", halign_to_string (_h_align));
+ e->set_attribute ("HAlign", halign_to_string (h_align));
}
}
- if (fabs(_h_position) > ALIGN_EPSILON) {
+ if (fabs(h_position) > ALIGN_EPSILON) {
if (context.standard == SMPTE) {
- e->set_attribute ("Hposition", raw_convert<string> (_h_position * 100, 6));
+ e->set_attribute ("Hposition", raw_convert<string> (h_position * 100, 6));
} else {
- e->set_attribute ("HPosition", raw_convert<string> (_h_position * 100, 6));
+ e->set_attribute ("HPosition", raw_convert<string> (h_position * 100, 6));
}
}
if (context.standard == SMPTE) {
- e->set_attribute ("Valign", valign_to_string (_v_align));
+ e->set_attribute ("Valign", valign_to_string (v_align));
} else {
- e->set_attribute ("VAlign", valign_to_string (_v_align));
+ e->set_attribute ("VAlign", valign_to_string (v_align));
}
- if (fabs(_v_position) > ALIGN_EPSILON) {
+ if (fabs(v_position) > ALIGN_EPSILON) {
if (context.standard == SMPTE) {
- e->set_attribute ("Vposition", raw_convert<string> (_v_position * 100, 6));
+ e->set_attribute ("Vposition", raw_convert<string> (v_position * 100, 6));
} else {
- e->set_attribute ("VPosition", raw_convert<string> (_v_position * 100, 6));
+ e->set_attribute ("VPosition", raw_convert<string> (v_position * 100, 6));
}
} else {
if (context.standard == SMPTE) {
e->set_attribute ("VPosition", "0");
}
}
+}
+
+xmlpp::Element*
+order::Text::as_xml (xmlpp::Element* parent, Context& context) const
+{
+ xmlpp::Element* e = parent->add_child ("Text", context.xmlns());
+
+ position_align (e, context, _h_align, _h_position, _v_align, _v_position);
/* Interop only supports "horizontal" or "vertical" for direction, so only write this
for SMPTE.
{
_values.clear ();
}
+
+xmlpp::Element *
+order::Image::as_xml (xmlpp::Element* parent, Context& context) const
+{
+ xmlpp::Element* e = parent->add_child ("Image", context.xmlns());
+
+ position_align (e, context, _h_align, _h_position, _v_align, _v_position);
+ e->add_child_text (image_subtitle_file (context.image_number++));
+
+ return e;
+}
+
+string
+dcp::image_subtitle_file (int n)
+{
+ return String::compose ("sub_%1.png", n);
+}
#include "raw_convert.h"
#include "types.h"
#include "dcp_time.h"
+#include "data.h"
#include <libxml++/libxml++.h>
#include <boost/foreach.hpp>
int time_code_rate;
Standard standard;
int spot_number;
+ int image_number;
};
class Font
Time _fade_down;
};
+class Image : public Part
+{
+public:
+ Image (boost::shared_ptr<Part> parent, Data png_data, HAlign h_align, float h_position, VAlign v_align, float v_position)
+ : Part (parent)
+ , _png_data (png_data)
+ , _h_align (h_align)
+ , _h_position (h_position)
+ , _v_align (v_align)
+ , _v_position (v_position)
+ {}
+
+ xmlpp::Element* as_xml (xmlpp::Element* parent, Context& context) const;
+
+private:
+ Data _png_data;
+ HAlign _h_align;
+ float _h_position;
+ VAlign _v_align;
+ float _v_position;
+};
+
}
+
+std::string image_subtitle_file (int n);
+
}
#endif
_text = t;
}
- void set_colour (dcp::Colour c) {
+ void set_colour (Colour c) {
_colour = c;
}
_effect = e;
}
- void set_effect_colour (dcp::Colour c) {
+ void set_effect_colour (Colour c) {
_effect_colour = c;
}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<DCSubtitle Version="1.0"><SubtitleID>a6c58cff-3e1e-4b38-acec-a42224475ef6</SubtitleID><MovieTitle>Test</MovieTitle><ReelNumber>1</ReelNumber><Language>EN</Language><Subtitle SpotNumber="1" TimeIn="00:04:09:229" TimeOut="00:04:11:229" FadeUpTime="0" FadeDownTime="0"><Image VAlign="top" VPosition="80">sub_0.png</Image></Subtitle></DCSubtitle>
/*
- Copyright (C) 2015-2016 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2015-2018 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
#include "interop_subtitle_asset.h"
#include "smpte_subtitle_asset.h"
#include "subtitle_string.h"
+#include "subtitle_image.h"
#include "subtitle_asset_internal.h"
#include "test.h"
+#include "util.h"
#include <boost/test/unit_test.hpp>
using std::list;
);
}
+/* Write some subtitle content as Interop XML using bitmaps and check that it is right */
+BOOST_AUTO_TEST_CASE (write_interop_subtitle_test3)
+{
+ dcp::InteropSubtitleAsset c;
+ c.set_reel_number ("1");
+ c.set_language ("EN");
+ c.set_movie_title ("Test");
+
+ c.add (
+ shared_ptr<dcp::Subtitle> (
+ new dcp::SubtitleImage (
+ dcp::Data ("test/data/sub.png"),
+ dcp::Time (0, 4, 9, 22, 24),
+ dcp::Time (0, 4, 11, 22, 24),
+ 0,
+ dcp::HALIGN_CENTER,
+ 0.8,
+ dcp::VALIGN_TOP,
+ dcp::Time (0, 0, 0, 0, 24),
+ dcp::Time (0, 0, 0, 0, 24)
+ )
+ )
+ );
+
+ c._id = "a6c58cff-3e1e-4b38-acec-a42224475ef6";
+
+ boost::filesystem::create_directories ("build/test/write_interop_subtitle_test3");
+ c.write ("build/test/write_interop_subtitle_test3/subs.xml");
+
+ check_xml (
+ dcp::file_to_string("test/data/write_interop_subtitle_test3.xml"),
+ dcp::file_to_string("build/test/write_interop_subtitle_test3/subs.xml"),
+ list<string>()
+ );
+ check_file ("build/test/write_interop_subtitle_test3/sub_0.png", "test/data/sub.png");
+}
+
/* Write some subtitle content as SMPTE XML and check that it is right */
BOOST_AUTO_TEST_CASE (write_smpte_subtitle_test)
{