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)
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:
12 // The above copyright notice and this permission notice shall be included in
13 // all copies or substantial portions of the Software.
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.
23 // stupid macros needed to access some functions in version 2 of the GNU C
30 # include "../config.h"
31 #endif // HAVE_CONFIG_H
34 #include "BaseDisplay.h"
37 #ifdef HAVE_SYS_TYPES_H
38 # include <sys/types.h>
39 #endif // HAVE_SYS_TYPES_H
43 typedef uint32_t u_int32_t
;
46 typedef __uint32_t u_int32_t
;
48 typedef unsigned int u_int32_t
;
55 #endif // HAVE_STDLIB_H
59 #endif // HAVE_STRING_H
63 #endif // HAVE_STDIO_H
67 #endif // HAVE_CTYPE_H
73 static unsigned long bsqrt(unsigned long x
) {
77 unsigned long r
= x
>> 1;
88 BImage::BImage(BImageControl
&c
, unsigned int w
, unsigned int h
) : control(c
) {
89 width
= ((signed) w
> 0) ? w
: 1;
90 height
= ((signed) h
> 0) ? h
: 1;
92 red
= new unsigned char[width
* height
];
93 green
= new unsigned char[width
* height
];
94 blue
= new unsigned char[width
* height
];
96 xtable
= ytable
= (unsigned int *) 0;
98 cpc
= control
.getColorsPerChannel();
101 control
.getColorTables(&red_table
, &green_table
, &blue_table
,
102 &red_offset
, &green_offset
, &blue_offset
,
103 &red_bits
, &green_bits
, &blue_bits
);
105 if (control
.getVisual()->c_class
!= TrueColor
)
106 control
.getXColorTable(&colors
, &ncolors
);
110 BImage::~BImage(void) {
111 if (red
) delete [] red
;
112 if (green
) delete [] green
;
113 if (blue
) delete [] blue
;
117 Pixmap
BImage::render(BTexture
*texture
) {
118 if (texture
->getTexture() & BImage_ParentRelative
)
119 return ParentRelative
;
120 else if (texture
->getTexture() & BImage_Solid
)
121 return render_solid(texture
);
122 else if (texture
->getTexture() & BImage_Gradient
)
123 return render_gradient(texture
);
129 Pixmap
BImage::render_solid(BTexture
*texture
) {
130 Pixmap pixmap
= XCreatePixmap(control
.getBaseDisplay().getXDisplay(),
131 control
.getDrawable(), width
,
132 height
, control
.getDepth());
133 if (pixmap
== None
) {
134 fprintf(stderr
, i18n
->getMessage(ImageSet
, ImageErrorCreatingSolidPixmap
,
135 "BImage::render_solid: error creating pixmap\n"));
142 gcv
.foreground
= texture
->getColor()->getPixel();
143 gcv
.fill_style
= FillSolid
;
144 gc
= XCreateGC(control
.getBaseDisplay().getXDisplay(), pixmap
,
145 GCForeground
| GCFillStyle
, &gcv
);
147 gcv
.foreground
= texture
->getHiColor()->getPixel();
148 hgc
= XCreateGC(control
.getBaseDisplay().getXDisplay(), pixmap
,
151 gcv
.foreground
= texture
->getLoColor()->getPixel();
152 lgc
= XCreateGC(control
.getBaseDisplay().getXDisplay(), pixmap
,
155 XFillRectangle(control
.getBaseDisplay().getXDisplay(), pixmap
, gc
, 0, 0,
159 if (texture
->getTexture() & BImage_Interlaced
) {
160 gcv
.foreground
= texture
->getColorTo()->getPixel();
161 GC igc
= XCreateGC(control
.getBaseDisplay().getXDisplay(), pixmap
,
164 register unsigned int i
= 0;
165 for (; i
< height
; i
+= 2)
166 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, igc
,
169 XFreeGC(control
.getBaseDisplay().getXDisplay(), igc
);
174 if (texture
->getTexture() & BImage_Bevel1
) {
175 if (texture
->getTexture() & BImage_Raised
) {
176 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, lgc
,
177 0, height
- 1, width
- 1, height
- 1);
178 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, lgc
,
179 width
- 1, height
- 1, width
- 1, 0);
181 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, hgc
,
183 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, hgc
,
184 0, height
- 1, 0, 0);
185 } else if (texture
->getTexture() & BImage_Sunken
) {
186 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, hgc
,
187 0, height
- 1, width
- 1, height
- 1);
188 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, hgc
,
189 width
- 1, height
- 1, width
- 1, 0);
191 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, lgc
,
193 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, lgc
,
194 0, height
- 1, 0, 0);
196 } else if (texture
->getTexture() & BImage_Bevel2
) {
197 if (texture
->getTexture() & BImage_Raised
) {
198 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, lgc
,
199 1, height
- 3, width
- 3, height
- 3);
200 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, lgc
,
201 width
- 3, height
- 3, width
- 3, 1);
203 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, hgc
,
205 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, hgc
,
206 1, height
- 3, 1, 1);
207 } else if (texture
->getTexture() & BImage_Sunken
) {
208 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, hgc
,
209 1, height
- 3, width
- 3, height
- 3);
210 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, hgc
,
211 width
- 3, height
- 3, width
- 3, 1);
213 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, lgc
,
215 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, lgc
,
216 1, height
- 3, 1, 1);
220 XFreeGC(control
.getBaseDisplay().getXDisplay(), gc
);
221 XFreeGC(control
.getBaseDisplay().getXDisplay(), hgc
);
222 XFreeGC(control
.getBaseDisplay().getXDisplay(), lgc
);
228 Pixmap
BImage::render_gradient(BTexture
*texture
) {
232 interlaced
= texture
->getTexture() & BImage_Interlaced
;
235 if (texture
->getTexture() & BImage_Sunken
) {
236 from
= texture
->getColorTo();
237 to
= texture
->getColor();
239 if (! (texture
->getTexture() & BImage_Invert
)) inverted
= 1;
241 from
= texture
->getColor();
242 to
= texture
->getColorTo();
244 if (texture
->getTexture() & BImage_Invert
) inverted
= 1;
247 control
.getGradientBuffers(width
, height
, &xtable
, &ytable
);
249 if (texture
->getTexture() & BImage_Diagonal
) dgradient();
250 else if (texture
->getTexture() & BImage_Elliptic
) egradient();
251 else if (texture
->getTexture() & BImage_Horizontal
) hgradient();
252 else if (texture
->getTexture() & BImage_Pyramid
) pgradient();
253 else if (texture
->getTexture() & BImage_Rectangle
) rgradient();
254 else if (texture
->getTexture() & BImage_Vertical
) vgradient();
255 else if (texture
->getTexture() & BImage_CrossDiagonal
) cdgradient();
256 else if (texture
->getTexture() & BImage_PipeCross
) pcgradient();
258 if (texture
->getTexture() & BImage_Bevel1
) bevel1();
259 else if (texture
->getTexture() & BImage_Bevel2
) bevel2();
261 if (inverted
) invert();
263 Pixmap pixmap
= renderPixmap();
270 XImage
*BImage::renderXImage(void) {
272 XCreateImage(control
.getBaseDisplay().getXDisplay(),
273 control
.getVisual(), control
.getDepth(), ZPixmap
, 0, 0,
274 width
, height
, 32, 0);
277 fprintf(stderr
, i18n
->getMessage(ImageSet
, ImageErrorCreatingXImage
,
278 "BImage::renderXImage: error creating XImage\n"));
283 image
->data
= (char *) 0;
285 unsigned char *d
= new unsigned char[image
->bytes_per_line
* (height
+ 1)];
286 register unsigned int x
, y
, dithx
, dithy
, r
, g
, b
, o
, er
, eg
, eb
, offset
;
288 unsigned char *pixel_data
= d
, *ppixel_data
= d
;
291 o
= image
->bits_per_pixel
+ ((image
->byte_order
== MSBFirst
) ? 1 : 0);
293 if (control
.doDither() && width
> 1 && height
> 1) {
294 unsigned char dither4
[4][4] = { {0, 4, 1, 5},
300 unsigned char dither8
[8][8] = { { 0, 32, 8, 40, 2, 34, 10, 42 },
301 { 48, 16, 56, 24, 50, 18, 58, 26 },
302 { 12, 44, 4, 36, 14, 46, 6, 38 },
303 { 60, 28, 52, 20, 62, 30, 54, 22 },
304 { 3, 35, 11, 43, 1, 33, 9, 41 },
305 { 51, 19, 59, 27, 49, 17, 57, 25 },
306 { 15, 47, 7, 39, 13, 45, 5, 37 },
307 { 63, 31, 55, 23, 61, 29, 53, 21 } };
308 #endif // ORDEREDPSEUDO
310 switch (control
.getVisual()->c_class
) {
312 // algorithm: ordered dithering... many many thanks to rasterman
313 // (raster@rasterman.com) for telling me about this... portions of this
314 // code is based off of his code in Imlib
315 for (y
= 0, offset
= 0; y
< height
; y
++) {
318 for (x
= 0; x
< width
; x
++, offset
++) {
324 er
= r
& (red_bits
- 1);
325 eg
= g
& (green_bits
- 1);
326 eb
= b
& (blue_bits
- 1);
332 if ((dither4
[dithy
][dithx
] < er
) && (r
< red_table
[255])) r
++;
333 if ((dither4
[dithy
][dithx
] < eg
) && (g
< green_table
[255])) g
++;
334 if ((dither4
[dithy
][dithx
] < eb
) && (b
< blue_table
[255])) b
++;
336 pixel
= (r
<< red_offset
) | (g
<< green_offset
) | (b
<< blue_offset
);
340 *pixel_data
++ = pixel
;
343 case 16: // 16bpp LSB
344 *pixel_data
++ = pixel
;
345 *pixel_data
++ = pixel
>> 8;
348 case 17: // 16bpp MSB
349 *pixel_data
++ = pixel
>> 8;
350 *pixel_data
++ = pixel
;
353 case 24: // 24bpp LSB
354 *pixel_data
++ = pixel
;
355 *pixel_data
++ = pixel
>> 8;
356 *pixel_data
++ = pixel
>> 16;
359 case 25: // 24bpp MSB
360 *pixel_data
++ = pixel
>> 16;
361 *pixel_data
++ = pixel
>> 8;
362 *pixel_data
++ = pixel
;
365 case 32: // 32bpp LSB
366 *pixel_data
++ = pixel
;
367 *pixel_data
++ = pixel
>> 8;
368 *pixel_data
++ = pixel
>> 16;
369 *pixel_data
++ = pixel
>> 24;
372 case 33: // 32bpp MSB
373 *pixel_data
++ = pixel
>> 24;
374 *pixel_data
++ = pixel
>> 16;
375 *pixel_data
++ = pixel
>> 8;
376 *pixel_data
++ = pixel
;
381 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
388 #ifndef ORDEREDPSEUDO
390 *rerr
= new short[width
+ 2],
391 *gerr
= new short[width
+ 2],
392 *berr
= new short[width
+ 2],
393 *nrerr
= new short[width
+ 2],
394 *ngerr
= new short[width
+ 2],
395 *nberr
= new short[width
+ 2];
396 int rr
, gg
, bb
, rer
, ger
, ber
;
397 int dd
= 255 / control
.getColorsPerChannel();
399 for (x
= 0; x
< width
; x
++) {
400 *(rerr
+ x
) = *(red
+ x
);
401 *(gerr
+ x
) = *(green
+ x
);
402 *(berr
+ x
) = *(blue
+ x
);
405 *(rerr
+ x
) = *(gerr
+ x
) = *(berr
+ x
) = 0;
406 #endif // ORDEREDPSEUDO
408 for (y
= 0, offset
= 0; y
< height
; y
++) {
412 for (x
= 0; x
< width
; x
++, offset
++) {
419 er
= r
& (red_bits
- 1);
420 eg
= g
& (green_bits
- 1);
421 eb
= b
& (blue_bits
- 1);
427 if ((dither8
[dithy
][dithx
] < er
) && (r
< red_table
[255])) r
++;
428 if ((dither8
[dithy
][dithx
] < eg
) && (g
< green_table
[255])) g
++;
429 if ((dither8
[dithy
][dithx
] < eb
) && (b
< blue_table
[255])) b
++;
431 pixel
= (r
* cpccpc
) + (g
* cpc
) + b
;
432 *(pixel_data
++) = colors
[pixel
].pixel
;
435 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
437 #else // !ORDEREDPSEUDO
438 if (y
< (height
- 1)) {
439 int i
= offset
+ width
;
440 for (x
= 0; x
< width
; x
++, i
++) {
441 *(nrerr
+ x
) = *(red
+ i
);
442 *(ngerr
+ x
) = *(green
+ i
);
443 *(nberr
+ x
) = *(blue
+ i
);
446 *(nrerr
+ x
) = *(red
+ (--i
));
447 *(ngerr
+ x
) = *(green
+ i
);
448 *(nberr
+ x
) = *(blue
+ i
);
451 for (x
= 0; x
< width
; x
++) {
456 if (rr
> 255) rr
= 255; else if (rr
< 0) rr
= 0;
457 if (gg
> 255) gg
= 255; else if (gg
< 0) gg
= 0;
458 if (bb
> 255) bb
= 255; else if (bb
< 0) bb
= 0;
464 rer
= rerr
[x
] - r
*dd
;
465 ger
= gerr
[x
] - g
*dd
;
466 ber
= berr
[x
] - b
*dd
;
468 pixel
= (r
* cpccpc
) + (g
* cpc
) + b
;
469 *pixel_data
++ = colors
[pixel
].pixel
;
484 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
505 #endif // ORDEREDPSUEDO
510 fprintf(stderr
, i18n
->getMessage(ImageSet
, ImageUnsupVisual
,
511 "BImage::renderXImage: unsupported visual\n"));
513 XDestroyImage(image
);
517 switch (control
.getVisual()->c_class
) {
520 for (y
= 0, offset
= 0; y
< height
; y
++) {
521 for (x
= 0; x
< width
; x
++, offset
++) {
522 r
= red_table
[red
[offset
]];
523 g
= green_table
[green
[offset
]];
524 b
= blue_table
[blue
[offset
]];
526 pixel
= (r
* cpccpc
) + (g
* cpc
) + b
;
527 *pixel_data
++ = colors
[pixel
].pixel
;
530 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
536 for (y
= 0, offset
= 0; y
< height
; y
++) {
537 for (x
= 0; x
< width
; x
++, offset
++) {
538 r
= red_table
[red
[offset
]];
539 g
= green_table
[green
[offset
]];
540 b
= blue_table
[blue
[offset
]];
542 pixel
= (r
<< red_offset
) | (g
<< green_offset
) | (b
<< blue_offset
);
546 *pixel_data
++ = pixel
;
549 case 16: // 16bpp LSB
550 *pixel_data
++ = pixel
;
551 *pixel_data
++ = pixel
>> 8;
554 case 17: // 16bpp MSB
555 *pixel_data
++ = pixel
>> 8;
556 *pixel_data
++ = pixel
;
559 case 24: // 24bpp LSB
560 *pixel_data
++ = pixel
;
561 *pixel_data
++ = pixel
>> 8;
562 *pixel_data
++ = pixel
>> 16;
565 case 25: // 24bpp MSB
566 *pixel_data
++ = pixel
>> 16;
567 *pixel_data
++ = pixel
>> 8;
568 *pixel_data
++ = pixel
;
571 case 32: // 32bpp LSB
572 *pixel_data
++ = pixel
;
573 *pixel_data
++ = pixel
>> 8;
574 *pixel_data
++ = pixel
>> 16;
575 *pixel_data
++ = pixel
>> 24;
578 case 33: // 32bpp MSB
579 *pixel_data
++ = pixel
>> 24;
580 *pixel_data
++ = pixel
>> 16;
581 *pixel_data
++ = pixel
>> 8;
582 *pixel_data
++ = pixel
;
587 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
594 for (y
= 0, offset
= 0; y
< height
; y
++) {
595 for (x
= 0; x
< width
; x
++, offset
++) {
596 r
= *(red_table
+ *(red
+ offset
));
597 g
= *(green_table
+ *(green
+ offset
));
598 b
= *(blue_table
+ *(blue
+ offset
));
600 g
= ((r
* 30) + (g
* 59) + (b
* 11)) / 100;
601 *pixel_data
++ = colors
[g
].pixel
;
604 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
610 fprintf(stderr
, i18n
->getMessage(ImageSet
, ImageUnsupVisual
,
611 "BImage::renderXImage: unsupported visual\n"));
613 XDestroyImage(image
);
618 image
->data
= (char *) d
;
623 Pixmap
BImage::renderPixmap(void) {
625 XCreatePixmap(control
.getBaseDisplay().getXDisplay(),
626 control
.getDrawable(), width
, height
, control
.getDepth());
628 if (pixmap
== None
) {
629 fprintf(stderr
, i18n
->getMessage(ImageSet
, ImageErrorCreatingPixmap
,
630 "BImage::renderPixmap: error creating pixmap\n"));
634 XImage
*image
= renderXImage();
637 XFreePixmap(control
.getBaseDisplay().getXDisplay(), pixmap
);
639 } else if (! image
->data
) {
640 XDestroyImage(image
);
641 XFreePixmap(control
.getBaseDisplay().getXDisplay(), pixmap
);
645 XPutImage(control
.getBaseDisplay().getXDisplay(), pixmap
,
646 DefaultGC(control
.getBaseDisplay().getXDisplay(),
647 control
.getScreenInfo().getScreenNumber()),
648 image
, 0, 0, 0, 0, width
, height
);
651 delete [] image
->data
;
655 XDestroyImage(image
);
661 void BImage::bevel1(void) {
662 if (width
> 2 && height
> 2) {
663 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
665 register unsigned char r
, g
, b
, rr
,gg
,bb
;
666 register unsigned int w
= width
, h
= height
- 1, wh
= w
* h
;
684 rr
= (r
>> 2) + (r
>> 1);
687 gg
= (g
>> 2) + (g
>> 1);
690 bb
= (b
>> 2) + (b
>> 1);
713 rr
= (r
>> 2) + (r
>> 1);
716 gg
= (g
>> 2) + (g
>> 1);
719 bb
= (b
>> 2) + (b
>> 1);
750 rr
= (r
>> 2) + (r
>> 1);
753 gg
= (g
>> 2) + (g
>> 1);
756 bb
= (b
>> 2) + (b
>> 1);
783 rr
= (r
>> 2) + (r
>> 1);
786 gg
= (g
>> 2) + (g
>> 1);
789 bb
= (b
>> 2) + (b
>> 1);
799 void BImage::bevel2(void) {
800 if (width
> 4 && height
> 4) {
801 unsigned char r
, g
, b
, rr
,gg
,bb
, *pr
= red
+ width
+ 1,
802 *pg
= green
+ width
+ 1, *pb
= blue
+ width
+ 1;
803 unsigned int w
= width
- 2, h
= height
- 1, wh
= width
* (height
- 3);
821 rr
= (r
>> 2) + (r
>> 1);
824 gg
= (g
>> 2) + (g
>> 1);
827 bb
= (b
>> 2) + (b
>> 1);
859 rr
= (r
>> 2) + (r
>> 1);
862 gg
= (g
>> 2) + (g
>> 1);
865 bb
= (b
>> 2) + (b
>> 1);
878 void BImage::invert(void) {
879 register unsigned int i
, j
, wh
= (width
* height
) - 1;
882 for (i
= 0, j
= wh
; j
> i
; j
--, i
++) {
884 *(red
+ j
) = *(red
+ i
);
888 *(green
+ j
) = *(green
+ i
);
892 *(blue
+ j
) = *(blue
+ i
);
898 void BImage::dgradient(void) {
899 // diagonal gradient code was written by Mike Cole <mike@mydot.com>
900 // modified for interlacing by Brad Hughes
902 float drx
, dgx
, dbx
, dry
, dgy
, dby
, yr
= 0.0, yg
= 0.0, yb
= 0.0,
903 xr
= (float) from
->getRed(),
904 xg
= (float) from
->getGreen(),
905 xb
= (float) from
->getBlue();
906 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
907 unsigned int w
= width
* 2, h
= height
* 2, *xt
= xtable
, *yt
= ytable
;
909 register unsigned int x
, y
;
911 dry
= drx
= (float) (to
->getRed() - from
->getRed());
912 dgy
= dgx
= (float) (to
->getGreen() - from
->getGreen());
913 dby
= dbx
= (float) (to
->getBlue() - from
->getBlue());
920 for (x
= 0; x
< width
; x
++) {
921 *(xt
++) = (unsigned char) (xr
);
922 *(xt
++) = (unsigned char) (xg
);
923 *(xt
++) = (unsigned char) (xb
);
935 for (y
= 0; y
< height
; y
++) {
936 *(yt
++) = ((unsigned char) yr
);
937 *(yt
++) = ((unsigned char) yg
);
938 *(yt
++) = ((unsigned char) yb
);
945 // Combine tables to create gradient
952 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
953 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
954 *(pr
++) = *(xt
++) + *(yt
);
955 *(pg
++) = *(xt
++) + *(yt
+ 1);
956 *(pb
++) = *(xt
++) + *(yt
+ 2);
962 // faked interlacing effect
963 unsigned char channel
, channel2
;
965 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
966 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
968 channel
= *(xt
++) + *(yt
);
969 channel2
= (channel
>> 1) + (channel
>> 2);
970 if (channel2
> channel
) channel2
= 0;
973 channel
= *(xt
++) + *(yt
+ 1);
974 channel2
= (channel
>> 1) + (channel
>> 2);
975 if (channel2
> channel
) channel2
= 0;
978 channel
= *(xt
++) + *(yt
+ 2);
979 channel2
= (channel
>> 1) + (channel
>> 2);
980 if (channel2
> channel
) channel2
= 0;
983 channel
= *(xt
++) + *(yt
);
984 channel2
= channel
+ (channel
>> 3);
985 if (channel2
< channel
) channel2
= ~0;
988 channel
= *(xt
++) + *(yt
+ 1);
989 channel2
= channel
+ (channel
>> 3);
990 if (channel2
< channel
) channel2
= ~0;
993 channel
= *(xt
++) + *(yt
+ 2);
994 channel2
= channel
+ (channel
>> 3);
995 if (channel2
< channel
) channel2
= ~0;
1006 void BImage::hgradient(void) {
1007 float drx
, dgx
, dbx
,
1008 xr
= (float) from
->getRed(),
1009 xg
= (float) from
->getGreen(),
1010 xb
= (float) from
->getBlue();
1011 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1013 register unsigned int x
, y
;
1015 drx
= (float) (to
->getRed() - from
->getRed());
1016 dgx
= (float) (to
->getGreen() - from
->getGreen());
1017 dbx
= (float) (to
->getBlue() - from
->getBlue());
1024 if (interlaced
&& height
> 2) {
1025 // faked interlacing effect
1026 unsigned char channel
, channel2
;
1028 for (x
= 0; x
< width
; x
++, pr
++, pg
++, pb
++) {
1029 channel
= (unsigned char) xr
;
1030 channel2
= (channel
>> 1) + (channel
>> 2);
1031 if (channel2
> channel
) channel2
= 0;
1034 channel
= (unsigned char) xg
;
1035 channel2
= (channel
>> 1) + (channel
>> 2);
1036 if (channel2
> channel
) channel2
= 0;
1039 channel
= (unsigned char) xb
;
1040 channel2
= (channel
>> 1) + (channel
>> 2);
1041 if (channel2
> channel
) channel2
= 0;
1045 channel
= (unsigned char) xr
;
1046 channel2
= channel
+ (channel
>> 3);
1047 if (channel2
< channel
) channel2
= ~0;
1048 *(pr
+ width
) = channel2
;
1050 channel
= (unsigned char) xg
;
1051 channel2
= channel
+ (channel
>> 3);
1052 if (channel2
< channel
) channel2
= ~0;
1053 *(pg
+ width
) = channel2
;
1055 channel
= (unsigned char) xb
;
1056 channel2
= channel
+ (channel
>> 3);
1057 if (channel2
< channel
) channel2
= ~0;
1058 *(pb
+ width
) = channel2
;
1071 for (y
= 2; y
< height
; y
++, pr
+= width
, pg
+= width
, pb
+= width
) {
1072 if (y
& 1) offset
= width
; else offset
= 0;
1074 memcpy(pr
, (red
+ offset
), width
);
1075 memcpy(pg
, (green
+ offset
), width
);
1076 memcpy(pb
, (blue
+ offset
), width
);
1082 for (x
= 0; x
< width
; x
++) {
1083 *(pr
++) = (unsigned char) (xr
);
1084 *(pg
++) = (unsigned char) (xg
);
1085 *(pb
++) = (unsigned char) (xb
);
1092 for (y
= 1; y
< height
; y
++, pr
+= width
, pg
+= width
, pb
+= width
) {
1093 memcpy(pr
, red
, width
);
1094 memcpy(pg
, green
, width
);
1095 memcpy(pb
, blue
, width
);
1105 void BImage::vgradient(void) {
1106 float dry
, dgy
, dby
,
1107 yr
= (float) from
->getRed(),
1108 yg
= (float) from
->getGreen(),
1109 yb
= (float) from
->getBlue();
1110 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1112 register unsigned int y
;
1114 dry
= (float) (to
->getRed() - from
->getRed());
1115 dgy
= (float) (to
->getGreen() - from
->getGreen());
1116 dby
= (float) (to
->getBlue() - from
->getBlue());
1124 // faked interlacing effect
1125 unsigned char channel
, channel2
;
1127 for (y
= 0; y
< height
; y
++, pr
+= width
, pg
+= width
, pb
+= width
) {
1129 channel
= (unsigned char) yr
;
1130 channel2
= (channel
>> 1) + (channel
>> 2);
1131 if (channel2
> channel
) channel2
= 0;
1132 memset(pr
, channel2
, width
);
1134 channel
= (unsigned char) yg
;
1135 channel2
= (channel
>> 1) + (channel
>> 2);
1136 if (channel2
> channel
) channel2
= 0;
1137 memset(pg
, channel2
, width
);
1139 channel
= (unsigned char) yb
;
1140 channel2
= (channel
>> 1) + (channel
>> 2);
1141 if (channel2
> channel
) channel2
= 0;
1142 memset(pb
, channel2
, width
);
1144 channel
= (unsigned char) yr
;
1145 channel2
= channel
+ (channel
>> 3);
1146 if (channel2
< channel
) channel2
= ~0;
1147 memset(pr
, channel2
, width
);
1149 channel
= (unsigned char) yg
;
1150 channel2
= channel
+ (channel
>> 3);
1151 if (channel2
< channel
) channel2
= ~0;
1152 memset(pg
, channel2
, width
);
1154 channel
= (unsigned char) yb
;
1155 channel2
= channel
+ (channel
>> 3);
1156 if (channel2
< channel
) channel2
= ~0;
1157 memset(pb
, channel2
, width
);
1168 for (y
= 0; y
< height
; y
++, pr
+= width
, pg
+= width
, pb
+= width
) {
1169 memset(pr
, (unsigned char) yr
, width
);
1170 memset(pg
, (unsigned char) yg
, width
);
1171 memset(pb
, (unsigned char) yb
, width
);
1185 void BImage::pgradient(void) {
1186 // pyramid gradient - based on original dgradient, written by
1187 // Mosfet (mosfet@kde.org)
1188 // adapted from kde sources for Openbox by Brad Hughes
1190 float yr
, yg
, yb
, drx
, dgx
, dbx
, dry
, dgy
, dby
,
1192 int rsign
, gsign
, bsign
;
1193 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1194 unsigned int tr
= to
->getRed(), tg
= to
->getGreen(), tb
= to
->getBlue(),
1195 *xt
= xtable
, *yt
= ytable
;
1197 register unsigned int x
, y
;
1199 dry
= drx
= (float) (to
->getRed() - from
->getRed());
1200 dgy
= dgx
= (float) (to
->getGreen() - from
->getGreen());
1201 dby
= dbx
= (float) (to
->getBlue() - from
->getBlue());
1203 rsign
= (drx
< 0) ? -1 : 1;
1204 gsign
= (dgx
< 0) ? -1 : 1;
1205 bsign
= (dbx
< 0) ? -1 : 1;
1207 xr
= yr
= (drx
/ 2);
1208 xg
= yg
= (dgx
/ 2);
1209 xb
= yb
= (dbx
/ 2);
1216 for (x
= 0; x
< width
; x
++) {
1217 *(xt
++) = (unsigned char) ((xr
< 0) ? -xr
: xr
);
1218 *(xt
++) = (unsigned char) ((xg
< 0) ? -xg
: xg
);
1219 *(xt
++) = (unsigned char) ((xb
< 0) ? -xb
: xb
);
1231 for (y
= 0; y
< height
; y
++) {
1232 *(yt
++) = ((unsigned char) ((yr
< 0) ? -yr
: yr
));
1233 *(yt
++) = ((unsigned char) ((yg
< 0) ? -yg
: yg
));
1234 *(yt
++) = ((unsigned char) ((yb
< 0) ? -yb
: yb
));
1241 // Combine tables to create gradient
1248 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1249 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1250 *(pr
++) = (unsigned char) (tr
- (rsign
* (*(xt
++) + *(yt
))));
1251 *(pg
++) = (unsigned char) (tg
- (gsign
* (*(xt
++) + *(yt
+ 1))));
1252 *(pb
++) = (unsigned char) (tb
- (bsign
* (*(xt
++) + *(yt
+ 2))));
1258 // faked interlacing effect
1259 unsigned char channel
, channel2
;
1261 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1262 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1264 channel
= (unsigned char) (tr
- (rsign
* (*(xt
++) + *(yt
))));
1265 channel2
= (channel
>> 1) + (channel
>> 2);
1266 if (channel2
> channel
) channel2
= 0;
1269 channel
= (unsigned char) (tg
- (gsign
* (*(xt
++) + *(yt
+ 1))));
1270 channel2
= (channel
>> 1) + (channel
>> 2);
1271 if (channel2
> channel
) channel2
= 0;
1274 channel
= (unsigned char) (tb
- (bsign
* (*(xt
++) + *(yt
+ 2))));
1275 channel2
= (channel
>> 1) + (channel
>> 2);
1276 if (channel2
> channel
) channel2
= 0;
1279 channel
= (unsigned char) (tr
- (rsign
* (*(xt
++) + *(yt
))));
1280 channel2
= channel
+ (channel
>> 3);
1281 if (channel2
< channel
) channel2
= ~0;
1284 channel
= (unsigned char) (tg
- (gsign
* (*(xt
++) + *(yt
+ 1))));
1285 channel2
= channel
+ (channel
>> 3);
1286 if (channel2
< channel
) channel2
= ~0;
1289 channel
= (unsigned char) (tb
- (bsign
* (*(xt
++) + *(yt
+ 2))));
1290 channel2
= channel
+ (channel
>> 3);
1291 if (channel2
< channel
) channel2
= ~0;
1301 void BImage::rgradient(void) {
1302 // rectangle gradient - based on original dgradient, written by
1303 // Mosfet (mosfet@kde.org)
1304 // adapted from kde sources for Openbox by Brad Hughes
1306 float drx
, dgx
, dbx
, dry
, dgy
, dby
, xr
, xg
, xb
, yr
, yg
, yb
;
1307 int rsign
, gsign
, bsign
;
1308 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1309 unsigned int tr
= to
->getRed(), tg
= to
->getGreen(), tb
= to
->getBlue(),
1310 *xt
= xtable
, *yt
= ytable
;
1312 register unsigned int x
, y
;
1314 dry
= drx
= (float) (to
->getRed() - from
->getRed());
1315 dgy
= dgx
= (float) (to
->getGreen() - from
->getGreen());
1316 dby
= dbx
= (float) (to
->getBlue() - from
->getBlue());
1318 rsign
= (drx
< 0) ? -2 : 2;
1319 gsign
= (dgx
< 0) ? -2 : 2;
1320 bsign
= (dbx
< 0) ? -2 : 2;
1322 xr
= yr
= (drx
/ 2);
1323 xg
= yg
= (dgx
/ 2);
1324 xb
= yb
= (dbx
/ 2);
1331 for (x
= 0; x
< width
; x
++) {
1332 *(xt
++) = (unsigned char) ((xr
< 0) ? -xr
: xr
);
1333 *(xt
++) = (unsigned char) ((xg
< 0) ? -xg
: xg
);
1334 *(xt
++) = (unsigned char) ((xb
< 0) ? -xb
: xb
);
1346 for (y
= 0; y
< height
; y
++) {
1347 *(yt
++) = ((unsigned char) ((yr
< 0) ? -yr
: yr
));
1348 *(yt
++) = ((unsigned char) ((yg
< 0) ? -yg
: yg
));
1349 *(yt
++) = ((unsigned char) ((yb
< 0) ? -yb
: yb
));
1356 // Combine tables to create gradient
1363 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1364 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1365 *(pr
++) = (unsigned char) (tr
- (rsign
* max(*(xt
++), *(yt
))));
1366 *(pg
++) = (unsigned char) (tg
- (gsign
* max(*(xt
++), *(yt
+ 1))));
1367 *(pb
++) = (unsigned char) (tb
- (bsign
* max(*(xt
++), *(yt
+ 2))));
1373 // faked interlacing effect
1374 unsigned char channel
, channel2
;
1376 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1377 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1379 channel
= (unsigned char) (tr
- (rsign
* max(*(xt
++), *(yt
))));
1380 channel2
= (channel
>> 1) + (channel
>> 2);
1381 if (channel2
> channel
) channel2
= 0;
1384 channel
= (unsigned char) (tg
- (gsign
* max(*(xt
++), *(yt
+ 1))));
1385 channel2
= (channel
>> 1) + (channel
>> 2);
1386 if (channel2
> channel
) channel2
= 0;
1389 channel
= (unsigned char) (tb
- (bsign
* max(*(xt
++), *(yt
+ 2))));
1390 channel2
= (channel
>> 1) + (channel
>> 2);
1391 if (channel2
> channel
) channel2
= 0;
1394 channel
= (unsigned char) (tr
- (rsign
* max(*(xt
++), *(yt
))));
1395 channel2
= channel
+ (channel
>> 3);
1396 if (channel2
< channel
) channel2
= ~0;
1399 channel
= (unsigned char) (tg
- (gsign
* max(*(xt
++), *(yt
+ 1))));
1400 channel2
= channel
+ (channel
>> 3);
1401 if (channel2
< channel
) channel2
= ~0;
1404 channel
= (unsigned char) (tb
- (bsign
* max(*(xt
++), *(yt
+ 2))));
1405 channel2
= channel
+ (channel
>> 3);
1406 if (channel2
< channel
) channel2
= ~0;
1416 void BImage::egradient(void) {
1417 // elliptic gradient - based on original dgradient, written by
1418 // Mosfet (mosfet@kde.org)
1419 // adapted from kde sources for Openbox by Brad Hughes
1421 float drx
, dgx
, dbx
, dry
, dgy
, dby
, yr
, yg
, yb
, xr
, xg
, xb
;
1422 int rsign
, gsign
, bsign
;
1423 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1424 unsigned int *xt
= xtable
, *yt
= ytable
,
1425 tr
= (unsigned long) to
->getRed(),
1426 tg
= (unsigned long) to
->getGreen(),
1427 tb
= (unsigned long) to
->getBlue();
1429 register unsigned int x
, y
;
1431 dry
= drx
= (float) (to
->getRed() - from
->getRed());
1432 dgy
= dgx
= (float) (to
->getGreen() - from
->getGreen());
1433 dby
= dbx
= (float) (to
->getBlue() - from
->getBlue());
1435 rsign
= (drx
< 0) ? -1 : 1;
1436 gsign
= (dgx
< 0) ? -1 : 1;
1437 bsign
= (dbx
< 0) ? -1 : 1;
1439 xr
= yr
= (drx
/ 2);
1440 xg
= yg
= (dgx
/ 2);
1441 xb
= yb
= (dbx
/ 2);
1448 for (x
= 0; x
< width
; x
++) {
1449 *(xt
++) = (unsigned long) (xr
* xr
);
1450 *(xt
++) = (unsigned long) (xg
* xg
);
1451 *(xt
++) = (unsigned long) (xb
* xb
);
1463 for (y
= 0; y
< height
; y
++) {
1464 *(yt
++) = (unsigned long) (yr
* yr
);
1465 *(yt
++) = (unsigned long) (yg
* yg
);
1466 *(yt
++) = (unsigned long) (yb
* yb
);
1473 // Combine tables to create gradient
1480 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1481 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1482 *(pr
++) = (unsigned char)
1483 (tr
- (rsign
* control
.getSqrt(*(xt
++) + *(yt
))));
1484 *(pg
++) = (unsigned char)
1485 (tg
- (gsign
* control
.getSqrt(*(xt
++) + *(yt
+ 1))));
1486 *(pb
++) = (unsigned char)
1487 (tb
- (bsign
* control
.getSqrt(*(xt
++) + *(yt
+ 2))));
1493 // faked interlacing effect
1494 unsigned char channel
, channel2
;
1496 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1497 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1499 channel
= (unsigned char)
1500 (tr
- (rsign
* control
.getSqrt(*(xt
++) + *(yt
))));
1501 channel2
= (channel
>> 1) + (channel
>> 2);
1502 if (channel2
> channel
) channel2
= 0;
1505 channel
= (unsigned char)
1506 (tg
- (gsign
* control
.getSqrt(*(xt
++) + *(yt
+ 1))));
1507 channel2
= (channel
>> 1) + (channel
>> 2);
1508 if (channel2
> channel
) channel2
= 0;
1511 channel
= (unsigned char)
1512 (tb
- (bsign
* control
.getSqrt(*(xt
++) + *(yt
+ 2))));
1513 channel2
= (channel
>> 1) + (channel
>> 2);
1514 if (channel2
> channel
) channel2
= 0;
1517 channel
= (unsigned char)
1518 (tr
- (rsign
* control
.getSqrt(*(xt
++) + *(yt
))));
1519 channel2
= channel
+ (channel
>> 3);
1520 if (channel2
< channel
) channel2
= ~0;
1523 channel
= (unsigned char)
1524 (tg
- (gsign
* control
.getSqrt(*(xt
++) + *(yt
+ 1))));
1525 channel2
= channel
+ (channel
>> 3);
1526 if (channel2
< channel
) channel2
= ~0;
1529 channel
= (unsigned char)
1530 (tb
- (bsign
* control
.getSqrt(*(xt
++) + *(yt
+ 2))));
1531 channel2
= channel
+ (channel
>> 3);
1532 if (channel2
< channel
) channel2
= ~0;
1542 void BImage::pcgradient(void) {
1543 // pipe cross gradient - based on original dgradient, written by
1544 // Mosfet (mosfet@kde.org)
1545 // adapted from kde sources for Openbox by Brad Hughes
1547 float drx
, dgx
, dbx
, dry
, dgy
, dby
, xr
, xg
, xb
, yr
, yg
, yb
;
1548 int rsign
, gsign
, bsign
;
1549 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1550 unsigned int *xt
= xtable
, *yt
= ytable
,
1552 tg
= to
->getGreen(),
1555 register unsigned int x
, y
;
1557 dry
= drx
= (float) (to
->getRed() - from
->getRed());
1558 dgy
= dgx
= (float) (to
->getGreen() - from
->getGreen());
1559 dby
= dbx
= (float) (to
->getBlue() - from
->getBlue());
1561 rsign
= (drx
< 0) ? -2 : 2;
1562 gsign
= (dgx
< 0) ? -2 : 2;
1563 bsign
= (dbx
< 0) ? -2 : 2;
1565 xr
= yr
= (drx
/ 2);
1566 xg
= yg
= (dgx
/ 2);
1567 xb
= yb
= (dbx
/ 2);
1574 for (x
= 0; x
< width
; x
++) {
1575 *(xt
++) = (unsigned char) ((xr
< 0) ? -xr
: xr
);
1576 *(xt
++) = (unsigned char) ((xg
< 0) ? -xg
: xg
);
1577 *(xt
++) = (unsigned char) ((xb
< 0) ? -xb
: xb
);
1589 for (y
= 0; y
< height
; y
++) {
1590 *(yt
++) = ((unsigned char) ((yr
< 0) ? -yr
: yr
));
1591 *(yt
++) = ((unsigned char) ((yg
< 0) ? -yg
: yg
));
1592 *(yt
++) = ((unsigned char) ((yb
< 0) ? -yb
: yb
));
1599 // Combine tables to create gradient
1605 // normal pcgradient
1606 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1607 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1608 *(pr
++) = (unsigned char) (tr
- (rsign
* min(*(xt
++), *(yt
))));
1609 *(pg
++) = (unsigned char) (tg
- (gsign
* min(*(xt
++), *(yt
+ 1))));
1610 *(pb
++) = (unsigned char) (tb
- (bsign
* min(*(xt
++), *(yt
+ 2))));
1616 // faked interlacing effect
1617 unsigned char channel
, channel2
;
1619 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1620 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1622 channel
= (unsigned char) (tr
- (rsign
* min(*(xt
++), *(yt
))));
1623 channel2
= (channel
>> 1) + (channel
>> 2);
1624 if (channel2
> channel
) channel2
= 0;
1627 channel
= (unsigned char) (tg
- (bsign
* min(*(xt
++), *(yt
+ 1))));
1628 channel2
= (channel
>> 1) + (channel
>> 2);
1629 if (channel2
> channel
) channel2
= 0;
1632 channel
= (unsigned char) (tb
- (gsign
* min(*(xt
++), *(yt
+ 2))));
1633 channel2
= (channel
>> 1) + (channel
>> 2);
1634 if (channel2
> channel
) channel2
= 0;
1637 channel
= (unsigned char) (tr
- (rsign
* min(*(xt
++), *(yt
))));
1638 channel2
= channel
+ (channel
>> 3);
1639 if (channel2
< channel
) channel2
= ~0;
1642 channel
= (unsigned char) (tg
- (gsign
* min(*(xt
++), *(yt
+ 1))));
1643 channel2
= channel
+ (channel
>> 3);
1644 if (channel2
< channel
) channel2
= ~0;
1647 channel
= (unsigned char) (tb
- (bsign
* min(*(xt
++), *(yt
+ 2))));
1648 channel2
= channel
+ (channel
>> 3);
1649 if (channel2
< channel
) channel2
= ~0;
1659 void BImage::cdgradient(void) {
1660 // cross diagonal gradient - based on original dgradient, written by
1661 // Mosfet (mosfet@kde.org)
1662 // adapted from kde sources for Openbox by Brad Hughes
1664 float drx
, dgx
, dbx
, dry
, dgy
, dby
, yr
= 0.0, yg
= 0.0, yb
= 0.0,
1665 xr
= (float) from
->getRed(),
1666 xg
= (float) from
->getGreen(),
1667 xb
= (float) from
->getBlue();
1668 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1669 unsigned int w
= width
* 2, h
= height
* 2, *xt
, *yt
;
1671 register unsigned int x
, y
;
1673 dry
= drx
= (float) (to
->getRed() - from
->getRed());
1674 dgy
= dgx
= (float) (to
->getGreen() - from
->getGreen());
1675 dby
= dbx
= (float) (to
->getBlue() - from
->getBlue());
1682 for (xt
= (xtable
+ (width
* 3) - 1), x
= 0; x
< width
; x
++) {
1683 *(xt
--) = (unsigned char) xb
;
1684 *(xt
--) = (unsigned char) xg
;
1685 *(xt
--) = (unsigned char) xr
;
1697 for (yt
= ytable
, y
= 0; y
< height
; y
++) {
1698 *(yt
++) = (unsigned char) yr
;
1699 *(yt
++) = (unsigned char) yg
;
1700 *(yt
++) = (unsigned char) yb
;
1707 // Combine tables to create gradient
1713 // normal cdgradient
1714 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1715 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1716 *(pr
++) = *(xt
++) + *(yt
);
1717 *(pg
++) = *(xt
++) + *(yt
+ 1);
1718 *(pb
++) = *(xt
++) + *(yt
+ 2);
1724 // faked interlacing effect
1725 unsigned char channel
, channel2
;
1727 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1728 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1730 channel
= *(xt
++) + *(yt
);
1731 channel2
= (channel
>> 1) + (channel
>> 2);
1732 if (channel2
> channel
) channel2
= 0;
1735 channel
= *(xt
++) + *(yt
+ 1);
1736 channel2
= (channel
>> 1) + (channel
>> 2);
1737 if (channel2
> channel
) channel2
= 0;
1740 channel
= *(xt
++) + *(yt
+ 2);
1741 channel2
= (channel
>> 1) + (channel
>> 2);
1742 if (channel2
> channel
) channel2
= 0;
1745 channel
= *(xt
++) + *(yt
);
1746 channel2
= channel
+ (channel
>> 3);
1747 if (channel2
< channel
) channel2
= ~0;
1750 channel
= *(xt
++) + *(yt
+ 1);
1751 channel2
= channel
+ (channel
>> 3);
1752 if (channel2
< channel
) channel2
= ~0;
1755 channel
= *(xt
++) + *(yt
+ 2);
1756 channel2
= channel
+ (channel
>> 3);
1757 if (channel2
< channel
) channel2
= ~0;
1767 BImageControl::BImageControl(BaseDisplay
&dpy
, ScreenInfo
&scrn
, Bool _dither
,
1768 int _cpc
, unsigned long cache_timeout
,
1769 unsigned long cmax
) : basedisplay(dpy
),
1773 setColorsPerChannel(_cpc
);
1777 if (cache_timeout
) {
1778 timer
= new BTimer(basedisplay
, *this);
1779 timer
->setTimeout(cache_timeout
);
1782 timer
= (BTimer
*) 0;
1783 #endif // TIMEDCACHE
1785 colors
= (XColor
*) 0;
1788 grad_xbuffer
= grad_ybuffer
= (unsigned int *) 0;
1789 grad_buffer_width
= grad_buffer_height
= 0;
1791 sqrt_table
= (unsigned long *) 0;
1793 screen_depth
= screeninfo
.getDepth();
1794 window
= screeninfo
.getRootWindow();
1795 screen_number
= screeninfo
.getScreenNumber();
1798 XPixmapFormatValues
*pmv
= XListPixmapFormats(basedisplay
.getXDisplay(),
1800 colormap
= screeninfo
.getColormap();
1804 for (int i
= 0; i
< count
; i
++)
1805 if (pmv
[i
].depth
== screen_depth
) {
1806 bits_per_pixel
= pmv
[i
].bits_per_pixel
;
1813 if (bits_per_pixel
== 0) bits_per_pixel
= screen_depth
;
1814 if (bits_per_pixel
>= 24) setDither(False
);
1816 red_offset
= green_offset
= blue_offset
= 0;
1818 switch (getVisual()->c_class
) {
1823 // compute color tables
1824 unsigned long red_mask
= getVisual()->red_mask
,
1825 green_mask
= getVisual()->green_mask
,
1826 blue_mask
= getVisual()->blue_mask
;
1828 while (! (red_mask
& 1)) { red_offset
++; red_mask
>>= 1; }
1829 while (! (green_mask
& 1)) { green_offset
++; green_mask
>>= 1; }
1830 while (! (blue_mask
& 1)) { blue_offset
++; blue_mask
>>= 1; }
1832 red_bits
= 255 / red_mask
;
1833 green_bits
= 255 / green_mask
;
1834 blue_bits
= 255 / blue_mask
;
1836 for (i
= 0; i
< 256; i
++) {
1837 red_color_table
[i
] = i
/ red_bits
;
1838 green_color_table
[i
] = i
/ green_bits
;
1839 blue_color_table
[i
] = i
/ blue_bits
;
1848 ncolors
= colors_per_channel
* colors_per_channel
* colors_per_channel
;
1850 if (ncolors
> (1 << screen_depth
)) {
1851 colors_per_channel
= (1 << screen_depth
) / 3;
1852 ncolors
= colors_per_channel
* colors_per_channel
* colors_per_channel
;
1855 if (colors_per_channel
< 2 || ncolors
> (1 << screen_depth
)) {
1856 fprintf(stderr
, i18n
->getMessage(ImageSet
, ImageInvalidColormapSize
,
1857 "BImageControl::BImageControl: invalid colormap size %d "
1858 "(%d/%d/%d) - reducing"),
1859 ncolors
, colors_per_channel
, colors_per_channel
,
1860 colors_per_channel
);
1862 colors_per_channel
= (1 << screen_depth
) / 3;
1865 colors
= new XColor
[ncolors
];
1867 fprintf(stderr
, i18n
->getMessage(ImageSet
,
1868 ImageErrorAllocatingColormap
,
1869 "BImageControl::BImageControl: error allocating "
1874 int i
= 0, ii
, p
, r
, g
, b
,
1876 #ifdef ORDEREDPSEUDO
1877 bits
= 256 / colors_per_channel
;
1878 #else // !ORDEREDPSEUDO
1879 bits
= 255 / (colors_per_channel
- 1);
1880 #endif // ORDEREDPSEUDO
1882 red_bits
= green_bits
= blue_bits
= bits
;
1884 for (i
= 0; i
< 256; i
++)
1885 red_color_table
[i
] = green_color_table
[i
] = blue_color_table
[i
] =
1888 for (r
= 0, i
= 0; r
< colors_per_channel
; r
++)
1889 for (g
= 0; g
< colors_per_channel
; g
++)
1890 for (b
= 0; b
< colors_per_channel
; b
++, i
++) {
1891 colors
[i
].red
= (r
* 0xffff) / (colors_per_channel
- 1);
1892 colors
[i
].green
= (g
* 0xffff) / (colors_per_channel
- 1);
1893 colors
[i
].blue
= (b
* 0xffff) / (colors_per_channel
- 1);;
1894 colors
[i
].flags
= DoRed
|DoGreen
|DoBlue
;
1899 for (i
= 0; i
< ncolors
; i
++)
1900 if (! XAllocColor(basedisplay
.getXDisplay(), colormap
, &colors
[i
])) {
1901 fprintf(stderr
, i18n
->getMessage(ImageSet
, ImageColorAllocFail
,
1902 "couldn't alloc color %i %i %i\n"),
1903 colors
[i
].red
, colors
[i
].green
, colors
[i
].blue
);
1904 colors
[i
].flags
= 0;
1906 colors
[i
].flags
= DoRed
|DoGreen
|DoBlue
;
1908 basedisplay
.ungrab();
1910 XColor icolors
[256];
1911 int incolors
= (((1 << screen_depth
) > 256) ? 256 : (1 << screen_depth
));
1913 for (i
= 0; i
< incolors
; i
++)
1914 icolors
[i
].pixel
= i
;
1916 XQueryColors(basedisplay
.getXDisplay(), colormap
, icolors
, incolors
);
1917 for (i
= 0; i
< ncolors
; i
++) {
1918 if (! colors
[i
].flags
) {
1919 unsigned long chk
= 0xffffffff, pixel
, close
= 0;
1923 for (ii
= 0; ii
< incolors
; ii
++) {
1924 r
= (colors
[i
].red
- icolors
[i
].red
) >> 8;
1925 g
= (colors
[i
].green
- icolors
[i
].green
) >> 8;
1926 b
= (colors
[i
].blue
- icolors
[i
].blue
) >> 8;
1927 pixel
= (r
* r
) + (g
* g
) + (b
* b
);
1934 colors
[i
].red
= icolors
[close
].red
;
1935 colors
[i
].green
= icolors
[close
].green
;
1936 colors
[i
].blue
= icolors
[close
].blue
;
1938 if (XAllocColor(basedisplay
.getXDisplay(), colormap
,
1940 colors
[i
].flags
= DoRed
|DoGreen
|DoBlue
;
1955 if (getVisual()->c_class
== StaticGray
) {
1956 ncolors
= 1 << screen_depth
;
1958 ncolors
= colors_per_channel
* colors_per_channel
* colors_per_channel
;
1960 if (ncolors
> (1 << screen_depth
)) {
1961 colors_per_channel
= (1 << screen_depth
) / 3;
1963 colors_per_channel
* colors_per_channel
* colors_per_channel
;
1967 if (colors_per_channel
< 2 || ncolors
> (1 << screen_depth
)) {
1968 fprintf(stderr
, i18n
->getMessage(ImageSet
, ImageInvalidColormapSize
,
1969 "BImageControl::BImageControl: invalid colormap size %d "
1970 "(%d/%d/%d) - reducing"),
1971 ncolors
, colors_per_channel
, colors_per_channel
,
1972 colors_per_channel
);
1974 colors_per_channel
= (1 << screen_depth
) / 3;
1977 colors
= new XColor
[ncolors
];
1979 fprintf(stderr
, i18n
->getMessage(ImageSet
,
1980 ImageErrorAllocatingColormap
,
1981 "BImageControl::BImageControl: error allocating "
1986 int i
= 0, ii
, p
, bits
= 255 / (colors_per_channel
- 1);
1987 red_bits
= green_bits
= blue_bits
= bits
;
1989 for (i
= 0; i
< 256; i
++)
1990 red_color_table
[i
] = green_color_table
[i
] = blue_color_table
[i
] =
1994 for (i
= 0; i
< ncolors
; i
++) {
1995 colors
[i
].red
= (i
* 0xffff) / (colors_per_channel
- 1);
1996 colors
[i
].green
= (i
* 0xffff) / (colors_per_channel
- 1);
1997 colors
[i
].blue
= (i
* 0xffff) / (colors_per_channel
- 1);;
1998 colors
[i
].flags
= DoRed
|DoGreen
|DoBlue
;
2000 if (! XAllocColor(basedisplay
.getXDisplay(), colormap
,
2002 fprintf(stderr
, i18n
->getMessage(ImageSet
, ImageColorAllocFail
,
2003 "couldn't alloc color %i %i %i\n"),
2004 colors
[i
].red
, colors
[i
].green
, colors
[i
].blue
);
2005 colors
[i
].flags
= 0;
2007 colors
[i
].flags
= DoRed
|DoGreen
|DoBlue
;
2010 basedisplay
.ungrab();
2012 XColor icolors
[256];
2013 int incolors
= (((1 << screen_depth
) > 256) ? 256 :
2014 (1 << screen_depth
));
2016 for (i
= 0; i
< incolors
; i
++)
2017 icolors
[i
].pixel
= i
;
2019 XQueryColors(basedisplay
.getXDisplay(), colormap
, icolors
, incolors
);
2020 for (i
= 0; i
< ncolors
; i
++) {
2021 if (! colors
[i
].flags
) {
2022 unsigned long chk
= 0xffffffff, pixel
, close
= 0;
2026 for (ii
= 0; ii
< incolors
; ii
++) {
2027 int r
= (colors
[i
].red
- icolors
[i
].red
) >> 8;
2028 int g
= (colors
[i
].green
- icolors
[i
].green
) >> 8;
2029 int b
= (colors
[i
].blue
- icolors
[i
].blue
) >> 8;
2030 pixel
= (r
* r
) + (g
* g
) + (b
* b
);
2037 colors
[i
].red
= icolors
[close
].red
;
2038 colors
[i
].green
= icolors
[close
].green
;
2039 colors
[i
].blue
= icolors
[close
].blue
;
2041 if (XAllocColor(basedisplay
.getXDisplay(), colormap
,
2043 colors
[i
].flags
= DoRed
|DoGreen
|DoBlue
;
2055 fprintf(stderr
, i18n
->getMessage(ImageSet
, ImageUnsupVisual
,
2056 "BImageControl::BImageControl: unsupported visual %d\n"),
2057 getVisual()->c_class
);
2063 BImageControl::~BImageControl(void) {
2065 delete [] sqrt_table
;
2069 delete [] grad_xbuffer
;
2073 delete [] grad_ybuffer
;
2077 unsigned long *pixels
= new unsigned long [ncolors
];
2080 for (i
= 0; i
< ncolors
; i
++)
2081 *(pixels
+ i
) = (*(colors
+ i
)).pixel
;
2083 XFreeColors(basedisplay
.getXDisplay(), colormap
, pixels
, ncolors
, 0);
2088 if (!cache
.empty()) {
2089 int i
, n
= cache
.size();
2090 fprintf(stderr
, i18n
->getMessage(ImageSet
, ImagePixmapRelease
,
2091 "BImageContol::~BImageControl: pixmap cache - "
2092 "releasing %d pixmaps\n"), n
);
2094 for (i
= 0; i
< n
; i
++) {
2095 Cache
*tmp
= cache
.front();
2096 XFreePixmap(basedisplay
.getXDisplay(), tmp
->pixmap
);
2106 #endif // TIMEDCACHE
2111 Pixmap
BImageControl::searchCache(unsigned int width
, unsigned int height
,
2112 unsigned long texture
,
2113 BColor
*c1
, BColor
*c2
) {
2114 if (!cache
.empty()) {
2116 CacheList::iterator it
;
2117 for (it
= cache
.begin(); it
!= cache
.end(); ++it
) {
2119 if ((tmp
->width
== width
) && (tmp
->height
== height
) &&
2120 (tmp
->texture
== texture
) && (tmp
->pixel1
== c1
->getPixel()))
2121 if (texture
& BImage_Gradient
) {
2122 if (tmp
->pixel2
== c2
->getPixel()) {
2137 Pixmap
BImageControl::renderImage(unsigned int width
, unsigned int height
,
2138 BTexture
*texture
) {
2139 if (texture
->getTexture() & BImage_ParentRelative
) return ParentRelative
;
2141 Pixmap pixmap
= searchCache(width
, height
, texture
->getTexture(),
2142 texture
->getColor(), texture
->getColorTo());
2143 if (pixmap
) return pixmap
;
2145 BImage
image(*this, width
, height
);
2146 pixmap
= image
.render(texture
);
2149 Cache
*tmp
= new Cache
;
2151 tmp
->pixmap
= pixmap
;
2153 tmp
->height
= height
;
2155 tmp
->texture
= texture
->getTexture();
2156 tmp
->pixel1
= texture
->getColor()->getPixel();
2158 if (texture
->getTexture() & BImage_Gradient
)
2159 tmp
->pixel2
= texture
->getColorTo()->getPixel();
2163 cache
.push_back(tmp
);
2165 if ((unsigned) cache
.size() > cache_max
) {
2167 fprintf(stderr
, i18n
->getMessage(ImageSet
, ImagePixmapCacheLarge
,
2168 "BImageControl::renderImage: cache is large, "
2169 "forcing cleanout\n"));
2182 void BImageControl::removeImage(Pixmap pixmap
) {
2184 CacheList::iterator it
;
2185 for (it
= cache
.begin(); it
!= cache
.end(); ++it
) {
2187 if (tmp
->pixmap
== pixmap
) {
2192 if (! timer
) timeout();
2193 #else // !TIMEDCACHE
2194 if (! tmp
->count
) timeout();
2195 #endif // TIMEDCACHE
2205 unsigned long BImageControl::getColor(const char *colorname
,
2206 unsigned char *r
, unsigned char *g
,
2212 if (! XParseColor(basedisplay
.getXDisplay(), colormap
, colorname
, &color
))
2213 fprintf(stderr
, "BImageControl::getColor: color parse error: \"%s\"\n",
2215 else if (! XAllocColor(basedisplay
.getXDisplay(), colormap
, &color
))
2216 fprintf(stderr
, "BImageControl::getColor: color alloc error: \"%s\"\n",
2219 if (color
.red
== 65535) *r
= 0xff;
2220 else *r
= (unsigned char) (color
.red
/ 0xff);
2221 if (color
.green
== 65535) *g
= 0xff;
2222 else *g
= (unsigned char) (color
.green
/ 0xff);
2223 if (color
.blue
== 65535) *b
= 0xff;
2224 else *b
= (unsigned char) (color
.blue
/ 0xff);
2230 unsigned long BImageControl::getColor(const char *colorname
) {
2234 if (! XParseColor(basedisplay
.getXDisplay(), colormap
, colorname
, &color
))
2235 fprintf(stderr
, "BImageControl::getColor: color parse error: \"%s\"\n",
2237 else if (! XAllocColor(basedisplay
.getXDisplay(), colormap
, &color
))
2238 fprintf(stderr
, "BImageControl::getColor: color alloc error: \"%s\"\n",
2245 void BImageControl::getColorTables(unsigned char **rmt
, unsigned char **gmt
,
2246 unsigned char **bmt
,
2247 int *roff
, int *goff
, int *boff
,
2248 int *rbit
, int *gbit
, int *bbit
) {
2249 if (rmt
) *rmt
= red_color_table
;
2250 if (gmt
) *gmt
= green_color_table
;
2251 if (bmt
) *bmt
= blue_color_table
;
2253 if (roff
) *roff
= red_offset
;
2254 if (goff
) *goff
= green_offset
;
2255 if (boff
) *boff
= blue_offset
;
2257 if (rbit
) *rbit
= red_bits
;
2258 if (gbit
) *gbit
= green_bits
;
2259 if (bbit
) *bbit
= blue_bits
;
2263 void BImageControl::getXColorTable(XColor
**c
, int *n
) {
2265 if (n
) *n
= ncolors
;
2269 void BImageControl::getGradientBuffers(unsigned int w
,
2271 unsigned int **xbuf
,
2272 unsigned int **ybuf
)
2274 if (w
> grad_buffer_width
) {
2276 delete [] grad_xbuffer
;
2279 grad_buffer_width
= w
;
2281 grad_xbuffer
= new unsigned int[grad_buffer_width
* 3];
2284 if (h
> grad_buffer_height
) {
2286 delete [] grad_ybuffer
;
2289 grad_buffer_height
= h
;
2291 grad_ybuffer
= new unsigned int[grad_buffer_height
* 3];
2294 *xbuf
= grad_xbuffer
;
2295 *ybuf
= grad_ybuffer
;
2299 void BImageControl::installRootColormap(void) {
2302 Bool install
= True
;
2303 int i
= 0, ncmap
= 0;
2305 XListInstalledColormaps(basedisplay
.getXDisplay(), window
, &ncmap
);
2308 for (i
= 0; i
< ncmap
; i
++)
2309 if (*(cmaps
+ i
) == colormap
)
2313 XInstallColormap(basedisplay
.getXDisplay(), colormap
);
2318 basedisplay
.ungrab();
2322 void BImageControl::setColorsPerChannel(int cpc
) {
2323 if (cpc
< 2) cpc
= 2;
2324 if (cpc
> 6) cpc
= 6;
2326 colors_per_channel
= cpc
;
2330 unsigned long BImageControl::getSqrt(unsigned int x
) {
2332 // build sqrt table for use with elliptic gradient
2334 sqrt_table
= new unsigned long[(256 * 256 * 2) + 1];
2337 for (; i
< (256 * 256 * 2); i
++)
2338 *(sqrt_table
+ i
) = bsqrt(i
);
2341 return (*(sqrt_table
+ x
));
2345 void BImageControl::parseTexture(BTexture
*texture
, const char *t
) {
2346 if ((! texture
) || (! t
)) return;
2348 int t_len
= strlen(t
) + 1, i
;
2349 char *ts
= new char[t_len
];
2352 // convert to lower case
2353 for (i
= 0; i
< t_len
; i
++)
2354 *(ts
+ i
) = tolower(*(t
+ i
));
2356 if (strstr(ts
, "parentrelative")) {
2357 texture
->setTexture(BImage_ParentRelative
);
2359 texture
->setTexture(0);
2361 if (strstr(ts
, "solid"))
2362 texture
->addTexture(BImage_Solid
);
2363 else if (strstr(ts
, "gradient")) {
2364 texture
->addTexture(BImage_Gradient
);
2365 if (strstr(ts
, "crossdiagonal"))
2366 texture
->addTexture(BImage_CrossDiagonal
);
2367 else if (strstr(ts
, "rectangle"))
2368 texture
->addTexture(BImage_Rectangle
);
2369 else if (strstr(ts
, "pyramid"))
2370 texture
->addTexture(BImage_Pyramid
);
2371 else if (strstr(ts
, "pipecross"))
2372 texture
->addTexture(BImage_PipeCross
);
2373 else if (strstr(ts
, "elliptic"))
2374 texture
->addTexture(BImage_Elliptic
);
2375 else if (strstr(ts
, "diagonal"))
2376 texture
->addTexture(BImage_Diagonal
);
2377 else if (strstr(ts
, "horizontal"))
2378 texture
->addTexture(BImage_Horizontal
);
2379 else if (strstr(ts
, "vertical"))
2380 texture
->addTexture(BImage_Vertical
);
2382 texture
->addTexture(BImage_Diagonal
);
2384 texture
->addTexture(BImage_Solid
);
2386 if (strstr(ts
, "raised"))
2387 texture
->addTexture(BImage_Raised
);
2388 else if (strstr(ts
, "sunken"))
2389 texture
->addTexture(BImage_Sunken
);
2390 else if (strstr(ts
, "flat"))
2391 texture
->addTexture(BImage_Flat
);
2393 texture
->addTexture(BImage_Raised
);
2395 if (! (texture
->getTexture() & BImage_Flat
))
2396 if (strstr(ts
, "bevel2"))
2397 texture
->addTexture(BImage_Bevel2
);
2399 texture
->addTexture(BImage_Bevel1
);
2402 if (strstr(ts
, "interlaced"))
2403 texture
->addTexture(BImage_Interlaced
);
2411 void BImageControl::parseColor(BColor
*color
, const char *c
) {
2412 if (! color
) return;
2414 if (color
->isAllocated()) {
2415 unsigned long pixel
= color
->getPixel();
2417 XFreeColors(basedisplay
.getXDisplay(), colormap
, &pixel
, 1, 0);
2419 color
->setPixel(0l);
2420 color
->setRGB(0, 0, 0);
2421 color
->setAllocated(False
);
2425 unsigned char r
, g
, b
;
2427 color
->setPixel(getColor(c
, &r
, &g
, &b
));
2428 color
->setRGB(r
, g
, b
);
2429 color
->setAllocated(True
);
2434 void BImageControl::timeout(void) {
2435 CacheList::iterator it
;
2436 for (it
= cache
.begin(); it
!= cache
.end(); ) {
2438 ++it
; // move on to the next item before this one is removed
2439 if (tmp
->count
<= 0) {
2440 XFreePixmap(basedisplay
.getXDisplay(), tmp
->pixmap
);