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
;
56 #endif // STDC_HEADERS
60 #endif // HAVE_STDIO_H
64 #endif // HAVE_CTYPE_H
69 static unsigned long bsqrt(unsigned long x
) {
73 unsigned long r
= x
>> 1;
84 BImage::BImage(BImageControl
&c
, unsigned int w
, unsigned int h
) : control(c
) {
85 width
= ((signed) w
> 0) ? w
: 1;
86 height
= ((signed) h
> 0) ? h
: 1;
88 red
= new unsigned char[width
* height
];
89 green
= new unsigned char[width
* height
];
90 blue
= new unsigned char[width
* height
];
92 xtable
= ytable
= (unsigned int *) 0;
94 cpc
= control
.getColorsPerChannel();
97 control
.getColorTables(&red_table
, &green_table
, &blue_table
,
98 &red_offset
, &green_offset
, &blue_offset
,
99 &red_bits
, &green_bits
, &blue_bits
);
101 if (control
.getVisual()->c_class
!= TrueColor
)
102 control
.getXColorTable(&colors
, &ncolors
);
106 BImage::~BImage(void) {
107 if (red
) delete [] red
;
108 if (green
) delete [] green
;
109 if (blue
) delete [] blue
;
113 Pixmap
BImage::render(BTexture
*texture
) {
114 if (texture
->getTexture() & BImage_ParentRelative
)
115 return ParentRelative
;
116 else if (texture
->getTexture() & BImage_Solid
)
117 return render_solid(texture
);
118 else if (texture
->getTexture() & BImage_Gradient
)
119 return render_gradient(texture
);
125 Pixmap
BImage::render_solid(BTexture
*texture
) {
126 Pixmap pixmap
= XCreatePixmap(control
.getBaseDisplay().getXDisplay(),
127 control
.getDrawable(), width
,
128 height
, control
.getDepth());
129 if (pixmap
== None
) {
130 fprintf(stderr
, i18n
->getMessage(ImageSet
, ImageErrorCreatingSolidPixmap
,
131 "BImage::render_solid: error creating pixmap\n"));
138 gcv
.foreground
= texture
->getColor()->getPixel();
139 gcv
.fill_style
= FillSolid
;
140 gc
= XCreateGC(control
.getBaseDisplay().getXDisplay(), pixmap
,
141 GCForeground
| GCFillStyle
, &gcv
);
143 gcv
.foreground
= texture
->getHiColor()->getPixel();
144 hgc
= XCreateGC(control
.getBaseDisplay().getXDisplay(), pixmap
,
147 gcv
.foreground
= texture
->getLoColor()->getPixel();
148 lgc
= XCreateGC(control
.getBaseDisplay().getXDisplay(), pixmap
,
151 XFillRectangle(control
.getBaseDisplay().getXDisplay(), pixmap
, gc
, 0, 0,
155 if (texture
->getTexture() & BImage_Interlaced
) {
156 gcv
.foreground
= texture
->getColorTo()->getPixel();
157 GC igc
= XCreateGC(control
.getBaseDisplay().getXDisplay(), pixmap
,
160 register unsigned int i
= 0;
161 for (; i
< height
; i
+= 2)
162 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, igc
,
165 XFreeGC(control
.getBaseDisplay().getXDisplay(), igc
);
170 if (texture
->getTexture() & BImage_Bevel1
) {
171 if (texture
->getTexture() & BImage_Raised
) {
172 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, lgc
,
173 0, height
- 1, width
- 1, height
- 1);
174 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, lgc
,
175 width
- 1, height
- 1, width
- 1, 0);
177 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, hgc
,
179 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, hgc
,
180 0, height
- 1, 0, 0);
181 } else if (texture
->getTexture() & BImage_Sunken
) {
182 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, hgc
,
183 0, height
- 1, width
- 1, height
- 1);
184 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, hgc
,
185 width
- 1, height
- 1, width
- 1, 0);
187 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, lgc
,
189 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, lgc
,
190 0, height
- 1, 0, 0);
192 } else if (texture
->getTexture() & BImage_Bevel2
) {
193 if (texture
->getTexture() & BImage_Raised
) {
194 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, lgc
,
195 1, height
- 3, width
- 3, height
- 3);
196 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, lgc
,
197 width
- 3, height
- 3, width
- 3, 1);
199 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, hgc
,
201 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, hgc
,
202 1, height
- 3, 1, 1);
203 } else if (texture
->getTexture() & BImage_Sunken
) {
204 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, hgc
,
205 1, height
- 3, width
- 3, height
- 3);
206 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, hgc
,
207 width
- 3, height
- 3, width
- 3, 1);
209 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, lgc
,
211 XDrawLine(control
.getBaseDisplay().getXDisplay(), pixmap
, lgc
,
212 1, height
- 3, 1, 1);
216 XFreeGC(control
.getBaseDisplay().getXDisplay(), gc
);
217 XFreeGC(control
.getBaseDisplay().getXDisplay(), hgc
);
218 XFreeGC(control
.getBaseDisplay().getXDisplay(), lgc
);
224 Pixmap
BImage::render_gradient(BTexture
*texture
) {
228 interlaced
= texture
->getTexture() & BImage_Interlaced
;
231 if (texture
->getTexture() & BImage_Sunken
) {
232 from
= texture
->getColorTo();
233 to
= texture
->getColor();
235 if (! (texture
->getTexture() & BImage_Invert
)) inverted
= 1;
237 from
= texture
->getColor();
238 to
= texture
->getColorTo();
240 if (texture
->getTexture() & BImage_Invert
) inverted
= 1;
243 control
.getGradientBuffers(width
, height
, &xtable
, &ytable
);
245 if (texture
->getTexture() & BImage_Diagonal
) dgradient();
246 else if (texture
->getTexture() & BImage_Elliptic
) egradient();
247 else if (texture
->getTexture() & BImage_Horizontal
) hgradient();
248 else if (texture
->getTexture() & BImage_Pyramid
) pgradient();
249 else if (texture
->getTexture() & BImage_Rectangle
) rgradient();
250 else if (texture
->getTexture() & BImage_Vertical
) vgradient();
251 else if (texture
->getTexture() & BImage_CrossDiagonal
) cdgradient();
252 else if (texture
->getTexture() & BImage_PipeCross
) pcgradient();
254 if (texture
->getTexture() & BImage_Bevel1
) bevel1();
255 else if (texture
->getTexture() & BImage_Bevel2
) bevel2();
257 if (inverted
) invert();
259 Pixmap pixmap
= renderPixmap();
266 XImage
*BImage::renderXImage(void) {
268 XCreateImage(control
.getBaseDisplay().getXDisplay(),
269 control
.getVisual(), control
.getDepth(), ZPixmap
, 0, 0,
270 width
, height
, 32, 0);
273 fprintf(stderr
, i18n
->getMessage(ImageSet
, ImageErrorCreatingXImage
,
274 "BImage::renderXImage: error creating XImage\n"));
279 image
->data
= (char *) 0;
281 unsigned char *d
= new unsigned char[image
->bytes_per_line
* (height
+ 1)];
282 register unsigned int x
, y
, dithx
, dithy
, r
, g
, b
, o
, er
, eg
, eb
, offset
;
284 unsigned char *pixel_data
= d
, *ppixel_data
= d
;
287 o
= image
->bits_per_pixel
+ ((image
->byte_order
== MSBFirst
) ? 1 : 0);
289 if (control
.doDither() && width
> 1 && height
> 1) {
290 unsigned char dither4
[4][4] = { {0, 4, 1, 5},
296 unsigned char dither8
[8][8] = { { 0, 32, 8, 40, 2, 34, 10, 42 },
297 { 48, 16, 56, 24, 50, 18, 58, 26 },
298 { 12, 44, 4, 36, 14, 46, 6, 38 },
299 { 60, 28, 52, 20, 62, 30, 54, 22 },
300 { 3, 35, 11, 43, 1, 33, 9, 41 },
301 { 51, 19, 59, 27, 49, 17, 57, 25 },
302 { 15, 47, 7, 39, 13, 45, 5, 37 },
303 { 63, 31, 55, 23, 61, 29, 53, 21 } };
304 #endif // ORDEREDPSEUDO
306 switch (control
.getVisual()->c_class
) {
308 // algorithm: ordered dithering... many many thanks to rasterman
309 // (raster@rasterman.com) for telling me about this... portions of this
310 // code is based off of his code in Imlib
311 for (y
= 0, offset
= 0; y
< height
; y
++) {
314 for (x
= 0; x
< width
; x
++, offset
++) {
320 er
= r
& (red_bits
- 1);
321 eg
= g
& (green_bits
- 1);
322 eb
= b
& (blue_bits
- 1);
328 if ((dither4
[dithy
][dithx
] < er
) && (r
< red_table
[255])) r
++;
329 if ((dither4
[dithy
][dithx
] < eg
) && (g
< green_table
[255])) g
++;
330 if ((dither4
[dithy
][dithx
] < eb
) && (b
< blue_table
[255])) b
++;
332 pixel
= (r
<< red_offset
) | (g
<< green_offset
) | (b
<< blue_offset
);
336 *pixel_data
++ = pixel
;
339 case 16: // 16bpp LSB
340 *pixel_data
++ = pixel
;
341 *pixel_data
++ = pixel
>> 8;
344 case 17: // 16bpp MSB
345 *pixel_data
++ = pixel
>> 8;
346 *pixel_data
++ = pixel
;
349 case 24: // 24bpp LSB
350 *pixel_data
++ = pixel
;
351 *pixel_data
++ = pixel
>> 8;
352 *pixel_data
++ = pixel
>> 16;
355 case 25: // 24bpp MSB
356 *pixel_data
++ = pixel
>> 16;
357 *pixel_data
++ = pixel
>> 8;
358 *pixel_data
++ = pixel
;
361 case 32: // 32bpp LSB
362 *pixel_data
++ = pixel
;
363 *pixel_data
++ = pixel
>> 8;
364 *pixel_data
++ = pixel
>> 16;
365 *pixel_data
++ = pixel
>> 24;
368 case 33: // 32bpp MSB
369 *pixel_data
++ = pixel
>> 24;
370 *pixel_data
++ = pixel
>> 16;
371 *pixel_data
++ = pixel
>> 8;
372 *pixel_data
++ = pixel
;
377 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
384 #ifndef ORDEREDPSEUDO
386 *rerr
= new short[width
+ 2],
387 *gerr
= new short[width
+ 2],
388 *berr
= new short[width
+ 2],
389 *nrerr
= new short[width
+ 2],
390 *ngerr
= new short[width
+ 2],
391 *nberr
= new short[width
+ 2];
392 int rr
, gg
, bb
, rer
, ger
, ber
;
393 int dd
= 255 / control
.getColorsPerChannel();
395 for (x
= 0; x
< width
; x
++) {
396 *(rerr
+ x
) = *(red
+ x
);
397 *(gerr
+ x
) = *(green
+ x
);
398 *(berr
+ x
) = *(blue
+ x
);
401 *(rerr
+ x
) = *(gerr
+ x
) = *(berr
+ x
) = 0;
402 #endif // ORDEREDPSEUDO
404 for (y
= 0, offset
= 0; y
< height
; y
++) {
408 for (x
= 0; x
< width
; x
++, offset
++) {
415 er
= r
& (red_bits
- 1);
416 eg
= g
& (green_bits
- 1);
417 eb
= b
& (blue_bits
- 1);
423 if ((dither8
[dithy
][dithx
] < er
) && (r
< red_table
[255])) r
++;
424 if ((dither8
[dithy
][dithx
] < eg
) && (g
< green_table
[255])) g
++;
425 if ((dither8
[dithy
][dithx
] < eb
) && (b
< blue_table
[255])) b
++;
427 pixel
= (r
* cpccpc
) + (g
* cpc
) + b
;
428 *(pixel_data
++) = colors
[pixel
].pixel
;
431 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
433 #else // !ORDEREDPSEUDO
434 if (y
< (height
- 1)) {
435 int i
= offset
+ width
;
436 for (x
= 0; x
< width
; x
++, i
++) {
437 *(nrerr
+ x
) = *(red
+ i
);
438 *(ngerr
+ x
) = *(green
+ i
);
439 *(nberr
+ x
) = *(blue
+ i
);
442 *(nrerr
+ x
) = *(red
+ (--i
));
443 *(ngerr
+ x
) = *(green
+ i
);
444 *(nberr
+ x
) = *(blue
+ i
);
447 for (x
= 0; x
< width
; x
++) {
452 if (rr
> 255) rr
= 255; else if (rr
< 0) rr
= 0;
453 if (gg
> 255) gg
= 255; else if (gg
< 0) gg
= 0;
454 if (bb
> 255) bb
= 255; else if (bb
< 0) bb
= 0;
460 rer
= rerr
[x
] - r
*dd
;
461 ger
= gerr
[x
] - g
*dd
;
462 ber
= berr
[x
] - b
*dd
;
464 pixel
= (r
* cpccpc
) + (g
* cpc
) + b
;
465 *pixel_data
++ = colors
[pixel
].pixel
;
480 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
501 #endif // ORDEREDPSUEDO
506 fprintf(stderr
, i18n
->getMessage(ImageSet
, ImageUnsupVisual
,
507 "BImage::renderXImage: unsupported visual\n"));
509 XDestroyImage(image
);
513 switch (control
.getVisual()->c_class
) {
516 for (y
= 0, offset
= 0; y
< height
; y
++) {
517 for (x
= 0; x
< width
; x
++, offset
++) {
518 r
= red_table
[red
[offset
]];
519 g
= green_table
[green
[offset
]];
520 b
= blue_table
[blue
[offset
]];
522 pixel
= (r
* cpccpc
) + (g
* cpc
) + b
;
523 *pixel_data
++ = colors
[pixel
].pixel
;
526 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
532 for (y
= 0, offset
= 0; y
< height
; y
++) {
533 for (x
= 0; x
< width
; x
++, offset
++) {
534 r
= red_table
[red
[offset
]];
535 g
= green_table
[green
[offset
]];
536 b
= blue_table
[blue
[offset
]];
538 pixel
= (r
<< red_offset
) | (g
<< green_offset
) | (b
<< blue_offset
);
542 *pixel_data
++ = pixel
;
545 case 16: // 16bpp LSB
546 *pixel_data
++ = pixel
;
547 *pixel_data
++ = pixel
>> 8;
550 case 17: // 16bpp MSB
551 *pixel_data
++ = pixel
>> 8;
552 *pixel_data
++ = pixel
;
555 case 24: // 24bpp LSB
556 *pixel_data
++ = pixel
;
557 *pixel_data
++ = pixel
>> 8;
558 *pixel_data
++ = pixel
>> 16;
561 case 25: // 24bpp MSB
562 *pixel_data
++ = pixel
>> 16;
563 *pixel_data
++ = pixel
>> 8;
564 *pixel_data
++ = pixel
;
567 case 32: // 32bpp LSB
568 *pixel_data
++ = pixel
;
569 *pixel_data
++ = pixel
>> 8;
570 *pixel_data
++ = pixel
>> 16;
571 *pixel_data
++ = pixel
>> 24;
574 case 33: // 32bpp MSB
575 *pixel_data
++ = pixel
>> 24;
576 *pixel_data
++ = pixel
>> 16;
577 *pixel_data
++ = pixel
>> 8;
578 *pixel_data
++ = pixel
;
583 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
590 for (y
= 0, offset
= 0; y
< height
; y
++) {
591 for (x
= 0; x
< width
; x
++, offset
++) {
592 r
= *(red_table
+ *(red
+ offset
));
593 g
= *(green_table
+ *(green
+ offset
));
594 b
= *(blue_table
+ *(blue
+ offset
));
596 g
= ((r
* 30) + (g
* 59) + (b
* 11)) / 100;
597 *pixel_data
++ = colors
[g
].pixel
;
600 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
606 fprintf(stderr
, i18n
->getMessage(ImageSet
, ImageUnsupVisual
,
607 "BImage::renderXImage: unsupported visual\n"));
609 XDestroyImage(image
);
614 image
->data
= (char *) d
;
619 Pixmap
BImage::renderPixmap(void) {
621 XCreatePixmap(control
.getBaseDisplay().getXDisplay(),
622 control
.getDrawable(), width
, height
, control
.getDepth());
624 if (pixmap
== None
) {
625 fprintf(stderr
, i18n
->getMessage(ImageSet
, ImageErrorCreatingPixmap
,
626 "BImage::renderPixmap: error creating pixmap\n"));
630 XImage
*image
= renderXImage();
633 XFreePixmap(control
.getBaseDisplay().getXDisplay(), pixmap
);
635 } else if (! image
->data
) {
636 XDestroyImage(image
);
637 XFreePixmap(control
.getBaseDisplay().getXDisplay(), pixmap
);
641 XPutImage(control
.getBaseDisplay().getXDisplay(), pixmap
,
642 DefaultGC(control
.getBaseDisplay().getXDisplay(),
643 control
.getScreenInfo().getScreenNumber()),
644 image
, 0, 0, 0, 0, width
, height
);
647 delete [] image
->data
;
651 XDestroyImage(image
);
657 void BImage::bevel1(void) {
658 if (width
> 2 && height
> 2) {
659 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
661 register unsigned char r
, g
, b
, rr
,gg
,bb
;
662 register unsigned int w
= width
, h
= height
- 1, wh
= w
* h
;
680 rr
= (r
>> 2) + (r
>> 1);
683 gg
= (g
>> 2) + (g
>> 1);
686 bb
= (b
>> 2) + (b
>> 1);
709 rr
= (r
>> 2) + (r
>> 1);
712 gg
= (g
>> 2) + (g
>> 1);
715 bb
= (b
>> 2) + (b
>> 1);
746 rr
= (r
>> 2) + (r
>> 1);
749 gg
= (g
>> 2) + (g
>> 1);
752 bb
= (b
>> 2) + (b
>> 1);
779 rr
= (r
>> 2) + (r
>> 1);
782 gg
= (g
>> 2) + (g
>> 1);
785 bb
= (b
>> 2) + (b
>> 1);
795 void BImage::bevel2(void) {
796 if (width
> 4 && height
> 4) {
797 unsigned char r
, g
, b
, rr
,gg
,bb
, *pr
= red
+ width
+ 1,
798 *pg
= green
+ width
+ 1, *pb
= blue
+ width
+ 1;
799 unsigned int w
= width
- 2, h
= height
- 1, wh
= width
* (height
- 3);
817 rr
= (r
>> 2) + (r
>> 1);
820 gg
= (g
>> 2) + (g
>> 1);
823 bb
= (b
>> 2) + (b
>> 1);
855 rr
= (r
>> 2) + (r
>> 1);
858 gg
= (g
>> 2) + (g
>> 1);
861 bb
= (b
>> 2) + (b
>> 1);
874 void BImage::invert(void) {
875 register unsigned int i
, j
, wh
= (width
* height
) - 1;
878 for (i
= 0, j
= wh
; j
> i
; j
--, i
++) {
880 *(red
+ j
) = *(red
+ i
);
884 *(green
+ j
) = *(green
+ i
);
888 *(blue
+ j
) = *(blue
+ i
);
894 void BImage::dgradient(void) {
895 // diagonal gradient code was written by Mike Cole <mike@mydot.com>
896 // modified for interlacing by Brad Hughes
898 float drx
, dgx
, dbx
, dry
, dgy
, dby
, yr
= 0.0, yg
= 0.0, yb
= 0.0,
899 xr
= (float) from
->getRed(),
900 xg
= (float) from
->getGreen(),
901 xb
= (float) from
->getBlue();
902 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
903 unsigned int w
= width
* 2, h
= height
* 2, *xt
= xtable
, *yt
= ytable
;
905 register unsigned int x
, y
;
907 dry
= drx
= (float) (to
->getRed() - from
->getRed());
908 dgy
= dgx
= (float) (to
->getGreen() - from
->getGreen());
909 dby
= dbx
= (float) (to
->getBlue() - from
->getBlue());
916 for (x
= 0; x
< width
; x
++) {
917 *(xt
++) = (unsigned char) (xr
);
918 *(xt
++) = (unsigned char) (xg
);
919 *(xt
++) = (unsigned char) (xb
);
931 for (y
= 0; y
< height
; y
++) {
932 *(yt
++) = ((unsigned char) yr
);
933 *(yt
++) = ((unsigned char) yg
);
934 *(yt
++) = ((unsigned char) yb
);
941 // Combine tables to create gradient
948 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
949 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
950 *(pr
++) = *(xt
++) + *(yt
);
951 *(pg
++) = *(xt
++) + *(yt
+ 1);
952 *(pb
++) = *(xt
++) + *(yt
+ 2);
958 // faked interlacing effect
959 unsigned char channel
, channel2
;
961 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
962 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
964 channel
= *(xt
++) + *(yt
);
965 channel2
= (channel
>> 1) + (channel
>> 2);
966 if (channel2
> channel
) channel2
= 0;
969 channel
= *(xt
++) + *(yt
+ 1);
970 channel2
= (channel
>> 1) + (channel
>> 2);
971 if (channel2
> channel
) channel2
= 0;
974 channel
= *(xt
++) + *(yt
+ 2);
975 channel2
= (channel
>> 1) + (channel
>> 2);
976 if (channel2
> channel
) channel2
= 0;
979 channel
= *(xt
++) + *(yt
);
980 channel2
= channel
+ (channel
>> 3);
981 if (channel2
< channel
) channel2
= ~0;
984 channel
= *(xt
++) + *(yt
+ 1);
985 channel2
= channel
+ (channel
>> 3);
986 if (channel2
< channel
) channel2
= ~0;
989 channel
= *(xt
++) + *(yt
+ 2);
990 channel2
= channel
+ (channel
>> 3);
991 if (channel2
< channel
) channel2
= ~0;
1002 void BImage::hgradient(void) {
1003 float drx
, dgx
, dbx
,
1004 xr
= (float) from
->getRed(),
1005 xg
= (float) from
->getGreen(),
1006 xb
= (float) from
->getBlue();
1007 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1009 register unsigned int x
, y
;
1011 drx
= (float) (to
->getRed() - from
->getRed());
1012 dgx
= (float) (to
->getGreen() - from
->getGreen());
1013 dbx
= (float) (to
->getBlue() - from
->getBlue());
1020 if (interlaced
&& height
> 2) {
1021 // faked interlacing effect
1022 unsigned char channel
, channel2
;
1024 for (x
= 0; x
< width
; x
++, pr
++, pg
++, pb
++) {
1025 channel
= (unsigned char) xr
;
1026 channel2
= (channel
>> 1) + (channel
>> 2);
1027 if (channel2
> channel
) channel2
= 0;
1030 channel
= (unsigned char) xg
;
1031 channel2
= (channel
>> 1) + (channel
>> 2);
1032 if (channel2
> channel
) channel2
= 0;
1035 channel
= (unsigned char) xb
;
1036 channel2
= (channel
>> 1) + (channel
>> 2);
1037 if (channel2
> channel
) channel2
= 0;
1041 channel
= (unsigned char) xr
;
1042 channel2
= channel
+ (channel
>> 3);
1043 if (channel2
< channel
) channel2
= ~0;
1044 *(pr
+ width
) = channel2
;
1046 channel
= (unsigned char) xg
;
1047 channel2
= channel
+ (channel
>> 3);
1048 if (channel2
< channel
) channel2
= ~0;
1049 *(pg
+ width
) = channel2
;
1051 channel
= (unsigned char) xb
;
1052 channel2
= channel
+ (channel
>> 3);
1053 if (channel2
< channel
) channel2
= ~0;
1054 *(pb
+ width
) = channel2
;
1067 for (y
= 2; y
< height
; y
++, pr
+= width
, pg
+= width
, pb
+= width
) {
1068 if (y
& 1) offset
= width
; else offset
= 0;
1070 memcpy(pr
, (red
+ offset
), width
);
1071 memcpy(pg
, (green
+ offset
), width
);
1072 memcpy(pb
, (blue
+ offset
), width
);
1078 for (x
= 0; x
< width
; x
++) {
1079 *(pr
++) = (unsigned char) (xr
);
1080 *(pg
++) = (unsigned char) (xg
);
1081 *(pb
++) = (unsigned char) (xb
);
1088 for (y
= 1; y
< height
; y
++, pr
+= width
, pg
+= width
, pb
+= width
) {
1089 memcpy(pr
, red
, width
);
1090 memcpy(pg
, green
, width
);
1091 memcpy(pb
, blue
, width
);
1101 void BImage::vgradient(void) {
1102 float dry
, dgy
, dby
,
1103 yr
= (float) from
->getRed(),
1104 yg
= (float) from
->getGreen(),
1105 yb
= (float) from
->getBlue();
1106 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1108 register unsigned int y
;
1110 dry
= (float) (to
->getRed() - from
->getRed());
1111 dgy
= (float) (to
->getGreen() - from
->getGreen());
1112 dby
= (float) (to
->getBlue() - from
->getBlue());
1120 // faked interlacing effect
1121 unsigned char channel
, channel2
;
1123 for (y
= 0; y
< height
; y
++, pr
+= width
, pg
+= width
, pb
+= width
) {
1125 channel
= (unsigned char) yr
;
1126 channel2
= (channel
>> 1) + (channel
>> 2);
1127 if (channel2
> channel
) channel2
= 0;
1128 memset(pr
, channel2
, width
);
1130 channel
= (unsigned char) yg
;
1131 channel2
= (channel
>> 1) + (channel
>> 2);
1132 if (channel2
> channel
) channel2
= 0;
1133 memset(pg
, channel2
, width
);
1135 channel
= (unsigned char) yb
;
1136 channel2
= (channel
>> 1) + (channel
>> 2);
1137 if (channel2
> channel
) channel2
= 0;
1138 memset(pb
, channel2
, width
);
1140 channel
= (unsigned char) yr
;
1141 channel2
= channel
+ (channel
>> 3);
1142 if (channel2
< channel
) channel2
= ~0;
1143 memset(pr
, channel2
, width
);
1145 channel
= (unsigned char) yg
;
1146 channel2
= channel
+ (channel
>> 3);
1147 if (channel2
< channel
) channel2
= ~0;
1148 memset(pg
, channel2
, width
);
1150 channel
= (unsigned char) yb
;
1151 channel2
= channel
+ (channel
>> 3);
1152 if (channel2
< channel
) channel2
= ~0;
1153 memset(pb
, channel2
, width
);
1164 for (y
= 0; y
< height
; y
++, pr
+= width
, pg
+= width
, pb
+= width
) {
1165 memset(pr
, (unsigned char) yr
, width
);
1166 memset(pg
, (unsigned char) yg
, width
);
1167 memset(pb
, (unsigned char) yb
, width
);
1181 void BImage::pgradient(void) {
1182 // pyramid gradient - based on original dgradient, written by
1183 // Mosfet (mosfet@kde.org)
1184 // adapted from kde sources for Openbox by Brad Hughes
1186 float yr
, yg
, yb
, drx
, dgx
, dbx
, dry
, dgy
, dby
,
1188 int rsign
, gsign
, bsign
;
1189 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1190 unsigned int tr
= to
->getRed(), tg
= to
->getGreen(), tb
= to
->getBlue(),
1191 *xt
= xtable
, *yt
= ytable
;
1193 register unsigned int x
, y
;
1195 dry
= drx
= (float) (to
->getRed() - from
->getRed());
1196 dgy
= dgx
= (float) (to
->getGreen() - from
->getGreen());
1197 dby
= dbx
= (float) (to
->getBlue() - from
->getBlue());
1199 rsign
= (drx
< 0) ? -1 : 1;
1200 gsign
= (dgx
< 0) ? -1 : 1;
1201 bsign
= (dbx
< 0) ? -1 : 1;
1203 xr
= yr
= (drx
/ 2);
1204 xg
= yg
= (dgx
/ 2);
1205 xb
= yb
= (dbx
/ 2);
1212 for (x
= 0; x
< width
; x
++) {
1213 *(xt
++) = (unsigned char) ((xr
< 0) ? -xr
: xr
);
1214 *(xt
++) = (unsigned char) ((xg
< 0) ? -xg
: xg
);
1215 *(xt
++) = (unsigned char) ((xb
< 0) ? -xb
: xb
);
1227 for (y
= 0; y
< height
; y
++) {
1228 *(yt
++) = ((unsigned char) ((yr
< 0) ? -yr
: yr
));
1229 *(yt
++) = ((unsigned char) ((yg
< 0) ? -yg
: yg
));
1230 *(yt
++) = ((unsigned char) ((yb
< 0) ? -yb
: yb
));
1237 // Combine tables to create gradient
1244 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1245 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1246 *(pr
++) = (unsigned char) (tr
- (rsign
* (*(xt
++) + *(yt
))));
1247 *(pg
++) = (unsigned char) (tg
- (gsign
* (*(xt
++) + *(yt
+ 1))));
1248 *(pb
++) = (unsigned char) (tb
- (bsign
* (*(xt
++) + *(yt
+ 2))));
1254 // faked interlacing effect
1255 unsigned char channel
, channel2
;
1257 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1258 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1260 channel
= (unsigned char) (tr
- (rsign
* (*(xt
++) + *(yt
))));
1261 channel2
= (channel
>> 1) + (channel
>> 2);
1262 if (channel2
> channel
) channel2
= 0;
1265 channel
= (unsigned char) (tg
- (gsign
* (*(xt
++) + *(yt
+ 1))));
1266 channel2
= (channel
>> 1) + (channel
>> 2);
1267 if (channel2
> channel
) channel2
= 0;
1270 channel
= (unsigned char) (tb
- (bsign
* (*(xt
++) + *(yt
+ 2))));
1271 channel2
= (channel
>> 1) + (channel
>> 2);
1272 if (channel2
> channel
) channel2
= 0;
1275 channel
= (unsigned char) (tr
- (rsign
* (*(xt
++) + *(yt
))));
1276 channel2
= channel
+ (channel
>> 3);
1277 if (channel2
< channel
) channel2
= ~0;
1280 channel
= (unsigned char) (tg
- (gsign
* (*(xt
++) + *(yt
+ 1))));
1281 channel2
= channel
+ (channel
>> 3);
1282 if (channel2
< channel
) channel2
= ~0;
1285 channel
= (unsigned char) (tb
- (bsign
* (*(xt
++) + *(yt
+ 2))));
1286 channel2
= channel
+ (channel
>> 3);
1287 if (channel2
< channel
) channel2
= ~0;
1297 void BImage::rgradient(void) {
1298 // rectangle gradient - based on original dgradient, written by
1299 // Mosfet (mosfet@kde.org)
1300 // adapted from kde sources for Openbox by Brad Hughes
1302 float drx
, dgx
, dbx
, dry
, dgy
, dby
, xr
, xg
, xb
, yr
, yg
, yb
;
1303 int rsign
, gsign
, bsign
;
1304 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1305 unsigned int tr
= to
->getRed(), tg
= to
->getGreen(), tb
= to
->getBlue(),
1306 *xt
= xtable
, *yt
= ytable
;
1308 register unsigned int x
, y
;
1310 dry
= drx
= (float) (to
->getRed() - from
->getRed());
1311 dgy
= dgx
= (float) (to
->getGreen() - from
->getGreen());
1312 dby
= dbx
= (float) (to
->getBlue() - from
->getBlue());
1314 rsign
= (drx
< 0) ? -2 : 2;
1315 gsign
= (dgx
< 0) ? -2 : 2;
1316 bsign
= (dbx
< 0) ? -2 : 2;
1318 xr
= yr
= (drx
/ 2);
1319 xg
= yg
= (dgx
/ 2);
1320 xb
= yb
= (dbx
/ 2);
1327 for (x
= 0; x
< width
; x
++) {
1328 *(xt
++) = (unsigned char) ((xr
< 0) ? -xr
: xr
);
1329 *(xt
++) = (unsigned char) ((xg
< 0) ? -xg
: xg
);
1330 *(xt
++) = (unsigned char) ((xb
< 0) ? -xb
: xb
);
1342 for (y
= 0; y
< height
; y
++) {
1343 *(yt
++) = ((unsigned char) ((yr
< 0) ? -yr
: yr
));
1344 *(yt
++) = ((unsigned char) ((yg
< 0) ? -yg
: yg
));
1345 *(yt
++) = ((unsigned char) ((yb
< 0) ? -yb
: yb
));
1352 // Combine tables to create gradient
1359 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1360 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1361 *(pr
++) = (unsigned char) (tr
- (rsign
* max(*(xt
++), *(yt
))));
1362 *(pg
++) = (unsigned char) (tg
- (gsign
* max(*(xt
++), *(yt
+ 1))));
1363 *(pb
++) = (unsigned char) (tb
- (bsign
* max(*(xt
++), *(yt
+ 2))));
1369 // faked interlacing effect
1370 unsigned char channel
, channel2
;
1372 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1373 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1375 channel
= (unsigned char) (tr
- (rsign
* max(*(xt
++), *(yt
))));
1376 channel2
= (channel
>> 1) + (channel
>> 2);
1377 if (channel2
> channel
) channel2
= 0;
1380 channel
= (unsigned char) (tg
- (gsign
* max(*(xt
++), *(yt
+ 1))));
1381 channel2
= (channel
>> 1) + (channel
>> 2);
1382 if (channel2
> channel
) channel2
= 0;
1385 channel
= (unsigned char) (tb
- (bsign
* max(*(xt
++), *(yt
+ 2))));
1386 channel2
= (channel
>> 1) + (channel
>> 2);
1387 if (channel2
> channel
) channel2
= 0;
1390 channel
= (unsigned char) (tr
- (rsign
* max(*(xt
++), *(yt
))));
1391 channel2
= channel
+ (channel
>> 3);
1392 if (channel2
< channel
) channel2
= ~0;
1395 channel
= (unsigned char) (tg
- (gsign
* max(*(xt
++), *(yt
+ 1))));
1396 channel2
= channel
+ (channel
>> 3);
1397 if (channel2
< channel
) channel2
= ~0;
1400 channel
= (unsigned char) (tb
- (bsign
* max(*(xt
++), *(yt
+ 2))));
1401 channel2
= channel
+ (channel
>> 3);
1402 if (channel2
< channel
) channel2
= ~0;
1412 void BImage::egradient(void) {
1413 // elliptic gradient - based on original dgradient, written by
1414 // Mosfet (mosfet@kde.org)
1415 // adapted from kde sources for Openbox by Brad Hughes
1417 float drx
, dgx
, dbx
, dry
, dgy
, dby
, yr
, yg
, yb
, xr
, xg
, xb
;
1418 int rsign
, gsign
, bsign
;
1419 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1420 unsigned int *xt
= xtable
, *yt
= ytable
,
1421 tr
= (unsigned long) to
->getRed(),
1422 tg
= (unsigned long) to
->getGreen(),
1423 tb
= (unsigned long) to
->getBlue();
1425 register unsigned int x
, y
;
1427 dry
= drx
= (float) (to
->getRed() - from
->getRed());
1428 dgy
= dgx
= (float) (to
->getGreen() - from
->getGreen());
1429 dby
= dbx
= (float) (to
->getBlue() - from
->getBlue());
1431 rsign
= (drx
< 0) ? -1 : 1;
1432 gsign
= (dgx
< 0) ? -1 : 1;
1433 bsign
= (dbx
< 0) ? -1 : 1;
1435 xr
= yr
= (drx
/ 2);
1436 xg
= yg
= (dgx
/ 2);
1437 xb
= yb
= (dbx
/ 2);
1444 for (x
= 0; x
< width
; x
++) {
1445 *(xt
++) = (unsigned long) (xr
* xr
);
1446 *(xt
++) = (unsigned long) (xg
* xg
);
1447 *(xt
++) = (unsigned long) (xb
* xb
);
1459 for (y
= 0; y
< height
; y
++) {
1460 *(yt
++) = (unsigned long) (yr
* yr
);
1461 *(yt
++) = (unsigned long) (yg
* yg
);
1462 *(yt
++) = (unsigned long) (yb
* yb
);
1469 // Combine tables to create gradient
1476 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1477 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1478 *(pr
++) = (unsigned char)
1479 (tr
- (rsign
* control
.getSqrt(*(xt
++) + *(yt
))));
1480 *(pg
++) = (unsigned char)
1481 (tg
- (gsign
* control
.getSqrt(*(xt
++) + *(yt
+ 1))));
1482 *(pb
++) = (unsigned char)
1483 (tb
- (bsign
* control
.getSqrt(*(xt
++) + *(yt
+ 2))));
1489 // faked interlacing effect
1490 unsigned char channel
, channel2
;
1492 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1493 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1495 channel
= (unsigned char)
1496 (tr
- (rsign
* control
.getSqrt(*(xt
++) + *(yt
))));
1497 channel2
= (channel
>> 1) + (channel
>> 2);
1498 if (channel2
> channel
) channel2
= 0;
1501 channel
= (unsigned char)
1502 (tg
- (gsign
* control
.getSqrt(*(xt
++) + *(yt
+ 1))));
1503 channel2
= (channel
>> 1) + (channel
>> 2);
1504 if (channel2
> channel
) channel2
= 0;
1507 channel
= (unsigned char)
1508 (tb
- (bsign
* control
.getSqrt(*(xt
++) + *(yt
+ 2))));
1509 channel2
= (channel
>> 1) + (channel
>> 2);
1510 if (channel2
> channel
) channel2
= 0;
1513 channel
= (unsigned char)
1514 (tr
- (rsign
* control
.getSqrt(*(xt
++) + *(yt
))));
1515 channel2
= channel
+ (channel
>> 3);
1516 if (channel2
< channel
) channel2
= ~0;
1519 channel
= (unsigned char)
1520 (tg
- (gsign
* control
.getSqrt(*(xt
++) + *(yt
+ 1))));
1521 channel2
= channel
+ (channel
>> 3);
1522 if (channel2
< channel
) channel2
= ~0;
1525 channel
= (unsigned char)
1526 (tb
- (bsign
* control
.getSqrt(*(xt
++) + *(yt
+ 2))));
1527 channel2
= channel
+ (channel
>> 3);
1528 if (channel2
< channel
) channel2
= ~0;
1538 void BImage::pcgradient(void) {
1539 // pipe cross gradient - based on original dgradient, written by
1540 // Mosfet (mosfet@kde.org)
1541 // adapted from kde sources for Openbox by Brad Hughes
1543 float drx
, dgx
, dbx
, dry
, dgy
, dby
, xr
, xg
, xb
, yr
, yg
, yb
;
1544 int rsign
, gsign
, bsign
;
1545 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1546 unsigned int *xt
= xtable
, *yt
= ytable
,
1548 tg
= to
->getGreen(),
1551 register unsigned int x
, y
;
1553 dry
= drx
= (float) (to
->getRed() - from
->getRed());
1554 dgy
= dgx
= (float) (to
->getGreen() - from
->getGreen());
1555 dby
= dbx
= (float) (to
->getBlue() - from
->getBlue());
1557 rsign
= (drx
< 0) ? -2 : 2;
1558 gsign
= (dgx
< 0) ? -2 : 2;
1559 bsign
= (dbx
< 0) ? -2 : 2;
1561 xr
= yr
= (drx
/ 2);
1562 xg
= yg
= (dgx
/ 2);
1563 xb
= yb
= (dbx
/ 2);
1570 for (x
= 0; x
< width
; x
++) {
1571 *(xt
++) = (unsigned char) ((xr
< 0) ? -xr
: xr
);
1572 *(xt
++) = (unsigned char) ((xg
< 0) ? -xg
: xg
);
1573 *(xt
++) = (unsigned char) ((xb
< 0) ? -xb
: xb
);
1585 for (y
= 0; y
< height
; y
++) {
1586 *(yt
++) = ((unsigned char) ((yr
< 0) ? -yr
: yr
));
1587 *(yt
++) = ((unsigned char) ((yg
< 0) ? -yg
: yg
));
1588 *(yt
++) = ((unsigned char) ((yb
< 0) ? -yb
: yb
));
1595 // Combine tables to create gradient
1601 // normal pcgradient
1602 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1603 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1604 *(pr
++) = (unsigned char) (tr
- (rsign
* min(*(xt
++), *(yt
))));
1605 *(pg
++) = (unsigned char) (tg
- (gsign
* min(*(xt
++), *(yt
+ 1))));
1606 *(pb
++) = (unsigned char) (tb
- (bsign
* min(*(xt
++), *(yt
+ 2))));
1612 // faked interlacing effect
1613 unsigned char channel
, channel2
;
1615 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1616 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1618 channel
= (unsigned char) (tr
- (rsign
* min(*(xt
++), *(yt
))));
1619 channel2
= (channel
>> 1) + (channel
>> 2);
1620 if (channel2
> channel
) channel2
= 0;
1623 channel
= (unsigned char) (tg
- (bsign
* min(*(xt
++), *(yt
+ 1))));
1624 channel2
= (channel
>> 1) + (channel
>> 2);
1625 if (channel2
> channel
) channel2
= 0;
1628 channel
= (unsigned char) (tb
- (gsign
* min(*(xt
++), *(yt
+ 2))));
1629 channel2
= (channel
>> 1) + (channel
>> 2);
1630 if (channel2
> channel
) channel2
= 0;
1633 channel
= (unsigned char) (tr
- (rsign
* min(*(xt
++), *(yt
))));
1634 channel2
= channel
+ (channel
>> 3);
1635 if (channel2
< channel
) channel2
= ~0;
1638 channel
= (unsigned char) (tg
- (gsign
* min(*(xt
++), *(yt
+ 1))));
1639 channel2
= channel
+ (channel
>> 3);
1640 if (channel2
< channel
) channel2
= ~0;
1643 channel
= (unsigned char) (tb
- (bsign
* min(*(xt
++), *(yt
+ 2))));
1644 channel2
= channel
+ (channel
>> 3);
1645 if (channel2
< channel
) channel2
= ~0;
1655 void BImage::cdgradient(void) {
1656 // cross diagonal gradient - based on original dgradient, written by
1657 // Mosfet (mosfet@kde.org)
1658 // adapted from kde sources for Openbox by Brad Hughes
1660 float drx
, dgx
, dbx
, dry
, dgy
, dby
, yr
= 0.0, yg
= 0.0, yb
= 0.0,
1661 xr
= (float) from
->getRed(),
1662 xg
= (float) from
->getGreen(),
1663 xb
= (float) from
->getBlue();
1664 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1665 unsigned int w
= width
* 2, h
= height
* 2, *xt
, *yt
;
1667 register unsigned int x
, y
;
1669 dry
= drx
= (float) (to
->getRed() - from
->getRed());
1670 dgy
= dgx
= (float) (to
->getGreen() - from
->getGreen());
1671 dby
= dbx
= (float) (to
->getBlue() - from
->getBlue());
1678 for (xt
= (xtable
+ (width
* 3) - 1), x
= 0; x
< width
; x
++) {
1679 *(xt
--) = (unsigned char) xb
;
1680 *(xt
--) = (unsigned char) xg
;
1681 *(xt
--) = (unsigned char) xr
;
1693 for (yt
= ytable
, y
= 0; y
< height
; y
++) {
1694 *(yt
++) = (unsigned char) yr
;
1695 *(yt
++) = (unsigned char) yg
;
1696 *(yt
++) = (unsigned char) yb
;
1703 // Combine tables to create gradient
1709 // normal cdgradient
1710 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1711 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1712 *(pr
++) = *(xt
++) + *(yt
);
1713 *(pg
++) = *(xt
++) + *(yt
+ 1);
1714 *(pb
++) = *(xt
++) + *(yt
+ 2);
1720 // faked interlacing effect
1721 unsigned char channel
, channel2
;
1723 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1724 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1726 channel
= *(xt
++) + *(yt
);
1727 channel2
= (channel
>> 1) + (channel
>> 2);
1728 if (channel2
> channel
) channel2
= 0;
1731 channel
= *(xt
++) + *(yt
+ 1);
1732 channel2
= (channel
>> 1) + (channel
>> 2);
1733 if (channel2
> channel
) channel2
= 0;
1736 channel
= *(xt
++) + *(yt
+ 2);
1737 channel2
= (channel
>> 1) + (channel
>> 2);
1738 if (channel2
> channel
) channel2
= 0;
1741 channel
= *(xt
++) + *(yt
);
1742 channel2
= channel
+ (channel
>> 3);
1743 if (channel2
< channel
) channel2
= ~0;
1746 channel
= *(xt
++) + *(yt
+ 1);
1747 channel2
= channel
+ (channel
>> 3);
1748 if (channel2
< channel
) channel2
= ~0;
1751 channel
= *(xt
++) + *(yt
+ 2);
1752 channel2
= channel
+ (channel
>> 3);
1753 if (channel2
< channel
) channel2
= ~0;
1763 BImageControl::BImageControl(BaseDisplay
&dpy
, ScreenInfo
&scrn
, Bool _dither
,
1764 int _cpc
, unsigned long cache_timeout
,
1765 unsigned long cmax
) : basedisplay(dpy
),
1769 setColorsPerChannel(_cpc
);
1773 if (cache_timeout
) {
1774 timer
= new BTimer(basedisplay
, *this);
1775 timer
->setTimeout(cache_timeout
);
1778 timer
= (BTimer
*) 0;
1779 #endif // TIMEDCACHE
1781 colors
= (XColor
*) 0;
1784 grad_xbuffer
= grad_ybuffer
= (unsigned int *) 0;
1785 grad_buffer_width
= grad_buffer_height
= 0;
1787 sqrt_table
= (unsigned long *) 0;
1789 screen_depth
= screeninfo
.getDepth();
1790 window
= screeninfo
.getRootWindow();
1791 screen_number
= screeninfo
.getScreenNumber();
1794 XPixmapFormatValues
*pmv
= XListPixmapFormats(basedisplay
.getXDisplay(),
1796 colormap
= screeninfo
.getColormap();
1800 for (int i
= 0; i
< count
; i
++)
1801 if (pmv
[i
].depth
== screen_depth
) {
1802 bits_per_pixel
= pmv
[i
].bits_per_pixel
;
1809 if (bits_per_pixel
== 0) bits_per_pixel
= screen_depth
;
1810 if (bits_per_pixel
>= 24) setDither(False
);
1812 red_offset
= green_offset
= blue_offset
= 0;
1814 switch (getVisual()->c_class
) {
1819 // compute color tables
1820 unsigned long red_mask
= getVisual()->red_mask
,
1821 green_mask
= getVisual()->green_mask
,
1822 blue_mask
= getVisual()->blue_mask
;
1824 while (! (red_mask
& 1)) { red_offset
++; red_mask
>>= 1; }
1825 while (! (green_mask
& 1)) { green_offset
++; green_mask
>>= 1; }
1826 while (! (blue_mask
& 1)) { blue_offset
++; blue_mask
>>= 1; }
1828 red_bits
= 255 / red_mask
;
1829 green_bits
= 255 / green_mask
;
1830 blue_bits
= 255 / blue_mask
;
1832 for (i
= 0; i
< 256; i
++) {
1833 red_color_table
[i
] = i
/ red_bits
;
1834 green_color_table
[i
] = i
/ green_bits
;
1835 blue_color_table
[i
] = i
/ blue_bits
;
1844 ncolors
= colors_per_channel
* colors_per_channel
* colors_per_channel
;
1846 if (ncolors
> (1 << screen_depth
)) {
1847 colors_per_channel
= (1 << screen_depth
) / 3;
1848 ncolors
= colors_per_channel
* colors_per_channel
* colors_per_channel
;
1851 if (colors_per_channel
< 2 || ncolors
> (1 << screen_depth
)) {
1852 fprintf(stderr
, i18n
->getMessage(ImageSet
, ImageInvalidColormapSize
,
1853 "BImageControl::BImageControl: invalid colormap size %d "
1854 "(%d/%d/%d) - reducing"),
1855 ncolors
, colors_per_channel
, colors_per_channel
,
1856 colors_per_channel
);
1858 colors_per_channel
= (1 << screen_depth
) / 3;
1861 colors
= new XColor
[ncolors
];
1863 fprintf(stderr
, i18n
->getMessage(ImageSet
,
1864 ImageErrorAllocatingColormap
,
1865 "BImageControl::BImageControl: error allocating "
1870 int i
= 0, ii
, p
, r
, g
, b
,
1872 #ifdef ORDEREDPSEUDO
1873 bits
= 256 / colors_per_channel
;
1874 #else // !ORDEREDPSEUDO
1875 bits
= 255 / (colors_per_channel
- 1);
1876 #endif // ORDEREDPSEUDO
1878 red_bits
= green_bits
= blue_bits
= bits
;
1880 for (i
= 0; i
< 256; i
++)
1881 red_color_table
[i
] = green_color_table
[i
] = blue_color_table
[i
] =
1884 for (r
= 0, i
= 0; r
< colors_per_channel
; r
++)
1885 for (g
= 0; g
< colors_per_channel
; g
++)
1886 for (b
= 0; b
< colors_per_channel
; b
++, i
++) {
1887 colors
[i
].red
= (r
* 0xffff) / (colors_per_channel
- 1);
1888 colors
[i
].green
= (g
* 0xffff) / (colors_per_channel
- 1);
1889 colors
[i
].blue
= (b
* 0xffff) / (colors_per_channel
- 1);;
1890 colors
[i
].flags
= DoRed
|DoGreen
|DoBlue
;
1895 for (i
= 0; i
< ncolors
; i
++)
1896 if (! XAllocColor(basedisplay
.getXDisplay(), colormap
, &colors
[i
])) {
1897 fprintf(stderr
, i18n
->getMessage(ImageSet
, ImageColorAllocFail
,
1898 "couldn't alloc color %i %i %i\n"),
1899 colors
[i
].red
, colors
[i
].green
, colors
[i
].blue
);
1900 colors
[i
].flags
= 0;
1902 colors
[i
].flags
= DoRed
|DoGreen
|DoBlue
;
1904 basedisplay
.ungrab();
1906 XColor icolors
[256];
1907 int incolors
= (((1 << screen_depth
) > 256) ? 256 : (1 << screen_depth
));
1909 for (i
= 0; i
< incolors
; i
++)
1910 icolors
[i
].pixel
= i
;
1912 XQueryColors(basedisplay
.getXDisplay(), colormap
, icolors
, incolors
);
1913 for (i
= 0; i
< ncolors
; i
++) {
1914 if (! colors
[i
].flags
) {
1915 unsigned long chk
= 0xffffffff, pixel
, close
= 0;
1919 for (ii
= 0; ii
< incolors
; ii
++) {
1920 r
= (colors
[i
].red
- icolors
[i
].red
) >> 8;
1921 g
= (colors
[i
].green
- icolors
[i
].green
) >> 8;
1922 b
= (colors
[i
].blue
- icolors
[i
].blue
) >> 8;
1923 pixel
= (r
* r
) + (g
* g
) + (b
* b
);
1930 colors
[i
].red
= icolors
[close
].red
;
1931 colors
[i
].green
= icolors
[close
].green
;
1932 colors
[i
].blue
= icolors
[close
].blue
;
1934 if (XAllocColor(basedisplay
.getXDisplay(), colormap
,
1936 colors
[i
].flags
= DoRed
|DoGreen
|DoBlue
;
1951 if (getVisual()->c_class
== StaticGray
) {
1952 ncolors
= 1 << screen_depth
;
1954 ncolors
= colors_per_channel
* colors_per_channel
* colors_per_channel
;
1956 if (ncolors
> (1 << screen_depth
)) {
1957 colors_per_channel
= (1 << screen_depth
) / 3;
1959 colors_per_channel
* colors_per_channel
* colors_per_channel
;
1963 if (colors_per_channel
< 2 || ncolors
> (1 << screen_depth
)) {
1964 fprintf(stderr
, i18n
->getMessage(ImageSet
, ImageInvalidColormapSize
,
1965 "BImageControl::BImageControl: invalid colormap size %d "
1966 "(%d/%d/%d) - reducing"),
1967 ncolors
, colors_per_channel
, colors_per_channel
,
1968 colors_per_channel
);
1970 colors_per_channel
= (1 << screen_depth
) / 3;
1973 colors
= new XColor
[ncolors
];
1975 fprintf(stderr
, i18n
->getMessage(ImageSet
,
1976 ImageErrorAllocatingColormap
,
1977 "BImageControl::BImageControl: error allocating "
1982 int i
= 0, ii
, p
, bits
= 255 / (colors_per_channel
- 1);
1983 red_bits
= green_bits
= blue_bits
= bits
;
1985 for (i
= 0; i
< 256; i
++)
1986 red_color_table
[i
] = green_color_table
[i
] = blue_color_table
[i
] =
1990 for (i
= 0; i
< ncolors
; i
++) {
1991 colors
[i
].red
= (i
* 0xffff) / (colors_per_channel
- 1);
1992 colors
[i
].green
= (i
* 0xffff) / (colors_per_channel
- 1);
1993 colors
[i
].blue
= (i
* 0xffff) / (colors_per_channel
- 1);;
1994 colors
[i
].flags
= DoRed
|DoGreen
|DoBlue
;
1996 if (! XAllocColor(basedisplay
.getXDisplay(), colormap
,
1998 fprintf(stderr
, i18n
->getMessage(ImageSet
, ImageColorAllocFail
,
1999 "couldn't alloc color %i %i %i\n"),
2000 colors
[i
].red
, colors
[i
].green
, colors
[i
].blue
);
2001 colors
[i
].flags
= 0;
2003 colors
[i
].flags
= DoRed
|DoGreen
|DoBlue
;
2006 basedisplay
.ungrab();
2008 XColor icolors
[256];
2009 int incolors
= (((1 << screen_depth
) > 256) ? 256 :
2010 (1 << screen_depth
));
2012 for (i
= 0; i
< incolors
; i
++)
2013 icolors
[i
].pixel
= i
;
2015 XQueryColors(basedisplay
.getXDisplay(), colormap
, icolors
, incolors
);
2016 for (i
= 0; i
< ncolors
; i
++) {
2017 if (! colors
[i
].flags
) {
2018 unsigned long chk
= 0xffffffff, pixel
, close
= 0;
2022 for (ii
= 0; ii
< incolors
; ii
++) {
2023 int r
= (colors
[i
].red
- icolors
[i
].red
) >> 8;
2024 int g
= (colors
[i
].green
- icolors
[i
].green
) >> 8;
2025 int b
= (colors
[i
].blue
- icolors
[i
].blue
) >> 8;
2026 pixel
= (r
* r
) + (g
* g
) + (b
* b
);
2033 colors
[i
].red
= icolors
[close
].red
;
2034 colors
[i
].green
= icolors
[close
].green
;
2035 colors
[i
].blue
= icolors
[close
].blue
;
2037 if (XAllocColor(basedisplay
.getXDisplay(), colormap
,
2039 colors
[i
].flags
= DoRed
|DoGreen
|DoBlue
;
2051 fprintf(stderr
, i18n
->getMessage(ImageSet
, ImageUnsupVisual
,
2052 "BImageControl::BImageControl: unsupported visual %d\n"),
2053 getVisual()->c_class
);
2057 cache
= new LinkedList
<Cache
>;
2061 BImageControl::~BImageControl(void) {
2063 delete [] sqrt_table
;
2067 delete [] grad_xbuffer
;
2071 delete [] grad_ybuffer
;
2075 unsigned long *pixels
= new unsigned long [ncolors
];
2078 for (i
= 0; i
< ncolors
; i
++)
2079 *(pixels
+ i
) = (*(colors
+ i
)).pixel
;
2081 XFreeColors(basedisplay
.getXDisplay(), colormap
, pixels
, ncolors
, 0);
2086 if (cache
->count()) {
2087 int i
, n
= cache
->count();
2088 fprintf(stderr
, i18n
->getMessage(ImageSet
, ImagePixmapRelease
,
2089 "BImageContol::~BImageControl: pixmap cache - "
2090 "releasing %d pixmaps\n"), n
);
2092 for (i
= 0; i
< n
; i
++) {
2093 Cache
*tmp
= cache
->first();
2094 XFreePixmap(basedisplay
.getXDisplay(), tmp
->pixmap
);
2104 #endif // TIMEDCACHE
2111 Pixmap
BImageControl::searchCache(unsigned int width
, unsigned int height
,
2112 unsigned long texture
,
2113 BColor
*c1
, BColor
*c2
) {
2114 if (cache
->count()) {
2115 LinkedListIterator
<Cache
> it(cache
);
2117 for (Cache
*tmp
= it
.current(); tmp
; it
++, tmp
= it
.current()) {
2118 if ((tmp
->width
== width
) && (tmp
->height
== height
) &&
2119 (tmp
->texture
== texture
) && (tmp
->pixel1
== c1
->getPixel()))
2120 if (texture
& BImage_Gradient
) {
2121 if (tmp
->pixel2
== c2
->getPixel()) {
2136 Pixmap
BImageControl::renderImage(unsigned int width
, unsigned int height
,
2137 BTexture
*texture
) {
2138 if (texture
->getTexture() & BImage_ParentRelative
) return ParentRelative
;
2140 Pixmap pixmap
= searchCache(width
, height
, texture
->getTexture(),
2141 texture
->getColor(), texture
->getColorTo());
2142 if (pixmap
) return pixmap
;
2144 BImage
image(*this, width
, height
);
2145 pixmap
= image
.render(texture
);
2148 Cache
*tmp
= new Cache
;
2150 tmp
->pixmap
= pixmap
;
2152 tmp
->height
= height
;
2154 tmp
->texture
= texture
->getTexture();
2155 tmp
->pixel1
= texture
->getColor()->getPixel();
2157 if (texture
->getTexture() & BImage_Gradient
)
2158 tmp
->pixel2
= texture
->getColorTo()->getPixel();
2164 if ((unsigned) cache
->count() > cache_max
) {
2166 fprintf(stderr
, i18n
->getMessage(ImageSet
, ImagePixmapCacheLarge
,
2167 "BImageControl::renderImage: cache is large, "
2168 "forcing cleanout\n"));
2181 void BImageControl::removeImage(Pixmap pixmap
) {
2183 LinkedListIterator
<Cache
> it(cache
);
2184 for (Cache
*tmp
= it
.current(); tmp
; it
++, tmp
= it
.current()) {
2185 if (tmp
->pixmap
== pixmap
) {
2190 if (! timer
) timeout();
2191 #else // !TIMEDCACHE
2192 if (! tmp
->count
) timeout();
2193 #endif // TIMEDCACHE
2203 unsigned long BImageControl::getColor(const char *colorname
,
2204 unsigned char *r
, unsigned char *g
,
2210 if (! XParseColor(basedisplay
.getXDisplay(), colormap
, colorname
, &color
))
2211 fprintf(stderr
, "BImageControl::getColor: color parse error: \"%s\"\n",
2213 else if (! XAllocColor(basedisplay
.getXDisplay(), colormap
, &color
))
2214 fprintf(stderr
, "BImageControl::getColor: color alloc error: \"%s\"\n",
2217 if (color
.red
== 65535) *r
= 0xff;
2218 else *r
= (unsigned char) (color
.red
/ 0xff);
2219 if (color
.green
== 65535) *g
= 0xff;
2220 else *g
= (unsigned char) (color
.green
/ 0xff);
2221 if (color
.blue
== 65535) *b
= 0xff;
2222 else *b
= (unsigned char) (color
.blue
/ 0xff);
2228 unsigned long BImageControl::getColor(const char *colorname
) {
2232 if (! XParseColor(basedisplay
.getXDisplay(), colormap
, colorname
, &color
))
2233 fprintf(stderr
, "BImageControl::getColor: color parse error: \"%s\"\n",
2235 else if (! XAllocColor(basedisplay
.getXDisplay(), colormap
, &color
))
2236 fprintf(stderr
, "BImageControl::getColor: color alloc error: \"%s\"\n",
2243 void BImageControl::getColorTables(unsigned char **rmt
, unsigned char **gmt
,
2244 unsigned char **bmt
,
2245 int *roff
, int *goff
, int *boff
,
2246 int *rbit
, int *gbit
, int *bbit
) {
2247 if (rmt
) *rmt
= red_color_table
;
2248 if (gmt
) *gmt
= green_color_table
;
2249 if (bmt
) *bmt
= blue_color_table
;
2251 if (roff
) *roff
= red_offset
;
2252 if (goff
) *goff
= green_offset
;
2253 if (boff
) *boff
= blue_offset
;
2255 if (rbit
) *rbit
= red_bits
;
2256 if (gbit
) *gbit
= green_bits
;
2257 if (bbit
) *bbit
= blue_bits
;
2261 void BImageControl::getXColorTable(XColor
**c
, int *n
) {
2263 if (n
) *n
= ncolors
;
2267 void BImageControl::getGradientBuffers(unsigned int w
,
2269 unsigned int **xbuf
,
2270 unsigned int **ybuf
)
2272 if (w
> grad_buffer_width
) {
2274 delete [] grad_xbuffer
;
2277 grad_buffer_width
= w
;
2279 grad_xbuffer
= new unsigned int[grad_buffer_width
* 3];
2282 if (h
> grad_buffer_height
) {
2284 delete [] grad_ybuffer
;
2287 grad_buffer_height
= h
;
2289 grad_ybuffer
= new unsigned int[grad_buffer_height
* 3];
2292 *xbuf
= grad_xbuffer
;
2293 *ybuf
= grad_ybuffer
;
2297 void BImageControl::installRootColormap(void) {
2300 Bool install
= True
;
2301 int i
= 0, ncmap
= 0;
2303 XListInstalledColormaps(basedisplay
.getXDisplay(), window
, &ncmap
);
2306 for (i
= 0; i
< ncmap
; i
++)
2307 if (*(cmaps
+ i
) == colormap
)
2311 XInstallColormap(basedisplay
.getXDisplay(), colormap
);
2316 basedisplay
.ungrab();
2320 void BImageControl::setColorsPerChannel(int cpc
) {
2321 if (cpc
< 2) cpc
= 2;
2322 if (cpc
> 6) cpc
= 6;
2324 colors_per_channel
= cpc
;
2328 unsigned long BImageControl::getSqrt(unsigned int x
) {
2330 // build sqrt table for use with elliptic gradient
2332 sqrt_table
= new unsigned long[(256 * 256 * 2) + 1];
2335 for (; i
< (256 * 256 * 2); i
++)
2336 *(sqrt_table
+ i
) = bsqrt(i
);
2339 return (*(sqrt_table
+ x
));
2343 void BImageControl::parseTexture(BTexture
*texture
, const char *t
) {
2344 if ((! texture
) || (! t
)) return;
2346 int t_len
= strlen(t
) + 1, i
;
2347 char *ts
= new char[t_len
];
2350 // convert to lower case
2351 for (i
= 0; i
< t_len
; i
++)
2352 *(ts
+ i
) = tolower(*(t
+ i
));
2354 if (strstr(ts
, "parentrelative")) {
2355 texture
->setTexture(BImage_ParentRelative
);
2357 texture
->setTexture(0);
2359 if (strstr(ts
, "solid"))
2360 texture
->addTexture(BImage_Solid
);
2361 else if (strstr(ts
, "gradient")) {
2362 texture
->addTexture(BImage_Gradient
);
2363 if (strstr(ts
, "crossdiagonal"))
2364 texture
->addTexture(BImage_CrossDiagonal
);
2365 else if (strstr(ts
, "rectangle"))
2366 texture
->addTexture(BImage_Rectangle
);
2367 else if (strstr(ts
, "pyramid"))
2368 texture
->addTexture(BImage_Pyramid
);
2369 else if (strstr(ts
, "pipecross"))
2370 texture
->addTexture(BImage_PipeCross
);
2371 else if (strstr(ts
, "elliptic"))
2372 texture
->addTexture(BImage_Elliptic
);
2373 else if (strstr(ts
, "diagonal"))
2374 texture
->addTexture(BImage_Diagonal
);
2375 else if (strstr(ts
, "horizontal"))
2376 texture
->addTexture(BImage_Horizontal
);
2377 else if (strstr(ts
, "vertical"))
2378 texture
->addTexture(BImage_Vertical
);
2380 texture
->addTexture(BImage_Diagonal
);
2382 texture
->addTexture(BImage_Solid
);
2384 if (strstr(ts
, "raised"))
2385 texture
->addTexture(BImage_Raised
);
2386 else if (strstr(ts
, "sunken"))
2387 texture
->addTexture(BImage_Sunken
);
2388 else if (strstr(ts
, "flat"))
2389 texture
->addTexture(BImage_Flat
);
2391 texture
->addTexture(BImage_Raised
);
2393 if (! (texture
->getTexture() & BImage_Flat
))
2394 if (strstr(ts
, "bevel2"))
2395 texture
->addTexture(BImage_Bevel2
);
2397 texture
->addTexture(BImage_Bevel1
);
2400 if (strstr(ts
, "interlaced"))
2401 texture
->addTexture(BImage_Interlaced
);
2409 void BImageControl::parseColor(BColor
*color
, const char *c
) {
2410 if (! color
) return;
2412 if (color
->isAllocated()) {
2413 unsigned long pixel
= color
->getPixel();
2415 XFreeColors(basedisplay
.getXDisplay(), colormap
, &pixel
, 1, 0);
2417 color
->setPixel(0l);
2418 color
->setRGB(0, 0, 0);
2419 color
->setAllocated(False
);
2423 unsigned char r
, g
, b
;
2425 color
->setPixel(getColor(c
, &r
, &g
, &b
));
2426 color
->setRGB(r
, g
, b
);
2427 color
->setAllocated(True
);
2432 void BImageControl::timeout(void) {
2433 LinkedListIterator
<Cache
> it(cache
);
2434 for (Cache
*tmp
= it
.current(); tmp
; it
++, tmp
= it
.current()) {
2435 if (tmp
->count
<= 0) {
2436 XFreePixmap(basedisplay
.getXDisplay(), tmp
->pixmap
);