X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;ds=inline;f=src%2Ftypes.cc;h=29e2c387ff05d028c02bce6724b87ff49d85bee7;hb=9ec8f4724969c789c3add7edc7c548827f73d8a3;hp=0ecf7a16439c0b1bed10ee6f7d8f4e42c2bee202;hpb=bfb33feb40c5b014e9eae3958b1ecb8161f1d090;p=libdcp.git diff --git a/src/types.cc b/src/types.cc index 0ecf7a16..29e2c387 100644 --- a/src/types.cc +++ b/src/types.cc @@ -1,25 +1,42 @@ /* - Copyright (C) 2012-2014 Carl Hetherington + Copyright (C) 2012-2019 Carl Hetherington - This program is free software; you can redistribute it and/or modify + This file is part of libdcp. + + libdcp is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, + libdcp is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + along with libdcp. If not, see . + + In addition, as a special exception, the copyright holders give + permission to link the code of portions of this program with the + OpenSSL library under certain conditions as described in each + individual source file, and distribute linked combinations + including the two. + You must obey the GNU General Public License in all respects + for all of the code used other than OpenSSL. If you modify + file(s) with this exception, you may extend this exception to your + version of the file(s), but you are not obligated to do so. If you + do not wish to do so, delete this exception statement from your + version. If you delete this exception statement from all source + files in the program, then also delete it here. */ +#include "raw_convert.h" #include "types.h" #include "exceptions.h" -#include +#include "compose.hpp" +#include "dcp_assert.h" +#include #include #include #include @@ -29,6 +46,22 @@ using namespace std; using namespace dcp; using namespace boost; +bool dcp::operator== (dcp::Size const & a, dcp::Size const & b) +{ + return (a.width == b.width && a.height == b.height); +} + +bool dcp::operator!= (dcp::Size const & a, dcp::Size const & b) +{ + return !(a == b); +} + +ostream& dcp::operator<< (ostream& s, dcp::Size const & a) +{ + s << a.width << "x" << a.height; + return s; +} + /** Construct a Fraction from a string of the form * e.g. "1 3". */ @@ -39,8 +72,14 @@ Fraction::Fraction (string s) if (b.size() != 2) { boost::throw_exception (XMLError ("malformed fraction " + s + " in XML node")); } - numerator = lexical_cast (b[0]); - denominator = lexical_cast (b[1]); + numerator = raw_convert (b[0]); + denominator = raw_convert (b[1]); +} + +string +Fraction::as_string () const +{ + return String::compose ("%1 %2", numerator, denominator); } bool @@ -55,8 +94,15 @@ dcp::operator!= (Fraction const & a, Fraction const & b) return (a.numerator != b.numerator || a.denominator != b.denominator); } -/** Construct a Color, initialising it to black. */ -Color::Color () +ostream& +dcp::operator<< (ostream& s, Fraction const & f) +{ + s << f.numerator << "/" << f.denominator; + return s; +} + +/** Construct a Colour, initialising it to black. */ +Colour::Colour () : r (0) , g (0) , b (0) @@ -64,10 +110,10 @@ Color::Color () } -/** Construct a Color from R, G and B. The values run between +/** Construct a Colour from R, G and B. The values run between * 0 and 255. */ -Color::Color (int r_, int g_, int b_) +Colour::Colour (int r_, int g_, int b_) : r (r_) , g (g_) , b (b_) @@ -75,14 +121,14 @@ Color::Color (int r_, int g_, int b_) } -/** Construct a Color from an ARGB hex string; the alpha value is ignored. +/** Construct a Colour from an ARGB hex string; the alpha value is ignored. * @param argb_hex A string of the form AARRGGBB, where e.g. RR is a two-character * hex value. */ -Color::Color (string argb_hex) +Colour::Colour (string argb_hex) { int alpha; - if (sscanf (argb_hex.c_str(), "%2x%2x%2x%2x", &alpha, &r, &g, &b) < 4) { + if (sscanf (argb_hex.c_str(), "%2x%2x%2x%2x", &alpha, &r, &g, &b) != 4) { boost::throw_exception (XMLError ("could not parse colour string")); } } @@ -91,42 +137,46 @@ Color::Color (string argb_hex) * hex value. The alpha value will always be FF (ie 255; maximum alpha). */ string -Color::to_argb_string () const +Colour::to_argb_string () const { - stringstream s; - s << "FF"; - s << hex - << setw(2) << setfill('0') << r - << setw(2) << setfill('0') << g - << setw(2) << setfill('0') << b; + char buffer[9]; + snprintf (buffer, sizeof(buffer), "FF%02X%02X%02X", r, g, b); + return buffer; +} - string t = s.str(); - to_upper (t); - return t; +/** @return An RGB string of the form RRGGBB, where e.g. RR is a two-character + * hex value. + */ +string +Colour::to_rgb_string () const +{ + char buffer[7]; + snprintf (buffer, sizeof(buffer), "%02X%02X%02X", r, g, b); + return buffer; } -/** operator== for Colors. - * @param a First color to compare. - * @param b Second color to compare. +/** operator== for Colours. + * @param a First colour to compare. + * @param b Second colour to compare. */ bool -dcp::operator== (Color const & a, Color const & b) +dcp::operator== (Colour const & a, Colour const & b) { return (a.r == b.r && a.g == b.g && a.b == b.b); } -/** operator!= for Colors. - * @param a First color to compare. - * @param b Second color to compare. +/** operator!= for Colours. + * @param a First colour to compare. + * @param b Second colour to compare. */ bool -dcp::operator!= (Color const & a, Color const & b) +dcp::operator!= (Colour const & a, Colour const & b) { return !(a == b); } ostream & -dcp::operator<< (ostream& s, Color const & c) +dcp::operator<< (ostream& s, Colour const & c) { s << "(" << c.r << ", " << c.g << ", " << c.b << ")"; return s; @@ -161,33 +211,254 @@ dcp::string_to_effect (string s) boost::throw_exception (DCPReadError ("unknown subtitle effect type")); } +string +dcp::halign_to_string (HAlign h) +{ + switch (h) { + case HALIGN_LEFT: + return "left"; + case HALIGN_CENTER: + return "center"; + case HALIGN_RIGHT: + return "right"; + } + + boost::throw_exception (MiscError ("unknown subtitle halign type")); +} + +HAlign +dcp::string_to_halign (string s) +{ + if (s == "left") { + return HALIGN_LEFT; + } else if (s == "center") { + return HALIGN_CENTER; + } else if (s == "right") { + return HALIGN_RIGHT; + } + + boost::throw_exception (DCPReadError ("unknown subtitle halign type")); +} + string dcp::valign_to_string (VAlign v) { switch (v) { - case TOP: + case VALIGN_TOP: return "top"; - case CENTER: + case VALIGN_CENTER: return "center"; - case BOTTOM: + case VALIGN_BOTTOM: return "bottom"; } - boost::throw_exception (MiscError ("unknown valign type")); + boost::throw_exception (MiscError ("unknown subtitle valign type")); } VAlign dcp::string_to_valign (string s) { if (s == "top") { - return TOP; + return VALIGN_TOP; } else if (s == "center") { - return CENTER; + return VALIGN_CENTER; } else if (s == "bottom") { - return BOTTOM; + return VALIGN_BOTTOM; } - + boost::throw_exception (DCPReadError ("unknown subtitle valign type")); } - +string +dcp::direction_to_string (Direction v) +{ + switch (v) { + case DIRECTION_LTR: + return "ltr"; + case DIRECTION_RTL: + return "rtl"; + case DIRECTION_TTB: + return "ttb"; + case DIRECTION_BTT: + return "btt"; + } + + boost::throw_exception (MiscError ("unknown subtitle direction type")); +} + +Direction +dcp::string_to_direction (string s) +{ + if (s == "ltr" || s == "horizontal") { + return DIRECTION_LTR; + } else if (s == "rtl") { + return DIRECTION_RTL; + } else if (s == "ttb" || s == "vertical") { + return DIRECTION_TTB; + } else if (s == "btt") { + return DIRECTION_BTT; + } + + boost::throw_exception (DCPReadError ("unknown subtitle direction type")); +} + +/** Convert a content kind to a string which can be used in a + * <ContentKind> node. + * @param kind ContentKind. + * @return string. + */ +string +dcp::content_kind_to_string (ContentKind kind) +{ + switch (kind) { + case FEATURE: + return "feature"; + case SHORT: + return "short"; + case TRAILER: + return "trailer"; + case TEST: + return "test"; + case TRANSITIONAL: + return "transitional"; + case RATING: + return "rating"; + case TEASER: + return "teaser"; + case POLICY: + return "policy"; + case PUBLIC_SERVICE_ANNOUNCEMENT: + return "psa"; + case ADVERTISEMENT: + return "advertisement"; + case EPISODE: + return "episode"; + case PROMO: + return "promo"; + } + + DCP_ASSERT (false); +} + +/** Convert a string from a <ContentKind> node to a libdcp ContentKind. + * Reasonably tolerant about varying case. + * @param kind Content kind string. + * @return libdcp ContentKind. + */ +dcp::ContentKind +dcp::content_kind_from_string (string kind) +{ + transform (kind.begin(), kind.end(), kind.begin(), ::tolower); + + if (kind == "feature") { + return FEATURE; + } else if (kind == "short") { + return SHORT; + } else if (kind == "trailer") { + return TRAILER; + } else if (kind == "test") { + return TEST; + } else if (kind == "transitional") { + return TRANSITIONAL; + } else if (kind == "rating") { + return RATING; + } else if (kind == "teaser") { + return TEASER; + } else if (kind == "policy") { + return POLICY; + } else if (kind == "psa") { + return PUBLIC_SERVICE_ANNOUNCEMENT; + } else if (kind == "advertisement") { + return ADVERTISEMENT; + } else if (kind == "episode") { + return EPISODE; + } else if (kind == "promo") { + return PROMO; + } + + throw BadContentKindError (kind); +} + +string +dcp::marker_to_string (dcp::Marker m) +{ + switch (m) { + case FFOC: + return "FFOC"; + case LFOC: + return "LFOC"; + case FFTC: + return "FFTC"; + case LFTC: + return "LFTC"; + case FFOI: + return "FFOI"; + case LFOI: + return "LFOI"; + case FFEC: + return "FFEC"; + case LFEC: + return "LFEC"; + case FFMC: + return "FFMC"; + case LFMC: + return "LFMC"; + } + + DCP_ASSERT (false); +} + +dcp::Marker +dcp::marker_from_string (string s) +{ + if (s == "FFOC") { + return FFOC; + } else if (s == "LFOC") { + return LFOC; + } else if (s == "FFTC") { + return FFTC; + } else if (s == "LFTC") { + return LFTC; + } else if (s == "FFOI") { + return FFOI; + } else if (s == "LFOI") { + return LFOI; + } else if (s == "FFEC") { + return FFEC; + } else if (s == "LFEC") { + return LFEC; + } else if (s == "FFMC") { + return FFMC; + } else if (s == "LFMC") { + return LFMC; + } + + DCP_ASSERT (false); +} + +Rating::Rating (cxml::ConstNodePtr node) +{ + agency = node->string_child("Agency"); + label = node->string_child("Label"); + node->done (); +} + +void +Rating::as_xml (xmlpp::Element* parent) const +{ + parent->add_child("Agency")->add_child_text(agency); + parent->add_child("Label")->add_child_text(label); +} + +bool +dcp::operator== (Rating const & a, Rating const & b) +{ + return a.agency == b.agency && a.label == b.label; +} + +ostream & +dcp::operator<< (ostream& s, Rating const & r) +{ + s << r.agency << " " << r.label; + return s; +}