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