diff options
Diffstat (limited to 'unix')
-rwxr-xr-x | unix/tkUnixColor.c | 201 |
1 files changed, 110 insertions, 91 deletions
diff --git a/unix/tkUnixColor.c b/unix/tkUnixColor.c index 722dd06..205056b 100755 --- a/unix/tkUnixColor.c +++ b/unix/tkUnixColor.c @@ -1,46 +1,45 @@ -/* +/* * tkUnixColor.c -- * - * This file contains the platform specific color routines - * needed for X support. + * This file contains the platform specific color routines needed for X + * support. * * Copyright (c) 1996 by Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include <tkColor.h> /* - * If a colormap fills up, attempts to allocate new colors from that - * colormap will fail. When that happens, we'll just choose the - * closest color from those that are available in the colormap. - * One of the following structures will be created for each "stressed" - * colormap to keep track of the colors that are available in the - * colormap (otherwise we would have to re-query from the server on - * each allocation, which would be very slow). These entries are - * flushed after a few seconds, since other clients may release or + * If a colormap fills up, attempts to allocate new colors from that colormap + * will fail. When that happens, we'll just choose the closest color from + * those that are available in the colormap. One of the following structures + * will be created for each "stressed" colormap to keep track of the colors + * that are available in the colormap (otherwise we would have to re-query + * from the server on each allocation, which would be very slow). These + * entries are flushed after a few seconds, since other clients may release or * reallocate colors over time. */ struct TkStressedCmap { - Colormap colormap; /* X's token for the colormap. */ - int numColors; /* Number of entries currently active - * at *colorPtr. */ - XColor *colorPtr; /* Pointer to malloc'ed array of all - * colors that seem to be available in - * the colormap. Some may not actually - * be available, e.g. because they are - * read-write for another client; when - * we find this out, we remove them - * from the array. */ - struct TkStressedCmap *nextPtr; /* Next in list of all stressed - * colormaps for the display. */ + Colormap colormap; /* X's token for the colormap. */ + int numColors; /* Number of entries currently active at + * *colorPtr. */ + XColor *colorPtr; /* Pointer to malloc'ed array of all colors + * that seem to be available in the colormap. + * Some may not actually be available, e.g. + * because they are read-write for another + * client; when we find this out, we remove + * them from the array. */ + struct TkStressedCmap *nextPtr; + /* Next in list of all stressed colormaps for + * the display. */ }; /* - * Forward declarations for procedures defined in this file: + * Forward declarations for functions defined in this file: */ static void DeleteStressedCmap _ANSI_ARGS_((Display *display, @@ -59,8 +58,8 @@ static void FindClosestColor _ANSI_ARGS_((Tk_Window tkwin, * None * * Side effects: - * Invalidates the colormap cache for the colormap associated with - * the given color. + * Invalidates the colormap cache for the colormap associated with the + * given color. * *---------------------------------------------------------------------- */ @@ -75,14 +74,13 @@ TkpFreeColor(tkColPtr) Screen *screen = tkColPtr->screen; /* - * Careful! Don't free black or white, since this will - * make some servers very unhappy. Also, there is a bug in - * some servers (such Sun's X11/NeWS server) where reference - * counting is performed incorrectly, so that if a color is - * allocated twice in different places and then freed twice, - * the second free generates an error (this bug existed as of - * 10/1/92). To get around this problem, ignore errors that - * occur during the free operation. + * Careful! Don't free black or white, since this will make some servers + * very unhappy. Also, there is a bug in some servers (such Sun's X11/NeWS + * server) where reference counting is performed incorrectly, so that if a + * color is allocated twice in different places and then freed twice, the + * second free generates an error (this bug existed as of 10/1/92). To get + * around this problem, ignore errors that occur during the free + * operation. */ visual = tkColPtr->visual; @@ -112,8 +110,7 @@ TkpFreeColor(tkColPtr) * * Side effects: * May invalidate the colormap cache associated with tkwin upon - * allocating a new colormap entry. Allocates a new TkColor - * structure. + * allocating a new colormap entry. Allocates a new TkColor structure. * *---------------------------------------------------------------------- */ @@ -130,7 +127,7 @@ TkpGetColor(tkwin, name) TkColor *tkColPtr; /* - * Map from the name to a pixel value. Call XAllocNamedColor rather than + * Map from the name to a pixel value. Call XAllocNamedColor rather than * XParseColor for non-# names: this saves a server round-trip for those * names. */ @@ -138,6 +135,18 @@ TkpGetColor(tkwin, name) if (*name != '#') { XColor screen; + if (((*name - 'A') & 0xdf) < sizeof(tkWebColors)/sizeof(tkWebColors[0])) { + const char *p = tkWebColors[((*name - 'A') & 0x1f)]; + if (p) { + const char *q = name; + while (!((*p - *(++q)) & 0xdf)) { + if (!*p++) { + name = p; + goto gotWebColor; + } + } + } + } if (strlen(name) > 99) { /* Don't bother to parse this. [Bug 2809525]*/ return (TkColor *) NULL; @@ -145,10 +154,10 @@ TkpGetColor(tkwin, name) DeleteStressedCmap(display, colormap); } else { /* - * Couldn't allocate the color. Try translating the name to - * a color value, to see whether the problem is a bad color - * name or a full colormap. If the colormap is full, then - * pick an approximation to the desired color. + * Couldn't allocate the color. Try translating the name to a + * color value, to see whether the problem is a bad color name or + * a full colormap. If the colormap is full, then pick an + * approximation to the desired color. */ if (XLookupColor(display, colormap, name, &color, &screen) == 0) { @@ -157,6 +166,7 @@ TkpGetColor(tkwin, name) FindClosestColor(tkwin, &screen, &color); } } else { + gotWebColor: if (TkParseColor(display, colormap, name, &color) == 0) { return (TkColor *) NULL; } @@ -178,19 +188,18 @@ TkpGetColor(tkwin, name) * * TkpGetColorByValue -- * - * Given a desired set of red-green-blue intensities for a color, - * locate a pixel value to use to draw that color in a given - * window. + * Given a desired set of red-green-blue intensities for a color, locate + * a pixel value to use to draw that color in a given window. * * Results: - * The return value is a pointer to an TkColor structure that - * indicates the closest red, blue, and green intensities available - * to those specified in colorPtr, and also specifies a pixel - * value to use to draw in that color. + * The return value is a pointer to an TkColor structure that indicates + * the closest red, blue, and green intensities available to those + * specified in colorPtr, and also specifies a pixel value to use to draw + * in that color. * * Side effects: - * May invalidate the colormap cache for the specified window. - * Allocates a new TkColor structure. + * May invalidate the colormap cache for the specified window. Allocates + * a new TkColor structure. * *---------------------------------------------------------------------- */ @@ -222,15 +231,15 @@ TkpGetColorByValue(tkwin, colorPtr) * * FindClosestColor -- * - * When Tk can't allocate a color because a colormap has filled - * up, this procedure is called to find and allocate the closest - * available color in the colormap. + * When Tk can't allocate a color because a colormap has filled up, this + * function is called to find and allocate the closest available color in + * the colormap. * * Results: - * There is no return value, but *actualColorPtr is filled in - * with information about the closest available color in tkwin's - * colormap. This color has been allocated via X, so it must - * be released by the caller when the caller is done with it. + * There is no return value, but *actualColorPtr is filled in with + * information about the closest available color in tkwin's colormap. + * This color has been allocated via X, so it must be released by the + * caller when the caller is done with it. * * Side effects: * A color is allocated. @@ -256,8 +265,8 @@ FindClosestColor(tkwin, desiredColorPtr, actualColorPtr) XVisualInfo template, *visInfoPtr; /* - * Find the TkStressedCmap structure for this colormap, or create - * a new one if needed. + * Find the TkStressedCmap structure for this colormap, or create a new + * one if needed. */ for (stressPtr = dispPtr->stressPtr; ; stressPtr = stressPtr->nextPtr) { @@ -265,20 +274,24 @@ FindClosestColor(tkwin, desiredColorPtr, actualColorPtr) stressPtr = (TkStressedCmap *) ckalloc(sizeof(TkStressedCmap)); stressPtr->colormap = colormap; template.visualid = XVisualIDFromVisual(Tk_Visual(tkwin)); + visInfoPtr = XGetVisualInfo(Tk_Display(tkwin), VisualIDMask, &template, &numFound); if (numFound < 1) { - panic("FindClosestColor couldn't lookup visual"); + Tcl_Panic("FindClosestColor couldn't lookup visual"); } + stressPtr->numColors = visInfoPtr->colormap_size; XFree((char *) visInfoPtr); stressPtr->colorPtr = (XColor *) ckalloc((unsigned) (stressPtr->numColors * sizeof(XColor))); - for (i = 0; i < stressPtr->numColors; i++) { + for (i = 0; i < stressPtr->numColors; i++) { stressPtr->colorPtr[i].pixel = (unsigned long) i; } + XQueryColors(dispPtr->display, colormap, stressPtr->colorPtr, stressPtr->numColors); + stressPtr->nextPtr = dispPtr->stressPtr; dispPtr->stressPtr = stressPtr; break; @@ -289,27 +302,27 @@ FindClosestColor(tkwin, desiredColorPtr, actualColorPtr) } /* - * Find the color that best approximates the desired one, then - * try to allocate that color. If that fails, it must mean that - * the color was read-write (so we can't use it, since it's owner - * might change it) or else it was already freed. Try again, - * over and over again, until something succeeds. + * Find the color that best approximates the desired one, then try to + * allocate that color. If that fails, it must mean that the color was + * read-write (so we can't use it, since it's owner might change it) or + * else it was already freed. Try again, over and over again, until + * something succeeds. */ - while (1) { + while (1) { if (stressPtr->numColors == 0) { - panic("FindClosestColor ran out of colors"); + Tcl_Panic("FindClosestColor ran out of colors"); } closestDistance = 1e30; closest = 0; for (colorPtr = stressPtr->colorPtr, i = 0; i < stressPtr->numColors; colorPtr++, i++) { /* - * Use Euclidean distance in RGB space, weighted by Y (of YIQ) - * as the objective function; this accounts for differences - * in the color sensitivity of the eye. + * Use Euclidean distance in RGB space, weighted by Y (of YIQ) as + * the objective function; this accounts for differences in the + * color sensitivity of the eye. */ - + tmp = .30*(((int) desiredColorPtr->red) - (int) colorPtr->red); distance = tmp*tmp; tmp = .61*(((int) desiredColorPtr->green) - (int) colorPtr->green); @@ -328,8 +341,8 @@ FindClosestColor(tkwin, desiredColorPtr, actualColorPtr) } /* - * Couldn't allocate the color. Remove it from the table and - * go back to look for the next best color. + * Couldn't allocate the color. Remove it from the table and go back + * to look for the next best color. */ stressPtr->colorPtr[closest] = @@ -343,30 +356,29 @@ FindClosestColor(tkwin, desiredColorPtr, actualColorPtr) * * DeleteStressedCmap -- * - * This procedure releases the information cached for "colormap" - * so that it will be refetched from the X server the next time - * it is needed. + * This function releases the information cached for "colormap" so that + * it will be refetched from the X server the next time it is needed. * * Results: * None. * * Side effects: - * The TkStressedCmap structure for colormap is deleted; the - * colormap is no longer considered to be "stressed". + * The TkStressedCmap structure for colormap is deleted; the colormap is + * no longer considered to be "stressed". * * Note: - * This procedure is invoked whenever a color in a colormap is - * freed, and whenever a color allocation in a colormap succeeds. - * This guarantees that TkStressedCmap structures are always - * deleted before the corresponding Colormap is freed. + * This function is invoked whenever a color in a colormap is freed, and + * whenever a color allocation in a colormap succeeds. This guarantees + * that TkStressedCmap structures are always deleted before the + * corresponding Colormap is freed. * *---------------------------------------------------------------------- */ static void DeleteStressedCmap(display, colormap) - Display *display; /* Xlib's handle for the display - * containing the colormap. */ + Display *display; /* Xlib's handle for the display containing + * the colormap. */ Colormap colormap; /* Colormap to flush. */ { TkStressedCmap *prevPtr, *stressPtr; @@ -392,12 +404,11 @@ DeleteStressedCmap(display, colormap) * * TkpCmapStressed -- * - * Check to see whether a given colormap is known to be out - * of entries. + * Check to see whether a given colormap is known to be out of entries. * * Results: - * 1 is returned if "colormap" is stressed (i.e. it has run out - * of entries recently), 0 otherwise. + * 1 is returned if "colormap" is stressed (i.e. it has run out of + * entries recently), 0 otherwise. * * Side effects: * None. @@ -421,3 +432,11 @@ TkpCmapStressed(tkwin, colormap) } return 0; } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ |