Still more licence fixups.
[libdcp.git] / src / types.cc
1 /*
2     Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
3
4     This file is part of libdcp.
5
6     libdcp is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     libdcp is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with libdcp.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "raw_convert.h"
21 #include "types.h"
22 #include "exceptions.h"
23 #include "compose.hpp"
24 #include <boost/algorithm/string.hpp>
25 #include <vector>
26 #include <cstdio>
27 #include <iomanip>
28
29 using namespace std;
30 using namespace dcp;
31 using namespace boost;
32
33 /** Construct a Fraction from a string of the form <numerator> <denominator>
34  *  e.g. "1 3".
35  */
36 Fraction::Fraction (string s)
37 {
38         vector<string> b;
39         split (b, s, is_any_of (" "));
40         if (b.size() != 2) {
41                 boost::throw_exception (XMLError ("malformed fraction " + s + " in XML node"));
42         }
43         numerator = raw_convert<int> (b[0]);
44         denominator = raw_convert<int> (b[1]);
45 }
46
47 string
48 Fraction::as_string () const
49 {
50         return String::compose ("%1 %2", numerator, denominator);
51 }
52
53 bool
54 dcp::operator== (Fraction const & a, Fraction const & b)
55 {
56         return (a.numerator == b.numerator && a.denominator == b.denominator);
57 }
58
59 bool
60 dcp::operator!= (Fraction const & a, Fraction const & b)
61 {
62         return (a.numerator != b.numerator || a.denominator != b.denominator);
63 }
64
65 ostream&
66 dcp::operator<< (ostream& s, Fraction const & f)
67 {
68         s << f.numerator << "/" << f.denominator;
69         return s;
70 }
71
72 /** Construct a Colour, initialising it to black. */
73 Colour::Colour ()
74         : r (0)
75         , g (0)
76         , b (0)
77 {
78
79 }
80
81 /** Construct a Colour from R, G and B.  The values run between
82  *  0 and 255.
83  */
84 Colour::Colour (int r_, int g_, int b_)
85         : r (r_)
86         , g (g_)
87         , b (b_)
88 {
89
90 }
91
92 /** Construct a Colour from an ARGB hex string; the alpha value is ignored.
93  *  @param argb_hex A string of the form AARRGGBB, where e.g. RR is a two-character
94  *  hex value.
95  */
96 Colour::Colour (string argb_hex)
97 {
98         int alpha;
99         if (sscanf (argb_hex.c_str(), "%2x%2x%2x%2x", &alpha, &r, &g, &b) != 4) {
100                 boost::throw_exception (XMLError ("could not parse colour string"));
101         }
102 }
103
104 /** @return An ARGB string of the form AARRGGBB, where e.g. RR is a two-character
105  *  hex value.  The alpha value will always be FF (ie 255; maximum alpha).
106  */
107 string
108 Colour::to_argb_string () const
109 {
110         stringstream s;
111         s << "FF";
112         s << hex
113           << setw(2) << setfill('0') << r
114           << setw(2) << setfill('0') << g
115           << setw(2) << setfill('0') << b;
116
117         string t = s.str();
118         to_upper (t);
119         return t;
120 }
121
122 /** operator== for Colours.
123  *  @param a First colour to compare.
124  *  @param b Second colour to compare.
125  */
126 bool
127 dcp::operator== (Colour const & a, Colour const & b)
128 {
129         return (a.r == b.r && a.g == b.g && a.b == b.b);
130 }
131
132 /** operator!= for Colours.
133  *  @param a First colour to compare.
134  *  @param b Second colour to compare.
135  */
136 bool
137 dcp::operator!= (Colour const & a, Colour const & b)
138 {
139         return !(a == b);
140 }
141
142 ostream &
143 dcp::operator<< (ostream& s, Colour const & c)
144 {
145         s << "(" << c.r << ", " << c.g << ", " << c.b << ")";
146         return s;
147 }
148
149 string
150 dcp::effect_to_string (Effect e)
151 {
152         switch (e) {
153         case NONE:
154                 return "none";
155         case BORDER:
156                 return "border";
157         case SHADOW:
158                 return "shadow";
159         }
160
161         boost::throw_exception (MiscError ("unknown effect type"));
162 }
163
164 Effect
165 dcp::string_to_effect (string s)
166 {
167         if (s == "none") {
168                 return NONE;
169         } else if (s == "border") {
170                 return BORDER;
171         } else if (s == "shadow") {
172                 return SHADOW;
173         }
174
175         boost::throw_exception (DCPReadError ("unknown subtitle effect type"));
176 }
177
178 string
179 dcp::halign_to_string (HAlign h)
180 {
181         switch (h) {
182         case HALIGN_LEFT:
183                 return "left";
184         case HALIGN_CENTER:
185                 return "center";
186         case HALIGN_RIGHT:
187                 return "right";
188         }
189
190         boost::throw_exception (MiscError ("unknown subtitle halign type"));
191 }
192
193 HAlign
194 dcp::string_to_halign (string s)
195 {
196         if (s == "left") {
197                 return HALIGN_LEFT;
198         } else if (s == "center") {
199                 return HALIGN_CENTER;
200         } else if (s == "right") {
201                 return HALIGN_RIGHT;
202         }
203
204         boost::throw_exception (DCPReadError ("unknown subtitle halign type"));
205 }
206
207 string
208 dcp::valign_to_string (VAlign v)
209 {
210         switch (v) {
211         case VALIGN_TOP:
212                 return "top";
213         case VALIGN_CENTER:
214                 return "center";
215         case VALIGN_BOTTOM:
216                 return "bottom";
217         }
218
219         boost::throw_exception (MiscError ("unknown subtitle valign type"));
220 }
221
222 VAlign
223 dcp::string_to_valign (string s)
224 {
225         if (s == "top") {
226                 return VALIGN_TOP;
227         } else if (s == "center") {
228                 return VALIGN_CENTER;
229         } else if (s == "bottom") {
230                 return VALIGN_BOTTOM;
231         }
232
233         boost::throw_exception (DCPReadError ("unknown subtitle valign type"));
234 }
235
236 string
237 dcp::direction_to_string (Direction v)
238 {
239         switch (v) {
240         case DIRECTION_LTR:
241                 return "ltr";
242         case DIRECTION_RTL:
243                 return "rtl";
244         case DIRECTION_TTB:
245                 return "ttb";
246         case DIRECTION_BTT:
247                 return "btt";
248         }
249
250         boost::throw_exception (MiscError ("unknown subtitle direction type"));
251 }
252
253 Direction
254 dcp::string_to_direction (string s)
255 {
256         if (s == "ltr" || s == "horizontal") {
257                 return DIRECTION_LTR;
258         } else if (s == "rtl") {
259                 return DIRECTION_RTL;
260         } else if (s == "ttb" || s == "vertical") {
261                 return DIRECTION_TTB;
262         } else if (s == "btt") {
263                 return DIRECTION_BTT;
264         }
265
266         boost::throw_exception (DCPReadError ("unknown subtitle direction type"));
267 }