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