1
2 #include <X11/Xlib.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5
6 #ifndef __color_mapper_h
7 # include "color_mapper.H"
8 #endif
9
ColorMapper(Display * dpy_in)10 ColorMapper::ColorMapper(Display *dpy_in)
11 : dpy(dpy_in)
12 {
13 Screen *screen = DefaultScreenOfDisplay(dpy);
14
15 mymap=DefaultColormapOfScreen(screen);
16 cells=0;
17 colors=0;
18 if (DefaultVisualOfScreen(screen)->c_class!=PseudoColor) return;
19
20 cells=CellsOfScreen(screen);
21 colors = new XColor[cells];
22 setup_usage();
23 }
24
~ColorMapper()25 ColorMapper::~ColorMapper() {
26 free_usage();
27 if (colors) delete [] colors;
28 }
29
free_usage()30 void ColorMapper::free_usage() {
31 int i;
32
33 for (i=0;i<cells;i++) {
34 if (colors[i].flags) {
35 XFreeColors(dpy,mymap,&colors[i].pixel,1,0L);
36 }
37 }
38 }
39
setup_usage()40 void ColorMapper::setup_usage() {
41 int i;
42 unsigned long *help;
43
44 for (i=0;i<cells;i++) colors[i].pixel = i;
45 XQueryColors(dpy,mymap,colors,cells);
46 for (i=0;i<cells;i++) colors[i].flags = DoRed | DoGreen | DoBlue;
47
48 help = new unsigned long[cells];
49 /*
50 * allocate unused cells of the colormap for read/write
51 */
52 i = 0;
53 while(XAllocColorCells( dpy, mymap, False, 0L, 0, &help[i], 1 )) {
54 colors[help[i]].flags = 0; // mark unusable for shared color
55 i++;
56 }
57
58 /*
59 * free the pixels again
60 */
61 XFreeColors(dpy,mymap,help,i,0L);
62 delete [] help;
63 XSync( dpy, 0 );
64
65 for (i=0;i<cells;i++) {
66 if (colors[i].flags) { // still not invalidated
67 // all shareable colors are again allocated !!
68 if (XAllocColor(dpy,mymap,&colors[i])) {
69 if ((unsigned)i!=colors[i].pixel) {
70 XFreeColors(dpy,mymap,&colors[i].pixel,1,0L);
71 colors[i].flags=0; // different pixel -> not usefull
72 }
73 }
74 else {
75 colors[i].flags=0; // not allocatable -> not usefull
76 }
77 }
78 }
79 return;
80 }
81
alloc_color(XColor * def)82 unsigned long ColorMapper::alloc_color(XColor *def) {
83 int i;
84 long min_dist=0;
85 int min_i;
86
87 if (!colors) {
88 def->flags=DoRed | DoGreen | DoBlue;
89 if (!XAllocColor(dpy,mymap,def)) {
90 fprintf( stderr, "\n*** failed to allocated color on '%s'\n\n", DisplayString(dpy) );
91 exit(0);
92 }
93 return def->pixel;
94 }
95
96 min_i=-1;
97 for (i=0;i<cells;i++) {
98 if (colors[i].flags) {
99 long rd = ((long)colors[i].red - (long)def->red)/4;
100 long gd = ((long)colors[i].green - (long)def->green)/4;
101 long bd = ((long)colors[i].blue - (long)def->blue)/4;
102 long dist=rd*rd+gd*gd+bd*bd;
103
104 if (min_i<0 || dist<min_dist) {
105 min_dist = dist;
106 min_i = i;
107 }
108 }
109 }
110
111 // reuse already allocated color, when possible
112 if (min_i>=0 && min_dist<15000) {
113 return colors[min_i].pixel;
114 }
115
116 // allocate additional entry for that pixel
117 def->flags=DoRed | DoGreen | DoBlue;
118 if (XAllocColor(dpy,mymap,def)) {
119 colors[def->pixel] = *def;
120 return def->pixel;
121 }
122
123 // allocate the closest entry
124 if (min_i>=0) {
125 return colors[min_i].pixel;
126 }
127
128 // everything else failed ...
129 fprintf( stderr, "can't handle colormap overflow ...\n" );
130 exit(0);
131 return 0; // to eliminate warning
132 }
133
alloc_named_color(const char * name)134 unsigned long ColorMapper::alloc_named_color( const char *name ) {
135 XColor def;
136 if (!XLookupColor(dpy,mymap,name,&def,&def )) {
137 fprintf( stderr, "\n*** failed to query color '%s'\n\n", name );
138 exit(0);
139 }
140 def.flags = DoRed | DoGreen | DoBlue;
141 return alloc_color(&def);
142 }
143