BRL-CAD
color.c
Go to the documentation of this file.
1 /* C O L O R . C
2  * BRL-CAD
3  *
4  * Copyright (c) 2008-2014 United States Government as represented by
5  * the U.S. Army Research Laboratory.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * version 2.1 as published by the Free Software Foundation.
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this file; see the file named COPYING for more
18  * information.
19  */
20 /** @file libged/color.c
21  *
22  * The color command.
23  *
24  */
25 
26 #include "common.h"
27 
28 #include <stdlib.h>
29 #include <ctype.h>
30 #include <string.h>
31 
32 #include "bu/getopt.h"
33 #include "ged.h"
34 #include "db.h"
35 #include "mater.h"
36 
37 #include "./ged_private.h"
38 
39 
40 /**
41  * Used to create a database record and get it written out to a granule.
42  * In some cases, storage will need to be allocated.
43  */
44 void
45 color_putrec(struct ged *gedp, struct mater *mp)
46 {
47  struct directory dir;
48  union record rec;
49 
50  /* we get here only if database is NOT read-only */
51 
52  rec.md.md_id = ID_MATERIAL;
53  rec.md.md_low = mp->mt_low;
54  rec.md.md_hi = mp->mt_high;
55  rec.md.md_r = mp->mt_r;
56  rec.md.md_g = mp->mt_g;
57  rec.md.md_b = mp->mt_b;
58 
59  /* Fake up a directory entry for db_* routines */
60  RT_DIR_SET_NAMEP(&dir, "color_putrec");
61  dir.d_magic = RT_DIR_MAGIC;
62  dir.d_flags = 0;
63 
64  if (mp->mt_daddr == MATER_NO_ADDR) {
65  /* Need to allocate new database space */
66  if (db_alloc(gedp->ged_wdbp->dbip, &dir, 1)) {
67  bu_vls_printf(gedp->ged_result_str, "Database alloc error, aborting");
68  return;
69  }
70  mp->mt_daddr = dir.d_addr;
71  } else {
72  dir.d_addr = mp->mt_daddr;
73  dir.d_len = 1;
74  }
75 
76  if (db_put(gedp->ged_wdbp->dbip, &dir, &rec, 0, 1)) {
77  bu_vls_printf(gedp->ged_result_str, "Database write error, aborting");
78  return;
79  }
80 }
81 
82 
83 /**
84  * Used to release database resources occupied by a material record.
85  */
86 void
87 color_zaprec(struct ged *gedp, struct mater *mp)
88 {
89  struct directory dir;
90 
91  /* we get here only if database is NOT read-only */
92  if (mp->mt_daddr == MATER_NO_ADDR)
93  return;
94 
95  dir.d_magic = RT_DIR_MAGIC;
96  RT_DIR_SET_NAMEP(&dir, "color_zaprec");
97  dir.d_len = 1;
98  dir.d_addr = mp->mt_daddr;
99  dir.d_flags = 0;
100 
101  if (db_delete(gedp->ged_wdbp->dbip, &dir) != 0) {
102  bu_vls_printf(gedp->ged_result_str, "Database delete error, aborting");
103  return;
104  }
105  mp->mt_daddr = MATER_NO_ADDR;
106 }
107 
108 
109 /*
110  * used by the 'color' command when provided the -e option
111  */
112 static int
113 edcolor(struct ged *gedp, int argc, const char *argv[])
114 {
115  struct mater *mp;
116  struct mater *zot;
117  FILE *fp;
118  int c;
119  char line[128];
120  static char hdr[] = "LOW\tHIGH\tRed\tGreen\tBlue\n";
121  char tmpfil[MAXPATHLEN];
122  char *editstring = NULL;
123 
126  GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR);
127 
128  bu_optind = 1;
129  /* First, grab the editstring off of the argv list */
130  while ((c = bu_getopt(argc, (char * const *)argv, "E:")) != -1) {
131  switch (c) {
132  case 'E' :
133  editstring = bu_optarg;
134  break;
135  default :
136  break;
137  }
138  }
139 
140  argc -= bu_optind - 1;
141  argv += bu_optind - 1;
142 
143  /* initialize result */
144  bu_vls_trunc(gedp->ged_result_str, 0);
145 
146  fp = bu_temp_file(tmpfil, MAXPATHLEN);
147  if (fp == NULL) {
148  bu_vls_printf(gedp->ged_result_str, "%s: could not create tmp file", argv[0]);
149  return GED_ERROR;
150  }
151 
152  fprintf(fp, "%s", hdr);
153  for (mp = rt_material_head(); mp != MATER_NULL; mp = mp->mt_forw) {
154  fprintf(fp, "%d\t%d\t%3d\t%3d\t%3d",
155  mp->mt_low, mp->mt_high,
156  mp->mt_r, mp->mt_g, mp->mt_b);
157  fprintf(fp, "\n");
158  }
159  (void)fclose(fp);
160 
161  if (!_ged_editit(editstring, (const char *)tmpfil)) {
162  bu_vls_printf(gedp->ged_result_str, "%s: editor returned bad status. Aborted\n", argv[0]);
163  return GED_ERROR;
164  }
165 
166  /* Read file and process it */
167  if ((fp = fopen(tmpfil, "r")) == NULL) {
168  perror(tmpfil);
169  return GED_ERROR;
170  }
171 
172  if (bu_fgets(line, sizeof (line), fp) == NULL ||
173  line[0] != hdr[0]) {
174  bu_vls_printf(gedp->ged_result_str, "%s: Header line damaged, aborting\n", argv[0]);
175  (void)fclose(fp);
176  return GED_ERROR;
177  }
178 
179  if (db_version(gedp->ged_wdbp->dbip) < 5) {
180  /* Zap all the current records, both in core and on disk */
181  while (rt_material_head() != MATER_NULL) {
182  zot = rt_material_head();
183  rt_new_material_head(zot->mt_forw);
184  color_zaprec(gedp, zot);
185  bu_free((void *)zot, "mater rec");
186  }
187 
188  while (bu_fgets(line, sizeof (line), fp) != NULL) {
189  int cnt;
190  int low, hi, r, g, b;
191 
192  /* character-separated numbers (ideally a space) */
193  cnt = sscanf(line, "%d%*c%d%*c%d%*c%d%*c%d",
194  &low, &hi, &r, &g, &b);
195  if (cnt != 9) {
196  bu_vls_printf(gedp->ged_result_str, "%s: Discarding %s\n", argv[0], line);
197  continue;
198  }
199  BU_ALLOC(mp, struct mater);
200  mp->mt_low = low;
201  mp->mt_high = hi;
202  mp->mt_r = r;
203  mp->mt_g = g;
204  mp->mt_b = b;
205  mp->mt_daddr = MATER_NO_ADDR;
206  rt_insert_color(mp);
207  color_putrec(gedp, mp);
208  }
209  } else {
210  struct bu_vls vls = BU_VLS_INIT_ZERO;
211 
212  /* free colors in rt_material_head */
213  rt_color_free();
214 
215  while (bu_fgets(line, sizeof (line), fp) != NULL) {
216  int cnt;
217  int low, hi, r, g, b;
218 
219  /* character-separated numbers (ideally a space) */
220  cnt = sscanf(line, "%d%*c%d%*c%d%*c%d%*c%d",
221  &low, &hi, &r, &g, &b);
222 
223  /* check to see if line is reasonable */
224  if (cnt != 5) {
225  bu_vls_printf(gedp->ged_result_str, "%s: Discarding %s\n", argv[0], line);
226  continue;
227  }
228  bu_vls_printf(&vls, "{%d %d %d %d %d} ", low, hi, r, g, b);
229  }
230 
231  db5_update_attribute("_GLOBAL", "regionid_colortable", bu_vls_addr(&vls), gedp->ged_wdbp->dbip);
233  bu_vls_free(&vls);
234  }
235 
236  (void)fclose(fp);
237  bu_file_delete(tmpfil);
238 
239  /* if there are drawables, update their colors */
240  if (gedp->ged_gdp)
242 
243  return GED_OK;
244 }
245 
246 
247 int
248 ged_edcolor(struct ged *gedp, int argc, const char *argv[])
249 {
252  GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR);
253 
254  /* initialize result */
255  bu_vls_trunc(gedp->ged_result_str, 0);
256 
257  if (argc != 3) {
258  bu_vls_printf(gedp->ged_result_str, "Usage: %s", argv[0]);
259  return GED_ERROR;
260  }
261 
262  return edcolor(gedp, argc, argv);
263 }
264 
265 
266 int
267 ged_color(struct ged *gedp, int argc, const char *argv[])
268 {
269  struct mater *newp;
270  struct mater *mp;
271  struct mater *next_mater;
272  static const char *usage = "[-e] [low high r g b]";
273 
276  GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR);
277 
278  /* initialize result */
279  bu_vls_trunc(gedp->ged_result_str, 0);
280 
281  /* must be wanting help */
282  if (argc == 1) {
283  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
284  return GED_HELP;
285  }
286 
287  if (argc != 6 && argc != 2) {
288  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
289  return GED_ERROR;
290  }
291 
292  /* edcolor */
293  if (argc == 2) {
294  if (argv[1][0] == '-' && argv[1][1] == 'e' && argv[1][2] == '\0') {
295  return edcolor(gedp, argc, argv);
296  } else {
297  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
298  return GED_ERROR;
299  }
300  }
301 
302  if (db_version(gedp->ged_wdbp->dbip) < 5) {
303  /* Delete all color records from the database */
304  mp = rt_material_head();
305  while (mp != MATER_NULL) {
306  next_mater = mp->mt_forw;
307  color_zaprec(gedp, mp);
308  mp = next_mater;
309  }
310 
311  /* construct the new color record */
312  BU_ALLOC(newp, struct mater);
313  newp->mt_low = atoi(argv[1]);
314  newp->mt_high = atoi(argv[2]);
315  newp->mt_r = atoi(argv[3]);
316  newp->mt_g = atoi(argv[4]);
317  newp->mt_b = atoi(argv[5]);
318  newp->mt_daddr = MATER_NO_ADDR; /* not in database yet */
319 
320  /* Insert new color record in the in-memory list */
321  rt_insert_color(newp);
322 
323  /* Write new color records for all colors in the list */
324  mp = rt_material_head();
325  while (mp != MATER_NULL) {
326  next_mater = mp->mt_forw;
327  color_putrec(gedp, mp);
328  mp = next_mater;
329  }
330  } else {
331  struct bu_vls colors = BU_VLS_INIT_ZERO;
332 
333  /* construct the new color record */
334  BU_ALLOC(newp, struct mater);
335  newp->mt_low = atoi(argv[1]);
336  newp->mt_high = atoi(argv[2]);
337  newp->mt_r = atoi(argv[3]);
338  newp->mt_g = atoi(argv[4]);
339  newp->mt_b = atoi(argv[5]);
340  newp->mt_daddr = MATER_NO_ADDR; /* not in database yet */
341 
342  /* Insert new color record in the in-memory list */
343  rt_insert_color(newp);
344 
345  /*
346  * Gather color records from the in-memory list to build
347  * the _GLOBAL objects regionid_colortable attribute.
348  */
349  rt_vls_color_map(&colors);
350 
351  db5_update_attribute("_GLOBAL", "regionid_colortable", bu_vls_addr(&colors), gedp->ged_wdbp->dbip);
352  bu_vls_free(&colors);
353  }
354 
355  return GED_OK;
356 }
357 
358 
359 /*
360  * Local Variables:
361  * tab-width: 8
362  * mode: C
363  * indent-tabs-mode: t
364  * c-file-style: "stroustrup"
365  * End:
366  * ex: shiftwidth=4 tabstop=8
367  */
void usage(struct ged *gedp)
Definition: coil.c:315
#define GED_OK
Definition: ged.h:55
int ged_color(struct ged *gedp, int argc, const char *argv[])
Definition: color.c:267
#define RT_DIR_SET_NAMEP(_dp, _name)
Definition: raytrace.h:901
size_t d_len
of db granules used
Definition: raytrace.h:867
Definition: ged.h:338
void dl_color_soltab(struct bu_list *hdlp)
Definition: display_list.c:573
struct db_i * dbip
Definition: raytrace.h:1266
void bu_vls_trunc(struct bu_vls *vp, int len)
Definition: vls.c:198
#define GED_CHECK_ARGC_GT_0(_gedp, _argc, _flags)
Definition: ged.h:202
int db_version(struct db_i *dbip)
Definition: db5_scan.c:414
int ged_edcolor(struct ged *gedp, int argc, const char *argv[])
Definition: color.c:248
struct rt_wdb * ged_wdbp
Definition: ged.h:340
char * bu_optarg
Definition: globals.c:91
Header file for the BRL-CAD common definitions.
int bu_optind
Definition: globals.c:89
uint32_t d_magic
Magic number.
Definition: raytrace.h:858
int bu_getopt(int nargc, char *const nargv[], const char *ostr)
Definition: getopt.c:43
struct bu_list * gd_headDisplay
head of display list
Definition: ged.h:307
#define GED_ERROR
Definition: ged.h:61
void bu_vls_free(struct bu_vls *vp)
Definition: vls.c:248
void rt_insert_color(struct mater *newp)
Definition: mater.c:95
void color_putrec(struct ged *gedp, struct mater *mp)
Definition: color.c:45
#define GED_CHECK_DATABASE_OPEN(_gedp, _flags)
Definition: ged.h:114
#define BU_ALLOC(_ptr, _type)
Definition: malloc.h:223
int db_alloc(struct db_i *, struct directory *dp, size_t count)
FILE * bu_temp_file(char *filepath, size_t len)
Definition: temp.c:180
void rt_vls_color_map(struct bu_vls *str)
Definition: mater.c:221
void rt_new_material_head(struct mater *newmat)
Definition: mater.c:253
char * bu_vls_addr(const struct bu_vls *vp)
Definition: vls.c:111
struct bu_vls * ged_result_str
Definition: ged.h:357
struct ged_drawable * ged_gdp
Definition: ged.h:360
struct mater * rt_material_head(void)
Definition: mater.c:243
void db5_import_color_table(char *cp)
Definition: db5_io.c:996
int _ged_editit(char *editstring, const char *filename)
Definition: editit.c:49
int db_put(struct db_i *, const struct directory *dp, union record *where, off_t offset, size_t len)
Definition: db_io.c:212
void bu_vls_printf(struct bu_vls *vls, const char *fmt,...) _BU_ATTR_PRINTF23
Definition: vls.c:694
#define GED_HELP
Definition: ged.h:62
void bu_free(void *ptr, const char *str)
Definition: malloc.c:328
#define RT_DIR_MAGIC
Definition: magic.h:159
char * bu_fgets(char *s, int size, FILE *stream)
Definition: fgets.c:31
#define BU_VLS_INIT_ZERO
Definition: vls.h:84
#define GED_CHECK_READ_ONLY(_gedp, _flags)
Definition: ged.h:181
int d_flags
flags
Definition: raytrace.h:869
Definition: vls.h:56
void color_zaprec(struct ged *gedp, struct mater *mp)
Definition: color.c:87
int db_delete(struct db_i *, struct directory *dp)
Definition: db_alloc.c:132
void rt_color_free(void)
Definition: mater.c:294
int db5_update_attribute(const char *obj_name, const char *aname, const char *value, struct db_i *dbip)
Definition: attributes.c:365
int bu_file_delete(const char *path)
Definition: file.c:278
#define MAXPATHLEN
Definition: defines.h:113