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