diff options
Diffstat (limited to 'nx-X11/lib/dps/dpsXcmu.c')
-rw-r--r-- | nx-X11/lib/dps/dpsXcmu.c | 1602 |
1 files changed, 0 insertions, 1602 deletions
diff --git a/nx-X11/lib/dps/dpsXcmu.c b/nx-X11/lib/dps/dpsXcmu.c deleted file mode 100644 index 502649d51..000000000 --- a/nx-X11/lib/dps/dpsXcmu.c +++ /dev/null @@ -1,1602 +0,0 @@ -/* - * dpsXcmu.c -- Simple color management/allocation utility - * - * (c) Copyright 1988-1994 Adobe Systems Incorporated. - * All rights reserved. - * - * Permission to use, copy, modify, distribute, and sublicense this software - * and its documentation for any purpose and without fee is hereby granted, - * provided that the above copyright notices appear in all copies and that - * both those copyright notices and this permission notice appear in - * supporting documentation and that the name of Adobe Systems Incorporated - * not be used in advertising or publicity pertaining to distribution of the - * software without specific, written prior permission. No trademark license - * to use the Adobe trademarks is hereby granted. If the Adobe trademark - * "Display PostScript"(tm) is used to describe this software, its - * functionality or for any other purpose, such use shall be limited to a - * statement that this software works in conjunction with the Display - * PostScript system. Proper trademark attribution to reflect Adobe's - * ownership of the trademark shall be given whenever any such reference to - * the Display PostScript system is made. - * - * ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR - * ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. - * ADOBE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL - * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NON- INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE - * TO YOU OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE, STRICT LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT - * PROVIDE ANY TRAINING OR OTHER SUPPORT FOR THE SOFTWARE. - * - * Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems - * Incorporated which may be registered in certain jurisdictions - * - * Portions Copyright 1989 by the Massachusetts Institute of Technology - * - * 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 and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of M.I.T. not be used in advertising - * or publicity pertaining to distribution of the software without specific, - * written prior permission. M.I.T. makes no representations about the - * suitability of this software for any purpose. It is provided "as is" - * without express or implied warranty. - * - * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T. - * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Author: Adobe Systems Incorporated and Donna Converse, MIT X Consortium - */ -/* $XFree86: xc/lib/dps/dpsXcmu.c,v 1.4 2000/09/26 15:56:59 tsi Exp $ */ - -#include <X11/X.h> -#include <X11/Xlib.h> -#include <X11/Xutil.h> -#include <X11/Xatom.h> -#include <X11/Xresource.h> -#include <X11/Xos.h> -#include <stdlib.h> -#include <stdio.h> -#include <pwd.h> - -#include "dpsassert.h" -#include "cslibint.h" - -/* Defines for standard colormap routines */ - -#define PrivSort qsort -#include <stddef.h> - -static char redsName[] = "reds"; -static char greensName[] = "greens"; -static char bluesName[] = "blues"; -static char graysName[] = "grays"; - -/* Database containing DPS default color cube values */ - -typedef struct _dpyRec { - Display *dpy; - XrmDatabase db; - Atom XA_GRAY_DEFAULT_MAP; - struct _dpyRec *next; -} DpyRec; - -static DpyRec *dpyRec = NULL; -static DpyRec *curDpyRec; -static DpyRec *FindDpyRec(Display *); - -typedef struct { - unsigned long *pixels; - int npixels; -} PixelRec; - -static Bool AllocateColor(Display *, Colormap, XColor *); -static Bool AllocateColormap(Display *, XStandardColormap *, XVisualInfo *, int *, PixelRec *, int *, int *, unsigned long); -static Bool CheckCube(XColor *, XColor *, XStandardColormap *); -static Bool CubicCube(XStandardColormap *); -static Bool GetColorCubeFromProperty(Display *, XVisualInfo *, XStandardColormap *, XStandardColormap **, int *); -static Bool GetGrayRampFromProperty(Display *, XVisualInfo *, XStandardColormap *, XStandardColormap **, int *); -Status XDPSCreateStandardColormaps(Display *, Drawable, Visual *, int, int, int, int, XStandardColormap *, XStandardColormap *, Bool); -static Status contiguous(unsigned long *, int, int *, unsigned long, int *, int *); -static XVisualInfo *PickCorrectVisual(Display *, XVisualInfo *, int, Colormap); -static int FindRampSize(XColor *, XColor *); -static long NumColors(char *, char *, char *); -static void AllocateColorCube(Display *, XVisualInfo *, XStandardColormap *, PixelRec *); -static void AllocateGrayRamp(Display *, XVisualInfo *, XStandardColormap *, XStandardColormap *, PixelRec *); -static void ColorValuesFromMask(unsigned long, unsigned long *, unsigned long *); -static void CreateDefaultsDb(Display *); -static void DefineProperty(Display *, XStandardColormap *, XVisualInfo *, XStandardColormap *, int, Atom); -static void FindStaticColorCube(Display *, XVisualInfo *, XStandardColormap *); -static void FindStaticGrayRamp(Display *, XVisualInfo *, XStandardColormap *, XStandardColormap *); -static void GetDatabaseValues(Display *, XVisualInfo *, XStandardColormap *, XStandardColormap *); -static void GetHomeDir(char *); -static void SetRamp(XColor *, XColor *, int, int *, unsigned long *); -static void ShrinkMapToFit(XStandardColormap *, int *, XVisualInfo *); -static void UseGrayCorners(XStandardColormap *, XStandardColormap *); -static void UseGrayDiagonal(XStandardColormap *, XStandardColormap *); - -#define SCALE 65535 -#undef ABS -#define ABS(x) ((x) < 0 ? -(x) : (x)) - -void XDPSGetDefaultColorMaps( - Display *dpy, - Screen *screen, - Drawable drawable, - XStandardColormap *colorCube, - XStandardColormap *grayRamp) -{ - Window root; - Visual *visual; - XStandardColormap g; - - /* If there is a screen specified, use it; otherwise use the drawable */ - - if (screen == NULL) { - if (drawable == None || ScreenCount(dpy) == 1) { - root = DefaultRootWindow(dpy); - screen = DefaultScreenOfDisplay(dpy); - } else { - /* Have to get the root for this drawable */ - int x, y; - int i; - unsigned int width, height, bwidth, depth; - if (!XGetGeometry(dpy, drawable, &root, &x, &y, &width, &height, - &bwidth, &depth)) root = DefaultRootWindow(dpy); - for (i = 0; - i < ScreenCount(dpy) && root != RootWindow(dpy, i); - i++) {} - screen = ScreenOfDisplay(dpy, i); - } - } else root = RootWindowOfScreen(screen); - - if (grayRamp == NULL) grayRamp = &g; - - visual = DefaultVisualOfScreen(screen); - grayRamp->colormap = DefaultColormapOfScreen(screen); - if (colorCube != NULL) colorCube->colormap = grayRamp->colormap; - - (void) XDPSCreateStandardColormaps(dpy, root, visual, - 0, 0, 0, 0, colorCube, grayRamp, True); -} - -Status XDPSCreateStandardColormaps( - Display *dpy, - Drawable drawable, - Visual *visual, - int reds, int greens, int blues, int grays, - XStandardColormap *colorCube, - XStandardColormap *grayRamp, - Bool retain) -{ - XVisualInfo vtemp, *vinfo; - int nvis; - XStandardColormap *propCube = NULL, *propRamp = NULL; - int nPropCube = 0, nPropRamp = 0; - Bool gotCube = False, gotRamp; - PixelRec pixels; - - if (grayRamp == NULL) return 0; - if (colorCube != NULL && - colorCube->colormap != grayRamp->colormap) return 0; - - if (dpy == NULL || (drawable == None && visual == NULL)) return 0; - - if (visual == NULL) { - XWindowAttributes attr; - if (XGetWindowAttributes(dpy, drawable, &attr) == 0) return 0; - visual = attr.visual; - } - - if (grayRamp->colormap == None && drawable == None) return 0; - - curDpyRec = FindDpyRec(dpy); - if (curDpyRec == NULL) return 0; - - vtemp.visualid = XVisualIDFromVisual(visual); - vinfo = XGetVisualInfo(dpy, VisualIDMask, &vtemp, &nvis); - if (nvis == 0) return 0; - - if (nvis > 1) { - vinfo = PickCorrectVisual(dpy, vinfo, nvis, grayRamp->colormap); - } - if (vinfo == NULL) return 0; - - if (grays <= 1) grayRamp->red_max = 0; - else grayRamp->red_max = grays - 1; - - if (colorCube != NULL) { - if (reds <= 1) colorCube->red_max = 0; - else colorCube->red_max = reds - 1; - if (greens <= 1) colorCube->green_max = 0; - else colorCube->green_max = greens - 1; - if (blues <= 1) colorCube->blue_max = 0; - else colorCube->blue_max = blues - 1; - } - - if ((vinfo->class == StaticGray || vinfo->class == GrayScale) && - colorCube != NULL) { - /* Can't do a color cube in a gray visual! */ - colorCube->red_max = colorCube->green_max = colorCube->blue_max = - colorCube->red_mult = colorCube->green_mult = colorCube->blue_mult = - colorCube->base_pixel = 0; - colorCube = NULL; - } - - if (retain) { - Display *newDpy = XOpenDisplay(XDisplayString(dpy)); - if (newDpy == NULL) retain = False; - else dpy = newDpy; - XGrabServer(dpy); - } - - if (grayRamp->colormap == None) { - grayRamp->colormap = XCreateColormap(dpy, drawable, vinfo->visual, - AllocNone); - if (colorCube != NULL) colorCube->colormap = grayRamp->colormap; - } - - if (colorCube != NULL) { - gotCube = GetColorCubeFromProperty(dpy, vinfo, colorCube, - &propCube, &nPropCube); - } - gotRamp = GetGrayRampFromProperty(dpy, vinfo, grayRamp, - &propRamp, &nPropRamp); - - if (!gotRamp || (colorCube != NULL && !gotCube)) { - /* Couldn't find at least one thing we wanted, so let's look in the - database */ - - GetDatabaseValues(dpy, vinfo, colorCube, grayRamp); - - pixels.pixels = NULL; - pixels.npixels = 0; - - if (colorCube != NULL) { - if (colorCube->red_max != 0) { - AllocateColorCube(dpy, vinfo, colorCube, &pixels); - } - if (colorCube->red_max == 0) { - colorCube->green_max = colorCube->blue_max = - colorCube->red_mult = colorCube->green_mult = - colorCube->blue_mult = 0; - } - } - - if (grayRamp->red_max != 0) { - AllocateGrayRamp(dpy, vinfo, grayRamp, colorCube, &pixels); - } - - if (pixels.pixels != NULL) { - if (pixels.npixels != 0) { - XFreeColors(dpy, grayRamp->colormap, - pixels.pixels, pixels.npixels, 0); - } - free((char *) pixels.pixels); - } - - if (retain) { - Pixmap p; - - /* Create something to put in killid field so the entries can - be deleted sometime */ - p = XCreatePixmap(dpy, RootWindow(dpy, vinfo->screen), 1, 1, 1); - if (colorCube != NULL && !gotCube && colorCube->red_max != 0) { - colorCube->visualid = vinfo->visualid; - colorCube->killid = p; - DefineProperty(dpy, colorCube, vinfo, propCube, nPropCube, - XA_RGB_DEFAULT_MAP); - } - if (!gotRamp && grayRamp->red_max != 0) { - grayRamp->visualid = vinfo->visualid; - grayRamp->killid = p; - DefineProperty(dpy, grayRamp, vinfo, propRamp, nPropRamp, - (vinfo->class == GrayScale ? XA_RGB_GRAY_MAP : - curDpyRec->XA_GRAY_DEFAULT_MAP)); - } - XSetCloseDownMode(dpy, RetainTemporary); - } - } - - if (grayRamp->red_max == 0) { - /* Use special magic values. If this is a default colormap, - the server recognizes a gray ramp with red_max=1, red_mult=1, - base_pixel=0 to mean a 2 gray ramp with BlackPixel being - the lowest intensity gray and WhitePixel being the highest - intensity gray. If it's not a default colormap, then the - server will either generate a BadValue error, or just happily - use pixel values 0 and 1; either is better than the alternative, - silently converting into a null device. */ - grayRamp->red_max = 1; - grayRamp->red_mult = 1; - grayRamp->base_pixel = 0; - } - - if (retain) { - XUngrabServer(dpy); - XCloseDisplay(dpy); - } - if (propCube != NULL) XFree((void *) propCube); - if (propRamp != NULL) XFree((void *) propRamp); - XFree((void *) vinfo); - return 1; -} - -static DpyRec *FindDpyRec(Display *dpy) -{ - DpyRec *d; - - for (d = dpyRec; d != NULL; d = d->next) { - if (d->dpy == dpy) return d; - } - - d = (DpyRec *) malloc(sizeof(DpyRec)); - if (d == NULL) return NULL; - d->XA_GRAY_DEFAULT_MAP = XInternAtom(dpy, "DEFAULT_GRAY", False); - d->db = NULL; - d->next = dpyRec; - dpyRec = d; - return d; -} - -static XVisualInfo *PickCorrectVisual( - Display *dpy, - XVisualInfo *vlist, - int n, - Colormap cmap) -{ - register int i; - register int screen_number; - Bool def_cmap = False; - - /* A visual id may be valid on multiple screens. Also, there may - * be multiple visuals with identical visual ids at different depths. - * If the colormap is the Default Colormap, use the Default Visual. - * Otherwise, arbitrarily, use the deepest visual. - */ - - for (screen_number = ScreenCount(dpy); --screen_number >= 0; /**/) { - if (cmap == DefaultColormap(dpy, screen_number)) { - def_cmap = True; - break; - } - } - - if (def_cmap) { - for (i = 0; i < n; i++, vlist++) { - if (vlist->visual == DefaultVisual(dpy, screen_number)) { - return vlist; - } - } - return NULL; /* Visual does not match colormap */ - } else { - int maxdepth = 0; - XVisualInfo *v = 0; - - for (i = 0; i < n; i++, vlist++) { - if (vlist->depth > maxdepth) { - maxdepth = vlist->depth; - v = vlist; - } - } - return v; - } -} - -/* Do some rudimentary checking of the properties to avoid obviously bad ones. - How did they get there, anyway? */ - -static Bool ValidCube( - XStandardColormap *c, - XVisualInfo *vinfo) -{ - unsigned long max = 1 << vinfo->depth; - unsigned long pixel; - - if (c->red_max < 1 || c->green_max < 1 || c->blue_max < 1) return False; - if (c->base_pixel > max) return False; - pixel = (c->red_max * c->red_mult + c->green_max * c->green_mult + - c->blue_max * c->blue_mult + c->base_pixel) & 0xFFFFFFFF; - if (pixel > max) return False; - - return True; -} - -static Bool ValidRamp( - XStandardColormap *c, - XVisualInfo *vinfo) -{ - unsigned long max = 1 << vinfo->depth; - unsigned long pixel; - - if (c->red_max < 1) return False; - if (c->base_pixel > max) return False; - pixel = (c->red_max * c->red_mult + c->base_pixel) & 0xFFFFFFFF; - if (pixel > max) return False; - - return True; -} - -static Bool GetColorCubeFromProperty( - Display *dpy, - XVisualInfo *vinfo, - XStandardColormap *colorCube, - XStandardColormap **cube, - int *ncube) -{ - int gotCube; - int i; - register XStandardColormap *c; - - gotCube = XGetRGBColormaps(dpy, RootWindow(dpy, vinfo->screen), cube, - ncube, XA_RGB_DEFAULT_MAP); - - if (gotCube) { - /* Try to find a match with the visual */ - c = *cube; - for (i = 0; i < *ncube; i++) { - if (c->colormap == colorCube->colormap && - c->visualid == vinfo->visualid && - ValidCube(c, vinfo)) { - colorCube->red_max = c->red_max; - colorCube->red_mult = c->red_mult; - colorCube->green_max = c->green_max; - colorCube->green_mult = c->green_mult; - colorCube->blue_max = c->blue_max; - colorCube->blue_mult = c->blue_mult; - colorCube->base_pixel = c->base_pixel; - colorCube->visualid = c->visualid; - colorCube->killid = c->killid; - break; - } - c++; - } - if (i == *ncube) gotCube = False; - } - return gotCube; -} - -static Bool GetGrayRampFromProperty( - Display *dpy, - XVisualInfo *vinfo, - XStandardColormap *grayRamp, - XStandardColormap **ramp, - int *nramp) -{ - int gotRamp; - int i; - Atom grayAtom; - register XStandardColormap *c; - - if (vinfo->class == GrayScale) grayAtom = XA_RGB_GRAY_MAP; - else grayAtom = curDpyRec->XA_GRAY_DEFAULT_MAP; - - gotRamp = XGetRGBColormaps(dpy, RootWindow(dpy, vinfo->screen), ramp, - nramp, grayAtom); - - if (gotRamp) { - /* Try to find a match with the visual */ - c = *ramp; - for (i = 0; i < *nramp; i++) { - if (c->colormap == grayRamp->colormap && - c->visualid == vinfo->visualid && - ValidRamp(c, vinfo)) { - grayRamp->red_max = c->red_max; - grayRamp->red_mult = c->red_mult; - grayRamp->base_pixel = c->base_pixel; - grayRamp->visualid = c->visualid; - grayRamp->killid = c->killid; - break; - } - c++; - } - if (i == *nramp) gotRamp = False; - } - return gotRamp; -} - -static void GetDatabaseValues( - Display *dpy, - XVisualInfo *vinfo, - XStandardColormap *colorCube, - XStandardColormap *grayRamp) -{ - char *class, *depth; - char namePrefix[40], classPrefix[40]; - unsigned long max; - XStandardColormap fakeCube; - - switch (vinfo->class) { - default: - case StaticGray: class = "StaticGray."; break; - case GrayScale: class = "GrayScale."; break; - case StaticColor: class = "StaticColor."; break; - case PseudoColor: class = "PseudoColor."; break; - case TrueColor: class = "TrueColor."; break; - case DirectColor: class = "DirectColor."; break; - } - - if (vinfo->depth >= 24) depth = "24."; - else if (vinfo->depth >= 12) depth = "12."; - else if (vinfo->depth >= 8) depth = "8."; - else if (vinfo->depth >= 4) depth = "4."; - else if (vinfo->depth >= 2) depth = "2."; - else depth = "1."; - - (void) strcpy(namePrefix, "dpsColorCube."); - (void) strcat(strcat(namePrefix, class), depth); - (void) strcpy(classPrefix, "DPSColorCube."); - (void) strcat(strcat(classPrefix, class), depth); - - CreateDefaultsDb(dpy); - - if (colorCube == NULL && vinfo->class == TrueColor) { - /* We'll need the color cube information to compute the gray ramp, - even if it wasn't asked for, so make colorCube point to a - temporary structure */ - colorCube = &fakeCube; - } - - if (colorCube != NULL) { - switch (vinfo->class) { - case StaticGray: - case GrayScale: - /* We can't do a color cube for these visuals */ - break; - - case TrueColor: - /* Rewrite whatever was there before with real values */ - ColorValuesFromMask(vinfo->red_mask, &colorCube->red_max, - &colorCube->red_mult); - ColorValuesFromMask(vinfo->green_mask, &colorCube->green_max, - &colorCube->green_mult); - ColorValuesFromMask(vinfo->blue_mask, &colorCube->blue_max, - &colorCube->blue_mult); - colorCube->base_pixel = 0; - break; - - case DirectColor: - /* Get the mults from the masks; ignore maxes */ - ColorValuesFromMask(vinfo->red_mask, &max, - &colorCube->red_mult); - ColorValuesFromMask(vinfo->green_mask, &max, - &colorCube->green_mult); - ColorValuesFromMask(vinfo->blue_mask, &max, - &colorCube->blue_mult); - /* Get the maxes from the database */ - if (colorCube->red_max == 0) { - colorCube->red_max = - NumColors(namePrefix, classPrefix, redsName) - 1; - } - if (colorCube->green_max == 0) { - colorCube->green_max = - NumColors(namePrefix, classPrefix, greensName) - 1; - } - if (colorCube->blue_max == 0) { - colorCube->blue_max = - NumColors(namePrefix, classPrefix, bluesName) - 1; - } - colorCube->base_pixel = 0; - break; - - case PseudoColor: - if (colorCube->red_max == 0) { - colorCube->red_max = - NumColors(namePrefix, classPrefix, redsName) - 1; - } - if (colorCube->green_max == 0) { - colorCube->green_max = - NumColors(namePrefix, classPrefix, greensName) - 1; - } - if (colorCube->blue_max == 0) { - colorCube->blue_max = - NumColors(namePrefix, classPrefix, bluesName) - 1; - } - colorCube->red_mult = (colorCube->green_max + 1) * - (colorCube->blue_max + 1); - colorCube->green_mult = colorCube->blue_max + 1; - colorCube->blue_mult = 1; - break; - - case StaticColor: - FindStaticColorCube(dpy, vinfo, colorCube); - break; - } - } - - switch (vinfo->class) { - case GrayScale: - case PseudoColor: - case DirectColor: - if (grayRamp->red_max == 0) { - grayRamp->red_max = - NumColors(namePrefix, classPrefix, graysName) - 1; - } - grayRamp->red_mult = 1; - break; - - case TrueColor: - /* If the color cube is truly a cube, use its diagonal. Otherwise - were SOL and have to use a two-element ramp. */ - if (CubicCube(colorCube)) UseGrayDiagonal(colorCube, grayRamp); - else UseGrayCorners(colorCube, grayRamp); - break; - - case StaticColor: - case StaticGray: - FindStaticGrayRamp(dpy, vinfo, grayRamp, colorCube); - break; - } -} - -static Bool CubicCube(XStandardColormap *cube) -{ - return cube->red_max == cube->green_max && cube->red_max == - cube->blue_max; -} - -static void UseGrayDiagonal(XStandardColormap *cube, XStandardColormap *ramp) -{ - ramp->red_max = cube->red_max; - ramp->red_mult = cube->red_mult + cube->green_mult + cube->blue_mult; - ramp->base_pixel = cube->base_pixel; -} - -static void UseGrayCorners(XStandardColormap *cube, XStandardColormap *ramp) -{ - ramp->red_max = 1; - ramp->red_mult = (cube->red_max + 1) * (cube->green_max + 1) * - (cube->blue_max + 1) - 1; - if (* (int *) &(cube->red_mult) < 0) ramp->red_mult *= -1; - ramp->base_pixel = cube->base_pixel; -} - -static void ColorValuesFromMask( - unsigned long mask, - unsigned long *maxColor, - unsigned long *mult) -{ - *mult = 1; - while ((mask & 1) == 0) { - *mult <<= 1; - mask >>= 1; - } - *maxColor = mask; -} - -/* -Resource definitions for default color cube / gray ramp sizes -are based on visual class and depth. Working from least choices -to most, here's motivation for the defaults: - -If unspecified, default is 0 values for red, green, and blue, -and 2 (black and white) for grays. This covers StaticGray, StaticColor, -and depths less than 4 of the other visual classes. - -If we have a choice, we try to allocate a gray ramp with an odd number -of colors; this is so 50% gray can be rendered without dithering. -In general we don't want to allocate a large cube (even when many -colormap entries are available) because allocation of each entry -requires a round-trip to the server (entries allocated read-only -via XAllocColor). - -For GrayScale, any depth less than 4 is treated as monochrome. - -PseudoColor depth 4 we try for a 2x2x2 cube with the gray ramp on -the diagonal. Depth 8 uses a 4x4x4 cube with a separate 9 entry -gray ramp. Depth 12 uses a 6x6x5 "cube" with a separate 17 entry gray -ramp. The cube is non-symmetrical; we don't want to use the diagonal -for a gray ramp and we can get by with fewer blues than reds or greens. - -For DirectColor, allocating a gray ramp separate from the color cube -is wasteful of map entries, so we specify a symmetrical cube and -share the diagonal entries for the gray ramp. - -For TrueColor, # color shades is set equal to the # shades / primary; -we don't actually allocate map entries, but it's handy to be able to -do the resource lookup blindly and get the right value. -*/ - -static char dpsDefaults[] = "\ -*reds: 0\n\ -*greens: 0\n\ -*blues: 0\n\ -*grays: 2\n\ -\ -*GrayScale.4.grays: 9\n\ -*GrayScale.8.grays: 17\n\ -\ -*PseudoColor.4.reds: 2\n\ -*PseudoColor.4.greens: 2\n\ -*PseudoColor.4.blues: 2\n\ -*PseudoColor.4.grays: 2\n\ -*PseudoColor.8.reds: 4\n\ -*PseudoColor.8.greens: 4\n\ -*PseudoColor.8.blues: 4\n\ -*PseudoColor.8.grays: 9\n\ -*PseudoColor.12.reds: 6\n\ -*PseudoColor.12.greens: 6\n\ -*PseudoColor.12.blues: 5\n\ -*PseudoColor.12.grays: 17\n\ -\ -*DirectColor.8.reds: 4\n\ -*DirectColor.8.greens: 4\n\ -*DirectColor.8.blues: 4\n\ -*DirectColor.8.grays: 4\n\ -*DirectColor.12.reds: 6\n\ -*DirectColor.12.greens: 6\n\ -*DirectColor.12.blues: 6\n\ -*DirectColor.12.grays: 6\n\ -*DirectColor.24.reds: 7\n\ -*DirectColor.24.greens: 7\n\ -*DirectColor.24.blues: 7\n\ -*DirectColor.24.grays: 7\n\ -\ -*TrueColor.12.reds: 16\n\ -*TrueColor.12.greens: 16\n\ -*TrueColor.12.blues: 16\n\ -*TrueColor.12.grays: 16\n\ -*TrueColor.24.reds: 256\n\ -*TrueColor.24.greens: 256\n\ -*TrueColor.24.blues: 256\n\ -*TrueColor.24.grays: 256\n\ -"; - -static XrmDatabase defaultDB = NULL; - -static void CreateDefaultsDb(Display *dpy) -{ - char home[256], *dpyDefaults; - - if (defaultDB == NULL) defaultDB = XrmGetStringDatabase(dpsDefaults); - - if (curDpyRec->db != NULL) return; - - dpyDefaults = XResourceManagerString(dpy); - if (dpyDefaults != NULL) { - curDpyRec->db = XrmGetStringDatabase(dpyDefaults); - } - - if (curDpyRec->db == NULL) { - GetHomeDir(home); - strcpy(home, "/.Xdefaults"); - curDpyRec->db = XrmGetFileDatabase(home); - } -} - -static void GetHomeDir(char *buf) -{ -#ifndef X_NOT_POSIX - uid_t uid; -#else - int uid; - extern int getuid(); -#ifndef SYSV386 - extern struct passwd *getpwuid(), *getpwnam(); -#endif -#endif - struct passwd *pw; - static char *ptr = NULL; - - if (ptr == NULL) { - if (!(ptr = getenv("HOME"))) { - if ((ptr = getenv("USER")) != 0) pw = getpwnam(ptr); - else { - uid = getuid(); - pw = getpwuid(uid); - } - if (pw) ptr = pw->pw_dir; - else { - ptr = NULL; - *buf = '\0'; - } - } - } - - if (ptr) - (void) strcpy(buf, ptr); - - buf += strlen(buf); - *buf = '/'; - buf++; - *buf = '\0'; - return; -} - -static long NumColors(char *namePrefix, char *classPrefix, char *color) -{ - char name[40], class[40]; - XrmValue rtnValue; - char *rtnType; - long value; - - (void) strcpy(name, namePrefix); - (void) strcpy(class, classPrefix); - if (! XrmGetResource(curDpyRec->db, strcat(name, color), - strcat(class, color), &rtnType, &rtnValue)) { - if (! XrmGetResource(defaultDB, name, class, &rtnType, &rtnValue)) { - /* This should never happen, as our defaults cover all cases */ - return 0; - } - } - - /* Resource value is number of shades of specified color. If value - is not an integer, atoi returns 0, so we return 0. If value - is less than 2, it is invalid (need at least 2 shades of a color). - Explicitly setting 0 is ok for colors (means to not use a color - cube) but merits a warning for gray. */ - - if (strcmp(rtnValue.addr, "0") == 0 && strcmp(color, "grays") != 0) { - return 0; - } - - value = atol(rtnValue.addr); - if (value < 2) { - char mbuf[512]; - sprintf(mbuf, "%% Value '%s' is invalid for %s resource\n", - rtnValue.addr, name); - DPSWarnProc(NULL, mbuf); - } - return value; -} - -/* Query the entire colormap in the static color case, then try to find - a color cube. Check pairs of black and white cells trying to find - a cube between them and take the first one you find. */ - -static void FindStaticColorCube( - Display *dpy, - XVisualInfo *vinfo, - XStandardColormap *colorCube) -{ - XColor *ramp, *black, *white, *altBlack, *altWhite; - int i, entries; - - entries = 1 << vinfo->depth; - ramp = (XColor *) calloc(entries, sizeof(XColor)); - - if (ramp == NULL) { - colorCube->red_max = 0; - return; - } - - /* Query the colormap */ - for (i = 0; i < entries; i++) ramp[i].pixel = i; - XQueryColors(dpy, colorCube->colormap, ramp, entries); - - /* Find the white and black entries */ - - black = white = altBlack = altWhite = NULL; - for (i = 0; i < entries; i++) { - if (ramp[i].flags != (DoRed | DoBlue | DoGreen)) continue; - if (ramp[i].red == 0 && ramp[i].blue == 0 && - ramp[i].green == 0) { - if (black == NULL) black = ramp+i; - else if (altBlack == NULL) altBlack = ramp+i; - } else if (ramp[i].red == SCALE && ramp[i].blue == SCALE && - ramp[i].green == SCALE) { - if (white == NULL) white = ramp+i; - else if (altWhite == NULL) altWhite = ramp+i; - } - } - - if (black == NULL || white == NULL) { - colorCube->red_max = 0; - free(ramp); - return; - } - - /* Look for cubes between pairs of black & white */ - if (!CheckCube(black, white, colorCube) && - !CheckCube(altBlack, white, colorCube) && - !CheckCube(black, altWhite, colorCube) && - !CheckCube(altBlack, altWhite, colorCube)) { - colorCube->red_max = 0; - } - - free(ramp); -} - -#define R 1 -#define G 2 -#define B 4 -#define C 8 -#define M 16 -#define Y 32 - -#define SMALLSCALE 255 -#define CheckColor(color,r,g,b) ((((color)->red >> 8) == (r) * SMALLSCALE) && \ - (((color)->green >> 8) == (g) * SMALLSCALE) && \ - (((color)->blue >> 8) == (b) * SMALLSCALE)) - -static Bool CheckCube( - XColor *black, - XColor *white, - XStandardColormap *cube) -{ - int r = 0, g = 0, b = 0, c = 0, m = 0, y = 0, k, w; - XColor *color; - unsigned int found = 0; - int small, middle, large; - int smallMult, smallMax, middleMult, middleMax, largeMult, largeMax; - Bool backwards = False; - int mult = 1; - XStandardColormap test; /* Test cube */ - int i; - int size; - - if (black == NULL || white == NULL) return False; - - k = black->pixel; - w = white->pixel - k; - - size = ABS(w); - if (w < 0) { - backwards = True; - mult = -1; - } - - for (i = 1; i < size; i++) { - color = black + i*mult; - if (color->flags != (DoRed | DoBlue | DoGreen)) return False; - - /* If black or white is in the middle of the cube, can't work */ - if (CheckColor(color, 0, 0, 0)) return False; - if (CheckColor(color, 1, 1, 1)) return False; - - /* Check for red, green, blue, cyan, magenta, and yellow */ - if (CheckColor(color, 1, 0, 0)) {r = color->pixel-k; found |= R;} - else if (CheckColor(color, 0, 1, 0)) {g = color->pixel-k; found |= G;} - else if (CheckColor(color, 0, 0, 1)) {b = color->pixel-k; found |= B;} - else if (CheckColor(color, 0, 1, 1)) {c = color->pixel-k; found |= C;} - else if (CheckColor(color, 1, 0, 1)) {m = color->pixel-k; found |= M;} - else if (CheckColor(color, 1, 1, 0)) {y = color->pixel-k; found |= Y;} - } - - /* If any color is missing no cube is possible */ - if (found != (R | G | B | C | M | Y)) return False; - - /* Next test. Make sure B + G = C, R + B = M, R + G = Y, - and R + G + B = W */ - if (b + g != c) return False; - if (r + b != m) return False; - if (r + g != y) return False; - if (r + g + b != w) return False; - - /* Looking good! Compensate for backwards cubes */ - if (backwards) { - w = ABS(w); - r = ABS(r); - g = ABS(g); - b = ABS(b); - } - - /* Find the smallest, middle, and largest difference */ - if (r < b && b < g) { - small = r; middle = b; large = g; - } else if (r < g && g < b) { - small = r; middle = g; large = b; - } else if (b < r && r < g) { - small = b; middle = r; large = g; - } else if (b < g && g < r) { - small = b; middle = g; large = r; - } else if (g < r && r < b) { - small = g; middle = r; large = b; - } else { - small = g; middle = b; large = r; - } - - /* The smallest must divide the middle, and the middle the large */ - if ((middle % (small + 1)) != 0) return False; - if ((large % (small + middle + 1)) != 0) return False; - - /* OK, we believe we have a cube. Compute the description */ - smallMult = 1; - smallMax = small; - middleMult = small + 1; - middleMax = middle / middleMult; - largeMult = small + middle + 1; - largeMax = large / largeMult; - - if (small == r) { - test.red_max = smallMax; test.red_mult = smallMult; - if (middle == b) { - test.blue_max = middleMax; test.blue_mult = middleMult; - test.green_max = largeMax; test.green_mult = largeMult; - } else { - test.green_max = middleMax; test.green_mult = middleMult; - test.blue_max = largeMax; test.blue_mult = largeMult; - } - } else if (small == g) { - test.green_max = smallMax; test.green_mult = smallMult; - if (middle == b) { - test.blue_max = middleMax; test.blue_mult = middleMult; - test.red_max = largeMax; test.red_mult = largeMult; - } else { - test.red_max = middleMax; test.red_mult = middleMult; - test.blue_max = largeMax; test.blue_mult = largeMult; - } - } else { /* small == b */ - test.blue_max = smallMax; test.blue_mult = smallMult; - if (middle == r) { - test.red_max = middleMax; test.red_mult = middleMult; - test.green_max = largeMax; test.green_mult = largeMult; - } else { - test.green_max = middleMax; test.green_mult = middleMult; - test.red_max = largeMax; test.red_mult = largeMult; - } - } - - /* Re-compensate for backwards cube */ - if (backwards) { - test.red_mult *= -1; - test.green_mult *= -1; - test.blue_mult *= -1; - } - - /* Finally, test the hypothesis! The answer must be correct within 1 - bit. Only look at the top 8 bits; the others are too noisy */ - - for (i = 1; i < size; i++) { -#define calc(i, max, mult) ((((i / test.mult) % \ - (test.max + 1)) * SCALE) / test.max) - r = ((unsigned short) calc(i, red_max, red_mult) >> 8) - - (black[i*mult].red >> 8); - g = ((unsigned short) calc(i, green_max, green_mult) >> 8) - - (black[i*mult].green >> 8); - b = ((unsigned short) calc(i, blue_max, blue_mult) >> 8) - - (black[i*mult].blue >> 8); -#undef calc - if (ABS(r) > 2 || ABS(g) > 2 || ABS(b) > 2) return False; - } - cube->red_max = test.red_max; - cube->red_mult = test.red_mult; - cube->green_max = test.green_max; - cube->green_mult = test.green_mult; - cube->blue_max = test.blue_max; - cube->blue_mult = test.blue_mult; - cube->base_pixel = k; - return True; -} - -#undef R -#undef G -#undef B -#undef C -#undef M -#undef Y - -/* Query the entire colormap in the static gray case, then try to find - a gray ramp. This handles there being 2 white or black entries - in the colormap and finds the longest linear ramp between pairs of - white and black. If there is a color cube, also check its diagonal and - use its corners if we need to */ - -static void FindStaticGrayRamp( - Display *dpy, - XVisualInfo *vinfo, - XStandardColormap *grayRamp, - XStandardColormap *colorCube) -{ - XColor *ramp, *black, *white, *altBlack, *altWhite; - int i, r0, r1, r2, r3, size, entries, redMult; - unsigned long base; - - entries = 1 << vinfo->depth; - ramp = (XColor *) calloc(entries, sizeof(XColor)); - - if (ramp == NULL) { - grayRamp->red_max = 0; - return; - } - - /* Query the colormap */ - for (i = 0; i < entries; i++) ramp[i].pixel = i; - XQueryColors(dpy, grayRamp->colormap, ramp, entries); - - /* Find the white and black entries */ - - black = white = altBlack = altWhite = NULL; - for (i = 0; i < entries; i++) { - if (ramp[i].flags != (DoRed | DoBlue | DoGreen)) continue; - if (CheckColor(ramp+i, 0, 0, 0)) { - if (black == NULL) black = ramp+i; - else if (altBlack == NULL) altBlack = ramp+i; - } else if (CheckColor(ramp+i, 1, 1, 1)) { - if (white == NULL) white = ramp+i; - else if (altWhite == NULL) altWhite = ramp+i; - } - } - - if (black == NULL || white == NULL) { - grayRamp->red_max = 0; - free(ramp); - return; - } - - /* Find out how large a ramp exists between pairs of black & white */ - r0 = FindRampSize(black, white); - r1 = FindRampSize(altBlack, white); - r2 = FindRampSize(black, altWhite); - r3 = FindRampSize(altBlack, altWhite); - - size = r0; - if (r1 > size) size = r1; - if (r2 > size) size = r2; - if (r3 > size) size = r3; - if (size == r0) SetRamp(black, white, size, &redMult, &base); - else if (size == r1) SetRamp(altBlack, white, size, &redMult, &base); - else if (size == r2) SetRamp(black, altWhite, size, &redMult, &base); - else if (size == r3) SetRamp(altBlack, altWhite, size, &redMult, &base); - - if (colorCube != NULL && CubicCube(colorCube) && - colorCube->red_max > size) { - UseGrayDiagonal(colorCube, grayRamp); - } else { - grayRamp->red_max = size; - grayRamp->red_mult = redMult; - grayRamp->base_pixel = base; - } - - free(ramp); -} - -static int FindRampSize(XColor *black, XColor *white) -{ - XColor *c; - int r; - int mult = 1; - int i, size; - - if (black == NULL || white == NULL) return 0; - size = ABS(white - black); - - /* See if we have a backwards ramp */ - if (black > white) mult = -1; - - /* See if all cells between black and white are linear, to within 1 bit. - Only look at the high order 8 bits */ - - for (i = 1; i < size; i++) { - c = &black[i*mult]; - if (c->red != c->blue || c->red != c->green) return 1; - r = ((unsigned short) ((i * SCALE) / size) >> 8) - (c->red >> 8); - if (ABS(r) > 2) return 1; - } - return size; -} - -static void SetRamp( - XColor *black, - XColor *white, - int size, - int *mult, - unsigned long *base) -{ - *base = black->pixel; - *mult = (white - black) / size; -} - -#define lowbit(x) ((x) & (~(x) + 1)) - -static unsigned long shiftdown(unsigned long x) -{ - while ((x & 1) == 00) { - x = x >> 1; - } - return x; -} - -static void AllocateColorCube( - Display *dpy, - XVisualInfo *vinfo, - XStandardColormap *colorCube, - PixelRec *pixels) -{ - int count, first, remain, n, j; - unsigned long i; - Colormap cmap = colorCube->colormap; - unsigned long delta; - XColor color; - - /* We do no allocation for TrueColor or StaticColor */ - if (vinfo->class == TrueColor || vinfo->class == StaticColor) return; - - if (vinfo->class == DirectColor) { - if ((i = shiftdown(vinfo->red_mask)) > colorCube->red_max) - colorCube->red_max = i; - if ((i = shiftdown(vinfo->green_mask)) > colorCube->green_max) - colorCube->green_max = i; - if ((i = shiftdown(vinfo->blue_mask)) > colorCube->blue_max) - colorCube->blue_max = i; - - /* We only handle symmetric DirectColor */ - count = colorCube->red_max + 1; - if (colorCube->blue_max + 1 < count) count = colorCube->blue_max + 1; - if (colorCube->green_max + 1 < count) count = colorCube->green_max + 1; - colorCube->red_max = colorCube->blue_max = colorCube->green_max = - count - 1; - - delta = lowbit(vinfo->red_mask) + lowbit(vinfo->green_mask) + - lowbit(vinfo->blue_mask); - } else { - count = (colorCube->red_max + 1) * (colorCube->blue_max + 1) * - (colorCube->green_max + 1); - delta = 1; - } - - colorCube->base_pixel = 0; /* temporary, may change */ - - pixels->pixels = (unsigned long *) calloc(vinfo->colormap_size, - sizeof(unsigned long)); - if (pixels->pixels == NULL) { - colorCube->red_max = 0; - return; - } - - if (!AllocateColormap(dpy, colorCube, vinfo, &count, pixels, - &first, &remain, delta)) { - free((char *) pixels->pixels); - pixels->pixels = NULL; - colorCube->red_max = 0; - return; - } - - colorCube->base_pixel = pixels->pixels[first]; - color.flags = DoRed | DoGreen | DoBlue; - - /* Define colors */ - for (n = 0, j = 0; j < count; ++j, n += delta) { - color.pixel = n + pixels->pixels[first]; - if (vinfo->class == PseudoColor) { -#define calc(i, max, mult) ((((i / colorCube->mult) % \ - (colorCube->max + 1)) * SCALE) / colorCube->max) - color.red = (unsigned short) calc(n, red_max, red_mult); - color.green = (unsigned short) calc(n, green_max, green_mult); - color.blue = (unsigned short) calc(n, blue_max, blue_mult); -#undef calc - } else { - color.red = color.green = color.blue = - (j * SCALE) / colorCube->red_max; - } - if (!AllocateColor(dpy, cmap, &color)) { - XFreeColors(dpy, cmap, pixels->pixels, count+first+remain, 0); - free((char *) pixels->pixels); - pixels->pixels = NULL; - colorCube->red_max = 0; - return; - } - } - - /* Smush down unused pixels, if any */ - - for (j = 0; j < remain; j++) { - pixels->pixels[first+j] = pixels->pixels[first+count+j]; - } - pixels->npixels -= count; -} - -static void AllocateGrayRamp( - Display *dpy, - XVisualInfo *vinfo, - XStandardColormap *grayRamp, - XStandardColormap *colorCube, - PixelRec *pixels) -{ - int count, first, remain, n, i; - Colormap cmap = grayRamp->colormap; - XColor color; - unsigned long delta; - - /* Allocate cells in read/write visuals only */ - if (vinfo->class != PseudoColor && vinfo->class != GrayScale && - vinfo->class != DirectColor) return; - - if (vinfo->class == DirectColor) { - delta = lowbit(vinfo->red_mask) + lowbit(vinfo->green_mask) + - lowbit(vinfo->blue_mask); - } else delta = 1; - - /* First of all see if there's a usable gray ramp in the color cube */ - - if (colorCube != NULL) { - if (CubicCube(colorCube)) { - if (colorCube->red_max >= grayRamp->red_max) { - /* diagonal is long enough! use it */ - UseGrayDiagonal(colorCube, grayRamp); - return; - } - } - } - - grayRamp->base_pixel = 0; /* temporary, may change */ - - count = grayRamp->red_max + 1; - - if (pixels->pixels == NULL) { - pixels->pixels = (unsigned long *) calloc(vinfo->colormap_size, - sizeof(unsigned long)); - if (pixels->pixels == NULL) { - grayRamp->red_max = 0; - return; - } - } - - if (!AllocateColormap(dpy, grayRamp, vinfo, &count, pixels, - &first, &remain, delta)) { - /* Last gasp: try any diagonal or the corners of the color cube */ - if (colorCube != NULL) { - if (CubicCube(colorCube)) UseGrayDiagonal(colorCube, grayRamp); - else UseGrayCorners(colorCube, grayRamp); - } else { - grayRamp->red_max = 0; - } - return; - } - - grayRamp->base_pixel = pixels->pixels[first]; - color.flags = DoRed | DoGreen | DoBlue; - - /* Define colors */ - for (n = 0, i = 0; i < count; ++i, n += delta) { - color.pixel = n + pixels->pixels[first]; - color.red = (unsigned short)((n * SCALE) / (grayRamp->red_max)); - color.green = color.red; - color.blue = color.red; - - if (!AllocateColor(dpy, cmap, &color)) { - /* Don't need to free pixels here; we'll do it on return */ - grayRamp->red_max = 0; - return; - } - } - - /* Smush down unused pixels, if any */ - - for (i = 0; i < remain; i++) { - pixels->pixels[first+i] = pixels->pixels[first+count+i]; - } - pixels->npixels -= count; -} - -static int compare(const void *a1, const void *a2) -{ - register unsigned long *e1 = (unsigned long *) a1, - *e2 = (unsigned long *) a2; - - if (*e1 < *e2) return -1; - if (*e1 > *e2) return 1; - return 0; -} - -static Bool AllocateColormap( - Display *dpy, - XStandardColormap *map, - XVisualInfo *vinfo, - int *count, - PixelRec *pixels, - int *first, int *remain, - unsigned long delta) -{ - Colormap cmap = map->colormap; - int npixels, ok, i; - Bool success = False; - - if (pixels->npixels == 0) { - /* First try to allocate the entire colormap */ - npixels = vinfo->colormap_size; - ok = XAllocColorCells(dpy, cmap, 1, NULL, 0, pixels->pixels, npixels); - if (ok) success = True; - else { - int total; - int top, mid = 0; - - /* If it's a gray ramp or direct color we need at least 2; - others 8 */ - if (map->blue_max == 0 || vinfo->class == DirectColor) total = 2; - else total = 8; - - /* Allocate all available cells, using binary backoff */ - top = vinfo->colormap_size - 1; - while (total <= top) { - mid = total + ((top - total + 1) / 2); - ok = XAllocColorCells(dpy, cmap, 1, NULL, 0, - pixels->pixels, mid); - if (ok) { - if (mid == top) { - success = True; - break; - } else { - XFreeColors(dpy, cmap, pixels->pixels, mid, 0); - total = mid; - } - } else top = mid - 1; - } - if (success) npixels = mid; - else npixels = 0; - } - } else { - /* We must be in the gray ramp case, so we need at least 2 entries */ - npixels = pixels->npixels; - if (map->blue_max != 0 || npixels >= 2) success = True; - } - - if (success) { - /* Avoid pessimal case by testing to see if already sorted */ - for (i = 0; i < npixels-1; ++i) { - if (pixels->pixels[i] != pixels->pixels[i+1]-1) break; - } - - if (i < npixels-1) { - PrivSort((char *)pixels->pixels, npixels, - sizeof(unsigned long), compare); - } - - if (!contiguous(pixels->pixels, npixels, count, delta, - first, remain)) { - /* If there are enough free cells, shrink the map to fit. - Otherwise fail; we'll free the pixels later */ - if (((map->blue_max == 0 || vinfo->class == DirectColor) && - *count >= 2) || *count >=8) { - ShrinkMapToFit(map, count, vinfo); - *remain = npixels - *first - *count; - } else success = False; - } - } - - pixels->npixels = npixels; - return success; -} - -static Bool contiguous( - unsigned long pixels[], /* specifies allocated pixels */ - int npixels, /* specifies count of alloc'd pixels */ - int *ncolors, /* specifies needed sequence length - If not available, returns max - available contiguous sequence */ - unsigned long delta, - int *first, /* returns first index of sequence */ - int *rem) /* returns first index after sequence, - * or 0, if none follow */ -{ - register int i = 1; /* walking index into the pixel array */ - register int count = 1; /* length of sequence discovered so far */ - int max = 1; /* longest sequence we found */ - int maxstart = 0; - - *first = 0; - while (count < *ncolors && i < npixels) { - if (pixels[i-1] + delta == pixels[i]) count++; - else { - if (count > max) { - max = count; - maxstart = *first; - } - count = 1; - *first = i; - } - i++; - } - if (i == npixels && count > max) { - max = count; - maxstart = *first; - } - *rem = npixels - i; - if (count != *ncolors) { - *ncolors = max; - *first = maxstart; - return False; - } return True; -} - -static Bool AllocateColor( - Display *dpy, - Colormap cmap, - XColor *color) -{ - unsigned long pix = color->pixel; - XColor request; - int ok; - - request = *color; - - /* Free RW, Alloc RO, if fails, try RW */ - XFreeColors(dpy, cmap, &pix, 1, 0); - ok = XAllocColor(dpy, cmap, &request); - - /* If the pixel we get back isn't the request one, probably RO - White or Black, so shove it in RW so our cube is correct. - If alloc fails, try RW. */ - - if (!ok || request.pixel != color->pixel) { - ok = XAllocColorCells(dpy, cmap, 0, NULL, 0, &pix, 1); - - if (pix != color->pixel) XFreeColors(dpy, cmap, &pix, 1, 0); - if (!ok || pix != color->pixel) { - return False; - } - request = *color; - XStoreColor(dpy, cmap, &request); - } - return True; -} - -static void ShrinkMapToFit( - XStandardColormap *map, - int *space, - XVisualInfo *vinfo) -{ - if (map->blue_max == 0) map->red_max = *space - 1; - else if (vinfo->class == DirectColor) { - if (map->red_max > *space - 1) map->red_max = *space - 1; - if (map->green_max > *space - 1) map->green_max = *space - 1; - if (map->blue_max > *space - 1) map->blue_max = *space - 1; - } else { - int which = 2; - while ((map->red_max + 1) * (map->green_max + 1) * - (map->blue_max + 1) > *space) { - if (which == 0) { - if (map->red_max > 1) map->red_max--; - which = 1; - } else if (which == 1) { - if (map->green_max > 1) map->green_max--; - which = 2; - } else { - if (map->blue_max > 1) map->blue_max--; - which = 0; - } - } - *space = (map->red_max + 1) * (map->green_max + 1) * - (map->blue_max + 1); - - map->red_mult = (map->green_max + 1) * (map->blue_max + 1); - map->green_mult = map->blue_max + 1; - map->blue_mult = 1; - } -} - -static void DefineProperty( - Display *dpy, - XStandardColormap *map, - XVisualInfo *vinfo, - XStandardColormap *prop, - int nProp, - Atom atom) -{ - XStandardColormap *copy; - int i; - - if (nProp == 0) { - XSetRGBColormaps(dpy, RootWindow(dpy, vinfo->screen), map, 1, atom); - return; - } - - copy = (XStandardColormap *) calloc(nProp+1, sizeof(XStandardColormap)); - - /* Hm. If I can't allocate the list, is it better to just put our - property on, or to leave the ones there? I'll guess the latter... */ - if (copy == NULL) return; - - if (vinfo->visual == DefaultVisual(dpy, vinfo->screen) && - map->colormap == DefaultColormap(dpy, vinfo->screen)) { - /* Put new entry first; it's more likely to be useful */ - for (i = 0; i < nProp; i++) copy[i+1] = prop[i]; - i = 0; - } else { - /* Put it at the end */ - for (i = 0; i < nProp; i++) copy[i] = prop[i]; - /* i = nProp; (it does already) */ - } - - copy[i] = *map; - XSetRGBColormaps(dpy, RootWindow(dpy, vinfo->screen), copy, nProp+1, atom); - - free((void *) copy); -} |