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),
95 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
96 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
101 dcp::Colour (255, 255, 255),
104 dcp::Time (0, 0, 5, 198, 250),
105 dcp::Time (0, 0, 7, 115, 250),
114 dcp::Colour (0, 0, 0),
115 dcp::Time (0, 0, 0, 1, 250),
116 dcp::Time (0, 0, 0, 1, 250),
121 s = subs.subtitles_during (dcp::Time (0, 0, 7, 190, 250), dcp::Time (0, 0, 7, 191, 250), false);
122 BOOST_REQUIRE_EQUAL (s.size(), 2U);
123 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
124 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
125 string ("theFontId"),
129 dcp::Colour (255, 255, 255),
132 dcp::Time (0, 0, 7, 177, 250),
133 dcp::Time (0, 0, 11, 31, 250),
140 "My corset was H.M. The Queen's",
142 dcp::Colour (0, 0, 0),
143 dcp::Time (0, 0, 0, 1, 250),
144 dcp::Time (0, 0, 0, 1, 250),
148 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
149 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
150 string ("theFontId"),
154 dcp::Colour (255, 255, 255),
157 dcp::Time (0, 0, 7, 177, 250),
158 dcp::Time (0, 0, 11, 31, 250),
165 "My large wonderbra",
167 dcp::Colour (0, 0, 0),
168 dcp::Time (0, 0, 0, 1, 250),
169 dcp::Time (0, 0, 0, 1, 250),
174 s = subs.subtitles_during (dcp::Time (0, 0, 11, 95, 250), dcp::Time (0, 0, 11, 96, 250), false);
175 BOOST_REQUIRE_EQUAL (s.size(), 1U);
176 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
177 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
178 string ("theFontId"),
182 dcp::Colour (255, 255, 255),
185 dcp::Time (0, 0, 11, 94, 250),
186 dcp::Time (0, 0, 13, 63, 250),
193 "Once belonged to the Shah",
195 dcp::Colour (0, 0, 0),
196 dcp::Time (0, 0, 0, 1, 250),
197 dcp::Time (0, 0, 0, 1, 250),
202 s = subs.subtitles_during (dcp::Time (0, 0, 14, 42, 250), dcp::Time (0, 0, 14, 43, 250), false);
203 BOOST_REQUIRE_EQUAL (s.size(), 1U);
204 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
205 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
206 string ("theFontId"),
210 dcp::Colour (255, 255, 255),
213 dcp::Time (0, 0, 13, 104, 250),
214 dcp::Time (0, 0, 15, 177, 250),
221 "And these are Roy Hattersley's jeans",
223 dcp::Colour (0, 0, 0),
224 dcp::Time (0, 0, 0, 1, 250),
225 dcp::Time (0, 0, 0, 1, 250),
231 /** And similarly for another one */
232 BOOST_AUTO_TEST_CASE (read_interop_subtitle_test2)
234 dcp::InteropSubtitleAsset subs ("test/data/subs2.xml");
236 auto s = subs.subtitles_during (dcp::Time (0, 0, 42, 100, 250), dcp::Time (0, 0, 42, 101, 250), false);
237 BOOST_REQUIRE_EQUAL (s.size(), 2U);
238 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
239 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
244 dcp::Colour (255, 255, 255),
247 dcp::Time (0, 0, 41, 62, 250),
248 dcp::Time (0, 0, 43, 52, 250),
255 "At afternoon tea with John Peel",
257 dcp::Colour (0, 0, 0),
258 dcp::Time (0, 0, 0, 0, 250),
259 dcp::Time (0, 0, 0, 0, 250),
263 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
264 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
269 dcp::Colour (255, 255, 255),
272 dcp::Time (0, 0, 41, 62, 250),
273 dcp::Time (0, 0, 43, 52, 250),
280 "I enquired if his accent was real",
282 dcp::Colour (0, 0, 0),
283 dcp::Time (0, 0, 0, 0, 250),
284 dcp::Time (0, 0, 0, 0, 250),
289 s = subs.subtitles_during (dcp::Time (0, 0, 50, 50, 250), dcp::Time (0, 0, 50, 51, 250), false);
290 BOOST_REQUIRE_EQUAL (s.size(), 2U);
291 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
292 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
297 dcp::Colour (255, 255, 255),
300 dcp::Time (0, 0, 50, 42, 250),
301 dcp::Time (0, 0, 52, 21, 250),
308 "He said \"out of the house",
310 dcp::Colour (0, 0, 0),
311 dcp::Time (0, 0, 0, 0, 250),
312 dcp::Time (0, 0, 0, 0, 250),
316 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
317 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
322 dcp::Colour (255, 255, 255),
325 dcp::Time (0, 0, 50, 42, 250),
326 dcp::Time (0, 0, 52, 21, 250),
333 "I'm incredibly scouse",
335 dcp::Colour (0, 0, 0),
336 dcp::Time (0, 0, 0, 0, 250),
337 dcp::Time (0, 0, 0, 0, 250),
342 s = subs.subtitles_during (dcp::Time (0, 1, 2, 300, 250), dcp::Time (0, 1, 2, 301, 250), false);
343 BOOST_REQUIRE_EQUAL (s.size(), 2U);
344 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
345 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
350 dcp::Colour(255, 255, 255),
353 dcp::Time(0, 1, 2, 208, 250),
354 dcp::Time(0, 1, 4, 10, 250),
361 "At home it depends how I feel.\"",
363 dcp::Colour(0, 0, 0),
364 dcp::Time(0, 0, 0, 0, 250),
365 dcp::Time(0, 0, 0, 0, 250),
369 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
370 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
375 dcp::Colour(255, 255, 255),
378 dcp::Time(0, 1, 2, 208, 250),
379 dcp::Time(0, 1, 4, 10, 250),
386 "I spent a long weekend in Brighton",
388 dcp::Colour(0, 0, 0),
389 dcp::Time(0, 0, 0, 0, 250),
390 dcp::Time(0, 0, 0, 0, 250),
395 s = subs.subtitles_during (dcp::Time (0, 1, 15, 50, 250), dcp::Time (0, 1, 15, 51, 250), false);
396 BOOST_REQUIRE_EQUAL (s.size(), 2U);
397 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
398 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
403 dcp::Colour(255, 255, 255),
406 dcp::Time(0, 1, 15, 42, 250),
407 dcp::Time(0, 1, 16, 42, 250),
414 "With the legendary Miss Enid Blyton",
416 dcp::Colour(0, 0, 0),
417 dcp::Time(0, 0, 0, 0, 250),
418 dcp::Time(0, 0, 0, 0, 250),
422 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
423 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
428 dcp::Colour(255, 255, 255),
431 dcp::Time(0, 1, 15, 42, 250),
432 dcp::Time(0, 1, 16, 42, 250),
439 "She said \"you be Noddy",
441 dcp::Colour(0, 0, 0),
442 dcp::Time(0, 0, 0, 0, 250),
443 dcp::Time(0, 0, 0, 0, 250),
448 s = subs.subtitles_during (dcp::Time (0, 1, 27, 200, 250), dcp::Time (0, 1, 27, 201, 250), false);
449 BOOST_REQUIRE_EQUAL (s.size(), 2U);
450 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
451 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
456 dcp::Colour(255, 255, 255),
459 dcp::Time(0, 1, 27, 115, 250),
460 dcp::Time(0, 1, 28, 208, 250),
467 "That curious creature the Sphinx",
469 dcp::Colour(0, 0, 0),
470 dcp::Time(0, 0, 0, 0, 250),
471 dcp::Time(0, 0, 0, 0, 250),
475 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
476 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
481 dcp::Colour(255, 255, 255),
484 dcp::Time(0, 1, 27, 115, 250),
485 dcp::Time(0, 1, 28, 208, 250),
492 "Is smarter than anyone thinks",
494 dcp::Colour(0, 0, 0),
495 dcp::Time(0, 0, 0, 0, 250),
496 dcp::Time(0, 0, 0, 0, 250),
501 s = subs.subtitles_during (dcp::Time (0, 1, 42, 300, 250), dcp::Time (0, 1, 42, 301, 250), false);
502 BOOST_REQUIRE_EQUAL (s.size(), 2U);
503 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
504 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
509 dcp::Colour (255, 255, 255),
512 dcp::Time (0, 1, 42, 229, 250),
513 dcp::Time (0, 1, 45, 62, 250),
520 "It sits there and smirks",
522 dcp::Colour(0, 0, 0),
523 dcp::Time(0, 0, 0, 0, 250),
524 dcp::Time(0, 0, 0, 0, 250),
528 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
529 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
534 dcp::Colour (255, 255, 255),
537 dcp::Time (0, 1, 42, 229, 250),
538 dcp::Time (0, 1, 45, 62, 250),
545 "And you don't think it works",
547 dcp::Colour(0, 0, 0),
548 dcp::Time(0, 0, 0, 0, 250),
549 dcp::Time(0, 0, 0, 0, 250),
554 s = subs.subtitles_during (dcp::Time (0, 1, 45, 200, 250), dcp::Time (0, 1, 45, 201, 250), false);
555 BOOST_REQUIRE_EQUAL (s.size(), 2U);
556 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
557 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
562 dcp::Colour(255, 255, 255),
565 dcp::Time(0, 1, 45, 146, 250),
566 dcp::Time(0, 1, 47, 94, 250),
573 "Then when you're not looking, it winks.",
575 dcp::Colour(0, 0, 0),
576 dcp::Time(0, 0, 0, 0, 250),
577 dcp::Time(0, 0, 0, 0, 250),
581 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
582 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
587 dcp::Colour (255, 255, 255),
590 dcp::Time (0, 1, 45, 146, 250),
591 dcp::Time (0, 1, 47, 94, 250),
598 "When it snows you will find Sister Sledge",
600 dcp::Colour(0, 0, 0),
601 dcp::Time(0, 0, 0, 0, 250),
602 dcp::Time(0, 0, 0, 0, 250),
607 s = subs.subtitles_during (dcp::Time (0, 1, 47, 249, 250), dcp::Time (0, 1, 47, 250, 250), false);
608 BOOST_REQUIRE_EQUAL (s.size(), 2U);
609 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
610 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
615 dcp::Colour(255, 255, 255),
618 dcp::Time(0, 1, 47, 146, 250),
619 dcp::Time(0, 1, 48, 167, 250),
626 "Out mooning, at night, on the ledge",
628 dcp::Colour(0, 0, 0),
629 dcp::Time(0, 0, 0, 0, 250),
630 dcp::Time(0, 0, 0, 0, 250),
634 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
635 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
640 dcp::Colour(255, 255, 255),
643 dcp::Time(0, 1, 47, 146, 250),
644 dcp::Time(0, 1, 48, 167, 250),
653 dcp::Colour(0, 0, 0),
654 dcp::Time(0, 0, 0, 0, 250),
655 dcp::Time(0, 0, 0, 0, 250),
660 s = subs.subtitles_during (dcp::Time (0, 2, 6, 210, 250), dcp::Time (0, 2, 6, 211, 250), false);
661 BOOST_REQUIRE_EQUAL (s.size(), 2U);
662 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
663 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
668 dcp::Colour (255, 255, 255),
671 dcp::Time (0, 2, 5, 208, 250),
672 dcp::Time (0, 2, 7, 31, 250),
681 dcp::Colour(0, 0, 0),
682 dcp::Time(0, 0, 0, 0, 250),
683 dcp::Time(0, 0, 0, 0, 250),
687 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
688 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
693 dcp::Colour(255, 255, 255),
696 dcp::Time(0, 2, 5, 208, 250),
697 dcp::Time(0, 2, 7, 31, 250),
706 dcp::Colour(0, 0, 0),
707 dcp::Time(0, 0, 0, 0, 250),
708 dcp::Time(0, 0, 0, 0, 250),
714 /** And one with bitmap subtitles */
715 BOOST_AUTO_TEST_CASE (read_interop_subtitle_test3)
717 dcp::InteropSubtitleAsset subs ("test/data/subs3.xml");
719 BOOST_REQUIRE_EQUAL (subs.subtitles().size(), 1U);
720 auto si = dynamic_pointer_cast<const dcp::SubtitleImage>(subs.subtitles().front());
722 BOOST_CHECK (si->png_image() == dcp::ArrayData("test/data/sub.png"));
726 /** Write some subtitle content as Interop XML and check that it is right */
727 BOOST_AUTO_TEST_CASE (write_interop_subtitle_test)
729 dcp::InteropSubtitleAsset c;
730 c.set_reel_number ("1");
731 c.set_language ("EN");
732 c.set_movie_title ("Test");
735 std::make_shared<dcp::SubtitleString>(
740 dcp::Colour (255, 255, 255),
743 dcp::Time (0, 4, 9, 22, 24),
744 dcp::Time (0, 4, 11, 22, 24),
753 dcp::Colour (0, 0, 0),
754 dcp::Time (0, 0, 0, 0, 24),
755 dcp::Time (0, 0, 0, 0, 24),
757 std::vector<dcp::Ruby>()
762 std::make_shared<dcp::SubtitleString>(
763 boost::optional<string> (),
767 dcp::Colour (128, 0, 64),
770 dcp::Time (5, 41, 0, 21, 24),
771 dcp::Time (6, 12, 15, 21, 24),
780 dcp::Colour (1, 2, 3),
781 dcp::Time (1, 2, 3, 4, 24),
782 dcp::Time (5, 6, 7, 8, 24),
784 std::vector<dcp::Ruby>()
789 std::make_shared<dcp::SubtitleString>(
790 boost::optional<string> (),
794 dcp::Colour (128, 0, 64),
797 dcp::Time (5, 41, 0, 21, 24),
798 dcp::Time (6, 12, 15, 21, 24),
807 dcp::Colour (1, 2, 3),
808 dcp::Time (1, 2, 3, 4, 24),
809 dcp::Time (5, 6, 7, 8, 24),
811 std::vector<dcp::Ruby>()
815 c._id = "a6c58cff-3e1e-4b38-acec-a42224475ef6";
818 "<DCSubtitle Version=\"1.0\">\n"
819 " <SubtitleID>a6c58cff-3e1e-4b38-acec-a42224475ef6</SubtitleID>\n"
820 " <MovieTitle>Test</MovieTitle>\n"
821 " <ReelNumber>1</ReelNumber>\n"
822 " <Language>EN</Language>\n"
823 " <Font AspectAdjust=\"1.0\" Color=\"FFFFFFFF\" Effect=\"none\" EffectColor=\"FF000000\" Id=\"Frutiger\" Italic=\"no\" Script=\"normal\" Size=\"48\" Underlined=\"no\" Weight=\"normal\">\n"
824 " <Subtitle SpotNumber=\"1\" TimeIn=\"00:04:09:229\" TimeOut=\"00:04:11:229\" FadeUpTime=\"0\" FadeDownTime=\"0\">\n"
825 " <Text VAlign=\"top\" VPosition=\"80\">Hello world</Text>\n"
828 " <Font AspectAdjust=\"1.0\" Color=\"FF800040\" Effect=\"border\" EffectColor=\"FF010203\" Italic=\"yes\" Script=\"normal\" Size=\"91\" Underlined=\"yes\" Weight=\"bold\">\n"
829 " <Subtitle SpotNumber=\"2\" TimeIn=\"05:41:00:219\" TimeOut=\"06:12:15:219\" FadeUpTime=\"930792\" FadeDownTime=\"4591834\">\n"
830 " <Text VAlign=\"bottom\" VPosition=\"40\">What's going <Space Size=\"9em\"/>on</Text>\n"
839 /** Write some subtitle content as Interop XML and check that it is right.
840 * This test includes some horizontal alignment.
842 BOOST_AUTO_TEST_CASE (write_interop_subtitle_test2)
844 dcp::InteropSubtitleAsset c;
845 c.set_reel_number ("1");
846 c.set_language ("EN");
847 c.set_movie_title ("Test");
850 std::make_shared<dcp::SubtitleString>(
855 dcp::Colour (255, 255, 255),
858 dcp::Time (0, 4, 9, 22, 24),
859 dcp::Time (0, 4, 11, 22, 24),
868 dcp::Colour (0, 0, 0),
869 dcp::Time (0, 0, 0, 0, 24),
870 dcp::Time (0, 0, 0, 0, 24),
872 std::vector<dcp::Ruby>()
877 std::make_shared<dcp::SubtitleString>(
878 boost::optional<string>(),
882 dcp::Colour (128, 0, 64),
885 dcp::Time (5, 41, 0, 21, 24),
886 dcp::Time (6, 12, 15, 21, 24),
895 dcp::Colour (1, 2, 3),
896 dcp::Time (1, 2, 3, 4, 24),
897 dcp::Time (5, 6, 7, 8, 24),
899 std::vector<dcp::Ruby>()
903 c._id = "a6c58cff-3e1e-4b38-acec-a42224475ef6";
906 "<DCSubtitle Version=\"1.0\">\n"
907 " <SubtitleID>a6c58cff-3e1e-4b38-acec-a42224475ef6</SubtitleID>\n"
908 " <MovieTitle>Test</MovieTitle>\n"
909 " <ReelNumber>1</ReelNumber>\n"
910 " <Language>EN</Language>\n"
911 " <Font AspectAdjust=\"1.0\" Color=\"FFFFFFFF\" Effect=\"none\" EffectColor=\"FF000000\" Id=\"Frutiger\" Italic=\"no\" Script=\"normal\" Size=\"48\" Underlined=\"no\" Weight=\"normal\">\n"
912 " <Subtitle SpotNumber=\"1\" TimeIn=\"00:04:09:229\" TimeOut=\"00:04:11:229\" FadeUpTime=\"0\" FadeDownTime=\"0\">\n"
913 " <Text HPosition=\"-20\" VAlign=\"top\" VPosition=\"80\">Hello world</Text>\n"
916 " <Font AspectAdjust=\"1.0\" Color=\"FF800040\" Effect=\"border\" EffectColor=\"FF010203\" Italic=\"yes\" Script=\"normal\" Size=\"91\" Underlined=\"yes\" Weight=\"bold\">\n"
917 " <Subtitle SpotNumber=\"2\" TimeIn=\"05:41:00:219\" TimeOut=\"06:12:15:219\" FadeUpTime=\"930792\" FadeDownTime=\"4591834\">\n"
918 " <Text HPosition=\"-20\" VAlign=\"bottom\" VPosition=\"40\">What's going on</Text>\n"
927 /* Write some subtitle content as Interop XML using bitmaps and check that it is right */
928 BOOST_AUTO_TEST_CASE (write_interop_subtitle_test3)
932 auto c = std::make_shared<dcp::InteropSubtitleAsset>();
933 c->set_reel_number ("1");
934 c->set_language ("EN");
935 c->set_movie_title ("Test");
938 std::make_shared<dcp::SubtitleImage>(
939 dcp::ArrayData ("test/data/sub.png"),
940 dcp::Time (0, 4, 9, 22, 24),
941 dcp::Time (0, 4, 11, 22, 24),
947 dcp::Time (0, 0, 0, 0, 24),
948 dcp::Time (0, 0, 0, 0, 24)
952 c->_id = "a6c58cff-3e1e-4b38-acec-a42224475ef6";
953 boost::filesystem::remove_all ("build/test/write_interop_subtitle_test3");
954 boost::filesystem::create_directories ("build/test/write_interop_subtitle_test3");
955 c->write ("build/test/write_interop_subtitle_test3/subs.xml");
957 auto reel = std::make_shared<dcp::Reel>();
958 reel->add(std::make_shared<dcp::ReelInteropSubtitleAsset>(c, dcp::Fraction(24, 1), 6046, 0));
960 string const issue_date = "2018-09-02T04:45:18+00:00";
961 string const issuer = "libdcp";
962 string const creator = "libdcp";
963 string const annotation_text = "Created by libdcp";
965 auto cpl = std::make_shared<dcp::CPL>("My film", dcp::ContentKind::FEATURE, dcp::Standard::INTEROP);
967 cpl->set_issuer (issuer);
968 cpl->set_creator (creator);
969 cpl->set_issue_date (issue_date);
970 cpl->set_annotation_text (annotation_text);
971 auto cv = cpl->content_version();
973 cv->label_text = "foo";
974 cpl->set_content_version (*cv);
976 dcp::DCP dcp ("build/test/write_interop_subtitle_test3");
978 dcp.set_issuer(issuer);
979 dcp.set_creator(creator);
980 dcp.set_issue_date(issue_date);
981 dcp.set_annotation_text(annotation_text);
985 dcp::file_to_string("test/ref/write_interop_subtitle_test3/subs.xml"),
986 dcp::file_to_string("build/test/write_interop_subtitle_test3/subs.xml"),
989 check_file(find_file("build/test/write_interop_subtitle_test3", ".png"), "test/data/sub.png");
992 dcp::file_to_string("test/ref/write_interop_subtitle_test3/ASSETMAP"),
993 dcp::file_to_string("build/test/write_interop_subtitle_test3/ASSETMAP"),
998 dcp::file_to_string(find_file("test/ref/write_interop_subtitle_test3", "pkl")),
999 dcp::file_to_string(find_file("build/test/write_interop_subtitle_test3", "pkl")),