color_rules.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. /*!
  2. \file lib/gis/color_rules.c
  3. \brief GIS Library - Color tables management subroutines
  4. Taken from r.colors module.
  5. (C) 2001-2011 by the GRASS Development Team
  6. */
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <grass/gis.h>
  10. #include <grass/glocale.h>
  11. struct colorinfo
  12. {
  13. char *name;
  14. char *desc;
  15. char *type;
  16. };
  17. static struct colorinfo *get_colorinfo(int *);
  18. static void free_colorinfo(struct colorinfo *, int);
  19. static int cmp_clrname(const void *a, const void *b)
  20. {
  21. struct colorinfo *ca = (struct colorinfo *) a;
  22. struct colorinfo *cb = (struct colorinfo *) b;
  23. return (strcmp(ca->name, cb->name));
  24. }
  25. /*!
  26. \brief Get list of color rules for Option->options
  27. \return allocated string buffer with options
  28. */
  29. char *G_color_rules_options(void)
  30. {
  31. char *list;
  32. const char *name;
  33. int size, len, nrules;
  34. int i, n;
  35. struct colorinfo *colorinfo;
  36. list = NULL;
  37. size = len = 0;
  38. colorinfo = get_colorinfo(&nrules);
  39. for (i = 0; i < nrules; i++) {
  40. name = colorinfo[i].name;
  41. n = strlen(name);
  42. if (size < len + n + 2) {
  43. size = len + n + 200;
  44. list = G_realloc(list, size);
  45. }
  46. if (len > 0)
  47. list[len++] = ',';
  48. memcpy(&list[len], name, n + 1);
  49. len += n;
  50. }
  51. free_colorinfo(colorinfo, nrules);
  52. return list;
  53. }
  54. /*!
  55. \brief Get color rules description for Option->descriptions
  56. \return allocated buffer with descriptions
  57. */
  58. char *G_color_rules_descriptions(void)
  59. {
  60. int result_len, result_max;
  61. char *result;
  62. const char *name, *desc;
  63. int i, len, nrules;
  64. struct colorinfo *colorinfo;
  65. result_len = 0;
  66. result_max = 2000;
  67. result = G_malloc(result_max);
  68. colorinfo = get_colorinfo(&nrules);
  69. for (i = 0; i < nrules; i++) {
  70. name = colorinfo[i].name;
  71. desc = colorinfo[i].desc;
  72. if (!desc)
  73. desc = _("no description");
  74. /* desc = _(desc); */
  75. len = strlen(name) + strlen(desc) + 2;
  76. if (result_len + len >= result_max) {
  77. result_max = result_len + len + 1000;
  78. result = G_realloc(result, result_max);
  79. }
  80. sprintf(result + result_len, "%s;%s;", name, desc);
  81. result_len += len;
  82. }
  83. free_colorinfo(colorinfo, nrules);
  84. return result;
  85. }
  86. /*!
  87. \brief Get color rules description for Option->descriptions
  88. The type of color rule including range is appended to the description
  89. \return allocated buffer with name, description, and type
  90. */
  91. char *G_color_rules_description_type(void)
  92. {
  93. int i, len, nrules;
  94. struct colorinfo *colorinfo;
  95. const char *name, *desc, *type;
  96. int result_len, result_max;
  97. char *result;
  98. colorinfo = get_colorinfo(&nrules);
  99. result_len = 0;
  100. result_max = 2000;
  101. result = G_malloc(result_max);
  102. for (i = 0; i < nrules; i++) {
  103. name = colorinfo[i].name;
  104. desc = colorinfo[i].desc;
  105. type = colorinfo[i].type;
  106. if (desc) {
  107. len = strlen(name) + strlen(desc) + strlen(type) + 5;
  108. if (result_len + len >= result_max) {
  109. result_max = result_len + len + 1000;
  110. result = G_realloc(result, result_max);
  111. }
  112. sprintf(result + result_len, "%s;%s [%s];", name, desc, type);
  113. result_len += len;
  114. }
  115. else {
  116. len = strlen(name) + strlen(type) + 5;
  117. if (result_len + len >= result_max) {
  118. result_max = result_len + len + 1000;
  119. result = G_realloc(result, result_max);
  120. }
  121. sprintf(result + result_len, "%s; [%s];", name, type);
  122. result_len += len;
  123. }
  124. }
  125. free_colorinfo(colorinfo, nrules);
  126. return result;
  127. }
  128. /*!
  129. \brief Print color rules
  130. \param out file where to print
  131. */
  132. void G_list_color_rules(FILE *out)
  133. {
  134. int i, nrules;
  135. struct colorinfo *colorinfo;
  136. colorinfo = get_colorinfo(&nrules);
  137. for (i = 0; i < nrules; i++)
  138. fprintf(out, "%s\n", colorinfo[i].name);
  139. free_colorinfo(colorinfo, nrules);
  140. }
  141. /*!
  142. \brief Print color rules with description and type
  143. The type of color rule including range is appended to the description.
  144. If a color rule name is given, color info is printed only for this
  145. rule.
  146. \param name optional color rule name, or NULL
  147. \param out file where to print
  148. */
  149. void G_list_color_rules_description_type(FILE *out, char *name)
  150. {
  151. int i, nrules;
  152. struct colorinfo *colorinfo, csearch, *cfound;
  153. colorinfo = get_colorinfo(&nrules);
  154. cfound = NULL;
  155. if (name) {
  156. csearch.name = name;
  157. cfound = bsearch(&csearch, colorinfo, nrules,
  158. sizeof(struct colorinfo), cmp_clrname);
  159. if (cfound) {
  160. if (cfound->desc) {
  161. fprintf(out, "%s: %s [%s]\n", cfound->name,
  162. cfound->desc, cfound->type);
  163. }
  164. else {
  165. fprintf(out, "%s: [%s]\n", cfound->name,
  166. cfound->type);
  167. }
  168. }
  169. }
  170. if (cfound == NULL) {
  171. for (i = 0; i < nrules; i++) {
  172. if (colorinfo[i].desc) {
  173. fprintf(out, "%s: %s [%s]\n", colorinfo[i].name,
  174. colorinfo[i].desc, colorinfo[i].type);
  175. }
  176. else {
  177. fprintf(out, "%s: [%s]\n", colorinfo[i].name,
  178. colorinfo[i].type);
  179. }
  180. }
  181. }
  182. free_colorinfo(colorinfo, nrules);
  183. }
  184. /*!
  185. \brief Check if color rule is defined
  186. \param name color rule name
  187. \return 1 found
  188. \return 0 not found
  189. */
  190. int G_find_color_rule(const char *name)
  191. {
  192. int result, nrules;
  193. struct colorinfo *colorinfo, csearch;
  194. colorinfo = get_colorinfo(&nrules);
  195. csearch.name = (char *)name;
  196. result = (bsearch(&csearch, colorinfo, nrules,
  197. sizeof(struct colorinfo), cmp_clrname) != NULL);
  198. free_colorinfo(colorinfo, nrules);
  199. return result;
  200. }
  201. struct colorinfo *get_colorinfo(int *nrules)
  202. {
  203. int i;
  204. char path[GPATH_MAX];
  205. FILE *fp;
  206. struct colorinfo *colorinfo;
  207. char **cnames;
  208. /* load color rules */
  209. G_snprintf(path, GPATH_MAX, "%s/etc/colors", G_gisbase());
  210. *nrules = 0;
  211. cnames = G_ls2(path, nrules);
  212. (*nrules) += 3;
  213. colorinfo = G_malloc(*nrules * sizeof(struct colorinfo));
  214. for (i = 0; i < *nrules - 3; i++) {
  215. char buf[1024];
  216. double rmin, rmax;
  217. int first;
  218. int cisperc;
  219. colorinfo[i].name = G_store(cnames[i]);
  220. colorinfo[i].desc = NULL;
  221. /* open color rule file */
  222. G_snprintf(path, GPATH_MAX, "%s/etc/colors/%s", G_gisbase(),
  223. colorinfo[i].name);
  224. fp = fopen(path, "r");
  225. if (!fp)
  226. G_fatal_error(_("Unable to open color rule"));
  227. /* scan all lines */
  228. first = 1;
  229. rmin = rmax = 0;
  230. cisperc = 0;
  231. while (G_getl2(buf, sizeof(buf), fp)) {
  232. char value[80], color[80];
  233. double x;
  234. char c;
  235. G_strip(buf);
  236. if (*buf == '\0')
  237. continue;
  238. if (*buf == '#')
  239. continue;
  240. if (sscanf(buf, "%s %[^\n]", value, color) != 2)
  241. continue;
  242. if (G_strcasecmp(value, "default") == 0) {
  243. continue;
  244. }
  245. if (G_strcasecmp(value, "nv") == 0) {
  246. continue;
  247. }
  248. if (sscanf(value, "%lf%c", &x, &c) == 2 && c == '%') {
  249. cisperc = 1;
  250. break;
  251. }
  252. if (sscanf(value, "%lf", &x) == 1) {
  253. if (first) {
  254. first = 0;
  255. rmin = rmax = x;
  256. }
  257. else {
  258. if (rmin > x)
  259. rmin = x;
  260. if (rmax < x)
  261. rmax = x;
  262. }
  263. }
  264. }
  265. fclose(fp);
  266. if (cisperc)
  267. colorinfo[i].type = G_store(_("range: map values"));
  268. else {
  269. G_snprintf(buf, sizeof(buf) - 1, _("range: %g to %g"), rmin, rmax);
  270. colorinfo[i].type = G_store(buf);
  271. }
  272. }
  273. G_free(cnames);
  274. /* colors without rules but description */
  275. colorinfo[*nrules - 3].name = G_store("random");
  276. colorinfo[*nrules - 3].desc = NULL;
  277. colorinfo[*nrules - 3].type = G_store(_("range: map values"));
  278. colorinfo[*nrules - 2].name = G_store("grey.eq");
  279. colorinfo[*nrules - 2].desc = NULL;
  280. colorinfo[*nrules - 2].type = G_store(_("range: map values"));
  281. colorinfo[*nrules - 1].name = G_store("grey.log");
  282. colorinfo[*nrules - 1].desc = NULL;
  283. colorinfo[*nrules - 1].type = G_store(_("range: map values"));
  284. qsort(colorinfo, *nrules, sizeof(struct colorinfo), cmp_clrname);
  285. /* load color descriptions */
  286. G_snprintf(path, GPATH_MAX, "%s/etc/colors.desc", G_gisbase());
  287. fp = fopen(path, "r");
  288. if (!fp)
  289. G_fatal_error(_("Unable to open color descriptions"));
  290. for (;;) {
  291. char buf[1024];
  292. char tok_buf[1024];
  293. char *cname, *cdesc;
  294. int ntokens;
  295. char **tokens;
  296. struct colorinfo csearch, *cfound;
  297. if (!G_getl2(buf, sizeof(buf), fp))
  298. break;
  299. strcpy(tok_buf, buf);
  300. tokens = G_tokenize(tok_buf, ":");
  301. ntokens = G_number_of_tokens(tokens);
  302. if (ntokens != 2)
  303. continue;
  304. cname = G_chop(tokens[0]);
  305. cdesc = G_chop(tokens[1]);
  306. csearch.name = cname;
  307. cfound = bsearch(&csearch, colorinfo, *nrules,
  308. sizeof(struct colorinfo), cmp_clrname);
  309. if (cfound) {
  310. cfound->desc = G_store(cdesc);
  311. }
  312. G_free_tokens(tokens);
  313. }
  314. fclose(fp);
  315. return colorinfo;
  316. }
  317. void free_colorinfo(struct colorinfo *colorinfo, int nrules)
  318. {
  319. int i;
  320. for (i = 0; i < nrules; i++) {
  321. if (colorinfo[i].name)
  322. G_free(colorinfo[i].name);
  323. if (colorinfo[i].desc)
  324. G_free(colorinfo[i].desc);
  325. if (colorinfo[i].type)
  326. G_free(colorinfo[i].type);
  327. }
  328. if (nrules > 0)
  329. G_free(colorinfo);
  330. }