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
72 static unsigned long bsqrt(unsigned long x
) {
76 unsigned long r
= x
>> 1;
87 BImage::BImage(BImageControl
&c
, unsigned int w
, unsigned int h
) : control(c
) {
88 width
= ((signed) w
> 0) ? w
: 1;
89 height
= ((signed) h
> 0) ? h
: 1;
91 red
= new unsigned char[width
* height
];
92 green
= new unsigned char[width
* height
];
93 blue
= new unsigned char[width
* height
];
95 xtable
= ytable
= (unsigned int *) 0;
97 cpc
= control
.getColorsPerChannel();
100 control
.getColorTables(&red_table
, &green_table
, &blue_table
,
101 &red_offset
, &green_offset
, &blue_offset
,
102 &red_bits
, &green_bits
, &blue_bits
);
104 if (control
.getVisual()->c_class
!= TrueColor
)
105 control
.getXColorTable(&colors
, &ncolors
);
109 BImage::~BImage(void) {
110 if (red
) delete [] red
;
111 if (green
) delete [] green
;
112 if (blue
) delete [] blue
;
116 Pixmap
BImage::render(BTexture
*texture
) {
117 if (texture
->getTexture() & BImage_ParentRelative
)
118 return ParentRelative
;
119 else if (texture
->getTexture() & BImage_Solid
)
120 return render_solid(texture
);
121 else if (texture
->getTexture() & BImage_Gradient
)
122 return render_gradient(texture
);
128 Pixmap
BImage::render_solid(BTexture
*texture
) {
129 Pixmap pixmap
= XCreatePixmap(control
.getBaseDisplay().getXDisplay(),
130 control
.getDrawable(), width
,
131 height
, control
.getDepth());
132 if (pixmap
== None
) {
133 fprintf(stderr
, i18n
->getMessage(ImageSet
, ImageErrorCreatingSolidPixmap
,
134 "BImage::render_solid: error creating pixmap\n"));
141 gcv
.foreground
= texture
->getColor()->getPixel();
142 gcv
.fill_style
= FillSolid
;
143 gc
= XCreateGC(control
.getBaseDisplay().getXDisplay(), pixmap
,
144 GCForeground
| GCFillStyle
, &gcv
);
146 gcv
.foreground
= texture
->getHiColor()->getPixel();
147 hgc
= XCreateGC(control
.getBaseDisplay().getXDisplay(), pixmap
,
150 gcv
.foreground
= texture
->getLoColor()->getPixel();
151 lgc
= XCreateGC(control
.getBaseDisplay().getXDisplay(), pixmap
,
154 XFillRectangle(control
.getBaseDisplay().getXDisplay(), pixmap
, gc
, 0, 0,
158 if (texture
->getTexture() & BImage_Interlaced
) {
159 gcv
.foreground
= texture
->getColorTo()->getPixel();
160 GC igc
= XCreateGC(control
.getBaseDisplay().getXDisplay(), pixmap
,
163 register unsigned int i
= 0;
164 for (; i
< height
; i
+= 2)
165 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, igc
,
168 XFreeGC(control
.getBaseDisplay().getXDisplay(), igc
);
173 if (texture
->getTexture() & BImage_Bevel1
) {
174 if (texture
->getTexture() & BImage_Raised
) {
175 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, lgc
,
176 0, height
- 1, width
- 1, height
- 1);
177 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, lgc
,
178 width
- 1, height
- 1, width
- 1, 0);
180 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, hgc
,
182 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, hgc
,
183 0, height
- 1, 0, 0);
184 } else if (texture
->getTexture() & BImage_Sunken
) {
185 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, hgc
,
186 0, height
- 1, width
- 1, height
- 1);
187 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, hgc
,
188 width
- 1, height
- 1, width
- 1, 0);
190 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, lgc
,
192 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, lgc
,
193 0, height
- 1, 0, 0);
195 } else if (texture
->getTexture() & BImage_Bevel2
) {
196 if (texture
->getTexture() & BImage_Raised
) {
197 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, lgc
,
198 1, height
- 3, width
- 3, height
- 3);
199 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, lgc
,
200 width
- 3, height
- 3, width
- 3, 1);
202 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, hgc
,
204 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, hgc
,
205 1, height
- 3, 1, 1);
206 } else if (texture
->getTexture() & BImage_Sunken
) {
207 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, hgc
,
208 1, height
- 3, width
- 3, height
- 3);
209 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, hgc
,
210 width
- 3, height
- 3, width
- 3, 1);
212 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, lgc
,
214 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, lgc
,
215 1, height
- 3, 1, 1);
219 XFreeGC(control
.getBaseDisplay().getXDisplay(), gc
);
220 XFreeGC(control
.getBaseDisplay().getXDisplay(), hgc
);
221 XFreeGC(control
.getBaseDisplay().getXDisplay(), lgc
);
227 Pixmap
BImage::render_gradient(BTexture
*texture
) {
231 interlaced
= texture
->getTexture() & BImage_Interlaced
;
234 if (texture
->getTexture() & BImage_Sunken
) {
235 from
= texture
->getColorTo();
236 to
= texture
->getColor();
238 if (! (texture
->getTexture() & BImage_Invert
)) inverted
= 1;
240 from
= texture
->getColor();
241 to
= texture
->getColorTo();
243 if (texture
->getTexture() & BImage_Invert
) inverted
= 1;
246 control
.getGradientBuffers(width
, height
, &xtable
, &ytable
);
248 if (texture
->getTexture() & BImage_Diagonal
) dgradient();
249 else if (texture
->getTexture() & BImage_Elliptic
) egradient();
250 else if (texture
->getTexture() & BImage_Horizontal
) hgradient();
251 else if (texture
->getTexture() & BImage_Pyramid
) pgradient();
252 else if (texture
->getTexture() & BImage_Rectangle
) rgradient();
253 else if (texture
->getTexture() & BImage_Vertical
) vgradient();
254 else if (texture
->getTexture() & BImage_CrossDiagonal
) cdgradient();
255 else if (texture
->getTexture() & BImage_PipeCross
) pcgradient();
257 if (texture
->getTexture() & BImage_Bevel1
) bevel1();
258 else if (texture
->getTexture() & BImage_Bevel2
) bevel2();
260 if (inverted
) invert();
262 Pixmap pixmap
= renderPixmap();
269 XImage
*BImage::renderXImage(void) {
271 XCreateImage(control
.getBaseDisplay().getXDisplay(),
272 control
.getVisual(), control
.getDepth(), ZPixmap
, 0, 0,
273 width
, height
, 32, 0);
276 fprintf(stderr
, i18n
->getMessage(ImageSet
, ImageErrorCreatingXImage
,
277 "BImage::renderXImage: error creating XImage\n"));
282 image
->data
= (char *) 0;
284 unsigned char *d
= new unsigned char[image
->bytes_per_line
* (height
+ 1)];
285 register unsigned int x
, y
, dithx
, dithy
, r
, g
, b
, o
, er
, eg
, eb
, offset
;
287 unsigned char *pixel_data
= d
, *ppixel_data
= d
;
290 o
= image
->bits_per_pixel
+ ((image
->byte_order
== MSBFirst
) ? 1 : 0);
292 if (control
.doDither() && width
> 1 && height
> 1) {
293 unsigned char dither4
[4][4] = { {0, 4, 1, 5},
299 unsigned char dither8
[8][8] = { { 0, 32, 8, 40, 2, 34, 10, 42 },
300 { 48, 16, 56, 24, 50, 18, 58, 26 },
301 { 12, 44, 4, 36, 14, 46, 6, 38 },
302 { 60, 28, 52, 20, 62, 30, 54, 22 },
303 { 3, 35, 11, 43, 1, 33, 9, 41 },
304 { 51, 19, 59, 27, 49, 17, 57, 25 },
305 { 15, 47, 7, 39, 13, 45, 5, 37 },
306 { 63, 31, 55, 23, 61, 29, 53, 21 } };
307 #endif // ORDEREDPSEUDO
309 switch (control
.getVisual()->c_class
) {
311 // algorithm: ordered dithering... many many thanks to rasterman
312 // (raster@rasterman.com) for telling me about this... portions of this
313 // code is based off of his code in Imlib
314 for (y
= 0, offset
= 0; y
< height
; y
++) {
317 for (x
= 0; x
< width
; x
++, offset
++) {
323 er
= r
& (red_bits
- 1);
324 eg
= g
& (green_bits
- 1);
325 eb
= b
& (blue_bits
- 1);
331 if ((dither4
[dithy
][dithx
] < er
) && (r
< red_table
[255])) r
++;
332 if ((dither4
[dithy
][dithx
] < eg
) && (g
< green_table
[255])) g
++;
333 if ((dither4
[dithy
][dithx
] < eb
) && (b
< blue_table
[255])) b
++;
335 pixel
= (r
<< red_offset
) | (g
<< green_offset
) | (b
<< blue_offset
);
339 *pixel_data
++ = pixel
;
342 case 16: // 16bpp LSB
343 *pixel_data
++ = pixel
;
344 *pixel_data
++ = pixel
>> 8;
347 case 17: // 16bpp MSB
348 *pixel_data
++ = pixel
>> 8;
349 *pixel_data
++ = pixel
;
352 case 24: // 24bpp LSB
353 *pixel_data
++ = pixel
;
354 *pixel_data
++ = pixel
>> 8;
355 *pixel_data
++ = pixel
>> 16;
358 case 25: // 24bpp MSB
359 *pixel_data
++ = pixel
>> 16;
360 *pixel_data
++ = pixel
>> 8;
361 *pixel_data
++ = pixel
;
364 case 32: // 32bpp LSB
365 *pixel_data
++ = pixel
;
366 *pixel_data
++ = pixel
>> 8;
367 *pixel_data
++ = pixel
>> 16;
368 *pixel_data
++ = pixel
>> 24;
371 case 33: // 32bpp MSB
372 *pixel_data
++ = pixel
>> 24;
373 *pixel_data
++ = pixel
>> 16;
374 *pixel_data
++ = pixel
>> 8;
375 *pixel_data
++ = pixel
;
380 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
387 #ifndef ORDEREDPSEUDO
389 *rerr
= new short[width
+ 2],
390 *gerr
= new short[width
+ 2],
391 *berr
= new short[width
+ 2],
392 *nrerr
= new short[width
+ 2],
393 *ngerr
= new short[width
+ 2],
394 *nberr
= new short[width
+ 2];
395 int rr
, gg
, bb
, rer
, ger
, ber
;
396 int dd
= 255 / control
.getColorsPerChannel();
398 for (x
= 0; x
< width
; x
++) {
399 *(rerr
+ x
) = *(red
+ x
);
400 *(gerr
+ x
) = *(green
+ x
);
401 *(berr
+ x
) = *(blue
+ x
);
404 *(rerr
+ x
) = *(gerr
+ x
) = *(berr
+ x
) = 0;
405 #endif // ORDEREDPSEUDO
407 for (y
= 0, offset
= 0; y
< height
; y
++) {
411 for (x
= 0; x
< width
; x
++, offset
++) {
418 er
= r
& (red_bits
- 1);
419 eg
= g
& (green_bits
- 1);
420 eb
= b
& (blue_bits
- 1);
426 if ((dither8
[dithy
][dithx
] < er
) && (r
< red_table
[255])) r
++;
427 if ((dither8
[dithy
][dithx
] < eg
) && (g
< green_table
[255])) g
++;
428 if ((dither8
[dithy
][dithx
] < eb
) && (b
< blue_table
[255])) b
++;
430 pixel
= (r
* cpccpc
) + (g
* cpc
) + b
;
431 *(pixel_data
++) = colors
[pixel
].pixel
;
434 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
436 #else // !ORDEREDPSEUDO
437 if (y
< (height
- 1)) {
438 int i
= offset
+ width
;
439 for (x
= 0; x
< width
; x
++, i
++) {
440 *(nrerr
+ x
) = *(red
+ i
);
441 *(ngerr
+ x
) = *(green
+ i
);
442 *(nberr
+ x
) = *(blue
+ i
);
445 *(nrerr
+ x
) = *(red
+ (--i
));
446 *(ngerr
+ x
) = *(green
+ i
);
447 *(nberr
+ x
) = *(blue
+ i
);
450 for (x
= 0; x
< width
; x
++) {
455 if (rr
> 255) rr
= 255; else if (rr
< 0) rr
= 0;
456 if (gg
> 255) gg
= 255; else if (gg
< 0) gg
= 0;
457 if (bb
> 255) bb
= 255; else if (bb
< 0) bb
= 0;
463 rer
= rerr
[x
] - r
*dd
;
464 ger
= gerr
[x
] - g
*dd
;
465 ber
= berr
[x
] - b
*dd
;
467 pixel
= (r
* cpccpc
) + (g
* cpc
) + b
;
468 *pixel_data
++ = colors
[pixel
].pixel
;
483 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
504 #endif // ORDEREDPSUEDO
509 fprintf(stderr
, i18n
->getMessage(ImageSet
, ImageUnsupVisual
,
510 "BImage::renderXImage: unsupported visual\n"));
512 XDestroyImage(image
);
516 switch (control
.getVisual()->c_class
) {
519 for (y
= 0, offset
= 0; y
< height
; y
++) {
520 for (x
= 0; x
< width
; x
++, offset
++) {
521 r
= red_table
[red
[offset
]];
522 g
= green_table
[green
[offset
]];
523 b
= blue_table
[blue
[offset
]];
525 pixel
= (r
* cpccpc
) + (g
* cpc
) + b
;
526 *pixel_data
++ = colors
[pixel
].pixel
;
529 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
535 for (y
= 0, offset
= 0; y
< height
; y
++) {
536 for (x
= 0; x
< width
; x
++, offset
++) {
537 r
= red_table
[red
[offset
]];
538 g
= green_table
[green
[offset
]];
539 b
= blue_table
[blue
[offset
]];
541 pixel
= (r
<< red_offset
) | (g
<< green_offset
) | (b
<< blue_offset
);
545 *pixel_data
++ = pixel
;
548 case 16: // 16bpp LSB
549 *pixel_data
++ = pixel
;
550 *pixel_data
++ = pixel
>> 8;
553 case 17: // 16bpp MSB
554 *pixel_data
++ = pixel
>> 8;
555 *pixel_data
++ = pixel
;
558 case 24: // 24bpp LSB
559 *pixel_data
++ = pixel
;
560 *pixel_data
++ = pixel
>> 8;
561 *pixel_data
++ = pixel
>> 16;
564 case 25: // 24bpp MSB
565 *pixel_data
++ = pixel
>> 16;
566 *pixel_data
++ = pixel
>> 8;
567 *pixel_data
++ = pixel
;
570 case 32: // 32bpp LSB
571 *pixel_data
++ = pixel
;
572 *pixel_data
++ = pixel
>> 8;
573 *pixel_data
++ = pixel
>> 16;
574 *pixel_data
++ = pixel
>> 24;
577 case 33: // 32bpp MSB
578 *pixel_data
++ = pixel
>> 24;
579 *pixel_data
++ = pixel
>> 16;
580 *pixel_data
++ = pixel
>> 8;
581 *pixel_data
++ = pixel
;
586 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
593 for (y
= 0, offset
= 0; y
< height
; y
++) {
594 for (x
= 0; x
< width
; x
++, offset
++) {
595 r
= *(red_table
+ *(red
+ offset
));
596 g
= *(green_table
+ *(green
+ offset
));
597 b
= *(blue_table
+ *(blue
+ offset
));
599 g
= ((r
* 30) + (g
* 59) + (b
* 11)) / 100;
600 *pixel_data
++ = colors
[g
].pixel
;
603 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
609 fprintf(stderr
, i18n
->getMessage(ImageSet
, ImageUnsupVisual
,
610 "BImage::renderXImage: unsupported visual\n"));
612 XDestroyImage(image
);
617 image
->data
= (char *) d
;
622 Pixmap
BImage::renderPixmap(void) {
624 XCreatePixmap(control
.getBaseDisplay().getXDisplay(),
625 control
.getDrawable(), width
, height
, control
.getDepth());
627 if (pixmap
== None
) {
628 fprintf(stderr
, i18n
->getMessage(ImageSet
, ImageErrorCreatingPixmap
,
629 "BImage::renderPixmap: error creating pixmap\n"));
633 XImage
*image
= renderXImage();
636 XFreePixmap(control
.getBaseDisplay().getXDisplay(), pixmap
);
638 } else if (! image
->data
) {
639 XDestroyImage(image
);
640 XFreePixmap(control
.getBaseDisplay().getXDisplay(), pixmap
);
644 XPutImage(control
.getBaseDisplay().getXDisplay(), pixmap
,
645 DefaultGC(control
.getBaseDisplay().getXDisplay(),
646 control
.getScreenInfo().getScreenNumber()),
647 image
, 0, 0, 0, 0, width
, height
);
650 delete [] image
->data
;
654 XDestroyImage(image
);
660 void BImage::bevel1(void) {
661 if (width
> 2 && height
> 2) {
662 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
664 register unsigned char r
, g
, b
, rr
,gg
,bb
;
665 register unsigned int w
= width
, h
= height
- 1, wh
= w
* h
;
683 rr
= (r
>> 2) + (r
>> 1);
686 gg
= (g
>> 2) + (g
>> 1);
689 bb
= (b
>> 2) + (b
>> 1);
712 rr
= (r
>> 2) + (r
>> 1);
715 gg
= (g
>> 2) + (g
>> 1);
718 bb
= (b
>> 2) + (b
>> 1);
749 rr
= (r
>> 2) + (r
>> 1);
752 gg
= (g
>> 2) + (g
>> 1);
755 bb
= (b
>> 2) + (b
>> 1);
782 rr
= (r
>> 2) + (r
>> 1);
785 gg
= (g
>> 2) + (g
>> 1);
788 bb
= (b
>> 2) + (b
>> 1);
798 void BImage::bevel2(void) {
799 if (width
> 4 && height
> 4) {
800 unsigned char r
, g
, b
, rr
,gg
,bb
, *pr
= red
+ width
+ 1,
801 *pg
= green
+ width
+ 1, *pb
= blue
+ width
+ 1;
802 unsigned int w
= width
- 2, h
= height
- 1, wh
= width
* (height
- 3);
820 rr
= (r
>> 2) + (r
>> 1);
823 gg
= (g
>> 2) + (g
>> 1);
826 bb
= (b
>> 2) + (b
>> 1);
858 rr
= (r
>> 2) + (r
>> 1);
861 gg
= (g
>> 2) + (g
>> 1);
864 bb
= (b
>> 2) + (b
>> 1);
877 void BImage::invert(void) {
878 register unsigned int i
, j
, wh
= (width
* height
) - 1;
881 for (i
= 0, j
= wh
; j
> i
; j
--, i
++) {
883 *(red
+ j
) = *(red
+ i
);
887 *(green
+ j
) = *(green
+ i
);
891 *(blue
+ j
) = *(blue
+ i
);
897 void BImage::dgradient(void) {
898 // diagonal gradient code was written by Mike Cole <mike@mydot.com>
899 // modified for interlacing by Brad Hughes
901 float drx
, dgx
, dbx
, dry
, dgy
, dby
, yr
= 0.0, yg
= 0.0, yb
= 0.0,
902 xr
= (float) from
->getRed(),
903 xg
= (float) from
->getGreen(),
904 xb
= (float) from
->getBlue();
905 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
906 unsigned int w
= width
* 2, h
= height
* 2, *xt
= xtable
, *yt
= ytable
;
908 register unsigned int x
, y
;
910 dry
= drx
= (float) (to
->getRed() - from
->getRed());
911 dgy
= dgx
= (float) (to
->getGreen() - from
->getGreen());
912 dby
= dbx
= (float) (to
->getBlue() - from
->getBlue());
919 for (x
= 0; x
< width
; x
++) {
920 *(xt
++) = (unsigned char) (xr
);
921 *(xt
++) = (unsigned char) (xg
);
922 *(xt
++) = (unsigned char) (xb
);
934 for (y
= 0; y
< height
; y
++) {
935 *(yt
++) = ((unsigned char) yr
);
936 *(yt
++) = ((unsigned char) yg
);
937 *(yt
++) = ((unsigned char) yb
);
944 // Combine tables to create gradient
951 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
952 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
953 *(pr
++) = *(xt
++) + *(yt
);
954 *(pg
++) = *(xt
++) + *(yt
+ 1);
955 *(pb
++) = *(xt
++) + *(yt
+ 2);
961 // faked interlacing effect
962 unsigned char channel
, channel2
;
964 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
965 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
967 channel
= *(xt
++) + *(yt
);
968 channel2
= (channel
>> 1) + (channel
>> 2);
969 if (channel2
> channel
) channel2
= 0;
972 channel
= *(xt
++) + *(yt
+ 1);
973 channel2
= (channel
>> 1) + (channel
>> 2);
974 if (channel2
> channel
) channel2
= 0;
977 channel
= *(xt
++) + *(yt
+ 2);
978 channel2
= (channel
>> 1) + (channel
>> 2);
979 if (channel2
> channel
) channel2
= 0;
982 channel
= *(xt
++) + *(yt
);
983 channel2
= channel
+ (channel
>> 3);
984 if (channel2
< channel
) channel2
= ~0;
987 channel
= *(xt
++) + *(yt
+ 1);
988 channel2
= channel
+ (channel
>> 3);
989 if (channel2
< channel
) channel2
= ~0;
992 channel
= *(xt
++) + *(yt
+ 2);
993 channel2
= channel
+ (channel
>> 3);
994 if (channel2
< channel
) channel2
= ~0;
1005 void BImage::hgradient(void) {
1006 float drx
, dgx
, dbx
,
1007 xr
= (float) from
->getRed(),
1008 xg
= (float) from
->getGreen(),
1009 xb
= (float) from
->getBlue();
1010 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1012 register unsigned int x
, y
;
1014 drx
= (float) (to
->getRed() - from
->getRed());
1015 dgx
= (float) (to
->getGreen() - from
->getGreen());
1016 dbx
= (float) (to
->getBlue() - from
->getBlue());
1023 if (interlaced
&& height
> 2) {
1024 // faked interlacing effect
1025 unsigned char channel
, channel2
;
1027 for (x
= 0; x
< width
; x
++, pr
++, pg
++, pb
++) {
1028 channel
= (unsigned char) xr
;
1029 channel2
= (channel
>> 1) + (channel
>> 2);
1030 if (channel2
> channel
) channel2
= 0;
1033 channel
= (unsigned char) xg
;
1034 channel2
= (channel
>> 1) + (channel
>> 2);
1035 if (channel2
> channel
) channel2
= 0;
1038 channel
= (unsigned char) xb
;
1039 channel2
= (channel
>> 1) + (channel
>> 2);
1040 if (channel2
> channel
) channel2
= 0;
1044 channel
= (unsigned char) xr
;
1045 channel2
= channel
+ (channel
>> 3);
1046 if (channel2
< channel
) channel2
= ~0;
1047 *(pr
+ width
) = channel2
;
1049 channel
= (unsigned char) xg
;
1050 channel2
= channel
+ (channel
>> 3);
1051 if (channel2
< channel
) channel2
= ~0;
1052 *(pg
+ width
) = channel2
;
1054 channel
= (unsigned char) xb
;
1055 channel2
= channel
+ (channel
>> 3);
1056 if (channel2
< channel
) channel2
= ~0;
1057 *(pb
+ width
) = channel2
;
1070 for (y
= 2; y
< height
; y
++, pr
+= width
, pg
+= width
, pb
+= width
) {
1071 if (y
& 1) offset
= width
; else offset
= 0;
1073 memcpy(pr
, (red
+ offset
), width
);
1074 memcpy(pg
, (green
+ offset
), width
);
1075 memcpy(pb
, (blue
+ offset
), width
);
1081 for (x
= 0; x
< width
; x
++) {
1082 *(pr
++) = (unsigned char) (xr
);
1083 *(pg
++) = (unsigned char) (xg
);
1084 *(pb
++) = (unsigned char) (xb
);
1091 for (y
= 1; y
< height
; y
++, pr
+= width
, pg
+= width
, pb
+= width
) {
1092 memcpy(pr
, red
, width
);
1093 memcpy(pg
, green
, width
);
1094 memcpy(pb
, blue
, width
);
1104 void BImage::vgradient(void) {
1105 float dry
, dgy
, dby
,
1106 yr
= (float) from
->getRed(),
1107 yg
= (float) from
->getGreen(),
1108 yb
= (float) from
->getBlue();
1109 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1111 register unsigned int y
;
1113 dry
= (float) (to
->getRed() - from
->getRed());
1114 dgy
= (float) (to
->getGreen() - from
->getGreen());
1115 dby
= (float) (to
->getBlue() - from
->getBlue());
1123 // faked interlacing effect
1124 unsigned char channel
, channel2
;
1126 for (y
= 0; y
< height
; y
++, pr
+= width
, pg
+= width
, pb
+= width
) {
1128 channel
= (unsigned char) yr
;
1129 channel2
= (channel
>> 1) + (channel
>> 2);
1130 if (channel2
> channel
) channel2
= 0;
1131 memset(pr
, channel2
, width
);
1133 channel
= (unsigned char) yg
;
1134 channel2
= (channel
>> 1) + (channel
>> 2);
1135 if (channel2
> channel
) channel2
= 0;
1136 memset(pg
, channel2
, width
);
1138 channel
= (unsigned char) yb
;
1139 channel2
= (channel
>> 1) + (channel
>> 2);
1140 if (channel2
> channel
) channel2
= 0;
1141 memset(pb
, channel2
, width
);
1143 channel
= (unsigned char) yr
;
1144 channel2
= channel
+ (channel
>> 3);
1145 if (channel2
< channel
) channel2
= ~0;
1146 memset(pr
, channel2
, width
);
1148 channel
= (unsigned char) yg
;
1149 channel2
= channel
+ (channel
>> 3);
1150 if (channel2
< channel
) channel2
= ~0;
1151 memset(pg
, channel2
, width
);
1153 channel
= (unsigned char) yb
;
1154 channel2
= channel
+ (channel
>> 3);
1155 if (channel2
< channel
) channel2
= ~0;
1156 memset(pb
, channel2
, width
);
1167 for (y
= 0; y
< height
; y
++, pr
+= width
, pg
+= width
, pb
+= width
) {
1168 memset(pr
, (unsigned char) yr
, width
);
1169 memset(pg
, (unsigned char) yg
, width
);
1170 memset(pb
, (unsigned char) yb
, width
);
1184 void BImage::pgradient(void) {
1185 // pyramid gradient - based on original dgradient, written by
1186 // Mosfet (mosfet@kde.org)
1187 // adapted from kde sources for Openbox by Brad Hughes
1189 float yr
, yg
, yb
, drx
, dgx
, dbx
, dry
, dgy
, dby
,
1191 int rsign
, gsign
, bsign
;
1192 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1193 unsigned int tr
= to
->getRed(), tg
= to
->getGreen(), tb
= to
->getBlue(),
1194 *xt
= xtable
, *yt
= ytable
;
1196 register unsigned int x
, y
;
1198 dry
= drx
= (float) (to
->getRed() - from
->getRed());
1199 dgy
= dgx
= (float) (to
->getGreen() - from
->getGreen());
1200 dby
= dbx
= (float) (to
->getBlue() - from
->getBlue());
1202 rsign
= (drx
< 0) ? -1 : 1;
1203 gsign
= (dgx
< 0) ? -1 : 1;
1204 bsign
= (dbx
< 0) ? -1 : 1;
1206 xr
= yr
= (drx
/ 2);
1207 xg
= yg
= (dgx
/ 2);
1208 xb
= yb
= (dbx
/ 2);
1215 for (x
= 0; x
< width
; x
++) {
1216 *(xt
++) = (unsigned char) ((xr
< 0) ? -xr
: xr
);
1217 *(xt
++) = (unsigned char) ((xg
< 0) ? -xg
: xg
);
1218 *(xt
++) = (unsigned char) ((xb
< 0) ? -xb
: xb
);
1230 for (y
= 0; y
< height
; y
++) {
1231 *(yt
++) = ((unsigned char) ((yr
< 0) ? -yr
: yr
));
1232 *(yt
++) = ((unsigned char) ((yg
< 0) ? -yg
: yg
));
1233 *(yt
++) = ((unsigned char) ((yb
< 0) ? -yb
: yb
));
1240 // Combine tables to create gradient
1247 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1248 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1249 *(pr
++) = (unsigned char) (tr
- (rsign
* (*(xt
++) + *(yt
))));
1250 *(pg
++) = (unsigned char) (tg
- (gsign
* (*(xt
++) + *(yt
+ 1))));
1251 *(pb
++) = (unsigned char) (tb
- (bsign
* (*(xt
++) + *(yt
+ 2))));
1257 // faked interlacing effect
1258 unsigned char channel
, channel2
;
1260 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1261 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1263 channel
= (unsigned char) (tr
- (rsign
* (*(xt
++) + *(yt
))));
1264 channel2
= (channel
>> 1) + (channel
>> 2);
1265 if (channel2
> channel
) channel2
= 0;
1268 channel
= (unsigned char) (tg
- (gsign
* (*(xt
++) + *(yt
+ 1))));
1269 channel2
= (channel
>> 1) + (channel
>> 2);
1270 if (channel2
> channel
) channel2
= 0;
1273 channel
= (unsigned char) (tb
- (bsign
* (*(xt
++) + *(yt
+ 2))));
1274 channel2
= (channel
>> 1) + (channel
>> 2);
1275 if (channel2
> channel
) channel2
= 0;
1278 channel
= (unsigned char) (tr
- (rsign
* (*(xt
++) + *(yt
))));
1279 channel2
= channel
+ (channel
>> 3);
1280 if (channel2
< channel
) channel2
= ~0;
1283 channel
= (unsigned char) (tg
- (gsign
* (*(xt
++) + *(yt
+ 1))));
1284 channel2
= channel
+ (channel
>> 3);
1285 if (channel2
< channel
) channel2
= ~0;
1288 channel
= (unsigned char) (tb
- (bsign
* (*(xt
++) + *(yt
+ 2))));
1289 channel2
= channel
+ (channel
>> 3);
1290 if (channel2
< channel
) channel2
= ~0;
1300 void BImage::rgradient(void) {
1301 // rectangle gradient - based on original dgradient, written by
1302 // Mosfet (mosfet@kde.org)
1303 // adapted from kde sources for Openbox by Brad Hughes
1305 float drx
, dgx
, dbx
, dry
, dgy
, dby
, xr
, xg
, xb
, yr
, yg
, yb
;
1306 int rsign
, gsign
, bsign
;
1307 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1308 unsigned int tr
= to
->getRed(), tg
= to
->getGreen(), tb
= to
->getBlue(),
1309 *xt
= xtable
, *yt
= ytable
;
1311 register unsigned int x
, y
;
1313 dry
= drx
= (float) (to
->getRed() - from
->getRed());
1314 dgy
= dgx
= (float) (to
->getGreen() - from
->getGreen());
1315 dby
= dbx
= (float) (to
->getBlue() - from
->getBlue());
1317 rsign
= (drx
< 0) ? -2 : 2;
1318 gsign
= (dgx
< 0) ? -2 : 2;
1319 bsign
= (dbx
< 0) ? -2 : 2;
1321 xr
= yr
= (drx
/ 2);
1322 xg
= yg
= (dgx
/ 2);
1323 xb
= yb
= (dbx
/ 2);
1330 for (x
= 0; x
< width
; x
++) {
1331 *(xt
++) = (unsigned char) ((xr
< 0) ? -xr
: xr
);
1332 *(xt
++) = (unsigned char) ((xg
< 0) ? -xg
: xg
);
1333 *(xt
++) = (unsigned char) ((xb
< 0) ? -xb
: xb
);
1345 for (y
= 0; y
< height
; y
++) {
1346 *(yt
++) = ((unsigned char) ((yr
< 0) ? -yr
: yr
));
1347 *(yt
++) = ((unsigned char) ((yg
< 0) ? -yg
: yg
));
1348 *(yt
++) = ((unsigned char) ((yb
< 0) ? -yb
: yb
));
1355 // Combine tables to create gradient
1362 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1363 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1364 *(pr
++) = (unsigned char) (tr
- (rsign
* max(*(xt
++), *(yt
))));
1365 *(pg
++) = (unsigned char) (tg
- (gsign
* max(*(xt
++), *(yt
+ 1))));
1366 *(pb
++) = (unsigned char) (tb
- (bsign
* max(*(xt
++), *(yt
+ 2))));
1372 // faked interlacing effect
1373 unsigned char channel
, channel2
;
1375 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1376 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1378 channel
= (unsigned char) (tr
- (rsign
* max(*(xt
++), *(yt
))));
1379 channel2
= (channel
>> 1) + (channel
>> 2);
1380 if (channel2
> channel
) channel2
= 0;
1383 channel
= (unsigned char) (tg
- (gsign
* max(*(xt
++), *(yt
+ 1))));
1384 channel2
= (channel
>> 1) + (channel
>> 2);
1385 if (channel2
> channel
) channel2
= 0;
1388 channel
= (unsigned char) (tb
- (bsign
* max(*(xt
++), *(yt
+ 2))));
1389 channel2
= (channel
>> 1) + (channel
>> 2);
1390 if (channel2
> channel
) channel2
= 0;
1393 channel
= (unsigned char) (tr
- (rsign
* max(*(xt
++), *(yt
))));
1394 channel2
= channel
+ (channel
>> 3);
1395 if (channel2
< channel
) channel2
= ~0;
1398 channel
= (unsigned char) (tg
- (gsign
* max(*(xt
++), *(yt
+ 1))));
1399 channel2
= channel
+ (channel
>> 3);
1400 if (channel2
< channel
) channel2
= ~0;
1403 channel
= (unsigned char) (tb
- (bsign
* max(*(xt
++), *(yt
+ 2))));
1404 channel2
= channel
+ (channel
>> 3);
1405 if (channel2
< channel
) channel2
= ~0;
1415 void BImage::egradient(void) {
1416 // elliptic gradient - based on original dgradient, written by
1417 // Mosfet (mosfet@kde.org)
1418 // adapted from kde sources for Openbox by Brad Hughes
1420 float drx
, dgx
, dbx
, dry
, dgy
, dby
, yr
, yg
, yb
, xr
, xg
, xb
;
1421 int rsign
, gsign
, bsign
;
1422 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1423 unsigned int *xt
= xtable
, *yt
= ytable
,
1424 tr
= (unsigned long) to
->getRed(),
1425 tg
= (unsigned long) to
->getGreen(),
1426 tb
= (unsigned long) to
->getBlue();
1428 register unsigned int x
, y
;
1430 dry
= drx
= (float) (to
->getRed() - from
->getRed());
1431 dgy
= dgx
= (float) (to
->getGreen() - from
->getGreen());
1432 dby
= dbx
= (float) (to
->getBlue() - from
->getBlue());
1434 rsign
= (drx
< 0) ? -1 : 1;
1435 gsign
= (dgx
< 0) ? -1 : 1;
1436 bsign
= (dbx
< 0) ? -1 : 1;
1438 xr
= yr
= (drx
/ 2);
1439 xg
= yg
= (dgx
/ 2);
1440 xb
= yb
= (dbx
/ 2);
1447 for (x
= 0; x
< width
; x
++) {
1448 *(xt
++) = (unsigned long) (xr
* xr
);
1449 *(xt
++) = (unsigned long) (xg
* xg
);
1450 *(xt
++) = (unsigned long) (xb
* xb
);
1462 for (y
= 0; y
< height
; y
++) {
1463 *(yt
++) = (unsigned long) (yr
* yr
);
1464 *(yt
++) = (unsigned long) (yg
* yg
);
1465 *(yt
++) = (unsigned long) (yb
* yb
);
1472 // Combine tables to create gradient
1479 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1480 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1481 *(pr
++) = (unsigned char)
1482 (tr
- (rsign
* control
.getSqrt(*(xt
++) + *(yt
))));
1483 *(pg
++) = (unsigned char)
1484 (tg
- (gsign
* control
.getSqrt(*(xt
++) + *(yt
+ 1))));
1485 *(pb
++) = (unsigned char)
1486 (tb
- (bsign
* control
.getSqrt(*(xt
++) + *(yt
+ 2))));
1492 // faked interlacing effect
1493 unsigned char channel
, channel2
;
1495 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1496 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1498 channel
= (unsigned char)
1499 (tr
- (rsign
* control
.getSqrt(*(xt
++) + *(yt
))));
1500 channel2
= (channel
>> 1) + (channel
>> 2);
1501 if (channel2
> channel
) channel2
= 0;
1504 channel
= (unsigned char)
1505 (tg
- (gsign
* control
.getSqrt(*(xt
++) + *(yt
+ 1))));
1506 channel2
= (channel
>> 1) + (channel
>> 2);
1507 if (channel2
> channel
) channel2
= 0;
1510 channel
= (unsigned char)
1511 (tb
- (bsign
* control
.getSqrt(*(xt
++) + *(yt
+ 2))));
1512 channel2
= (channel
>> 1) + (channel
>> 2);
1513 if (channel2
> channel
) channel2
= 0;
1516 channel
= (unsigned char)
1517 (tr
- (rsign
* control
.getSqrt(*(xt
++) + *(yt
))));
1518 channel2
= channel
+ (channel
>> 3);
1519 if (channel2
< channel
) channel2
= ~0;
1522 channel
= (unsigned char)
1523 (tg
- (gsign
* control
.getSqrt(*(xt
++) + *(yt
+ 1))));
1524 channel2
= channel
+ (channel
>> 3);
1525 if (channel2
< channel
) channel2
= ~0;
1528 channel
= (unsigned char)
1529 (tb
- (bsign
* control
.getSqrt(*(xt
++) + *(yt
+ 2))));
1530 channel2
= channel
+ (channel
>> 3);
1531 if (channel2
< channel
) channel2
= ~0;
1541 void BImage::pcgradient(void) {
1542 // pipe cross gradient - based on original dgradient, written by
1543 // Mosfet (mosfet@kde.org)
1544 // adapted from kde sources for Openbox by Brad Hughes
1546 float drx
, dgx
, dbx
, dry
, dgy
, dby
, xr
, xg
, xb
, yr
, yg
, yb
;
1547 int rsign
, gsign
, bsign
;
1548 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1549 unsigned int *xt
= xtable
, *yt
= ytable
,
1551 tg
= to
->getGreen(),
1554 register unsigned int x
, y
;
1556 dry
= drx
= (float) (to
->getRed() - from
->getRed());
1557 dgy
= dgx
= (float) (to
->getGreen() - from
->getGreen());
1558 dby
= dbx
= (float) (to
->getBlue() - from
->getBlue());
1560 rsign
= (drx
< 0) ? -2 : 2;
1561 gsign
= (dgx
< 0) ? -2 : 2;
1562 bsign
= (dbx
< 0) ? -2 : 2;
1564 xr
= yr
= (drx
/ 2);
1565 xg
= yg
= (dgx
/ 2);
1566 xb
= yb
= (dbx
/ 2);
1573 for (x
= 0; x
< width
; x
++) {
1574 *(xt
++) = (unsigned char) ((xr
< 0) ? -xr
: xr
);
1575 *(xt
++) = (unsigned char) ((xg
< 0) ? -xg
: xg
);
1576 *(xt
++) = (unsigned char) ((xb
< 0) ? -xb
: xb
);
1588 for (y
= 0; y
< height
; y
++) {
1589 *(yt
++) = ((unsigned char) ((yr
< 0) ? -yr
: yr
));
1590 *(yt
++) = ((unsigned char) ((yg
< 0) ? -yg
: yg
));
1591 *(yt
++) = ((unsigned char) ((yb
< 0) ? -yb
: yb
));
1598 // Combine tables to create gradient
1604 // normal pcgradient
1605 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1606 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1607 *(pr
++) = (unsigned char) (tr
- (rsign
* min(*(xt
++), *(yt
))));
1608 *(pg
++) = (unsigned char) (tg
- (gsign
* min(*(xt
++), *(yt
+ 1))));
1609 *(pb
++) = (unsigned char) (tb
- (bsign
* min(*(xt
++), *(yt
+ 2))));
1615 // faked interlacing effect
1616 unsigned char channel
, channel2
;
1618 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1619 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1621 channel
= (unsigned char) (tr
- (rsign
* min(*(xt
++), *(yt
))));
1622 channel2
= (channel
>> 1) + (channel
>> 2);
1623 if (channel2
> channel
) channel2
= 0;
1626 channel
= (unsigned char) (tg
- (bsign
* min(*(xt
++), *(yt
+ 1))));
1627 channel2
= (channel
>> 1) + (channel
>> 2);
1628 if (channel2
> channel
) channel2
= 0;
1631 channel
= (unsigned char) (tb
- (gsign
* min(*(xt
++), *(yt
+ 2))));
1632 channel2
= (channel
>> 1) + (channel
>> 2);
1633 if (channel2
> channel
) channel2
= 0;
1636 channel
= (unsigned char) (tr
- (rsign
* min(*(xt
++), *(yt
))));
1637 channel2
= channel
+ (channel
>> 3);
1638 if (channel2
< channel
) channel2
= ~0;
1641 channel
= (unsigned char) (tg
- (gsign
* min(*(xt
++), *(yt
+ 1))));
1642 channel2
= channel
+ (channel
>> 3);
1643 if (channel2
< channel
) channel2
= ~0;
1646 channel
= (unsigned char) (tb
- (bsign
* min(*(xt
++), *(yt
+ 2))));
1647 channel2
= channel
+ (channel
>> 3);
1648 if (channel2
< channel
) channel2
= ~0;
1658 void BImage::cdgradient(void) {
1659 // cross diagonal gradient - based on original dgradient, written by
1660 // Mosfet (mosfet@kde.org)
1661 // adapted from kde sources for Openbox by Brad Hughes
1663 float drx
, dgx
, dbx
, dry
, dgy
, dby
, yr
= 0.0, yg
= 0.0, yb
= 0.0,
1664 xr
= (float) from
->getRed(),
1665 xg
= (float) from
->getGreen(),
1666 xb
= (float) from
->getBlue();
1667 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1668 unsigned int w
= width
* 2, h
= height
* 2, *xt
, *yt
;
1670 register unsigned int x
, y
;
1672 dry
= drx
= (float) (to
->getRed() - from
->getRed());
1673 dgy
= dgx
= (float) (to
->getGreen() - from
->getGreen());
1674 dby
= dbx
= (float) (to
->getBlue() - from
->getBlue());
1681 for (xt
= (xtable
+ (width
* 3) - 1), x
= 0; x
< width
; x
++) {
1682 *(xt
--) = (unsigned char) xb
;
1683 *(xt
--) = (unsigned char) xg
;
1684 *(xt
--) = (unsigned char) xr
;
1696 for (yt
= ytable
, y
= 0; y
< height
; y
++) {
1697 *(yt
++) = (unsigned char) yr
;
1698 *(yt
++) = (unsigned char) yg
;
1699 *(yt
++) = (unsigned char) yb
;
1706 // Combine tables to create gradient
1712 // normal cdgradient
1713 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1714 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1715 *(pr
++) = *(xt
++) + *(yt
);
1716 *(pg
++) = *(xt
++) + *(yt
+ 1);
1717 *(pb
++) = *(xt
++) + *(yt
+ 2);
1723 // faked interlacing effect
1724 unsigned char channel
, channel2
;
1726 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1727 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1729 channel
= *(xt
++) + *(yt
);
1730 channel2
= (channel
>> 1) + (channel
>> 2);
1731 if (channel2
> channel
) channel2
= 0;
1734 channel
= *(xt
++) + *(yt
+ 1);
1735 channel2
= (channel
>> 1) + (channel
>> 2);
1736 if (channel2
> channel
) channel2
= 0;
1739 channel
= *(xt
++) + *(yt
+ 2);
1740 channel2
= (channel
>> 1) + (channel
>> 2);
1741 if (channel2
> channel
) channel2
= 0;
1744 channel
= *(xt
++) + *(yt
);
1745 channel2
= channel
+ (channel
>> 3);
1746 if (channel2
< channel
) channel2
= ~0;
1749 channel
= *(xt
++) + *(yt
+ 1);
1750 channel2
= channel
+ (channel
>> 3);
1751 if (channel2
< channel
) channel2
= ~0;
1754 channel
= *(xt
++) + *(yt
+ 2);
1755 channel2
= channel
+ (channel
>> 3);
1756 if (channel2
< channel
) channel2
= ~0;
1766 BImageControl::BImageControl(BaseDisplay
&dpy
, ScreenInfo
&scrn
, Bool _dither
,
1767 int _cpc
, unsigned long cache_timeout
,
1768 unsigned long cmax
) : basedisplay(dpy
),
1772 setColorsPerChannel(_cpc
);
1776 if (cache_timeout
) {
1777 timer
= new BTimer(basedisplay
, *this);
1778 timer
->setTimeout(cache_timeout
);
1781 timer
= (BTimer
*) 0;
1782 #endif // TIMEDCACHE
1784 colors
= (XColor
*) 0;
1787 grad_xbuffer
= grad_ybuffer
= (unsigned int *) 0;
1788 grad_buffer_width
= grad_buffer_height
= 0;
1790 sqrt_table
= (unsigned long *) 0;
1792 screen_depth
= screeninfo
.getDepth();
1793 window
= screeninfo
.getRootWindow();
1794 screen_number
= screeninfo
.getScreenNumber();
1797 XPixmapFormatValues
*pmv
= XListPixmapFormats(basedisplay
.getXDisplay(),
1799 colormap
= screeninfo
.getColormap();
1803 for (int i
= 0; i
< count
; i
++)
1804 if (pmv
[i
].depth
== screen_depth
) {
1805 bits_per_pixel
= pmv
[i
].bits_per_pixel
;
1812 if (bits_per_pixel
== 0) bits_per_pixel
= screen_depth
;
1813 if (bits_per_pixel
>= 24) setDither(False
);
1815 red_offset
= green_offset
= blue_offset
= 0;
1817 switch (getVisual()->c_class
) {
1822 // compute color tables
1823 unsigned long red_mask
= getVisual()->red_mask
,
1824 green_mask
= getVisual()->green_mask
,
1825 blue_mask
= getVisual()->blue_mask
;
1827 while (! (red_mask
& 1)) { red_offset
++; red_mask
>>= 1; }
1828 while (! (green_mask
& 1)) { green_offset
++; green_mask
>>= 1; }
1829 while (! (blue_mask
& 1)) { blue_offset
++; blue_mask
>>= 1; }
1831 red_bits
= 255 / red_mask
;
1832 green_bits
= 255 / green_mask
;
1833 blue_bits
= 255 / blue_mask
;
1835 for (i
= 0; i
< 256; i
++) {
1836 red_color_table
[i
] = i
/ red_bits
;
1837 green_color_table
[i
] = i
/ green_bits
;
1838 blue_color_table
[i
] = i
/ blue_bits
;
1847 ncolors
= colors_per_channel
* colors_per_channel
* colors_per_channel
;
1849 if (ncolors
> (1 << screen_depth
)) {
1850 colors_per_channel
= (1 << screen_depth
) / 3;
1851 ncolors
= colors_per_channel
* colors_per_channel
* colors_per_channel
;
1854 if (colors_per_channel
< 2 || ncolors
> (1 << screen_depth
)) {
1855 fprintf(stderr
, i18n
->getMessage(ImageSet
, ImageInvalidColormapSize
,
1856 "BImageControl::BImageControl: invalid colormap size %d "
1857 "(%d/%d/%d) - reducing"),
1858 ncolors
, colors_per_channel
, colors_per_channel
,
1859 colors_per_channel
);
1861 colors_per_channel
= (1 << screen_depth
) / 3;
1864 colors
= new XColor
[ncolors
];
1866 fprintf(stderr
, i18n
->getMessage(ImageSet
,
1867 ImageErrorAllocatingColormap
,
1868 "BImageControl::BImageControl: error allocating "
1873 int i
= 0, ii
, p
, r
, g
, b
,
1875 #ifdef ORDEREDPSEUDO
1876 bits
= 256 / colors_per_channel
;
1877 #else // !ORDEREDPSEUDO
1878 bits
= 255 / (colors_per_channel
- 1);
1879 #endif // ORDEREDPSEUDO
1881 red_bits
= green_bits
= blue_bits
= bits
;
1883 for (i
= 0; i
< 256; i
++)
1884 red_color_table
[i
] = green_color_table
[i
] = blue_color_table
[i
] =
1887 for (r
= 0, i
= 0; r
< colors_per_channel
; r
++)
1888 for (g
= 0; g
< colors_per_channel
; g
++)
1889 for (b
= 0; b
< colors_per_channel
; b
++, i
++) {
1890 colors
[i
].red
= (r
* 0xffff) / (colors_per_channel
- 1);
1891 colors
[i
].green
= (g
* 0xffff) / (colors_per_channel
- 1);
1892 colors
[i
].blue
= (b
* 0xffff) / (colors_per_channel
- 1);;
1893 colors
[i
].flags
= DoRed
|DoGreen
|DoBlue
;
1898 for (i
= 0; i
< ncolors
; i
++)
1899 if (! XAllocColor(basedisplay
.getXDisplay(), colormap
, &colors
[i
])) {
1900 fprintf(stderr
, i18n
->getMessage(ImageSet
, ImageColorAllocFail
,
1901 "couldn't alloc color %i %i %i\n"),
1902 colors
[i
].red
, colors
[i
].green
, colors
[i
].blue
);
1903 colors
[i
].flags
= 0;
1905 colors
[i
].flags
= DoRed
|DoGreen
|DoBlue
;
1907 basedisplay
.ungrab();
1909 XColor icolors
[256];
1910 int incolors
= (((1 << screen_depth
) > 256) ? 256 : (1 << screen_depth
));
1912 for (i
= 0; i
< incolors
; i
++)
1913 icolors
[i
].pixel
= i
;
1915 XQueryColors(basedisplay
.getXDisplay(), colormap
, icolors
, incolors
);
1916 for (i
= 0; i
< ncolors
; i
++) {
1917 if (! colors
[i
].flags
) {
1918 unsigned long chk
= 0xffffffff, pixel
, close
= 0;
1922 for (ii
= 0; ii
< incolors
; ii
++) {
1923 r
= (colors
[i
].red
- icolors
[i
].red
) >> 8;
1924 g
= (colors
[i
].green
- icolors
[i
].green
) >> 8;
1925 b
= (colors
[i
].blue
- icolors
[i
].blue
) >> 8;
1926 pixel
= (r
* r
) + (g
* g
) + (b
* b
);
1933 colors
[i
].red
= icolors
[close
].red
;
1934 colors
[i
].green
= icolors
[close
].green
;
1935 colors
[i
].blue
= icolors
[close
].blue
;
1937 if (XAllocColor(basedisplay
.getXDisplay(), colormap
,
1939 colors
[i
].flags
= DoRed
|DoGreen
|DoBlue
;
1954 if (getVisual()->c_class
== StaticGray
) {
1955 ncolors
= 1 << screen_depth
;
1957 ncolors
= colors_per_channel
* colors_per_channel
* colors_per_channel
;
1959 if (ncolors
> (1 << screen_depth
)) {
1960 colors_per_channel
= (1 << screen_depth
) / 3;
1962 colors_per_channel
* colors_per_channel
* colors_per_channel
;
1966 if (colors_per_channel
< 2 || ncolors
> (1 << screen_depth
)) {
1967 fprintf(stderr
, i18n
->getMessage(ImageSet
, ImageInvalidColormapSize
,
1968 "BImageControl::BImageControl: invalid colormap size %d "
1969 "(%d/%d/%d) - reducing"),
1970 ncolors
, colors_per_channel
, colors_per_channel
,
1971 colors_per_channel
);
1973 colors_per_channel
= (1 << screen_depth
) / 3;
1976 colors
= new XColor
[ncolors
];
1978 fprintf(stderr
, i18n
->getMessage(ImageSet
,
1979 ImageErrorAllocatingColormap
,
1980 "BImageControl::BImageControl: error allocating "
1985 int i
= 0, ii
, p
, bits
= 255 / (colors_per_channel
- 1);
1986 red_bits
= green_bits
= blue_bits
= bits
;
1988 for (i
= 0; i
< 256; i
++)
1989 red_color_table
[i
] = green_color_table
[i
] = blue_color_table
[i
] =
1993 for (i
= 0; i
< ncolors
; i
++) {
1994 colors
[i
].red
= (i
* 0xffff) / (colors_per_channel
- 1);
1995 colors
[i
].green
= (i
* 0xffff) / (colors_per_channel
- 1);
1996 colors
[i
].blue
= (i
* 0xffff) / (colors_per_channel
- 1);;
1997 colors
[i
].flags
= DoRed
|DoGreen
|DoBlue
;
1999 if (! XAllocColor(basedisplay
.getXDisplay(), colormap
,
2001 fprintf(stderr
, i18n
->getMessage(ImageSet
, ImageColorAllocFail
,
2002 "couldn't alloc color %i %i %i\n"),
2003 colors
[i
].red
, colors
[i
].green
, colors
[i
].blue
);
2004 colors
[i
].flags
= 0;
2006 colors
[i
].flags
= DoRed
|DoGreen
|DoBlue
;
2009 basedisplay
.ungrab();
2011 XColor icolors
[256];
2012 int incolors
= (((1 << screen_depth
) > 256) ? 256 :
2013 (1 << screen_depth
));
2015 for (i
= 0; i
< incolors
; i
++)
2016 icolors
[i
].pixel
= i
;
2018 XQueryColors(basedisplay
.getXDisplay(), colormap
, icolors
, incolors
);
2019 for (i
= 0; i
< ncolors
; i
++) {
2020 if (! colors
[i
].flags
) {
2021 unsigned long chk
= 0xffffffff, pixel
, close
= 0;
2025 for (ii
= 0; ii
< incolors
; ii
++) {
2026 int r
= (colors
[i
].red
- icolors
[i
].red
) >> 8;
2027 int g
= (colors
[i
].green
- icolors
[i
].green
) >> 8;
2028 int b
= (colors
[i
].blue
- icolors
[i
].blue
) >> 8;
2029 pixel
= (r
* r
) + (g
* g
) + (b
* b
);
2036 colors
[i
].red
= icolors
[close
].red
;
2037 colors
[i
].green
= icolors
[close
].green
;
2038 colors
[i
].blue
= icolors
[close
].blue
;
2040 if (XAllocColor(basedisplay
.getXDisplay(), colormap
,
2042 colors
[i
].flags
= DoRed
|DoGreen
|DoBlue
;
2054 fprintf(stderr
, i18n
->getMessage(ImageSet
, ImageUnsupVisual
,
2055 "BImageControl::BImageControl: unsupported visual %d\n"),
2056 getVisual()->c_class
);
2060 cache
= new LinkedList
<Cache
>;
2064 BImageControl::~BImageControl(void) {
2066 delete [] sqrt_table
;
2070 delete [] grad_xbuffer
;
2074 delete [] grad_ybuffer
;
2078 unsigned long *pixels
= new unsigned long [ncolors
];
2081 for (i
= 0; i
< ncolors
; i
++)
2082 *(pixels
+ i
) = (*(colors
+ i
)).pixel
;
2084 XFreeColors(basedisplay
.getXDisplay(), colormap
, pixels
, ncolors
, 0);
2089 if (cache
->count()) {
2090 int i
, n
= cache
->count();
2091 fprintf(stderr
, i18n
->getMessage(ImageSet
, ImagePixmapRelease
,
2092 "BImageContol::~BImageControl: pixmap cache - "
2093 "releasing %d pixmaps\n"), n
);
2095 for (i
= 0; i
< n
; i
++) {
2096 Cache
*tmp
= cache
->first();
2097 XFreePixmap(basedisplay
.getXDisplay(), tmp
->pixmap
);
2107 #endif // TIMEDCACHE
2114 Pixmap
BImageControl::searchCache(unsigned int width
, unsigned int height
,
2115 unsigned long texture
,
2116 BColor
*c1
, BColor
*c2
) {
2117 if (cache
->count()) {
2118 LinkedListIterator
<Cache
> it(cache
);
2120 for (Cache
*tmp
= it
.current(); tmp
; it
++, tmp
= it
.current()) {
2121 if ((tmp
->width
== width
) && (tmp
->height
== height
) &&
2122 (tmp
->texture
== texture
) && (tmp
->pixel1
== c1
->getPixel()))
2123 if (texture
& BImage_Gradient
) {
2124 if (tmp
->pixel2
== c2
->getPixel()) {
2139 Pixmap
BImageControl::renderImage(unsigned int width
, unsigned int height
,
2140 BTexture
*texture
) {
2141 if (texture
->getTexture() & BImage_ParentRelative
) return ParentRelative
;
2143 Pixmap pixmap
= searchCache(width
, height
, texture
->getTexture(),
2144 texture
->getColor(), texture
->getColorTo());
2145 if (pixmap
) return pixmap
;
2147 BImage
image(*this, width
, height
);
2148 pixmap
= image
.render(texture
);
2151 Cache
*tmp
= new Cache
;
2153 tmp
->pixmap
= pixmap
;
2155 tmp
->height
= height
;
2157 tmp
->texture
= texture
->getTexture();
2158 tmp
->pixel1
= texture
->getColor()->getPixel();
2160 if (texture
->getTexture() & BImage_Gradient
)
2161 tmp
->pixel2
= texture
->getColorTo()->getPixel();
2167 if ((unsigned) cache
->count() > cache_max
) {
2169 fprintf(stderr
, i18n
->getMessage(ImageSet
, ImagePixmapCacheLarge
,
2170 "BImageControl::renderImage: cache is large, "
2171 "forcing cleanout\n"));
2184 void BImageControl::removeImage(Pixmap pixmap
) {
2186 LinkedListIterator
<Cache
> it(cache
);
2187 for (Cache
*tmp
= it
.current(); tmp
; it
++, tmp
= it
.current()) {
2188 if (tmp
->pixmap
== pixmap
) {
2193 if (! timer
) timeout();
2194 #else // !TIMEDCACHE
2195 if (! tmp
->count
) timeout();
2196 #endif // TIMEDCACHE
2206 unsigned long BImageControl::getColor(const char *colorname
,
2207 unsigned char *r
, unsigned char *g
,
2213 if (! XParseColor(basedisplay
.getXDisplay(), colormap
, colorname
, &color
))
2214 fprintf(stderr
, "BImageControl::getColor: color parse error: \"%s\"\n",
2216 else if (! XAllocColor(basedisplay
.getXDisplay(), colormap
, &color
))
2217 fprintf(stderr
, "BImageControl::getColor: color alloc error: \"%s\"\n",
2220 if (color
.red
== 65535) *r
= 0xff;
2221 else *r
= (unsigned char) (color
.red
/ 0xff);
2222 if (color
.green
== 65535) *g
= 0xff;
2223 else *g
= (unsigned char) (color
.green
/ 0xff);
2224 if (color
.blue
== 65535) *b
= 0xff;
2225 else *b
= (unsigned char) (color
.blue
/ 0xff);
2231 unsigned long BImageControl::getColor(const char *colorname
) {
2235 if (! XParseColor(basedisplay
.getXDisplay(), colormap
, colorname
, &color
))
2236 fprintf(stderr
, "BImageControl::getColor: color parse error: \"%s\"\n",
2238 else if (! XAllocColor(basedisplay
.getXDisplay(), colormap
, &color
))
2239 fprintf(stderr
, "BImageControl::getColor: color alloc error: \"%s\"\n",
2246 void BImageControl::getColorTables(unsigned char **rmt
, unsigned char **gmt
,
2247 unsigned char **bmt
,
2248 int *roff
, int *goff
, int *boff
,
2249 int *rbit
, int *gbit
, int *bbit
) {
2250 if (rmt
) *rmt
= red_color_table
;
2251 if (gmt
) *gmt
= green_color_table
;
2252 if (bmt
) *bmt
= blue_color_table
;
2254 if (roff
) *roff
= red_offset
;
2255 if (goff
) *goff
= green_offset
;
2256 if (boff
) *boff
= blue_offset
;
2258 if (rbit
) *rbit
= red_bits
;
2259 if (gbit
) *gbit
= green_bits
;
2260 if (bbit
) *bbit
= blue_bits
;
2264 void BImageControl::getXColorTable(XColor
**c
, int *n
) {
2266 if (n
) *n
= ncolors
;
2270 void BImageControl::getGradientBuffers(unsigned int w
,
2272 unsigned int **xbuf
,
2273 unsigned int **ybuf
)
2275 if (w
> grad_buffer_width
) {
2277 delete [] grad_xbuffer
;
2280 grad_buffer_width
= w
;
2282 grad_xbuffer
= new unsigned int[grad_buffer_width
* 3];
2285 if (h
> grad_buffer_height
) {
2287 delete [] grad_ybuffer
;
2290 grad_buffer_height
= h
;
2292 grad_ybuffer
= new unsigned int[grad_buffer_height
* 3];
2295 *xbuf
= grad_xbuffer
;
2296 *ybuf
= grad_ybuffer
;
2300 void BImageControl::installRootColormap(void) {
2303 Bool install
= True
;
2304 int i
= 0, ncmap
= 0;
2306 XListInstalledColormaps(basedisplay
.getXDisplay(), window
, &ncmap
);
2309 for (i
= 0; i
< ncmap
; i
++)
2310 if (*(cmaps
+ i
) == colormap
)
2314 XInstallColormap(basedisplay
.getXDisplay(), colormap
);
2319 basedisplay
.ungrab();
2323 void BImageControl::setColorsPerChannel(int cpc
) {
2324 if (cpc
< 2) cpc
= 2;
2325 if (cpc
> 6) cpc
= 6;
2327 colors_per_channel
= cpc
;
2331 unsigned long BImageControl::getSqrt(unsigned int x
) {
2333 // build sqrt table for use with elliptic gradient
2335 sqrt_table
= new unsigned long[(256 * 256 * 2) + 1];
2338 for (; i
< (256 * 256 * 2); i
++)
2339 *(sqrt_table
+ i
) = bsqrt(i
);
2342 return (*(sqrt_table
+ x
));
2346 void BImageControl::parseTexture(BTexture
*texture
, const char *t
) {
2347 if ((! texture
) || (! t
)) return;
2349 int t_len
= strlen(t
) + 1, i
;
2350 char *ts
= new char[t_len
];
2353 // convert to lower case
2354 for (i
= 0; i
< t_len
; i
++)
2355 *(ts
+ i
) = tolower(*(t
+ i
));
2357 if (strstr(ts
, "parentrelative")) {
2358 texture
->setTexture(BImage_ParentRelative
);
2360 texture
->setTexture(0);
2362 if (strstr(ts
, "solid"))
2363 texture
->addTexture(BImage_Solid
);
2364 else if (strstr(ts
, "gradient")) {
2365 texture
->addTexture(BImage_Gradient
);
2366 if (strstr(ts
, "crossdiagonal"))
2367 texture
->addTexture(BImage_CrossDiagonal
);
2368 else if (strstr(ts
, "rectangle"))
2369 texture
->addTexture(BImage_Rectangle
);
2370 else if (strstr(ts
, "pyramid"))
2371 texture
->addTexture(BImage_Pyramid
);
2372 else if (strstr(ts
, "pipecross"))
2373 texture
->addTexture(BImage_PipeCross
);
2374 else if (strstr(ts
, "elliptic"))
2375 texture
->addTexture(BImage_Elliptic
);
2376 else if (strstr(ts
, "diagonal"))
2377 texture
->addTexture(BImage_Diagonal
);
2378 else if (strstr(ts
, "horizontal"))
2379 texture
->addTexture(BImage_Horizontal
);
2380 else if (strstr(ts
, "vertical"))
2381 texture
->addTexture(BImage_Vertical
);
2383 texture
->addTexture(BImage_Diagonal
);
2385 texture
->addTexture(BImage_Solid
);
2387 if (strstr(ts
, "raised"))
2388 texture
->addTexture(BImage_Raised
);
2389 else if (strstr(ts
, "sunken"))
2390 texture
->addTexture(BImage_Sunken
);
2391 else if (strstr(ts
, "flat"))
2392 texture
->addTexture(BImage_Flat
);
2394 texture
->addTexture(BImage_Raised
);
2396 if (! (texture
->getTexture() & BImage_Flat
))
2397 if (strstr(ts
, "bevel2"))
2398 texture
->addTexture(BImage_Bevel2
);
2400 texture
->addTexture(BImage_Bevel1
);
2403 if (strstr(ts
, "interlaced"))
2404 texture
->addTexture(BImage_Interlaced
);
2412 void BImageControl::parseColor(BColor
*color
, const char *c
) {
2413 if (! color
) return;
2415 if (color
->isAllocated()) {
2416 unsigned long pixel
= color
->getPixel();
2418 XFreeColors(basedisplay
.getXDisplay(), colormap
, &pixel
, 1, 0);
2420 color
->setPixel(0l);
2421 color
->setRGB(0, 0, 0);
2422 color
->setAllocated(False
);
2426 unsigned char r
, g
, b
;
2428 color
->setPixel(getColor(c
, &r
, &g
, &b
));
2429 color
->setRGB(r
, g
, b
);
2430 color
->setAllocated(True
);
2435 void BImageControl::timeout(void) {
2436 LinkedListIterator
<Cache
> it(cache
);
2437 for (Cache
*tmp
= it
.current(); tmp
; it
++, tmp
= it
.current()) {
2438 if (tmp
->count
<= 0) {
2439 XFreePixmap(basedisplay
.getXDisplay(), tmp
->pixmap
);