Tidy up write_xml() API a little.
[libdcp.git] / test / interop_subtitle_test.cc
1 /*
2     Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
3
4     This file is part of libdcp.
5
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.
10
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.
15
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/>.
18
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
23     including the two.
24
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.
32 */
33
34
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"
40 #include "test.h"
41 #include <boost/test/unit_test.hpp>
42 #include <iostream>
43
44
45 using std::dynamic_pointer_cast;
46 using std::make_shared;
47 using std::shared_ptr;
48 using std::string;
49 using std::vector;
50
51
52 /** Load some subtitle content from Interop XML and check that it is read correctly */
53 BOOST_AUTO_TEST_CASE (read_interop_subtitle_test1)
54 {
55         dcp::InteropSubtitleAsset subs ("test/data/subs1.xml");
56
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");
61
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");
68
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 (
73                                    string ("theFontId"),
74                                    false,
75                                    false,
76                                    false,
77                                    dcp::Colour (255, 255, 255),
78                                    39,
79                                    1.0,
80                                    dcp::Time (0, 0, 5, 198, 250),
81                                    dcp::Time (0, 0, 7, 115, 250),
82                                    0,
83                                    dcp::HAlign::CENTER,
84                                    0.15,
85                                    dcp::VAlign::BOTTOM,
86                                    dcp::Direction::LTR,
87                                    "My jacket was ",
88                                    dcp::Effect::BORDER,
89                                    dcp::Colour (0, 0, 0),
90                                    dcp::Time (0, 0, 0, 1, 250),
91                                    dcp::Time (0, 0, 0, 1, 250),
92                                    0
93                                    ));
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 (
96                                    string ("theFontId"),
97                                    false,
98                                    false,
99                                    false,
100                                    dcp::Colour (255, 255, 255),
101                                    39,
102                                    1.0,
103                                    dcp::Time (0, 0, 5, 198, 250),
104                                    dcp::Time (0, 0, 7, 115, 250),
105                                    0,
106                                    dcp::HAlign::CENTER,
107                                    0.15,
108                                    dcp::VAlign::BOTTOM,
109                                    dcp::Direction::LTR,
110                                    "Idi Amin's",
111                                    dcp::Effect::BORDER,
112                                    dcp::Colour (0, 0, 0),
113                                    dcp::Time (0, 0, 0, 1, 250),
114                                    dcp::Time (0, 0, 0, 1, 250),
115                                    6
116                                    ));
117
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"),
123                                    true,
124                                    false,
125                                    false,
126                                    dcp::Colour (255, 255, 255),
127                                    39,
128                                    1.0,
129                                    dcp::Time (0, 0, 7, 177, 250),
130                                    dcp::Time (0, 0, 11, 31, 250),
131                                    0,
132                                    dcp::HAlign::CENTER,
133                                    0.21,
134                                    dcp::VAlign::BOTTOM,
135                                    dcp::Direction::LTR,
136                                    "My corset was H.M. The Queen's",
137                                    dcp::Effect::BORDER,
138                                    dcp::Colour (0, 0, 0),
139                                    dcp::Time (0, 0, 0, 1, 250),
140                                    dcp::Time (0, 0, 0, 1, 250),
141                                    0
142                                    ));
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"),
146                                    false,
147                                    false,
148                                    false,
149                                    dcp::Colour (255, 255, 255),
150                                    39,
151                                    1.0,
152                                    dcp::Time (0, 0, 7, 177, 250),
153                                    dcp::Time (0, 0, 11, 31, 250),
154                                    0,
155                                    dcp::HAlign::CENTER,
156                                    0.15,
157                                    dcp::VAlign::BOTTOM,
158                                    dcp::Direction::LTR,
159                                    "My large wonderbra",
160                                    dcp::Effect::BORDER,
161                                    dcp::Colour (0, 0, 0),
162                                    dcp::Time (0, 0, 0, 1, 250),
163                                    dcp::Time (0, 0, 0, 1, 250),
164                                    0
165                                    ));
166
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"),
172                                    false,
173                                    false,
174                                    false,
175                                    dcp::Colour (255, 255, 255),
176                                    39,
177                                    1.0,
178                                    dcp::Time (0, 0, 11, 94, 250),
179                                    dcp::Time (0, 0, 13, 63, 250),
180                                    0,
181                                    dcp::HAlign::CENTER,
182                                    0.15,
183                                    dcp::VAlign::BOTTOM,
184                                    dcp::Direction::LTR,
185                                    "Once belonged to the Shah",
186                                    dcp::Effect::BORDER,
187                                    dcp::Colour (0, 0, 0),
188                                    dcp::Time (0, 0, 0, 1, 250),
189                                    dcp::Time (0, 0, 0, 1, 250),
190                                    0
191                                    ));
192
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"),
198                                    false,
199                                    true,
200                                    true,
201                                    dcp::Colour (255, 255, 255),
202                                    39,
203                                    1.0,
204                                    dcp::Time (0, 0, 13, 104, 250),
205                                    dcp::Time (0, 0, 15, 177, 250),
206                                    0,
207                                    dcp::HAlign::CENTER,
208                                    0.15,
209                                    dcp::VAlign::BOTTOM,
210                                    dcp::Direction::LTR,
211                                    "And these are Roy Hattersley's jeans",
212                                    dcp::Effect::BORDER,
213                                    dcp::Colour (0, 0, 0),
214                                    dcp::Time (0, 0, 0, 1, 250),
215                                    dcp::Time (0, 0, 0, 1, 250),
216                                    0
217                                    ));
218 }
219
220 /** And similarly for another one */
221 BOOST_AUTO_TEST_CASE (read_interop_subtitle_test2)
222 {
223         dcp::InteropSubtitleAsset subs ("test/data/subs2.xml");
224
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 (
229                                    string ("theFont"),
230                                    true,
231                                    false,
232                                    false,
233                                    dcp::Colour (255, 255, 255),
234                                    42,
235                                    1.0,
236                                    dcp::Time (0, 0, 41, 62, 250),
237                                    dcp::Time (0, 0, 43, 52, 250),
238                                    0,
239                                    dcp::HAlign::CENTER,
240                                    0.89,
241                                    dcp::VAlign::TOP,
242                                    dcp::Direction::LTR,
243                                    "At afternoon tea with John Peel",
244                                    dcp::Effect::BORDER,
245                                    dcp::Colour (0, 0, 0),
246                                    dcp::Time (0, 0, 0, 0, 250),
247                                    dcp::Time (0, 0, 0, 0, 250),
248                                    0
249                                    ));
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 (
252                                    string ("theFont"),
253                                    true,
254                                    false,
255                                    false,
256                                    dcp::Colour (255, 255, 255),
257                                    42,
258                                    1.0,
259                                    dcp::Time (0, 0, 41, 62, 250),
260                                    dcp::Time (0, 0, 43, 52, 250),
261                                    0,
262                                    dcp::HAlign::CENTER,
263                                    0.95,
264                                    dcp::VAlign::TOP,
265                                    dcp::Direction::LTR,
266                                    "I enquired if his accent was real",
267                                    dcp::Effect::BORDER,
268                                    dcp::Colour (0, 0, 0),
269                                    dcp::Time (0, 0, 0, 0, 250),
270                                    dcp::Time (0, 0, 0, 0, 250),
271                                    0
272                                    ));
273
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 (
278                                    string ("theFont"),
279                                    true,
280                                    false,
281                                    false,
282                                    dcp::Colour (255, 255, 255),
283                                    42,
284                                    1.0,
285                                    dcp::Time (0, 0, 50, 42, 250),
286                                    dcp::Time (0, 0, 52, 21, 250),
287                                    0,
288                                    dcp::HAlign::CENTER,
289                                    0.89,
290                                    dcp::VAlign::TOP,
291                                    dcp::Direction::LTR,
292                                    "He said \"out of the house",
293                                    dcp::Effect::BORDER,
294                                    dcp::Colour (0, 0, 0),
295                                    dcp::Time (0, 0, 0, 0, 250),
296                                    dcp::Time (0, 0, 0, 0, 250),
297                                    0
298                                    ));
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 (
301                                    string ("theFont"),
302                                    true,
303                                    false,
304                                    false,
305                                    dcp::Colour (255, 255, 255),
306                                    42,
307                                    1.0,
308                                    dcp::Time (0, 0, 50, 42, 250),
309                                    dcp::Time (0, 0, 52, 21, 250),
310                                    0,
311                                    dcp::HAlign::CENTER,
312                                    0.95,
313                                    dcp::VAlign::TOP,
314                                    dcp::Direction::LTR,
315                                    "I'm incredibly scouse",
316                                    dcp::Effect::BORDER,
317                                    dcp::Colour (0, 0, 0),
318                                    dcp::Time (0, 0, 0, 0, 250),
319                                    dcp::Time (0, 0, 0, 0, 250),
320                                    0
321                                    ));
322
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 (
327                                    string("theFont"),
328                                    true,
329                                    false,
330                                    false,
331                                    dcp::Colour(255, 255, 255),
332                                    42,
333                                    1.0,
334                                    dcp::Time(0, 1, 2, 208, 250),
335                                    dcp::Time(0, 1, 4, 10, 250),
336                                    0,
337                                    dcp::HAlign::CENTER,
338                                    0.89,
339                                    dcp::VAlign::TOP,
340                                    dcp::Direction::LTR,
341                                    "At home it depends how I feel.\"",
342                                    dcp::Effect::BORDER,
343                                    dcp::Colour(0, 0, 0),
344                                    dcp::Time(0, 0, 0, 0, 250),
345                                    dcp::Time(0, 0, 0, 0, 250),
346                                    0
347                                    ));
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 (
350                                    string ("theFont"),
351                                    true,
352                                    false,
353                                    false,
354                                    dcp::Colour(255, 255, 255),
355                                    42,
356                                    1.0,
357                                    dcp::Time(0, 1, 2, 208, 250),
358                                    dcp::Time(0, 1, 4, 10, 250),
359                                    0,
360                                    dcp::HAlign::CENTER,
361                                    0.95,
362                                    dcp::VAlign::TOP,
363                                    dcp::Direction::LTR,
364                                    "I spent a long weekend in Brighton",
365                                    dcp::Effect::BORDER,
366                                    dcp::Colour(0, 0, 0),
367                                    dcp::Time(0, 0, 0, 0, 250),
368                                    dcp::Time(0, 0, 0, 0, 250),
369                                    0
370                                    ));
371
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 (
376                                    string ("theFont"),
377                                    true,
378                                    false,
379                                    false,
380                                    dcp::Colour(255, 255, 255),
381                                    42,
382                                    1.0,
383                                    dcp::Time(0, 1, 15, 42, 250),
384                                    dcp::Time(0, 1, 16, 42, 250),
385                                    0,
386                                    dcp::HAlign::CENTER,
387                                    0.89,
388                                    dcp::VAlign::TOP,
389                                    dcp::Direction::RTL,
390                                    "With the legendary Miss Enid Blyton",
391                                    dcp::Effect::BORDER,
392                                    dcp::Colour(0, 0, 0),
393                                    dcp::Time(0, 0, 0, 0, 250),
394                                    dcp::Time(0, 0, 0, 0, 250),
395                                    0
396                                    ));
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 (
399                                    string ("theFont"),
400                                    true,
401                                    false,
402                                    false,
403                                    dcp::Colour(255, 255, 255),
404                                    42,
405                                    1.0,
406                                    dcp::Time(0, 1, 15, 42, 250),
407                                    dcp::Time(0, 1, 16, 42, 250),
408                                    0,
409                                    dcp::HAlign::CENTER,
410                                    0.95,
411                                    dcp::VAlign::TOP,
412                                    dcp::Direction::TTB,
413                                    "She said \"you be Noddy",
414                                    dcp::Effect::BORDER,
415                                    dcp::Colour(0, 0, 0),
416                                    dcp::Time(0, 0, 0, 0, 250),
417                                    dcp::Time(0, 0, 0, 0, 250),
418                                    0
419                                    ));
420
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 (
425                                    string ("theFont"),
426                                    true,
427                                    false,
428                                    false,
429                                    dcp::Colour(255, 255, 255),
430                                    42,
431                                    1.0,
432                                    dcp::Time(0, 1, 27, 115, 250),
433                                    dcp::Time(0, 1, 28, 208, 250),
434                                    0,
435                                    dcp::HAlign::CENTER,
436                                    0.89,
437                                    dcp::VAlign::TOP,
438                                    dcp::Direction::BTT,
439                                    "That curious creature the Sphinx",
440                                    dcp::Effect::BORDER,
441                                    dcp::Colour(0, 0, 0),
442                                    dcp::Time(0, 0, 0, 0, 250),
443                                    dcp::Time(0, 0, 0, 0, 250),
444                                    0
445                                    ));
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 (
448                                    string ("theFont"),
449                                    true,
450                                    false,
451                                    false,
452                                    dcp::Colour(255, 255, 255),
453                                    42,
454                                    1.0,
455                                    dcp::Time(0, 1, 27, 115, 250),
456                                    dcp::Time(0, 1, 28, 208, 250),
457                                    0,
458                                    dcp::HAlign::CENTER,
459                                    0.95,
460                                    dcp::VAlign::TOP,
461                                    dcp::Direction::LTR,
462                                    "Is smarter than anyone thinks",
463                                    dcp::Effect::BORDER,
464                                    dcp::Colour(0, 0, 0),
465                                    dcp::Time(0, 0, 0, 0, 250),
466                                    dcp::Time(0, 0, 0, 0, 250),
467                                    0
468                                    ));
469
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 (
474                                    string ("theFont"),
475                                    false,
476                                    false,
477                                    false,
478                                    dcp::Colour (255, 255, 255),
479                                    42,
480                                    1.0,
481                                    dcp::Time (0, 1, 42, 229, 250),
482                                    dcp::Time (0, 1, 45, 62, 250),
483                                    0,
484                                    dcp::HAlign::CENTER,
485                                    0.89,
486                                    dcp::VAlign::TOP,
487                                    dcp::Direction::LTR,
488                                    "It sits there and smirks",
489                                    dcp::Effect::BORDER,
490                                    dcp::Colour(0, 0, 0),
491                                    dcp::Time(0, 0, 0, 0, 250),
492                                    dcp::Time(0, 0, 0, 0, 250),
493                                    0
494                                    ));
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 (
497                                    string ("theFont"),
498                                    false,
499                                    false,
500                                    false,
501                                    dcp::Colour (255, 255, 255),
502                                    42,
503                                    1.0,
504                                    dcp::Time (0, 1, 42, 229, 250),
505                                    dcp::Time (0, 1, 45, 62, 250),
506                                    0,
507                                    dcp::HAlign::CENTER,
508                                    0.95,
509                                    dcp::VAlign::TOP,
510                                    dcp::Direction::LTR,
511                                    "And you don't think it works",
512                                    dcp::Effect::BORDER,
513                                    dcp::Colour(0, 0, 0),
514                                    dcp::Time(0, 0, 0, 0, 250),
515                                    dcp::Time(0, 0, 0, 0, 250),
516                                    0
517                                    ));
518
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 (
523                                    string("theFont"),
524                                    false,
525                                    false,
526                                    false,
527                                    dcp::Colour(255, 255, 255),
528                                    42,
529                                    1.0,
530                                    dcp::Time(0, 1, 45, 146, 250),
531                                    dcp::Time(0, 1, 47, 94, 250),
532                                    0,
533                                    dcp::HAlign::CENTER,
534                                    0.89,
535                                    dcp::VAlign::TOP,
536                                    dcp::Direction::LTR,
537                                    "Then when you're not looking, it winks.",
538                                    dcp::Effect::BORDER,
539                                    dcp::Colour(0, 0, 0),
540                                    dcp::Time(0, 0, 0, 0, 250),
541                                    dcp::Time(0, 0, 0, 0, 250),
542                                    0
543                                    ));
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 (
546                                    string ("theFont"),
547                                    false,
548                                    false,
549                                    false,
550                                    dcp::Colour (255, 255, 255),
551                                    42,
552                                    1.0,
553                                    dcp::Time (0, 1, 45, 146, 250),
554                                    dcp::Time (0, 1, 47, 94, 250),
555                                    0,
556                                    dcp::HAlign::CENTER,
557                                    0.95,
558                                    dcp::VAlign::TOP,
559                                    dcp::Direction::LTR,
560                                    "When it snows you will find Sister Sledge",
561                                    dcp::Effect::BORDER,
562                                    dcp::Colour(0, 0, 0),
563                                    dcp::Time(0, 0, 0, 0, 250),
564                                    dcp::Time(0, 0, 0, 0, 250),
565                                    0
566                                    ));
567
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 (
572                                    string ("theFont"),
573                                    false,
574                                    false,
575                                    false,
576                                    dcp::Colour(255, 255, 255),
577                                    42,
578                                    1.0,
579                                    dcp::Time(0, 1, 47, 146, 250),
580                                    dcp::Time(0, 1, 48, 167, 250),
581                                    0,
582                                    dcp::HAlign::CENTER,
583                                    0.89,
584                                    dcp::VAlign::TOP,
585                                    dcp::Direction::LTR,
586                                    "Out mooning, at night, on the ledge",
587                                    dcp::Effect::BORDER,
588                                    dcp::Colour(0, 0, 0),
589                                    dcp::Time(0, 0, 0, 0, 250),
590                                    dcp::Time(0, 0, 0, 0, 250),
591                                    0
592                                    ));
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 (
595                                    string ("theFont"),
596                                    false,
597                                    false,
598                                    false,
599                                    dcp::Colour(255, 255, 255),
600                                    42,
601                                    1.0,
602                                    dcp::Time(0, 1, 47, 146, 250),
603                                    dcp::Time(0, 1, 48, 167, 250),
604                                    0,
605                                    dcp::HAlign::CENTER,
606                                    0.95,
607                                    dcp::VAlign::TOP,
608                                    dcp::Direction::LTR,
609                                    "One storey down",
610                                    dcp::Effect::BORDER,
611                                    dcp::Colour(0, 0, 0),
612                                    dcp::Time(0, 0, 0, 0, 250),
613                                    dcp::Time(0, 0, 0, 0, 250),
614                                    0
615                                    ));
616
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 (
621                                    string ("theFont"),
622                                    true,
623                                    false,
624                                    false,
625                                    dcp::Colour (255, 255, 255),
626                                    42,
627                                    1.0,
628                                    dcp::Time (0, 2, 5, 208, 250),
629                                    dcp::Time (0, 2, 7, 31, 250),
630                                    0,
631                                    dcp::HAlign::CENTER,
632                                    0.89,
633                                    dcp::VAlign::TOP,
634                                    dcp::Direction::LTR,
635                                    "HELLO",
636                                    dcp::Effect::BORDER,
637                                    dcp::Colour(0, 0, 0),
638                                    dcp::Time(0, 0, 0, 0, 250),
639                                    dcp::Time(0, 0, 0, 0, 250),
640                                    0
641                                    ));
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 (
644                                    string ("theFont"),
645                                    true,
646                                    false,
647                                    false,
648                                    dcp::Colour(255, 255, 255),
649                                    42,
650                                    1.0,
651                                    dcp::Time(0, 2, 5, 208, 250),
652                                    dcp::Time(0, 2, 7, 31, 250),
653                                    0,
654                                    dcp::HAlign::CENTER,
655                                    0.95,
656                                    dcp::VAlign::TOP,
657                                    dcp::Direction::LTR,
658                                    "WORLD",
659                                    dcp::Effect::BORDER,
660                                    dcp::Colour(0, 0, 0),
661                                    dcp::Time(0, 0, 0, 0, 250),
662                                    dcp::Time(0, 0, 0, 0, 250),
663                                    0
664                                    ));
665 }
666
667 /** And one with bitmap subtitles */
668 BOOST_AUTO_TEST_CASE (read_interop_subtitle_test3)
669 {
670         dcp::InteropSubtitleAsset subs ("test/data/subs3.xml");
671
672         BOOST_REQUIRE_EQUAL (subs.subtitles().size(), 1U);
673         auto si = dynamic_pointer_cast<const dcp::SubtitleImage>(subs.subtitles().front());
674         BOOST_REQUIRE (si);
675         BOOST_CHECK (si->png_image() == dcp::ArrayData("test/data/sub.png"));
676 }
677
678
679 /** Write some subtitle content as Interop XML and check that it is right */
680 BOOST_AUTO_TEST_CASE (write_interop_subtitle_test)
681 {
682         dcp::InteropSubtitleAsset c;
683         c.set_reel_number ("1");
684         c.set_language ("EN");
685         c.set_movie_title ("Test");
686
687         c.add (
688                 make_shared<dcp::SubtitleString>(
689                         string ("Frutiger"),
690                         false,
691                         false,
692                         false,
693                         dcp::Colour (255, 255, 255),
694                         48,
695                         1.0,
696                         dcp::Time (0, 4,  9, 22, 24),
697                         dcp::Time (0, 4, 11, 22, 24),
698                         0,
699                         dcp::HAlign::CENTER,
700                         0.8,
701                         dcp::VAlign::TOP,
702                         dcp::Direction::LTR,
703                         "Hello world",
704                         dcp::Effect::NONE,
705                         dcp::Colour (0, 0, 0),
706                         dcp::Time (0, 0, 0, 0, 24),
707                         dcp::Time (0, 0, 0, 0, 24),
708                         0
709                         )
710                 );
711
712         c.add (
713                 make_shared<dcp::SubtitleString>(
714                         boost::optional<string> (),
715                         true,
716                         true,
717                         true,
718                         dcp::Colour (128, 0, 64),
719                         91,
720                         1.0,
721                         dcp::Time (5, 41,  0, 21, 24),
722                         dcp::Time (6, 12, 15, 21, 24),
723                         0,
724                         dcp::HAlign::CENTER,
725                         0.4,
726                         dcp::VAlign::BOTTOM,
727                         dcp::Direction::LTR,
728                         "What's going ",
729                         dcp::Effect::BORDER,
730                         dcp::Colour (1, 2, 3),
731                         dcp::Time (1, 2, 3, 4, 24),
732                         dcp::Time (5, 6, 7, 8, 24),
733                         0
734                         )
735                 );
736
737         c.add (
738                 make_shared<dcp::SubtitleString>(
739                         boost::optional<string> (),
740                         true,
741                         true,
742                         true,
743                         dcp::Colour (128, 0, 64),
744                         91,
745                         1.0,
746                         dcp::Time (5, 41,  0, 21, 24),
747                         dcp::Time (6, 12, 15, 21, 24),
748                         0,
749                         dcp::HAlign::CENTER,
750                         0.4,
751                         dcp::VAlign::BOTTOM,
752                         dcp::Direction::LTR,
753                         "on",
754                         dcp::Effect::BORDER,
755                         dcp::Colour (1, 2, 3),
756                         dcp::Time (1, 2, 3, 4, 24),
757                         dcp::Time (5, 6, 7, 8, 24),
758                         9
759                         )
760                 );
761
762         c._id = "a6c58cff-3e1e-4b38-acec-a42224475ef6";
763
764         check_xml (
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"
773                 "    </Subtitle>\n"
774                 "  </Font>\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"
778                 "    </Subtitle>\n"
779                 "  </Font>\n"
780                 "</DCSubtitle>",
781                 c.xml_as_string (),
782                 vector<string>()
783                 );
784 }
785
786 /** Write some subtitle content as Interop XML and check that it is right.
787  *  This test includes some horizontal alignment.
788  */
789 BOOST_AUTO_TEST_CASE (write_interop_subtitle_test2)
790 {
791         dcp::InteropSubtitleAsset c;
792         c.set_reel_number ("1");
793         c.set_language ("EN");
794         c.set_movie_title ("Test");
795
796         c.add (
797                 make_shared<dcp::SubtitleString>(
798                         string ("Frutiger"),
799                         false,
800                         false,
801                         false,
802                         dcp::Colour (255, 255, 255),
803                         48,
804                         1.0,
805                         dcp::Time (0, 4,  9, 22, 24),
806                         dcp::Time (0, 4, 11, 22, 24),
807                         -0.2,
808                         dcp::HAlign::CENTER,
809                         0.8,
810                         dcp::VAlign::TOP,
811                         dcp::Direction::LTR,
812                         "Hello world",
813                         dcp::Effect::NONE,
814                         dcp::Colour (0, 0, 0),
815                         dcp::Time (0, 0, 0, 0, 24),
816                         dcp::Time (0, 0, 0, 0, 24),
817                         0
818                         )
819                 );
820
821         c.add (
822                 make_shared<dcp::SubtitleString>(
823                         boost::optional<string>(),
824                         true,
825                         true,
826                         true,
827                         dcp::Colour (128, 0, 64),
828                         91,
829                         1.0,
830                         dcp::Time (5, 41,  0, 21, 24),
831                         dcp::Time (6, 12, 15, 21, 24),
832                         -0.2,
833                         dcp::HAlign::CENTER,
834                         0.4,
835                         dcp::VAlign::BOTTOM,
836                         dcp::Direction::LTR,
837                         "What's going on",
838                         dcp::Effect::BORDER,
839                         dcp::Colour (1, 2, 3),
840                         dcp::Time (1, 2, 3, 4, 24),
841                         dcp::Time (5, 6, 7, 8, 24),
842                         0
843                         )
844                 );
845
846         c._id = "a6c58cff-3e1e-4b38-acec-a42224475ef6";
847
848         check_xml (
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"
857                 "    </Subtitle>\n"
858                 "  </Font>\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"
862                 "    </Subtitle>\n"
863                 "  </Font>\n"
864                 "</DCSubtitle>",
865                 c.xml_as_string (),
866                 vector<string>()
867                 );
868 }
869
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)
872 {
873         RNGFixer fix;
874
875         auto c = make_shared<dcp::InteropSubtitleAsset>();
876         c->set_reel_number ("1");
877         c->set_language ("EN");
878         c->set_movie_title ("Test");
879
880         c->add (
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),
885                         0,
886                         dcp::HAlign::CENTER,
887                         0.8,
888                         dcp::VAlign::TOP,
889                         dcp::Time (0, 0, 0, 0, 24),
890                         dcp::Time (0, 0, 0, 0, 24)
891                         )
892                 );
893
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");
898
899         auto reel = make_shared<dcp::Reel>();
900         reel->add(make_shared<dcp::ReelInteropSubtitleAsset>(c, dcp::Fraction(24, 1), 6046, 0));
901
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";
906
907         auto cpl = make_shared<dcp::CPL>("My film", dcp::ContentKind::FEATURE, dcp::Standard::INTEROP);
908         cpl->add (reel);
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();
914         BOOST_REQUIRE (cv);
915         cv->label_text = "foo";
916         cpl->set_content_version (*cv);
917
918         dcp::DCP dcp ("build/test/write_interop_subtitle_test3");
919         dcp.add (cpl);
920         dcp.set_issuer(issuer);
921         dcp.set_creator(creator);
922         dcp.set_issue_date(issue_date);
923         dcp.set_annotation_text(annotation_text);
924         dcp.write_xml();
925
926         check_xml (
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"),
929                 vector<string>()
930                 );
931         check_file ("build/test/write_interop_subtitle_test3/d36f4bb3-c4fa-4a95-9915-6fec3110cd71.png", "test/data/sub.png");
932
933         check_xml (
934                 dcp::file_to_string("test/ref/write_interop_subtitle_test3/ASSETMAP"),
935                 dcp::file_to_string("build/test/write_interop_subtitle_test3/ASSETMAP"),
936                 vector<string>()
937                 );
938
939         check_xml (
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")),
942                 vector<string>()
943                 );
944 }
945