2 Copyright (C) 2015-2021 Carl Hetherington <cth@carlh.net>
4 This file is part of libdcp.
6 libdcp is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 libdcp is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with libdcp. If not, see <http://www.gnu.org/licenses/>.
19 In addition, as a special exception, the copyright holders give
20 permission to link the code of portions of this program with the
21 OpenSSL library under certain conditions as described in each
22 individual source file, and distribute linked combinations
25 You must obey the GNU General Public License in all respects
26 for all of the code used other than OpenSSL. If you modify
27 file(s) with this exception, you may extend this exception to your
28 version of the file(s), but you are not obligated to do so. If you
29 do not wish to do so, delete this exception statement from your
30 version. If you delete this exception statement from all source
31 files in the program, then also delete it here.
34 #include "interop_subtitle_asset.h"
35 #include "smpte_subtitle_asset.h"
36 #include "subtitle_string.h"
37 #include "subtitle_image.h"
38 #include "subtitle_asset_internal.h"
39 #include "reel_interop_subtitle_asset.h"
45 #include <boost/test/unit_test.hpp>
48 using std::shared_ptr;
50 using std::make_shared;
51 using boost::optional;
53 /** Test dcp::order::Font::take_intersection */
54 BOOST_AUTO_TEST_CASE (take_intersection_test)
57 A._values["foo"] = "bar";
58 A._values["fred"] = "jim";
61 B._values["foo"] = "bar";
62 B._values["sheila"] = "baz";
64 A.take_intersection (B);
65 BOOST_REQUIRE_EQUAL (A._values.size(), 1);
66 BOOST_CHECK_EQUAL (A._values["foo"], "bar");
71 A._values["foo"] = "bar";
72 A._values["fred"] = "jim";
74 B._values["foo"] = "hello";
75 B._values["sheila"] = "baz";
77 A.take_intersection (B);
78 BOOST_CHECK_EQUAL (A._values.size(), 0);
81 /** Test dcp::order::Font::take_difference */
82 BOOST_AUTO_TEST_CASE (take_difference_test)
85 A._values["foo"] = "bar";
86 A._values["fred"] = "jim";
89 B._values["foo"] = "bar";
90 B._values["sheila"] = "baz";
92 A.take_difference (B);
93 BOOST_REQUIRE_EQUAL (A._values.size(), 1);
94 BOOST_CHECK_EQUAL (A._values["fred"], "jim");
97 /** Test dcp::order::Subtitle::pull_fonts */
98 BOOST_AUTO_TEST_CASE (pull_fonts_test1)
100 auto root = make_shared<dcp::order::Part>(shared_ptr<dcp::order::Part>());
101 auto sub1 = make_shared<dcp::order::Subtitle>(root, dcp::Time(), dcp::Time(), dcp::Time(), dcp::Time());
102 root->children.push_back (sub1);
103 auto text1 = make_shared<dcp::order::Text>(sub1, dcp::HAlign::CENTER, 0, dcp::VAlign::TOP, 0, dcp::Direction::LTR);
104 sub1->children.push_back (text1);
105 text1->font._values["font"] = "Inconsolata";
106 text1->font._values["size"] = "42";
108 dcp::SubtitleAsset::pull_fonts (root);
110 BOOST_REQUIRE_EQUAL (sub1->font._values.size(), 2);
111 BOOST_CHECK_EQUAL (sub1->font._values["font"], "Inconsolata");
112 BOOST_CHECK_EQUAL (sub1->font._values["size"], "42");
113 BOOST_CHECK_EQUAL (text1->font._values.size(), 0);
116 /** Test dcp::order::Subtitle::pull_fonts */
117 BOOST_AUTO_TEST_CASE (pull_fonts_test2)
119 auto root = make_shared<dcp::order::Part>(shared_ptr<dcp::order::Part> ());
120 auto sub1 = make_shared<dcp::order::Subtitle>(root, dcp::Time(), dcp::Time(), dcp::Time(), dcp::Time());
121 root->children.push_back (sub1);
122 auto text1 = make_shared<dcp::order::Text>(sub1, dcp::HAlign::CENTER, 0, dcp::VAlign::TOP, 0, dcp::Direction::LTR);
123 sub1->children.push_back (text1);
124 text1->font._values["font"] = "Inconsolata";
125 text1->font._values["size"] = "42";
126 auto text2 = make_shared<dcp::order::Text>(sub1, dcp::HAlign::CENTER, 0, dcp::VAlign::TOP, 0, dcp::Direction::LTR);
127 sub1->children.push_back (text2);
128 text2->font._values["font"] = "Inconsolata";
129 text2->font._values["size"] = "48";
131 dcp::SubtitleAsset::pull_fonts (root);
133 BOOST_REQUIRE_EQUAL (sub1->font._values.size(), 1);
134 BOOST_CHECK_EQUAL (sub1->font._values["font"], "Inconsolata");
135 BOOST_REQUIRE_EQUAL (text1->font._values.size(), 1);
136 BOOST_CHECK_EQUAL (text1->font._values["size"], "42");
137 BOOST_REQUIRE_EQUAL (text2->font._values.size(), 1);
138 BOOST_CHECK_EQUAL (text2->font._values["size"], "48");
141 /** Test dcp::order::Subtitle::pull_fonts */
142 BOOST_AUTO_TEST_CASE (pull_fonts_test3)
144 auto root = make_shared<dcp::order::Part>(shared_ptr<dcp::order::Part> ());
145 auto sub1 = make_shared<dcp::order::Subtitle>(root, dcp::Time(), dcp::Time(), dcp::Time(), dcp::Time());
146 root->children.push_back (sub1);
147 auto text1 = make_shared<dcp::order::Text>(sub1, dcp::HAlign::CENTER, 0, dcp::VAlign::TOP, 0, dcp::Direction::LTR);
148 sub1->children.push_back (text1);
149 dcp::order::Font font;
150 font._values["font"] = "Inconsolata";
151 font._values["size"] = "42";
152 auto string1 = make_shared<dcp::order::String>(text1, font, "Hello world");
153 text1->children.push_back (string1);
155 dcp::SubtitleAsset::pull_fonts (root);
157 BOOST_REQUIRE_EQUAL (sub1->font._values.size(), 2);
158 BOOST_CHECK_EQUAL (sub1->font._values["font"], "Inconsolata");
159 BOOST_CHECK_EQUAL (sub1->font._values["size"], "42");
162 /** Write some subtitle content as Interop XML and check that it is right */
163 BOOST_AUTO_TEST_CASE (write_interop_subtitle_test)
165 dcp::InteropSubtitleAsset c;
166 c.set_reel_number ("1");
167 c.set_language ("EN");
168 c.set_movie_title ("Test");
171 make_shared<dcp::SubtitleString>(
176 dcp::Colour (255, 255, 255),
179 dcp::Time (0, 4, 9, 22, 24),
180 dcp::Time (0, 4, 11, 22, 24),
188 dcp::Colour (0, 0, 0),
189 dcp::Time (0, 0, 0, 0, 24),
190 dcp::Time (0, 0, 0, 0, 24)
195 make_shared<dcp::SubtitleString>(
196 boost::optional<string> (),
200 dcp::Colour (128, 0, 64),
203 dcp::Time (5, 41, 0, 21, 24),
204 dcp::Time (6, 12, 15, 21, 24),
212 dcp::Colour (1, 2, 3),
213 dcp::Time (1, 2, 3, 4, 24),
214 dcp::Time (5, 6, 7, 8, 24)
218 c._id = "a6c58cff-3e1e-4b38-acec-a42224475ef6";
221 "<DCSubtitle Version=\"1.0\">"
222 "<SubtitleID>a6c58cff-3e1e-4b38-acec-a42224475ef6</SubtitleID>"
223 "<MovieTitle>Test</MovieTitle>"
224 "<ReelNumber>1</ReelNumber>"
225 "<Language>EN</Language>"
226 "<Font AspectAdjust=\"1.0\" Color=\"FFFFFFFF\" Effect=\"none\" EffectColor=\"FF000000\" Id=\"Frutiger\" Italic=\"no\" Script=\"normal\" Size=\"48\" Underlined=\"no\" Weight=\"normal\">"
227 "<Subtitle SpotNumber=\"1\" TimeIn=\"00:04:09:229\" TimeOut=\"00:04:11:229\" FadeUpTime=\"0\" FadeDownTime=\"0\">"
228 "<Text VAlign=\"top\" VPosition=\"80\">Hello world</Text>"
231 "<Font AspectAdjust=\"1.0\" Color=\"FF800040\" Effect=\"border\" EffectColor=\"FF010203\" Italic=\"yes\" Script=\"normal\" Size=\"91\" Underlined=\"yes\" Weight=\"bold\">"
232 "<Subtitle SpotNumber=\"2\" TimeIn=\"05:41:00:219\" TimeOut=\"06:12:15:219\" FadeUpTime=\"930792\" FadeDownTime=\"4591834\">"
233 "<Text VAlign=\"bottom\" VPosition=\"40\">What's going on</Text>"
242 /** Write some subtitle content as Interop XML and check that it is right.
243 * This test includes some horizontal alignment.
245 BOOST_AUTO_TEST_CASE (write_interop_subtitle_test2)
247 dcp::InteropSubtitleAsset c;
248 c.set_reel_number ("1");
249 c.set_language ("EN");
250 c.set_movie_title ("Test");
253 make_shared<dcp::SubtitleString>(
258 dcp::Colour (255, 255, 255),
261 dcp::Time (0, 4, 9, 22, 24),
262 dcp::Time (0, 4, 11, 22, 24),
270 dcp::Colour (0, 0, 0),
271 dcp::Time (0, 0, 0, 0, 24),
272 dcp::Time (0, 0, 0, 0, 24)
277 make_shared<dcp::SubtitleString>(
278 boost::optional<string>(),
282 dcp::Colour (128, 0, 64),
285 dcp::Time (5, 41, 0, 21, 24),
286 dcp::Time (6, 12, 15, 21, 24),
294 dcp::Colour (1, 2, 3),
295 dcp::Time (1, 2, 3, 4, 24),
296 dcp::Time (5, 6, 7, 8, 24)
300 c._id = "a6c58cff-3e1e-4b38-acec-a42224475ef6";
303 "<DCSubtitle Version=\"1.0\">"
304 "<SubtitleID>a6c58cff-3e1e-4b38-acec-a42224475ef6</SubtitleID>"
305 "<MovieTitle>Test</MovieTitle>"
306 "<ReelNumber>1</ReelNumber>"
307 "<Language>EN</Language>"
308 "<Font AspectAdjust=\"1.0\" Color=\"FFFFFFFF\" Effect=\"none\" EffectColor=\"FF000000\" Id=\"Frutiger\" Italic=\"no\" Script=\"normal\" Size=\"48\" Underlined=\"no\" Weight=\"normal\">"
309 "<Subtitle SpotNumber=\"1\" TimeIn=\"00:04:09:229\" TimeOut=\"00:04:11:229\" FadeUpTime=\"0\" FadeDownTime=\"0\">"
310 "<Text HPosition=\"-20\" VAlign=\"top\" VPosition=\"80\">Hello world</Text>"
313 "<Font AspectAdjust=\"1.0\" Color=\"FF800040\" Effect=\"border\" EffectColor=\"FF010203\" Italic=\"yes\" Script=\"normal\" Size=\"91\" Underlined=\"yes\" Weight=\"bold\">"
314 "<Subtitle SpotNumber=\"2\" TimeIn=\"05:41:00:219\" TimeOut=\"06:12:15:219\" FadeUpTime=\"930792\" FadeDownTime=\"4591834\">"
315 "<Text HPosition=\"-20\" VAlign=\"bottom\" VPosition=\"40\">What's going on</Text>"
324 /* Write some subtitle content as Interop XML using bitmaps and check that it is right */
325 BOOST_AUTO_TEST_CASE (write_interop_subtitle_test3)
329 auto c = make_shared<dcp::InteropSubtitleAsset>();
330 c->set_reel_number ("1");
331 c->set_language ("EN");
332 c->set_movie_title ("Test");
335 make_shared<dcp::SubtitleImage>(
336 dcp::ArrayData ("test/data/sub.png"),
337 dcp::Time (0, 4, 9, 22, 24),
338 dcp::Time (0, 4, 11, 22, 24),
343 dcp::Time (0, 0, 0, 0, 24),
344 dcp::Time (0, 0, 0, 0, 24)
348 c->_id = "a6c58cff-3e1e-4b38-acec-a42224475ef6";
349 boost::filesystem::remove_all ("build/test/write_interop_subtitle_test3");
350 boost::filesystem::create_directories ("build/test/write_interop_subtitle_test3");
351 c->write ("build/test/write_interop_subtitle_test3/subs.xml");
353 auto reel = make_shared<dcp::Reel>();
354 reel->add(make_shared<dcp::ReelInteropSubtitleAsset>(c, dcp::Fraction(24, 1), 6046, 0));
356 string const issue_date = "2018-09-02T04:45:18+00:00";
357 string const issuer = "libdcp";
358 string const creator = "libdcp";
359 string const annotation_text = "Created by libdcp";
361 auto cpl = make_shared<dcp::CPL>("My film", dcp::ContentKind::FEATURE, dcp::Standard::INTEROP);
363 cpl->set_issuer (issuer);
364 cpl->set_creator (creator);
365 cpl->set_issue_date (issue_date);
366 cpl->set_annotation_text (annotation_text);
367 auto cv = cpl->content_version();
369 cv->label_text = "foo";
370 cpl->set_content_version (*cv);
372 dcp::DCP dcp ("build/test/write_interop_subtitle_test3");
374 dcp.write_xml (issuer, creator, issue_date, annotation_text);
377 dcp::file_to_string("test/ref/write_interop_subtitle_test3/subs.xml"),
378 dcp::file_to_string("build/test/write_interop_subtitle_test3/subs.xml"),
381 check_file ("build/test/write_interop_subtitle_test3/d36f4bb3-c4fa-4a95-9915-6fec3110cd71.png", "test/data/sub.png");
384 dcp::file_to_string("test/ref/write_interop_subtitle_test3/ASSETMAP"),
385 dcp::file_to_string("build/test/write_interop_subtitle_test3/ASSETMAP"),
390 dcp::file_to_string("test/ref/write_interop_subtitle_test3/pkl.xml"),
391 dcp::file_to_string("build/test/write_interop_subtitle_test3/pkl_6a9e31a6-50a4-4ecb-8683-fa667848470a.xml"),