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::make_shared;
47 using std::shared_ptr;
52 /** Load some subtitle content from Interop XML and check that it is read correctly */
53 BOOST_AUTO_TEST_CASE (read_interop_subtitle_test1)
55 dcp::InteropSubtitleAsset subs ("test/data/subs1.xml");
57 BOOST_CHECK_EQUAL (subs.id(), "cab5c268-222b-41d2-88ae-6d6999441b17");
58 BOOST_CHECK_EQUAL (subs.movie_title(), "Movie Title");
59 BOOST_CHECK_EQUAL (subs.reel_number(), "1");
60 BOOST_CHECK_EQUAL (subs.language(), "French");
62 auto lfn = subs.load_font_nodes ();
63 BOOST_REQUIRE_EQUAL (lfn.size(), 1U);
64 shared_ptr<dcp::InteropLoadFontNode> interop_lfn = dynamic_pointer_cast<dcp::InteropLoadFontNode> (lfn.front ());
65 BOOST_REQUIRE (interop_lfn);
66 BOOST_CHECK_EQUAL (interop_lfn->id, "theFontId");
67 BOOST_CHECK_EQUAL (interop_lfn->uri, "arial.ttf");
69 auto s = subs.subtitles_during (dcp::Time (0, 0, 6, 1, 250), dcp::Time (0, 0, 6, 2, 250), false);
70 BOOST_REQUIRE_EQUAL (s.size(), 2U);
71 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
72 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
77 dcp::Colour (255, 255, 255),
80 dcp::Time (0, 0, 5, 198, 250),
81 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),
112 dcp::Colour (0, 0, 0),
113 dcp::Time (0, 0, 0, 1, 250),
114 dcp::Time (0, 0, 0, 1, 250),
118 s = subs.subtitles_during (dcp::Time (0, 0, 7, 190, 250), dcp::Time (0, 0, 7, 191, 250), false);
119 BOOST_REQUIRE_EQUAL (s.size(), 2U);
120 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
121 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
122 string ("theFontId"),
126 dcp::Colour (255, 255, 255),
129 dcp::Time (0, 0, 7, 177, 250),
130 dcp::Time (0, 0, 11, 31, 250),
136 "My corset was H.M. The Queen's",
138 dcp::Colour (0, 0, 0),
139 dcp::Time (0, 0, 0, 1, 250),
140 dcp::Time (0, 0, 0, 1, 250),
143 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
144 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
145 string ("theFontId"),
149 dcp::Colour (255, 255, 255),
152 dcp::Time (0, 0, 7, 177, 250),
153 dcp::Time (0, 0, 11, 31, 250),
159 "My large wonderbra",
161 dcp::Colour (0, 0, 0),
162 dcp::Time (0, 0, 0, 1, 250),
163 dcp::Time (0, 0, 0, 1, 250),
167 s = subs.subtitles_during (dcp::Time (0, 0, 11, 95, 250), dcp::Time (0, 0, 11, 96, 250), false);
168 BOOST_REQUIRE_EQUAL (s.size(), 1U);
169 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
170 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
171 string ("theFontId"),
175 dcp::Colour (255, 255, 255),
178 dcp::Time (0, 0, 11, 94, 250),
179 dcp::Time (0, 0, 13, 63, 250),
185 "Once belonged to the Shah",
187 dcp::Colour (0, 0, 0),
188 dcp::Time (0, 0, 0, 1, 250),
189 dcp::Time (0, 0, 0, 1, 250),
193 s = subs.subtitles_during (dcp::Time (0, 0, 14, 42, 250), dcp::Time (0, 0, 14, 43, 250), false);
194 BOOST_REQUIRE_EQUAL (s.size(), 1U);
195 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
196 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
197 string ("theFontId"),
201 dcp::Colour (255, 255, 255),
204 dcp::Time (0, 0, 13, 104, 250),
205 dcp::Time (0, 0, 15, 177, 250),
211 "And these are Roy Hattersley's jeans",
213 dcp::Colour (0, 0, 0),
214 dcp::Time (0, 0, 0, 1, 250),
215 dcp::Time (0, 0, 0, 1, 250),
220 /** And similarly for another one */
221 BOOST_AUTO_TEST_CASE (read_interop_subtitle_test2)
223 dcp::InteropSubtitleAsset subs ("test/data/subs2.xml");
225 auto s = subs.subtitles_during (dcp::Time (0, 0, 42, 100, 250), dcp::Time (0, 0, 42, 101, 250), false);
226 BOOST_REQUIRE_EQUAL (s.size(), 2U);
227 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
228 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
233 dcp::Colour (255, 255, 255),
236 dcp::Time (0, 0, 41, 62, 250),
237 dcp::Time (0, 0, 43, 52, 250),
243 "At afternoon tea with John Peel",
245 dcp::Colour (0, 0, 0),
246 dcp::Time (0, 0, 0, 0, 250),
247 dcp::Time (0, 0, 0, 0, 250),
250 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
251 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
256 dcp::Colour (255, 255, 255),
259 dcp::Time (0, 0, 41, 62, 250),
260 dcp::Time (0, 0, 43, 52, 250),
266 "I enquired if his accent was real",
268 dcp::Colour (0, 0, 0),
269 dcp::Time (0, 0, 0, 0, 250),
270 dcp::Time (0, 0, 0, 0, 250),
274 s = subs.subtitles_during (dcp::Time (0, 0, 50, 50, 250), dcp::Time (0, 0, 50, 51, 250), false);
275 BOOST_REQUIRE_EQUAL (s.size(), 2U);
276 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
277 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
282 dcp::Colour (255, 255, 255),
285 dcp::Time (0, 0, 50, 42, 250),
286 dcp::Time (0, 0, 52, 21, 250),
292 "He said \"out of the house",
294 dcp::Colour (0, 0, 0),
295 dcp::Time (0, 0, 0, 0, 250),
296 dcp::Time (0, 0, 0, 0, 250),
299 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
300 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
305 dcp::Colour (255, 255, 255),
308 dcp::Time (0, 0, 50, 42, 250),
309 dcp::Time (0, 0, 52, 21, 250),
315 "I'm incredibly scouse",
317 dcp::Colour (0, 0, 0),
318 dcp::Time (0, 0, 0, 0, 250),
319 dcp::Time (0, 0, 0, 0, 250),
323 s = subs.subtitles_during (dcp::Time (0, 1, 2, 300, 250), dcp::Time (0, 1, 2, 301, 250), false);
324 BOOST_REQUIRE_EQUAL (s.size(), 2U);
325 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
326 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
331 dcp::Colour(255, 255, 255),
334 dcp::Time(0, 1, 2, 208, 250),
335 dcp::Time(0, 1, 4, 10, 250),
341 "At home it depends how I feel.\"",
343 dcp::Colour(0, 0, 0),
344 dcp::Time(0, 0, 0, 0, 250),
345 dcp::Time(0, 0, 0, 0, 250),
348 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
349 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
354 dcp::Colour(255, 255, 255),
357 dcp::Time(0, 1, 2, 208, 250),
358 dcp::Time(0, 1, 4, 10, 250),
364 "I spent a long weekend in Brighton",
366 dcp::Colour(0, 0, 0),
367 dcp::Time(0, 0, 0, 0, 250),
368 dcp::Time(0, 0, 0, 0, 250),
372 s = subs.subtitles_during (dcp::Time (0, 1, 15, 50, 250), dcp::Time (0, 1, 15, 51, 250), false);
373 BOOST_REQUIRE_EQUAL (s.size(), 2U);
374 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
375 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
380 dcp::Colour(255, 255, 255),
383 dcp::Time(0, 1, 15, 42, 250),
384 dcp::Time(0, 1, 16, 42, 250),
390 "With the legendary Miss Enid Blyton",
392 dcp::Colour(0, 0, 0),
393 dcp::Time(0, 0, 0, 0, 250),
394 dcp::Time(0, 0, 0, 0, 250),
397 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
398 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
403 dcp::Colour(255, 255, 255),
406 dcp::Time(0, 1, 15, 42, 250),
407 dcp::Time(0, 1, 16, 42, 250),
413 "She said \"you be Noddy",
415 dcp::Colour(0, 0, 0),
416 dcp::Time(0, 0, 0, 0, 250),
417 dcp::Time(0, 0, 0, 0, 250),
421 s = subs.subtitles_during (dcp::Time (0, 1, 27, 200, 250), dcp::Time (0, 1, 27, 201, 250), false);
422 BOOST_REQUIRE_EQUAL (s.size(), 2U);
423 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
424 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
429 dcp::Colour(255, 255, 255),
432 dcp::Time(0, 1, 27, 115, 250),
433 dcp::Time(0, 1, 28, 208, 250),
439 "That curious creature the Sphinx",
441 dcp::Colour(0, 0, 0),
442 dcp::Time(0, 0, 0, 0, 250),
443 dcp::Time(0, 0, 0, 0, 250),
446 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
447 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
452 dcp::Colour(255, 255, 255),
455 dcp::Time(0, 1, 27, 115, 250),
456 dcp::Time(0, 1, 28, 208, 250),
462 "Is smarter than anyone thinks",
464 dcp::Colour(0, 0, 0),
465 dcp::Time(0, 0, 0, 0, 250),
466 dcp::Time(0, 0, 0, 0, 250),
470 s = subs.subtitles_during (dcp::Time (0, 1, 42, 300, 250), dcp::Time (0, 1, 42, 301, 250), false);
471 BOOST_REQUIRE_EQUAL (s.size(), 2U);
472 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
473 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
478 dcp::Colour (255, 255, 255),
481 dcp::Time (0, 1, 42, 229, 250),
482 dcp::Time (0, 1, 45, 62, 250),
488 "It sits there and smirks",
490 dcp::Colour(0, 0, 0),
491 dcp::Time(0, 0, 0, 0, 250),
492 dcp::Time(0, 0, 0, 0, 250),
495 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
496 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
501 dcp::Colour (255, 255, 255),
504 dcp::Time (0, 1, 42, 229, 250),
505 dcp::Time (0, 1, 45, 62, 250),
511 "And you don't think it works",
513 dcp::Colour(0, 0, 0),
514 dcp::Time(0, 0, 0, 0, 250),
515 dcp::Time(0, 0, 0, 0, 250),
519 s = subs.subtitles_during (dcp::Time (0, 1, 45, 200, 250), dcp::Time (0, 1, 45, 201, 250), false);
520 BOOST_REQUIRE_EQUAL (s.size(), 2U);
521 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
522 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
527 dcp::Colour(255, 255, 255),
530 dcp::Time(0, 1, 45, 146, 250),
531 dcp::Time(0, 1, 47, 94, 250),
537 "Then when you're not looking, it winks.",
539 dcp::Colour(0, 0, 0),
540 dcp::Time(0, 0, 0, 0, 250),
541 dcp::Time(0, 0, 0, 0, 250),
544 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
545 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
550 dcp::Colour (255, 255, 255),
553 dcp::Time (0, 1, 45, 146, 250),
554 dcp::Time (0, 1, 47, 94, 250),
560 "When it snows you will find Sister Sledge",
562 dcp::Colour(0, 0, 0),
563 dcp::Time(0, 0, 0, 0, 250),
564 dcp::Time(0, 0, 0, 0, 250),
568 s = subs.subtitles_during (dcp::Time (0, 1, 47, 249, 250), dcp::Time (0, 1, 47, 250, 250), false);
569 BOOST_REQUIRE_EQUAL (s.size(), 2U);
570 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
571 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
576 dcp::Colour(255, 255, 255),
579 dcp::Time(0, 1, 47, 146, 250),
580 dcp::Time(0, 1, 48, 167, 250),
586 "Out mooning, at night, on the ledge",
588 dcp::Colour(0, 0, 0),
589 dcp::Time(0, 0, 0, 0, 250),
590 dcp::Time(0, 0, 0, 0, 250),
593 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
594 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
599 dcp::Colour(255, 255, 255),
602 dcp::Time(0, 1, 47, 146, 250),
603 dcp::Time(0, 1, 48, 167, 250),
611 dcp::Colour(0, 0, 0),
612 dcp::Time(0, 0, 0, 0, 250),
613 dcp::Time(0, 0, 0, 0, 250),
617 s = subs.subtitles_during (dcp::Time (0, 2, 6, 210, 250), dcp::Time (0, 2, 6, 211, 250), false);
618 BOOST_REQUIRE_EQUAL (s.size(), 2U);
619 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
620 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
625 dcp::Colour (255, 255, 255),
628 dcp::Time (0, 2, 5, 208, 250),
629 dcp::Time (0, 2, 7, 31, 250),
637 dcp::Colour(0, 0, 0),
638 dcp::Time(0, 0, 0, 0, 250),
639 dcp::Time(0, 0, 0, 0, 250),
642 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
643 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
648 dcp::Colour(255, 255, 255),
651 dcp::Time(0, 2, 5, 208, 250),
652 dcp::Time(0, 2, 7, 31, 250),
660 dcp::Colour(0, 0, 0),
661 dcp::Time(0, 0, 0, 0, 250),
662 dcp::Time(0, 0, 0, 0, 250),
667 /** And one with bitmap subtitles */
668 BOOST_AUTO_TEST_CASE (read_interop_subtitle_test3)
670 dcp::InteropSubtitleAsset subs ("test/data/subs3.xml");
672 BOOST_REQUIRE_EQUAL (subs.subtitles().size(), 1U);
673 auto si = dynamic_pointer_cast<const dcp::SubtitleImage>(subs.subtitles().front());
675 BOOST_CHECK (si->png_image() == dcp::ArrayData("test/data/sub.png"));
679 /** Write some subtitle content as Interop XML and check that it is right */
680 BOOST_AUTO_TEST_CASE (write_interop_subtitle_test)
682 dcp::InteropSubtitleAsset c;
683 c.set_reel_number ("1");
684 c.set_language ("EN");
685 c.set_movie_title ("Test");
688 make_shared<dcp::SubtitleString>(
693 dcp::Colour (255, 255, 255),
696 dcp::Time (0, 4, 9, 22, 24),
697 dcp::Time (0, 4, 11, 22, 24),
705 dcp::Colour (0, 0, 0),
706 dcp::Time (0, 0, 0, 0, 24),
707 dcp::Time (0, 0, 0, 0, 24),
713 make_shared<dcp::SubtitleString>(
714 boost::optional<string> (),
718 dcp::Colour (128, 0, 64),
721 dcp::Time (5, 41, 0, 21, 24),
722 dcp::Time (6, 12, 15, 21, 24),
730 dcp::Colour (1, 2, 3),
731 dcp::Time (1, 2, 3, 4, 24),
732 dcp::Time (5, 6, 7, 8, 24),
738 make_shared<dcp::SubtitleString>(
739 boost::optional<string> (),
743 dcp::Colour (128, 0, 64),
746 dcp::Time (5, 41, 0, 21, 24),
747 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),
762 c._id = "a6c58cff-3e1e-4b38-acec-a42224475ef6";
765 "<DCSubtitle Version=\"1.0\">\n"
766 " <SubtitleID>a6c58cff-3e1e-4b38-acec-a42224475ef6</SubtitleID>\n"
767 " <MovieTitle>Test</MovieTitle>\n"
768 " <ReelNumber>1</ReelNumber>\n"
769 " <Language>EN</Language>\n"
770 " <Font AspectAdjust=\"1.0\" Color=\"FFFFFFFF\" Effect=\"none\" EffectColor=\"FF000000\" Id=\"Frutiger\" Italic=\"no\" Script=\"normal\" Size=\"48\" Underlined=\"no\" Weight=\"normal\">\n"
771 " <Subtitle SpotNumber=\"1\" TimeIn=\"00:04:09:229\" TimeOut=\"00:04:11:229\" FadeUpTime=\"0\" FadeDownTime=\"0\">\n"
772 " <Text VAlign=\"top\" VPosition=\"80\">Hello world</Text>\n"
775 " <Font AspectAdjust=\"1.0\" Color=\"FF800040\" Effect=\"border\" EffectColor=\"FF010203\" Italic=\"yes\" Script=\"normal\" Size=\"91\" Underlined=\"yes\" Weight=\"bold\">\n"
776 " <Subtitle SpotNumber=\"2\" TimeIn=\"05:41:00:219\" TimeOut=\"06:12:15:219\" FadeUpTime=\"930792\" FadeDownTime=\"4591834\">\n"
777 " <Text VAlign=\"bottom\" VPosition=\"40\">What's going <Space Size=\"9em\"/>on</Text>\n"
786 /** Write some subtitle content as Interop XML and check that it is right.
787 * This test includes some horizontal alignment.
789 BOOST_AUTO_TEST_CASE (write_interop_subtitle_test2)
791 dcp::InteropSubtitleAsset c;
792 c.set_reel_number ("1");
793 c.set_language ("EN");
794 c.set_movie_title ("Test");
797 make_shared<dcp::SubtitleString>(
802 dcp::Colour (255, 255, 255),
805 dcp::Time (0, 4, 9, 22, 24),
806 dcp::Time (0, 4, 11, 22, 24),
814 dcp::Colour (0, 0, 0),
815 dcp::Time (0, 0, 0, 0, 24),
816 dcp::Time (0, 0, 0, 0, 24),
822 make_shared<dcp::SubtitleString>(
823 boost::optional<string>(),
827 dcp::Colour (128, 0, 64),
830 dcp::Time (5, 41, 0, 21, 24),
831 dcp::Time (6, 12, 15, 21, 24),
839 dcp::Colour (1, 2, 3),
840 dcp::Time (1, 2, 3, 4, 24),
841 dcp::Time (5, 6, 7, 8, 24),
846 c._id = "a6c58cff-3e1e-4b38-acec-a42224475ef6";
849 "<DCSubtitle Version=\"1.0\">\n"
850 " <SubtitleID>a6c58cff-3e1e-4b38-acec-a42224475ef6</SubtitleID>\n"
851 " <MovieTitle>Test</MovieTitle>\n"
852 " <ReelNumber>1</ReelNumber>\n"
853 " <Language>EN</Language>\n"
854 " <Font AspectAdjust=\"1.0\" Color=\"FFFFFFFF\" Effect=\"none\" EffectColor=\"FF000000\" Id=\"Frutiger\" Italic=\"no\" Script=\"normal\" Size=\"48\" Underlined=\"no\" Weight=\"normal\">\n"
855 " <Subtitle SpotNumber=\"1\" TimeIn=\"00:04:09:229\" TimeOut=\"00:04:11:229\" FadeUpTime=\"0\" FadeDownTime=\"0\">\n"
856 " <Text HPosition=\"-20\" VAlign=\"top\" VPosition=\"80\">Hello world</Text>\n"
859 " <Font AspectAdjust=\"1.0\" Color=\"FF800040\" Effect=\"border\" EffectColor=\"FF010203\" Italic=\"yes\" Script=\"normal\" Size=\"91\" Underlined=\"yes\" Weight=\"bold\">\n"
860 " <Subtitle SpotNumber=\"2\" TimeIn=\"05:41:00:219\" TimeOut=\"06:12:15:219\" FadeUpTime=\"930792\" FadeDownTime=\"4591834\">\n"
861 " <Text HPosition=\"-20\" VAlign=\"bottom\" VPosition=\"40\">What's going on</Text>\n"
870 /* Write some subtitle content as Interop XML using bitmaps and check that it is right */
871 BOOST_AUTO_TEST_CASE (write_interop_subtitle_test3)
875 auto c = make_shared<dcp::InteropSubtitleAsset>();
876 c->set_reel_number ("1");
877 c->set_language ("EN");
878 c->set_movie_title ("Test");
881 make_shared<dcp::SubtitleImage>(
882 dcp::ArrayData ("test/data/sub.png"),
883 dcp::Time (0, 4, 9, 22, 24),
884 dcp::Time (0, 4, 11, 22, 24),
889 dcp::Time (0, 0, 0, 0, 24),
890 dcp::Time (0, 0, 0, 0, 24)
894 c->_id = "a6c58cff-3e1e-4b38-acec-a42224475ef6";
895 boost::filesystem::remove_all ("build/test/write_interop_subtitle_test3");
896 boost::filesystem::create_directories ("build/test/write_interop_subtitle_test3");
897 c->write ("build/test/write_interop_subtitle_test3/subs.xml");
899 auto reel = make_shared<dcp::Reel>();
900 reel->add(make_shared<dcp::ReelInteropSubtitleAsset>(c, dcp::Fraction(24, 1), 6046, 0));
902 string const issue_date = "2018-09-02T04:45:18+00:00";
903 string const issuer = "libdcp";
904 string const creator = "libdcp";
905 string const annotation_text = "Created by libdcp";
907 auto cpl = make_shared<dcp::CPL>("My film", dcp::ContentKind::FEATURE, dcp::Standard::INTEROP);
909 cpl->set_issuer (issuer);
910 cpl->set_creator (creator);
911 cpl->set_issue_date (issue_date);
912 cpl->set_annotation_text (annotation_text);
913 auto cv = cpl->content_version();
915 cv->label_text = "foo";
916 cpl->set_content_version (*cv);
918 dcp::DCP dcp ("build/test/write_interop_subtitle_test3");
920 dcp.set_issuer(issuer);
921 dcp.set_creator(creator);
922 dcp.set_issue_date(issue_date);
923 dcp.set_annotation_text(annotation_text);
927 dcp::file_to_string("test/ref/write_interop_subtitle_test3/subs.xml"),
928 dcp::file_to_string("build/test/write_interop_subtitle_test3/subs.xml"),
931 check_file ("build/test/write_interop_subtitle_test3/d36f4bb3-c4fa-4a95-9915-6fec3110cd71.png", "test/data/sub.png");
934 dcp::file_to_string("test/ref/write_interop_subtitle_test3/ASSETMAP"),
935 dcp::file_to_string("build/test/write_interop_subtitle_test3/ASSETMAP"),
940 dcp::file_to_string(find_file("test/ref/write_interop_subtitle_test3", "pkl")),
941 dcp::file_to_string(find_file("build/test/write_interop_subtitle_test3", "pkl")),