1 // Image.cc for Blackbox - an X11 Window manager
2 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
4 // Permission is hereby granted, free of charge, to any person obtaining a
5 // copy of this software and associated documentation files (the "Software"),
6 // to deal in the Software without restriction, including without limitation
7 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 // and/or sell copies of the Software, and to permit persons to whom the
9 // Software is furnished to do so, subject to the following conditions:
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 // DEALINGS IN THE SOFTWARE.
24 // stupid macros needed to access some functions in version 2 of the GNU C
32 #endif // HAVE_CONFIG_H
34 #include "BaseDisplay.hh"
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
66 static unsigned long bsqrt(unsigned long x
) {
70 unsigned long r
= x
>> 1;
81 BImage::BImage(BImageControl
*c
, unsigned int w
, unsigned int h
) {
84 width
= ((signed) w
> 0) ? w
: 1;
85 height
= ((signed) h
> 0) ? h
: 1;
87 red
= new unsigned char[width
* height
];
88 green
= new unsigned char[width
* height
];
89 blue
= new unsigned char[width
* height
];
91 xtable
= ytable
= (unsigned int *) 0;
93 cpc
= control
->getColorsPerChannel();
96 control
->getColorTables(&red_table
, &green_table
, &blue_table
,
97 &red_offset
, &green_offset
, &blue_offset
,
98 &red_bits
, &green_bits
, &blue_bits
);
100 if (control
->getVisual()->c_class
!= TrueColor
)
101 control
->getXColorTable(&colors
, &ncolors
);
105 BImage::~BImage(void) {
106 if (red
) delete [] red
;
107 if (green
) delete [] green
;
108 if (blue
) delete [] blue
;
112 Pixmap
BImage::render(BTexture
*texture
) {
113 if (texture
->getTexture() & BImage_ParentRelative
)
114 return ParentRelative
;
115 else if (texture
->getTexture() & BImage_Solid
)
116 return render_solid(texture
);
117 else if (texture
->getTexture() & BImage_Gradient
)
118 return render_gradient(texture
);
124 Pixmap
BImage::render_solid(BTexture
*texture
) {
125 Pixmap pixmap
= XCreatePixmap(control
->getBaseDisplay()->getXDisplay(),
126 control
->getDrawable(), width
,
127 height
, control
->getDepth());
128 if (pixmap
== None
) {
130 "BImage::render_solid: error creating pixmap\n");
137 gcv
.foreground
= texture
->getColor()->getPixel();
138 gcv
.fill_style
= FillSolid
;
139 gc
= XCreateGC(control
->getBaseDisplay()->getXDisplay(), pixmap
,
140 GCForeground
| GCFillStyle
, &gcv
);
142 gcv
.foreground
= texture
->getHiColor()->getPixel();
143 hgc
= XCreateGC(control
->getBaseDisplay()->getXDisplay(), pixmap
,
146 gcv
.foreground
= texture
->getLoColor()->getPixel();
147 lgc
= XCreateGC(control
->getBaseDisplay()->getXDisplay(), pixmap
,
150 XFillRectangle(control
->getBaseDisplay()->getXDisplay(), pixmap
, gc
, 0, 0,
154 if (texture
->getTexture() & BImage_Interlaced
) {
155 gcv
.foreground
= texture
->getColorTo()->getPixel();
156 GC igc
= XCreateGC(control
->getBaseDisplay()->getXDisplay(), pixmap
,
159 register unsigned int i
= 0;
160 for (; i
< height
; i
+= 2)
161 XDrawLine(control
->getBaseDisplay()->getXDisplay(), pixmap
, igc
,
164 XFreeGC(control
->getBaseDisplay()->getXDisplay(), igc
);
169 if (texture
->getTexture() & BImage_Bevel1
) {
170 if (texture
->getTexture() & BImage_Raised
) {
171 XDrawLine(control
->getBaseDisplay()->getXDisplay(), pixmap
, lgc
,
172 0, height
- 1, width
- 1, height
- 1);
173 XDrawLine(control
->getBaseDisplay()->getXDisplay(), pixmap
, lgc
,
174 width
- 1, height
- 1, width
- 1, 0);
176 XDrawLine(control
->getBaseDisplay()->getXDisplay(), pixmap
, hgc
,
178 XDrawLine(control
->getBaseDisplay()->getXDisplay(), pixmap
, hgc
,
179 0, height
- 1, 0, 0);
180 } else if (texture
->getTexture() & BImage_Sunken
) {
181 XDrawLine(control
->getBaseDisplay()->getXDisplay(), pixmap
, hgc
,
182 0, height
- 1, width
- 1, height
- 1);
183 XDrawLine(control
->getBaseDisplay()->getXDisplay(), pixmap
, hgc
,
184 width
- 1, height
- 1, width
- 1, 0);
186 XDrawLine(control
->getBaseDisplay()->getXDisplay(), pixmap
, lgc
,
188 XDrawLine(control
->getBaseDisplay()->getXDisplay(), pixmap
, lgc
,
189 0, height
- 1, 0, 0);
191 } else if (texture
->getTexture() & BImage_Bevel2
) {
192 if (texture
->getTexture() & BImage_Raised
) {
193 XDrawLine(control
->getBaseDisplay()->getXDisplay(), pixmap
, lgc
,
194 1, height
- 3, width
- 3, height
- 3);
195 XDrawLine(control
->getBaseDisplay()->getXDisplay(), pixmap
, lgc
,
196 width
- 3, height
- 3, width
- 3, 1);
198 XDrawLine(control
->getBaseDisplay()->getXDisplay(), pixmap
, hgc
,
200 XDrawLine(control
->getBaseDisplay()->getXDisplay(), pixmap
, hgc
,
201 1, height
- 3, 1, 1);
202 } else if (texture
->getTexture() & BImage_Sunken
) {
203 XDrawLine(control
->getBaseDisplay()->getXDisplay(), pixmap
, hgc
,
204 1, height
- 3, width
- 3, height
- 3);
205 XDrawLine(control
->getBaseDisplay()->getXDisplay(), pixmap
, hgc
,
206 width
- 3, height
- 3, width
- 3, 1);
208 XDrawLine(control
->getBaseDisplay()->getXDisplay(), pixmap
, lgc
,
210 XDrawLine(control
->getBaseDisplay()->getXDisplay(), pixmap
, lgc
,
211 1, height
- 3, 1, 1);
215 XFreeGC(control
->getBaseDisplay()->getXDisplay(), gc
);
216 XFreeGC(control
->getBaseDisplay()->getXDisplay(), hgc
);
217 XFreeGC(control
->getBaseDisplay()->getXDisplay(), lgc
);
223 Pixmap
BImage::render_gradient(BTexture
*texture
) {
227 interlaced
= texture
->getTexture() & BImage_Interlaced
;
230 if (texture
->getTexture() & BImage_Sunken
) {
231 from
= texture
->getColorTo();
232 to
= texture
->getColor();
234 if (! (texture
->getTexture() & BImage_Invert
)) inverted
= 1;
236 from
= texture
->getColor();
237 to
= texture
->getColorTo();
239 if (texture
->getTexture() & BImage_Invert
) inverted
= 1;
242 control
->getGradientBuffers(width
, height
, &xtable
, &ytable
);
244 if (texture
->getTexture() & BImage_Diagonal
) dgradient();
245 else if (texture
->getTexture() & BImage_Elliptic
) egradient();
246 else if (texture
->getTexture() & BImage_Horizontal
) hgradient();
247 else if (texture
->getTexture() & BImage_Pyramid
) pgradient();
248 else if (texture
->getTexture() & BImage_Rectangle
) rgradient();
249 else if (texture
->getTexture() & BImage_Vertical
) vgradient();
250 else if (texture
->getTexture() & BImage_CrossDiagonal
) cdgradient();
251 else if (texture
->getTexture() & BImage_PipeCross
) pcgradient();
253 if (texture
->getTexture() & BImage_Bevel1
) bevel1();
254 else if (texture
->getTexture() & BImage_Bevel2
) bevel2();
256 if (inverted
) invert();
258 Pixmap pixmap
= renderPixmap();
265 XImage
*BImage::renderXImage(void) {
267 XCreateImage(control
->getBaseDisplay()->getXDisplay(),
268 control
->getVisual(), control
->getDepth(), ZPixmap
, 0, 0,
269 width
, height
, 32, 0);
273 "BImage::renderXImage: error creating XImage\n");
278 image
->data
= (char *) 0;
280 unsigned char *d
= new unsigned char[image
->bytes_per_line
* (height
+ 1)];
281 register unsigned int x
, y
, dithx
, dithy
, r
, g
, b
, o
, er
, eg
, eb
, offset
;
283 unsigned char *pixel_data
= d
, *ppixel_data
= d
;
286 o
= image
->bits_per_pixel
+ ((image
->byte_order
== MSBFirst
) ? 1 : 0);
288 if (control
->doDither() && width
> 1 && height
> 1) {
289 unsigned char dither4
[4][4] = { {0, 4, 1, 5},
295 unsigned char dither8
[8][8] = { { 0, 32, 8, 40, 2, 34, 10, 42 },
296 { 48, 16, 56, 24, 50, 18, 58, 26 },
297 { 12, 44, 4, 36, 14, 46, 6, 38 },
298 { 60, 28, 52, 20, 62, 30, 54, 22 },
299 { 3, 35, 11, 43, 1, 33, 9, 41 },
300 { 51, 19, 59, 27, 49, 17, 57, 25 },
301 { 15, 47, 7, 39, 13, 45, 5, 37 },
302 { 63, 31, 55, 23, 61, 29, 53, 21 } };
303 #endif // ORDEREDPSEUDO
305 switch (control
->getVisual()->c_class
) {
307 // algorithm: ordered dithering... many many thanks to rasterman
308 // (raster@rasterman.com) for telling me about this... portions of this
309 // code is based off of his code in Imlib
310 for (y
= 0, offset
= 0; y
< height
; y
++) {
313 for (x
= 0; x
< width
; x
++, offset
++) {
319 er
= r
& (red_bits
- 1);
320 eg
= g
& (green_bits
- 1);
321 eb
= b
& (blue_bits
- 1);
327 if ((dither4
[dithy
][dithx
] < er
) && (r
< red_table
[255])) r
++;
328 if ((dither4
[dithy
][dithx
] < eg
) && (g
< green_table
[255])) g
++;
329 if ((dither4
[dithy
][dithx
] < eb
) && (b
< blue_table
[255])) b
++;
331 pixel
= (r
<< red_offset
) | (g
<< green_offset
) | (b
<< blue_offset
);
334 case 16: // 16bpp LSB
335 *pixel_data
++ = pixel
;
336 *pixel_data
++ = pixel
>> 8;
339 case 17: // 16bpp MSB
340 *pixel_data
++ = pixel
>> 8;
341 *pixel_data
++ = pixel
;
344 case 24: // 24bpp LSB
345 *pixel_data
++ = pixel
;
346 *pixel_data
++ = pixel
>> 8;
347 *pixel_data
++ = pixel
>> 16;
350 case 25: // 24bpp MSB
351 *pixel_data
++ = pixel
>> 16;
352 *pixel_data
++ = pixel
>> 8;
353 *pixel_data
++ = pixel
;
356 case 32: // 32bpp LSB
357 *pixel_data
++ = pixel
;
358 *pixel_data
++ = pixel
>> 8;
359 *pixel_data
++ = pixel
>> 16;
360 *pixel_data
++ = pixel
>> 24;
363 case 33: // 32bpp MSB
364 *pixel_data
++ = pixel
>> 24;
365 *pixel_data
++ = pixel
>> 16;
366 *pixel_data
++ = pixel
>> 8;
367 *pixel_data
++ = pixel
;
372 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
379 #ifndef ORDEREDPSEUDO
381 *rerr
= new short[width
+ 2],
382 *gerr
= new short[width
+ 2],
383 *berr
= new short[width
+ 2],
384 *nrerr
= new short[width
+ 2],
385 *ngerr
= new short[width
+ 2],
386 *nberr
= new short[width
+ 2];
387 int rr
, gg
, bb
, rer
, ger
, ber
;
388 int dd
= 255 / control
->getColorsPerChannel();
390 for (x
= 0; x
< width
; x
++) {
391 *(rerr
+ x
) = *(red
+ x
);
392 *(gerr
+ x
) = *(green
+ x
);
393 *(berr
+ x
) = *(blue
+ x
);
396 *(rerr
+ x
) = *(gerr
+ x
) = *(berr
+ x
) = 0;
397 #endif // ORDEREDPSEUDO
399 for (y
= 0, offset
= 0; y
< height
; y
++) {
403 for (x
= 0; x
< width
; x
++, offset
++) {
410 er
= r
& (red_bits
- 1);
411 eg
= g
& (green_bits
- 1);
412 eb
= b
& (blue_bits
- 1);
418 if ((dither8
[dithy
][dithx
] < er
) && (r
< red_table
[255])) r
++;
419 if ((dither8
[dithy
][dithx
] < eg
) && (g
< green_table
[255])) g
++;
420 if ((dither8
[dithy
][dithx
] < eb
) && (b
< blue_table
[255])) b
++;
422 pixel
= (r
* cpccpc
) + (g
* cpc
) + b
;
423 *(pixel_data
++) = colors
[pixel
].pixel
;
426 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
428 #else // !ORDEREDPSEUDO
429 if (y
< (height
- 1)) {
430 int i
= offset
+ width
;
431 for (x
= 0; x
< width
; x
++, i
++) {
432 *(nrerr
+ x
) = *(red
+ i
);
433 *(ngerr
+ x
) = *(green
+ i
);
434 *(nberr
+ x
) = *(blue
+ i
);
437 *(nrerr
+ x
) = *(red
+ (--i
));
438 *(ngerr
+ x
) = *(green
+ i
);
439 *(nberr
+ x
) = *(blue
+ i
);
442 for (x
= 0; x
< width
; x
++) {
447 if (rr
> 255) rr
= 255; else if (rr
< 0) rr
= 0;
448 if (gg
> 255) gg
= 255; else if (gg
< 0) gg
= 0;
449 if (bb
> 255) bb
= 255; else if (bb
< 0) bb
= 0;
455 rer
= rerr
[x
] - r
*dd
;
456 ger
= gerr
[x
] - g
*dd
;
457 ber
= berr
[x
] - b
*dd
;
459 pixel
= (r
* cpccpc
) + (g
* cpc
) + b
;
460 *pixel_data
++ = colors
[pixel
].pixel
;
475 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
496 #endif // ORDEREDPSUEDO
503 for (y = 0, offset = 0; y < height; y++) {
506 for (x = 0; x < width; x++, offset++) {
510 g = *(green + offset);
511 b = *(blue + offset);
517 if ((dither[dithy][dithx] < er) && (r < (256 - 8)))
519 if ((dither[dithy][dithx] < (eg << 1)) && (g < (256 - 4)))
521 if ((dither[dithy][dithx] < eb) && (b < (256 - 8)))
524 r = *(red_table + r);
525 g = *(green_table + g);
526 b = *(blue_table + b);
528 g = ((r * 30) + (g * 59) + (b * 11)) / 100;
529 *pixel_data++ = colors[g].pixel;
532 pixel_data = (ppixel_data += image->bytes_per_line);
540 "BImage::renderXImage: unsupported visual\n");
542 XDestroyImage(image
);
546 switch (control
->getVisual()->c_class
) {
549 for (y
= 0, offset
= 0; y
< height
; y
++) {
550 for (x
= 0; x
< width
; x
++, offset
++) {
551 r
= red_table
[red
[offset
]];
552 g
= green_table
[green
[offset
]];
553 b
= blue_table
[blue
[offset
]];
555 pixel
= (r
* cpccpc
) + (g
* cpc
) + b
;
556 *pixel_data
++ = colors
[pixel
].pixel
;
559 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
565 for (y
= 0, offset
= 0; y
< height
; y
++) {
566 for (x
= 0; x
< width
; x
++, offset
++) {
567 r
= red_table
[red
[offset
]];
568 g
= green_table
[green
[offset
]];
569 b
= blue_table
[blue
[offset
]];
571 pixel
= (r
<< red_offset
) | (g
<< green_offset
) | (b
<< blue_offset
);
574 case 16: // 16bpp LSB
575 *pixel_data
++ = pixel
;
576 *pixel_data
++ = pixel
>> 8;
579 case 17: // 16bpp MSB
580 *pixel_data
++ = pixel
>> 8;
581 *pixel_data
++ = pixel
;
584 case 24: // 24bpp LSB
585 *pixel_data
++ = pixel
;
586 *pixel_data
++ = pixel
>> 8;
587 *pixel_data
++ = pixel
>> 16;
590 case 25: // 24bpp MSB
591 *pixel_data
++ = pixel
>> 16;
592 *pixel_data
++ = pixel
>> 8;
593 *pixel_data
++ = pixel
;
596 case 32: // 32bpp LSB
597 *pixel_data
++ = pixel
;
598 *pixel_data
++ = pixel
>> 8;
599 *pixel_data
++ = pixel
>> 16;
600 *pixel_data
++ = pixel
>> 24;
603 case 33: // 32bpp MSB
604 *pixel_data
++ = pixel
>> 24;
605 *pixel_data
++ = pixel
>> 16;
606 *pixel_data
++ = pixel
>> 8;
607 *pixel_data
++ = pixel
;
612 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
619 for (y
= 0, offset
= 0; y
< height
; y
++) {
620 for (x
= 0; x
< width
; x
++, offset
++) {
621 r
= *(red_table
+ *(red
+ offset
));
622 g
= *(green_table
+ *(green
+ offset
));
623 b
= *(blue_table
+ *(blue
+ offset
));
625 g
= ((r
* 30) + (g
* 59) + (b
* 11)) / 100;
626 *pixel_data
++ = colors
[g
].pixel
;
629 pixel_data
= (ppixel_data
+= image
->bytes_per_line
);
636 "BImage::renderXImage: unsupported visual\n");
638 XDestroyImage(image
);
643 image
->data
= (char *) d
;
648 Pixmap
BImage::renderPixmap(void) {
650 XCreatePixmap(control
->getBaseDisplay()->getXDisplay(),
651 control
->getDrawable(), width
, height
, control
->getDepth());
653 if (pixmap
== None
) {
655 "BImage::renderPixmap: error creating pixmap\n");
659 XImage
*image
= renderXImage();
662 XFreePixmap(control
->getBaseDisplay()->getXDisplay(), pixmap
);
664 } else if (! image
->data
) {
665 XDestroyImage(image
);
666 XFreePixmap(control
->getBaseDisplay()->getXDisplay(), pixmap
);
670 XPutImage(control
->getBaseDisplay()->getXDisplay(), pixmap
,
671 DefaultGC(control
->getBaseDisplay()->getXDisplay(),
672 control
->getScreenInfo()->getScreenNumber()),
673 image
, 0, 0, 0, 0, width
, height
);
676 delete [] image
->data
;
680 XDestroyImage(image
);
686 void BImage::bevel1(void) {
687 if (width
> 2 && height
> 2) {
688 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
690 register unsigned char r
, g
, b
, rr
,gg
,bb
;
691 register unsigned int w
= width
, h
= height
- 1, wh
= w
* h
;
709 rr
= (r
>> 2) + (r
>> 1);
712 gg
= (g
>> 2) + (g
>> 1);
715 bb
= (b
>> 2) + (b
>> 1);
738 rr
= (r
>> 2) + (r
>> 1);
741 gg
= (g
>> 2) + (g
>> 1);
744 bb
= (b
>> 2) + (b
>> 1);
775 rr
= (r
>> 2) + (r
>> 1);
778 gg
= (g
>> 2) + (g
>> 1);
781 bb
= (b
>> 2) + (b
>> 1);
808 rr
= (r
>> 2) + (r
>> 1);
811 gg
= (g
>> 2) + (g
>> 1);
814 bb
= (b
>> 2) + (b
>> 1);
824 void BImage::bevel2(void) {
825 if (width
> 4 && height
> 4) {
826 unsigned char r
, g
, b
, rr
,gg
,bb
, *pr
= red
+ width
+ 1,
827 *pg
= green
+ width
+ 1, *pb
= blue
+ width
+ 1;
828 unsigned int w
= width
- 2, h
= height
- 1, wh
= width
* (height
- 3);
846 rr
= (r
>> 2) + (r
>> 1);
849 gg
= (g
>> 2) + (g
>> 1);
852 bb
= (b
>> 2) + (b
>> 1);
884 rr
= (r
>> 2) + (r
>> 1);
887 gg
= (g
>> 2) + (g
>> 1);
890 bb
= (b
>> 2) + (b
>> 1);
903 void BImage::invert(void) {
904 register unsigned int i
, j
, wh
= (width
* height
) - 1;
907 for (i
= 0, j
= wh
; j
> i
; j
--, i
++) {
909 *(red
+ j
) = *(red
+ i
);
913 *(green
+ j
) = *(green
+ i
);
917 *(blue
+ j
) = *(blue
+ i
);
923 void BImage::dgradient(void) {
924 // diagonal gradient code was written by Mike Cole <mike@mydot.com>
925 // modified for interlacing by Brad Hughes
927 float drx
, dgx
, dbx
, dry
, dgy
, dby
, yr
= 0.0, yg
= 0.0, yb
= 0.0,
928 xr
= (float) from
->getRed(),
929 xg
= (float) from
->getGreen(),
930 xb
= (float) from
->getBlue();
931 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
932 unsigned int w
= width
* 2, h
= height
* 2, *xt
= xtable
, *yt
= ytable
;
934 register unsigned int x
, y
;
936 dry
= drx
= (float) (to
->getRed() - from
->getRed());
937 dgy
= dgx
= (float) (to
->getGreen() - from
->getGreen());
938 dby
= dbx
= (float) (to
->getBlue() - from
->getBlue());
945 for (x
= 0; x
< width
; x
++) {
946 *(xt
++) = (unsigned char) (xr
);
947 *(xt
++) = (unsigned char) (xg
);
948 *(xt
++) = (unsigned char) (xb
);
960 for (y
= 0; y
< height
; y
++) {
961 *(yt
++) = ((unsigned char) yr
);
962 *(yt
++) = ((unsigned char) yg
);
963 *(yt
++) = ((unsigned char) yb
);
970 // Combine tables to create gradient
977 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
978 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
979 *(pr
++) = *(xt
++) + *(yt
);
980 *(pg
++) = *(xt
++) + *(yt
+ 1);
981 *(pb
++) = *(xt
++) + *(yt
+ 2);
987 // faked interlacing effect
988 unsigned char channel
, channel2
;
990 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
991 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
993 channel
= *(xt
++) + *(yt
);
994 channel2
= (channel
>> 1) + (channel
>> 2);
995 if (channel2
> channel
) channel2
= 0;
998 channel
= *(xt
++) + *(yt
+ 1);
999 channel2
= (channel
>> 1) + (channel
>> 2);
1000 if (channel2
> channel
) channel2
= 0;
1003 channel
= *(xt
++) + *(yt
+ 2);
1004 channel2
= (channel
>> 1) + (channel
>> 2);
1005 if (channel2
> channel
) channel2
= 0;
1008 channel
= *(xt
++) + *(yt
);
1009 channel2
= channel
+ (channel
>> 3);
1010 if (channel2
< channel
) channel2
= ~0;
1013 channel
= *(xt
++) + *(yt
+ 1);
1014 channel2
= channel
+ (channel
>> 3);
1015 if (channel2
< channel
) channel2
= ~0;
1018 channel
= *(xt
++) + *(yt
+ 2);
1019 channel2
= channel
+ (channel
>> 3);
1020 if (channel2
< channel
) channel2
= ~0;
1031 void BImage::hgradient(void) {
1032 float drx
, dgx
, dbx
,
1033 xr
= (float) from
->getRed(),
1034 xg
= (float) from
->getGreen(),
1035 xb
= (float) from
->getBlue();
1036 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1038 register unsigned int x
, y
;
1040 drx
= (float) (to
->getRed() - from
->getRed());
1041 dgx
= (float) (to
->getGreen() - from
->getGreen());
1042 dbx
= (float) (to
->getBlue() - from
->getBlue());
1049 if (interlaced
&& height
> 2) {
1050 // faked interlacing effect
1051 unsigned char channel
, channel2
;
1053 for (x
= 0; x
< width
; x
++, pr
++, pg
++, pb
++) {
1054 channel
= (unsigned char) xr
;
1055 channel2
= (channel
>> 1) + (channel
>> 2);
1056 if (channel2
> channel
) channel2
= 0;
1059 channel
= (unsigned char) xg
;
1060 channel2
= (channel
>> 1) + (channel
>> 2);
1061 if (channel2
> channel
) channel2
= 0;
1064 channel
= (unsigned char) xb
;
1065 channel2
= (channel
>> 1) + (channel
>> 2);
1066 if (channel2
> channel
) channel2
= 0;
1070 channel
= (unsigned char) xr
;
1071 channel2
= channel
+ (channel
>> 3);
1072 if (channel2
< channel
) channel2
= ~0;
1073 *(pr
+ width
) = channel2
;
1075 channel
= (unsigned char) xg
;
1076 channel2
= channel
+ (channel
>> 3);
1077 if (channel2
< channel
) channel2
= ~0;
1078 *(pg
+ width
) = channel2
;
1080 channel
= (unsigned char) xb
;
1081 channel2
= channel
+ (channel
>> 3);
1082 if (channel2
< channel
) channel2
= ~0;
1083 *(pb
+ width
) = channel2
;
1096 for (y
= 2; y
< height
; y
++, pr
+= width
, pg
+= width
, pb
+= width
) {
1097 if (y
& 1) offset
= width
; else offset
= 0;
1099 memcpy(pr
, (red
+ offset
), width
);
1100 memcpy(pg
, (green
+ offset
), width
);
1101 memcpy(pb
, (blue
+ offset
), width
);
1107 for (x
= 0; x
< width
; x
++) {
1108 *(pr
++) = (unsigned char) (xr
);
1109 *(pg
++) = (unsigned char) (xg
);
1110 *(pb
++) = (unsigned char) (xb
);
1117 for (y
= 1; y
< height
; y
++, pr
+= width
, pg
+= width
, pb
+= width
) {
1118 memcpy(pr
, red
, width
);
1119 memcpy(pg
, green
, width
);
1120 memcpy(pb
, blue
, width
);
1130 void BImage::vgradient(void) {
1131 float dry
, dgy
, dby
,
1132 yr
= (float) from
->getRed(),
1133 yg
= (float) from
->getGreen(),
1134 yb
= (float) from
->getBlue();
1135 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1137 register unsigned int y
;
1139 dry
= (float) (to
->getRed() - from
->getRed());
1140 dgy
= (float) (to
->getGreen() - from
->getGreen());
1141 dby
= (float) (to
->getBlue() - from
->getBlue());
1149 // faked interlacing effect
1150 unsigned char channel
, channel2
;
1152 for (y
= 0; y
< height
; y
++, pr
+= width
, pg
+= width
, pb
+= width
) {
1154 channel
= (unsigned char) yr
;
1155 channel2
= (channel
>> 1) + (channel
>> 2);
1156 if (channel2
> channel
) channel2
= 0;
1157 memset(pr
, channel2
, width
);
1159 channel
= (unsigned char) yg
;
1160 channel2
= (channel
>> 1) + (channel
>> 2);
1161 if (channel2
> channel
) channel2
= 0;
1162 memset(pg
, channel2
, width
);
1164 channel
= (unsigned char) yb
;
1165 channel2
= (channel
>> 1) + (channel
>> 2);
1166 if (channel2
> channel
) channel2
= 0;
1167 memset(pb
, channel2
, width
);
1169 channel
= (unsigned char) yr
;
1170 channel2
= channel
+ (channel
>> 3);
1171 if (channel2
< channel
) channel2
= ~0;
1172 memset(pr
, channel2
, width
);
1174 channel
= (unsigned char) yg
;
1175 channel2
= channel
+ (channel
>> 3);
1176 if (channel2
< channel
) channel2
= ~0;
1177 memset(pg
, channel2
, width
);
1179 channel
= (unsigned char) yb
;
1180 channel2
= channel
+ (channel
>> 3);
1181 if (channel2
< channel
) channel2
= ~0;
1182 memset(pb
, channel2
, width
);
1193 for (y
= 0; y
< height
; y
++, pr
+= width
, pg
+= width
, pb
+= width
) {
1194 memset(pr
, (unsigned char) yr
, width
);
1195 memset(pg
, (unsigned char) yg
, width
);
1196 memset(pb
, (unsigned char) yb
, width
);
1210 void BImage::pgradient(void) {
1211 // pyramid gradient - based on original dgradient, written by
1212 // Mosfet (mosfet@kde.org)
1213 // adapted from kde sources for Blackbox by Brad Hughes
1215 float yr
, yg
, yb
, drx
, dgx
, dbx
, dry
, dgy
, dby
,
1217 int rsign
, gsign
, bsign
;
1218 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1219 unsigned int tr
= to
->getRed(), tg
= to
->getGreen(), tb
= to
->getBlue(),
1220 *xt
= xtable
, *yt
= ytable
;
1222 register unsigned int x
, y
;
1224 dry
= drx
= (float) (to
->getRed() - from
->getRed());
1225 dgy
= dgx
= (float) (to
->getGreen() - from
->getGreen());
1226 dby
= dbx
= (float) (to
->getBlue() - from
->getBlue());
1228 rsign
= (drx
< 0) ? -1 : 1;
1229 gsign
= (dgx
< 0) ? -1 : 1;
1230 bsign
= (dbx
< 0) ? -1 : 1;
1232 xr
= yr
= (drx
/ 2);
1233 xg
= yg
= (dgx
/ 2);
1234 xb
= yb
= (dbx
/ 2);
1241 for (x
= 0; x
< width
; x
++) {
1242 *(xt
++) = (unsigned char) ((xr
< 0) ? -xr
: xr
);
1243 *(xt
++) = (unsigned char) ((xg
< 0) ? -xg
: xg
);
1244 *(xt
++) = (unsigned char) ((xb
< 0) ? -xb
: xb
);
1256 for (y
= 0; y
< height
; y
++) {
1257 *(yt
++) = ((unsigned char) ((yr
< 0) ? -yr
: yr
));
1258 *(yt
++) = ((unsigned char) ((yg
< 0) ? -yg
: yg
));
1259 *(yt
++) = ((unsigned char) ((yb
< 0) ? -yb
: yb
));
1266 // Combine tables to create gradient
1273 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1274 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1275 *(pr
++) = (unsigned char) (tr
- (rsign
* (*(xt
++) + *(yt
))));
1276 *(pg
++) = (unsigned char) (tg
- (gsign
* (*(xt
++) + *(yt
+ 1))));
1277 *(pb
++) = (unsigned char) (tb
- (bsign
* (*(xt
++) + *(yt
+ 2))));
1283 // faked interlacing effect
1284 unsigned char channel
, channel2
;
1286 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1287 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1289 channel
= (unsigned char) (tr
- (rsign
* (*(xt
++) + *(yt
))));
1290 channel2
= (channel
>> 1) + (channel
>> 2);
1291 if (channel2
> channel
) channel2
= 0;
1294 channel
= (unsigned char) (tg
- (gsign
* (*(xt
++) + *(yt
+ 1))));
1295 channel2
= (channel
>> 1) + (channel
>> 2);
1296 if (channel2
> channel
) channel2
= 0;
1299 channel
= (unsigned char) (tb
- (bsign
* (*(xt
++) + *(yt
+ 2))));
1300 channel2
= (channel
>> 1) + (channel
>> 2);
1301 if (channel2
> channel
) channel2
= 0;
1304 channel
= (unsigned char) (tr
- (rsign
* (*(xt
++) + *(yt
))));
1305 channel2
= channel
+ (channel
>> 3);
1306 if (channel2
< channel
) channel2
= ~0;
1309 channel
= (unsigned char) (tg
- (gsign
* (*(xt
++) + *(yt
+ 1))));
1310 channel2
= channel
+ (channel
>> 3);
1311 if (channel2
< channel
) channel2
= ~0;
1314 channel
= (unsigned char) (tb
- (bsign
* (*(xt
++) + *(yt
+ 2))));
1315 channel2
= channel
+ (channel
>> 3);
1316 if (channel2
< channel
) channel2
= ~0;
1327 void BImage::rgradient(void) {
1328 // rectangle gradient - based on original dgradient, written by
1329 // Mosfet (mosfet@kde.org)
1330 // adapted from kde sources for Blackbox by Brad Hughes
1332 float drx
, dgx
, dbx
, dry
, dgy
, dby
, xr
, xg
, xb
, yr
, yg
, yb
;
1333 int rsign
, gsign
, bsign
;
1334 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1335 unsigned int tr
= to
->getRed(), tg
= to
->getGreen(), tb
= to
->getBlue(),
1336 *xt
= xtable
, *yt
= ytable
;
1338 register unsigned int x
, y
;
1340 dry
= drx
= (float) (to
->getRed() - from
->getRed());
1341 dgy
= dgx
= (float) (to
->getGreen() - from
->getGreen());
1342 dby
= dbx
= (float) (to
->getBlue() - from
->getBlue());
1344 rsign
= (drx
< 0) ? -2 : 2;
1345 gsign
= (dgx
< 0) ? -2 : 2;
1346 bsign
= (dbx
< 0) ? -2 : 2;
1348 xr
= yr
= (drx
/ 2);
1349 xg
= yg
= (dgx
/ 2);
1350 xb
= yb
= (dbx
/ 2);
1357 for (x
= 0; x
< width
; x
++) {
1358 *(xt
++) = (unsigned char) ((xr
< 0) ? -xr
: xr
);
1359 *(xt
++) = (unsigned char) ((xg
< 0) ? -xg
: xg
);
1360 *(xt
++) = (unsigned char) ((xb
< 0) ? -xb
: xb
);
1372 for (y
= 0; y
< height
; y
++) {
1373 *(yt
++) = ((unsigned char) ((yr
< 0) ? -yr
: yr
));
1374 *(yt
++) = ((unsigned char) ((yg
< 0) ? -yg
: yg
));
1375 *(yt
++) = ((unsigned char) ((yb
< 0) ? -yb
: yb
));
1382 // Combine tables to create gradient
1389 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1390 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1391 *(pr
++) = (unsigned char) (tr
- (rsign
* max(*(xt
++), *(yt
))));
1392 *(pg
++) = (unsigned char) (tg
- (gsign
* max(*(xt
++), *(yt
+ 1))));
1393 *(pb
++) = (unsigned char) (tb
- (bsign
* max(*(xt
++), *(yt
+ 2))));
1399 // faked interlacing effect
1400 unsigned char channel
, channel2
;
1402 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1403 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1405 channel
= (unsigned char) (tr
- (rsign
* max(*(xt
++), *(yt
))));
1406 channel2
= (channel
>> 1) + (channel
>> 2);
1407 if (channel2
> channel
) channel2
= 0;
1410 channel
= (unsigned char) (tg
- (gsign
* max(*(xt
++), *(yt
+ 1))));
1411 channel2
= (channel
>> 1) + (channel
>> 2);
1412 if (channel2
> channel
) channel2
= 0;
1415 channel
= (unsigned char) (tb
- (bsign
* max(*(xt
++), *(yt
+ 2))));
1416 channel2
= (channel
>> 1) + (channel
>> 2);
1417 if (channel2
> channel
) channel2
= 0;
1420 channel
= (unsigned char) (tr
- (rsign
* max(*(xt
++), *(yt
))));
1421 channel2
= channel
+ (channel
>> 3);
1422 if (channel2
< channel
) channel2
= ~0;
1425 channel
= (unsigned char) (tg
- (gsign
* max(*(xt
++), *(yt
+ 1))));
1426 channel2
= channel
+ (channel
>> 3);
1427 if (channel2
< channel
) channel2
= ~0;
1430 channel
= (unsigned char) (tb
- (bsign
* max(*(xt
++), *(yt
+ 2))));
1431 channel2
= channel
+ (channel
>> 3);
1432 if (channel2
< channel
) channel2
= ~0;
1443 void BImage::egradient(void) {
1444 // elliptic gradient - based on original dgradient, written by
1445 // Mosfet (mosfet@kde.org)
1446 // adapted from kde sources for Blackbox by Brad Hughes
1448 float drx
, dgx
, dbx
, dry
, dgy
, dby
, yr
, yg
, yb
, xr
, xg
, xb
;
1449 int rsign
, gsign
, bsign
;
1450 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1451 unsigned int *xt
= xtable
, *yt
= ytable
,
1452 tr
= (unsigned long) to
->getRed(),
1453 tg
= (unsigned long) to
->getGreen(),
1454 tb
= (unsigned long) to
->getBlue();
1456 register unsigned int x
, y
;
1458 dry
= drx
= (float) (to
->getRed() - from
->getRed());
1459 dgy
= dgx
= (float) (to
->getGreen() - from
->getGreen());
1460 dby
= dbx
= (float) (to
->getBlue() - from
->getBlue());
1462 rsign
= (drx
< 0) ? -1 : 1;
1463 gsign
= (dgx
< 0) ? -1 : 1;
1464 bsign
= (dbx
< 0) ? -1 : 1;
1466 xr
= yr
= (drx
/ 2);
1467 xg
= yg
= (dgx
/ 2);
1468 xb
= yb
= (dbx
/ 2);
1475 for (x
= 0; x
< width
; x
++) {
1476 *(xt
++) = (unsigned long) (xr
* xr
);
1477 *(xt
++) = (unsigned long) (xg
* xg
);
1478 *(xt
++) = (unsigned long) (xb
* xb
);
1490 for (y
= 0; y
< height
; y
++) {
1491 *(yt
++) = (unsigned long) (yr
* yr
);
1492 *(yt
++) = (unsigned long) (yg
* yg
);
1493 *(yt
++) = (unsigned long) (yb
* yb
);
1500 // Combine tables to create gradient
1507 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1508 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1509 *(pr
++) = (unsigned char)
1510 (tr
- (rsign
* control
->getSqrt(*(xt
++) + *(yt
))));
1511 *(pg
++) = (unsigned char)
1512 (tg
- (gsign
* control
->getSqrt(*(xt
++) + *(yt
+ 1))));
1513 *(pb
++) = (unsigned char)
1514 (tb
- (bsign
* control
->getSqrt(*(xt
++) + *(yt
+ 2))));
1520 // faked interlacing effect
1521 unsigned char channel
, channel2
;
1523 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1524 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1526 channel
= (unsigned char)
1527 (tr
- (rsign
* control
->getSqrt(*(xt
++) + *(yt
))));
1528 channel2
= (channel
>> 1) + (channel
>> 2);
1529 if (channel2
> channel
) channel2
= 0;
1532 channel
= (unsigned char)
1533 (tg
- (gsign
* control
->getSqrt(*(xt
++) + *(yt
+ 1))));
1534 channel2
= (channel
>> 1) + (channel
>> 2);
1535 if (channel2
> channel
) channel2
= 0;
1538 channel
= (unsigned char)
1539 (tb
- (bsign
* control
->getSqrt(*(xt
++) + *(yt
+ 2))));
1540 channel2
= (channel
>> 1) + (channel
>> 2);
1541 if (channel2
> channel
) channel2
= 0;
1544 channel
= (unsigned char)
1545 (tr
- (rsign
* control
->getSqrt(*(xt
++) + *(yt
))));
1546 channel2
= channel
+ (channel
>> 3);
1547 if (channel2
< channel
) channel2
= ~0;
1550 channel
= (unsigned char)
1551 (tg
- (gsign
* control
->getSqrt(*(xt
++) + *(yt
+ 1))));
1552 channel2
= channel
+ (channel
>> 3);
1553 if (channel2
< channel
) channel2
= ~0;
1556 channel
= (unsigned char)
1557 (tb
- (bsign
* control
->getSqrt(*(xt
++) + *(yt
+ 2))));
1558 channel2
= channel
+ (channel
>> 3);
1559 if (channel2
< channel
) channel2
= ~0;
1570 void BImage::pcgradient(void) {
1571 // pipe cross gradient - based on original dgradient, written by
1572 // Mosfet (mosfet@kde.org)
1573 // adapted from kde sources for Blackbox by Brad Hughes
1575 float drx
, dgx
, dbx
, dry
, dgy
, dby
, xr
, xg
, xb
, yr
, yg
, yb
;
1576 int rsign
, gsign
, bsign
;
1577 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1578 unsigned int *xt
= xtable
, *yt
= ytable
,
1580 tg
= to
->getGreen(),
1583 register unsigned int x
, y
;
1585 dry
= drx
= (float) (to
->getRed() - from
->getRed());
1586 dgy
= dgx
= (float) (to
->getGreen() - from
->getGreen());
1587 dby
= dbx
= (float) (to
->getBlue() - from
->getBlue());
1589 rsign
= (drx
< 0) ? -2 : 2;
1590 gsign
= (dgx
< 0) ? -2 : 2;
1591 bsign
= (dbx
< 0) ? -2 : 2;
1593 xr
= yr
= (drx
/ 2);
1594 xg
= yg
= (dgx
/ 2);
1595 xb
= yb
= (dbx
/ 2);
1602 for (x
= 0; x
< width
; x
++) {
1603 *(xt
++) = (unsigned char) ((xr
< 0) ? -xr
: xr
);
1604 *(xt
++) = (unsigned char) ((xg
< 0) ? -xg
: xg
);
1605 *(xt
++) = (unsigned char) ((xb
< 0) ? -xb
: xb
);
1617 for (y
= 0; y
< height
; y
++) {
1618 *(yt
++) = ((unsigned char) ((yr
< 0) ? -yr
: yr
));
1619 *(yt
++) = ((unsigned char) ((yg
< 0) ? -yg
: yg
));
1620 *(yt
++) = ((unsigned char) ((yb
< 0) ? -yb
: yb
));
1627 // Combine tables to create gradient
1633 // normal pcgradient
1634 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1635 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1636 *(pr
++) = (unsigned char) (tr
- (rsign
* min(*(xt
++), *(yt
))));
1637 *(pg
++) = (unsigned char) (tg
- (gsign
* min(*(xt
++), *(yt
+ 1))));
1638 *(pb
++) = (unsigned char) (tb
- (bsign
* min(*(xt
++), *(yt
+ 2))));
1644 // faked interlacing effect
1645 unsigned char channel
, channel2
;
1647 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1648 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1650 channel
= (unsigned char) (tr
- (rsign
* min(*(xt
++), *(yt
))));
1651 channel2
= (channel
>> 1) + (channel
>> 2);
1652 if (channel2
> channel
) channel2
= 0;
1655 channel
= (unsigned char) (tg
- (bsign
* min(*(xt
++), *(yt
+ 1))));
1656 channel2
= (channel
>> 1) + (channel
>> 2);
1657 if (channel2
> channel
) channel2
= 0;
1660 channel
= (unsigned char) (tb
- (gsign
* min(*(xt
++), *(yt
+ 2))));
1661 channel2
= (channel
>> 1) + (channel
>> 2);
1662 if (channel2
> channel
) channel2
= 0;
1665 channel
= (unsigned char) (tr
- (rsign
* min(*(xt
++), *(yt
))));
1666 channel2
= channel
+ (channel
>> 3);
1667 if (channel2
< channel
) channel2
= ~0;
1670 channel
= (unsigned char) (tg
- (gsign
* min(*(xt
++), *(yt
+ 1))));
1671 channel2
= channel
+ (channel
>> 3);
1672 if (channel2
< channel
) channel2
= ~0;
1675 channel
= (unsigned char) (tb
- (bsign
* min(*(xt
++), *(yt
+ 2))));
1676 channel2
= channel
+ (channel
>> 3);
1677 if (channel2
< channel
) channel2
= ~0;
1688 void BImage::cdgradient(void) {
1689 // cross diagonal gradient - based on original dgradient, written by
1690 // Mosfet (mosfet@kde.org)
1691 // adapted from kde sources for Blackbox by Brad Hughes
1693 float drx
, dgx
, dbx
, dry
, dgy
, dby
, yr
= 0.0, yg
= 0.0, yb
= 0.0,
1694 xr
= (float) from
->getRed(),
1695 xg
= (float) from
->getGreen(),
1696 xb
= (float) from
->getBlue();
1697 unsigned char *pr
= red
, *pg
= green
, *pb
= blue
;
1698 unsigned int w
= width
* 2, h
= height
* 2, *xt
, *yt
;
1700 register unsigned int x
, y
;
1702 dry
= drx
= (float) (to
->getRed() - from
->getRed());
1703 dgy
= dgx
= (float) (to
->getGreen() - from
->getGreen());
1704 dby
= dbx
= (float) (to
->getBlue() - from
->getBlue());
1711 for (xt
= (xtable
+ (width
* 3) - 1), x
= 0; x
< width
; x
++) {
1712 *(xt
--) = (unsigned char) xb
;
1713 *(xt
--) = (unsigned char) xg
;
1714 *(xt
--) = (unsigned char) xr
;
1726 for (yt
= ytable
, y
= 0; y
< height
; y
++) {
1727 *(yt
++) = (unsigned char) yr
;
1728 *(yt
++) = (unsigned char) yg
;
1729 *(yt
++) = (unsigned char) yb
;
1736 // Combine tables to create gradient
1742 // normal cdgradient
1743 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1744 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1745 *(pr
++) = *(xt
++) + *(yt
);
1746 *(pg
++) = *(xt
++) + *(yt
+ 1);
1747 *(pb
++) = *(xt
++) + *(yt
+ 2);
1753 // faked interlacing effect
1754 unsigned char channel
, channel2
;
1756 for (yt
= ytable
, y
= 0; y
< height
; y
++, yt
+= 3) {
1757 for (xt
= xtable
, x
= 0; x
< width
; x
++) {
1759 channel
= *(xt
++) + *(yt
);
1760 channel2
= (channel
>> 1) + (channel
>> 2);
1761 if (channel2
> channel
) channel2
= 0;
1764 channel
= *(xt
++) + *(yt
+ 1);
1765 channel2
= (channel
>> 1) + (channel
>> 2);
1766 if (channel2
> channel
) channel2
= 0;
1769 channel
= *(xt
++) + *(yt
+ 2);
1770 channel2
= (channel
>> 1) + (channel
>> 2);
1771 if (channel2
> channel
) channel2
= 0;
1774 channel
= *(xt
++) + *(yt
);
1775 channel2
= channel
+ (channel
>> 3);
1776 if (channel2
< channel
) channel2
= ~0;
1779 channel
= *(xt
++) + *(yt
+ 1);
1780 channel2
= channel
+ (channel
>> 3);
1781 if (channel2
< channel
) channel2
= ~0;
1784 channel
= *(xt
++) + *(yt
+ 2);
1785 channel2
= channel
+ (channel
>> 3);
1786 if (channel2
< channel
) channel2
= ~0;
1797 BImageControl::BImageControl(BaseDisplay
*dpy
, ScreenInfo
*scrn
, Bool _dither
,
1798 int _cpc
, unsigned long cache_timeout
,
1804 setColorsPerChannel(_cpc
);
1808 if (cache_timeout
) {
1809 timer
= new BTimer(basedisplay
, this);
1810 timer
->setTimeout(cache_timeout
);
1813 timer
= (BTimer
*) 0;
1814 #endif // TIMEDCACHE
1816 colors
= (XColor
*) 0;
1819 grad_xbuffer
= grad_ybuffer
= (unsigned int *) 0;
1820 grad_buffer_width
= grad_buffer_height
= 0;
1822 sqrt_table
= (unsigned long *) 0;
1824 screen_depth
= screeninfo
->getDepth();
1825 window
= screeninfo
->getRootWindow();
1826 screen_number
= screeninfo
->getScreenNumber();
1829 XPixmapFormatValues
*pmv
= XListPixmapFormats(basedisplay
->getXDisplay(),
1831 root_colormap
= DefaultColormap(basedisplay
->getXDisplay(), screen_number
);
1835 for (int i
= 0; i
< count
; i
++)
1836 if (pmv
[i
].depth
== screen_depth
) {
1837 bits_per_pixel
= pmv
[i
].bits_per_pixel
;
1844 if (bits_per_pixel
== 0) bits_per_pixel
= screen_depth
;
1845 if (bits_per_pixel
>= 24) setDither(False
);
1847 red_offset
= green_offset
= blue_offset
= 0;
1849 switch (getVisual()->c_class
) {
1854 // compute color tables
1855 unsigned long red_mask
= getVisual()->red_mask
,
1856 green_mask
= getVisual()->green_mask
,
1857 blue_mask
= getVisual()->blue_mask
;
1859 while (! (red_mask
& 1)) { red_offset
++; red_mask
>>= 1; }
1860 while (! (green_mask
& 1)) { green_offset
++; green_mask
>>= 1; }
1861 while (! (blue_mask
& 1)) { blue_offset
++; blue_mask
>>= 1; }
1863 red_bits
= 255 / red_mask
;
1864 green_bits
= 255 / green_mask
;
1865 blue_bits
= 255 / blue_mask
;
1867 for (i
= 0; i
< 256; i
++) {
1868 red_color_table
[i
] = i
/ red_bits
;
1869 green_color_table
[i
] = i
/ green_bits
;
1870 blue_color_table
[i
] = i
/ blue_bits
;
1879 ncolors
= colors_per_channel
* colors_per_channel
* colors_per_channel
;
1881 if (ncolors
> (1 << screen_depth
)) {
1882 colors_per_channel
= (1 << screen_depth
) / 3;
1883 ncolors
= colors_per_channel
* colors_per_channel
* colors_per_channel
;
1886 if (colors_per_channel
< 2 || ncolors
> (1 << screen_depth
)) {
1887 fprintf(stderr
, "BImageControl::BImageControl: invalid colormap size %d "
1888 "(%d/%d/%d) - reducing",
1889 ncolors
, colors_per_channel
, colors_per_channel
,
1890 colors_per_channel
);
1892 colors_per_channel
= (1 << screen_depth
) / 3;
1895 colors
= new XColor
[ncolors
];
1898 "BImageControl::BImageControl: error allocating "
1903 int i
= 0, ii
, p
, r
, g
, b
,
1905 #ifdef ORDEREDPSEUDO
1906 bits
= 256 / colors_per_channel
;
1907 #else // !ORDEREDPSEUDO
1908 bits
= 255 / (colors_per_channel
- 1);
1909 #endif // ORDEREDPSEUDO
1911 red_bits
= green_bits
= blue_bits
= bits
;
1913 for (i
= 0; i
< 256; i
++)
1914 red_color_table
[i
] = green_color_table
[i
] = blue_color_table
[i
] =
1917 for (r
= 0, i
= 0; r
< colors_per_channel
; r
++)
1918 for (g
= 0; g
< colors_per_channel
; g
++)
1919 for (b
= 0; b
< colors_per_channel
; b
++, i
++) {
1920 colors
[i
].red
= (r
* 0xffff) / (colors_per_channel
- 1);
1921 colors
[i
].green
= (g
* 0xffff) / (colors_per_channel
- 1);
1922 colors
[i
].blue
= (b
* 0xffff) / (colors_per_channel
- 1);;
1923 colors
[i
].flags
= DoRed
|DoGreen
|DoBlue
;
1926 for (i
= 0; i
< ncolors
; i
++)
1927 if (! XAllocColor(basedisplay
->getXDisplay(), getColormap(),
1929 fprintf(stderr
, "couldn't alloc color %i %i %i\n",
1930 colors
[i
].red
, colors
[i
].green
, colors
[i
].blue
);
1931 colors
[i
].flags
= 0;
1933 colors
[i
].flags
= DoRed
|DoGreen
|DoBlue
;
1935 XColor icolors
[256];
1936 int incolors
= (((1 << screen_depth
) > 256) ? 256 : (1 << screen_depth
));
1938 for (i
= 0; i
< incolors
; i
++)
1939 icolors
[i
].pixel
= i
;
1941 XQueryColors(basedisplay
->getXDisplay(), getColormap(), icolors
,
1943 for (i
= 0; i
< ncolors
; i
++) {
1944 if (! colors
[i
].flags
) {
1945 unsigned long chk
= 0xffffffff, pixel
, close
= 0;
1949 for (ii
= 0; ii
< incolors
; ii
++) {
1950 r
= (colors
[i
].red
- icolors
[i
].red
) >> 8;
1951 g
= (colors
[i
].green
- icolors
[i
].green
) >> 8;
1952 b
= (colors
[i
].blue
- icolors
[i
].blue
) >> 8;
1953 pixel
= (r
* r
) + (g
* g
) + (b
* b
);
1960 colors
[i
].red
= icolors
[close
].red
;
1961 colors
[i
].green
= icolors
[close
].green
;
1962 colors
[i
].blue
= icolors
[close
].blue
;
1964 if (XAllocColor(basedisplay
->getXDisplay(), getColormap(),
1966 colors
[i
].flags
= DoRed
|DoGreen
|DoBlue
;
1981 if (getVisual()->c_class
== StaticGray
) {
1982 ncolors
= 1 << screen_depth
;
1984 ncolors
= colors_per_channel
* colors_per_channel
* colors_per_channel
;
1986 if (ncolors
> (1 << screen_depth
)) {
1987 colors_per_channel
= (1 << screen_depth
) / 3;
1989 colors_per_channel
* colors_per_channel
* colors_per_channel
;
1993 if (colors_per_channel
< 2 || ncolors
> (1 << screen_depth
)) {
1994 fprintf(stderr
, "BImageControl::BImageControl: invalid colormap size %d "
1995 "(%d/%d/%d) - reducing",
1996 ncolors
, colors_per_channel
, colors_per_channel
,
1997 colors_per_channel
);
1999 colors_per_channel
= (1 << screen_depth
) / 3;
2002 colors
= new XColor
[ncolors
];
2004 fprintf(stderr
, "BImageControl::BImageControl: error allocating "
2009 int i
= 0, ii
, p
, bits
= 255 / (colors_per_channel
- 1);
2010 red_bits
= green_bits
= blue_bits
= bits
;
2012 for (i
= 0; i
< 256; i
++)
2013 red_color_table
[i
] = green_color_table
[i
] = blue_color_table
[i
] =
2016 for (i
= 0; i
< ncolors
; i
++) {
2017 colors
[i
].red
= (i
* 0xffff) / (colors_per_channel
- 1);
2018 colors
[i
].green
= (i
* 0xffff) / (colors_per_channel
- 1);
2019 colors
[i
].blue
= (i
* 0xffff) / (colors_per_channel
- 1);;
2020 colors
[i
].flags
= DoRed
|DoGreen
|DoBlue
;
2022 if (! XAllocColor(basedisplay
->getXDisplay(), getColormap(),
2024 fprintf(stderr
, "couldn't alloc color %i %i %i\n",
2025 colors
[i
].red
, colors
[i
].green
, colors
[i
].blue
);
2026 colors
[i
].flags
= 0;
2028 colors
[i
].flags
= DoRed
|DoGreen
|DoBlue
;
2031 XColor icolors
[256];
2032 int incolors
= (((1 << screen_depth
) > 256) ? 256 :
2033 (1 << screen_depth
));
2035 for (i
= 0; i
< incolors
; i
++)
2036 icolors
[i
].pixel
= i
;
2038 XQueryColors(basedisplay
->getXDisplay(), getColormap(), icolors
,
2040 for (i
= 0; i
< ncolors
; i
++) {
2041 if (! colors
[i
].flags
) {
2042 unsigned long chk
= 0xffffffff, pixel
, close
= 0;
2046 for (ii
= 0; ii
< incolors
; ii
++) {
2047 int r
= (colors
[i
].red
- icolors
[i
].red
) >> 8;
2048 int g
= (colors
[i
].green
- icolors
[i
].green
) >> 8;
2049 int b
= (colors
[i
].blue
- icolors
[i
].blue
) >> 8;
2050 pixel
= (r
* r
) + (g
* g
) + (b
* b
);
2057 colors
[i
].red
= icolors
[close
].red
;
2058 colors
[i
].green
= icolors
[close
].green
;
2059 colors
[i
].blue
= icolors
[close
].blue
;
2061 if (XAllocColor(basedisplay
->getXDisplay(), getColormap(),
2063 colors
[i
].flags
= DoRed
|DoGreen
|DoBlue
;
2075 fprintf(stderr
, "BImageControl::BImageControl: unsupported visual %d\n",
2076 getVisual()->c_class
);
2080 cache
= new LinkedList
<Cache
>;
2084 BImageControl::~BImageControl(void) {
2086 delete [] sqrt_table
;
2090 delete [] grad_xbuffer
;
2094 delete [] grad_ybuffer
;
2098 unsigned long *pixels
= new unsigned long [ncolors
];
2101 for (i
= 0; i
< ncolors
; i
++)
2102 *(pixels
+ i
) = (*(colors
+ i
)).pixel
;
2104 XFreeColors(basedisplay
->getXDisplay(), getColormap(),
2105 pixels
, ncolors
, 0);
2110 if (cache
->count()) {
2111 int i
, n
= cache
->count();
2113 "BImageContol::~BImageControl: pixmap cache - "
2114 "releasing %d pixmaps\n", n
);
2116 for (i
= 0; i
< n
; i
++) {
2117 Cache
*tmp
= cache
->first();
2118 XFreePixmap(basedisplay
->getXDisplay(), tmp
->pixmap
);
2128 #endif // TIMEDCACHE
2135 Pixmap
BImageControl::searchCache(unsigned int width
, unsigned int height
,
2136 unsigned long texture
,
2137 BColor
*c1
, BColor
*c2
) {
2138 if (cache
->count()) {
2139 LinkedListIterator
<Cache
> it(cache
);
2141 for (; it
.current(); it
++) {
2142 if ((it
.current()->width
== width
) &&
2143 (it
.current()->height
== height
) &&
2144 (it
.current()->texture
== texture
) &&
2145 (it
.current()->pixel1
== c1
->getPixel()))
2146 if (texture
& BImage_Gradient
) {
2147 if (it
.current()->pixel2
== c2
->getPixel()) {
2148 it
.current()->count
++;
2149 return it
.current()->pixmap
;
2152 it
.current()->count
++;
2153 return it
.current()->pixmap
;
2162 Pixmap
BImageControl::renderImage(unsigned int width
, unsigned int height
,
2163 BTexture
*texture
) {
2164 if (texture
->getTexture() & BImage_ParentRelative
) return ParentRelative
;
2166 Pixmap pixmap
= searchCache(width
, height
, texture
->getTexture(),
2167 texture
->getColor(), texture
->getColorTo());
2168 if (pixmap
) return pixmap
;
2170 BImage
image(this, width
, height
);
2171 pixmap
= image
.render(texture
);
2174 Cache
*tmp
= new Cache
;
2176 tmp
->pixmap
= pixmap
;
2178 tmp
->height
= height
;
2180 tmp
->texture
= texture
->getTexture();
2181 tmp
->pixel1
= texture
->getColor()->getPixel();
2183 if (texture
->getTexture() & BImage_Gradient
)
2184 tmp
->pixel2
= texture
->getColorTo()->getPixel();
2190 if ((unsigned) cache
->count() > cache_max
) {
2193 "BImageControl::renderImage: cache is large, "
2194 "forcing cleanout\n");
2207 void BImageControl::removeImage(Pixmap pixmap
) {
2209 LinkedListIterator
<Cache
> it(cache
);
2210 for (; it
.current(); it
++) {
2211 if (it
.current()->pixmap
== pixmap
) {
2212 Cache
*tmp
= it
.current();
2218 if (! timer
) timeout();
2219 #else // !TIMEDCACHE
2220 if (! tmp
->count
) timeout();
2221 #endif // TIMEDCACHE
2231 unsigned long BImageControl::getColor(const char *colorname
,
2232 unsigned char *r
, unsigned char *g
,
2238 if (! XParseColor(basedisplay
->getXDisplay(), getColormap(),
2239 colorname
, &color
)) {
2240 fprintf(stderr
, "BImageControl::getColor: color parse error: \"%s\"\n",
2242 } else if (! XAllocColor(basedisplay
->getXDisplay(), getColormap(),
2244 fprintf(stderr
, "BImageControl::getColor: color alloc error: \"%s\"\n",
2248 if (color
.red
== 65535) *r
= 0xff;
2249 else *r
= (unsigned char) (color
.red
/ 0xff);
2250 if (color
.green
== 65535) *g
= 0xff;
2251 else *g
= (unsigned char) (color
.green
/ 0xff);
2252 if (color
.blue
== 65535) *b
= 0xff;
2253 else *b
= (unsigned char) (color
.blue
/ 0xff);
2259 unsigned long BImageControl::getColor(const char *colorname
) {
2263 if (! XParseColor(basedisplay
->getXDisplay(), getColormap(),
2264 colorname
, &color
)) {
2265 fprintf(stderr
, "BImageControl::getColor: color parse error: \"%s\"\n",
2267 } else if (! XAllocColor(basedisplay
->getXDisplay(), getColormap(),
2269 fprintf(stderr
, "BImageControl::getColor: color alloc error: \"%s\"\n",
2277 void BImageControl::getColorTables(unsigned char **rmt
, unsigned char **gmt
,
2278 unsigned char **bmt
,
2279 int *roff
, int *goff
, int *boff
,
2280 int *rbit
, int *gbit
, int *bbit
) {
2281 if (rmt
) *rmt
= red_color_table
;
2282 if (gmt
) *gmt
= green_color_table
;
2283 if (bmt
) *bmt
= blue_color_table
;
2285 if (roff
) *roff
= red_offset
;
2286 if (goff
) *goff
= green_offset
;
2287 if (boff
) *boff
= blue_offset
;
2289 if (rbit
) *rbit
= red_bits
;
2290 if (gbit
) *gbit
= green_bits
;
2291 if (bbit
) *bbit
= blue_bits
;
2295 void BImageControl::getXColorTable(XColor
**c
, int *n
) {
2297 if (n
) *n
= ncolors
;
2301 void BImageControl::getGradientBuffers(unsigned int w
,
2303 unsigned int **xbuf
,
2304 unsigned int **ybuf
)
2306 if (w
> grad_buffer_width
) {
2308 delete [] grad_xbuffer
;
2311 grad_buffer_width
= w
;
2313 grad_xbuffer
= new unsigned int[grad_buffer_width
* 3];
2316 if (h
> grad_buffer_height
) {
2318 delete [] grad_ybuffer
;
2321 grad_buffer_height
= h
;
2323 grad_ybuffer
= new unsigned int[grad_buffer_height
* 3];
2326 *xbuf
= grad_xbuffer
;
2327 *ybuf
= grad_ybuffer
;
2331 void BImageControl::installRootColormap(void) {
2332 Bool install
= True
;
2333 int i
= 0, ncmap
= 0;
2335 XListInstalledColormaps(basedisplay
->getXDisplay(), window
, &ncmap
);
2338 for (i
= 0; i
< ncmap
; i
++)
2339 if (*(cmaps
+ i
) == getColormap())
2343 XInstallColormap(basedisplay
->getXDisplay(), getColormap());
2350 void BImageControl::setColorsPerChannel(int cpc
) {
2351 if (cpc
< 2) cpc
= 2;
2352 if (cpc
> 6) cpc
= 6;
2354 colors_per_channel
= cpc
;
2358 unsigned long BImageControl::getSqrt(unsigned int x
) {
2360 // build sqrt table for use with elliptic gradient
2362 sqrt_table
= new unsigned long[(256 * 256 * 2) + 1];
2365 for (; i
< (256 * 256 * 2); i
++)
2366 *(sqrt_table
+ i
) = bsqrt(i
);
2369 return (*(sqrt_table
+ x
));
2373 void BImageControl::parseTexture(BTexture
*texture
, const char *t
) {
2374 if ((! texture
) || (! t
)) return;
2376 int t_len
= strlen(t
) + 1, i
;
2377 char *ts
= new char[t_len
];
2380 // convert to lower case
2381 for (i
= 0; i
< t_len
; i
++)
2382 *(ts
+ i
) = tolower(*(t
+ i
));
2384 if (strstr(ts
, "parentrelative")) {
2385 texture
->setTexture(BImage_ParentRelative
);
2387 texture
->setTexture(0);
2389 if (strstr(ts
, "solid"))
2390 texture
->addTexture(BImage_Solid
);
2391 else if (strstr(ts
, "gradient")) {
2392 texture
->addTexture(BImage_Gradient
);
2393 if (strstr(ts
, "crossdiagonal"))
2394 texture
->addTexture(BImage_CrossDiagonal
);
2395 else if (strstr(ts
, "rectangle"))
2396 texture
->addTexture(BImage_Rectangle
);
2397 else if (strstr(ts
, "pyramid"))
2398 texture
->addTexture(BImage_Pyramid
);
2399 else if (strstr(ts
, "pipecross"))
2400 texture
->addTexture(BImage_PipeCross
);
2401 else if (strstr(ts
, "elliptic"))
2402 texture
->addTexture(BImage_Elliptic
);
2403 else if (strstr(ts
, "diagonal"))
2404 texture
->addTexture(BImage_Diagonal
);
2405 else if (strstr(ts
, "horizontal"))
2406 texture
->addTexture(BImage_Horizontal
);
2407 else if (strstr(ts
, "vertical"))
2408 texture
->addTexture(BImage_Vertical
);
2410 texture
->addTexture(BImage_Diagonal
);
2412 texture
->addTexture(BImage_Solid
);
2414 if (strstr(ts
, "raised"))
2415 texture
->addTexture(BImage_Raised
);
2416 else if (strstr(ts
, "sunken"))
2417 texture
->addTexture(BImage_Sunken
);
2418 else if (strstr(ts
, "flat"))
2419 texture
->addTexture(BImage_Flat
);
2421 texture
->addTexture(BImage_Raised
);
2423 if (! (texture
->getTexture() & BImage_Flat
))
2424 if (strstr(ts
, "bevel2"))
2425 texture
->addTexture(BImage_Bevel2
);
2427 texture
->addTexture(BImage_Bevel1
);
2430 if (strstr(ts
, "interlaced"))
2431 texture
->addTexture(BImage_Interlaced
);
2439 void BImageControl::parseColor(BColor
*color
, const char *c
) {
2440 if (! color
) return;
2442 if (color
->isAllocated()) {
2443 unsigned long pixel
= color
->getPixel();
2445 XFreeColors(basedisplay
->getXDisplay(), getColormap(), &pixel
, 1, 0);
2447 color
->setPixel(0l);
2448 color
->setRGB(0, 0, 0);
2449 color
->setAllocated(False
);
2453 unsigned char r
, g
, b
;
2455 color
->setPixel(getColor(c
, &r
, &g
, &b
));
2456 color
->setRGB(r
, g
, b
);
2457 color
->setAllocated(True
);
2462 void BImageControl::timeout(void) {
2463 LinkedListIterator
<Cache
> it(cache
);
2464 for (; it
.current(); it
++) {
2465 Cache
*tmp
= it
.current();
2467 if (tmp
->count
<= 0) {
2468 XFreePixmap(basedisplay
->getXDisplay(), tmp
->pixmap
);