* FvwmTheme/FvwmTheme.1: Language check, general edits,
[fvwm.git] / libs / PictureUtils.c
blob3480694356220cde0759f5d11e3f374308134272
1 /* -*-c-*- */
2 /* Copyright (C) 1993, Robert Nation
3 * Copyright (C) 2002 Olivier Chapuis
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 /* ---------------------------- included header files ----------------------- */
22 #include "config.h"
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <signal.h>
27 #include <ctype.h>
28 #include <time.h>
29 #include <math.h>
31 #include <X11/Xlib.h>
32 #include <X11/Xmd.h>
34 #include <fvwmlib.h>
35 #include "PictureBase.h"
36 #include "PictureUtils.h"
37 #include "PictureDitherMatrice.h"
39 /* ---------------------------- local definitions and macro ------------------ */
41 #define PICTURE_DEBUG_COLORS_ALLOC_FAILURE 0
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
52 #define SQUARE(X) ((X)*(X))
54 #define TRUE_DIST(r1,g1,b1,r2,g2,b2) (long)\
55 (SQUARE((long)((r1 - r2)>>8)) \
56 + SQUARE((long)((g1 - g2)>>8)) \
57 + SQUARE((long)((b1 - b2)>>8)))
59 #define FAST_DIST(r1,g1,b1,r2,g2,b2) (long)\
60 (abs((long)(r1 - r2)) \
61 + abs((long)(g1 - g2)) \
62 + abs((long)(b1 - b2)))
64 #define FVWM_DIST(r1,g1,b1,r2,g2,b2) \
65 (abs(r1 - r2) + abs(g1 - g2) + abs(b1 - b2) \
66 + 2*abs(abs(r1-g1) + abs(g1-b1) + abs(r1-b1) \
67 - abs(r2-g2) - abs(g2-b2) - abs(r2-b2)))
69 #define USED_DIST(r1,g1,b1,r2,g2,b2) FVWM_DIST(r1,g1,b1,r2,g2,b2)
71 #define PICTURE_COLOR_CLOSENESS USED_DIST(3,3,3,0,0,0)
73 #define PICTURE_PAllocTable 1000000
74 #define PICTURE_PUseDynamicColors 100000
75 #define PICTURE_PStrictColorLimit 10000
76 #define PICTURE_use_named 1000
77 #define PICTURE_TABLETYPE_LENGHT 7
79 /* humm ... dither is probably borken with gamma correction. Anyway I do
80 * do think that using gamma correction for the colors cubes is a good
81 * idea */
82 #define USE_GAMMA_CORECTION 0
83 /* 2.2 is recommanded by the Poynon colors FAQ, some others suggest 1.5 and 2
84 * Use float constants!*/
85 #define COLOR_GAMMA 1.5
86 #define GREY_GAMMA 2.0
88 /* ---------------------------- imports ------------------------------------- */
90 /* ---------------------------- included code files ------------------------- */
92 /* ---------------------------- local types --------------------------------- */
94 typedef struct
96 XColor color; /* rgb color info */
97 unsigned long alloc_count; /* nbr of allocation */
98 } PColor;
100 typedef struct
103 * info for colors table (depth <= 8)
105 /* color cube used */
106 short nr;
107 short ng;
108 short nb;
109 short ngrey;
110 /* grey palette def, nbr of grey = 2^grey_bits */
111 short grey_bits;
112 /* color cube used for dithering with the named table */
113 short d_nr;
114 short d_ng;
115 short d_nb;
116 short d_ngrey_bits;
117 /* do we found a pre-allocated pallet ? */
118 Bool pre_allocated_pallet;
119 /* info for depth > 8 */
120 int red_shift;
121 int green_shift;
122 int blue_shift;
123 int red_prec;
124 int green_prec;
125 int blue_prec;
126 /* for dithering in depth 15 and 16 */
127 unsigned short *red_dither;
128 unsigned short *green_dither;
129 unsigned short *blue_dither;
130 /* colors allocation function */
131 int (*alloc_color)();
132 int (*alloc_color_no_limit)();
133 int (*alloc_color_dither)();
134 void (*free_colors)();
135 void (*free_colors_no_limit)();
136 } PColorsInfo;
138 typedef struct {
139 int cols_index;
140 long closeness;
141 } CloseColor;
143 /* ---------------------------- forward declarations ------------------------ */
145 /* ---------------------------- local variables ----------------------------- */
147 static int PColorLimit = 0;
148 static PColor *Pct = NULL;
149 static PColor *Pac = NULL;
150 static short *PMappingTable = NULL;
151 static short *PDitherMappingTable = NULL;
152 static Bool PStrictColorLimit = 0;
153 static Bool PAllocTable = 0;
154 static PColorsInfo Pcsi = {
155 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL,
156 NULL, NULL, NULL, NULL};
158 /* ---------------------------- exported variables (globals) ---------------- */
160 /* ---------------------------- local functions ----------------------------- */
162 /* ***************************************************************************
163 * get shift and prec from a mask
164 * ***************************************************************************/
165 static
166 void decompose_mask(
167 unsigned long mask, int *shift, int *prec)
169 *shift = 0;
170 *prec = 0;
172 while (!(mask & 0x1))
174 (*shift)++;
175 mask >>= 1;
178 while (mask & 0x1)
180 (*prec)++;
181 mask >>= 1;
185 /* ***************************************************************************
186 * color allocation in the colormap. strongly inspired by SetCloseColor from
187 * the Xpm library (depth <= 8)
188 * ***************************************************************************/
190 static int
191 closeness_cmp(const void *a, const void *b)
193 CloseColor *x = (CloseColor *) a, *y = (CloseColor *) b;
195 /* cast to int as qsort requires */
196 return (int) (x->closeness - y->closeness);
199 static
200 int alloc_color_in_cmap(XColor *c, Bool force)
202 static XColor colors[256];
203 CloseColor closenesses[256];
204 XColor tmp;
205 int i,j;
206 int map_entries = (Pvisual->class == DirectColor)?
207 (1 << Pdepth) : Pvisual->map_entries;
208 time_t current_time;
209 time_t last_time = 0;
211 map_entries = (map_entries > 256)? 256:map_entries;
212 current_time = time(NULL);
213 if (current_time - last_time >= 2 || force)
215 last_time = current_time;
216 for (i = 0; i < map_entries; i++)
218 colors[i].pixel = i;
220 XQueryColors(Pdpy, Pcmap, colors, map_entries);
222 for(i = 0; i < map_entries; i++)
224 closenesses[i].cols_index = i;
225 closenesses[i].closeness = USED_DIST(
226 (int)(c->red),
227 (int)(c->green),
228 (int)(c->blue),
229 (int)(colors[i].red),
230 (int)(colors[i].green),
231 (int)(colors[i].blue));
233 qsort(closenesses, map_entries, sizeof(CloseColor), closeness_cmp);
235 i = 0;
236 j = closenesses[i].cols_index;
237 while (force ||
238 (abs((long)c->red - (long)colors[j].red) <=
239 PICTURE_COLOR_CLOSENESS &&
240 abs((long)c->green - (long)colors[j].green) <=
241 PICTURE_COLOR_CLOSENESS &&
242 abs((long)c->blue - (long)colors[j].blue) <=
243 PICTURE_COLOR_CLOSENESS))
245 tmp.red = colors[j].red;
246 tmp.green = colors[j].green;
247 tmp.blue = colors[j].blue;
248 if (XAllocColor(Pdpy, Pcmap, &tmp))
250 c->red = tmp.red;
251 c->green = tmp.green;
252 c->blue = tmp.blue;
253 c->pixel = tmp.pixel;
254 return 1;
256 else
258 i++;
259 if (i == map_entries)
260 break;
261 j = closenesses[i].cols_index;
264 return 0;
267 /* ***************************************************************************
268 * dithering
269 * ***************************************************************************/
271 static
272 int my_dither(int x, int y, XColor *c)
274 /* the dither matrice */
275 static const char DM[128][128] = DITHER_MATRICE;
276 int index;
277 const char *dmp;
279 if (Pcsi.grey_bits != 0)
281 /* Grey Scale */
282 int prec = Pcsi.grey_bits;
284 if (Pcsi.grey_bits == 1)
286 /* FIXME, can we do a better dithering */
287 prec = 2;
289 dmp = DM[(0 + y) & (DM_HEIGHT - 1)];
290 index = (c->green + ((c->blue + c->red) >> 1)) >> 1;
291 index += (dmp[(0 + x) & (DM_WIDTH - 1)] << 2) >> prec;
292 index = (index - (index >> prec));
293 index = index >> (8 - Pcsi.grey_bits);
295 else
297 /* color cube */
298 int dith, rs, gs, bs, gb, b;
299 int tr,tb,tg;
301 rs = Pcsi.d_nr - 1;
302 gs = Pcsi.d_ng - 1;
303 bs = Pcsi.d_nb - 1;
304 gb = Pcsi.d_ng*Pcsi.d_nb;
305 b = Pcsi.d_nb;
307 dmp = DM[(0 + y) & (DM_HEIGHT - 1)];
308 dith = (dmp[(0 + x) & (DM_WIDTH - 1)] << 2) | 7;
309 tr = ((c->red * rs) + dith) >> 8;
310 tg = ((c->green * gs) + (262 - dith)) >> 8;
311 tb = ((c->blue * bs) + dith) >> 8;
312 index = tr * gb + tg * b + tb;
313 #if 0
314 /* try to use the additonal grey. Not easy, good for
315 * certain image/gradient bad for others */
316 if (Pcsi.d_ngrey_bits)
318 int g_index;
320 /* dither in the Pcsi.ngrey^3 cc */
321 tr = ((c->red * (Pcsi.ngrey-1)) + dith) >> 8;
322 tg = ((c->green * (Pcsi.ngrey-1)) + (262 - dith)) >> 8;
323 tb = ((c->blue * (Pcsi.ngrey-1)) + dith) >> 8;
324 /* get the grey */
325 fprintf(stderr, "%i,%i,%i(%i/%i) ", tr,tg,tb,
326 abs(tr-tg) + abs(tb-tg) + abs(tb-tr),Pcsi.ngrey);
327 g_index = ((tr + tg + tb)/3);
328 if (g_index != 0 && g_index != Pcsi.ngrey-1 &&
329 abs(tr-tg) + abs(tb-tg) + abs(tb-tr) <=
330 Pcsi.d_ngrey_bits)
332 g_index = g_index + Pcsi.ng*Pcsi.nb*Pcsi.ng -1;
333 index = g_index;
336 #endif
337 if (PDitherMappingTable != NULL)
339 index = PDitherMappingTable[index];
342 return index;
345 static
346 int my_dither_depth_15_16_init(void)
348 const unsigned char _dither_44[4][4] =
350 {0, 4, 1, 5},
351 {6, 2, 7, 3},
352 {1, 5, 0, 4},
353 {7, 3, 6, 2}
355 int y,x,i;
356 int rm = 0xf8, re = 0x7, gm = 0xfc, ge = 0x3, bm = 0xf8, be = 0x7;
358 if (Pdepth == 16 && (Pvisual->red_mask == 0xf800) &&
359 (Pvisual->green_mask == 0x7e0) &&
360 (Pvisual->blue_mask == 0x1f))
362 /* ok */
364 else if (Pdepth == 15 && (Pvisual->red_mask == 0x7c00) &&
365 (Pvisual->green_mask == 0x3e0) &&
366 (Pvisual->blue_mask == 0x1f))
368 gm = 0xf8; ge = 0x7;
370 else
372 return 0; /* fail */
375 Pcsi.red_dither =
376 (unsigned short *)safemalloc(4*4*256*sizeof(unsigned short));
377 Pcsi.green_dither =
378 (unsigned short *)safemalloc(4*4*256*sizeof(unsigned short));
379 Pcsi.blue_dither =
380 (unsigned short *)safemalloc(4*4*256*sizeof(unsigned short));
382 for (y = 0; y < 4; y++)
384 for (x = 0; x < 4; x++)
386 for (i = 0; i < 256; i++)
388 if ((_dither_44[x][y] < (i & re)) &&
389 (i < (256 - 8)))
391 Pcsi.red_dither[
392 (x << 10) | (y << 8) | i] =
393 ((i + 8) & rm) << 8;
395 else
397 Pcsi.red_dither[
398 (x << 10) | (y << 8) | i] =
399 (i & rm) << 8;
401 if ((_dither_44[x][y] < ((i & ge) << 1))
402 && (i < (256 - 4)))
404 Pcsi.green_dither[
405 (x << 10) | (y << 8) | i] =
406 ((i + 4) & gm) << 8;
408 else
410 Pcsi.green_dither[
411 (x << 10) | (y << 8) | i] =
412 (i & gm) << 8;
414 if ((_dither_44[x][y] < (i & be)) &&
415 (i < (256 - 8)))
417 Pcsi.blue_dither[
418 (x << 10) | (y << 8) | i] =
419 ((i + 8) & bm) << 8;
421 else
423 Pcsi.blue_dither[
424 (x << 10) | (y << 8) | i] =
425 (i & bm) << 8;
430 return 1;
433 /* ***************************************************************************
434 * Color allocation in the "palette"
435 * ***************************************************************************/
437 static
438 int alloc_color_in_pct(XColor *c, int index)
440 if (Pct[index].alloc_count == 0)
442 int s = PStrictColorLimit;
444 PStrictColorLimit = 0;
445 c->red = Pct[index].color.red;
446 c->green = Pct[index].color.green;
447 c->blue = Pct[index].color.blue;
448 PictureAllocColor(Pdpy, Pcmap, c, True); /* WARN (rec) */
449 Pct[index].color.pixel = c->pixel;
450 Pct[index].alloc_count = 1;
451 PStrictColorLimit = s;
453 else
455 c->red = Pct[index].color.red;
456 c->green = Pct[index].color.green;
457 c->blue = Pct[index].color.blue;
458 c->pixel = Pct[index].color.pixel;
459 if (Pct[index].alloc_count < 0xffffffff)
460 (Pct[index].alloc_count)++;
462 return 1;
465 static
466 int get_color_index(int r, int g, int b, int is_8)
468 int index;
470 if (!is_8)
472 r= r >> 8;
473 g= g >> 8;
474 b= b >> 8;
476 if (Pcsi.grey_bits > 0)
478 /* FIXME: Use other proporition ? */
479 index = ((r+g+b)/3) >> (8 - Pcsi.grey_bits);
481 else
483 #if 1
484 /* "exact" computation (corrected linear dist) */
485 float fr,fg,fb;
486 int ir, ig, ib;
488 /* map to the cube */
489 fr = ((float)r * (Pcsi.nr-1))/255;
490 fg = ((float)g * (Pcsi.ng-1))/255;
491 fb = ((float)b * (Pcsi.nb-1))/255;
493 if (PMappingTable != NULL)
495 ir = (int)fr + (fr - (int)fr > 0.5);
496 ig = (int)fg + (fg - (int)fg > 0.5);
497 ib = (int)fb + (fb - (int)fb > 0.5);
499 index = ir * Pcsi.ng*Pcsi.nb + ig * Pcsi.nb + ib;
501 else
503 /* found the best of the 8 linear closest points */
504 int lr,lg,lb,tr,tg,tb,best_dist = -1,i,d;
506 index = 0;
507 lr = min((int)fr+1,Pcsi.nr-1);
508 lg = min((int)fg+1,Pcsi.ng-1);
509 lb = min((int)fb+1,Pcsi.nb-1);
510 for(tr =(int)fr; tr<=lr; tr++)
512 for(tg =(int)fg; tg<=lg; tg++)
514 for(tb =(int)fb; tb<=lb; tb++)
516 i = tr * Pcsi.ng*Pcsi.nb +
517 tg * Pcsi.nb +
519 d = USED_DIST(
520 r,g,b,
521 (Pct[i].color.red>>8),
522 (Pct[i].color.green>>8),
523 (Pct[i].color.blue>>8));
524 if (best_dist == -1 ||
525 d < best_dist)
527 index = i;
528 best_dist = d;
534 /* now found the best grey */
535 if (Pcsi.ngrey - 2 > 0)
537 /* FIXME: speedup this with more than 8 grey */
538 int start = Pcsi.nr*Pcsi.ng*Pcsi.nb;
539 for(i=start; i < start+Pcsi.ngrey-2; i++)
541 d = USED_DIST(
542 r,g,b,
543 (Pct[i].color.red>>8),
544 (Pct[i].color.green>>8),
545 (Pct[i].color.blue>>8));
546 if (d < best_dist)
548 index = i;
549 best_dist = d;
553 return index;
555 #else
556 /* approximation; faster */
557 index = ((r * Pcsi.nr)>>8) * Pcsi.ng*Pcsi.nb +
558 ((g * Pcsi.ng)>>8) * Pcsi.nb +
559 ((b * Pcsi.nb)>>8);
560 #endif
561 if (PMappingTable != NULL)
563 index = PMappingTable[index];
566 return index;
569 /* ***************************************************************************
570 * Main colors allocator
571 * ***************************************************************************/
572 static
573 int alloc_color_proportion(Display *dpy, Colormap cmap, XColor *c)
575 c->pixel = (Pixel)(
576 ((c->red >> (16 - Pcsi.red_prec))<< Pcsi.red_shift) +
577 ((c->green >> (16 - Pcsi.green_prec))<< Pcsi.green_shift) +
578 ((c->blue >> (16 - Pcsi.blue_prec))<< Pcsi.blue_shift)
580 return 1;
583 static
584 int alloc_color_proportion_dither(
585 Display *dpy, Colormap cmap, XColor *c, int x, int y)
587 /* 8 bit colors !! */
588 c->red = Pcsi.red_dither[
589 (((x + 0) & 0x3) << 10) | ((y & 0x3) << 8) |
590 ((c->red) & 0xff)] * 257;
591 c->green = Pcsi.green_dither[
592 (((x + 0) & 0x3) << 10) | ((y & 0x3) << 8) |
593 ((c->green) & 0xff)] * 257;
594 c->blue = Pcsi.blue_dither[
595 (((x + 0) & 0x3) << 10) | ((y & 0x3) << 8) |
596 ((c->blue) & 0xff)] * 257;
597 c->pixel = (Pixel)(
598 ((c->red >> (16 - Pcsi.red_prec)) << Pcsi.red_shift) +
599 ((c->green >> (16 - Pcsi.green_prec))
600 << Pcsi.green_shift) +
601 ((c->blue >> (16 - Pcsi.blue_prec)) << Pcsi.blue_shift)
603 return 1;
606 static
607 int alloc_color_proportion_grey(
608 Display *dpy, Colormap cmap, XColor *c)
610 /* FIXME: is this ok in general? */
611 c->pixel = ((c->red + c->green + c->blue)/3);
612 if (Pdepth < 16)
614 c->pixel = c->pixel >> (16 - Pdepth);
616 return 1;
619 static
620 int alloc_color_in_table(Display *dpy, Colormap cmap, XColor *c)
623 int index = get_color_index(c->red,c->green,c->blue, False);
624 return alloc_color_in_pct(c, index);
627 static
628 int alloc_color_in_table_dither(
629 Display *dpy, Colormap cmap, XColor *c, int x, int y)
631 int index;
632 /* 8 bit colors !! */
633 index = my_dither(x, y, c);
634 return alloc_color_in_pct(c, index);
637 static
638 int alloc_color_dynamic_no_limit(
639 Display *dpy, Colormap cmap, XColor *c)
641 int r = 0;
643 if (XAllocColor(dpy, cmap, c))
645 r = 1;
647 else if (!alloc_color_in_cmap(c, False))
649 XGrabServer(dpy);
650 r = alloc_color_in_cmap(c, True);
651 XUngrabServer(dpy);
653 else
655 r = 1;
657 if (r && Pac != NULL && (c->pixel <= (1 << Pdepth) /* always true*/))
659 Pac[c->pixel].alloc_count++;
660 Pac[c->pixel].color.red = c->red;
661 Pac[c->pixel].color.green = c->green;
662 Pac[c->pixel].color.blue = c->blue;
663 Pac[c->pixel].color.pixel = c->pixel;
665 return r;
668 static
669 int alloc_color_x(
670 Display *dpy, Colormap cmap, XColor *c)
672 return XAllocColor(dpy, cmap, c);
675 static
676 void free_colors_in_table(
677 Display *dpy, Colormap cmap, Pixel *pixels, int n, unsigned long planes,
678 Bool no_limit)
680 Pixel *p;
681 int i,j,do_free;
682 int m = 0;
684 if (!Pct || !PUseDynamicColors)
686 return;
689 p = (Pixel *)safemalloc(n*sizeof(Pixel));
690 for(i= 0; i < n; i++)
692 do_free = 1;
693 for(j=0; j<PColorLimit; j++)
695 if (Pct[j].alloc_count &&
696 Pct[j].alloc_count < 0xffffffff &&
697 pixels[i] == Pct[j].color.pixel)
699 (Pct[j].alloc_count)--;
700 if (Pct[j].alloc_count)
701 do_free = 0;
702 break;
705 if (do_free)
707 p[m++] = pixels[i];
710 if (m > 0)
712 XFreeColors(dpy, cmap, p, m, planes);
714 free(p);
716 return;
719 static
720 void free_colors_x(
721 Display *dpy, Colormap cmap, Pixel *pixels, int n, unsigned long planes,
722 Bool no_limit)
724 XFreeColors(dpy, cmap, pixels, n, planes);
725 if (Pac != NULL)
727 int nbr_colors = (1 << Pdepth);
728 int i;
730 for(i= 0; i < n; i++)
732 if (pixels[i] <= nbr_colors)
734 Pac[pixels[i]].alloc_count--;
740 /* ***************************************************************************
741 * local function for building pallet (dynamic colors, private DirectColor
742 * cmap)
743 * ***************************************************************************/
744 static
745 XColor *build_mapping_colors(int nr, int ng, int nb)
747 int r, g, b, i;
748 XColor *colors;
750 colors = (XColor *)safemalloc(nr*ng*nb * sizeof(XColor));
751 i = 0;
752 for (r = 0; r < nr; r++)
754 for (g = 0; g < ng; g++)
756 for (b = 0; b < nb; b++)
758 colors[i].red =
759 r * 65535 / (nr - 1);
760 colors[i].green =
761 g * 65535 / (ng - 1);
762 colors[i].blue =
763 b * 65535 / (nb - 1);
764 i++;
768 return colors;
771 short *build_mapping_table(int nr, int ng, int nb, Bool use_named)
773 int size = nr*ng*nb;
774 XColor *colors_map;
775 short *Table;
776 int i,j, minind;
777 double mindst = 40000;
778 double dst;
780 colors_map = build_mapping_colors(nr, ng, nb);
781 Table = (short *)safemalloc((size+1) * sizeof(short));
782 for(i=0; i<size; i++)
784 minind = 0;
785 for(j=0; j<PColorLimit; j++)
787 if (use_named)
789 /* for back ward compatibility */
790 dst = TRUE_DIST(colors_map[i].red,
791 colors_map[i].green,
792 colors_map[i].blue,
793 Pct[j].color.red,
794 Pct[j].color.green,
795 Pct[j].color.blue);
797 else
799 dst = USED_DIST(colors_map[i].red,
800 colors_map[i].green,
801 colors_map[i].blue,
802 Pct[j].color.red,
803 Pct[j].color.green,
804 Pct[j].color.blue);
806 if (j == 0 || dst < mindst)
808 mindst=dst;
809 minind=j;
812 Table[i] = minind;
814 Table[size] = Table[size-1];
815 free(colors_map);
816 return Table;
819 static
820 void free_table_colors(PColor *color_table, int npixels)
822 Pixel pixels[256];
823 int i,n=0;
825 if (npixels > 0)
827 for(i = 0; i < npixels; i++)
829 if (color_table[i].alloc_count)
831 pixels[n++] = color_table[i].color.pixel;
833 color_table[i].alloc_count = 0;
835 if (n > 0)
837 XFreeColors(Pdpy, Pcmap, pixels, n, 0);
842 /* FIXME: the DirectColor case */
843 static
844 int get_nbr_of_free_colors(int max_check)
846 int check = 1;
847 Pixel Pixels[256];
848 int map_entries = (Pvisual->class == DirectColor)?
849 (1 << Pdepth):Pvisual->map_entries;
850 if (max_check < 1)
851 return 0;
852 if (map_entries > 256)
854 max_check = 256;
856 max_check = (max_check > map_entries) ? map_entries:max_check;
857 while(1)
859 if (XAllocColorCells(
860 Pdpy, Pcmap, False, NULL, 0, Pixels, check))
862 XFreeColors(Pdpy, Pcmap, Pixels, check, 0);
863 check++;
865 else
867 return check-1;
869 if (check > max_check)
871 return check-1;
874 return check-1;
877 static
878 PColor *alloc_color_cube(
879 int nr, int ng, int nb, int ngrey, int grey_bits, Bool do_allocate)
881 int r, g, b, grey, i, start_grey, end_grey;
882 PColor *color_table;
883 XColor color;
884 int size;
886 size = nr*ng*nb + ngrey + (1 << grey_bits)*(grey_bits != 0);
887 if (grey_bits)
889 ngrey = (1 << grey_bits);
891 if (nr > 0 && ngrey > 0)
893 start_grey = 1;
894 end_grey = ngrey - 1;
895 size = size - 2;
897 else
899 start_grey = 0;
900 end_grey = ngrey;
903 color_table = (PColor *)safemalloc((size+1) * sizeof(PColor));
905 i = 0;
907 #if USE_GAMMA_CORECTION
908 #define CG(x) 65535.0 * pow((x)/65535.0,1/COLOR_GAMMA)
909 #define GG(x) 65535.0 * pow((x)/65535.0,1/GREY_GAMMA)
910 #else
911 #define CG(x) x
912 #define GG(x) x
913 #endif
915 if (nr > 0)
917 for (r = 0; r < nr; r++)
919 for (g = 0; g < ng; g++)
921 for (b = 0; b < nb; b++)
923 color.red = CG(r * 65535 / (nr - 1));
924 color.green = CG(g * 65535 / (ng - 1));
925 color.blue = CG(b * 65535 / (nb - 1));
926 if (do_allocate)
928 if (!XAllocColor(Pdpy, Pcmap,
929 &color))
931 free_table_colors(
932 color_table, i);
933 free(color_table);
934 return NULL;
936 color_table[i].color.pixel =
937 color.pixel;
938 color_table[i].alloc_count = 1;
940 else
942 color_table[i].alloc_count = 0;
944 color_table[i].color.red = color.red;
945 color_table[i].color.green = color.green;
946 color_table[i].color.blue = color.blue;
947 i++;
953 if (ngrey > 0)
955 for (grey = start_grey; grey < end_grey; grey++)
957 color.red = color.green = color.blue =
958 GG(grey * 65535 / (ngrey - 1));
959 if (do_allocate)
961 if (!XAllocColor(Pdpy, Pcmap, &color))
963 free_table_colors(color_table, i);
964 free(color_table);
965 return NULL;
967 color_table[i].color.pixel = color.pixel;
968 color_table[i].alloc_count = 1;
970 else
972 color_table[i].alloc_count = 0;
974 color_table[i].color.red = color.red;
975 color_table[i].color.green = color.green;
976 color_table[i].color.blue = color.blue;
977 i++;
980 color_table[size].color.red = color_table[size-1].color.red;
981 color_table[size].color.green = color_table[size-1].color.green;
982 color_table[size].color.blue = color_table[size-1].color.blue;
983 color_table[size].color.pixel = color_table[size-1].color.pixel;
984 color_table[size].alloc_count = 0;
985 PColorLimit = size;
986 return color_table;
990 static
991 PColor *alloc_named_ct(int *limit, Bool do_allocate)
994 /* First thing in base array are colors probably already in the color map
995 because they have familiar names.
996 I pasted them into a xpm and spread them out so that similar colors are
997 spread out.
998 Toward the end are some colors to fill in the gaps.
999 Currently 61 colors in this list.
1001 char *color_names[] =
1003 "black",
1004 "white",
1005 "grey",
1006 "green",
1007 "blue",
1008 "red",
1009 "cyan",
1010 "yellow",
1011 "magenta",
1012 "DodgerBlue",
1013 "SteelBlue",
1014 "chartreuse",
1015 "wheat",
1016 "turquoise",
1017 "CadetBlue",
1018 "gray87",
1019 "CornflowerBlue",
1020 "YellowGreen",
1021 "NavyBlue",
1022 "MediumBlue",
1023 "plum",
1024 "aquamarine",
1025 "orchid",
1026 "ForestGreen",
1027 "lightyellow",
1028 "brown",
1029 "orange",
1030 "red3",
1031 "HotPink",
1032 "LightBlue",
1033 "gray47",
1034 "pink",
1035 "red4",
1036 "violet",
1037 "purple",
1038 "gray63",
1039 "gray94",
1040 "plum1",
1041 "PeachPuff",
1042 "maroon",
1043 "lavender",
1044 "salmon", /* for peachpuff, orange gap */
1045 "blue4", /* for navyblue/mediumblue gap */
1046 "PaleGreen4", /* for forestgreen, yellowgreen gap */
1047 "#AA7700", /* brick, no close named color */
1048 "#11EE88", /* light green, no close named color */
1049 "#884466", /* dark brown, no close named color */
1050 "#CC8888", /* light brick, no close named color */
1051 "#EECC44", /* gold, no close named color */
1052 "#AAAA44", /* dull green, no close named color */
1053 "#FF1188", /* pinkish red */
1054 "#992299", /* purple */
1055 "#CCFFAA", /* light green */
1056 "#664400", /* dark brown*/
1057 "#AADD99", /* light green */
1058 "#66CCFF", /* light blue */
1059 "#CC2299", /* dark red */
1060 "#FF11CC", /* bright pink */
1061 "#11CC99", /* grey/green */
1062 "#AA77AA", /* purple/red */
1063 "#EEBB77" /* orange/yellow */
1065 int NColors = sizeof(color_names)/sizeof(char *);
1066 int i,rc;
1067 PColor *color_table;
1068 XColor color;
1070 *limit = (*limit > NColors)? NColors: *limit;
1071 color_table = (PColor *)safemalloc((*limit+1) * sizeof(PColor));
1072 for(i=0; i<*limit; i++)
1074 rc=XParseColor(Pdpy, Pcmap, color_names[i], &color);
1075 if (rc==0) {
1076 fprintf(stderr,"color_to_rgb: can't parse color %s,"
1077 " rc %d\n", color_names[i], rc);
1078 free_table_colors(color_table, i);
1079 free(color_table);
1080 return NULL;
1082 if (do_allocate)
1084 if (!XAllocColor(Pdpy, Pcmap, &color))
1086 free_table_colors(color_table, i);
1087 free(color_table);
1088 return NULL;
1090 color_table[i].color.pixel = color.pixel;
1091 color_table[i].alloc_count = 1;
1093 else
1095 color_table[i].alloc_count = 0;
1097 color_table[i].color.red = color.red;
1098 color_table[i].color.green = color.green;
1099 color_table[i].color.blue = color.blue;
1101 color_table[*limit].color.red = color_table[*limit-1].color.red;
1102 color_table[*limit].color.green = color_table[*limit-1].color.green;
1103 color_table[*limit].color.blue = color_table[*limit-1].color.blue;
1104 color_table[*limit].color.pixel = color_table[*limit-1].color.pixel;
1105 color_table[*limit].alloc_count = 0;
1106 PColorLimit = *limit;
1107 return color_table;
1110 static
1111 void create_mapping_table(
1112 int nr, int ng, int nb, int ngrey, int grey_bits,
1113 Bool non_regular_pallet)
1116 Pcsi.grey_bits = 0;
1118 /* initialize dithering colors numbers */
1119 if (!non_regular_pallet)
1121 /* */
1122 Pcsi.d_nr = nr;
1123 Pcsi.d_ng = ng;
1124 Pcsi.d_nb = nb;
1125 Pcsi.d_ngrey_bits = 2;
1126 while((1<<Pcsi.d_ngrey_bits) < ngrey)
1128 Pcsi.d_ngrey_bits++;
1130 if (1<<Pcsi.d_ngrey_bits != ngrey)
1132 Pcsi.d_ngrey_bits = 0;
1134 Pcsi.grey_bits = grey_bits;
1136 else
1138 /* dither table should be small */
1139 Pcsi.grey_bits = 0;
1140 if (PColorLimit <= 9)
1142 Pcsi.d_nr = 3;
1143 Pcsi.d_ng = 3;
1144 Pcsi.d_nb = 3;
1145 Pcsi.d_ngrey_bits = 0;
1147 else if (PColorLimit <= 64)
1149 Pcsi.d_nr = 4;
1150 Pcsi.d_ng = 4;
1151 Pcsi.d_nb = 4;
1152 Pcsi.d_ngrey_bits = 0;
1154 else
1156 Pcsi.d_nr = 8;
1157 Pcsi.d_ng = 8;
1158 Pcsi.d_nb = 8;
1159 Pcsi.d_ngrey_bits = 0;
1161 PDitherMappingTable = build_mapping_table(
1162 Pcsi.d_nr, Pcsi.d_ng, Pcsi.d_nb, non_regular_pallet);
1165 /* initialize colors number fo index computation */
1166 if (PColorLimit == 2)
1168 /* ok */
1169 Pcsi.nr = 0;
1170 Pcsi.ng = 0;
1171 Pcsi.nb = 0;
1172 Pcsi.ngrey = 0;
1173 Pcsi.grey_bits = 1;
1175 else if (grey_bits > 0)
1177 Pcsi.nr = 0;
1178 Pcsi.ng = 0;
1179 Pcsi.nb = 0;
1180 Pcsi.ngrey = 0;
1181 Pcsi.grey_bits = grey_bits;
1183 else if (non_regular_pallet || (0&&ngrey>0))
1185 /* note: using these table with !used_named && ngrey>0 will
1186 * probably leads to faster image loading. But I see nothing
1187 * of significative. On the others hands not using it gives
1188 * maybe better colors approximation. */
1189 if (PColorLimit <= 9)
1191 Pcsi.nr = 8;
1192 Pcsi.ng = 8;
1193 Pcsi.nb = 8;
1194 Pcsi.ngrey = 0;
1196 else
1198 Pcsi.nr = 16;
1199 Pcsi.ng = 16;
1200 Pcsi.nb = 16;
1201 Pcsi.ngrey = 0;
1203 PMappingTable = build_mapping_table(
1204 Pcsi.nr, Pcsi.ng, Pcsi.nb, non_regular_pallet);
1206 else
1208 Pcsi.nr = nr;
1209 Pcsi.ng = ng;
1210 Pcsi.nb = nb;
1211 Pcsi.ngrey = ngrey;
1212 Pcsi.grey_bits = 0;
1216 void finish_ct_init(
1217 int call_type, int ctt, int nr, int ng, int nb, int ngrey, int grey_bits,
1218 Bool use_named)
1220 if (call_type == PICTURE_CALLED_BY_FVWM)
1222 char *env;
1224 if (PAllocTable)
1226 ctt = PICTURE_PAllocTable + ctt;
1228 if (PUseDynamicColors)
1230 ctt = PICTURE_PUseDynamicColors + ctt;
1232 if (PStrictColorLimit)
1234 ctt = PICTURE_PStrictColorLimit + ctt;
1236 if (use_named)
1238 ctt = PICTURE_use_named + ctt;
1240 else
1242 ctt++;
1244 env = safemalloc(21+PICTURE_TABLETYPE_LENGHT+1);
1245 sprintf(env,"FVWM_COLORTABLE_TYPE=%i",ctt);
1246 putenv(env);
1247 if (Pdepth <= 8)
1249 Pac = (PColor *)safecalloc(
1250 (1 << Pdepth), sizeof(PColor));
1254 if (Pct)
1256 if (!PAllocTable && call_type == PICTURE_CALLED_BY_FVWM)
1258 free_table_colors(Pct, PColorLimit);
1260 create_mapping_table(nr,ng,nb,ngrey,grey_bits,use_named);
1264 #define PA_COLOR_CUBE (1 << 1)
1265 #define FVWM_COLOR_CUBE (1 << 2)
1266 #define PA_GRAY_SCALE (1 << 3)
1267 #define FVWM_GRAY_SCALE (1 << 4)
1268 #define ANY_COLOR_CUBE (PA_COLOR_CUBE|FVWM_COLOR_CUBE)
1269 #define ANY_GRAY_SCALE (PA_GRAY_SCALE|FVWM_GRAY_SCALE)
1271 static
1272 int PictureAllocColorTable(
1273 PictureColorLimitOption *opt, int call_type, Bool use_my_color_limit)
1275 char *envp;
1276 int free_colors, nbr_of_color, limit, cc_nbr, i, size;
1277 int use_named_table = 0;
1278 int do_allocate = 0;
1279 int use_default = 1;
1280 int private_cmap = !(Pdefault);
1281 int dyn_cl_set = False;
1282 int strict_cl_set = False;
1283 int alloc_table_set = False;
1284 int color_limit;
1285 int pa_type = (Pvisual->class != GrayScale)? PA_COLOR_CUBE:PA_GRAY_SCALE;
1286 int fvwm_type = (Pvisual->class != GrayScale)?
1287 FVWM_COLOR_CUBE:FVWM_GRAY_SCALE;
1288 int cc[][6] =
1290 /* {nr,ng,nb,ngrey,grey_bits,logic} */
1291 /* 5 first for direct colors and Pdepth > 8*/
1292 /* 8192 colors depth 13, a reasonable max for a color table */
1293 {16, 32, 16, 0, 0, FVWM_COLOR_CUBE},
1294 /* 4096 colors depth 12 */
1295 {16, 16, 16, 0, 0, FVWM_COLOR_CUBE},
1296 /* 1024 colors depth 10 */
1297 {8, 16, 8, 0, 0, FVWM_COLOR_CUBE},
1298 /* 512 colors depth 9 */
1299 {8, 8, 8, 0, 0, FVWM_COLOR_CUBE},
1300 /* 256 colors 3/3/2 standard colormap */
1301 {8, 8, 4, 0, 0, FVWM_COLOR_CUBE},
1302 /* 256 grey scale */
1303 {0, 0, 0, 0, 8, ANY_GRAY_SCALE},
1304 /* 244 Xrender XFree-4.2 */
1305 {6, 6, 6, 30, 0, ANY_COLOR_CUBE},
1306 /* 216 Xrender XFree-4.2,GTK/QT "default cc" */
1307 {6, 6, 6, 0, 0, ANY_COLOR_CUBE},
1308 /* 180 (GTK) */
1309 {6, 6, 5, 0, 0, ANY_COLOR_CUBE},
1310 /* 144 (GTK) */
1311 {6, 6, 4, 0, 0, ANY_COLOR_CUBE},
1312 /* 128 grey scale */
1313 {0, 0, 0, 0, 7, ANY_GRAY_SCALE},
1314 /* 125 GTK mini default cc (may change? 444) */
1315 {5, 5, 5, 0, 0, ANY_COLOR_CUBE},
1316 /* 100 (GTK with color limit) */
1317 {5, 5, 4, 0, 0, ANY_COLOR_CUBE},
1318 /* 85 Xrender XFree-4.3 */
1319 {4, 4, 4, 23, 0, ANY_COLOR_CUBE},
1320 /* 78 (in fact 76) a good default ??*/
1321 {4, 4, 4, 16, 0, FVWM_COLOR_CUBE},
1322 /* 70 a good default ?? */
1323 {4, 4, 4, 8, 0, ANY_COLOR_CUBE},
1324 /* 68 a good default ?? */
1325 {4, 4, 4, 6, 0, ANY_COLOR_CUBE},
1326 /* 64 Xrender XFree-4.3 (GTK wcl) */
1327 {4, 4, 4, 0, 0, ANY_COLOR_CUBE},
1328 /* 64 grey scale */
1329 {0, 0, 0, 0, 6, ANY_GRAY_SCALE},
1330 /* 54, maybe a good default? */
1331 {4, 4, 3, 8, 0, FVWM_COLOR_CUBE},
1332 /* 48, (GTK wcl) no grey but ok */
1333 {4, 4, 3, 0, 0, FVWM_COLOR_CUBE},
1334 /* 32, 2/2/1 standard colormap */
1335 {4, 4, 2, 0, 0, FVWM_COLOR_CUBE},
1336 /* 32 xrender xfree-4.2 */
1337 {0, 0, 0, 0, 6, ANY_GRAY_SCALE},
1338 /* 29 */
1339 {3, 3, 3, 4, 0, FVWM_COLOR_CUBE},
1340 /* 27 (xrender in depth 6&7(hypo) GTK wcl) */
1341 {3, 3, 3, 0, 0, FVWM_COLOR_CUBE|PA_COLOR_CUBE*(Pdepth<8)},
1342 /* 16 grey scale */
1343 {0, 0, 0, 0, 4, FVWM_GRAY_SCALE},
1344 /* 10 */
1345 {2, 2, 2, 4, 0, FVWM_COLOR_CUBE},
1346 /* 8 (xrender/qt/gtk wcl) */
1347 {2, 2, 2, 0, 0, FVWM_COLOR_CUBE},
1348 /* 8 grey scale Xrender depth 4 and XFree-4.3 */
1349 {0, 0, 0, 0, 3, FVWM_GRAY_SCALE|PA_GRAY_SCALE*(Pdepth<5)},
1350 /* 4 grey scale*/
1351 {0, 0, 0, 0, 2,
1352 FVWM_GRAY_SCALE|FVWM_COLOR_CUBE|PA_COLOR_CUBE*(Pdepth<4)},
1353 /* 2 */
1354 {0, 0, 0, 0, 1, FVWM_COLOR_CUBE|FVWM_GRAY_SCALE}
1357 cc_nbr = sizeof(cc)/(sizeof(cc[0]));
1359 /* set up default */
1360 PStrictColorLimit = 0;
1361 PUseDynamicColors = 1;
1362 PAllocTable = 0;
1363 use_named_table = False;
1364 color_limit = 0;
1365 use_default = True;
1367 /* use fvwm color limit */
1368 if (!use_my_color_limit &&
1369 (envp = getenv("FVWM_COLORTABLE_TYPE")) != NULL)
1371 int nr = 0, ng = 0, nb = 0, grey_bits = 0, ngrey = 0;
1372 int ctt = atoi(envp);
1374 if (ctt >= PICTURE_PAllocTable)
1376 ctt -= PICTURE_PAllocTable;
1377 PAllocTable = 1; /* not useful for a module !*/
1379 if (ctt >= PICTURE_PUseDynamicColors)
1381 PUseDynamicColors = 1;
1382 ctt -= PICTURE_PUseDynamicColors;
1384 if (ctt >= PICTURE_PStrictColorLimit)
1386 PStrictColorLimit = 1;
1387 ctt -= PICTURE_PStrictColorLimit;
1389 if (ctt >= PICTURE_use_named)
1391 ctt -= PICTURE_use_named;
1392 Pct = alloc_named_ct(&ctt, False);
1393 use_named_table = True;
1395 else if (ctt == 0)
1397 /* depth <= 8 and no colors limit ! */
1398 PColorLimit = 0;
1399 return 0;
1401 else if (ctt <= cc_nbr)
1403 ctt--;
1404 Pct = alloc_color_cube(
1405 cc[ctt][0], cc[ctt][1], cc[ctt][2], cc[ctt][3],
1406 cc[ctt][4],
1407 False);
1408 nr = cc[ctt][0];
1409 ng = cc[ctt][1];
1410 nb = cc[ctt][2];
1411 ngrey = cc[ctt][3];
1412 grey_bits = cc[ctt][4];
1414 if (Pct != NULL)
1416 /* should always happen */
1417 finish_ct_init(
1418 call_type, ctt, nr, ng, nb, ngrey, grey_bits,
1419 use_named_table);
1420 return PColorLimit;
1424 nbr_of_color = (1 << Pdepth);
1425 color_limit = 0;
1427 /* parse the color limit env variable */
1428 if ((envp = getenv("FVWM_COLORLIMIT")) != NULL)
1430 char *rest, *l;
1432 rest = GetQuotedString(envp, &l, ":", NULL, NULL, NULL);
1433 if (l && *l != '\0' && (color_limit = atoi(l)) >= 0)
1435 use_default = 0;
1437 if (l != NULL)
1439 free(l);
1441 if (color_limit == 9 || color_limit == 61)
1443 use_named_table = 1;
1445 if (rest && *rest != '\0')
1447 if (rest[0] == '1')
1449 strict_cl_set = True;
1450 PStrictColorLimit = 1;
1452 else
1454 strict_cl_set = True;
1455 PStrictColorLimit = 0;
1457 if (strlen(rest) > 1 && rest[1] == '1')
1459 use_named_table = 1;
1461 else
1463 use_named_table = 0;
1465 if (strlen(rest) > 2 && rest[2] == '1')
1467 dyn_cl_set = True;
1468 PUseDynamicColors = 1;
1470 else
1472 dyn_cl_set = True;
1473 PUseDynamicColors = 0;
1475 if (strlen(rest) > 3 && rest[3] == '1')
1477 alloc_table_set = True;
1478 PAllocTable = 1;
1480 else
1482 alloc_table_set = True;
1483 PAllocTable = 0;
1487 else if (opt != NULL) /* use the option */
1489 if (opt->color_limit > 0)
1491 use_default = 0;
1492 color_limit = opt->color_limit;
1494 if (color_limit == 9 || color_limit == 61)
1496 use_named_table = 1;
1498 if (opt->strict > 0)
1500 strict_cl_set = True;
1501 PStrictColorLimit = 1;
1503 else if (opt->strict == 0)
1505 strict_cl_set = True;
1506 PStrictColorLimit = 0;
1508 if (opt->use_named_table > 0)
1510 use_named_table = 1;
1512 else if (opt->use_named_table == 0)
1514 use_named_table = 0;
1516 if (opt->not_dynamic > 0)
1518 dyn_cl_set = True;
1519 PUseDynamicColors = 0;
1521 else if (opt->not_dynamic == 0)
1523 dyn_cl_set = True;
1524 PUseDynamicColors = 0;
1526 if (opt->allocate > 0)
1528 alloc_table_set = True;
1529 PAllocTable = 1;
1531 else if (opt->allocate == 0)
1533 alloc_table_set = True;
1534 PAllocTable = 0;
1538 if (color_limit <= 0)
1540 use_default = 1;
1541 color_limit = nbr_of_color;
1544 /* first try to see if we have a "pre-allocated" color cube.
1545 * The bultin RENDER X extension pre-allocate a color cube plus
1546 * some grey's (xc/programs/Xserver/render/miindex)
1547 * See gdk/gdkrgb.c for the cubes used by gtk+-2, 666 is the default,
1548 * 555 is the minimal cc (this may change): if gtk cannot allocate
1549 * the 555 cc (or better) a private cmap is used.
1550 * for qt-3: see src/kernel/{qapplication.cpp,qimage.cpp,qcolor_x11.c}
1551 * the 666 cube is used by default (with approx in the cmap if some
1552 * color allocation fail), and some qt app may accept an
1553 * --ncols option to limit the nbr of colors, then some "2:3:1"
1554 * proportions color cube are used (222, 232, ..., 252, 342, ..., 362,
1555 * 452, ...,693, ...)
1556 * imlib2 try to allocate the 666 cube if this fail it try more
1557 * exotic table (see rend.c and rgba.c) */
1558 i = 0;
1559 free_colors = 0;
1560 if (Pdepth <= 8 && !private_cmap && use_default &&
1561 i < cc_nbr && Pct == NULL && (Pvisual->class & 1))
1563 free_colors = get_nbr_of_free_colors(nbr_of_color);
1565 while(Pdepth <= 8 && !private_cmap && use_default &&
1566 i < cc_nbr && Pct == NULL && (Pvisual->class & 1))
1568 size = cc[i][0]*cc[i][1]*cc[i][2] + cc[i][3] - 2*(cc[i][3] > 0) +
1569 (1 << cc[i][4])*(cc[i][4] != 0);
1570 if (size > nbr_of_color || !(cc[i][5] & pa_type))
1572 i++;
1573 continue;
1575 if (free_colors <= nbr_of_color - size)
1577 Pct = alloc_color_cube(
1578 cc[i][0], cc[i][1], cc[i][2], cc[i][3], cc[i][4],
1579 True);
1581 if (Pct != NULL)
1583 if (free_colors <=
1584 get_nbr_of_free_colors(nbr_of_color))
1586 /* done */
1588 else
1590 free_table_colors(Pct, PColorLimit);
1591 free(Pct);
1592 Pct = NULL;
1595 i++;
1597 if (Pct != NULL)
1599 PUseDynamicColors = 0;
1600 PAllocTable = 1;
1601 Pcsi.pre_allocated_pallet = 1;
1602 i = i - 1;
1603 finish_ct_init(
1604 call_type, i, cc[i][0], cc[i][1], cc[i][2], cc[i][3],
1605 cc[i][4], 0);
1606 return PColorLimit;
1610 * now use "our" table
1613 limit = (color_limit >= nbr_of_color)? nbr_of_color:color_limit;
1615 if (use_default && !private_cmap)
1617 /* XRender cvs default: */
1618 #if 0
1619 if (limit > 100)
1620 limit = nbr_of_color/3;
1621 else
1622 limit = nbr_of_color/2;
1623 /* depth 8: 85 */
1624 /* depth 4: 8 */
1625 #endif
1626 if (limit > 256)
1628 /* direct colors & Pdepth > 8 */
1629 if (Pdepth >= 16)
1631 limit = 8192;
1633 else if (Pdepth >= 15)
1635 limit = 4096;
1637 else
1639 limit = 512;
1642 else if (limit == 256)
1644 if (Pvisual->class == GrayScale)
1646 limit = 64;
1648 else if (Pvisual->class == DirectColor)
1650 limit = 32;
1652 else
1654 limit = 68;
1655 /* candidate:
1656 * limit = 54; 4x4x3 + 6 grey
1657 * limit = 61 (named table)
1658 * limit = 85 current XRender default 4cc + 21
1659 * limit = 76 future(?) XRender default 4cc + 16
1660 * limit = 68 4x4x4 + 4
1661 * limit = 64 4x4x4 + 0 */
1665 else if (limit == 128 || limit == 64)
1667 if (Pvisual->class == GrayScale)
1669 limit = 32;
1671 else
1673 limit = 31;
1676 else if (limit >= 16)
1678 if (Pvisual->class == GrayScale)
1680 limit = 8;
1682 else
1684 limit = 10;
1687 else if (limit >= 8)
1689 limit = 4;
1691 else
1693 limit = 2;
1696 if (limit < 2)
1698 limit = 2;
1701 if (Pvisual->class == DirectColor)
1703 /* humm ... Any way this case should never happen in real life:
1704 * DirectColor default colormap! */
1705 PUseDynamicColors = 0;
1706 PAllocTable = 1;
1707 PStrictColorLimit = 1;
1709 if (PAllocTable)
1711 do_allocate = 1;
1713 else
1715 do_allocate = 0;
1718 /* use the named table ? */
1719 if (use_named_table)
1721 i = limit;
1722 while(Pct == NULL && i >= 2)
1724 Pct = alloc_named_ct(&i, do_allocate);
1725 i--;
1728 if (Pct != NULL)
1730 finish_ct_init(
1731 call_type, PColorLimit, 0, 0, 0, 0, 0, 1);
1732 return PColorLimit;
1735 /* color cube or regular grey scale */
1736 i = 0;
1737 while(i < cc_nbr && Pct == NULL)
1739 if ((cc[i][5] & fvwm_type) &&
1740 cc[i][0]*cc[i][1]*cc[i][2] + cc[i][3] - 2*(cc[i][3] > 0) +
1741 (1 << cc[i][4])*(cc[i][4] != 0) <= limit)
1743 Pct = alloc_color_cube(
1744 cc[i][0], cc[i][1], cc[i][2], cc[i][3], cc[i][4],
1745 do_allocate);
1747 i++;
1749 if (Pct != NULL)
1751 i = i-1;
1752 finish_ct_init(
1753 call_type, i, cc[i][0], cc[i][1], cc[i][2], cc[i][3],
1754 cc[i][4], 0);
1755 return PColorLimit;
1758 /* I do not think we can be here */
1759 Pct = alloc_color_cube(0, 0, 0, 0, 1, False);
1760 finish_ct_init(call_type, cc_nbr-1, 0, 0, 0, 0, 1, 0);
1761 if (Pct == NULL)
1763 fprintf(stderr,
1764 "[FVWM] ERR -- Cannot get Black and White. exiting!\n");
1765 exit(2);
1767 return PColorLimit;
1770 /* ***************************************************************************
1771 * Allocation of a private DirectColor cmap this is broken for depth > 16
1772 * ***************************************************************************/
1773 static
1774 Bool alloc_direct_colors(int *limit, Bool use_my_color_limit)
1776 unsigned long nr,ng,nb,r,g,b,cr,cg,cf,pr,pg;
1777 unsigned long red_mask, green_mask, blue_mask;
1778 XColor *colors;
1780 if (Pdepth <= 16)
1782 red_mask = Pvisual->red_mask;
1783 green_mask = Pvisual->green_mask;
1784 blue_mask = Pvisual->blue_mask;
1786 else
1788 /* Use a standard depth 16 colormap. This is broken FIXME! */
1789 red_mask = 0xf800;
1790 green_mask = 0x7e0;
1791 blue_mask = 0x1f;
1794 decompose_mask(
1795 red_mask, &Pcsi.red_shift, &Pcsi.red_prec);
1796 decompose_mask(
1797 green_mask, &Pcsi.green_shift, &Pcsi.green_prec);
1798 decompose_mask(
1799 blue_mask, &Pcsi.blue_shift, &Pcsi.blue_prec);
1801 if (!use_my_color_limit)
1803 /* colors allocated by fvwm we can return */
1804 return 1;
1807 nr = 1 << Pcsi.red_prec;
1808 ng = 1 << Pcsi.green_prec;
1809 nb = 1 << Pcsi.blue_prec;
1811 colors = (XColor *)safemalloc(nb*sizeof(XColor));
1812 cf = DoRed|DoBlue|DoGreen;
1813 for (r=0; r<nr; r++)
1815 cr = r * 65535 / (nr - 1);
1816 pr = (cr >> (16 - Pcsi.red_prec)) << Pcsi.red_shift;
1817 for (g = 0; g < ng; g++)
1819 cg = g * 65535 / (ng - 1);
1820 pg = (cg >> (16 - Pcsi.green_prec)) << Pcsi.green_shift;
1821 for (b = 0; b < nb; b++)
1823 colors[b].flags = cf;
1824 colors[b].red = cr;
1825 colors[b].green = cg;
1826 colors[b].blue = b * 65535 / (nb - 1);
1827 colors[b].pixel =
1828 (Pixel)(pr + pg +
1829 ((colors[b].blue >>
1830 (16 - Pcsi.blue_prec)) <<
1831 Pcsi.blue_shift));
1833 XStoreColors(Pdpy, Pcmap, colors, nb);
1836 free(colors);
1837 return 1;
1840 /* ***************************************************************************
1841 * Init the table for Static Colors
1842 * ***************************************************************************/
1843 static
1844 void init_static_colors_table(void)
1846 XColor colors[256];
1847 int i;
1848 int nbr_of_colors = max(256, (1 << Pdepth));
1850 PColorLimit = nbr_of_colors;
1851 Pct = (PColor *)safemalloc((nbr_of_colors+1) * sizeof(PColor));
1852 for (i = 0; i < nbr_of_colors; i++)
1854 colors[i].pixel = Pct[i].color.pixel = i;
1856 XQueryColors(Pdpy, Pcmap, colors, nbr_of_colors);
1857 for (i = 0; i < nbr_of_colors; i++)
1859 Pct[i].color.red = colors[i].red;
1860 Pct[i].color.green = colors[i].green;
1861 Pct[i].color.blue = colors[i].blue;
1862 Pct[i].alloc_count = 1;
1864 Pct[PColorLimit].color.red = Pct[PColorLimit-1].color.red;
1865 Pct[PColorLimit].color.green = Pct[PColorLimit-1].color.green;
1866 Pct[PColorLimit].color.blue = Pct[PColorLimit-1].color.blue;
1867 Pct[PColorLimit].alloc_count = 1;
1868 create_mapping_table(0, 0, 0, 0, 0, True);
1872 /* ***************************************************************************
1873 * misc local functions
1874 * ***************************************************************************/
1875 static
1876 void print_colormap(Colormap cmap)
1878 XColor colors[256];
1879 int i;
1880 int nbr_of_colors = max(256, (1 << Pdepth));
1881 for (i = 0; i < nbr_of_colors; i++)
1883 colors[i].pixel = i;
1885 XQueryColors(Pdpy, cmap, colors, nbr_of_colors);
1886 for (i = 0; i < nbr_of_colors; i++)
1888 fprintf(stderr," rgb(%.3i): %.3i/%.3i/%.3i\n", i,
1889 colors[i].red >> 8,
1890 colors[i].green >> 8,
1891 colors[i].blue >> 8);
1895 /* ---------------------------- interface functions ------------------------- */
1897 int PictureAllocColor(Display *dpy, Colormap cmap, XColor *c, int no_limit)
1899 if (PStrictColorLimit && Pct != NULL)
1901 no_limit = 0;
1904 if (no_limit)
1906 return Pcsi.alloc_color_no_limit(dpy, cmap, c);
1908 else
1910 return Pcsi.alloc_color(dpy, cmap, c);
1912 return 0;
1916 int PictureAllocColorAllProp(
1917 Display *dpy, Colormap cmap, XColor *c, int x, int y,
1918 Bool no_limit, Bool is_8, Bool do_dither)
1921 if (!no_limit && do_dither && Pcsi.alloc_color_dither != NULL)
1923 if (!is_8)
1925 c->red = c->red >> 8;
1926 c->green = c->green >> 8;
1927 c->blue = c->blue >> 8;
1929 return Pcsi.alloc_color_dither(dpy, cmap, c, x, y);
1931 else
1933 if (is_8)
1935 c->red = c->red << 8;
1936 c->green = c->green << 8;
1937 c->blue = c->blue << 8;
1939 return PictureAllocColor(dpy, cmap, c, False);
1941 return 0;
1944 int PictureAllocColorImage(
1945 Display *dpy, PictureImageColorAllocator *pica, XColor *c, int x, int y)
1947 int r;
1949 r = PictureAllocColorAllProp(
1950 dpy, pica->cmap, c, x, y,
1951 pica->no_limit, pica->is_8, pica->dither);
1952 if (r && pica->pixels_table != NULL && pica->pixels_table_size &&
1953 c->pixel < pica->pixels_table_size)
1955 pica->pixels_table[c->pixel]++;
1957 return r;
1960 PictureImageColorAllocator *PictureOpenImageColorAllocator(
1961 Display *dpy, Colormap cmap, int x, int y, Bool no_limit,
1962 Bool do_not_save_pixels, int dither, Bool is_8)
1964 PictureImageColorAllocator *pica;
1965 Bool do_save_pixels = False;
1967 pica = (PictureImageColorAllocator *)safemalloc(
1968 sizeof(PictureImageColorAllocator));
1969 if (Pdepth <= 8 && !do_not_save_pixels && (Pvisual->class & 1) &&
1970 ((PUseDynamicColors && Pct) || no_limit))
1972 int s = 1 << Pdepth;
1973 pica->pixels_table = (unsigned long *)safecalloc(
1974 s, sizeof(unsigned long));
1975 pica->pixels_table_size = s;
1976 do_save_pixels = True;
1978 if (!do_save_pixels)
1980 pica->pixels_table = NULL;
1981 pica->pixels_table_size = 0;
1983 pica->is_8 = is_8;
1984 if (dither && Pdepth <= 16)
1986 pica->dither = dither;
1988 else
1990 pica->dither = dither;
1992 pica->no_limit = no_limit;
1993 pica->cmap = cmap;
1994 return pica;
1997 void PictureCloseImageColorAllocator(
1998 Display *dpy, PictureImageColorAllocator *pica, int *nalloc_pixels,
1999 Pixel **alloc_pixels, Bool *no_limit)
2001 if (nalloc_pixels)
2003 *nalloc_pixels = 0;
2005 if (alloc_pixels != NULL)
2007 *alloc_pixels = NULL;
2009 if (no_limit != NULL)
2011 *no_limit = 0;
2013 if (pica->pixels_table)
2015 int i,j;
2016 int k = 0, l = 0, np = 0;
2017 int free_num = 0;
2018 Pixel *free_pixels = NULL;
2019 Pixel *save_pixels = NULL;
2021 for(i = 0; i < pica->pixels_table_size; i++)
2023 if (pica->pixels_table[i])
2025 free_num += (pica->pixels_table[i]-1);
2026 np++;
2029 if (free_num)
2031 free_pixels = (Pixel *)safemalloc(
2032 free_num * sizeof(Pixel));
2034 if (np && nalloc_pixels != NULL && alloc_pixels != NULL)
2036 save_pixels = (Pixel *)safemalloc(np * sizeof(Pixel));
2038 for(i = 0; i < pica->pixels_table_size; i++)
2040 if (pica->pixels_table[i])
2042 if (save_pixels)
2044 save_pixels[k++] = i;
2046 for(j=1; j < pica->pixels_table[i]; j++)
2048 free_pixels[l++] = i;
2052 if (free_num)
2054 PictureFreeColors(
2055 dpy, pica->cmap, free_pixels, free_num, 0,
2056 pica->no_limit);
2057 free(free_pixels);
2059 if (nalloc_pixels != NULL && alloc_pixels != NULL)
2061 *nalloc_pixels = np;
2062 *alloc_pixels = save_pixels;
2063 if (no_limit != NULL)
2065 *no_limit = pica->no_limit;
2068 else if (save_pixels)
2070 free(save_pixels);
2072 free(pica->pixels_table);
2074 free(pica);
2075 return;
2078 void PictureFreeColors(
2079 Display *dpy, Colormap cmap, Pixel *pixels, int n, unsigned long planes,
2080 Bool no_limit)
2082 if (no_limit)
2084 if (Pcsi.free_colors_no_limit != NULL)
2086 Pcsi.free_colors_no_limit(
2087 dpy, cmap, pixels, n, planes);
2090 else
2092 if (Pcsi.free_colors != NULL)
2094 Pcsi.free_colors(dpy, cmap, pixels, n, planes);
2097 return;
2100 Pixel PictureGetNextColor(Pixel p, int n)
2102 int i;
2103 XColor c;
2105 if (n >= 0)
2106 n = 1;
2107 else
2108 n = -1;
2110 if (Pct == NULL)
2112 return p;
2114 for(i=0; i<PColorLimit; i++)
2116 if (Pct[i].color.pixel == p)
2118 if (i == 0 && n < 0)
2120 c = Pct[PColorLimit-1].color;
2121 alloc_color_in_pct(&c, PColorLimit-1);
2122 return Pct[PColorLimit-1].color.pixel;
2124 else if (i == PColorLimit-1 && n > 0)
2126 c = Pct[0].color;
2127 alloc_color_in_pct(&c, 0);
2128 return Pct[0].color.pixel;
2130 else
2132 c = Pct[i+n].color;
2133 alloc_color_in_pct(&c, i+n);
2134 return Pct[i+n].color.pixel;
2138 return p;
2141 /* Replace the color in my_color by the closest matching color
2142 from base_table */
2143 void PictureReduceColorName(char **my_color)
2145 int index;
2146 XColor rgb; /* place to calc rgb for each color in xpm */
2148 if (!XpmSupport)
2149 return;
2151 if (!strcasecmp(*my_color,"none")) {
2152 return; /* do not substitute the "none" color */
2155 if (!XParseColor(Pdpy, Pcmap, *my_color, &rgb))
2157 fprintf(stderr,"color_to_rgb: can't parse color %s\n",
2158 *my_color);
2160 index = get_color_index(rgb.red,rgb.green,rgb.blue, False);
2161 /* Finally: replace the color string by the newly determined color
2162 * string */
2163 free(*my_color); /* free old color */
2164 /* area for new color */
2165 *my_color = safemalloc(8);
2166 sprintf(*my_color,"#%x%x%x",
2167 Pct[index].color.red >> 8,
2168 Pct[index].color.green >> 8,
2169 Pct[index].color.blue >> 8); /* put it there */
2170 return;
2173 Bool PictureDitherByDefault(void)
2175 if (Pct != NULL)
2177 return True;
2179 return False;
2182 Bool PictureUseBWOnly(void)
2184 if (Pdepth < 2 || (PStrictColorLimit && PColorLimit == 2))
2186 return True;
2188 return False;
2191 int PictureInitColors(
2192 int call_type, Bool init_color_limit, PictureColorLimitOption *opt,
2193 Bool use_my_color_limit, Bool init_dither)
2195 Bool dither_ok = False;
2197 switch (Pvisual->class)
2199 case DirectColor:
2200 /* direct colors is more or less broken */
2201 decompose_mask(
2202 Pvisual->red_mask, &Pcsi.red_shift,
2203 &Pcsi.red_prec);
2204 decompose_mask(
2205 Pvisual->green_mask, &Pcsi.green_shift,
2206 &Pcsi.green_prec);
2207 decompose_mask(
2208 Pvisual->blue_mask, &Pcsi.blue_shift,
2209 &Pcsi.blue_prec);
2210 Pcsi.alloc_color_no_limit = alloc_color_proportion;
2211 Pcsi.alloc_color = alloc_color_proportion;
2212 Pcsi.alloc_color_dither = alloc_color_proportion_dither;
2213 Pcsi.free_colors_no_limit = NULL;
2214 Pcsi.free_colors = NULL;
2215 PColorLimit = 0;
2216 break;
2217 case TrueColor:
2218 decompose_mask(
2219 Pvisual->red_mask, &Pcsi.red_shift,
2220 &Pcsi.red_prec);
2221 decompose_mask(
2222 Pvisual->green_mask, &Pcsi.green_shift,
2223 &Pcsi.green_prec);
2224 decompose_mask(
2225 Pvisual->blue_mask, &Pcsi.blue_shift,
2226 &Pcsi.blue_prec);
2227 Pcsi.alloc_color_no_limit = alloc_color_proportion;
2228 Pcsi.alloc_color = alloc_color_proportion;
2229 Pcsi.free_colors_no_limit = NULL;
2230 Pcsi.free_colors = NULL;
2231 PColorLimit = 0;
2232 if (init_dither && (Pdepth == 15 || Pdepth == 16))
2234 dither_ok = my_dither_depth_15_16_init();
2236 if (dither_ok)
2238 Pcsi.alloc_color_dither = alloc_color_proportion_dither;
2240 else
2242 Pcsi.alloc_color_dither = NULL;
2244 break;
2245 case StaticColor:
2246 if (0 && Pvisual->red_mask != 0 && Pvisual->green_mask != 0 &&
2247 Pvisual->blue_mask != 0)
2249 decompose_mask(
2250 Pvisual->red_mask, &Pcsi.red_shift,
2251 &Pcsi.red_prec);
2252 decompose_mask(
2253 Pvisual->green_mask, &Pcsi.green_shift,
2254 &Pcsi.green_prec);
2255 decompose_mask(
2256 Pvisual->blue_mask, &Pcsi.blue_shift,
2257 &Pcsi.blue_prec);
2258 Pcsi.alloc_color_no_limit = alloc_color_proportion;
2259 Pcsi.alloc_color = alloc_color_proportion;
2260 PColorLimit = 0;
2262 else
2264 if (init_color_limit)
2266 Pcsi.alloc_color = alloc_color_in_table;
2267 Pcsi.alloc_color_dither =
2268 alloc_color_in_table_dither;
2269 Pcsi.alloc_color_no_limit = alloc_color_x;
2270 init_static_colors_table();
2272 else
2274 Pcsi.alloc_color = alloc_color_x;
2275 Pcsi.alloc_color_dither = NULL;
2276 Pcsi.alloc_color_no_limit = alloc_color_x;
2279 Pcsi.free_colors_no_limit = NULL;
2280 Pcsi.free_colors = NULL;
2281 break;
2282 case StaticGray:
2283 /* FIXME: we assume that we have a regular grey ramp */
2284 if (0)
2286 Pcsi.alloc_color_no_limit = alloc_color_proportion_grey;
2287 Pcsi.alloc_color = alloc_color_proportion;
2288 PColorLimit = 0;
2290 else
2292 if (init_color_limit)
2294 Pcsi.alloc_color = alloc_color_in_table;
2295 Pcsi.alloc_color_dither =
2296 alloc_color_in_table_dither;
2297 Pcsi.alloc_color_no_limit = alloc_color_x;
2298 init_static_colors_table();
2300 else
2302 Pcsi.alloc_color = alloc_color_x;
2303 Pcsi.alloc_color_dither = NULL;
2304 Pcsi.alloc_color_no_limit = alloc_color_x;
2307 Pcsi.free_colors_no_limit = NULL;
2308 Pcsi.free_colors = NULL;
2309 break;
2310 case PseudoColor:
2311 case GrayScale:
2312 default:
2313 Pcsi.alloc_color_no_limit = alloc_color_dynamic_no_limit;
2314 Pcsi.free_colors_no_limit = free_colors_x;
2315 break;
2318 if (!(Pvisual->class & 1))
2320 /* static classes */
2321 PUseDynamicColors = 0;
2322 if (call_type == PICTURE_CALLED_BY_FVWM &&
2323 getenv("FVWM_COLORTABLE_TYPE") != NULL)
2325 putenv("FVWM_COLORTABLE_TYPE=");
2327 return PColorLimit;
2330 /* dynamic classes */
2332 if (!Pdefault && Pvisual->class == DirectColor)
2334 PColorLimit = 0;
2335 PUseDynamicColors = 0;
2336 alloc_direct_colors(0, use_my_color_limit);
2337 if (call_type == PICTURE_CALLED_BY_FVWM &&
2338 getenv("FVWM_COLORTABLE_TYPE") != NULL)
2340 putenv("FVWM_COLORTABLE_TYPE=");
2342 return 0;
2346 if (init_color_limit)
2348 Pcsi.alloc_color = alloc_color_in_table;
2349 Pcsi.alloc_color_dither = alloc_color_in_table_dither;
2350 PictureAllocColorTable(opt, call_type, use_my_color_limit);
2351 if (PUseDynamicColors)
2353 Pcsi.free_colors = free_colors_in_table;
2355 else
2357 Pcsi.free_colors = NULL;
2360 else
2362 Pcsi.alloc_color = alloc_color_dynamic_no_limit;
2363 Pcsi.free_colors = free_colors_x;
2364 Pcsi.alloc_color_dither = NULL;
2366 return PColorLimit;
2369 void PicturePrintColorInfo(int verbose)
2371 unsigned long nbr_of_colors = 1 << Pdepth;
2373 fprintf(stderr, "FVWM info on colors\n");
2374 fprintf(stderr, " Visual ID: 0x%x, Default?: %s, Class: ",
2375 (int)(Pvisual->visualid),
2376 (Pdefault)? "Yes":"No");
2377 if (Pvisual->class == TrueColor)
2379 fprintf(stderr,"TrueColor");
2381 else if (Pvisual->class == PseudoColor)
2383 fprintf(stderr,"PseudoColor");
2385 else if (Pvisual->class == DirectColor)
2387 fprintf(stderr,"DirectColor");
2389 else if (Pvisual->class == StaticColor)
2391 fprintf(stderr,"StaticColor");
2393 else if (Pvisual->class == GrayScale)
2395 fprintf(stderr,"GrayScale");
2397 else if (Pvisual->class == StaticGray)
2399 fprintf(stderr,"StaticGray");
2401 fprintf(stderr, "\n");
2402 fprintf(stderr, " Depth: %i, Number of colors: %lu",
2403 Pdepth, (unsigned long)nbr_of_colors);
2404 if (Pct != NULL)
2406 fprintf(stderr,"\n Pallet with %i colors", PColorLimit);
2407 if (Pvisual->class & 1)
2409 fprintf(stderr,", Number of free colors: %i\n",
2410 get_nbr_of_free_colors((1 << Pdepth)));
2411 fprintf(stderr,
2412 " Auto Detected: %s, Strict: %s, Allocated: %s,"
2413 " Dynamic: %s\n",
2414 (Pcsi.pre_allocated_pallet)? "Yes":"No",
2415 (PStrictColorLimit)? "Yes":"No",
2416 (PAllocTable)? "Yes":"No",
2417 (PUseDynamicColors)? "Yes":"No");
2419 else
2421 fprintf(stderr," (default colormap)\n");
2423 if (PColorLimit <= 256)
2425 int i;
2426 int count = 0;
2427 int count_alloc = 0;
2429 if (verbose)
2431 fprintf(stderr," The fvwm colors table:\n");
2433 for (i = 0; i < PColorLimit; i++)
2435 if (verbose)
2437 fprintf(
2438 stderr,
2439 " rgb:%.3i/%.3i/%.3i\t%lu\n",
2440 Pct[i].color.red >> 8,
2441 Pct[i].color.green >> 8,
2442 Pct[i].color.blue >> 8,
2443 Pct[i].alloc_count);
2445 if (Pct[i].alloc_count)
2447 count++;
2450 if ((Pvisual->class & 1) && Pac != NULL)
2452 if (verbose)
2454 fprintf(stderr," fvwm colors not in"
2455 " the table:\n");
2457 for(i=0; i < nbr_of_colors; i++)
2459 int j = 0;
2460 Bool found = False;
2462 if (!Pac[i].alloc_count)
2463 continue;
2464 while(j < PColorLimit && !found)
2466 if (i == Pct[j].color.pixel)
2468 found = True;
2470 j++;
2472 if (found)
2473 continue;
2474 count_alloc++;
2475 if (verbose)
2477 fprintf(
2478 stderr,
2479 " rgb:"
2480 "%.3i/%.3i/%.3i\t%lu\n",
2481 Pac[i].color.red >> 8,
2482 Pac[i].color.green >> 8,
2483 Pac[i].color.blue >> 8,
2484 Pac[i].alloc_count);
2487 if (verbose && count_alloc == 0)
2489 if (verbose)
2491 fprintf(stderr," None\n");
2495 if (Pvisual->class & 1)
2497 fprintf(stderr,
2498 " Number of colours used by fvwm:\n");
2499 fprintf(stderr,
2500 " In the table: %i\n", count);
2501 fprintf(
2502 stderr, " Out of the table: %i\n",
2503 count_alloc);
2504 fprintf(stderr,
2505 " Total: %i\n", count_alloc+count);
2509 else
2511 if (Pvisual->class == DirectColor)
2513 fprintf(stderr, ", Pseudo Pallet with: %i colors\n",
2514 (1 << Pcsi.red_prec)*(1 << Pcsi.green_prec)*
2515 (1 << Pcsi.blue_prec));
2517 else
2519 fprintf(stderr, ", No Pallet (static colors)\n");
2521 fprintf(stderr, " red: %i, green: %i, blue %i\n",
2522 1 << Pcsi.red_prec, 1 << Pcsi.green_prec,
2523 1 << Pcsi.blue_prec);
2524 if (verbose && Pdepth <= 8)
2526 if (Pvisual->class == DirectColor)
2528 fprintf(stderr, " Colormap:\n");
2530 else
2532 fprintf(stderr,
2533 " Static Colormap used by fvwm:\n");
2535 print_colormap(Pcmap);
2539 if (Pdepth <= 8 && verbose >= 2)
2541 fprintf(stderr,"\n Default Colormap:\n");
2542 print_colormap(DefaultColormap(Pdpy,DefaultScreen(Pdpy)));