1 /****************************************************************************
2 Freeciv - Copyright (C) 2010 - The Freeciv Team
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12 ****************************************************************************/
15 #include <fc_config.h>
26 #include "fc_interface.h"
31 /****************************************************************************
32 Allocate new rgbcolor structure.
33 ****************************************************************************/
34 struct rgbcolor
*rgbcolor_new(int r
, int g
, int b
)
36 struct rgbcolor
*prgbcolor
;
38 prgbcolor
= fc_calloc(1, sizeof(*prgbcolor
));
42 prgbcolor
->color
= NULL
;
47 /****************************************************************************
48 Allocate new rgbcolor structure and make it copy of one given as input.
50 ****************************************************************************/
51 struct rgbcolor
*rgbcolor_copy(const struct rgbcolor
*prgbcolor
)
53 fc_assert_ret_val(prgbcolor
!= NULL
, NULL
);
55 return rgbcolor_new(prgbcolor
->r
, prgbcolor
->g
, prgbcolor
->b
);
58 /****************************************************************************
59 Test whether two rgbcolor structures represent the exact same color value.
60 (Does not attempt to determine whether they are visually distinguishable.)
61 ****************************************************************************/
62 bool rgbcolors_are_equal(const struct rgbcolor
*c1
, const struct rgbcolor
*c2
)
64 fc_assert_ret_val(c1
!= NULL
&& c2
!= NULL
, FALSE
);
66 /* No check of cached 'color' member -- if values are equal, it should be
68 return (c1
->r
== c2
->r
&& c1
->g
== c2
->g
&& c1
->b
== c2
->b
);
71 /****************************************************************************
72 Free rgbcolor structure.
73 ****************************************************************************/
74 void rgbcolor_destroy(struct rgbcolor
*prgbcolor
)
80 if (prgbcolor
->color
) {
81 fc_funcs
->gui_color_free(prgbcolor
->color
);
86 /****************************************************************************
87 Lookup an RGB color definition (<colorpath>.red, <colorpath>.green and
88 <colorpath>.blue). Returns TRUE on success and FALSE on error.
89 ****************************************************************************/
90 bool rgbcolor_load(struct section_file
*file
, struct rgbcolor
**prgbcolor
,
97 fc_assert_ret_val(file
!= NULL
, FALSE
);
98 fc_assert_ret_val(*prgbcolor
== NULL
, FALSE
);
100 va_start(args
, path
);
101 fc_vsnprintf(colorpath
, sizeof(colorpath
), path
, args
);
104 if (!secfile_lookup_int(file
, &r
, "%s.r", colorpath
)
105 || !secfile_lookup_int(file
, &g
, "%s.g", colorpath
)
106 || !secfile_lookup_int(file
, &b
, "%s.b", colorpath
)) {
107 /* One color value (red, green or blue) is missing. */
111 rgbcolor_check(colorpath
, r
, g
, b
);
112 *prgbcolor
= rgbcolor_new(r
, g
, b
);
117 /****************************************************************************
118 Save an RGB color definition (<colorpath>.red, <colorpath>.green and
120 ****************************************************************************/
121 void rgbcolor_save(struct section_file
*file
,
122 const struct rgbcolor
*prgbcolor
, char *path
, ...)
127 fc_assert_ret(file
!= NULL
);
128 fc_assert_ret(prgbcolor
!= NULL
);
130 va_start(args
, path
);
131 fc_vsnprintf(colorpath
, sizeof(colorpath
), path
, args
);
134 secfile_insert_int(file
, prgbcolor
->r
, "%s.r", colorpath
);
135 secfile_insert_int(file
, prgbcolor
->g
, "%s.g", colorpath
);
136 secfile_insert_int(file
, prgbcolor
->b
, "%s.b", colorpath
);
139 /****************************************************************************
140 Convert a rgb color to a hex string (like 0xff0000 for red [255, 0, 0]).
141 ****************************************************************************/
142 bool rgbcolor_to_hex(const struct rgbcolor
*prgbcolor
, char *hex
,
145 fc_assert_ret_val(prgbcolor
!= NULL
, FALSE
);
146 /* Needs a length greater than 7 ('#' + 6 hex digites and '\0'). */
147 fc_assert_ret_val(hex_len
> 7, FALSE
);
149 fc_assert_ret_val(0 <= prgbcolor
->r
&& prgbcolor
->r
<= 255, FALSE
);
150 fc_assert_ret_val(0 <= prgbcolor
->g
&& prgbcolor
->g
<= 255, FALSE
);
151 fc_assert_ret_val(0 <= prgbcolor
->b
&& prgbcolor
->b
<= 255, FALSE
);
153 fc_snprintf(hex
, hex_len
, "#%06x",
154 (prgbcolor
->r
* 256 + prgbcolor
->g
) * 256 + prgbcolor
->b
);
159 /****************************************************************************
160 Convert a hex string into a rgb color
161 ****************************************************************************/
162 bool rgbcolor_from_hex(struct rgbcolor
**prgbcolor
, const char *hex
)
167 fc_assert_ret_val(*prgbcolor
== NULL
, FALSE
);
168 fc_assert_ret_val(hex
!= NULL
, FALSE
);
174 if (strlen(hex
) != 6) {
178 fc_snprintf(hex2
, sizeof(hex2
), "0x%s", hex
);
179 if (!sscanf(hex2
, "%x", &rgb
)) {
184 g
= (rgb
- r
* 256 * 256) / 256;
187 *prgbcolor
= rgbcolor_new(r
, g
, b
);
192 /****************************************************************************
193 Return a number indicating the perceptual brightness of this color
194 relative to others (larger is brighter).
195 ****************************************************************************/
196 int rgbcolor_brightness_score(struct rgbcolor
*prgbcolor
)
198 /* This simple scoring system taken from W3C "Techniques For Accessibility
199 * Evaluation And Repair Tools", http://www.w3.org/TR/AERT#color-contrast
201 * "Color brightness is determined by the following formula:
202 * ((Red value X 299) + (Green value X 587) + (Blue value X 114)) / 1000
203 * Note: This algorithm is taken from a formula for converting RGB values to
204 * YIQ [NTSC] values [specifically the Y component]. This brightness value
205 * gives a perceived brightness for a color." */
206 return (prgbcolor
->r
*299 + prgbcolor
->g
*587 + prgbcolor
->b
*114) / 1000;