Mercurial > sdl-ios-xcode
comparison src/video/Xext/XmuStdCmap/CrCmap.c @ 2185:2032348afed1
This code adds support for DirectColor visuals to SDL 1.3. The support uses part of the Xmu library. To ensure that the library is
available and to keep people form having to install yet another library I have added the essential parts of Xmu in
src/video/extensions/XmuStdCmap and an include file in src/video/extensions. The support makes use of standard X11 mechanisms to
create color maps and make sure that an application uses the same color map for each window/visual combination. This should make it
possible for gamma support to be implemented based on a single color map per application.
Hurm... it looks like "make indent" modified a few extra files. Those are getting committed too.
author | Bob Pendleton <bob@pendleton.com> |
---|---|
date | Thu, 12 Jul 2007 20:00:50 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
2184:8f8516e79a13 | 2185:2032348afed1 |
---|---|
1 /* $Xorg: CrCmap.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */ | |
2 | |
3 /* | |
4 | |
5 Copyright 1989, 1998 The Open Group | |
6 | |
7 Permission to use, copy, modify, distribute, and sell this software and its | |
8 documentation for any purpose is hereby granted without fee, provided that | |
9 the above copyright notice appear in all copies and that both that | |
10 copyright notice and this permission notice appear in supporting | |
11 documentation. | |
12 | |
13 The above copyright notice and this permission notice shall be included in | |
14 all copies or substantial portions of the Software. | |
15 | |
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
19 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN | |
20 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |
21 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
22 | |
23 Except as contained in this notice, the name of The Open Group shall not be | |
24 used in advertising or otherwise to promote the sale, use or other dealings | |
25 in this Software without prior written authorization from The Open Group. | |
26 | |
27 */ | |
28 /* $XFree86: xc/lib/Xmu/CrCmap.c,v 3.6 2001/01/17 19:42:53 dawes Exp $ */ | |
29 | |
30 /* | |
31 * Author: Donna Converse, MIT X Consortium | |
32 */ | |
33 | |
34 /* | |
35 * CreateCmap.c - given a standard colormap description, make the map. | |
36 */ | |
37 | |
38 #ifdef HAVE_CONFIG_H | |
39 #include <config.h> | |
40 #endif | |
41 #include <stdio.h> | |
42 #include <stdlib.h> | |
43 #include <X11/Xlib.h> | |
44 #include <X11/Xutil.h> | |
45 #include "../extensions/StdCmap.h" | |
46 | |
47 /* | |
48 * Prototypes | |
49 */ | |
50 /* allocate entire map Read Only */ | |
51 static int ROmap(Display *, Colormap, unsigned long[], int, int); | |
52 | |
53 /* allocate a cell, prefer Read Only */ | |
54 static Status ROorRWcell(Display *, Colormap, unsigned long[], int, | |
55 XColor *, unsigned long); | |
56 | |
57 /* allocate a cell Read Write */ | |
58 static Status RWcell(Display *, Colormap, XColor *, XColor *, | |
59 unsigned long *); | |
60 | |
61 /* for quicksort */ | |
62 static int compare(_Xconst void *, _Xconst void *); | |
63 | |
64 /* find contiguous sequence of cells */ | |
65 static Status contiguous(unsigned long[], int, int, unsigned long, int *, | |
66 int *); | |
67 | |
68 /* frees resources before quitting */ | |
69 static void free_cells(Display *, Colormap, unsigned long[], int, int); | |
70 | |
71 /* create a map in a RO visual type */ | |
72 static Status readonly_map(Display *, XVisualInfo *, XStandardColormap *); | |
73 | |
74 /* create a map in a RW visual type */ | |
75 static Status readwrite_map(Display *, XVisualInfo *, XStandardColormap *); | |
76 | |
77 #define lowbit(x) ((x) & (~(x) + 1)) | |
78 #define TRUEMATCH(mult,max,mask) \ | |
79 (colormap->max * colormap->mult <= vinfo->mask && \ | |
80 lowbit(vinfo->mask) == colormap->mult) | |
81 | |
82 /* | |
83 * To create any one colormap which is described by an XStandardColormap | |
84 * structure, use XmuCreateColormap(). | |
85 * | |
86 * Return 0 on failure, non-zero on success. | |
87 * Resources created by this function are not made permanent. | |
88 * No argument error checking is provided. Use at your own risk. | |
89 * | |
90 * All colormaps are created with read only allocations, with the exception | |
91 * of read only allocations of colors in the default map or otherwise | |
92 * which fail to return the expected pixel value, and these are individually | |
93 * defined as read/write allocations. This is done so that all the cells | |
94 * defined in the default map are contiguous, for use in image processing. | |
95 * This typically happens with White and Black in the default map. | |
96 * | |
97 * Colormaps of static visuals are considered to be successfully created if | |
98 * the map of the static visual matches the definition given in the | |
99 * standard colormap structure. | |
100 */ | |
101 | |
102 Status | |
103 XmuCreateColormap(Display * dpy, XStandardColormap * colormap) | |
104 /* dpy - specifies the connection under which the map is created | |
105 * colormap - specifies the map to be created, and returns, particularly | |
106 * if the map is created as a subset of the default colormap | |
107 * of the screen, the base_pixel of the map. | |
108 */ | |
109 { | |
110 XVisualInfo vinfo_template; /* template visual information */ | |
111 XVisualInfo *vinfo; /* matching visual information */ | |
112 XVisualInfo *vpointer; /* for freeing the entire list */ | |
113 long vinfo_mask; /* specifies the visual mask value */ | |
114 int n; /* number of matching visuals */ | |
115 int status; | |
116 | |
117 vinfo_template.visualid = colormap->visualid; | |
118 vinfo_mask = VisualIDMask; | |
119 if ((vinfo = | |
120 XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL) | |
121 return 0; | |
122 | |
123 /* A visual id may be valid on multiple screens. Also, there may | |
124 * be multiple visuals with identical visual ids at different depths. | |
125 * If the colormap is the Default Colormap, use the Default Visual. | |
126 * Otherwise, arbitrarily, use the deepest visual. | |
127 */ | |
128 vpointer = vinfo; | |
129 if (n > 1) { | |
130 register int i; | |
131 register int screen_number; | |
132 Bool def_cmap; | |
133 | |
134 def_cmap = False; | |
135 for (screen_number = ScreenCount(dpy); --screen_number >= 0;) | |
136 if (colormap->colormap == DefaultColormap(dpy, screen_number)) { | |
137 def_cmap = True; | |
138 break; | |
139 } | |
140 | |
141 if (def_cmap) { | |
142 for (i = 0; i < n; i++, vinfo++) { | |
143 if (vinfo->visual == DefaultVisual(dpy, screen_number)) | |
144 break; | |
145 } | |
146 } else { | |
147 int maxdepth = 0; | |
148 XVisualInfo *v = NULL; | |
149 | |
150 for (i = 0; i < n; i++, vinfo++) | |
151 if (vinfo->depth > maxdepth) { | |
152 maxdepth = vinfo->depth; | |
153 v = vinfo; | |
154 } | |
155 vinfo = v; | |
156 } | |
157 } | |
158 | |
159 if (vinfo->class == PseudoColor || vinfo->class == DirectColor || | |
160 vinfo->class == GrayScale) | |
161 status = readwrite_map(dpy, vinfo, colormap); | |
162 else if (vinfo->class == TrueColor) | |
163 status = TRUEMATCH(red_mult, red_max, red_mask) && | |
164 TRUEMATCH(green_mult, green_max, green_mask) && | |
165 TRUEMATCH(blue_mult, blue_max, blue_mask); | |
166 else | |
167 status = readonly_map(dpy, vinfo, colormap); | |
168 | |
169 XFree((char *) vpointer); | |
170 return status; | |
171 } | |
172 | |
173 /****************************************************************************/ | |
174 static Status | |
175 readwrite_map(Display * dpy, XVisualInfo * vinfo, | |
176 XStandardColormap * colormap) | |
177 { | |
178 register unsigned long i, n; /* index counters */ | |
179 unsigned long ncolors; /* number of colors to be defined */ | |
180 int npixels; /* number of pixels allocated R/W */ | |
181 int first_index; /* first index of pixels to use */ | |
182 int remainder; /* first index of remainder */ | |
183 XColor color; /* the definition of a color */ | |
184 unsigned long *pixels; /* array of colormap pixels */ | |
185 unsigned long delta; | |
186 | |
187 | |
188 /* Determine ncolors, the number of colors to be defined. | |
189 * Insure that 1 < ncolors <= the colormap size. | |
190 */ | |
191 if (vinfo->class == DirectColor) { | |
192 ncolors = colormap->red_max; | |
193 if (colormap->green_max > ncolors) | |
194 ncolors = colormap->green_max; | |
195 if (colormap->blue_max > ncolors) | |
196 ncolors = colormap->blue_max; | |
197 ncolors++; | |
198 delta = lowbit(vinfo->red_mask) + | |
199 lowbit(vinfo->green_mask) + lowbit(vinfo->blue_mask); | |
200 } else { | |
201 ncolors = colormap->red_max * colormap->red_mult + | |
202 colormap->green_max * colormap->green_mult + | |
203 colormap->blue_max * colormap->blue_mult + 1; | |
204 delta = 1; | |
205 } | |
206 if (ncolors <= 1 || (int) ncolors > vinfo->colormap_size) | |
207 return 0; | |
208 | |
209 /* Allocate Read/Write as much of the colormap as we can possibly get. | |
210 * Then insure that the pixels we were allocated are given in | |
211 * monotonically increasing order, using a quicksort. Next, insure | |
212 * that our allocation includes a subset of contiguous pixels at least | |
213 * as long as the number of colors to be defined. Now we know that | |
214 * these conditions are met: | |
215 * 1) There are no free cells in the colormap. | |
216 * 2) We have a contiguous sequence of pixels, monotonically | |
217 * increasing, of length >= the number of colors requested. | |
218 * | |
219 * One cell at a time, we will free, compute the next color value, | |
220 * then allocate read only. This takes a long time. | |
221 * This is done to insure that cells are allocated read only in the | |
222 * contiguous order which we prefer. If the server has a choice of | |
223 * cells to grant to an allocation request, the server may give us any | |
224 * cell, so that is why we do these slow gymnastics. | |
225 */ | |
226 | |
227 if ((pixels = (unsigned long *) calloc((unsigned) vinfo->colormap_size, | |
228 sizeof(unsigned long))) == NULL) | |
229 return 0; | |
230 | |
231 if ((npixels = ROmap(dpy, colormap->colormap, pixels, | |
232 vinfo->colormap_size, ncolors)) == 0) { | |
233 free((char *) pixels); | |
234 return 0; | |
235 } | |
236 | |
237 qsort((char *) pixels, npixels, sizeof(unsigned long), compare); | |
238 | |
239 if (!contiguous | |
240 (pixels, npixels, ncolors, delta, &first_index, &remainder)) { | |
241 /* can't find enough contiguous cells, give up */ | |
242 XFreeColors(dpy, colormap->colormap, pixels, npixels, | |
243 (unsigned long) 0); | |
244 free((char *) pixels); | |
245 return 0; | |
246 } | |
247 colormap->base_pixel = pixels[first_index]; | |
248 | |
249 /* construct a gray map */ | |
250 if (colormap->red_mult == 1 && colormap->green_mult == 1 && | |
251 colormap->blue_mult == 1) | |
252 for (n = colormap->base_pixel, i = 0; i < ncolors; i++, n += delta) { | |
253 color.pixel = n; | |
254 color.blue = color.green = color.red = | |
255 (unsigned short) ((i * 65535) / (colormap->red_max + | |
256 colormap->green_max + | |
257 colormap->blue_max)); | |
258 | |
259 if (!ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color, | |
260 first_index + i)) | |
261 return 0; | |
262 } | |
263 | |
264 /* construct a red ramp map */ | |
265 else if (colormap->green_max == 0 && colormap->blue_max == 0) | |
266 for (n = colormap->base_pixel, i = 0; i < ncolors; i++, n += delta) { | |
267 color.pixel = n; | |
268 color.red = (unsigned short) ((i * 65535) / colormap->red_max); | |
269 color.green = color.blue = 0; | |
270 | |
271 if (!ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color, | |
272 first_index + i)) | |
273 return 0; | |
274 } | |
275 | |
276 /* construct a green ramp map */ | |
277 else if (colormap->red_max == 0 && colormap->blue_max == 0) | |
278 for (n = colormap->base_pixel, i = 0; i < ncolors; i++, n += delta) { | |
279 color.pixel = n; | |
280 color.green = | |
281 (unsigned short) ((i * 65535) / colormap->green_max); | |
282 color.red = color.blue = 0; | |
283 | |
284 if (!ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color, | |
285 first_index + i)) | |
286 return 0; | |
287 } | |
288 | |
289 /* construct a blue ramp map */ | |
290 else if (colormap->red_max == 0 && colormap->green_max == 0) | |
291 for (n = colormap->base_pixel, i = 0; i < ncolors; i++, n += delta) { | |
292 color.pixel = n; | |
293 color.blue = (unsigned short) ((i * 65535) / colormap->blue_max); | |
294 color.red = color.green = 0; | |
295 | |
296 if (!ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color, | |
297 first_index + i)) | |
298 return 0; | |
299 } | |
300 | |
301 /* construct a standard red green blue cube map */ | |
302 else { | |
303 #define calc(max,mult) (((n / colormap->mult) % \ | |
304 (colormap->max + 1)) * 65535) / colormap->max | |
305 | |
306 for (n = 0, i = 0; i < ncolors; i++, n += delta) { | |
307 color.pixel = n + colormap->base_pixel; | |
308 color.red = calc(red_max, red_mult); | |
309 color.green = calc(green_max, green_mult); | |
310 color.blue = calc(blue_max, blue_mult); | |
311 if (!ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color, | |
312 first_index + i)) | |
313 return 0; | |
314 } | |
315 #undef calc | |
316 } | |
317 /* We have a read-only map defined. Now free unused cells, | |
318 * first those occuring before the contiguous sequence begins, | |
319 * then any following the contiguous sequence. | |
320 */ | |
321 | |
322 if (first_index) | |
323 XFreeColors(dpy, colormap->colormap, pixels, first_index, | |
324 (unsigned long) 0); | |
325 if (remainder) | |
326 XFreeColors(dpy, colormap->colormap, | |
327 &(pixels[first_index + ncolors]), remainder, | |
328 (unsigned long) 0); | |
329 | |
330 free((char *) pixels); | |
331 return 1; | |
332 } | |
333 | |
334 | |
335 /****************************************************************************/ | |
336 static int | |
337 ROmap(Display * dpy, Colormap cmap, unsigned long pixels[], int m, int n) | |
338 /* | |
339 * dpy - the X server connection | |
340 * cmap - specifies colormap ID | |
341 * pixels - returns pixel allocations | |
342 * m - specifies colormap size | |
343 * n - specifies number of colors | |
344 */ | |
345 { | |
346 register int p; | |
347 | |
348 /* first try to allocate the entire colormap */ | |
349 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL, | |
350 (unsigned) 0, pixels, (unsigned) m)) | |
351 return m; | |
352 | |
353 /* Allocate all available cells in the colormap, using a binary | |
354 * algorithm to discover how many cells we can allocate in the colormap. | |
355 */ | |
356 m--; | |
357 while (n <= m) { | |
358 p = n + ((m - n + 1) / 2); | |
359 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL, | |
360 (unsigned) 0, pixels, (unsigned) p)) { | |
361 if (p == m) | |
362 return p; | |
363 else { | |
364 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0); | |
365 n = p; | |
366 } | |
367 } else | |
368 m = p - 1; | |
369 } | |
370 return 0; | |
371 } | |
372 | |
373 | |
374 /****************************************************************************/ | |
375 static Status | |
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 | |
384 */ | |
385 { | |
386 register int i = 1; /* walking index into the pixel array */ | |
387 register int count = 1; /* length of sequence discovered so far */ | |
388 | |
389 *first = 0; | |
390 if (npixels == ncolors) { | |
391 *rem = 0; | |
392 return 1; | |
393 } | |
394 *rem = npixels - 1; | |
395 while (count < ncolors && ncolors - count <= *rem) { | |
396 if (pixels[i - 1] + delta == pixels[i]) | |
397 count++; | |
398 else { | |
399 count = 1; | |
400 *first = i; | |
401 } | |
402 i++; | |
403 (*rem)--; | |
404 } | |
405 if (count != ncolors) | |
406 return 0; | |
407 return 1; | |
408 } | |
409 | |
410 | |
411 /****************************************************************************/ | |
412 static Status | |
413 ROorRWcell(Display * dpy, Colormap cmap, unsigned long pixels[], | |
414 int npixels, XColor * color, unsigned long p) | |
415 { | |
416 unsigned long pixel; | |
417 XColor request; | |
418 | |
419 /* Free the read/write allocation of one cell in the colormap. | |
420 * Request a read only allocation of one cell in the colormap. | |
421 * If the read only allocation cannot be granted, give up, because | |
422 * there must be no free cells in the colormap. | |
423 * If the read only allocation is granted, but gives us a cell which | |
424 * is not the one that we just freed, it is probably the case that | |
425 * we are trying allocate White or Black or some other color which | |
426 * already has a read-only allocation in the map. So we try to | |
427 * allocate the previously freed cell with a read/write allocation, | |
428 * because we want contiguous cells for image processing algorithms. | |
429 */ | |
430 | |
431 pixel = color->pixel; | |
432 request.red = color->red; | |
433 request.green = color->green; | |
434 request.blue = color->blue; | |
435 | |
436 XFreeColors(dpy, cmap, &pixel, 1, (unsigned long) 0); | |
437 if (!XAllocColor(dpy, cmap, color) | |
438 || (color->pixel != pixel && | |
439 (!RWcell(dpy, cmap, color, &request, &pixel)))) { | |
440 free_cells(dpy, cmap, pixels, npixels, (int) p); | |
441 return 0; | |
442 } | |
443 return 1; | |
444 } | |
445 | |
446 | |
447 /****************************************************************************/ | |
448 static void | |
449 free_cells(Display * dpy, Colormap cmap, unsigned long pixels[], | |
450 int npixels, int p) | |
451 /* | |
452 * pixels - to be freed | |
453 * npixels - original number allocated | |
454 */ | |
455 { | |
456 /* One of the npixels allocated has already been freed. | |
457 * p is the index of the freed pixel. | |
458 * First free the pixels preceeding p, and there are p of them; | |
459 * then free the pixels following p, there are npixels - p - 1 of them. | |
460 */ | |
461 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0); | |
462 XFreeColors(dpy, cmap, &(pixels[p + 1]), npixels - p - 1, | |
463 (unsigned long) 0); | |
464 free((char *) pixels); | |
465 } | |
466 | |
467 | |
468 /****************************************************************************/ | |
469 static Status | |
470 RWcell(Display * dpy, Colormap cmap, XColor * color, XColor * request, | |
471 unsigned long *pixel) | |
472 { | |
473 unsigned long n = *pixel; | |
474 | |
475 XFreeColors(dpy, cmap, &(color->pixel), 1, (unsigned long) 0); | |
476 if (!XAllocColorCells(dpy, cmap, (Bool) 0, (unsigned long *) NULL, | |
477 (unsigned) 0, pixel, (unsigned) 1)) | |
478 return 0; | |
479 if (*pixel != n) { | |
480 XFreeColors(dpy, cmap, pixel, 1, (unsigned long) 0); | |
481 return 0; | |
482 } | |
483 color->pixel = *pixel; | |
484 color->flags = DoRed | DoGreen | DoBlue; | |
485 color->red = request->red; | |
486 color->green = request->green; | |
487 color->blue = request->blue; | |
488 XStoreColors(dpy, cmap, color, 1); | |
489 return 1; | |
490 } | |
491 | |
492 | |
493 /****************************************************************************/ | |
494 static int | |
495 compare(_Xconst void *e1, _Xconst void *e2) | |
496 { | |
497 return ((int) (*(long *) e1 - *(long *) e2)); | |
498 } | |
499 | |
500 | |
501 /****************************************************************************/ | |
502 static Status | |
503 readonly_map(Display * dpy, XVisualInfo * vinfo, XStandardColormap * colormap) | |
504 { | |
505 int i, last_pixel; | |
506 XColor color; | |
507 | |
508 last_pixel = (colormap->red_max + 1) * (colormap->green_max + 1) * | |
509 (colormap->blue_max + 1) + colormap->base_pixel - 1; | |
510 | |
511 for (i = colormap->base_pixel; i <= last_pixel; i++) { | |
512 | |
513 color.pixel = (unsigned long) i; | |
514 color.red = (unsigned short) | |
515 (((i / colormap->red_mult) * 65535) / colormap->red_max); | |
516 | |
517 if (vinfo->class == StaticColor) { | |
518 color.green = (unsigned short) | |
519 ((((i / colormap->green_mult) % (colormap->green_max + 1)) * | |
520 65535) / colormap->green_max); | |
521 color.blue = (unsigned short) | |
522 (((i % colormap->green_mult) * 65535) / colormap->blue_max); | |
523 } else /* vinfo->class == GrayScale, old style allocation XXX */ | |
524 color.green = color.blue = color.red; | |
525 | |
526 XAllocColor(dpy, colormap->colormap, &color); | |
527 if (color.pixel != (unsigned long) i) | |
528 return 0; | |
529 } | |
530 return 1; | |
531 } |