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