Merge master.
[libdcp.git] / src / types.cc
1 /*
2     Copyright (C) 2012-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 "raw_convert.h"
21 #include "types.h"
22 #include "exceptions.h"
23 #include <boost/algorithm/string.hpp>
24 #include <vector>
25 #include <cstdio>
26 #include <iomanip>
27
28 using namespace std;
29 using namespace dcp;
30 using namespace boost;
31
32 /** Construct a Fraction from a string of the form <numerator> <denominator>
33  *  e.g. "1 3".
34  */
35 Fraction::Fraction (string s)
36 {
37         vector<string> b;
38         split (b, s, is_any_of (" "));
39         if (b.size() != 2) {
40                 boost::throw_exception (XMLError ("malformed fraction " + s + " in XML node"));
41         }
42         numerator = raw_convert<int> (b[0]);
43         denominator = raw_convert<int> (b[1]);
44 }
45
46 bool
47 dcp::operator== (Fraction const & a, Fraction const & b)
48 {
49         return (a.numerator == b.numerator && a.denominator == b.denominator);
50 }
51
52 bool
53 dcp::operator!= (Fraction const & a, Fraction const & b)
54 {
55         return (a.numerator != b.numerator || a.denominator != b.denominator);
56 }
57
58 /** Construct a Color, initialising it to black. */
59 Color::Color ()
60         : r (0)
61         , g (0)
62         , b (0)
63 {
64
65 }
66
67 /** Construct a Color from R, G and B.  The values run between
68  *  0 and 255.
69  */
70 Color::Color (int r_, int g_, int b_)
71         : r (r_)
72         , g (g_)
73         , b (b_)
74 {
75
76 }
77
78 /** Construct a Color from an ARGB hex string; the alpha value is ignored.
79  *  @param argb_hex A string of the form AARRGGBB, where e.g. RR is a two-character
80  *  hex value.
81  */
82 Color::Color (string argb_hex)
83 {
84         int alpha;
85         if (sscanf (argb_hex.c_str(), "%2x%2x%2x%2x", &alpha, &r, &g, &b) < 4) {
86                 boost::throw_exception (XMLError ("could not parse colour string"));
87         }
88 }
89
90 /** @return An ARGB string of the form AARRGGBB, where e.g. RR is a two-character
91  *  hex value.  The alpha value will always be FF (ie 255; maximum alpha).
92  */
93 string
94 Color::to_argb_string () const
95 {
96         stringstream s;
97         s << "FF";
98         s << hex
99           << setw(2) << setfill('0') << r
100           << setw(2) << setfill('0') << g
101           << setw(2) << setfill('0') << b;
102
103         string t = s.str();
104         to_upper (t);
105         return t;
106 }
107
108 /** operator== for Colors.
109  *  @param a First color to compare.
110  *  @param b Second color to compare.
111  */
112 bool
113 dcp::operator== (Color const & a, Color const & b)
114 {
115         return (a.r == b.r && a.g == b.g && a.b == b.b);
116 }
117
118 /** operator!= for Colors.
119  *  @param a First color to compare.
120  *  @param b Second color to compare.
121  */
122 bool
123 dcp::operator!= (Color const & a, Color const & b)
124 {
125         return !(a == b);
126 }
127
128 ostream &
129 dcp::operator<< (ostream& s, Color const & c)
130 {
131         s << "(" << c.r << ", " << c.g << ", " << c.b << ")";
132         return s;
133 }
134
135 string
136 dcp::effect_to_string (Effect e)
137 {
138         switch (e) {
139         case NONE:
140                 return "none";
141         case BORDER:
142                 return "border";
143         case SHADOW:
144                 return "shadow";
145         }
146
147         boost::throw_exception (MiscError ("unknown effect type"));
148 }
149
150 Effect
151 dcp::string_to_effect (string s)
152 {
153         if (s == "none") {
154                 return NONE;
155         } else if (s == "border") {
156                 return BORDER;
157         } else if (s == "shadow") {
158                 return SHADOW;
159         }
160
161         boost::throw_exception (DCPReadError ("unknown subtitle effect type"));
162 }
163
164 string
165 dcp::valign_to_string (VAlign v)
166 {
167         switch (v) {
168         case TOP:
169                 return "top";
170         case CENTER:
171                 return "center";
172         case BOTTOM:
173                 return "bottom";
174         }
175
176         boost::throw_exception (MiscError ("unknown valign type"));
177 }
178
179 VAlign
180 dcp::string_to_valign (string s)
181 {
182         if (s == "top") {
183                 return TOP;
184         } else if (s == "center") {
185                 return CENTER;
186         } else if (s == "bottom") {
187                 return BOTTOM;
188         }
189         
190         boost::throw_exception (DCPReadError ("unknown subtitle valign type"));
191 }
192
193