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
) {
87 width
= ((signed) w
> 0) ? w
: 1;
88 height
= ((signed) h
> 0) ? h
: 1;
90 red
= new unsigned char[width
* height
];
91 green
= new unsigned char[width
* height
];
92 blue
= new unsigned char[width
* height
];
94 xtable
= ytable
= (unsigned int *) 0;
96 cpc
= control
->getColorsPerChannel();
99 control
->getColorTables(&red_table
, &green_table
, &blue_table
,
100 &red_offset
, &green_offset
, &blue_offset
,
101 &red_bits
, &green_bits
, &blue_bits
);
103 if (control
->getVisual()->c_class
!= TrueColor
)
104 control
->getXColorTable(&colors
, &ncolors
);
108 BImage::~BImage(void) {
109 if (red
) delete [] red
;
110 if (green
) delete [] green
;
111 if (blue
) delete [] blue
;
115 Pixmap
BImage::render(BTexture
*texture
) {
116 if (texture
->getTexture() & BImage_ParentRelative
)
117 return ParentRelative
;
118 else if (texture
->getTexture() & BImage_Solid
)
119 return render_solid(texture
);
120 else if (texture
->getTexture() & BImage_Gradient
)
121 return render_gradient(texture
);
127 Pixmap
BImage::render_solid(BTexture
*texture
) {
128 Pixmap pixmap
= XCreatePixmap(control
->getBaseDisplay()->getXDisplay(),
129 control
->getDrawable(), width
,
130 height
, control
->getDepth());
131 if (pixmap
== None
) {
132 fprintf(stderr
, i18n
->getMessage(ImageSet
, ImageErrorCreatingSolidPixmap
,
133 "BImage::render_solid: error creating pixmap\n"));
140 gcv
.foreground
= texture
->getColor()->getPixel();
141 gcv
.fill_style
= FillSolid
;
142 gc
= XCreateGC(control
->getBaseDisplay()->getXDisplay(), pixmap
,
143 GCForeground
| GCFillStyle
, &gcv
);
145 gcv
.foreground
= texture
->getHiColor()->getPixel();
146 hgc
= XCreateGC(control
->getBaseDisplay()->getXDisplay(), pixmap
,
149 gcv
.foreground
= texture
->getLoColor()->getPixel();
150 lgc
= XCreateGC(control
->getBaseDisplay()->getXDisplay(), pixmap
,
153 XFillRectangle(control
->getBaseDisplay()->getXDisplay(), pixmap
, gc
, 0, 0,
157 if (texture
->getTexture() & BImage_Interlaced
) {
158 gcv
.foreground
= texture
->getColorTo()->getPixel();
159 GC igc
= XCreateGC(control
->getBaseDisplay()->getXDisplay(), pixmap
,
162 register unsigned int i
= 0;
163 for (; i
< height
; i
+= 2)
164 XDrawLine(control
->getBaseDisplay()->getXDisplay(), pixmap
, igc
,
167 XFreeGC(control
->getBaseDisplay()->getXDisplay(), igc
);
172 if (texture
->getTexture() & BImage_Bevel1
) {
173 if (texture
->getTexture() & BImage_Raised
) {
174 XDrawLine(control
->getBaseDisplay()->getXDisplay(), pixmap
, lgc
,
175 0, height
- 1, width
- 1, height
- 1);
176 XDrawLine(control
->getBaseDisplay()->getXDisplay(), pixmap
, lgc
,
177 width
- 1, height
- 1, width
- 1, 0);
179 XDrawLine(control
->getBaseDisplay()->getXDisplay(), pixmap
, hgc
,
181 XDrawLine(control
->getBaseDisplay()->getXDisplay(), pixmap
, hgc
,
182 0, height
- 1, 0, 0);
183 } else if (texture
->getTexture() & BImage_Sunken
) {
184 XDrawLine(control
->getBaseDisplay()->getXDisplay(), pixmap
, hgc
,
185 0, height
- 1, width
- 1, height
- 1);
186 XDrawLine(control
->getBaseDisplay()->getXDisplay(), pixmap
, hgc
,
187 width
- 1, height
- 1, width
- 1, 0);
189 XDrawLine(control
->getBaseDisplay()->getXDisplay(), pixmap
, lgc
,
191 XDrawLine(control
->getBaseDisplay()->getXDisplay(), pixmap
, lgc
,
192 0, height
- 1, 0, 0);
194 } else if (texture
->getTexture() & BImage_Bevel2
) {
195 if (texture
->getTexture() & BImage_Raised
) {
196 XDrawLine(control
->getBaseDisplay()->getXDisplay(), pixmap
, lgc
,
197 1, height
- 3, width
- 3, height
- 3);
198 XDrawLine(control
->getBaseDisplay()->getXDisplay(), pixmap
, lgc
,
199 width
- 3, height
- 3, width
- 3, 1);
201 XDrawLine(control
->getBaseDisplay()->getXDisplay(), pixmap
, hgc
,
203 XDrawLine(control
->getBaseDisplay()->getXDisplay(), pixmap
, hgc
,
204 1, height
- 3, 1, 1);
205 } else if (texture
->getTexture() & BImage_Sunken
) {
206 XDrawLine(control
->getBaseDisplay()->getXDisplay(), pixmap
, hgc
,
207 1, height
- 3, width
- 3, height
- 3);
208 XDrawLine(control
->getBaseDisplay()->getXDisplay(), pixmap
, hgc
,
209 width
- 3, height
- 3, width
- 3, 1);
211 XDrawLine(control
->getBaseDisplay()->getXDisplay(), pixmap
, lgc
,
213 XDrawLine(control
->getBaseDisplay()->getXDisplay(), pixmap
, lgc
,
214 1, height
- 3, 1, 1);
218 XFreeGC(control
->getBaseDisplay()->getXDisplay(), gc
);
219 XFreeGC(control
->getBaseDisplay()->getXDisplay(), hgc
);
220 XFreeGC(control
->getBaseDisplay()->getXDisplay(), lgc
);
226 Pixmap
BImage::render_gradient(BTexture
*texture
) {
230 interlaced
= texture
->getTexture() & BImage_Interlaced
;
233 if (texture
->getTexture() & BImage_Sunken
) {
234 from
= texture
->getColorTo();
235 to
= texture
->getColor();
237 if (! (texture
->getTexture() & BImage_Invert
)) inverted
= 1;
239 from
= texture
->getColor();
240 to
= texture
->getColorTo();
242 if (texture
->getTexture() & BImage_Invert
) inverted
= 1;
245 control
->getGradientBuffers(width
, height
, &xtable
, &ytable
);
247 if (texture
->getTexture() & BImage_Diagonal
) dgradient();
248 else if (texture
->getTexture() & BImage_Elliptic
) egradient();
249 else if (texture
->getTexture() & BImage_Horizontal
) hgradient();
250 else if (texture
->getTexture() & BImage_Pyramid
) pgradient();
251 else if (texture
->getTexture() & BImage_Rectangle
) rgradient();
252 else if (texture
->getTexture() & BImage_Vertical
) vgradient();
253 else if (texture
->getTexture() & BImage_CrossDiagonal
) cdgradient();
254 else if (texture
->getTexture() & BImage_PipeCross
) pcgradient();
256 if (texture
->getTexture() & BImage_Bevel1
) bevel1();
257 else if (texture
->getTexture() & BImage_Bevel2
) bevel2();
259 if (inverted
) invert();
261 Pixmap pixmap
= renderPixmap();
268 XImage
*BImage::renderXImage(void) {
270 XCreateImage(control
->getBaseDisplay()->getXDisplay(),
271 control
->getVisual(), control
->getDepth(), ZPixmap
, 0, 0,
272 width
, height
, 32, 0);
275 fprintf(stderr
, i18n
->getMessage(ImageSet
, ImageErrorCreatingXImage
,
276 "BImage::renderXImage: error creating XImage\n"));
281 image
->data
= (char *) 0;
283 unsigned char *d
= new unsigned char[image
->bytes_per_line
* (height
+ 1)];
284 register unsigned int x
, y
, dithx
, dithy
, r
, g
, b
, o
, er
, eg
, eb
, offset
;
286 unsigned char *pixel_data
= d
, *ppixel_data
= d
;
289 o
= image
->bits_per_pixel
+ ((image
->byte_order
== MSBFirst
) ? 1 : 0);
291 if (control
->doDither() && width
> 1 && height
> 1) {
292 unsigned char dither4
[4][4] = { {0, 4, 1, 5},
298 unsigned char dither8
[8][8] = { { 0, 32, 8, 40, 2, 34, 10, 42 },
299 { 48, 16, 56, 24, 50, 18, 58, 26 },
300 { 12, 44, 4, 36, 14, 46, 6, 38 },
301 { 60, 28, 52, 20, 62, 30, 54, 22 },
302 { 3, 35, 11, 43, 1, 33, 9, 41 },
303 { 51, 19, 59, 27, 49, 17, 57, 25 },
304 { 15, 47, 7, 39, 13, 45, 5, 37 },
305 { 63, 31, 55, 23, 61, 29, 53, 21 } };
306 #endif // ORDEREDPSEUDO
308 switch (control
->getVisual()->c_class
) {
310 // algorithm: ordered dithering... many many thanks to rasterman
311 // (raster@rasterman.com) for telling me about this... portions of this
312 // code is based off of his code in Imlib
313 for (y
= 0, offset
= 0; y
< height
; y
++) {
316 for (x
= 0; x
< width
; x
++, offset
++) {
322 er
= r
& (red_bits
- 1);
323 eg
= g
& (green_bits
- 1);
324 eb
= b
& (blue_bits
- 1);
330 if ((dither4
[dithy
][dithx
] < er
) && (r
< red_table
[255])) r
++;
331 if ((dither4
[dithy
][dithx
] < eg
) && (g
< green_table
[255])) g
++;
332 if ((dither4
[dithy
][dithx
] < eb
) && (b
< blue_table
[255])) b
++;
334 pixel
= (r
<< red_offset
) | (g
<< green_offset
) | (b
<< blue_offset
);
338 *pixel_data
++ = pixel
;
341 case 16: // 16bpp LSB
342 *pixel_data
++ = pixel
;
343 *pixel_data
++ = pixel
>> 8;
346 case 17: // 16bpp MSB
347 *pixel_data
++ = pixel
>> 8;
348 *pixel_data
++ = pixel
;
351 case 24: // 24bpp LSB
352 *pixel_data
++ = pixel
;
353 *pixel_data
++ = pixel
>> 8;
354 *pixel_data
++ = pixel
>> 16;
357 case 25: // 24bpp MSB
358 *pixel_data
++ = pixel
>> 16;
359 *pixel_data
++ = pixel
>> 8;
360 *pixel_data
++ = pixel
;
363 case 32: // 32bpp LSB
364 *pixel_data
++ = pixel
;
365 *pixel_data
++ = pixel
>> 8;
366 *pixel_data
++ = pixel
>> 16;
367 *pixel_data
++ = pixel
>> 24;
370 case 33: // 32bpp MSB
371 *pixel_data
++ = pixel
>> 24;
372 *pixel_data
++ = pixel
>> 16;
373 *pixel_data
++ = pixel
>> 8;
374 *pixel_data
++ = pixel
;
379 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
386 #ifndef ORDEREDPSEUDO
388 *rerr
= new short[width
+ 2],
389 *gerr
= new short[width
+ 2],
390 *berr
= new short[width
+ 2],
391 *nrerr
= new short[width
+ 2],
392 *ngerr
= new short[width
+ 2],
393 *nberr
= new short[width
+ 2];
394 int rr
, gg
, bb
, rer
, ger
, ber
;
395 int dd
= 255 / control
->getColorsPerChannel();
397 for (x
= 0; x
< width
; x
++) {
398 *(rerr
+ x
) = *(red
+ x
);
399 *(gerr
+ x
) = *(green
+ x
);
400 *(berr
+ x
) = *(blue
+ x
);
403 *(rerr
+ x
) = *(gerr
+ x
) = *(berr
+ x
) = 0;
404 #endif // ORDEREDPSEUDO
406 for (y
= 0, offset
= 0; y
< height
; y
++) {
410 for (x
= 0; x
< width
; x
++, offset
++) {
417 er
= r
& (red_bits
- 1);
418 eg
= g
& (green_bits
- 1);
419 eb
= b
& (blue_bits
- 1);
425 if ((dither8
[dithy
][dithx
] < er
) && (r
< red_table
[255])) r
++;
426 if ((dither8
[dithy
][dithx
] < eg
) && (g
< green_table
[255])) g
++;
427 if ((dither8
[dithy
][dithx
] < eb
) && (b
< blue_table
[255])) b
++;
429 pixel
= (r
* cpccpc
) + (g
* cpc
) + b
;
430 *(pixel_data
++) = colors
[pixel
].pixel
;
433 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
435 #else // !ORDEREDPSEUDO
436 if (y
< (height
- 1)) {
437 int i
= offset
+ width
;
438 for (x
= 0; x
< width
; x
++, i
++) {
439 *(nrerr
+ x
) = *(red
+ i
);
440 *(ngerr
+ x
) = *(green
+ i
);
441 *(nberr
+ x
) = *(blue
+ i
);
444 *(nrerr
+ x
) = *(red
+ (--i
));
445 *(ngerr
+ x
) = *(green
+ i
);
446 *(nberr
+ x
) = *(blue
+ i
);
449 for (x
= 0; x
< width
; x
++) {
454 if (rr
> 255) rr
= 255; else if (rr
< 0) rr
= 0;
455 if (gg
> 255) gg
= 255; else if (gg
< 0) gg
= 0;
456 if (bb
> 255) bb
= 255; else if (bb
< 0) bb
= 0;
462 rer
= rerr
[x
] - r
*dd
;
463 ger
= gerr
[x
] - g
*dd
;
464 ber
= berr
[x
] - b
*dd
;
466 pixel
= (r
* cpccpc
) + (g
* cpc
) + b
;
467 *pixel_data
++ = colors
[pixel
].pixel
;
482 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
503 #endif // ORDEREDPSUEDO
508 fprintf(stderr
, i18n
->getMessage(ImageSet
, ImageUnsupVisual
,
509 "BImage::renderXImage: unsupported visual\n"));
511 XDestroyImage(image
);
515 switch (control
->getVisual()->c_class
) {
518 for (y
= 0, offset
= 0; y
< height
; y
++) {
519 for (x
= 0; x
< width
; x
++, offset
++) {
520 r
= red_table
[red
[offset
]];
521 g
= green_table
[green
[offset
]];
522 b
= blue_table
[blue
[offset
]];
524 pixel
= (r
* cpccpc
) + (g
* cpc
) + b
;
525 *pixel_data
++ = colors
[pixel
].pixel
;
528 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
534 for (y
= 0, offset
= 0; y
< height
; y
++) {
535 for (x
= 0; x
< width
; x
++, offset
++) {
536 r
= red_table
[red
[offset
]];
537 g
= green_table
[green
[offset
]];
538 b
= blue_table
[blue
[offset
]];
540 pixel
= (r
<< red_offset
) | (g
<< green_offset
) | (b
<< blue_offset
);
544 *pixel_data
++ = pixel
;
547 case 16: // 16bpp LSB
548 *pixel_data
++ = pixel
;
549 *pixel_data
++ = pixel
>> 8;
552 case 17: // 16bpp MSB
553 *pixel_data
++ = pixel
>> 8;
554 *pixel_data
++ = pixel
;
557 case 24: // 24bpp LSB
558 *pixel_data
++ = pixel
;
559 *pixel_data
++ = pixel
>> 8;
560 *pixel_data
++ = pixel
>> 16;
563 case 25: // 24bpp MSB
564 *pixel_data
++ = pixel
>> 16;
565 *pixel_data
++ = pixel
>> 8;
566 *pixel_data
++ = pixel
;
569 case 32: // 32bpp LSB
570 *pixel_data
++ = pixel
;
571 *pixel_data
++ = pixel
>> 8;
572 *pixel_data
++ = pixel
>> 16;
573 *pixel_data
++ = pixel
>> 24;
576 case 33: // 32bpp MSB
577 *pixel_data
++ = pixel
>> 24;
578 *pixel_data
++ = pixel
>> 16;
579 *pixel_data
++ = pixel
>> 8;
580 *pixel_data
++ = pixel
;
585 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
592 for (y
= 0, offset
= 0; y
< height
; y
++) {
593 for (x
= 0; x
< width
; x
++, offset
++) {
594 r
= *(red_table
+ *(red
+ offset
));
595 g
= *(green_table
+ *(green
+ offset
));
596 b
= *(blue_table
+ *(blue
+ offset
));
598 g
= ((r
* 30) + (g
* 59) + (b
* 11)) / 100;
599 *pixel_data
++ = colors
[g
].pixel
;
602 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
608 fprintf(stderr
, i18n
->getMessage(ImageSet
, ImageUnsupVisual
,
609 "BImage::renderXImage: unsupported visual\n"));
611 XDestroyImage(image
);
616 image
->data
= (char *) d
;
621 Pixmap
BImage::renderPixmap(void) {
623 XCreatePixmap(control
->getBaseDisplay()->getXDisplay(),
624 control
->getDrawable(), width
, height
, control
->getDepth());
626 if (pixmap
== None
) {
627 fprintf(stderr
, i18n
->getMessage(ImageSet
, ImageErrorCreatingPixmap
,
628 "BImage::renderPixmap: error creating pixmap\n"));
632 XImage
*image
= renderXImage();
635 XFreePixmap(control
->getBaseDisplay()->getXDisplay(), pixmap
);
637 } else if (! image
->data
) {
638 XDestroyImage(image
);
639 XFreePixmap(control
->getBaseDisplay()->getXDisplay(), pixmap
);
643 XPutImage(control
->getBaseDisplay()->getXDisplay(), pixmap
,
644 DefaultGC(control
->getBaseDisplay()->getXDisplay(),
645 control
->getScreenInfo()->getScreenNumber()),
646 image
, 0, 0, 0, 0, width
, height
);
649 delete [] image
->data
;
653 XDestroyImage(image
);
659 void BImage::bevel1(void) {
660 if (width
> 2 && height
> 2) {
661 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
663 register unsigned char r
, g
, b
, rr
,gg
,bb
;
664 register unsigned int w
= width
, h
= height
- 1, wh
= w
* h
;
682 rr
= (r
>> 2) + (r
>> 1);
685 gg
= (g
>> 2) + (g
>> 1);
688 bb
= (b
>> 2) + (b
>> 1);
711 rr
= (r
>> 2) + (r
>> 1);
714 gg
= (g
>> 2) + (g
>> 1);
717 bb
= (b
>> 2) + (b
>> 1);
748 rr
= (r
>> 2) + (r
>> 1);
751 gg
= (g
>> 2) + (g
>> 1);
754 bb
= (b
>> 2) + (b
>> 1);
781 rr
= (r
>> 2) + (r
>> 1);
784 gg
= (g
>> 2) + (g
>> 1);
787 bb
= (b
>> 2) + (b
>> 1);
797 void BImage::bevel2(void) {
798 if (width
> 4 && height
> 4) {
799 unsigned char r
, g
, b
, rr
,gg
,bb
, *pr
= red
+ width
+ 1,
800 *pg
= green
+ width
+ 1, *pb
= blue
+ width
+ 1;
801 unsigned int w
= width
- 2, h
= height
- 1, wh
= width
* (height
- 3);
819 rr
= (r
>> 2) + (r
>> 1);
822 gg
= (g
>> 2) + (g
>> 1);
825 bb
= (b
>> 2) + (b
>> 1);
857 rr
= (r
>> 2) + (r
>> 1);
860 gg
= (g
>> 2) + (g
>> 1);
863 bb
= (b
>> 2) + (b
>> 1);
876 void BImage::invert(void) {
877 register unsigned int i
, j
, wh
= (width
* height
) - 1;
880 for (i
= 0, j
= wh
; j
> i
; j
--, i
++) {
882 *(red
+ j
) = *(red
+ i
);
886 *(green
+ j
) = *(green
+ i
);
890 *(blue
+ j
) = *(blue
+ i
);
896 void BImage::dgradient(void) {
897 // diagonal gradient code was written by Mike Cole <mike@mydot.com>
898 // modified for interlacing by Brad Hughes
900 float drx
, dgx
, dbx
, dry
, dgy
, dby
, yr
= 0.0, yg
= 0.0, yb
= 0.0,
901 xr
= (float) from
->getRed(),
902 xg
= (float) from
->getGreen(),
903 xb
= (float) from
->getBlue();
904 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
905 unsigned int w
= width
* 2, h
= height
* 2, *xt
= xtable
, *yt
= ytable
;
907 register unsigned int x
, y
;
909 dry
= drx
= (float) (to
->getRed() - from
->getRed());
910 dgy
= dgx
= (float) (to
->getGreen() - from
->getGreen());
911 dby
= dbx
= (float) (to
->getBlue() - from
->getBlue());
918 for (x
= 0; x
< width
; x
++) {
919 *(xt
++) = (unsigned char) (xr
);
920 *(xt
++) = (unsigned char) (xg
);
921 *(xt
++) = (unsigned char) (xb
);
933 for (y
= 0; y
< height
; y
++) {
934 *(yt
++) = ((unsigned char) yr
);
935 *(yt
++) = ((unsigned char) yg
);
936 *(yt
++) = ((unsigned char) yb
);
943 // Combine tables to create gradient
950 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
951 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
952 *(pr
++) = *(xt
++) + *(yt
);
953 *(pg
++) = *(xt
++) + *(yt
+ 1);
954 *(pb
++) = *(xt
++) + *(yt
+ 2);
960 // faked interlacing effect
961 unsigned char channel
, channel2
;
963 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
964 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
966 channel
= *(xt
++) + *(yt
);
967 channel2
= (channel
>> 1) + (channel
>> 2);
968 if (channel2
> channel
) channel2
= 0;
971 channel
= *(xt
++) + *(yt
+ 1);
972 channel2
= (channel
>> 1) + (channel
>> 2);
973 if (channel2
> channel
) channel2
= 0;
976 channel
= *(xt
++) + *(yt
+ 2);
977 channel2
= (channel
>> 1) + (channel
>> 2);
978 if (channel2
> channel
) channel2
= 0;
981 channel
= *(xt
++) + *(yt
);
982 channel2
= channel
+ (channel
>> 3);
983 if (channel2
< channel
) channel2
= ~0;
986 channel
= *(xt
++) + *(yt
+ 1);
987 channel2
= channel
+ (channel
>> 3);
988 if (channel2
< channel
) channel2
= ~0;
991 channel
= *(xt
++) + *(yt
+ 2);
992 channel2
= channel
+ (channel
>> 3);
993 if (channel2
< channel
) channel2
= ~0;
1004 void BImage::hgradient(void) {
1005 float drx
, dgx
, dbx
,
1006 xr
= (float) from
->getRed(),
1007 xg
= (float) from
->getGreen(),
1008 xb
= (float) from
->getBlue();
1009 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1011 register unsigned int x
, y
;
1013 drx
= (float) (to
->getRed() - from
->getRed());
1014 dgx
= (float) (to
->getGreen() - from
->getGreen());
1015 dbx
= (float) (to
->getBlue() - from
->getBlue());
1022 if (interlaced
&& height
> 2) {
1023 // faked interlacing effect
1024 unsigned char channel
, channel2
;
1026 for (x
= 0; x
< width
; x
++, pr
++, pg
++, pb
++) {
1027 channel
= (unsigned char) xr
;
1028 channel2
= (channel
>> 1) + (channel
>> 2);
1029 if (channel2
> channel
) channel2
= 0;
1032 channel
= (unsigned char) xg
;
1033 channel2
= (channel
>> 1) + (channel
>> 2);
1034 if (channel2
> channel
) channel2
= 0;
1037 channel
= (unsigned char) xb
;
1038 channel2
= (channel
>> 1) + (channel
>> 2);
1039 if (channel2
> channel
) channel2
= 0;
1043 channel
= (unsigned char) xr
;
1044 channel2
= channel
+ (channel
>> 3);
1045 if (channel2
< channel
) channel2
= ~0;
1046 *(pr
+ width
) = channel2
;
1048 channel
= (unsigned char) xg
;
1049 channel2
= channel
+ (channel
>> 3);
1050 if (channel2
< channel
) channel2
= ~0;
1051 *(pg
+ width
) = channel2
;
1053 channel
= (unsigned char) xb
;
1054 channel2
= channel
+ (channel
>> 3);
1055 if (channel2
< channel
) channel2
= ~0;
1056 *(pb
+ width
) = channel2
;
1069 for (y
= 2; y
< height
; y
++, pr
+= width
, pg
+= width
, pb
+= width
) {
1070 if (y
& 1) offset
= width
; else offset
= 0;
1072 memcpy(pr
, (red
+ offset
), width
);
1073 memcpy(pg
, (green
+ offset
), width
);
1074 memcpy(pb
, (blue
+ offset
), width
);
1080 for (x
= 0; x
< width
; x
++) {
1081 *(pr
++) = (unsigned char) (xr
);
1082 *(pg
++) = (unsigned char) (xg
);
1083 *(pb
++) = (unsigned char) (xb
);
1090 for (y
= 1; y
< height
; y
++, pr
+= width
, pg
+= width
, pb
+= width
) {
1091 memcpy(pr
, red
, width
);
1092 memcpy(pg
, green
, width
);
1093 memcpy(pb
, blue
, width
);
1103 void BImage::vgradient(void) {
1104 float dry
, dgy
, dby
,
1105 yr
= (float) from
->getRed(),
1106 yg
= (float) from
->getGreen(),
1107 yb
= (float) from
->getBlue();
1108 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1110 register unsigned int y
;
1112 dry
= (float) (to
->getRed() - from
->getRed());
1113 dgy
= (float) (to
->getGreen() - from
->getGreen());
1114 dby
= (float) (to
->getBlue() - from
->getBlue());
1122 // faked interlacing effect
1123 unsigned char channel
, channel2
;
1125 for (y
= 0; y
< height
; y
++, pr
+= width
, pg
+= width
, pb
+= width
) {
1127 channel
= (unsigned char) yr
;
1128 channel2
= (channel
>> 1) + (channel
>> 2);
1129 if (channel2
> channel
) channel2
= 0;
1130 memset(pr
, channel2
, width
);
1132 channel
= (unsigned char) yg
;
1133 channel2
= (channel
>> 1) + (channel
>> 2);
1134 if (channel2
> channel
) channel2
= 0;
1135 memset(pg
, channel2
, width
);
1137 channel
= (unsigned char) yb
;
1138 channel2
= (channel
>> 1) + (channel
>> 2);
1139 if (channel2
> channel
) channel2
= 0;
1140 memset(pb
, channel2
, width
);
1142 channel
= (unsigned char) yr
;
1143 channel2
= channel
+ (channel
>> 3);
1144 if (channel2
< channel
) channel2
= ~0;
1145 memset(pr
, channel2
, width
);
1147 channel
= (unsigned char) yg
;
1148 channel2
= channel
+ (channel
>> 3);
1149 if (channel2
< channel
) channel2
= ~0;
1150 memset(pg
, channel2
, width
);
1152 channel
= (unsigned char) yb
;
1153 channel2
= channel
+ (channel
>> 3);
1154 if (channel2
< channel
) channel2
= ~0;
1155 memset(pb
, channel2
, width
);
1166 for (y
= 0; y
< height
; y
++, pr
+= width
, pg
+= width
, pb
+= width
) {
1167 memset(pr
, (unsigned char) yr
, width
);
1168 memset(pg
, (unsigned char) yg
, width
);
1169 memset(pb
, (unsigned char) yb
, width
);
1183 void BImage::pgradient(void) {
1184 // pyramid gradient - based on original dgradient, written by
1185 // Mosfet (mosfet@kde.org)
1186 // adapted from kde sources for Openbox by Brad Hughes
1188 float yr
, yg
, yb
, drx
, dgx
, dbx
, dry
, dgy
, dby
,
1190 int rsign
, gsign
, bsign
;
1191 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1192 unsigned int tr
= to
->getRed(), tg
= to
->getGreen(), tb
= to
->getBlue(),
1193 *xt
= xtable
, *yt
= ytable
;
1195 register unsigned int x
, y
;
1197 dry
= drx
= (float) (to
->getRed() - from
->getRed());
1198 dgy
= dgx
= (float) (to
->getGreen() - from
->getGreen());
1199 dby
= dbx
= (float) (to
->getBlue() - from
->getBlue());
1201 rsign
= (drx
< 0) ? -1 : 1;
1202 gsign
= (dgx
< 0) ? -1 : 1;
1203 bsign
= (dbx
< 0) ? -1 : 1;
1205 xr
= yr
= (drx
/ 2);
1206 xg
= yg
= (dgx
/ 2);
1207 xb
= yb
= (dbx
/ 2);
1214 for (x
= 0; x
< width
; x
++) {
1215 *(xt
++) = (unsigned char) ((xr
< 0) ? -xr
: xr
);
1216 *(xt
++) = (unsigned char) ((xg
< 0) ? -xg
: xg
);
1217 *(xt
++) = (unsigned char) ((xb
< 0) ? -xb
: xb
);
1229 for (y
= 0; y
< height
; y
++) {
1230 *(yt
++) = ((unsigned char) ((yr
< 0) ? -yr
: yr
));
1231 *(yt
++) = ((unsigned char) ((yg
< 0) ? -yg
: yg
));
1232 *(yt
++) = ((unsigned char) ((yb
< 0) ? -yb
: yb
));
1239 // Combine tables to create gradient
1246 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1247 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1248 *(pr
++) = (unsigned char) (tr
- (rsign
* (*(xt
++) + *(yt
))));
1249 *(pg
++) = (unsigned char) (tg
- (gsign
* (*(xt
++) + *(yt
+ 1))));
1250 *(pb
++) = (unsigned char) (tb
- (bsign
* (*(xt
++) + *(yt
+ 2))));
1256 // faked interlacing effect
1257 unsigned char channel
, channel2
;
1259 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1260 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1262 channel
= (unsigned char) (tr
- (rsign
* (*(xt
++) + *(yt
))));
1263 channel2
= (channel
>> 1) + (channel
>> 2);
1264 if (channel2
> channel
) channel2
= 0;
1267 channel
= (unsigned char) (tg
- (gsign
* (*(xt
++) + *(yt
+ 1))));
1268 channel2
= (channel
>> 1) + (channel
>> 2);
1269 if (channel2
> channel
) channel2
= 0;
1272 channel
= (unsigned char) (tb
- (bsign
* (*(xt
++) + *(yt
+ 2))));
1273 channel2
= (channel
>> 1) + (channel
>> 2);
1274 if (channel2
> channel
) channel2
= 0;
1277 channel
= (unsigned char) (tr
- (rsign
* (*(xt
++) + *(yt
))));
1278 channel2
= channel
+ (channel
>> 3);
1279 if (channel2
< channel
) channel2
= ~0;
1282 channel
= (unsigned char) (tg
- (gsign
* (*(xt
++) + *(yt
+ 1))));
1283 channel2
= channel
+ (channel
>> 3);
1284 if (channel2
< channel
) channel2
= ~0;
1287 channel
= (unsigned char) (tb
- (bsign
* (*(xt
++) + *(yt
+ 2))));
1288 channel2
= channel
+ (channel
>> 3);
1289 if (channel2
< channel
) channel2
= ~0;
1299 void BImage::rgradient(void) {
1300 // rectangle gradient - based on original dgradient, written by
1301 // Mosfet (mosfet@kde.org)
1302 // adapted from kde sources for Openbox by Brad Hughes
1304 float drx
, dgx
, dbx
, dry
, dgy
, dby
, xr
, xg
, xb
, yr
, yg
, yb
;
1305 int rsign
, gsign
, bsign
;
1306 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1307 unsigned int tr
= to
->getRed(), tg
= to
->getGreen(), tb
= to
->getBlue(),
1308 *xt
= xtable
, *yt
= ytable
;
1310 register unsigned int x
, y
;
1312 dry
= drx
= (float) (to
->getRed() - from
->getRed());
1313 dgy
= dgx
= (float) (to
->getGreen() - from
->getGreen());
1314 dby
= dbx
= (float) (to
->getBlue() - from
->getBlue());
1316 rsign
= (drx
< 0) ? -2 : 2;
1317 gsign
= (dgx
< 0) ? -2 : 2;
1318 bsign
= (dbx
< 0) ? -2 : 2;
1320 xr
= yr
= (drx
/ 2);
1321 xg
= yg
= (dgx
/ 2);
1322 xb
= yb
= (dbx
/ 2);
1329 for (x
= 0; x
< width
; x
++) {
1330 *(xt
++) = (unsigned char) ((xr
< 0) ? -xr
: xr
);
1331 *(xt
++) = (unsigned char) ((xg
< 0) ? -xg
: xg
);
1332 *(xt
++) = (unsigned char) ((xb
< 0) ? -xb
: xb
);
1344 for (y
= 0; y
< height
; y
++) {
1345 *(yt
++) = ((unsigned char) ((yr
< 0) ? -yr
: yr
));
1346 *(yt
++) = ((unsigned char) ((yg
< 0) ? -yg
: yg
));
1347 *(yt
++) = ((unsigned char) ((yb
< 0) ? -yb
: yb
));
1354 // Combine tables to create gradient
1361 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1362 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1363 *(pr
++) = (unsigned char) (tr
- (rsign
* max(*(xt
++), *(yt
))));
1364 *(pg
++) = (unsigned char) (tg
- (gsign
* max(*(xt
++), *(yt
+ 1))));
1365 *(pb
++) = (unsigned char) (tb
- (bsign
* max(*(xt
++), *(yt
+ 2))));
1371 // faked interlacing effect
1372 unsigned char channel
, channel2
;
1374 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1375 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1377 channel
= (unsigned char) (tr
- (rsign
* max(*(xt
++), *(yt
))));
1378 channel2
= (channel
>> 1) + (channel
>> 2);
1379 if (channel2
> channel
) channel2
= 0;
1382 channel
= (unsigned char) (tg
- (gsign
* max(*(xt
++), *(yt
+ 1))));
1383 channel2
= (channel
>> 1) + (channel
>> 2);
1384 if (channel2
> channel
) channel2
= 0;
1387 channel
= (unsigned char) (tb
- (bsign
* max(*(xt
++), *(yt
+ 2))));
1388 channel2
= (channel
>> 1) + (channel
>> 2);
1389 if (channel2
> channel
) channel2
= 0;
1392 channel
= (unsigned char) (tr
- (rsign
* max(*(xt
++), *(yt
))));
1393 channel2
= channel
+ (channel
>> 3);
1394 if (channel2
< channel
) channel2
= ~0;
1397 channel
= (unsigned char) (tg
- (gsign
* max(*(xt
++), *(yt
+ 1))));
1398 channel2
= channel
+ (channel
>> 3);
1399 if (channel2
< channel
) channel2
= ~0;
1402 channel
= (unsigned char) (tb
- (bsign
* max(*(xt
++), *(yt
+ 2))));
1403 channel2
= channel
+ (channel
>> 3);
1404 if (channel2
< channel
) channel2
= ~0;
1414 void BImage::egradient(void) {
1415 // elliptic gradient - based on original dgradient, written by
1416 // Mosfet (mosfet@kde.org)
1417 // adapted from kde sources for Openbox by Brad Hughes
1419 float drx
, dgx
, dbx
, dry
, dgy
, dby
, yr
, yg
, yb
, xr
, xg
, xb
;
1420 int rsign
, gsign
, bsign
;
1421 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1422 unsigned int *xt
= xtable
, *yt
= ytable
,
1423 tr
= (unsigned long) to
->getRed(),
1424 tg
= (unsigned long) to
->getGreen(),
1425 tb
= (unsigned long) to
->getBlue();
1427 register unsigned int x
, y
;
1429 dry
= drx
= (float) (to
->getRed() - from
->getRed());
1430 dgy
= dgx
= (float) (to
->getGreen() - from
->getGreen());
1431 dby
= dbx
= (float) (to
->getBlue() - from
->getBlue());
1433 rsign
= (drx
< 0) ? -1 : 1;
1434 gsign
= (dgx
< 0) ? -1 : 1;
1435 bsign
= (dbx
< 0) ? -1 : 1;
1437 xr
= yr
= (drx
/ 2);
1438 xg
= yg
= (dgx
/ 2);
1439 xb
= yb
= (dbx
/ 2);
1446 for (x
= 0; x
< width
; x
++) {
1447 *(xt
++) = (unsigned long) (xr
* xr
);
1448 *(xt
++) = (unsigned long) (xg
* xg
);
1449 *(xt
++) = (unsigned long) (xb
* xb
);
1461 for (y
= 0; y
< height
; y
++) {
1462 *(yt
++) = (unsigned long) (yr
* yr
);
1463 *(yt
++) = (unsigned long) (yg
* yg
);
1464 *(yt
++) = (unsigned long) (yb
* yb
);
1471 // Combine tables to create gradient
1478 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1479 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1480 *(pr
++) = (unsigned char)
1481 (tr
- (rsign
* control
->getSqrt(*(xt
++) + *(yt
))));
1482 *(pg
++) = (unsigned char)
1483 (tg
- (gsign
* control
->getSqrt(*(xt
++) + *(yt
+ 1))));
1484 *(pb
++) = (unsigned char)
1485 (tb
- (bsign
* control
->getSqrt(*(xt
++) + *(yt
+ 2))));
1491 // faked interlacing effect
1492 unsigned char channel
, channel2
;
1494 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1495 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1497 channel
= (unsigned char)
1498 (tr
- (rsign
* control
->getSqrt(*(xt
++) + *(yt
))));
1499 channel2
= (channel
>> 1) + (channel
>> 2);
1500 if (channel2
> channel
) channel2
= 0;
1503 channel
= (unsigned char)
1504 (tg
- (gsign
* control
->getSqrt(*(xt
++) + *(yt
+ 1))));
1505 channel2
= (channel
>> 1) + (channel
>> 2);
1506 if (channel2
> channel
) channel2
= 0;
1509 channel
= (unsigned char)
1510 (tb
- (bsign
* control
->getSqrt(*(xt
++) + *(yt
+ 2))));
1511 channel2
= (channel
>> 1) + (channel
>> 2);
1512 if (channel2
> channel
) channel2
= 0;
1515 channel
= (unsigned char)
1516 (tr
- (rsign
* control
->getSqrt(*(xt
++) + *(yt
))));
1517 channel2
= channel
+ (channel
>> 3);
1518 if (channel2
< channel
) channel2
= ~0;
1521 channel
= (unsigned char)
1522 (tg
- (gsign
* control
->getSqrt(*(xt
++) + *(yt
+ 1))));
1523 channel2
= channel
+ (channel
>> 3);
1524 if (channel2
< channel
) channel2
= ~0;
1527 channel
= (unsigned char)
1528 (tb
- (bsign
* control
->getSqrt(*(xt
++) + *(yt
+ 2))));
1529 channel2
= channel
+ (channel
>> 3);
1530 if (channel2
< channel
) channel2
= ~0;
1540 void BImage::pcgradient(void) {
1541 // pipe cross gradient - based on original dgradient, written by
1542 // Mosfet (mosfet@kde.org)
1543 // adapted from kde sources for Openbox by Brad Hughes
1545 float drx
, dgx
, dbx
, dry
, dgy
, dby
, xr
, xg
, xb
, yr
, yg
, yb
;
1546 int rsign
, gsign
, bsign
;
1547 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1548 unsigned int *xt
= xtable
, *yt
= ytable
,
1550 tg
= to
->getGreen(),
1553 register unsigned int x
, y
;
1555 dry
= drx
= (float) (to
->getRed() - from
->getRed());
1556 dgy
= dgx
= (float) (to
->getGreen() - from
->getGreen());
1557 dby
= dbx
= (float) (to
->getBlue() - from
->getBlue());
1559 rsign
= (drx
< 0) ? -2 : 2;
1560 gsign
= (dgx
< 0) ? -2 : 2;
1561 bsign
= (dbx
< 0) ? -2 : 2;
1563 xr
= yr
= (drx
/ 2);
1564 xg
= yg
= (dgx
/ 2);
1565 xb
= yb
= (dbx
/ 2);
1572 for (x
= 0; x
< width
; x
++) {
1573 *(xt
++) = (unsigned char) ((xr
< 0) ? -xr
: xr
);
1574 *(xt
++) = (unsigned char) ((xg
< 0) ? -xg
: xg
);
1575 *(xt
++) = (unsigned char) ((xb
< 0) ? -xb
: xb
);
1587 for (y
= 0; y
< height
; y
++) {
1588 *(yt
++) = ((unsigned char) ((yr
< 0) ? -yr
: yr
));
1589 *(yt
++) = ((unsigned char) ((yg
< 0) ? -yg
: yg
));
1590 *(yt
++) = ((unsigned char) ((yb
< 0) ? -yb
: yb
));
1597 // Combine tables to create gradient
1603 // normal pcgradient
1604 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1605 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1606 *(pr
++) = (unsigned char) (tr
- (rsign
* min(*(xt
++), *(yt
))));
1607 *(pg
++) = (unsigned char) (tg
- (gsign
* min(*(xt
++), *(yt
+ 1))));
1608 *(pb
++) = (unsigned char) (tb
- (bsign
* min(*(xt
++), *(yt
+ 2))));
1614 // faked interlacing effect
1615 unsigned char channel
, channel2
;
1617 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1618 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1620 channel
= (unsigned char) (tr
- (rsign
* min(*(xt
++), *(yt
))));
1621 channel2
= (channel
>> 1) + (channel
>> 2);
1622 if (channel2
> channel
) channel2
= 0;
1625 channel
= (unsigned char) (tg
- (bsign
* min(*(xt
++), *(yt
+ 1))));
1626 channel2
= (channel
>> 1) + (channel
>> 2);
1627 if (channel2
> channel
) channel2
= 0;
1630 channel
= (unsigned char) (tb
- (gsign
* min(*(xt
++), *(yt
+ 2))));
1631 channel2
= (channel
>> 1) + (channel
>> 2);
1632 if (channel2
> channel
) channel2
= 0;
1635 channel
= (unsigned char) (tr
- (rsign
* min(*(xt
++), *(yt
))));
1636 channel2
= channel
+ (channel
>> 3);
1637 if (channel2
< channel
) channel2
= ~0;
1640 channel
= (unsigned char) (tg
- (gsign
* min(*(xt
++), *(yt
+ 1))));
1641 channel2
= channel
+ (channel
>> 3);
1642 if (channel2
< channel
) channel2
= ~0;
1645 channel
= (unsigned char) (tb
- (bsign
* min(*(xt
++), *(yt
+ 2))));
1646 channel2
= channel
+ (channel
>> 3);
1647 if (channel2
< channel
) channel2
= ~0;
1657 void BImage::cdgradient(void) {
1658 // cross diagonal gradient - based on original dgradient, written by
1659 // Mosfet (mosfet@kde.org)
1660 // adapted from kde sources for Openbox by Brad Hughes
1662 float drx
, dgx
, dbx
, dry
, dgy
, dby
, yr
= 0.0, yg
= 0.0, yb
= 0.0,
1663 xr
= (float) from
->getRed(),
1664 xg
= (float) from
->getGreen(),
1665 xb
= (float) from
->getBlue();
1666 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1667 unsigned int w
= width
* 2, h
= height
* 2, *xt
, *yt
;
1669 register unsigned int x
, y
;
1671 dry
= drx
= (float) (to
->getRed() - from
->getRed());
1672 dgy
= dgx
= (float) (to
->getGreen() - from
->getGreen());
1673 dby
= dbx
= (float) (to
->getBlue() - from
->getBlue());
1680 for (xt
= (xtable
+ (width
* 3) - 1), x
= 0; x
< width
; x
++) {
1681 *(xt
--) = (unsigned char) xb
;
1682 *(xt
--) = (unsigned char) xg
;
1683 *(xt
--) = (unsigned char) xr
;
1695 for (yt
= ytable
, y
= 0; y
< height
; y
++) {
1696 *(yt
++) = (unsigned char) yr
;
1697 *(yt
++) = (unsigned char) yg
;
1698 *(yt
++) = (unsigned char) yb
;
1705 // Combine tables to create gradient
1711 // normal cdgradient
1712 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1713 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1714 *(pr
++) = *(xt
++) + *(yt
);
1715 *(pg
++) = *(xt
++) + *(yt
+ 1);
1716 *(pb
++) = *(xt
++) + *(yt
+ 2);
1722 // faked interlacing effect
1723 unsigned char channel
, channel2
;
1725 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1726 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1728 channel
= *(xt
++) + *(yt
);
1729 channel2
= (channel
>> 1) + (channel
>> 2);
1730 if (channel2
> channel
) channel2
= 0;
1733 channel
= *(xt
++) + *(yt
+ 1);
1734 channel2
= (channel
>> 1) + (channel
>> 2);
1735 if (channel2
> channel
) channel2
= 0;
1738 channel
= *(xt
++) + *(yt
+ 2);
1739 channel2
= (channel
>> 1) + (channel
>> 2);
1740 if (channel2
> channel
) channel2
= 0;
1743 channel
= *(xt
++) + *(yt
);
1744 channel2
= channel
+ (channel
>> 3);
1745 if (channel2
< channel
) channel2
= ~0;
1748 channel
= *(xt
++) + *(yt
+ 1);
1749 channel2
= channel
+ (channel
>> 3);
1750 if (channel2
< channel
) channel2
= ~0;
1753 channel
= *(xt
++) + *(yt
+ 2);
1754 channel2
= channel
+ (channel
>> 3);
1755 if (channel2
< channel
) channel2
= ~0;
1765 BImageControl::BImageControl(BaseDisplay
*dpy
, ScreenInfo
*scrn
, Bool _dither
,
1766 int _cpc
, unsigned long cache_timeout
,
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
;
1896 basedisplay
->grab();
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
] =
1992 basedisplay
->grab();
1993 for (i
= 0; i
< ncolors
; i
++) {
1994 colors
[i
].red
= (i
* 0xffff) / (colors_per_channel
- 1);
1995 colors
[i
].green
= (i
* 0xffff) / (colors_per_channel
- 1);
1996 colors
[i
].blue
= (i
* 0xffff) / (colors_per_channel
- 1);;
1997 colors
[i
].flags
= DoRed
|DoGreen
|DoBlue
;
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) {
2301 basedisplay
->grab();
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
, 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
, 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
);