1 // Image.cc from 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:
10 //
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
13 //
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 // stupid macros needed to access some functions in version 2 of the GNU C
23 // library
24
25 #ifndef _GNU_SOURCE
26 #define _GNU_SOURCE
27 #endif // _GNU_SOURCE
28
29 #ifdef HAVE_CONFIG_H
30 # include "../config.h"
31 #endif // HAVE_CONFIG_H
32
33 #include "BaseDisplay.hh"
34 #include "Image.hh"
35
36 #ifdef HAVE_SYS_TYPES_H
37 # include <sys/types.h>
38 #endif // HAVE_SYS_TYPES_H
39
40 #ifndef u_int32_t
41 # ifdef uint_32_t
42 typedef uint32_t u_int32_t;
43 # else
44 # ifdef __uint32_t
45 typedef __uint32_t u_int32_t;
46 # else
47 typedef unsigned int u_int32_t;
48 # endif
49 # endif
50 #endif
51
52 #ifdef STDC_HEADERS
53 # include <stdlib.h>
54 # include <string.h>
55 #endif // STDC_HEADERS
56
57 #ifdef HAVE_STDIO_H
58 # include <stdio.h>
59 #endif // HAVE_STDIO_H
60
61 #ifdef HAVE_CTYPE_H
62 # include <ctype.h>
63 #endif // HAVE_CTYPE_H
64
bsqrt(unsigned long x)65 static 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
BImage(BImageControl * c,unsigned int w,unsigned int h)80 BImage::BImage(BImageControl *c, unsigned int w, unsigned int h) {
81 control = c;
82
83 width = ((signed) w > 0) ? w : 1;
84 height = ((signed) h > 0) ? h : 1;
85
86 red = new unsigned char[width * height];
87 green = new unsigned char[width * height];
88 blue = new unsigned char[width * height];
89
90 xtable = ytable = (unsigned int *) 0;
91
92 cpc = control->getColorsPerChannel();
93 cpccpc = cpc * cpc;
94
95 control->getColorTables(&red_table, &green_table, &blue_table,
96 &red_offset, &green_offset, &blue_offset,
97 &red_bits, &green_bits, &blue_bits);
98
99 if (control->getVisual()->c_class != TrueColor)
100 control->getXColorTable(&colors, &ncolors);
101 }
102
103
~BImage(void)104 BImage::~BImage(void) {
105 if (red) delete [] red;
106 if (green) delete [] green;
107 if (blue) delete [] blue;
108 }
109
110
render(BTexture * texture)111 Pixmap BImage::render(BTexture *texture) {
112 if (texture->getTexture() & BImage_ParentRelative)
113 return ParentRelative;
114 else if (texture->getTexture() & BImage_Solid)
115 return render_solid(texture);
116 else if (texture->getTexture() & BImage_Gradient)
117 return render_gradient(texture);
118
119 return None;
120 }
121
122
render_solid(BTexture * texture)123 Pixmap BImage::render_solid(BTexture *texture) {
124 Pixmap pixmap = XCreatePixmap(control->getBaseDisplay()->getXDisplay(),
125 control->getDrawable(), width,
126 height, control->getDepth());
127 if (pixmap == None) {
128 fprintf(stderr,
129 "BImage::render_solid: error creating pixmap\n");
130 return None;
131 }
132
133 XGCValues gcv;
134 GC gc, hgc, lgc;
135
136 gcv.foreground = texture->getColor()->getPixel();
137 gcv.fill_style = FillSolid;
138 gc = XCreateGC(control->getBaseDisplay()->getXDisplay(), pixmap,
139 GCForeground | GCFillStyle, &gcv);
140
141 gcv.foreground = texture->getHiColor()->getPixel();
142 hgc = XCreateGC(control->getBaseDisplay()->getXDisplay(), pixmap,
143 GCForeground, &gcv);
144
145 gcv.foreground = texture->getLoColor()->getPixel();
146 lgc = XCreateGC(control->getBaseDisplay()->getXDisplay(), pixmap,
147 GCForeground, &gcv);
148
149 XFillRectangle(control->getBaseDisplay()->getXDisplay(), pixmap, gc, 0, 0,
150 width, height);
151
152 #ifdef INTERLACE
153 if (texture->getTexture() & BImage_Interlaced) {
154 gcv.foreground = texture->getColorTo()->getPixel();
155 GC igc = XCreateGC(control->getBaseDisplay()->getXDisplay(), pixmap,
156 GCForeground, &gcv);
157
158 register unsigned int i = 0;
159 for (; i < height; i += 2)
160 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, igc,
161 0, i, width, i);
162
163 XFreeGC(control->getBaseDisplay()->getXDisplay(), igc);
164 }
165 #endif // INTERLACE
166
167
168 if (texture->getTexture() & BImage_Bevel1) {
169 if (texture->getTexture() & BImage_Raised) {
170 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, lgc,
171 0, height - 1, width - 1, height - 1);
172 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, lgc,
173 width - 1, height - 1, width - 1, 0);
174
175 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, hgc,
176 0, 0, width - 1, 0);
177 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, hgc,
178 0, height - 1, 0, 0);
179 } else if (texture->getTexture() & BImage_Sunken) {
180 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, hgc,
181 0, height - 1, width - 1, height - 1);
182 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, hgc,
183 width - 1, height - 1, width - 1, 0);
184
185 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, lgc,
186 0, 0, width - 1, 0);
187 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, lgc,
188 0, height - 1, 0, 0);
189 }
190 } else if (texture->getTexture() & BImage_Bevel2) {
191 if (texture->getTexture() & BImage_Raised) {
192 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, lgc,
193 1, height - 3, width - 3, height - 3);
194 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, lgc,
195 width - 3, height - 3, width - 3, 1);
196
197 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, hgc,
198 1, 1, width - 3, 1);
199 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, hgc,
200 1, height - 3, 1, 1);
201 } else if (texture->getTexture() & BImage_Sunken) {
202 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, hgc,
203 1, height - 3, width - 3, height - 3);
204 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, hgc,
205 width - 3, height - 3, width - 3, 1);
206
207 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, lgc,
208 1, 1, width - 3, 1);
209 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, lgc,
210 1, height - 3, 1, 1);
211 }
212 }
213
214 XFreeGC(control->getBaseDisplay()->getXDisplay(), gc);
215 XFreeGC(control->getBaseDisplay()->getXDisplay(), hgc);
216 XFreeGC(control->getBaseDisplay()->getXDisplay(), lgc);
217
218 return pixmap;
219 }
220
221
render_gradient(BTexture * texture)222 Pixmap BImage::render_gradient(BTexture *texture) {
223 int inverted = 0;
224
225 #ifdef INTERLACE
226 interlaced = texture->getTexture() & BImage_Interlaced;
227 #endif // INTERLACE
228
229 if (texture->getTexture() & BImage_Sunken) {
230 from = texture->getColorTo();
231 to = texture->getColor();
232
233 if (! (texture->getTexture() & BImage_Invert)) inverted = 1;
234 } else {
235 from = texture->getColor();
236 to = texture->getColorTo();
237
238 if (texture->getTexture() & BImage_Invert) inverted = 1;
239 }
240
241 control->getGradientBuffers(width, height, &xtable, &ytable);
242
243 if (texture->getTexture() & BImage_Diagonal) dgradient();
244 else if (texture->getTexture() & BImage_Elliptic) egradient();
245 else if (texture->getTexture() & BImage_Horizontal) hgradient();
246 else if (texture->getTexture() & BImage_Pyramid) pgradient();
247 else if (texture->getTexture() & BImage_Rectangle) rgradient();
248 else if (texture->getTexture() & BImage_Vertical) vgradient();
249 else if (texture->getTexture() & BImage_CrossDiagonal) cdgradient();
250 else if (texture->getTexture() & BImage_PipeCross) pcgradient();
251
252 if (texture->getTexture() & BImage_Bevel1) bevel1();
253 else if (texture->getTexture() & BImage_Bevel2) bevel2();
254
255 if (inverted) invert();
256
257 Pixmap pixmap = renderPixmap();
258
259 return pixmap;
260
261 }
262
263
renderXImage(void)264 XImage *BImage::renderXImage(void) {
265 XImage *image =
266 XCreateImage(control->getBaseDisplay()->getXDisplay(),
267 control->getVisual(), /*24*/control->getDepth(), ZPixmap, 0, 0,
268 width, height, 32, 0);
269
270 if (! image) {
271 fprintf(stderr,
272 "BImage::renderXImage: error creating XImage\n");
273 return (XImage *) 0;
274 }
275
276 // insurance policy
277 image->data = (char *) 0;
278
279 unsigned char *d = new unsigned char[image->bytes_per_line * (height + 1)];
280 register unsigned int x, y, dithx, dithy, r, g, b, o, er, eg, eb, offset;
281
282 unsigned char *pixel_data = d, *ppixel_data = d;
283 unsigned long pixel;
284
285 o = image->bits_per_pixel + ((image->byte_order == MSBFirst) ? 1 : 0);
286
287 if (control->doDither() && width > 1 && height > 1) {
288 unsigned char dither4[4][4] = { {0, 4, 1, 5},
289 {6, 2, 7, 3},
290 {1, 5, 0, 4},
291 {7, 3, 6, 2} };
292
293 #ifdef ORDEREDPSEUDO
294 unsigned char dither8[8][8] = { { 0, 32, 8, 40, 2, 34, 10, 42 },
295 { 48, 16, 56, 24, 50, 18, 58, 26 },
296 { 12, 44, 4, 36, 14, 46, 6, 38 },
297 { 60, 28, 52, 20, 62, 30, 54, 22 },
298 { 3, 35, 11, 43, 1, 33, 9, 41 },
299 { 51, 19, 59, 27, 49, 17, 57, 25 },
300 { 15, 47, 7, 39, 13, 45, 5, 37 },
301 { 63, 31, 55, 23, 61, 29, 53, 21 } };
302 #endif // ORDEREDPSEUDO
303
304 switch (control->getVisual()->c_class) {
305 case TrueColor:
306 // algorithm: ordered dithering... many many thanks to rasterman
307 // (raster@rasterman.com) for telling me about this... portions of this
308 // code is based off of his code in Imlib
309 for (y = 0, offset = 0; y < height; y++) {
310 dithy = y & 0x3;
311
312 for (x = 0; x < width; x++, offset++) {
313 dithx = x & 0x3;
314 r = red[offset];
315 g = green[offset];
316 b = blue[offset];
317
318 er = r & (red_bits - 1);
319 eg = g & (green_bits - 1);
320 eb = b & (blue_bits - 1);
321
322 r = red_table[r];
323 g = green_table[g];
324 b = blue_table[b];
325
326 if ((dither4[dithy][dithx] < er) && (r < red_table[255])) r++;
327 if ((dither4[dithy][dithx] < eg) && (g < green_table[255])) g++;
328 if ((dither4[dithy][dithx] < eb) && (b < blue_table[255])) b++;
329
330 pixel = (r << red_offset) | (g << green_offset) | (b << blue_offset);
331
332 switch (o) {
333 case 16: // 16bpp LSB
334 *pixel_data++ = pixel;
335 *pixel_data++ = pixel >> 8;
336 break;
337
338 case 17: // 16bpp MSB
339 *pixel_data++ = pixel >> 8;
340 *pixel_data++ = pixel;
341 break;
342
343 case 24: // 24bpp LSB
344 *pixel_data++ = pixel;
345 *pixel_data++ = pixel >> 8;
346 *pixel_data++ = pixel >> 16;
347 break;
348
349 case 25: // 24bpp MSB
350 *pixel_data++ = pixel >> 16;
351 *pixel_data++ = pixel >> 8;
352 *pixel_data++ = pixel;
353 break;
354
355 case 32: // 32bpp LSB
356 *pixel_data++ = pixel;
357 *pixel_data++ = pixel >> 8;
358 *pixel_data++ = pixel >> 16;
359 *pixel_data++ = pixel >> 24;
360 break;
361
362 case 33: // 32bpp MSB
363 *pixel_data++ = pixel >> 24;
364 *pixel_data++ = pixel >> 16;
365 *pixel_data++ = pixel >> 8;
366 *pixel_data++ = pixel;
367 break;
368 }
369 }
370
371 pixel_data = (ppixel_data += image->bytes_per_line);
372 }
373
374 break;
375
376 case StaticColor:
377 case PseudoColor: {
378 #ifndef ORDEREDPSEUDO
379 short *terr,
380 *rerr = new short[width + 2],
381 *gerr = new short[width + 2],
382 *berr = new short[width + 2],
383 *nrerr = new short[width + 2],
384 *ngerr = new short[width + 2],
385 *nberr = new short[width + 2];
386 int rr, gg, bb, rer, ger, ber;
387 int dd = 255 / control->getColorsPerChannel();
388
389 for (x = 0; x < width; x++) {
390 *(rerr + x) = *(red + x);
391 *(gerr + x) = *(green + x);
392 *(berr + x) = *(blue + x);
393 }
394
395 *(rerr + x) = *(gerr + x) = *(berr + x) = 0;
396 #endif // ORDEREDPSEUDO
397
398 for (y = 0, offset = 0; y < height; y++) {
399 #ifdef ORDEREDPSEUDO
400 dithy = y & 7;
401
402 for (x = 0; x < width; x++, offset++) {
403 dithx = x & 7;
404
405 r = red[offset];
406 g = green[offset];
407 b = blue[offset];
408
409 er = r & (red_bits - 1);
410 eg = g & (green_bits - 1);
411 eb = b & (blue_bits - 1);
412
413 r = red_table[r];
414 g = green_table[g];
415 b = blue_table[b];
416
417 if ((dither8[dithy][dithx] < er) && (r < red_table[255])) r++;
418 if ((dither8[dithy][dithx] < eg) && (g < green_table[255])) g++;
419 if ((dither8[dithy][dithx] < eb) && (b < blue_table[255])) b++;
420
421 pixel = (r * cpccpc) + (g * cpc) + b;
422 *(pixel_data++) = colors[pixel].pixel;
423 }
424
425 pixel_data = (ppixel_data += image->bytes_per_line);
426 }
427 #else // !ORDEREDPSEUDO
428 if (y < (height - 1)) {
429 int i = offset + width;
430 for (x = 0; x < width; x++, i++) {
431 *(nrerr + x) = *(red + i);
432 *(ngerr + x) = *(green + i);
433 *(nberr + x) = *(blue + i);
434 }
435
436 *(nrerr + x) = *(red + (--i));
437 *(ngerr + x) = *(green + i);
438 *(nberr + x) = *(blue + i);
439 }
440
441 for (x = 0; x < width; x++) {
442 rr = rerr[x];
443 gg = gerr[x];
444 bb = berr[x];
445
446 if (rr > 255) rr = 255; else if (rr < 0) rr = 0;
447 if (gg > 255) gg = 255; else if (gg < 0) gg = 0;
448 if (bb > 255) bb = 255; else if (bb < 0) bb = 0;
449
450 r = red_table[rr];
451 g = green_table[gg];
452 b = blue_table[bb];
453
454 rer = rerr[x] - r*dd;
455 ger = gerr[x] - g*dd;
456 ber = berr[x] - b*dd;
457
458 pixel = (r * cpccpc) + (g * cpc) + b;
459 *pixel_data++ = colors[pixel].pixel;
460
461 r = rer >> 1;
462 g = ger >> 1;
463 b = ber >> 1;
464 rerr[x+1] += r;
465 gerr[x+1] += g;
466 berr[x+1] += b;
467 nrerr[x] += r;
468 ngerr[x] += g;
469 nberr[x] += b;
470 }
471
472 offset += width;
473
474 pixel_data = (ppixel_data += image->bytes_per_line);
475
476 terr = rerr;
477 rerr = nrerr;
478 nrerr = terr;
479
480 terr = gerr;
481 gerr = ngerr;
482 ngerr = terr;
483
484 terr = berr;
485 berr = nberr;
486 nberr = terr;
487 }
488
489 delete [] rerr;
490 delete [] gerr;
491 delete [] berr;
492 delete [] nrerr;
493 delete [] ngerr;
494 delete [] nberr;
495 #endif // ORDEREDPSUEDO
496
497 break; }
498
499 /*
500 case StaticGray:
501 case GrayScale:
502 for (y = 0, offset = 0; y < height; y++) {
503 dithy = y & 0x3;
504
505 for (x = 0; x < width; x++, offset++) {
506 dithx = x & 0x3;
507
508 r = *(red + offset);
509 g = *(green + offset);
510 b = *(blue + offset);
511
512 er = r & 0x7;
513 eg = g & 0x7;
514 eb = b & 0x7;
515
516 if ((dither[dithy][dithx] < er) && (r < (256 - 8)))
517 r += 8;
518 if ((dither[dithy][dithx] < (eg << 1)) && (g < (256 - 4)))
519 g += 4;
520 if ((dither[dithy][dithx] < eb) && (b < (256 - 8)))
521 b += 8;
522
523 r = *(red_table + r);
524 g = *(green_table + g);
525 b = *(blue_table + b);
526
527 g = ((r * 30) + (g * 59) + (b * 11)) / 100;
528 *pixel_data++ = colors[g].pixel;
529 }
530
531 pixel_data = (ppixel_data += image->bytes_per_line);
532 }
533
534 break;
535 */
536
537 default:
538 fprintf(stderr,
539 "BImage::renderXImage: unsupported visual\n");
540 delete [] d;
541 XDestroyImage(image);
542 return (XImage *) 0;
543 }
544 } else {
545 switch (control->getVisual()->c_class) {
546 case StaticColor:
547 case PseudoColor:
548 for (y = 0, offset = 0; y < height; y++) {
549 for (x = 0; x < width; x++, offset++) {
550 r = red_table[red[offset]];
551 g = green_table[green[offset]];
552 b = blue_table[blue[offset]];
553
554 pixel = (r * cpccpc) + (g * cpc) + b;
555 *pixel_data++ = colors[pixel].pixel;
556 }
557
558 pixel_data = (ppixel_data += image->bytes_per_line);
559 }
560
561 break;
562
563 case TrueColor:
564 for (y = 0, offset = 0; y < height; y++) {
565 for (x = 0; x < width; x++, offset++) {
566 r = red_table[red[offset]];
567 g = green_table[green[offset]];
568 b = blue_table[blue[offset]];
569
570 pixel = (r << red_offset) | (g << green_offset) | (b << blue_offset);
571
572 switch (o) {
573 case 16: // 16bpp LSB
574 *pixel_data++ = pixel;
575 *pixel_data++ = pixel >> 8;
576 break;
577
578 case 17: // 16bpp MSB
579 *pixel_data++ = pixel >> 8;
580 *pixel_data++ = pixel;
581 break;
582
583 case 24: // 24bpp LSB
584 *pixel_data++ = pixel;
585 *pixel_data++ = pixel >> 8;
586 *pixel_data++ = pixel >> 16;
587 break;
588
589 case 25: // 24bpp MSB
590 *pixel_data++ = pixel >> 16;
591 *pixel_data++ = pixel >> 8;
592 *pixel_data++ = pixel;
593 break;
594
595 case 32: // 32bpp LSB
596 *pixel_data++ = pixel;
597 *pixel_data++ = pixel >> 8;
598 *pixel_data++ = pixel >> 16;
599 *pixel_data++ = pixel >> 24;
600 break;
601
602 case 33: // 32bpp MSB
603 *pixel_data++ = pixel >> 24;
604 *pixel_data++ = pixel >> 16;
605 *pixel_data++ = pixel >> 8;
606 *pixel_data++ = pixel;
607 break;
608 }
609 }
610
611 pixel_data = (ppixel_data += image->bytes_per_line);
612 }
613
614 break;
615
616 case StaticGray:
617 case GrayScale:
618 for (y = 0, offset = 0; y < height; y++) {
619 for (x = 0; x < width; x++, offset++) {
620 r = *(red_table + *(red + offset));
621 g = *(green_table + *(green + offset));
622 b = *(blue_table + *(blue + offset));
623
624 g = ((r * 30) + (g * 59) + (b * 11)) / 100;
625 *pixel_data++ = colors[g].pixel;
626 }
627
628 pixel_data = (ppixel_data += image->bytes_per_line);
629 }
630
631 break;
632
633 default:
634 fprintf(stderr,
635 "BImage::renderXImage: unsupported visual\n");
636 delete [] d;
637 XDestroyImage(image);
638 return (XImage *) 0;
639 }
640 }
641
642 image->data = (char *) d;
643 return image;
644 }
645
646
renderPixmap(void)647 Pixmap BImage::renderPixmap(void) {
648 Pixmap pixmap =
649 XCreatePixmap(control->getBaseDisplay()->getXDisplay(),
650 control->getDrawable(), width, height,
651 /*24*/control->getDepth());
652
653
654 if (pixmap == None) {
655 fprintf(stderr,
656 "BImage::renderPixmap: error creating pixmap\n");
657 return None;
658 }
659 #ifdef DEBUG
660 fprintf(stderr,"Pixmap drawable: %X\n",control->getDrawable());
661 fprintf(stderr,"width: %d, height: %d\n",width,height);
662 fprintf(stderr,"depth: %d\n",control->getDepth());
663 #endif
664 XImage *image = renderXImage();
665
666 if (! image) {
667 XFreePixmap(control->getBaseDisplay()->getXDisplay(), pixmap);
668 return None;
669 } else if (! image->data) {
670 XDestroyImage(image);
671 XFreePixmap(control->getBaseDisplay()->getXDisplay(), pixmap);
672 return None;
673 }
674 #if DEBUG>=2
675 fprintf(stderr,"Attempting XPutImage...\n");
676 fprintf(stderr,"Display: %X\n",control->getBaseDisplay()->getXDisplay());
677 fprintf(stderr,"pixmap: %X\n",pixmap);
678 fprintf(stderr,"GC: %X\n",DefaultGC(control->getBaseDisplay()->getXDisplay(), control->getScreenInfo()->getScreenNumber()));
679 fprintf(stderr,"image: %X\n",image);
680 fprintf(stderr,"width: %d\n",width);
681 fprintf(stderr,"height: %d\n",height);
682 // return pixmap;
683 #endif
684 XPutImage(control->getBaseDisplay()->getXDisplay(), pixmap,
685 DefaultGC(control->getBaseDisplay()->getXDisplay(),
686 control->getScreenInfo()->getScreenNumber()),
687 image, 0, 0, 0, 0, width, height);
688
689 if (image->data) {
690 delete [] image->data;
691 image->data = NULL;
692 }
693
694 XDestroyImage(image);
695
696 return pixmap;
697 }
698
699
bevel1(void)700 void BImage::bevel1(void) {
701 if (width > 2 && height > 2) {
702 unsigned char *pr = red, *pg = green, *pb = blue;
703
704 register unsigned char r, g, b, rr ,gg ,bb;
705 register unsigned int w = width, h = height - 1, wh = w * h;
706
707 while (--w) {
708 r = *pr;
709 rr = r + (r >> 1);
710 if (rr < r) rr = ~0;
711 g = *pg;
712 gg = g + (g >> 1);
713 if (gg < g) gg = ~0;
714 b = *pb;
715 bb = b + (b >> 1);
716 if (bb < b) bb = ~0;
717
718 *pr = rr;
719 *pg = gg;
720 *pb = bb;
721
722 r = *(pr + wh);
723 rr = (r >> 2) + (r >> 1);
724 if (rr > r) rr = 0;
725 g = *(pg + wh);
726 gg = (g >> 2) + (g >> 1);
727 if (gg > g) gg = 0;
728 b = *(pb + wh);
729 bb = (b >> 2) + (b >> 1);
730 if (bb > b) bb = 0;
731
732 *((pr++) + wh) = rr;
733 *((pg++) + wh) = gg;
734 *((pb++) + wh) = bb;
735 }
736
737 r = *pr;
738 rr = r + (r >> 1);
739 if (rr < r) rr = ~0;
740 g = *pg;
741 gg = g + (g >> 1);
742 if (gg < g) gg = ~0;
743 b = *pb;
744 bb = b + (b >> 1);
745 if (bb < b) bb = ~0;
746
747 *pr = rr;
748 *pg = gg;
749 *pb = bb;
750
751 r = *(pr + wh);
752 rr = (r >> 2) + (r >> 1);
753 if (rr > r) rr = 0;
754 g = *(pg + wh);
755 gg = (g >> 2) + (g >> 1);
756 if (gg > g) gg = 0;
757 b = *(pb + wh);
758 bb = (b >> 2) + (b >> 1);
759 if (bb > b) bb = 0;
760
761 *(pr + wh) = rr;
762 *(pg + wh) = gg;
763 *(pb + wh) = bb;
764
765 pr = red + width;
766 pg = green + width;
767 pb = blue + width;
768
769 while (--h) {
770 r = *pr;
771 rr = r + (r >> 1);
772 if (rr < r) rr = ~0;
773 g = *pg;
774 gg = g + (g >> 1);
775 if (gg < g) gg = ~0;
776 b = *pb;
777 bb = b + (b >> 1);
778 if (bb < b) bb = ~0;
779
780 *pr = rr;
781 *pg = gg;
782 *pb = bb;
783
784 pr += width - 1;
785 pg += width - 1;
786 pb += width - 1;
787
788 r = *pr;
789 rr = (r >> 2) + (r >> 1);
790 if (rr > r) rr = 0;
791 g = *pg;
792 gg = (g >> 2) + (g >> 1);
793 if (gg > g) gg = 0;
794 b = *pb;
795 bb = (b >> 2) + (b >> 1);
796 if (bb > b) bb = 0;
797
798 *(pr++) = rr;
799 *(pg++) = gg;
800 *(pb++) = bb;
801 }
802
803 r = *pr;
804 rr = r + (r >> 1);
805 if (rr < r) rr = ~0;
806 g = *pg;
807 gg = g + (g >> 1);
808 if (gg < g) gg = ~0;
809 b = *pb;
810 bb = b + (b >> 1);
811 if (bb < b) bb = ~0;
812
813 *pr = rr;
814 *pg = gg;
815 *pb = bb;
816
817 pr += width - 1;
818 pg += width - 1;
819 pb += width - 1;
820
821 r = *pr;
822 rr = (r >> 2) + (r >> 1);
823 if (rr > r) rr = 0;
824 g = *pg;
825 gg = (g >> 2) + (g >> 1);
826 if (gg > g) gg = 0;
827 b = *pb;
828 bb = (b >> 2) + (b >> 1);
829 if (bb > b) bb = 0;
830
831 *pr = rr;
832 *pg = gg;
833 *pb = bb;
834 }
835 }
836
837
bevel2(void)838 void BImage::bevel2(void) {
839 if (width > 4 && height > 4) {
840 unsigned char r, g, b, rr ,gg ,bb, *pr = red + width + 1,
841 *pg = green + width + 1, *pb = blue + width + 1;
842 unsigned int w = width - 2, h = height - 1, wh = width * (height - 3);
843
844 while (--w) {
845 r = *pr;
846 rr = r + (r >> 1);
847 if (rr < r) rr = ~0;
848 g = *pg;
849 gg = g + (g >> 1);
850 if (gg < g) gg = ~0;
851 b = *pb;
852 bb = b + (b >> 1);
853 if (bb < b) bb = ~0;
854
855 *pr = rr;
856 *pg = gg;
857 *pb = bb;
858
859 r = *(pr + wh);
860 rr = (r >> 2) + (r >> 1);
861 if (rr > r) rr = 0;
862 g = *(pg + wh);
863 gg = (g >> 2) + (g >> 1);
864 if (gg > g) gg = 0;
865 b = *(pb + wh);
866 bb = (b >> 2) + (b >> 1);
867 if (bb > b) bb = 0;
868
869 *((pr++) + wh) = rr;
870 *((pg++) + wh) = gg;
871 *((pb++) + wh) = bb;
872 }
873
874 pr = red + width;
875 pg = green + width;
876 pb = blue + width;
877
878 while (--h) {
879 r = *pr;
880 rr = r + (r >> 1);
881 if (rr < r) rr = ~0;
882 g = *pg;
883 gg = g + (g >> 1);
884 if (gg < g) gg = ~0;
885 b = *pb;
886 bb = b + (b >> 1);
887 if (bb < b) bb = ~0;
888
889 *(++pr) = rr;
890 *(++pg) = gg;
891 *(++pb) = bb;
892
893 pr += width - 3;
894 pg += width - 3;
895 pb += width - 3;
896
897 r = *pr;
898 rr = (r >> 2) + (r >> 1);
899 if (rr > r) rr = 0;
900 g = *pg;
901 gg = (g >> 2) + (g >> 1);
902 if (gg > g) gg = 0;
903 b = *pb;
904 bb = (b >> 2) + (b >> 1);
905 if (bb > b) bb = 0;
906
907 *(pr++) = rr;
908 *(pg++) = gg;
909 *(pb++) = bb;
910
911 pr++; pg++; pb++;
912 }
913 }
914 }
915
916
invert(void)917 void BImage::invert(void) {
918 register unsigned int i, j, wh = (width * height) - 1;
919 unsigned char tmp;
920
921 for (i = 0, j = wh; j > i; j--, i++) {
922 tmp = *(red + j);
923 *(red + j) = *(red + i);
924 *(red + i) = tmp;
925
926 tmp = *(green + j);
927 *(green + j) = *(green + i);
928 *(green + i) = tmp;
929
930 tmp = *(blue + j);
931 *(blue + j) = *(blue + i);
932 *(blue + i) = tmp;
933 }
934 }
935
936
dgradient(void)937 void BImage::dgradient(void) {
938 // diagonal gradient code was written by Mike Cole <mike@mydot.com>
939 // modified for interlacing by Brad Hughes
940
941 float drx, dgx, dbx, dry, dgy, dby, yr = 0.0, yg = 0.0, yb = 0.0,
942 xr = (float) from->getRed(),
943 xg = (float) from->getGreen(),
944 xb = (float) from->getBlue();
945 unsigned char *pr = red, *pg = green, *pb = blue;
946 unsigned int w = width * 2, h = height * 2, *xt = xtable, *yt = ytable;
947
948 register unsigned int x, y;
949
950 dry = drx = (float) (to->getRed() - from->getRed());
951 dgy = dgx = (float) (to->getGreen() - from->getGreen());
952 dby = dbx = (float) (to->getBlue() - from->getBlue());
953
954 // Create X table
955 drx /= w;
956 dgx /= w;
957 dbx /= w;
958
959 for (x = 0; x < width; x++) {
960 *(xt++) = (unsigned char) (xr);
961 *(xt++) = (unsigned char) (xg);
962 *(xt++) = (unsigned char) (xb);
963
964 xr += drx;
965 xg += dgx;
966 xb += dbx;
967 }
968
969 // Create Y table
970 dry /= h;
971 dgy /= h;
972 dby /= h;
973
974 for (y = 0; y < height; y++) {
975 *(yt++) = ((unsigned char) yr);
976 *(yt++) = ((unsigned char) yg);
977 *(yt++) = ((unsigned char) yb);
978
979 yr += dry;
980 yg += dgy;
981 yb += dby;
982 }
983
984 // Combine tables to create gradient
985
986 #ifdef INTERLACE
987 if (! interlaced) {
988 #endif // INTERLACE
989
990 // normal dgradient
991 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
992 for (xt = xtable, x = 0; x < width; x++) {
993 *(pr++) = *(xt++) + *(yt);
994 *(pg++) = *(xt++) + *(yt + 1);
995 *(pb++) = *(xt++) + *(yt + 2);
996 }
997 }
998
999 #ifdef INTERLACE
1000 } else {
1001 // faked interlacing effect
1002 unsigned char channel, channel2;
1003
1004 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1005 for (xt = xtable, x = 0; x < width; x++) {
1006 if (y & 1) {
1007 channel = *(xt++) + *(yt);
1008 channel2 = (channel >> 1) + (channel >> 2);
1009 if (channel2 > channel) channel2 = 0;
1010 *(pr++) = channel2;
1011
1012 channel = *(xt++) + *(yt + 1);
1013 channel2 = (channel >> 1) + (channel >> 2);
1014 if (channel2 > channel) channel2 = 0;
1015 *(pg++) = channel2;
1016
1017 channel = *(xt++) + *(yt + 2);
1018 channel2 = (channel >> 1) + (channel >> 2);
1019 if (channel2 > channel) channel2 = 0;
1020 *(pb++) = channel2;
1021 } else {
1022 channel = *(xt++) + *(yt);
1023 channel2 = channel + (channel >> 3);
1024 if (channel2 < channel) channel2 = ~0;
1025 *(pr++) = channel2;
1026
1027 channel = *(xt++) + *(yt + 1);
1028 channel2 = channel + (channel >> 3);
1029 if (channel2 < channel) channel2 = ~0;
1030 *(pg++) = channel2;
1031
1032 channel = *(xt++) + *(yt + 2);
1033 channel2 = channel + (channel >> 3);
1034 if (channel2 < channel) channel2 = ~0;
1035 *(pb++) = channel2;
1036 }
1037 }
1038 }
1039 }
1040 #endif // INTERLACE
1041
1042 }
1043
1044
hgradient(void)1045 void BImage::hgradient(void) {
1046 float drx, dgx, dbx,
1047 xr = (float) from->getRed(),
1048 xg = (float) from->getGreen(),
1049 xb = (float) from->getBlue();
1050 unsigned char *pr = red, *pg = green, *pb = blue;
1051
1052 register unsigned int x, y;
1053
1054 drx = (float) (to->getRed() - from->getRed());
1055 dgx = (float) (to->getGreen() - from->getGreen());
1056 dbx = (float) (to->getBlue() - from->getBlue());
1057
1058 drx /= width;
1059 dgx /= width;
1060 dbx /= width;
1061
1062 #ifdef INTERLACE
1063 if (interlaced && height > 2) {
1064 // faked interlacing effect
1065 unsigned char channel, channel2;
1066
1067 for (x = 0; x < width; x++, pr++, pg++, pb++) {
1068 channel = (unsigned char) xr;
1069 channel2 = (channel >> 1) + (channel >> 2);
1070 if (channel2 > channel) channel2 = 0;
1071 *pr = channel2;
1072
1073 channel = (unsigned char) xg;
1074 channel2 = (channel >> 1) + (channel >> 2);
1075 if (channel2 > channel) channel2 = 0;
1076 *pg = channel2;
1077
1078 channel = (unsigned char) xb;
1079 channel2 = (channel >> 1) + (channel >> 2);
1080 if (channel2 > channel) channel2 = 0;
1081 *pb = channel2;
1082
1083
1084 channel = (unsigned char) xr;
1085 channel2 = channel + (channel >> 3);
1086 if (channel2 < channel) channel2 = ~0;
1087 *(pr + width) = channel2;
1088
1089 channel = (unsigned char) xg;
1090 channel2 = channel + (channel >> 3);
1091 if (channel2 < channel) channel2 = ~0;
1092 *(pg + width) = channel2;
1093
1094 channel = (unsigned char) xb;
1095 channel2 = channel + (channel >> 3);
1096 if (channel2 < channel) channel2 = ~0;
1097 *(pb + width) = channel2;
1098
1099 xr += drx;
1100 xg += dgx;
1101 xb += dbx;
1102 }
1103
1104 pr += width;
1105 pg += width;
1106 pb += width;
1107
1108 int offset;
1109
1110 for (y = 2; y < height; y++, pr += width, pg += width, pb += width) {
1111 if (y & 1) offset = width; else offset = 0;
1112
1113 memcpy(pr, (red + offset), width);
1114 memcpy(pg, (green + offset), width);
1115 memcpy(pb, (blue + offset), width);
1116 }
1117 } else {
1118 #endif // INTERLACE
1119
1120 // normal hgradient
1121 for (x = 0; x < width; x++) {
1122 *(pr++) = (unsigned char) (xr);
1123 *(pg++) = (unsigned char) (xg);
1124 *(pb++) = (unsigned char) (xb);
1125
1126 xr += drx;
1127 xg += dgx;
1128 xb += dbx;
1129 }
1130
1131 for (y = 1; y < height; y++, pr += width, pg += width, pb += width) {
1132 memcpy(pr, red, width);
1133 memcpy(pg, green, width);
1134 memcpy(pb, blue, width);
1135 }
1136
1137 #ifdef INTERLACE
1138 }
1139 #endif // INTERLACE
1140
1141 }
1142
1143
vgradient(void)1144 void BImage::vgradient(void) {
1145 float dry, dgy, dby,
1146 yr = (float) from->getRed(),
1147 yg = (float) from->getGreen(),
1148 yb = (float) from->getBlue();
1149 unsigned char *pr = red, *pg = green, *pb = blue;
1150
1151 register unsigned int y;
1152
1153 dry = (float) (to->getRed() - from->getRed());
1154 dgy = (float) (to->getGreen() - from->getGreen());
1155 dby = (float) (to->getBlue() - from->getBlue());
1156
1157 dry /= height;
1158 dgy /= height;
1159 dby /= height;
1160
1161 #ifdef INTERLACE
1162 if (interlaced) {
1163 // faked interlacing effect
1164 unsigned char channel, channel2;
1165
1166 for (y = 0; y < height; y++, pr += width, pg += width, pb += width) {
1167 if (y & 1) {
1168 channel = (unsigned char) yr;
1169 channel2 = (channel >> 1) + (channel >> 2);
1170 if (channel2 > channel) channel2 = 0;
1171 memset(pr, channel2, width);
1172
1173 channel = (unsigned char) yg;
1174 channel2 = (channel >> 1) + (channel >> 2);
1175 if (channel2 > channel) channel2 = 0;
1176 memset(pg, channel2, width);
1177
1178 channel = (unsigned char) yb;
1179 channel2 = (channel >> 1) + (channel >> 2);
1180 if (channel2 > channel) channel2 = 0;
1181 memset(pb, channel2, width);
1182 } else {
1183 channel = (unsigned char) yr;
1184 channel2 = channel + (channel >> 3);
1185 if (channel2 < channel) channel2 = ~0;
1186 memset(pr, channel2, width);
1187
1188 channel = (unsigned char) yg;
1189 channel2 = channel + (channel >> 3);
1190 if (channel2 < channel) channel2 = ~0;
1191 memset(pg, channel2, width);
1192
1193 channel = (unsigned char) yb;
1194 channel2 = channel + (channel >> 3);
1195 if (channel2 < channel) channel2 = ~0;
1196 memset(pb, channel2, width);
1197 }
1198
1199 yr += dry;
1200 yg += dgy;
1201 yb += dby;
1202 }
1203 } else {
1204 #endif // INTERLACE
1205
1206 // normal vgradient
1207 for (y = 0; y < height; y++, pr += width, pg += width, pb += width) {
1208 memset(pr, (unsigned char) yr, width);
1209 memset(pg, (unsigned char) yg, width);
1210 memset(pb, (unsigned char) yb, width);
1211
1212 yr += dry;
1213 yg += dgy;
1214 yb += dby;
1215 }
1216
1217 #ifdef INTERLACE
1218 }
1219 #endif // INTERLACE
1220
1221 }
1222
1223
pgradient(void)1224 void BImage::pgradient(void) {
1225 // pyramid gradient - based on original dgradient, written by
1226 // Mosfet (mosfet@kde.org)
1227 // adapted from kde sources for Blackbox by Brad Hughes
1228
1229 float yr, yg, yb, drx, dgx, dbx, dry, dgy, dby,
1230 xr, xg, xb;
1231 int rsign, gsign, bsign;
1232 unsigned char *pr = red, *pg = green, *pb = blue;
1233 unsigned int tr = to->getRed(), tg = to->getGreen(), tb = to->getBlue(),
1234 *xt = xtable, *yt = ytable;
1235
1236 register unsigned int x, y;
1237
1238 dry = drx = (float) (to->getRed() - from->getRed());
1239 dgy = dgx = (float) (to->getGreen() - from->getGreen());
1240 dby = dbx = (float) (to->getBlue() - from->getBlue());
1241
1242 rsign = (drx < 0) ? -1 : 1;
1243 gsign = (dgx < 0) ? -1 : 1;
1244 bsign = (dbx < 0) ? -1 : 1;
1245
1246 xr = yr = (drx / 2);
1247 xg = yg = (dgx / 2);
1248 xb = yb = (dbx / 2);
1249
1250 // Create X table
1251 drx /= width;
1252 dgx /= width;
1253 dbx /= width;
1254
1255 for (x = 0; x < width; x++) {
1256 *(xt++) = (unsigned char) ((xr < 0) ? -xr : xr);
1257 *(xt++) = (unsigned char) ((xg < 0) ? -xg : xg);
1258 *(xt++) = (unsigned char) ((xb < 0) ? -xb : xb);
1259
1260 xr -= drx;
1261 xg -= dgx;
1262 xb -= dbx;
1263 }
1264
1265 // Create Y table
1266 dry /= height;
1267 dgy /= height;
1268 dby /= height;
1269
1270 for (y = 0; y < height; y++) {
1271 *(yt++) = ((unsigned char) ((yr < 0) ? -yr : yr));
1272 *(yt++) = ((unsigned char) ((yg < 0) ? -yg : yg));
1273 *(yt++) = ((unsigned char) ((yb < 0) ? -yb : yb));
1274
1275 yr -= dry;
1276 yg -= dgy;
1277 yb -= dby;
1278 }
1279
1280 // Combine tables to create gradient
1281
1282 #ifdef INTERLACE
1283 if (! interlaced) {
1284 #endif // INTERLACE
1285
1286 // normal pgradient
1287 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1288 for (xt = xtable, x = 0; x < width; x++) {
1289 *(pr++) = (unsigned char) (tr - (rsign * (*(xt++) + *(yt))));
1290 *(pg++) = (unsigned char) (tg - (gsign * (*(xt++) + *(yt + 1))));
1291 *(pb++) = (unsigned char) (tb - (bsign * (*(xt++) + *(yt + 2))));
1292 }
1293 }
1294
1295 #ifdef INTERLACE
1296 } else {
1297 // faked interlacing effect
1298 unsigned char channel, channel2;
1299
1300 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1301 for (xt = xtable, x = 0; x < width; x++) {
1302 if (y & 1) {
1303 channel = (unsigned char) (tr - (rsign * (*(xt++) + *(yt))));
1304 channel2 = (channel >> 1) + (channel >> 2);
1305 if (channel2 > channel) channel2 = 0;
1306 *(pr++) = channel2;
1307
1308 channel = (unsigned char) (tg - (gsign * (*(xt++) + *(yt + 1))));
1309 channel2 = (channel >> 1) + (channel >> 2);
1310 if (channel2 > channel) channel2 = 0;
1311 *(pg++) = channel2;
1312
1313 channel = (unsigned char) (tb - (bsign * (*(xt++) + *(yt + 2))));
1314 channel2 = (channel >> 1) + (channel >> 2);
1315 if (channel2 > channel) channel2 = 0;
1316 *(pb++) = channel2;
1317 } else {
1318 channel = (unsigned char) (tr - (rsign * (*(xt++) + *(yt))));
1319 channel2 = channel + (channel >> 3);
1320 if (channel2 < channel) channel2 = ~0;
1321 *(pr++) = channel2;
1322
1323 channel = (unsigned char) (tg - (gsign * (*(xt++) + *(yt + 1))));
1324 channel2 = channel + (channel >> 3);
1325 if (channel2 < channel) channel2 = ~0;
1326 *(pg++) = channel2;
1327
1328 channel = (unsigned char) (tb - (bsign * (*(xt++) + *(yt + 2))));
1329 channel2 = channel + (channel >> 3);
1330 if (channel2 < channel) channel2 = ~0;
1331 *(pb++) = channel2;
1332 }
1333 }
1334 }
1335 }
1336 #endif // INTERLACE
1337
1338 }
1339
1340
rgradient(void)1341 void BImage::rgradient(void) {
1342 // rectangle gradient - based on original dgradient, written by
1343 // Mosfet (mosfet@kde.org)
1344 // adapted from kde sources for Blackbox by Brad Hughes
1345
1346 float drx, dgx, dbx, dry, dgy, dby, xr, xg, xb, yr, yg, yb;
1347 int rsign, gsign, bsign;
1348 unsigned char *pr = red, *pg = green, *pb = blue;
1349 unsigned int tr = to->getRed(), tg = to->getGreen(), tb = to->getBlue(),
1350 *xt = xtable, *yt = ytable;
1351
1352 register unsigned int x, y;
1353
1354 dry = drx = (float) (to->getRed() - from->getRed());
1355 dgy = dgx = (float) (to->getGreen() - from->getGreen());
1356 dby = dbx = (float) (to->getBlue() - from->getBlue());
1357
1358 rsign = (drx < 0) ? -2 : 2;
1359 gsign = (dgx < 0) ? -2 : 2;
1360 bsign = (dbx < 0) ? -2 : 2;
1361
1362 xr = yr = (drx / 2);
1363 xg = yg = (dgx / 2);
1364 xb = yb = (dbx / 2);
1365
1366 // Create X table
1367 drx /= width;
1368 dgx /= width;
1369 dbx /= width;
1370
1371 for (x = 0; x < width; x++) {
1372 *(xt++) = (unsigned char) ((xr < 0) ? -xr : xr);
1373 *(xt++) = (unsigned char) ((xg < 0) ? -xg : xg);
1374 *(xt++) = (unsigned char) ((xb < 0) ? -xb : xb);
1375
1376 xr -= drx;
1377 xg -= dgx;
1378 xb -= dbx;
1379 }
1380
1381 // Create Y table
1382 dry /= height;
1383 dgy /= height;
1384 dby /= height;
1385
1386 for (y = 0; y < height; y++) {
1387 *(yt++) = ((unsigned char) ((yr < 0) ? -yr : yr));
1388 *(yt++) = ((unsigned char) ((yg < 0) ? -yg : yg));
1389 *(yt++) = ((unsigned char) ((yb < 0) ? -yb : yb));
1390
1391 yr -= dry;
1392 yg -= dgy;
1393 yb -= dby;
1394 }
1395
1396 // Combine tables to create gradient
1397
1398 #ifdef INTERLACE
1399 if (! interlaced) {
1400 #endif // INTERLACE
1401
1402 // normal rgradient
1403 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1404 for (xt = xtable, x = 0; x < width; x++) {
1405 *(pr++) = (unsigned char) (tr - (rsign * max(*(xt++), *(yt))));
1406 *(pg++) = (unsigned char) (tg - (gsign * max(*(xt++), *(yt + 1))));
1407 *(pb++) = (unsigned char) (tb - (bsign * max(*(xt++), *(yt + 2))));
1408 }
1409 }
1410
1411 #ifdef INTERLACE
1412 } else {
1413 // faked interlacing effect
1414 unsigned char channel, channel2;
1415
1416 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1417 for (xt = xtable, x = 0; x < width; x++) {
1418 if (y & 1) {
1419 channel = (unsigned char) (tr - (rsign * max(*(xt++), *(yt))));
1420 channel2 = (channel >> 1) + (channel >> 2);
1421 if (channel2 > channel) channel2 = 0;
1422 *(pr++) = channel2;
1423
1424 channel = (unsigned char) (tg - (gsign * max(*(xt++), *(yt + 1))));
1425 channel2 = (channel >> 1) + (channel >> 2);
1426 if (channel2 > channel) channel2 = 0;
1427 *(pg++) = channel2;
1428
1429 channel = (unsigned char) (tb - (bsign * max(*(xt++), *(yt + 2))));
1430 channel2 = (channel >> 1) + (channel >> 2);
1431 if (channel2 > channel) channel2 = 0;
1432 *(pb++) = channel2;
1433 } else {
1434 channel = (unsigned char) (tr - (rsign * max(*(xt++), *(yt))));
1435 channel2 = channel + (channel >> 3);
1436 if (channel2 < channel) channel2 = ~0;
1437 *(pr++) = channel2;
1438
1439 channel = (unsigned char) (tg - (gsign * max(*(xt++), *(yt + 1))));
1440 channel2 = channel + (channel >> 3);
1441 if (channel2 < channel) channel2 = ~0;
1442 *(pg++) = channel2;
1443
1444 channel = (unsigned char) (tb - (bsign * max(*(xt++), *(yt + 2))));
1445 channel2 = channel + (channel >> 3);
1446 if (channel2 < channel) channel2 = ~0;
1447 *(pb++) = channel2;
1448 }
1449 }
1450 }
1451 }
1452 #endif // INTERLACE
1453
1454 }
1455
1456
egradient(void)1457 void BImage::egradient(void) {
1458 // elliptic gradient - based on original dgradient, written by
1459 // Mosfet (mosfet@kde.org)
1460 // adapted from kde sources for Blackbox by Brad Hughes
1461
1462 float drx, dgx, dbx, dry, dgy, dby, yr, yg, yb, xr, xg, xb;
1463 int rsign, gsign, bsign;
1464 unsigned char *pr = red, *pg = green, *pb = blue;
1465 unsigned int *xt = xtable, *yt = ytable,
1466 tr = (unsigned long) to->getRed(),
1467 tg = (unsigned long) to->getGreen(),
1468 tb = (unsigned long) to->getBlue();
1469
1470 register unsigned int x, y;
1471
1472 dry = drx = (float) (to->getRed() - from->getRed());
1473 dgy = dgx = (float) (to->getGreen() - from->getGreen());
1474 dby = dbx = (float) (to->getBlue() - from->getBlue());
1475
1476 rsign = (drx < 0) ? -1 : 1;
1477 gsign = (dgx < 0) ? -1 : 1;
1478 bsign = (dbx < 0) ? -1 : 1;
1479
1480 xr = yr = (drx / 2);
1481 xg = yg = (dgx / 2);
1482 xb = yb = (dbx / 2);
1483
1484 // Create X table
1485 drx /= width;
1486 dgx /= width;
1487 dbx /= width;
1488
1489 for (x = 0; x < width; x++) {
1490 *(xt++) = (unsigned long) (xr * xr);
1491 *(xt++) = (unsigned long) (xg * xg);
1492 *(xt++) = (unsigned long) (xb * xb);
1493
1494 xr -= drx;
1495 xg -= dgx;
1496 xb -= dbx;
1497 }
1498
1499 // Create Y table
1500 dry /= height;
1501 dgy /= height;
1502 dby /= height;
1503
1504 for (y = 0; y < height; y++) {
1505 *(yt++) = (unsigned long) (yr * yr);
1506 *(yt++) = (unsigned long) (yg * yg);
1507 *(yt++) = (unsigned long) (yb * yb);
1508
1509 yr -= dry;
1510 yg -= dgy;
1511 yb -= dby;
1512 }
1513
1514 // Combine tables to create gradient
1515
1516 #ifdef INTERLACE
1517 if (! interlaced) {
1518 #endif // INTERLACE
1519
1520 // normal egradient
1521 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1522 for (xt = xtable, x = 0; x < width; x++) {
1523 *(pr++) = (unsigned char)
1524 (tr - (rsign * control->getSqrt(*(xt++) + *(yt))));
1525 *(pg++) = (unsigned char)
1526 (tg - (gsign * control->getSqrt(*(xt++) + *(yt + 1))));
1527 *(pb++) = (unsigned char)
1528 (tb - (bsign * control->getSqrt(*(xt++) + *(yt + 2))));
1529 }
1530 }
1531
1532 #ifdef INTERLACE
1533 } else {
1534 // faked interlacing effect
1535 unsigned char channel, channel2;
1536
1537 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1538 for (xt = xtable, x = 0; x < width; x++) {
1539 if (y & 1) {
1540 channel = (unsigned char)
1541 (tr - (rsign * control->getSqrt(*(xt++) + *(yt))));
1542 channel2 = (channel >> 1) + (channel >> 2);
1543 if (channel2 > channel) channel2 = 0;
1544 *(pr++) = channel2;
1545
1546 channel = (unsigned char)
1547 (tg - (gsign * control->getSqrt(*(xt++) + *(yt + 1))));
1548 channel2 = (channel >> 1) + (channel >> 2);
1549 if (channel2 > channel) channel2 = 0;
1550 *(pg++) = channel2;
1551
1552 channel = (unsigned char)
1553 (tb - (bsign * control->getSqrt(*(xt++) + *(yt + 2))));
1554 channel2 = (channel >> 1) + (channel >> 2);
1555 if (channel2 > channel) channel2 = 0;
1556 *(pb++) = channel2;
1557 } else {
1558 channel = (unsigned char)
1559 (tr - (rsign * control->getSqrt(*(xt++) + *(yt))));
1560 channel2 = channel + (channel >> 3);
1561 if (channel2 < channel) channel2 = ~0;
1562 *(pr++) = channel2;
1563
1564 channel = (unsigned char)
1565 (tg - (gsign * control->getSqrt(*(xt++) + *(yt + 1))));
1566 channel2 = channel + (channel >> 3);
1567 if (channel2 < channel) channel2 = ~0;
1568 *(pg++) = channel2;
1569
1570 channel = (unsigned char)
1571 (tb - (bsign * control->getSqrt(*(xt++) + *(yt + 2))));
1572 channel2 = channel + (channel >> 3);
1573 if (channel2 < channel) channel2 = ~0;
1574 *(pb++) = channel2;
1575 }
1576 }
1577 }
1578 }
1579 #endif // INTERLACE
1580
1581 }
1582
1583
pcgradient(void)1584 void BImage::pcgradient(void) {
1585 // pipe cross gradient - based on original dgradient, written by
1586 // Mosfet (mosfet@kde.org)
1587 // adapted from kde sources for Blackbox by Brad Hughes
1588
1589 float drx, dgx, dbx, dry, dgy, dby, xr, xg, xb, yr, yg, yb;
1590 int rsign, gsign, bsign;
1591 unsigned char *pr = red, *pg = green, *pb = blue;
1592 unsigned int *xt = xtable, *yt = ytable,
1593 tr = to->getRed(),
1594 tg = to->getGreen(),
1595 tb = to->getBlue();
1596
1597 register unsigned int x, y;
1598
1599 dry = drx = (float) (to->getRed() - from->getRed());
1600 dgy = dgx = (float) (to->getGreen() - from->getGreen());
1601 dby = dbx = (float) (to->getBlue() - from->getBlue());
1602
1603 rsign = (drx < 0) ? -2 : 2;
1604 gsign = (dgx < 0) ? -2 : 2;
1605 bsign = (dbx < 0) ? -2 : 2;
1606
1607 xr = yr = (drx / 2);
1608 xg = yg = (dgx / 2);
1609 xb = yb = (dbx / 2);
1610
1611 // Create X table
1612 drx /= width;
1613 dgx /= width;
1614 dbx /= width;
1615
1616 for (x = 0; x < width; x++) {
1617 *(xt++) = (unsigned char) ((xr < 0) ? -xr : xr);
1618 *(xt++) = (unsigned char) ((xg < 0) ? -xg : xg);
1619 *(xt++) = (unsigned char) ((xb < 0) ? -xb : xb);
1620
1621 xr -= drx;
1622 xg -= dgx;
1623 xb -= dbx;
1624 }
1625
1626 // Create Y table
1627 dry /= height;
1628 dgy /= height;
1629 dby /= height;
1630
1631 for (y = 0; y < height; y++) {
1632 *(yt++) = ((unsigned char) ((yr < 0) ? -yr : yr));
1633 *(yt++) = ((unsigned char) ((yg < 0) ? -yg : yg));
1634 *(yt++) = ((unsigned char) ((yb < 0) ? -yb : yb));
1635
1636 yr -= dry;
1637 yg -= dgy;
1638 yb -= dby;
1639 }
1640
1641 // Combine tables to create gradient
1642
1643 #ifdef INTERLACE
1644 if (! interlaced) {
1645 #endif // INTERLACE
1646
1647 // normal pcgradient
1648 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1649 for (xt = xtable, x = 0; x < width; x++) {
1650 *(pr++) = (unsigned char) (tr - (rsign * min(*(xt++), *(yt))));
1651 *(pg++) = (unsigned char) (tg - (gsign * min(*(xt++), *(yt + 1))));
1652 *(pb++) = (unsigned char) (tb - (bsign * min(*(xt++), *(yt + 2))));
1653 }
1654 }
1655
1656 #ifdef INTERLACE
1657 } else {
1658 // faked interlacing effect
1659 unsigned char channel, channel2;
1660
1661 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1662 for (xt = xtable, x = 0; x < width; x++) {
1663 if (y & 1) {
1664 channel = (unsigned char) (tr - (rsign * min(*(xt++), *(yt))));
1665 channel2 = (channel >> 1) + (channel >> 2);
1666 if (channel2 > channel) channel2 = 0;
1667 *(pr++) = channel2;
1668
1669 channel = (unsigned char) (tg - (bsign * min(*(xt++), *(yt + 1))));
1670 channel2 = (channel >> 1) + (channel >> 2);
1671 if (channel2 > channel) channel2 = 0;
1672 *(pg++) = channel2;
1673
1674 channel = (unsigned char) (tb - (gsign * min(*(xt++), *(yt + 2))));
1675 channel2 = (channel >> 1) + (channel >> 2);
1676 if (channel2 > channel) channel2 = 0;
1677 *(pb++) = channel2;
1678 } else {
1679 channel = (unsigned char) (tr - (rsign * min(*(xt++), *(yt))));
1680 channel2 = channel + (channel >> 3);
1681 if (channel2 < channel) channel2 = ~0;
1682 *(pr++) = channel2;
1683
1684 channel = (unsigned char) (tg - (gsign * min(*(xt++), *(yt + 1))));
1685 channel2 = channel + (channel >> 3);
1686 if (channel2 < channel) channel2 = ~0;
1687 *(pg++) = channel2;
1688
1689 channel = (unsigned char) (tb - (bsign * min(*(xt++), *(yt + 2))));
1690 channel2 = channel + (channel >> 3);
1691 if (channel2 < channel) channel2 = ~0;
1692 *(pb++) = channel2;
1693 }
1694 }
1695 }
1696 }
1697 #endif // INTERLACE
1698
1699 }
1700
1701
cdgradient(void)1702 void BImage::cdgradient(void) {
1703 // cross diagonal gradient - based on original dgradient, written by
1704 // Mosfet (mosfet@kde.org)
1705 // adapted from kde sources for Blackbox by Brad Hughes
1706
1707 float drx, dgx, dbx, dry, dgy, dby, yr = 0.0, yg = 0.0, yb = 0.0,
1708 xr = (float) from->getRed(),
1709 xg = (float) from->getGreen(),
1710 xb = (float) from->getBlue();
1711 unsigned char *pr = red, *pg = green, *pb = blue;
1712 unsigned int w = width * 2, h = height * 2, *xt, *yt;
1713
1714 register unsigned int x, y;
1715
1716 dry = drx = (float) (to->getRed() - from->getRed());
1717 dgy = dgx = (float) (to->getGreen() - from->getGreen());
1718 dby = dbx = (float) (to->getBlue() - from->getBlue());
1719
1720 // Create X table
1721 drx /= w;
1722 dgx /= w;
1723 dbx /= w;
1724
1725 for (xt = (xtable + (width * 3) - 1), x = 0; x < width; x++) {
1726 *(xt--) = (unsigned char) xb;
1727 *(xt--) = (unsigned char) xg;
1728 *(xt--) = (unsigned char) xr;
1729
1730 xr += drx;
1731 xg += dgx;
1732 xb += dbx;
1733 }
1734
1735 // Create Y table
1736 dry /= h;
1737 dgy /= h;
1738 dby /= h;
1739
1740 for (yt = ytable, y = 0; y < height; y++) {
1741 *(yt++) = (unsigned char) yr;
1742 *(yt++) = (unsigned char) yg;
1743 *(yt++) = (unsigned char) yb;
1744
1745 yr += dry;
1746 yg += dgy;
1747 yb += dby;
1748 }
1749
1750 // Combine tables to create gradient
1751
1752 #ifdef INTERLACE
1753 if (! interlaced) {
1754 #endif // INTERLACE
1755
1756 // normal cdgradient
1757 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1758 for (xt = xtable, x = 0; x < width; x++) {
1759 *(pr++) = *(xt++) + *(yt);
1760 *(pg++) = *(xt++) + *(yt + 1);
1761 *(pb++) = *(xt++) + *(yt + 2);
1762 }
1763 }
1764
1765 #ifdef INTERLACE
1766 } else {
1767 // faked interlacing effect
1768 unsigned char channel, channel2;
1769
1770 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1771 for (xt = xtable, x = 0; x < width; x++) {
1772 if (y & 1) {
1773 channel = *(xt++) + *(yt);
1774 channel2 = (channel >> 1) + (channel >> 2);
1775 if (channel2 > channel) channel2 = 0;
1776 *(pr++) = channel2;
1777
1778 channel = *(xt++) + *(yt + 1);
1779 channel2 = (channel >> 1) + (channel >> 2);
1780 if (channel2 > channel) channel2 = 0;
1781 *(pg++) = channel2;
1782
1783 channel = *(xt++) + *(yt + 2);
1784 channel2 = (channel >> 1) + (channel >> 2);
1785 if (channel2 > channel) channel2 = 0;
1786 *(pb++) = channel2;
1787 } else {
1788 channel = *(xt++) + *(yt);
1789 channel2 = channel + (channel >> 3);
1790 if (channel2 < channel) channel2 = ~0;
1791 *(pr++) = channel2;
1792
1793 channel = *(xt++) + *(yt + 1);
1794 channel2 = channel + (channel >> 3);
1795 if (channel2 < channel) channel2 = ~0;
1796 *(pg++) = channel2;
1797
1798 channel = *(xt++) + *(yt + 2);
1799 channel2 = channel + (channel >> 3);
1800 if (channel2 < channel) channel2 = ~0;
1801 *(pb++) = channel2;
1802 }
1803 }
1804 }
1805 }
1806 #endif // INTERLACE
1807
1808 }
1809
1810
BImageControl(BaseDisplay * dpy,ScreenInfo * scrn,Bool _dither,int _cpc,unsigned long cache_timeout,unsigned long cmax)1811 BImageControl::BImageControl(BaseDisplay *dpy, ScreenInfo *scrn, Bool _dither,
1812 int _cpc, unsigned long cache_timeout,
1813 unsigned long cmax)
1814 {
1815 basedisplay = dpy;
1816 screeninfo = scrn;
1817 setDither(_dither);
1818 setColorsPerChannel(_cpc);
1819
1820 cache_max = cmax;
1821 #ifdef TIMEDCACHE
1822 if (cache_timeout) {
1823 timer = new BTimer(basedisplay, this);
1824 timer->setTimeout(cache_timeout);
1825 timer->start();
1826 } else
1827 timer = (BTimer *) 0;
1828 #endif // TIMEDCACHE
1829
1830 colors = (XColor *) 0;
1831 ncolors = 0;
1832
1833 grad_xbuffer = grad_ybuffer = (unsigned int *) 0;
1834 grad_buffer_width = grad_buffer_height = 0;
1835
1836 sqrt_table = (unsigned long *) 0;
1837
1838 screen_depth = screeninfo->getDepth();
1839 window = screeninfo->getRootWindow();
1840 screen_number = screeninfo->getScreenNumber();
1841
1842 int count;
1843 XPixmapFormatValues *pmv = XListPixmapFormats(basedisplay->getXDisplay(),
1844 &count);
1845 root_colormap = DefaultColormap(basedisplay->getXDisplay(), screen_number);
1846
1847 if (pmv) {
1848 bits_per_pixel = 0;
1849 for (int i = 0; i < count; i++)
1850 if (pmv[i].depth == screen_depth) {
1851 bits_per_pixel = pmv[i].bits_per_pixel;
1852 break;
1853 }
1854
1855 XFree(pmv);
1856 }
1857
1858 if (bits_per_pixel == 0) bits_per_pixel = screen_depth;
1859 if (bits_per_pixel >= 24) setDither(False);
1860
1861 red_offset = green_offset = blue_offset = 0;
1862
1863 switch (getVisual()->c_class) {
1864 case TrueColor:
1865 {
1866 int i;
1867
1868 // compute color tables
1869 unsigned long red_mask = getVisual()->red_mask,
1870 green_mask = getVisual()->green_mask,
1871 blue_mask = getVisual()->blue_mask;
1872
1873 while (! (red_mask & 1)) { red_offset++; red_mask >>= 1; }
1874 while (! (green_mask & 1)) { green_offset++; green_mask >>= 1; }
1875 while (! (blue_mask & 1)) { blue_offset++; blue_mask >>= 1; }
1876
1877 red_bits = 255 / red_mask;
1878 green_bits = 255 / green_mask;
1879 blue_bits = 255 / blue_mask;
1880
1881 for (i = 0; i < 256; i++) {
1882 red_color_table[i] = i / red_bits;
1883 green_color_table[i] = i / green_bits;
1884 blue_color_table[i] = i / blue_bits;
1885 }
1886 }
1887
1888 break;
1889
1890 case PseudoColor:
1891 case StaticColor:
1892 {
1893 ncolors = colors_per_channel * colors_per_channel * colors_per_channel;
1894
1895 if (ncolors > (1 << screen_depth)) {
1896 colors_per_channel = (1 << screen_depth) / 3;
1897 ncolors = colors_per_channel * colors_per_channel * colors_per_channel;
1898 }
1899
1900 if (colors_per_channel < 2 || ncolors > (1 << screen_depth)) {
1901 fprintf(stderr,
1902 "BImageControl::BImageControl: invalid colormap size %d "
1903 "(%d/%d/%d) - reducing",
1904 ncolors, colors_per_channel, colors_per_channel,
1905 colors_per_channel);
1906
1907 colors_per_channel = (1 << screen_depth) / 3;
1908 }
1909
1910 colors = new XColor[ncolors];
1911 if (! colors) {
1912 fprintf(stderr,
1913 "BImageControl::BImageControl: error allocating "
1914 "colormap\n");
1915 exit(1);
1916 }
1917
1918 int i = 0, ii, p, r, g, b,
1919
1920 #ifdef ORDEREDPSEUDO
1921 bits = 256 / colors_per_channel;
1922 #else // !ORDEREDPSEUDO
1923 bits = 255 / (colors_per_channel - 1);
1924 #endif // ORDEREDPSEUDO
1925
1926 red_bits = green_bits = blue_bits = bits;
1927
1928 for (i = 0; i < 256; i++)
1929 red_color_table[i] = green_color_table[i] = blue_color_table[i] =
1930 i / bits;
1931
1932 for (r = 0, i = 0; r < colors_per_channel; r++)
1933 for (g = 0; g < colors_per_channel; g++)
1934 for (b = 0; b < colors_per_channel; b++, i++) {
1935 colors[i].red = (r * 0xffff) / (colors_per_channel - 1);
1936 colors[i].green = (g * 0xffff) / (colors_per_channel - 1);
1937 colors[i].blue = (b * 0xffff) / (colors_per_channel - 1);;
1938 colors[i].flags = DoRed|DoGreen|DoBlue;
1939 }
1940
1941 basedisplay->grab();
1942
1943 for (i = 0; i < ncolors; i++)
1944 if (! XAllocColor(basedisplay->getXDisplay(), getColormap(),
1945 &colors[i])) {
1946 fprintf(stderr,
1947 "couldn't alloc color %i %i %i\n",
1948 colors[i].red, colors[i].green, colors[i].blue);
1949 colors[i].flags = 0;
1950 } else
1951 colors[i].flags = DoRed|DoGreen|DoBlue;
1952
1953 basedisplay->ungrab();
1954
1955 XColor icolors[256];
1956 int incolors = (((1 << screen_depth) > 256) ? 256 : (1 << screen_depth));
1957
1958 for (i = 0; i < incolors; i++)
1959 icolors[i].pixel = i;
1960
1961 XQueryColors(basedisplay->getXDisplay(), getColormap(), icolors,
1962 incolors);
1963 for (i = 0; i < ncolors; i++) {
1964 if (! colors[i].flags) {
1965 unsigned long chk = 0xffffffff, pixel, close = 0;
1966
1967 p = 2;
1968 while (p--) {
1969 for (ii = 0; ii < incolors; ii++) {
1970 r = (colors[i].red - icolors[i].red) >> 8;
1971 g = (colors[i].green - icolors[i].green) >> 8;
1972 b = (colors[i].blue - icolors[i].blue) >> 8;
1973 pixel = (r * r) + (g * g) + (b * b);
1974
1975 if (pixel < chk) {
1976 chk = pixel;
1977 close = ii;
1978 }
1979
1980 colors[i].red = icolors[close].red;
1981 colors[i].green = icolors[close].green;
1982 colors[i].blue = icolors[close].blue;
1983
1984 if (XAllocColor(basedisplay->getXDisplay(), getColormap(),
1985 &colors[i])) {
1986 colors[i].flags = DoRed|DoGreen|DoBlue;
1987 break;
1988 }
1989 }
1990 }
1991 }
1992 }
1993
1994 break;
1995 }
1996
1997 case GrayScale:
1998 case StaticGray:
1999 {
2000
2001 if (getVisual()->c_class == StaticGray) {
2002 ncolors = 1 << screen_depth;
2003 } else {
2004 ncolors = colors_per_channel * colors_per_channel * colors_per_channel;
2005
2006 if (ncolors > (1 << screen_depth)) {
2007 colors_per_channel = (1 << screen_depth) / 3;
2008 ncolors =
2009 colors_per_channel * colors_per_channel * colors_per_channel;
2010 }
2011 }
2012
2013 if (colors_per_channel < 2 || ncolors > (1 << screen_depth)) {
2014 fprintf(stderr,
2015 "BImageControl::BImageControl: invalid colormap size %d "
2016 "(%d/%d/%d) - reducing",
2017 ncolors, colors_per_channel, colors_per_channel,
2018 colors_per_channel);
2019
2020 colors_per_channel = (1 << screen_depth) / 3;
2021 }
2022
2023 colors = new XColor[ncolors];
2024 if (! colors) {
2025 fprintf(stderr,
2026 "BImageControl::BImageControl: error allocating "
2027 "colormap\n");
2028 exit(1);
2029 }
2030
2031 int i = 0, ii, p, bits = 255 / (colors_per_channel - 1);
2032 red_bits = green_bits = blue_bits = bits;
2033
2034 for (i = 0; i < 256; i++)
2035 red_color_table[i] = green_color_table[i] = blue_color_table[i] =
2036 i / bits;
2037
2038 basedisplay->grab();
2039 for (i = 0; i < ncolors; i++) {
2040 colors[i].red = (i * 0xffff) / (colors_per_channel - 1);
2041 colors[i].green = (i * 0xffff) / (colors_per_channel - 1);
2042 colors[i].blue = (i * 0xffff) / (colors_per_channel - 1);;
2043 colors[i].flags = DoRed|DoGreen|DoBlue;
2044
2045 if (! XAllocColor(basedisplay->getXDisplay(), getColormap(),
2046 &colors[i])) {
2047 fprintf(stderr,
2048 "couldn't alloc color %i %i %i\n",
2049 colors[i].red, colors[i].green, colors[i].blue);
2050 colors[i].flags = 0;
2051 } else
2052 colors[i].flags = DoRed|DoGreen|DoBlue;
2053 }
2054
2055 basedisplay->ungrab();
2056
2057 XColor icolors[256];
2058 int incolors = (((1 << screen_depth) > 256) ? 256 :
2059 (1 << screen_depth));
2060
2061 for (i = 0; i < incolors; i++)
2062 icolors[i].pixel = i;
2063
2064 XQueryColors(basedisplay->getXDisplay(), getColormap(), icolors,
2065 incolors);
2066 for (i = 0; i < ncolors; i++) {
2067 if (! colors[i].flags) {
2068 unsigned long chk = 0xffffffff, pixel, close = 0;
2069
2070 p = 2;
2071 while (p--) {
2072 for (ii = 0; ii < incolors; ii++) {
2073 int r = (colors[i].red - icolors[i].red) >> 8;
2074 int g = (colors[i].green - icolors[i].green) >> 8;
2075 int b = (colors[i].blue - icolors[i].blue) >> 8;
2076 pixel = (r * r) + (g * g) + (b * b);
2077
2078 if (pixel < chk) {
2079 chk = pixel;
2080 close = ii;
2081 }
2082
2083 colors[i].red = icolors[close].red;
2084 colors[i].green = icolors[close].green;
2085 colors[i].blue = icolors[close].blue;
2086
2087 if (XAllocColor(basedisplay->getXDisplay(), getColormap(),
2088 &colors[i])) {
2089 colors[i].flags = DoRed|DoGreen|DoBlue;
2090 break;
2091 }
2092 }
2093 }
2094 }
2095 }
2096
2097 break;
2098 }
2099
2100 default:
2101 fprintf(stderr,
2102 "BImageControl::BImageControl: unsupported visual %d\n",
2103 getVisual()->c_class);
2104 exit(1);
2105 }
2106
2107 cache = new LinkedList<Cache>;
2108 }
2109
2110
~BImageControl(void)2111 BImageControl::~BImageControl(void) {
2112 if (sqrt_table) {
2113 delete [] sqrt_table;
2114 }
2115
2116 if (grad_xbuffer) {
2117 delete [] grad_xbuffer;
2118 }
2119
2120 if (grad_ybuffer) {
2121 delete [] grad_ybuffer;
2122 }
2123
2124 if (colors) {
2125 unsigned long *pixels = new unsigned long [ncolors];
2126
2127 int i;
2128 for (i = 0; i < ncolors; i++)
2129 *(pixels + i) = (*(colors + i)).pixel;
2130
2131 XFreeColors(basedisplay->getXDisplay(), getColormap(),
2132 pixels, ncolors, 0);
2133
2134 delete [] colors;
2135 }
2136
2137 if (cache->count()) {
2138 int i, n = cache->count();
2139 fprintf(stderr,
2140 "BImageContol::~BImageControl: pixmap cache - "
2141 "releasing %d pixmaps\n", n);
2142
2143 for (i = 0; i < n; i++) {
2144 Cache *tmp = cache->first();
2145 XFreePixmap(basedisplay->getXDisplay(), tmp->pixmap);
2146 cache->remove(tmp);
2147 delete tmp;
2148 }
2149
2150 #ifdef TIMEDCACHE
2151 if (timer) {
2152 timer->stop();
2153 delete timer;
2154 }
2155 #endif // TIMEDCACHE
2156 }
2157
2158 delete cache;
2159 }
2160
2161
searchCache(unsigned int width,unsigned int height,unsigned long texture,BColor * c1,BColor * c2)2162 Pixmap BImageControl::searchCache(unsigned int width, unsigned int height,
2163 unsigned long texture,
2164 BColor *c1, BColor *c2) {
2165 if (cache->count()) {
2166 LinkedListIterator<Cache> it(cache);
2167
2168 for (; it.current(); it++) {
2169 if ((it.current()->width == width) &&
2170 (it.current()->height == height) &&
2171 (it.current()->texture == texture) &&
2172 (it.current()->pixel1 == c1->getPixel()))
2173 if (texture & BImage_Gradient) {
2174 if (it.current()->pixel2 == c2->getPixel()) {
2175 it.current()->count++;
2176 return it.current()->pixmap;
2177 }
2178 } else {
2179 it.current()->count++;
2180 return it.current()->pixmap;
2181 }
2182 }
2183 }
2184
2185 return None;
2186 }
2187
2188
renderImage(unsigned int width,unsigned int height,BTexture * texture)2189 Pixmap BImageControl::renderImage(unsigned int width, unsigned int height,
2190 BTexture *texture) {
2191 if (texture->getTexture() & BImage_ParentRelative) return ParentRelative;
2192
2193 Pixmap pixmap = searchCache(width, height, texture->getTexture(),
2194 texture->getColor(), texture->getColorTo());
2195 if (pixmap) return pixmap;
2196
2197 BImage image(this, width, height);
2198 pixmap = image.render(texture);
2199
2200 if (pixmap) {
2201 Cache *tmp = new Cache;
2202
2203 tmp->pixmap = pixmap;
2204 tmp->width = width;
2205 tmp->height = height;
2206 tmp->count = 1;
2207 tmp->texture = texture->getTexture();
2208 tmp->pixel1 = texture->getColor()->getPixel();
2209
2210 if (texture->getTexture() & BImage_Gradient)
2211 tmp->pixel2 = texture->getColorTo()->getPixel();
2212 else
2213 tmp->pixel2 = 0l;
2214
2215 cache->insert(tmp);
2216
2217 if ((unsigned) cache->count() > cache_max) {
2218 #ifdef DEBUG
2219 fprintf(stderr,
2220 "BImageControl::renderImage: cache is large, "
2221 "forcing cleanout\n");
2222 #endif // DEBUG
2223
2224 timeout();
2225 }
2226
2227 return pixmap;
2228 }
2229
2230 return None;
2231 }
2232
2233
removeImage(Pixmap pixmap)2234 void BImageControl::removeImage(Pixmap pixmap) {
2235 if (pixmap) {
2236 LinkedListIterator<Cache> it(cache);
2237 for (; it.current(); it++) {
2238 if (it.current()->pixmap == pixmap) {
2239 Cache *tmp = it.current();
2240
2241 if (tmp->count) {
2242 tmp->count--;
2243
2244 #ifdef TIMEDCACHE
2245 if (! timer) timeout();
2246 #else // !TIMEDCACHE
2247 if (! tmp->count) timeout();
2248 #endif // TIMEDCACHE
2249 }
2250
2251 return;
2252 }
2253 }
2254 }
2255 }
2256
2257
getColor(const char * colorname,unsigned char * r,unsigned char * g,unsigned char * b)2258 unsigned long BImageControl::getColor(const char *colorname,
2259 unsigned char *r, unsigned char *g,
2260 unsigned char *b)
2261 {
2262 XColor color;
2263 color.pixel = 0;
2264
2265 if (! XParseColor(basedisplay->getXDisplay(), getColormap(),
2266 colorname, &color)) {
2267 fprintf(stderr, "BImageControl::getColor: color parse error: \"%s\"\n",
2268 colorname);
2269 } else if (! XAllocColor(basedisplay->getXDisplay(), getColormap(),
2270 &color)) {
2271 fprintf(stderr, "BImageControl::getColor: color alloc error: \"%s\"\n",
2272 colorname);
2273 }
2274
2275 if (color.red == 65535) *r = 0xff;
2276 else *r = (unsigned char) (color.red / 0xff);
2277 if (color.green == 65535) *g = 0xff;
2278 else *g = (unsigned char) (color.green / 0xff);
2279 if (color.blue == 65535) *b = 0xff;
2280 else *b = (unsigned char) (color.blue / 0xff);
2281
2282 return color.pixel;
2283 }
2284
2285
getColor(const char * colorname)2286 unsigned long BImageControl::getColor(const char *colorname) {
2287 XColor color;
2288 color.pixel = 0;
2289
2290 if (! XParseColor(basedisplay->getXDisplay(), getColormap(),
2291 colorname, &color)) {
2292 fprintf(stderr, "BImageControl::getColor: color parse error: \"%s\"\n",
2293 colorname);
2294 } else if (! XAllocColor(basedisplay->getXDisplay(), getColormap(),
2295 &color)) {
2296 fprintf(stderr, "BImageControl::getColor: color alloc error: \"%s\"\n",
2297 colorname);
2298 }
2299
2300 return color.pixel;
2301 }
2302
2303
getColorTables(unsigned char ** rmt,unsigned char ** gmt,unsigned char ** bmt,int * roff,int * goff,int * boff,int * rbit,int * gbit,int * bbit)2304 void BImageControl::getColorTables(unsigned char **rmt, unsigned char **gmt,
2305 unsigned char **bmt,
2306 int *roff, int *goff, int *boff,
2307 int *rbit, int *gbit, int *bbit) {
2308 if (rmt) *rmt = red_color_table;
2309 if (gmt) *gmt = green_color_table;
2310 if (bmt) *bmt = blue_color_table;
2311
2312 if (roff) *roff = red_offset;
2313 if (goff) *goff = green_offset;
2314 if (boff) *boff = blue_offset;
2315
2316 if (rbit) *rbit = red_bits;
2317 if (gbit) *gbit = green_bits;
2318 if (bbit) *bbit = blue_bits;
2319 }
2320
2321
getXColorTable(XColor ** c,int * n)2322 void BImageControl::getXColorTable(XColor **c, int *n) {
2323 if (c) *c = colors;
2324 if (n) *n = ncolors;
2325 }
2326
2327
getGradientBuffers(unsigned int w,unsigned int h,unsigned int ** xbuf,unsigned int ** ybuf)2328 void BImageControl::getGradientBuffers(unsigned int w,
2329 unsigned int h,
2330 unsigned int **xbuf,
2331 unsigned int **ybuf)
2332 {
2333 if (w > grad_buffer_width) {
2334 if (grad_xbuffer) {
2335 delete [] grad_xbuffer;
2336 }
2337
2338 grad_buffer_width = w;
2339
2340 grad_xbuffer = new unsigned int[grad_buffer_width * 3];
2341 }
2342
2343 if (h > grad_buffer_height) {
2344 if (grad_ybuffer) {
2345 delete [] grad_ybuffer;
2346 }
2347
2348 grad_buffer_height = h;
2349
2350 grad_ybuffer = new unsigned int[grad_buffer_height * 3];
2351 }
2352
2353 *xbuf = grad_xbuffer;
2354 *ybuf = grad_ybuffer;
2355 }
2356
2357
installRootColormap(void)2358 void BImageControl::installRootColormap(void) {
2359 basedisplay->grab();
2360
2361 Bool install = True;
2362 int i = 0, ncmap = 0;
2363 Colormap *cmaps =
2364 XListInstalledColormaps(basedisplay->getXDisplay(), window, &ncmap);
2365
2366 if (cmaps) {
2367 for (i = 0; i < ncmap; i++)
2368 if (*(cmaps + i) == getColormap())
2369 install = False;
2370
2371 if (install)
2372 XInstallColormap(basedisplay->getXDisplay(), getColormap());
2373
2374 XFree(cmaps);
2375 }
2376
2377 basedisplay->ungrab();
2378 }
2379
2380
setColorsPerChannel(int cpc)2381 void BImageControl::setColorsPerChannel(int cpc) {
2382 if (cpc < 2) cpc = 2;
2383 if (cpc > 6) cpc = 6;
2384
2385 colors_per_channel = cpc;
2386 }
2387
2388
getSqrt(unsigned int x)2389 unsigned long BImageControl::getSqrt(unsigned int x) {
2390 if (! sqrt_table) {
2391 // build sqrt table for use with elliptic gradient
2392
2393 sqrt_table = new unsigned long[(256 * 256 * 2) + 1];
2394 int i = 0;
2395
2396 for (; i < (256 * 256 * 2); i++)
2397 *(sqrt_table + i) = bsqrt(i);
2398 }
2399
2400 return (*(sqrt_table + x));
2401 }
2402
2403
parseTexture(BTexture * texture,const char * t)2404 void BImageControl::parseTexture(BTexture *texture, const char *t) {
2405 if ((! texture) || (! t)) return;
2406
2407 int t_len = strlen(t) + 1, i;
2408 char *ts = new char[t_len];
2409 if (! ts) return;
2410
2411 // convert to lower case
2412 for (i = 0; i < t_len; i++)
2413 *(ts + i) = tolower(*(t + i));
2414
2415 if (strstr(ts, "parentrelative")) {
2416 texture->setTexture(BImage_ParentRelative);
2417 } else {
2418 texture->setTexture(0);
2419
2420 if (strstr(ts, "solid"))
2421 texture->addTexture(BImage_Solid);
2422 else if (strstr(ts, "gradient")) {
2423 texture->addTexture(BImage_Gradient);
2424 if (strstr(ts, "crossdiagonal"))
2425 texture->addTexture(BImage_CrossDiagonal);
2426 else if (strstr(ts, "rectangle"))
2427 texture->addTexture(BImage_Rectangle);
2428 else if (strstr(ts, "pyramid"))
2429 texture->addTexture(BImage_Pyramid);
2430 else if (strstr(ts, "pipecross"))
2431 texture->addTexture(BImage_PipeCross);
2432 else if (strstr(ts, "elliptic"))
2433 texture->addTexture(BImage_Elliptic);
2434 else if (strstr(ts, "diagonal"))
2435 texture->addTexture(BImage_Diagonal);
2436 else if (strstr(ts, "horizontal"))
2437 texture->addTexture(BImage_Horizontal);
2438 else if (strstr(ts, "vertical"))
2439 texture->addTexture(BImage_Vertical);
2440 else
2441 texture->addTexture(BImage_Diagonal);
2442 } else
2443 texture->addTexture(BImage_Solid);
2444
2445 if (strstr(ts, "raised"))
2446 texture->addTexture(BImage_Raised);
2447 else if (strstr(ts, "sunken"))
2448 texture->addTexture(BImage_Sunken);
2449 else if (strstr(ts, "flat"))
2450 texture->addTexture(BImage_Flat);
2451 else
2452 texture->addTexture(BImage_Raised);
2453
2454 if (! (texture->getTexture() & BImage_Flat))
2455 if (strstr(ts, "bevel2"))
2456 texture->addTexture(BImage_Bevel2);
2457 else
2458 texture->addTexture(BImage_Bevel1);
2459
2460 #ifdef INTERLACE
2461 if (strstr(ts, "interlaced"))
2462 texture->addTexture(BImage_Interlaced);
2463 #endif // INTERLACE
2464 }
2465
2466 delete [] ts;
2467 }
2468
2469
parseColor(BColor * color,const char * c)2470 void BImageControl::parseColor(BColor *color, const char *c) {
2471 if (! color) return;
2472
2473 if (color->isAllocated()) {
2474 unsigned long pixel = color->getPixel();
2475
2476 XFreeColors(basedisplay->getXDisplay(), getColormap(), &pixel, 1, 0);
2477
2478 color->setPixel(0l);
2479 color->setRGB(0, 0, 0);
2480 color->setAllocated(False);
2481 }
2482
2483 if (c) {
2484 unsigned char r, g, b;
2485
2486 color->setPixel(getColor(c, &r, &g, &b));
2487 color->setRGB(r, g, b);
2488 color->setAllocated(True);
2489 }
2490 }
2491
2492
timeout(void)2493 void BImageControl::timeout(void) {
2494 LinkedListIterator<Cache> it(cache);
2495 for (; it.current(); it++) {
2496 Cache *tmp = it.current();
2497
2498 if (tmp->count <= 0) {
2499 XFreePixmap(basedisplay->getXDisplay(), tmp->pixmap);
2500 cache->remove(tmp);
2501 delete tmp;
2502 }
2503 }
2504 }
2505