⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tkunixcolor.c

📁 linux系统下的音频通信
💻 C
字号:
/*  * tkUnixColor.c -- * *	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. * * SCCS: @(#) tkUnixColor.c 1.1 96/10/22 16:52:31 */#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 * 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. */};/* * Forward declarations for procedures defined in this file: */static void		DeleteStressedCmap _ANSI_ARGS_((Display *display,			    Colormap colormap));static void		FindClosestColor _ANSI_ARGS_((Tk_Window tkwin,			    XColor *desiredColorPtr, XColor *actualColorPtr));/* *---------------------------------------------------------------------- * * TkpFreeColor -- * *	Release the specified color back to the system. * * Results: *	None * * Side effects: *	Invalidates the colormap cache for the colormap associated with *	the given color. * *---------------------------------------------------------------------- */voidTkpFreeColor(tkColPtr)    TkColor *tkColPtr;		/* Color to be released.  Must have been				 * allocated by TkpGetColor or				 * TkpGetColorByValue. */{    Visual *visual;    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.     */    visual = tkColPtr->visual;    if ((visual->class != StaticGray) && (visual->class != StaticColor)	    && (tkColPtr->color.pixel != BlackPixelOfScreen(screen))	    && (tkColPtr->color.pixel != WhitePixelOfScreen(screen))) {	Tk_ErrorHandler handler;	handler = Tk_CreateErrorHandler(DisplayOfScreen(screen),		-1, -1, -1, (Tk_ErrorProc *) NULL, (ClientData) NULL);	XFreeColors(DisplayOfScreen(screen), tkColPtr->colormap,		&tkColPtr->color.pixel, 1, 0L);	Tk_DeleteErrorHandler(handler);    }    DeleteStressedCmap(DisplayOfScreen(screen), tkColPtr->colormap);}/* *---------------------------------------------------------------------- * * TkpGetColor -- * *	Allocate a new TkColor for the color with the given name. * * Results: *	Returns a newly allocated TkColor, or NULL on failure. * * Side effects: *	May invalidate the colormap cache associated with tkwin upon *	allocating a new colormap entry.  Allocates a new TkColor *	structure. * *---------------------------------------------------------------------- */TkColor *TkpGetColor(tkwin, name)    Tk_Window tkwin;		/* Window in which color will be used. */    Tk_Uid name;		/* Name of color to allocated (in form				 * suitable for passing to XParseColor). */{    Display *display = Tk_Display(tkwin);    Colormap colormap = Tk_Colormap(tkwin);    XColor color;    TkColor *tkColPtr;    /*     * 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.     */    if (*name != '#') {	XColor screen;	if (XAllocNamedColor(display, colormap, name, &screen,		&color) != 0) {	    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.	     */	    if (XLookupColor(display, colormap, name, &color,		    &screen) == 0) {		return (TkColor *) NULL;	    }	    FindClosestColor(tkwin, &screen, &color);	}    } else {	if (XParseColor(display, colormap, name, &color) == 0) {	    return (TkColor *) NULL;	}	if (XAllocColor(display, colormap, &color) != 0) {	    DeleteStressedCmap(display, colormap);	} else {	    FindClosestColor(tkwin, &color, &color);	}    }    tkColPtr = (TkColor *) ckalloc(sizeof(TkColor));    tkColPtr->color = color;    return tkColPtr;}/* *---------------------------------------------------------------------- * * 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. * * 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. * * Side effects: *	May invalidate the colormap cache for the specified window. *	Allocates a new TkColor structure. * *---------------------------------------------------------------------- */TkColor *TkpGetColorByValue(tkwin, colorPtr)    Tk_Window tkwin;		/* Window in which color will be used. */    XColor *colorPtr;		/* Red, green, and blue fields indicate				 * desired color. */{    Display *display = Tk_Display(tkwin);    Colormap colormap = Tk_Colormap(tkwin);    TkColor *tkColPtr = (TkColor *) ckalloc(sizeof(TkColor));    tkColPtr->color.red = colorPtr->red;    tkColPtr->color.green = colorPtr->green;    tkColPtr->color.blue = colorPtr->blue;    if (XAllocColor(display, colormap, &tkColPtr->color) != 0) {	DeleteStressedCmap(display, colormap);    } else {	FindClosestColor(tkwin, &tkColPtr->color, &tkColPtr->color);    }    return tkColPtr;}/* *---------------------------------------------------------------------- * * 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. * * 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. * * Side effects: *	A color is allocated. * *---------------------------------------------------------------------- */static voidFindClosestColor(tkwin, desiredColorPtr, actualColorPtr)    Tk_Window tkwin;			/* Window where color will be used. */    XColor *desiredColorPtr;		/* RGB values of color that was					 * wanted (but unavailable). */    XColor *actualColorPtr;		/* Structure to fill in with RGB and					 * pixel for closest available					 * color. */{    TkStressedCmap *stressPtr;    double tmp, distance, closestDistance;    int i, closest, numFound;    XColor *colorPtr;    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;    Colormap colormap = Tk_Colormap(tkwin);    XVisualInfo template, *visInfoPtr;    /*     * Find the TkStressedCmap structure for this colormap, or create     * a new one if needed.     */    for (stressPtr = dispPtr->stressPtr; ; stressPtr = stressPtr->nextPtr) {	if (stressPtr == NULL) {	    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");	    }	    stressPtr->numColors = visInfoPtr->colormap_size;	    XFree((char *) visInfoPtr);	    stressPtr->colorPtr = (XColor *) ckalloc((unsigned)		    (stressPtr->numColors * sizeof(XColor)));	    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;	}	if (stressPtr->colormap == colormap) {	    break;	}    }    /*     * 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)  {	if (stressPtr->numColors == 0) {	    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.	     */    	    tmp = .30*(((int) desiredColorPtr->red) - (int) colorPtr->red);	    distance = tmp*tmp;	    tmp = .61*(((int) desiredColorPtr->green) - (int) colorPtr->green);	    distance += tmp*tmp;	    tmp = .11*(((int) desiredColorPtr->blue) - (int) colorPtr->blue);	    distance += tmp*tmp;	    if (distance < closestDistance) {		closest = i;		closestDistance = distance;	    }	}	if (XAllocColor(dispPtr->display, colormap,		&stressPtr->colorPtr[closest]) != 0) {	    *actualColorPtr = stressPtr->colorPtr[closest];	    return;	}	/*	 * Couldn't allocate the color.  Remove it from the table and	 * go back to look for the next best color.	 */	stressPtr->colorPtr[closest] =		stressPtr->colorPtr[stressPtr->numColors-1];	stressPtr->numColors -= 1;    }}/* *---------------------------------------------------------------------- * * 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. * * Results: *	None. * * Side effects: *	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. * *---------------------------------------------------------------------- */static voidDeleteStressedCmap(display, colormap)    Display *display;		/* Xlib's handle for the display				 * containing the colormap. */    Colormap colormap;		/* Colormap to flush. */{    TkStressedCmap *prevPtr, *stressPtr;    TkDisplay *dispPtr = TkGetDisplay(display);    for (prevPtr = NULL, stressPtr = dispPtr->stressPtr; stressPtr != NULL;	    prevPtr = stressPtr, stressPtr = stressPtr->nextPtr) {	if (stressPtr->colormap == colormap) {	    if (prevPtr == NULL) {		dispPtr->stressPtr = stressPtr->nextPtr;	    } else {		prevPtr->nextPtr = stressPtr->nextPtr;	    }	    ckfree((char *) stressPtr->colorPtr);	    ckfree((char *) stressPtr);	    return;	}    }}/* *---------------------------------------------------------------------- * * TkpCmapStressed -- * *	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. * * Side effects: *	None. * *---------------------------------------------------------------------- */intTkpCmapStressed(tkwin, colormap)    Tk_Window tkwin;		/* Window that identifies the display				 * containing the colormap. */    Colormap colormap;		/* Colormap to check for stress. */{    TkStressedCmap *stressPtr;    for (stressPtr = ((TkWindow *) tkwin)->dispPtr->stressPtr;	    stressPtr != NULL; stressPtr = stressPtr->nextPtr) {	if (stressPtr->colormap == colormap) {	    return 1;	}    }    return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -