2 Copyright (C) 2012-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.
35 #include "interop_subtitle_asset.h"
36 #include "interop_load_font_node.h"
37 #include "reel_interop_subtitle_asset.h"
38 #include "subtitle_string.h"
39 #include "subtitle_image.h"
41 #include <boost/test/unit_test.hpp>
45 using std::dynamic_pointer_cast;
46 using std::shared_ptr;
51 /** Load some subtitle content from Interop XML and check that it is read correctly */
52 BOOST_AUTO_TEST_CASE (read_interop_subtitle_test1)
54 dcp::InteropSubtitleAsset subs ("test/data/subs1.xml");
56 BOOST_CHECK_EQUAL (subs.id(), "cab5c268-222b-41d2-88ae-6d6999441b17");
57 BOOST_CHECK_EQUAL (subs.movie_title(), "Movie Title");
58 BOOST_CHECK_EQUAL (subs.reel_number(), "1");
59 BOOST_CHECK_EQUAL (subs.language(), "French");
61 auto lfn = subs.load_font_nodes ();
62 BOOST_REQUIRE_EQUAL (lfn.size(), 1U);
63 shared_ptr<dcp::InteropLoadFontNode> interop_lfn = dynamic_pointer_cast<dcp::InteropLoadFontNode> (lfn.front ());
64 BOOST_REQUIRE (interop_lfn);
65 BOOST_CHECK_EQUAL (interop_lfn->id, "theFontId");
66 BOOST_CHECK_EQUAL (interop_lfn->uri, "arial.ttf");
68 auto s = subs.subtitles_during (dcp::Time (0, 0, 6, 1, 250), dcp::Time (0, 0, 6, 2, 250), false);
69 BOOST_REQUIRE_EQUAL (s.size(), 2U);
70 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
71 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
76 dcp::Colour (255, 255, 255),
79 dcp::Time (0, 0, 5, 198, 250),
80 dcp::Time (0, 0, 7, 115, 250),
89 dcp::Colour (0, 0, 0),
90 dcp::Time (0, 0, 0, 1, 250),
91 dcp::Time (0, 0, 0, 1, 250),
94 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
95 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
100 dcp::Colour (255, 255, 255),
103 dcp::Time (0, 0, 5, 198, 250),
104 dcp::Time (0, 0, 7, 115, 250),
113 dcp::Colour (0, 0, 0),
114 dcp::Time (0, 0, 0, 1, 250),
115 dcp::Time (0, 0, 0, 1, 250),
119 s = subs.subtitles_during (dcp::Time (0, 0, 7, 190, 250), dcp::Time (0, 0, 7, 191, 250), false);
120 BOOST_REQUIRE_EQUAL (s.size(), 2U);
121 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
122 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
123 string ("theFontId"),
127 dcp::Colour (255, 255, 255),
130 dcp::Time (0, 0, 7, 177, 250),
131 dcp::Time (0, 0, 11, 31, 250),
138 "My corset was H.M. The Queen's",
140 dcp::Colour (0, 0, 0),
141 dcp::Time (0, 0, 0, 1, 250),
142 dcp::Time (0, 0, 0, 1, 250),
145 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
146 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
147 string ("theFontId"),
151 dcp::Colour (255, 255, 255),
154 dcp::Time (0, 0, 7, 177, 250),
155 dcp::Time (0, 0, 11, 31, 250),
162 "My large wonderbra",
164 dcp::Colour (0, 0, 0),
165 dcp::Time (0, 0, 0, 1, 250),
166 dcp::Time (0, 0, 0, 1, 250),
170 s = subs.subtitles_during (dcp::Time (0, 0, 11, 95, 250), dcp::Time (0, 0, 11, 96, 250), false);
171 BOOST_REQUIRE_EQUAL (s.size(), 1U);
172 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
173 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
174 string ("theFontId"),
178 dcp::Colour (255, 255, 255),
181 dcp::Time (0, 0, 11, 94, 250),
182 dcp::Time (0, 0, 13, 63, 250),
189 "Once belonged to the Shah",
191 dcp::Colour (0, 0, 0),
192 dcp::Time (0, 0, 0, 1, 250),
193 dcp::Time (0, 0, 0, 1, 250),
197 s = subs.subtitles_during (dcp::Time (0, 0, 14, 42, 250), dcp::Time (0, 0, 14, 43, 250), false);
198 BOOST_REQUIRE_EQUAL (s.size(), 1U);
199 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
200 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
201 string ("theFontId"),
205 dcp::Colour (255, 255, 255),
208 dcp::Time (0, 0, 13, 104, 250),
209 dcp::Time (0, 0, 15, 177, 250),
216 "And these are Roy Hattersley's jeans",
218 dcp::Colour (0, 0, 0),
219 dcp::Time (0, 0, 0, 1, 250),
220 dcp::Time (0, 0, 0, 1, 250),
225 /** And similarly for another one */
226 BOOST_AUTO_TEST_CASE (read_interop_subtitle_test2)
228 dcp::InteropSubtitleAsset subs ("test/data/subs2.xml");
230 auto s = subs.subtitles_during (dcp::Time (0, 0, 42, 100, 250), dcp::Time (0, 0, 42, 101, 250), false);
231 BOOST_REQUIRE_EQUAL (s.size(), 2U);
232 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
233 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
238 dcp::Colour (255, 255, 255),
241 dcp::Time (0, 0, 41, 62, 250),
242 dcp::Time (0, 0, 43, 52, 250),
249 "At afternoon tea with John Peel",
251 dcp::Colour (0, 0, 0),
252 dcp::Time (0, 0, 0, 0, 250),
253 dcp::Time (0, 0, 0, 0, 250),
256 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
257 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
262 dcp::Colour (255, 255, 255),
265 dcp::Time (0, 0, 41, 62, 250),
266 dcp::Time (0, 0, 43, 52, 250),
273 "I enquired if his accent was real",
275 dcp::Colour (0, 0, 0),
276 dcp::Time (0, 0, 0, 0, 250),
277 dcp::Time (0, 0, 0, 0, 250),
281 s = subs.subtitles_during (dcp::Time (0, 0, 50, 50, 250), dcp::Time (0, 0, 50, 51, 250), false);
282 BOOST_REQUIRE_EQUAL (s.size(), 2U);
283 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
284 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
289 dcp::Colour (255, 255, 255),
292 dcp::Time (0, 0, 50, 42, 250),
293 dcp::Time (0, 0, 52, 21, 250),
300 "He said \"out of the house",
302 dcp::Colour (0, 0, 0),
303 dcp::Time (0, 0, 0, 0, 250),
304 dcp::Time (0, 0, 0, 0, 250),
307 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
308 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
313 dcp::Colour (255, 255, 255),
316 dcp::Time (0, 0, 50, 42, 250),
317 dcp::Time (0, 0, 52, 21, 250),
324 "I'm incredibly scouse",
326 dcp::Colour (0, 0, 0),
327 dcp::Time (0, 0, 0, 0, 250),
328 dcp::Time (0, 0, 0, 0, 250),
332 s = subs.subtitles_during (dcp::Time (0, 1, 2, 300, 250), dcp::Time (0, 1, 2, 301, 250), false);
333 BOOST_REQUIRE_EQUAL (s.size(), 2U);
334 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
335 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
340 dcp::Colour(255, 255, 255),
343 dcp::Time(0, 1, 2, 208, 250),
344 dcp::Time(0, 1, 4, 10, 250),
351 "At home it depends how I feel.\"",
353 dcp::Colour(0, 0, 0),
354 dcp::Time(0, 0, 0, 0, 250),
355 dcp::Time(0, 0, 0, 0, 250),
358 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
359 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
364 dcp::Colour(255, 255, 255),
367 dcp::Time(0, 1, 2, 208, 250),
368 dcp::Time(0, 1, 4, 10, 250),
375 "I spent a long weekend in Brighton",
377 dcp::Colour(0, 0, 0),
378 dcp::Time(0, 0, 0, 0, 250),
379 dcp::Time(0, 0, 0, 0, 250),
383 s = subs.subtitles_during (dcp::Time (0, 1, 15, 50, 250), dcp::Time (0, 1, 15, 51, 250), false);
384 BOOST_REQUIRE_EQUAL (s.size(), 2U);
385 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
386 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
391 dcp::Colour(255, 255, 255),
394 dcp::Time(0, 1, 15, 42, 250),
395 dcp::Time(0, 1, 16, 42, 250),
402 "With the legendary Miss Enid Blyton",
404 dcp::Colour(0, 0, 0),
405 dcp::Time(0, 0, 0, 0, 250),
406 dcp::Time(0, 0, 0, 0, 250),
409 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
410 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
415 dcp::Colour(255, 255, 255),
418 dcp::Time(0, 1, 15, 42, 250),
419 dcp::Time(0, 1, 16, 42, 250),
426 "She said \"you be Noddy",
428 dcp::Colour(0, 0, 0),
429 dcp::Time(0, 0, 0, 0, 250),
430 dcp::Time(0, 0, 0, 0, 250),
434 s = subs.subtitles_during (dcp::Time (0, 1, 27, 200, 250), dcp::Time (0, 1, 27, 201, 250), false);
435 BOOST_REQUIRE_EQUAL (s.size(), 2U);
436 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
437 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
442 dcp::Colour(255, 255, 255),
445 dcp::Time(0, 1, 27, 115, 250),
446 dcp::Time(0, 1, 28, 208, 250),
453 "That curious creature the Sphinx",
455 dcp::Colour(0, 0, 0),
456 dcp::Time(0, 0, 0, 0, 250),
457 dcp::Time(0, 0, 0, 0, 250),
460 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
461 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
466 dcp::Colour(255, 255, 255),
469 dcp::Time(0, 1, 27, 115, 250),
470 dcp::Time(0, 1, 28, 208, 250),
477 "Is smarter than anyone thinks",
479 dcp::Colour(0, 0, 0),
480 dcp::Time(0, 0, 0, 0, 250),
481 dcp::Time(0, 0, 0, 0, 250),
485 s = subs.subtitles_during (dcp::Time (0, 1, 42, 300, 250), dcp::Time (0, 1, 42, 301, 250), false);
486 BOOST_REQUIRE_EQUAL (s.size(), 2U);
487 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
488 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
493 dcp::Colour (255, 255, 255),
496 dcp::Time (0, 1, 42, 229, 250),
497 dcp::Time (0, 1, 45, 62, 250),
504 "It sits there and smirks",
506 dcp::Colour(0, 0, 0),
507 dcp::Time(0, 0, 0, 0, 250),
508 dcp::Time(0, 0, 0, 0, 250),
511 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
512 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
517 dcp::Colour (255, 255, 255),
520 dcp::Time (0, 1, 42, 229, 250),
521 dcp::Time (0, 1, 45, 62, 250),
528 "And you don't think it works",
530 dcp::Colour(0, 0, 0),
531 dcp::Time(0, 0, 0, 0, 250),
532 dcp::Time(0, 0, 0, 0, 250),
536 s = subs.subtitles_during (dcp::Time (0, 1, 45, 200, 250), dcp::Time (0, 1, 45, 201, 250), false);
537 BOOST_REQUIRE_EQUAL (s.size(), 2U);
538 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
539 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
544 dcp::Colour(255, 255, 255),
547 dcp::Time(0, 1, 45, 146, 250),
548 dcp::Time(0, 1, 47, 94, 250),
555 "Then when you're not looking, it winks.",
557 dcp::Colour(0, 0, 0),
558 dcp::Time(0, 0, 0, 0, 250),
559 dcp::Time(0, 0, 0, 0, 250),
562 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
563 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
568 dcp::Colour (255, 255, 255),
571 dcp::Time (0, 1, 45, 146, 250),
572 dcp::Time (0, 1, 47, 94, 250),
579 "When it snows you will find Sister Sledge",
581 dcp::Colour(0, 0, 0),
582 dcp::Time(0, 0, 0, 0, 250),
583 dcp::Time(0, 0, 0, 0, 250),
587 s = subs.subtitles_during (dcp::Time (0, 1, 47, 249, 250), dcp::Time (0, 1, 47, 250, 250), false);
588 BOOST_REQUIRE_EQUAL (s.size(), 2U);
589 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
590 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
595 dcp::Colour(255, 255, 255),
598 dcp::Time(0, 1, 47, 146, 250),
599 dcp::Time(0, 1, 48, 167, 250),
606 "Out mooning, at night, on the ledge",
608 dcp::Colour(0, 0, 0),
609 dcp::Time(0, 0, 0, 0, 250),
610 dcp::Time(0, 0, 0, 0, 250),
613 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
614 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
619 dcp::Colour(255, 255, 255),
622 dcp::Time(0, 1, 47, 146, 250),
623 dcp::Time(0, 1, 48, 167, 250),
632 dcp::Colour(0, 0, 0),
633 dcp::Time(0, 0, 0, 0, 250),
634 dcp::Time(0, 0, 0, 0, 250),
638 s = subs.subtitles_during (dcp::Time (0, 2, 6, 210, 250), dcp::Time (0, 2, 6, 211, 250), false);
639 BOOST_REQUIRE_EQUAL (s.size(), 2U);
640 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
641 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
646 dcp::Colour (255, 255, 255),
649 dcp::Time (0, 2, 5, 208, 250),
650 dcp::Time (0, 2, 7, 31, 250),
659 dcp::Colour(0, 0, 0),
660 dcp::Time(0, 0, 0, 0, 250),
661 dcp::Time(0, 0, 0, 0, 250),
664 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
665 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
670 dcp::Colour(255, 255, 255),
673 dcp::Time(0, 2, 5, 208, 250),
674 dcp::Time(0, 2, 7, 31, 250),
683 dcp::Colour(0, 0, 0),
684 dcp::Time(0, 0, 0, 0, 250),
685 dcp::Time(0, 0, 0, 0, 250),
690 /** And one with bitmap subtitles */
691 BOOST_AUTO_TEST_CASE (read_interop_subtitle_test3)
693 dcp::InteropSubtitleAsset subs ("test/data/subs3.xml");
695 BOOST_REQUIRE_EQUAL (subs.subtitles().size(), 1U);
696 auto si = dynamic_pointer_cast<const dcp::SubtitleImage>(subs.subtitles().front());
698 BOOST_CHECK (si->png_image() == dcp::ArrayData("test/data/sub.png"));
702 /** Write some subtitle content as Interop XML and check that it is right */
703 BOOST_AUTO_TEST_CASE (write_interop_subtitle_test)
705 dcp::InteropSubtitleAsset c;
706 c.set_reel_number ("1");
707 c.set_language ("EN");
708 c.set_movie_title ("Test");
711 std::make_shared<dcp::SubtitleString>(
716 dcp::Colour (255, 255, 255),
719 dcp::Time (0, 4, 9, 22, 24),
720 dcp::Time (0, 4, 11, 22, 24),
729 dcp::Colour (0, 0, 0),
730 dcp::Time (0, 0, 0, 0, 24),
731 dcp::Time (0, 0, 0, 0, 24),
737 std::make_shared<dcp::SubtitleString>(
738 boost::optional<string> (),
742 dcp::Colour (128, 0, 64),
745 dcp::Time (5, 41, 0, 21, 24),
746 dcp::Time (6, 12, 15, 21, 24),
755 dcp::Colour (1, 2, 3),
756 dcp::Time (1, 2, 3, 4, 24),
757 dcp::Time (5, 6, 7, 8, 24),
763 std::make_shared<dcp::SubtitleString>(
764 boost::optional<string> (),
768 dcp::Colour (128, 0, 64),
771 dcp::Time (5, 41, 0, 21, 24),
772 dcp::Time (6, 12, 15, 21, 24),
781 dcp::Colour (1, 2, 3),
782 dcp::Time (1, 2, 3, 4, 24),
783 dcp::Time (5, 6, 7, 8, 24),
788 c._id = "a6c58cff-3e1e-4b38-acec-a42224475ef6";
791 "<DCSubtitle Version=\"1.0\">\n"
792 " <SubtitleID>a6c58cff-3e1e-4b38-acec-a42224475ef6</SubtitleID>\n"
793 " <MovieTitle>Test</MovieTitle>\n"
794 " <ReelNumber>1</ReelNumber>\n"
795 " <Language>EN</Language>\n"
796 " <Font AspectAdjust=\"1.0\" Color=\"FFFFFFFF\" Effect=\"none\" EffectColor=\"FF000000\" Id=\"Frutiger\" Italic=\"no\" Script=\"normal\" Size=\"48\" Underlined=\"no\" Weight=\"normal\">\n"
797 " <Subtitle SpotNumber=\"1\" TimeIn=\"00:04:09:229\" TimeOut=\"00:04:11:229\" FadeUpTime=\"0\" FadeDownTime=\"0\">\n"
798 " <Text VAlign=\"top\" VPosition=\"80\">Hello world</Text>\n"
801 " <Font AspectAdjust=\"1.0\" Color=\"FF800040\" Effect=\"border\" EffectColor=\"FF010203\" Italic=\"yes\" Script=\"normal\" Size=\"91\" Underlined=\"yes\" Weight=\"bold\">\n"
802 " <Subtitle SpotNumber=\"2\" TimeIn=\"05:41:00:219\" TimeOut=\"06:12:15:219\" FadeUpTime=\"930792\" FadeDownTime=\"4591834\">\n"
803 " <Text VAlign=\"bottom\" VPosition=\"40\">What's going <Space Size=\"9em\"/>on</Text>\n"
812 /** Write some subtitle content as Interop XML and check that it is right.
813 * This test includes some horizontal alignment.
815 BOOST_AUTO_TEST_CASE (write_interop_subtitle_test2)
817 dcp::InteropSubtitleAsset c;
818 c.set_reel_number ("1");
819 c.set_language ("EN");
820 c.set_movie_title ("Test");
823 std::make_shared<dcp::SubtitleString>(
828 dcp::Colour (255, 255, 255),
831 dcp::Time (0, 4, 9, 22, 24),
832 dcp::Time (0, 4, 11, 22, 24),
841 dcp::Colour (0, 0, 0),
842 dcp::Time (0, 0, 0, 0, 24),
843 dcp::Time (0, 0, 0, 0, 24),
849 std::make_shared<dcp::SubtitleString>(
850 boost::optional<string>(),
854 dcp::Colour (128, 0, 64),
857 dcp::Time (5, 41, 0, 21, 24),
858 dcp::Time (6, 12, 15, 21, 24),
867 dcp::Colour (1, 2, 3),
868 dcp::Time (1, 2, 3, 4, 24),
869 dcp::Time (5, 6, 7, 8, 24),
874 c._id = "a6c58cff-3e1e-4b38-acec-a42224475ef6";
877 "<DCSubtitle Version=\"1.0\">\n"
878 " <SubtitleID>a6c58cff-3e1e-4b38-acec-a42224475ef6</SubtitleID>\n"
879 " <MovieTitle>Test</MovieTitle>\n"
880 " <ReelNumber>1</ReelNumber>\n"
881 " <Language>EN</Language>\n"
882 " <Font AspectAdjust=\"1.0\" Color=\"FFFFFFFF\" Effect=\"none\" EffectColor=\"FF000000\" Id=\"Frutiger\" Italic=\"no\" Script=\"normal\" Size=\"48\" Underlined=\"no\" Weight=\"normal\">\n"
883 " <Subtitle SpotNumber=\"1\" TimeIn=\"00:04:09:229\" TimeOut=\"00:04:11:229\" FadeUpTime=\"0\" FadeDownTime=\"0\">\n"
884 " <Text HPosition=\"-20\" VAlign=\"top\" VPosition=\"80\">Hello world</Text>\n"
887 " <Font AspectAdjust=\"1.0\" Color=\"FF800040\" Effect=\"border\" EffectColor=\"FF010203\" Italic=\"yes\" Script=\"normal\" Size=\"91\" Underlined=\"yes\" Weight=\"bold\">\n"
888 " <Subtitle SpotNumber=\"2\" TimeIn=\"05:41:00:219\" TimeOut=\"06:12:15:219\" FadeUpTime=\"930792\" FadeDownTime=\"4591834\">\n"
889 " <Text HPosition=\"-20\" VAlign=\"bottom\" VPosition=\"40\">What's going on</Text>\n"
898 /* Write some subtitle content as Interop XML using bitmaps and check that it is right */
899 BOOST_AUTO_TEST_CASE (write_interop_subtitle_test3)
903 auto c = std::make_shared<dcp::InteropSubtitleAsset>();
904 c->set_reel_number ("1");
905 c->set_language ("EN");
906 c->set_movie_title ("Test");
909 std::make_shared<dcp::SubtitleImage>(
910 dcp::ArrayData ("test/data/sub.png"),
911 dcp::Time (0, 4, 9, 22, 24),
912 dcp::Time (0, 4, 11, 22, 24),
918 dcp::Time (0, 0, 0, 0, 24),
919 dcp::Time (0, 0, 0, 0, 24)
923 c->_id = "a6c58cff-3e1e-4b38-acec-a42224475ef6";
924 boost::filesystem::remove_all ("build/test/write_interop_subtitle_test3");
925 boost::filesystem::create_directories ("build/test/write_interop_subtitle_test3");
926 c->write ("build/test/write_interop_subtitle_test3/subs.xml");
928 auto reel = std::make_shared<dcp::Reel>();
929 reel->add(std::make_shared<dcp::ReelInteropSubtitleAsset>(c, dcp::Fraction(24, 1), 6046, 0));
931 string const issue_date = "2018-09-02T04:45:18+00:00";
932 string const issuer = "libdcp";
933 string const creator = "libdcp";
934 string const annotation_text = "Created by libdcp";
936 auto cpl = std::make_shared<dcp::CPL>("My film", dcp::ContentKind::FEATURE, dcp::Standard::INTEROP);
938 cpl->set_issuer (issuer);
939 cpl->set_creator (creator);
940 cpl->set_issue_date (issue_date);
941 cpl->set_annotation_text (annotation_text);
942 auto cv = cpl->content_version();
944 cv->label_text = "foo";
945 cpl->set_content_version (*cv);
947 dcp::DCP dcp ("build/test/write_interop_subtitle_test3");
949 dcp.set_issuer(issuer);
950 dcp.set_creator(creator);
951 dcp.set_issue_date(issue_date);
952 dcp.set_annotation_text(annotation_text);
956 dcp::file_to_string("test/ref/write_interop_subtitle_test3/subs.xml"),
957 dcp::file_to_string("build/test/write_interop_subtitle_test3/subs.xml"),
960 check_file(find_file("build/test/write_interop_subtitle_test3", ".png"), "test/data/sub.png");
963 dcp::file_to_string("test/ref/write_interop_subtitle_test3/ASSETMAP"),
964 dcp::file_to_string("build/test/write_interop_subtitle_test3/ASSETMAP"),
969 dcp::file_to_string(find_file("test/ref/write_interop_subtitle_test3", "pkl")),
970 dcp::file_to_string(find_file("build/test/write_interop_subtitle_test3", "pkl")),