2 Copyright (C) 2012-202]1 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;
47 using std::make_shared;
48 using std::shared_ptr;
53 /** Load some subtitle content from Interop XML and check that it is read correctly */
54 BOOST_AUTO_TEST_CASE (read_interop_subtitle_test1)
56 dcp::InteropSubtitleAsset subs ("test/data/subs1.xml");
58 BOOST_CHECK_EQUAL (subs.id(), "cab5c268-222b-41d2-88ae-6d6999441b17");
59 BOOST_CHECK_EQUAL (subs.movie_title(), "Movie Title");
60 BOOST_CHECK_EQUAL (subs.reel_number(), "1");
61 BOOST_CHECK_EQUAL (subs.language(), "French");
63 auto lfn = subs.load_font_nodes ();
64 BOOST_REQUIRE_EQUAL (lfn.size(), 1);
65 shared_ptr<dcp::InteropLoadFontNode> interop_lfn = dynamic_pointer_cast<dcp::InteropLoadFontNode> (lfn.front ());
66 BOOST_REQUIRE (interop_lfn);
67 BOOST_CHECK_EQUAL (interop_lfn->id, "theFontId");
68 BOOST_CHECK_EQUAL (interop_lfn->uri, "arial.ttf");
70 auto s = subs.subtitles_during (dcp::Time (0, 0, 6, 1, 250), dcp::Time (0, 0, 6, 2, 250), false);
71 BOOST_REQUIRE_EQUAL (s.size(), 1);
72 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
73 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
78 dcp::Colour (255, 255, 255),
81 dcp::Time (0, 0, 5, 198, 250),
82 dcp::Time (0, 0, 7, 115, 250),
88 "My jacket was Idi Amin's",
90 dcp::Colour (0, 0, 0),
91 dcp::Time (0, 0, 0, 1, 250),
92 dcp::Time (0, 0, 0, 1, 250)
95 s = subs.subtitles_during (dcp::Time (0, 0, 7, 190, 250), dcp::Time (0, 0, 7, 191, 250), false);
96 BOOST_REQUIRE_EQUAL (s.size(), 2);
97 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
98 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
103 dcp::Colour (255, 255, 255),
106 dcp::Time (0, 0, 7, 177, 250),
107 dcp::Time (0, 0, 11, 31, 250),
113 "My corset was H.M. The Queen's",
115 dcp::Colour (0, 0, 0),
116 dcp::Time (0, 0, 0, 1, 250),
117 dcp::Time (0, 0, 0, 1, 250)
119 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
120 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
121 string ("theFontId"),
125 dcp::Colour (255, 255, 255),
128 dcp::Time (0, 0, 7, 177, 250),
129 dcp::Time (0, 0, 11, 31, 250),
135 "My large wonderbra",
137 dcp::Colour (0, 0, 0),
138 dcp::Time (0, 0, 0, 1, 250),
139 dcp::Time (0, 0, 0, 1, 250)
142 s = subs.subtitles_during (dcp::Time (0, 0, 11, 95, 250), dcp::Time (0, 0, 11, 96, 250), false);
143 BOOST_REQUIRE_EQUAL (s.size(), 1);
144 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
145 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
146 string ("theFontId"),
150 dcp::Colour (255, 255, 255),
153 dcp::Time (0, 0, 11, 94, 250),
154 dcp::Time (0, 0, 13, 63, 250),
160 "Once belonged to the Shah",
162 dcp::Colour (0, 0, 0),
163 dcp::Time (0, 0, 0, 1, 250),
164 dcp::Time (0, 0, 0, 1, 250)
167 s = subs.subtitles_during (dcp::Time (0, 0, 14, 42, 250), dcp::Time (0, 0, 14, 43, 250), false);
168 BOOST_REQUIRE_EQUAL (s.size(), 1);
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, 13, 104, 250),
179 dcp::Time (0, 0, 15, 177, 250),
185 "And these are Roy Hattersley's jeans",
187 dcp::Colour (0, 0, 0),
188 dcp::Time (0, 0, 0, 1, 250),
189 dcp::Time (0, 0, 0, 1, 250)
193 /** And similarly for another one */
194 BOOST_AUTO_TEST_CASE (read_interop_subtitle_test2)
196 dcp::InteropSubtitleAsset subs ("test/data/subs2.xml");
198 auto s = subs.subtitles_during (dcp::Time (0, 0, 42, 100, 250), dcp::Time (0, 0, 42, 101, 250), false);
199 BOOST_REQUIRE_EQUAL (s.size(), 2);
200 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
201 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
206 dcp::Colour (255, 255, 255),
209 dcp::Time (0, 0, 41, 62, 250),
210 dcp::Time (0, 0, 43, 52, 250),
216 "At afternoon tea with John Peel",
218 dcp::Colour (0, 0, 0),
219 dcp::Time (0, 0, 0, 0, 250),
220 dcp::Time (0, 0, 0, 0, 250)
222 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
223 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
228 dcp::Colour (255, 255, 255),
231 dcp::Time (0, 0, 41, 62, 250),
232 dcp::Time (0, 0, 43, 52, 250),
238 "I enquired if his accent was real",
240 dcp::Colour (0, 0, 0),
241 dcp::Time (0, 0, 0, 0, 250),
242 dcp::Time (0, 0, 0, 0, 250)
245 s = subs.subtitles_during (dcp::Time (0, 0, 50, 50, 250), dcp::Time (0, 0, 50, 51, 250), false);
246 BOOST_REQUIRE_EQUAL (s.size(), 2);
247 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
248 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
253 dcp::Colour (255, 255, 255),
256 dcp::Time (0, 0, 50, 42, 250),
257 dcp::Time (0, 0, 52, 21, 250),
263 "He said \"out of the house",
265 dcp::Colour (0, 0, 0),
266 dcp::Time (0, 0, 0, 0, 250),
267 dcp::Time (0, 0, 0, 0, 250)
269 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
270 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
275 dcp::Colour (255, 255, 255),
278 dcp::Time (0, 0, 50, 42, 250),
279 dcp::Time (0, 0, 52, 21, 250),
285 "I'm incredibly scouse",
287 dcp::Colour (0, 0, 0),
288 dcp::Time (0, 0, 0, 0, 250),
289 dcp::Time (0, 0, 0, 0, 250)
292 s = subs.subtitles_during (dcp::Time (0, 1, 2, 300, 250), dcp::Time (0, 1, 2, 301, 250), false);
293 BOOST_REQUIRE_EQUAL (s.size(), 2);
294 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
295 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
300 dcp::Colour(255, 255, 255),
303 dcp::Time(0, 1, 2, 208, 250),
304 dcp::Time(0, 1, 4, 10, 250),
310 "At home it depends how I feel.\"",
312 dcp::Colour(0, 0, 0),
313 dcp::Time(0, 0, 0, 0, 250),
314 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, 1, 2, 208, 250),
326 dcp::Time(0, 1, 4, 10, 250),
332 "I spent a long weekend in Brighton",
334 dcp::Colour(0, 0, 0),
335 dcp::Time(0, 0, 0, 0, 250),
336 dcp::Time(0, 0, 0, 0, 250)
339 s = subs.subtitles_during (dcp::Time (0, 1, 15, 50, 250), dcp::Time (0, 1, 15, 51, 250), false);
340 BOOST_REQUIRE_EQUAL (s.size(), 2);
341 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
342 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
347 dcp::Colour(255, 255, 255),
350 dcp::Time(0, 1, 15, 42, 250),
351 dcp::Time(0, 1, 16, 42, 250),
357 "With the legendary Miss Enid Blyton",
359 dcp::Colour(0, 0, 0),
360 dcp::Time(0, 0, 0, 0, 250),
361 dcp::Time(0, 0, 0, 0, 250)
363 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
364 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
369 dcp::Colour(255, 255, 255),
372 dcp::Time(0, 1, 15, 42, 250),
373 dcp::Time(0, 1, 16, 42, 250),
379 "She said \"you be Noddy",
381 dcp::Colour(0, 0, 0),
382 dcp::Time(0, 0, 0, 0, 250),
383 dcp::Time(0, 0, 0, 0, 250)
386 s = subs.subtitles_during (dcp::Time (0, 1, 27, 200, 250), dcp::Time (0, 1, 27, 201, 250), false);
387 BOOST_REQUIRE_EQUAL (s.size(), 2);
388 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
389 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
394 dcp::Colour(255, 255, 255),
397 dcp::Time(0, 1, 27, 115, 250),
398 dcp::Time(0, 1, 28, 208, 250),
404 "That curious creature the Sphinx",
406 dcp::Colour(0, 0, 0),
407 dcp::Time(0, 0, 0, 0, 250),
408 dcp::Time(0, 0, 0, 0, 250)
410 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
411 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
416 dcp::Colour(255, 255, 255),
419 dcp::Time(0, 1, 27, 115, 250),
420 dcp::Time(0, 1, 28, 208, 250),
426 "Is smarter than anyone thinks",
428 dcp::Colour(0, 0, 0),
429 dcp::Time(0, 0, 0, 0, 250),
430 dcp::Time(0, 0, 0, 0, 250)
433 s = subs.subtitles_during (dcp::Time (0, 1, 42, 300, 250), dcp::Time (0, 1, 42, 301, 250), false);
434 BOOST_REQUIRE_EQUAL (s.size(), 2);
435 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
436 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
441 dcp::Colour (255, 255, 255),
444 dcp::Time (0, 1, 42, 229, 250),
445 dcp::Time (0, 1, 45, 62, 250),
451 "It sits there and smirks",
453 dcp::Colour(0, 0, 0),
454 dcp::Time(0, 0, 0, 0, 250),
455 dcp::Time(0, 0, 0, 0, 250)
457 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
458 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
463 dcp::Colour (255, 255, 255),
466 dcp::Time (0, 1, 42, 229, 250),
467 dcp::Time (0, 1, 45, 62, 250),
473 "And you don't think it works",
475 dcp::Colour(0, 0, 0),
476 dcp::Time(0, 0, 0, 0, 250),
477 dcp::Time(0, 0, 0, 0, 250)
480 s = subs.subtitles_during (dcp::Time (0, 1, 45, 200, 250), dcp::Time (0, 1, 45, 201, 250), false);
481 BOOST_REQUIRE_EQUAL (s.size(), 2);
482 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
483 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
488 dcp::Colour(255, 255, 255),
491 dcp::Time(0, 1, 45, 146, 250),
492 dcp::Time(0, 1, 47, 94, 250),
498 "Then when you're not looking, it winks.",
500 dcp::Colour(0, 0, 0),
501 dcp::Time(0, 0, 0, 0, 250),
502 dcp::Time(0, 0, 0, 0, 250)
504 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
505 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
510 dcp::Colour (255, 255, 255),
513 dcp::Time (0, 1, 45, 146, 250),
514 dcp::Time (0, 1, 47, 94, 250),
520 "When it snows you will find Sister Sledge",
522 dcp::Colour(0, 0, 0),
523 dcp::Time(0, 0, 0, 0, 250),
524 dcp::Time(0, 0, 0, 0, 250)
527 s = subs.subtitles_during (dcp::Time (0, 1, 47, 249, 250), dcp::Time (0, 1, 47, 250, 250), false);
528 BOOST_REQUIRE_EQUAL (s.size(), 2);
529 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
530 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
535 dcp::Colour(255, 255, 255),
538 dcp::Time(0, 1, 47, 146, 250),
539 dcp::Time(0, 1, 48, 167, 250),
545 "Out mooning, at night, on the ledge",
547 dcp::Colour(0, 0, 0),
548 dcp::Time(0, 0, 0, 0, 250),
549 dcp::Time(0, 0, 0, 0, 250)
551 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
552 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
557 dcp::Colour(255, 255, 255),
560 dcp::Time(0, 1, 47, 146, 250),
561 dcp::Time(0, 1, 48, 167, 250),
569 dcp::Colour(0, 0, 0),
570 dcp::Time(0, 0, 0, 0, 250),
571 dcp::Time(0, 0, 0, 0, 250)
574 s = subs.subtitles_during (dcp::Time (0, 2, 6, 210, 250), dcp::Time (0, 2, 6, 211, 250), false);
575 BOOST_REQUIRE_EQUAL (s.size(), 2);
576 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
577 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
582 dcp::Colour (255, 255, 255),
585 dcp::Time (0, 2, 5, 208, 250),
586 dcp::Time (0, 2, 7, 31, 250),
594 dcp::Colour(0, 0, 0),
595 dcp::Time(0, 0, 0, 0, 250),
596 dcp::Time(0, 0, 0, 0, 250)
598 BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
599 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
604 dcp::Colour(255, 255, 255),
607 dcp::Time(0, 2, 5, 208, 250),
608 dcp::Time(0, 2, 7, 31, 250),
616 dcp::Colour(0, 0, 0),
617 dcp::Time(0, 0, 0, 0, 250),
618 dcp::Time(0, 0, 0, 0, 250)
622 /** And one with bitmap subtitles */
623 BOOST_AUTO_TEST_CASE (read_interop_subtitle_test3)
625 dcp::InteropSubtitleAsset subs ("test/data/subs3.xml");
627 BOOST_REQUIRE_EQUAL (subs.subtitles().size(), 1);
628 auto si = dynamic_pointer_cast<const dcp::SubtitleImage>(subs.subtitles().front());
630 BOOST_CHECK (si->png_image() == dcp::ArrayData("test/data/sub.png"));
634 /** Write some subtitle content as Interop XML and check that it is right */
635 BOOST_AUTO_TEST_CASE (write_interop_subtitle_test)
637 dcp::InteropSubtitleAsset c;
638 c.set_reel_number ("1");
639 c.set_language ("EN");
640 c.set_movie_title ("Test");
643 make_shared<dcp::SubtitleString>(
648 dcp::Colour (255, 255, 255),
651 dcp::Time (0, 4, 9, 22, 24),
652 dcp::Time (0, 4, 11, 22, 24),
660 dcp::Colour (0, 0, 0),
661 dcp::Time (0, 0, 0, 0, 24),
662 dcp::Time (0, 0, 0, 0, 24)
667 make_shared<dcp::SubtitleString>(
668 boost::optional<string> (),
672 dcp::Colour (128, 0, 64),
675 dcp::Time (5, 41, 0, 21, 24),
676 dcp::Time (6, 12, 15, 21, 24),
684 dcp::Colour (1, 2, 3),
685 dcp::Time (1, 2, 3, 4, 24),
686 dcp::Time (5, 6, 7, 8, 24)
690 c._id = "a6c58cff-3e1e-4b38-acec-a42224475ef6";
693 "<DCSubtitle Version=\"1.0\">"
694 "<SubtitleID>a6c58cff-3e1e-4b38-acec-a42224475ef6</SubtitleID>"
695 "<MovieTitle>Test</MovieTitle>"
696 "<ReelNumber>1</ReelNumber>"
697 "<Language>EN</Language>"
698 "<Font AspectAdjust=\"1.0\" Color=\"FFFFFFFF\" Effect=\"none\" EffectColor=\"FF000000\" Id=\"Frutiger\" Italic=\"no\" Script=\"normal\" Size=\"48\" Underlined=\"no\" Weight=\"normal\">"
699 "<Subtitle SpotNumber=\"1\" TimeIn=\"00:04:09:229\" TimeOut=\"00:04:11:229\" FadeUpTime=\"0\" FadeDownTime=\"0\">"
700 "<Text VAlign=\"top\" VPosition=\"80\">Hello world</Text>"
703 "<Font AspectAdjust=\"1.0\" Color=\"FF800040\" Effect=\"border\" EffectColor=\"FF010203\" Italic=\"yes\" Script=\"normal\" Size=\"91\" Underlined=\"yes\" Weight=\"bold\">"
704 "<Subtitle SpotNumber=\"2\" TimeIn=\"05:41:00:219\" TimeOut=\"06:12:15:219\" FadeUpTime=\"930792\" FadeDownTime=\"4591834\">"
705 "<Text VAlign=\"bottom\" VPosition=\"40\">What's going on</Text>"
714 /** Write some subtitle content as Interop XML and check that it is right.
715 * This test includes some horizontal alignment.
717 BOOST_AUTO_TEST_CASE (write_interop_subtitle_test2)
719 dcp::InteropSubtitleAsset c;
720 c.set_reel_number ("1");
721 c.set_language ("EN");
722 c.set_movie_title ("Test");
725 make_shared<dcp::SubtitleString>(
730 dcp::Colour (255, 255, 255),
733 dcp::Time (0, 4, 9, 22, 24),
734 dcp::Time (0, 4, 11, 22, 24),
742 dcp::Colour (0, 0, 0),
743 dcp::Time (0, 0, 0, 0, 24),
744 dcp::Time (0, 0, 0, 0, 24)
749 make_shared<dcp::SubtitleString>(
750 boost::optional<string>(),
754 dcp::Colour (128, 0, 64),
757 dcp::Time (5, 41, 0, 21, 24),
758 dcp::Time (6, 12, 15, 21, 24),
766 dcp::Colour (1, 2, 3),
767 dcp::Time (1, 2, 3, 4, 24),
768 dcp::Time (5, 6, 7, 8, 24)
772 c._id = "a6c58cff-3e1e-4b38-acec-a42224475ef6";
775 "<DCSubtitle Version=\"1.0\">"
776 "<SubtitleID>a6c58cff-3e1e-4b38-acec-a42224475ef6</SubtitleID>"
777 "<MovieTitle>Test</MovieTitle>"
778 "<ReelNumber>1</ReelNumber>"
779 "<Language>EN</Language>"
780 "<Font AspectAdjust=\"1.0\" Color=\"FFFFFFFF\" Effect=\"none\" EffectColor=\"FF000000\" Id=\"Frutiger\" Italic=\"no\" Script=\"normal\" Size=\"48\" Underlined=\"no\" Weight=\"normal\">"
781 "<Subtitle SpotNumber=\"1\" TimeIn=\"00:04:09:229\" TimeOut=\"00:04:11:229\" FadeUpTime=\"0\" FadeDownTime=\"0\">"
782 "<Text HPosition=\"-20\" VAlign=\"top\" VPosition=\"80\">Hello world</Text>"
785 "<Font AspectAdjust=\"1.0\" Color=\"FF800040\" Effect=\"border\" EffectColor=\"FF010203\" Italic=\"yes\" Script=\"normal\" Size=\"91\" Underlined=\"yes\" Weight=\"bold\">"
786 "<Subtitle SpotNumber=\"2\" TimeIn=\"05:41:00:219\" TimeOut=\"06:12:15:219\" FadeUpTime=\"930792\" FadeDownTime=\"4591834\">"
787 "<Text HPosition=\"-20\" VAlign=\"bottom\" VPosition=\"40\">What's going on</Text>"
796 /* Write some subtitle content as Interop XML using bitmaps and check that it is right */
797 BOOST_AUTO_TEST_CASE (write_interop_subtitle_test3)
801 auto c = make_shared<dcp::InteropSubtitleAsset>();
802 c->set_reel_number ("1");
803 c->set_language ("EN");
804 c->set_movie_title ("Test");
807 make_shared<dcp::SubtitleImage>(
808 dcp::ArrayData ("test/data/sub.png"),
809 dcp::Time (0, 4, 9, 22, 24),
810 dcp::Time (0, 4, 11, 22, 24),
815 dcp::Time (0, 0, 0, 0, 24),
816 dcp::Time (0, 0, 0, 0, 24)
820 c->_id = "a6c58cff-3e1e-4b38-acec-a42224475ef6";
821 boost::filesystem::remove_all ("build/test/write_interop_subtitle_test3");
822 boost::filesystem::create_directories ("build/test/write_interop_subtitle_test3");
823 c->write ("build/test/write_interop_subtitle_test3/subs.xml");
825 auto reel = make_shared<dcp::Reel>();
826 reel->add(make_shared<dcp::ReelInteropSubtitleAsset>(c, dcp::Fraction(24, 1), 6046, 0));
828 string const issue_date = "2018-09-02T04:45:18+00:00";
829 string const issuer = "libdcp";
830 string const creator = "libdcp";
831 string const annotation_text = "Created by libdcp";
833 auto cpl = make_shared<dcp::CPL>("My film", dcp::ContentKind::FEATURE, dcp::Standard::INTEROP);
835 cpl->set_issuer (issuer);
836 cpl->set_creator (creator);
837 cpl->set_issue_date (issue_date);
838 cpl->set_annotation_text (annotation_text);
839 auto cv = cpl->content_version();
841 cv->label_text = "foo";
842 cpl->set_content_version (*cv);
844 dcp::DCP dcp ("build/test/write_interop_subtitle_test3");
846 dcp.write_xml (issuer, creator, issue_date, annotation_text);
849 dcp::file_to_string("test/ref/write_interop_subtitle_test3/subs.xml"),
850 dcp::file_to_string("build/test/write_interop_subtitle_test3/subs.xml"),
853 check_file ("build/test/write_interop_subtitle_test3/d36f4bb3-c4fa-4a95-9915-6fec3110cd71.png", "test/data/sub.png");
856 dcp::file_to_string("test/ref/write_interop_subtitle_test3/ASSETMAP"),
857 dcp::file_to_string("build/test/write_interop_subtitle_test3/ASSETMAP"),
862 dcp::file_to_string("test/ref/write_interop_subtitle_test3/pkl.xml"),
863 dcp::file_to_string("build/test/write_interop_subtitle_test3/pkl_6a9e31a6-50a4-4ecb-8683-fa667848470a.xml"),