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