Cleanup: move EqualityOptions into its own file.
[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::shared_ptr;
47 using std::string;
48 using std::vector;
49
50
51 /** Load some subtitle content from Interop XML and check that it is read correctly */
52 BOOST_AUTO_TEST_CASE (read_interop_subtitle_test1)
53 {
54         dcp::InteropSubtitleAsset subs ("test/data/subs1.xml");
55
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");
60
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");
67
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 (
72                                    string ("theFontId"),
73                                    false,
74                                    false,
75                                    false,
76                                    dcp::Colour (255, 255, 255),
77                                    39,
78                                    1.0,
79                                    dcp::Time (0, 0, 5, 198, 250),
80                                    dcp::Time (0, 0, 7, 115, 250),
81                                    0,
82                                    dcp::HAlign::CENTER,
83                                    0.15,
84                                    dcp::VAlign::BOTTOM,
85                                    0,
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                                    0,
110                                    dcp::Direction::LTR,
111                                    "Idi Amin's",
112                                    dcp::Effect::BORDER,
113                                    dcp::Colour (0, 0, 0),
114                                    dcp::Time (0, 0, 0, 1, 250),
115                                    dcp::Time (0, 0, 0, 1, 250),
116                                    6
117                                    ));
118
119         s = subs.subtitles_during (dcp::Time (0, 0, 7, 190, 250), dcp::Time (0, 0, 7, 191, 250), false);
120         BOOST_REQUIRE_EQUAL (s.size(), 2U);
121         BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
122         BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
123                                    string ("theFontId"),
124                                    true,
125                                    false,
126                                    false,
127                                    dcp::Colour (255, 255, 255),
128                                    39,
129                                    1.0,
130                                    dcp::Time (0, 0, 7, 177, 250),
131                                    dcp::Time (0, 0, 11, 31, 250),
132                                    0,
133                                    dcp::HAlign::CENTER,
134                                    0.21,
135                                    dcp::VAlign::BOTTOM,
136                                    0,
137                                    dcp::Direction::LTR,
138                                    "My corset was H.M. The Queen's",
139                                    dcp::Effect::BORDER,
140                                    dcp::Colour (0, 0, 0),
141                                    dcp::Time (0, 0, 0, 1, 250),
142                                    dcp::Time (0, 0, 0, 1, 250),
143                                    0
144                                    ));
145         BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
146         BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
147                                    string ("theFontId"),
148                                    false,
149                                    false,
150                                    false,
151                                    dcp::Colour (255, 255, 255),
152                                    39,
153                                    1.0,
154                                    dcp::Time (0, 0, 7, 177, 250),
155                                    dcp::Time (0, 0, 11, 31, 250),
156                                    0,
157                                    dcp::HAlign::CENTER,
158                                    0.15,
159                                    dcp::VAlign::BOTTOM,
160                                    0,
161                                    dcp::Direction::LTR,
162                                    "My large wonderbra",
163                                    dcp::Effect::BORDER,
164                                    dcp::Colour (0, 0, 0),
165                                    dcp::Time (0, 0, 0, 1, 250),
166                                    dcp::Time (0, 0, 0, 1, 250),
167                                    0
168                                    ));
169
170         s = subs.subtitles_during (dcp::Time (0, 0, 11, 95, 250), dcp::Time (0, 0, 11, 96, 250), false);
171         BOOST_REQUIRE_EQUAL (s.size(), 1U);
172         BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
173         BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
174                                    string ("theFontId"),
175                                    false,
176                                    false,
177                                    false,
178                                    dcp::Colour (255, 255, 255),
179                                    39,
180                                    1.0,
181                                    dcp::Time (0, 0, 11, 94, 250),
182                                    dcp::Time (0, 0, 13, 63, 250),
183                                    0,
184                                    dcp::HAlign::CENTER,
185                                    0.15,
186                                    dcp::VAlign::BOTTOM,
187                                    0,
188                                    dcp::Direction::LTR,
189                                    "Once belonged to the Shah",
190                                    dcp::Effect::BORDER,
191                                    dcp::Colour (0, 0, 0),
192                                    dcp::Time (0, 0, 0, 1, 250),
193                                    dcp::Time (0, 0, 0, 1, 250),
194                                    0
195                                    ));
196
197         s = subs.subtitles_during (dcp::Time (0, 0, 14, 42, 250), dcp::Time (0, 0, 14, 43, 250), false);
198         BOOST_REQUIRE_EQUAL (s.size(), 1U);
199         BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
200         BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
201                                    string ("theFontId"),
202                                    false,
203                                    true,
204                                    true,
205                                    dcp::Colour (255, 255, 255),
206                                    39,
207                                    1.0,
208                                    dcp::Time (0, 0, 13, 104, 250),
209                                    dcp::Time (0, 0, 15, 177, 250),
210                                    0,
211                                    dcp::HAlign::CENTER,
212                                    0.15,
213                                    dcp::VAlign::BOTTOM,
214                                    0,
215                                    dcp::Direction::LTR,
216                                    "And these are Roy Hattersley's jeans",
217                                    dcp::Effect::BORDER,
218                                    dcp::Colour (0, 0, 0),
219                                    dcp::Time (0, 0, 0, 1, 250),
220                                    dcp::Time (0, 0, 0, 1, 250),
221                                    0
222                                    ));
223 }
224
225 /** And similarly for another one */
226 BOOST_AUTO_TEST_CASE (read_interop_subtitle_test2)
227 {
228         dcp::InteropSubtitleAsset subs ("test/data/subs2.xml");
229
230         auto s = subs.subtitles_during (dcp::Time (0, 0, 42, 100, 250), dcp::Time (0, 0, 42, 101, 250), false);
231         BOOST_REQUIRE_EQUAL (s.size(), 2U);
232         BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
233         BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
234                                    string ("theFont"),
235                                    true,
236                                    false,
237                                    false,
238                                    dcp::Colour (255, 255, 255),
239                                    42,
240                                    1.0,
241                                    dcp::Time (0, 0, 41, 62, 250),
242                                    dcp::Time (0, 0, 43, 52, 250),
243                                    0,
244                                    dcp::HAlign::CENTER,
245                                    0.89,
246                                    dcp::VAlign::TOP,
247                                    0,
248                                    dcp::Direction::LTR,
249                                    "At afternoon tea with John Peel",
250                                    dcp::Effect::BORDER,
251                                    dcp::Colour (0, 0, 0),
252                                    dcp::Time (0, 0, 0, 0, 250),
253                                    dcp::Time (0, 0, 0, 0, 250),
254                                    0
255                                    ));
256         BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
257         BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
258                                    string ("theFont"),
259                                    true,
260                                    false,
261                                    false,
262                                    dcp::Colour (255, 255, 255),
263                                    42,
264                                    1.0,
265                                    dcp::Time (0, 0, 41, 62, 250),
266                                    dcp::Time (0, 0, 43, 52, 250),
267                                    0,
268                                    dcp::HAlign::CENTER,
269                                    0.95,
270                                    dcp::VAlign::TOP,
271                                    0,
272                                    dcp::Direction::LTR,
273                                    "I enquired if his accent was real",
274                                    dcp::Effect::BORDER,
275                                    dcp::Colour (0, 0, 0),
276                                    dcp::Time (0, 0, 0, 0, 250),
277                                    dcp::Time (0, 0, 0, 0, 250),
278                                    0
279                                    ));
280
281         s = subs.subtitles_during (dcp::Time (0, 0, 50, 50, 250), dcp::Time (0, 0, 50, 51, 250), false);
282         BOOST_REQUIRE_EQUAL (s.size(), 2U);
283         BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
284         BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
285                                    string ("theFont"),
286                                    true,
287                                    false,
288                                    false,
289                                    dcp::Colour (255, 255, 255),
290                                    42,
291                                    1.0,
292                                    dcp::Time (0, 0, 50, 42, 250),
293                                    dcp::Time (0, 0, 52, 21, 250),
294                                    0,
295                                    dcp::HAlign::CENTER,
296                                    0.89,
297                                    dcp::VAlign::TOP,
298                                    0,
299                                    dcp::Direction::LTR,
300                                    "He said \"out of the house",
301                                    dcp::Effect::BORDER,
302                                    dcp::Colour (0, 0, 0),
303                                    dcp::Time (0, 0, 0, 0, 250),
304                                    dcp::Time (0, 0, 0, 0, 250),
305                                    0
306                                    ));
307         BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
308         BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
309                                    string ("theFont"),
310                                    true,
311                                    false,
312                                    false,
313                                    dcp::Colour (255, 255, 255),
314                                    42,
315                                    1.0,
316                                    dcp::Time (0, 0, 50, 42, 250),
317                                    dcp::Time (0, 0, 52, 21, 250),
318                                    0,
319                                    dcp::HAlign::CENTER,
320                                    0.95,
321                                    dcp::VAlign::TOP,
322                                    0,
323                                    dcp::Direction::LTR,
324                                    "I'm incredibly scouse",
325                                    dcp::Effect::BORDER,
326                                    dcp::Colour (0, 0, 0),
327                                    dcp::Time (0, 0, 0, 0, 250),
328                                    dcp::Time (0, 0, 0, 0, 250),
329                                    0
330                                    ));
331
332         s = subs.subtitles_during (dcp::Time (0, 1, 2, 300, 250), dcp::Time (0, 1, 2, 301, 250), false);
333         BOOST_REQUIRE_EQUAL (s.size(), 2U);
334         BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
335         BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
336                                    string("theFont"),
337                                    true,
338                                    false,
339                                    false,
340                                    dcp::Colour(255, 255, 255),
341                                    42,
342                                    1.0,
343                                    dcp::Time(0, 1, 2, 208, 250),
344                                    dcp::Time(0, 1, 4, 10, 250),
345                                    0,
346                                    dcp::HAlign::CENTER,
347                                    0.89,
348                                    dcp::VAlign::TOP,
349                                    0,
350                                    dcp::Direction::LTR,
351                                    "At home it depends how I feel.\"",
352                                    dcp::Effect::BORDER,
353                                    dcp::Colour(0, 0, 0),
354                                    dcp::Time(0, 0, 0, 0, 250),
355                                    dcp::Time(0, 0, 0, 0, 250),
356                                    0
357                                    ));
358         BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
359         BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
360                                    string ("theFont"),
361                                    true,
362                                    false,
363                                    false,
364                                    dcp::Colour(255, 255, 255),
365                                    42,
366                                    1.0,
367                                    dcp::Time(0, 1, 2, 208, 250),
368                                    dcp::Time(0, 1, 4, 10, 250),
369                                    0,
370                                    dcp::HAlign::CENTER,
371                                    0.95,
372                                    dcp::VAlign::TOP,
373                                    0,
374                                    dcp::Direction::LTR,
375                                    "I spent a long weekend in Brighton",
376                                    dcp::Effect::BORDER,
377                                    dcp::Colour(0, 0, 0),
378                                    dcp::Time(0, 0, 0, 0, 250),
379                                    dcp::Time(0, 0, 0, 0, 250),
380                                    0
381                                    ));
382
383         s = subs.subtitles_during (dcp::Time (0, 1, 15, 50, 250), dcp::Time (0, 1, 15, 51, 250), false);
384         BOOST_REQUIRE_EQUAL (s.size(), 2U);
385         BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
386         BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
387                                    string ("theFont"),
388                                    true,
389                                    false,
390                                    false,
391                                    dcp::Colour(255, 255, 255),
392                                    42,
393                                    1.0,
394                                    dcp::Time(0, 1, 15, 42, 250),
395                                    dcp::Time(0, 1, 16, 42, 250),
396                                    0,
397                                    dcp::HAlign::CENTER,
398                                    0.89,
399                                    dcp::VAlign::TOP,
400                                    0,
401                                    dcp::Direction::RTL,
402                                    "With the legendary Miss Enid Blyton",
403                                    dcp::Effect::BORDER,
404                                    dcp::Colour(0, 0, 0),
405                                    dcp::Time(0, 0, 0, 0, 250),
406                                    dcp::Time(0, 0, 0, 0, 250),
407                                    0
408                                    ));
409         BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
410         BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
411                                    string ("theFont"),
412                                    true,
413                                    false,
414                                    false,
415                                    dcp::Colour(255, 255, 255),
416                                    42,
417                                    1.0,
418                                    dcp::Time(0, 1, 15, 42, 250),
419                                    dcp::Time(0, 1, 16, 42, 250),
420                                    0,
421                                    dcp::HAlign::CENTER,
422                                    0.95,
423                                    dcp::VAlign::TOP,
424                                    0,
425                                    dcp::Direction::TTB,
426                                    "She said \"you be Noddy",
427                                    dcp::Effect::BORDER,
428                                    dcp::Colour(0, 0, 0),
429                                    dcp::Time(0, 0, 0, 0, 250),
430                                    dcp::Time(0, 0, 0, 0, 250),
431                                    0
432                                    ));
433
434         s = subs.subtitles_during (dcp::Time (0, 1, 27, 200, 250), dcp::Time (0, 1, 27, 201, 250), false);
435         BOOST_REQUIRE_EQUAL (s.size(), 2U);
436         BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
437         BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
438                                    string ("theFont"),
439                                    true,
440                                    false,
441                                    false,
442                                    dcp::Colour(255, 255, 255),
443                                    42,
444                                    1.0,
445                                    dcp::Time(0, 1, 27, 115, 250),
446                                    dcp::Time(0, 1, 28, 208, 250),
447                                    0,
448                                    dcp::HAlign::CENTER,
449                                    0.89,
450                                    dcp::VAlign::TOP,
451                                    0,
452                                    dcp::Direction::BTT,
453                                    "That curious creature the Sphinx",
454                                    dcp::Effect::BORDER,
455                                    dcp::Colour(0, 0, 0),
456                                    dcp::Time(0, 0, 0, 0, 250),
457                                    dcp::Time(0, 0, 0, 0, 250),
458                                    0
459                                    ));
460         BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
461         BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
462                                    string ("theFont"),
463                                    true,
464                                    false,
465                                    false,
466                                    dcp::Colour(255, 255, 255),
467                                    42,
468                                    1.0,
469                                    dcp::Time(0, 1, 27, 115, 250),
470                                    dcp::Time(0, 1, 28, 208, 250),
471                                    0,
472                                    dcp::HAlign::CENTER,
473                                    0.95,
474                                    dcp::VAlign::TOP,
475                                    0,
476                                    dcp::Direction::LTR,
477                                    "Is smarter than anyone thinks",
478                                    dcp::Effect::BORDER,
479                                    dcp::Colour(0, 0, 0),
480                                    dcp::Time(0, 0, 0, 0, 250),
481                                    dcp::Time(0, 0, 0, 0, 250),
482                                    0
483                                    ));
484
485         s = subs.subtitles_during (dcp::Time (0, 1, 42, 300, 250), dcp::Time (0, 1, 42, 301, 250), false);
486         BOOST_REQUIRE_EQUAL (s.size(), 2U);
487         BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
488         BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
489                                    string ("theFont"),
490                                    false,
491                                    false,
492                                    false,
493                                    dcp::Colour (255, 255, 255),
494                                    42,
495                                    1.0,
496                                    dcp::Time (0, 1, 42, 229, 250),
497                                    dcp::Time (0, 1, 45, 62, 250),
498                                    0,
499                                    dcp::HAlign::CENTER,
500                                    0.89,
501                                    dcp::VAlign::TOP,
502                                    0,
503                                    dcp::Direction::LTR,
504                                    "It sits there and smirks",
505                                    dcp::Effect::BORDER,
506                                    dcp::Colour(0, 0, 0),
507                                    dcp::Time(0, 0, 0, 0, 250),
508                                    dcp::Time(0, 0, 0, 0, 250),
509                                    0
510                                    ));
511         BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
512         BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
513                                    string ("theFont"),
514                                    false,
515                                    false,
516                                    false,
517                                    dcp::Colour (255, 255, 255),
518                                    42,
519                                    1.0,
520                                    dcp::Time (0, 1, 42, 229, 250),
521                                    dcp::Time (0, 1, 45, 62, 250),
522                                    0,
523                                    dcp::HAlign::CENTER,
524                                    0.95,
525                                    dcp::VAlign::TOP,
526                                    0,
527                                    dcp::Direction::LTR,
528                                    "And you don't think it works",
529                                    dcp::Effect::BORDER,
530                                    dcp::Colour(0, 0, 0),
531                                    dcp::Time(0, 0, 0, 0, 250),
532                                    dcp::Time(0, 0, 0, 0, 250),
533                                    0
534                                    ));
535
536         s = subs.subtitles_during (dcp::Time (0, 1, 45, 200, 250), dcp::Time (0, 1, 45, 201, 250), false);
537         BOOST_REQUIRE_EQUAL (s.size(), 2U);
538         BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
539         BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
540                                    string("theFont"),
541                                    false,
542                                    false,
543                                    false,
544                                    dcp::Colour(255, 255, 255),
545                                    42,
546                                    1.0,
547                                    dcp::Time(0, 1, 45, 146, 250),
548                                    dcp::Time(0, 1, 47, 94, 250),
549                                    0,
550                                    dcp::HAlign::CENTER,
551                                    0.89,
552                                    dcp::VAlign::TOP,
553                                    0,
554                                    dcp::Direction::LTR,
555                                    "Then when you're not looking, it winks.",
556                                    dcp::Effect::BORDER,
557                                    dcp::Colour(0, 0, 0),
558                                    dcp::Time(0, 0, 0, 0, 250),
559                                    dcp::Time(0, 0, 0, 0, 250),
560                                    0
561                                    ));
562         BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
563         BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
564                                    string ("theFont"),
565                                    false,
566                                    false,
567                                    false,
568                                    dcp::Colour (255, 255, 255),
569                                    42,
570                                    1.0,
571                                    dcp::Time (0, 1, 45, 146, 250),
572                                    dcp::Time (0, 1, 47, 94, 250),
573                                    0,
574                                    dcp::HAlign::CENTER,
575                                    0.95,
576                                    dcp::VAlign::TOP,
577                                    0,
578                                    dcp::Direction::LTR,
579                                    "When it snows you will find Sister Sledge",
580                                    dcp::Effect::BORDER,
581                                    dcp::Colour(0, 0, 0),
582                                    dcp::Time(0, 0, 0, 0, 250),
583                                    dcp::Time(0, 0, 0, 0, 250),
584                                    0
585                                    ));
586
587         s = subs.subtitles_during (dcp::Time (0, 1, 47, 249, 250), dcp::Time (0, 1, 47, 250, 250), false);
588         BOOST_REQUIRE_EQUAL (s.size(), 2U);
589         BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
590         BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
591                                    string ("theFont"),
592                                    false,
593                                    false,
594                                    false,
595                                    dcp::Colour(255, 255, 255),
596                                    42,
597                                    1.0,
598                                    dcp::Time(0, 1, 47, 146, 250),
599                                    dcp::Time(0, 1, 48, 167, 250),
600                                    0,
601                                    dcp::HAlign::CENTER,
602                                    0.89,
603                                    dcp::VAlign::TOP,
604                                    0,
605                                    dcp::Direction::LTR,
606                                    "Out mooning, at night, on the ledge",
607                                    dcp::Effect::BORDER,
608                                    dcp::Colour(0, 0, 0),
609                                    dcp::Time(0, 0, 0, 0, 250),
610                                    dcp::Time(0, 0, 0, 0, 250),
611                                    0
612                                    ));
613         BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
614         BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
615                                    string ("theFont"),
616                                    false,
617                                    false,
618                                    false,
619                                    dcp::Colour(255, 255, 255),
620                                    42,
621                                    1.0,
622                                    dcp::Time(0, 1, 47, 146, 250),
623                                    dcp::Time(0, 1, 48, 167, 250),
624                                    0,
625                                    dcp::HAlign::CENTER,
626                                    0.95,
627                                    dcp::VAlign::TOP,
628                                    0,
629                                    dcp::Direction::LTR,
630                                    "One storey down",
631                                    dcp::Effect::BORDER,
632                                    dcp::Colour(0, 0, 0),
633                                    dcp::Time(0, 0, 0, 0, 250),
634                                    dcp::Time(0, 0, 0, 0, 250),
635                                    0
636                                    ));
637
638         s = subs.subtitles_during (dcp::Time (0, 2, 6, 210, 250), dcp::Time (0, 2, 6, 211, 250), false);
639         BOOST_REQUIRE_EQUAL (s.size(), 2U);
640         BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.front()));
641         BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.front()), dcp::SubtitleString (
642                                    string ("theFont"),
643                                    true,
644                                    false,
645                                    false,
646                                    dcp::Colour (255, 255, 255),
647                                    42,
648                                    1.0,
649                                    dcp::Time (0, 2, 5, 208, 250),
650                                    dcp::Time (0, 2, 7, 31, 250),
651                                    0,
652                                    dcp::HAlign::CENTER,
653                                    0.89,
654                                    dcp::VAlign::TOP,
655                                    0,
656                                    dcp::Direction::LTR,
657                                    "HELLO",
658                                    dcp::Effect::BORDER,
659                                    dcp::Colour(0, 0, 0),
660                                    dcp::Time(0, 0, 0, 0, 250),
661                                    dcp::Time(0, 0, 0, 0, 250),
662                                    0
663                                    ));
664         BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
665         BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
666                                    string ("theFont"),
667                                    true,
668                                    false,
669                                    false,
670                                    dcp::Colour(255, 255, 255),
671                                    42,
672                                    1.0,
673                                    dcp::Time(0, 2, 5, 208, 250),
674                                    dcp::Time(0, 2, 7, 31, 250),
675                                    0,
676                                    dcp::HAlign::CENTER,
677                                    0.95,
678                                    dcp::VAlign::TOP,
679                                    0,
680                                    dcp::Direction::LTR,
681                                    "WORLD",
682                                    dcp::Effect::BORDER,
683                                    dcp::Colour(0, 0, 0),
684                                    dcp::Time(0, 0, 0, 0, 250),
685                                    dcp::Time(0, 0, 0, 0, 250),
686                                    0
687                                    ));
688 }
689
690 /** And one with bitmap subtitles */
691 BOOST_AUTO_TEST_CASE (read_interop_subtitle_test3)
692 {
693         dcp::InteropSubtitleAsset subs ("test/data/subs3.xml");
694
695         BOOST_REQUIRE_EQUAL (subs.subtitles().size(), 1U);
696         auto si = dynamic_pointer_cast<const dcp::SubtitleImage>(subs.subtitles().front());
697         BOOST_REQUIRE (si);
698         BOOST_CHECK (si->png_image() == dcp::ArrayData("test/data/sub.png"));
699 }
700
701
702 /** Write some subtitle content as Interop XML and check that it is right */
703 BOOST_AUTO_TEST_CASE (write_interop_subtitle_test)
704 {
705         dcp::InteropSubtitleAsset c;
706         c.set_reel_number ("1");
707         c.set_language ("EN");
708         c.set_movie_title ("Test");
709
710         c.add (
711                 std::make_shared<dcp::SubtitleString>(
712                         string ("Frutiger"),
713                         false,
714                         false,
715                         false,
716                         dcp::Colour (255, 255, 255),
717                         48,
718                         1.0,
719                         dcp::Time (0, 4,  9, 22, 24),
720                         dcp::Time (0, 4, 11, 22, 24),
721                         0,
722                         dcp::HAlign::CENTER,
723                         0.8,
724                         dcp::VAlign::TOP,
725                         0,
726                         dcp::Direction::LTR,
727                         "Hello world",
728                         dcp::Effect::NONE,
729                         dcp::Colour (0, 0, 0),
730                         dcp::Time (0, 0, 0, 0, 24),
731                         dcp::Time (0, 0, 0, 0, 24),
732                         0
733                         )
734                 );
735
736         c.add (
737                 std::make_shared<dcp::SubtitleString>(
738                         boost::optional<string> (),
739                         true,
740                         true,
741                         true,
742                         dcp::Colour (128, 0, 64),
743                         91,
744                         1.0,
745                         dcp::Time (5, 41,  0, 21, 24),
746                         dcp::Time (6, 12, 15, 21, 24),
747                         0,
748                         dcp::HAlign::CENTER,
749                         0.4,
750                         dcp::VAlign::BOTTOM,
751                         0,
752                         dcp::Direction::LTR,
753                         "What's going ",
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                         0
759                         )
760                 );
761
762         c.add (
763                 std::make_shared<dcp::SubtitleString>(
764                         boost::optional<string> (),
765                         true,
766                         true,
767                         true,
768                         dcp::Colour (128, 0, 64),
769                         91,
770                         1.0,
771                         dcp::Time (5, 41,  0, 21, 24),
772                         dcp::Time (6, 12, 15, 21, 24),
773                         0,
774                         dcp::HAlign::CENTER,
775                         0.4,
776                         dcp::VAlign::BOTTOM,
777                         0,
778                         dcp::Direction::LTR,
779                         "on",
780                         dcp::Effect::BORDER,
781                         dcp::Colour (1, 2, 3),
782                         dcp::Time (1, 2, 3, 4, 24),
783                         dcp::Time (5, 6, 7, 8, 24),
784                         9
785                         )
786                 );
787
788         c._id = "a6c58cff-3e1e-4b38-acec-a42224475ef6";
789
790         check_xml (
791                 "<DCSubtitle Version=\"1.0\">\n"
792                 "  <SubtitleID>a6c58cff-3e1e-4b38-acec-a42224475ef6</SubtitleID>\n"
793                 "  <MovieTitle>Test</MovieTitle>\n"
794                 "  <ReelNumber>1</ReelNumber>\n"
795                 "  <Language>EN</Language>\n"
796                 "  <Font AspectAdjust=\"1.0\" Color=\"FFFFFFFF\" Effect=\"none\" EffectColor=\"FF000000\" Id=\"Frutiger\" Italic=\"no\" Script=\"normal\" Size=\"48\" Underlined=\"no\" Weight=\"normal\">\n"
797                 "    <Subtitle SpotNumber=\"1\" TimeIn=\"00:04:09:229\" TimeOut=\"00:04:11:229\" FadeUpTime=\"0\" FadeDownTime=\"0\">\n"
798                 "      <Text VAlign=\"top\" VPosition=\"80\">Hello world</Text>\n"
799                 "    </Subtitle>\n"
800                 "  </Font>\n"
801                 "  <Font AspectAdjust=\"1.0\" Color=\"FF800040\" Effect=\"border\" EffectColor=\"FF010203\" Italic=\"yes\" Script=\"normal\" Size=\"91\" Underlined=\"yes\" Weight=\"bold\">\n"
802                 "    <Subtitle SpotNumber=\"2\" TimeIn=\"05:41:00:219\" TimeOut=\"06:12:15:219\" FadeUpTime=\"930792\" FadeDownTime=\"4591834\">\n"
803                 "      <Text VAlign=\"bottom\" VPosition=\"40\">What's going <Space Size=\"9em\"/>on</Text>\n"
804                 "    </Subtitle>\n"
805                 "  </Font>\n"
806                 "</DCSubtitle>",
807                 c.xml_as_string (),
808                 vector<string>()
809                 );
810 }
811
812 /** Write some subtitle content as Interop XML and check that it is right.
813  *  This test includes some horizontal alignment.
814  */
815 BOOST_AUTO_TEST_CASE (write_interop_subtitle_test2)
816 {
817         dcp::InteropSubtitleAsset c;
818         c.set_reel_number ("1");
819         c.set_language ("EN");
820         c.set_movie_title ("Test");
821
822         c.add (
823                 std::make_shared<dcp::SubtitleString>(
824                         string ("Frutiger"),
825                         false,
826                         false,
827                         false,
828                         dcp::Colour (255, 255, 255),
829                         48,
830                         1.0,
831                         dcp::Time (0, 4,  9, 22, 24),
832                         dcp::Time (0, 4, 11, 22, 24),
833                         -0.2,
834                         dcp::HAlign::CENTER,
835                         0.8,
836                         dcp::VAlign::TOP,
837                         0,
838                         dcp::Direction::LTR,
839                         "Hello world",
840                         dcp::Effect::NONE,
841                         dcp::Colour (0, 0, 0),
842                         dcp::Time (0, 0, 0, 0, 24),
843                         dcp::Time (0, 0, 0, 0, 24),
844                         0
845                         )
846                 );
847
848         c.add (
849                 std::make_shared<dcp::SubtitleString>(
850                         boost::optional<string>(),
851                         true,
852                         true,
853                         true,
854                         dcp::Colour (128, 0, 64),
855                         91,
856                         1.0,
857                         dcp::Time (5, 41,  0, 21, 24),
858                         dcp::Time (6, 12, 15, 21, 24),
859                         -0.2,
860                         dcp::HAlign::CENTER,
861                         0.4,
862                         dcp::VAlign::BOTTOM,
863                         0,
864                         dcp::Direction::LTR,
865                         "What's going on",
866                         dcp::Effect::BORDER,
867                         dcp::Colour (1, 2, 3),
868                         dcp::Time (1, 2, 3, 4, 24),
869                         dcp::Time (5, 6, 7, 8, 24),
870                         0
871                         )
872                 );
873
874         c._id = "a6c58cff-3e1e-4b38-acec-a42224475ef6";
875
876         check_xml (
877                 "<DCSubtitle Version=\"1.0\">\n"
878                 "  <SubtitleID>a6c58cff-3e1e-4b38-acec-a42224475ef6</SubtitleID>\n"
879                 "  <MovieTitle>Test</MovieTitle>\n"
880                 "  <ReelNumber>1</ReelNumber>\n"
881                 "  <Language>EN</Language>\n"
882                 "  <Font AspectAdjust=\"1.0\" Color=\"FFFFFFFF\" Effect=\"none\" EffectColor=\"FF000000\" Id=\"Frutiger\" Italic=\"no\" Script=\"normal\" Size=\"48\" Underlined=\"no\" Weight=\"normal\">\n"
883                 "    <Subtitle SpotNumber=\"1\" TimeIn=\"00:04:09:229\" TimeOut=\"00:04:11:229\" FadeUpTime=\"0\" FadeDownTime=\"0\">\n"
884                 "      <Text HPosition=\"-20\" VAlign=\"top\" VPosition=\"80\">Hello world</Text>\n"
885                 "    </Subtitle>\n"
886                 "  </Font>\n"
887                 "  <Font AspectAdjust=\"1.0\" Color=\"FF800040\" Effect=\"border\" EffectColor=\"FF010203\" Italic=\"yes\" Script=\"normal\" Size=\"91\" Underlined=\"yes\" Weight=\"bold\">\n"
888                 "    <Subtitle SpotNumber=\"2\" TimeIn=\"05:41:00:219\" TimeOut=\"06:12:15:219\" FadeUpTime=\"930792\" FadeDownTime=\"4591834\">\n"
889                 "      <Text HPosition=\"-20\" VAlign=\"bottom\" VPosition=\"40\">What's going on</Text>\n"
890                 "    </Subtitle>\n"
891                 "  </Font>\n"
892                 "</DCSubtitle>",
893                 c.xml_as_string (),
894                 vector<string>()
895                 );
896 }
897
898 /* Write some subtitle content as Interop XML using bitmaps and check that it is right */
899 BOOST_AUTO_TEST_CASE (write_interop_subtitle_test3)
900 {
901         RNGFixer fix;
902
903         auto c = std::make_shared<dcp::InteropSubtitleAsset>();
904         c->set_reel_number ("1");
905         c->set_language ("EN");
906         c->set_movie_title ("Test");
907
908         c->add (
909                 std::make_shared<dcp::SubtitleImage>(
910                         dcp::ArrayData ("test/data/sub.png"),
911                         dcp::Time (0, 4,  9, 22, 24),
912                         dcp::Time (0, 4, 11, 22, 24),
913                         0,
914                         dcp::HAlign::CENTER,
915                         0.8,
916                         dcp::VAlign::TOP,
917                         0,
918                         dcp::Time (0, 0, 0, 0, 24),
919                         dcp::Time (0, 0, 0, 0, 24)
920                         )
921                 );
922
923         c->_id = "a6c58cff-3e1e-4b38-acec-a42224475ef6";
924         boost::filesystem::remove_all ("build/test/write_interop_subtitle_test3");
925         boost::filesystem::create_directories ("build/test/write_interop_subtitle_test3");
926         c->write ("build/test/write_interop_subtitle_test3/subs.xml");
927
928         auto reel = std::make_shared<dcp::Reel>();
929         reel->add(std::make_shared<dcp::ReelInteropSubtitleAsset>(c, dcp::Fraction(24, 1), 6046, 0));
930
931         string const issue_date = "2018-09-02T04:45:18+00:00";
932         string const issuer = "libdcp";
933         string const creator = "libdcp";
934         string const annotation_text = "Created by libdcp";
935
936         auto cpl = std::make_shared<dcp::CPL>("My film", dcp::ContentKind::FEATURE, dcp::Standard::INTEROP);
937         cpl->add (reel);
938         cpl->set_issuer (issuer);
939         cpl->set_creator (creator);
940         cpl->set_issue_date (issue_date);
941         cpl->set_annotation_text (annotation_text);
942         auto cv = cpl->content_version();
943         BOOST_REQUIRE (cv);
944         cv->label_text = "foo";
945         cpl->set_content_version (*cv);
946
947         dcp::DCP dcp ("build/test/write_interop_subtitle_test3");
948         dcp.add (cpl);
949         dcp.set_issuer(issuer);
950         dcp.set_creator(creator);
951         dcp.set_issue_date(issue_date);
952         dcp.set_annotation_text(annotation_text);
953         dcp.write_xml();
954
955         check_xml (
956                 dcp::file_to_string("test/ref/write_interop_subtitle_test3/subs.xml"),
957                 dcp::file_to_string("build/test/write_interop_subtitle_test3/subs.xml"),
958                 vector<string>()
959                 );
960         check_file(find_file("build/test/write_interop_subtitle_test3", ".png"), "test/data/sub.png");
961
962         check_xml (
963                 dcp::file_to_string("test/ref/write_interop_subtitle_test3/ASSETMAP"),
964                 dcp::file_to_string("build/test/write_interop_subtitle_test3/ASSETMAP"),
965                 vector<string>()
966                 );
967
968         check_xml (
969                 dcp::file_to_string(find_file("test/ref/write_interop_subtitle_test3", "pkl")),
970                 dcp::file_to_string(find_file("build/test/write_interop_subtitle_test3", "pkl")),
971                 vector<string>()
972                 );
973 }
974