Add a couple of Z position tests.
[libdcp.git] / test / smpte_subtitle_test.cc
1 /*
2     Copyright (C) 2018-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 "smpte_load_font_node.h"
36 #include "smpte_subtitle_asset.h"
37 #include "stream_operators.h"
38 #include "subtitle_image.h"
39 #include "test.h"
40 #include "types.h"
41 #include <boost/optional/optional_io.hpp>
42 #include <boost/test/unit_test.hpp>
43
44
45 using std::make_shared;
46 using std::string;
47 using std::shared_ptr;
48 using std::dynamic_pointer_cast;
49 using std::vector;
50 using boost::optional;
51
52
53 BOOST_AUTO_TEST_CASE (smpte_subtitle_id_test)
54 {
55         dcp::SMPTESubtitleAsset subs;
56         subs.add(
57                 make_shared<dcp::SubtitleString>(
58                         optional<string>(),
59                         false, false, false,
60                         dcp::Colour(),
61                         64,
62                         1,
63                         dcp::Time(0, 1, 2, 3, 24),
64                         dcp::Time(0, 2, 2, 3, 24),
65                         0.5,
66                         dcp::HAlign::CENTER,
67                         0.5,
68                         dcp::VAlign::CENTER,
69                         0,
70                         dcp::Direction::LTR,
71                         "Hello",
72                         dcp::Effect::NONE,
73                         dcp::Colour(),
74                         dcp::Time(0, 0, 0, 0, 24),
75                         dcp::Time(0, 0, 0, 0, 24),
76                         0
77                         )
78                 );
79         subs.write("build/test/smpte_subtitle_id_test.mxf");
80
81         dcp::SMPTESubtitleAsset check("build/test/smpte_subtitle_id_test.mxf");
82         BOOST_CHECK(check.id() != check.xml_id());
83 }
84
85
86 /** Check reading of a SMPTE subtitle file */
87 BOOST_AUTO_TEST_CASE (read_smpte_subtitle_test)
88 {
89         dcp::SMPTESubtitleAsset sc (
90                 private_test /
91                 "data" /
92                 "JourneyToJah_TLR-1_F_EN-DE-FR_CH_51_2K_LOK_20140225_DGL_SMPTE_OV" /
93                 "8b48f6ae-c74b-4b80-b994-a8236bbbad74_sub.mxf"
94                 );
95
96         BOOST_CHECK_EQUAL (sc.id(), "8b48f6ae-c74b-4b80-b994-a8236bbbad74");
97         BOOST_CHECK_EQUAL (sc.content_title_text(), "Journey to Jah");
98         BOOST_REQUIRE (sc.annotation_text());
99         BOOST_CHECK_EQUAL (sc.annotation_text().get(), "Journey to Jah");
100         BOOST_CHECK_EQUAL (sc.issue_date(), dcp::LocalTime ("2014-02-25T11:22:48.000-00:00"));
101         BOOST_REQUIRE (sc.reel_number());
102         BOOST_CHECK_EQUAL (sc.reel_number().get(), 1);
103         BOOST_REQUIRE (sc.language ());
104         BOOST_CHECK_EQUAL (sc.language().get (), "de");
105         BOOST_CHECK_EQUAL (sc.edit_rate(), dcp::Fraction (25, 1));
106         BOOST_CHECK_EQUAL (sc.time_code_rate(), 25);
107         BOOST_CHECK_EQUAL (sc.start_time(), dcp::Time (0, 0, 0, 0, 25));
108         auto lfn = sc.load_font_nodes ();
109         BOOST_REQUIRE_EQUAL (lfn.size(), 1U);
110         shared_ptr<dcp::SMPTELoadFontNode> smpte_lfn = dynamic_pointer_cast<dcp::SMPTELoadFontNode> (lfn.front ());
111         BOOST_REQUIRE (smpte_lfn);
112         BOOST_CHECK_EQUAL (smpte_lfn->id, "theFontId");
113         BOOST_CHECK_EQUAL (smpte_lfn->urn, "9118bbce-4105-4a05-b37c-a5a6f75e1fea");
114         BOOST_REQUIRE_EQUAL (sc.subtitles().size(), 63U);
115         BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(sc.subtitles().front()));
116         BOOST_CHECK_EQUAL (dynamic_pointer_cast<const dcp::SubtitleString>(sc.subtitles().front())->text(), "Noch mal.");
117         BOOST_CHECK_EQUAL (dynamic_pointer_cast<const dcp::SubtitleString>(sc.subtitles().front())->space_before(), 0.0f);
118         BOOST_CHECK_EQUAL (sc.subtitles().front()->in(), dcp::Time (0, 0, 25, 12, 25));
119         BOOST_CHECK_EQUAL (sc.subtitles().front()->out(), dcp::Time (0, 0, 26, 4, 25));
120         BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(sc.subtitles().back()));
121         BOOST_CHECK_EQUAL (dynamic_pointer_cast<const dcp::SubtitleString>(sc.subtitles().back())->text(), "Prochainement");
122         BOOST_CHECK_EQUAL (dynamic_pointer_cast<const dcp::SubtitleString>(sc.subtitles().back())->space_before(), 0.0f);
123         BOOST_CHECK_EQUAL (sc.subtitles().back()->in(), dcp::Time (0, 1, 57, 17, 25));
124         BOOST_CHECK_EQUAL (sc.subtitles().back()->out(), dcp::Time (0, 1, 58, 12, 25));
125 }
126
127
128 /** And another one featuring <Font> within <Text> and some <Space> */
129 BOOST_AUTO_TEST_CASE (read_smpte_subtitle_test2)
130 {
131         dcp::SMPTESubtitleAsset sc (private_test / "olsson.xml");
132
133         auto subs = sc.subtitles();
134         BOOST_REQUIRE_EQUAL (subs.size(), 6U);
135         auto i = 0;
136         auto is = dynamic_pointer_cast<const dcp::SubtitleString>(subs[i]);
137         BOOST_REQUIRE (is);
138         BOOST_CHECK_EQUAL (is->text(), "Testing is ");
139         BOOST_CHECK (!is->italic());
140         BOOST_CHECK_CLOSE (is->space_before(), 0, 0.1);
141         ++i;
142         is = dynamic_pointer_cast<const dcp::SubtitleString>(subs[i]);
143         BOOST_REQUIRE (is);
144         BOOST_CHECK_EQUAL (is->text(), "really");
145         BOOST_CHECK (is->italic());
146         BOOST_CHECK_CLOSE (is->space_before(), 0, 0.1);
147         ++i;
148         is = dynamic_pointer_cast<const dcp::SubtitleString>(subs[i]);
149         BOOST_REQUIRE (is);
150         BOOST_CHECK_EQUAL (is->text(), " fun!");
151         BOOST_CHECK (!is->italic());
152         BOOST_CHECK_CLOSE (is->space_before(), 5, 0.1);
153         ++i;
154         is = dynamic_pointer_cast<const dcp::SubtitleString>(subs[i]);
155         BOOST_REQUIRE (is);
156         BOOST_CHECK_EQUAL (is->text(), "This is the ");
157         BOOST_CHECK (!is->italic());
158         BOOST_CHECK_CLOSE (is->space_before(), 0, 0.1);
159         ++i;
160         is = dynamic_pointer_cast<const dcp::SubtitleString>(subs[i]);
161         BOOST_REQUIRE (is);
162         BOOST_CHECK_EQUAL (is->text(), "second");
163         BOOST_CHECK (is->italic());
164         BOOST_CHECK_CLOSE (is->space_before(), 0, 0.1);
165         ++i;
166         is = dynamic_pointer_cast<const dcp::SubtitleString>(subs[i]);
167         BOOST_REQUIRE (is);
168         BOOST_CHECK_EQUAL (is->text(), " line!");
169         BOOST_CHECK (!is->italic());
170         BOOST_CHECK_CLOSE (is->space_before(), 0, 0.1);
171 }
172
173
174 /* Write some subtitle content as SMPTE XML and check that it is right */
175 BOOST_AUTO_TEST_CASE (write_smpte_subtitle_test)
176 {
177         dcp::SMPTESubtitleAsset c;
178         c.set_reel_number (1);
179         c.set_language (dcp::LanguageTag("en"));
180         c.set_content_title_text ("Test");
181         c.set_issue_date (dcp::LocalTime ("2016-04-01T03:52:00+00:00"));
182
183         c.add (
184                 make_shared<dcp::SubtitleString> (
185                         string ("Frutiger"),
186                         false,
187                         false,
188                         false,
189                         dcp::Colour (255, 255, 255),
190                         48,
191                         1.0,
192                         dcp::Time (0, 4,  9, 22, 24),
193                         dcp::Time (0, 4, 11, 22, 24),
194                         0,
195                         dcp::HAlign::CENTER,
196                         0.8,
197                         dcp::VAlign::TOP,
198                         0.3,
199                         dcp::Direction::LTR,
200                         "Hello world",
201                         dcp::Effect::NONE,
202                         dcp::Colour (0, 0, 0),
203                         dcp::Time (0, 0, 0, 0, 24),
204                         dcp::Time (0, 0, 0, 0, 24),
205                         0
206                         )
207                 );
208
209         c.add (
210                 make_shared<dcp::SubtitleString>(
211                         boost::optional<string> (),
212                         true,
213                         true,
214                         true,
215                         dcp::Colour (128, 0, 64),
216                         91,
217                         1.0,
218                         dcp::Time (5, 41,  0, 21, 24),
219                         dcp::Time (6, 12, 15, 21, 24),
220                         0,
221                         dcp::HAlign::CENTER,
222                         0.4,
223                         dcp::VAlign::BOTTOM,
224                         0,
225                         dcp::Direction::RTL,
226                         "What's going ",
227                         dcp::Effect::BORDER,
228                         dcp::Colour (1, 2, 3),
229                         dcp::Time (1, 2, 3, 4, 24),
230                         dcp::Time (5, 6, 7, 8, 24),
231                         0
232                         )
233                 );
234
235         c.add (
236                 make_shared<dcp::SubtitleString>(
237                         boost::optional<string> (),
238                         true,
239                         true,
240                         true,
241                         dcp::Colour (128, 0, 64),
242                         91,
243                         1.0,
244                         dcp::Time (5, 41,  0, 21, 24),
245                         dcp::Time (6, 12, 15, 21, 24),
246                         0,
247                         dcp::HAlign::CENTER,
248                         0.4,
249                         dcp::VAlign::BOTTOM,
250                         0,
251                         dcp::Direction::RTL,
252                         "on",
253                         dcp::Effect::BORDER,
254                         dcp::Colour (1, 2, 3),
255                         dcp::Time (1, 2, 3, 4, 24),
256                         dcp::Time (5, 6, 7, 8, 24),
257                         4.2
258                         )
259                 );
260
261         c._xml_id = "a6c58cff-3e1e-4b38-acec-a42224475ef6";
262
263         check_xml (
264                 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
265                 "<SubtitleReel xmlns=\"http://www.smpte-ra.org/schemas/428-7/2010/DCST\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n"
266                 "  <Id>urn:uuid:a6c58cff-3e1e-4b38-acec-a42224475ef6</Id>\n"
267                 "  <ContentTitleText>Test</ContentTitleText>\n"
268                 "  <IssueDate>2016-04-01T03:52:00.000+00:00</IssueDate>\n"
269                 "  <ReelNumber>1</ReelNumber>\n"
270                 "  <Language>en</Language>\n"
271                 "  <EditRate>24 1</EditRate>\n"
272                 "  <TimeCodeRate>24</TimeCodeRate>\n"
273                 "  <SubtitleList>\n"
274                 "    <Font AspectAdjust=\"1.0\" Color=\"FFFFFFFF\" Effect=\"none\" EffectColor=\"FF000000\" ID=\"Frutiger\" Italic=\"no\" Script=\"normal\" Size=\"48\" Underline=\"no\" Weight=\"normal\">\n"
275                 "      <Subtitle SpotNumber=\"1\" TimeIn=\"00:04:09:22\" TimeOut=\"00:04:11:22\" FadeUpTime=\"00:00:00:00\" FadeDownTime=\"00:00:00:00\">\n"
276                 "        <Text Valign=\"top\" Vposition=\"80\" Zposition=\"30\">Hello world</Text>\n"
277                 "      </Subtitle>\n"
278                 "    </Font>\n"
279                 "    <Font AspectAdjust=\"1.0\" Color=\"FF800040\" Effect=\"border\" EffectColor=\"FF010203\" Italic=\"yes\" Script=\"normal\" Size=\"91\" Underline=\"yes\" Weight=\"bold\">\n"
280                 "      <Subtitle SpotNumber=\"2\" TimeIn=\"05:41:00:21\" TimeOut=\"06:12:15:21\" FadeUpTime=\"01:02:03:04\" FadeDownTime=\"05:06:07:08\">\n"
281                 "        <Text Valign=\"bottom\" Vposition=\"40\" Direction=\"rtl\">What's going <Space Size=\"4.2\"/>on</Text>\n"
282                 "      </Subtitle>\n"
283                 "    </Font>\n"
284                 "  </SubtitleList>\n"
285                 "</SubtitleReel>",
286                 c.xml_as_string (),
287                 vector<string>()
288                 );
289 }
290
291 /* Write some subtitle content as SMPTE XML and check that it is right.
292    This includes in-line font changes.
293 */
294 BOOST_AUTO_TEST_CASE (write_smpte_subtitle_test2)
295 {
296         dcp::SMPTESubtitleAsset c;
297         c.set_reel_number (1);
298         c.set_language (dcp::LanguageTag("en"));
299         c.set_content_title_text ("Test");
300         c.set_issue_date (dcp::LocalTime ("2016-04-01T03:52:00+00:00"));
301
302         c.add (
303                 make_shared<dcp::SubtitleString>(
304                         string ("Arial"),
305                         false,
306                         false,
307                         false,
308                         dcp::Colour (255, 255, 255),
309                         48,
310                         1.0,
311                         dcp::Time (0, 0, 1, 0, 24),
312                         dcp::Time (0, 0, 9, 0, 24),
313                         0,
314                         dcp::HAlign::CENTER,
315                         0.8,
316                         dcp::VAlign::TOP,
317                         0,
318                         dcp::Direction::LTR,
319                         "Testing is ",
320                         dcp::Effect::NONE,
321                         dcp::Colour (0, 0, 0),
322                         dcp::Time (0, 0, 0, 0, 24),
323                         dcp::Time (0, 0, 0, 0, 24),
324                         0
325                         )
326                 );
327
328         c.add (
329                 make_shared<dcp::SubtitleString>(
330                         string ("Arial"),
331                         true,
332                         false,
333                         false,
334                         dcp::Colour (255, 255, 255),
335                         48,
336                         1.0,
337                         dcp::Time (0, 0, 1, 0, 24),
338                         dcp::Time (0, 0, 9, 0, 24),
339                         0,
340                         dcp::HAlign::CENTER,
341                         0.8,
342                         dcp::VAlign::TOP,
343                         0,
344                         dcp::Direction::LTR,
345                         "really",
346                         dcp::Effect::NONE,
347                         dcp::Colour (0, 0, 0),
348                         dcp::Time (0, 0, 0, 0, 24),
349                         dcp::Time (0, 0, 0, 0, 24),
350                         0
351                         )
352                 );
353
354         c.add (
355                 make_shared<dcp::SubtitleString>(
356                         string ("Arial"),
357                         false,
358                         false,
359                         false,
360                         dcp::Colour (255, 255, 255),
361                         48,
362                         1.0,
363                         dcp::Time (0, 0, 1, 0, 24),
364                         dcp::Time (0, 0, 9, 0, 24),
365                         0,
366                         dcp::HAlign::CENTER,
367                         0.8,
368                         dcp::VAlign::TOP,
369                         0,
370                         dcp::Direction::LTR,
371                         " fun",
372                         dcp::Effect::NONE,
373                         dcp::Colour (0, 0, 0),
374                         dcp::Time (0, 0, 0, 0, 24),
375                         dcp::Time (0, 0, 0, 0, 24),
376                         0
377                         )
378                 );
379
380         c.add (
381                 make_shared<dcp::SubtitleString>(
382                         string ("Arial"),
383                         false,
384                         false,
385                         false,
386                         dcp::Colour (255, 255, 255),
387                         48,
388                         1.0,
389                         dcp::Time (0, 0, 1, 0, 24),
390                         dcp::Time (0, 0, 9, 0, 24),
391                         0,
392                         dcp::HAlign::CENTER,
393                         0.9,
394                         dcp::VAlign::TOP,
395                         0,
396                         dcp::Direction::LTR,
397                         "This is the ",
398                         dcp::Effect::NONE,
399                         dcp::Colour (0, 0, 0),
400                         dcp::Time (0, 0, 0, 0, 24),
401                         dcp::Time (0, 0, 0, 0, 24),
402                         0
403                         )
404                 );
405
406         c.add (
407                 make_shared<dcp::SubtitleString>(
408                         string ("Arial"),
409                         true,
410                         false,
411                         false,
412                         dcp::Colour (255, 255, 255),
413                         48,
414                         1.0,
415                         dcp::Time (0, 0, 1, 0, 24),
416                         dcp::Time (0, 0, 9, 0, 24),
417                         0,
418                         dcp::HAlign::CENTER,
419                         0.9,
420                         dcp::VAlign::TOP,
421                         0,
422                         dcp::Direction::LTR,
423                         "second",
424                         dcp::Effect::NONE,
425                         dcp::Colour (0, 0, 0),
426                         dcp::Time (0, 0, 0, 0, 24),
427                         dcp::Time (0, 0, 0, 0, 24),
428                         0
429                         )
430                 );
431
432         c.add (
433                 make_shared<dcp::SubtitleString>(
434                         string ("Arial"),
435                         false,
436                         false,
437                         false,
438                         dcp::Colour (255, 255, 255),
439                         48,
440                         1.0,
441                         dcp::Time (0, 0, 1, 0, 24),
442                         dcp::Time (0, 0, 9, 0, 24),
443                         0,
444                         dcp::HAlign::CENTER,
445                         0.9,
446                         dcp::VAlign::TOP,
447                         0,
448                         dcp::Direction::LTR,
449                         " line",
450                         dcp::Effect::NONE,
451                         dcp::Colour (0, 0, 0),
452                         dcp::Time (0, 0, 0, 0, 24),
453                         dcp::Time (0, 0, 0, 0, 24),
454                         0
455                         )
456                 );
457
458         c._xml_id = "a6c58cff-3e1e-4b38-acec-a42224475ef6";
459
460         check_xml (
461                 c.xml_as_string(),
462                 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
463                 "<SubtitleReel xmlns=\"http://www.smpte-ra.org/schemas/428-7/2010/DCST\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n"
464                 "  <Id>urn:uuid:a6c58cff-3e1e-4b38-acec-a42224475ef6</Id>\n"
465                 "  <ContentTitleText>Test</ContentTitleText>\n"
466                 "  <IssueDate>2016-04-01T03:52:00.000+00:00</IssueDate>\n"
467                 "  <ReelNumber>1</ReelNumber>\n"
468                 "  <Language>en</Language>\n"
469                 "  <EditRate>24 1</EditRate>\n"
470                 "  <TimeCodeRate>24</TimeCodeRate>\n"
471                 "  <SubtitleList>\n"
472                 "    <Font AspectAdjust=\"1.0\" Color=\"FFFFFFFF\" Effect=\"none\" EffectColor=\"FF000000\" ID=\"Arial\" Script=\"normal\" Size=\"48\" Underline=\"no\" Weight=\"normal\">\n"
473                 "      <Subtitle SpotNumber=\"1\" TimeIn=\"00:00:01:00\" TimeOut=\"00:00:09:00\" FadeUpTime=\"00:00:00:00\" FadeDownTime=\"00:00:00:00\">\n"
474                 "        <Text Valign=\"top\" Vposition=\"80\"><Font Italic=\"no\">Testing is </Font><Font Italic=\"yes\">really</Font><Font Italic=\"no\"> fun</Font></Text>\n"
475                 "        <Text Valign=\"top\" Vposition=\"90\"><Font Italic=\"no\">This is the </Font><Font Italic=\"yes\">second</Font><Font Italic=\"no\"> line</Font></Text>\n"
476                 "      </Subtitle>\n"
477                 "    </Font>\n"
478                 "  </SubtitleList>\n"
479                 "</SubtitleReel>",
480                 vector<string>()
481                 );
482 }
483
484 /* Write some subtitle content as SMPTE using bitmaps and check that it is right */
485 BOOST_AUTO_TEST_CASE (write_smpte_subtitle_test3)
486 {
487         dcp::SMPTESubtitleAsset c;
488         c.set_reel_number (1);
489         c.set_language (dcp::LanguageTag("en"));
490         c.set_content_title_text ("Test");
491         c.set_start_time (dcp::Time());
492
493         boost::filesystem::path const sub_image = "test/data/sub.png";
494
495         c.add (
496                 make_shared<dcp::SubtitleImage>(
497                         dcp::ArrayData(sub_image),
498                         dcp::Time (0, 4,  9, 22, 24),
499                         dcp::Time (0, 4, 11, 22, 24),
500                         0,
501                         dcp::HAlign::CENTER,
502                         0.8,
503                         dcp::VAlign::TOP,
504                         -88,
505                         dcp::Time (0, 0, 0, 0, 24),
506                         dcp::Time (0, 0, 0, 0, 24)
507                         )
508               );
509
510         c._id = "a6c58cff-3e1e-4b38-acec-a42224475ef6";
511
512         boost::filesystem::path path = "build/test/write_smpte_subtitle_test3";
513         boost::filesystem::create_directories (path);
514         c.write (path / "subs.mxf");
515
516         dcp::SMPTESubtitleAsset read_back (path / "subs.mxf");
517         auto subs = read_back.subtitles ();
518         BOOST_REQUIRE_EQUAL (subs.size(), 1U);
519         auto image = dynamic_pointer_cast<const dcp::SubtitleImage>(subs[0]);
520         BOOST_REQUIRE (image);
521
522         BOOST_CHECK (image->png_image() == dcp::ArrayData(sub_image));
523         BOOST_CHECK (image->in() == dcp::Time(0, 4, 9, 22, 24));
524         BOOST_CHECK (image->out() == dcp::Time(0, 4, 11, 22, 24));
525         BOOST_CHECK_CLOSE (image->h_position(), 0.0, 1);
526         BOOST_CHECK (image->h_align() == dcp::HAlign::CENTER);
527         BOOST_CHECK_CLOSE (image->v_position(), 0.8, 1);
528         BOOST_CHECK (image->v_align() == dcp::VAlign::TOP);
529         BOOST_CHECK_EQUAL(image->z_position(), -88);
530         BOOST_CHECK (image->fade_up_time() == dcp::Time(0, 0, 0, 0, 24));
531         BOOST_CHECK (image->fade_down_time() == dcp::Time(0, 0, 0, 0, 24));
532 }
533
534
535 /* Some closed caption systems require the <Text> elements to be written in order of their
536  * vertical position (see DoM bug #2106).
537  */
538 BOOST_AUTO_TEST_CASE (write_subtitles_in_vertical_order_with_top_alignment)
539 {
540         dcp::SMPTESubtitleAsset c;
541         c.set_reel_number (1);
542         c.set_language (dcp::LanguageTag("en"));
543         c.set_content_title_text ("Test");
544         c.set_issue_date (dcp::LocalTime ("2016-04-01T03:52:00+00:00"));
545
546         c.add (
547                 make_shared<dcp::SubtitleString>(
548                         string ("Arial"),
549                         false,
550                         false,
551                         false,
552                         dcp::Colour (255, 255, 255),
553                         48,
554                         1.0,
555                         dcp::Time (0, 0, 1, 0, 24),
556                         dcp::Time (0, 0, 9, 0, 24),
557                         0,
558                         dcp::HAlign::CENTER,
559                         0.8,
560                         dcp::VAlign::TOP,
561                         0,
562                         dcp::Direction::LTR,
563                         "Top line",
564                         dcp::Effect::NONE,
565                         dcp::Colour (0, 0, 0),
566                         dcp::Time (0, 0, 0, 0, 24),
567                         dcp::Time (0, 0, 0, 0, 24),
568                         0
569                         )
570                 );
571
572         c.add (
573                 make_shared<dcp::SubtitleString>(
574                         string ("Arial"),
575                         false,
576                         false,
577                         false,
578                         dcp::Colour (255, 255, 255),
579                         48,
580                         1.0,
581                         dcp::Time (0, 0, 1, 0, 24),
582                         dcp::Time (0, 0, 9, 0, 24),
583                         0,
584                         dcp::HAlign::CENTER,
585                         0.9,
586                         dcp::VAlign::TOP,
587                         0,
588                         dcp::Direction::LTR,
589                         "Bottom line",
590                         dcp::Effect::NONE,
591                         dcp::Colour (0, 0, 0),
592                         dcp::Time (0, 0, 0, 0, 24),
593                         dcp::Time (0, 0, 0, 0, 24),
594                         0
595                         )
596                 );
597
598         c._xml_id = "a6c58cff-3e1e-4b38-acec-a42224475ef6";
599
600         check_xml (
601                 c.xml_as_string(),
602                 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
603                 "<SubtitleReel xmlns=\"http://www.smpte-ra.org/schemas/428-7/2010/DCST\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n"
604                 "  <Id>urn:uuid:a6c58cff-3e1e-4b38-acec-a42224475ef6</Id>\n"
605                 "  <ContentTitleText>Test</ContentTitleText>\n"
606                 "  <IssueDate>2016-04-01T03:52:00.000+00:00</IssueDate>\n"
607                 "  <ReelNumber>1</ReelNumber>\n"
608                 "  <Language>en</Language>\n"
609                 "  <EditRate>24 1</EditRate>\n"
610                 "  <TimeCodeRate>24</TimeCodeRate>\n"
611                 "  <SubtitleList>\n"
612                 "    <Font AspectAdjust=\"1.0\" Color=\"FFFFFFFF\" Effect=\"none\" EffectColor=\"FF000000\" ID=\"Arial\" Italic=\"no\" Script=\"normal\" Size=\"48\" Underline=\"no\" Weight=\"normal\">\n"
613                 "      <Subtitle SpotNumber=\"1\" TimeIn=\"00:00:01:00\" TimeOut=\"00:00:09:00\" FadeUpTime=\"00:00:00:00\" FadeDownTime=\"00:00:00:00\">\n"
614                 "        <Text Valign=\"top\" Vposition=\"80\">Top line</Text>\n"
615                 "        <Text Valign=\"top\" Vposition=\"90\">Bottom line</Text>\n"
616                 "      </Subtitle>\n"
617                 "    </Font>\n"
618                 "  </SubtitleList>\n"
619                 "</SubtitleReel>",
620                 {}
621                 );
622 }
623
624
625 /* See the test above */
626 BOOST_AUTO_TEST_CASE (write_subtitles_in_vertical_order_with_bottom_alignment)
627 {
628         dcp::SMPTESubtitleAsset c;
629         c.set_reel_number (1);
630         c.set_language (dcp::LanguageTag("en"));
631         c.set_content_title_text ("Test");
632         c.set_issue_date (dcp::LocalTime ("2016-04-01T03:52:00+00:00"));
633
634         c.add (
635                 make_shared<dcp::SubtitleString>(
636                         string ("Arial"),
637                         false,
638                         false,
639                         false,
640                         dcp::Colour (255, 255, 255),
641                         48,
642                         1.0,
643                         dcp::Time (0, 0, 1, 0, 24),
644                         dcp::Time (0, 0, 9, 0, 24),
645                         0,
646                         dcp::HAlign::CENTER,
647                         0.8,
648                         dcp::VAlign::BOTTOM,
649                         0,
650                         dcp::Direction::LTR,
651                         "Top line",
652                         dcp::Effect::NONE,
653                         dcp::Colour (0, 0, 0),
654                         dcp::Time (0, 0, 0, 0, 24),
655                         dcp::Time (0, 0, 0, 0, 24),
656                         0
657                         )
658                 );
659
660         c.add (
661                 make_shared<dcp::SubtitleString>(
662                         string ("Arial"),
663                         false,
664                         false,
665                         false,
666                         dcp::Colour (255, 255, 255),
667                         48,
668                         1.0,
669                         dcp::Time (0, 0, 1, 0, 24),
670                         dcp::Time (0, 0, 9, 0, 24),
671                         0,
672                         dcp::HAlign::CENTER,
673                         0.7,
674                         dcp::VAlign::BOTTOM,
675                         0,
676                         dcp::Direction::LTR,
677                         "Bottom line",
678                         dcp::Effect::NONE,
679                         dcp::Colour (0, 0, 0),
680                         dcp::Time (0, 0, 0, 0, 24),
681                         dcp::Time (0, 0, 0, 0, 24),
682                         0
683                         )
684                 );
685
686         c._xml_id = "a6c58cff-3e1e-4b38-acec-a42224475ef6";
687
688         check_xml (
689                 c.xml_as_string(),
690                 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
691                 "<SubtitleReel xmlns=\"http://www.smpte-ra.org/schemas/428-7/2010/DCST\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n"
692                 "  <Id>urn:uuid:a6c58cff-3e1e-4b38-acec-a42224475ef6</Id>\n"
693                 "  <ContentTitleText>Test</ContentTitleText>\n"
694                 "  <IssueDate>2016-04-01T03:52:00.000+00:00</IssueDate>\n"
695                 "  <ReelNumber>1</ReelNumber>\n"
696                 "  <Language>en</Language>\n"
697                 "  <EditRate>24 1</EditRate>\n"
698                 "  <TimeCodeRate>24</TimeCodeRate>\n"
699                 "  <SubtitleList>\n"
700                 "    <Font AspectAdjust=\"1.0\" Color=\"FFFFFFFF\" Effect=\"none\" EffectColor=\"FF000000\" ID=\"Arial\" Italic=\"no\" Script=\"normal\" Size=\"48\" Underline=\"no\" Weight=\"normal\">\n"
701                 "      <Subtitle SpotNumber=\"1\" TimeIn=\"00:00:01:00\" TimeOut=\"00:00:09:00\" FadeUpTime=\"00:00:00:00\" FadeDownTime=\"00:00:00:00\">\n"
702                 "        <Text Valign=\"bottom\" Vposition=\"80\">Top line</Text>\n"
703                 "        <Text Valign=\"bottom\" Vposition=\"70\">Bottom line</Text>\n"
704                 "      </Subtitle>\n"
705                 "    </Font>\n"
706                 "  </SubtitleList>\n"
707                 "</SubtitleReel>",
708                 {}
709                 );
710 }
711