3 Copyright 1989, 1998 The Open Group
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
28 * Author: Donna Converse, MIT X Consortium
32 * CreateCmap.c - given a standard colormap description, make the map.
41 #include <X11/Xutil.h>
42 #include <X11/Xmu/StdCmap.h>
47 /* allocate entire map Read Only */
48 static int ROmap(Display*, Colormap, unsigned long[], int, int);
50 /* allocate a cell, prefer Read Only */
51 static Status ROorRWcell(Display*, Colormap, unsigned long[], int,
52 XColor*, unsigned long);
54 /* allocate a cell Read Write */
55 static Status RWcell(Display*, Colormap, XColor*, XColor*, unsigned long*);
58 static int compare(_Xconst void*, _Xconst void*);
60 /* find contiguous sequence of cells */
61 static Status contiguous(unsigned long[], int, int, unsigned long, int*, int*);
63 /* frees resources before quitting */
64 static void free_cells(Display*, Colormap, unsigned long[], int, int);
66 /* create a map in a RO visual type */
67 static Status readonly_map(Display*, XVisualInfo*, XStandardColormap*);
69 /* create a map in a RW visual type */
70 static Status readwrite_map(Display*, XVisualInfo*, XStandardColormap*);
72 #define lowbit(x) ((x) & (~(x) + 1))
73 #define TRUEMATCH(mult,max,mask) \
74 (colormap->max * colormap->mult <= vinfo->mask && \
75 lowbit(vinfo->mask) == colormap->mult)
78 * To create any one colormap which is described by an XStandardColormap
79 * structure, use XmuCreateColormap().
81 * Return 0 on failure, non-zero on success.
82 * Resources created by this function are not made permanent.
83 * No argument error checking is provided. Use at your own risk.
85 * All colormaps are created with read only allocations, with the exception
86 * of read only allocations of colors in the default map or otherwise
87 * which fail to return the expected pixel value, and these are individually
88 * defined as read/write allocations. This is done so that all the cells
89 * defined in the default map are contiguous, for use in image processing.
90 * This typically happens with White and Black in the default map.
92 * Colormaps of static visuals are considered to be successfully created if
93 * the map of the static visual matches the definition given in the
94 * standard colormap structure.
98 XmuCreateColormap(Display *dpy, XStandardColormap *colormap)
99 /* dpy - specifies the connection under which the map is created
100 * colormap - specifies the map to be created, and returns, particularly
101 * if the map is created as a subset of the default colormap
102 * of the screen, the base_pixel of the map.
105 XVisualInfo vinfo_template; /* template visual information */
106 XVisualInfo *vinfo; /* matching visual information */
107 XVisualInfo *vpointer; /* for freeing the entire list */
108 long vinfo_mask; /* specifies the visual mask value */
109 int n; /* number of matching visuals */
112 vinfo_template.visualid = colormap->visualid;
113 vinfo_mask = VisualIDMask;
114 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
117 /* A visual id may be valid on multiple screens. Also, there may
118 * be multiple visuals with identical visual ids at different depths.
119 * If the colormap is the Default Colormap, use the Default Visual.
120 * Otherwise, arbitrarily, use the deepest visual.
126 register int screen_number;
130 for (screen_number = ScreenCount(dpy); --screen_number >= 0; )
131 if (colormap->colormap == DefaultColormap(dpy, screen_number)) {
137 for (i=0; i < n; i++, vinfo++) {
138 if (vinfo->visual == DefaultVisual(dpy, screen_number))
143 XVisualInfo *v = NULL;
145 for (i=0; i < n; i++, vinfo++)
146 if (vinfo->depth > maxdepth) {
147 maxdepth = vinfo->depth;
154 if (vinfo->class == PseudoColor || vinfo->class == DirectColor ||
155 vinfo->class == GrayScale)
156 status = readwrite_map(dpy, vinfo, colormap);
157 else if (vinfo->class == TrueColor)
158 status = TRUEMATCH(red_mult, red_max, red_mask) &&
159 TRUEMATCH(green_mult, green_max, green_mask) &&
160 TRUEMATCH(blue_mult, blue_max, blue_mask);
162 status = readonly_map(dpy, vinfo, colormap);
164 XFree((char *) vpointer);
168 /****************************************************************************/
170 readwrite_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
172 register unsigned long i, n; /* index counters */
173 unsigned long ncolors; /* number of colors to be defined */
174 int npixels; /* number of pixels allocated R/W */
175 int first_index; /* first index of pixels to use */
176 int remainder; /* first index of remainder */
177 XColor color; /* the definition of a color */
178 unsigned long *pixels; /* array of colormap pixels */
182 /* Determine ncolors, the number of colors to be defined.
183 * Insure that 1 < ncolors <= the colormap size.
185 if (vinfo->class == DirectColor) {
186 ncolors = colormap->red_max;
187 if (colormap->green_max > ncolors)
188 ncolors = colormap->green_max;
189 if (colormap->blue_max > ncolors)
190 ncolors = colormap->blue_max;
192 delta = lowbit(vinfo->red_mask) +
193 lowbit(vinfo->green_mask) +
194 lowbit(vinfo->blue_mask);
196 ncolors = colormap->red_max * colormap->red_mult +
197 colormap->green_max * colormap->green_mult +
198 colormap->blue_max * colormap->blue_mult + 1;
201 if (ncolors <= 1 || (int) ncolors > vinfo->colormap_size) return 0;
203 /* Allocate Read/Write as much of the colormap as we can possibly get.
204 * Then insure that the pixels we were allocated are given in
205 * monotonically increasing order, using a quicksort. Next, insure
206 * that our allocation includes a subset of contiguous pixels at least
207 * as long as the number of colors to be defined. Now we know that
208 * these conditions are met:
209 * 1) There are no free cells in the colormap.
210 * 2) We have a contiguous sequence of pixels, monotonically
211 * increasing, of length >= the number of colors requested.
213 * One cell at a time, we will free, compute the next color value,
214 * then allocate read only. This takes a long time.
215 * This is done to insure that cells are allocated read only in the
216 * contiguous order which we prefer. If the server has a choice of
217 * cells to grant to an allocation request, the server may give us any
218 * cell, so that is why we do these slow gymnastics.
221 if ((pixels = (unsigned long *) calloc((unsigned) vinfo->colormap_size,
222 sizeof(unsigned long))) == NULL)
225 if ((npixels = ROmap(dpy, colormap->colormap, pixels,
226 vinfo->colormap_size, ncolors)) == 0) {
227 free((char *) pixels);
231 qsort((char *) pixels, npixels, sizeof(unsigned long), compare);
233 if (!contiguous(pixels, npixels, ncolors, delta, &first_index, &remainder))
235 /* can't find enough contiguous cells, give up */
236 XFreeColors(dpy, colormap->colormap, pixels, npixels,
238 free((char *) pixels);
241 colormap->base_pixel = pixels[first_index];
243 /* construct a gray map */
244 if (colormap->red_mult == 1 && colormap->green_mult == 1 &&
245 colormap->blue_mult == 1)
246 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
249 color.blue = color.green = color.red =
250 (unsigned short) ((i * 65535) / (colormap->red_max +
251 colormap->green_max +
252 colormap->blue_max));
254 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
259 /* construct a red ramp map */
260 else if (colormap->green_max == 0 && colormap->blue_max == 0)
261 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
264 color.red = (unsigned short) ((i * 65535) / colormap->red_max);
265 color.green = color.blue = 0;
267 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
272 /* construct a green ramp map */
273 else if (colormap->red_max == 0 && colormap->blue_max == 0)
274 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
277 color.green = (unsigned short) ((i * 65535) / colormap->green_max);
278 color.red = color.blue = 0;
280 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
285 /* construct a blue ramp map */
286 else if (colormap->red_max == 0 && colormap->green_max == 0)
287 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
290 color.blue = (unsigned short) ((i * 65535) / colormap->blue_max);
291 color.red = color.green = 0;
293 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
298 /* construct a standard red green blue cube map */
301 #define calc(max,mult) (((n / colormap->mult) % \
302 (colormap->max + 1)) * 65535) / colormap->max
304 for (n=0, i=0; i < ncolors; i++, n += delta)
306 color.pixel = n + colormap->base_pixel;
307 color.red = calc(red_max, red_mult);
308 color.green = calc(green_max, green_mult);
309 color.blue = calc(blue_max, blue_mult);
310 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
316 /* We have a read-only map defined. Now free unused cells,
317 * first those occuring before the contiguous sequence begins,
318 * then any following the contiguous sequence.
322 XFreeColors(dpy, colormap->colormap, pixels, first_index,
325 XFreeColors(dpy, colormap->colormap,
326 &(pixels[first_index + ncolors]), remainder,
329 free((char *) pixels);
334 /****************************************************************************/
336 ROmap(Display *dpy, Colormap cmap, unsigned long pixels[], int m, int n)
338 * dpy - the X server connection
339 * cmap - specifies colormap ID
340 * pixels - returns pixel allocations
341 * m - specifies colormap size
342 * n - specifies number of colors
347 /* first try to allocate the entire colormap */
348 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
349 (unsigned) 0, pixels, (unsigned) m))
352 /* Allocate all available cells in the colormap, using a binary
353 * algorithm to discover how many cells we can allocate in the colormap.
357 p = n + ((m - n + 1) / 2);
358 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
359 (unsigned) 0, pixels, (unsigned) p)) {
363 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
374 /****************************************************************************/
376 contiguous(unsigned long pixels[], int npixels, int ncolors,
377 unsigned long delta, int *first, int *rem)
378 /* pixels - specifies allocated pixels
379 * npixels - specifies count of alloc'd pixels
380 * ncolors - specifies needed sequence length
381 * delta - between pixels
382 * first - returns first index of sequence
383 * rem - returns first index after sequence, or 0, if none follow
386 register int i = 1; /* walking index into the pixel array */
387 register int count = 1; /* length of sequence discovered so far */
390 if (npixels == ncolors) {
395 while (count < ncolors && ncolors - count <= *rem)
397 if (pixels[i-1] + delta == pixels[i])
406 if (count != ncolors)
412 /****************************************************************************/
414 ROorRWcell(Display *dpy, Colormap cmap, unsigned long pixels[],
415 int npixels, XColor *color, unsigned long p)
420 /* Free the read/write allocation of one cell in the colormap.
421 * Request a read only allocation of one cell in the colormap.
422 * If the read only allocation cannot be granted, give up, because
423 * there must be no free cells in the colormap.
424 * If the read only allocation is granted, but gives us a cell which
425 * is not the one that we just freed, it is probably the case that
426 * we are trying allocate White or Black or some other color which
427 * already has a read-only allocation in the map. So we try to
428 * allocate the previously freed cell with a read/write allocation,
429 * because we want contiguous cells for image processing algorithms.
432 pixel = color->pixel;
433 request.red = color->red;
434 request.green = color->green;
435 request.blue = color->blue;
437 XFreeColors(dpy, cmap, &pixel, 1, (unsigned long) 0);
438 if (! XAllocColor(dpy, cmap, color)
439 || (color->pixel != pixel &&
440 (!RWcell(dpy, cmap, color, &request, &pixel))))
442 free_cells(dpy, cmap, pixels, npixels, (int)p);
449 /****************************************************************************/
451 free_cells(Display *dpy, Colormap cmap, unsigned long pixels[],
454 * pixels - to be freed
455 * npixels - original number allocated
458 /* One of the npixels allocated has already been freed.
459 * p is the index of the freed pixel.
460 * First free the pixels preceeding p, and there are p of them;
461 * then free the pixels following p, there are npixels - p - 1 of them.
463 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
464 XFreeColors(dpy, cmap, &(pixels[p+1]), npixels - p - 1, (unsigned long) 0);
465 free((char *) pixels);
469 /****************************************************************************/
471 RWcell(Display *dpy, Colormap cmap, XColor *color, XColor *request,
472 unsigned long *pixel)
474 unsigned long n = *pixel;
476 XFreeColors(dpy, cmap, &(color->pixel), 1, (unsigned long)0);
477 if (! XAllocColorCells(dpy, cmap, (Bool) 0, (unsigned long *) NULL,
478 (unsigned) 0, pixel, (unsigned) 1))
482 XFreeColors(dpy, cmap, pixel, 1, (unsigned long) 0);
485 color->pixel = *pixel;
486 color->flags = DoRed | DoGreen | DoBlue;
487 color->red = request->red;
488 color->green = request->green;
489 color->blue = request->blue;
490 XStoreColors(dpy, cmap, color, 1);
495 /****************************************************************************/
497 compare(_Xconst void *e1, _Xconst void *e2)
499 return ((int)(*(_Xconst long *)e1 - *(_Xconst long *)e2));
503 /****************************************************************************/
505 readonly_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
510 last_pixel = (colormap->red_max + 1) * (colormap->green_max + 1) *
511 (colormap->blue_max + 1) + colormap->base_pixel - 1;
513 for(i=colormap->base_pixel; i <= last_pixel; i++) {
515 color.pixel = (unsigned long) i;
516 color.red = (unsigned short)
517 (((i/colormap->red_mult) * 65535) / colormap->red_max);
519 if (vinfo->class == StaticColor) {
520 color.green = (unsigned short)
521 ((((i/colormap->green_mult) % (colormap->green_max + 1)) *
522 65535) / colormap->green_max);
523 color.blue = (unsigned short)
524 (((i%colormap->green_mult) * 65535) / colormap->blue_max);
526 else /* vinfo->class == GrayScale, old style allocation XXX */
527 color.green = color.blue = color.red;
529 XAllocColor(dpy, colormap->colormap, &color);
530 if (color.pixel != (unsigned long) i)