CENTRE_OF_SCREEN -> VERTICAL_CENTRE_OF_SCREEN.
[libsub.git] / src / stl_text_reader.cc
1 /*
2     Copyright (C) 2014-2016 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 "stl_text_reader.h"
21 #include "compose.hpp"
22 #include <boost/algorithm/string.hpp>
23 #include <boost/lexical_cast.hpp>
24 #include <vector>
25 #include <iostream>
26
27 using std::list;
28 using std::ostream;
29 using std::istream;
30 using std::string;
31 using std::vector;
32 using std::cout;
33 using boost::algorithm::trim;
34 using boost::algorithm::starts_with;
35 using boost::is_any_of;
36 using boost::optional;
37 using boost::lexical_cast;
38 using namespace sub;
39
40 STLTextReader::STLTextReader (istream& in)
41 {
42         /* This reader extracts no information about where the subtitle
43            should be on screen, so its reference is TOP_OF_SUBTITLE.
44         */
45         _subtitle.vertical_position.line = 0;
46         _subtitle.vertical_position.reference = TOP_OF_SUBTITLE;
47
48         while (in.good ()) {
49                 string line;
50                 getline (in, line);
51                 if (!in.good ()) {
52                         return;
53                 }
54
55                 trim (line);
56
57                 if (starts_with (line, "//")) {
58                         continue;
59                 }
60
61                 if (line.size() > 0 && line[0] == '$') {
62                         /* $ variables */
63                         vector<string> bits;
64                         split (bits, line, is_any_of ("="));
65                         if (bits.size() == 2) {
66                                 string name = bits[0];
67                                 trim (name);
68                                 string value = bits[1];
69                                 trim (value);
70
71                                 set (name, value);
72                         } else {
73                                 warn (String::compose ("Unrecognised line %1", line));
74                         }
75                 } else {
76                         /* "Normal" lines */
77                         size_t divider[2];
78                         divider[0] = line.find_first_of (",");
79                         if (divider[0] != string::npos) {
80                                 divider[1] = line.find_first_of (",", divider[0] + 1);
81                         }
82
83                         if (divider[0] == string::npos || divider[1] == string::npos || divider[0] <= 1 || divider[1] >= line.length() - 1) {
84                                 warn (String::compose ("Unrecognised line %1", line));
85                                 continue;
86                         }
87
88                         string from_string = line.substr (0, divider[0] - 1);
89                         trim (from_string);
90                         string to_string = line.substr (divider[0] + 1, divider[1] - divider[0] - 1);
91                         trim (to_string);
92
93                         optional<Time> from = time (from_string);
94                         optional<Time> to = time (to_string);
95
96                         if (!from || !to) {
97                                 warn (String::compose ("Unrecognised line %1", line));
98                                 continue;
99                         }
100
101                         _subtitle.from = from.get ();
102                         _subtitle.to = to.get ();
103
104                         /* Parse ^B/^I/^U */
105                         string text = line.substr (divider[1] + 1);
106                         for (size_t i = 0; i < text.length(); ++i) {
107                                 if (text[i] == '|') {
108                                         maybe_push ();
109                                         _subtitle.vertical_position.line = _subtitle.vertical_position.line.get() + 1;
110                                 } else if (text[i] == '^') {
111                                         maybe_push ();
112                                         if ((i + 1) < text.length()) {
113                                                 switch (text[i + 1]) {
114                                                 case 'B':
115                                                         _subtitle.bold = !_subtitle.bold;
116                                                         break;
117                                                 case 'I':
118                                                         _subtitle.italic = !_subtitle.italic;
119                                                         break;
120                                                 case 'U':
121                                                         _subtitle.underline = !_subtitle.underline;
122                                                         break;
123                                                 }
124                                         }
125                                         ++i;
126                                 } else {
127                                         _subtitle.text += text[i];
128                                 }
129                         }
130
131                         maybe_push ();
132                 }
133         }
134 }
135
136 optional<Time>
137 STLTextReader::time (string t) const
138 {
139         vector<string> b;
140         split (b, t, is_any_of (":"));
141         if (b.size() != 4) {
142                 warn (String::compose ("Unrecognised time %1", t));
143                 return optional<Time> ();
144         }
145
146         return sub::Time::from_hmsf (lexical_cast<int> (b[0]), lexical_cast<int> (b[1]), lexical_cast<int> (b[2]), lexical_cast<int> (b[3]));
147 }
148
149 void
150 STLTextReader::set (string name, string value)
151 {
152         if (name == "$FontName") {
153                 _subtitle.font = value;
154         } else if (name == "$Bold") {
155                 _subtitle.bold = value == "True";
156         } else if (name == "$Italic") {
157                 _subtitle.italic = value == "True";
158         } else if (name == "$Underlined") {
159                 _subtitle.underline = value == "True";
160         } else if (name == "$FontSize") {
161                 _subtitle.font_size.set_points (lexical_cast<int> (value));
162         }
163 }
164
165 void
166 STLTextReader::maybe_push ()
167 {
168         if (!_subtitle.text.empty ()) {
169                 _subs.push_back (_subtitle);
170                 _subtitle.text.clear ();
171                 _subtitle.vertical_position.line = 0;
172         }
173 }