Basics of subtitle rendering.
[dcpomatic.git] / test / subrip_test.cc
1 /*
2     Copyright (C) 2014 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 <boost/test/unit_test.hpp>
21 #include <libdcp/subtitle_asset.h>
22 #include "lib/subrip.h"
23 #include "lib/subrip_content.h"
24 #include "lib/subrip_decoder.h"
25 #include "lib/render_subtitles.h"
26 #include "test.h"
27
28 using std::list;
29 using std::vector;
30 using std::string;
31 using boost::shared_ptr;
32
33 /** Test SubRip::convert_time */
34 BOOST_AUTO_TEST_CASE (subrip_time_test)
35 {
36         BOOST_CHECK_EQUAL (SubRip::convert_time ("00:03:10,500"), rint (((3 * 60) + 10 + 0.5) * TIME_HZ));
37         BOOST_CHECK_EQUAL (SubRip::convert_time ("04:19:51,782"), rint (((4 * 3600) + (19 * 60) + 51 + 0.782) * TIME_HZ));
38 }
39
40 /** Test SubRip::convert_coordinate */
41 BOOST_AUTO_TEST_CASE (subrip_coordinate_test)
42 {
43         BOOST_CHECK_EQUAL (SubRip::convert_coordinate ("foo:42"), 42);
44         BOOST_CHECK_EQUAL (SubRip::convert_coordinate ("X1:999"), 999);
45 }
46
47 /** Test SubRip::convert_content */
48 BOOST_AUTO_TEST_CASE (subrip_content_test)
49 {
50         list<string> c;
51         list<SubRipSubtitlePiece> p;
52         
53         c.push_back ("Hello world");
54         p = SubRip::convert_content (c);
55         BOOST_CHECK_EQUAL (p.size(), 1);
56         BOOST_CHECK_EQUAL (p.front().text, "Hello world");
57         c.clear ();
58
59         c.push_back ("<b>Hello world</b>");
60         p = SubRip::convert_content (c);
61         BOOST_CHECK_EQUAL (p.size(), 1);
62         BOOST_CHECK_EQUAL (p.front().text, "Hello world");
63         BOOST_CHECK_EQUAL (p.front().bold, true);
64         c.clear ();
65
66         c.push_back ("<i>Hello world</i>");
67         p = SubRip::convert_content (c);
68         BOOST_CHECK_EQUAL (p.size(), 1);
69         BOOST_CHECK_EQUAL (p.front().text, "Hello world");
70         BOOST_CHECK_EQUAL (p.front().italic, true);
71         c.clear ();
72
73         c.push_back ("<u>Hello world</u>");
74         p = SubRip::convert_content (c);
75         BOOST_CHECK_EQUAL (p.size(), 1);
76         BOOST_CHECK_EQUAL (p.front().text, "Hello world");
77         BOOST_CHECK_EQUAL (p.front().underline, true);
78         c.clear ();
79
80         c.push_back ("{b}Hello world{/b}");
81         p = SubRip::convert_content (c);
82         BOOST_CHECK_EQUAL (p.size(), 1);
83         BOOST_CHECK_EQUAL (p.front().text, "Hello world");
84         BOOST_CHECK_EQUAL (p.front().bold, true);
85         c.clear ();
86
87         c.push_back ("{i}Hello world{/i}");
88         p = SubRip::convert_content (c);
89         BOOST_CHECK_EQUAL (p.size(), 1);
90         BOOST_CHECK_EQUAL (p.front().text, "Hello world");
91         BOOST_CHECK_EQUAL (p.front().italic, true);
92         c.clear ();
93
94         c.push_back ("{u}Hello world{/u}");
95         p = SubRip::convert_content (c);
96         BOOST_CHECK_EQUAL (p.size(), 1);
97         BOOST_CHECK_EQUAL (p.front().text, "Hello world");
98         BOOST_CHECK_EQUAL (p.front().underline, true);
99         c.clear ();
100
101         c.push_back ("<b>This is <i>nesting</i> of subtitles</b>");
102         p = SubRip::convert_content (c);
103         BOOST_CHECK_EQUAL (p.size(), 3);
104         list<SubRipSubtitlePiece>::iterator i = p.begin ();     
105         BOOST_CHECK_EQUAL (i->text, "This is ");
106         BOOST_CHECK_EQUAL (i->bold, true);
107         BOOST_CHECK_EQUAL (i->italic, false);
108         ++i;
109         BOOST_CHECK_EQUAL (i->text, "nesting");
110         BOOST_CHECK_EQUAL (i->bold, true);
111         BOOST_CHECK_EQUAL (i->italic, true);
112         ++i;
113         BOOST_CHECK_EQUAL (i->text, " of subtitles");
114         BOOST_CHECK_EQUAL (i->bold, true);
115         BOOST_CHECK_EQUAL (i->italic, false);
116         ++i;
117         c.clear ();
118 }
119
120 /** Test parsing of full SubRip file content */
121 BOOST_AUTO_TEST_CASE (subrip_parse_test)
122 {
123         shared_ptr<SubRipContent> content (new SubRipContent (shared_ptr<Film> (), "test/data/subrip.srt"));
124         content->examine (shared_ptr<Job> ());
125         BOOST_CHECK_EQUAL (content->full_length(), ((3 * 60) + 56.471) * TIME_HZ);
126
127         SubRip s (content);
128
129         vector<SubRipSubtitle>::const_iterator i = s._subtitles.begin();
130
131         BOOST_CHECK (i != s._subtitles.end ());
132         BOOST_CHECK_EQUAL (i->from, ((1 * 60) + 49.200) * TIME_HZ);
133         BOOST_CHECK_EQUAL (i->to, ((1 * 60) + 52.351) * TIME_HZ);
134         BOOST_CHECK_EQUAL (i->pieces.size(), 1);
135         BOOST_CHECK_EQUAL (i->pieces.front().text, "This is a subtitle, and it goes over two lines.");
136
137         ++i;
138         BOOST_CHECK (i != s._subtitles.end ());
139         BOOST_CHECK_EQUAL (i->from, ((1 * 60) + 52.440) * TIME_HZ);
140         BOOST_CHECK_EQUAL (i->to, ((1 * 60) + 54.351) * TIME_HZ);
141         BOOST_CHECK_EQUAL (i->pieces.size(), 1);
142         BOOST_CHECK_EQUAL (i->pieces.front().text, "We have emboldened this");
143         BOOST_CHECK_EQUAL (i->pieces.front().bold, true);
144
145         ++i;
146         BOOST_CHECK (i != s._subtitles.end ());
147         BOOST_CHECK_EQUAL (i->from, ((1 * 60) + 54.440) * TIME_HZ);
148         BOOST_CHECK_EQUAL (i->to, ((1 * 60) + 56.590) * TIME_HZ);
149         BOOST_CHECK_EQUAL (i->pieces.size(), 1);
150         BOOST_CHECK_EQUAL (i->pieces.front().text, "And italicised this.");
151         BOOST_CHECK_EQUAL (i->pieces.front().italic, true);
152
153         ++i;
154         BOOST_CHECK (i != s._subtitles.end ());
155         BOOST_CHECK_EQUAL (i->from, ((1 * 60) + 56.680) * TIME_HZ);
156         BOOST_CHECK_EQUAL (i->to, ((1 * 60) + 58.955) * TIME_HZ);
157         BOOST_CHECK_EQUAL (i->pieces.size(), 1);
158         BOOST_CHECK_EQUAL (i->pieces.front().text, "Shall I compare thee to a summers' day?");
159
160         ++i;
161         BOOST_CHECK (i != s._subtitles.end ());
162         BOOST_CHECK_EQUAL (i->from, ((2 * 60) + 0.840) * TIME_HZ);
163         BOOST_CHECK_EQUAL (i->to, ((2 * 60) + 3.400) * TIME_HZ);
164         BOOST_CHECK_EQUAL (i->pieces.size(), 1);
165         BOOST_CHECK_EQUAL (i->pieces.front().text, "Is this a dagger I see before me?");
166
167         ++i;
168         BOOST_CHECK (i != s._subtitles.end ());
169         BOOST_CHECK_EQUAL (i->from, ((3 * 60) + 54.560) * TIME_HZ);
170         BOOST_CHECK_EQUAL (i->to, ((3 * 60) + 56.471) * TIME_HZ);
171         BOOST_CHECK_EQUAL (i->pieces.size(), 1);
172         BOOST_CHECK_EQUAL (i->pieces.front().text, "Hello world.");
173
174         ++i;
175         BOOST_CHECK (i == s._subtitles.end ());
176 }
177
178 static list<libdcp::Subtitle> subtitles;
179
180 static void
181 process_subtitle (list<libdcp::Subtitle> s)
182 {
183         subtitles = s;
184 }
185
186
187 /** Test rendering of a SubRip subtitle */
188 BOOST_AUTO_TEST_CASE (subrip_render_test)
189 {
190         shared_ptr<SubRipContent> content (new SubRipContent (shared_ptr<Film> (), "test/data/subrip.srt"));
191         content->examine (shared_ptr<Job> ());
192         BOOST_CHECK_EQUAL (content->full_length(), ((3 * 60) + 56.471) * TIME_HZ);
193
194         shared_ptr<Film> film = new_test_film ("subrip_render_test");
195
196         shared_ptr<SubRipDecoder> decoder (new SubRipDecoder (film, content));
197         decoder->TextSubtitle.connect (boost::bind (&process_subtitle, _1));
198         decoder->pass ();
199
200         shared_ptr<Image> image;
201         Position<int> position;
202         render_subtitles (subtitles, libdcp::Size (1998, 1080), image, position);
203         write_image (image, "build/test/subrip_render_test.png");
204         check_file ("build/test/subrip_render_test.png", "test/data/subrip_render_test.png");
205 }