Freeciv21
Develop your civilization from humble roots to a global empire
rgbcolor.cpp
Go to the documentation of this file.
1 /*
2 _ ._ Copyright (c) 1996-2021 Freeciv21 and Freeciv contributors.
3  \ | This file is part of Freeciv21. Freeciv21 is free software: you
4  \_| can redistribute it and/or modify it under the terms of the
5  .' '. GNU General Public License as published by the Free
6  :O O: Software Foundation, either version 3 of the License,
7  '/ \' or (at your option) any later version. You should have
8  :X: received a copy of the GNU General Public License along with
9  :X: Freeciv21. If not, see https://www.gnu.org/licenses/.
10  */
11 
12 #include <cstdarg>
13 
14 // utility
15 #include "log.h"
16 #include "registry.h"
17 #include "registry_ini.h"
18 
19 // common
20 #include "rgbcolor.h"
21 
25 struct rgbcolor *rgbcolor_new(int r, int g, int b)
26 {
27  struct rgbcolor *prgbcolor;
28 
29  prgbcolor = new rgbcolor;
30  prgbcolor->r = r;
31  prgbcolor->g = g;
32  prgbcolor->b = b;
33 
34  return prgbcolor;
35 }
36 
41 struct rgbcolor *rgbcolor_copy(const struct rgbcolor *prgbcolor)
42 {
43  fc_assert_ret_val(prgbcolor != nullptr, nullptr);
44 
45  return rgbcolor_new(prgbcolor->r, prgbcolor->g, prgbcolor->b);
46 }
47 
52 bool rgbcolors_are_equal(const struct rgbcolor *c1,
53  const struct rgbcolor *c2)
54 {
55  fc_assert_ret_val(c1 != nullptr && c2 != nullptr, false);
56 
57  /* No check of cached 'color' member -- if values are equal, it should be
58  * equivalent */
59  return (c1->r == c2->r && c1->g == c2->g && c1->b == c2->b);
60 }
61 
65 void rgbcolor_destroy(struct rgbcolor *prgbcolor)
66 {
67  if (!prgbcolor) {
68  return;
69  }
70 
71  delete prgbcolor;
72 }
73 
78 bool rgbcolor_load(struct section_file *file, struct rgbcolor **prgbcolor,
79  const char *path, ...)
80 {
81  int r, g, b;
82  char colorpath[256];
83  va_list args;
84 
85  fc_assert_ret_val(file != nullptr, false);
86  fc_assert_ret_val(*prgbcolor == nullptr, false);
87 
88  va_start(args, path);
89  fc_vsnprintf(colorpath, sizeof(colorpath), path, args);
90  va_end(args);
91 
92  if (!secfile_lookup_int(file, &r, "%s.r", colorpath)
93  || !secfile_lookup_int(file, &g, "%s.g", colorpath)
94  || !secfile_lookup_int(file, &b, "%s.b", colorpath)) {
95  // One color value (red, green or blue) is missing.
96  return false;
97  }
98 
99  rgbcolor_check(colorpath, r, g, b);
100  *prgbcolor = rgbcolor_new(r, g, b);
101 
102  return true;
103 }
104 
109 void rgbcolor_save(struct section_file *file,
110  const struct rgbcolor *prgbcolor, const char *path, ...)
111 {
112  char colorpath[256];
113  va_list args;
114 
115  fc_assert_ret(file != nullptr);
116  fc_assert_ret(prgbcolor != nullptr);
117 
118  va_start(args, path);
119  fc_vsnprintf(colorpath, sizeof(colorpath), path, args);
120  va_end(args);
121 
122  secfile_insert_int(file, prgbcolor->r, "%s.r", colorpath);
123  secfile_insert_int(file, prgbcolor->g, "%s.g", colorpath);
124  secfile_insert_int(file, prgbcolor->b, "%s.b", colorpath);
125 }
126 
130 bool rgbcolor_to_hex(const struct rgbcolor *prgbcolor, char *hex,
131  size_t hex_len)
132 {
133  fc_assert_ret_val(prgbcolor != nullptr, false);
134  // Needs a length greater than 7 ('#' + 6 hex digites and '/* Needs a
135  // length greater than 7 ('#' + 6 hex digites and '\0'). */').
136  fc_assert_ret_val(hex_len > 7, false);
137 
138  fc_assert_ret_val(0 <= prgbcolor->r && prgbcolor->r <= 255, false);
139  fc_assert_ret_val(0 <= prgbcolor->g && prgbcolor->g <= 255, false);
140  fc_assert_ret_val(0 <= prgbcolor->b && prgbcolor->b <= 255, false);
141 
142  fc_snprintf(hex, hex_len, "#%06x",
143  (prgbcolor->r * 256 + prgbcolor->g) * 256 + prgbcolor->b);
144 
145  return true;
146 }
147 
151 bool rgbcolor_from_hex(struct rgbcolor **prgbcolor, const char *hex)
152 {
153  int rgb, r, g, b;
154  char hex2[16];
155 
156  fc_assert_ret_val(*prgbcolor == nullptr, false);
157  fc_assert_ret_val(hex != nullptr, false);
158 
159  if (hex[0] == '#') {
160  hex++;
161  }
162 
163  if (strlen(hex) != 6) {
164  return false;
165  }
166 
167  fc_snprintf(hex2, sizeof(hex2), "0x%s", hex);
168  if (!sscanf(hex2, "%x", &rgb)) {
169  return false;
170  }
171 
172  r = rgb / 256 / 256;
173  g = (rgb - r * 256 * 256) / 256;
174  b = rgb % 256;
175 
176  *prgbcolor = rgbcolor_new(r, g, b);
177 
178  return true;
179 }
180 
185 int rgbcolor_brightness_score(struct rgbcolor *prgbcolor)
186 {
187  /* This simple scoring system taken from W3C "Techniques For Accessibility
188  * Evaluation And Repair Tools", http://www.w3.org/TR/AERT#color-contrast
189  *
190  * "Color brightness is determined by the following formula:
191  * ((Red value X 299) + (Green value X 587) + (Blue value X 114)) / 1000
192  * Note: This algorithm is taken from a formula for converting RGB values
193  * to YIQ [NTSC] values [specifically the Y component]. This brightness
194  * value gives a perceived brightness for a color." */
195  return (prgbcolor->r * 299 + prgbcolor->g * 587 + prgbcolor->b * 114)
196  / 1000;
197 }
#define fc_assert_ret(condition)
Definition: log.h:112
#define fc_assert_ret_val(condition, val)
Definition: log.h:114
bool secfile_lookup_int(const struct section_file *secfile, int *ival, const char *path,...)
Lookup a integer value in the secfile.
#define secfile_insert_int(secfile, value, path,...)
Definition: registry_ini.h:116
bool rgbcolor_from_hex(struct rgbcolor **prgbcolor, const char *hex)
Convert a hex string into a rgb color.
Definition: rgbcolor.cpp:151
void rgbcolor_destroy(struct rgbcolor *prgbcolor)
Free rgbcolor structure.
Definition: rgbcolor.cpp:65
bool rgbcolors_are_equal(const struct rgbcolor *c1, const struct rgbcolor *c2)
Test whether two rgbcolor structures represent the exact same color value.
Definition: rgbcolor.cpp:52
bool rgbcolor_load(struct section_file *file, struct rgbcolor **prgbcolor, const char *path,...)
Lookup an RGB color definition ([colorpath].red, [colorpath].green and [colorpath]....
Definition: rgbcolor.cpp:78
struct rgbcolor * rgbcolor_new(int r, int g, int b)
Allocate new rgbcolor structure.
Definition: rgbcolor.cpp:25
void rgbcolor_save(struct section_file *file, const struct rgbcolor *prgbcolor, const char *path,...)
Save an RGB color definition ([colorpath].red, [colorpath].green and [colorpath].blue).
Definition: rgbcolor.cpp:109
bool rgbcolor_to_hex(const struct rgbcolor *prgbcolor, char *hex, size_t hex_len)
Convert a rgb color to a hex string (like 0xff0000 for red [255, 0, 0]).
Definition: rgbcolor.cpp:130
int rgbcolor_brightness_score(struct rgbcolor *prgbcolor)
Return a number indicating the perceptual brightness of this color relative to others (larger is brig...
Definition: rgbcolor.cpp:185
struct rgbcolor * rgbcolor_copy(const struct rgbcolor *prgbcolor)
Allocate new rgbcolor structure and make it copy of one given as input.
Definition: rgbcolor.cpp:41
#define rgbcolor_check(_str, _r, _g, _b)
Definition: rgbcolor.h:52
int g
Definition: rgbcolor.h:27
int b
Definition: rgbcolor.h:27
int r
Definition: rgbcolor.h:27
int fc_snprintf(char *str, size_t n, const char *format,...)
See also fc_utf8_snprintf_trunc(), fc_utf8_snprintf_rep().
Definition: support.cpp:537
int fc_vsnprintf(char *str, size_t n, const char *format, va_list ap)
Definition: support.cpp:512