diff options
author | fluxgen <fluxgen> | 2003-01-09 21:09:49 (GMT) |
---|---|---|
committer | fluxgen <fluxgen> | 2003-01-09 21:09:49 (GMT) |
commit | 7dd4823340ae5f710a08ff3a8fbe4276defc6b85 (patch) | |
tree | f4b6623ecf435a643fcf247d3075aaf79d6e82f3 /src/FbTk/ImageControl.cc | |
parent | 7a74a56fe48b319fecf56cede8e16f9c03dfaa96 (diff) | |
download | fluxbox-7dd4823340ae5f710a08ff3a8fbe4276defc6b85.zip fluxbox-7dd4823340ae5f710a08ff3a8fbe4276defc6b85.tar.bz2 |
moved from fluxbox to fbtk
Diffstat (limited to 'src/FbTk/ImageControl.cc')
-rw-r--r-- | src/FbTk/ImageControl.cc | 613 |
1 files changed, 613 insertions, 0 deletions
diff --git a/src/FbTk/ImageControl.cc b/src/FbTk/ImageControl.cc new file mode 100644 index 0000000..f43628f --- /dev/null +++ b/src/FbTk/ImageControl.cc | |||
@@ -0,0 +1,613 @@ | |||
1 | // ImageControl.cc for FbTk - Fluxbox Toolkit | ||
2 | // Copyright (c) 2001 - 2003 Henrik Kinnunen (fluxbox at users.sourceforge.net) | ||
3 | // | ||
4 | // Image.cc for Blackbox - an X11 Window manager | ||
5 | // Copyright (c) 1997 - 2000 Brad Hughes (bhughes at tcac.net) | ||
6 | // | ||
7 | // Permission is hereby granted, free of charge, to any person obtaining a | ||
8 | // copy of this software and associated documentation files (the "Software"), | ||
9 | // to deal in the Software without restriction, including without limitation | ||
10 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
11 | // and/or sell copies of the Software, and to permit persons to whom the | ||
12 | // Software is furnished to do so, subject to the following conditions: | ||
13 | // | ||
14 | // The above copyright notice and this permission notice shall be included in | ||
15 | // all copies or substantial portions of the Software. | ||
16 | // | ||
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
20 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
22 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
23 | // DEALINGS IN THE SOFTWARE. | ||
24 | |||
25 | // $Id: ImageControl.cc,v 1.1 2003/01/09 21:09:49 fluxgen Exp $ | ||
26 | |||
27 | #include "ImageControl.hh" | ||
28 | |||
29 | #include "TextureRender.hh" | ||
30 | #include "App.hh" | ||
31 | |||
32 | //use GNU extensions | ||
33 | #ifndef _GNU_SOURCE | ||
34 | #define _GNU_SOURCE | ||
35 | #endif // _GNU_SOURCE | ||
36 | |||
37 | |||
38 | #ifdef HAVE_CONFIG_H | ||
39 | #include "config.h" | ||
40 | #endif // HAVE_CONFIG_H | ||
41 | |||
42 | #ifdef HAVE_SYS_TYPES_H | ||
43 | #include <sys/types.h> | ||
44 | #endif // HAVE_SYS_TYPES_H | ||
45 | |||
46 | #include <cstdlib> | ||
47 | #include <cstring> | ||
48 | #include <cstdio> | ||
49 | |||
50 | #ifdef HAVE_CTYPE_H | ||
51 | #include <ctype.h> | ||
52 | #endif // HAVE_CTYPE_H | ||
53 | |||
54 | #include <iostream> | ||
55 | |||
56 | using namespace std; | ||
57 | |||
58 | namespace FbTk { | ||
59 | |||
60 | // lookup table for texture | ||
61 | unsigned long *ImageControl::sqrt_table = 0; | ||
62 | |||
63 | namespace { // anonymous | ||
64 | |||
65 | unsigned long bsqrt(unsigned long x) { | ||
66 | if (x <= 0) return 0; | ||
67 | if (x == 1) return 1; | ||
68 | |||
69 | unsigned long r = x >> 1; | ||
70 | unsigned long q; | ||
71 | |||
72 | while (1) { | ||
73 | q = x / r; | ||
74 | if (q >= r) return r; | ||
75 | r = (r + q) >> 1; | ||
76 | } | ||
77 | } | ||
78 | |||
79 | }; // end anonymous namespace | ||
80 | |||
81 | |||
82 | ImageControl::ImageControl(int screen_num, bool dither, | ||
83 | int cpc, unsigned long cache_timeout, unsigned long cmax): | ||
84 | m_dither(dither), | ||
85 | m_timer(this), | ||
86 | m_colors(0), | ||
87 | m_num_colors(0), | ||
88 | m_colors_per_channel(cpc) { | ||
89 | |||
90 | Display *disp = FbTk::App::instance()->display(); | ||
91 | |||
92 | m_screen_depth = DefaultDepth(disp, screen_num); | ||
93 | m_screen_num = screen_num; | ||
94 | m_root_window = RootWindow(disp, screen_num); | ||
95 | m_visual = DefaultVisual(disp, screen_num); | ||
96 | m_colormap = DefaultColormap(disp, screen_num); | ||
97 | |||
98 | cache_max = cmax; | ||
99 | #ifdef TIMEDCACHE | ||
100 | if (cache_timeout) { | ||
101 | m_timer.setTimeout(cache_timeout); | ||
102 | m_timer.start(); | ||
103 | } | ||
104 | #endif // TIMEDCACHE | ||
105 | |||
106 | createColorTable(); | ||
107 | } | ||
108 | |||
109 | |||
110 | ImageControl::~ImageControl() { | ||
111 | if (sqrt_table) { | ||
112 | delete [] sqrt_table; | ||
113 | } | ||
114 | |||
115 | if (grad_xbuffer) { | ||
116 | delete [] grad_xbuffer; | ||
117 | } | ||
118 | |||
119 | if (grad_ybuffer) { | ||
120 | delete [] grad_ybuffer; | ||
121 | } | ||
122 | |||
123 | if (m_colors) { | ||
124 | unsigned long *pixels = new unsigned long [m_num_colors]; | ||
125 | |||
126 | for (unsigned int color = 0; color < m_num_colors; color++) | ||
127 | *(pixels + color) = (*(m_colors + color)).pixel; | ||
128 | |||
129 | XFreeColors(FbTk::App::instance()->display(), m_colormap, pixels, m_num_colors, 0); | ||
130 | |||
131 | delete [] m_colors; | ||
132 | } | ||
133 | |||
134 | if (cache.size() > 0) { | ||
135 | #ifdef DEBUG | ||
136 | cerr<<"FbTk::ImageContol: pixmap cache - releasing "<<cache.size()<<" pixmaps."<<endl; | ||
137 | #endif // DEBUG | ||
138 | CacheList::iterator it = cache.begin(); | ||
139 | CacheList::iterator it_end = cache.end(); | ||
140 | Display *disp = FbTk::App::instance()->display(); | ||
141 | for (; it != it_end; ++it) { | ||
142 | XFreePixmap(disp, (*it)->pixmap); | ||
143 | delete (*it); | ||
144 | } | ||
145 | |||
146 | } | ||
147 | } | ||
148 | |||
149 | |||
150 | Pixmap ImageControl::searchCache(unsigned int width, unsigned int height, | ||
151 | unsigned long texture_type, | ||
152 | const FbTk::Color &color, const FbTk::Color &color_to) const { | ||
153 | CacheList::iterator it = cache.begin(); | ||
154 | CacheList::iterator it_end = cache.end(); | ||
155 | for (; it != it_end; ++it) { | ||
156 | if (((*it)->width == width) && | ||
157 | ((*it)->height == height) && | ||
158 | ((*it)->texture == texture_type) && | ||
159 | ((*it)->pixel1 == color.pixel())) { | ||
160 | if (texture_type & FbTk::Texture::GRADIENT) { | ||
161 | if ((*it)->pixel2 == color_to.pixel()) { | ||
162 | (*it)->count++; | ||
163 | return (*it)->pixmap; | ||
164 | } | ||
165 | } else { | ||
166 | (*it)->count++; | ||
167 | return (*it)->pixmap; | ||
168 | } | ||
169 | } | ||
170 | } | ||
171 | |||
172 | return None; | ||
173 | } | ||
174 | |||
175 | |||
176 | Pixmap ImageControl::renderImage(unsigned int width, unsigned int height, | ||
177 | const FbTk::Texture &texture) { | ||
178 | |||
179 | if (texture.type() & FbTk::Texture::PARENTRELATIVE) | ||
180 | return ParentRelative; | ||
181 | |||
182 | // search cache first | ||
183 | Pixmap pixmap = searchCache(width, height, texture.type(), | ||
184 | texture.color(), texture.colorTo()); | ||
185 | if (pixmap) | ||
186 | return pixmap; // return cache item | ||
187 | |||
188 | // render new image | ||
189 | TextureRender image(*this, width, height); | ||
190 | pixmap = image.render(texture); | ||
191 | |||
192 | if (pixmap) { | ||
193 | // create new cache item and add it to cache list | ||
194 | |||
195 | Cache *tmp = new Cache; | ||
196 | |||
197 | tmp->pixmap = pixmap; | ||
198 | tmp->width = width; | ||
199 | tmp->height = height; | ||
200 | tmp->count = 1; | ||
201 | tmp->texture = texture.type(); | ||
202 | tmp->pixel1 = texture.color().pixel(); | ||
203 | |||
204 | if (texture.type() & FbTk::Texture::GRADIENT) | ||
205 | tmp->pixel2 = texture.colorTo().pixel(); | ||
206 | else | ||
207 | tmp->pixel2 = 0l; | ||
208 | |||
209 | cache.push_back(tmp); | ||
210 | |||
211 | if ((unsigned) cache.size() > cache_max) { | ||
212 | #ifdef DEBUG | ||
213 | cerr<<"FbTk::ImageControl::renderImage(): cache is large, forcing cleanout"<<endl; | ||
214 | #endif // DEBUG | ||
215 | timeout(); | ||
216 | } | ||
217 | |||
218 | return pixmap; | ||
219 | } | ||
220 | |||
221 | return None; | ||
222 | } | ||
223 | |||
224 | |||
225 | void ImageControl::removeImage(Pixmap pixmap) { | ||
226 | if (!pixmap) | ||
227 | return; | ||
228 | |||
229 | CacheList::iterator it = cache.begin(); | ||
230 | CacheList::iterator it_end = cache.end(); | ||
231 | for (; it != it_end; ++it) { | ||
232 | if ((*it)->pixmap == pixmap) { | ||
233 | if ((*it)->count) { | ||
234 | (*it)->count--; | ||
235 | |||
236 | #ifdef TIMEDCACHE | ||
237 | timeout(); | ||
238 | #else // !TIMEDCACHE | ||
239 | if (! (*it)->count) timeout(); | ||
240 | #endif // TIMEDCACHE | ||
241 | } | ||
242 | |||
243 | return; | ||
244 | } | ||
245 | } | ||
246 | } | ||
247 | |||
248 | |||
249 | void ImageControl::colorTables(const unsigned char **rmt, const unsigned char **gmt, | ||
250 | const unsigned char **bmt, | ||
251 | int *roff, int *goff, int *boff, | ||
252 | int *rbit, int *gbit, int *bbit) const { | ||
253 | |||
254 | if (rmt) *rmt = red_color_table; | ||
255 | if (gmt) *gmt = green_color_table; | ||
256 | if (bmt) *bmt = blue_color_table; | ||
257 | |||
258 | if (roff) *roff = red_offset; | ||
259 | if (goff) *goff = green_offset; | ||
260 | if (boff) *boff = blue_offset; | ||
261 | |||
262 | if (rbit) *rbit = red_bits; | ||
263 | if (gbit) *gbit = green_bits; | ||
264 | if (bbit) *bbit = blue_bits; | ||
265 | } | ||
266 | |||
267 | |||
268 | void ImageControl::getXColorTable(XColor **c, int *n) { | ||
269 | if (c) *c = m_colors; | ||
270 | if (n) *n = m_num_colors; | ||
271 | } | ||
272 | |||
273 | |||
274 | void ImageControl::getGradientBuffers(unsigned int w, | ||
275 | unsigned int h, | ||
276 | unsigned int **xbuf, | ||
277 | unsigned int **ybuf) { | ||
278 | |||
279 | if (w > grad_buffer_width) { | ||
280 | if (grad_xbuffer) { | ||
281 | delete [] grad_xbuffer; | ||
282 | } | ||
283 | |||
284 | grad_buffer_width = w; | ||
285 | |||
286 | grad_xbuffer = new unsigned int[grad_buffer_width * 3]; | ||
287 | } | ||
288 | |||
289 | if (h > grad_buffer_height) { | ||
290 | if (grad_ybuffer) { | ||
291 | delete [] grad_ybuffer; | ||
292 | } | ||
293 | |||
294 | grad_buffer_height = h; | ||
295 | |||
296 | grad_ybuffer = new unsigned int[grad_buffer_height * 3]; | ||
297 | } | ||
298 | |||
299 | *xbuf = grad_xbuffer; | ||
300 | *ybuf = grad_ybuffer; | ||
301 | } | ||
302 | |||
303 | |||
304 | void ImageControl::installRootColormap() { | ||
305 | XGrabServer(FbTk::App::instance()->display()); | ||
306 | |||
307 | |||
308 | Display *disp = FbTk::App::instance()->display(); | ||
309 | bool install = true; | ||
310 | int i = 0, ncmap = 0; | ||
311 | Colormap *cmaps = | ||
312 | XListInstalledColormaps(disp, m_root_window, &ncmap); | ||
313 | |||
314 | if (cmaps) { | ||
315 | for (i = 0; i < ncmap; i++) { | ||
316 | if (*(cmaps + i) == m_colormap) | ||
317 | install = false; | ||
318 | } | ||
319 | |||
320 | if (install) | ||
321 | XInstallColormap(disp, m_colormap); | ||
322 | |||
323 | XFree(cmaps); | ||
324 | } | ||
325 | |||
326 | XUngrabServer(FbTk::App::instance()->display()); | ||
327 | } | ||
328 | |||
329 | |||
330 | void ImageControl::setColorsPerChannel(int cpc) { | ||
331 | if (cpc < 2) cpc = 2; | ||
332 | if (cpc > 6) cpc = 6; | ||
333 | |||
334 | m_colors_per_channel = cpc; | ||
335 | } | ||
336 | |||
337 | |||
338 | unsigned long ImageControl::getSqrt(unsigned int x) const { | ||
339 | if (! sqrt_table) { | ||
340 | // build sqrt table for use with elliptic gradient | ||
341 | |||
342 | sqrt_table = new unsigned long[(256 * 256 * 2) + 1]; | ||
343 | int i = 0; | ||
344 | |||
345 | for (; i < (256 * 256 * 2); i++) | ||
346 | *(sqrt_table + i) = bsqrt(i); | ||
347 | } | ||
348 | |||
349 | return (*(sqrt_table + x)); | ||
350 | } | ||
351 | |||
352 | void ImageControl::timeout() { | ||
353 | Display *disp = FbTk::App::instance()->display(); | ||
354 | CacheList::iterator it = cache.begin(); | ||
355 | CacheList::iterator it_end = cache.end(); | ||
356 | for (; it != it_end; ++it) { | ||
357 | Cache *tmp = (*it); | ||
358 | |||
359 | if (tmp->count <= 0) { | ||
360 | XFreePixmap(disp, tmp->pixmap); | ||
361 | it = cache.erase(it); | ||
362 | delete tmp; | ||
363 | if (it == it_end) break; | ||
364 | } | ||
365 | } | ||
366 | } | ||
367 | |||
368 | void ImageControl::createColorTable() { | ||
369 | Display *disp = FbTk::App::instance()->display(); | ||
370 | |||
371 | grad_xbuffer = grad_ybuffer = (unsigned int *) 0; | ||
372 | grad_buffer_width = grad_buffer_height = 0; | ||
373 | |||
374 | int count; | ||
375 | XPixmapFormatValues *pmv = XListPixmapFormats(disp, &count); | ||
376 | |||
377 | if (pmv) { | ||
378 | bits_per_pixel = 0; | ||
379 | for (int i = 0; i < count; i++) { | ||
380 | if (pmv[i].depth == m_screen_depth) { | ||
381 | bits_per_pixel = pmv[i].bits_per_pixel; | ||
382 | break; | ||
383 | } | ||
384 | } | ||
385 | |||
386 | XFree(pmv); | ||
387 | } | ||
388 | |||
389 | if (bits_per_pixel == 0) | ||
390 | bits_per_pixel = m_screen_depth; | ||
391 | if (bits_per_pixel >= 24) | ||
392 | setDither(false); | ||
393 | |||
394 | red_offset = green_offset = blue_offset = 0; | ||
395 | |||
396 | switch (visual()->c_class) { | ||
397 | case TrueColor: { | ||
398 | int i; | ||
399 | |||
400 | // compute color tables | ||
401 | unsigned long red_mask = visual()->red_mask, | ||
402 | green_mask = visual()->green_mask, | ||
403 | blue_mask = visual()->blue_mask; | ||
404 | |||
405 | while (! (red_mask & 1)) { red_offset++; red_mask >>= 1; } | ||
406 | while (! (green_mask & 1)) { green_offset++; green_mask >>= 1; } | ||
407 | while (! (blue_mask & 1)) { blue_offset++; blue_mask >>= 1; } | ||
408 | |||
409 | red_bits = 255 / red_mask; | ||
410 | green_bits = 255 / green_mask; | ||
411 | blue_bits = 255 / blue_mask; | ||
412 | |||
413 | for (i = 0; i < 256; i++) { | ||
414 | red_color_table[i] = i / red_bits; | ||
415 | green_color_table[i] = i / green_bits; | ||
416 | blue_color_table[i] = i / blue_bits; | ||
417 | } | ||
418 | } | ||
419 | |||
420 | break; | ||
421 | |||
422 | case PseudoColor: | ||
423 | case StaticColor: { | ||
424 | |||
425 | m_num_colors = m_colors_per_channel * m_colors_per_channel * m_colors_per_channel; | ||
426 | |||
427 | if (m_num_colors > static_cast<unsigned int>(1 << m_screen_depth)) { | ||
428 | m_colors_per_channel = (1 << m_screen_depth) / 3; | ||
429 | m_num_colors = m_colors_per_channel * m_colors_per_channel * m_colors_per_channel; | ||
430 | } | ||
431 | |||
432 | if (m_colors_per_channel < 2 || m_num_colors > static_cast<unsigned int>(1 << m_screen_depth)) { | ||
433 | fprintf(stderr, "ImageControl::ImageControl: invalid colormap size %d " | ||
434 | "(%d/%d/%d) - reducing", | ||
435 | m_num_colors, m_colors_per_channel, m_colors_per_channel, | ||
436 | m_colors_per_channel); | ||
437 | |||
438 | m_colors_per_channel = (1 << m_screen_depth) / 3; | ||
439 | } | ||
440 | |||
441 | m_colors = new XColor[m_num_colors]; | ||
442 | |||
443 | int bits = 256 / m_colors_per_channel; | ||
444 | |||
445 | #ifndef ORDEREDPSEUDO | ||
446 | bits = 255 / (m_colors_per_channel - 1); | ||
447 | #endif // ORDEREDPSEUDO | ||
448 | |||
449 | red_bits = green_bits = blue_bits = bits; | ||
450 | |||
451 | for (unsigned int i = 0; i < 256; i++) { | ||
452 | red_color_table[i] = green_color_table[i] = blue_color_table[i] = | ||
453 | i / bits; | ||
454 | } | ||
455 | |||
456 | for (int r = 0, i = 0; r < m_colors_per_channel; r++) { | ||
457 | for (int g = 0; g < m_colors_per_channel; g++) { | ||
458 | for (int b = 0; b < m_colors_per_channel; b++, i++) { | ||
459 | m_colors[i].red = (r * 0xffff) / (m_colors_per_channel - 1); | ||
460 | m_colors[i].green = (g * 0xffff) / (m_colors_per_channel - 1); | ||
461 | m_colors[i].blue = (b * 0xffff) / (m_colors_per_channel - 1);; | ||
462 | m_colors[i].flags = DoRed|DoGreen|DoBlue; | ||
463 | } | ||
464 | } | ||
465 | } | ||
466 | |||
467 | for (unsigned int i = 0; i < m_num_colors; i++) { | ||
468 | if (! XAllocColor(disp, m_colormap, &m_colors[i])) { | ||
469 | fprintf(stderr, "couldn't alloc color %i %i %i\n", | ||
470 | m_colors[i].red, m_colors[i].green, m_colors[i].blue); | ||
471 | m_colors[i].flags = 0; | ||
472 | } else | ||
473 | m_colors[i].flags = DoRed|DoGreen|DoBlue; | ||
474 | } | ||
475 | |||
476 | XColor icolors[256]; | ||
477 | unsigned int incolors = (((1 << m_screen_depth) > 256) ? 256 : (1 << m_screen_depth)); | ||
478 | |||
479 | for (unsigned int i = 0; i < incolors; i++) | ||
480 | icolors[i].pixel = i; | ||
481 | |||
482 | XQueryColors(disp, m_colormap, icolors, incolors); | ||
483 | for (unsigned int i = 0; i < m_num_colors; i++) { | ||
484 | if (! m_colors[i].flags) { | ||
485 | unsigned long chk = 0xffffffff, pixel, close = 0; | ||
486 | char p = 2; | ||
487 | |||
488 | while (p--) { | ||
489 | for (unsigned int ii = 0; ii < incolors; ii++) { | ||
490 | int r = (m_colors[i].red - icolors[i].red) >> 8; | ||
491 | int g = (m_colors[i].green - icolors[i].green) >> 8; | ||
492 | int b = (m_colors[i].blue - icolors[i].blue) >> 8; | ||
493 | pixel = (r * r) + (g * g) + (b * b); | ||
494 | |||
495 | if (pixel < chk) { | ||
496 | chk = pixel; | ||
497 | close = ii; | ||
498 | } | ||
499 | |||
500 | m_colors[i].red = icolors[close].red; | ||
501 | m_colors[i].green = icolors[close].green; | ||
502 | m_colors[i].blue = icolors[close].blue; | ||
503 | |||
504 | if (XAllocColor(disp, m_colormap, | ||
505 | &m_colors[i])) { | ||
506 | m_colors[i].flags = DoRed|DoGreen|DoBlue; | ||
507 | break; | ||
508 | } | ||
509 | } | ||
510 | } | ||
511 | } | ||
512 | } | ||
513 | |||
514 | break; | ||
515 | } | ||
516 | |||
517 | case GrayScale: | ||
518 | case StaticGray: | ||
519 | { | ||
520 | |||
521 | if (visual()->c_class == StaticGray) { | ||
522 | m_num_colors = 1 << m_screen_depth; | ||
523 | } else { | ||
524 | m_num_colors = m_colors_per_channel * m_colors_per_channel * m_colors_per_channel; | ||
525 | |||
526 | if (m_num_colors > static_cast<unsigned int>(1 << m_screen_depth)) { | ||
527 | m_colors_per_channel = (1 << m_screen_depth) / 3; | ||
528 | m_num_colors = m_colors_per_channel * m_colors_per_channel * m_colors_per_channel; | ||
529 | } | ||
530 | } | ||
531 | |||
532 | if (m_colors_per_channel < 2 || m_num_colors > static_cast<unsigned int>(1 << m_screen_depth)) { | ||
533 | fprintf(stderr,"FbTk::ImageControl: invalid colormap size %d " | ||
534 | "(%d/%d/%d) - reducing", | ||
535 | m_num_colors, m_colors_per_channel, m_colors_per_channel, | ||
536 | m_colors_per_channel); | ||
537 | |||
538 | m_colors_per_channel = (1 << m_screen_depth) / 3; | ||
539 | } | ||
540 | |||
541 | m_colors = new XColor[m_num_colors]; | ||
542 | |||
543 | int p, bits = 255 / (m_colors_per_channel - 1); | ||
544 | red_bits = green_bits = blue_bits = bits; | ||
545 | |||
546 | for (unsigned int i = 0; i < 256; i++) | ||
547 | red_color_table[i] = green_color_table[i] = blue_color_table[i] = | ||
548 | i / bits; | ||
549 | |||
550 | for (unsigned int i = 0; i < m_num_colors; i++) { | ||
551 | m_colors[i].red = (i * 0xffff) / (m_colors_per_channel - 1); | ||
552 | m_colors[i].green = (i * 0xffff) / (m_colors_per_channel - 1); | ||
553 | m_colors[i].blue = (i * 0xffff) / (m_colors_per_channel - 1);; | ||
554 | m_colors[i].flags = DoRed|DoGreen|DoBlue; | ||
555 | |||
556 | if (! XAllocColor(disp, m_colormap, | ||
557 | &m_colors[i])) { | ||
558 | fprintf(stderr, "Couldn't alloc color %i %i %i\n", | ||
559 | m_colors[i].red, m_colors[i].green, m_colors[i].blue); | ||
560 | m_colors[i].flags = 0; | ||
561 | } else | ||
562 | m_colors[i].flags = DoRed|DoGreen|DoBlue; | ||
563 | } | ||
564 | |||
565 | |||
566 | XColor icolors[256]; | ||
567 | unsigned int incolors = (((1 << m_screen_depth) > 256) ? 256 : | ||
568 | (1 << m_screen_depth)); | ||
569 | |||
570 | for (unsigned int i = 0; i < incolors; i++) | ||
571 | icolors[i].pixel = i; | ||
572 | |||
573 | XQueryColors(disp, m_colormap, icolors, incolors); | ||
574 | for (unsigned int i = 0; i < m_num_colors; i++) { | ||
575 | if (! m_colors[i].flags) { | ||
576 | unsigned long chk = 0xffffffff, pixel, close = 0; | ||
577 | |||
578 | p = 2; | ||
579 | while (p--) { | ||
580 | for (unsigned int ii = 0; ii < incolors; ii++) { | ||
581 | int r = (m_colors[i].red - icolors[i].red) >> 8; | ||
582 | int g = (m_colors[i].green - icolors[i].green) >> 8; | ||
583 | int b = (m_colors[i].blue - icolors[i].blue) >> 8; | ||
584 | pixel = (r * r) + (g * g) + (b * b); | ||
585 | |||
586 | if (pixel < chk) { | ||
587 | chk = pixel; | ||
588 | close = ii; | ||
589 | } | ||
590 | |||
591 | m_colors[i].red = icolors[close].red; | ||
592 | m_colors[i].green = icolors[close].green; | ||
593 | m_colors[i].blue = icolors[close].blue; | ||
594 | |||
595 | if (XAllocColor(disp, m_colormap, &m_colors[i])) { | ||
596 | m_colors[i].flags = DoRed|DoGreen|DoBlue; | ||
597 | break; | ||
598 | } | ||
599 | } | ||
600 | } | ||
601 | } | ||
602 | } | ||
603 | |||
604 | break; | ||
605 | } | ||
606 | |||
607 | default: | ||
608 | cerr<<"FbTk::ImageControl: Unsupported visual"<<endl; | ||
609 | break; | ||
610 | } | ||
611 | } | ||
612 | |||
613 | }; // end namespace FbTk | ||