1 /* grCmap.c -
2 *
3 * *********************************************************************
4 * * Copyright (C) 1985, 1990 Regents of the University of California. *
5 * * Permission to use, copy, modify, and distribute this *
6 * * software and its documentation for any purpose and without *
7 * * fee is hereby granted, provided that the above copyright *
8 * * notice appear in all copies. The University of California *
9 * * makes no representations about the suitability of this *
10 * * software for any purpose. It is provided "as is" without *
11 * * express or implied warranty. Export of this software outside *
12 * * of the United States of America may require an export license. *
13 * *********************************************************************
14 *
15 * This file provides routines that manipulate the color map on behalf
16 * of the magic design system.
17 */
18
19 #ifndef lint
20 static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/graphics/grCMap.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
21 #endif /* not lint */
22
23 #include <stdio.h>
24 #include <string.h>
25
26 #include "utils/magic.h"
27 #include "utils/malloc.h"
28 #include "utils/geometry.h"
29 #include "tiles/tile.h"
30 #include "utils/hash.h"
31 #include "database/database.h"
32 #include "windows/windows.h"
33 #include "graphics/graphics.h"
34 #include "graphics/graphicsInt.h"
35 #include "utils/utils.h"
36 #include "textio/textio.h"
37
38 static colorEntry *colorMap = NULL; /* Storage for the color map. */
39 int GrNumColors = 0; /* Number of colors */
40
41
42 /*-----------------------------------------------------------------------------
43 *
44 * GrResetCMap --
45 *
46 * Free memory associated with the colormap in preparation for
47 * rereading the colormap file or reading a different colormap file.
48 *
49 * Results:
50 * None.
51 *
52 * Side Effects:
53 * Currently does nothing; size of colormap structures are fixed.
54 *
55 *-----------------------------------------------------------------------------
56 */
57
58 void
GrResetCMap()59 GrResetCMap()
60 {
61 int i;
62 colorEntry *ce;
63
64 if (colorMap == NULL || GrNumColors == 0) return;
65
66 for (i = 0; i < GrNumColors; i++)
67 {
68 ce = colorMap + i;
69 if (ce->name != NULL)
70 freeMagic(ce->name);
71 }
72 freeMagic(colorMap);
73 colorMap = NULL;
74 GrNumColors = 0;
75 }
76
77
78 /*-----------------------------------------------------------------------------
79 * GrReadCmap:
80 *
81 * This routine initializes the color map values from the data
82 * given in a file.
83 *
84 * Results:
85 * The return value is TRUE if the color map was successfully
86 * loaded, and FALSE otherwise.
87 *
88 * Side Effects:
89 * The color map is read from the file and loaded into the graphics
90 * display. The name of the color map file is x.y.z.cmap, where
91 * x is techStyle, y is dispType, and z is monType.
92 *
93 * Design:
94 * The format of the file is one or more lines of the form
95 * <red> <green> <blue> <max location>. When the first line
96 * is read in, the given red, green, and blue values are used
97 * to fill locations 0 - <max location> in the color map. Then
98 * the next line is used to fill from there to the next max location,
99 * which must be larger than the first, and so on. The last
100 * <max location> is expected to be 255.
101 *-----------------------------------------------------------------------------
102 */
103
104 bool
GrReadCMap(techStyle,dispType,monType,path,libPath)105 GrReadCMap(techStyle, dispType, monType, path, libPath)
106 char *techStyle; /* The type of dstyle file requested by
107 * the current technology.
108 */
109 char *dispType; /* A class of color map files for one or
110 * more display types. Usually this
111 * is defaulted to NULL, in which case the
112 * type required by the current driver is
113 * used. If the current driver lists a
114 * NULL type, it means no color map is
115 * needed at all (it's a black-and-white
116 * display), so nothing is loaded.
117 */
118 char *monType; /* The class of monitors being used. Usually
119 * given as "std".
120 */
121 char *path; /* a search path */
122 char *libPath; /* a library search path */
123
124 {
125 FILE *f;
126 int max, red, green, blue, newmax, argc, i;
127 colorEntry *ce;
128 char fullName[256], inputLine[128], colorName[100];
129
130 if (dispType == NULL)
131 {
132 if (grCMapType == NULL) return TRUE;
133 dispType = grCMapType;
134 }
135 (void) sprintf(fullName, "%.80s.%.80s.%.80s", techStyle,
136 dispType, monType);
137
138 f = PaOpen(fullName, "r", ".cmap", path, libPath, (char **) NULL);
139 if (f == NULL)
140 {
141 /* Check for original ".cmap1" file (prior to magic v. 7.2.27) */
142 f = PaOpen(fullName, "r", ".cmap1", path, libPath, (char **) NULL);
143 if (f == NULL)
144 {
145 TxError("Couldn't open color map file \"%s.cmap\"\n", fullName);
146 return FALSE;
147 }
148 }
149
150 /* Reset original colormap if necessary */
151 GrResetCMap();
152
153 /* Get maximum color entry from file (1st pass) */
154
155 max = 0;
156 while (fgets(inputLine, 128, f) != NULL)
157 {
158 argc = sscanf(inputLine, "%*d %*d %*d %d", &newmax);
159 if (argc == 0)
160 {
161 /* Allow comment lines */
162 if (*inputLine == '#') continue;
163
164 TxError("Syntax error in color map file \"%s.cmap\"\n", fullName);
165 TxError("Last color read was index %d\n", max);
166 return FALSE;
167 }
168 else
169 {
170 if (newmax > max)
171 max = newmax;
172 }
173 }
174 rewind(f);
175 colorMap = (colorEntry *)mallocMagic((max + 1) * sizeof(colorEntry));
176 GrNumColors = max + 1;
177
178 /* Read data into colorMap (2nd pass) */
179
180 for (i = 0; i < GrNumColors; )
181 {
182 if (fgets(inputLine, 128, f) == NULL)
183 {
184 TxError("Premature end-of-file in color map file \"%s.cmap\"\n",
185 fullName);
186 break;
187 }
188 if ((argc = sscanf(inputLine, "%d %d %d %d %99[^\n]",
189 &red, &green, &blue, &newmax, colorName)) < 4)
190 {
191 /* Allow comment lines */
192 if (*inputLine == '#') continue;
193
194 TxError("Syntax error in color map file \"%s.cmap\"\n", fullName);
195 TxError("Expecting to read color index %d\n", i);
196 break;
197 }
198 else if (newmax < i)
199 {
200 TxError("Colors in map are out of order!\n");
201 break;
202 }
203
204 for (; i <= newmax; i++)
205 {
206 ce = colorMap + i;
207 ce->red = (unsigned char)(red & 0xff);
208 ce->green = (unsigned char)(green & 0xff);
209 ce->blue = (unsigned char)(blue & 0xff);
210 if (argc == 5)
211 ce->name = StrDup(NULL, colorName);
212 else
213 ce->name = NULL;
214 }
215 }
216
217 fclose(f);
218 if (i < GrNumColors) return FALSE;
219
220 GrSetCMap();
221 return TRUE;
222 }
223
224
225 /*-----------------------------------------------------------------------------
226 * GrSaveCMap
227 *
228 * CMSave will save the current contents of the color map in a file
229 * so that it can be read back in later with GrLoadCMap.
230 *
231 * Results:
232 * TRUE is returned if the color map was successfully saved. Otherwise
233 * FALSE is returned. The file that's actually modified is x.y.z.cmap,
234 * where x is techStyle, y is dispType, and z is monType.
235 *
236 * Side Effects:
237 * The file is overwritten with the color map values in the form
238 * described above under GrLoadCMap.
239 *-----------------------------------------------------------------------------
240 */
241
242 bool
GrSaveCMap(techStyle,dispType,monType,path,libPath)243 GrSaveCMap(techStyle, dispType, monType, path, libPath)
244 char *techStyle; /* The type of dstyle file requested by
245 * the current technology.
246 */
247 char *dispType; /* A class of color map files for one or
248 * more display types. Usually this
249 * is defaulted to NULL, in which case the
250 * type required by the current driver is
251 * used.
252 */
253 char *monType; /* The class of monitors being used. Usually
254 * given as "std".
255 */
256 char *path; /* a search path */
257 char *libPath; /* a library search path */
258
259 {
260 FILE *f;
261 colorEntry *ce, *ce2;
262 int red, green, blue;
263 int i;
264 char fullName[256];
265
266 if (dispType == NULL) dispType = grCMapType;
267 (void) sprintf(fullName, "%.80s.%.80s.%.80s", techStyle,
268 dispType, monType);
269 f = PaOpen(fullName, "w", ".cmap", path, libPath, (char **) NULL);
270 if (f == NULL)
271 {
272 TxError("Couldn't write color map file \"%s.cmap\"\n", fullName);
273 return FALSE;
274 }
275
276 for (i = 0; i < GrNumColors; i++)
277 {
278 ce = colorMap + i;
279 red = (int)ce->red;
280 green = (int)ce->green;
281 blue = (int)ce->blue;
282
283 while (i < (GrNumColors - 1))
284 {
285 ce2 = colorMap + i + 1;
286 if ((red != (int)ce2->red) || (green != (int)ce2->green)
287 || (blue != (int)ce2->blue))
288 break;
289 i++;
290 }
291
292 fprintf(f, "%d %d %d %d", red, green, blue, i);
293 if (ce->name != NULL)
294 fprintf(f, " %s", ce->name);
295 fprintf(f, "\n");
296 }
297 (void) fclose(f);
298 return TRUE;
299 }
300
301 /*
302 *-----------------------------------------------------------------------------
303 * GrNameToColor --
304 *
305 * Get the index of a specific named color, as named in the
306 * colormap file.
307 *
308 * Results:
309 * The index of the named color, or -1 if there is no match.
310 *
311 * Side Effects:
312 * None.
313 *
314 *-----------------------------------------------------------------------------
315 */
316
317 int
GrNameToColor(colorname)318 GrNameToColor(colorname)
319 char *colorname;
320 {
321 int i;
322 colorEntry *ce;
323
324 for (i = 0; i < GrNumColors; i++)
325 {
326 ce = colorMap + i;
327 if (ce->name == NULL) continue;
328 else if (!strcmp(colorname, ce->name))
329 return i;
330 }
331 return -1;
332 }
333
334 /*
335 *-----------------------------------------------------------------------------
336 * GrGetColor --
337 * reads a color value out of the map.
338 *
339 * Results:
340 * TRUE on success, FALSE on passing an illegal color index.
341 *
342 * Side Effects:
343 * The values of red, green, and blue are overwritten with the
344 * red, green, and blue intensities for the color indicated by
345 * layer.
346 *-----------------------------------------------------------------------------
347 */
348
349 bool
GrGetColor(color,red,green,blue)350 GrGetColor(color, red, green, blue)
351 int color; /* Color to be read. */
352 int *red, *green, *blue; /* Pointers to values of color elements. */
353 {
354 colorEntry *ce;
355
356 if (color >= GrNumColors) return FALSE;
357
358 ce = colorMap + color;
359 *red = (int)ce->red;
360 *green = (int)ce->green;
361 *blue = (int)ce->blue;
362 return TRUE;
363 }
364
365
366 /*-----------------------------------------------------------------------------
367 * GrPutColor --
368 * modifies the color map values for a single layer spec.
369 *
370 * Results:
371 * TRUE on success, FALSE on passing an illegal color index.
372 *
373 * Side Effects:
374 * The indicated color is modified to have the given red, green, and
375 * blue intensities.
376 *-----------------------------------------------------------------------------
377 */
378
379 bool
GrPutColor(color,red,green,blue)380 GrPutColor(color, red, green, blue)
381 int color; /* Color to be changed. */
382 int red, green, blue; /* New intensities for color. */
383 {
384 colorEntry *ce;
385
386 if (color >= GrNumColors) return FALSE;
387
388 ce = colorMap + color;
389 ce->red = (unsigned char)(red & 0xff);
390 ce->green = (unsigned char)(green & 0xff);
391 ce->blue = (unsigned char)(blue & 0xff);
392 if (ce->name != NULL)
393 {
394 freeMagic(ce->name);
395 ce->name = NULL;
396 }
397 GrSetCMap();
398 return TRUE;
399 }
400
401
402 /*-----------------------------------------------------------------------------
403 * GrPutManyColors --
404 *
405 * Stores a new set of intensities in all portions of the map
406 * which contain a given set of color bits.
407 *
408 * Results:
409 * None.
410 *
411 * Side Effects:
412 * The color map entries for all layer combinations containing at
413 * least the bits in layers are reset to have the values given by
414 * red, green, and blue. For example, if layers is 1 then all odd
415 * map entries are changed. If layers is 3, every fourth map entry
416 * is changed, and if layers is 0 then all entries are changed. This
417 * routine is a little tricky because if an opaque layer is present,
418 * then the six mask color bits must match exactly, since the opaque
419 * layer obscures ones beneath it.
420 *-----------------------------------------------------------------------------
421 */
422
423 void
GrPutManyColors(color,red,green,blue,opaqueBit)424 GrPutManyColors(color, red, green, blue, opaqueBit)
425 int color; /* A specification of colors to be modified. */
426 int red, green, blue; /* New intensity values. */
427 int opaqueBit; /* The opaque/transparent bit. It is assumed
428 * that the opaque layer colors or
429 * transparent layer bits lie to the right
430 * of the opaque/transparent bit.
431 */
432
433 {
434 int i;
435 int mask = color;
436
437 /* if a transparent layer */
438 if (color & (opaqueBit + opaqueBit - 1)) mask |= opaqueBit;
439
440 /* if a opaque layer */
441 if (color & opaqueBit) mask |= (opaqueBit - 1);
442
443 for (i = 0; i < GrNumColors; i++)
444 if ((i & mask) == color)
445 (void) GrPutColor(i, red, green, blue);
446
447 GrSetCMap();
448 }
449