1
2 #include <stdio.h>
3 #include <stdlib.h>
4
5 #include <X11/Xlib.h>
6
7 #include <grass/gis.h>
8 #include <grass/glocale.h>
9
10 extern Display *dpy;
11 extern int scrn;
12 extern Window grwin;
13 extern XWindowAttributes xwa;
14
15 static int NCOLORS;
16 static unsigned long *xpixels;
17
18 static int Red[256], Grn[256], Blu[256];
19 static int Gray[256];
20
21 static int r_pos, g_pos, b_pos;
22 static int r_size, g_size, b_size;
23 static int r_scale, g_scale, b_scale;
24
25
get_shifts(unsigned long mask,int * pos,int * size,int * scale)26 static void get_shifts(unsigned long mask, int *pos, int *size, int *scale)
27 {
28 int i, j;
29
30 for (i = 0; (mask & 1) == 0; i++)
31 mask >>= 1;
32 if (pos)
33 *pos = i;
34
35 for (j = i; (mask & 1) != 0; j++)
36 mask >>= 1;
37 if (size)
38 *size = j - i;
39 if (scale)
40 *scale = 8 - (j - i);
41 }
42
get_rgb_shifts(void)43 static int get_rgb_shifts(void)
44 {
45 get_shifts(xwa.visual->red_mask, &r_pos, &r_size, &r_scale);
46 get_shifts(xwa.visual->green_mask, &g_pos, &g_size, &g_scale);
47 get_shifts(xwa.visual->blue_mask, &b_pos, &b_size, &b_scale);
48
49 return (1 << r_size) * (1 << g_size) * (1 << b_size);
50 }
51
52 static unsigned long
find_color_gray(unsigned int r,unsigned int g,unsigned int b)53 find_color_gray(unsigned int r, unsigned int g, unsigned int b)
54 {
55 unsigned int y = (r + g + b) / 3;
56
57 return xpixels[Gray[y]];
58 }
59
60 static unsigned long
find_color_indexed(unsigned int r,unsigned int g,unsigned int b)61 find_color_indexed(unsigned int r, unsigned int g, unsigned int b)
62 {
63 return xpixels[Red[r] + Grn[g] + Blu[b]];
64 }
65
66 static unsigned long
find_color_rgb(unsigned int r,unsigned int g,unsigned int b)67 find_color_rgb(unsigned int r, unsigned int g, unsigned int b)
68 {
69 unsigned int rr = r >> r_scale;
70 unsigned int gg = g >> g_scale;
71 unsigned int bb = b >> b_scale;
72
73 return (rr << r_pos) + (gg << g_pos) + (bb << b_pos);
74 }
75
find_color(unsigned int r,unsigned int g,unsigned int b)76 unsigned long find_color(unsigned int r, unsigned int g, unsigned int b)
77 {
78
79 switch (xwa.visual->class) {
80 case StaticGray:
81 case GrayScale:
82 return find_color_gray(r, g, b);
83 case StaticColor:
84 case PseudoColor:
85 return find_color_indexed(r, g, b);
86 case TrueColor:
87 case DirectColor:
88 return find_color_rgb(r, g, b);
89 default:
90 G_fatal_error(_("Unknown visual class [%d]."), xwa.visual->class);
91 return 0;
92 }
93 }
94
get_max_levels(int n_colors,int * rr,int * gg,int * bb)95 static void get_max_levels(int n_colors, int *rr, int *gg, int *bb)
96 {
97 int r, g, b, i;
98
99 for (i = 0; i * i * i < n_colors; i++) ;
100
101 for (r = g = b = i;;) {
102 if (r * g * b <= n_colors)
103 break;
104 b--;
105 if (r * g * b <= n_colors)
106 break;
107 r--;
108 if (r * g * b <= n_colors)
109 break;
110 g--;
111 }
112
113 *rr = r;
114 *gg = g;
115 *bb = b;
116 }
117
get_fewer_levels(int * rr,int * gg,int * bb)118 static int get_fewer_levels(int *rr, int *gg, int *bb)
119 {
120 int r = *rr;
121 int g = *gg;
122 int b = *bb;
123
124 /* 888 -> 887 -> 787 -> 777 -> ... */
125
126 if (r > b) /* 887 -> 787 */
127 r--;
128 else if (g > b) /* 787 -> 777 */
129 g--;
130 else /* 888 -> 888 */
131 b--;
132
133 *rr = r;
134 *gg = g;
135 *bb = b;
136
137 return r >= 2 && g >= 2 && b >= 2;
138 }
139
try_get_colors(Colormap cmap,int nr,int ng,int nb)140 static int try_get_colors(Colormap cmap, int nr, int ng, int nb)
141 {
142 XColor xcolor;
143 int n_pixels;
144 int r, g, b;
145
146 xpixels = (unsigned long *)G_realloc(xpixels,
147 nr * ng * nb *
148 sizeof(unsigned long));
149 n_pixels = 0;
150
151 xcolor.flags = DoRed | DoGreen | DoBlue;
152
153 for (r = 0; r < nr; r++) {
154 for (g = 0; g < ng; g++) {
155 for (b = 0; b < nb; b++) {
156 xcolor.red = (unsigned short)(r * 0xFFFF / (nr - 1));
157 xcolor.green = (unsigned short)(g * 0xFFFF / (ng - 1));
158 xcolor.blue = (unsigned short)(b * 0xFFFF / (nb - 1));
159 if (!XAllocColor(dpy, cmap, &xcolor)) {
160 XFreeColors(dpy, cmap, xpixels, n_pixels,
161 (unsigned long)0);
162 return 0;
163 }
164
165 xpixels[n_pixels++] = xcolor.pixel;
166 }
167 }
168 }
169
170 return 1;
171 }
172
try_get_grays(Colormap cmap,int ny)173 static int try_get_grays(Colormap cmap, int ny)
174 {
175 XColor xcolor;
176 int n_pixels;
177 int y;
178
179 xpixels = (unsigned long *)G_realloc(xpixels, ny * sizeof(unsigned long));
180 n_pixels = 0;
181
182 xcolor.flags = DoRed | DoGreen | DoBlue;
183
184 for (y = 0; y < ny; y++) {
185 unsigned short v = (unsigned short)(y * 0xFFFF / (ny - 1));
186
187 xcolor.red = v;
188 xcolor.green = v;
189 xcolor.blue = v;
190
191 if (!XAllocColor(dpy, cmap, &xcolor)) {
192 XFreeColors(dpy, cmap, xpixels, n_pixels, (unsigned long)0);
193 return y;
194 }
195
196 xpixels[n_pixels++] = xcolor.pixel;
197 }
198
199 return ny;
200 }
201
ramp_colormap(void)202 static Colormap ramp_colormap(void)
203 {
204 int n_colors = xwa.visual->map_entries;
205 Colormap cmap = XCreateColormap(dpy, RootWindow(dpy, scrn),
206 xwa.visual, AllocAll);
207 int i;
208
209 for (i = 0; i < n_colors; i++) {
210 unsigned int k = i * 65535 / (n_colors - 1);
211 unsigned int l = i * 255 / (n_colors - 1);
212 XColor xcolor;
213
214 xcolor.flags = DoRed | DoGreen | DoBlue;
215 xcolor.blue = k;
216 xcolor.green = k;
217 xcolor.red = k;
218 xcolor.pixel = find_color_rgb(l, l, l);
219
220 XStoreColor(dpy, cmap, &xcolor);
221 }
222
223 return cmap;
224 }
225
InitColorTableFixed(Colormap cmap)226 Colormap InitColorTableFixed(Colormap cmap)
227 {
228 int n_colors = xwa.visual->map_entries;
229 int r, g, b, y, i;
230
231 switch (xwa.visual->class) {
232 case StaticGray:
233 case GrayScale:
234 /* determine how many levels of gray we can actually get */
235 y = try_get_grays(cmap, n_colors);
236 if (y > 2 && y < n_colors)
237 y = try_get_grays(cmap, y);
238 if (y < 2)
239 G_fatal_error(_("Unable to get sufficient gray shades."));
240
241 NCOLORS = y;
242
243 for (i = 0; i < 256; i++)
244 Gray[i] = i * y / 256;
245
246 break;
247
248 case StaticColor:
249 case PseudoColor:
250 /* determine how many levels of r, g, and b are possible */
251 get_max_levels(n_colors, &r, &g, &b);
252
253 /* now see how many we can actually get */
254 while (!try_get_colors(cmap, r, g, b))
255 if (!get_fewer_levels(&r, &g, &b))
256 G_fatal_error(_("Unable to get sufficient colors."));
257
258 NCOLORS = r * g * b;
259
260 for (i = 0; i < 256; i++) {
261 Red[i] = (i * r / 256) * g * b;
262 Grn[i] = (i * g / 256) * b;
263 Blu[i] = (i * b / 256);
264 }
265
266 break;
267
268 case DirectColor:
269 G_warning(_("Using private colormap for DirectColor visual."));
270
271 /* free any previously-allocated Colormap */
272 if (cmap != DefaultColormap(dpy, scrn))
273 XFreeColormap(dpy, cmap);
274
275 /* get shift factors for R,G,B masks */
276 NCOLORS = get_rgb_shifts();
277
278 /* create colormap (emulates TrueColor visual) */
279 cmap = ramp_colormap();
280 break;
281
282 case TrueColor:
283 /* get shift factors for R,G,B masks */
284 NCOLORS = get_rgb_shifts();
285 break;
286
287 default:
288 G_fatal_error(_("Unknown visual class [%d]."), xwa.visual->class);
289 break;
290 }
291
292 return cmap;
293 }
294