1 #if 0
2 static const char sccsid[] = "@(#)color.c 4.00 97/01/01 xlockmore";
3
4 #endif
5
6 /*-
7 * color.c - extracted from swirl.c, xlock.c and util.c
8 *
9 * See xlock.c for copying information.
10 *
11 * xlock.c and util.c Copyright (c) 1988-91 by Patrick J. Naughton.
12 * swirl.c Copyright (c) 1994 M.Dobie <mrd@ecs.soton.ac.uk>
13 *
14 */
15
16 #include "xlock.h"
17 #include "color.h"
18
19 /* Formerly in util.c */
20 /*-
21 * Create an HSB ramp.
22 *
23 * Revision History:
24 * Changes maintained by David Bagley <bagleyd AT verizon.net>
25 * 22-Jun-94: Modified for VMS
26 * <Anthony.D.Clarke@Support.Hatfield.Raytheon.bae.eurokom.ie>
27 * Changes of Patrick J. Naughton
28 * 29-Jul-90: renamed hsbramp.c from HSBmap.c
29 * minor optimizations.
30 * 01-Sep-88: Written.
31 */
32
33 static void
hsb2rgb(double H,double S,double B,unsigned char * r,unsigned char * g,unsigned char * b)34 hsb2rgb(double H, double S, double B,
35 unsigned char *r, unsigned char *g, unsigned char *b)
36 {
37 int i;
38 double f, bb;
39 unsigned char p, q, t;
40
41 H -= floor(H); /* remove anything over 1 */
42 H *= 6.0;
43 i = (int) floor(H); /* 0..5 */
44 f = H - (float) i; /* f = fractional part of H */
45 bb = 255.0 * B;
46 p = (unsigned char) (bb * (1.0 - S));
47 q = (unsigned char) (bb * (1.0 - (S * f)));
48 t = (unsigned char) (bb * (1.0 - (S * (1.0 - f))));
49 switch (i) {
50 case 0:
51 *r = (unsigned char) bb;
52 *g = t;
53 *b = p;
54 break;
55 case 1:
56 *r = q;
57 *g = (unsigned char) bb;
58 *b = p;
59 break;
60 case 2:
61 *r = p;
62 *g = (unsigned char) bb;
63 *b = t;
64 break;
65 case 3:
66 *r = p;
67 *g = q;
68 *b = (unsigned char) bb;
69 break;
70 case 4:
71 *r = t;
72 *g = p;
73 *b = (unsigned char) bb;
74 break;
75 case 5:
76 *r = (unsigned char) bb;
77 *g = p;
78 *b = q;
79 break;
80 }
81 }
82
83
84 /*-
85 * Input is two points in HSB color space and a count
86 * of how many discreet rgb space values the caller wants.
87 *
88 * Output is that many rgb triples which describe a linear
89 * interpolate ramp between the two input colors.
90 */
91 #ifdef WIN32
92 /*-
93 * make sure this function is NOT static under WIN32. We use it to
94 * create the colortable in WIN32 specific stuff in xlock.c
95 */
96 void
97 #else
98 static void
99 #endif
hsbramp(double h1,double s1,double b1,double h2,double s2,double b2,int count,unsigned char * red,unsigned char * green,unsigned char * blue)100 hsbramp(double h1, double s1, double b1, double h2, double s2, double b2,
101 int count, unsigned char *red, unsigned char *green, unsigned char *blue)
102 {
103 double dh, ds, db;
104
105 dh = (h2 - h1) / count;
106 ds = (s2 - s1) / count;
107 db = (b2 - b1) / count;
108 while (count--) {
109 hsb2rgb(h1, s1, b1, red++, green++, blue++);
110 h1 += dh;
111 s1 += ds;
112 b1 += db;
113 }
114 }
115
116
117 /* Formerly in xlock.c */
118
119 unsigned long
allocPixel(Display * display,Colormap cmap,char * name,char * def)120 allocPixel(Display * display, Colormap cmap, char *name, char *def)
121 {
122 XColor col, tmp;
123
124 (void) XParseColor(display, cmap, name, &col);
125 if (!XAllocColor(display, cmap, &col)) {
126 (void) fprintf(stderr, "could not allocate: %s, using %s instead\n",
127 name, def);
128 (void) XAllocNamedColor(display, cmap, def, &col, &tmp);
129 }
130 return col.pixel;
131 }
132
133 static void
monoColormap(Screen * scr,ScreenInfo * si,char * foreground,char * background)134 monoColormap(Screen * scr, ScreenInfo * si, char *foreground, char *background)
135 {
136 si->black_pixel = BlackPixelOfScreen(scr);
137 si->white_pixel = WhitePixelOfScreen(scr);
138 if (strcmp(foreground, "White") == 0 || strcmp(foreground, "white") == 0 ||
139 strcmp(background, "Black") == 0 || strcmp(background, "black") == 0) {
140 si->fg_pixel = WhitePixelOfScreen(scr);
141 si->bg_pixel = BlackPixelOfScreen(scr);
142 } else {
143 si->fg_pixel = BlackPixelOfScreen(scr);
144 si->bg_pixel = WhitePixelOfScreen(scr);
145 }
146 si->pixels[0] = WhitePixelOfScreen(scr);
147 si->pixels[1] = BlackPixelOfScreen(scr);
148 si->npixels = 2;
149 }
150
151 extern char *foreground;
152 extern char *background;
153 #ifdef USE_DTSAVER
154 extern Bool dtsaver;
155 #endif
156
157 void
fixColormap(ModeInfo * mi,int ncolors,float saturation,Bool mono,Bool install,Bool inroot,Bool inwindow,Bool verbose)158 fixColormap(ModeInfo * mi, int ncolors, float saturation,
159 Bool mono, Bool install, Bool inroot, Bool inwindow, Bool verbose)
160 {
161 Display *display = MI_DISPLAY(mi);
162 Window window = MI_WINDOW(mi);
163 Screen *scr = MI_SCREENPTR(mi);
164 Colormap cmap = MI_COLORMAP(mi);
165 Colormap dcmap = DefaultColormapOfScreen(scr);
166 XColor xcolor;
167 unsigned char *red = (unsigned char *) NULL,
168 *green = (unsigned char *) NULL,
169 *blue = (unsigned char *) NULL;
170 int colorcount, i, fixed, visualclass;
171
172 #ifndef COMPLIANT_COLORMAP
173 Bool retry = False;
174
175 #endif
176
177 if (mono || CellsOfScreen(scr) <= 2) {
178 if (MI_PIXELS(mi))
179 return;
180 if ((MI_PIXELS(mi) = (unsigned long *) calloc(2,
181 sizeof (unsigned long))) == NULL) {
182 (void) fprintf(stderr, "could not get the 2 colors for mono\n");
183 }
184
185 monoColormap(scr, MI_SCREENINFO(mi), foreground, background);
186 return;
187 }
188 colorcount = ncolors;
189 if ((( red = (unsigned char *) calloc(ncolors,
190 sizeof (unsigned char))) == NULL) ||
191 ((green = (unsigned char *) calloc(ncolors,
192 sizeof (unsigned char))) == NULL) ||
193 (( blue = (unsigned char *) calloc(ncolors,
194 sizeof (unsigned char))) == NULL)) {
195 (void) fprintf(stderr, "could not get the %d colors\n", ncolors);
196 if (red != NULL)
197 free(red);
198 if (green != NULL)
199 free(green);
200 return;
201 }
202
203 visualclass = MI_VISUALCLASS(mi);
204 fixed = (visualclass == StaticGray) || (visualclass == StaticColor) ||
205 (visualclass == TrueColor);
206 if (
207 #ifdef USE_DTSAVER
208 dtsaver || /* needs to be in focus without mouse */
209
210 #endif
211 inroot || (!install && !fixed) || cmap == None) {
212 cmap = dcmap;
213 }
214 if (cmap != dcmap && MI_PIXELS(mi)) {
215 XFreeColors(display, cmap, MI_PIXELS(mi), MI_NPIXELS(mi), 0);
216 #ifndef COMPLIANT_COLORMAP
217 XFreeColors(display, cmap, &(MI_BLACK_PIXEL(mi)), 1, 0);
218 XFreeColors(display, cmap, &(MI_WHITE_PIXEL(mi)), 1, 0);
219 #endif
220 XFreeColors(display, cmap, &(MI_BG_PIXEL(mi)), 1, 0);
221 XFreeColors(display, cmap, &(MI_FG_PIXEL(mi)), 1, 0);
222 }
223 /* else if (cmap) { (void) printf("cmap: this case is possible?\n"); } */
224 if (MI_PIXELS(mi))
225 free(MI_PIXELS(mi));
226 if ((MI_PIXELS(mi) = (unsigned long *) calloc(ncolors,
227 sizeof (unsigned long))) == NULL) {
228 (void) fprintf(stderr, "could not get the %d colors\n", ncolors);
229 }
230 /* "allocate" the black and white pixels, so that they
231 will be included by XCopyColormapAndFree() if it gets called */
232 #ifdef COMPLIANT_COLORMAP
233 MI_BLACK_PIXEL(mi) = BlackPixelOfScreen(scr);
234 MI_WHITE_PIXEL(mi) = WhitePixelOfScreen(scr);
235 #else
236 MI_BLACK_PIXEL(mi) = allocPixel(display, cmap, (char *) "Black", (char *) "Black");
237 MI_WHITE_PIXEL(mi) = allocPixel(display, cmap, (char *) "White", (char *) "White");
238 #endif
239 MI_BG_PIXEL(mi) = allocPixel(display, cmap, background, (char *) "White");
240 MI_FG_PIXEL(mi) = allocPixel(display, cmap, foreground, (char *) "Black");
241 hsbramp(0.0, saturation, 1.0, 1.0, saturation, 1.0, colorcount,
242 red, green, blue);
243
244 MI_NPIXELS(mi) = 0;
245 for (i = 0; i < colorcount; i++) {
246 xcolor.red = red[i] << 8;
247 xcolor.green = green[i] << 8;
248 xcolor.blue = blue[i] << 8;
249 xcolor.flags = DoRed | DoGreen | DoBlue;
250
251 if (!XAllocColor(display, cmap, &xcolor)) {
252 #ifdef COMPLIANT_COLORMAP
253 if (!install || cmap != dcmap)
254 break;
255 if ((cmap = XCopyColormapAndFree(display, cmap)) == dcmap)
256 break;
257 if (verbose)
258 (void) fprintf(stderr, "using private colormap\n");
259 if (!XAllocColor(display, cmap, &xcolor))
260 break;
261 #else
262 if (verbose)
263 (void) fprintf(stderr, "ran out of colors on colormap\n");
264 if ((saturation != 1.0 || ncolors != 64) && MI_NPIXELS(mi) < 2) {
265 if (verbose)
266 (void) fprintf(stderr,
267 "retrying with saturation = 1.0 and ncolors = 64\n");
268 retry = True;
269 }
270 break;
271 #endif
272 }
273 MI_PIXELS(mi)[i] = xcolor.pixel;
274 MI_NPIXELS(mi)++;
275 }
276 free(red);
277 free(green);
278 free(blue);
279 if (verbose)
280 (void) fprintf(stderr, "%d pixel%s allocated\n", MI_NPIXELS(mi),
281 (MI_NPIXELS(mi) == 1) ? "" : "s");
282 if (MI_NPIXELS(mi) <= 4) {
283 XFreeColors(display, cmap, MI_PIXELS(mi), MI_NPIXELS(mi), 0);
284 #ifndef COMPLIANT_COLORMAP
285 XFreeColors(display, cmap, &(MI_BLACK_PIXEL(mi)), 1, 0);
286 XFreeColors(display, cmap, &(MI_WHITE_PIXEL(mi) ), 1, 0);
287 #endif
288 XFreeColors(display, cmap, &(MI_BG_PIXEL(mi)), 1, 0);
289 XFreeColors(display, cmap, &(MI_FG_PIXEL(mi)), 1, 0);
290 #ifndef COMPLIANT_COLORMAP
291 if (retry) {
292 fixColormap(mi, 64, 1.0,
293 mono, install, inroot, inwindow, verbose);
294 return;
295 }
296 #endif
297 monoColormap(scr, MI_SCREENINFO(mi), foreground, background);
298 MI_COLORMAP(mi) = cmap = DefaultColormapOfScreen(scr);
299 return;
300 }
301 MI_COLORMAP(mi) = cmap;
302 if ((install || fixed) && !inroot && MI_NPIXELS(mi) > 2) {
303 #if 0
304 (void) XGetWindowAttributes(display, window, &xgwa);
305 if (cmap != xgwa.colormap)
306 #endif
307 #if 1 /* Turn off to simulate fvwm and tvwm */
308 setColormap(display, window, cmap, inwindow);
309 #endif
310 }
311 #if 0
312 else {
313 /* white and black colors may not be right for GL modes so lets set them */
314 MI_BLACK_PIXEL(mi) = BlackPixelOfScreen(scr);
315 MI_WHITE_PIXEL(mi) = WhitePixelOfScreen(scr);
316 /* foreground and background colors may not be right.... */
317 BlackPixelOfScreen(scr) = MI_BLACK_PIXEL(mi);
318 WhitePixelOfScreen(scr) = MI_WHITE_PIXEL(mi);
319 }
320 #endif
321 }
322
323 void
setColormap(Display * display,Window window,Colormap cmap,Bool inwindow)324 setColormap(Display * display, Window window, Colormap cmap, Bool inwindow)
325 {
326 XSetWindowColormap(display, window, cmap);
327 /* Now, here we have a problem. When we are running full-screen, the
328 window's override_redirect attribute is on. So, the window manager
329 never gets the ColormapNotify event that gets generated on the
330 above XSetWindowColormap() call, and does not So, a quick solution
331 is to install it ourselves. The problem with this is that it
332 violates the ICCCM convention that only window managers should
333 install colormaps. Indeed, Fvwm _enforces_ this by immediately
334 un-doing any XInstallColormap() performed by a client (which is why
335 this does not work right under Fvwm). */
336
337 if (!inwindow) {
338 XInstallColormap(display, cmap);
339 }
340 }
341
342 #if 0
343 /*-
344 * useableColors
345 */
346 int
347 preserveColors(unsigned long black, unsigned long white,
348 unsigned long bg, unsigned long fg)
349 {
350 /* how many colours should we preserve (out of white, black, fg, bg)? */
351 if (((bg == black) || (bg == white)) && ((fg == black) || (fg == white)))
352 return 2;
353 else if ((bg == black) || (fg == black) ||
354 (bg == white) || (fg == white) || (bg == fg))
355 return 3;
356 else
357 return 4;
358 }
359 #endif
360
361 #ifdef HAVE_XPM
362 void
reserveColors(ModeInfo * mi,Colormap cmap,unsigned long * black)363 reserveColors(ModeInfo * mi, Colormap cmap, unsigned long *black)
364 {
365 Display *display = MI_DISPLAY(mi);
366 XColor blackcolor, whitecolor;
367
368 blackcolor.flags = DoRed | DoGreen | DoBlue;
369 blackcolor.pixel = MI_BLACK_PIXEL(mi);
370 blackcolor.red = 0;
371 blackcolor.green = 0;
372 blackcolor.blue = 0;
373 whitecolor.flags = DoRed | DoGreen | DoBlue;
374 whitecolor.pixel = MI_WHITE_PIXEL(mi);
375 whitecolor.red = 0xFFFF;
376 whitecolor.green = 0xFFFF;
377 whitecolor.blue = 0xFFFF;
378
379 /* If they fail what should I do? */
380 (void) XAllocColor(display, cmap, &blackcolor);
381 (void) XAllocColor(display, cmap, &whitecolor);
382 *black = blackcolor.pixel;
383
384 #if 0
385 {
386 XColor bgcolor, fgcolor;
387
388 bgcolor.pixel = MI_BG_PIXEL(mi);
389 fgcolor.pixel = MI_FG_PIXEL(mi);
390 XQueryColor(display, cmap, &bgcolor);
391 XQueryColor(display, cmap, &fgcolor);
392 (void) XAllocColor(display, cmap, &bgcolor);
393 (void) XAllocColor(display, cmap, &fgcolor);
394 }
395 #endif
396 }
397
398 #endif
399
400 /* the remaining of this file was hacked from colors.c and hsv.c from
401 * xscreensaver
402 *
403 * xscreensaver, Copyright (c) 1997 Jamie Zawinski <jwz AT jwz.org>
404 *
405 * Permission to use, copy, modify, distribute, and sell this software and its
406 * documentation for any purpose is hereby granted without fee, provided that
407 * the above copyright notice appear in all copies and that both that
408 * copyright notice and this permission notice appear in supporting
409 * documentation. No representations are made about the suitability of this
410 * software for any purpose. It is provided "as is" without express or
411 * implied warranty.
412 *
413 * Modified for the use with xlockmore by Jouk Jansen <joukj AT hrem.nano.tudelft.nl>
414 * 12 June 1998
415 */
416
417 /* This file contains some utility routines for randomly picking the colors
418 to hack the screen with.
419 */
420
421 void
free_colors(Display * dpy,Colormap cmap,XColor * colors,int ncolors)422 free_colors(Display * dpy, Colormap cmap, XColor * colors, int ncolors)
423 {
424 int i;
425
426 if (ncolors > 0) {
427 unsigned long *pixels;
428
429 if ((pixels = (unsigned long *) malloc(sizeof (unsigned long) *
430 ncolors)) == NULL) {
431 (void) fprintf(stderr, "could not free colors\n");
432 return;
433 }
434
435 for (i = 0; i < ncolors; i++)
436 pixels[i] = colors[i].pixel;
437 XFreeColors(dpy, cmap, pixels, ncolors, 0L);
438 free(pixels);
439 }
440 }
441
442
443 static void
allocate_writable_colors(Display * dpy,Colormap cmap,unsigned long * pixels,int * ncolorsP)444 allocate_writable_colors(Display * dpy, Colormap cmap,
445 unsigned long *pixels, int *ncolorsP)
446 {
447 int desired = *ncolorsP;
448 int got = 0;
449 int requested = desired;
450 unsigned long *new_pixels = pixels;
451
452 *ncolorsP = 0;
453 while (got < desired
454 && requested > 0) {
455 if (desired - got < requested)
456 requested = desired - got;
457
458 if (XAllocColorCells(dpy, cmap, False, 0, 0, new_pixels, requested)) {
459 /* Got all the pixels we asked for. */
460 new_pixels += requested;
461 got += requested;
462 } else {
463 /* We didn't get all/any of the pixels we asked for. This time, ask
464 for half as many. (If we do get all that we ask for, we ask for
465 the same number again next time, so we only do O(log(n)) server
466 roundtrips.)
467 */
468 requested = requested / 2;
469 }
470 }
471 *ncolorsP += got;
472 }
473
474
475
476 void
make_color_ramp(Display * dpy,Colormap cmap,int h1,double s1,double v1,int h2,double s2,double v2,XColor * colors,int * ncolorsP,Bool closed_p,Bool allocate_p,Bool writable_p)477 make_color_ramp(Display * dpy, Colormap cmap,
478 int h1, double s1, double v1, /* 0-360, 0-1.0, 0-1.0 */
479 int h2, double s2, double v2, /* 0-360, 0-1.0, 0-1.0 */
480 XColor * colors, int *ncolorsP,
481 Bool closed_p,
482 Bool allocate_p,
483 Bool writable_p)
484 {
485 int i;
486 int ncolors = *ncolorsP;
487 double dh, ds, dv; /* deltas */
488
489 AGAIN:
490
491 (void) memset(colors, 0, (*ncolorsP) * sizeof (*colors));
492
493 if (closed_p)
494 ncolors = (ncolors / 2) + 1;
495
496 /* Note: unlike other routines in this module, this function assumes that
497 if h1 and h2 are more than 180 degrees apart, then the desired direction
498 is always from h1 to h2 (rather than the shorter path.) make_uniform
499 depends on this.
500 */
501 dh = ((double) h2 - (double) h1) / ncolors;
502 ds = (s2 - s1) / ncolors;
503 dv = (v2 - v1) / ncolors;
504
505 for (i = 0; i < ncolors; i++) {
506 colors[i].flags = DoRed | DoGreen | DoBlue;
507 hsv_to_rgb((int) (h1 + (i * dh)), (s1 + (i * ds)), (v1 + (i * dv)),
508 &colors[i].red, &colors[i].green, &colors[i].blue);
509 }
510
511 if (closed_p)
512 for (i = ncolors; i < *ncolorsP; i++)
513 colors[i] = colors[(*ncolorsP) - i];
514
515 if (!allocate_p)
516 return;
517
518 if (writable_p) {
519 unsigned long *pixels;
520
521 if ((pixels = (unsigned long *) malloc(sizeof (unsigned long) *
522 ((*ncolorsP) + 1))) == NULL) {
523 goto FAIL;
524 }
525
526 /* allocate_writable_colors() won't do here, because we need exactly this
527 number of cells, or the color sequence we've chosen won't fit. */
528 if (!XAllocColorCells(dpy, cmap, False, 0, 0, pixels, *ncolorsP)) {
529 free(pixels);
530 goto FAIL;
531 }
532 for (i = 0; i < *ncolorsP; i++)
533 colors[i].pixel = pixels[i];
534 free(pixels);
535
536 XStoreColors(dpy, cmap, colors, *ncolorsP);
537 } else {
538 for (i = 0; i < *ncolorsP; i++) {
539 XColor color;
540
541 color = colors[i];
542 if (XAllocColor(dpy, cmap, &color)) {
543 colors[i].pixel = color.pixel;
544 } else {
545 free_colors(dpy, cmap, colors, i);
546 goto FAIL;
547 }
548 }
549 }
550
551 return;
552
553 FAIL:
554 /* we weren't able to allocate all the colors we wanted;
555 decrease the requested number and try again.
556 */
557 ncolors = (ncolors > 170 ? ncolors - 20 :
558 ncolors > 100 ? ncolors - 10 :
559 ncolors > 75 ? ncolors - 5 :
560 ncolors > 25 ? ncolors - 3 :
561 ncolors > 10 ? ncolors - 2 :
562 ncolors > 2 ? ncolors - 1 :
563 0);
564 *ncolorsP = ncolors;
565 if (ncolors > 0)
566 goto AGAIN;
567 }
568
569
570 #define MAXPOINTS 50 /* yeah, so I'm lazy */
571
572
573 static void
make_color_path(Display * dpy,Colormap cmap,int npoints,int * h,double * s,double * v,XColor * colors,int * ncolorsP,Bool allocate_p,Bool writable_p)574 make_color_path(Display * dpy, Colormap cmap,
575 int npoints, int *h, double *s, double *v,
576 XColor * colors, int *ncolorsP,
577 Bool allocate_p,
578 Bool writable_p)
579 {
580 int i, k;
581 int total_ncolors = *ncolorsP;
582
583 int ncolors[MAXPOINTS]; /* number of pixels per edge */
584 double dh[MAXPOINTS]; /* distance between pixels, per edge (0 - 360.0) */
585 double ds[MAXPOINTS]; /* distance between pixels, per edge (0 - 1.0) */
586 double dv[MAXPOINTS]; /* distance between pixels, per edge (0 - 1.0) */
587
588 if (npoints == 0) {
589 *ncolorsP = 0;
590 return;
591 } else if (npoints == 2) { /* using make_color_ramp() will be faster */
592 make_color_ramp(dpy, cmap,
593 h[0], s[0], v[0], h[1], s[1], v[1],
594 colors, ncolorsP,
595 True, /* closed_p */
596 allocate_p, writable_p);
597 return;
598 } else if (npoints >= MAXPOINTS) {
599 npoints = MAXPOINTS - 1;
600 }
601 AGAIN:
602
603 {
604 double DH[MAXPOINTS]; /* Distance between H values in the shortest
605
606 direction around the circle, that is, the
607 distance between 10 and 350 is 20.
608 (Range is 0 - 360.0.)
609 */
610 double edge[MAXPOINTS]; /* lengths of edges in unit HSV space. */
611 double ratio[MAXPOINTS]; /* proportions of the edges (total 1.0) */
612 double circum = 0;
613 double one_point_oh = 0; /* (debug) */
614
615 for (i = 0; i < npoints; i++) {
616 int j = (i + 1) % npoints;
617 double d = ((double) (h[i] - h[j])) / 360;
618
619 if (d < 0)
620 d = -d;
621 if (d > 0.5)
622 d = 0.5 - (d - 0.5);
623 DH[i] = d;
624 }
625
626 for (i = 0; i < npoints; i++) {
627 int j = (i + 1) % npoints;
628
629 edge[i] = sqrt((DH[i] * DH[j]) +
630 ((s[j] - s[i]) * (s[j] - s[i])) +
631 ((v[j] - v[i]) * (v[j] - v[i])));
632 circum += edge[i];
633 }
634
635 #ifdef DEBUG
636 (void) fprintf(stderr, "\ncolors:");
637 for (i = 0; i < npoints; i++)
638 (void) fprintf(stderr, " (%d, %.3f, %.3f)", h[i], s[i], v[i]);
639 (void) fprintf(stderr, "\nlengths:");
640 for (i = 0; i < npoints; i++)
641 (void) fprintf(stderr, " %.3f", edge[i]);
642 #endif /* DEBUG */
643
644 if (circum < 0.0001)
645 goto FAIL;
646
647 for (i = 0; i < npoints; i++) {
648 ratio[i] = edge[i] / circum;
649 one_point_oh += ratio[i];
650 }
651
652 #ifdef DEBUG
653 (void) fprintf(stderr, "\nratios:");
654 for (i = 0; i < npoints; i++)
655 (void) fprintf(stderr, " %.3f", ratio[i]);
656 #endif /* DEBUG */
657
658 if (one_point_oh < 0.99999 || one_point_oh > 1.00001)
659 abort();
660
661 /* space the colors evenly along the circumference -- that means that the
662 number of pixels on a edge is proportional to the length of that edge
663 (relative to the lengths of the other edges.)
664 */
665 for (i = 0; i < npoints; i++)
666 ncolors[i] = (int) (total_ncolors * ratio[i]);
667
668
669 #ifdef DEBUG
670 (void) fprintf(stderr, "\npixels:");
671 for (i = 0; i < npoints; i++)
672 (void) fprintf(stderr, " %d", ncolors[i]);
673 (void) fprintf(stderr, " (%d)\n", total_ncolors);
674 #endif /* DEBUG */
675
676 for (i = 0; i < npoints; i++) {
677 int j = (i + 1) % npoints;
678
679 if (ncolors[i] > 0) {
680 dh[i] = 360 * (DH[i] / ncolors[i]);
681 ds[i] = (s[j] - s[i]) / ncolors[i];
682 dv[i] = (v[j] - v[i]) / ncolors[i];
683 }
684 }
685 }
686
687 (void) memset(colors, 0, (*ncolorsP) * sizeof (*colors));
688
689 k = 0;
690 for (i = 0; i < npoints; i++) {
691 int distance, direction, j;
692
693 distance = h[(i + 1) % npoints] - h[i];
694 direction = (distance >= 0 ? -1 : 1);
695
696 if (distance > 180)
697 distance = 180 - (distance - 180);
698 else if (distance < -180)
699 distance = -(180 - ((-distance) - 180));
700 else
701 direction = -direction;
702
703 #ifdef DEBUG
704 (void) fprintf(stderr, "point %d: %3d %.2f %.2f\n",
705 i, h[i], s[i], v[i]);
706 (void) fprintf(stderr, " h[i]=%d dh[i]=%.2f ncolors[i]=%d\n",
707 h[i], dh[i], ncolors[i]);
708 #endif /* DEBUG */
709 for (j = 0; j < ncolors[i]; j++, k++) {
710 double hh = (h[i] + (j * dh[i] * direction));
711
712 if (hh < 0)
713 hh += 360;
714 else if (hh > 360)
715 hh -= 0;
716 colors[k].flags = DoRed | DoGreen | DoBlue;
717 hsv_to_rgb((int)
718 hh,
719 (s[i] + (j * ds[i])),
720 (v[i] + (j * dv[i])),
721 &colors[k].red, &colors[k].green, &colors[k].blue);
722 #ifdef DEBUG
723 (void) fprintf(stderr, "point %d+%d: %.2f %.2f %.2f %04X %04X %04X\n",
724 i, j,
725 hh,
726 (s[i] + (j * ds[i])),
727 (v[i] + (j * dv[i])),
728 colors[k].red, colors[k].green, colors[k].blue);
729 #endif /* DEBUG */
730 }
731 }
732
733 /* Floating-point round-off can make us decide to use fewer colors. */
734 if (k < *ncolorsP) {
735 *ncolorsP = k;
736 if (k <= 0)
737 return;
738 }
739 if (!allocate_p)
740 return;
741
742 if (writable_p) {
743 unsigned long *pixels = (unsigned long *)
744 malloc(sizeof (unsigned long) * ((*ncolorsP) + 1));
745
746 /* allocate_writable_colors() won't do here, because we need exactly this
747 number of cells, or the color sequence we've chosen won't fit. */
748 if (!XAllocColorCells(dpy, cmap, False, 0, 0, pixels, *ncolorsP)) {
749 free(pixels);
750 goto FAIL;
751 }
752 for (i = 0; i < *ncolorsP; i++)
753 colors[i].pixel = pixels[i];
754 free(pixels);
755
756 XStoreColors(dpy, cmap, colors, *ncolorsP);
757 } else {
758 for (i = 0; i < *ncolorsP; i++) {
759 XColor color;
760
761 color = colors[i];
762 if (XAllocColor(dpy, cmap, &color)) {
763 colors[i].pixel = color.pixel;
764 } else {
765 free_colors(dpy, cmap, colors, i);
766 goto FAIL;
767 }
768 }
769 }
770
771 return;
772
773 FAIL:
774 /* we weren't able to allocate all the colors we wanted;
775 decrease the requested number and try again.
776 */
777 total_ncolors = (total_ncolors > 170 ? total_ncolors - 20 :
778 total_ncolors > 100 ? total_ncolors - 10 :
779 total_ncolors > 75 ? total_ncolors - 5 :
780 total_ncolors > 25 ? total_ncolors - 3 :
781 total_ncolors > 10 ? total_ncolors - 2 :
782 total_ncolors > 2 ? total_ncolors - 1 :
783 0);
784 *ncolorsP = total_ncolors;
785 if (total_ncolors > 0)
786 goto AGAIN;
787 }
788
789 #if 0
790 void
791 make_color_loop(Display * dpy, Colormap cmap,
792 int h0, double s0, double v0, /* 0-360, 0-1.0, 0-1.0 */
793 int h1, double s1, double v1, /* 0-360, 0-1.0, 0-1.0 */
794 int h2, double s2, double v2, /* 0-360, 0-1.0, 0-1.0 */
795 XColor * colors, int *ncolorsP,
796 Bool allocate_p,
797 Bool writable_p)
798 {
799 int h[3];
800 double s[3], v[3];
801
802 h[0] = h0;
803 h[1] = h1;
804 h[2] = h2;
805 s[0] = s0;
806 s[1] = s1;
807 s[2] = s2;
808 v[0] = v0;
809 v[1] = v1;
810 v[2] = v2;
811 make_color_path(dpy, cmap,
812 3, h, s, v,
813 colors, ncolorsP,
814 allocate_p, writable_p);
815 }
816 #endif
817
818 static void
complain(int wanted_colors,int got_colors,Bool wanted_writable,Bool got_writable)819 complain(int wanted_colors, int got_colors,
820 Bool wanted_writable, Bool got_writable)
821 {
822 if (wanted_writable && !got_writable)
823 (void) fprintf(stderr,
824 "%s: wanted %d writable colors; got %d read-only colors.\n",
825 ProgramName, wanted_colors, got_colors);
826
827 else if (wanted_colors > (got_colors + 10))
828 /* don't bother complaining if we're within ten pixels. */
829 (void) fprintf(stderr, "%s: wanted %d%s colors; got %d.\n",
830 ProgramName, wanted_colors, (got_writable ? " writable" : ""),
831 got_colors);
832 }
833
834
835 void
make_smooth_colormap(ModeInfo * mi,Colormap cmap,XColor * colors,int * ncolorsP,Bool allocate_p,Bool * writable_pP)836 make_smooth_colormap(ModeInfo * mi, Colormap cmap,
837 XColor * colors, int *ncolorsP,
838 Bool allocate_p,
839 Bool * writable_pP)
840 {
841 int npoints;
842 int ncolors = *ncolorsP;
843 Bool wanted_writable = (allocate_p && writable_pP && *writable_pP);
844 int i;
845 int h[MAXPOINTS];
846 double s[MAXPOINTS];
847 double v[MAXPOINTS];
848 double total_s = 0;
849 double total_v = 0;
850
851 if (*ncolorsP <= 0)
852 return;
853
854 {
855 int n = (int) (LRAND() % 20);
856
857 if (n <= 5)
858 npoints = 2; /* 30% of the time */
859 else if (n <= 15)
860 npoints = 3; /* 50% of the time */
861 else if (n <= 18)
862 npoints = 4; /* 15% of the time */
863 else
864 npoints = 5; /* 5% of the time */
865 }
866
867 REPICK_ALL_COLORS:
868 for (i = 0; i < npoints; i++) {
869 REPICK_THIS_COLOR:
870 h[i] = (int) (LRAND() % 360);
871 s[i] = LRAND() / MAXRAND;
872 v[i] = 0.8 * LRAND() / MAXRAND + 0.2;
873
874 /* Make sure that no two adjacent colors are *too* close together.
875 If they are, try again.
876 */
877 if (i > 0) {
878 int j = (i + 1 == npoints) ? 0 : (i - 1);
879 double hi = ((double) h[i]) / 360;
880 double hj = ((double) h[j]) / 360;
881 double dh = hj - hi;
882 double distance;
883
884 if (dh < 0)
885 dh = -dh;
886 if (dh > 0.5)
887 dh = 0.5 - (dh - 0.5);
888 distance = sqrt((dh * dh) +
889 ((s[j] - s[i]) * (s[j] - s[i])) +
890 ((v[j] - v[i]) * (v[j] - v[i])));
891 if (distance < 0.2)
892 goto REPICK_THIS_COLOR;
893 }
894 total_s += s[i];
895 total_v += v[i];
896 }
897
898 /* If the average saturation or intensity are too low, repick the colors,
899 so that we don't end up with a black-and-white or too-dark map.
900 */
901 if (total_s / npoints < 0.2)
902 goto REPICK_ALL_COLORS;
903 if (total_v / npoints < 0.3)
904 goto REPICK_ALL_COLORS;
905
906 /* If this visual doesn't support writable cells, don't bother trying.
907 */
908 if (wanted_writable && !has_writable_cells(mi))
909 *writable_pP = False;
910
911 RETRY_NON_WRITABLE:
912 make_color_path(MI_DISPLAY(mi), cmap, npoints, h, s, v, colors, &ncolors,
913 allocate_p, (writable_pP && *writable_pP));
914
915 /* If we tried for writable cells and got none, try for non-writable. */
916 if (allocate_p && *ncolorsP == 0 && *writable_pP) {
917 *writable_pP = False;
918 goto RETRY_NON_WRITABLE;
919 }
920 if (MI_IS_VERBOSE(mi) || MI_IS_DEBUG(mi))
921 complain(*ncolorsP, ncolors, wanted_writable,
922 wanted_writable && *writable_pP);
923
924 *ncolorsP = ncolors;
925 }
926
927
928 void
make_uniform_colormap(ModeInfo * mi,Colormap cmap,XColor * colors,int * ncolorsP,Bool allocate_p,Bool * writable_pP)929 make_uniform_colormap(ModeInfo * mi, Colormap cmap,
930 XColor * colors, int *ncolorsP,
931 Bool allocate_p,
932 Bool * writable_pP)
933 {
934 int ncolors = *ncolorsP;
935 Bool wanted_writable = (allocate_p && writable_pP && *writable_pP);
936
937 double S = ((double) (LRAND() % 34) + 66) / 100.0; /* range 66%-100% */
938 double V = ((double) (LRAND() % 34) + 66) / 100.0; /* range 66%-100% */
939
940 if (*ncolorsP <= 0)
941 return;
942
943 /* If this visual doesn't support writable cells, don't bother trying. */
944 if (wanted_writable && !has_writable_cells(mi))
945 *writable_pP = False;
946
947 RETRY_NON_WRITABLE:
948 make_color_ramp(MI_DISPLAY(mi), cmap,
949 0, S, V,
950 359, S, V,
951 colors, &ncolors,
952 False, True, wanted_writable);
953
954 /* If we tried for writable cells and got none, try for non-writable. */
955 if (allocate_p && *ncolorsP == 0 && writable_pP && *writable_pP) {
956 ncolors = *ncolorsP;
957 *writable_pP = False;
958 goto RETRY_NON_WRITABLE;
959 }
960 if (MI_IS_VERBOSE(mi) || MI_IS_DEBUG(mi))
961 complain(*ncolorsP, ncolors, wanted_writable,
962 wanted_writable && *writable_pP);
963
964 *ncolorsP = ncolors;
965 }
966
967
968 void
make_random_colormap(ModeInfo * mi,Colormap cmap,XColor * colors,int * ncolorsP,Bool bright_p,Bool allocate_p,Bool * writable_pP)969 make_random_colormap(ModeInfo * mi, Colormap cmap,
970 XColor * colors, int *ncolorsP,
971 Bool bright_p,
972 Bool allocate_p,
973 Bool * writable_pP)
974 {
975 Bool wanted_writable = (allocate_p && writable_pP && *writable_pP);
976 int ncolors = *ncolorsP;
977 int i;
978
979 if (*ncolorsP <= 0)
980 return;
981
982 /* If this visual doesn't support writable cells, don't bother trying. */
983 if (wanted_writable && !has_writable_cells(mi))
984 *writable_pP = False;
985
986 for (i = 0; i < ncolors; i++) {
987 colors[i].flags = DoRed | DoGreen | DoBlue;
988 if (bright_p) {
989 int H = (int) LRAND() % 360; /* range 0-360 */
990 double S = ((double) (LRAND() % 70) + 30) / 100.0; /* range 30%-100% */
991 double V = ((double) (LRAND() % 34) + 66) / 100.0; /* range 66%-100% */
992
993 hsv_to_rgb(H, S, V,
994 &colors[i].red, &colors[i].green, &colors[i].blue);
995 } else {
996 colors[i].red = (unsigned short) (LRAND() % 0xFFFF);
997 colors[i].green = (unsigned short) (LRAND() % 0xFFFF);
998 colors[i].blue = (unsigned short) (LRAND() % 0xFFFF);
999 }
1000 }
1001
1002 if (!allocate_p)
1003 return;
1004
1005 RETRY_NON_WRITABLE:
1006 if (writable_pP && *writable_pP) {
1007 unsigned long *pixels = (unsigned long *)
1008 malloc(sizeof (unsigned long) * (ncolors + 1));
1009
1010 allocate_writable_colors(MI_DISPLAY(mi), cmap, pixels, &ncolors);
1011 if (ncolors > 0)
1012 for (i = 0; i < ncolors; i++)
1013 colors[i].pixel = pixels[i];
1014 free(pixels);
1015 if (ncolors > 0)
1016 XStoreColors(MI_DISPLAY(mi), cmap, colors, ncolors);
1017 } else {
1018 for (i = 0; i < ncolors; i++) {
1019 XColor color;
1020
1021 color = colors[i];
1022 if (!XAllocColor(MI_DISPLAY(mi), cmap, &color))
1023 break;
1024 colors[i].pixel = color.pixel;
1025 }
1026 ncolors = i;
1027 }
1028
1029 /* If we tried for writable cells and got none, try for non-writable. */
1030 if (allocate_p && ncolors == 0 && writable_pP && *writable_pP) {
1031 ncolors = *ncolorsP;
1032 *writable_pP = False;
1033 goto RETRY_NON_WRITABLE;
1034 }
1035 if (MI_IS_VERBOSE(mi) || MI_IS_DEBUG(mi))
1036 complain(*ncolorsP, ncolors, wanted_writable,
1037 wanted_writable && *writable_pP);
1038
1039 *ncolorsP = ncolors;
1040 }
1041
1042
1043 void
rotate_colors(Display * dpy,Colormap cmap,XColor * colors,int ncolors,int distance)1044 rotate_colors(Display * dpy, Colormap cmap,
1045 XColor * colors, int ncolors, int distance)
1046 {
1047 int i;
1048 XColor *colors2;
1049
1050 if (ncolors < 2)
1051 return;
1052 colors2 = (XColor *) malloc(sizeof (XColor) * ncolors);
1053 distance = distance % ncolors;
1054 for (i = 0; i < ncolors; i++) {
1055 int j = i - distance;
1056
1057 if (j >= ncolors)
1058 j -= ncolors;
1059 if (j < 0)
1060 j += ncolors;
1061 colors2[i] = colors[j];
1062 colors2[i].pixel = colors[i].pixel;
1063 }
1064 XStoreColors(dpy, cmap, colors2, ncolors);
1065 XFlush(dpy);
1066 (void) memcpy((char *) colors, colors2, sizeof (*colors) * ncolors);
1067 free(colors2);
1068 }
1069
1070 /* xscreensaver, Copyright (c) 1992, 1997 Jamie Zawinski <jwz AT jwz.org>
1071
1072 * Permission to use, copy, modify, distribute, and sell this software and its
1073 * documentation for any purpose is hereby granted without fee, provided that
1074 * the above copyright notice appear in all copies and that both that
1075 * copyright notice and this permission notice appear in supporting
1076 * documentation. No representations are made about the suitability of this
1077 * software for any purpose. It is provided "as is" without express or
1078 * implied warranty.
1079 */
1080
1081 /* This file contains some utility routines for randomly picking the colors
1082 to hack the screen with.
1083 */
1084
1085 void
hsv_to_rgb(int h,double s,double v,unsigned short * r,unsigned short * g,unsigned short * b)1086 hsv_to_rgb(int h, double s, double v,
1087 unsigned short *r, unsigned short *g, unsigned short *b)
1088 {
1089 double H, S, V, R, G, B;
1090 double p1, p2, p3;
1091 double f;
1092 int i;
1093
1094 if (s < 0)
1095 s = 0;
1096 if (v < 0)
1097 v = 0;
1098 if (s > 1)
1099 s = 1;
1100 if (v > 1)
1101 v = 1;
1102
1103 S = s;
1104 V = v;
1105 H = (h % 360) / 60.0;
1106 i = (int) H;
1107 f = H - i;
1108 p1 = V * (1 - S);
1109 p2 = V * (1 - (S * f));
1110 p3 = V * (1 - (S * (1 - f)));
1111 if (i == 0) {
1112 R = V;
1113 G = p3;
1114 B = p1;
1115 } else if (i == 1) {
1116 R = p2;
1117 G = V;
1118 B = p1;
1119 } else if (i == 2) {
1120 R = p1;
1121 G = V;
1122 B = p3;
1123 } else if (i == 3) {
1124 R = p1;
1125 G = p2;
1126 B = V;
1127 } else if (i == 4) {
1128 R = p3;
1129 G = p1;
1130 B = V;
1131 } else {
1132 R = V;
1133 G = p1;
1134 B = p2;
1135 }
1136 *r = (short unsigned int) (R * 65535);
1137 *g = (short unsigned int) (G * 65535);
1138 *b = (short unsigned int) (B * 65535);
1139 }
1140
1141 #if 0
1142 void
1143 rgb_to_hsv(unsigned short r, unsigned short g, unsigned short b,
1144 int *h, double *s, double *v)
1145 {
1146 double R, G, B, H, S, V;
1147 double cmax, cmin;
1148 double cmm;
1149 int imax;
1150
1151 R = ((double) r) / 65535.0;
1152 G = ((double) g) / 65535.0;
1153 B = ((double) b) / 65535.0;
1154 cmax = R;
1155 cmin = G;
1156 imax = 1;
1157 if (cmax < G) {
1158 cmax = G;
1159 cmin = R;
1160 imax = 2;
1161 }
1162 if (cmax < B) {
1163 cmax = B;
1164 imax = 3;
1165 }
1166 if (cmin > B) {
1167 cmin = B;
1168 }
1169 cmm = cmax - cmin;
1170 V = cmax;
1171 if (cmm == 0)
1172 S = H = 0;
1173 else {
1174 S = cmm / cmax;
1175 if (imax == 1)
1176 H = (G - B) / cmm;
1177 else if (imax == 2)
1178 H = 2.0 + (B - R) / cmm;
1179 else /*if (imax == 3) */
1180 H = 4.0 + (R - G) / cmm;
1181 if (H < 0)
1182 H += 6.0;
1183 }
1184 *h = (int) (H * 60.0);
1185 *s = S;
1186 *v = V;
1187 }
1188 #endif
1189
1190 #ifndef WIN32
1191 static int
allocate_color_planes(Display * dpy,Colormap cmap,int nplanes,unsigned long * plane_masks,unsigned long * base_pixel_ret)1192 allocate_color_planes (Display *dpy, Colormap cmap,
1193 int nplanes, unsigned long *plane_masks,
1194 unsigned long *base_pixel_ret)
1195 {
1196 while (nplanes > 1 &&
1197 !XAllocColorCells (dpy, cmap, False, plane_masks, nplanes,
1198 base_pixel_ret, 1))
1199 nplanes--;
1200
1201 return nplanes;
1202 }
1203
1204 static void
merge_colors(int argc,XColor ** argv,XColor * into_color,int mask,Bool additive_p)1205 merge_colors (int argc, XColor **argv, XColor *into_color, int mask,
1206 Bool additive_p)
1207 {
1208 int j;
1209 *into_color = *argv [0];
1210 into_color->pixel |= mask;
1211
1212 for (j = 1; j < argc; j++)
1213 {
1214 # define SHORT_INC(x,y) (x = ((((x)+(y)) > 0xFFFF) ? 0xFFFF : ((x)+(y))))
1215 # define SHORT_DEC(x,y) (x = ((((x)-(y)) < 0) ? 0 : ((x)-(y))))
1216 if (additive_p)
1217 {
1218 SHORT_INC (into_color->red, argv[j]->red);
1219 SHORT_INC (into_color->green, argv[j]->green);
1220 SHORT_INC (into_color->blue, argv[j]->blue);
1221 }
1222 else
1223 {
1224 SHORT_DEC (into_color->red, argv[j]->red);
1225 SHORT_DEC (into_color->green, argv[j]->green);
1226 SHORT_DEC (into_color->blue, argv[j]->blue);
1227 }
1228 # undef SHORT_INC
1229 # undef SHORT_DEC
1230 }
1231 }
1232
1233 static int
i_exp(int i,int j)1234 i_exp (int i, int j)
1235 {
1236 int k = 1;
1237 while (j--) k *= i;
1238 return k;
1239 }
1240
1241 static void
permute_colors(XColor * pcolors,XColor * colors,int count,unsigned long * plane_masks,Bool additive_p)1242 permute_colors (XColor *pcolors, XColor *colors,
1243 int count,
1244 unsigned long *plane_masks,
1245 Bool additive_p)
1246 {
1247 int out = 0;
1248 int max = i_exp (2, count);
1249 if (count > 31) abort ();
1250 for (out = 1; out < max; out++)
1251 {
1252 XColor *argv [32];
1253 int this_mask = 0;
1254 int argc = 0;
1255 int bit;
1256 for (bit = 0; bit < 32; bit++)
1257 if (out & (1<<bit))
1258 {
1259 argv [argc++] = &pcolors [bit];
1260 this_mask |= plane_masks [bit];
1261 }
1262 merge_colors (argc, argv, &colors [out-1], this_mask, additive_p);
1263 }
1264 }
1265
1266 static void
initialize_transparency_colormap(Display * dpy,Colormap cmap,int nplanes,unsigned long base_pixel,unsigned long * plane_masks,XColor * colors,Bool additive_p,ModeInfo * mi)1267 initialize_transparency_colormap (Display *dpy, Colormap cmap,
1268 int nplanes,
1269 unsigned long base_pixel,
1270 unsigned long *plane_masks,
1271 XColor *colors,
1272 Bool additive_p , ModeInfo* mi )
1273 {
1274 int i;
1275 int total_colors = i_exp (2, nplanes);
1276 XColor *all_colors = (XColor *) calloc (total_colors, sizeof (XColor));
1277
1278 for (i = 0; i < nplanes; i++)
1279 colors[i].pixel = base_pixel | plane_masks [i];
1280 permute_colors (colors, all_colors, nplanes, plane_masks, additive_p);
1281
1282 /* clone the default background of the window into our "base" pixel */
1283 all_colors [total_colors - 1].pixel = MI_BLACK_PIXEL( mi );
1284 XQueryColor (dpy, cmap, &all_colors [total_colors - 1]);
1285 all_colors [total_colors - 1].pixel = base_pixel;
1286
1287 for (i = 0; i < total_colors; i++)
1288 all_colors[i].flags = DoRed|DoGreen|DoBlue;
1289 XStoreColors (dpy, cmap, all_colors, total_colors);
1290 XFree ((XPointer) all_colors);
1291 }
1292 #endif
1293
1294 int
screen_number(Screen * screen)1295 screen_number (Screen *screen)
1296 {
1297 #ifndef WIN32
1298 Display *dpy = DisplayOfScreen (screen);
1299 int i;
1300 for (i = 0; i < ScreenCount (dpy); i++)
1301 if (ScreenOfDisplay (dpy, i) == screen)
1302 return i;
1303 #endif
1304 return 0;
1305 }
1306
1307
1308 int
visual_depth(Screen * screen,Visual * visual)1309 visual_depth (Screen *screen, Visual *visual)
1310 {
1311 #ifdef WIN32
1312 return 8;
1313 #else
1314 Display *dpy = DisplayOfScreen (screen);
1315 XVisualInfo vi_in, *vi_out;
1316 int out_count, d;
1317 vi_in.screen = screen_number (screen);
1318 vi_in.visualid = XVisualIDFromVisual (visual);
1319 vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
1320 &vi_in, &out_count);
1321 if (! vi_out) abort ();
1322 d = vi_out [0].depth;
1323 XFree ((char *) vi_out);
1324 return d;
1325 #endif
1326 }
1327
1328
1329 /* You very probably don't want to be using this.
1330 Pixmap depth doesn't refer to the depths of pixmaps, but rather, to
1331 the depth of protocol-level on-the-wire pixmap data, that is, XImages.
1332 To get this info, you should be looking at XImage->bits_per_pixel
1333 instead. (And allocating the data for your XImage structures by
1334 multiplying ximage->bytes_per_line by ximage->height.)
1335
1336 Still, it can be useful to know bits_per_pixel before the XImage exists.
1337
1338 XCreateImage calls _XGetBitsPerPixel to figure this out, but that function
1339 is private to Xlib.
1340
1341 For some reason, _XGetBitsPerPixel tries a hard-coded list of depths if
1342 it doesn't find a matching pixmap format, but I (Dave Odell) couldn't
1343 find any justification for this in the X11 spec. And the XFree86 CVS
1344 repository doesn't quite go back far enough to shed any light on what
1345 the deal is with that.
1346 http://cvsweb.xfree86.org/cvsweb/xc/lib/X11/ImUtil.c
1347
1348 The hard-coded list apparently was added between X11R5 and X11R6.
1349 See <ftp://ftp.x.org/pub/>.
1350 */
1351 int
visual_pixmap_depth(Screen * screen,Visual * visual)1352 visual_pixmap_depth (Screen *screen, Visual *visual)
1353 {
1354 #ifdef WIN32
1355 return 1; /* XApi.c XPutImage only does bitmaps. */
1356 #else
1357 Display *dpy = DisplayOfScreen (screen);
1358 int vdepth = visual_depth (screen, visual);
1359 int pdepth = vdepth;
1360 int i, pfvc = 0;
1361 XPixmapFormatValues *pfv = XListPixmapFormats (dpy, &pfvc);
1362
1363 /* Return the first matching depth in the pixmap formats. If there are no
1364 matching pixmap formats (which shouldn't be able to happen at all) then
1365 return the visual depth instead. */
1366 for (i = 0; i < pfvc; i++)
1367 if (pfv[i].depth == vdepth)
1368 {
1369 pdepth = pfv[i].bits_per_pixel;
1370 break;
1371 }
1372 if (pfv)
1373 XFree (pfv);
1374 return pdepth;
1375 #endif
1376 }
1377
1378
1379 Bool
allocate_alpha_colors(Screen * screen,Visual * visual,Colormap cmap,int * nplanesP,Bool additive_p,unsigned long ** plane_masks,unsigned long * base_pixelP,ModeInfo * mi)1380 allocate_alpha_colors (Screen *screen, Visual *visual, Colormap cmap,
1381 int *nplanesP, Bool additive_p,
1382 unsigned long **plane_masks,
1383 unsigned long *base_pixelP , ModeInfo* mi)
1384 {
1385 #ifdef WIN32
1386 return False;
1387 #else
1388 Display *dpy = DisplayOfScreen (screen);
1389 XColor *colors;
1390 int nplanes = *nplanesP;
1391 int i;
1392
1393 if (!has_writable_cells (mi))
1394 cmap = 0;
1395
1396 if (!cmap) /* A TrueColor visual, or similar. */
1397 {
1398 int depth = visual_depth (screen, visual);
1399 unsigned long masks;
1400 XVisualInfo vi_in, *vi_out;
1401
1402 /* Find out which bits the R, G, and B components actually occupy
1403 on this visual. */
1404 vi_in.screen = screen_number (screen);
1405 vi_in.visualid = XVisualIDFromVisual (visual);
1406 vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
1407 &vi_in, &i);
1408 if (! vi_out) return False;
1409 masks = vi_out[0].red_mask | vi_out[0].green_mask | vi_out[0].blue_mask;
1410 XFree ((char *) vi_out);
1411
1412 if (nplanes > depth)
1413 nplanes = depth;
1414 *nplanesP = nplanes;
1415 *base_pixelP = 0;
1416 *plane_masks = (unsigned long *) calloc(sizeof(unsigned long), nplanes);
1417
1418 /* Pick the planar values randomly, but constrain them to fall within
1419 the bit positions of the R, G, and B fields. */
1420 for (i = 0; i < nplanes; i++)
1421 (*plane_masks)[i] = LRAND() & masks;
1422
1423 }
1424 else /* A PseudoColor visual, or similar. */
1425 {
1426 if (nplanes > 31) nplanes = 31;
1427 *plane_masks = (unsigned long *) malloc(sizeof(unsigned long) * nplanes);
1428
1429 nplanes = allocate_color_planes (dpy, cmap, nplanes, *plane_masks,
1430 base_pixelP);
1431 *nplanesP = nplanes;
1432
1433 if (nplanes <= 1)
1434 {
1435 free(*plane_masks);
1436 *plane_masks = 0;
1437 return False;
1438 }
1439
1440 colors = (XColor *) calloc (nplanes, sizeof (XColor));
1441 for (i = 0; i < nplanes; i++)
1442 {
1443 /* pick the base colors. If we are in subtractive mode, pick higher
1444 intensities. */
1445 hsv_to_rgb (NRAND( 360 ),
1446 NRAND( 100000 ) / 100000.0 ,
1447 NRAND( 100000 ) / 200000.0 + (additive_p ? 0.2 : 0.5),
1448 &colors[i].red,
1449 &colors[i].green,
1450 &colors[i].blue);
1451 }
1452 initialize_transparency_colormap (dpy, cmap, nplanes,
1453 *base_pixelP, *plane_masks, colors,
1454 additive_p , mi );
1455 XFree ((XPointer) colors);
1456 }
1457 return True;
1458 #endif
1459 }
1460