Apply extremely trivial free() patch to WindowList.
[fvwm.git] / libs / PictureUtils.c
blob8da68fc17e04eeba82070e861bc9f1cae74accbd
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 "Grab.h"
34 #include "Parse.h"
35 #include "ftime.h"
36 #include "PictureBase.h"
37 #include "PictureUtils.h"
38 #include "PictureDitherMatrice.h"
40 /* ---------------------------- local definitions and macro ----------------- */
42 #if 0
43 /* dv: unused */
44 /* form alloc_in_cmap from the xpm lib */
45 #define XPM_DIST(r1,g1,b1,r2,g2,b2) (long)\
46 (3*(abs((long)r1-(long)r2) + \
47 abs((long)g1-(long)g2) + \
48 abs((long)b1-(long)b2)) + \
49 abs((long)r1 + (long)g1 + (long)b1 - \
50 ((long)r2 + (long)g2 + (long)b2)))
51 #define XPM_COLOR_CLOSENESS 40000
52 #endif
54 #define SQUARE(X) ((X)*(X))
56 #define TRUE_DIST(r1,g1,b1,r2,g2,b2) (long)\
57 (SQUARE((long)((r1 - r2)>>8)) \
58 + SQUARE((long)((g1 - g2)>>8)) \
59 + SQUARE((long)((b1 - b2)>>8)))
61 #define FAST_DIST(r1,g1,b1,r2,g2,b2) (long)\
62 (abs((long)(r1 - r2)) \
63 + abs((long)(g1 - g2)) \
64 + abs((long)(b1 - b2)))
66 #define FVWM_DIST(r1,g1,b1,r2,g2,b2) \
67 (abs(r1 - r2) + abs(g1 - g2) + abs(b1 - b2) \
68 + 2*abs(abs(r1-g1) + abs(g1-b1) + abs(r1-b1) \
69 - abs(r2-g2) - abs(g2-b2) - abs(r2-b2)))
71 #define USED_DIST(r1,g1,b1,r2,g2,b2) FVWM_DIST(r1,g1,b1,r2,g2,b2)
73 #define PICTURE_COLOR_CLOSENESS USED_DIST(3,3,3,0,0,0)
75 #define PICTURE_PAllocTable 1000000
76 #define PICTURE_PUseDynamicColors 100000
77 #define PICTURE_PStrictColorLimit 10000
78 #define PICTURE_use_named 1000
79 #define PICTURE_TABLETYPE_LENGHT 7
81 /* humm ... dither is probably borken with gamma correction. Anyway I do
82 * do think that using gamma correction for the colors cubes is a good
83 * idea */
84 #define USE_GAMMA_CORECTION 0
85 /* 2.2 is recommanded by the Poynon colors FAQ, some others suggest 1.5 and 2
86 * Use float constants!*/
87 #define COLOR_GAMMA 1.5
88 #define GREY_GAMMA 2.0
90 /* ---------------------------- imports ------------------------------------ */
92 /* ---------------------------- included code files ------------------------ */
94 /* ---------------------------- local types -------------------------------- */
96 typedef struct
98 XColor color; /* rgb color info */
99 unsigned long alloc_count; /* nbr of allocation */
100 } PColor;
102 typedef struct
105 * info for colors table (depth <= 8)
107 /* color cube used */
108 short nr;
109 short ng;
110 short nb;
111 short ngrey;
112 /* grey palette def, nbr of grey = 2^grey_bits */
113 short grey_bits;
114 /* color cube used for dithering with the named table */
115 short d_nr;
116 short d_ng;
117 short d_nb;
118 short d_ngrey_bits;
119 /* do we found a pre-allocated pallet ? */
120 Bool pre_allocated_pallet;
121 /* info for depth > 8 */
122 int red_shift;
123 int green_shift;
124 int blue_shift;
125 int red_prec;
126 int green_prec;
127 int blue_prec;
128 /* for dithering in depth 15 and 16 */
129 unsigned short *red_dither;
130 unsigned short *green_dither;
131 unsigned short *blue_dither;
132 /* colors allocation function */
133 int (*alloc_color)(Display *dpy, Colormap cmap, XColor *c);
134 int (*alloc_color_no_limit)(Display *dpy, Colormap cmap, XColor *c);
135 int (*alloc_color_dither)(
136 Display *dpy, Colormap cmap, XColor *c, int x, int y);
137 void (*free_colors)(
138 Display *dpy, Colormap cmap, Pixel *pixels, int n,
139 unsigned long planes);
140 void (*free_colors_no_limit)(
141 Display *dpy, Colormap cmap, Pixel *pixels, int n,
142 unsigned long planes);
143 } PColorsInfo;
145 typedef struct {
146 int cols_index;
147 long closeness;
148 } CloseColor;
150 /* ---------------------------- forward declarations ----------------------- */
152 /* ---------------------------- local variables ---------------------------- */
154 static int PColorLimit = 0;
155 static PColor *Pct = NULL;
156 static PColor *Pac = NULL;
157 static short *PMappingTable = NULL;
158 static short *PDitherMappingTable = NULL;
159 static Bool PStrictColorLimit = 0;
160 static Bool PAllocTable = 0;
161 static PColorsInfo Pcsi = {
162 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL,
163 NULL, NULL, NULL, NULL};
165 /* ---------------------------- exported variables (globals) --------------- */
167 /* ---------------------------- local functions ---------------------------- */
170 * get shift and prec from a mask
172 static
173 void decompose_mask(
174 unsigned long mask, int *shift, int *prec)
176 *shift = 0;
177 *prec = 0;
179 while (!(mask & 0x1))
181 (*shift)++;
182 mask >>= 1;
185 while (mask & 0x1)
187 (*prec)++;
188 mask >>= 1;
193 * color allocation in the colormap. strongly inspired by SetCloseColor from
194 * the Xpm library (depth <= 8)
197 static int
198 closeness_cmp(const void *a, const void *b)
200 CloseColor *x = (CloseColor *) a, *y = (CloseColor *) b;
202 /* cast to int as qsort requires */
203 return (int) (x->closeness - y->closeness);
206 static
207 int alloc_color_in_cmap(XColor *c, Bool force)
209 static XColor colors[256];
210 CloseColor closenesses[256];
211 XColor tmp;
212 int i,j;
213 int map_entries = (Pvisual->class == DirectColor)?
214 (1 << Pdepth) : Pvisual->map_entries;
215 time_t current_time;
216 time_t last_time = 0;
218 map_entries = (map_entries > 256)? 256:map_entries;
219 current_time = time(NULL);
220 if (current_time - last_time >= 2 || force)
222 last_time = current_time;
223 for (i = 0; i < map_entries; i++)
225 colors[i].pixel = i;
227 XQueryColors(Pdpy, Pcmap, colors, map_entries);
229 for(i = 0; i < map_entries; i++)
231 closenesses[i].cols_index = i;
232 closenesses[i].closeness = USED_DIST(
233 (int)(c->red),
234 (int)(c->green),
235 (int)(c->blue),
236 (int)(colors[i].red),
237 (int)(colors[i].green),
238 (int)(colors[i].blue));
240 qsort(closenesses, map_entries, sizeof(CloseColor), closeness_cmp);
242 i = 0;
243 j = closenesses[i].cols_index;
244 while (force ||
245 (abs((long)c->red - (long)colors[j].red) <=
246 PICTURE_COLOR_CLOSENESS &&
247 abs((long)c->green - (long)colors[j].green) <=
248 PICTURE_COLOR_CLOSENESS &&
249 abs((long)c->blue - (long)colors[j].blue) <=
250 PICTURE_COLOR_CLOSENESS))
252 tmp.red = colors[j].red;
253 tmp.green = colors[j].green;
254 tmp.blue = colors[j].blue;
255 if (XAllocColor(Pdpy, Pcmap, &tmp))
257 c->red = tmp.red;
258 c->green = tmp.green;
259 c->blue = tmp.blue;
260 c->pixel = tmp.pixel;
261 return 1;
263 else
265 i++;
266 if (i == map_entries)
267 break;
268 j = closenesses[i].cols_index;
271 return 0;
275 * dithering
278 static
279 int my_dither(int x, int y, XColor *c)
281 /* the dither matrice */
282 static const char DM[128][128] = DITHER_MATRICE;
283 int index;
284 const char *dmp;
286 if (Pcsi.grey_bits != 0)
288 /* Grey Scale */
289 int prec = Pcsi.grey_bits;
291 if (Pcsi.grey_bits == 1)
293 /* FIXME, can we do a better dithering */
294 prec = 2;
296 dmp = DM[(0 + y) & (DM_HEIGHT - 1)];
297 index = (c->green + ((c->blue + c->red) >> 1)) >> 1;
298 index += (dmp[(0 + x) & (DM_WIDTH - 1)] << 2) >> prec;
299 index = (index - (index >> prec));
300 index = index >> (8 - Pcsi.grey_bits);
302 else
304 /* color cube */
305 int dith, rs, gs, bs, gb, b;
306 int tr,tb,tg;
308 rs = Pcsi.d_nr - 1;
309 gs = Pcsi.d_ng - 1;
310 bs = Pcsi.d_nb - 1;
311 gb = Pcsi.d_ng*Pcsi.d_nb;
312 b = Pcsi.d_nb;
314 dmp = DM[(0 + y) & (DM_HEIGHT - 1)];
315 dith = (dmp[(0 + x) & (DM_WIDTH - 1)] << 2) | 7;
316 tr = ((c->red * rs) + dith) >> 8;
317 tg = ((c->green * gs) + (262 - dith)) >> 8;
318 tb = ((c->blue * bs) + dith) >> 8;
319 index = tr * gb + tg * b + tb;
320 #if 0
321 /* try to use the additonal grey. Not easy, good for
322 * certain image/gradient bad for others */
323 if (Pcsi.d_ngrey_bits)
325 int g_index;
327 /* dither in the Pcsi.ngrey^3 cc */
328 tr = ((c->red * (Pcsi.ngrey-1)) + dith) >> 8;
329 tg = ((c->green * (Pcsi.ngrey-1)) + (262 - dith)) >> 8;
330 tb = ((c->blue * (Pcsi.ngrey-1)) + dith) >> 8;
331 /* get the grey */
332 fprintf(stderr, "%i,%i,%i(%i/%i) ", tr,tg,tb,
333 abs(tr-tg) + abs(tb-tg) + abs(tb-tr),Pcsi.ngrey);
334 g_index = ((tr + tg + tb)/3);
335 if (g_index != 0 && g_index != Pcsi.ngrey-1 &&
336 abs(tr-tg) + abs(tb-tg) + abs(tb-tr) <=
337 Pcsi.d_ngrey_bits)
339 g_index = g_index + Pcsi.ng*Pcsi.nb*Pcsi.ng -1;
340 index = g_index;
343 #endif
344 if (PDitherMappingTable != NULL)
346 index = PDitherMappingTable[index];
349 return index;
352 static
353 int my_dither_depth_15_16_init(void)
355 const unsigned char _dither_44[4][4] =
357 {0, 4, 1, 5},
358 {6, 2, 7, 3},
359 {1, 5, 0, 4},
360 {7, 3, 6, 2}
362 int y,x,i;
363 int rm = 0xf8, re = 0x7, gm = 0xfc, ge = 0x3, bm = 0xf8, be = 0x7;
365 if (Pdepth == 16 && (Pvisual->red_mask == 0xf800) &&
366 (Pvisual->green_mask == 0x7e0) &&
367 (Pvisual->blue_mask == 0x1f))
369 /* ok */
371 else if (Pdepth == 15 && (Pvisual->red_mask == 0x7c00) &&
372 (Pvisual->green_mask == 0x3e0) &&
373 (Pvisual->blue_mask == 0x1f))
375 gm = 0xf8; ge = 0x7;
377 else
379 return 0; /* fail */
382 Pcsi.red_dither =
383 (unsigned short *)safemalloc(4*4*256*sizeof(unsigned short));
384 Pcsi.green_dither =
385 (unsigned short *)safemalloc(4*4*256*sizeof(unsigned short));
386 Pcsi.blue_dither =
387 (unsigned short *)safemalloc(4*4*256*sizeof(unsigned short));
389 for (y = 0; y < 4; y++)
391 for (x = 0; x < 4; x++)
393 for (i = 0; i < 256; i++)
395 if ((_dither_44[x][y] < (i & re)) &&
396 (i < (256 - 8)))
398 Pcsi.red_dither[
399 (x << 10) | (y << 8) | i] =
400 ((i + 8) & rm) << 8;
402 else
404 Pcsi.red_dither[
405 (x << 10) | (y << 8) | i] =
406 (i & rm) << 8;
408 if ((_dither_44[x][y] < ((i & ge) << 1))
409 && (i < (256 - 4)))
411 Pcsi.green_dither[
412 (x << 10) | (y << 8) | i] =
413 ((i + 4) & gm) << 8;
415 else
417 Pcsi.green_dither[
418 (x << 10) | (y << 8) | i] =
419 (i & gm) << 8;
421 if ((_dither_44[x][y] < (i & be)) &&
422 (i < (256 - 8)))
424 Pcsi.blue_dither[
425 (x << 10) | (y << 8) | i] =
426 ((i + 8) & bm) << 8;
428 else
430 Pcsi.blue_dither[
431 (x << 10) | (y << 8) | i] =
432 (i & bm) << 8;
437 return 1;
441 * Color allocation in the "palette"
444 static
445 int alloc_color_in_pct(XColor *c, int index)
447 if (Pct[index].alloc_count == 0)
449 int s = PStrictColorLimit;
451 PStrictColorLimit = 0;
452 c->red = Pct[index].color.red;
453 c->green = Pct[index].color.green;
454 c->blue = Pct[index].color.blue;
455 PictureAllocColor(Pdpy, Pcmap, c, True); /* WARN (rec) */
456 Pct[index].color.pixel = c->pixel;
457 Pct[index].alloc_count = 1;
458 PStrictColorLimit = s;
460 else
462 c->red = Pct[index].color.red;
463 c->green = Pct[index].color.green;
464 c->blue = Pct[index].color.blue;
465 c->pixel = Pct[index].color.pixel;
466 if (Pct[index].alloc_count < 0xffffffff)
467 (Pct[index].alloc_count)++;
469 return 1;
472 static
473 int get_color_index(int r, int g, int b, int is_8)
475 int index;
477 if (!is_8)
479 r= r >> 8;
480 g= g >> 8;
481 b= b >> 8;
483 if (Pcsi.grey_bits > 0)
485 /* FIXME: Use other proporition ? */
486 index = ((r+g+b)/3) >> (8 - Pcsi.grey_bits);
488 else
490 #if 1
491 /* "exact" computation (corrected linear dist) */
492 float fr,fg,fb;
493 int ir, ig, ib;
495 /* map to the cube */
496 fr = ((float)r * (Pcsi.nr-1))/255;
497 fg = ((float)g * (Pcsi.ng-1))/255;
498 fb = ((float)b * (Pcsi.nb-1))/255;
500 if (PMappingTable != NULL)
502 ir = (int)fr + (fr - (int)fr > 0.5);
503 ig = (int)fg + (fg - (int)fg > 0.5);
504 ib = (int)fb + (fb - (int)fb > 0.5);
506 index = ir * Pcsi.ng*Pcsi.nb + ig * Pcsi.nb + ib;
508 else
510 /* found the best of the 8 linear closest points */
511 int lr,lg,lb,tr,tg,tb,best_dist = -1,i,d;
513 index = 0;
514 lr = min((int)fr+1,Pcsi.nr-1);
515 lg = min((int)fg+1,Pcsi.ng-1);
516 lb = min((int)fb+1,Pcsi.nb-1);
517 for(tr =(int)fr; tr<=lr; tr++)
519 for(tg =(int)fg; tg<=lg; tg++)
521 for(tb =(int)fb; tb<=lb; tb++)
523 i = tr * Pcsi.ng*Pcsi.nb +
524 tg * Pcsi.nb +
526 d = USED_DIST(
527 r,g,b,
528 (Pct[i].color.red>>8),
529 (Pct[i].color.green>>8),
530 (Pct[i].color.blue>>8));
531 if (best_dist == -1 ||
532 d < best_dist)
534 index = i;
535 best_dist = d;
541 /* now found the best grey */
542 if (Pcsi.ngrey - 2 > 0)
544 /* FIXME: speedup this with more than 8 grey */
545 int start = Pcsi.nr*Pcsi.ng*Pcsi.nb;
546 for(i=start; i < start+Pcsi.ngrey-2; i++)
548 d = USED_DIST(
549 r,g,b,
550 (Pct[i].color.red>>8),
551 (Pct[i].color.green>>8),
552 (Pct[i].color.blue>>8));
553 if (d < best_dist)
555 index = i;
556 best_dist = d;
560 return index;
562 #else
563 /* approximation; faster */
564 index = ((r * Pcsi.nr)>>8) * Pcsi.ng*Pcsi.nb +
565 ((g * Pcsi.ng)>>8) * Pcsi.nb +
566 ((b * Pcsi.nb)>>8);
567 #endif
568 if (PMappingTable != NULL)
570 index = PMappingTable[index];
573 return index;
577 * Main colors allocator
579 static
580 int alloc_color_proportion(Display *dpy, Colormap cmap, XColor *c)
582 c->pixel = (Pixel)(
583 ((c->red >> (16 - Pcsi.red_prec))<< Pcsi.red_shift) +
584 ((c->green >> (16 - Pcsi.green_prec))<< Pcsi.green_shift) +
585 ((c->blue >> (16 - Pcsi.blue_prec))<< Pcsi.blue_shift)
587 return 1;
590 static
591 int alloc_color_proportion_dither(
592 Display *dpy, Colormap cmap, XColor *c, int x, int y)
594 /* 8 bit colors !! */
595 c->red = Pcsi.red_dither[
596 (((x + 0) & 0x3) << 10) | ((y & 0x3) << 8) |
597 ((c->red) & 0xff)] * 257;
598 c->green = Pcsi.green_dither[
599 (((x + 0) & 0x3) << 10) | ((y & 0x3) << 8) |
600 ((c->green) & 0xff)] * 257;
601 c->blue = Pcsi.blue_dither[
602 (((x + 0) & 0x3) << 10) | ((y & 0x3) << 8) |
603 ((c->blue) & 0xff)] * 257;
604 c->pixel = (Pixel)(
605 ((c->red >> (16 - Pcsi.red_prec)) << Pcsi.red_shift) +
606 ((c->green >> (16 - Pcsi.green_prec))
607 << Pcsi.green_shift) +
608 ((c->blue >> (16 - Pcsi.blue_prec)) << Pcsi.blue_shift)
610 return 1;
613 static
614 int alloc_color_proportion_grey(
615 Display *dpy, Colormap cmap, XColor *c)
617 /* FIXME: is this ok in general? */
618 c->pixel = ((c->red + c->green + c->blue)/3);
619 if (Pdepth < 16)
621 c->pixel = c->pixel >> (16 - Pdepth);
623 return 1;
626 static
627 int alloc_color_in_table(Display *dpy, Colormap cmap, XColor *c)
630 int index = get_color_index(c->red,c->green,c->blue, False);
631 return alloc_color_in_pct(c, index);
634 static
635 int alloc_color_in_table_dither(
636 Display *dpy, Colormap cmap, XColor *c, int x, int y)
638 int index;
639 /* 8 bit colors !! */
640 index = my_dither(x, y, c);
641 return alloc_color_in_pct(c, index);
644 static
645 int alloc_color_dynamic_no_limit(
646 Display *dpy, Colormap cmap, XColor *c)
648 int r = 0;
650 if (XAllocColor(dpy, cmap, c))
652 r = 1;
654 else if (!alloc_color_in_cmap(c, False))
656 MyXGrabServer(dpy);
657 r = alloc_color_in_cmap(c, True);
658 MyXUngrabServer(dpy);
660 else
662 r = 1;
664 if (r && Pac != NULL && (c->pixel <= (1 << Pdepth) /* always true*/))
666 Pac[c->pixel].alloc_count++;
667 Pac[c->pixel].color.red = c->red;
668 Pac[c->pixel].color.green = c->green;
669 Pac[c->pixel].color.blue = c->blue;
670 Pac[c->pixel].color.pixel = c->pixel;
672 return r;
675 static
676 int alloc_color_x(
677 Display *dpy, Colormap cmap, XColor *c)
679 return XAllocColor(dpy, cmap, c);
682 static
683 void free_colors_in_table(
684 Display *dpy, Colormap cmap, Pixel *pixels, int n,
685 unsigned long planes)
687 Pixel *p;
688 int i,j,do_free;
689 int m = 0;
691 if (!Pct || !PUseDynamicColors)
693 return;
696 p = (Pixel *)safemalloc(n*sizeof(Pixel));
697 for(i= 0; i < n; i++)
699 do_free = 1;
700 for(j=0; j<PColorLimit; j++)
702 if (Pct[j].alloc_count &&
703 Pct[j].alloc_count < 0xffffffff &&
704 pixels[i] == Pct[j].color.pixel)
706 (Pct[j].alloc_count)--;
707 if (Pct[j].alloc_count)
708 do_free = 0;
709 break;
712 if (do_free)
714 p[m++] = pixels[i];
717 if (m > 0)
719 XFreeColors(dpy, cmap, p, m, planes);
721 free(p);
723 return;
726 static
727 void free_colors_x(
728 Display *dpy, Colormap cmap, Pixel *pixels, int n,
729 unsigned long planes)
731 XFreeColors(dpy, cmap, pixels, n, planes);
732 if (Pac != NULL)
734 int nbr_colors = (1 << Pdepth);
735 int i;
737 for(i= 0; i < n; i++)
739 if (pixels[i] <= nbr_colors)
741 Pac[pixels[i]].alloc_count--;
748 * local function for building pallet (dynamic colors, private DirectColor
749 * cmap)
751 static
752 XColor *build_mapping_colors(int nr, int ng, int nb)
754 int r, g, b, i;
755 XColor *colors;
757 colors = (XColor *)safemalloc(nr*ng*nb * sizeof(XColor));
758 i = 0;
759 for (r = 0; r < nr; r++)
761 for (g = 0; g < ng; g++)
763 for (b = 0; b < nb; b++)
765 colors[i].red =
766 r * 65535 / (nr - 1);
767 colors[i].green =
768 g * 65535 / (ng - 1);
769 colors[i].blue =
770 b * 65535 / (nb - 1);
771 i++;
775 return colors;
778 static short *build_mapping_table(int nr, int ng, int nb, Bool use_named)
780 int size = nr*ng*nb;
781 XColor *colors_map;
782 short *Table;
783 int i,j, minind;
784 double mindst = 40000;
785 double dst;
787 colors_map = build_mapping_colors(nr, ng, nb);
788 Table = (short *)safemalloc((size+1) * sizeof(short));
789 for(i=0; i<size; i++)
791 minind = 0;
792 for(j=0; j<PColorLimit; j++)
794 if (use_named)
796 /* for back ward compatibility */
797 dst = TRUE_DIST(colors_map[i].red,
798 colors_map[i].green,
799 colors_map[i].blue,
800 Pct[j].color.red,
801 Pct[j].color.green,
802 Pct[j].color.blue);
804 else
806 dst = USED_DIST(colors_map[i].red,
807 colors_map[i].green,
808 colors_map[i].blue,
809 Pct[j].color.red,
810 Pct[j].color.green,
811 Pct[j].color.blue);
813 if (j == 0 || dst < mindst)
815 mindst=dst;
816 minind=j;
819 Table[i] = minind;
821 Table[size] = Table[size-1];
822 free(colors_map);
823 return Table;
826 static
827 void free_table_colors(PColor *color_table, int npixels)
829 Pixel pixels[256];
830 int i,n=0;
832 if (npixels > 0)
834 for(i = 0; i < npixels; i++)
836 if (color_table[i].alloc_count)
838 pixels[n++] = color_table[i].color.pixel;
840 color_table[i].alloc_count = 0;
842 if (n > 0)
844 XFreeColors(Pdpy, Pcmap, pixels, n, 0);
849 /* FIXME: the DirectColor case */
850 static
851 int get_nbr_of_free_colors(int max_check)
853 int check = 1;
854 Pixel Pixels[256];
855 int map_entries = (Pvisual->class == DirectColor)?
856 (1 << Pdepth):Pvisual->map_entries;
857 if (max_check < 1)
858 return 0;
859 if (map_entries > 256)
861 max_check = 256;
863 max_check = (max_check > map_entries) ? map_entries:max_check;
864 while(1)
866 if (XAllocColorCells(
867 Pdpy, Pcmap, False, NULL, 0, Pixels, check))
869 XFreeColors(Pdpy, Pcmap, Pixels, check, 0);
870 check++;
872 else
874 return check-1;
876 if (check > max_check)
878 return check-1;
881 return check-1;
884 static
885 PColor *alloc_color_cube(
886 int nr, int ng, int nb, int ngrey, int grey_bits, Bool do_allocate)
888 int r, g, b, grey, i, start_grey, end_grey;
889 PColor *color_table;
890 XColor color;
891 int size;
893 size = nr*ng*nb + ngrey + (1 << grey_bits)*(grey_bits != 0);
894 if (grey_bits)
896 ngrey = (1 << grey_bits);
898 if (nr > 0 && ngrey > 0)
900 start_grey = 1;
901 end_grey = ngrey - 1;
902 size = size - 2;
904 else
906 start_grey = 0;
907 end_grey = ngrey;
910 color_table = (PColor *)safemalloc((size+1) * sizeof(PColor));
912 i = 0;
914 #if USE_GAMMA_CORECTION
915 #define CG(x) 65535.0 * pow((x)/65535.0,1/COLOR_GAMMA)
916 #define GG(x) 65535.0 * pow((x)/65535.0,1/GREY_GAMMA)
917 #else
918 #define CG(x) x
919 #define GG(x) x
920 #endif
922 if (nr > 0)
924 for (r = 0; r < nr; r++)
926 for (g = 0; g < ng; g++)
928 for (b = 0; b < nb; b++)
930 color.red = CG(r * 65535 / (nr - 1));
931 color.green = CG(g * 65535 / (ng - 1));
932 color.blue = CG(b * 65535 / (nb - 1));
933 if (do_allocate)
935 if (!XAllocColor(Pdpy, Pcmap,
936 &color))
938 free_table_colors(
939 color_table, i);
940 free(color_table);
941 return NULL;
943 color_table[i].color.pixel =
944 color.pixel;
945 color_table[i].alloc_count = 1;
947 else
949 color_table[i].alloc_count = 0;
951 color_table[i].color.red = color.red;
952 color_table[i].color.green = color.green;
953 color_table[i].color.blue = color.blue;
954 i++;
960 if (ngrey > 0)
962 for (grey = start_grey; grey < end_grey; grey++)
964 color.red = color.green = color.blue =
965 GG(grey * 65535 / (ngrey - 1));
966 if (do_allocate)
968 if (!XAllocColor(Pdpy, Pcmap, &color))
970 free_table_colors(color_table, i);
971 free(color_table);
972 return NULL;
974 color_table[i].color.pixel = color.pixel;
975 color_table[i].alloc_count = 1;
977 else
979 color_table[i].alloc_count = 0;
981 color_table[i].color.red = color.red;
982 color_table[i].color.green = color.green;
983 color_table[i].color.blue = color.blue;
984 i++;
987 color_table[size].color.red = color_table[size-1].color.red;
988 color_table[size].color.green = color_table[size-1].color.green;
989 color_table[size].color.blue = color_table[size-1].color.blue;
990 color_table[size].color.pixel = color_table[size-1].color.pixel;
991 color_table[size].alloc_count = 0;
992 PColorLimit = size;
993 return color_table;
997 static
998 PColor *alloc_named_ct(int *limit, Bool do_allocate)
1001 /* First thing in base array are colors probably already in the color map
1002 because they have familiar names.
1003 I pasted them into a xpm and spread them out so that similar colors are
1004 spread out.
1005 Toward the end are some colors to fill in the gaps.
1006 Currently 61 colors in this list.
1008 char *color_names[] =
1010 "black",
1011 "white",
1012 "grey",
1013 "green",
1014 "blue",
1015 "red",
1016 "cyan",
1017 "yellow",
1018 "magenta",
1019 "DodgerBlue",
1020 "SteelBlue",
1021 "chartreuse",
1022 "wheat",
1023 "turquoise",
1024 "CadetBlue",
1025 "gray87",
1026 "CornflowerBlue",
1027 "YellowGreen",
1028 "NavyBlue",
1029 "MediumBlue",
1030 "plum",
1031 "aquamarine",
1032 "orchid",
1033 "ForestGreen",
1034 "lightyellow",
1035 "brown",
1036 "orange",
1037 "red3",
1038 "HotPink",
1039 "LightBlue",
1040 "gray47",
1041 "pink",
1042 "red4",
1043 "violet",
1044 "purple",
1045 "gray63",
1046 "gray94",
1047 "plum1",
1048 "PeachPuff",
1049 "maroon",
1050 "lavender",
1051 "salmon", /* for peachpuff, orange gap */
1052 "blue4", /* for navyblue/mediumblue gap */
1053 "PaleGreen4", /* for forestgreen, yellowgreen gap */
1054 "#AA7700", /* brick, no close named color */
1055 "#11EE88", /* light green, no close named color */
1056 "#884466", /* dark brown, no close named color */
1057 "#CC8888", /* light brick, no close named color */
1058 "#EECC44", /* gold, no close named color */
1059 "#AAAA44", /* dull green, no close named color */
1060 "#FF1188", /* pinkish red */
1061 "#992299", /* purple */
1062 "#CCFFAA", /* light green */
1063 "#664400", /* dark brown*/
1064 "#AADD99", /* light green */
1065 "#66CCFF", /* light blue */
1066 "#CC2299", /* dark red */
1067 "#FF11CC", /* bright pink */
1068 "#11CC99", /* grey/green */
1069 "#AA77AA", /* purple/red */
1070 "#EEBB77" /* orange/yellow */
1072 int NColors = sizeof(color_names)/sizeof(char *);
1073 int i,rc;
1074 PColor *color_table;
1075 XColor color;
1077 *limit = (*limit > NColors)? NColors: *limit;
1078 color_table = (PColor *)safemalloc((*limit+1) * sizeof(PColor));
1079 for(i=0; i<*limit; i++)
1081 rc=XParseColor(Pdpy, Pcmap, color_names[i], &color);
1082 if (rc==0) {
1083 fprintf(stderr,"color_to_rgb: can't parse color %s,"
1084 " rc %d\n", color_names[i], rc);
1085 free_table_colors(color_table, i);
1086 free(color_table);
1087 return NULL;
1089 if (do_allocate)
1091 if (!XAllocColor(Pdpy, Pcmap, &color))
1093 free_table_colors(color_table, i);
1094 free(color_table);
1095 return NULL;
1097 color_table[i].color.pixel = color.pixel;
1098 color_table[i].alloc_count = 1;
1100 else
1102 color_table[i].alloc_count = 0;
1104 color_table[i].color.red = color.red;
1105 color_table[i].color.green = color.green;
1106 color_table[i].color.blue = color.blue;
1108 color_table[*limit].color.red = color_table[*limit-1].color.red;
1109 color_table[*limit].color.green = color_table[*limit-1].color.green;
1110 color_table[*limit].color.blue = color_table[*limit-1].color.blue;
1111 color_table[*limit].color.pixel = color_table[*limit-1].color.pixel;
1112 color_table[*limit].alloc_count = 0;
1113 PColorLimit = *limit;
1114 return color_table;
1117 static
1118 void create_mapping_table(
1119 int nr, int ng, int nb, int ngrey, int grey_bits,
1120 Bool non_regular_pallet)
1123 Pcsi.grey_bits = 0;
1125 /* initialize dithering colors numbers */
1126 if (!non_regular_pallet)
1128 /* */
1129 Pcsi.d_nr = nr;
1130 Pcsi.d_ng = ng;
1131 Pcsi.d_nb = nb;
1132 Pcsi.d_ngrey_bits = 2;
1133 while((1<<Pcsi.d_ngrey_bits) < ngrey)
1135 Pcsi.d_ngrey_bits++;
1137 if (1<<Pcsi.d_ngrey_bits != ngrey)
1139 Pcsi.d_ngrey_bits = 0;
1141 Pcsi.grey_bits = grey_bits;
1143 else
1145 /* dither table should be small */
1146 Pcsi.grey_bits = 0;
1147 if (PColorLimit <= 9)
1149 Pcsi.d_nr = 3;
1150 Pcsi.d_ng = 3;
1151 Pcsi.d_nb = 3;
1152 Pcsi.d_ngrey_bits = 0;
1154 else if (PColorLimit <= 64)
1156 Pcsi.d_nr = 4;
1157 Pcsi.d_ng = 4;
1158 Pcsi.d_nb = 4;
1159 Pcsi.d_ngrey_bits = 0;
1161 else
1163 Pcsi.d_nr = 8;
1164 Pcsi.d_ng = 8;
1165 Pcsi.d_nb = 8;
1166 Pcsi.d_ngrey_bits = 0;
1168 PDitherMappingTable = build_mapping_table(
1169 Pcsi.d_nr, Pcsi.d_ng, Pcsi.d_nb, non_regular_pallet);
1172 /* initialize colors number fo index computation */
1173 if (PColorLimit == 2)
1175 /* ok */
1176 Pcsi.nr = 0;
1177 Pcsi.ng = 0;
1178 Pcsi.nb = 0;
1179 Pcsi.ngrey = 0;
1180 Pcsi.grey_bits = 1;
1182 else if (grey_bits > 0)
1184 Pcsi.nr = 0;
1185 Pcsi.ng = 0;
1186 Pcsi.nb = 0;
1187 Pcsi.ngrey = 0;
1188 Pcsi.grey_bits = grey_bits;
1190 else if (non_regular_pallet || (0&&ngrey>0))
1192 /* note: using these table with !used_named && ngrey>0 will
1193 * probably leads to faster image loading. But I see nothing
1194 * of significative. On the others hands not using it gives
1195 * maybe better colors approximation. */
1196 if (PColorLimit <= 9)
1198 Pcsi.nr = 8;
1199 Pcsi.ng = 8;
1200 Pcsi.nb = 8;
1201 Pcsi.ngrey = 0;
1203 else
1205 Pcsi.nr = 16;
1206 Pcsi.ng = 16;
1207 Pcsi.nb = 16;
1208 Pcsi.ngrey = 0;
1210 PMappingTable = build_mapping_table(
1211 Pcsi.nr, Pcsi.ng, Pcsi.nb, non_regular_pallet);
1213 else
1215 Pcsi.nr = nr;
1216 Pcsi.ng = ng;
1217 Pcsi.nb = nb;
1218 Pcsi.ngrey = ngrey;
1219 Pcsi.grey_bits = 0;
1223 static void finish_ct_init(
1224 int call_type, int ctt, int nr, int ng, int nb, int ngrey,
1225 int grey_bits, Bool use_named)
1227 if (call_type == PICTURE_CALLED_BY_FVWM)
1229 char *env;
1231 if (PAllocTable)
1233 ctt = PICTURE_PAllocTable + ctt;
1235 if (PUseDynamicColors)
1237 ctt = PICTURE_PUseDynamicColors + ctt;
1239 if (PStrictColorLimit)
1241 ctt = PICTURE_PStrictColorLimit + ctt;
1243 if (use_named)
1245 ctt = PICTURE_use_named + ctt;
1247 else
1249 ctt++;
1251 env = safemalloc(PICTURE_TABLETYPE_LENGHT + 1);
1252 sprintf(env, "%i", ctt);
1253 flib_putenv("FVWM_COLORTABLE_TYPE", env);
1254 free(env);
1255 if (Pdepth <= 8)
1257 Pac = (PColor *)safecalloc(
1258 (1 << Pdepth), sizeof(PColor));
1262 if (Pct)
1264 if (!PAllocTable && call_type == PICTURE_CALLED_BY_FVWM)
1266 free_table_colors(Pct, PColorLimit);
1268 create_mapping_table(nr,ng,nb,ngrey,grey_bits,use_named);
1272 #define PA_COLOR_CUBE (1 << 1)
1273 #define FVWM_COLOR_CUBE (1 << 2)
1274 #define PA_GRAY_SCALE (1 << 3)
1275 #define FVWM_GRAY_SCALE (1 << 4)
1276 #define ANY_COLOR_CUBE (PA_COLOR_CUBE|FVWM_COLOR_CUBE)
1277 #define ANY_GRAY_SCALE (PA_GRAY_SCALE|FVWM_GRAY_SCALE)
1279 static
1280 int PictureAllocColorTable(
1281 PictureColorLimitOption *opt, int call_type, Bool use_my_color_limit)
1283 char *envp;
1284 int free_colors, nbr_of_color, limit, cc_nbr, i, size;
1285 int use_named_table = 0;
1286 int do_allocate = 0;
1287 int use_default = 1;
1288 int private_cmap = !(Pdefault);
1289 int dyn_cl_set = False;
1290 int strict_cl_set = False;
1291 int alloc_table_set = False;
1292 int color_limit;
1293 int pa_type = (Pvisual->class != GrayScale) ?
1294 PA_COLOR_CUBE : PA_GRAY_SCALE;
1295 int fvwm_type = (Pvisual->class != GrayScale) ?
1296 FVWM_COLOR_CUBE : FVWM_GRAY_SCALE;
1297 int cc[][6] =
1299 /* {nr,ng,nb,ngrey,grey_bits,logic} */
1300 /* 5 first for direct colors and Pdepth > 8*/
1301 /* 8192 colors depth 13, a reasonable max for a color table */
1302 {16, 32, 16, 0, 0, FVWM_COLOR_CUBE},
1303 /* 4096 colors depth 12 */
1304 {16, 16, 16, 0, 0, FVWM_COLOR_CUBE},
1305 /* 1024 colors depth 10 */
1306 {8, 16, 8, 0, 0, FVWM_COLOR_CUBE},
1307 /* 512 colors depth 9 */
1308 {8, 8, 8, 0, 0, FVWM_COLOR_CUBE},
1309 /* 256 colors 3/3/2 standard colormap */
1310 {8, 8, 4, 0, 0, FVWM_COLOR_CUBE},
1311 /* 256 grey scale */
1312 {0, 0, 0, 0, 8, ANY_GRAY_SCALE},
1313 /* 244 Xrender XFree-4.2 */
1314 {6, 6, 6, 30, 0, ANY_COLOR_CUBE},
1315 /* 216 Xrender XFree-4.2,GTK/QT "default cc" */
1316 {6, 6, 6, 0, 0, ANY_COLOR_CUBE},
1317 /* 180 (GTK) */
1318 {6, 6, 5, 0, 0, ANY_COLOR_CUBE},
1319 /* 144 (GTK) */
1320 {6, 6, 4, 0, 0, ANY_COLOR_CUBE},
1321 /* 128 grey scale */
1322 {0, 0, 0, 0, 7, ANY_GRAY_SCALE},
1323 /* 125 GTK mini default cc (may change? 444) */
1324 {5, 5, 5, 0, 0, ANY_COLOR_CUBE},
1325 /* 100 (GTK with color limit) */
1326 {5, 5, 4, 0, 0, ANY_COLOR_CUBE},
1327 /* 85 Xrender XFree-4.3 */
1328 {4, 4, 4, 23, 0, ANY_COLOR_CUBE},
1329 /* 78 (in fact 76) a good default ??*/
1330 {4, 4, 4, 16, 0, FVWM_COLOR_CUBE},
1331 /* 70 a good default ?? */
1332 {4, 4, 4, 8, 0, ANY_COLOR_CUBE},
1333 /* 68 a good default ?? */
1334 {4, 4, 4, 6, 0, ANY_COLOR_CUBE},
1335 /* 64 Xrender XFree-4.3 (GTK wcl) */
1336 {4, 4, 4, 0, 0, ANY_COLOR_CUBE},
1337 /* 64 grey scale */
1338 {0, 0, 0, 0, 6, ANY_GRAY_SCALE},
1339 /* 54, maybe a good default? */
1340 {4, 4, 3, 8, 0, FVWM_COLOR_CUBE},
1341 /* 48, (GTK wcl) no grey but ok */
1342 {4, 4, 3, 0, 0, FVWM_COLOR_CUBE},
1343 /* 32, 2/2/1 standard colormap */
1344 {4, 4, 2, 0, 0, FVWM_COLOR_CUBE},
1345 /* 32 xrender xfree-4.2 */
1346 {0, 0, 0, 0, 6, ANY_GRAY_SCALE},
1347 /* 29 */
1348 {3, 3, 3, 4, 0, FVWM_COLOR_CUBE},
1349 /* 27 (xrender in depth 6&7(hypo) GTK wcl) */
1350 {3, 3, 3, 0, 0, FVWM_COLOR_CUBE|PA_COLOR_CUBE*(Pdepth<8)},
1351 /* 16 grey scale */
1352 {0, 0, 0, 0, 4, FVWM_GRAY_SCALE},
1353 /* 10 */
1354 {2, 2, 2, 4, 0, FVWM_COLOR_CUBE},
1355 /* 8 (xrender/qt/gtk wcl) */
1356 {2, 2, 2, 0, 0, FVWM_COLOR_CUBE},
1357 /* 8 grey scale Xrender depth 4 and XFree-4.3 */
1358 {0, 0, 0, 0, 3, FVWM_GRAY_SCALE|PA_GRAY_SCALE*(Pdepth<5)},
1359 /* 4 grey scale*/
1360 {0, 0, 0, 0, 2,
1361 FVWM_GRAY_SCALE|FVWM_COLOR_CUBE|PA_COLOR_CUBE*(Pdepth<4)},
1362 /* 2 */
1363 {0, 0, 0, 0, 1, FVWM_COLOR_CUBE|FVWM_GRAY_SCALE}
1366 cc_nbr = sizeof(cc)/(sizeof(cc[0]));
1368 /* set up default */
1369 PStrictColorLimit = 0;
1370 PUseDynamicColors = 1;
1371 PAllocTable = 0;
1372 use_named_table = False;
1373 color_limit = 0;
1374 use_default = True;
1376 /* use fvwm color limit */
1377 if (!use_my_color_limit &&
1378 (envp = getenv("FVWM_COLORTABLE_TYPE")) != NULL)
1380 int nr = 0, ng = 0, nb = 0, grey_bits = 0, ngrey = 0;
1381 int ctt = atoi(envp);
1383 if (ctt >= PICTURE_PAllocTable)
1385 ctt -= PICTURE_PAllocTable;
1386 PAllocTable = 1; /* not useful for a module !*/
1388 if (ctt >= PICTURE_PUseDynamicColors)
1390 PUseDynamicColors = 1;
1391 ctt -= PICTURE_PUseDynamicColors;
1393 if (ctt >= PICTURE_PStrictColorLimit)
1395 PStrictColorLimit = 1;
1396 ctt -= PICTURE_PStrictColorLimit;
1398 if (ctt >= PICTURE_use_named)
1400 ctt -= PICTURE_use_named;
1401 Pct = alloc_named_ct(&ctt, False);
1402 use_named_table = True;
1404 else if (ctt == 0)
1406 /* depth <= 8 and no colors limit ! */
1407 PColorLimit = 0;
1408 return 0;
1410 else if (ctt <= cc_nbr)
1412 ctt--;
1413 Pct = alloc_color_cube(
1414 cc[ctt][0], cc[ctt][1], cc[ctt][2], cc[ctt][3],
1415 cc[ctt][4],
1416 False);
1417 nr = cc[ctt][0];
1418 ng = cc[ctt][1];
1419 nb = cc[ctt][2];
1420 ngrey = cc[ctt][3];
1421 grey_bits = cc[ctt][4];
1423 if (Pct != NULL)
1425 /* should always happen */
1426 finish_ct_init(
1427 call_type, ctt, nr, ng, nb, ngrey, grey_bits,
1428 use_named_table);
1429 return PColorLimit;
1433 nbr_of_color = (1 << Pdepth);
1434 color_limit = 0;
1436 /* parse the color limit env variable */
1437 if ((envp = getenv("FVWM_COLORLIMIT")) != NULL)
1439 char *rest, *l;
1441 rest = GetQuotedString(envp, &l, ":", NULL, NULL, NULL);
1442 if (l && *l != '\0' && (color_limit = atoi(l)) >= 0)
1444 use_default = 0;
1446 if (l != NULL)
1448 free(l);
1450 if (color_limit == 9 || color_limit == 61)
1452 use_named_table = 1;
1454 if (rest && *rest != '\0')
1456 if (rest[0] == '1')
1458 strict_cl_set = True;
1459 PStrictColorLimit = 1;
1461 else
1463 strict_cl_set = True;
1464 PStrictColorLimit = 0;
1466 if (strlen(rest) > 1 && rest[1] == '1')
1468 use_named_table = 1;
1470 else
1472 use_named_table = 0;
1474 if (strlen(rest) > 2 && rest[2] == '1')
1476 dyn_cl_set = True;
1477 PUseDynamicColors = 1;
1479 else
1481 dyn_cl_set = True;
1482 PUseDynamicColors = 0;
1484 if (strlen(rest) > 3 && rest[3] == '1')
1486 alloc_table_set = True;
1487 PAllocTable = 1;
1489 else
1491 alloc_table_set = True;
1492 PAllocTable = 0;
1496 else if (opt != NULL) /* use the option */
1498 if (opt->color_limit > 0)
1500 use_default = 0;
1501 color_limit = opt->color_limit;
1503 if (color_limit == 9 || color_limit == 61)
1505 use_named_table = 1;
1507 if (opt->strict > 0)
1509 strict_cl_set = True;
1510 PStrictColorLimit = 1;
1512 else if (opt->strict == 0)
1514 strict_cl_set = True;
1515 PStrictColorLimit = 0;
1517 if (opt->use_named_table > 0)
1519 use_named_table = 1;
1521 else if (opt->use_named_table == 0)
1523 use_named_table = 0;
1525 if (opt->not_dynamic > 0)
1527 dyn_cl_set = True;
1528 PUseDynamicColors = 0;
1530 else if (opt->not_dynamic == 0)
1532 dyn_cl_set = True;
1533 PUseDynamicColors = 0;
1535 if (opt->allocate > 0)
1537 alloc_table_set = True;
1538 PAllocTable = 1;
1540 else if (opt->allocate == 0)
1542 alloc_table_set = True;
1543 PAllocTable = 0;
1547 if (color_limit <= 0)
1549 use_default = 1;
1550 color_limit = nbr_of_color;
1553 /* first try to see if we have a "pre-allocated" color cube.
1554 * The bultin RENDER X extension pre-allocate a color cube plus
1555 * some grey's (xc/programs/Xserver/render/miindex)
1556 * See gdk/gdkrgb.c for the cubes used by gtk+-2, 666 is the default,
1557 * 555 is the minimal cc (this may change): if gtk cannot allocate
1558 * the 555 cc (or better) a private cmap is used.
1559 * for qt-3: see src/kernel/{qapplication.cpp,qimage.cpp,qcolor_x11.c}
1560 * the 666 cube is used by default (with approx in the cmap if some
1561 * color allocation fail), and some qt app may accept an
1562 * --ncols option to limit the nbr of colors, then some "2:3:1"
1563 * proportions color cube are used (222, 232, ..., 252, 342, ..., 362,
1564 * 452, ...,693, ...)
1565 * imlib2 try to allocate the 666 cube if this fail it try more
1566 * exotic table (see rend.c and rgba.c) */
1567 i = 0;
1568 free_colors = 0;
1569 if (Pdepth <= 8 && !private_cmap && use_default &&
1570 i < cc_nbr && Pct == NULL && (Pvisual->class & 1))
1572 free_colors = get_nbr_of_free_colors(nbr_of_color);
1574 while(Pdepth <= 8 && !private_cmap && use_default &&
1575 i < cc_nbr && Pct == NULL && (Pvisual->class & 1))
1577 size = cc[i][0]*cc[i][1]*cc[i][2] + cc[i][3] -
1578 2*(cc[i][3] > 0) + (1 << cc[i][4])*(cc[i][4] != 0);
1579 if (size > nbr_of_color || !(cc[i][5] & pa_type))
1581 i++;
1582 continue;
1584 if (free_colors <= nbr_of_color - size)
1586 Pct = alloc_color_cube(
1587 cc[i][0], cc[i][1], cc[i][2], cc[i][3],
1588 cc[i][4], True);
1590 if (Pct != NULL)
1592 if (free_colors <=
1593 get_nbr_of_free_colors(nbr_of_color))
1595 /* done */
1597 else
1599 free_table_colors(Pct, PColorLimit);
1600 free(Pct);
1601 Pct = NULL;
1604 i++;
1606 if (Pct != NULL)
1608 PUseDynamicColors = 0;
1609 PAllocTable = 1;
1610 Pcsi.pre_allocated_pallet = 1;
1611 i = i - 1;
1612 finish_ct_init(
1613 call_type, i, cc[i][0], cc[i][1], cc[i][2], cc[i][3],
1614 cc[i][4], 0);
1615 return PColorLimit;
1619 * now use "our" table
1622 limit = (color_limit >= nbr_of_color)? nbr_of_color:color_limit;
1624 if (use_default && !private_cmap)
1626 /* XRender cvs default: */
1627 #if 0
1628 if (limit > 100)
1629 limit = nbr_of_color/3;
1630 else
1631 limit = nbr_of_color/2;
1632 /* depth 8: 85 */
1633 /* depth 4: 8 */
1634 #endif
1635 if (limit > 256)
1637 /* direct colors & Pdepth > 8 */
1638 if (Pdepth >= 16)
1640 limit = 8192;
1642 else if (Pdepth >= 15)
1644 limit = 4096;
1646 else
1648 limit = 512;
1651 else if (limit == 256)
1653 if (Pvisual->class == GrayScale)
1655 limit = 64;
1657 else if (Pvisual->class == DirectColor)
1659 limit = 32;
1661 else
1663 limit = 68;
1664 /* candidate:
1665 * limit = 54; 4x4x3 + 6 grey
1666 * limit = 61 (named table)
1667 * limit = 85 current XRender default 4cc + 21
1668 * limit = 76 future(?) XRender default 4cc + 16
1669 * limit = 68 4x4x4 + 4
1670 * limit = 64 4x4x4 + 0 */
1674 else if (limit == 128 || limit == 64)
1676 if (Pvisual->class == GrayScale)
1678 limit = 32;
1680 else
1682 limit = 31;
1685 else if (limit >= 16)
1687 if (Pvisual->class == GrayScale)
1689 limit = 8;
1691 else
1693 limit = 10;
1696 else if (limit >= 8)
1698 limit = 4;
1700 else
1702 limit = 2;
1705 if (limit < 2)
1707 limit = 2;
1710 if (Pvisual->class == DirectColor)
1712 /* humm ... Any way this case should never happen in real life:
1713 * DirectColor default colormap! */
1714 PUseDynamicColors = 0;
1715 PAllocTable = 1;
1716 PStrictColorLimit = 1;
1718 if (PAllocTable)
1720 do_allocate = 1;
1722 else
1724 do_allocate = 0;
1727 /* use the named table ? */
1728 if (use_named_table)
1730 i = limit;
1731 while(Pct == NULL && i >= 2)
1733 Pct = alloc_named_ct(&i, do_allocate);
1734 i--;
1737 if (Pct != NULL)
1739 finish_ct_init(
1740 call_type, PColorLimit, 0, 0, 0, 0, 0, 1);
1741 return PColorLimit;
1744 /* color cube or regular grey scale */
1745 i = 0;
1746 while(i < cc_nbr && Pct == NULL)
1748 if ((cc[i][5] & fvwm_type) &&
1749 cc[i][0]*cc[i][1]*cc[i][2] + cc[i][3] - 2*(cc[i][3] > 0) +
1750 (1 << cc[i][4])*(cc[i][4] != 0) <= limit)
1752 Pct = alloc_color_cube(
1753 cc[i][0], cc[i][1], cc[i][2], cc[i][3], cc[i][4],
1754 do_allocate);
1756 i++;
1758 if (Pct != NULL)
1760 i = i-1;
1761 finish_ct_init(
1762 call_type, i, cc[i][0], cc[i][1], cc[i][2], cc[i][3],
1763 cc[i][4], 0);
1764 return PColorLimit;
1767 /* I do not think we can be here */
1768 Pct = alloc_color_cube(0, 0, 0, 0, 1, False);
1769 finish_ct_init(call_type, cc_nbr-1, 0, 0, 0, 0, 1, 0);
1770 if (Pct == NULL)
1772 fprintf(stderr,
1773 "[fvwm] ERR -- Cannot get Black and White. exiting!\n");
1774 exit(2);
1776 return PColorLimit;
1780 * Allocation of a private DirectColor cmap this is broken for depth > 16
1782 static
1783 Bool alloc_direct_colors(int *limit, Bool use_my_color_limit)
1785 unsigned long nr,ng,nb,r,g,b,cr,cg,cf,pr,pg;
1786 unsigned long red_mask, green_mask, blue_mask;
1787 XColor *colors;
1789 if (Pdepth <= 16)
1791 red_mask = Pvisual->red_mask;
1792 green_mask = Pvisual->green_mask;
1793 blue_mask = Pvisual->blue_mask;
1795 else
1797 /* Use a standard depth 16 colormap. This is broken FIXME! */
1798 red_mask = 0xf800;
1799 green_mask = 0x7e0;
1800 blue_mask = 0x1f;
1803 decompose_mask(
1804 red_mask, &Pcsi.red_shift, &Pcsi.red_prec);
1805 decompose_mask(
1806 green_mask, &Pcsi.green_shift, &Pcsi.green_prec);
1807 decompose_mask(
1808 blue_mask, &Pcsi.blue_shift, &Pcsi.blue_prec);
1810 if (!use_my_color_limit)
1812 /* colors allocated by fvwm we can return */
1813 return 1;
1816 nr = 1 << Pcsi.red_prec;
1817 ng = 1 << Pcsi.green_prec;
1818 nb = 1 << Pcsi.blue_prec;
1820 colors = (XColor *)safemalloc(nb*sizeof(XColor));
1821 cf = DoRed|DoBlue|DoGreen;
1822 for (r=0; r<nr; r++)
1824 cr = r * 65535 / (nr - 1);
1825 pr = (cr >> (16 - Pcsi.red_prec)) << Pcsi.red_shift;
1826 for (g = 0; g < ng; g++)
1828 cg = g * 65535 / (ng - 1);
1829 pg = (cg >> (16 - Pcsi.green_prec)) << Pcsi.green_shift;
1830 for (b = 0; b < nb; b++)
1832 colors[b].flags = cf;
1833 colors[b].red = cr;
1834 colors[b].green = cg;
1835 colors[b].blue = b * 65535 / (nb - 1);
1836 colors[b].pixel =
1837 (Pixel)(pr + pg +
1838 ((colors[b].blue >>
1839 (16 - Pcsi.blue_prec)) <<
1840 Pcsi.blue_shift));
1842 XStoreColors(Pdpy, Pcmap, colors, nb);
1845 free(colors);
1846 return 1;
1850 * Init the table for Static Colors
1852 static
1853 void init_static_colors_table(void)
1855 XColor colors[256];
1856 int i;
1857 int nbr_of_colors = min(256, (1 << Pdepth));
1859 PColorLimit = nbr_of_colors;
1860 Pct = (PColor *)safemalloc((nbr_of_colors+1) * sizeof(PColor));
1861 for (i = 0; i < nbr_of_colors; i++)
1863 colors[i].pixel = Pct[i].color.pixel = i;
1865 XQueryColors(Pdpy, Pcmap, colors, nbr_of_colors);
1866 for (i = 0; i < nbr_of_colors; i++)
1868 Pct[i].color.red = colors[i].red;
1869 Pct[i].color.green = colors[i].green;
1870 Pct[i].color.blue = colors[i].blue;
1871 Pct[i].alloc_count = 1;
1873 Pct[PColorLimit].color.red = Pct[PColorLimit-1].color.red;
1874 Pct[PColorLimit].color.green = Pct[PColorLimit-1].color.green;
1875 Pct[PColorLimit].color.blue = Pct[PColorLimit-1].color.blue;
1876 Pct[PColorLimit].alloc_count = 1;
1877 create_mapping_table(0, 0, 0, 0, 0, True);
1882 * misc local functions
1884 static
1885 void print_colormap(Colormap cmap)
1887 XColor colors[256];
1888 int i;
1889 int nbr_of_colors = max(256, (1 << Pdepth));
1890 for (i = 0; i < nbr_of_colors; i++)
1892 colors[i].pixel = i;
1894 XQueryColors(Pdpy, cmap, colors, nbr_of_colors);
1895 for (i = 0; i < nbr_of_colors; i++)
1897 fprintf(stderr," rgb(%.3i): %.3i/%.3i/%.3i\n", i,
1898 colors[i].red >> 8,
1899 colors[i].green >> 8,
1900 colors[i].blue >> 8);
1904 /* ---------------------------- interface functions ------------------------ */
1906 int PictureAllocColor(Display *dpy, Colormap cmap, XColor *c, int no_limit)
1908 if (PStrictColorLimit && Pct != NULL)
1910 no_limit = 0;
1913 if (no_limit)
1915 return Pcsi.alloc_color_no_limit(dpy, cmap, c);
1917 else
1919 return Pcsi.alloc_color(dpy, cmap, c);
1921 return 0;
1925 int PictureAllocColorAllProp(
1926 Display *dpy, Colormap cmap, XColor *c, int x, int y,
1927 Bool no_limit, Bool is_8, Bool do_dither)
1930 if (!no_limit && do_dither && Pcsi.alloc_color_dither != NULL)
1932 if (!is_8)
1934 c->red = c->red >> 8;
1935 c->green = c->green >> 8;
1936 c->blue = c->blue >> 8;
1938 return Pcsi.alloc_color_dither(dpy, cmap, c, x, y);
1940 else
1942 if (is_8)
1944 c->red = c->red << 8;
1945 c->green = c->green << 8;
1946 c->blue = c->blue << 8;
1948 return PictureAllocColor(dpy, cmap, c, False);
1950 return 0;
1953 int PictureAllocColorImage(
1954 Display *dpy, PictureImageColorAllocator *pica, XColor *c, int x, int y)
1956 int r;
1958 r = PictureAllocColorAllProp(
1959 dpy, pica->cmap, c, x, y,
1960 pica->no_limit, pica->is_8, pica->dither);
1961 if (r && pica->pixels_table != NULL && pica->pixels_table_size &&
1962 c->pixel < pica->pixels_table_size)
1964 pica->pixels_table[c->pixel]++;
1966 return r;
1969 PictureImageColorAllocator *PictureOpenImageColorAllocator(
1970 Display *dpy, Colormap cmap, int x, int y, Bool no_limit,
1971 Bool do_not_save_pixels, int dither, Bool is_8)
1973 PictureImageColorAllocator *pica;
1974 Bool do_save_pixels = False;
1976 pica = (PictureImageColorAllocator *)safemalloc(
1977 sizeof(PictureImageColorAllocator));
1978 if (Pdepth <= 8 && !do_not_save_pixels && (Pvisual->class & 1) &&
1979 ((PUseDynamicColors && Pct) || no_limit))
1981 int s = 1 << Pdepth;
1982 pica->pixels_table = (unsigned long *)safecalloc(
1983 s, sizeof(unsigned long));
1984 pica->pixels_table_size = s;
1985 do_save_pixels = True;
1987 if (!do_save_pixels)
1989 pica->pixels_table = NULL;
1990 pica->pixels_table_size = 0;
1992 pica->is_8 = is_8;
1993 if (dither && Pdepth <= 16)
1995 pica->dither = dither;
1997 else
1999 pica->dither = dither;
2001 pica->no_limit = no_limit;
2002 pica->cmap = cmap;
2003 return pica;
2006 void PictureCloseImageColorAllocator(
2007 Display *dpy, PictureImageColorAllocator *pica,
2008 int *nalloc_pixels, Pixel **alloc_pixels, Bool *no_limit)
2010 if (nalloc_pixels)
2012 *nalloc_pixels = 0;
2014 if (alloc_pixels != NULL)
2016 *alloc_pixels = NULL;
2018 if (no_limit != NULL)
2020 *no_limit = 0;
2022 if (pica->pixels_table)
2024 int i,j;
2025 int k = 0, l = 0;
2026 unsigned int np = 0;
2027 int free_num = 0;
2028 Pixel *free_pixels = NULL;
2029 Pixel *save_pixels = NULL;
2031 for(i = 0; i < pica->pixels_table_size; i++)
2033 if (pica->pixels_table[i])
2035 free_num += (pica->pixels_table[i]-1);
2036 np++;
2039 if (free_num)
2041 free_pixels = (Pixel *)safemalloc(
2042 free_num * sizeof(Pixel));
2044 if (np && nalloc_pixels != NULL && alloc_pixels != NULL)
2046 save_pixels = (Pixel *)safemalloc(np * sizeof(Pixel));
2048 for(i = 0; i < pica->pixels_table_size; i++)
2050 if (pica->pixels_table[i])
2052 if (save_pixels)
2054 save_pixels[k++] = i;
2056 for(j=1; j < pica->pixels_table[i]; j++)
2058 free_pixels[l++] = i;
2062 if (free_num)
2064 PictureFreeColors(
2065 dpy, pica->cmap, free_pixels, free_num, 0,
2066 pica->no_limit);
2067 free(free_pixels);
2069 if (nalloc_pixels != NULL && alloc_pixels != NULL)
2071 *nalloc_pixels = np;
2072 *alloc_pixels = save_pixels;
2073 if (no_limit != NULL)
2075 *no_limit = pica->no_limit;
2078 else if (save_pixels)
2080 free(save_pixels);
2082 free(pica->pixels_table);
2084 free(pica);
2085 return;
2088 void PictureFreeColors(
2089 Display *dpy, Colormap cmap, Pixel *pixels, int n,
2090 unsigned long planes, Bool no_limit)
2092 if (no_limit)
2094 if (Pcsi.free_colors_no_limit != NULL)
2096 Pcsi.free_colors_no_limit(
2097 dpy, cmap, pixels, n, planes);
2100 else
2102 if (Pcsi.free_colors != NULL)
2104 Pcsi.free_colors(dpy, cmap, pixels, n, planes);
2107 return;
2110 Pixel PictureGetNextColor(Pixel p, int n)
2112 int i;
2113 XColor c;
2115 if (n >= 0)
2116 n = 1;
2117 else
2118 n = -1;
2120 if (Pct == NULL)
2122 return p;
2124 for(i=0; i<PColorLimit; i++)
2126 if (Pct[i].color.pixel == p)
2128 if (i == 0 && n < 0)
2130 c = Pct[PColorLimit-1].color;
2131 alloc_color_in_pct(&c, PColorLimit-1);
2132 return Pct[PColorLimit-1].color.pixel;
2134 else if (i == PColorLimit-1 && n > 0)
2136 c = Pct[0].color;
2137 alloc_color_in_pct(&c, 0);
2138 return Pct[0].color.pixel;
2140 else
2142 c = Pct[i+n].color;
2143 alloc_color_in_pct(&c, i+n);
2144 return Pct[i+n].color.pixel;
2148 return p;
2151 /* Replace the color in my_color by the closest matching color
2152 from base_table */
2153 void PictureReduceColorName(char **my_color)
2155 int index;
2156 XColor rgb; /* place to calc rgb for each color in xpm */
2158 if (!XpmSupport)
2159 return;
2161 if (!strcasecmp(*my_color,"none")) {
2162 return; /* do not substitute the "none" color */
2165 if (!XParseColor(Pdpy, Pcmap, *my_color, &rgb))
2167 fprintf(stderr,"color_to_rgb: can't parse color %s\n",
2168 *my_color);
2170 index = get_color_index(rgb.red,rgb.green,rgb.blue, False);
2171 /* Finally: replace the color string by the newly determined color
2172 * string */
2173 free(*my_color); /* free old color */
2174 /* area for new color */
2175 *my_color = safemalloc(8);
2176 sprintf(*my_color,"#%x%x%x",
2177 Pct[index].color.red >> 8,
2178 Pct[index].color.green >> 8,
2179 Pct[index].color.blue >> 8); /* put it there */
2180 return;
2183 Bool PictureDitherByDefault(void)
2185 if (Pct != NULL)
2187 return True;
2189 return False;
2192 Bool PictureUseBWOnly(void)
2194 if (Pdepth < 2 || (PStrictColorLimit && PColorLimit == 2))
2196 return True;
2198 return False;
2201 int PictureInitColors(
2202 int call_type, Bool init_color_limit, PictureColorLimitOption *opt,
2203 Bool use_my_color_limit, Bool init_dither)
2205 Bool dither_ok = False;
2207 switch (Pvisual->class)
2209 case DirectColor:
2210 /* direct colors is more or less broken */
2211 decompose_mask(
2212 Pvisual->red_mask, &Pcsi.red_shift,
2213 &Pcsi.red_prec);
2214 decompose_mask(
2215 Pvisual->green_mask, &Pcsi.green_shift,
2216 &Pcsi.green_prec);
2217 decompose_mask(
2218 Pvisual->blue_mask, &Pcsi.blue_shift,
2219 &Pcsi.blue_prec);
2220 Pcsi.alloc_color_no_limit = alloc_color_proportion;
2221 Pcsi.alloc_color = alloc_color_proportion;
2222 Pcsi.alloc_color_dither = alloc_color_proportion_dither;
2223 Pcsi.free_colors_no_limit = NULL;
2224 Pcsi.free_colors = NULL;
2225 PColorLimit = 0;
2226 break;
2227 case TrueColor:
2228 decompose_mask(
2229 Pvisual->red_mask, &Pcsi.red_shift,
2230 &Pcsi.red_prec);
2231 decompose_mask(
2232 Pvisual->green_mask, &Pcsi.green_shift,
2233 &Pcsi.green_prec);
2234 decompose_mask(
2235 Pvisual->blue_mask, &Pcsi.blue_shift,
2236 &Pcsi.blue_prec);
2237 Pcsi.alloc_color_no_limit = alloc_color_proportion;
2238 Pcsi.alloc_color = alloc_color_proportion;
2239 Pcsi.free_colors_no_limit = NULL;
2240 Pcsi.free_colors = NULL;
2241 PColorLimit = 0;
2242 if (init_dither && (Pdepth == 15 || Pdepth == 16))
2244 dither_ok = my_dither_depth_15_16_init();
2246 if (dither_ok)
2248 Pcsi.alloc_color_dither = alloc_color_proportion_dither;
2250 else
2252 Pcsi.alloc_color_dither = NULL;
2254 break;
2255 case StaticColor:
2256 if (0 && Pvisual->red_mask != 0 && Pvisual->green_mask != 0 &&
2257 Pvisual->blue_mask != 0)
2259 decompose_mask(
2260 Pvisual->red_mask, &Pcsi.red_shift,
2261 &Pcsi.red_prec);
2262 decompose_mask(
2263 Pvisual->green_mask, &Pcsi.green_shift,
2264 &Pcsi.green_prec);
2265 decompose_mask(
2266 Pvisual->blue_mask, &Pcsi.blue_shift,
2267 &Pcsi.blue_prec);
2268 Pcsi.alloc_color_no_limit = alloc_color_proportion;
2269 Pcsi.alloc_color = alloc_color_proportion;
2270 PColorLimit = 0;
2272 else
2274 if (init_color_limit)
2276 Pcsi.alloc_color = alloc_color_in_table;
2277 Pcsi.alloc_color_dither =
2278 alloc_color_in_table_dither;
2279 Pcsi.alloc_color_no_limit = alloc_color_x;
2280 init_static_colors_table();
2282 else
2284 Pcsi.alloc_color = alloc_color_x;
2285 Pcsi.alloc_color_dither = NULL;
2286 Pcsi.alloc_color_no_limit = alloc_color_x;
2289 Pcsi.free_colors_no_limit = NULL;
2290 Pcsi.free_colors = NULL;
2291 break;
2292 case StaticGray:
2293 /* FIXME: we assume that we have a regular grey ramp */
2294 if (0)
2296 Pcsi.alloc_color_no_limit = alloc_color_proportion_grey;
2297 Pcsi.alloc_color = alloc_color_proportion;
2298 PColorLimit = 0;
2300 else
2302 if (init_color_limit)
2304 Pcsi.alloc_color = alloc_color_in_table;
2305 Pcsi.alloc_color_dither =
2306 alloc_color_in_table_dither;
2307 Pcsi.alloc_color_no_limit = alloc_color_x;
2308 init_static_colors_table();
2310 else
2312 Pcsi.alloc_color = alloc_color_x;
2313 Pcsi.alloc_color_dither = NULL;
2314 Pcsi.alloc_color_no_limit = alloc_color_x;
2317 Pcsi.free_colors_no_limit = NULL;
2318 Pcsi.free_colors = NULL;
2319 break;
2320 case PseudoColor:
2321 case GrayScale:
2322 default:
2323 Pcsi.alloc_color_no_limit = alloc_color_dynamic_no_limit;
2324 Pcsi.free_colors_no_limit = free_colors_x;
2325 break;
2328 if (!(Pvisual->class & 1))
2330 /* static classes */
2331 PUseDynamicColors = 0;
2332 if (call_type == PICTURE_CALLED_BY_FVWM &&
2333 getenv("FVWM_COLORTABLE_TYPE") != NULL)
2335 flib_putenv("FVWM_COLORTABLE_TYPE", "");
2337 return PColorLimit;
2340 /* dynamic classes */
2342 if (!Pdefault && Pvisual->class == DirectColor)
2344 PColorLimit = 0;
2345 PUseDynamicColors = 0;
2346 alloc_direct_colors(0, use_my_color_limit);
2347 if (call_type == PICTURE_CALLED_BY_FVWM &&
2348 getenv("FVWM_COLORTABLE_TYPE") != NULL)
2350 flib_putenv("FVWM_COLORTABLE_TYPE", "");
2352 return 0;
2356 if (init_color_limit)
2358 Pcsi.alloc_color = alloc_color_in_table;
2359 Pcsi.alloc_color_dither = alloc_color_in_table_dither;
2360 PictureAllocColorTable(opt, call_type, use_my_color_limit);
2361 if (PUseDynamicColors)
2363 Pcsi.free_colors = free_colors_in_table;
2365 else
2367 Pcsi.free_colors = NULL;
2370 else
2372 Pcsi.alloc_color = alloc_color_dynamic_no_limit;
2373 Pcsi.free_colors = free_colors_x;
2374 Pcsi.alloc_color_dither = NULL;
2376 return PColorLimit;
2379 void PicturePrintColorInfo(int verbose)
2381 unsigned long nbr_of_colors = 1 << Pdepth;
2383 fprintf(stderr, "fvwm info on colors\n");
2384 fprintf(stderr, " Visual ID: 0x%x, Default?: %s, Class: ",
2385 (int)(Pvisual->visualid),
2386 (Pdefault)? "Yes":"No");
2387 if (Pvisual->class == TrueColor)
2389 fprintf(stderr,"TrueColor");
2391 else if (Pvisual->class == PseudoColor)
2393 fprintf(stderr,"PseudoColor");
2395 else if (Pvisual->class == DirectColor)
2397 fprintf(stderr,"DirectColor");
2399 else if (Pvisual->class == StaticColor)
2401 fprintf(stderr,"StaticColor");
2403 else if (Pvisual->class == GrayScale)
2405 fprintf(stderr,"GrayScale");
2407 else if (Pvisual->class == StaticGray)
2409 fprintf(stderr,"StaticGray");
2411 fprintf(stderr, "\n");
2412 fprintf(stderr, " Depth: %i, Number of colors: %lu",
2413 Pdepth, (unsigned long)nbr_of_colors);
2414 if (Pct != NULL)
2416 fprintf(stderr,"\n Pallet with %i colors", PColorLimit);
2417 if (Pvisual->class & 1)
2419 fprintf(stderr,", Number of free colors: %i\n",
2420 get_nbr_of_free_colors((1 << Pdepth)));
2421 fprintf(stderr,
2422 " Auto Detected: %s, Strict: %s, Allocated: %s,"
2423 " Dynamic: %s\n",
2424 (Pcsi.pre_allocated_pallet)? "Yes":"No",
2425 (PStrictColorLimit)? "Yes":"No",
2426 (PAllocTable)? "Yes":"No",
2427 (PUseDynamicColors)? "Yes":"No");
2429 else
2431 fprintf(stderr," (default colormap)\n");
2433 if (PColorLimit <= 256)
2435 int i;
2436 int count = 0;
2437 int count_alloc = 0;
2439 if (verbose)
2441 fprintf(stderr," The fvwm colors table:\n");
2443 for (i = 0; i < PColorLimit; i++)
2445 if (verbose)
2447 fprintf(
2448 stderr,
2449 " rgb:%.3i/%.3i/%.3i\t%lu\n",
2450 Pct[i].color.red >> 8,
2451 Pct[i].color.green >> 8,
2452 Pct[i].color.blue >> 8,
2453 Pct[i].alloc_count);
2455 if (Pct[i].alloc_count)
2457 count++;
2460 if ((Pvisual->class & 1) && Pac != NULL)
2462 if (verbose)
2464 fprintf(stderr," fvwm colors not in"
2465 " the table:\n");
2467 for(i=0; i < nbr_of_colors; i++)
2469 int j = 0;
2470 Bool found = False;
2472 if (!Pac[i].alloc_count)
2473 continue;
2474 while(j < PColorLimit && !found)
2476 if (i == Pct[j].color.pixel)
2478 found = True;
2480 j++;
2482 if (found)
2483 continue;
2484 count_alloc++;
2485 if (verbose)
2487 fprintf(
2488 stderr,
2489 " rgb:"
2490 "%.3i/%.3i/%.3i\t%lu\n",
2491 Pac[i].color.red >> 8,
2492 Pac[i].color.green >> 8,
2493 Pac[i].color.blue >> 8,
2494 Pac[i].alloc_count);
2497 if (verbose && count_alloc == 0)
2499 if (verbose)
2501 fprintf(stderr," None\n");
2505 if (Pvisual->class & 1)
2507 fprintf(stderr,
2508 " Number of colours used by fvwm:\n");
2509 fprintf(stderr,
2510 " In the table: %i\n", count);
2511 fprintf(
2512 stderr, " Out of the table: %i\n",
2513 count_alloc);
2514 fprintf(stderr,
2515 " Total: %i\n", count_alloc+count);
2519 else
2521 if (Pvisual->class == DirectColor)
2523 fprintf(stderr, ", Pseudo Pallet with: %i colors\n",
2524 (1 << Pcsi.red_prec)*(1 << Pcsi.green_prec)*
2525 (1 << Pcsi.blue_prec));
2527 else
2529 fprintf(stderr, ", No Pallet (static colors)\n");
2531 fprintf(stderr, " red: %i, green: %i, blue %i\n",
2532 1 << Pcsi.red_prec, 1 << Pcsi.green_prec,
2533 1 << Pcsi.blue_prec);
2534 if (verbose && Pdepth <= 8)
2536 if (Pvisual->class == DirectColor)
2538 fprintf(stderr, " Colormap:\n");
2540 else
2542 fprintf(stderr,
2543 " Static Colormap used by fvwm:\n");
2545 print_colormap(Pcmap);
2549 if (Pdepth <= 8 && verbose >= 2)
2551 fprintf(stderr,"\n Default Colormap:\n");
2552 print_colormap(DefaultColormap(Pdpy,DefaultScreen(Pdpy)));