* remove unusesd static variable nocursor
[fvwm.git] / libs / PictureUtils.c
blob84bf6c450eca84f4b66fa8cd7f1b87224669bfdd
1 /* -*-c-*- */
2 /* Copyright (C) 1993, Robert Nation
3 * Copyright (C) 2002 Olivier Chapuis */
4 /* This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 /* ---------------------------- included header files ---------------------- */
21 #include "config.h"
23 #include <stdio.h>
24 #include <signal.h>
25 #include <ctype.h>
26 #include <math.h>
28 #include <X11/Xlib.h>
29 #include <X11/Xmd.h>
31 #include "fvwmlib.h"
32 #include "envvar.h"
33 #include "Parse.h"
34 #include "ftime.h"
35 #include "PictureBase.h"
36 #include "PictureUtils.h"
37 #include "PictureDitherMatrice.h"
39 /* ---------------------------- local definitions and macro ----------------- */
41 #if 0
42 /* dv: unused */
43 /* form alloc_in_cmap from the xpm lib */
44 #define XPM_DIST(r1,g1,b1,r2,g2,b2) (long)\
45 (3*(abs((long)r1-(long)r2) + \
46 abs((long)g1-(long)g2) + \
47 abs((long)b1-(long)b2)) + \
48 abs((long)r1 + (long)g1 + (long)b1 - \
49 ((long)r2 + (long)g2 + (long)b2)))
50 #define XPM_COLOR_CLOSENESS 40000
51 #endif
53 #define SQUARE(X) ((X)*(X))
55 #define TRUE_DIST(r1,g1,b1,r2,g2,b2) (long)\
56 (SQUARE((long)((r1 - r2)>>8)) \
57 + SQUARE((long)((g1 - g2)>>8)) \
58 + SQUARE((long)((b1 - b2)>>8)))
60 #define FAST_DIST(r1,g1,b1,r2,g2,b2) (long)\
61 (abs((long)(r1 - r2)) \
62 + abs((long)(g1 - g2)) \
63 + abs((long)(b1 - b2)))
65 #define FVWM_DIST(r1,g1,b1,r2,g2,b2) \
66 (abs(r1 - r2) + abs(g1 - g2) + abs(b1 - b2) \
67 + 2*abs(abs(r1-g1) + abs(g1-b1) + abs(r1-b1) \
68 - abs(r2-g2) - abs(g2-b2) - abs(r2-b2)))
70 #define USED_DIST(r1,g1,b1,r2,g2,b2) FVWM_DIST(r1,g1,b1,r2,g2,b2)
72 #define PICTURE_COLOR_CLOSENESS USED_DIST(3,3,3,0,0,0)
74 #define PICTURE_PAllocTable 1000000
75 #define PICTURE_PUseDynamicColors 100000
76 #define PICTURE_PStrictColorLimit 10000
77 #define PICTURE_use_named 1000
78 #define PICTURE_TABLETYPE_LENGHT 7
80 /* humm ... dither is probably borken with gamma correction. Anyway I do
81 * do think that using gamma correction for the colors cubes is a good
82 * idea */
83 #define USE_GAMMA_CORECTION 0
84 /* 2.2 is recommanded by the Poynon colors FAQ, some others suggest 1.5 and 2
85 * Use float constants!*/
86 #define COLOR_GAMMA 1.5
87 #define GREY_GAMMA 2.0
89 /* ---------------------------- imports ------------------------------------ */
91 /* ---------------------------- included code files ------------------------ */
93 /* ---------------------------- local types -------------------------------- */
95 typedef struct
97 XColor color; /* rgb color info */
98 unsigned long alloc_count; /* nbr of allocation */
99 } PColor;
101 typedef struct
104 * info for colors table (depth <= 8)
106 /* color cube used */
107 short nr;
108 short ng;
109 short nb;
110 short ngrey;
111 /* grey palette def, nbr of grey = 2^grey_bits */
112 short grey_bits;
113 /* color cube used for dithering with the named table */
114 short d_nr;
115 short d_ng;
116 short d_nb;
117 short d_ngrey_bits;
118 /* do we found a pre-allocated pallet ? */
119 Bool pre_allocated_pallet;
120 /* info for depth > 8 */
121 int red_shift;
122 int green_shift;
123 int blue_shift;
124 int red_prec;
125 int green_prec;
126 int blue_prec;
127 /* for dithering in depth 15 and 16 */
128 unsigned short *red_dither;
129 unsigned short *green_dither;
130 unsigned short *blue_dither;
131 /* colors allocation function */
132 int (*alloc_color)(Display *dpy, Colormap cmap, XColor *c);
133 int (*alloc_color_no_limit)(Display *dpy, Colormap cmap, XColor *c);
134 int (*alloc_color_dither)(
135 Display *dpy, Colormap cmap, XColor *c, int x, int y);
136 void (*free_colors)(
137 Display *dpy, Colormap cmap, Pixel *pixels, int n,
138 unsigned long planes);
139 void (*free_colors_no_limit)(
140 Display *dpy, Colormap cmap, Pixel *pixels, int n,
141 unsigned long planes);
142 } PColorsInfo;
144 typedef struct {
145 int cols_index;
146 long closeness;
147 } CloseColor;
149 /* ---------------------------- forward declarations ----------------------- */
151 /* ---------------------------- local variables ---------------------------- */
153 static int PColorLimit = 0;
154 static PColor *Pct = NULL;
155 static PColor *Pac = NULL;
156 static short *PMappingTable = NULL;
157 static short *PDitherMappingTable = NULL;
158 static Bool PStrictColorLimit = 0;
159 static Bool PAllocTable = 0;
160 static PColorsInfo Pcsi = {
161 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL,
162 NULL, NULL, NULL, NULL};
164 /* ---------------------------- exported variables (globals) --------------- */
166 /* ---------------------------- local functions ---------------------------- */
169 * get shift and prec from a mask
171 static
172 void decompose_mask(
173 unsigned long mask, int *shift, int *prec)
175 *shift = 0;
176 *prec = 0;
178 while (!(mask & 0x1))
180 (*shift)++;
181 mask >>= 1;
184 while (mask & 0x1)
186 (*prec)++;
187 mask >>= 1;
192 * color allocation in the colormap. strongly inspired by SetCloseColor from
193 * the Xpm library (depth <= 8)
196 static int
197 closeness_cmp(const void *a, const void *b)
199 CloseColor *x = (CloseColor *) a, *y = (CloseColor *) b;
201 /* cast to int as qsort requires */
202 return (int) (x->closeness - y->closeness);
205 static
206 int alloc_color_in_cmap(XColor *c, Bool force)
208 static XColor colors[256];
209 CloseColor closenesses[256];
210 XColor tmp;
211 int i,j;
212 int map_entries = (Pvisual->class == DirectColor)?
213 (1 << Pdepth) : Pvisual->map_entries;
214 time_t current_time;
215 time_t last_time = 0;
217 map_entries = (map_entries > 256)? 256:map_entries;
218 current_time = time(NULL);
219 if (current_time - last_time >= 2 || force)
221 last_time = current_time;
222 for (i = 0; i < map_entries; i++)
224 colors[i].pixel = i;
226 XQueryColors(Pdpy, Pcmap, colors, map_entries);
228 for(i = 0; i < map_entries; i++)
230 closenesses[i].cols_index = i;
231 closenesses[i].closeness = USED_DIST(
232 (int)(c->red),
233 (int)(c->green),
234 (int)(c->blue),
235 (int)(colors[i].red),
236 (int)(colors[i].green),
237 (int)(colors[i].blue));
239 qsort(closenesses, map_entries, sizeof(CloseColor), closeness_cmp);
241 i = 0;
242 j = closenesses[i].cols_index;
243 while (force ||
244 (abs((long)c->red - (long)colors[j].red) <=
245 PICTURE_COLOR_CLOSENESS &&
246 abs((long)c->green - (long)colors[j].green) <=
247 PICTURE_COLOR_CLOSENESS &&
248 abs((long)c->blue - (long)colors[j].blue) <=
249 PICTURE_COLOR_CLOSENESS))
251 tmp.red = colors[j].red;
252 tmp.green = colors[j].green;
253 tmp.blue = colors[j].blue;
254 if (XAllocColor(Pdpy, Pcmap, &tmp))
256 c->red = tmp.red;
257 c->green = tmp.green;
258 c->blue = tmp.blue;
259 c->pixel = tmp.pixel;
260 return 1;
262 else
264 i++;
265 if (i == map_entries)
266 break;
267 j = closenesses[i].cols_index;
270 return 0;
274 * dithering
277 static
278 int my_dither(int x, int y, XColor *c)
280 /* the dither matrice */
281 static const char DM[128][128] = DITHER_MATRICE;
282 int index;
283 const char *dmp;
285 if (Pcsi.grey_bits != 0)
287 /* Grey Scale */
288 int prec = Pcsi.grey_bits;
290 if (Pcsi.grey_bits == 1)
292 /* FIXME, can we do a better dithering */
293 prec = 2;
295 dmp = DM[(0 + y) & (DM_HEIGHT - 1)];
296 index = (c->green + ((c->blue + c->red) >> 1)) >> 1;
297 index += (dmp[(0 + x) & (DM_WIDTH - 1)] << 2) >> prec;
298 index = (index - (index >> prec));
299 index = index >> (8 - Pcsi.grey_bits);
301 else
303 /* color cube */
304 int dith, rs, gs, bs, gb, b;
305 int tr,tb,tg;
307 rs = Pcsi.d_nr - 1;
308 gs = Pcsi.d_ng - 1;
309 bs = Pcsi.d_nb - 1;
310 gb = Pcsi.d_ng*Pcsi.d_nb;
311 b = Pcsi.d_nb;
313 dmp = DM[(0 + y) & (DM_HEIGHT - 1)];
314 dith = (dmp[(0 + x) & (DM_WIDTH - 1)] << 2) | 7;
315 tr = ((c->red * rs) + dith) >> 8;
316 tg = ((c->green * gs) + (262 - dith)) >> 8;
317 tb = ((c->blue * bs) + dith) >> 8;
318 index = tr * gb + tg * b + tb;
319 #if 0
320 /* try to use the additonal grey. Not easy, good for
321 * certain image/gradient bad for others */
322 if (Pcsi.d_ngrey_bits)
324 int g_index;
326 /* dither in the Pcsi.ngrey^3 cc */
327 tr = ((c->red * (Pcsi.ngrey-1)) + dith) >> 8;
328 tg = ((c->green * (Pcsi.ngrey-1)) + (262 - dith)) >> 8;
329 tb = ((c->blue * (Pcsi.ngrey-1)) + dith) >> 8;
330 /* get the grey */
331 fprintf(stderr, "%i,%i,%i(%i/%i) ", tr,tg,tb,
332 abs(tr-tg) + abs(tb-tg) + abs(tb-tr),Pcsi.ngrey);
333 g_index = ((tr + tg + tb)/3);
334 if (g_index != 0 && g_index != Pcsi.ngrey-1 &&
335 abs(tr-tg) + abs(tb-tg) + abs(tb-tr) <=
336 Pcsi.d_ngrey_bits)
338 g_index = g_index + Pcsi.ng*Pcsi.nb*Pcsi.ng -1;
339 index = g_index;
342 #endif
343 if (PDitherMappingTable != NULL)
345 index = PDitherMappingTable[index];
348 return index;
351 static
352 int my_dither_depth_15_16_init(void)
354 const unsigned char _dither_44[4][4] =
356 {0, 4, 1, 5},
357 {6, 2, 7, 3},
358 {1, 5, 0, 4},
359 {7, 3, 6, 2}
361 int y,x,i;
362 int rm = 0xf8, re = 0x7, gm = 0xfc, ge = 0x3, bm = 0xf8, be = 0x7;
364 if (Pdepth == 16 && (Pvisual->red_mask == 0xf800) &&
365 (Pvisual->green_mask == 0x7e0) &&
366 (Pvisual->blue_mask == 0x1f))
368 /* ok */
370 else if (Pdepth == 15 && (Pvisual->red_mask == 0x7c00) &&
371 (Pvisual->green_mask == 0x3e0) &&
372 (Pvisual->blue_mask == 0x1f))
374 gm = 0xf8; ge = 0x7;
376 else
378 return 0; /* fail */
381 Pcsi.red_dither =
382 (unsigned short *)safemalloc(4*4*256*sizeof(unsigned short));
383 Pcsi.green_dither =
384 (unsigned short *)safemalloc(4*4*256*sizeof(unsigned short));
385 Pcsi.blue_dither =
386 (unsigned short *)safemalloc(4*4*256*sizeof(unsigned short));
388 for (y = 0; y < 4; y++)
390 for (x = 0; x < 4; x++)
392 for (i = 0; i < 256; i++)
394 if ((_dither_44[x][y] < (i & re)) &&
395 (i < (256 - 8)))
397 Pcsi.red_dither[
398 (x << 10) | (y << 8) | i] =
399 ((i + 8) & rm) << 8;
401 else
403 Pcsi.red_dither[
404 (x << 10) | (y << 8) | i] =
405 (i & rm) << 8;
407 if ((_dither_44[x][y] < ((i & ge) << 1))
408 && (i < (256 - 4)))
410 Pcsi.green_dither[
411 (x << 10) | (y << 8) | i] =
412 ((i + 4) & gm) << 8;
414 else
416 Pcsi.green_dither[
417 (x << 10) | (y << 8) | i] =
418 (i & gm) << 8;
420 if ((_dither_44[x][y] < (i & be)) &&
421 (i < (256 - 8)))
423 Pcsi.blue_dither[
424 (x << 10) | (y << 8) | i] =
425 ((i + 8) & bm) << 8;
427 else
429 Pcsi.blue_dither[
430 (x << 10) | (y << 8) | i] =
431 (i & bm) << 8;
436 return 1;
440 * Color allocation in the "palette"
443 static
444 int alloc_color_in_pct(XColor *c, int index)
446 if (Pct[index].alloc_count == 0)
448 int s = PStrictColorLimit;
450 PStrictColorLimit = 0;
451 c->red = Pct[index].color.red;
452 c->green = Pct[index].color.green;
453 c->blue = Pct[index].color.blue;
454 PictureAllocColor(Pdpy, Pcmap, c, True); /* WARN (rec) */
455 Pct[index].color.pixel = c->pixel;
456 Pct[index].alloc_count = 1;
457 PStrictColorLimit = s;
459 else
461 c->red = Pct[index].color.red;
462 c->green = Pct[index].color.green;
463 c->blue = Pct[index].color.blue;
464 c->pixel = Pct[index].color.pixel;
465 if (Pct[index].alloc_count < 0xffffffff)
466 (Pct[index].alloc_count)++;
468 return 1;
471 static
472 int get_color_index(int r, int g, int b, int is_8)
474 int index;
476 if (!is_8)
478 r= r >> 8;
479 g= g >> 8;
480 b= b >> 8;
482 if (Pcsi.grey_bits > 0)
484 /* FIXME: Use other proporition ? */
485 index = ((r+g+b)/3) >> (8 - Pcsi.grey_bits);
487 else
489 #if 1
490 /* "exact" computation (corrected linear dist) */
491 float fr,fg,fb;
492 int ir, ig, ib;
494 /* map to the cube */
495 fr = ((float)r * (Pcsi.nr-1))/255;
496 fg = ((float)g * (Pcsi.ng-1))/255;
497 fb = ((float)b * (Pcsi.nb-1))/255;
499 if (PMappingTable != NULL)
501 ir = (int)fr + (fr - (int)fr > 0.5);
502 ig = (int)fg + (fg - (int)fg > 0.5);
503 ib = (int)fb + (fb - (int)fb > 0.5);
505 index = ir * Pcsi.ng*Pcsi.nb + ig * Pcsi.nb + ib;
507 else
509 /* found the best of the 8 linear closest points */
510 int lr,lg,lb,tr,tg,tb,best_dist = -1,i,d;
512 index = 0;
513 lr = min((int)fr+1,Pcsi.nr-1);
514 lg = min((int)fg+1,Pcsi.ng-1);
515 lb = min((int)fb+1,Pcsi.nb-1);
516 for(tr =(int)fr; tr<=lr; tr++)
518 for(tg =(int)fg; tg<=lg; tg++)
520 for(tb =(int)fb; tb<=lb; tb++)
522 i = tr * Pcsi.ng*Pcsi.nb +
523 tg * Pcsi.nb +
525 d = USED_DIST(
526 r,g,b,
527 (Pct[i].color.red>>8),
528 (Pct[i].color.green>>8),
529 (Pct[i].color.blue>>8));
530 if (best_dist == -1 ||
531 d < best_dist)
533 index = i;
534 best_dist = d;
540 /* now found the best grey */
541 if (Pcsi.ngrey - 2 > 0)
543 /* FIXME: speedup this with more than 8 grey */
544 int start = Pcsi.nr*Pcsi.ng*Pcsi.nb;
545 for(i=start; i < start+Pcsi.ngrey-2; i++)
547 d = USED_DIST(
548 r,g,b,
549 (Pct[i].color.red>>8),
550 (Pct[i].color.green>>8),
551 (Pct[i].color.blue>>8));
552 if (d < best_dist)
554 index = i;
555 best_dist = d;
559 return index;
561 #else
562 /* approximation; faster */
563 index = ((r * Pcsi.nr)>>8) * Pcsi.ng*Pcsi.nb +
564 ((g * Pcsi.ng)>>8) * Pcsi.nb +
565 ((b * Pcsi.nb)>>8);
566 #endif
567 if (PMappingTable != NULL)
569 index = PMappingTable[index];
572 return index;
576 * Main colors allocator
578 static
579 int alloc_color_proportion(Display *dpy, Colormap cmap, XColor *c)
581 c->pixel = (Pixel)(
582 ((c->red >> (16 - Pcsi.red_prec))<< Pcsi.red_shift) +
583 ((c->green >> (16 - Pcsi.green_prec))<< Pcsi.green_shift) +
584 ((c->blue >> (16 - Pcsi.blue_prec))<< Pcsi.blue_shift)
586 return 1;
589 static
590 int alloc_color_proportion_dither(
591 Display *dpy, Colormap cmap, XColor *c, int x, int y)
593 /* 8 bit colors !! */
594 c->red = Pcsi.red_dither[
595 (((x + 0) & 0x3) << 10) | ((y & 0x3) << 8) |
596 ((c->red) & 0xff)] * 257;
597 c->green = Pcsi.green_dither[
598 (((x + 0) & 0x3) << 10) | ((y & 0x3) << 8) |
599 ((c->green) & 0xff)] * 257;
600 c->blue = Pcsi.blue_dither[
601 (((x + 0) & 0x3) << 10) | ((y & 0x3) << 8) |
602 ((c->blue) & 0xff)] * 257;
603 c->pixel = (Pixel)(
604 ((c->red >> (16 - Pcsi.red_prec)) << Pcsi.red_shift) +
605 ((c->green >> (16 - Pcsi.green_prec))
606 << Pcsi.green_shift) +
607 ((c->blue >> (16 - Pcsi.blue_prec)) << Pcsi.blue_shift)
609 return 1;
612 static
613 int alloc_color_proportion_grey(
614 Display *dpy, Colormap cmap, XColor *c)
616 /* FIXME: is this ok in general? */
617 c->pixel = ((c->red + c->green + c->blue)/3);
618 if (Pdepth < 16)
620 c->pixel = c->pixel >> (16 - Pdepth);
622 return 1;
625 static
626 int alloc_color_in_table(Display *dpy, Colormap cmap, XColor *c)
629 int index = get_color_index(c->red,c->green,c->blue, False);
630 return alloc_color_in_pct(c, index);
633 static
634 int alloc_color_in_table_dither(
635 Display *dpy, Colormap cmap, XColor *c, int x, int y)
637 int index;
638 /* 8 bit colors !! */
639 index = my_dither(x, y, c);
640 return alloc_color_in_pct(c, index);
643 static
644 int alloc_color_dynamic_no_limit(
645 Display *dpy, Colormap cmap, XColor *c)
647 int r = 0;
649 if (XAllocColor(dpy, cmap, c))
651 r = 1;
653 else if (!alloc_color_in_cmap(c, False))
655 XGrabServer(dpy);
656 r = alloc_color_in_cmap(c, True);
657 XUngrabServer(dpy);
659 else
661 r = 1;
663 if (r && Pac != NULL && (c->pixel <= (1 << Pdepth) /* always true*/))
665 Pac[c->pixel].alloc_count++;
666 Pac[c->pixel].color.red = c->red;
667 Pac[c->pixel].color.green = c->green;
668 Pac[c->pixel].color.blue = c->blue;
669 Pac[c->pixel].color.pixel = c->pixel;
671 return r;
674 static
675 int alloc_color_x(
676 Display *dpy, Colormap cmap, XColor *c)
678 return XAllocColor(dpy, cmap, c);
681 static
682 void free_colors_in_table(
683 Display *dpy, Colormap cmap, Pixel *pixels, int n,
684 unsigned long planes)
686 Pixel *p;
687 int i,j,do_free;
688 int m = 0;
690 if (!Pct || !PUseDynamicColors)
692 return;
695 p = (Pixel *)safemalloc(n*sizeof(Pixel));
696 for(i= 0; i < n; i++)
698 do_free = 1;
699 for(j=0; j<PColorLimit; j++)
701 if (Pct[j].alloc_count &&
702 Pct[j].alloc_count < 0xffffffff &&
703 pixels[i] == Pct[j].color.pixel)
705 (Pct[j].alloc_count)--;
706 if (Pct[j].alloc_count)
707 do_free = 0;
708 break;
711 if (do_free)
713 p[m++] = pixels[i];
716 if (m > 0)
718 XFreeColors(dpy, cmap, p, m, planes);
720 free(p);
722 return;
725 static
726 void free_colors_x(
727 Display *dpy, Colormap cmap, Pixel *pixels, int n,
728 unsigned long planes)
730 XFreeColors(dpy, cmap, pixels, n, planes);
731 if (Pac != NULL)
733 int nbr_colors = (1 << Pdepth);
734 int i;
736 for(i= 0; i < n; i++)
738 if (pixels[i] <= nbr_colors)
740 Pac[pixels[i]].alloc_count--;
747 * local function for building pallet (dynamic colors, private DirectColor
748 * cmap)
750 static
751 XColor *build_mapping_colors(int nr, int ng, int nb)
753 int r, g, b, i;
754 XColor *colors;
756 colors = (XColor *)safemalloc(nr*ng*nb * sizeof(XColor));
757 i = 0;
758 for (r = 0; r < nr; r++)
760 for (g = 0; g < ng; g++)
762 for (b = 0; b < nb; b++)
764 colors[i].red =
765 r * 65535 / (nr - 1);
766 colors[i].green =
767 g * 65535 / (ng - 1);
768 colors[i].blue =
769 b * 65535 / (nb - 1);
770 i++;
774 return colors;
777 static short *build_mapping_table(int nr, int ng, int nb, Bool use_named)
779 int size = nr*ng*nb;
780 XColor *colors_map;
781 short *Table;
782 int i,j, minind;
783 double mindst = 40000;
784 double dst;
786 colors_map = build_mapping_colors(nr, ng, nb);
787 Table = (short *)safemalloc((size+1) * sizeof(short));
788 for(i=0; i<size; i++)
790 minind = 0;
791 for(j=0; j<PColorLimit; j++)
793 if (use_named)
795 /* for back ward compatibility */
796 dst = TRUE_DIST(colors_map[i].red,
797 colors_map[i].green,
798 colors_map[i].blue,
799 Pct[j].color.red,
800 Pct[j].color.green,
801 Pct[j].color.blue);
803 else
805 dst = USED_DIST(colors_map[i].red,
806 colors_map[i].green,
807 colors_map[i].blue,
808 Pct[j].color.red,
809 Pct[j].color.green,
810 Pct[j].color.blue);
812 if (j == 0 || dst < mindst)
814 mindst=dst;
815 minind=j;
818 Table[i] = minind;
820 Table[size] = Table[size-1];
821 free(colors_map);
822 return Table;
825 static
826 void free_table_colors(PColor *color_table, int npixels)
828 Pixel pixels[256];
829 int i,n=0;
831 if (npixels > 0)
833 for(i = 0; i < npixels; i++)
835 if (color_table[i].alloc_count)
837 pixels[n++] = color_table[i].color.pixel;
839 color_table[i].alloc_count = 0;
841 if (n > 0)
843 XFreeColors(Pdpy, Pcmap, pixels, n, 0);
848 /* FIXME: the DirectColor case */
849 static
850 int get_nbr_of_free_colors(int max_check)
852 int check = 1;
853 Pixel Pixels[256];
854 int map_entries = (Pvisual->class == DirectColor)?
855 (1 << Pdepth):Pvisual->map_entries;
856 if (max_check < 1)
857 return 0;
858 if (map_entries > 256)
860 max_check = 256;
862 max_check = (max_check > map_entries) ? map_entries:max_check;
863 while(1)
865 if (XAllocColorCells(
866 Pdpy, Pcmap, False, NULL, 0, Pixels, check))
868 XFreeColors(Pdpy, Pcmap, Pixels, check, 0);
869 check++;
871 else
873 return check-1;
875 if (check > max_check)
877 return check-1;
880 return check-1;
883 static
884 PColor *alloc_color_cube(
885 int nr, int ng, int nb, int ngrey, int grey_bits, Bool do_allocate)
887 int r, g, b, grey, i, start_grey, end_grey;
888 PColor *color_table;
889 XColor color;
890 int size;
892 size = nr*ng*nb + ngrey + (1 << grey_bits)*(grey_bits != 0);
893 if (grey_bits)
895 ngrey = (1 << grey_bits);
897 if (nr > 0 && ngrey > 0)
899 start_grey = 1;
900 end_grey = ngrey - 1;
901 size = size - 2;
903 else
905 start_grey = 0;
906 end_grey = ngrey;
909 color_table = (PColor *)safemalloc((size+1) * sizeof(PColor));
911 i = 0;
913 #if USE_GAMMA_CORECTION
914 #define CG(x) 65535.0 * pow((x)/65535.0,1/COLOR_GAMMA)
915 #define GG(x) 65535.0 * pow((x)/65535.0,1/GREY_GAMMA)
916 #else
917 #define CG(x) x
918 #define GG(x) x
919 #endif
921 if (nr > 0)
923 for (r = 0; r < nr; r++)
925 for (g = 0; g < ng; g++)
927 for (b = 0; b < nb; b++)
929 color.red = CG(r * 65535 / (nr - 1));
930 color.green = CG(g * 65535 / (ng - 1));
931 color.blue = CG(b * 65535 / (nb - 1));
932 if (do_allocate)
934 if (!XAllocColor(Pdpy, Pcmap,
935 &color))
937 free_table_colors(
938 color_table, i);
939 free(color_table);
940 return NULL;
942 color_table[i].color.pixel =
943 color.pixel;
944 color_table[i].alloc_count = 1;
946 else
948 color_table[i].alloc_count = 0;
950 color_table[i].color.red = color.red;
951 color_table[i].color.green = color.green;
952 color_table[i].color.blue = color.blue;
953 i++;
959 if (ngrey > 0)
961 for (grey = start_grey; grey < end_grey; grey++)
963 color.red = color.green = color.blue =
964 GG(grey * 65535 / (ngrey - 1));
965 if (do_allocate)
967 if (!XAllocColor(Pdpy, Pcmap, &color))
969 free_table_colors(color_table, i);
970 free(color_table);
971 return NULL;
973 color_table[i].color.pixel = color.pixel;
974 color_table[i].alloc_count = 1;
976 else
978 color_table[i].alloc_count = 0;
980 color_table[i].color.red = color.red;
981 color_table[i].color.green = color.green;
982 color_table[i].color.blue = color.blue;
983 i++;
986 color_table[size].color.red = color_table[size-1].color.red;
987 color_table[size].color.green = color_table[size-1].color.green;
988 color_table[size].color.blue = color_table[size-1].color.blue;
989 color_table[size].color.pixel = color_table[size-1].color.pixel;
990 color_table[size].alloc_count = 0;
991 PColorLimit = size;
992 return color_table;
996 static
997 PColor *alloc_named_ct(int *limit, Bool do_allocate)
1000 /* First thing in base array are colors probably already in the color map
1001 because they have familiar names.
1002 I pasted them into a xpm and spread them out so that similar colors are
1003 spread out.
1004 Toward the end are some colors to fill in the gaps.
1005 Currently 61 colors in this list.
1007 char *color_names[] =
1009 "black",
1010 "white",
1011 "grey",
1012 "green",
1013 "blue",
1014 "red",
1015 "cyan",
1016 "yellow",
1017 "magenta",
1018 "DodgerBlue",
1019 "SteelBlue",
1020 "chartreuse",
1021 "wheat",
1022 "turquoise",
1023 "CadetBlue",
1024 "gray87",
1025 "CornflowerBlue",
1026 "YellowGreen",
1027 "NavyBlue",
1028 "MediumBlue",
1029 "plum",
1030 "aquamarine",
1031 "orchid",
1032 "ForestGreen",
1033 "lightyellow",
1034 "brown",
1035 "orange",
1036 "red3",
1037 "HotPink",
1038 "LightBlue",
1039 "gray47",
1040 "pink",
1041 "red4",
1042 "violet",
1043 "purple",
1044 "gray63",
1045 "gray94",
1046 "plum1",
1047 "PeachPuff",
1048 "maroon",
1049 "lavender",
1050 "salmon", /* for peachpuff, orange gap */
1051 "blue4", /* for navyblue/mediumblue gap */
1052 "PaleGreen4", /* for forestgreen, yellowgreen gap */
1053 "#AA7700", /* brick, no close named color */
1054 "#11EE88", /* light green, no close named color */
1055 "#884466", /* dark brown, no close named color */
1056 "#CC8888", /* light brick, no close named color */
1057 "#EECC44", /* gold, no close named color */
1058 "#AAAA44", /* dull green, no close named color */
1059 "#FF1188", /* pinkish red */
1060 "#992299", /* purple */
1061 "#CCFFAA", /* light green */
1062 "#664400", /* dark brown*/
1063 "#AADD99", /* light green */
1064 "#66CCFF", /* light blue */
1065 "#CC2299", /* dark red */
1066 "#FF11CC", /* bright pink */
1067 "#11CC99", /* grey/green */
1068 "#AA77AA", /* purple/red */
1069 "#EEBB77" /* orange/yellow */
1071 int NColors = sizeof(color_names)/sizeof(char *);
1072 int i,rc;
1073 PColor *color_table;
1074 XColor color;
1076 *limit = (*limit > NColors)? NColors: *limit;
1077 color_table = (PColor *)safemalloc((*limit+1) * sizeof(PColor));
1078 for(i=0; i<*limit; i++)
1080 rc=XParseColor(Pdpy, Pcmap, color_names[i], &color);
1081 if (rc==0) {
1082 fprintf(stderr,"color_to_rgb: can't parse color %s,"
1083 " rc %d\n", color_names[i], rc);
1084 free_table_colors(color_table, i);
1085 free(color_table);
1086 return NULL;
1088 if (do_allocate)
1090 if (!XAllocColor(Pdpy, Pcmap, &color))
1092 free_table_colors(color_table, i);
1093 free(color_table);
1094 return NULL;
1096 color_table[i].color.pixel = color.pixel;
1097 color_table[i].alloc_count = 1;
1099 else
1101 color_table[i].alloc_count = 0;
1103 color_table[i].color.red = color.red;
1104 color_table[i].color.green = color.green;
1105 color_table[i].color.blue = color.blue;
1107 color_table[*limit].color.red = color_table[*limit-1].color.red;
1108 color_table[*limit].color.green = color_table[*limit-1].color.green;
1109 color_table[*limit].color.blue = color_table[*limit-1].color.blue;
1110 color_table[*limit].color.pixel = color_table[*limit-1].color.pixel;
1111 color_table[*limit].alloc_count = 0;
1112 PColorLimit = *limit;
1113 return color_table;
1116 static
1117 void create_mapping_table(
1118 int nr, int ng, int nb, int ngrey, int grey_bits,
1119 Bool non_regular_pallet)
1122 Pcsi.grey_bits = 0;
1124 /* initialize dithering colors numbers */
1125 if (!non_regular_pallet)
1127 /* */
1128 Pcsi.d_nr = nr;
1129 Pcsi.d_ng = ng;
1130 Pcsi.d_nb = nb;
1131 Pcsi.d_ngrey_bits = 2;
1132 while((1<<Pcsi.d_ngrey_bits) < ngrey)
1134 Pcsi.d_ngrey_bits++;
1136 if (1<<Pcsi.d_ngrey_bits != ngrey)
1138 Pcsi.d_ngrey_bits = 0;
1140 Pcsi.grey_bits = grey_bits;
1142 else
1144 /* dither table should be small */
1145 Pcsi.grey_bits = 0;
1146 if (PColorLimit <= 9)
1148 Pcsi.d_nr = 3;
1149 Pcsi.d_ng = 3;
1150 Pcsi.d_nb = 3;
1151 Pcsi.d_ngrey_bits = 0;
1153 else if (PColorLimit <= 64)
1155 Pcsi.d_nr = 4;
1156 Pcsi.d_ng = 4;
1157 Pcsi.d_nb = 4;
1158 Pcsi.d_ngrey_bits = 0;
1160 else
1162 Pcsi.d_nr = 8;
1163 Pcsi.d_ng = 8;
1164 Pcsi.d_nb = 8;
1165 Pcsi.d_ngrey_bits = 0;
1167 PDitherMappingTable = build_mapping_table(
1168 Pcsi.d_nr, Pcsi.d_ng, Pcsi.d_nb, non_regular_pallet);
1171 /* initialize colors number fo index computation */
1172 if (PColorLimit == 2)
1174 /* ok */
1175 Pcsi.nr = 0;
1176 Pcsi.ng = 0;
1177 Pcsi.nb = 0;
1178 Pcsi.ngrey = 0;
1179 Pcsi.grey_bits = 1;
1181 else if (grey_bits > 0)
1183 Pcsi.nr = 0;
1184 Pcsi.ng = 0;
1185 Pcsi.nb = 0;
1186 Pcsi.ngrey = 0;
1187 Pcsi.grey_bits = grey_bits;
1189 else if (non_regular_pallet || (0&&ngrey>0))
1191 /* note: using these table with !used_named && ngrey>0 will
1192 * probably leads to faster image loading. But I see nothing
1193 * of significative. On the others hands not using it gives
1194 * maybe better colors approximation. */
1195 if (PColorLimit <= 9)
1197 Pcsi.nr = 8;
1198 Pcsi.ng = 8;
1199 Pcsi.nb = 8;
1200 Pcsi.ngrey = 0;
1202 else
1204 Pcsi.nr = 16;
1205 Pcsi.ng = 16;
1206 Pcsi.nb = 16;
1207 Pcsi.ngrey = 0;
1209 PMappingTable = build_mapping_table(
1210 Pcsi.nr, Pcsi.ng, Pcsi.nb, non_regular_pallet);
1212 else
1214 Pcsi.nr = nr;
1215 Pcsi.ng = ng;
1216 Pcsi.nb = nb;
1217 Pcsi.ngrey = ngrey;
1218 Pcsi.grey_bits = 0;
1222 static void finish_ct_init(
1223 int call_type, int ctt, int nr, int ng, int nb, int ngrey,
1224 int grey_bits, Bool use_named)
1226 if (call_type == PICTURE_CALLED_BY_FVWM)
1228 char *env;
1230 if (PAllocTable)
1232 ctt = PICTURE_PAllocTable + ctt;
1234 if (PUseDynamicColors)
1236 ctt = PICTURE_PUseDynamicColors + ctt;
1238 if (PStrictColorLimit)
1240 ctt = PICTURE_PStrictColorLimit + ctt;
1242 if (use_named)
1244 ctt = PICTURE_use_named + ctt;
1246 else
1248 ctt++;
1250 env = safemalloc(PICTURE_TABLETYPE_LENGHT + 1);
1251 sprintf(env, "%i", ctt);
1252 flib_putenv("FVWM_COLORTABLE_TYPE", env);
1253 free(env);
1254 if (Pdepth <= 8)
1256 Pac = (PColor *)safecalloc(
1257 (1 << Pdepth), sizeof(PColor));
1261 if (Pct)
1263 if (!PAllocTable && call_type == PICTURE_CALLED_BY_FVWM)
1265 free_table_colors(Pct, PColorLimit);
1267 create_mapping_table(nr,ng,nb,ngrey,grey_bits,use_named);
1271 #define PA_COLOR_CUBE (1 << 1)
1272 #define FVWM_COLOR_CUBE (1 << 2)
1273 #define PA_GRAY_SCALE (1 << 3)
1274 #define FVWM_GRAY_SCALE (1 << 4)
1275 #define ANY_COLOR_CUBE (PA_COLOR_CUBE|FVWM_COLOR_CUBE)
1276 #define ANY_GRAY_SCALE (PA_GRAY_SCALE|FVWM_GRAY_SCALE)
1278 static
1279 int PictureAllocColorTable(
1280 PictureColorLimitOption *opt, int call_type, Bool use_my_color_limit)
1282 char *envp;
1283 int free_colors, nbr_of_color, limit, cc_nbr, i, size;
1284 int use_named_table = 0;
1285 int do_allocate = 0;
1286 int use_default = 1;
1287 int private_cmap = !(Pdefault);
1288 int dyn_cl_set = False;
1289 int strict_cl_set = False;
1290 int alloc_table_set = False;
1291 int color_limit;
1292 int pa_type = (Pvisual->class != GrayScale) ?
1293 PA_COLOR_CUBE : PA_GRAY_SCALE;
1294 int fvwm_type = (Pvisual->class != GrayScale) ?
1295 FVWM_COLOR_CUBE : FVWM_GRAY_SCALE;
1296 int cc[][6] =
1298 /* {nr,ng,nb,ngrey,grey_bits,logic} */
1299 /* 5 first for direct colors and Pdepth > 8*/
1300 /* 8192 colors depth 13, a reasonable max for a color table */
1301 {16, 32, 16, 0, 0, FVWM_COLOR_CUBE},
1302 /* 4096 colors depth 12 */
1303 {16, 16, 16, 0, 0, FVWM_COLOR_CUBE},
1304 /* 1024 colors depth 10 */
1305 {8, 16, 8, 0, 0, FVWM_COLOR_CUBE},
1306 /* 512 colors depth 9 */
1307 {8, 8, 8, 0, 0, FVWM_COLOR_CUBE},
1308 /* 256 colors 3/3/2 standard colormap */
1309 {8, 8, 4, 0, 0, FVWM_COLOR_CUBE},
1310 /* 256 grey scale */
1311 {0, 0, 0, 0, 8, ANY_GRAY_SCALE},
1312 /* 244 Xrender XFree-4.2 */
1313 {6, 6, 6, 30, 0, ANY_COLOR_CUBE},
1314 /* 216 Xrender XFree-4.2,GTK/QT "default cc" */
1315 {6, 6, 6, 0, 0, ANY_COLOR_CUBE},
1316 /* 180 (GTK) */
1317 {6, 6, 5, 0, 0, ANY_COLOR_CUBE},
1318 /* 144 (GTK) */
1319 {6, 6, 4, 0, 0, ANY_COLOR_CUBE},
1320 /* 128 grey scale */
1321 {0, 0, 0, 0, 7, ANY_GRAY_SCALE},
1322 /* 125 GTK mini default cc (may change? 444) */
1323 {5, 5, 5, 0, 0, ANY_COLOR_CUBE},
1324 /* 100 (GTK with color limit) */
1325 {5, 5, 4, 0, 0, ANY_COLOR_CUBE},
1326 /* 85 Xrender XFree-4.3 */
1327 {4, 4, 4, 23, 0, ANY_COLOR_CUBE},
1328 /* 78 (in fact 76) a good default ??*/
1329 {4, 4, 4, 16, 0, FVWM_COLOR_CUBE},
1330 /* 70 a good default ?? */
1331 {4, 4, 4, 8, 0, ANY_COLOR_CUBE},
1332 /* 68 a good default ?? */
1333 {4, 4, 4, 6, 0, ANY_COLOR_CUBE},
1334 /* 64 Xrender XFree-4.3 (GTK wcl) */
1335 {4, 4, 4, 0, 0, ANY_COLOR_CUBE},
1336 /* 64 grey scale */
1337 {0, 0, 0, 0, 6, ANY_GRAY_SCALE},
1338 /* 54, maybe a good default? */
1339 {4, 4, 3, 8, 0, FVWM_COLOR_CUBE},
1340 /* 48, (GTK wcl) no grey but ok */
1341 {4, 4, 3, 0, 0, FVWM_COLOR_CUBE},
1342 /* 32, 2/2/1 standard colormap */
1343 {4, 4, 2, 0, 0, FVWM_COLOR_CUBE},
1344 /* 32 xrender xfree-4.2 */
1345 {0, 0, 0, 0, 6, ANY_GRAY_SCALE},
1346 /* 29 */
1347 {3, 3, 3, 4, 0, FVWM_COLOR_CUBE},
1348 /* 27 (xrender in depth 6&7(hypo) GTK wcl) */
1349 {3, 3, 3, 0, 0, FVWM_COLOR_CUBE|PA_COLOR_CUBE*(Pdepth<8)},
1350 /* 16 grey scale */
1351 {0, 0, 0, 0, 4, FVWM_GRAY_SCALE},
1352 /* 10 */
1353 {2, 2, 2, 4, 0, FVWM_COLOR_CUBE},
1354 /* 8 (xrender/qt/gtk wcl) */
1355 {2, 2, 2, 0, 0, FVWM_COLOR_CUBE},
1356 /* 8 grey scale Xrender depth 4 and XFree-4.3 */
1357 {0, 0, 0, 0, 3, FVWM_GRAY_SCALE|PA_GRAY_SCALE*(Pdepth<5)},
1358 /* 4 grey scale*/
1359 {0, 0, 0, 0, 2,
1360 FVWM_GRAY_SCALE|FVWM_COLOR_CUBE|PA_COLOR_CUBE*(Pdepth<4)},
1361 /* 2 */
1362 {0, 0, 0, 0, 1, FVWM_COLOR_CUBE|FVWM_GRAY_SCALE}
1365 cc_nbr = sizeof(cc)/(sizeof(cc[0]));
1367 /* set up default */
1368 PStrictColorLimit = 0;
1369 PUseDynamicColors = 1;
1370 PAllocTable = 0;
1371 use_named_table = False;
1372 color_limit = 0;
1373 use_default = True;
1375 /* use fvwm color limit */
1376 if (!use_my_color_limit &&
1377 (envp = getenv("FVWM_COLORTABLE_TYPE")) != NULL)
1379 int nr = 0, ng = 0, nb = 0, grey_bits = 0, ngrey = 0;
1380 int ctt = atoi(envp);
1382 if (ctt >= PICTURE_PAllocTable)
1384 ctt -= PICTURE_PAllocTable;
1385 PAllocTable = 1; /* not useful for a module !*/
1387 if (ctt >= PICTURE_PUseDynamicColors)
1389 PUseDynamicColors = 1;
1390 ctt -= PICTURE_PUseDynamicColors;
1392 if (ctt >= PICTURE_PStrictColorLimit)
1394 PStrictColorLimit = 1;
1395 ctt -= PICTURE_PStrictColorLimit;
1397 if (ctt >= PICTURE_use_named)
1399 ctt -= PICTURE_use_named;
1400 Pct = alloc_named_ct(&ctt, False);
1401 use_named_table = True;
1403 else if (ctt == 0)
1405 /* depth <= 8 and no colors limit ! */
1406 PColorLimit = 0;
1407 return 0;
1409 else if (ctt <= cc_nbr)
1411 ctt--;
1412 Pct = alloc_color_cube(
1413 cc[ctt][0], cc[ctt][1], cc[ctt][2], cc[ctt][3],
1414 cc[ctt][4],
1415 False);
1416 nr = cc[ctt][0];
1417 ng = cc[ctt][1];
1418 nb = cc[ctt][2];
1419 ngrey = cc[ctt][3];
1420 grey_bits = cc[ctt][4];
1422 if (Pct != NULL)
1424 /* should always happen */
1425 finish_ct_init(
1426 call_type, ctt, nr, ng, nb, ngrey, grey_bits,
1427 use_named_table);
1428 return PColorLimit;
1432 nbr_of_color = (1 << Pdepth);
1433 color_limit = 0;
1435 /* parse the color limit env variable */
1436 if ((envp = getenv("FVWM_COLORLIMIT")) != NULL)
1438 char *rest, *l;
1440 rest = GetQuotedString(envp, &l, ":", NULL, NULL, NULL);
1441 if (l && *l != '\0' && (color_limit = atoi(l)) >= 0)
1443 use_default = 0;
1445 if (l != NULL)
1447 free(l);
1449 if (color_limit == 9 || color_limit == 61)
1451 use_named_table = 1;
1453 if (rest && *rest != '\0')
1455 if (rest[0] == '1')
1457 strict_cl_set = True;
1458 PStrictColorLimit = 1;
1460 else
1462 strict_cl_set = True;
1463 PStrictColorLimit = 0;
1465 if (strlen(rest) > 1 && rest[1] == '1')
1467 use_named_table = 1;
1469 else
1471 use_named_table = 0;
1473 if (strlen(rest) > 2 && rest[2] == '1')
1475 dyn_cl_set = True;
1476 PUseDynamicColors = 1;
1478 else
1480 dyn_cl_set = True;
1481 PUseDynamicColors = 0;
1483 if (strlen(rest) > 3 && rest[3] == '1')
1485 alloc_table_set = True;
1486 PAllocTable = 1;
1488 else
1490 alloc_table_set = True;
1491 PAllocTable = 0;
1495 else if (opt != NULL) /* use the option */
1497 if (opt->color_limit > 0)
1499 use_default = 0;
1500 color_limit = opt->color_limit;
1502 if (color_limit == 9 || color_limit == 61)
1504 use_named_table = 1;
1506 if (opt->strict > 0)
1508 strict_cl_set = True;
1509 PStrictColorLimit = 1;
1511 else if (opt->strict == 0)
1513 strict_cl_set = True;
1514 PStrictColorLimit = 0;
1516 if (opt->use_named_table > 0)
1518 use_named_table = 1;
1520 else if (opt->use_named_table == 0)
1522 use_named_table = 0;
1524 if (opt->not_dynamic > 0)
1526 dyn_cl_set = True;
1527 PUseDynamicColors = 0;
1529 else if (opt->not_dynamic == 0)
1531 dyn_cl_set = True;
1532 PUseDynamicColors = 0;
1534 if (opt->allocate > 0)
1536 alloc_table_set = True;
1537 PAllocTable = 1;
1539 else if (opt->allocate == 0)
1541 alloc_table_set = True;
1542 PAllocTable = 0;
1546 if (color_limit <= 0)
1548 use_default = 1;
1549 color_limit = nbr_of_color;
1552 /* first try to see if we have a "pre-allocated" color cube.
1553 * The bultin RENDER X extension pre-allocate a color cube plus
1554 * some grey's (xc/programs/Xserver/render/miindex)
1555 * See gdk/gdkrgb.c for the cubes used by gtk+-2, 666 is the default,
1556 * 555 is the minimal cc (this may change): if gtk cannot allocate
1557 * the 555 cc (or better) a private cmap is used.
1558 * for qt-3: see src/kernel/{qapplication.cpp,qimage.cpp,qcolor_x11.c}
1559 * the 666 cube is used by default (with approx in the cmap if some
1560 * color allocation fail), and some qt app may accept an
1561 * --ncols option to limit the nbr of colors, then some "2:3:1"
1562 * proportions color cube are used (222, 232, ..., 252, 342, ..., 362,
1563 * 452, ...,693, ...)
1564 * imlib2 try to allocate the 666 cube if this fail it try more
1565 * exotic table (see rend.c and rgba.c) */
1566 i = 0;
1567 free_colors = 0;
1568 if (Pdepth <= 8 && !private_cmap && use_default &&
1569 i < cc_nbr && Pct == NULL && (Pvisual->class & 1))
1571 free_colors = get_nbr_of_free_colors(nbr_of_color);
1573 while(Pdepth <= 8 && !private_cmap && use_default &&
1574 i < cc_nbr && Pct == NULL && (Pvisual->class & 1))
1576 size = cc[i][0]*cc[i][1]*cc[i][2] + cc[i][3] -
1577 2*(cc[i][3] > 0) + (1 << cc[i][4])*(cc[i][4] != 0);
1578 if (size > nbr_of_color || !(cc[i][5] & pa_type))
1580 i++;
1581 continue;
1583 if (free_colors <= nbr_of_color - size)
1585 Pct = alloc_color_cube(
1586 cc[i][0], cc[i][1], cc[i][2], cc[i][3],
1587 cc[i][4], True);
1589 if (Pct != NULL)
1591 if (free_colors <=
1592 get_nbr_of_free_colors(nbr_of_color))
1594 /* done */
1596 else
1598 free_table_colors(Pct, PColorLimit);
1599 free(Pct);
1600 Pct = NULL;
1603 i++;
1605 if (Pct != NULL)
1607 PUseDynamicColors = 0;
1608 PAllocTable = 1;
1609 Pcsi.pre_allocated_pallet = 1;
1610 i = i - 1;
1611 finish_ct_init(
1612 call_type, i, cc[i][0], cc[i][1], cc[i][2], cc[i][3],
1613 cc[i][4], 0);
1614 return PColorLimit;
1618 * now use "our" table
1621 limit = (color_limit >= nbr_of_color)? nbr_of_color:color_limit;
1623 if (use_default && !private_cmap)
1625 /* XRender cvs default: */
1626 #if 0
1627 if (limit > 100)
1628 limit = nbr_of_color/3;
1629 else
1630 limit = nbr_of_color/2;
1631 /* depth 8: 85 */
1632 /* depth 4: 8 */
1633 #endif
1634 if (limit > 256)
1636 /* direct colors & Pdepth > 8 */
1637 if (Pdepth >= 16)
1639 limit = 8192;
1641 else if (Pdepth >= 15)
1643 limit = 4096;
1645 else
1647 limit = 512;
1650 else if (limit == 256)
1652 if (Pvisual->class == GrayScale)
1654 limit = 64;
1656 else if (Pvisual->class == DirectColor)
1658 limit = 32;
1660 else
1662 limit = 68;
1663 /* candidate:
1664 * limit = 54; 4x4x3 + 6 grey
1665 * limit = 61 (named table)
1666 * limit = 85 current XRender default 4cc + 21
1667 * limit = 76 future(?) XRender default 4cc + 16
1668 * limit = 68 4x4x4 + 4
1669 * limit = 64 4x4x4 + 0 */
1673 else if (limit == 128 || limit == 64)
1675 if (Pvisual->class == GrayScale)
1677 limit = 32;
1679 else
1681 limit = 31;
1684 else if (limit >= 16)
1686 if (Pvisual->class == GrayScale)
1688 limit = 8;
1690 else
1692 limit = 10;
1695 else if (limit >= 8)
1697 limit = 4;
1699 else
1701 limit = 2;
1704 if (limit < 2)
1706 limit = 2;
1709 if (Pvisual->class == DirectColor)
1711 /* humm ... Any way this case should never happen in real life:
1712 * DirectColor default colormap! */
1713 PUseDynamicColors = 0;
1714 PAllocTable = 1;
1715 PStrictColorLimit = 1;
1717 if (PAllocTable)
1719 do_allocate = 1;
1721 else
1723 do_allocate = 0;
1726 /* use the named table ? */
1727 if (use_named_table)
1729 i = limit;
1730 while(Pct == NULL && i >= 2)
1732 Pct = alloc_named_ct(&i, do_allocate);
1733 i--;
1736 if (Pct != NULL)
1738 finish_ct_init(
1739 call_type, PColorLimit, 0, 0, 0, 0, 0, 1);
1740 return PColorLimit;
1743 /* color cube or regular grey scale */
1744 i = 0;
1745 while(i < cc_nbr && Pct == NULL)
1747 if ((cc[i][5] & fvwm_type) &&
1748 cc[i][0]*cc[i][1]*cc[i][2] + cc[i][3] - 2*(cc[i][3] > 0) +
1749 (1 << cc[i][4])*(cc[i][4] != 0) <= limit)
1751 Pct = alloc_color_cube(
1752 cc[i][0], cc[i][1], cc[i][2], cc[i][3], cc[i][4],
1753 do_allocate);
1755 i++;
1757 if (Pct != NULL)
1759 i = i-1;
1760 finish_ct_init(
1761 call_type, i, cc[i][0], cc[i][1], cc[i][2], cc[i][3],
1762 cc[i][4], 0);
1763 return PColorLimit;
1766 /* I do not think we can be here */
1767 Pct = alloc_color_cube(0, 0, 0, 0, 1, False);
1768 finish_ct_init(call_type, cc_nbr-1, 0, 0, 0, 0, 1, 0);
1769 if (Pct == NULL)
1771 fprintf(stderr,
1772 "[FVWM] ERR -- Cannot get Black and White. exiting!\n");
1773 exit(2);
1775 return PColorLimit;
1779 * Allocation of a private DirectColor cmap this is broken for depth > 16
1781 static
1782 Bool alloc_direct_colors(int *limit, Bool use_my_color_limit)
1784 unsigned long nr,ng,nb,r,g,b,cr,cg,cf,pr,pg;
1785 unsigned long red_mask, green_mask, blue_mask;
1786 XColor *colors;
1788 if (Pdepth <= 16)
1790 red_mask = Pvisual->red_mask;
1791 green_mask = Pvisual->green_mask;
1792 blue_mask = Pvisual->blue_mask;
1794 else
1796 /* Use a standard depth 16 colormap. This is broken FIXME! */
1797 red_mask = 0xf800;
1798 green_mask = 0x7e0;
1799 blue_mask = 0x1f;
1802 decompose_mask(
1803 red_mask, &Pcsi.red_shift, &Pcsi.red_prec);
1804 decompose_mask(
1805 green_mask, &Pcsi.green_shift, &Pcsi.green_prec);
1806 decompose_mask(
1807 blue_mask, &Pcsi.blue_shift, &Pcsi.blue_prec);
1809 if (!use_my_color_limit)
1811 /* colors allocated by fvwm we can return */
1812 return 1;
1815 nr = 1 << Pcsi.red_prec;
1816 ng = 1 << Pcsi.green_prec;
1817 nb = 1 << Pcsi.blue_prec;
1819 colors = (XColor *)safemalloc(nb*sizeof(XColor));
1820 cf = DoRed|DoBlue|DoGreen;
1821 for (r=0; r<nr; r++)
1823 cr = r * 65535 / (nr - 1);
1824 pr = (cr >> (16 - Pcsi.red_prec)) << Pcsi.red_shift;
1825 for (g = 0; g < ng; g++)
1827 cg = g * 65535 / (ng - 1);
1828 pg = (cg >> (16 - Pcsi.green_prec)) << Pcsi.green_shift;
1829 for (b = 0; b < nb; b++)
1831 colors[b].flags = cf;
1832 colors[b].red = cr;
1833 colors[b].green = cg;
1834 colors[b].blue = b * 65535 / (nb - 1);
1835 colors[b].pixel =
1836 (Pixel)(pr + pg +
1837 ((colors[b].blue >>
1838 (16 - Pcsi.blue_prec)) <<
1839 Pcsi.blue_shift));
1841 XStoreColors(Pdpy, Pcmap, colors, nb);
1844 free(colors);
1845 return 1;
1849 * Init the table for Static Colors
1851 static
1852 void init_static_colors_table(void)
1854 XColor colors[256];
1855 int i;
1856 int nbr_of_colors = min(256, (1 << Pdepth));
1858 PColorLimit = nbr_of_colors;
1859 Pct = (PColor *)safemalloc((nbr_of_colors+1) * sizeof(PColor));
1860 for (i = 0; i < nbr_of_colors; i++)
1862 colors[i].pixel = Pct[i].color.pixel = i;
1864 XQueryColors(Pdpy, Pcmap, colors, nbr_of_colors);
1865 for (i = 0; i < nbr_of_colors; i++)
1867 Pct[i].color.red = colors[i].red;
1868 Pct[i].color.green = colors[i].green;
1869 Pct[i].color.blue = colors[i].blue;
1870 Pct[i].alloc_count = 1;
1872 Pct[PColorLimit].color.red = Pct[PColorLimit-1].color.red;
1873 Pct[PColorLimit].color.green = Pct[PColorLimit-1].color.green;
1874 Pct[PColorLimit].color.blue = Pct[PColorLimit-1].color.blue;
1875 Pct[PColorLimit].alloc_count = 1;
1876 create_mapping_table(0, 0, 0, 0, 0, True);
1881 * misc local functions
1883 static
1884 void print_colormap(Colormap cmap)
1886 XColor colors[256];
1887 int i;
1888 int nbr_of_colors = max(256, (1 << Pdepth));
1889 for (i = 0; i < nbr_of_colors; i++)
1891 colors[i].pixel = i;
1893 XQueryColors(Pdpy, cmap, colors, nbr_of_colors);
1894 for (i = 0; i < nbr_of_colors; i++)
1896 fprintf(stderr," rgb(%.3i): %.3i/%.3i/%.3i\n", i,
1897 colors[i].red >> 8,
1898 colors[i].green >> 8,
1899 colors[i].blue >> 8);
1903 /* ---------------------------- interface functions ------------------------ */
1905 int PictureAllocColor(Display *dpy, Colormap cmap, XColor *c, int no_limit)
1907 if (PStrictColorLimit && Pct != NULL)
1909 no_limit = 0;
1912 if (no_limit)
1914 return Pcsi.alloc_color_no_limit(dpy, cmap, c);
1916 else
1918 return Pcsi.alloc_color(dpy, cmap, c);
1920 return 0;
1924 int PictureAllocColorAllProp(
1925 Display *dpy, Colormap cmap, XColor *c, int x, int y,
1926 Bool no_limit, Bool is_8, Bool do_dither)
1929 if (!no_limit && do_dither && Pcsi.alloc_color_dither != NULL)
1931 if (!is_8)
1933 c->red = c->red >> 8;
1934 c->green = c->green >> 8;
1935 c->blue = c->blue >> 8;
1937 return Pcsi.alloc_color_dither(dpy, cmap, c, x, y);
1939 else
1941 if (is_8)
1943 c->red = c->red << 8;
1944 c->green = c->green << 8;
1945 c->blue = c->blue << 8;
1947 return PictureAllocColor(dpy, cmap, c, False);
1949 return 0;
1952 int PictureAllocColorImage(
1953 Display *dpy, PictureImageColorAllocator *pica, XColor *c, int x, int y)
1955 int r;
1957 r = PictureAllocColorAllProp(
1958 dpy, pica->cmap, c, x, y,
1959 pica->no_limit, pica->is_8, pica->dither);
1960 if (r && pica->pixels_table != NULL && pica->pixels_table_size &&
1961 c->pixel < pica->pixels_table_size)
1963 pica->pixels_table[c->pixel]++;
1965 return r;
1968 PictureImageColorAllocator *PictureOpenImageColorAllocator(
1969 Display *dpy, Colormap cmap, int x, int y, Bool no_limit,
1970 Bool do_not_save_pixels, int dither, Bool is_8)
1972 PictureImageColorAllocator *pica;
1973 Bool do_save_pixels = False;
1975 pica = (PictureImageColorAllocator *)safemalloc(
1976 sizeof(PictureImageColorAllocator));
1977 if (Pdepth <= 8 && !do_not_save_pixels && (Pvisual->class & 1) &&
1978 ((PUseDynamicColors && Pct) || no_limit))
1980 int s = 1 << Pdepth;
1981 pica->pixels_table = (unsigned long *)safecalloc(
1982 s, sizeof(unsigned long));
1983 pica->pixels_table_size = s;
1984 do_save_pixels = True;
1986 if (!do_save_pixels)
1988 pica->pixels_table = NULL;
1989 pica->pixels_table_size = 0;
1991 pica->is_8 = is_8;
1992 if (dither && Pdepth <= 16)
1994 pica->dither = dither;
1996 else
1998 pica->dither = dither;
2000 pica->no_limit = no_limit;
2001 pica->cmap = cmap;
2002 return pica;
2005 void PictureCloseImageColorAllocator(
2006 Display *dpy, PictureImageColorAllocator *pica,
2007 int *nalloc_pixels, Pixel **alloc_pixels, Bool *no_limit)
2009 if (nalloc_pixels)
2011 *nalloc_pixels = 0;
2013 if (alloc_pixels != NULL)
2015 *alloc_pixels = NULL;
2017 if (no_limit != NULL)
2019 *no_limit = 0;
2021 if (pica->pixels_table)
2023 int i,j;
2024 int k = 0, l = 0;
2025 unsigned int np = 0;
2026 int free_num = 0;
2027 Pixel *free_pixels = NULL;
2028 Pixel *save_pixels = NULL;
2030 for(i = 0; i < pica->pixels_table_size; i++)
2032 if (pica->pixels_table[i])
2034 free_num += (pica->pixels_table[i]-1);
2035 np++;
2038 if (free_num)
2040 free_pixels = (Pixel *)safemalloc(
2041 free_num * sizeof(Pixel));
2043 if (np && nalloc_pixels != NULL && alloc_pixels != NULL)
2045 save_pixels = (Pixel *)safemalloc(np * sizeof(Pixel));
2047 for(i = 0; i < pica->pixels_table_size; i++)
2049 if (pica->pixels_table[i])
2051 if (save_pixels)
2053 save_pixels[k++] = i;
2055 for(j=1; j < pica->pixels_table[i]; j++)
2057 free_pixels[l++] = i;
2061 if (free_num)
2063 PictureFreeColors(
2064 dpy, pica->cmap, free_pixels, free_num, 0,
2065 pica->no_limit);
2066 free(free_pixels);
2068 if (nalloc_pixels != NULL && alloc_pixels != NULL)
2070 *nalloc_pixels = np;
2071 *alloc_pixels = save_pixels;
2072 if (no_limit != NULL)
2074 *no_limit = pica->no_limit;
2077 else if (save_pixels)
2079 free(save_pixels);
2081 free(pica->pixels_table);
2083 free(pica);
2084 return;
2087 void PictureFreeColors(
2088 Display *dpy, Colormap cmap, Pixel *pixels, int n,
2089 unsigned long planes, Bool no_limit)
2091 if (no_limit)
2093 if (Pcsi.free_colors_no_limit != NULL)
2095 Pcsi.free_colors_no_limit(
2096 dpy, cmap, pixels, n, planes);
2099 else
2101 if (Pcsi.free_colors != NULL)
2103 Pcsi.free_colors(dpy, cmap, pixels, n, planes);
2106 return;
2109 Pixel PictureGetNextColor(Pixel p, int n)
2111 int i;
2112 XColor c;
2114 if (n >= 0)
2115 n = 1;
2116 else
2117 n = -1;
2119 if (Pct == NULL)
2121 return p;
2123 for(i=0; i<PColorLimit; i++)
2125 if (Pct[i].color.pixel == p)
2127 if (i == 0 && n < 0)
2129 c = Pct[PColorLimit-1].color;
2130 alloc_color_in_pct(&c, PColorLimit-1);
2131 return Pct[PColorLimit-1].color.pixel;
2133 else if (i == PColorLimit-1 && n > 0)
2135 c = Pct[0].color;
2136 alloc_color_in_pct(&c, 0);
2137 return Pct[0].color.pixel;
2139 else
2141 c = Pct[i+n].color;
2142 alloc_color_in_pct(&c, i+n);
2143 return Pct[i+n].color.pixel;
2147 return p;
2150 /* Replace the color in my_color by the closest matching color
2151 from base_table */
2152 void PictureReduceColorName(char **my_color)
2154 int index;
2155 XColor rgb; /* place to calc rgb for each color in xpm */
2157 if (!XpmSupport)
2158 return;
2160 if (!strcasecmp(*my_color,"none")) {
2161 return; /* do not substitute the "none" color */
2164 if (!XParseColor(Pdpy, Pcmap, *my_color, &rgb))
2166 fprintf(stderr,"color_to_rgb: can't parse color %s\n",
2167 *my_color);
2169 index = get_color_index(rgb.red,rgb.green,rgb.blue, False);
2170 /* Finally: replace the color string by the newly determined color
2171 * string */
2172 free(*my_color); /* free old color */
2173 /* area for new color */
2174 *my_color = safemalloc(8);
2175 sprintf(*my_color,"#%x%x%x",
2176 Pct[index].color.red >> 8,
2177 Pct[index].color.green >> 8,
2178 Pct[index].color.blue >> 8); /* put it there */
2179 return;
2182 Bool PictureDitherByDefault(void)
2184 if (Pct != NULL)
2186 return True;
2188 return False;
2191 Bool PictureUseBWOnly(void)
2193 if (Pdepth < 2 || (PStrictColorLimit && PColorLimit == 2))
2195 return True;
2197 return False;
2200 int PictureInitColors(
2201 int call_type, Bool init_color_limit, PictureColorLimitOption *opt,
2202 Bool use_my_color_limit, Bool init_dither)
2204 Bool dither_ok = False;
2206 switch (Pvisual->class)
2208 case DirectColor:
2209 /* direct colors is more or less broken */
2210 decompose_mask(
2211 Pvisual->red_mask, &Pcsi.red_shift,
2212 &Pcsi.red_prec);
2213 decompose_mask(
2214 Pvisual->green_mask, &Pcsi.green_shift,
2215 &Pcsi.green_prec);
2216 decompose_mask(
2217 Pvisual->blue_mask, &Pcsi.blue_shift,
2218 &Pcsi.blue_prec);
2219 Pcsi.alloc_color_no_limit = alloc_color_proportion;
2220 Pcsi.alloc_color = alloc_color_proportion;
2221 Pcsi.alloc_color_dither = alloc_color_proportion_dither;
2222 Pcsi.free_colors_no_limit = NULL;
2223 Pcsi.free_colors = NULL;
2224 PColorLimit = 0;
2225 break;
2226 case TrueColor:
2227 decompose_mask(
2228 Pvisual->red_mask, &Pcsi.red_shift,
2229 &Pcsi.red_prec);
2230 decompose_mask(
2231 Pvisual->green_mask, &Pcsi.green_shift,
2232 &Pcsi.green_prec);
2233 decompose_mask(
2234 Pvisual->blue_mask, &Pcsi.blue_shift,
2235 &Pcsi.blue_prec);
2236 Pcsi.alloc_color_no_limit = alloc_color_proportion;
2237 Pcsi.alloc_color = alloc_color_proportion;
2238 Pcsi.free_colors_no_limit = NULL;
2239 Pcsi.free_colors = NULL;
2240 PColorLimit = 0;
2241 if (init_dither && (Pdepth == 15 || Pdepth == 16))
2243 dither_ok = my_dither_depth_15_16_init();
2245 if (dither_ok)
2247 Pcsi.alloc_color_dither = alloc_color_proportion_dither;
2249 else
2251 Pcsi.alloc_color_dither = NULL;
2253 break;
2254 case StaticColor:
2255 if (0 && Pvisual->red_mask != 0 && Pvisual->green_mask != 0 &&
2256 Pvisual->blue_mask != 0)
2258 decompose_mask(
2259 Pvisual->red_mask, &Pcsi.red_shift,
2260 &Pcsi.red_prec);
2261 decompose_mask(
2262 Pvisual->green_mask, &Pcsi.green_shift,
2263 &Pcsi.green_prec);
2264 decompose_mask(
2265 Pvisual->blue_mask, &Pcsi.blue_shift,
2266 &Pcsi.blue_prec);
2267 Pcsi.alloc_color_no_limit = alloc_color_proportion;
2268 Pcsi.alloc_color = alloc_color_proportion;
2269 PColorLimit = 0;
2271 else
2273 if (init_color_limit)
2275 Pcsi.alloc_color = alloc_color_in_table;
2276 Pcsi.alloc_color_dither =
2277 alloc_color_in_table_dither;
2278 Pcsi.alloc_color_no_limit = alloc_color_x;
2279 init_static_colors_table();
2281 else
2283 Pcsi.alloc_color = alloc_color_x;
2284 Pcsi.alloc_color_dither = NULL;
2285 Pcsi.alloc_color_no_limit = alloc_color_x;
2288 Pcsi.free_colors_no_limit = NULL;
2289 Pcsi.free_colors = NULL;
2290 break;
2291 case StaticGray:
2292 /* FIXME: we assume that we have a regular grey ramp */
2293 if (0)
2295 Pcsi.alloc_color_no_limit = alloc_color_proportion_grey;
2296 Pcsi.alloc_color = alloc_color_proportion;
2297 PColorLimit = 0;
2299 else
2301 if (init_color_limit)
2303 Pcsi.alloc_color = alloc_color_in_table;
2304 Pcsi.alloc_color_dither =
2305 alloc_color_in_table_dither;
2306 Pcsi.alloc_color_no_limit = alloc_color_x;
2307 init_static_colors_table();
2309 else
2311 Pcsi.alloc_color = alloc_color_x;
2312 Pcsi.alloc_color_dither = NULL;
2313 Pcsi.alloc_color_no_limit = alloc_color_x;
2316 Pcsi.free_colors_no_limit = NULL;
2317 Pcsi.free_colors = NULL;
2318 break;
2319 case PseudoColor:
2320 case GrayScale:
2321 default:
2322 Pcsi.alloc_color_no_limit = alloc_color_dynamic_no_limit;
2323 Pcsi.free_colors_no_limit = free_colors_x;
2324 break;
2327 if (!(Pvisual->class & 1))
2329 /* static classes */
2330 PUseDynamicColors = 0;
2331 if (call_type == PICTURE_CALLED_BY_FVWM &&
2332 getenv("FVWM_COLORTABLE_TYPE") != NULL)
2334 flib_putenv("FVWM_COLORTABLE_TYPE", "");
2336 return PColorLimit;
2339 /* dynamic classes */
2341 if (!Pdefault && Pvisual->class == DirectColor)
2343 PColorLimit = 0;
2344 PUseDynamicColors = 0;
2345 alloc_direct_colors(0, use_my_color_limit);
2346 if (call_type == PICTURE_CALLED_BY_FVWM &&
2347 getenv("FVWM_COLORTABLE_TYPE") != NULL)
2349 flib_putenv("FVWM_COLORTABLE_TYPE", "");
2351 return 0;
2355 if (init_color_limit)
2357 Pcsi.alloc_color = alloc_color_in_table;
2358 Pcsi.alloc_color_dither = alloc_color_in_table_dither;
2359 PictureAllocColorTable(opt, call_type, use_my_color_limit);
2360 if (PUseDynamicColors)
2362 Pcsi.free_colors = free_colors_in_table;
2364 else
2366 Pcsi.free_colors = NULL;
2369 else
2371 Pcsi.alloc_color = alloc_color_dynamic_no_limit;
2372 Pcsi.free_colors = free_colors_x;
2373 Pcsi.alloc_color_dither = NULL;
2375 return PColorLimit;
2378 void PicturePrintColorInfo(int verbose)
2380 unsigned long nbr_of_colors = 1 << Pdepth;
2382 fprintf(stderr, "FVWM info on colors\n");
2383 fprintf(stderr, " Visual ID: 0x%x, Default?: %s, Class: ",
2384 (int)(Pvisual->visualid),
2385 (Pdefault)? "Yes":"No");
2386 if (Pvisual->class == TrueColor)
2388 fprintf(stderr,"TrueColor");
2390 else if (Pvisual->class == PseudoColor)
2392 fprintf(stderr,"PseudoColor");
2394 else if (Pvisual->class == DirectColor)
2396 fprintf(stderr,"DirectColor");
2398 else if (Pvisual->class == StaticColor)
2400 fprintf(stderr,"StaticColor");
2402 else if (Pvisual->class == GrayScale)
2404 fprintf(stderr,"GrayScale");
2406 else if (Pvisual->class == StaticGray)
2408 fprintf(stderr,"StaticGray");
2410 fprintf(stderr, "\n");
2411 fprintf(stderr, " Depth: %i, Number of colors: %lu",
2412 Pdepth, (unsigned long)nbr_of_colors);
2413 if (Pct != NULL)
2415 fprintf(stderr,"\n Pallet with %i colors", PColorLimit);
2416 if (Pvisual->class & 1)
2418 fprintf(stderr,", Number of free colors: %i\n",
2419 get_nbr_of_free_colors((1 << Pdepth)));
2420 fprintf(stderr,
2421 " Auto Detected: %s, Strict: %s, Allocated: %s,"
2422 " Dynamic: %s\n",
2423 (Pcsi.pre_allocated_pallet)? "Yes":"No",
2424 (PStrictColorLimit)? "Yes":"No",
2425 (PAllocTable)? "Yes":"No",
2426 (PUseDynamicColors)? "Yes":"No");
2428 else
2430 fprintf(stderr," (default colormap)\n");
2432 if (PColorLimit <= 256)
2434 int i;
2435 int count = 0;
2436 int count_alloc = 0;
2438 if (verbose)
2440 fprintf(stderr," The fvwm colors table:\n");
2442 for (i = 0; i < PColorLimit; i++)
2444 if (verbose)
2446 fprintf(
2447 stderr,
2448 " rgb:%.3i/%.3i/%.3i\t%lu\n",
2449 Pct[i].color.red >> 8,
2450 Pct[i].color.green >> 8,
2451 Pct[i].color.blue >> 8,
2452 Pct[i].alloc_count);
2454 if (Pct[i].alloc_count)
2456 count++;
2459 if ((Pvisual->class & 1) && Pac != NULL)
2461 if (verbose)
2463 fprintf(stderr," fvwm colors not in"
2464 " the table:\n");
2466 for(i=0; i < nbr_of_colors; i++)
2468 int j = 0;
2469 Bool found = False;
2471 if (!Pac[i].alloc_count)
2472 continue;
2473 while(j < PColorLimit && !found)
2475 if (i == Pct[j].color.pixel)
2477 found = True;
2479 j++;
2481 if (found)
2482 continue;
2483 count_alloc++;
2484 if (verbose)
2486 fprintf(
2487 stderr,
2488 " rgb:"
2489 "%.3i/%.3i/%.3i\t%lu\n",
2490 Pac[i].color.red >> 8,
2491 Pac[i].color.green >> 8,
2492 Pac[i].color.blue >> 8,
2493 Pac[i].alloc_count);
2496 if (verbose && count_alloc == 0)
2498 if (verbose)
2500 fprintf(stderr," None\n");
2504 if (Pvisual->class & 1)
2506 fprintf(stderr,
2507 " Number of colours used by fvwm:\n");
2508 fprintf(stderr,
2509 " In the table: %i\n", count);
2510 fprintf(
2511 stderr, " Out of the table: %i\n",
2512 count_alloc);
2513 fprintf(stderr,
2514 " Total: %i\n", count_alloc+count);
2518 else
2520 if (Pvisual->class == DirectColor)
2522 fprintf(stderr, ", Pseudo Pallet with: %i colors\n",
2523 (1 << Pcsi.red_prec)*(1 << Pcsi.green_prec)*
2524 (1 << Pcsi.blue_prec));
2526 else
2528 fprintf(stderr, ", No Pallet (static colors)\n");
2530 fprintf(stderr, " red: %i, green: %i, blue %i\n",
2531 1 << Pcsi.red_prec, 1 << Pcsi.green_prec,
2532 1 << Pcsi.blue_prec);
2533 if (verbose && Pdepth <= 8)
2535 if (Pvisual->class == DirectColor)
2537 fprintf(stderr, " Colormap:\n");
2539 else
2541 fprintf(stderr,
2542 " Static Colormap used by fvwm:\n");
2544 print_colormap(Pcmap);
2548 if (Pdepth <= 8 && verbose >= 2)
2550 fprintf(stderr,"\n Default Colormap:\n");
2551 print_colormap(DefaultColormap(Pdpy,DefaultScreen(Pdpy)));