00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <stdio.h>
00024 #include <grass/gis.h>
00025 #include <grass/glocale.h>
00026
00027 struct rule
00028 {
00029 int set;
00030 int r, g, b;
00031 DCELL val;
00032 };
00033
00034 enum rule_error
00035 {
00036 CR_OK = 0,
00037 CR_ERROR_SYNTAX,
00038 CR_ERROR_RGB,
00039 CR_ERROR_COLOR,
00040 CR_ERROR_PERCENT,
00041 CR_ERROR_VALUE,
00042 };
00043
00044 int G_parse_color_rule(DCELL min, DCELL max, const char *buf,
00045 DCELL * val, int *r, int *g, int *b,
00046 int *norm, int *nval, int *dflt)
00047 {
00048 char value[80], color[80];
00049 double x;
00050 char c;
00051
00052 *norm = *nval = *dflt = 0;
00053
00054 if (sscanf(buf, "%s %[^\n]", value, color) != 2)
00055 return CR_ERROR_SYNTAX;
00056
00057 G_chop(color);
00058
00059 if (sscanf(color, "%d:%d:%d", r, g, b) == 3 ||
00060 sscanf(color, "%d %d %d", r, g, b) == 3) {
00061 if (*r < 0 || *r > 255 || *g < 0 || *g > 255 || *b < 0 || *b > 255)
00062 return CR_ERROR_RGB;
00063 }
00064 else {
00065 float fr, fg, fb;
00066
00067 if (G_color_values(color, &fr, &fg, &fb) < 0)
00068 return CR_ERROR_COLOR;
00069
00070 *r = (int)(fr * 255.99);
00071 *g = (int)(fg * 255.99);
00072 *b = (int)(fb * 255.99);
00073 }
00074
00075 G_chop(value);
00076
00077 if (G_strcasecmp(value, "default") == 0) {
00078 *dflt = 1;
00079 return CR_OK;
00080 }
00081
00082 if (G_strcasecmp(value, "nv") == 0) {
00083 *nval = 1;
00084 return CR_OK;
00085 }
00086
00087 if (sscanf(value, "%lf%c", &x, &c) == 2 && c == '%') {
00088 if (x < 0 || x > 100)
00089 return CR_ERROR_PERCENT;
00090
00091 *val = min + (max - min) * (x / 100);
00092 *norm = 1;
00093 return CR_OK;
00094 }
00095
00096 if (sscanf(value, "%lf", val) == 1) {
00097 *norm = 1;
00098 return CR_OK;
00099 }
00100
00101 return CR_ERROR_VALUE;
00102 }
00103
00104 const char *G_parse_color_rule_error(int code)
00105 {
00106 switch (code) {
00107 case CR_OK:
00108 return "";
00109 case CR_ERROR_SYNTAX:
00110 return _("syntax error");
00111 case CR_ERROR_RGB:
00112 return _("R/G/B not in range 0-255");
00113 case CR_ERROR_COLOR:
00114 return _("invalid color name");
00115 case CR_ERROR_PERCENT:
00116 return _("percentage not in range 0-100");
00117 case CR_ERROR_VALUE:
00118 return _("invalid value");
00119 default:
00120 return _("unknown error");
00121 }
00122 }
00123
00124 int G_read_color_rule(void *closure, DCELL min, DCELL max,
00125 DCELL * val, int *r, int *g, int *b,
00126 int *norm, int *nval, int *dflt)
00127 {
00128 char buf[1024];
00129 FILE *fp = closure;
00130 int ret;
00131
00132 *norm = *nval = *dflt = 0;
00133
00134 for (;;) {
00135 if (!G_getl2(buf, sizeof(buf), fp))
00136 return 0;
00137
00138 G_strip(buf);
00139 G_debug(5, "color buf = [%s]", buf);
00140
00141 if (*buf == '\0')
00142 continue;
00143 if (*buf == '#')
00144 continue;
00145
00146 ret =
00147 G_parse_color_rule(min, max, buf, val, r, g, b, norm, nval, dflt);
00148 if (ret == 0)
00149 return 1;
00150
00151 G_fatal_error(_("bad rule (%s): [%s]"),
00152 G_parse_color_rule_error(ret), buf);
00153 }
00154
00155 return 0;
00156 }
00157
00158 int G_read_color_rules(struct Colors *colors, DCELL min, DCELL max,
00159 read_rule_fn * read_rule, void *closure)
00160 {
00161 struct rule *rule = NULL;
00162 int nrules = 0;
00163 struct rule dflt, null;
00164 int set, is_null, is_dflt, r, g, b;
00165 DCELL val;
00166 int n;
00167
00168 if (!read_rule)
00169 read_rule = G_read_color_rule;
00170
00171 G_init_colors(colors);
00172
00173
00174 dflt.r = dflt.g = dflt.b = dflt.set = 0;
00175 null.r = null.g = null.b = null.set = 0;
00176
00177 while ((*read_rule)
00178 (closure, min, max, &val, &r, &g, &b, &set, &is_null, &is_dflt)) {
00179 struct rule *p;
00180
00181 if (set) {
00182 n = nrules++;
00183 rule = G_realloc(rule, nrules * sizeof(struct rule));
00184 p = &rule[n];
00185 }
00186 else if (is_dflt)
00187 p = &dflt;
00188 else if (is_null)
00189 p = &null;
00190
00191 p->r = r;
00192 p->g = g;
00193 p->b = b;
00194 p->set = 1;
00195 p->val = val;
00196 }
00197
00198 if (nrules == 0)
00199 return 0;
00200
00201 if (nrules == 1) {
00202 const struct rule *p = &rule[0];
00203
00204 G_set_d_color(p->val, p->r, p->g, p->b, colors);
00205 }
00206
00207 for (n = 1; n < nrules; n++) {
00208 struct rule *lo = &rule[n - 1];
00209 struct rule *hi = &rule[n];
00210
00211 G_add_d_raster_color_rule(&lo->val, lo->r, lo->g, lo->b,
00212 &hi->val, hi->r, hi->g, hi->b, colors);
00213 }
00214
00215
00216 if (null.set)
00217 G_set_null_value_color(null.r, null.g, null.b, colors);
00218
00219 if (dflt.set)
00220 G_set_default_color(dflt.r, dflt.g, dflt.b, colors);
00221
00222 return 1;
00223 }
00224
00225 static int load_rules_file(struct Colors *colors, const char *path, DCELL min,
00226 DCELL max)
00227 {
00228 FILE *fp;
00229 int ret;
00230
00231 fp = fopen(path, "r");
00232
00233 if (!fp)
00234 return 0;
00235
00236 ret = G_read_color_rules(colors, min, max, G_read_color_rule, (void *)fp);
00237
00238 fclose(fp);
00239
00240 return ret;
00241 }
00242
00243 int G_load_colors(struct Colors *colors, const char *path, CELL min, CELL max)
00244 {
00245 return load_rules_file(colors, path, (DCELL) min, (DCELL) max);
00246 }
00247
00248 int G_load_fp_colors(struct Colors *colors, const char *path, DCELL min,
00249 DCELL max)
00250 {
00251 return load_rules_file(colors, path, min, max);
00252 }
00253
00254 static int load_rules_name(struct Colors *colors, const char *name, DCELL min,
00255 DCELL max)
00256 {
00257 char path[GPATH_MAX];
00258
00259 sprintf(path, "%s/etc/colors/%s", G_gisbase(), name);
00260
00261 return load_rules_file(colors, path, min, max);
00262 }
00263
00264 int G_make_colors(struct Colors *colors, const char *name, CELL min, CELL max)
00265 {
00266 return load_rules_name(colors, name, (DCELL) min, (DCELL) max);
00267 }
00268
00269 int G_make_fp_colors(struct Colors *colors, const char *name, DCELL min,
00270 DCELL max)
00271 {
00272 return load_rules_name(colors, name, min, max);
00273 }