fixing parse error in execcommand
[bbkeys.git] / src / Image.cc
blob6074e3766a3ba88b204b8d287ed2ee09a9893bd6
1 // Image.cc for Blackbox - an X11 Window manager
2 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a
5 // copy of this software and associated documentation files (the "Software"),
6 // to deal in the Software without restriction, including without limitation
7 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 // and/or sell copies of the Software, and to permit persons to whom the
9 // Software is furnished to do so, subject to the following conditions:
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 // DEALINGS IN THE SOFTWARE.
21 //
22 // $Id$
24 // stupid macros needed to access some functions in version 2 of the GNU C
25 // library
26 #ifndef _GNU_SOURCE
27 #define _GNU_SOURCE
28 #endif // _GNU_SOURCE
30 #ifdef HAVE_CONFIG_H
31 # include "config.h"
32 #endif // HAVE_CONFIG_H
34 #include "BaseDisplay.hh"
35 #include "Image.hh"
37 #ifdef HAVE_SYS_TYPES_H
38 # include <sys/types.h>
39 #endif // HAVE_SYS_TYPES_H
41 #ifndef u_int32_t
42 # ifdef uint_32_t
43 typedef uint32_t u_int32_t;
44 # else
45 # ifdef __uint32_t
46 typedef __uint32_t u_int32_t;
47 # else
48 typedef unsigned int u_int32_t;
49 # endif
50 # endif
51 #endif
53 #ifdef STDC_HEADERS
54 # include <stdlib.h>
55 # include <string.h>
56 #endif // STDC_HEADERS
58 #ifdef HAVE_STDIO_H
59 # include <stdio.h>
60 #endif // HAVE_STDIO_H
62 #ifdef HAVE_CTYPE_H
63 # include <ctype.h>
64 #endif // HAVE_CTYPE_H
66 static unsigned long bsqrt(unsigned long x) {
67 if (x <= 0) return 0;
68 if (x == 1) return 1;
70 unsigned long r = x >> 1;
71 unsigned long q;
73 while (1) {
74 q = x / r;
75 if (q >= r) return r;
76 r = (r + q) >> 1;
81 BImage::BImage(BImageControl *c, unsigned int w, unsigned int h) {
82 control = c;
84 width = ((signed) w > 0) ? w : 1;
85 height = ((signed) h > 0) ? h : 1;
87 red = new unsigned char[width * height];
88 green = new unsigned char[width * height];
89 blue = new unsigned char[width * height];
91 xtable = ytable = (unsigned int *) 0;
93 cpc = control->getColorsPerChannel();
94 cpccpc = cpc * cpc;
96 control->getColorTables(&red_table, &green_table, &blue_table,
97 &red_offset, &green_offset, &blue_offset,
98 &red_bits, &green_bits, &blue_bits);
100 if (control->getVisual()->c_class != TrueColor)
101 control->getXColorTable(&colors, &ncolors);
105 BImage::~BImage(void) {
106 if (red) delete [] red;
107 if (green) delete [] green;
108 if (blue) delete [] blue;
112 Pixmap BImage::render(BTexture *texture) {
113 if (texture->getTexture() & BImage_ParentRelative)
114 return ParentRelative;
115 else if (texture->getTexture() & BImage_Solid)
116 return render_solid(texture);
117 else if (texture->getTexture() & BImage_Gradient)
118 return render_gradient(texture);
120 return None;
124 Pixmap BImage::render_solid(BTexture *texture) {
125 Pixmap pixmap = XCreatePixmap(control->getBaseDisplay()->getXDisplay(),
126 control->getDrawable(), width,
127 height, control->getDepth());
128 if (pixmap == None) {
129 fprintf(stderr,
130 "BImage::render_solid: error creating pixmap\n");
131 return None;
134 XGCValues gcv;
135 GC gc, hgc, lgc;
137 gcv.foreground = texture->getColor()->getPixel();
138 gcv.fill_style = FillSolid;
139 gc = XCreateGC(control->getBaseDisplay()->getXDisplay(), pixmap,
140 GCForeground | GCFillStyle, &gcv);
142 gcv.foreground = texture->getHiColor()->getPixel();
143 hgc = XCreateGC(control->getBaseDisplay()->getXDisplay(), pixmap,
144 GCForeground, &gcv);
146 gcv.foreground = texture->getLoColor()->getPixel();
147 lgc = XCreateGC(control->getBaseDisplay()->getXDisplay(), pixmap,
148 GCForeground, &gcv);
150 XFillRectangle(control->getBaseDisplay()->getXDisplay(), pixmap, gc, 0, 0,
151 width, height);
153 #ifdef INTERLACE
154 if (texture->getTexture() & BImage_Interlaced) {
155 gcv.foreground = texture->getColorTo()->getPixel();
156 GC igc = XCreateGC(control->getBaseDisplay()->getXDisplay(), pixmap,
157 GCForeground, &gcv);
159 register unsigned int i = 0;
160 for (; i < height; i += 2)
161 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, igc,
162 0, i, width, i);
164 XFreeGC(control->getBaseDisplay()->getXDisplay(), igc);
166 #endif // INTERLACE
169 if (texture->getTexture() & BImage_Bevel1) {
170 if (texture->getTexture() & BImage_Raised) {
171 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, lgc,
172 0, height - 1, width - 1, height - 1);
173 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, lgc,
174 width - 1, height - 1, width - 1, 0);
176 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, hgc,
177 0, 0, width - 1, 0);
178 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, hgc,
179 0, height - 1, 0, 0);
180 } else if (texture->getTexture() & BImage_Sunken) {
181 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, hgc,
182 0, height - 1, width - 1, height - 1);
183 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, hgc,
184 width - 1, height - 1, width - 1, 0);
186 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, lgc,
187 0, 0, width - 1, 0);
188 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, lgc,
189 0, height - 1, 0, 0);
191 } else if (texture->getTexture() & BImage_Bevel2) {
192 if (texture->getTexture() & BImage_Raised) {
193 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, lgc,
194 1, height - 3, width - 3, height - 3);
195 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, lgc,
196 width - 3, height - 3, width - 3, 1);
198 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, hgc,
199 1, 1, width - 3, 1);
200 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, hgc,
201 1, height - 3, 1, 1);
202 } else if (texture->getTexture() & BImage_Sunken) {
203 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, hgc,
204 1, height - 3, width - 3, height - 3);
205 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, hgc,
206 width - 3, height - 3, width - 3, 1);
208 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, lgc,
209 1, 1, width - 3, 1);
210 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, lgc,
211 1, height - 3, 1, 1);
215 XFreeGC(control->getBaseDisplay()->getXDisplay(), gc);
216 XFreeGC(control->getBaseDisplay()->getXDisplay(), hgc);
217 XFreeGC(control->getBaseDisplay()->getXDisplay(), lgc);
219 return pixmap;
223 Pixmap BImage::render_gradient(BTexture *texture) {
224 int inverted = 0;
226 #ifdef INTERLACE
227 interlaced = texture->getTexture() & BImage_Interlaced;
228 #endif // INTERLACE
230 if (texture->getTexture() & BImage_Sunken) {
231 from = texture->getColorTo();
232 to = texture->getColor();
234 if (! (texture->getTexture() & BImage_Invert)) inverted = 1;
235 } else {
236 from = texture->getColor();
237 to = texture->getColorTo();
239 if (texture->getTexture() & BImage_Invert) inverted = 1;
242 control->getGradientBuffers(width, height, &xtable, &ytable);
244 if (texture->getTexture() & BImage_Diagonal) dgradient();
245 else if (texture->getTexture() & BImage_Elliptic) egradient();
246 else if (texture->getTexture() & BImage_Horizontal) hgradient();
247 else if (texture->getTexture() & BImage_Pyramid) pgradient();
248 else if (texture->getTexture() & BImage_Rectangle) rgradient();
249 else if (texture->getTexture() & BImage_Vertical) vgradient();
250 else if (texture->getTexture() & BImage_CrossDiagonal) cdgradient();
251 else if (texture->getTexture() & BImage_PipeCross) pcgradient();
253 if (texture->getTexture() & BImage_Bevel1) bevel1();
254 else if (texture->getTexture() & BImage_Bevel2) bevel2();
256 if (inverted) invert();
258 Pixmap pixmap = renderPixmap();
260 return pixmap;
265 XImage *BImage::renderXImage(void) {
266 XImage *image =
267 XCreateImage(control->getBaseDisplay()->getXDisplay(),
268 control->getVisual(), control->getDepth(), ZPixmap, 0, 0,
269 width, height, 32, 0);
271 if (! image) {
272 fprintf(stderr,
273 "BImage::renderXImage: error creating XImage\n");
274 return (XImage *) 0;
277 // insurance policy
278 image->data = (char *) 0;
280 unsigned char *d = new unsigned char[image->bytes_per_line * (height + 1)];
281 register unsigned int x, y, dithx, dithy, r, g, b, o, er, eg, eb, offset;
283 unsigned char *pixel_data = d, *ppixel_data = d;
284 unsigned long pixel;
286 o = image->bits_per_pixel + ((image->byte_order == MSBFirst) ? 1 : 0);
288 if (control->doDither() && width > 1 && height > 1) {
289 unsigned char dither4[4][4] = { {0, 4, 1, 5},
290 {6, 2, 7, 3},
291 {1, 5, 0, 4},
292 {7, 3, 6, 2} };
294 #ifdef ORDEREDPSEUDO
295 unsigned char dither8[8][8] = { { 0, 32, 8, 40, 2, 34, 10, 42 },
296 { 48, 16, 56, 24, 50, 18, 58, 26 },
297 { 12, 44, 4, 36, 14, 46, 6, 38 },
298 { 60, 28, 52, 20, 62, 30, 54, 22 },
299 { 3, 35, 11, 43, 1, 33, 9, 41 },
300 { 51, 19, 59, 27, 49, 17, 57, 25 },
301 { 15, 47, 7, 39, 13, 45, 5, 37 },
302 { 63, 31, 55, 23, 61, 29, 53, 21 } };
303 #endif // ORDEREDPSEUDO
305 switch (control->getVisual()->c_class) {
306 case TrueColor:
307 // algorithm: ordered dithering... many many thanks to rasterman
308 // (raster@rasterman.com) for telling me about this... portions of this
309 // code is based off of his code in Imlib
310 for (y = 0, offset = 0; y < height; y++) {
311 dithy = y & 0x3;
313 for (x = 0; x < width; x++, offset++) {
314 dithx = x & 0x3;
315 r = red[offset];
316 g = green[offset];
317 b = blue[offset];
319 er = r & (red_bits - 1);
320 eg = g & (green_bits - 1);
321 eb = b & (blue_bits - 1);
323 r = red_table[r];
324 g = green_table[g];
325 b = blue_table[b];
327 if ((dither4[dithy][dithx] < er) && (r < red_table[255])) r++;
328 if ((dither4[dithy][dithx] < eg) && (g < green_table[255])) g++;
329 if ((dither4[dithy][dithx] < eb) && (b < blue_table[255])) b++;
331 pixel = (r << red_offset) | (g << green_offset) | (b << blue_offset);
333 switch (o) {
334 case 16: // 16bpp LSB
335 *pixel_data++ = pixel;
336 *pixel_data++ = pixel >> 8;
337 break;
339 case 17: // 16bpp MSB
340 *pixel_data++ = pixel >> 8;
341 *pixel_data++ = pixel;
342 break;
344 case 24: // 24bpp LSB
345 *pixel_data++ = pixel;
346 *pixel_data++ = pixel >> 8;
347 *pixel_data++ = pixel >> 16;
348 break;
350 case 25: // 24bpp MSB
351 *pixel_data++ = pixel >> 16;
352 *pixel_data++ = pixel >> 8;
353 *pixel_data++ = pixel;
354 break;
356 case 32: // 32bpp LSB
357 *pixel_data++ = pixel;
358 *pixel_data++ = pixel >> 8;
359 *pixel_data++ = pixel >> 16;
360 *pixel_data++ = pixel >> 24;
361 break;
363 case 33: // 32bpp MSB
364 *pixel_data++ = pixel >> 24;
365 *pixel_data++ = pixel >> 16;
366 *pixel_data++ = pixel >> 8;
367 *pixel_data++ = pixel;
368 break;
372 pixel_data = (ppixel_data += image->bytes_per_line);
375 break;
377 case StaticColor:
378 case PseudoColor: {
379 #ifndef ORDEREDPSEUDO
380 short *terr,
381 *rerr = new short[width + 2],
382 *gerr = new short[width + 2],
383 *berr = new short[width + 2],
384 *nrerr = new short[width + 2],
385 *ngerr = new short[width + 2],
386 *nberr = new short[width + 2];
387 int rr, gg, bb, rer, ger, ber;
388 int dd = 255 / control->getColorsPerChannel();
390 for (x = 0; x < width; x++) {
391 *(rerr + x) = *(red + x);
392 *(gerr + x) = *(green + x);
393 *(berr + x) = *(blue + x);
396 *(rerr + x) = *(gerr + x) = *(berr + x) = 0;
397 #endif // ORDEREDPSEUDO
399 for (y = 0, offset = 0; y < height; y++) {
400 #ifdef ORDEREDPSEUDO
401 dithy = y & 7;
403 for (x = 0; x < width; x++, offset++) {
404 dithx = x & 7;
406 r = red[offset];
407 g = green[offset];
408 b = blue[offset];
410 er = r & (red_bits - 1);
411 eg = g & (green_bits - 1);
412 eb = b & (blue_bits - 1);
414 r = red_table[r];
415 g = green_table[g];
416 b = blue_table[b];
418 if ((dither8[dithy][dithx] < er) && (r < red_table[255])) r++;
419 if ((dither8[dithy][dithx] < eg) && (g < green_table[255])) g++;
420 if ((dither8[dithy][dithx] < eb) && (b < blue_table[255])) b++;
422 pixel = (r * cpccpc) + (g * cpc) + b;
423 *(pixel_data++) = colors[pixel].pixel;
426 pixel_data = (ppixel_data += image->bytes_per_line);
428 #else // !ORDEREDPSEUDO
429 if (y < (height - 1)) {
430 int i = offset + width;
431 for (x = 0; x < width; x++, i++) {
432 *(nrerr + x) = *(red + i);
433 *(ngerr + x) = *(green + i);
434 *(nberr + x) = *(blue + i);
437 *(nrerr + x) = *(red + (--i));
438 *(ngerr + x) = *(green + i);
439 *(nberr + x) = *(blue + i);
442 for (x = 0; x < width; x++) {
443 rr = rerr[x];
444 gg = gerr[x];
445 bb = berr[x];
447 if (rr > 255) rr = 255; else if (rr < 0) rr = 0;
448 if (gg > 255) gg = 255; else if (gg < 0) gg = 0;
449 if (bb > 255) bb = 255; else if (bb < 0) bb = 0;
451 r = red_table[rr];
452 g = green_table[gg];
453 b = blue_table[bb];
455 rer = rerr[x] - r*dd;
456 ger = gerr[x] - g*dd;
457 ber = berr[x] - b*dd;
459 pixel = (r * cpccpc) + (g * cpc) + b;
460 *pixel_data++ = colors[pixel].pixel;
462 r = rer >> 1;
463 g = ger >> 1;
464 b = ber >> 1;
465 rerr[x+1] += r;
466 gerr[x+1] += g;
467 berr[x+1] += b;
468 nrerr[x] += r;
469 ngerr[x] += g;
470 nberr[x] += b;
473 offset += width;
475 pixel_data = (ppixel_data += image->bytes_per_line);
477 terr = rerr;
478 rerr = nrerr;
479 nrerr = terr;
481 terr = gerr;
482 gerr = ngerr;
483 ngerr = terr;
485 terr = berr;
486 berr = nberr;
487 nberr = terr;
490 delete [] rerr;
491 delete [] gerr;
492 delete [] berr;
493 delete [] nrerr;
494 delete [] ngerr;
495 delete [] nberr;
496 #endif // ORDEREDPSUEDO
498 break; }
501 case StaticGray:
502 case GrayScale:
503 for (y = 0, offset = 0; y < height; y++) {
504 dithy = y & 0x3;
506 for (x = 0; x < width; x++, offset++) {
507 dithx = x & 0x3;
509 r = *(red + offset);
510 g = *(green + offset);
511 b = *(blue + offset);
513 er = r & 0x7;
514 eg = g & 0x7;
515 eb = b & 0x7;
517 if ((dither[dithy][dithx] < er) && (r < (256 - 8)))
518 r += 8;
519 if ((dither[dithy][dithx] < (eg << 1)) && (g < (256 - 4)))
520 g += 4;
521 if ((dither[dithy][dithx] < eb) && (b < (256 - 8)))
522 b += 8;
524 r = *(red_table + r);
525 g = *(green_table + g);
526 b = *(blue_table + b);
528 g = ((r * 30) + (g * 59) + (b * 11)) / 100;
529 *pixel_data++ = colors[g].pixel;
532 pixel_data = (ppixel_data += image->bytes_per_line);
535 break;
538 default:
539 fprintf(stderr,
540 "BImage::renderXImage: unsupported visual\n");
541 delete [] d;
542 XDestroyImage(image);
543 return (XImage *) 0;
545 } else {
546 switch (control->getVisual()->c_class) {
547 case StaticColor:
548 case PseudoColor:
549 for (y = 0, offset = 0; y < height; y++) {
550 for (x = 0; x < width; x++, offset++) {
551 r = red_table[red[offset]];
552 g = green_table[green[offset]];
553 b = blue_table[blue[offset]];
555 pixel = (r * cpccpc) + (g * cpc) + b;
556 *pixel_data++ = colors[pixel].pixel;
559 pixel_data = (ppixel_data += image->bytes_per_line);
562 break;
564 case TrueColor:
565 for (y = 0, offset = 0; y < height; y++) {
566 for (x = 0; x < width; x++, offset++) {
567 r = red_table[red[offset]];
568 g = green_table[green[offset]];
569 b = blue_table[blue[offset]];
571 pixel = (r << red_offset) | (g << green_offset) | (b << blue_offset);
573 switch (o) {
574 case 16: // 16bpp LSB
575 *pixel_data++ = pixel;
576 *pixel_data++ = pixel >> 8;
577 break;
579 case 17: // 16bpp MSB
580 *pixel_data++ = pixel >> 8;
581 *pixel_data++ = pixel;
582 break;
584 case 24: // 24bpp LSB
585 *pixel_data++ = pixel;
586 *pixel_data++ = pixel >> 8;
587 *pixel_data++ = pixel >> 16;
588 break;
590 case 25: // 24bpp MSB
591 *pixel_data++ = pixel >> 16;
592 *pixel_data++ = pixel >> 8;
593 *pixel_data++ = pixel;
594 break;
596 case 32: // 32bpp LSB
597 *pixel_data++ = pixel;
598 *pixel_data++ = pixel >> 8;
599 *pixel_data++ = pixel >> 16;
600 *pixel_data++ = pixel >> 24;
601 break;
603 case 33: // 32bpp MSB
604 *pixel_data++ = pixel >> 24;
605 *pixel_data++ = pixel >> 16;
606 *pixel_data++ = pixel >> 8;
607 *pixel_data++ = pixel;
608 break;
612 pixel_data = (ppixel_data += image->bytes_per_line);
615 break;
617 case StaticGray:
618 case GrayScale:
619 for (y = 0, offset = 0; y < height; y++) {
620 for (x = 0; x < width; x++, offset++) {
621 r = *(red_table + *(red + offset));
622 g = *(green_table + *(green + offset));
623 b = *(blue_table + *(blue + offset));
625 g = ((r * 30) + (g * 59) + (b * 11)) / 100;
626 *pixel_data++ = colors[g].pixel;
629 pixel_data = (ppixel_data += image->bytes_per_line);
632 break;
634 default:
635 fprintf(stderr,
636 "BImage::renderXImage: unsupported visual\n");
637 delete [] d;
638 XDestroyImage(image);
639 return (XImage *) 0;
643 image->data = (char *) d;
644 return image;
648 Pixmap BImage::renderPixmap(void) {
649 Pixmap pixmap =
650 XCreatePixmap(control->getBaseDisplay()->getXDisplay(),
651 control->getDrawable(), width, height, control->getDepth());
653 if (pixmap == None) {
654 fprintf(stderr,
655 "BImage::renderPixmap: error creating pixmap\n");
656 return None;
659 XImage *image = renderXImage();
661 if (! image) {
662 XFreePixmap(control->getBaseDisplay()->getXDisplay(), pixmap);
663 return None;
664 } else if (! image->data) {
665 XDestroyImage(image);
666 XFreePixmap(control->getBaseDisplay()->getXDisplay(), pixmap);
667 return None;
670 XPutImage(control->getBaseDisplay()->getXDisplay(), pixmap,
671 DefaultGC(control->getBaseDisplay()->getXDisplay(),
672 control->getScreenInfo()->getScreenNumber()),
673 image, 0, 0, 0, 0, width, height);
675 if (image->data) {
676 delete [] image->data;
677 image->data = NULL;
680 XDestroyImage(image);
682 return pixmap;
686 void BImage::bevel1(void) {
687 if (width > 2 && height > 2) {
688 unsigned char *pr = red, *pg = green, *pb = blue;
690 register unsigned char r, g, b, rr ,gg ,bb;
691 register unsigned int w = width, h = height - 1, wh = w * h;
693 while (--w) {
694 r = *pr;
695 rr = r + (r >> 1);
696 if (rr < r) rr = ~0;
697 g = *pg;
698 gg = g + (g >> 1);
699 if (gg < g) gg = ~0;
700 b = *pb;
701 bb = b + (b >> 1);
702 if (bb < b) bb = ~0;
704 *pr = rr;
705 *pg = gg;
706 *pb = bb;
708 r = *(pr + wh);
709 rr = (r >> 2) + (r >> 1);
710 if (rr > r) rr = 0;
711 g = *(pg + wh);
712 gg = (g >> 2) + (g >> 1);
713 if (gg > g) gg = 0;
714 b = *(pb + wh);
715 bb = (b >> 2) + (b >> 1);
716 if (bb > b) bb = 0;
718 *((pr++) + wh) = rr;
719 *((pg++) + wh) = gg;
720 *((pb++) + wh) = bb;
723 r = *pr;
724 rr = r + (r >> 1);
725 if (rr < r) rr = ~0;
726 g = *pg;
727 gg = g + (g >> 1);
728 if (gg < g) gg = ~0;
729 b = *pb;
730 bb = b + (b >> 1);
731 if (bb < b) bb = ~0;
733 *pr = rr;
734 *pg = gg;
735 *pb = bb;
737 r = *(pr + wh);
738 rr = (r >> 2) + (r >> 1);
739 if (rr > r) rr = 0;
740 g = *(pg + wh);
741 gg = (g >> 2) + (g >> 1);
742 if (gg > g) gg = 0;
743 b = *(pb + wh);
744 bb = (b >> 2) + (b >> 1);
745 if (bb > b) bb = 0;
747 *(pr + wh) = rr;
748 *(pg + wh) = gg;
749 *(pb + wh) = bb;
751 pr = red + width;
752 pg = green + width;
753 pb = blue + width;
755 while (--h) {
756 r = *pr;
757 rr = r + (r >> 1);
758 if (rr < r) rr = ~0;
759 g = *pg;
760 gg = g + (g >> 1);
761 if (gg < g) gg = ~0;
762 b = *pb;
763 bb = b + (b >> 1);
764 if (bb < b) bb = ~0;
766 *pr = rr;
767 *pg = gg;
768 *pb = bb;
770 pr += width - 1;
771 pg += width - 1;
772 pb += width - 1;
774 r = *pr;
775 rr = (r >> 2) + (r >> 1);
776 if (rr > r) rr = 0;
777 g = *pg;
778 gg = (g >> 2) + (g >> 1);
779 if (gg > g) gg = 0;
780 b = *pb;
781 bb = (b >> 2) + (b >> 1);
782 if (bb > b) bb = 0;
784 *(pr++) = rr;
785 *(pg++) = gg;
786 *(pb++) = bb;
789 r = *pr;
790 rr = r + (r >> 1);
791 if (rr < r) rr = ~0;
792 g = *pg;
793 gg = g + (g >> 1);
794 if (gg < g) gg = ~0;
795 b = *pb;
796 bb = b + (b >> 1);
797 if (bb < b) bb = ~0;
799 *pr = rr;
800 *pg = gg;
801 *pb = bb;
803 pr += width - 1;
804 pg += width - 1;
805 pb += width - 1;
807 r = *pr;
808 rr = (r >> 2) + (r >> 1);
809 if (rr > r) rr = 0;
810 g = *pg;
811 gg = (g >> 2) + (g >> 1);
812 if (gg > g) gg = 0;
813 b = *pb;
814 bb = (b >> 2) + (b >> 1);
815 if (bb > b) bb = 0;
817 *pr = rr;
818 *pg = gg;
819 *pb = bb;
824 void BImage::bevel2(void) {
825 if (width > 4 && height > 4) {
826 unsigned char r, g, b, rr ,gg ,bb, *pr = red + width + 1,
827 *pg = green + width + 1, *pb = blue + width + 1;
828 unsigned int w = width - 2, h = height - 1, wh = width * (height - 3);
830 while (--w) {
831 r = *pr;
832 rr = r + (r >> 1);
833 if (rr < r) rr = ~0;
834 g = *pg;
835 gg = g + (g >> 1);
836 if (gg < g) gg = ~0;
837 b = *pb;
838 bb = b + (b >> 1);
839 if (bb < b) bb = ~0;
841 *pr = rr;
842 *pg = gg;
843 *pb = bb;
845 r = *(pr + wh);
846 rr = (r >> 2) + (r >> 1);
847 if (rr > r) rr = 0;
848 g = *(pg + wh);
849 gg = (g >> 2) + (g >> 1);
850 if (gg > g) gg = 0;
851 b = *(pb + wh);
852 bb = (b >> 2) + (b >> 1);
853 if (bb > b) bb = 0;
855 *((pr++) + wh) = rr;
856 *((pg++) + wh) = gg;
857 *((pb++) + wh) = bb;
860 pr = red + width;
861 pg = green + width;
862 pb = blue + width;
864 while (--h) {
865 r = *pr;
866 rr = r + (r >> 1);
867 if (rr < r) rr = ~0;
868 g = *pg;
869 gg = g + (g >> 1);
870 if (gg < g) gg = ~0;
871 b = *pb;
872 bb = b + (b >> 1);
873 if (bb < b) bb = ~0;
875 *(++pr) = rr;
876 *(++pg) = gg;
877 *(++pb) = bb;
879 pr += width - 3;
880 pg += width - 3;
881 pb += width - 3;
883 r = *pr;
884 rr = (r >> 2) + (r >> 1);
885 if (rr > r) rr = 0;
886 g = *pg;
887 gg = (g >> 2) + (g >> 1);
888 if (gg > g) gg = 0;
889 b = *pb;
890 bb = (b >> 2) + (b >> 1);
891 if (bb > b) bb = 0;
893 *(pr++) = rr;
894 *(pg++) = gg;
895 *(pb++) = bb;
897 pr++; pg++; pb++;
903 void BImage::invert(void) {
904 register unsigned int i, j, wh = (width * height) - 1;
905 unsigned char tmp;
907 for (i = 0, j = wh; j > i; j--, i++) {
908 tmp = *(red + j);
909 *(red + j) = *(red + i);
910 *(red + i) = tmp;
912 tmp = *(green + j);
913 *(green + j) = *(green + i);
914 *(green + i) = tmp;
916 tmp = *(blue + j);
917 *(blue + j) = *(blue + i);
918 *(blue + i) = tmp;
923 void BImage::dgradient(void) {
924 // diagonal gradient code was written by Mike Cole <mike@mydot.com>
925 // modified for interlacing by Brad Hughes
927 float drx, dgx, dbx, dry, dgy, dby, yr = 0.0, yg = 0.0, yb = 0.0,
928 xr = (float) from->getRed(),
929 xg = (float) from->getGreen(),
930 xb = (float) from->getBlue();
931 unsigned char *pr = red, *pg = green, *pb = blue;
932 unsigned int w = width * 2, h = height * 2, *xt = xtable, *yt = ytable;
934 register unsigned int x, y;
936 dry = drx = (float) (to->getRed() - from->getRed());
937 dgy = dgx = (float) (to->getGreen() - from->getGreen());
938 dby = dbx = (float) (to->getBlue() - from->getBlue());
940 // Create X table
941 drx /= w;
942 dgx /= w;
943 dbx /= w;
945 for (x = 0; x < width; x++) {
946 *(xt++) = (unsigned char) (xr);
947 *(xt++) = (unsigned char) (xg);
948 *(xt++) = (unsigned char) (xb);
950 xr += drx;
951 xg += dgx;
952 xb += dbx;
955 // Create Y table
956 dry /= h;
957 dgy /= h;
958 dby /= h;
960 for (y = 0; y < height; y++) {
961 *(yt++) = ((unsigned char) yr);
962 *(yt++) = ((unsigned char) yg);
963 *(yt++) = ((unsigned char) yb);
965 yr += dry;
966 yg += dgy;
967 yb += dby;
970 // Combine tables to create gradient
972 #ifdef INTERLACE
973 if (! interlaced) {
974 #endif // INTERLACE
976 // normal dgradient
977 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
978 for (xt = xtable, x = 0; x < width; x++) {
979 *(pr++) = *(xt++) + *(yt);
980 *(pg++) = *(xt++) + *(yt + 1);
981 *(pb++) = *(xt++) + *(yt + 2);
985 #ifdef INTERLACE
986 } else {
987 // faked interlacing effect
988 unsigned char channel, channel2;
990 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
991 for (xt = xtable, x = 0; x < width; x++) {
992 if (y & 1) {
993 channel = *(xt++) + *(yt);
994 channel2 = (channel >> 1) + (channel >> 2);
995 if (channel2 > channel) channel2 = 0;
996 *(pr++) = channel2;
998 channel = *(xt++) + *(yt + 1);
999 channel2 = (channel >> 1) + (channel >> 2);
1000 if (channel2 > channel) channel2 = 0;
1001 *(pg++) = channel2;
1003 channel = *(xt++) + *(yt + 2);
1004 channel2 = (channel >> 1) + (channel >> 2);
1005 if (channel2 > channel) channel2 = 0;
1006 *(pb++) = channel2;
1007 } else {
1008 channel = *(xt++) + *(yt);
1009 channel2 = channel + (channel >> 3);
1010 if (channel2 < channel) channel2 = ~0;
1011 *(pr++) = channel2;
1013 channel = *(xt++) + *(yt + 1);
1014 channel2 = channel + (channel >> 3);
1015 if (channel2 < channel) channel2 = ~0;
1016 *(pg++) = channel2;
1018 channel = *(xt++) + *(yt + 2);
1019 channel2 = channel + (channel >> 3);
1020 if (channel2 < channel) channel2 = ~0;
1021 *(pb++) = channel2;
1026 #endif // INTERLACE
1031 void BImage::hgradient(void) {
1032 float drx, dgx, dbx,
1033 xr = (float) from->getRed(),
1034 xg = (float) from->getGreen(),
1035 xb = (float) from->getBlue();
1036 unsigned char *pr = red, *pg = green, *pb = blue;
1038 register unsigned int x, y;
1040 drx = (float) (to->getRed() - from->getRed());
1041 dgx = (float) (to->getGreen() - from->getGreen());
1042 dbx = (float) (to->getBlue() - from->getBlue());
1044 drx /= width;
1045 dgx /= width;
1046 dbx /= width;
1048 #ifdef INTERLACE
1049 if (interlaced && height > 2) {
1050 // faked interlacing effect
1051 unsigned char channel, channel2;
1053 for (x = 0; x < width; x++, pr++, pg++, pb++) {
1054 channel = (unsigned char) xr;
1055 channel2 = (channel >> 1) + (channel >> 2);
1056 if (channel2 > channel) channel2 = 0;
1057 *pr = channel2;
1059 channel = (unsigned char) xg;
1060 channel2 = (channel >> 1) + (channel >> 2);
1061 if (channel2 > channel) channel2 = 0;
1062 *pg = channel2;
1064 channel = (unsigned char) xb;
1065 channel2 = (channel >> 1) + (channel >> 2);
1066 if (channel2 > channel) channel2 = 0;
1067 *pb = channel2;
1070 channel = (unsigned char) xr;
1071 channel2 = channel + (channel >> 3);
1072 if (channel2 < channel) channel2 = ~0;
1073 *(pr + width) = channel2;
1075 channel = (unsigned char) xg;
1076 channel2 = channel + (channel >> 3);
1077 if (channel2 < channel) channel2 = ~0;
1078 *(pg + width) = channel2;
1080 channel = (unsigned char) xb;
1081 channel2 = channel + (channel >> 3);
1082 if (channel2 < channel) channel2 = ~0;
1083 *(pb + width) = channel2;
1085 xr += drx;
1086 xg += dgx;
1087 xb += dbx;
1090 pr += width;
1091 pg += width;
1092 pb += width;
1094 int offset;
1096 for (y = 2; y < height; y++, pr += width, pg += width, pb += width) {
1097 if (y & 1) offset = width; else offset = 0;
1099 memcpy(pr, (red + offset), width);
1100 memcpy(pg, (green + offset), width);
1101 memcpy(pb, (blue + offset), width);
1103 } else {
1104 #endif // INTERLACE
1106 // normal hgradient
1107 for (x = 0; x < width; x++) {
1108 *(pr++) = (unsigned char) (xr);
1109 *(pg++) = (unsigned char) (xg);
1110 *(pb++) = (unsigned char) (xb);
1112 xr += drx;
1113 xg += dgx;
1114 xb += dbx;
1117 for (y = 1; y < height; y++, pr += width, pg += width, pb += width) {
1118 memcpy(pr, red, width);
1119 memcpy(pg, green, width);
1120 memcpy(pb, blue, width);
1123 #ifdef INTERLACE
1125 #endif // INTERLACE
1130 void BImage::vgradient(void) {
1131 float dry, dgy, dby,
1132 yr = (float) from->getRed(),
1133 yg = (float) from->getGreen(),
1134 yb = (float) from->getBlue();
1135 unsigned char *pr = red, *pg = green, *pb = blue;
1137 register unsigned int y;
1139 dry = (float) (to->getRed() - from->getRed());
1140 dgy = (float) (to->getGreen() - from->getGreen());
1141 dby = (float) (to->getBlue() - from->getBlue());
1143 dry /= height;
1144 dgy /= height;
1145 dby /= height;
1147 #ifdef INTERLACE
1148 if (interlaced) {
1149 // faked interlacing effect
1150 unsigned char channel, channel2;
1152 for (y = 0; y < height; y++, pr += width, pg += width, pb += width) {
1153 if (y & 1) {
1154 channel = (unsigned char) yr;
1155 channel2 = (channel >> 1) + (channel >> 2);
1156 if (channel2 > channel) channel2 = 0;
1157 memset(pr, channel2, width);
1159 channel = (unsigned char) yg;
1160 channel2 = (channel >> 1) + (channel >> 2);
1161 if (channel2 > channel) channel2 = 0;
1162 memset(pg, channel2, width);
1164 channel = (unsigned char) yb;
1165 channel2 = (channel >> 1) + (channel >> 2);
1166 if (channel2 > channel) channel2 = 0;
1167 memset(pb, channel2, width);
1168 } else {
1169 channel = (unsigned char) yr;
1170 channel2 = channel + (channel >> 3);
1171 if (channel2 < channel) channel2 = ~0;
1172 memset(pr, channel2, width);
1174 channel = (unsigned char) yg;
1175 channel2 = channel + (channel >> 3);
1176 if (channel2 < channel) channel2 = ~0;
1177 memset(pg, channel2, width);
1179 channel = (unsigned char) yb;
1180 channel2 = channel + (channel >> 3);
1181 if (channel2 < channel) channel2 = ~0;
1182 memset(pb, channel2, width);
1185 yr += dry;
1186 yg += dgy;
1187 yb += dby;
1189 } else {
1190 #endif // INTERLACE
1192 // normal vgradient
1193 for (y = 0; y < height; y++, pr += width, pg += width, pb += width) {
1194 memset(pr, (unsigned char) yr, width);
1195 memset(pg, (unsigned char) yg, width);
1196 memset(pb, (unsigned char) yb, width);
1198 yr += dry;
1199 yg += dgy;
1200 yb += dby;
1203 #ifdef INTERLACE
1205 #endif // INTERLACE
1210 void BImage::pgradient(void) {
1211 // pyramid gradient - based on original dgradient, written by
1212 // Mosfet (mosfet@kde.org)
1213 // adapted from kde sources for Blackbox by Brad Hughes
1215 float yr, yg, yb, drx, dgx, dbx, dry, dgy, dby,
1216 xr, xg, xb;
1217 int rsign, gsign, bsign;
1218 unsigned char *pr = red, *pg = green, *pb = blue;
1219 unsigned int tr = to->getRed(), tg = to->getGreen(), tb = to->getBlue(),
1220 *xt = xtable, *yt = ytable;
1222 register unsigned int x, y;
1224 dry = drx = (float) (to->getRed() - from->getRed());
1225 dgy = dgx = (float) (to->getGreen() - from->getGreen());
1226 dby = dbx = (float) (to->getBlue() - from->getBlue());
1228 rsign = (drx < 0) ? -1 : 1;
1229 gsign = (dgx < 0) ? -1 : 1;
1230 bsign = (dbx < 0) ? -1 : 1;
1232 xr = yr = (drx / 2);
1233 xg = yg = (dgx / 2);
1234 xb = yb = (dbx / 2);
1236 // Create X table
1237 drx /= width;
1238 dgx /= width;
1239 dbx /= width;
1241 for (x = 0; x < width; x++) {
1242 *(xt++) = (unsigned char) ((xr < 0) ? -xr : xr);
1243 *(xt++) = (unsigned char) ((xg < 0) ? -xg : xg);
1244 *(xt++) = (unsigned char) ((xb < 0) ? -xb : xb);
1246 xr -= drx;
1247 xg -= dgx;
1248 xb -= dbx;
1251 // Create Y table
1252 dry /= height;
1253 dgy /= height;
1254 dby /= height;
1256 for (y = 0; y < height; y++) {
1257 *(yt++) = ((unsigned char) ((yr < 0) ? -yr : yr));
1258 *(yt++) = ((unsigned char) ((yg < 0) ? -yg : yg));
1259 *(yt++) = ((unsigned char) ((yb < 0) ? -yb : yb));
1261 yr -= dry;
1262 yg -= dgy;
1263 yb -= dby;
1266 // Combine tables to create gradient
1268 #ifdef INTERLACE
1269 if (! interlaced) {
1270 #endif // INTERLACE
1272 // normal pgradient
1273 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1274 for (xt = xtable, x = 0; x < width; x++) {
1275 *(pr++) = (unsigned char) (tr - (rsign * (*(xt++) + *(yt))));
1276 *(pg++) = (unsigned char) (tg - (gsign * (*(xt++) + *(yt + 1))));
1277 *(pb++) = (unsigned char) (tb - (bsign * (*(xt++) + *(yt + 2))));
1281 #ifdef INTERLACE
1282 } else {
1283 // faked interlacing effect
1284 unsigned char channel, channel2;
1286 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1287 for (xt = xtable, x = 0; x < width; x++) {
1288 if (y & 1) {
1289 channel = (unsigned char) (tr - (rsign * (*(xt++) + *(yt))));
1290 channel2 = (channel >> 1) + (channel >> 2);
1291 if (channel2 > channel) channel2 = 0;
1292 *(pr++) = channel2;
1294 channel = (unsigned char) (tg - (gsign * (*(xt++) + *(yt + 1))));
1295 channel2 = (channel >> 1) + (channel >> 2);
1296 if (channel2 > channel) channel2 = 0;
1297 *(pg++) = channel2;
1299 channel = (unsigned char) (tb - (bsign * (*(xt++) + *(yt + 2))));
1300 channel2 = (channel >> 1) + (channel >> 2);
1301 if (channel2 > channel) channel2 = 0;
1302 *(pb++) = channel2;
1303 } else {
1304 channel = (unsigned char) (tr - (rsign * (*(xt++) + *(yt))));
1305 channel2 = channel + (channel >> 3);
1306 if (channel2 < channel) channel2 = ~0;
1307 *(pr++) = channel2;
1309 channel = (unsigned char) (tg - (gsign * (*(xt++) + *(yt + 1))));
1310 channel2 = channel + (channel >> 3);
1311 if (channel2 < channel) channel2 = ~0;
1312 *(pg++) = channel2;
1314 channel = (unsigned char) (tb - (bsign * (*(xt++) + *(yt + 2))));
1315 channel2 = channel + (channel >> 3);
1316 if (channel2 < channel) channel2 = ~0;
1317 *(pb++) = channel2;
1322 #endif // INTERLACE
1327 void BImage::rgradient(void) {
1328 // rectangle gradient - based on original dgradient, written by
1329 // Mosfet (mosfet@kde.org)
1330 // adapted from kde sources for Blackbox by Brad Hughes
1332 float drx, dgx, dbx, dry, dgy, dby, xr, xg, xb, yr, yg, yb;
1333 int rsign, gsign, bsign;
1334 unsigned char *pr = red, *pg = green, *pb = blue;
1335 unsigned int tr = to->getRed(), tg = to->getGreen(), tb = to->getBlue(),
1336 *xt = xtable, *yt = ytable;
1338 register unsigned int x, y;
1340 dry = drx = (float) (to->getRed() - from->getRed());
1341 dgy = dgx = (float) (to->getGreen() - from->getGreen());
1342 dby = dbx = (float) (to->getBlue() - from->getBlue());
1344 rsign = (drx < 0) ? -2 : 2;
1345 gsign = (dgx < 0) ? -2 : 2;
1346 bsign = (dbx < 0) ? -2 : 2;
1348 xr = yr = (drx / 2);
1349 xg = yg = (dgx / 2);
1350 xb = yb = (dbx / 2);
1352 // Create X table
1353 drx /= width;
1354 dgx /= width;
1355 dbx /= width;
1357 for (x = 0; x < width; x++) {
1358 *(xt++) = (unsigned char) ((xr < 0) ? -xr : xr);
1359 *(xt++) = (unsigned char) ((xg < 0) ? -xg : xg);
1360 *(xt++) = (unsigned char) ((xb < 0) ? -xb : xb);
1362 xr -= drx;
1363 xg -= dgx;
1364 xb -= dbx;
1367 // Create Y table
1368 dry /= height;
1369 dgy /= height;
1370 dby /= height;
1372 for (y = 0; y < height; y++) {
1373 *(yt++) = ((unsigned char) ((yr < 0) ? -yr : yr));
1374 *(yt++) = ((unsigned char) ((yg < 0) ? -yg : yg));
1375 *(yt++) = ((unsigned char) ((yb < 0) ? -yb : yb));
1377 yr -= dry;
1378 yg -= dgy;
1379 yb -= dby;
1382 // Combine tables to create gradient
1384 #ifdef INTERLACE
1385 if (! interlaced) {
1386 #endif // INTERLACE
1388 // normal rgradient
1389 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1390 for (xt = xtable, x = 0; x < width; x++) {
1391 *(pr++) = (unsigned char) (tr - (rsign * max(*(xt++), *(yt))));
1392 *(pg++) = (unsigned char) (tg - (gsign * max(*(xt++), *(yt + 1))));
1393 *(pb++) = (unsigned char) (tb - (bsign * max(*(xt++), *(yt + 2))));
1397 #ifdef INTERLACE
1398 } else {
1399 // faked interlacing effect
1400 unsigned char channel, channel2;
1402 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1403 for (xt = xtable, x = 0; x < width; x++) {
1404 if (y & 1) {
1405 channel = (unsigned char) (tr - (rsign * max(*(xt++), *(yt))));
1406 channel2 = (channel >> 1) + (channel >> 2);
1407 if (channel2 > channel) channel2 = 0;
1408 *(pr++) = channel2;
1410 channel = (unsigned char) (tg - (gsign * max(*(xt++), *(yt + 1))));
1411 channel2 = (channel >> 1) + (channel >> 2);
1412 if (channel2 > channel) channel2 = 0;
1413 *(pg++) = channel2;
1415 channel = (unsigned char) (tb - (bsign * max(*(xt++), *(yt + 2))));
1416 channel2 = (channel >> 1) + (channel >> 2);
1417 if (channel2 > channel) channel2 = 0;
1418 *(pb++) = channel2;
1419 } else {
1420 channel = (unsigned char) (tr - (rsign * max(*(xt++), *(yt))));
1421 channel2 = channel + (channel >> 3);
1422 if (channel2 < channel) channel2 = ~0;
1423 *(pr++) = channel2;
1425 channel = (unsigned char) (tg - (gsign * max(*(xt++), *(yt + 1))));
1426 channel2 = channel + (channel >> 3);
1427 if (channel2 < channel) channel2 = ~0;
1428 *(pg++) = channel2;
1430 channel = (unsigned char) (tb - (bsign * max(*(xt++), *(yt + 2))));
1431 channel2 = channel + (channel >> 3);
1432 if (channel2 < channel) channel2 = ~0;
1433 *(pb++) = channel2;
1438 #endif // INTERLACE
1443 void BImage::egradient(void) {
1444 // elliptic gradient - based on original dgradient, written by
1445 // Mosfet (mosfet@kde.org)
1446 // adapted from kde sources for Blackbox by Brad Hughes
1448 float drx, dgx, dbx, dry, dgy, dby, yr, yg, yb, xr, xg, xb;
1449 int rsign, gsign, bsign;
1450 unsigned char *pr = red, *pg = green, *pb = blue;
1451 unsigned int *xt = xtable, *yt = ytable,
1452 tr = (unsigned long) to->getRed(),
1453 tg = (unsigned long) to->getGreen(),
1454 tb = (unsigned long) to->getBlue();
1456 register unsigned int x, y;
1458 dry = drx = (float) (to->getRed() - from->getRed());
1459 dgy = dgx = (float) (to->getGreen() - from->getGreen());
1460 dby = dbx = (float) (to->getBlue() - from->getBlue());
1462 rsign = (drx < 0) ? -1 : 1;
1463 gsign = (dgx < 0) ? -1 : 1;
1464 bsign = (dbx < 0) ? -1 : 1;
1466 xr = yr = (drx / 2);
1467 xg = yg = (dgx / 2);
1468 xb = yb = (dbx / 2);
1470 // Create X table
1471 drx /= width;
1472 dgx /= width;
1473 dbx /= width;
1475 for (x = 0; x < width; x++) {
1476 *(xt++) = (unsigned long) (xr * xr);
1477 *(xt++) = (unsigned long) (xg * xg);
1478 *(xt++) = (unsigned long) (xb * xb);
1480 xr -= drx;
1481 xg -= dgx;
1482 xb -= dbx;
1485 // Create Y table
1486 dry /= height;
1487 dgy /= height;
1488 dby /= height;
1490 for (y = 0; y < height; y++) {
1491 *(yt++) = (unsigned long) (yr * yr);
1492 *(yt++) = (unsigned long) (yg * yg);
1493 *(yt++) = (unsigned long) (yb * yb);
1495 yr -= dry;
1496 yg -= dgy;
1497 yb -= dby;
1500 // Combine tables to create gradient
1502 #ifdef INTERLACE
1503 if (! interlaced) {
1504 #endif // INTERLACE
1506 // normal egradient
1507 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1508 for (xt = xtable, x = 0; x < width; x++) {
1509 *(pr++) = (unsigned char)
1510 (tr - (rsign * control->getSqrt(*(xt++) + *(yt))));
1511 *(pg++) = (unsigned char)
1512 (tg - (gsign * control->getSqrt(*(xt++) + *(yt + 1))));
1513 *(pb++) = (unsigned char)
1514 (tb - (bsign * control->getSqrt(*(xt++) + *(yt + 2))));
1518 #ifdef INTERLACE
1519 } else {
1520 // faked interlacing effect
1521 unsigned char channel, channel2;
1523 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1524 for (xt = xtable, x = 0; x < width; x++) {
1525 if (y & 1) {
1526 channel = (unsigned char)
1527 (tr - (rsign * control->getSqrt(*(xt++) + *(yt))));
1528 channel2 = (channel >> 1) + (channel >> 2);
1529 if (channel2 > channel) channel2 = 0;
1530 *(pr++) = channel2;
1532 channel = (unsigned char)
1533 (tg - (gsign * control->getSqrt(*(xt++) + *(yt + 1))));
1534 channel2 = (channel >> 1) + (channel >> 2);
1535 if (channel2 > channel) channel2 = 0;
1536 *(pg++) = channel2;
1538 channel = (unsigned char)
1539 (tb - (bsign * control->getSqrt(*(xt++) + *(yt + 2))));
1540 channel2 = (channel >> 1) + (channel >> 2);
1541 if (channel2 > channel) channel2 = 0;
1542 *(pb++) = channel2;
1543 } else {
1544 channel = (unsigned char)
1545 (tr - (rsign * control->getSqrt(*(xt++) + *(yt))));
1546 channel2 = channel + (channel >> 3);
1547 if (channel2 < channel) channel2 = ~0;
1548 *(pr++) = channel2;
1550 channel = (unsigned char)
1551 (tg - (gsign * control->getSqrt(*(xt++) + *(yt + 1))));
1552 channel2 = channel + (channel >> 3);
1553 if (channel2 < channel) channel2 = ~0;
1554 *(pg++) = channel2;
1556 channel = (unsigned char)
1557 (tb - (bsign * control->getSqrt(*(xt++) + *(yt + 2))));
1558 channel2 = channel + (channel >> 3);
1559 if (channel2 < channel) channel2 = ~0;
1560 *(pb++) = channel2;
1565 #endif // INTERLACE
1570 void BImage::pcgradient(void) {
1571 // pipe cross gradient - based on original dgradient, written by
1572 // Mosfet (mosfet@kde.org)
1573 // adapted from kde sources for Blackbox by Brad Hughes
1575 float drx, dgx, dbx, dry, dgy, dby, xr, xg, xb, yr, yg, yb;
1576 int rsign, gsign, bsign;
1577 unsigned char *pr = red, *pg = green, *pb = blue;
1578 unsigned int *xt = xtable, *yt = ytable,
1579 tr = to->getRed(),
1580 tg = to->getGreen(),
1581 tb = to->getBlue();
1583 register unsigned int x, y;
1585 dry = drx = (float) (to->getRed() - from->getRed());
1586 dgy = dgx = (float) (to->getGreen() - from->getGreen());
1587 dby = dbx = (float) (to->getBlue() - from->getBlue());
1589 rsign = (drx < 0) ? -2 : 2;
1590 gsign = (dgx < 0) ? -2 : 2;
1591 bsign = (dbx < 0) ? -2 : 2;
1593 xr = yr = (drx / 2);
1594 xg = yg = (dgx / 2);
1595 xb = yb = (dbx / 2);
1597 // Create X table
1598 drx /= width;
1599 dgx /= width;
1600 dbx /= width;
1602 for (x = 0; x < width; x++) {
1603 *(xt++) = (unsigned char) ((xr < 0) ? -xr : xr);
1604 *(xt++) = (unsigned char) ((xg < 0) ? -xg : xg);
1605 *(xt++) = (unsigned char) ((xb < 0) ? -xb : xb);
1607 xr -= drx;
1608 xg -= dgx;
1609 xb -= dbx;
1612 // Create Y table
1613 dry /= height;
1614 dgy /= height;
1615 dby /= height;
1617 for (y = 0; y < height; y++) {
1618 *(yt++) = ((unsigned char) ((yr < 0) ? -yr : yr));
1619 *(yt++) = ((unsigned char) ((yg < 0) ? -yg : yg));
1620 *(yt++) = ((unsigned char) ((yb < 0) ? -yb : yb));
1622 yr -= dry;
1623 yg -= dgy;
1624 yb -= dby;
1627 // Combine tables to create gradient
1629 #ifdef INTERLACE
1630 if (! interlaced) {
1631 #endif // INTERLACE
1633 // normal pcgradient
1634 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1635 for (xt = xtable, x = 0; x < width; x++) {
1636 *(pr++) = (unsigned char) (tr - (rsign * min(*(xt++), *(yt))));
1637 *(pg++) = (unsigned char) (tg - (gsign * min(*(xt++), *(yt + 1))));
1638 *(pb++) = (unsigned char) (tb - (bsign * min(*(xt++), *(yt + 2))));
1642 #ifdef INTERLACE
1643 } else {
1644 // faked interlacing effect
1645 unsigned char channel, channel2;
1647 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1648 for (xt = xtable, x = 0; x < width; x++) {
1649 if (y & 1) {
1650 channel = (unsigned char) (tr - (rsign * min(*(xt++), *(yt))));
1651 channel2 = (channel >> 1) + (channel >> 2);
1652 if (channel2 > channel) channel2 = 0;
1653 *(pr++) = channel2;
1655 channel = (unsigned char) (tg - (bsign * min(*(xt++), *(yt + 1))));
1656 channel2 = (channel >> 1) + (channel >> 2);
1657 if (channel2 > channel) channel2 = 0;
1658 *(pg++) = channel2;
1660 channel = (unsigned char) (tb - (gsign * min(*(xt++), *(yt + 2))));
1661 channel2 = (channel >> 1) + (channel >> 2);
1662 if (channel2 > channel) channel2 = 0;
1663 *(pb++) = channel2;
1664 } else {
1665 channel = (unsigned char) (tr - (rsign * min(*(xt++), *(yt))));
1666 channel2 = channel + (channel >> 3);
1667 if (channel2 < channel) channel2 = ~0;
1668 *(pr++) = channel2;
1670 channel = (unsigned char) (tg - (gsign * min(*(xt++), *(yt + 1))));
1671 channel2 = channel + (channel >> 3);
1672 if (channel2 < channel) channel2 = ~0;
1673 *(pg++) = channel2;
1675 channel = (unsigned char) (tb - (bsign * min(*(xt++), *(yt + 2))));
1676 channel2 = channel + (channel >> 3);
1677 if (channel2 < channel) channel2 = ~0;
1678 *(pb++) = channel2;
1683 #endif // INTERLACE
1688 void BImage::cdgradient(void) {
1689 // cross diagonal gradient - based on original dgradient, written by
1690 // Mosfet (mosfet@kde.org)
1691 // adapted from kde sources for Blackbox by Brad Hughes
1693 float drx, dgx, dbx, dry, dgy, dby, yr = 0.0, yg = 0.0, yb = 0.0,
1694 xr = (float) from->getRed(),
1695 xg = (float) from->getGreen(),
1696 xb = (float) from->getBlue();
1697 unsigned char *pr = red, *pg = green, *pb = blue;
1698 unsigned int w = width * 2, h = height * 2, *xt, *yt;
1700 register unsigned int x, y;
1702 dry = drx = (float) (to->getRed() - from->getRed());
1703 dgy = dgx = (float) (to->getGreen() - from->getGreen());
1704 dby = dbx = (float) (to->getBlue() - from->getBlue());
1706 // Create X table
1707 drx /= w;
1708 dgx /= w;
1709 dbx /= w;
1711 for (xt = (xtable + (width * 3) - 1), x = 0; x < width; x++) {
1712 *(xt--) = (unsigned char) xb;
1713 *(xt--) = (unsigned char) xg;
1714 *(xt--) = (unsigned char) xr;
1716 xr += drx;
1717 xg += dgx;
1718 xb += dbx;
1721 // Create Y table
1722 dry /= h;
1723 dgy /= h;
1724 dby /= h;
1726 for (yt = ytable, y = 0; y < height; y++) {
1727 *(yt++) = (unsigned char) yr;
1728 *(yt++) = (unsigned char) yg;
1729 *(yt++) = (unsigned char) yb;
1731 yr += dry;
1732 yg += dgy;
1733 yb += dby;
1736 // Combine tables to create gradient
1738 #ifdef INTERLACE
1739 if (! interlaced) {
1740 #endif // INTERLACE
1742 // normal cdgradient
1743 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1744 for (xt = xtable, x = 0; x < width; x++) {
1745 *(pr++) = *(xt++) + *(yt);
1746 *(pg++) = *(xt++) + *(yt + 1);
1747 *(pb++) = *(xt++) + *(yt + 2);
1751 #ifdef INTERLACE
1752 } else {
1753 // faked interlacing effect
1754 unsigned char channel, channel2;
1756 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1757 for (xt = xtable, x = 0; x < width; x++) {
1758 if (y & 1) {
1759 channel = *(xt++) + *(yt);
1760 channel2 = (channel >> 1) + (channel >> 2);
1761 if (channel2 > channel) channel2 = 0;
1762 *(pr++) = channel2;
1764 channel = *(xt++) + *(yt + 1);
1765 channel2 = (channel >> 1) + (channel >> 2);
1766 if (channel2 > channel) channel2 = 0;
1767 *(pg++) = channel2;
1769 channel = *(xt++) + *(yt + 2);
1770 channel2 = (channel >> 1) + (channel >> 2);
1771 if (channel2 > channel) channel2 = 0;
1772 *(pb++) = channel2;
1773 } else {
1774 channel = *(xt++) + *(yt);
1775 channel2 = channel + (channel >> 3);
1776 if (channel2 < channel) channel2 = ~0;
1777 *(pr++) = channel2;
1779 channel = *(xt++) + *(yt + 1);
1780 channel2 = channel + (channel >> 3);
1781 if (channel2 < channel) channel2 = ~0;
1782 *(pg++) = channel2;
1784 channel = *(xt++) + *(yt + 2);
1785 channel2 = channel + (channel >> 3);
1786 if (channel2 < channel) channel2 = ~0;
1787 *(pb++) = channel2;
1792 #endif // INTERLACE
1797 BImageControl::BImageControl(BaseDisplay *dpy, ScreenInfo *scrn, Bool _dither,
1798 int _cpc, unsigned long cache_timeout,
1799 unsigned long cmax)
1801 basedisplay = dpy;
1802 screeninfo = scrn;
1803 setDither(_dither);
1804 setColorsPerChannel(_cpc);
1806 cache_max = cmax;
1807 #ifdef TIMEDCACHE
1808 if (cache_timeout) {
1809 timer = new BTimer(basedisplay, this);
1810 timer->setTimeout(cache_timeout);
1811 timer->start();
1812 } else
1813 timer = (BTimer *) 0;
1814 #endif // TIMEDCACHE
1816 colors = (XColor *) 0;
1817 ncolors = 0;
1819 grad_xbuffer = grad_ybuffer = (unsigned int *) 0;
1820 grad_buffer_width = grad_buffer_height = 0;
1822 sqrt_table = (unsigned long *) 0;
1824 screen_depth = screeninfo->getDepth();
1825 window = screeninfo->getRootWindow();
1826 screen_number = screeninfo->getScreenNumber();
1828 int count;
1829 XPixmapFormatValues *pmv = XListPixmapFormats(basedisplay->getXDisplay(),
1830 &count);
1831 root_colormap = DefaultColormap(basedisplay->getXDisplay(), screen_number);
1833 if (pmv) {
1834 bits_per_pixel = 0;
1835 for (int i = 0; i < count; i++)
1836 if (pmv[i].depth == screen_depth) {
1837 bits_per_pixel = pmv[i].bits_per_pixel;
1838 break;
1841 XFree(pmv);
1844 if (bits_per_pixel == 0) bits_per_pixel = screen_depth;
1845 if (bits_per_pixel >= 24) setDither(False);
1847 red_offset = green_offset = blue_offset = 0;
1849 switch (getVisual()->c_class) {
1850 case TrueColor:
1852 int i;
1854 // compute color tables
1855 unsigned long red_mask = getVisual()->red_mask,
1856 green_mask = getVisual()->green_mask,
1857 blue_mask = getVisual()->blue_mask;
1859 while (! (red_mask & 1)) { red_offset++; red_mask >>= 1; }
1860 while (! (green_mask & 1)) { green_offset++; green_mask >>= 1; }
1861 while (! (blue_mask & 1)) { blue_offset++; blue_mask >>= 1; }
1863 red_bits = 255 / red_mask;
1864 green_bits = 255 / green_mask;
1865 blue_bits = 255 / blue_mask;
1867 for (i = 0; i < 256; i++) {
1868 red_color_table[i] = i / red_bits;
1869 green_color_table[i] = i / green_bits;
1870 blue_color_table[i] = i / blue_bits;
1874 break;
1876 case PseudoColor:
1877 case StaticColor:
1879 ncolors = colors_per_channel * colors_per_channel * colors_per_channel;
1881 if (ncolors > (1 << screen_depth)) {
1882 colors_per_channel = (1 << screen_depth) / 3;
1883 ncolors = colors_per_channel * colors_per_channel * colors_per_channel;
1886 if (colors_per_channel < 2 || ncolors > (1 << screen_depth)) {
1887 fprintf(stderr, "BImageControl::BImageControl: invalid colormap size %d "
1888 "(%d/%d/%d) - reducing",
1889 ncolors, colors_per_channel, colors_per_channel,
1890 colors_per_channel);
1892 colors_per_channel = (1 << screen_depth) / 3;
1895 colors = new XColor[ncolors];
1896 if (! colors) {
1897 fprintf(stderr,
1898 "BImageControl::BImageControl: error allocating "
1899 "colormap\n");
1900 exit(1);
1903 int i = 0, ii, p, r, g, b,
1905 #ifdef ORDEREDPSEUDO
1906 bits = 256 / colors_per_channel;
1907 #else // !ORDEREDPSEUDO
1908 bits = 255 / (colors_per_channel - 1);
1909 #endif // ORDEREDPSEUDO
1911 red_bits = green_bits = blue_bits = bits;
1913 for (i = 0; i < 256; i++)
1914 red_color_table[i] = green_color_table[i] = blue_color_table[i] =
1915 i / bits;
1917 for (r = 0, i = 0; r < colors_per_channel; r++)
1918 for (g = 0; g < colors_per_channel; g++)
1919 for (b = 0; b < colors_per_channel; b++, i++) {
1920 colors[i].red = (r * 0xffff) / (colors_per_channel - 1);
1921 colors[i].green = (g * 0xffff) / (colors_per_channel - 1);
1922 colors[i].blue = (b * 0xffff) / (colors_per_channel - 1);;
1923 colors[i].flags = DoRed|DoGreen|DoBlue;
1926 for (i = 0; i < ncolors; i++)
1927 if (! XAllocColor(basedisplay->getXDisplay(), getColormap(),
1928 &colors[i])) {
1929 fprintf(stderr, "couldn't alloc color %i %i %i\n",
1930 colors[i].red, colors[i].green, colors[i].blue);
1931 colors[i].flags = 0;
1932 } else
1933 colors[i].flags = DoRed|DoGreen|DoBlue;
1935 XColor icolors[256];
1936 int incolors = (((1 << screen_depth) > 256) ? 256 : (1 << screen_depth));
1938 for (i = 0; i < incolors; i++)
1939 icolors[i].pixel = i;
1941 XQueryColors(basedisplay->getXDisplay(), getColormap(), icolors,
1942 incolors);
1943 for (i = 0; i < ncolors; i++) {
1944 if (! colors[i].flags) {
1945 unsigned long chk = 0xffffffff, pixel, close = 0;
1947 p = 2;
1948 while (p--) {
1949 for (ii = 0; ii < incolors; ii++) {
1950 r = (colors[i].red - icolors[i].red) >> 8;
1951 g = (colors[i].green - icolors[i].green) >> 8;
1952 b = (colors[i].blue - icolors[i].blue) >> 8;
1953 pixel = (r * r) + (g * g) + (b * b);
1955 if (pixel < chk) {
1956 chk = pixel;
1957 close = ii;
1960 colors[i].red = icolors[close].red;
1961 colors[i].green = icolors[close].green;
1962 colors[i].blue = icolors[close].blue;
1964 if (XAllocColor(basedisplay->getXDisplay(), getColormap(),
1965 &colors[i])) {
1966 colors[i].flags = DoRed|DoGreen|DoBlue;
1967 break;
1974 break;
1977 case GrayScale:
1978 case StaticGray:
1981 if (getVisual()->c_class == StaticGray) {
1982 ncolors = 1 << screen_depth;
1983 } else {
1984 ncolors = colors_per_channel * colors_per_channel * colors_per_channel;
1986 if (ncolors > (1 << screen_depth)) {
1987 colors_per_channel = (1 << screen_depth) / 3;
1988 ncolors =
1989 colors_per_channel * colors_per_channel * colors_per_channel;
1993 if (colors_per_channel < 2 || ncolors > (1 << screen_depth)) {
1994 fprintf(stderr, "BImageControl::BImageControl: invalid colormap size %d "
1995 "(%d/%d/%d) - reducing",
1996 ncolors, colors_per_channel, colors_per_channel,
1997 colors_per_channel);
1999 colors_per_channel = (1 << screen_depth) / 3;
2002 colors = new XColor[ncolors];
2003 if (! colors) {
2004 fprintf(stderr, "BImageControl::BImageControl: error allocating "
2005 "colormap\n");
2006 exit(1);
2009 int i = 0, ii, p, bits = 255 / (colors_per_channel - 1);
2010 red_bits = green_bits = blue_bits = bits;
2012 for (i = 0; i < 256; i++)
2013 red_color_table[i] = green_color_table[i] = blue_color_table[i] =
2014 i / bits;
2016 for (i = 0; i < ncolors; i++) {
2017 colors[i].red = (i * 0xffff) / (colors_per_channel - 1);
2018 colors[i].green = (i * 0xffff) / (colors_per_channel - 1);
2019 colors[i].blue = (i * 0xffff) / (colors_per_channel - 1);;
2020 colors[i].flags = DoRed|DoGreen|DoBlue;
2022 if (! XAllocColor(basedisplay->getXDisplay(), getColormap(),
2023 &colors[i])) {
2024 fprintf(stderr, "couldn't alloc color %i %i %i\n",
2025 colors[i].red, colors[i].green, colors[i].blue);
2026 colors[i].flags = 0;
2027 } else
2028 colors[i].flags = DoRed|DoGreen|DoBlue;
2031 XColor icolors[256];
2032 int incolors = (((1 << screen_depth) > 256) ? 256 :
2033 (1 << screen_depth));
2035 for (i = 0; i < incolors; i++)
2036 icolors[i].pixel = i;
2038 XQueryColors(basedisplay->getXDisplay(), getColormap(), icolors,
2039 incolors);
2040 for (i = 0; i < ncolors; i++) {
2041 if (! colors[i].flags) {
2042 unsigned long chk = 0xffffffff, pixel, close = 0;
2044 p = 2;
2045 while (p--) {
2046 for (ii = 0; ii < incolors; ii++) {
2047 int r = (colors[i].red - icolors[i].red) >> 8;
2048 int g = (colors[i].green - icolors[i].green) >> 8;
2049 int b = (colors[i].blue - icolors[i].blue) >> 8;
2050 pixel = (r * r) + (g * g) + (b * b);
2052 if (pixel < chk) {
2053 chk = pixel;
2054 close = ii;
2057 colors[i].red = icolors[close].red;
2058 colors[i].green = icolors[close].green;
2059 colors[i].blue = icolors[close].blue;
2061 if (XAllocColor(basedisplay->getXDisplay(), getColormap(),
2062 &colors[i])) {
2063 colors[i].flags = DoRed|DoGreen|DoBlue;
2064 break;
2071 break;
2074 default:
2075 fprintf(stderr, "BImageControl::BImageControl: unsupported visual %d\n",
2076 getVisual()->c_class);
2077 exit(1);
2080 cache = new LinkedList<Cache>;
2084 BImageControl::~BImageControl(void) {
2085 if (sqrt_table) {
2086 delete [] sqrt_table;
2089 if (grad_xbuffer) {
2090 delete [] grad_xbuffer;
2093 if (grad_ybuffer) {
2094 delete [] grad_ybuffer;
2097 if (colors) {
2098 unsigned long *pixels = new unsigned long [ncolors];
2100 int i;
2101 for (i = 0; i < ncolors; i++)
2102 *(pixels + i) = (*(colors + i)).pixel;
2104 XFreeColors(basedisplay->getXDisplay(), getColormap(),
2105 pixels, ncolors, 0);
2107 delete [] colors;
2110 if (cache->count()) {
2111 int i, n = cache->count();
2112 fprintf(stderr,
2113 "BImageContol::~BImageControl: pixmap cache - "
2114 "releasing %d pixmaps\n", n);
2116 for (i = 0; i < n; i++) {
2117 Cache *tmp = cache->first();
2118 XFreePixmap(basedisplay->getXDisplay(), tmp->pixmap);
2119 cache->remove(tmp);
2120 delete tmp;
2123 #ifdef TIMEDCACHE
2124 if (timer) {
2125 timer->stop();
2126 delete timer;
2128 #endif // TIMEDCACHE
2131 delete cache;
2135 Pixmap BImageControl::searchCache(unsigned int width, unsigned int height,
2136 unsigned long texture,
2137 BColor *c1, BColor *c2) {
2138 if (cache->count()) {
2139 LinkedListIterator<Cache> it(cache);
2141 for (; it.current(); it++) {
2142 if ((it.current()->width == width) &&
2143 (it.current()->height == height) &&
2144 (it.current()->texture == texture) &&
2145 (it.current()->pixel1 == c1->getPixel()))
2146 if (texture & BImage_Gradient) {
2147 if (it.current()->pixel2 == c2->getPixel()) {
2148 it.current()->count++;
2149 return it.current()->pixmap;
2151 } else {
2152 it.current()->count++;
2153 return it.current()->pixmap;
2158 return None;
2162 Pixmap BImageControl::renderImage(unsigned int width, unsigned int height,
2163 BTexture *texture) {
2164 if (texture->getTexture() & BImage_ParentRelative) return ParentRelative;
2166 Pixmap pixmap = searchCache(width, height, texture->getTexture(),
2167 texture->getColor(), texture->getColorTo());
2168 if (pixmap) return pixmap;
2170 BImage image(this, width, height);
2171 pixmap = image.render(texture);
2173 if (pixmap) {
2174 Cache *tmp = new Cache;
2176 tmp->pixmap = pixmap;
2177 tmp->width = width;
2178 tmp->height = height;
2179 tmp->count = 1;
2180 tmp->texture = texture->getTexture();
2181 tmp->pixel1 = texture->getColor()->getPixel();
2183 if (texture->getTexture() & BImage_Gradient)
2184 tmp->pixel2 = texture->getColorTo()->getPixel();
2185 else
2186 tmp->pixel2 = 0l;
2188 cache->insert(tmp);
2190 if ((unsigned) cache->count() > cache_max) {
2191 #ifdef DEBUG
2192 fprintf(stderr,
2193 "BImageControl::renderImage: cache is large, "
2194 "forcing cleanout\n");
2195 #endif // DEBUG
2197 timeout();
2200 return pixmap;
2203 return None;
2207 void BImageControl::removeImage(Pixmap pixmap) {
2208 if (pixmap) {
2209 LinkedListIterator<Cache> it(cache);
2210 for (; it.current(); it++) {
2211 if (it.current()->pixmap == pixmap) {
2212 Cache *tmp = it.current();
2214 if (tmp->count) {
2215 tmp->count--;
2217 #ifdef TIMEDCACHE
2218 if (! timer) timeout();
2219 #else // !TIMEDCACHE
2220 if (! tmp->count) timeout();
2221 #endif // TIMEDCACHE
2224 return;
2231 unsigned long BImageControl::getColor(const char *colorname,
2232 unsigned char *r, unsigned char *g,
2233 unsigned char *b)
2235 XColor color;
2236 color.pixel = 0;
2238 if (! XParseColor(basedisplay->getXDisplay(), getColormap(),
2239 colorname, &color)) {
2240 fprintf(stderr, "BImageControl::getColor: color parse error: \"%s\"\n",
2241 colorname);
2242 } else if (! XAllocColor(basedisplay->getXDisplay(), getColormap(),
2243 &color)) {
2244 fprintf(stderr, "BImageControl::getColor: color alloc error: \"%s\"\n",
2245 colorname);
2248 if (color.red == 65535) *r = 0xff;
2249 else *r = (unsigned char) (color.red / 0xff);
2250 if (color.green == 65535) *g = 0xff;
2251 else *g = (unsigned char) (color.green / 0xff);
2252 if (color.blue == 65535) *b = 0xff;
2253 else *b = (unsigned char) (color.blue / 0xff);
2255 return color.pixel;
2259 unsigned long BImageControl::getColor(const char *colorname) {
2260 XColor color;
2261 color.pixel = 0;
2263 if (! XParseColor(basedisplay->getXDisplay(), getColormap(),
2264 colorname, &color)) {
2265 fprintf(stderr, "BImageControl::getColor: color parse error: \"%s\"\n",
2266 colorname);
2267 } else if (! XAllocColor(basedisplay->getXDisplay(), getColormap(),
2268 &color)) {
2269 fprintf(stderr, "BImageControl::getColor: color alloc error: \"%s\"\n",
2270 colorname);
2273 return color.pixel;
2277 void BImageControl::getColorTables(unsigned char **rmt, unsigned char **gmt,
2278 unsigned char **bmt,
2279 int *roff, int *goff, int *boff,
2280 int *rbit, int *gbit, int *bbit) {
2281 if (rmt) *rmt = red_color_table;
2282 if (gmt) *gmt = green_color_table;
2283 if (bmt) *bmt = blue_color_table;
2285 if (roff) *roff = red_offset;
2286 if (goff) *goff = green_offset;
2287 if (boff) *boff = blue_offset;
2289 if (rbit) *rbit = red_bits;
2290 if (gbit) *gbit = green_bits;
2291 if (bbit) *bbit = blue_bits;
2295 void BImageControl::getXColorTable(XColor **c, int *n) {
2296 if (c) *c = colors;
2297 if (n) *n = ncolors;
2301 void BImageControl::getGradientBuffers(unsigned int w,
2302 unsigned int h,
2303 unsigned int **xbuf,
2304 unsigned int **ybuf)
2306 if (w > grad_buffer_width) {
2307 if (grad_xbuffer) {
2308 delete [] grad_xbuffer;
2311 grad_buffer_width = w;
2313 grad_xbuffer = new unsigned int[grad_buffer_width * 3];
2316 if (h > grad_buffer_height) {
2317 if (grad_ybuffer) {
2318 delete [] grad_ybuffer;
2321 grad_buffer_height = h;
2323 grad_ybuffer = new unsigned int[grad_buffer_height * 3];
2326 *xbuf = grad_xbuffer;
2327 *ybuf = grad_ybuffer;
2331 void BImageControl::installRootColormap(void) {
2332 Bool install = True;
2333 int i = 0, ncmap = 0;
2334 Colormap *cmaps =
2335 XListInstalledColormaps(basedisplay->getXDisplay(), window, &ncmap);
2337 if (cmaps) {
2338 for (i = 0; i < ncmap; i++)
2339 if (*(cmaps + i) == getColormap())
2340 install = False;
2342 if (install)
2343 XInstallColormap(basedisplay->getXDisplay(), getColormap());
2345 XFree(cmaps);
2350 void BImageControl::setColorsPerChannel(int cpc) {
2351 if (cpc < 2) cpc = 2;
2352 if (cpc > 6) cpc = 6;
2354 colors_per_channel = cpc;
2358 unsigned long BImageControl::getSqrt(unsigned int x) {
2359 if (! sqrt_table) {
2360 // build sqrt table for use with elliptic gradient
2362 sqrt_table = new unsigned long[(256 * 256 * 2) + 1];
2363 int i = 0;
2365 for (; i < (256 * 256 * 2); i++)
2366 *(sqrt_table + i) = bsqrt(i);
2369 return (*(sqrt_table + x));
2373 void BImageControl::parseTexture(BTexture *texture, const char *t) {
2374 if ((! texture) || (! t)) return;
2376 int t_len = strlen(t) + 1, i;
2377 char *ts = new char[t_len];
2378 if (! ts) return;
2380 // convert to lower case
2381 for (i = 0; i < t_len; i++)
2382 *(ts + i) = tolower(*(t + i));
2384 if (strstr(ts, "parentrelative")) {
2385 texture->setTexture(BImage_ParentRelative);
2386 } else {
2387 texture->setTexture(0);
2389 if (strstr(ts, "solid"))
2390 texture->addTexture(BImage_Solid);
2391 else if (strstr(ts, "gradient")) {
2392 texture->addTexture(BImage_Gradient);
2393 if (strstr(ts, "crossdiagonal"))
2394 texture->addTexture(BImage_CrossDiagonal);
2395 else if (strstr(ts, "rectangle"))
2396 texture->addTexture(BImage_Rectangle);
2397 else if (strstr(ts, "pyramid"))
2398 texture->addTexture(BImage_Pyramid);
2399 else if (strstr(ts, "pipecross"))
2400 texture->addTexture(BImage_PipeCross);
2401 else if (strstr(ts, "elliptic"))
2402 texture->addTexture(BImage_Elliptic);
2403 else if (strstr(ts, "diagonal"))
2404 texture->addTexture(BImage_Diagonal);
2405 else if (strstr(ts, "horizontal"))
2406 texture->addTexture(BImage_Horizontal);
2407 else if (strstr(ts, "vertical"))
2408 texture->addTexture(BImage_Vertical);
2409 else
2410 texture->addTexture(BImage_Diagonal);
2411 } else
2412 texture->addTexture(BImage_Solid);
2414 if (strstr(ts, "raised"))
2415 texture->addTexture(BImage_Raised);
2416 else if (strstr(ts, "sunken"))
2417 texture->addTexture(BImage_Sunken);
2418 else if (strstr(ts, "flat"))
2419 texture->addTexture(BImage_Flat);
2420 else
2421 texture->addTexture(BImage_Raised);
2423 if (! (texture->getTexture() & BImage_Flat))
2424 if (strstr(ts, "bevel2"))
2425 texture->addTexture(BImage_Bevel2);
2426 else
2427 texture->addTexture(BImage_Bevel1);
2429 #ifdef INTERLACE
2430 if (strstr(ts, "interlaced"))
2431 texture->addTexture(BImage_Interlaced);
2432 #endif // INTERLACE
2435 delete [] ts;
2439 void BImageControl::parseColor(BColor *color, const char *c) {
2440 if (! color) return;
2442 if (color->isAllocated()) {
2443 unsigned long pixel = color->getPixel();
2445 XFreeColors(basedisplay->getXDisplay(), getColormap(), &pixel, 1, 0);
2447 color->setPixel(0l);
2448 color->setRGB(0, 0, 0);
2449 color->setAllocated(False);
2452 if (c) {
2453 unsigned char r, g, b;
2455 color->setPixel(getColor(c, &r, &g, &b));
2456 color->setRGB(r, g, b);
2457 color->setAllocated(True);
2462 void BImageControl::timeout(void) {
2463 LinkedListIterator<Cache> it(cache);
2464 for (; it.current(); it++) {
2465 Cache *tmp = it.current();
2467 if (tmp->count <= 0) {
2468 XFreePixmap(basedisplay->getXDisplay(), tmp->pixmap);
2469 cache->remove(tmp);
2470 delete tmp;