GRASS GIS 8 Programmer's Manual 8.3.2(2024)-exported
Loading...
Searching...
No Matches
color_rules.c
Go to the documentation of this file.
1/*!
2 \file lib/gis/color_rules.c
3
4 \brief GIS Library - Color tables management subroutines
5
6 Taken from r.colors module.
7
8 (C) 2001-2011 by the GRASS Development Team
9 */
10
11#include <stdlib.h>
12#include <string.h>
13
14#include <grass/gis.h>
15#include <grass/glocale.h>
16
17struct colorinfo {
18 char *name;
19 char *desc;
20 char *type;
21};
22
23static struct colorinfo *get_colorinfo(int *);
24static void free_colorinfo(struct colorinfo *, int);
25
26static int cmp_clrname(const void *a, const void *b)
27{
28 struct colorinfo *ca = (struct colorinfo *)a;
29 struct colorinfo *cb = (struct colorinfo *)b;
30
31 return (strcmp(ca->name, cb->name));
32}
33
34/*!
35 \brief Get list of color rules for Option->options
36
37 \return allocated string buffer with options
38 */
40{
41 char *list;
42 const char *name;
43 int size, len, nrules;
44 int i, n;
45 struct colorinfo *colorinfo;
46
47 list = NULL;
48 size = len = 0;
49
50 colorinfo = get_colorinfo(&nrules);
51
52 for (i = 0; i < nrules; i++) {
53 name = colorinfo[i].name;
54 n = strlen(name);
55
56 if (size < len + n + 2) {
57 size = len + n + 200;
58 list = G_realloc(list, size);
59 }
60
61 if (len > 0)
62 list[len++] = ',';
63
64 memcpy(&list[len], name, n + 1);
65 len += n;
66 }
67
68 free_colorinfo(colorinfo, nrules);
69
70 return list;
71}
72
73/*!
74 \brief Get color rules description for Option->descriptions
75
76 \return allocated buffer with descriptions
77 */
79{
80 int result_len, result_max;
81 char *result;
82 const char *name, *desc;
83 int i, len, nrules;
84 struct colorinfo *colorinfo;
85
86 result_len = 0;
87 result_max = 2000;
88 result = G_malloc(result_max);
89
90 colorinfo = get_colorinfo(&nrules);
91
92 for (i = 0; i < nrules; i++) {
93 name = colorinfo[i].name;
94 desc = colorinfo[i].desc;
95
96 if (!desc)
97 desc = _("no description");
98
99 /* desc = _(desc); */
100
101 len = strlen(name) + strlen(desc) + 2;
102 if (result_len + len >= result_max) {
103 result_max = result_len + len + 1000;
104 result = G_realloc(result, result_max);
105 }
106
107 sprintf(result + result_len, "%s;%s;", name, desc);
108 result_len += len;
109 }
110
111 free_colorinfo(colorinfo, nrules);
112
113 return result;
114}
115
116/*!
117 \brief Get color rules description for Option->descriptions
118
119 The type of color rule including range is appended to the description
120
121 \return allocated buffer with name, description, and type
122 */
124{
125 int i, len, nrules;
126 struct colorinfo *colorinfo;
127 const char *name, *desc, *type;
128 int result_len, result_max;
129 char *result;
130
131 colorinfo = get_colorinfo(&nrules);
132
133 result_len = 0;
134 result_max = 2000;
135 result = G_malloc(result_max);
136
137 for (i = 0; i < nrules; i++) {
138 name = colorinfo[i].name;
139 desc = colorinfo[i].desc;
140 type = colorinfo[i].type;
141
142 if (desc) {
143 len = strlen(name) + strlen(desc) + strlen(type) + 5;
144 if (result_len + len >= result_max) {
145 result_max = result_len + len + 1000;
146 result = G_realloc(result, result_max);
147 }
148
149 sprintf(result + result_len, "%s;%s [%s];", name, desc, type);
150 result_len += len;
151 }
152 else {
153 len = strlen(name) + strlen(type) + 5;
154 if (result_len + len >= result_max) {
155 result_max = result_len + len + 1000;
156 result = G_realloc(result, result_max);
157 }
158
159 sprintf(result + result_len, "%s; [%s];", name, type);
160 result_len += len;
161 }
162 }
163
164 free_colorinfo(colorinfo, nrules);
165
166 return result;
167}
168
169/*!
170 \brief Print color rules
171
172 \param out file where to print
173 */
174void G_list_color_rules(FILE *out)
175{
176 int i, nrules;
177 struct colorinfo *colorinfo;
178
179 colorinfo = get_colorinfo(&nrules);
180
181 for (i = 0; i < nrules; i++)
182 fprintf(out, "%s\n", colorinfo[i].name);
183
184 free_colorinfo(colorinfo, nrules);
185}
186
187/*!
188 \brief Print color rules with description and type
189
190 The type of color rule including range is appended to the description.
191 If a color rule name is given, color info is printed only for this
192 rule.
193
194 \param name optional color rule name, or NULL
195 \param out file where to print
196 */
198{
199 int i, nrules;
200 struct colorinfo *colorinfo, csearch, *cfound;
201
202 colorinfo = get_colorinfo(&nrules);
203
204 cfound = NULL;
205 if (name) {
206 csearch.name = name;
207 cfound = bsearch(&csearch, colorinfo, nrules, sizeof(struct colorinfo),
208 cmp_clrname);
209
210 if (cfound) {
211 if (cfound->desc) {
212 fprintf(out, "%s: %s [%s]\n", cfound->name, cfound->desc,
213 cfound->type);
214 }
215 else {
216 fprintf(out, "%s: [%s]\n", cfound->name, cfound->type);
217 }
218 }
219 }
220
221 if (cfound == NULL) {
222 for (i = 0; i < nrules; i++) {
223 if (colorinfo[i].desc) {
224 fprintf(out, "%s: %s [%s]\n", colorinfo[i].name,
225 colorinfo[i].desc, colorinfo[i].type);
226 }
227 else {
228 fprintf(out, "%s: [%s]\n", colorinfo[i].name,
229 colorinfo[i].type);
230 }
231 }
232 }
233
234 free_colorinfo(colorinfo, nrules);
235}
236
237/*!
238 \brief Check if color rule is defined
239
240 \param name color rule name
241
242 \return 1 found
243 \return 0 not found
244 */
245int G_find_color_rule(const char *name)
246{
247 int result, nrules;
248 struct colorinfo *colorinfo, csearch;
249
250 colorinfo = get_colorinfo(&nrules);
251
252 csearch.name = (char *)name;
253 result = (bsearch(&csearch, colorinfo, nrules, sizeof(struct colorinfo),
254 cmp_clrname) != NULL);
255
256 free_colorinfo(colorinfo, nrules);
257
258 return result;
259}
260
261struct colorinfo *get_colorinfo(int *nrules)
262{
263 int i;
264 char path[GPATH_MAX];
265 FILE *fp;
266 struct colorinfo *colorinfo;
267 char **cnames;
268
269 /* load color rules */
270 G_snprintf(path, GPATH_MAX, "%s/etc/colors", G_gisbase());
271
272 *nrules = 0;
273 cnames = G_ls2(path, nrules);
274 (*nrules) += 3;
275 colorinfo = G_malloc(*nrules * sizeof(struct colorinfo));
276 for (i = 0; i < *nrules - 3; i++) {
277 char buf[1024];
278 double rmin, rmax;
279 int first;
280 int cisperc;
281
282 colorinfo[i].name = G_store(cnames[i]);
283 colorinfo[i].desc = NULL;
284
285 /* open color rule file */
286 G_snprintf(path, GPATH_MAX, "%s/etc/colors/%s", G_gisbase(),
287 colorinfo[i].name);
288 fp = fopen(path, "r");
289 if (!fp)
290 G_fatal_error(_("Unable to open color rule"));
291
292 /* scan all lines */
293 first = 1;
294 rmin = rmax = 0;
295 cisperc = 0;
296 while (G_getl2(buf, sizeof(buf), fp)) {
297 char value[80], color[80];
298 double x;
299 char c;
300
301 G_strip(buf);
302
303 if (*buf == '\0')
304 continue;
305 if (*buf == '#')
306 continue;
307
308 if (sscanf(buf, "%s %[^\n]", value, color) != 2)
309 continue;
310
311 if (G_strcasecmp(value, "default") == 0) {
312 continue;
313 }
314
315 if (G_strcasecmp(value, "nv") == 0) {
316 continue;
317 }
318
319 if (sscanf(value, "%lf%c", &x, &c) == 2 && c == '%') {
320 cisperc = 1;
321 break;
322 }
323 if (sscanf(value, "%lf", &x) == 1) {
324 if (first) {
325 first = 0;
326 rmin = rmax = x;
327 }
328 else {
329 if (rmin > x)
330 rmin = x;
331 if (rmax < x)
332 rmax = x;
333 }
334 }
335 }
336 fclose(fp);
337
338 if (cisperc)
339 colorinfo[i].type = G_store(_("range: map values"));
340 else {
341 G_snprintf(buf, sizeof(buf) - 1, _("range: %g to %g"), rmin, rmax);
342 colorinfo[i].type = G_store(buf);
343 }
344 }
345 G_free(cnames);
346
347 /* colors without rules but description */
348 colorinfo[*nrules - 3].name = G_store("random");
349 colorinfo[*nrules - 3].desc = NULL;
350 colorinfo[*nrules - 3].type = G_store(_("range: map values"));
351
352 colorinfo[*nrules - 2].name = G_store("grey.eq");
353 colorinfo[*nrules - 2].desc = NULL;
354 colorinfo[*nrules - 2].type = G_store(_("range: map values"));
355
356 colorinfo[*nrules - 1].name = G_store("grey.log");
357 colorinfo[*nrules - 1].desc = NULL;
358 colorinfo[*nrules - 1].type = G_store(_("range: map values"));
359
360 qsort(colorinfo, *nrules, sizeof(struct colorinfo), cmp_clrname);
361
362 /* load color descriptions */
363 G_snprintf(path, GPATH_MAX, "%s/etc/colors.desc", G_gisbase());
364 fp = fopen(path, "r");
365 if (!fp)
366 G_fatal_error(_("Unable to open color descriptions"));
367
368 for (;;) {
369 char buf[1024];
370 char tok_buf[1024];
371 char *cname, *cdesc;
372 int ntokens;
373 char **tokens;
374 struct colorinfo csearch, *cfound;
375
376 if (!G_getl2(buf, sizeof(buf), fp))
377 break;
378 strcpy(tok_buf, buf);
379 tokens = G_tokenize(tok_buf, ":");
380 ntokens = G_number_of_tokens(tokens);
381 if (ntokens != 2)
382 continue;
383
384 cname = G_chop(tokens[0]);
385 cdesc = G_chop(tokens[1]);
386
387 csearch.name = cname;
388 cfound = bsearch(&csearch, colorinfo, *nrules, sizeof(struct colorinfo),
389 cmp_clrname);
390
391 if (cfound) {
392 cfound->desc = G_store(cdesc);
393 }
394 G_free_tokens(tokens);
395 }
396 fclose(fp);
397
398 return colorinfo;
399}
400
401void free_colorinfo(struct colorinfo *colorinfo, int nrules)
402{
403 int i;
404
405 for (i = 0; i < nrules; i++) {
406 if (colorinfo[i].name)
407 G_free(colorinfo[i].name);
408 if (colorinfo[i].desc)
409 G_free(colorinfo[i].desc);
410 if (colorinfo[i].type)
411 G_free(colorinfo[i].type);
412 }
413 if (nrules > 0)
414 G_free(colorinfo);
415}
void G_free(void *buf)
Free allocated memory.
Definition alloc.c:150
struct cairo_state ca
#define NULL
Definition ccmath.h:32
char * G_color_rules_description_type(void)
Get color rules description for Option->descriptions.
char * G_color_rules_descriptions(void)
Get color rules description for Option->descriptions.
Definition color_rules.c:78
void G_list_color_rules(FILE *out)
Print color rules.
void G_list_color_rules_description_type(FILE *out, char *name)
Print color rules with description and type.
int G_find_color_rule(const char *name)
Check if color rule is defined.
char * G_color_rules_options(void)
Get list of color rules for Option->options.
Definition color_rules.c:39
double b
int G_getl2(char *buf, int n, FILE *fd)
Gets a line of text from a file of any pedigree.
Definition getl.c:65
void G_fatal_error(const char *msg,...)
Print a fatal error message to stderr.
Definition gis/error.c:159
const char * G_gisbase(void)
Get full path name of the top level module directory.
Definition gisbase.c:39
char ** G_ls2(const char *dir, int *num_files)
Stores a sorted directory listing in an array.
Definition ls.c:94
const char * name
Definition named_colr.c:6
struct list * list
Definition read_list.c:24
int G_snprintf(char *str, size_t size, const char *fmt,...)
snprintf() clone.
Definition snprintf.c:42
char * G_chop(char *line)
Chop leading and trailing white spaces.
Definition strings.c:331
int G_strcasecmp(const char *x, const char *y)
String compare ignoring case (upper or lower)
Definition strings.c:47
char * G_store(const char *s)
Copy string to allocated memory.
Definition strings.c:87
void G_strip(char *buf)
Removes all leading and trailing white space from string.
Definition strings.c:299
Definition path.h:15
void G_free_tokens(char **tokens)
Free memory allocated to tokens.
Definition token.c:198
char ** G_tokenize(const char *buf, const char *delim)
Tokenize string.
Definition token.c:47
int G_number_of_tokens(char **tokens)
Return number of tokens.
Definition token.c:179
#define x