The Battle for Wesnoth 1.21.0-dev
 
Loading...
Searching...
No Matches
color.hpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2003 - 2025
3 Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY.
11
12 See the COPYING file for more details.
13*/
14
15#pragma once
16
17#include <SDL3/SDL_pixels.h>
18
19#include <algorithm> // for max
20#include <cstdint>
21#include <limits>
22#include <ostream>
23#include <string>
24#include <tuple>
25#include <utility>
26
27constexpr uint32_t SDL_ALPHA_MASK = 0xFF000000;
28constexpr uint32_t SDL_RED_MASK = 0x00FF0000;
29constexpr uint32_t SDL_GREEN_MASK = 0x0000FF00;
30constexpr uint32_t SDL_BLUE_MASK = 0x000000FF;
31
32constexpr uint32_t SDL_ALPHA_BITSHIFT = 24;
33constexpr uint32_t SDL_RED_BITSHIFT = 16;
34constexpr uint32_t SDL_GREEN_BITSHIFT = 8;
35constexpr uint32_t SDL_BLUE_BITSHIFT = 0;
36
37constexpr uint8_t ALPHA_OPAQUE = SDL_ALPHA_OPAQUE; // This is always 255 in SDL
38
39// Functions for manipulating RGB values.
40constexpr uint8_t float_to_color(double n);
41constexpr uint8_t float_to_color(float n);
42constexpr uint8_t color_multiply(uint8_t n1, uint8_t n2);
43constexpr uint8_t color_blend(uint8_t n1, uint8_t n2, uint8_t p);
44
45/**
46 * The basic class for representing 8-bit RGB or RGBA colour values.
47 *
48 * This is a thin wrapper over SDL_Color, and can be used interchangeably.
49 */
50struct color_t : SDL_Color
51{
52 /** color_t initializes to fully opaque white by default. */
53 constexpr color_t() : SDL_Color{255, 255, 255, ALPHA_OPAQUE} {}
54
55 /** Basic RGB or RGBA constructor. */
56 constexpr color_t(uint8_t r_val, uint8_t g_val, uint8_t b_val, uint8_t a_val = ALPHA_OPAQUE)
57 : SDL_Color{r_val, g_val, b_val, a_val}
58 {}
59
60 /** This is a thin wrapper. There is nothing extra to do here. */
61 constexpr color_t(const SDL_Color& c) : SDL_Color{c} {}
62
63 /**
64 * Creates a new color_t object from a string variable in "R,G,B,A" format.
65 * An empty string results in white. Otherwise, omitting components other than
66 * alpha is an error.
67 *
68 * @param c A string variable, in "R,G,B,A" format.
69 * @return A new color_t object.
70 *
71 * @throw std::invalid_argument if the string is not correctly formatted
72 */
73 static color_t from_rgba_string(std::string_view c);
74
75 /**
76 * Creates a new opaque color_t object from a string variable in "R,G,B" format.
77 * An empty string results in white. Otherwise, omitting components is an error.
78 *
79 * @param c A string variable, in "R,G,B" format.
80 * @return A new color_t object.
81 *
82 * @throw std::invalid_argument if the string is not correctly formatted
83 */
84 static color_t from_rgb_string(std::string_view c);
85
86 /**
87 * Creates a new color_t object from a string variable in hex format.
88 *
89 * @param c A string variable, in rrggbb hex format.
90 * @return A new color_t object.
91 *
92 * @throw std::invalid_argument if the string is not correctly formatted
93 */
94 static color_t from_hex_string(std::string_view c);
95
96 /**
97 * Creates a new color_t object from a uint32_t variable.
98 *
99 * @param c A uint32_t variable, in ARGB format.
100 * @return A new color_t object.
101 */
102 static constexpr color_t from_argb_bytes(uint32_t c)
103 {
104 return {
105 static_cast<uint8_t>((SDL_RED_MASK & c) >> SDL_RED_BITSHIFT),
106 static_cast<uint8_t>((SDL_GREEN_MASK & c) >> SDL_GREEN_BITSHIFT),
107 static_cast<uint8_t>((SDL_BLUE_MASK & c) >> SDL_BLUE_BITSHIFT),
108 static_cast<uint8_t>((SDL_ALPHA_MASK & c) >> SDL_ALPHA_BITSHIFT),
109 };
110 }
111
112 /**
113 * Creates a new color_t object from a triplet of 16 bit color values,
114 * usually used by Pango.
115 *
116 * @param r The red channel's value as a 16 bit integer.
117 * @param g The green channel's value as a 16 bit integer.
118 * @param b The blue channel's value as a 16 bit integer.
119 * @return A new color_t object.
120 */
121 static constexpr color_t from_pango_format(uint16_t r, uint16_t g, uint16_t b)
122 {
123 return {
124 static_cast<uint8_t>(r * 255.0 / std::numeric_limits<uint16_t>::max()),
125 static_cast<uint8_t>(g * 255.0 / std::numeric_limits<uint16_t>::max()),
126 static_cast<uint8_t>(b * 255.0 / std::numeric_limits<uint16_t>::max())
127 };
128 }
129
130 /**
131 * Returns the stored color in rrggbb hex format.
132 *
133 * @return The string in hex format. The preceding '#' needed for pango markup
134 * is prepended.
135 */
136 std::string to_hex_string() const;
137
138 /**
139 * Returns the stored color as a uint32_t, an ARGB format.
140 *
141 * @return The new uint32_t object.
142 */
143 constexpr uint32_t to_argb_bytes() const
144 {
145 return
146 (static_cast<uint32_t>(a) << SDL_ALPHA_BITSHIFT) |
147 (static_cast<uint32_t>(r) << SDL_RED_BITSHIFT) |
148 (static_cast<uint32_t>(g) << SDL_GREEN_BITSHIFT) |
149 (static_cast<uint32_t>(b) << SDL_BLUE_BITSHIFT);
150 }
151
152 /**
153 * Returns the stored color as an "R,G,B,A" string
154 *
155 * @return The new color string.
156 */
157 std::string to_rgba_string() const;
158
159 /**
160 * Returns the stored color as an "R,G,B" string
161 *
162 * @return The new color string.
163 */
164 std::string to_rgb_string() const;
165
166 /**
167 * Returns the color as a triplet of 16 bit integers, a format used by Pango.
168 *
169 * @return A tuple containing R,G,B values as 16 bit integers
170 */
171 constexpr std::tuple<uint16_t, uint16_t, uint16_t> to_pango_format() const
172 {
173 return {
174 r / 255.0 * std::numeric_limits<uint16_t>::max(),
175 g / 255.0 * std::numeric_limits<uint16_t>::max(),
176 b / 255.0 * std::numeric_limits<uint16_t>::max()
177 };
178 }
179
180 constexpr bool null() const
181 {
182 return *this == null_color();
183 }
184
185 constexpr bool operator==(const color_t& c) const
186 {
187 return r == c.r && g == c.g && b == c.b && a == c.a;
188 }
189
190 constexpr bool operator!=(const color_t& c) const
191 {
192 return !(*this == c);
193 }
194
195 constexpr color_t blend_add(const color_t& c) const
196 {
197 // Do some magic to detect integer overflow
198 // We want overflows to max out the component instead of wrapping.
199 // The static_cast is to silence narrowing conversion warnings etc
200 return {
201 static_cast<uint8_t>(r > 255 - c.r ? 255 : r + c.r),
202 static_cast<uint8_t>(g > 255 - c.g ? 255 : g + c.g),
203 static_cast<uint8_t>(b > 255 - c.b ? 255 : b + c.b),
204 static_cast<uint8_t>(a > 255 - c.a ? 255 : a + c.a),
205 };
206 }
207
208 constexpr color_t blend_lighten(const color_t& c) const
209 {
210 return {
211 std::max<uint8_t>(r, c.r),
212 std::max<uint8_t>(g, c.g),
213 std::max<uint8_t>(b, c.b),
214 std::max<uint8_t>(a, c.a),
215 };
216 }
217
218 constexpr color_t inverse() const {
219 return {
220 static_cast<uint8_t>(255 - r),
221 static_cast<uint8_t>(255 - g),
222 static_cast<uint8_t>(255 - b),
223 a
224 };
225 }
226
227 /**
228 * Blend smoothly with another color_t.
229 *
230 * @param c The color to blend with.
231 * @param p The proportion of the other color to blend. 0 will
232 * return the original color, 255 the blending color.
233 */
234 constexpr color_t smooth_blend(const color_t& c, uint8_t p) const
235 {
236 return {
237 color_blend(r, c.r, p),
238 color_blend(g, c.g, p),
239 color_blend(b, c.b, p),
240 color_blend(a, c.a, p)
241 };
242 }
243
244 /** Definition of a 'null' color - fully transparent black. */
245 static constexpr color_t null_color()
246 {
247 return {0,0,0,0};
248 }
249};
250
251inline std::ostream& operator<<(std::ostream& s, const color_t& c)
252{
253 s << c.to_hex_string();
254 return s;
255}
256
257namespace std
258{
259 template<>
260 struct hash<color_t>
261 {
262 std::size_t operator()(const color_t& c) const noexcept
263 {
264 return c.to_argb_bytes();
265 }
266 };
267}
268
269/********************************************/
270/* Functions for manipulating colour values */
271/********************************************/
272
273/** Convert a double in the range [0.0,1.0] to an 8-bit colour value. */
274constexpr uint8_t float_to_color(double n)
275{
276 if(n <= 0.0) return 0;
277 else if(n >= 1.0) return 255;
278 else return uint8_t(n * 256.0);
279}
280
281/** Convert a float in the range [0.0,1.0] to an 8-bit colour value. */
282constexpr uint8_t float_to_color(float n)
283{
284 if(n <= 0.0f) return 0;
285 else if(n >= 1.0f) return 255;
286 else return uint8_t(n * 256.0f);
287}
288
289/** Multiply two 8-bit colour values as if in the range [0.0,1.0]. */
290constexpr uint8_t color_multiply(uint8_t n1, uint8_t n2)
291{
292 return uint8_t((uint16_t(n1) * uint16_t(n2))/255);
293}
294
295/**
296 * Blend 8-bit colour value with another in the given proportion.
297 *
298 * A proportion of 0 returns the first value, 255 the second.
299 */
300constexpr uint8_t color_blend(uint8_t n1, uint8_t n2, uint8_t p)
301{
302 return color_multiply(n1, ~p) + color_multiply(n2, p);
303}
constexpr uint8_t ALPHA_OPAQUE
Definition color.hpp:37
constexpr uint32_t SDL_RED_BITSHIFT
Definition color.hpp:33
constexpr uint32_t SDL_GREEN_BITSHIFT
Definition color.hpp:34
constexpr uint32_t SDL_GREEN_MASK
Definition color.hpp:29
constexpr uint32_t SDL_ALPHA_MASK
Definition color.hpp:27
constexpr uint8_t color_multiply(uint8_t n1, uint8_t n2)
Multiply two 8-bit colour values as if in the range [0.0,1.0].
Definition color.hpp:290
constexpr uint32_t SDL_BLUE_BITSHIFT
Definition color.hpp:35
constexpr uint8_t float_to_color(double n)
Convert a double in the range [0.0,1.0] to an 8-bit colour value.
Definition color.hpp:274
constexpr uint32_t SDL_ALPHA_BITSHIFT
Definition color.hpp:32
constexpr uint8_t color_blend(uint8_t n1, uint8_t n2, uint8_t p)
Blend 8-bit colour value with another in the given proportion.
Definition color.hpp:300
constexpr uint32_t SDL_RED_MASK
Definition color.hpp:28
std::ostream & operator<<(std::ostream &s, const color_t &c)
Definition color.hpp:251
constexpr uint32_t SDL_BLUE_MASK
Definition color.hpp:30
STL namespace.
The basic class for representing 8-bit RGB or RGBA colour values.
Definition color.hpp:51
constexpr bool null() const
Definition color.hpp:180
static color_t from_hex_string(std::string_view c)
Creates a new color_t object from a string variable in hex format.
Definition color.cpp:64
static constexpr color_t from_pango_format(uint16_t r, uint16_t g, uint16_t b)
Creates a new color_t object from a triplet of 16 bit color values, usually used by Pango.
Definition color.hpp:121
constexpr color_t smooth_blend(const color_t &c, uint8_t p) const
Blend smoothly with another color_t.
Definition color.hpp:234
constexpr uint32_t to_argb_bytes() const
Returns the stored color as a uint32_t, an ARGB format.
Definition color.hpp:143
constexpr bool operator!=(const color_t &c) const
Definition color.hpp:190
std::string to_hex_string() const
Returns the stored color in rrggbb hex format.
Definition color.cpp:88
static color_t from_rgb_string(std::string_view c)
Creates a new opaque color_t object from a string variable in "R,G,B" format.
Definition color.cpp:44
static constexpr color_t null_color()
Definition of a 'null' color - fully transparent black.
Definition color.hpp:245
std::string to_rgb_string() const
Returns the stored color as an "R,G,B" string.
Definition color.cpp:117
constexpr color_t blend_lighten(const color_t &c) const
Definition color.hpp:208
constexpr color_t(const SDL_Color &c)
This is a thin wrapper.
Definition color.hpp:61
constexpr color_t blend_add(const color_t &c) const
Definition color.hpp:195
constexpr color_t inverse() const
Definition color.hpp:218
constexpr bool operator==(const color_t &c) const
Definition color.hpp:185
static color_t from_rgba_string(std::string_view c)
Creates a new color_t object from a string variable in "R,G,B,A" format.
Definition color.cpp:23
constexpr std::tuple< uint16_t, uint16_t, uint16_t > to_pango_format() const
Returns the color as a triplet of 16 bit integers, a format used by Pango.
Definition color.hpp:171
static constexpr color_t from_argb_bytes(uint32_t c)
Creates a new color_t object from a uint32_t variable.
Definition color.hpp:102
std::string to_rgba_string() const
Returns the stored color as an "R,G,B,A" string.
Definition color.cpp:105
constexpr color_t()
color_t initializes to fully opaque white by default.
Definition color.hpp:53
constexpr color_t(uint8_t r_val, uint8_t g_val, uint8_t b_val, uint8_t a_val=ALPHA_OPAQUE)
Basic RGB or RGBA constructor.
Definition color.hpp:56
std::size_t operator()(const color_t &c) const noexcept
Definition color.hpp:262
mock_party p
static map_location::direction n
static map_location::direction s
#define g
#define c
#define b