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