GRASS 8 Programmer's Manual 8.6.0dev(2026)-79cd2b35f7
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 size_t size, len, n;
46 int i, nrules;
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{
82 size_t result_len, result_max, len;
83 char *result;
84 const char *name, *desc;
85 int i, 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, nrules;
128 size_t len, result_len, result_max;
129 struct colorinfo *colorinfo;
130 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) + (size_t)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 */
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/%s", G_colors_dir(), colorinfo[i].name);
289 fp = fopen(path, "r");
290 if (!fp)
291 G_fatal_error(_("Unable to open color rule"));
292
293 /* scan all lines */
294 first = 1;
295 rmin = rmax = 0;
296 cisperc = 0;
297 while (G_getl2(buf, sizeof(buf), fp)) {
298 char value[80], color[80];
299 double x;
300 char c;
301
302 G_strip(buf);
303
304 if (*buf == '\0')
305 continue;
306 if (*buf == '#')
307 continue;
308
309 if (sscanf(buf, "%s %[^\n]", value, color) != 2)
310 continue;
311
312 if (G_strcasecmp(value, "default") == 0) {
313 continue;
314 }
315
316 if (G_strcasecmp(value, "nv") == 0) {
317 continue;
318 }
319
320 if (sscanf(value, "%lf%c", &x, &c) == 2 && c == '%') {
321 cisperc = 1;
322 break;
323 }
324 if (sscanf(value, "%lf", &x) == 1) {
325 if (first) {
326 first = 0;
327 rmin = rmax = x;
328 }
329 else {
330 if (rmin > x)
331 rmin = x;
332 if (rmax < x)
333 rmax = x;
334 }
335 }
336 }
337 fclose(fp);
338
339 if (cisperc)
340 colorinfo[i].type = G_store(_("range: map values"));
341 else {
342 snprintf(buf, sizeof(buf) - 1, _("range: %g to %g"), rmin, rmax);
343 colorinfo[i].type = G_store(buf);
344 }
345 }
346 G_free(cnames);
347
348 /* colors without rules but description */
349 colorinfo[*nrules - 3].name = G_store("random");
350 colorinfo[*nrules - 3].desc = NULL;
351 colorinfo[*nrules - 3].type = G_store(_("range: map values"));
352
353 colorinfo[*nrules - 2].name = G_store("grey.eq");
354 colorinfo[*nrules - 2].desc = NULL;
355 colorinfo[*nrules - 2].type = G_store(_("range: map values"));
356
357 colorinfo[*nrules - 1].name = G_store("grey.log");
358 colorinfo[*nrules - 1].desc = NULL;
359 colorinfo[*nrules - 1].type = G_store(_("range: map values"));
360
361 qsort(colorinfo, *nrules, sizeof(struct colorinfo), cmp_clrname);
362
363 /* load color descriptions */
364 snprintf(path, GPATH_MAX, "%s/colors.desc", G_etc_dir());
365 fp = fopen(path, "r");
366 if (!fp)
367 G_fatal_error(_("Unable to open color descriptions"));
368
369 for (;;) {
370 char buf[1024];
371 char tok_buf[1024];
372 char *cname, *cdesc;
373 int ntokens;
374 char **tokens;
375 struct colorinfo csearch, *cfound;
376
377 if (!G_getl2(buf, sizeof(buf), fp))
378 break;
379 strcpy(tok_buf, buf);
380 tokens = G_tokenize(tok_buf, ":");
382 if (ntokens != 2)
383 continue;
384
385 cname = G_chop(tokens[0]);
386 cdesc = G_chop(tokens[1]);
387
389 cfound = bsearch(&csearch, colorinfo, *nrules, sizeof(struct colorinfo),
390 cmp_clrname);
391
392 if (cfound) {
393 cfound->desc = G_store(cdesc);
394 }
396 }
397 fclose(fp);
398
399 return colorinfo;
400}
401
402void free_colorinfo(struct colorinfo *colorinfo, int nrules)
403{
404 int i;
405
406 for (i = 0; i < nrules; i++) {
407 if (colorinfo[i].name)
408 G_free(colorinfo[i].name);
409 if (colorinfo[i].desc)
410 G_free(colorinfo[i].desc);
411 if (colorinfo[i].type)
412 G_free(colorinfo[i].type);
413 }
414 if (nrules > 0)
415 G_free(colorinfo);
416}
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
#define G_malloc(n)
Definition defs/gis.h:136
char ** G_tokenize(const char *, const char *)
Tokenize string.
Definition gis/token.c:45
const char * G_colors_dir(void)
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:299
const char * G_etc_dir(void)
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:46
char * G_chop(char *)
Chop leading and trailing white spaces.
Definition strings.c:331
char * G_store(const char *)
Copy string to allocated memory.
Definition strings.c:86
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:198
#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