Remove use of boost foreach.
[libsub.git] / test / ssa_reader_test.cc
1 /*
2     Copyright (C) 2016-2021 Carl Hetherington <cth@carlh.net>
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include "test.h"
21 #include "ssa_reader.h"
22 #include "collect.h"
23 #include "subtitle.h"
24 #include "exceptions.h"
25 #include <boost/test/unit_test.hpp>
26 #include <boost/filesystem.hpp>
27 #include <cstdio>
28 #include <cmath>
29 #include <iostream>
30
31 using std::fabs;
32 using std::vector;
33
34 BOOST_AUTO_TEST_CASE (ssa_reader_test)
35 {
36         boost::filesystem::path p = private_test / "example.ssa";
37         FILE* f = fopen (p.string().c_str(), "r");
38         sub::SSAReader reader (f);
39         fclose (f);
40         auto subs = sub::collect<vector<sub::Subtitle>> (reader.subtitles());
41
42         auto i = subs.begin ();
43
44         BOOST_REQUIRE (i != subs.end ());
45         BOOST_CHECK_EQUAL (i->from, sub::Time::from_hms (0, 2, 40, 650));
46         BOOST_CHECK_EQUAL (i->to, sub::Time::from_hms (0, 2, 41, 790));
47         auto j = i->lines.begin();
48         BOOST_REQUIRE (j != i->lines.end ());
49         BOOST_REQUIRE_EQUAL (j->blocks.size(), 1);
50         sub::Block b = j->blocks.front ();
51         BOOST_CHECK_EQUAL (b.text, "Et les enregistrements de ses ondes delta ?");
52         BOOST_CHECK_EQUAL (b.font.get(), "Wolf_Rain");
53         BOOST_CHECK_EQUAL (b.font_size.points().get(), 56);
54         BOOST_CHECK_EQUAL (b.bold, false);
55         BOOST_CHECK_EQUAL (b.italic, false);
56         BOOST_CHECK_EQUAL (b.underline, false);
57         ++i;
58
59         BOOST_REQUIRE (i != subs.end ());
60         BOOST_CHECK_EQUAL (i->from, sub::Time::from_hms (0, 2, 42, 420));
61         BOOST_CHECK_EQUAL (i->to, sub::Time::from_hms (0, 2, 44, 150));
62         j = i->lines.begin();
63         BOOST_REQUIRE (j != i->lines.end ());
64         BOOST_REQUIRE_EQUAL (j->blocks.size(), 1);
65         b = j->blocks.front ();
66         BOOST_CHECK_EQUAL (b.text, "Toujours rien.");
67         BOOST_CHECK_EQUAL (b.font.get(), "Wolf_Rain");
68         BOOST_CHECK_EQUAL (b.font_size.points().get(), 56);
69         BOOST_CHECK_EQUAL (b.bold, false);
70         BOOST_CHECK_EQUAL (b.italic, false);
71         BOOST_CHECK_EQUAL (b.underline, false);
72         ++i;
73
74         BOOST_CHECK (i == subs.end());
75 }
76
77 BOOST_AUTO_TEST_CASE (ssa_reader_line_test1)
78 {
79         sub::RawSubtitle base;
80         auto r = sub::SSAReader::parse_line (
81                 base,
82                 "This is a line with some {\\i1}italics{\\i0} and then\\nthere is a new line.",
83                 1920, 1080
84                 );
85
86         auto i = r.begin();
87         BOOST_CHECK_EQUAL (i->text, "This is a line with some ");
88         BOOST_CHECK_EQUAL (i->italic, false);
89         ++i;
90         BOOST_REQUIRE (i != r.end ());
91
92         BOOST_CHECK_EQUAL (i->text, "italics");
93         BOOST_CHECK_EQUAL (i->italic, true);
94         ++i;
95         BOOST_REQUIRE (i != r.end ());
96
97         BOOST_CHECK_EQUAL (i->text, " and then");
98         BOOST_CHECK_EQUAL (i->italic, false);
99         ++i;
100         BOOST_REQUIRE (i != r.end ());
101
102         BOOST_CHECK_EQUAL (i->text, "there is a new line.");
103         ++i;
104         BOOST_REQUIRE (i == r.end ());
105 }
106
107 BOOST_AUTO_TEST_CASE (ssa_reader_line_test2)
108 {
109         sub::RawSubtitle base;
110         auto r = sub::SSAReader::parse_line (
111                 base,
112                 "{\\i1}It's all just italics{\\i0}",
113                 1920, 1080
114                 );
115
116         auto i = r.begin ();
117         BOOST_CHECK_EQUAL (i->text, "It's all just italics");
118         BOOST_CHECK_EQUAL (i->italic, true);
119         ++i;
120         BOOST_REQUIRE (i == r.end ());
121
122         r = sub::SSAReader::parse_line (
123                 base,
124                 "{\\i1}Italic{\\i0}\\Nand new line",
125                 1920, 1080
126                 );
127
128         i = r.begin ();
129         BOOST_CHECK_EQUAL (i->text, "Italic");
130         BOOST_CHECK_EQUAL (i->italic, true);
131         BOOST_CHECK (fabs ((72.0 * 1.2 / 792) - i->vertical_position.proportional.get()) < 1e-5);
132         ++i;
133         BOOST_CHECK_EQUAL (i->text, "and new line");
134         BOOST_CHECK_EQUAL (i->italic, false);
135         BOOST_CHECK (i->vertical_position.proportional.get() < 1e-5);
136 }
137
138 static void
139 test (boost::filesystem::path p)
140 {
141         p = private_test / p;
142         FILE* f = fopen (p.string().c_str(), "r");
143         BOOST_REQUIRE (f);
144         sub::SSAReader r (f);
145         fclose (f);
146 }
147
148 /** Test of reading some typical .ssa files */
149 BOOST_AUTO_TEST_CASE (ssa_reader_test2)
150 {
151         test ("DKH_UT_EN20160601def.ssa");
152         test ("dcpsubtest-en.ssa");
153         test ("dcpsubtest-en.ssa");
154         test ("W_GERMAN_SUBS_grey.ass");
155 }
156
157 #define SUB_START(f, t) \
158         BOOST_REQUIRE (i != subs.end ()); \
159         BOOST_CHECK_EQUAL (i->from, f); \
160         BOOST_CHECK_EQUAL (i->to, t); \
161         j = i->lines.begin ();
162
163 #define LINE(vp, vr, hp, hr)                  \
164         BOOST_REQUIRE (j != i->lines.end ()); \
165         BOOST_CHECK (j->vertical_position.proportional); \
166         BOOST_CHECK (fabs (j->vertical_position.proportional.get() - vp) < 1e-5); \
167         BOOST_CHECK (j->vertical_position.reference); \
168         BOOST_CHECK_EQUAL (j->vertical_position.reference.get(), vr); \
169         BOOST_CHECK (fabs (j->horizontal_position.proportional - hp) < 1e-5); \
170         BOOST_CHECK_EQUAL (j->horizontal_position.reference, hr); \
171         k = j->blocks.begin (); \
172         ++j;
173
174 #define BLOCK(t, f, s, b, i, u) \
175         BOOST_REQUIRE (k != j->blocks.end ()); \
176         BOOST_CHECK_EQUAL (k->text, t); \
177         BOOST_CHECK_EQUAL (k->font.get(), f); \
178         BOOST_CHECK_EQUAL (k->font_size.points().get(), s); \
179         BOOST_CHECK_EQUAL (k->bold, b); \
180         BOOST_CHECK_EQUAL (k->italic, i); \
181         BOOST_CHECK_EQUAL (k->underline, u); \
182         ++k;
183
184 #define SUB_END() \
185         ++i;
186
187 /** Test reading of a file within the libsub tree which exercises the parser */
188 BOOST_AUTO_TEST_CASE (ssa_reader_test3)
189 {
190         boost::filesystem::path p = "test/data/test.ssa";
191         FILE* f = fopen (p.string().c_str(), "r");
192         sub::SSAReader reader (f);
193         fclose (f);
194         auto subs = sub::collect<vector<sub::Subtitle>> (reader.subtitles());
195
196         auto i = subs.begin();
197         vector<sub::Line>::iterator j;
198         vector<sub::Block>::iterator k;
199
200         /* Hello world */
201         SUB_START (sub::Time::from_hms (0, 0, 1, 230), sub::Time::from_hms (0, 0, 4, 550));
202         LINE (0, sub::BOTTOM_OF_SCREEN, 0, sub::HORIZONTAL_CENTRE_OF_SCREEN);
203         BLOCK ("Hello world", "Arial", 20, false, false, false);
204         SUB_END();
205
206         /* This is vertically moved\nand has two lines. */
207         SUB_START (sub::Time::from_hms (0, 0, 5, 740), sub::Time::from_hms (0, 0, 11, 0));
208         /* The first line should be 900 pixels and one line (20
209            points, 1.2 times spaced, as a proportion of the total
210            screen height 729 points) up.
211         */
212         LINE((900.0 / 1080) - (20.0 * 1.2 / 792), sub::BOTTOM_OF_SCREEN, 0, sub::HORIZONTAL_CENTRE_OF_SCREEN);
213         BLOCK("This is vertically moved", "Arial", 20, false, false, false);
214         LINE((900.0 / 1080), sub::BOTTOM_OF_SCREEN, 0, sub::HORIZONTAL_CENTRE_OF_SCREEN);
215         BLOCK("and has two lines.", "Arial", 20, false, false, false);
216         SUB_END();
217
218         /* Some {\i1}italics{\i} are here. */
219         SUB_START (sub::Time::from_hms (0, 0, 7, 740), sub::Time::from_hms (0, 0, 9, 0));
220         LINE(0, sub::BOTTOM_OF_SCREEN, 0, sub::HORIZONTAL_CENTRE_OF_SCREEN);
221         BLOCK("Some ", "Arial", 20, false, false, false);
222         BLOCK("italics", "Arial", 20, false, true, false);
223         BLOCK(" are here.", "Arial", 20, false, false, false);
224         SUB_END();
225
226         /* Alignments */
227
228         SUB_START (sub::Time::from_hms (0, 0, 9, 230), sub::Time::from_hms (0, 0, 11, 560));
229         LINE (0, sub::BOTTOM_OF_SCREEN, 0, sub::LEFT_OF_SCREEN);
230         BLOCK("bottom left", "Arial", 20, false, false, false);
231         SUB_END ();
232
233         SUB_START (sub::Time::from_hms (0, 0, 9, 240), sub::Time::from_hms (0, 0, 11, 560));
234         LINE (0, sub::BOTTOM_OF_SCREEN, 0, sub::HORIZONTAL_CENTRE_OF_SCREEN);
235         BLOCK("bottom centre", "Arial", 20, false, false, false);
236         SUB_END ();
237
238         SUB_START (sub::Time::from_hms (0, 0, 9, 250), sub::Time::from_hms (0, 0, 11, 560));
239         LINE (0, sub::BOTTOM_OF_SCREEN, 0, sub::RIGHT_OF_SCREEN);
240         BLOCK("bottom right", "Arial", 20, false, false, false);
241         SUB_END ();
242
243         SUB_START (sub::Time::from_hms (0, 0, 9, 260), sub::Time::from_hms (0, 0, 11, 560));
244         LINE (0, sub::VERTICAL_CENTRE_OF_SCREEN, 0, sub::LEFT_OF_SCREEN);
245         BLOCK("middle left", "Arial", 20, false, false, false);
246         SUB_END ();
247
248         SUB_START (sub::Time::from_hms (0, 0, 9, 270), sub::Time::from_hms (0, 0, 11, 560));
249         LINE (0, sub::VERTICAL_CENTRE_OF_SCREEN, 0, sub::HORIZONTAL_CENTRE_OF_SCREEN);
250         BLOCK("middle centre", "Arial", 20, false, false, false);
251         SUB_END ();
252
253         SUB_START (sub::Time::from_hms (0, 0, 9, 280), sub::Time::from_hms (0, 0, 11, 560));
254         LINE (0, sub::VERTICAL_CENTRE_OF_SCREEN, 0, sub::RIGHT_OF_SCREEN);
255         BLOCK("middle right", "Arial", 20, false, false, false);
256         SUB_END ();
257
258         SUB_START (sub::Time::from_hms (0, 0, 9, 290), sub::Time::from_hms (0, 0, 11, 560));
259         LINE (0, sub::TOP_OF_SCREEN, 0, sub::LEFT_OF_SCREEN);
260         BLOCK("top left", "Arial", 20, false, false, false);
261         SUB_END ();
262
263         SUB_START (sub::Time::from_hms (0, 0, 9, 300), sub::Time::from_hms (0, 0, 11, 560));
264         LINE (0, sub::TOP_OF_SCREEN, 0, sub::HORIZONTAL_CENTRE_OF_SCREEN);
265         BLOCK("top centre", "Arial", 20, false, false, false);
266         SUB_END ();
267
268         SUB_START (sub::Time::from_hms (0, 0, 9, 310), sub::Time::from_hms (0, 0, 11, 560));
269         LINE (0, sub::TOP_OF_SCREEN, 0, sub::RIGHT_OF_SCREEN);
270         BLOCK("top right", "Arial", 20, false, false, false);
271         SUB_END ();
272
273         BOOST_REQUIRE (i == subs.end ());
274 }
275
276 /** Test reading of a file within the libsub-test-private tree which exercises the parser */
277 BOOST_AUTO_TEST_CASE (ssa_reader_test4)
278 {
279         boost::filesystem::path p = private_test / "dcpsubtest2-en.ssa";
280         FILE* f = fopen (p.string().c_str(), "r");
281         sub::SSAReader reader (f);
282         fclose (f);
283         auto subs = sub::collect<vector<sub::Subtitle>> (reader.subtitles());
284
285         auto i = subs.begin();
286         vector<sub::Line>::iterator j;
287         vector<sub::Block>::iterator k;
288
289         BOOST_REQUIRE (i != subs.end ());
290
291         SUB_START (sub::Time::from_hms (0, 0, 1, 0), sub::Time::from_hms (0, 0, 3, 0));
292         /* The first line should be one line (50 points, 1.2 times
293            spaced, as a proportion of the total screen height 729
294            points) up.
295         */
296         LINE ((50.0 * 1.2 / 792), sub::BOTTOM_OF_SCREEN, 0, sub::HORIZONTAL_CENTRE_OF_SCREEN);
297         BLOCK ("1st line: This is normal", "Verdana", 50, false, false, false);
298         LINE (0, sub::BOTTOM_OF_SCREEN, 0, sub::HORIZONTAL_CENTRE_OF_SCREEN);
299         BLOCK ("2d line: this is bold", "Verdana", 50, true, false, false);
300         SUB_END ();
301
302         SUB_START (sub::Time::from_hms (0, 0, 3, 100), sub::Time::from_hms (0, 0, 5, 100));
303         LINE ((50.0 * 1.2 / 792), sub::BOTTOM_OF_SCREEN, 0, sub::HORIZONTAL_CENTRE_OF_SCREEN);
304         BLOCK ("1st line: this is bold", "Verdana", 50, true, false, false);
305         LINE (0, sub::BOTTOM_OF_SCREEN, 0, sub::HORIZONTAL_CENTRE_OF_SCREEN);
306         BLOCK ("2nd line: This is normal", "Verdana", 50, false, false, false);
307         SUB_END ();
308
309         SUB_START (sub::Time::from_hms (0, 0, 5, 200), sub::Time::from_hms (0, 0, 7, 200));
310         LINE ((50.0 * 1.2 / 792), sub::BOTTOM_OF_SCREEN, 0, sub::HORIZONTAL_CENTRE_OF_SCREEN);
311         BLOCK ("1st line: this is bold", "Verdana", 50, true, false, false);
312         LINE (0, sub::BOTTOM_OF_SCREEN, 0, sub::HORIZONTAL_CENTRE_OF_SCREEN);
313         BLOCK ("2nd line: this is italics", "Verdana", 50, false, true, false);
314         SUB_END ();
315
316         SUB_START (sub::Time::from_hms (0, 0, 7, 300), sub::Time::from_hms (0, 0, 9, 300));
317         LINE ((50.0 * 1.2 / 792), sub::BOTTOM_OF_SCREEN, 0, sub::HORIZONTAL_CENTRE_OF_SCREEN);
318         BLOCK ("1st line: this is italics", "Verdana", 50, false, true, false);
319         LINE (0, sub::BOTTOM_OF_SCREEN, 0, sub::HORIZONTAL_CENTRE_OF_SCREEN);
320         BLOCK ("2nd line: this is bold", "Verdana", 50, true, false, false);
321         SUB_END ();
322 }
323
324 /** Test reading of a .ass file */
325 BOOST_AUTO_TEST_CASE (ssa_reader_test5)
326 {
327         boost::filesystem::path p = private_test / "dcpsubtest-en.ass";
328         FILE* f = fopen (p.string().c_str(), "r");
329         sub::SSAReader reader (f);
330         fclose (f);
331         auto subs = sub::collect<vector<sub::Subtitle>> (reader.subtitles());
332
333         auto i = subs.begin ();
334         vector<sub::Line>::iterator j;
335         vector<sub::Block>::iterator k;
336
337         BOOST_REQUIRE (i != subs.end ());
338
339         SUB_START (sub::Time::from_hms (0, 0, 1, 0), sub::Time::from_hms (0, 0, 3, 0));
340         /* The first line should be one line (26 points, 1.2 times
341            spaced, as a proportion of the total screen height 729
342            points) up.
343         */
344         LINE ((26.0 * 1.2 / 792), sub::BOTTOM_OF_SCREEN, 0, sub::HORIZONTAL_CENTRE_OF_SCREEN);
345         BLOCK ("1st subtitle, 1st line", "arial", 26, true, false, false);
346         LINE (0, sub::BOTTOM_OF_SCREEN, 0, sub::HORIZONTAL_CENTRE_OF_SCREEN);
347         BLOCK ("2nd subtitle, 2nd line", "arial", 26, true, false, false);
348         SUB_END ();
349
350         SUB_START (sub::Time::from_hms (0, 0, 3, 100), sub::Time::from_hms (0, 0, 5, 100));
351         LINE ((26.0 * 1.2 / 792), sub::BOTTOM_OF_SCREEN, 0, sub::HORIZONTAL_CENTRE_OF_SCREEN);
352         BLOCK ("2nd subtitle, 1st line", "arial", 26, true, false, false);
353         LINE (0, sub::BOTTOM_OF_SCREEN, 0, sub::HORIZONTAL_CENTRE_OF_SCREEN);
354         BLOCK ("2nd subtitle, 2nd line", "arial", 26, true, false, false);
355         SUB_END ();
356
357         SUB_START (sub::Time::from_hms (0, 0, 5, 200), sub::Time::from_hms (0, 0, 7, 200));
358         LINE ((26.0 * 1.2 / 792), sub::BOTTOM_OF_SCREEN, 0, sub::HORIZONTAL_CENTRE_OF_SCREEN);
359         BLOCK ("3rd subtitle, 1st line", "arial", 26, true, false, false);
360         LINE (0, sub::BOTTOM_OF_SCREEN, 0, sub::HORIZONTAL_CENTRE_OF_SCREEN);
361         BLOCK ("3rd subtitle, 2nd line", "arial", 26, true, false, false);
362         SUB_END ();
363
364         SUB_START (sub::Time::from_hms (0, 0, 7, 300), sub::Time::from_hms (0, 0, 9, 300));
365         LINE ((26.0 * 1.2 / 792), sub::BOTTOM_OF_SCREEN, 0, sub::HORIZONTAL_CENTRE_OF_SCREEN);
366         BLOCK ("4th subtitle, 1st line", "arial", 26, true, false, false);
367         LINE (0, sub::BOTTOM_OF_SCREEN, 0, sub::HORIZONTAL_CENTRE_OF_SCREEN);
368         BLOCK ("4th subtitle, 2nd line", "arial", 26, true, false, false);
369         SUB_END ();
370 }
371
372 /** Test reading of another .ass file */
373 BOOST_AUTO_TEST_CASE (ssa_reader_test6)
374 {
375         boost::filesystem::path p = private_test / "DCP-o-matic_test_subs_1.ass";
376         FILE* f = fopen (p.string().c_str(), "r");
377         BOOST_REQUIRE (f);
378         sub::SSAReader reader (f);
379         fclose (f);
380         auto subs = sub::collect<vector<sub::Subtitle>> (reader.subtitles());
381
382         auto i = subs.begin ();
383         vector<sub::Line>::iterator j;
384         vector<sub::Block>::iterator k;
385
386         BOOST_REQUIRE (i != subs.end ());
387
388         SUB_START (sub::Time::from_hms (0, 0, 0, 70), sub::Time::from_hms (0, 0, 1, 110));
389         /* The first line should be one line (30 points, 1.2 times
390            spaced, as a proportion of the total screen height 729
391            points) up.
392         */
393         LINE ((30.0 * 1.2 / 792), sub::BOTTOM_OF_SCREEN, 0, sub::HORIZONTAL_CENTRE_OF_SCREEN);
394         BLOCK ("This line is normal", "Arial", 30, false, false, false);
395         LINE (0, sub::BOTTOM_OF_SCREEN, 0, sub::HORIZONTAL_CENTRE_OF_SCREEN);
396         BLOCK ("This line is bold", "Arial", 30, true, false, false);
397         SUB_END ();
398
399         SUB_START (sub::Time::from_hms (0, 0, 1, 200), sub::Time::from_hms (0, 0, 2, 240));
400         LINE ((30.0 * 1.2 / 792), sub::BOTTOM_OF_SCREEN, 0, sub::HORIZONTAL_CENTRE_OF_SCREEN);
401         BLOCK ("This line is bold", "Arial", 30, true, false, false);
402         LINE (0, sub::BOTTOM_OF_SCREEN, 0, sub::HORIZONTAL_CENTRE_OF_SCREEN);
403         BLOCK ("This line is normal", "Arial", 30, false, false, false);
404         SUB_END ();
405
406         SUB_START (sub::Time::from_hms (0, 0, 2, 300), sub::Time::from_hms (0, 0, 3, 380));
407         LINE ((30.0 * 1.2 / 792), sub::BOTTOM_OF_SCREEN, 0, sub::HORIZONTAL_CENTRE_OF_SCREEN);
408         BLOCK ("This line is bold", "Arial", 30, true, false, false);
409         LINE (0, sub::BOTTOM_OF_SCREEN, 0, sub::HORIZONTAL_CENTRE_OF_SCREEN);
410         BLOCK ("This line is italic", "Arial", 30, false, true, false);
411         SUB_END ();
412
413         SUB_START (sub::Time::from_hms (0, 0, 3, 400), sub::Time::from_hms (0, 0, 4, 480));
414         LINE ((30.0 * 1.2 / 792), sub::BOTTOM_OF_SCREEN, 0, sub::HORIZONTAL_CENTRE_OF_SCREEN);
415         BLOCK ("This line is italic", "Arial", 30, false, true, false);
416         LINE (0, sub::BOTTOM_OF_SCREEN, 0, sub::HORIZONTAL_CENTRE_OF_SCREEN);
417         BLOCK ("This line is bold", "Arial", 30, true, false, false);
418         SUB_END ();
419
420         SUB_START (sub::Time::from_hms (0, 0, 4, 510), sub::Time::from_hms (0, 0, 5, 600));
421         LINE ((30.0 * 1.2 / 792), sub::BOTTOM_OF_SCREEN, 0, sub::HORIZONTAL_CENTRE_OF_SCREEN);
422         BLOCK ("Last three words are ", "Arial", 30, false, false, false);
423         BLOCK ("bold AND italic", "Arial", 30, true, true, false);
424         LINE (0, sub::BOTTOM_OF_SCREEN, 0, sub::HORIZONTAL_CENTRE_OF_SCREEN);
425         BLOCK ("Last three words are ", "Arial", 30, false, false, false);
426         BLOCK ("italic AND bold", "Arial", 30, true, true, false);
427         SUB_END ();
428
429         SUB_START (sub::Time::from_hms (0, 0, 5, 620), sub::Time::from_hms (0, 0, 6, 710));
430         LINE ((30.0 * 1.2 / 792), sub::BOTTOM_OF_SCREEN, 0, sub::HORIZONTAL_CENTRE_OF_SCREEN);
431         BLOCK ("Last three words are ", "Arial", 30, false, false, false);
432         BLOCK ("bold AND italic", "Arial", 30, true, true, false);
433         LINE (0, sub::BOTTOM_OF_SCREEN, 0, sub::HORIZONTAL_CENTRE_OF_SCREEN);
434         BLOCK ("First three words", "Arial", 30, true, true, false);
435         BLOCK (" are italic AND bold", "Arial", 30, false, false, false);
436         SUB_END ();
437
438         SUB_START (sub::Time::from_hms (0, 0, 6, 730), sub::Time::from_hms (0, 0, 8, 30));
439         LINE ((30.0 * 1.2 / 792), sub::BOTTOM_OF_SCREEN, 0, sub::HORIZONTAL_CENTRE_OF_SCREEN);
440         BLOCK ("Last three words are ", "Arial", 30, false, false, false);
441         BLOCK ("bold AND italic", "Arial", 30, true, true, false);
442         LINE (0, sub::BOTTOM_OF_SCREEN, 0, sub::HORIZONTAL_CENTRE_OF_SCREEN);
443         BLOCK ("This line is normal", "Arial", 30, false, false, false);
444         SUB_END ();
445
446         SUB_START (sub::Time::from_hms (0, 0, 8, 90), sub::Time::from_hms (0, 0, 9, 210));
447         LINE ((30.0 * 1.2 / 792), sub::BOTTOM_OF_SCREEN, 0, sub::HORIZONTAL_CENTRE_OF_SCREEN);
448         BLOCK ("Both lines are bold AND italic", "Arial", 30, true, true, false);
449         LINE (0, sub::BOTTOM_OF_SCREEN, 0, sub::HORIZONTAL_CENTRE_OF_SCREEN);
450         BLOCK ("Both lines are bold AND italic", "Arial", 30, true, true, false);
451         SUB_END ();
452 }
453
454 /** Test \pos */
455 BOOST_AUTO_TEST_CASE (ssa_reader_pos)
456 {
457         boost::filesystem::path p = "test/data/test2.ssa";
458         FILE* f = fopen (p.string().c_str(), "r");
459         sub::SSAReader reader (f);
460         fclose (f);
461         auto subs = sub::collect<vector<sub::Subtitle>> (reader.subtitles());
462
463         auto i = subs.begin ();
464         vector<sub::Line>::iterator j;
465         vector<sub::Block>::iterator k;
466
467         /* Hello world */
468         SUB_START (sub::Time::from_hms (0, 0, 1, 230), sub::Time::from_hms (0, 0, 4, 550));
469         LINE (0, sub::BOTTOM_OF_SCREEN, 0, sub::HORIZONTAL_CENTRE_OF_SCREEN);
470         BLOCK ("Hello world this is ", "Arial", 20, false, false, false);
471         LINE (300.0 / 1080, sub::TOP_OF_SCREEN, 400.0 / 1920, sub::LEFT_OF_SCREEN);
472         BLOCK ("positioning.", "Arial", 20, false, false, false);
473         SUB_END();
474 }
475
476 /** Test \fs */
477 BOOST_AUTO_TEST_CASE (ssa_reader_fs)
478 {
479         sub::RawSubtitle base;
480         auto r = sub::SSAReader::parse_line (
481                 base,
482                 "This is a line with some {\\fs64}font sizing.",
483                 1920, 1080
484                 );
485
486         auto i = r.begin ();
487         BOOST_CHECK_EQUAL (i->text, "This is a line with some ");
488         ++i;
489         BOOST_REQUIRE (i != r.end ());
490
491         BOOST_CHECK_EQUAL (i->text, "font sizing.");
492         BOOST_CHECK (i->font_size.points());
493         BOOST_CHECK_EQUAL (i->font_size.points().get(), 64);
494         ++i;
495         BOOST_REQUIRE (i == r.end ());
496 }
497
498 /** Test a valid \c */
499 BOOST_AUTO_TEST_CASE (ssa_reader_c)
500 {
501         sub::RawSubtitle base;
502         auto r = sub::SSAReader::parse_line (
503                 base,
504                 "{\\c&H00FFFF&}Dieser Untertitel ist gelb",
505                 1920, 1080
506                 );
507
508         auto i = r.begin ();
509         BOOST_CHECK_EQUAL (i->text, "Dieser Untertitel ist gelb");
510         BOOST_CHECK (i->colour == sub::Colour::from_rgb_hex("ffff00"));
511         ++i;
512         BOOST_REQUIRE (i == r.end ());
513 }
514
515 /** Test invalid \c */
516 BOOST_AUTO_TEST_CASE (ssa_reader_c_bad)
517 {
518         sub::RawSubtitle base;
519         BOOST_CHECK_THROW(
520                 sub::SSAReader::parse_line(
521                         base,
522                         "{\\c&H0}Dieser Untertitel ist gelb",
523                         1920, 1080
524                         ),
525                 sub::SSAError
526                 );
527 }