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