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 ---------------------- */
36 #include "PictureBase.h"
37 #include "PictureUtils.h"
38 #include "PictureDitherMatrice.h"
40 /* ---------------------------- local definitions and macro ----------------- */
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
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
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 -------------------------------- */
98 XColor color
; /* rgb color info */
99 unsigned long alloc_count
; /* nbr of allocation */
105 * info for colors table (depth <= 8)
107 /* color cube used */
112 /* grey palette def, nbr of grey = 2^grey_bits */
114 /* color cube used for dithering with the named table */
119 /* do we found a pre-allocated pallet ? */
120 Bool pre_allocated_pallet
;
121 /* info for depth > 8 */
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
);
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
);
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
174 unsigned long mask
, int *shift
, int *prec
)
179 while (!(mask
& 0x1))
193 * color allocation in the colormap. strongly inspired by SetCloseColor from
194 * the Xpm library (depth <= 8)
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
);
207 int alloc_color_in_cmap(XColor
*c
, Bool force
)
209 static XColor colors
[256];
210 CloseColor closenesses
[256];
213 int map_entries
= (Pvisual
->class == DirectColor
)?
214 (1 << Pdepth
) : Pvisual
->map_entries
;
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
++)
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(
236 (int)(colors
[i
].red
),
237 (int)(colors
[i
].green
),
238 (int)(colors
[i
].blue
));
240 qsort(closenesses
, map_entries
, sizeof(CloseColor
), closeness_cmp
);
243 j
= closenesses
[i
].cols_index
;
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
))
258 c
->green
= tmp
.green
;
260 c
->pixel
= tmp
.pixel
;
266 if (i
== map_entries
)
268 j
= closenesses
[i
].cols_index
;
279 int my_dither(int x
, int y
, XColor
*c
)
281 /* the dither matrice */
282 static const char DM
[128][128] = DITHER_MATRICE
;
286 if (Pcsi
.grey_bits
!= 0)
289 int prec
= Pcsi
.grey_bits
;
291 if (Pcsi
.grey_bits
== 1)
293 /* FIXME, can we do a better dithering */
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
);
305 int dith
, rs
, gs
, bs
, gb
, b
;
311 gb
= Pcsi
.d_ng
*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
;
321 /* try to use the additonal grey. Not easy, good for
322 * certain image/gradient bad for others */
323 if (Pcsi
.d_ngrey_bits
)
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;
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
) <=
339 g_index
= g_index
+ Pcsi
.ng
*Pcsi
.nb
*Pcsi
.ng
-1;
344 if (PDitherMappingTable
!= NULL
)
346 index
= PDitherMappingTable
[index
];
353 int my_dither_depth_15_16_init(void)
355 const unsigned char _dither_44
[4][4] =
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))
371 else if (Pdepth
== 15 && (Pvisual
->red_mask
== 0x7c00) &&
372 (Pvisual
->green_mask
== 0x3e0) &&
373 (Pvisual
->blue_mask
== 0x1f))
383 (unsigned short *)safemalloc(4*4*256*sizeof(unsigned short));
385 (unsigned short *)safemalloc(4*4*256*sizeof(unsigned short));
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
)) &&
399 (x
<< 10) | (y
<< 8) | i
] =
405 (x
<< 10) | (y
<< 8) | i
] =
408 if ((_dither_44
[x
][y
] < ((i
& ge
) << 1))
412 (x
<< 10) | (y
<< 8) | i
] =
418 (x
<< 10) | (y
<< 8) | i
] =
421 if ((_dither_44
[x
][y
] < (i
& be
)) &&
425 (x
<< 10) | (y
<< 8) | i
] =
431 (x
<< 10) | (y
<< 8) | i
] =
441 * Color allocation in the "palette"
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
;
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
)++;
473 int get_color_index(int r
, int g
, int b
, int is_8
)
483 if (Pcsi
.grey_bits
> 0)
485 /* FIXME: Use other proporition ? */
486 index
= ((r
+g
+b
)/3) >> (8 - Pcsi
.grey_bits
);
491 /* "exact" computation (corrected linear dist) */
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
;
510 /* found the best of the 8 linear closest points */
511 int lr
,lg
,lb
,tr
,tg
,tb
,best_dist
= -1,i
,d
;
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
+
528 (Pct
[i
].color
.red
>>8),
529 (Pct
[i
].color
.green
>>8),
530 (Pct
[i
].color
.blue
>>8));
531 if (best_dist
== -1 ||
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
++)
550 (Pct
[i
].color
.red
>>8),
551 (Pct
[i
].color
.green
>>8),
552 (Pct
[i
].color
.blue
>>8));
563 /* approximation; faster */
564 index
= ((r
* Pcsi
.nr
)>>8) * Pcsi
.ng
*Pcsi
.nb
+
565 ((g
* Pcsi
.ng
)>>8) * Pcsi
.nb
+
568 if (PMappingTable
!= NULL
)
570 index
= PMappingTable
[index
];
577 * Main colors allocator
580 int alloc_color_proportion(Display
*dpy
, Colormap cmap
, XColor
*c
)
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
)
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;
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
)
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);
621 c
->pixel
= c
->pixel
>> (16 - Pdepth
);
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
);
635 int alloc_color_in_table_dither(
636 Display
*dpy
, Colormap cmap
, XColor
*c
, int x
, int y
)
639 /* 8 bit colors !! */
640 index
= my_dither(x
, y
, c
);
641 return alloc_color_in_pct(c
, index
);
645 int alloc_color_dynamic_no_limit(
646 Display
*dpy
, Colormap cmap
, XColor
*c
)
650 if (XAllocColor(dpy
, cmap
, c
))
654 else if (!alloc_color_in_cmap(c
, False
))
657 r
= alloc_color_in_cmap(c
, True
);
658 MyXUngrabServer(dpy
);
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
;
677 Display
*dpy
, Colormap cmap
, XColor
*c
)
679 return XAllocColor(dpy
, cmap
, c
);
683 void free_colors_in_table(
684 Display
*dpy
, Colormap cmap
, Pixel
*pixels
, int n
,
685 unsigned long planes
)
691 if (!Pct
|| !PUseDynamicColors
)
696 p
= (Pixel
*)safemalloc(n
*sizeof(Pixel
));
697 for(i
= 0; i
< n
; i
++)
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
)
719 XFreeColors(dpy
, cmap
, p
, m
, planes
);
728 Display
*dpy
, Colormap cmap
, Pixel
*pixels
, int n
,
729 unsigned long planes
)
731 XFreeColors(dpy
, cmap
, pixels
, n
, planes
);
734 int nbr_colors
= (1 << Pdepth
);
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
752 XColor
*build_mapping_colors(int nr
, int ng
, int nb
)
757 colors
= (XColor
*)safemalloc(nr
*ng
*nb
* sizeof(XColor
));
759 for (r
= 0; r
< nr
; r
++)
761 for (g
= 0; g
< ng
; g
++)
763 for (b
= 0; b
< nb
; b
++)
766 r
* 65535 / (nr
- 1);
768 g
* 65535 / (ng
- 1);
770 b
* 65535 / (nb
- 1);
778 static short *build_mapping_table(int nr
, int ng
, int nb
, Bool use_named
)
784 double mindst
= 40000;
787 colors_map
= build_mapping_colors(nr
, ng
, nb
);
788 Table
= (short *)safemalloc((size
+1) * sizeof(short));
789 for(i
=0; i
<size
; i
++)
792 for(j
=0; j
<PColorLimit
; j
++)
796 /* for back ward compatibility */
797 dst
= TRUE_DIST(colors_map
[i
].red
,
806 dst
= USED_DIST(colors_map
[i
].red
,
813 if (j
== 0 || dst
< mindst
)
821 Table
[size
] = Table
[size
-1];
827 void free_table_colors(PColor
*color_table
, int npixels
)
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;
844 XFreeColors(Pdpy
, Pcmap
, pixels
, n
, 0);
849 /* FIXME: the DirectColor case */
851 int get_nbr_of_free_colors(int max_check
)
855 int map_entries
= (Pvisual
->class == DirectColor
)?
856 (1 << Pdepth
):Pvisual
->map_entries
;
859 if (map_entries
> 256)
863 max_check
= (max_check
> map_entries
) ? map_entries
:max_check
;
866 if (XAllocColorCells(
867 Pdpy
, Pcmap
, False
, NULL
, 0, Pixels
, check
))
869 XFreeColors(Pdpy
, Pcmap
, Pixels
, check
, 0);
876 if (check
> max_check
)
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
;
893 size
= nr
*ng
*nb
+ ngrey
+ (1 << grey_bits
)*(grey_bits
!= 0);
896 ngrey
= (1 << grey_bits
);
898 if (nr
> 0 && ngrey
> 0)
901 end_grey
= ngrey
- 1;
910 color_table
= (PColor
*)safemalloc((size
+1) * sizeof(PColor
));
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)
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));
935 if (!XAllocColor(Pdpy
, Pcmap
,
943 color_table
[i
].color
.pixel
=
945 color_table
[i
].alloc_count
= 1;
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
;
962 for (grey
= start_grey
; grey
< end_grey
; grey
++)
964 color
.red
= color
.green
= color
.blue
=
965 GG(grey
* 65535 / (ngrey
- 1));
968 if (!XAllocColor(Pdpy
, Pcmap
, &color
))
970 free_table_colors(color_table
, i
);
974 color_table
[i
].color
.pixel
= color
.pixel
;
975 color_table
[i
].alloc_count
= 1;
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
;
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;
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
1005 Toward the end are some colors to fill in the gaps.
1006 Currently 61 colors in this list.
1008 char *color_names
[] =
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 *);
1074 PColor
*color_table
;
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
);
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
);
1091 if (!XAllocColor(Pdpy
, Pcmap
, &color
))
1093 free_table_colors(color_table
, i
);
1097 color_table
[i
].color
.pixel
= color
.pixel
;
1098 color_table
[i
].alloc_count
= 1;
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
;
1118 void create_mapping_table(
1119 int nr
, int ng
, int nb
, int ngrey
, int grey_bits
,
1120 Bool non_regular_pallet
)
1125 /* initialize dithering colors numbers */
1126 if (!non_regular_pallet
)
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
;
1145 /* dither table should be small */
1147 if (PColorLimit
<= 9)
1152 Pcsi
.d_ngrey_bits
= 0;
1154 else if (PColorLimit
<= 64)
1159 Pcsi
.d_ngrey_bits
= 0;
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)
1182 else if (grey_bits
> 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)
1210 PMappingTable
= build_mapping_table(
1211 Pcsi
.nr
, Pcsi
.ng
, Pcsi
.nb
, non_regular_pallet
);
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
)
1233 ctt
= PICTURE_PAllocTable
+ ctt
;
1235 if (PUseDynamicColors
)
1237 ctt
= PICTURE_PUseDynamicColors
+ ctt
;
1239 if (PStrictColorLimit
)
1241 ctt
= PICTURE_PStrictColorLimit
+ ctt
;
1245 ctt
= PICTURE_use_named
+ ctt
;
1251 env
= safemalloc(PICTURE_TABLETYPE_LENGHT
+ 1);
1252 sprintf(env
, "%i", ctt
);
1253 flib_putenv("FVWM_COLORTABLE_TYPE", env
);
1257 Pac
= (PColor
*)safecalloc(
1258 (1 << Pdepth
), sizeof(PColor
));
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)
1280 int PictureAllocColorTable(
1281 PictureColorLimitOption
*opt
, int call_type
, Bool use_my_color_limit
)
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
;
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
;
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
},
1318 {6, 6, 5, 0, 0, ANY_COLOR_CUBE
},
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
},
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
},
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)},
1352 {0, 0, 0, 0, 4, FVWM_GRAY_SCALE
},
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)},
1361 FVWM_GRAY_SCALE
|FVWM_COLOR_CUBE
|PA_COLOR_CUBE
*(Pdepth
<4)},
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;
1372 use_named_table
= False
;
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
;
1406 /* depth <= 8 and no colors limit ! */
1410 else if (ctt
<= cc_nbr
)
1413 Pct
= alloc_color_cube(
1414 cc
[ctt
][0], cc
[ctt
][1], cc
[ctt
][2], cc
[ctt
][3],
1421 grey_bits
= cc
[ctt
][4];
1425 /* should always happen */
1427 call_type
, ctt
, nr
, ng
, nb
, ngrey
, grey_bits
,
1433 nbr_of_color
= (1 << Pdepth
);
1436 /* parse the color limit env variable */
1437 if ((envp
= getenv("FVWM_COLORLIMIT")) != NULL
)
1441 rest
= GetQuotedString(envp
, &l
, ":", NULL
, NULL
, NULL
);
1442 if (l
&& *l
!= '\0' && (color_limit
= atoi(l
)) >= 0)
1450 if (color_limit
== 9 || color_limit
== 61)
1452 use_named_table
= 1;
1454 if (rest
&& *rest
!= '\0')
1458 strict_cl_set
= True
;
1459 PStrictColorLimit
= 1;
1463 strict_cl_set
= True
;
1464 PStrictColorLimit
= 0;
1466 if (strlen(rest
) > 1 && rest
[1] == '1')
1468 use_named_table
= 1;
1472 use_named_table
= 0;
1474 if (strlen(rest
) > 2 && rest
[2] == '1')
1477 PUseDynamicColors
= 1;
1482 PUseDynamicColors
= 0;
1484 if (strlen(rest
) > 3 && rest
[3] == '1')
1486 alloc_table_set
= True
;
1491 alloc_table_set
= True
;
1496 else if (opt
!= NULL
) /* use the option */
1498 if (opt
->color_limit
> 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)
1528 PUseDynamicColors
= 0;
1530 else if (opt
->not_dynamic
== 0)
1533 PUseDynamicColors
= 0;
1535 if (opt
->allocate
> 0)
1537 alloc_table_set
= True
;
1540 else if (opt
->allocate
== 0)
1542 alloc_table_set
= True
;
1547 if (color_limit
<= 0)
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) */
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
))
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],
1593 get_nbr_of_free_colors(nbr_of_color
))
1599 free_table_colors(Pct
, PColorLimit
);
1608 PUseDynamicColors
= 0;
1610 Pcsi
.pre_allocated_pallet
= 1;
1613 call_type
, i
, cc
[i
][0], cc
[i
][1], cc
[i
][2], cc
[i
][3],
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: */
1629 limit
= nbr_of_color
/3;
1631 limit
= nbr_of_color
/2;
1637 /* direct colors & Pdepth > 8 */
1642 else if (Pdepth
>= 15)
1651 else if (limit
== 256)
1653 if (Pvisual
->class == GrayScale
)
1657 else if (Pvisual
->class == DirectColor
)
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
)
1685 else if (limit
>= 16)
1687 if (Pvisual
->class == GrayScale
)
1696 else if (limit
>= 8)
1710 if (Pvisual
->class == DirectColor
)
1712 /* humm ... Any way this case should never happen in real life:
1713 * DirectColor default colormap! */
1714 PUseDynamicColors
= 0;
1716 PStrictColorLimit
= 1;
1727 /* use the named table ? */
1728 if (use_named_table
)
1731 while(Pct
== NULL
&& i
>= 2)
1733 Pct
= alloc_named_ct(&i
, do_allocate
);
1740 call_type
, PColorLimit
, 0, 0, 0, 0, 0, 1);
1744 /* color cube or regular grey scale */
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],
1762 call_type
, i
, cc
[i
][0], cc
[i
][1], cc
[i
][2], cc
[i
][3],
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);
1773 "[fvwm] ERR -- Cannot get Black and White. exiting!\n");
1780 * Allocation of a private DirectColor cmap this is broken for depth > 16
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
;
1791 red_mask
= Pvisual
->red_mask
;
1792 green_mask
= Pvisual
->green_mask
;
1793 blue_mask
= Pvisual
->blue_mask
;
1797 /* Use a standard depth 16 colormap. This is broken FIXME! */
1804 red_mask
, &Pcsi
.red_shift
, &Pcsi
.red_prec
);
1806 green_mask
, &Pcsi
.green_shift
, &Pcsi
.green_prec
);
1808 blue_mask
, &Pcsi
.blue_shift
, &Pcsi
.blue_prec
);
1810 if (!use_my_color_limit
)
1812 /* colors allocated by fvwm we can return */
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
;
1834 colors
[b
].green
= cg
;
1835 colors
[b
].blue
= b
* 65535 / (nb
- 1);
1839 (16 - Pcsi
.blue_prec
)) <<
1842 XStoreColors(Pdpy
, Pcmap
, colors
, nb
);
1850 * Init the table for Static Colors
1853 void init_static_colors_table(void)
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
1885 void print_colormap(Colormap cmap
)
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
,
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
)
1915 return Pcsi
.alloc_color_no_limit(dpy
, cmap
, c
);
1919 return Pcsi
.alloc_color(dpy
, cmap
, c
);
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
)
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
);
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
);
1953 int PictureAllocColorImage(
1954 Display
*dpy
, PictureImageColorAllocator
*pica
, XColor
*c
, int x
, int y
)
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
]++;
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;
1993 if (dither
&& Pdepth
<= 16)
1995 pica
->dither
= dither
;
1999 pica
->dither
= dither
;
2001 pica
->no_limit
= no_limit
;
2006 void PictureCloseImageColorAllocator(
2007 Display
*dpy
, PictureImageColorAllocator
*pica
,
2008 int *nalloc_pixels
, Pixel
**alloc_pixels
, Bool
*no_limit
)
2014 if (alloc_pixels
!= NULL
)
2016 *alloc_pixels
= NULL
;
2018 if (no_limit
!= NULL
)
2022 if (pica
->pixels_table
)
2026 unsigned int np
= 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);
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
])
2054 save_pixels
[k
++] = i
;
2056 for(j
=1; j
< pica
->pixels_table
[i
]; j
++)
2058 free_pixels
[l
++] = i
;
2065 dpy
, pica
->cmap
, free_pixels
, free_num
, 0,
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
)
2082 free(pica
->pixels_table
);
2088 void PictureFreeColors(
2089 Display
*dpy
, Colormap cmap
, Pixel
*pixels
, int n
,
2090 unsigned long planes
, Bool no_limit
)
2094 if (Pcsi
.free_colors_no_limit
!= NULL
)
2096 Pcsi
.free_colors_no_limit(
2097 dpy
, cmap
, pixels
, n
, planes
);
2102 if (Pcsi
.free_colors
!= NULL
)
2104 Pcsi
.free_colors(dpy
, cmap
, pixels
, n
, planes
);
2110 Pixel
PictureGetNextColor(Pixel p
, int n
)
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)
2137 alloc_color_in_pct(&c
, 0);
2138 return Pct
[0].color
.pixel
;
2143 alloc_color_in_pct(&c
, i
+n
);
2144 return Pct
[i
+n
].color
.pixel
;
2151 /* Replace the color in my_color by the closest matching color
2153 void PictureReduceColorName(char **my_color
)
2156 XColor rgb
; /* place to calc rgb for each color in xpm */
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",
2170 index
= get_color_index(rgb
.red
,rgb
.green
,rgb
.blue
, False
);
2171 /* Finally: replace the color string by the newly determined color
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 */
2183 Bool
PictureDitherByDefault(void)
2192 Bool
PictureUseBWOnly(void)
2194 if (Pdepth
< 2 || (PStrictColorLimit
&& PColorLimit
== 2))
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)
2210 /* direct colors is more or less broken */
2212 Pvisual
->red_mask
, &Pcsi
.red_shift
,
2215 Pvisual
->green_mask
, &Pcsi
.green_shift
,
2218 Pvisual
->blue_mask
, &Pcsi
.blue_shift
,
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
;
2229 Pvisual
->red_mask
, &Pcsi
.red_shift
,
2232 Pvisual
->green_mask
, &Pcsi
.green_shift
,
2235 Pvisual
->blue_mask
, &Pcsi
.blue_shift
,
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
;
2242 if (init_dither
&& (Pdepth
== 15 || Pdepth
== 16))
2244 dither_ok
= my_dither_depth_15_16_init();
2248 Pcsi
.alloc_color_dither
= alloc_color_proportion_dither
;
2252 Pcsi
.alloc_color_dither
= NULL
;
2256 if (0 && Pvisual
->red_mask
!= 0 && Pvisual
->green_mask
!= 0 &&
2257 Pvisual
->blue_mask
!= 0)
2260 Pvisual
->red_mask
, &Pcsi
.red_shift
,
2263 Pvisual
->green_mask
, &Pcsi
.green_shift
,
2266 Pvisual
->blue_mask
, &Pcsi
.blue_shift
,
2268 Pcsi
.alloc_color_no_limit
= alloc_color_proportion
;
2269 Pcsi
.alloc_color
= alloc_color_proportion
;
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();
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
;
2293 /* FIXME: we assume that we have a regular grey ramp */
2296 Pcsi
.alloc_color_no_limit
= alloc_color_proportion_grey
;
2297 Pcsi
.alloc_color
= alloc_color_proportion
;
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();
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
;
2323 Pcsi
.alloc_color_no_limit
= alloc_color_dynamic_no_limit
;
2324 Pcsi
.free_colors_no_limit
= free_colors_x
;
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", "");
2340 /* dynamic classes */
2342 if (!Pdefault
&& Pvisual
->class == DirectColor
)
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", "");
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
;
2367 Pcsi
.free_colors
= NULL
;
2372 Pcsi
.alloc_color
= alloc_color_dynamic_no_limit
;
2373 Pcsi
.free_colors
= free_colors_x
;
2374 Pcsi
.alloc_color_dither
= NULL
;
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
);
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
)));
2422 " Auto Detected: %s, Strict: %s, Allocated: %s,"
2424 (Pcsi
.pre_allocated_pallet
)? "Yes":"No",
2425 (PStrictColorLimit
)? "Yes":"No",
2426 (PAllocTable
)? "Yes":"No",
2427 (PUseDynamicColors
)? "Yes":"No");
2431 fprintf(stderr
," (default colormap)\n");
2433 if (PColorLimit
<= 256)
2437 int count_alloc
= 0;
2441 fprintf(stderr
," The fvwm colors table:\n");
2443 for (i
= 0; i
< PColorLimit
; i
++)
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
)
2460 if ((Pvisual
->class & 1) && Pac
!= NULL
)
2464 fprintf(stderr
," fvwm colors not in"
2467 for(i
=0; i
< nbr_of_colors
; i
++)
2472 if (!Pac
[i
].alloc_count
)
2474 while(j
< PColorLimit
&& !found
)
2476 if (i
== Pct
[j
].color
.pixel
)
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)
2501 fprintf(stderr
," None\n");
2505 if (Pvisual
->class & 1)
2508 " Number of colours used by fvwm:\n");
2510 " In the table: %i\n", count
);
2512 stderr
, " Out of the table: %i\n",
2515 " Total: %i\n", count_alloc
+count
);
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
));
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");
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
)));