453 lines
12 KiB
C
453 lines
12 KiB
C
/* grCmap.c -
|
|
*
|
|
* *********************************************************************
|
|
* * Copyright (C) 1985, 1990 Regents of the University of California. *
|
|
* * Permission to use, copy, modify, and distribute this *
|
|
* * software and its documentation for any purpose and without *
|
|
* * fee is hereby granted, provided that the above copyright *
|
|
* * notice appear in all copies. The University of California *
|
|
* * makes no representations about the suitability of this *
|
|
* * software for any purpose. It is provided "as is" without *
|
|
* * express or implied warranty. Export of this software outside *
|
|
* * of the United States of America may require an export license. *
|
|
* *********************************************************************
|
|
*
|
|
* This file provides routines that manipulate the color map on behalf
|
|
* of the magic design system.
|
|
*/
|
|
|
|
#ifndef lint
|
|
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 $";
|
|
#endif /* not lint */
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "utils/magic.h"
|
|
#include "utils/malloc.h"
|
|
#include "utils/geometry.h"
|
|
#include "tiles/tile.h"
|
|
#include "utils/hash.h"
|
|
#include "database/database.h"
|
|
#include "windows/windows.h"
|
|
#include "graphics/graphics.h"
|
|
#include "graphics/graphicsInt.h"
|
|
#include "utils/utils.h"
|
|
#include "textio/textio.h"
|
|
|
|
static colorEntry *colorMap = NULL; /* Storage for the color map. */
|
|
int GrNumColors = 0; /* Number of colors */
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
*
|
|
* GrResetCMap --
|
|
*
|
|
* Free memory associated with the colormap in preparation for
|
|
* rereading the colormap file or reading a different colormap file.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side Effects:
|
|
* Currently does nothing; size of colormap structures are fixed.
|
|
*
|
|
*-----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
GrResetCMap()
|
|
{
|
|
int i;
|
|
colorEntry *ce;
|
|
|
|
if (colorMap == NULL || GrNumColors == 0) return;
|
|
|
|
for (i = 0; i < GrNumColors; i++)
|
|
{
|
|
ce = colorMap + i;
|
|
if (ce->name != NULL)
|
|
freeMagic(ce->name);
|
|
}
|
|
freeMagic(colorMap);
|
|
colorMap = NULL;
|
|
GrNumColors = 0;
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* GrReadCmap:
|
|
*
|
|
* This routine initializes the color map values from the data
|
|
* given in a file.
|
|
*
|
|
* Results:
|
|
* The return value is TRUE if the color map was successfully
|
|
* loaded, and FALSE otherwise.
|
|
*
|
|
* Side Effects:
|
|
* The color map is read from the file and loaded into the graphics
|
|
* display. The name of the color map file is x.y.z.cmap, where
|
|
* x is techStyle, y is dispType, and z is monType.
|
|
*
|
|
* Design:
|
|
* The format of the file is one or more lines of the form
|
|
* <red> <green> <blue> <max location>. When the first line
|
|
* is read in, the given red, green, and blue values are used
|
|
* to fill locations 0 - <max location> in the color map. Then
|
|
* the next line is used to fill from there to the next max location,
|
|
* which must be larger than the first, and so on. The last
|
|
* <max location> is expected to be 255.
|
|
*-----------------------------------------------------------------------------
|
|
*/
|
|
|
|
bool
|
|
GrReadCMap(techStyle, dispType, monType, path, libPath)
|
|
char *techStyle; /* The type of dstyle file requested by
|
|
* the current technology.
|
|
*/
|
|
char *dispType; /* A class of color map files for one or
|
|
* more display types. Usually this
|
|
* is defaulted to NULL, in which case the
|
|
* type required by the current driver is
|
|
* used. If the current driver lists a
|
|
* NULL type, it means no color map is
|
|
* needed at all (it's a black-and-white
|
|
* display), so nothing is loaded.
|
|
*/
|
|
char *monType; /* The class of monitors being used. Usually
|
|
* given as "std".
|
|
*/
|
|
char *path; /* a search path */
|
|
char *libPath; /* a library search path */
|
|
|
|
{
|
|
int max, red, green, blue, newmax, argc, i;
|
|
colorEntry *ce;
|
|
char fullName[256], inputLine[128], colorName[100];
|
|
|
|
if (dispType == NULL)
|
|
{
|
|
if (grCMapType == NULL) return TRUE;
|
|
dispType = grCMapType;
|
|
}
|
|
(void) sprintf(fullName, "%.80s.%.80s.%.80s", techStyle,
|
|
dispType, monType);
|
|
|
|
FILE *f = PaOpen(fullName, "r", ".cmap", path, libPath, (char **) NULL);
|
|
if (f == NULL)
|
|
{
|
|
/* Check for original ".cmap1" file (prior to magic v. 7.2.27) */
|
|
f = PaOpen(fullName, "r", ".cmap1", path, libPath, (char **) NULL);
|
|
if (f == NULL)
|
|
{
|
|
TxError("Couldn't open color map file \"%s.cmap\"\n", fullName);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
/* Reset original colormap if necessary */
|
|
GrResetCMap();
|
|
|
|
/* Get maximum color entry from file (1st pass) */
|
|
|
|
max = 0;
|
|
while (fgets(inputLine, 128, f) != NULL)
|
|
{
|
|
argc = sscanf(inputLine, "%*d %*d %*d %d", &newmax);
|
|
if (argc <= 0)
|
|
{
|
|
/* Allow comment lines */
|
|
if (*inputLine == '#') continue;
|
|
|
|
TxError("Syntax error in color map file \"%s.cmap\"\n", fullName);
|
|
TxError("Last color read was index %d\n", max);
|
|
goto cleanup;
|
|
}
|
|
else
|
|
{
|
|
if (newmax > max)
|
|
max = newmax;
|
|
}
|
|
}
|
|
rewind(f);
|
|
colorMap = (colorEntry *)mallocMagic((max + 1) * sizeof(colorEntry));
|
|
GrNumColors = max + 1;
|
|
|
|
/* Read data into colorMap (2nd pass) */
|
|
|
|
for (i = 0; i < GrNumColors; )
|
|
{
|
|
if (fgets(inputLine, 128, f) == NULL)
|
|
{
|
|
TxError("Premature end-of-file in color map file \"%s.cmap\"\n",
|
|
fullName);
|
|
break;
|
|
}
|
|
if ((argc = sscanf(inputLine, "%d %d %d %d %99[^\n]",
|
|
&red, &green, &blue, &newmax, colorName)) < 4)
|
|
{
|
|
/* Allow comment lines */
|
|
if (*inputLine == '#') continue;
|
|
|
|
TxError("Syntax error in color map file \"%s.cmap\"\n", fullName);
|
|
TxError("Expecting to read color index %d\n", i);
|
|
break;
|
|
}
|
|
else if (newmax < i)
|
|
{
|
|
TxError("Colors in map are out of order!\n");
|
|
break;
|
|
}
|
|
|
|
for (; i <= newmax; i++)
|
|
{
|
|
ce = colorMap + i;
|
|
ce->red = (unsigned char)(red & 0xff);
|
|
ce->green = (unsigned char)(green & 0xff);
|
|
ce->blue = (unsigned char)(blue & 0xff);
|
|
if (argc == 5)
|
|
ce->name = StrDup(NULL, colorName);
|
|
else
|
|
ce->name = NULL;
|
|
}
|
|
}
|
|
|
|
fclose(f);
|
|
if (i < GrNumColors) return FALSE;
|
|
|
|
GrSetCMap();
|
|
return TRUE;
|
|
|
|
cleanup:
|
|
if(f)
|
|
fclose(f);
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* GrSaveCMap
|
|
*
|
|
* CMSave will save the current contents of the color map in a file
|
|
* so that it can be read back in later with GrLoadCMap.
|
|
*
|
|
* Results:
|
|
* TRUE is returned if the color map was successfully saved. Otherwise
|
|
* FALSE is returned. The file that's actually modified is x.y.z.cmap,
|
|
* where x is techStyle, y is dispType, and z is monType.
|
|
*
|
|
* Side Effects:
|
|
* The file is overwritten with the color map values in the form
|
|
* described above under GrLoadCMap.
|
|
*-----------------------------------------------------------------------------
|
|
*/
|
|
|
|
bool
|
|
GrSaveCMap(techStyle, dispType, monType, path, libPath)
|
|
char *techStyle; /* The type of dstyle file requested by
|
|
* the current technology.
|
|
*/
|
|
char *dispType; /* A class of color map files for one or
|
|
* more display types. Usually this
|
|
* is defaulted to NULL, in which case the
|
|
* type required by the current driver is
|
|
* used.
|
|
*/
|
|
char *monType; /* The class of monitors being used. Usually
|
|
* given as "std".
|
|
*/
|
|
char *path; /* a search path */
|
|
char *libPath; /* a library search path */
|
|
|
|
{
|
|
FILE *f;
|
|
colorEntry *ce, *ce2;
|
|
int red, green, blue;
|
|
int i;
|
|
char fullName[256];
|
|
|
|
if (dispType == NULL) dispType = grCMapType;
|
|
(void) sprintf(fullName, "%.80s.%.80s.%.80s", techStyle,
|
|
dispType, monType);
|
|
f = PaOpen(fullName, "w", ".cmap", path, libPath, (char **) NULL);
|
|
if (f == NULL)
|
|
{
|
|
TxError("Couldn't write color map file \"%s.cmap\"\n", fullName);
|
|
return FALSE;
|
|
}
|
|
|
|
for (i = 0; i < GrNumColors; i++)
|
|
{
|
|
ce = colorMap + i;
|
|
red = (int)ce->red;
|
|
green = (int)ce->green;
|
|
blue = (int)ce->blue;
|
|
|
|
while (i < (GrNumColors - 1))
|
|
{
|
|
ce2 = colorMap + i + 1;
|
|
if ((red != (int)ce2->red) || (green != (int)ce2->green)
|
|
|| (blue != (int)ce2->blue))
|
|
break;
|
|
i++;
|
|
}
|
|
|
|
fprintf(f, "%d %d %d %d", red, green, blue, i);
|
|
if (ce->name != NULL)
|
|
fprintf(f, " %s", ce->name);
|
|
fprintf(f, "\n");
|
|
}
|
|
(void) fclose(f);
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
*-----------------------------------------------------------------------------
|
|
* GrNameToColor --
|
|
*
|
|
* Get the index of a specific named color, as named in the
|
|
* colormap file.
|
|
*
|
|
* Results:
|
|
* The index of the named color, or -1 if there is no match.
|
|
*
|
|
* Side Effects:
|
|
* None.
|
|
*
|
|
*-----------------------------------------------------------------------------
|
|
*/
|
|
|
|
int
|
|
GrNameToColor(colorname)
|
|
char *colorname;
|
|
{
|
|
int i;
|
|
colorEntry *ce;
|
|
|
|
for (i = 0; i < GrNumColors; i++)
|
|
{
|
|
ce = colorMap + i;
|
|
if (ce->name == NULL) continue;
|
|
else if (!strcmp(colorname, ce->name))
|
|
return i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
*-----------------------------------------------------------------------------
|
|
* GrGetColor --
|
|
* reads a color value out of the map.
|
|
*
|
|
* Results:
|
|
* TRUE on success, FALSE on passing an illegal color index.
|
|
*
|
|
* Side Effects:
|
|
* The values of red, green, and blue are overwritten with the
|
|
* red, green, and blue intensities for the color indicated by
|
|
* layer.
|
|
*-----------------------------------------------------------------------------
|
|
*/
|
|
|
|
bool
|
|
GrGetColor(color, red, green, blue)
|
|
int color; /* Color to be read. */
|
|
int *red, *green, *blue; /* Pointers to values of color elements. */
|
|
{
|
|
colorEntry *ce;
|
|
|
|
if (color >= GrNumColors) return FALSE;
|
|
|
|
ce = colorMap + color;
|
|
*red = (int)ce->red;
|
|
*green = (int)ce->green;
|
|
*blue = (int)ce->blue;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* GrPutColor --
|
|
* modifies the color map values for a single layer spec.
|
|
*
|
|
* Results:
|
|
* TRUE on success, FALSE on passing an illegal color index.
|
|
*
|
|
* Side Effects:
|
|
* The indicated color is modified to have the given red, green, and
|
|
* blue intensities.
|
|
*-----------------------------------------------------------------------------
|
|
*/
|
|
|
|
bool
|
|
GrPutColor(color, red, green, blue)
|
|
int color; /* Color to be changed. */
|
|
int red, green, blue; /* New intensities for color. */
|
|
{
|
|
colorEntry *ce;
|
|
|
|
if (color >= GrNumColors) return FALSE;
|
|
|
|
ce = colorMap + color;
|
|
ce->red = (unsigned char)(red & 0xff);
|
|
ce->green = (unsigned char)(green & 0xff);
|
|
ce->blue = (unsigned char)(blue & 0xff);
|
|
if (ce->name != NULL)
|
|
{
|
|
freeMagic(ce->name);
|
|
ce->name = NULL;
|
|
}
|
|
GrSetCMap();
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* GrPutManyColors --
|
|
*
|
|
* Stores a new set of intensities in all portions of the map
|
|
* which contain a given set of color bits.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side Effects:
|
|
* The color map entries for all layer combinations containing at
|
|
* least the bits in layers are reset to have the values given by
|
|
* red, green, and blue. For example, if layers is 1 then all odd
|
|
* map entries are changed. If layers is 3, every fourth map entry
|
|
* is changed, and if layers is 0 then all entries are changed. This
|
|
* routine is a little tricky because if an opaque layer is present,
|
|
* then the six mask color bits must match exactly, since the opaque
|
|
* layer obscures ones beneath it.
|
|
*-----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
GrPutManyColors(color, red, green, blue, opaqueBit)
|
|
int color; /* A specification of colors to be modified. */
|
|
int red, green, blue; /* New intensity values. */
|
|
int opaqueBit; /* The opaque/transparent bit. It is assumed
|
|
* that the opaque layer colors or
|
|
* transparent layer bits lie to the right
|
|
* of the opaque/transparent bit.
|
|
*/
|
|
|
|
{
|
|
int i;
|
|
int mask = color;
|
|
|
|
/* if a transparent layer */
|
|
if (color & (opaqueBit + opaqueBit - 1)) mask |= opaqueBit;
|
|
|
|
/* if a opaque layer */
|
|
if (color & opaqueBit) mask |= (opaqueBit - 1);
|
|
|
|
for (i = 0; i < GrNumColors; i++)
|
|
if ((i & mask) == color)
|
|
(void) GrPutColor(i, red, green, blue);
|
|
|
|
GrSetCMap();
|
|
}
|