From 33b8c225e1ede99070d63936da1c76dcee218577 Mon Sep 17 00:00:00 2001 From: kojima Date: Tue, 16 Nov 1999 00:13:21 +0000 Subject: [PATCH] - standard colormap support for PseudoColor visuals - set wrlib library version to 4:0:3 (1.3.0) --- wrlib/CmapAlloc.c | 335 ++++++++++++++++++++++++++++++++++ wrlib/CrCmap.c | 524 +++++++++++++++++++++++++++++++++++++++++++++++++++++ wrlib/DelCmap.c | 67 +++++++ wrlib/LookupCmap.c | 312 +++++++++++++++++++++++++++++++ wrlib/Makefile.am | 8 +- wrlib/Makefile.in | 18 +- wrlib/StdCmap.c | 219 ++++++++++++++++++++++ wrlib/StdCmap.h | 112 ++++++++++++ wrlib/context.c | 208 ++++++++++++++++++++- wrlib/convert.c | 282 +++++++++++++++++++++++++--- wrlib/misc.c | 26 +-- wrlib/view.c | 2 + wrlib/wraster.h | 35 +++- 13 files changed, 2088 insertions(+), 60 deletions(-) create mode 100644 wrlib/CmapAlloc.c create mode 100644 wrlib/CrCmap.c create mode 100644 wrlib/DelCmap.c create mode 100644 wrlib/LookupCmap.c create mode 100644 wrlib/StdCmap.c create mode 100644 wrlib/StdCmap.h diff --git a/wrlib/CmapAlloc.c b/wrlib/CmapAlloc.c new file mode 100644 index 00000000..9da1d7c9 --- /dev/null +++ b/wrlib/CmapAlloc.c @@ -0,0 +1,335 @@ +/* $XConsortium: CmapAlloc.c,v 1.9 94/04/17 20:15:52 rws Exp $ */ + +/* + +Copyright (c) 1989, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + +*/ + +/* + * Author: Donna Converse, MIT X Consortium + */ + +#include +#include +#include +#include + +#define lowbit(x) ((x) & (~(x) + 1)) + +static int default_allocation(); +static void best_allocation(); +static void gray_allocation(); +static int icbrt(); +static int icbrt_with_bits(); +static int icbrt_with_guess(); + +/* To determine the best allocation of reds, greens, and blues in a + * standard colormap, use XmuGetColormapAllocation. + * vinfo specifies visual information for a chosen visual + * property specifies one of the standard colormap property names + * red_max returns maximum red value + * green_max returns maximum green value + * blue_max returns maximum blue value + * + * XmuGetColormapAllocation returns 0 on failure, non-zero on success. + * It is assumed that the visual is appropriate for the colormap property. + */ + +Status XmuGetColormapAllocation(vinfo, property, red_max, green_max, blue_max) + XVisualInfo *vinfo; + Atom property; + unsigned long *red_max, *green_max, *blue_max; +{ + Status status = 1; + + if (vinfo->colormap_size <= 2) + return 0; + + switch (property) + { + case XA_RGB_DEFAULT_MAP: + status = default_allocation(vinfo, red_max, green_max, blue_max); + break; + case XA_RGB_BEST_MAP: + best_allocation(vinfo, red_max, green_max, blue_max); + break; + case XA_RGB_GRAY_MAP: + gray_allocation(vinfo->colormap_size, red_max, green_max, blue_max); + break; + case XA_RGB_RED_MAP: + *red_max = vinfo->colormap_size - 1; + *green_max = *blue_max = 0; + break; + case XA_RGB_GREEN_MAP: + *green_max = vinfo->colormap_size - 1; + *red_max = *blue_max = 0; + break; + case XA_RGB_BLUE_MAP: + *blue_max = vinfo->colormap_size - 1; + *red_max = *green_max = 0; + break; + default: + status = 0; + } + return status; +} + +/****************************************************************************/ +/* Determine the appropriate color allocations of a gray scale. + * + * Keith Packard, MIT X Consortium + */ + +static void gray_allocation(n, red_max, green_max, blue_max) + int n; /* the number of cells of the gray scale */ + unsigned long *red_max, *green_max, *blue_max; +{ + *red_max = (n * 30) / 100; + *green_max = (n * 59) / 100; + *blue_max = (n * 11) / 100; + *green_max += ((n - 1) - (*red_max + *green_max + *blue_max)); +} + +/****************************************************************************/ +/* Determine an appropriate color allocation for the RGB_DEFAULT_MAP. + * If a map has less than a minimum number of definable entries, we do not + * produce an allocation for an RGB_DEFAULT_MAP. + * + * For 16 planes, the default colormap will have 27 each RGB; for 12 planes, + * 12 each. For 8 planes, let n = the number of colormap entries, which may + * be 256 or 254. Then, maximum red value = floor(cube_root(n - 125)) - 1. + * Maximum green and maximum blue values are identical to maximum red. + * This leaves at least 125 cells which clients can allocate. + * + * Return 0 if an allocation has been determined, non-zero otherwise. + */ + +static int default_allocation(vinfo, red, green, blue) + XVisualInfo *vinfo; + unsigned long *red, *green, *blue; +{ + int ngrays; /* number of gray cells */ + + switch (vinfo->class) { + case PseudoColor: + + if (vinfo->colormap_size > 65000) + /* intended for displays with 16 planes */ + *red = *green = *blue = (unsigned long) 27; + else if (vinfo->colormap_size > 4000) + /* intended for displays with 12 planes */ + *red = *green = *blue = (unsigned long) 12; + else if (vinfo->colormap_size < 250) + return 0; + else + /* intended for displays with 8 planes */ + *red = *green = *blue = (unsigned long) + (icbrt(vinfo->colormap_size - 125) - 1); + break; + + case DirectColor: + + if (vinfo->colormap_size < 10) + return 0; + *red = *green = *blue = vinfo->colormap_size / 2 - 1; + break; + + case TrueColor: + + *red = vinfo->red_mask / lowbit(vinfo->red_mask); + *green = vinfo->green_mask / lowbit(vinfo->green_mask); + *blue = vinfo->blue_mask / lowbit(vinfo->blue_mask); + break; + + case GrayScale: + + if (vinfo->colormap_size > 65000) + ngrays = 4096; + else if (vinfo->colormap_size > 4000) + ngrays = 512; + else if (vinfo->colormap_size < 250) + return 0; + else + ngrays = 12; + gray_allocation(ngrays, red, green, blue); + break; + + default: + return 0; + } + return 1; +} + +/****************************************************************************/ +/* Determine an appropriate color allocation for the RGB_BEST_MAP. + * + * For a DirectColor or TrueColor visual, the allocation is determined + * by the red_mask, green_mask, and blue_mask members of the visual info. + * + * Otherwise, if the colormap size is an integral power of 2, determine + * the allocation according to the number of bits given to each color, + * with green getting more than red, and red more than blue, if there + * are to be inequities in the distribution. If the colormap size is + * not an integral power of 2, let n = the number of colormap entries. + * Then maximum red value = floor(cube_root(n)) - 1; + * maximum blue value = floor(cube_root(n)) - 1; + * maximum green value = n / ((# red values) * (# blue values)) - 1; + * Which, on a GPX, allows for 252 entries in the best map, out of 254 + * defineable colormap entries. + */ + +static void best_allocation(vinfo, red, green, blue) + XVisualInfo *vinfo; + unsigned long *red, *green, *blue; +{ + + if (vinfo->class == DirectColor || vinfo->class == TrueColor) + { + *red = vinfo->red_mask; + while ((*red & 01) == 0) + *red >>= 1; + *green = vinfo->green_mask; + while ((*green & 01) == 0) + *green >>=1; + *blue = vinfo->blue_mask; + while ((*blue & 01) == 0) + *blue >>= 1; + } + else + { + register int bits, n; + + /* Determine n such that n is the least integral power of 2 which is + * greater than or equal to the number of entries in the colormap. + */ + n = 1; + bits = 0; + while (vinfo->colormap_size > n) + { + n = n << 1; + bits++; + } + + /* If the number of entries in the colormap is a power of 2, determine + * the allocation by "dealing" the bits, first to green, then red, then + * blue. If not, find the maximum integral red, green, and blue values + * which, when multiplied together, do not exceed the number of + + * colormap entries. + */ + if (n == vinfo->colormap_size) + { + register int r, g, b; + b = bits / 3; + g = b + ((bits % 3) ? 1 : 0); + r = b + (((bits % 3) == 2) ? 1 : 0); + *red = 1 << r; + *green = 1 << g; + *blue = 1 << b; + } + else + { + *red = icbrt_with_bits(vinfo->colormap_size, bits); + *blue = *red; + *green = (vinfo->colormap_size / ((*red) * (*blue))); + } + (*red)--; + (*green)--; + (*blue)--; + } + return; +} + +/* + * integer cube roots by Newton's method + * + * Stephen Gildea, MIT X Consortium, July 1991 + */ + +static int icbrt(a) /* integer cube root */ + int a; +{ + register int bits = 0; + register unsigned n = a; + + while (n) + { + bits++; + n >>= 1; + } + return icbrt_with_bits(a, bits); +} + + +static int icbrt_with_bits(a, bits) + int a; + int bits; /* log 2 of a */ +{ + return icbrt_with_guess(a, a>>2*bits/3); +} + +#ifdef _X_ROOT_STATS +int icbrt_loopcount; +#endif + +/* Newton's Method: x_n+1 = x_n - ( f(x_n) / f'(x_n) ) */ + +/* for cube roots, x^3 - a = 0, x_new = x - 1/3 (x - a/x^2) */ + +/* + * Quick and dirty cube roots. Nothing fancy here, just Newton's method. + * Only works for positive integers (since that's all we need). + * We actually return floor(cbrt(a)) because that's what we need here, too. + */ + +static int icbrt_with_guess(a, guess) + int a, guess; +{ + register int delta; + +#ifdef _X_ROOT_STATS + icbrt_loopcount = 0; +#endif + if (a <= 0) + return 0; + if (guess < 1) + guess = 1; + + do { +#ifdef _X_ROOT_STATS + icbrt_loopcount++; +#endif + delta = (guess - a/(guess*guess))/3; +#ifdef DEBUG + printf("pass %d: guess=%d, delta=%d\n", icbrt_loopcount, guess, delta); +#endif + guess -= delta; + } while (delta != 0); + + if (guess*guess*guess > a) + guess--; + + return guess; +} diff --git a/wrlib/CrCmap.c b/wrlib/CrCmap.c new file mode 100644 index 00000000..8522e7e7 --- /dev/null +++ b/wrlib/CrCmap.c @@ -0,0 +1,524 @@ +/* $XConsortium: CrCmap.c,v 1.6 94/04/17 20:15:53 rws Exp $ */ + +/* + +Copyright (c) 1989 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + +*/ + +/* + * Author: Donna Converse, MIT X Consortium + */ + +/* + * CreateCmap.c - given a standard colormap description, make the map. + */ + +#include +#include +#include +#include + + +static int ROmap(); /* allocate entire map Read Only */ +static Status ROorRWcell(); /* allocate a cell, prefer Read Only */ +static Status RWcell(); /* allocate a cell Read Write */ +static int compare(); /* for quicksort */ +static Status contiguous(); /* find contiguous sequence of cells */ +static void free_cells(); /* frees resources before quitting */ +static Status readonly_map(); /* create a map in a RO visual type */ +static Status readwrite_map(); /* create a map in a RW visual type */ + +#define lowbit(x) ((x) & (~(x) + 1)) +#define TRUEMATCH(mult,max,mask) \ + (colormap->max * colormap->mult <= vinfo->mask && \ + lowbit(vinfo->mask) == colormap->mult) + +/* + * To create any one colormap which is described by an XStandardColormap + * structure, use XmuCreateColormap(). + * + * Return 0 on failure, non-zero on success. + * Resources created by this function are not made permanent. + * No argument error checking is provided. Use at your own risk. + * + * All colormaps are created with read only allocations, with the exception + * of read only allocations of colors in the default map or otherwise + * which fail to return the expected pixel value, and these are individually + * defined as read/write allocations. This is done so that all the cells + * defined in the default map are contiguous, for use in image processing. + * This typically happens with White and Black in the default map. + * + * Colormaps of static visuals are considered to be successfully created if + * the map of the static visual matches the definition given in the + * standard colormap structure. + */ + +Status XmuCreateColormap(dpy, colormap) + Display *dpy; /* specifies the connection under + * which the map is created */ + XStandardColormap *colormap; /* specifies the map to be created, + * and returns, particularly if the + * map is created as a subset of the + * default colormap of the screen, + * the base_pixel of the map. + */ +{ + XVisualInfo vinfo_template; /* template visual information */ + XVisualInfo *vinfo; /* matching visual information */ + XVisualInfo *vpointer; /* for freeing the entire list */ + long vinfo_mask; /* specifies the visual mask value */ + int n; /* number of matching visuals */ + int status; + + vinfo_template.visualid = colormap->visualid; + vinfo_mask = VisualIDMask; + if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL) + return 0; + + /* 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. + */ + vpointer = vinfo; + if (n > 1) + { + register int i; + register int screen_number; + Bool def_cmap; + + def_cmap = False; + for (screen_number = ScreenCount(dpy); --screen_number >= 0; ) + if (colormap->colormap == DefaultColormap(dpy, screen_number)) { + def_cmap = True; + break; + } + + if (def_cmap) { + for (i=0; i < n; i++, vinfo++) { + if (vinfo->visual == DefaultVisual(dpy, screen_number)) + break; + } + } else { + unsigned int maxdepth = 0; + XVisualInfo *v; + + for (i=0; i < n; i++, vinfo++) + if (vinfo->depth > maxdepth) { + maxdepth = vinfo->depth; + v = vinfo; + } + vinfo = v; + } + } + + if (vinfo->class == PseudoColor || vinfo->class == DirectColor || + vinfo->class == GrayScale) + status = readwrite_map(dpy, vinfo, colormap); + else if (vinfo->class == TrueColor) + status = TRUEMATCH(red_mult, red_max, red_mask) && + TRUEMATCH(green_mult, green_max, green_mask) && + TRUEMATCH(blue_mult, blue_max, blue_mask); + else + status = readonly_map(dpy, vinfo, colormap); + + XFree((char *) vpointer); + return status; +} + +/****************************************************************************/ +static Status readwrite_map(dpy, vinfo, colormap) + Display *dpy; + XVisualInfo *vinfo; + XStandardColormap *colormap; +{ + register unsigned long i, n; /* index counters */ + int ncolors; /* number of colors to be defined */ + int npixels; /* number of pixels allocated R/W */ + int first_index; /* first index of pixels to use */ + int remainder; /* first index of remainder */ + XColor color; /* the definition of a color */ + unsigned long *pixels; /* array of colormap pixels */ + unsigned long delta; + + + /* Determine ncolors, the number of colors to be defined. + * Insure that 1 < ncolors <= the colormap size. + */ + if (vinfo->class == DirectColor) { + ncolors = colormap->red_max; + if (colormap->green_max > ncolors) + ncolors = colormap->green_max; + if (colormap->blue_max > ncolors) + ncolors = colormap->blue_max; + ncolors++; + delta = lowbit(vinfo->red_mask) + + lowbit(vinfo->green_mask) + + lowbit(vinfo->blue_mask); + } else { + ncolors = colormap->red_max * colormap->red_mult + + colormap->green_max * colormap->green_mult + + colormap->blue_max * colormap->blue_mult + 1; + delta = 1; + } + if (ncolors <= 1 || ncolors > vinfo->colormap_size) return 0; + + /* Allocate Read/Write as much of the colormap as we can possibly get. + * Then insure that the pixels we were allocated are given in + * monotonically increasing order, using a quicksort. Next, insure + * that our allocation includes a subset of contiguous pixels at least + * as long as the number of colors to be defined. Now we know that + * these conditions are met: + * 1) There are no free cells in the colormap. + * 2) We have a contiguous sequence of pixels, monotonically + * increasing, of length >= the number of colors requested. + * + * One cell at a time, we will free, compute the next color value, + * then allocate read only. This takes a long time. + * This is done to insure that cells are allocated read only in the + * contiguous order which we prefer. If the server has a choice of + * cells to grant to an allocation request, the server may give us any + * cell, so that is why we do these slow gymnastics. + */ + + if ((pixels = (unsigned long *) calloc((unsigned) vinfo->colormap_size, + sizeof(unsigned long))) == NULL) + return 0; + + if ((npixels = ROmap(dpy, colormap->colormap, pixels, + vinfo->colormap_size, ncolors)) == 0) { + free((char *) pixels); + return 0; + } + + qsort((char *) pixels, npixels, sizeof(unsigned long), compare); + + if (!contiguous(pixels, npixels, ncolors, delta, &first_index, &remainder)) + { + /* can't find enough contiguous cells, give up */ + XFreeColors(dpy, colormap->colormap, pixels, npixels, + (unsigned long) 0); + free((char *) pixels); + return 0; + } + colormap->base_pixel = pixels[first_index]; + + /* construct a gray map */ + if (colormap->red_mult == 1 && colormap->green_mult == 1 && + colormap->blue_mult == 1) + for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta) + { + color.pixel = n; + color.blue = color.green = color.red = + (unsigned short) ((i * 65535) / (colormap->red_max + + colormap->green_max + + colormap->blue_max)); + + if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color, + first_index + i)) + return 0; + } + + /* construct a red ramp map */ + else if (colormap->green_max == 0 && colormap->blue_max == 0) + for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta) + { + color.pixel = n; + color.red = (unsigned short) ((i * 65535) / colormap->red_max); + color.green = color.blue = 0; + + if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color, + first_index + i)) + return 0; + } + + /* construct a green ramp map */ + else if (colormap->red_max == 0 && colormap->blue_max == 0) + for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta) + { + color.pixel = n; + color.green = (unsigned short) ((i * 65535) / colormap->green_max); + color.red = color.blue = 0; + + if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color, + first_index + i)) + return 0; + } + + /* construct a blue ramp map */ + else if (colormap->red_max == 0 && colormap->green_max == 0) + for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta) + { + color.pixel = n; + color.blue = (unsigned short) ((i * 65535) / colormap->blue_max); + color.red = color.green = 0; + + if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color, + first_index + i)) + return 0; + } + + /* construct a standard red green blue cube map */ + else + { +#define calc(max,mult) (((n / colormap->mult) % \ + (colormap->max + 1)) * 65535) / colormap->max + + for (n=0, i=0; i < ncolors; i++, n += delta) + { + color.pixel = n + colormap->base_pixel; + color.red = calc(red_max, red_mult); + color.green = calc(green_max, green_mult); + color.blue = calc(blue_max, blue_mult); + if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color, + first_index + i)) + return 0; + } +#undef calc + } + /* We have a read-only map defined. Now free unused cells, + * first those occuring before the contiguous sequence begins, + * then any following the contiguous sequence. + */ + + if (first_index) + XFreeColors(dpy, colormap->colormap, pixels, first_index, + (unsigned long) 0); + if (remainder) + XFreeColors(dpy, colormap->colormap, + &(pixels[first_index + ncolors]), remainder, + (unsigned long) 0); + + free((char *) pixels); + return 1; +} + + +/****************************************************************************/ +static int ROmap(dpy, cmap, pixels, m, n) + Display *dpy; /* the X server connection */ + Colormap cmap; /* specifies colormap ID */ + unsigned long pixels[]; /* returns pixel allocations */ + int m; /* specifies colormap size */ + int n; /* specifies number of colors */ +{ + register int p; + + /* first try to allocate the entire colormap */ + if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL, + (unsigned) 0, pixels, (unsigned) m)) + return m; + + /* Allocate all available cells in the colormap, using a binary + * algorithm to discover how many cells we can allocate in the colormap. + */ + m--; + while (n <= m) { + p = n + ((m - n + 1) / 2); + if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL, + (unsigned) 0, pixels, (unsigned) p)) { + if (p == m) + return p; + else { + XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0); + n = p; + } + } + else + m = p - 1; + } + return 0; +} + + +/****************************************************************************/ +static Status contiguous(pixels, npixels, ncolors, delta, first, rem) + unsigned long pixels[]; /* specifies allocated pixels */ + int npixels; /* specifies count of alloc'd pixels */ + int ncolors; /* specifies needed sequence length */ + unsigned long delta; /* between pixels */ + 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 */ + + *first = 0; + if (npixels == ncolors) { + *rem = 0; + return 1; + } + *rem = npixels - 1; + while (count < ncolors && ncolors - count <= *rem) + { + if (pixels[i-1] + delta == pixels[i]) + count++; + else { + count = 1; + *first = i; + } + i++; + (*rem)--; + } + if (count != ncolors) + return 0; + return 1; +} + + +/****************************************************************************/ +static Status ROorRWcell(dpy, cmap, pixels, npixels, color, p) + Display *dpy; + Colormap cmap; + unsigned long pixels[]; + int npixels; + XColor *color; + unsigned long p; +{ + unsigned long pixel; + XColor request; + + /* Free the read/write allocation of one cell in the colormap. + * Request a read only allocation of one cell in the colormap. + * If the read only allocation cannot be granted, give up, because + * there must be no free cells in the colormap. + * If the read only allocation is granted, but gives us a cell which + * is not the one that we just freed, it is probably the case that + * we are trying allocate White or Black or some other color which + * already has a read-only allocation in the map. So we try to + * allocate the previously freed cell with a read/write allocation, + * because we want contiguous cells for image processing algorithms. + */ + + pixel = color->pixel; + request.red = color->red; + request.green = color->green; + request.blue = color->blue; + + XFreeColors(dpy, cmap, &pixel, 1, (unsigned long) 0); + if (! XAllocColor(dpy, cmap, color) + || (color->pixel != pixel && + (!RWcell(dpy, cmap, color, &request, &pixel)))) + { + free_cells(dpy, cmap, pixels, npixels, (int)p); + return 0; + } + return 1; +} + + +/****************************************************************************/ +static void free_cells(dpy, cmap, pixels, npixels, p) + Display *dpy; + Colormap cmap; + unsigned long pixels[]; /* to be freed */ + int npixels; /* original number allocated */ + int p; +{ + /* One of the npixels allocated has already been freed. + * p is the index of the freed pixel. + * First free the pixels preceeding p, and there are p of them; + * then free the pixels following p, there are npixels - p - 1 of them. + */ + XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0); + XFreeColors(dpy, cmap, &(pixels[p+1]), npixels - p - 1, (unsigned long) 0); + free((char *) pixels); +} + + +/****************************************************************************/ +static Status RWcell(dpy, cmap, color, request, pixel) + Display *dpy; + Colormap cmap; + XColor *color; + XColor *request; + unsigned long *pixel; +{ + unsigned long n = *pixel; + + XFreeColors(dpy, cmap, &(color->pixel), 1, (unsigned long)0); + if (! XAllocColorCells(dpy, cmap, (Bool) 0, (unsigned long *) NULL, + (unsigned) 0, pixel, (unsigned) 1)) + return 0; + if (*pixel != n) + { + XFreeColors(dpy, cmap, pixel, 1, (unsigned long) 0); + return 0; + } + color->pixel = *pixel; + color->flags = DoRed | DoGreen | DoBlue; + color->red = request->red; + color->green = request->green; + color->blue = request->blue; + XStoreColors(dpy, cmap, color, 1); + return 1; +} + + +/****************************************************************************/ +static int compare(e1, e2) + unsigned long *e1, *e2; +{ + if (*e1 < *e2) return -1; + if (*e1 > *e2) return 1; + return 0; +} + + +/****************************************************************************/ +static Status readonly_map(dpy, vinfo, colormap) + Display *dpy; + XVisualInfo *vinfo; + XStandardColormap *colormap; +{ + int i, last_pixel; + XColor color; + + last_pixel = (colormap->red_max + 1) * (colormap->green_max + 1) * + (colormap->blue_max + 1) + colormap->base_pixel - 1; + + for(i=colormap->base_pixel; i <= last_pixel; i++) { + + color.pixel = (unsigned long) i; + color.red = (unsigned short) + (((i/colormap->red_mult) * 65535) / colormap->red_max); + + if (vinfo->class == StaticColor) { + color.green = (unsigned short) + ((((i/colormap->green_mult) % (colormap->green_max + 1)) * + 65535) / colormap->green_max); + color.blue = (unsigned short) + (((i%colormap->green_mult) * 65535) / colormap->blue_max); + } + else /* vinfo->class == GrayScale, old style allocation XXX */ + color.green = color.blue = color.red; + + XAllocColor(dpy, colormap->colormap, &color); + if (color.pixel != (unsigned long) i) + return 0; + } + return 1; +} diff --git a/wrlib/DelCmap.c b/wrlib/DelCmap.c new file mode 100644 index 00000000..b02e3b80 --- /dev/null +++ b/wrlib/DelCmap.c @@ -0,0 +1,67 @@ +/* $XConsortium: DelCmap.c,v 1.2 94/04/17 20:15:58 converse Exp $ */ + +/* + +Copyright (c) 1989 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + +*/ + +/* + * Author: Donna Converse, MIT X Consortium + */ + +#include +#include + +/* To remove any standard colormap property, use XmuDeleteStandardColormap(). + * XmuDeleteStandardColormap() will remove the specified property from the + * specified screen, releasing any resources used by the colormap(s) of the + * property if possible. + */ + +void XmuDeleteStandardColormap(dpy, screen, property) + Display *dpy; /* specifies the X server to connect to */ + int screen; /* specifies the screen of the display */ + Atom property; /* specifies the standard colormap property */ +{ + XStandardColormap *stdcmaps, *s; + int count = 0; + + if (XGetRGBColormaps(dpy, RootWindow(dpy, screen), &stdcmaps, &count, + property)) + { + for (s=stdcmaps; count > 0; count--, s++) { + if ((s->killid == ReleaseByFreeingColormap) && + (s->colormap != None) && + (s->colormap != DefaultColormap(dpy, screen))) + XFreeColormap(dpy, s->colormap); + else if (s->killid != None) + XKillClient(dpy, s->killid); + } + XDeleteProperty(dpy, RootWindow(dpy, screen), property); + XFree((char *) stdcmaps); + XSync(dpy, False); + } +} + diff --git a/wrlib/LookupCmap.c b/wrlib/LookupCmap.c new file mode 100644 index 00000000..83ebd33d --- /dev/null +++ b/wrlib/LookupCmap.c @@ -0,0 +1,312 @@ +/* $XConsortium: LookupCmap.c,v 1.10 94/04/17 20:16:11 rws Exp $ */ + +/* + +Copyright (c) 1989 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + +*/ + +/* + * Author: Donna Converse, MIT X Consortium + */ + +#include +#include +#include +#include +#include +#include + + +static Status lookup(); + +/* + * To create a standard colormap if one does not currently exist, or + * replace the currently existing standard colormap, use + * XmuLookupStandardColormap(). + * + * Given a screen, a visual, and a property, XmuLookupStandardColormap() + * will determine the best allocation for the property under the specified + * visual, and determine the whether to create a new colormap or to use + * the default colormap of the screen. It will call XmuStandardColormap() + * to create the standard colormap. + * + * If replace is true, any previous definition of the property will be + * replaced. If retain is true, the property and the colormap will be + * made permanent for the duration of the server session. However, + * pre-existing property definitions which are not replaced cannot be made + * permanent by a call to XmuLookupStandardColormap(); a request to retain + * resources pertains to newly created resources. + * + * Returns 0 on failure, non-zero on success. A request to create a + * standard colormap upon a visual which cannot support such a map is + * considered a failure. An example of this would be requesting any + * standard colormap property on a monochrome visual, or, requesting an + * RGB_BEST_MAP on a display whose colormap size is 16. + */ + +Status XmuLookupStandardColormap(dpy, screen, visualid, depth, property, + replace, retain) + Display *dpy; /* specifies X server connection */ + int screen; /* specifies screen of display */ + VisualID visualid; /* specifies the visual type */ + unsigned int depth; /* specifies the visual type */ + Atom property; /* a standard colormap property */ + Bool replace; /* specifies whether to replace */ + Bool retain; /* specifies whether to retain */ +{ + Display *odpy; /* original display connection */ + XStandardColormap *colormap; + XVisualInfo vinfo_template, *vinfo; /* visual */ + long vinfo_mask; + unsigned long r_max, g_max, b_max; /* allocation */ + int count; + Colormap cmap; /* colormap ID */ + Status status = 0; + + + /* Match the requested visual */ + + vinfo_template.visualid = visualid; + vinfo_template.screen = screen; + vinfo_template.depth = depth; + vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask; + if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &count)) == + NULL) + return 0; + + /* Monochrome visuals have no standard maps */ + + if (vinfo->colormap_size <= 2) { + XFree((char *) vinfo); + return 0; + } + + /* If the requested property already exists on this screen, and, + * if the replace flag has not been set to true, return success. + * lookup() will remove a pre-existing map if replace is true. + */ + + if (lookup(dpy, screen, visualid, property, (XStandardColormap *) NULL, + replace) && !replace) { + XFree((char *) vinfo); + return 1; + } + + /* Determine the best allocation for this property under the requested + * visualid and depth, and determine whether or not to use the default + * colormap of the screen. + */ + + if (!XmuGetColormapAllocation(vinfo, property, &r_max, &g_max, &b_max)) { + XFree((char *) vinfo); + return 0; + } + + cmap = (property == XA_RGB_DEFAULT_MAP && + visualid == XVisualIDFromVisual(DefaultVisual(dpy, screen))) + ? DefaultColormap(dpy, screen) : None; + + /* If retaining resources, open a new connection to the same server */ + + if (retain) { + odpy = dpy; + if ((dpy = XOpenDisplay(XDisplayString(odpy))) == NULL) { + XFree((char *) vinfo); + return 0; + } + } + + /* Create the standard colormap */ + + colormap = XmuStandardColormap(dpy, screen, visualid, depth, property, + cmap, r_max, g_max, b_max); + + /* Set the standard colormap property */ + + if (colormap) { + XGrabServer(dpy); + + if (lookup(dpy, screen, visualid, property, colormap, replace) && + !replace) { + /* Someone has defined the property since we last looked. + * Since we will not replace it, release our own resources. + * If this is the default map, our allocations will be freed + * when this connection closes. + */ + if (colormap->killid == ReleaseByFreeingColormap) + XFreeColormap(dpy, colormap->colormap); + } + else if (retain) { + XSetCloseDownMode(dpy, RetainPermanent); + } + XUngrabServer(dpy); + XFree((char *) colormap); + status = 1; + } + + if (retain) + XCloseDisplay(dpy); + XFree((char *) vinfo); + return status; +} + +/***************************************************************************/ + +/* Lookup a standard colormap property. If the property is RGB_DEFAULT_MAP, + * the visualid is used to determine whether the indicated standard colormap + * exists. If the map exists and replace is true, delete the resources used + * by the map and remove the property. Return true if the map exists, + * or did exist and was deleted; return false if the map was not found. + * + * Note that this is not the way that a Status return is normally used. + * + * If new is not NULL, new points to an XStandardColormap structure which + * describes a standard colormap of the specified property. It will be made + * a standard colormap of the screen if none already exists, or if replace + * is true. + */ + +static Status lookup(dpy, screen, visualid, property, new, replace) + Display *dpy; /* specifies display connection */ + int screen; /* specifies screen number */ + VisualID visualid; /* specifies visualid for std map */ + Atom property; /* specifies colormap property name */ + XStandardColormap *new; /* specifies a standard colormap */ + Bool replace; /* specifies whether to replace */ +{ + register int i; + int count; + XStandardColormap *stdcmaps, *s; + Window win = RootWindow(dpy, screen); + + /* The property does not already exist */ + + if (! XGetRGBColormaps(dpy, win, &stdcmaps, &count, property)) { + if (new) + XSetRGBColormaps(dpy, win, new, 1, property); + return 0; + } + + /* The property exists and is not describing the RGB_DEFAULT_MAP */ + + if (property != XA_RGB_DEFAULT_MAP) { + if (replace) { + XmuDeleteStandardColormap(dpy, screen, property); + if (new) + XSetRGBColormaps(dpy, win, new, 1, property); + } + XFree((char *)stdcmaps); + return 1; + } + + /* The property exists and is RGB_DEFAULT_MAP */ + + for (i=0, s=stdcmaps; (i < count) && (s->visualid != visualid); i++, s++) + ; + + /* No RGB_DEFAULT_MAP property matches the given visualid */ + + if (i == count) { + if (new) { + XStandardColormap *m, *maps; + + s = (XStandardColormap *) malloc((unsigned) ((count+1) * sizeof + (XStandardColormap))); + + for (i = 0, m = s, maps = stdcmaps; i < count; i++, m++, maps++) { + m->colormap = maps->colormap; + m->red_max = maps->red_max; + m->red_mult = maps->red_mult; + m->green_max = maps->green_max; + m->green_mult = maps->green_mult; + m->blue_max = maps->blue_max; + m->blue_mult = maps->blue_mult; + m->base_pixel = maps->base_pixel; + m->visualid = maps->visualid; + m->killid = maps->killid; + } + m->colormap = new->colormap; + m->red_max = new->red_max; + m->red_mult = new->red_mult; + m->green_max = new->green_max; + m->green_mult = new->green_mult; + m->blue_max = new->blue_max; + m->blue_mult = new->blue_mult; + m->base_pixel = new->base_pixel; + m->visualid = new->visualid; + m->killid = new->killid; + + XSetRGBColormaps(dpy, win, s, ++count, property); + free((char *) s); + } + XFree((char *) stdcmaps); + return 0; + } + + /* Found an RGB_DEFAULT_MAP property with a matching visualid */ + + if (replace) { + /* Free old resources first - we may need them, particularly in + * the default colormap of the screen. However, because of this, + * it is possible that we will destroy the old resource and fail + * to create a new one if XmuStandardColormap() fails. + */ + + if (count == 1) { + XmuDeleteStandardColormap(dpy, screen, property); + if (new) + XSetRGBColormaps(dpy, win, new, 1, property); + } + else { + XStandardColormap *map; + + /* s still points to the matching standard colormap */ + + if (s->killid == ReleaseByFreeingColormap) { + if ((s->colormap != None) && + (s->colormap != DefaultColormap(dpy, screen))) + XFreeColormap(dpy, s->colormap); + } + else if (s->killid != None) + XKillClient(dpy, s->killid); + + map = (new) ? new : stdcmaps + --count; + + s->colormap = map->colormap; + s->red_max = map->red_max; + s->red_mult = map->red_mult; + s->green_max = map->green_max; + s->green_mult = map->green_mult; + s->blue_max = map->blue_max; + s->blue_mult = map->blue_mult; + s->visualid = map->visualid; + s->killid = map->killid; + + XSetRGBColormaps(dpy, win, stdcmaps, count, property); + } + } + XFree((char *) stdcmaps); + return 1; +} diff --git a/wrlib/Makefile.am b/wrlib/Makefile.am index 5efb158a..fcf3f194 100644 --- a/wrlib/Makefile.am +++ b/wrlib/Makefile.am @@ -4,7 +4,7 @@ AUTOMAKE_OPTIONS = no-dependencies lib_LTLIBRARIES = libwraster.la -libwraster_la_LDFLAGS = -version-info 3:1:2 +libwraster_la_LDFLAGS = -version-info 4:0:3 bin_SCRIPTS = get-wraster-flags @@ -14,6 +14,12 @@ EXTRA_DIST = test.png tile.xpm ballot_box.xpm include_HEADERS = wraster.h libwraster_la_SOURCES = \ + LookupCmap.c \ + StdCmap.c \ + StdCmap.h \ + CrCmap.c \ + DelCmap.c \ + CmapAlloc.c \ raster.c \ draw.c \ color.c \ diff --git a/wrlib/Makefile.in b/wrlib/Makefile.in index 69d62e24..630d8282 100644 --- a/wrlib/Makefile.in +++ b/wrlib/Makefile.in @@ -96,7 +96,7 @@ AUTOMAKE_OPTIONS = no-dependencies lib_LTLIBRARIES = libwraster.la -libwraster_la_LDFLAGS = -version-info 3:1:2 +libwraster_la_LDFLAGS = -version-info 4:0:3 bin_SCRIPTS = get-wraster-flags @@ -105,7 +105,7 @@ noinst_PROGRAMS = testgrad testdraw view EXTRA_DIST = test.png tile.xpm ballot_box.xpm include_HEADERS = wraster.h -libwraster_la_SOURCES = raster.c draw.c color.c load.c save.c gradient.c xpixmap.c convert.c context.c misc.c scale.c convolve.c nxpm.c xpm.c xutil.c ppm.c png.c jpeg.c tiff.c gif.c +libwraster_la_SOURCES = LookupCmap.c StdCmap.c StdCmap.h CrCmap.c DelCmap.c CmapAlloc.c raster.c draw.c color.c load.c save.c gradient.c xpixmap.c convert.c context.c misc.c scale.c convolve.c nxpm.c xpm.c xutil.c ppm.c png.c jpeg.c tiff.c gif.c INCLUDES = @DFLAGS@ @HEADER_SEARCH_PATH@ @@ -139,10 +139,10 @@ X_CFLAGS = @X_CFLAGS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ libwraster_la_DEPENDENCIES = @ALLOCA@ -libwraster_la_OBJECTS = raster.lo draw.lo color.lo load.lo save.lo \ -gradient.lo xpixmap.lo convert.lo context.lo misc.lo scale.lo \ -convolve.lo nxpm.lo xpm.lo xutil.lo ppm.lo png.lo jpeg.lo tiff.lo \ -gif.lo +libwraster_la_OBJECTS = LookupCmap.lo StdCmap.lo CrCmap.lo DelCmap.lo \ +CmapAlloc.lo raster.lo draw.lo color.lo load.lo save.lo gradient.lo \ +xpixmap.lo convert.lo context.lo misc.lo scale.lo convolve.lo nxpm.lo \ +xpm.lo xutil.lo ppm.lo png.lo jpeg.lo tiff.lo gif.lo PROGRAMS = $(noinst_PROGRAMS) testgrad_OBJECTS = testgrad.o @@ -169,7 +169,7 @@ Makefile.in NEWS TODO alloca.c configure.in DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) -TAR = tar +TAR = gtar GZIP_ENV = --best SOURCES = $(libwraster_la_SOURCES) $(testgrad_SOURCES) $(testdraw_SOURCES) $(view_SOURCES) OBJECTS = $(libwraster_la_OBJECTS) $(testgrad_OBJECTS) $(testdraw_OBJECTS) $(view_OBJECTS) @@ -178,7 +178,7 @@ all: all-redirect .SUFFIXES: .SUFFIXES: .S .c .lo .o .s $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) - cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps wrlib/Makefile + cd $(top_srcdir) && $(AUTOMAKE) --gnu wrlib/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) \ @@ -343,7 +343,7 @@ distdir: $(DISTFILES) @for file in $(DISTFILES); do \ d=$(srcdir); \ if test -d $$d/$$file; then \ - cp -pr $$d/$$file $(distdir)/$$file; \ + cp -pr $$/$$file $(distdir)/$$file; \ else \ test -f $(distdir)/$$file \ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ diff --git a/wrlib/StdCmap.c b/wrlib/StdCmap.c new file mode 100644 index 00000000..62c0a942 --- /dev/null +++ b/wrlib/StdCmap.c @@ -0,0 +1,219 @@ +/* $XConsortium: StdCmap.c,v 1.14 94/04/17 20:16:14 rws Exp $ */ + +/* + +Copyright (c) 1989 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + +*/ + +/* + * Author: Donna Converse, MIT X Consortium + */ + +#include +#include +#include +#include +#include + +#define lowbit(x) ((x) & (~(x) + 1)) + +static Status valid_args(); /* argument restrictions */ + +/* + * To create any one standard colormap, use XmuStandardColormap(). + * + * Create a standard colormap for the given screen, visualid, and visual + * depth, with the given red, green, and blue maximum values, with the + * given standard property name. Return a pointer to an XStandardColormap + * structure which describes the newly created colormap, upon success. + * Upon failure, return NULL. + * + * XmuStandardColormap() calls XmuCreateColormap() to create the map. + * + * Resources created by this function are not made permanent; that is the + * caller's responsibility. + */ + +XStandardColormap *XmuStandardColormap(dpy, screen, visualid, depth, property, + cmap, red_max, green_max, blue_max) + Display *dpy; /* specifies X server connection */ + int screen; /* specifies display screen */ + VisualID visualid; /* identifies the visual type */ + unsigned int depth; /* identifies the visual type */ + Atom property; /* a standard colormap property */ + Colormap cmap; /* specifies colormap ID or None */ + unsigned long red_max, green_max, blue_max; /* allocations */ +{ + XStandardColormap *stdcmap; + Status status; + XVisualInfo vinfo_template, *vinfo; + long vinfo_mask; + int n; + + /* Match the required visual information to an actual visual */ + vinfo_template.visualid = visualid; + vinfo_template.screen = screen; + vinfo_template.depth = depth; + vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask; + if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL) + return 0; + + /* Check the validity of the combination of visual characteristics, + * allocation, and colormap property. Create an XStandardColormap + * structure. + */ + + if (! valid_args(vinfo, red_max, green_max, blue_max, property) + || ((stdcmap = XAllocStandardColormap()) == NULL)) { + XFree((char *) vinfo); + return 0; + } + + /* Fill in the XStandardColormap structure */ + + if (cmap == DefaultColormap(dpy, screen)) { + /* Allocating out of the default map, cannot use XFreeColormap() */ + Window win = XCreateWindow(dpy, RootWindow(dpy, screen), 1, 1, 1, 1, + 0, 0, InputOnly, vinfo->visual, + (unsigned long) 0, + (XSetWindowAttributes *)NULL); + stdcmap->killid = (XID) XCreatePixmap(dpy, win, 1, 1, depth); + XDestroyWindow(dpy, win); + stdcmap->colormap = cmap; + } else { + stdcmap->killid = ReleaseByFreeingColormap; + stdcmap->colormap = XCreateColormap(dpy, RootWindow(dpy, screen), + vinfo->visual, AllocNone); + } + stdcmap->red_max = red_max; + stdcmap->green_max = green_max; + stdcmap->blue_max = blue_max; + if (property == XA_RGB_GRAY_MAP) + stdcmap->red_mult = stdcmap->green_mult = stdcmap->blue_mult = 1; + else if (vinfo->class == TrueColor || vinfo->class == DirectColor) { + stdcmap->red_mult = lowbit(vinfo->red_mask); + stdcmap->green_mult = lowbit(vinfo->green_mask); + stdcmap->blue_mult = lowbit(vinfo->blue_mask); + } else { + stdcmap->red_mult = (red_max > 0) + ? (green_max + 1) * (blue_max + 1) : 0; + stdcmap->green_mult = (green_max > 0) ? blue_max + 1 : 0; + stdcmap->blue_mult = (blue_max > 0) ? 1 : 0; + } + stdcmap->base_pixel = 0; /* base pixel may change */ + stdcmap->visualid = vinfo->visualid; + + /* Make the colormap */ + + status = XmuCreateColormap(dpy, stdcmap); + + /* Clean up */ + + XFree((char *) vinfo); + if (!status) { + + /* Free the colormap or the pixmap, if we created one */ + if (stdcmap->killid == ReleaseByFreeingColormap) + XFreeColormap(dpy, stdcmap->colormap); + else if (stdcmap->killid != None) + XFreePixmap(dpy, stdcmap->killid); + + XFree((char *) stdcmap); + return (XStandardColormap *) NULL; + } + return stdcmap; +} + +/****************************************************************************/ +static Status valid_args(vinfo, red_max, green_max, blue_max, property) + XVisualInfo *vinfo; /* specifies visual */ + unsigned long red_max, green_max, blue_max; /* specifies alloc */ + Atom property; /* specifies property name */ +{ + unsigned long ncolors; /* number of colors requested */ + + /* Determine that the number of colors requested is <= map size */ + + if ((vinfo->class == DirectColor) || (vinfo->class == TrueColor)) { + unsigned long mask; + + mask = vinfo->red_mask; + while (!(mask & 1)) + mask >>= 1; + if (red_max > mask) + return 0; + mask = vinfo->green_mask; + while (!(mask & 1)) + mask >>= 1; + if (green_max > mask) + return 0; + mask = vinfo->blue_mask; + while (!(mask & 1)) + mask >>= 1; + if (blue_max > mask) + return 0; + } else if (property == XA_RGB_GRAY_MAP) { + ncolors = red_max + green_max + blue_max + 1; + if (ncolors > vinfo->colormap_size) + return 0; + } else { + ncolors = (red_max + 1) * (green_max + 1) * (blue_max + 1); + if (ncolors > vinfo->colormap_size) + return 0; + } + + /* Determine that the allocation and visual make sense for the property */ + + switch (property) + { + case XA_RGB_DEFAULT_MAP: + if (red_max == 0 || green_max == 0 || blue_max == 0) + return 0; + break; + case XA_RGB_RED_MAP: + if (red_max == 0) + return 0; + break; + case XA_RGB_GREEN_MAP: + if (green_max == 0) + return 0; + break; + case XA_RGB_BLUE_MAP: + if (blue_max == 0) + return 0; + break; + case XA_RGB_BEST_MAP: + if (red_max == 0 || green_max == 0 || blue_max == 0) + return 0; + break; + case XA_RGB_GRAY_MAP: + if (red_max == 0 || blue_max == 0 || green_max == 0) + return 0; + break; + default: + return 0; + } + return 1; +} diff --git a/wrlib/StdCmap.h b/wrlib/StdCmap.h new file mode 100644 index 00000000..a1cdd2e7 --- /dev/null +++ b/wrlib/StdCmap.h @@ -0,0 +1,112 @@ +/* $XConsortium: StdCmap.h,v 1.4 94/04/17 20:16:15 converse Exp $ */ + +/* + +Copyright (c) 1988 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + +*/ + +/* + * The interfaces described by this header file are for miscellaneous utilities + * and are not part of the Xlib standard. + */ + +#ifndef _XMU_STDCMAP_H_ +#define _XMU_STDCMAP_H_ + +#include + +_XFUNCPROTOBEGIN + +Status XmuAllStandardColormaps( +#if NeedFunctionPrototypes + Display* /* dpy */ +#endif +); + +Status XmuCreateColormap( +#if NeedFunctionPrototypes + Display* /* dpy */, + XStandardColormap* /* colormap */ +#endif +); + +void XmuDeleteStandardColormap( +#if NeedFunctionPrototypes + Display* /* dpy */, + int /* screen */, + Atom /* property */ +#endif +); + +Status XmuGetColormapAllocation( +#if NeedFunctionPrototypes + XVisualInfo* /* vinfo */, + Atom /* property */, + unsigned long* /* red_max_return */, + unsigned long* /* green_max_return */, + unsigned long* /* blue_max_return */ +#endif +); + +Status XmuLookupStandardColormap( +#if NeedFunctionPrototypes + Display* /* dpy */, + int /* screen */, + VisualID /* visualid */, + unsigned int /* depth */, + Atom /* property */, + Bool /* replace */, + Bool /* retain */ +#endif +); + +XStandardColormap *XmuStandardColormap( +#if NeedFunctionPrototypes + Display* /* dpy */, + int /* screen */, + VisualID /* visualid */, + unsigned int /* depth */, + Atom /* property */, + Colormap /* cmap */, + unsigned long /* red_max */, + unsigned long /* green_max */, + unsigned long /* blue_max */ +#endif +); + +Status XmuVisualStandardColormaps( +#if NeedFunctionPrototypes + Display* /* dpy */, + int /* screen */, + VisualID /* visualid */, + unsigned int /* depth */, + Bool /* replace */, + Bool /* retain */ +#endif +); + +_XFUNCPROTOEND + +#endif /* _XMU_STDCMAP_H_ */ diff --git a/wrlib/context.c b/wrlib/context.c index aded9003..2772176e 100644 --- a/wrlib/context.c +++ b/wrlib/context.c @@ -32,6 +32,8 @@ #include +#include "StdCmap.h" + #include "wraster.h" @@ -49,11 +51,108 @@ static RContextAttributes DEFAULT_CONTEXT_ATTRIBS = { 0, 0, True, /* use_shared_memory */ - RMitchellFilter + RMitchellFilter, + RUseStdColormap }; -static XColor* + +/* + * + * Colormap allocation for PseudoColor visuals: + * + * + * switch standardColormap: + * none: + * allocate colors according to colors_per_channel + * + * best/default: + * if there's a std colormap defined + then use it + * + * else + * create a std colormap and set it + */ + + + + +/* + *---------------------------------------------------------------------- + * allocateStandardPseudoColor + * Creates the internal colormap for PseudoColor, setting the + * color values according to the supplied standard colormap. + * + * Returns: - + * + * Side effects: - + * + * Notes: - + *---------------------------------------------------------------------- + */ +static Bool +allocateStandardPseudoColor(RContext *ctx, XStandardColormap *stdcmap) +{ + int i; + + ctx->ncolors = stdcmap->red_max * stdcmap->red_mult + + stdcmap->green_max * stdcmap->green_mult + + stdcmap->blue_max * stdcmap->blue_mult + 1; + + if (ctx->ncolors <= 1) { + RErrorCode = RERR_INTERNAL; + puts("wraster: bad standard colormap"); + + return False; + } + + ctx->colors = malloc(sizeof(XColor)*ctx->ncolors); + if (!ctx->colors) { + RErrorCode = RERR_NOMEMORY; + + return False; + } + + +#define calc(max,mult) (((i / stdcmap->mult) % \ + (stdcmap->max + 1)) * 65535) / stdcmap->max + + for (i = 0; i < ctx->ncolors; i++) { + ctx->colors[i].pixel = i + stdcmap->base_pixel; + ctx->colors[i].red = calc(red_max, red_mult); + ctx->colors[i].green = calc(green_max, green_mult); + ctx->colors[i].blue = calc(blue_max, blue_mult); + } + +#undef calc + + return True; +} + + +static Bool +setupStandardColormap(RContext *ctx, Atom property) +{ + if (!XmuLookupStandardColormap(ctx->dpy, ctx->screen_number, + ctx->visual->visualid, + ctx->depth, property, + True, True)) { + RErrorCode = RERR_STDCMAPFAIL; + + return False; + } + return True; +} + + + + + + + + + +static Bool allocatePseudoColor(RContext *ctx) { XColor *colors; @@ -65,10 +164,10 @@ allocatePseudoColor(RContext *ctx) ncolors = cpc * cpc * cpc; - if ( ncolors > (1<depth) ) { - /* reduce colormap size */ - cpc = ctx->attribs->colors_per_channel = 1<<((int)ctx->depth/3); - ncolors = cpc * cpc * cpc; + if (ncolors > (1<depth)) { + /* reduce colormap size */ + cpc = ctx->attribs->colors_per_channel = 1<<((int)ctx->depth/3); + ncolors = cpc * cpc * cpc; } assert(cpc >= 2 && ncolors <= (1<depth)); @@ -76,7 +175,7 @@ allocatePseudoColor(RContext *ctx) colors = malloc(sizeof(XColor)*ncolors); if (!colors) { RErrorCode = RERR_NOMEMORY; - return NULL; + return False; } i=0; @@ -173,7 +272,11 @@ allocatePseudoColor(RContext *ctx) } } } - return colors; + + ctx->colors = colors; + ctx->ncolors = ncolors; + + return True; } @@ -283,6 +386,86 @@ allocateGrayScale(RContext *ctx) } +static Bool +setupPseudoColorColormap(RContext *context) +{ + Atom property = 0; + + if (context->attribs->standard_colormap_mode == RCreateStdColormap) { + property = XInternAtom(context->dpy, "RGB_DEFAULT_MAP", False); + + if (!setupStandardColormap(context, property)) { + return False; + } + } + + if (context->attribs->standard_colormap_mode != RIgnoreStdColormap) { + XStandardColormap *maps; + int count, i; + + if (!property) { + property = XInternAtom(context->dpy, "RGB_BEST_MAP", False); + if (!XGetRGBColormaps(context->dpy, + DefaultRootWindow(context->dpy), + &maps, &count, property)) { + maps = NULL; + } + + if (!maps) { + property = XInternAtom(context->dpy, "RGB_DEFAULT_MAP", False); + if (!XGetRGBColormaps(context->dpy, + DefaultRootWindow(context->dpy), + &maps, &count, property)) { + maps = NULL; + } + } + } else { + if (!XGetRGBColormaps(context->dpy, + DefaultRootWindow(context->dpy), + &maps, &count, property)) { + maps = NULL; + } + } + + if (maps) { + int theMap = -1; + + for (i = 0; i < count; i++) { + if (maps[i].visualid == context->visual->visualid) { + theMap = i; + break; + } + } + + if (theMap < 0) { + puts("wrlib: no std cmap found"); + } + + if (theMap >= 0 + && allocateStandardPseudoColor(context, &maps[theMap])) { + + context->std_rgb_map = XAllocStandardColormap(); + + *context->std_rgb_map = maps[theMap]; + + XFree(maps); + + return True; + } + + XFree(maps); + } + } + + context->attribs->standard_colormap_mode = RIgnoreStdColormap; + + /* RIgnoreStdColormap and fallback */ + return allocatePseudoColor(context); +} + + + + static char* mygetenv(char *var, int scr) { @@ -412,6 +595,10 @@ RCreateContext(Display *dpy, int screen_number, RContextAttributes *attribs) else *context->attribs = *attribs; + if (!(context->attribs->flags & RC_StandardColormap)) { + context->attribs->standard_colormap_mode = RUseStdColormap; + } + /* get configuration from environment variables */ gatherconfig(context, screen_number); @@ -475,10 +662,11 @@ RCreateContext(Display *dpy, int screen_number, RContextAttributes *attribs) |GCGraphicsExposures, &gcv); if (context->vclass == PseudoColor || context->vclass == StaticColor) { - context->colors = allocatePseudoColor(context); - if (!context->colors) { + + if (!setupPseudoColorColormap(context)) { return NULL; } + } else if (context->vclass == GrayScale || context->vclass == StaticGray) { context->colors = allocateGrayScale(context); if (!context->colors) { diff --git a/wrlib/convert.c b/wrlib/convert.c index bab3cbb2..54ed6385 100644 --- a/wrlib/convert.c +++ b/wrlib/convert.c @@ -57,11 +57,24 @@ Pixmap R_CreateXImageMappedPixmap(RContext *context, RXImage *ximage); typedef struct RConversionTable { unsigned short table[256]; unsigned short index; + struct RConversionTable *next; } RConversionTable; +typedef struct RStdConversionTable { + unsigned int table[256]; + + unsigned short mult; + unsigned short max; + + struct RStdConversionTable *next; +} RStdConversionTable; + + + static RConversionTable *conversionTable = NULL; +static RStdConversionTable *stdConversionTable = NULL; static unsigned short* @@ -93,6 +106,38 @@ computeTable(unsigned short mask) } +static unsigned int* +computeStdTable(unsigned int mult, unsigned int max) +{ + RStdConversionTable *tmp = stdConversionTable; + unsigned int i; + + while (tmp) { + if (tmp->mult == mult && tmp->max == max) + break; + tmp = tmp->next; + } + + if (tmp) + return tmp->table; + + tmp = (RStdConversionTable *)malloc(sizeof(RStdConversionTable)); + if (tmp == NULL) + return NULL; + + for (i=0; i<256; i++) { + tmp->table[i] = (i*max)/0xff * mult; + } + tmp->mult = mult; + tmp->max = max; + + tmp->next = stdConversionTable; + stdConversionTable = tmp; + + return tmp->table; +} + + static RXImage* image2TrueColorD16(RContext *ctx, RImage *image) @@ -585,6 +630,162 @@ image2PseudoColor(RContext *ctx, RImage *image) } +/* + * For standard colormap + */ +static RXImage* +image2StandardPseudoColor(RContext *ctx, RImage *image) +{ + RXImage *ximg; + register int x, y, r, g, b; + unsigned char *red, *grn, *blu; + unsigned long pixel; + unsigned char *data; + unsigned int *rtable, *gtable, *btable; + unsigned int base_pixel = ctx->std_rgb_map->base_pixel; + int ofs; + /*register unsigned char maxrgb = 0xff;*/ + + ximg = RCreateXImage(ctx, ctx->depth, image->width, image->height); + if (!ximg) { + return NULL; + } + + red = image->data[0]; + grn = image->data[1]; + blu = image->data[2]; + + data = (unsigned char *)ximg->image->data; + + + rtable = computeStdTable(ctx->std_rgb_map->red_mult, + ctx->std_rgb_map->red_max); + + gtable = computeStdTable(ctx->std_rgb_map->green_mult, + ctx->std_rgb_map->green_max); + + btable = computeStdTable(ctx->std_rgb_map->blue_mult, + ctx->std_rgb_map->blue_max); + + if (rtable==NULL || gtable==NULL || btable==NULL) { + RErrorCode = RERR_NOMEMORY; + RDestroyXImage(ctx, ximg); + return NULL; + } + + + if (ctx->attribs->render_mode == RBestMatchRendering) { + for (y=0, ofs = 0; yheight; y++) { + for (x=0; xwidth; x++, ofs++) { + /* reduce pixel */ + + pixel = (rtable[red[ofs]] + gtable[grn[ofs]] + + btable[blu[ofs]] + base_pixel) & 0xffffffff; + + XPutPixel(ximg->image, x, y, pixel); + } + } + } else { + /* dither */ + short *rerr, *gerr, *berr; + short *nrerr, *ngerr, *nberr; + short *terr; + int rer, ger, ber; + +#ifdef DEBUG + printf("pseudo color dithering with %d colors per channel\n", cpc); +#endif + rerr = (short*)alloca((image->width+2)*sizeof(short)); + gerr = (short*)alloca((image->width+2)*sizeof(short)); + berr = (short*)alloca((image->width+2)*sizeof(short)); + nrerr = (short*)alloca((image->width+2)*sizeof(short)); + ngerr = (short*)alloca((image->width+2)*sizeof(short)); + nberr = (short*)alloca((image->width+2)*sizeof(short)); + if (!rerr || !gerr || !berr || !nrerr || !ngerr || !nberr) { + RErrorCode = RERR_NOMEMORY; + RDestroyXImage(ctx, ximg); + return NULL; + } + for (x=0; xwidth; x++) { + rerr[x] = red[x]; + gerr[x] = grn[x]; + berr[x] = blu[x]; + } + rerr[x] = gerr[x] = berr[x] = 0; + /* convert and dither the image to XImage */ + for (y=0, ofs=0; yheight; y++) { + if (yheight-1) { + int x1; + for (x=0, x1=ofs+image->width; xwidth; x++, x1++) { + nrerr[x] = red[x1]; + ngerr[x] = grn[x1]; + nberr[x] = blu[x1]; + } + /* last column */ + x1--; + nrerr[x] = red[x1]; + ngerr[x] = grn[x1]; + nberr[x] = blu[x1]; + } + for (x=0; xwidth; x++, ofs++) { + /* reduce pixel */ + if (rerr[x]>0xff) rerr[x]=0xff; else if (rerr[x]<0) rerr[x]=0; + if (gerr[x]>0xff) gerr[x]=0xff; else if (gerr[x]<0) gerr[x]=0; + if (berr[x]>0xff) berr[x]=0xff; else if (berr[x]<0) berr[x]=0; + + r = rtable[rerr[x]]; + g = gtable[gerr[x]]; + b = btable[berr[x]]; + + pixel = r + g + b; + + XPutPixel(ximg->image, x, y, pixel+base_pixel); + + /* calc error */ + rer = rerr[x] - (ctx->colors[pixel].red>>8); + ger = gerr[x] - (ctx->colors[pixel].green>>8); + ber = berr[x] - (ctx->colors[pixel].blue>>8); + + /* distribute error */ + rerr[x+1]+=(rer*7)/16; + gerr[x+1]+=(ger*7)/16; + berr[x+1]+=(ber*7)/16; + + nrerr[x]+=(rer*5)/16; + ngerr[x]+=(ger*5)/16; + nberr[x]+=(ber*5)/16; + + if (x>0) { + nrerr[x-1]+=(rer*3)/16; + ngerr[x-1]+=(ger*3)/16; + nberr[x-1]+=(ber*3)/16; + } + + nrerr[x+1]+=rer/16; + ngerr[x+1]+=ger/16; + nberr[x+1]+=ber/16; + } + /* skip to next line */ + terr = rerr; + rerr = nrerr; + nrerr = terr; + + terr = gerr; + gerr = ngerr; + ngerr = terr; + + terr = berr; + berr = nberr; + nberr = terr; + } + } + ximg->image->data = (char*)data; + + return ximg; +} + + + static RXImage* image2GrayScale(RContext *ctx, RImage *image) { @@ -747,11 +948,19 @@ RConvertImage(RContext *context, RImage *image, Pixmap *pixmap) else ximg = image2TrueColor(context, image); - } else if (context->vclass == PseudoColor || context->vclass == StaticColor) + } else if (context->vclass == PseudoColor + || context->vclass == StaticColor) { + + if (context->attribs->standard_colormap_mode != RIgnoreStdColormap) + ximg = image2StandardPseudoColor(context, image); + else ximg = image2PseudoColor(context, image); - else if (context->vclass == GrayScale || context->vclass == StaticGray) + + } else if (context->vclass == GrayScale || context->vclass == StaticGray) { + ximg = image2GrayScale(context, image); - + } + if (!ximg) { #ifdef C_ALLOCA alloca(0); @@ -874,27 +1083,58 @@ RGetClosestXColor(RContext *context, RColor *color, XColor *retColor) retColor->green = color->green << 8; retColor->blue = color->blue << 8; retColor->flags = DoRed|DoGreen|DoBlue; - - } else if (context->vclass == PseudoColor || context->vclass == StaticColor) { - const int cpc=context->attribs->colors_per_channel; - const unsigned short rmask = cpc-1; /* different sizes could be used */ - const unsigned short gmask = rmask; /* for r,g,b */ - const unsigned short bmask = rmask; - unsigned short *rtable, *gtable, *btable; - const int cpccpc = cpc*cpc; - int index; - rtable = computeTable(rmask); - gtable = computeTable(gmask); - btable = computeTable(bmask); + } else if (context->vclass == PseudoColor + || context->vclass == StaticColor) { - if (rtable==NULL || gtable==NULL || btable==NULL) { - RErrorCode = RERR_NOMEMORY; - return False; + if (context->attribs->standard_colormap_mode != RIgnoreStdColormap) { + unsigned int *rtable, *gtable, *btable; + + rtable = computeStdTable(context->std_rgb_map->red_mult, + context->std_rgb_map->red_max); + + gtable = computeStdTable(context->std_rgb_map->green_mult, + context->std_rgb_map->green_max); + + btable = computeStdTable(context->std_rgb_map->blue_mult, + context->std_rgb_map->blue_max); + + if (rtable==NULL || gtable==NULL || btable==NULL) { + RErrorCode = RERR_NOMEMORY; + return False; + } + + retColor->pixel = (rtable[color->red] + + gtable[color->green] + + btable[color->blue] + + context->std_rgb_map->base_pixel) & 0xffffffff; + retColor->red = color->red<<8; + retColor->green = color->green<<8; + retColor->blue = color->blue<<8; + retColor->flags = DoRed|DoGreen|DoBlue; + + } else { + const int cpc=context->attribs->colors_per_channel; + const unsigned short rmask = cpc-1; /* different sizes could be used */ + const unsigned short gmask = rmask; /* for r,g,b */ + const unsigned short bmask = rmask; + unsigned short *rtable, *gtable, *btable; + const int cpccpc = cpc*cpc; + int index; + + rtable = computeTable(rmask); + gtable = computeTable(gmask); + btable = computeTable(bmask); + + if (rtable==NULL || gtable==NULL || btable==NULL) { + RErrorCode = RERR_NOMEMORY; + return False; + } + index = rtable[color->red]*cpccpc + gtable[color->green]*cpc + + btable[color->blue]; + *retColor = context->colors[index]; } - index = rtable[color->red]*cpccpc + gtable[color->green]*cpc - + btable[color->blue]; - *retColor = context->colors[index]; + } else if (context->vclass == GrayScale || context->vclass == StaticGray) { const int cpc = context->attribs->colors_per_channel; diff --git a/wrlib/misc.c b/wrlib/misc.c index 70f3b844..6453ba37 100644 --- a/wrlib/misc.c +++ b/wrlib/misc.c @@ -133,41 +133,43 @@ RMessageForError(int errorCode) switch (errorCode) { case RERR_NONE: return "no error"; - break; + case RERR_OPEN: return "could not open file"; - break; + case RERR_READ: return "error reading from file"; - break; + case RERR_WRITE: return "error writing to file"; - break; + case RERR_NOMEMORY: return "out of memory"; - break; + case RERR_NOCOLOR: return "out of color cells"; - break; + case RERR_BADIMAGEFILE: return "invalid or corrupted image file"; - break; + case RERR_BADFORMAT: return "the image format in the file is not supported and can't be loaded"; - break; + case RERR_BADINDEX: return "image file does not contain requested image index"; - break; + case RERR_BADVISUALID: return "request for an invalid visual ID"; - break; + + case RERR_STDCMAPFAIL: + return "failed to create standard colormap"; + case RERR_XERROR: return "internal X error"; - break; + default: case RERR_INTERNAL: return "internal error"; - break; } } diff --git a/wrlib/view.c b/wrlib/view.c index d683c1e1..8dcb14ab 100644 --- a/wrlib/view.c +++ b/wrlib/view.c @@ -24,6 +24,8 @@ int main(int argc, char **argv) attr.render_mode = RDitheredRendering; attr.colors_per_channel = 4; ctx = RCreateContext(dpy, DefaultScreen(dpy), &attr); + + if (argc<2) img = RGetImageFromXPMData(ctx, image_name); else diff --git a/wrlib/wraster.h b/wrlib/wraster.h index a3702832..e3634c60 100644 --- a/wrlib/wraster.h +++ b/wrlib/wraster.h @@ -39,8 +39,8 @@ #define RLRASTER_H_ -/* version of the header for the library: 0.15 */ -#define WRASTER_HEADER_VERSION 15 +/* version of the header for the library: 0.16 */ +#define WRASTER_HEADER_VERSION 16 #include @@ -50,6 +50,11 @@ #include #endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + /* RBestMatchRendering or RDitheredRendering */ #define RC_RenderMode (1<<0) @@ -71,10 +76,24 @@ /* filter type for smoothed scaling */ #define RC_ScalingFilter (1<<6) -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ +/* standard colormap usage */ +#define RC_StandardColormap (1<<7) + + + + + +/* std colormap usage/creation modes */ +enum { + RUseStdColormap, /* default. fallbacks to RIgnore.. if + there is none defined */ + RCreateStdColormap, + RIgnoreStdColormap +}; + + + typedef struct RContextAttributes { int flags; int render_mode; @@ -85,6 +104,7 @@ typedef struct RContextAttributes { VisualID visualid; /* visual ID to use */ int use_shared_memory; /* True of False */ int scaling_filter; + int standard_colormap_mode; /* what to do with std cma */ } RContextAttributes; @@ -110,7 +130,7 @@ typedef struct RContext { unsigned long black; unsigned long white; - + int red_offset; /* only used in 24bpp */ int green_offset; int blue_offset; @@ -252,7 +272,8 @@ enum { #define RERR_BADINDEX 8 /* no such image index in file */ #define RERR_BADVISUALID 16 /* invalid visual ID requested for context */ - +#define RERR_STDCMAPFAIL 17 /* failed to created std colormap */ + #define RERR_XERROR 127 /* internal X error */ #define RERR_INTERNAL 128 /* should not happen */ -- 2.11.4.GIT