1 /*
2    Copyright (C) 2003 - 2018 by the Battle for Wesnoth Project https://www.wesnoth.org/
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    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY.
10 
11    See the COPYING file for more details.
12 */
13 
14 #include "serialization/string_utils.hpp"
15 #include "color.hpp"
16 
17 #include <iomanip>
18 #include <sstream>
19 
from_rgba_string(const std::string & c)20 color_t color_t::from_rgba_string(const std::string& c)
21 {
22 	if(c.empty()) {
23 		return null_color();
24 	}
25 
26 	std::vector<std::string> fields = utils::split(c);
27 
28 	// Allow either 3 (automatic opaque alpha) or 4 (explicit alpha) fields
29 	if(fields.size() != 3 && fields.size() != 4) {
30 		throw std::invalid_argument("Wrong number of components for RGBA color");
31 	}
32 
33 	return {
34 		static_cast<uint8_t>(std::stoul(fields[0])),
35 		static_cast<uint8_t>(std::stoul(fields[1])),
36 		static_cast<uint8_t>(std::stoul(fields[2])),
37 		static_cast<uint8_t>(fields.size() == 4 ? std::stoul(fields[3]) : ALPHA_OPAQUE)
38 	};
39 }
40 
from_rgb_string(const std::string & c)41 color_t color_t::from_rgb_string(const std::string& c)
42 {
43 	if(c.empty()) {
44 		return null_color();
45 	}
46 
47 	std::vector<std::string> fields = utils::split(c);
48 
49 	if(fields.size() != 3) {
50 		throw std::invalid_argument("Wrong number of components for RGB color");
51 	}
52 
53 	return {
54 		static_cast<uint8_t>(std::stoul(fields[0])),
55 		static_cast<uint8_t>(std::stoul(fields[1])),
56 		static_cast<uint8_t>(std::stoul(fields[2])),
57 		static_cast<uint8_t>(ALPHA_OPAQUE)
58 	};
59 }
60 
from_hex_string(const std::string & c)61 color_t color_t::from_hex_string(const std::string& c)
62 {
63 	if(c.length() != 6) {
64 		throw std::invalid_argument("Color hex string should be exactly 6 digits");
65 	}
66 
67 	unsigned long temp_c = std::strtol(c.c_str(), nullptr, 16);
68 
69 	return {
70 		static_cast<uint8_t>((0x00FFFFFF & temp_c) >> 16),
71 		static_cast<uint8_t>((0x00FFFFFF & temp_c) >> 8),
72 		static_cast<uint8_t>((0x00FFFFFF & temp_c)),
73 		ALPHA_OPAQUE
74 	};
75 }
76 
from_rgba_bytes(uint32_t c)77 color_t color_t::from_rgba_bytes(uint32_t c)
78 {
79 	return {
80 		static_cast<uint8_t>((RGBA_RED_MASK   & c) >> RGBA_RED_BITSHIFT),
81 		static_cast<uint8_t>((RGBA_GREEN_MASK & c) >> RGBA_GREEN_BITSHIFT),
82 		static_cast<uint8_t>((RGBA_BLUE_MASK  & c) >> RGBA_BLUE_BITSHIFT),
83 		static_cast<uint8_t>((RGBA_ALPHA_MASK & c) >> RGBA_ALPHA_BITSHIFT),
84 	};
85 }
86 
from_argb_bytes(uint32_t c)87 color_t color_t::from_argb_bytes(uint32_t c)
88 {
89 	return {
90 		static_cast<uint8_t>((SDL_RED_MASK   & c) >> SDL_RED_BITSHIFT),
91 		static_cast<uint8_t>((SDL_GREEN_MASK & c) >> SDL_GREEN_BITSHIFT),
92 		static_cast<uint8_t>((SDL_BLUE_MASK  & c) >> SDL_BLUE_BITSHIFT),
93 		static_cast<uint8_t>((SDL_ALPHA_MASK & c) >> SDL_ALPHA_BITSHIFT),
94 	};
95 }
96 
to_hex_string() const97 std::string color_t::to_hex_string() const
98 {
99 	std::ostringstream h;
100 
101 	h << "#"
102 	  << std::hex << std::setfill('0')
103 	  << std::setw(2) << static_cast<int>(r)
104 	  << std::setw(2) << static_cast<int>(g)
105 	  << std::setw(2) << static_cast<int>(b);
106 
107 	return h.str();
108 }
109 
to_rgba_string() const110 std::string color_t::to_rgba_string() const
111 {
112 	std::ostringstream color;
113 
114 	color << static_cast<int>(r) << ','
115 	      << static_cast<int>(g) << ','
116 	      << static_cast<int>(b) << ','
117 	      << static_cast<int>(a);
118 
119 	return color.str();
120 }
121 
to_rgb_string() const122 std::string color_t::to_rgb_string() const
123 {
124 	std::ostringstream color;
125 
126 	color << static_cast<int>(r) << ','
127 	      << static_cast<int>(g) << ','
128 	      << static_cast<int>(b);
129 
130 	return color.str();
131 }
132