Obfuscate some test file names.
[libsub.git] / test / subrip_reader_test.cc
1 /*
2     Copyright (C) 2014-2020 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 "subrip_reader.h"
21 #include "subtitle.h"
22 #include "test.h"
23 #include "exceptions.h"
24 #include "collect.h"
25 #include <boost/test/unit_test.hpp>
26 #include <boost/filesystem.hpp>
27 #include <cmath>
28 #include <iostream>
29 #include <cstdio>
30
31 using std::list;
32 using std::cerr;
33 using std::vector;
34 using std::fabs;
35
36 /* Test reading of a Subrip file */
37 BOOST_AUTO_TEST_CASE (subrip_reader_test)
38 {
39         FILE* f = fopen ("test/data/test.srt", "r");
40         sub::SubripReader reader (f);
41         fclose (f);
42         list<sub::Subtitle> subs = sub::collect<std::list<sub::Subtitle> > (reader.subtitles ());
43
44         list<sub::Subtitle>::iterator i = subs.begin ();
45
46
47         /* First subtitle */
48
49         BOOST_CHECK (i != subs.end ());
50         BOOST_CHECK_EQUAL (i->from, sub::Time::from_hms (0, 0, 41, 90));
51         BOOST_CHECK_EQUAL (i->to, sub::Time::from_hms (0, 0, 42, 210));
52
53         list<sub::Line>::iterator j = i->lines.begin ();
54         BOOST_CHECK (j != i->lines.end ());
55         BOOST_CHECK_EQUAL (j->blocks.size(), 1);
56         sub::Block b = j->blocks.front ();
57         BOOST_CHECK_EQUAL (b.text, "This is a subtitle");
58         /* No font is specified by subrip, so none should be seen here */
59         BOOST_CHECK (!b.font);
60         BOOST_CHECK (!b.font_size.specified());
61         BOOST_CHECK_EQUAL (b.bold, false);
62         BOOST_CHECK_EQUAL (b.italic, false);
63         BOOST_CHECK_EQUAL (b.underline, false);
64         BOOST_REQUIRE (j->vertical_position.line);
65         BOOST_CHECK_EQUAL (j->vertical_position.line.get(), 0);
66         BOOST_CHECK_EQUAL (j->vertical_position.reference.get(), sub::TOP_OF_SUBTITLE);
67         ++j;
68
69         BOOST_CHECK (j != i->lines.end ());
70         BOOST_CHECK_EQUAL (j->blocks.size(), 1);
71         b = j->blocks.front ();
72         BOOST_CHECK_EQUAL (b.text, "and that's a line break");
73         /* No font is specified by subrip, so none should be seen here */
74         BOOST_CHECK (!b.font);
75         BOOST_CHECK (!b.font_size.specified());
76         BOOST_CHECK_EQUAL (b.bold, false);
77         BOOST_CHECK_EQUAL (b.italic, false);
78         BOOST_CHECK_EQUAL (b.underline, false);
79         BOOST_REQUIRE (j->vertical_position.line);
80         BOOST_CHECK_EQUAL (j->vertical_position.line.get(), 1);
81         BOOST_CHECK_EQUAL (j->vertical_position.reference.get(), sub::TOP_OF_SUBTITLE);
82         ++i;
83
84
85         /* Second subtitle */
86
87         BOOST_CHECK (i != subs.end ());
88         BOOST_CHECK_EQUAL (i->from, sub::Time::from_hms (0, 1, 1, 10));
89         BOOST_CHECK_EQUAL (i->to, sub::Time::from_hms (0, 1, 2, 100));
90
91         BOOST_CHECK_EQUAL (i->lines.size(), 1);
92         sub::Line l = i->lines.front ();
93         BOOST_CHECK_EQUAL (l.blocks.size(), 7);
94         BOOST_CHECK_EQUAL (l.vertical_position.line.get(), 0);
95         BOOST_CHECK_EQUAL (l.vertical_position.reference.get(), sub::TOP_OF_SUBTITLE);
96
97         list<sub::Block>::iterator k = l.blocks.begin ();
98
99         BOOST_CHECK (k != l.blocks.end ());
100         BOOST_CHECK_EQUAL (k->text, "This is some ");
101         /* No font is specified by subrip, so none should be seen here */
102         BOOST_CHECK (!b.font);
103         BOOST_CHECK (!b.font_size.specified());
104         BOOST_CHECK_EQUAL (k->bold, false);
105         BOOST_CHECK_EQUAL (k->italic, false);
106         BOOST_CHECK_EQUAL (k->underline, false);
107         ++k;
108
109         BOOST_CHECK (k != l.blocks.end ());
110         BOOST_CHECK_EQUAL (k->text, "bold");
111         /* No font is specified by subrip, so none should be seen here */
112         BOOST_CHECK (!b.font);
113         BOOST_CHECK (!b.font_size.specified());
114         BOOST_CHECK_EQUAL (k->bold, true);
115         BOOST_CHECK_EQUAL (k->italic, false);
116         BOOST_CHECK_EQUAL (k->underline, false);
117         ++k;
118
119         BOOST_CHECK (k != l.blocks.end ());
120         BOOST_CHECK_EQUAL (k->text, " and some ");
121         /* No font is specified by subrip, so none should be seen here */
122         BOOST_CHECK (!b.font);
123         BOOST_CHECK (!b.font_size.specified());
124         BOOST_CHECK_EQUAL (k->bold, false);
125         BOOST_CHECK_EQUAL (k->italic, false);
126         BOOST_CHECK_EQUAL (k->underline, false);
127         ++k;
128
129         BOOST_CHECK (k != l.blocks.end ());
130         BOOST_CHECK_EQUAL (k->text, "bold italic");
131         /* No font is specified by subrip, so none should be seen here */
132         BOOST_CHECK (!b.font);
133         BOOST_CHECK (!b.font_size.specified());
134         BOOST_CHECK_EQUAL (k->bold, true);
135         BOOST_CHECK_EQUAL (k->italic, true);
136         BOOST_CHECK_EQUAL (k->underline, false);
137         ++k;
138
139         BOOST_CHECK (k != l.blocks.end ());
140         BOOST_CHECK_EQUAL (k->text, " and some ");
141         /* No font is specified by subrip, so none should be seen here */
142         BOOST_CHECK (!b.font);
143         BOOST_CHECK (!b.font_size.specified());
144         BOOST_CHECK_EQUAL (k->bold, false);
145         BOOST_CHECK_EQUAL (k->italic, false);
146         BOOST_CHECK_EQUAL (k->underline, false);
147         ++k;
148
149         BOOST_CHECK (k != l.blocks.end ());
150         BOOST_CHECK_EQUAL (k->text, "underlined");
151         /* No font is specified by subrip, so none should be seen here */
152         BOOST_CHECK (!b.font);
153         BOOST_CHECK (!b.font_size.specified());
154         BOOST_CHECK_EQUAL (k->bold, false);
155         BOOST_CHECK_EQUAL (k->italic, false);
156         BOOST_CHECK_EQUAL (k->underline, true);
157         ++k;
158
159         BOOST_CHECK (k != l.blocks.end ());
160         BOOST_CHECK_EQUAL (k->text, ".");
161         /* No font is specified by subrip, so none should be seen here */
162         BOOST_CHECK (!b.font);
163         BOOST_CHECK (!b.font_size.specified());
164         BOOST_CHECK_EQUAL (k->bold, false);
165         BOOST_CHECK_EQUAL (k->italic, false);
166         BOOST_CHECK_EQUAL (k->underline, false);
167         ++k;
168
169         BOOST_CHECK (k == l.blocks.end ());
170 }
171
172 /* Test reading of another Subrip file */
173 BOOST_AUTO_TEST_CASE (subrip_reader_test2)
174 {
175         FILE* f = fopen ("test/data/test2.srt", "r");
176         sub::SubripReader reader (f);
177         fclose (f);
178         list<sub::Subtitle> subs = sub::collect<list<sub::Subtitle> > (reader.subtitles ());
179
180         list<sub::Subtitle>::const_iterator i = subs.begin();
181
182         BOOST_CHECK (i != subs.end ());
183         BOOST_CHECK_EQUAL (i->from, sub::Time::from_hms (0, 1, 49, 200));
184         BOOST_CHECK_EQUAL (i->to, sub::Time::from_hms (0, 1, 52, 351));
185         BOOST_CHECK_EQUAL (i->lines.size(), 2);
186         BOOST_CHECK_EQUAL (i->lines.front().blocks.front().text, "This is a subtitle, and it goes ");
187         BOOST_CHECK_EQUAL (i->lines.back().blocks.front().text, "over two lines.");
188
189         ++i;
190         BOOST_CHECK (i != subs.end ());
191         BOOST_CHECK_EQUAL (i->from, sub::Time::from_hms (0, 1, 52, 440));
192         BOOST_CHECK_EQUAL (i->to, sub::Time::from_hms (0, 1, 54, 351));
193         BOOST_CHECK_EQUAL (i->lines.size(), 1);
194         BOOST_CHECK_EQUAL (i->lines.front().blocks.front().text, "We have emboldened this");
195         BOOST_CHECK_EQUAL (i->lines.front().blocks.front().bold, true);
196
197         ++i;
198         BOOST_CHECK (i != subs.end ());
199         BOOST_CHECK_EQUAL (i->from, sub::Time::from_hms (0, 1, 54, 440));
200         BOOST_CHECK_EQUAL (i->to, sub::Time::from_hms (0, 1, 56, 590));
201         BOOST_CHECK_EQUAL (i->lines.size(), 1);
202         BOOST_CHECK_EQUAL (i->lines.front().blocks.front().text, "And italicised this.");
203         BOOST_CHECK_EQUAL (i->lines.front().blocks.front().italic, true);
204
205         ++i;
206         BOOST_CHECK (i != subs.end ());
207         BOOST_CHECK_EQUAL (i->from, sub::Time::from_hms (0, 1, 56, 680));
208         BOOST_CHECK_EQUAL (i->to, sub::Time::from_hms (0, 1, 58, 955));
209         BOOST_CHECK_EQUAL (i->lines.size(), 1);
210         BOOST_CHECK_EQUAL (i->lines.front().blocks.front().text, "Shall I compare thee to a summers' day?");
211
212         ++i;
213         BOOST_CHECK (i != subs.end ());
214         BOOST_CHECK_EQUAL (i->from, sub::Time::from_hms (0, 2, 0, 840));
215         BOOST_CHECK_EQUAL (i->to, sub::Time::from_hms (0, 2, 3, 400));
216         BOOST_CHECK_EQUAL (i->lines.size(), 1);
217         BOOST_CHECK_EQUAL (i->lines.front().blocks.front().text, "Is this a dagger I see before me?");
218
219         ++i;
220         BOOST_CHECK (i != subs.end ());
221         BOOST_CHECK_EQUAL (i->from, sub::Time::from_hms (0, 3, 54, 560));
222         BOOST_CHECK_EQUAL (i->to, sub::Time::from_hms (0, 3, 56, 471));
223         BOOST_CHECK_EQUAL (i->lines.size(), 1);
224         BOOST_CHECK_EQUAL (i->lines.front().blocks.front().text, "Hello world.");
225
226         ++i;
227         BOOST_CHECK (i != subs.end ());
228         BOOST_CHECK_EQUAL (i->from, sub::Time::from_hms (0, 4, 50, 123));
229         BOOST_CHECK_EQUAL (i->to, sub::Time::from_hms (0, 4, 55, 23));
230         BOOST_CHECK_EQUAL (i->lines.size(), 2);
231         BOOST_CHECK_EQUAL (i->lines.front().blocks.front().text, "Some italics over");
232         BOOST_CHECK_EQUAL (i->lines.front().blocks.front().italic, true);
233         BOOST_CHECK_EQUAL (i->lines.back().blocks.front().text, "multiple lines");
234         BOOST_CHECK_EQUAL (i->lines.back().blocks.front().italic, true);
235
236         ++i;
237         BOOST_CHECK (i == subs.end ());
238 }
239
240 /** Test SubripReader::convert_line */
241 BOOST_AUTO_TEST_CASE (subrip_reader_convert_line_test)
242 {
243         sub::SubripReader r;
244
245         sub::RawSubtitle rs;
246         r.convert_line ("Hello world", rs);
247         BOOST_CHECK_EQUAL (r._subs.size(), 1);
248         BOOST_CHECK_EQUAL (r._subs.front().text, "Hello world");
249         r._subs.clear ();
250
251         rs = sub::RawSubtitle();
252         r.convert_line ("<b>Hello world</b>", rs);
253         BOOST_CHECK_EQUAL (r._subs.size(), 1);
254         BOOST_CHECK_EQUAL (r._subs.front().text, "Hello world");
255         BOOST_CHECK_EQUAL (r._subs.front().bold, true);
256         r._subs.clear ();
257
258         rs = sub::RawSubtitle();
259         r.convert_line ("<i>Hello world</i>", rs);
260         BOOST_CHECK_EQUAL (r._subs.size(), 1);
261         BOOST_CHECK_EQUAL (r._subs.front().text, "Hello world");
262         BOOST_CHECK_EQUAL (r._subs.front().italic, true);
263         r._subs.clear ();
264
265         rs = sub::RawSubtitle();
266         r.convert_line ("<u>Hello world</u>", rs);
267         BOOST_CHECK_EQUAL (r._subs.size(), 1);
268         BOOST_CHECK_EQUAL (r._subs.front().text, "Hello world");
269         BOOST_CHECK_EQUAL (r._subs.front().underline, true);
270         r._subs.clear ();
271
272         rs = sub::RawSubtitle();
273         r.convert_line ("{b}Hello world{/b}", rs);
274         BOOST_CHECK_EQUAL (r._subs.size(), 1);
275         BOOST_CHECK_EQUAL (r._subs.front().text, "Hello world");
276         BOOST_CHECK_EQUAL (r._subs.front().bold, true);
277         r._subs.clear ();
278
279         rs = sub::RawSubtitle();
280         r.convert_line ("{i}Hello world{/i}", rs);
281         BOOST_CHECK_EQUAL (r._subs.size(), 1);
282         BOOST_CHECK_EQUAL (r._subs.front().text, "Hello world");
283         BOOST_CHECK_EQUAL (r._subs.front().italic, true);
284         r._subs.clear ();
285
286         rs = sub::RawSubtitle();
287         r.convert_line ("{u}Hello world{/u}", rs);
288         BOOST_CHECK_EQUAL (r._subs.size(), 1);
289         BOOST_CHECK_EQUAL (r._subs.front().text, "Hello world");
290         BOOST_CHECK_EQUAL (r._subs.front().underline, true);
291         r._subs.clear ();
292
293         rs = sub::RawSubtitle();
294         r.convert_line ("<b>This is <i>nesting</i> of subtitles</b>", rs);
295         BOOST_CHECK_EQUAL (r._subs.size(), 3);
296         list<sub::RawSubtitle>::iterator i = r._subs.begin ();
297         BOOST_CHECK_EQUAL (i->text, "This is ");
298         BOOST_CHECK_EQUAL (i->bold, true);
299         BOOST_CHECK_EQUAL (i->italic, false);
300         ++i;
301         BOOST_CHECK_EQUAL (i->text, "nesting");
302         BOOST_CHECK_EQUAL (i->bold, true);
303         BOOST_CHECK_EQUAL (i->italic, true);
304         ++i;
305         BOOST_CHECK_EQUAL (i->text, " of subtitles");
306         BOOST_CHECK_EQUAL (i->bold, true);
307         BOOST_CHECK_EQUAL (i->italic, false);
308         ++i;
309         r._subs.clear ();
310
311         rs = sub::RawSubtitle();
312         r.convert_line ("<font color=\"#ff00ff\">simple color</font>", rs);
313         BOOST_CHECK_EQUAL (r._subs.size(), 1);
314         BOOST_CHECK_EQUAL (r._subs.front().text, "simple color");
315         BOOST_CHECK_EQUAL (r._subs.front().bold, false);
316         BOOST_CHECK_CLOSE (r._subs.front().colour.r, 1, 0.1);
317         BOOST_CHECK (fabs (r._subs.front().colour.g) < 0.01);
318         BOOST_CHECK_CLOSE (r._subs.front().colour.b, 1, 0.1);
319         r._subs.clear ();
320
321         rs = sub::RawSubtitle();
322         r.convert_line ("<font color=\"#FF00FF\">simple color in capitals</font>", rs);
323         BOOST_CHECK_EQUAL (r._subs.size(), 1);
324         BOOST_CHECK_EQUAL (r._subs.front().text, "simple color in capitals");
325         BOOST_CHECK_EQUAL (r._subs.front().bold, false);
326         BOOST_CHECK_CLOSE (r._subs.front().colour.r, 1, 0.1);
327         BOOST_CHECK (fabs (r._subs.front().colour.g) < 0.01);
328         BOOST_CHECK_CLOSE (r._subs.front().colour.b, 1, 0.1);
329         r._subs.clear ();
330
331         rs = sub::RawSubtitle();
332         r.convert_line ("<font color=\"#ff0000\">some red text <b>in bold</b></font>", rs);
333         BOOST_CHECK_EQUAL (r._subs.size(), 2);
334         i = r._subs.begin ();
335         BOOST_CHECK_EQUAL (i->text, "some red text ");
336         BOOST_CHECK_EQUAL (i->bold, false);
337         BOOST_CHECK_CLOSE (i->colour.r, 1, 0.1);
338         BOOST_CHECK (fabs (i->colour.g) < 0.01);
339         BOOST_CHECK (fabs (i->colour.b) < 0.01);
340         ++i;
341         BOOST_CHECK_EQUAL (i->text, "in bold");
342         BOOST_CHECK_EQUAL (i->bold, true);
343         BOOST_CHECK_CLOSE (i->colour.r, 1, 0.1);
344         BOOST_CHECK (fabs (i->colour.g) < 0.01);
345         BOOST_CHECK (fabs (i->colour.b) < 0.01);
346         r._subs.clear ();
347
348         rs = sub::RawSubtitle();
349         r.convert_line ("<Font color=\"#ff0000\">some red text <b>in bold</b></font>", rs);
350         BOOST_CHECK_EQUAL (r._subs.size(), 2);
351         i = r._subs.begin ();
352         BOOST_CHECK_EQUAL (i->text, "some red text ");
353         BOOST_CHECK_EQUAL (i->bold, false);
354         BOOST_CHECK_CLOSE (i->colour.r, 1, 0.1);
355         BOOST_CHECK (fabs (i->colour.g) < 0.01);
356         BOOST_CHECK (fabs (i->colour.b) < 0.01);
357         ++i;
358         BOOST_CHECK_EQUAL (i->text, "in bold");
359         BOOST_CHECK_EQUAL (i->bold, true);
360         BOOST_CHECK_CLOSE (i->colour.r, 1, 0.1);
361         BOOST_CHECK (fabs (i->colour.g) < 0.01);
362         BOOST_CHECK (fabs (i->colour.b) < 0.01);
363         r._subs.clear ();
364
365         rs = sub::RawSubtitle();
366         r.convert_line ("<font color=\"#0000ff\">some blue text <b>in bold</b></font>", rs);
367         BOOST_CHECK_EQUAL (r._subs.size(), 2);
368         i = r._subs.begin ();
369         BOOST_CHECK_EQUAL (i->text, "some blue text ");
370         BOOST_CHECK_EQUAL (i->bold, false);
371         BOOST_CHECK (fabs (i->colour.r) < 0.01);
372         BOOST_CHECK (fabs (i->colour.g) < 0.01);
373         BOOST_CHECK_CLOSE (i->colour.b, 1, 0.1);
374         ++i;
375         BOOST_CHECK_EQUAL (i->text, "in bold");
376         BOOST_CHECK_EQUAL (i->bold, true);
377         BOOST_CHECK (fabs (i->colour.r) < 0.01);
378         BOOST_CHECK (fabs (i->colour.g) < 0.01);
379         BOOST_CHECK_CLOSE (i->colour.b, 1, 0.1);
380         r._subs.clear ();
381 }
382
383 /** Test SubripReader::convert_time */
384 BOOST_AUTO_TEST_CASE (subrip_reader_convert_time_test)
385 {
386         sub::SubripReader reader;
387         BOOST_CHECK_EQUAL (reader.convert_time ("00:03:10,500"), sub::Time::from_hms (0, 3, 10, 500));
388         BOOST_CHECK_EQUAL (reader.convert_time ("04:19:51,782"), sub::Time::from_hms (4, 19, 51, 782));
389 }
390
391 static void
392 test (boost::filesystem::path p)
393 {
394         p = private_test / p;
395         FILE* f = fopen (p.string().c_str(), "r");
396         BOOST_CHECK (f);
397         if (!f) {
398                 cerr << p << " not found.\n";
399                 return;
400         }
401         sub::SubripReader r (f);
402         fclose (f);
403 }
404
405 static void
406 test_throw (boost::filesystem::path p)
407 {
408         p = private_test / p;
409         FILE* f = fopen (p.string().c_str(), "r");
410         BOOST_CHECK (f);
411         if (!f) {
412                 cerr << p << " not found.\n";
413                 return;
414         }
415         BOOST_CHECK_THROW (sub::SubripReader r(f), sub::SubripError);
416         fclose (f);
417 }
418
419 /** Test of reading some typical .srt files */
420 BOOST_AUTO_TEST_CASE (subrip_read_test)
421 {
422         test ("sintel_en.srt");
423         test ("sintel_fr.srt");
424         test ("FC.srt");
425         test ("EU13.srt");
426         test ("Subtitulos_H_eng.srt");
427         test ("SWING.srt");
428         test_throw ("subtitulo1.srt");
429 }
430
431 #define SUB_START(f, t) \
432         BOOST_REQUIRE (i != subs.end ()); \
433         BOOST_CHECK_EQUAL (i->from, f); \
434         BOOST_CHECK_EQUAL (i->to, t); \
435         j = i->lines.begin ();
436
437 #define LINE(p)                                                 \
438         BOOST_REQUIRE (j != i->lines.end ()); \
439         BOOST_CHECK (j->vertical_position.line); \
440         BOOST_CHECK_EQUAL (j->vertical_position.line.get(), p); \
441         BOOST_CHECK (j->vertical_position.reference); \
442         BOOST_CHECK_EQUAL (j->vertical_position.reference.get(), sub::TOP_OF_SUBTITLE); \
443         k = j->blocks.begin (); \
444         ++j;
445
446 #define BLOCK(t, f, s, b, i, u) \
447         BOOST_REQUIRE (k != j->blocks.end ()); \
448         BOOST_CHECK_EQUAL (k->text, t); \
449         BOOST_CHECK_EQUAL (k->bold, b); \
450         BOOST_CHECK_EQUAL (k->italic, i); \
451         BOOST_CHECK_EQUAL (k->underline, u); \
452         ++k;
453
454 #define SUB_END() \
455         ++i;
456
457 /** Test reading of another .srt file */
458 BOOST_AUTO_TEST_CASE (subrip_reader_test3)
459 {
460         boost::filesystem::path p = private_test / "DCP-o-matic_test_subs_1.srt";
461         FILE* f = fopen (p.string().c_str(), "r");
462         sub::SubripReader reader (f);
463         fclose (f);
464         list<sub::Subtitle> subs = sub::collect<std::list<sub::Subtitle> > (reader.subtitles ());
465
466         list<sub::Subtitle>::iterator i = subs.begin ();
467         list<sub::Line>::iterator j;
468         list<sub::Block>::iterator k;
469
470         BOOST_REQUIRE (i != subs.end ());
471
472         SUB_START (sub::Time::from_hms (0, 0, 0, 76), sub::Time::from_hms (0, 0, 1, 116));
473         LINE (0);
474         BLOCK ("This line is normal", "Arial", 30, false, false, false);
475         LINE (1);
476         BLOCK ("This line is bold", "Arial", 30, true, false, false);
477         SUB_END ();
478
479         SUB_START (sub::Time::from_hms (0, 0, 1, 206), sub::Time::from_hms (0, 0, 2, 246));
480         LINE (0);
481         BLOCK ("This line is bold", "Arial", 30, true, false, false);
482         LINE (1);
483         BLOCK ("This line is normal", "Arial", 30, false, false, false);
484         SUB_END ();
485
486         SUB_START (sub::Time::from_hms (0, 0, 2, 308), sub::Time::from_hms (0, 0, 3, 380));
487         LINE (0);
488         BLOCK ("This line is bold", "Arial", 30, true, false, false);
489         LINE (1);
490         BLOCK ("This line is italic", "Arial", 30, false, true, false);
491         SUB_END ();
492
493         SUB_START (sub::Time::from_hms (0, 0, 3, 404), sub::Time::from_hms (0, 0, 4, 484));
494         LINE (0);
495         BLOCK ("This line is italic", "Arial", 30, false, true, false);
496         LINE (1);
497         BLOCK ("This line is bold", "Arial", 30, true, false, false);
498         SUB_END ();
499
500         SUB_START (sub::Time::from_hms (0, 0, 4, 519), sub::Time::from_hms (0, 0, 5, 604));
501         LINE (0);
502         BLOCK ("Last three words are ", "Arial", 30, false, false, false);
503         BLOCK ("bold AND italic", "Arial", 30, true, true, false);
504         LINE (1);
505         BLOCK ("Last three words are ", "Arial", 30, false, false, false);
506         BLOCK ("italic AND bold", "Arial", 30, true, true, false);
507         SUB_END ();
508
509         SUB_START (sub::Time::from_hms (0, 0, 5, 628), sub::Time::from_hms (0, 0, 6, 712));
510         LINE (0);
511         BLOCK ("Last three words are ", "Arial", 30, false, false, false);
512         BLOCK ("bold AND italic", "Arial", 30, true, true, false);
513         LINE (1);
514         BLOCK ("First three words", "Arial", 30, true, true, false);
515         BLOCK (" are italic AND bold", "Arial", 30, false, false, false);
516         SUB_END ();
517
518         SUB_START (sub::Time::from_hms (0, 0, 6, 736), sub::Time::from_hms (0, 0, 8, 31));
519         LINE (0);
520         BLOCK ("Last three words are ", "Arial", 30, false, false, false);
521         BLOCK ("bold AND italic", "Arial", 30, true, true, false);
522         LINE (1);
523         BLOCK ("This line is normal", "Arial", 30, false, false, false);
524         SUB_END ();
525
526         SUB_START (sub::Time::from_hms (0, 0, 8, 94), sub::Time::from_hms (0, 0, 9, 211));
527         LINE (0);
528         BLOCK ("Both lines are bold AND italic", "Arial", 30, true, true, false);
529         LINE (1);
530         BLOCK ("Both lines are bold AND italic", "Arial", 30, true, true, false);
531         SUB_END ();
532 }
533
534 /** Test reading of a .srt file with RTL text */
535 BOOST_AUTO_TEST_CASE (subrip_reader_test4)
536 {
537         boost::filesystem::path p = private_test / "rtl.srt";
538         FILE* f = fopen (p.string().c_str(), "r");
539         sub::SubripReader reader (f);
540         fclose (f);
541         list<sub::Subtitle> subs = sub::collect<std::list<sub::Subtitle> >(reader.subtitles());
542
543         list<sub::Subtitle>::iterator i = subs.begin ();
544         std::cout << i->lines.front().blocks.front().text << "\n";
545
546         std::string const t = i->lines.front().blocks.front().text;
547         for (size_t i = 0; i < t.length() - 2; ++i) {
548                 /* Check that unicode U+202B (right-to-left embedding) has been stripped */
549                 unsigned char const a = t[i];
550                 unsigned char const b = t[i+1];
551                 unsigned char const c = t[i+2];
552                 BOOST_CHECK ((a != 0xe2 || b != 0x80 || c != 0xab));
553         }
554
555         BOOST_CHECK (t == "- \"(دريه فابينار)\"");
556 }
557
558 /** Test <font color="rgba(255,255,255,255)"> */
559 BOOST_AUTO_TEST_CASE (subrip_reader_test5)
560 {
561         sub::RawSubtitle rs;
562         sub::SubripReader r;
563         r.convert_line ("<font color=\"rgba(255,128,64,15)\">Foo bar</font>", rs);
564         BOOST_REQUIRE_EQUAL (r._subs.size(), 1);
565         BOOST_CHECK_EQUAL (r._subs.front().text, "Foo bar");
566         BOOST_CHECK_CLOSE (r._subs.front().colour.r, 255.0 / 255, 0.1);
567         BOOST_CHECK_CLOSE (r._subs.front().colour.g, 128.0 / 255, 0.1);
568         BOOST_CHECK_CLOSE (r._subs.front().colour.b, 64.0 / 255, 0.1);
569         r._subs.clear ();
570
571         rs = sub::RawSubtitle ();
572         r.convert_line ("<font color=\"rgba(1, 2 , 3, 4)\">Foo bar</font>", rs);
573         BOOST_REQUIRE_EQUAL (r._subs.size(), 1);
574         BOOST_CHECK_EQUAL (r._subs.front().text, "Foo bar");
575         BOOST_CHECK_CLOSE (r._subs.front().colour.r, 1.0 / 255, 0.1);
576         BOOST_CHECK_CLOSE (r._subs.front().colour.g, 2.0 / 255, 0.1);
577         BOOST_CHECK_CLOSE (r._subs.front().colour.b, 3.0 / 255, 0.1);
578 }
579
580 /** Test alignment */
581 BOOST_AUTO_TEST_CASE (subrip_reader_test6)
582 {
583         sub::RawSubtitle rs;
584         rs.vertical_position.line = 0;
585         rs.vertical_position.reference = sub::TOP_OF_SUBTITLE;
586         sub::SubripReader r;
587         r.convert_line ("Hello world", rs);
588         BOOST_REQUIRE_EQUAL (r._subs.size(), 1);
589         BOOST_CHECK_EQUAL (r._subs.front().text, "Hello world");
590         BOOST_REQUIRE (r._subs.front().vertical_position.line);
591         BOOST_CHECK_EQUAL (r._subs.front().vertical_position.line.get(), 0);
592         BOOST_REQUIRE (r._subs.front().vertical_position.reference);
593         BOOST_CHECK_EQUAL (r._subs.front().vertical_position.reference.get(), sub::TOP_OF_SUBTITLE);
594         r._subs.clear ();
595
596         rs = sub::RawSubtitle ();
597         rs.vertical_position.line = 0;
598         r.convert_line ("{\\an1}Hello", rs);
599         BOOST_REQUIRE_EQUAL (r._subs.size(), 1);
600         BOOST_CHECK_EQUAL (r._subs.front().text, "Hello");
601         BOOST_REQUIRE (r._subs.front().vertical_position.line);
602         BOOST_CHECK_EQUAL (r._subs.front().vertical_position.line.get(), 0);
603         BOOST_REQUIRE (r._subs.front().vertical_position.reference);
604         BOOST_CHECK_EQUAL (r._subs.front().vertical_position.reference.get(), sub::BOTTOM_OF_SCREEN);
605         BOOST_CHECK_EQUAL (r._subs.front().horizontal_position.proportional, 0);
606         BOOST_CHECK_EQUAL (r._subs.front().horizontal_position.reference, sub::LEFT_OF_SCREEN);
607         r._subs.clear ();
608
609         rs = sub::RawSubtitle ();
610         rs.vertical_position.line = 0;
611         r.convert_line ("{\\an2}to", rs);
612         BOOST_REQUIRE_EQUAL (r._subs.size(), 1);
613         BOOST_CHECK_EQUAL (r._subs.front().text, "to");
614         BOOST_REQUIRE (r._subs.front().vertical_position.line);
615         BOOST_CHECK_EQUAL (r._subs.front().vertical_position.line.get(), 0);
616         BOOST_REQUIRE (r._subs.front().vertical_position.reference);
617         BOOST_CHECK_EQUAL (r._subs.front().vertical_position.reference.get(), sub::BOTTOM_OF_SCREEN);
618         BOOST_CHECK_EQUAL (r._subs.front().horizontal_position.proportional, 0);
619         BOOST_CHECK_EQUAL (r._subs.front().horizontal_position.reference, sub::HORIZONTAL_CENTRE_OF_SCREEN);
620         r._subs.clear ();
621
622         rs = sub::RawSubtitle ();
623         rs.vertical_position.line = 0;
624         r.convert_line ("{\\an3}you", rs);
625         BOOST_CHECK_EQUAL (r._subs.front().text, "you");
626         BOOST_REQUIRE (r._subs.front().vertical_position.line);
627         BOOST_CHECK_EQUAL (r._subs.front().vertical_position.line.get(), 0);
628         BOOST_REQUIRE (r._subs.front().vertical_position.reference);
629         BOOST_CHECK_EQUAL (r._subs.front().vertical_position.reference.get(), sub::BOTTOM_OF_SCREEN);
630         BOOST_CHECK_EQUAL (r._subs.front().horizontal_position.proportional, 0);
631         BOOST_CHECK_EQUAL (r._subs.front().horizontal_position.reference, sub::RIGHT_OF_SCREEN);
632         r._subs.clear ();
633 }
634