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