1 // Image.cc for Openbox
2 // Copyright (c) 2001 Sean 'Shaleh' Perry <shaleh@debian.org>
3 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
5 // Permission is hereby granted, free of charge, to any person obtaining a
6 // copy of this software and associated documentation files (the "Software"),
7 // to deal in the Software without restriction, including without limitation
8 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 // and/or sell copies of the Software, and to permit persons to whom the
10 // Software is furnished to do so, subject to the following conditions:
12 // The above copyright notice and this permission notice shall be included in
13 // all copies or substantial portions of the Software.
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 // DEALINGS IN THE SOFTWARE.
23 // stupid macros needed to access some functions in version 2 of the GNU C
30 # include "../config.h"
31 #endif // HAVE_CONFIG_H
34 #include "BaseDisplay.h"
37 #ifdef HAVE_SYS_TYPES_H
38 # include <sys/types.h>
39 #endif // HAVE_SYS_TYPES_H
43 typedef uint32_t u_int32_t;
46 typedef __uint32_t u_int32_t;
48 typedef unsigned int u_int32_t;
56 #endif // STDC_HEADERS
60 #endif // HAVE_STDIO_H
64 #endif // HAVE_CTYPE_H
69 static unsigned long bsqrt(unsigned long x) {
73 unsigned long r = x >> 1;
84 BImage::BImage(BImageControl *c, unsigned int w, unsigned int h) {
87 width = ((signed) w > 0) ? w : 1;
88 height = ((signed) h > 0) ? h : 1;
90 red = new unsigned char[width * height];
91 green = new unsigned char[width * height];
92 blue = new unsigned char[width * height];
94 xtable = ytable = (unsigned int *) 0;
96 cpc = control->getColorsPerChannel();
99 control->getColorTables(&red_table, &green_table, &blue_table,
100 &red_offset, &green_offset, &blue_offset,
101 &red_bits, &green_bits, &blue_bits);
103 if (control->getVisual()->c_class != TrueColor)
104 control->getXColorTable(&colors, &ncolors);
108 BImage::~BImage(void) {
109 if (red) delete [] red;
110 if (green) delete [] green;
111 if (blue) delete [] blue;
115 Pixmap BImage::render(BTexture *texture) {
116 if (texture->getTexture() & BImage_ParentRelative)
117 return ParentRelative;
118 else if (texture->getTexture() & BImage_Solid)
119 return render_solid(texture);
120 else if (texture->getTexture() & BImage_Gradient)
121 return render_gradient(texture);
127 Pixmap BImage::render_solid(BTexture *texture) {
128 Pixmap pixmap = XCreatePixmap(control->getBaseDisplay()->getXDisplay(),
129 control->getDrawable(), width,
130 height, control->getDepth());
131 if (pixmap == None) {
132 fprintf(stderr, i18n->getMessage(ImageSet, ImageErrorCreatingSolidPixmap,
133 "BImage::render_solid: error creating pixmap\n"));
140 gcv.foreground = texture->getColor()->getPixel();
141 gcv.fill_style = FillSolid;
142 gc = XCreateGC(control->getBaseDisplay()->getXDisplay(), pixmap,
143 GCForeground | GCFillStyle, &gcv);
145 gcv.foreground = texture->getHiColor()->getPixel();
146 hgc = XCreateGC(control->getBaseDisplay()->getXDisplay(), pixmap,
149 gcv.foreground = texture->getLoColor()->getPixel();
150 lgc = XCreateGC(control->getBaseDisplay()->getXDisplay(), pixmap,
153 XFillRectangle(control->getBaseDisplay()->getXDisplay(), pixmap, gc, 0, 0,
157 if (texture->getTexture() & BImage_Interlaced) {
158 gcv.foreground = texture->getColorTo()->getPixel();
159 GC igc = XCreateGC(control->getBaseDisplay()->getXDisplay(), pixmap,
162 register unsigned int i = 0;
163 for (; i < height; i += 2)
164 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, igc,
167 XFreeGC(control->getBaseDisplay()->getXDisplay(), igc);
172 if (texture->getTexture() & BImage_Bevel1) {
173 if (texture->getTexture() & BImage_Raised) {
174 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, lgc,
175 0, height - 1, width - 1, height - 1);
176 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, lgc,
177 width - 1, height - 1, width - 1, 0);
179 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, hgc,
181 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, hgc,
182 0, height - 1, 0, 0);
183 } else if (texture->getTexture() & BImage_Sunken) {
184 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, hgc,
185 0, height - 1, width - 1, height - 1);
186 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, hgc,
187 width - 1, height - 1, width - 1, 0);
189 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, lgc,
191 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, lgc,
192 0, height - 1, 0, 0);
194 } else if (texture->getTexture() & BImage_Bevel2) {
195 if (texture->getTexture() & BImage_Raised) {
196 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, lgc,
197 1, height - 3, width - 3, height - 3);
198 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, lgc,
199 width - 3, height - 3, width - 3, 1);
201 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, hgc,
203 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, hgc,
204 1, height - 3, 1, 1);
205 } else if (texture->getTexture() & BImage_Sunken) {
206 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, hgc,
207 1, height - 3, width - 3, height - 3);
208 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, hgc,
209 width - 3, height - 3, width - 3, 1);
211 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, lgc,
213 XDrawLine(control->getBaseDisplay()->getXDisplay(), pixmap, lgc,
214 1, height - 3, 1, 1);
218 XFreeGC(control->getBaseDisplay()->getXDisplay(), gc);
219 XFreeGC(control->getBaseDisplay()->getXDisplay(), hgc);
220 XFreeGC(control->getBaseDisplay()->getXDisplay(), lgc);
226 Pixmap BImage::render_gradient(BTexture *texture) {
230 interlaced = texture->getTexture() & BImage_Interlaced;
233 if (texture->getTexture() & BImage_Sunken) {
234 from = texture->getColorTo();
235 to = texture->getColor();
237 if (! (texture->getTexture() & BImage_Invert)) inverted = 1;
239 from = texture->getColor();
240 to = texture->getColorTo();
242 if (texture->getTexture() & BImage_Invert) inverted = 1;
245 control->getGradientBuffers(width, height, &xtable, &ytable);
247 if (texture->getTexture() & BImage_Diagonal) dgradient();
248 else if (texture->getTexture() & BImage_Elliptic) egradient();
249 else if (texture->getTexture() & BImage_Horizontal) hgradient();
250 else if (texture->getTexture() & BImage_Pyramid) pgradient();
251 else if (texture->getTexture() & BImage_Rectangle) rgradient();
252 else if (texture->getTexture() & BImage_Vertical) vgradient();
253 else if (texture->getTexture() & BImage_CrossDiagonal) cdgradient();
254 else if (texture->getTexture() & BImage_PipeCross) pcgradient();
256 if (texture->getTexture() & BImage_Bevel1) bevel1();
257 else if (texture->getTexture() & BImage_Bevel2) bevel2();
259 if (inverted) invert();
261 Pixmap pixmap = renderPixmap();
268 XImage *BImage::renderXImage(void) {
270 XCreateImage(control->getBaseDisplay()->getXDisplay(),
271 control->getVisual(), control->getDepth(), ZPixmap, 0, 0,
272 width, height, 32, 0);
275 fprintf(stderr, i18n->getMessage(ImageSet, ImageErrorCreatingXImage,
276 "BImage::renderXImage: error creating XImage\n"));
281 image->data = (char *) 0;
283 unsigned char *d = new unsigned char[image->bytes_per_line * (height + 1)];
284 register unsigned int x, y, dithx, dithy, r, g, b, o, er, eg, eb, offset;
286 unsigned char *pixel_data = d, *ppixel_data = d;
289 o = image->bits_per_pixel + ((image->byte_order == MSBFirst) ? 1 : 0);
291 if (control->doDither() && width > 1 && height > 1) {
292 unsigned char dither4[4][4] = { {0, 4, 1, 5},
298 unsigned char dither8[8][8] = { { 0, 32, 8, 40, 2, 34, 10, 42 },
299 { 48, 16, 56, 24, 50, 18, 58, 26 },
300 { 12, 44, 4, 36, 14, 46, 6, 38 },
301 { 60, 28, 52, 20, 62, 30, 54, 22 },
302 { 3, 35, 11, 43, 1, 33, 9, 41 },
303 { 51, 19, 59, 27, 49, 17, 57, 25 },
304 { 15, 47, 7, 39, 13, 45, 5, 37 },
305 { 63, 31, 55, 23, 61, 29, 53, 21 } };
306 #endif // ORDEREDPSEUDO
308 switch (control->getVisual()->c_class) {
310 // algorithm: ordered dithering... many many thanks to rasterman
311 // (raster@rasterman.com) for telling me about this... portions of this
312 // code is based off of his code in Imlib
313 for (y = 0, offset = 0; y < height; y++) {
316 for (x = 0; x < width; x++, offset++) {
322 er = r & (red_bits - 1);
323 eg = g & (green_bits - 1);
324 eb = b & (blue_bits - 1);
330 if ((dither4[dithy][dithx] < er) && (r < red_table[255])) r++;
331 if ((dither4[dithy][dithx] < eg) && (g < green_table[255])) g++;
332 if ((dither4[dithy][dithx] < eb) && (b < blue_table[255])) b++;
334 pixel = (r << red_offset) | (g << green_offset) | (b << blue_offset);
338 *pixel_data++ = pixel;
341 case 16: // 16bpp LSB
342 *pixel_data++ = pixel;
343 *pixel_data++ = pixel >> 8;
346 case 17: // 16bpp MSB
347 *pixel_data++ = pixel >> 8;
348 *pixel_data++ = pixel;
351 case 24: // 24bpp LSB
352 *pixel_data++ = pixel;
353 *pixel_data++ = pixel >> 8;
354 *pixel_data++ = pixel >> 16;
357 case 25: // 24bpp MSB
358 *pixel_data++ = pixel >> 16;
359 *pixel_data++ = pixel >> 8;
360 *pixel_data++ = pixel;
363 case 32: // 32bpp LSB
364 *pixel_data++ = pixel;
365 *pixel_data++ = pixel >> 8;
366 *pixel_data++ = pixel >> 16;
367 *pixel_data++ = pixel >> 24;
370 case 33: // 32bpp MSB
371 *pixel_data++ = pixel >> 24;
372 *pixel_data++ = pixel >> 16;
373 *pixel_data++ = pixel >> 8;
374 *pixel_data++ = pixel;
379 pixel_data = (ppixel_data += image->bytes_per_line);
386 #ifndef ORDEREDPSEUDO
388 *rerr = new short[width + 2],
389 *gerr = new short[width + 2],
390 *berr = new short[width + 2],
391 *nrerr = new short[width + 2],
392 *ngerr = new short[width + 2],
393 *nberr = new short[width + 2];
394 int rr, gg, bb, rer, ger, ber;
395 int dd = 255 / control->getColorsPerChannel();
397 for (x = 0; x < width; x++) {
398 *(rerr + x) = *(red + x);
399 *(gerr + x) = *(green + x);
400 *(berr + x) = *(blue + x);
403 *(rerr + x) = *(gerr + x) = *(berr + x) = 0;
404 #endif // ORDEREDPSEUDO
406 for (y = 0, offset = 0; y < height; y++) {
410 for (x = 0; x < width; x++, offset++) {
417 er = r & (red_bits - 1);
418 eg = g & (green_bits - 1);
419 eb = b & (blue_bits - 1);
425 if ((dither8[dithy][dithx] < er) && (r < red_table[255])) r++;
426 if ((dither8[dithy][dithx] < eg) && (g < green_table[255])) g++;
427 if ((dither8[dithy][dithx] < eb) && (b < blue_table[255])) b++;
429 pixel = (r * cpccpc) + (g * cpc) + b;
430 *(pixel_data++) = colors[pixel].pixel;
433 pixel_data = (ppixel_data += image->bytes_per_line);
435 #else // !ORDEREDPSEUDO
436 if (y < (height - 1)) {
437 int i = offset + width;
438 for (x = 0; x < width; x++, i++) {
439 *(nrerr + x) = *(red + i);
440 *(ngerr + x) = *(green + i);
441 *(nberr + x) = *(blue + i);
444 *(nrerr + x) = *(red + (--i));
445 *(ngerr + x) = *(green + i);
446 *(nberr + x) = *(blue + i);
449 for (x = 0; x < width; x++) {
454 if (rr > 255) rr = 255; else if (rr < 0) rr = 0;
455 if (gg > 255) gg = 255; else if (gg < 0) gg = 0;
456 if (bb > 255) bb = 255; else if (bb < 0) bb = 0;
462 rer = rerr[x] - r*dd;
463 ger = gerr[x] - g*dd;
464 ber = berr[x] - b*dd;
466 pixel = (r * cpccpc) + (g * cpc) + b;
467 *pixel_data++ = colors[pixel].pixel;
482 pixel_data = (ppixel_data += image->bytes_per_line);
503 #endif // ORDEREDPSUEDO
508 fprintf(stderr, i18n->getMessage(ImageSet, ImageUnsupVisual,
509 "BImage::renderXImage: unsupported visual\n"));
511 XDestroyImage(image);
515 switch (control->getVisual()->c_class) {
518 for (y = 0, offset = 0; y < height; y++) {
519 for (x = 0; x < width; x++, offset++) {
520 r = red_table[red[offset]];
521 g = green_table[green[offset]];
522 b = blue_table[blue[offset]];
524 pixel = (r * cpccpc) + (g * cpc) + b;
525 *pixel_data++ = colors[pixel].pixel;
528 pixel_data = (ppixel_data += image->bytes_per_line);
534 for (y = 0, offset = 0; y < height; y++) {
535 for (x = 0; x < width; x++, offset++) {
536 r = red_table[red[offset]];
537 g = green_table[green[offset]];
538 b = blue_table[blue[offset]];
540 pixel = (r << red_offset) | (g << green_offset) | (b << blue_offset);
544 *pixel_data++ = pixel;
547 case 16: // 16bpp LSB
548 *pixel_data++ = pixel;
549 *pixel_data++ = pixel >> 8;
552 case 17: // 16bpp MSB
553 *pixel_data++ = pixel >> 8;
554 *pixel_data++ = pixel;
557 case 24: // 24bpp LSB
558 *pixel_data++ = pixel;
559 *pixel_data++ = pixel >> 8;
560 *pixel_data++ = pixel >> 16;
563 case 25: // 24bpp MSB
564 *pixel_data++ = pixel >> 16;
565 *pixel_data++ = pixel >> 8;
566 *pixel_data++ = pixel;
569 case 32: // 32bpp LSB
570 *pixel_data++ = pixel;
571 *pixel_data++ = pixel >> 8;
572 *pixel_data++ = pixel >> 16;
573 *pixel_data++ = pixel >> 24;
576 case 33: // 32bpp MSB
577 *pixel_data++ = pixel >> 24;
578 *pixel_data++ = pixel >> 16;
579 *pixel_data++ = pixel >> 8;
580 *pixel_data++ = pixel;
585 pixel_data = (ppixel_data += image->bytes_per_line);
592 for (y = 0, offset = 0; y < height; y++) {
593 for (x = 0; x < width; x++, offset++) {
594 r = *(red_table + *(red + offset));
595 g = *(green_table + *(green + offset));
596 b = *(blue_table + *(blue + offset));
598 g = ((r * 30) + (g * 59) + (b * 11)) / 100;
599 *pixel_data++ = colors[g].pixel;
602 pixel_data = (ppixel_data += image->bytes_per_line);
608 fprintf(stderr, i18n->getMessage(ImageSet, ImageUnsupVisual,
609 "BImage::renderXImage: unsupported visual\n"));
611 XDestroyImage(image);
616 image->data = (char *) d;
621 Pixmap BImage::renderPixmap(void) {
623 XCreatePixmap(control->getBaseDisplay()->getXDisplay(),
624 control->getDrawable(), width, height, control->getDepth());
626 if (pixmap == None) {
627 fprintf(stderr, i18n->getMessage(ImageSet, ImageErrorCreatingPixmap,
628 "BImage::renderPixmap: error creating pixmap\n"));
632 XImage *image = renderXImage();
635 XFreePixmap(control->getBaseDisplay()->getXDisplay(), pixmap);
637 } else if (! image->data) {
638 XDestroyImage(image);
639 XFreePixmap(control->getBaseDisplay()->getXDisplay(), pixmap);
643 XPutImage(control->getBaseDisplay()->getXDisplay(), pixmap,
644 DefaultGC(control->getBaseDisplay()->getXDisplay(),
645 control->getScreenInfo()->getScreenNumber()),
646 image, 0, 0, 0, 0, width, height);
649 delete [] image->data;
653 XDestroyImage(image);
659 void BImage::bevel1(void) {
660 if (width > 2 && height > 2) {
661 unsigned char *pr = red, *pg = green, *pb = blue;
663 register unsigned char r, g, b, rr ,gg ,bb;
664 register unsigned int w = width, h = height - 1, wh = w * h;
682 rr = (r >> 2) + (r >> 1);
685 gg = (g >> 2) + (g >> 1);
688 bb = (b >> 2) + (b >> 1);
711 rr = (r >> 2) + (r >> 1);
714 gg = (g >> 2) + (g >> 1);
717 bb = (b >> 2) + (b >> 1);
748 rr = (r >> 2) + (r >> 1);
751 gg = (g >> 2) + (g >> 1);
754 bb = (b >> 2) + (b >> 1);
781 rr = (r >> 2) + (r >> 1);
784 gg = (g >> 2) + (g >> 1);
787 bb = (b >> 2) + (b >> 1);
797 void BImage::bevel2(void) {
798 if (width > 4 && height > 4) {
799 unsigned char r, g, b, rr ,gg ,bb, *pr = red + width + 1,
800 *pg = green + width + 1, *pb = blue + width + 1;
801 unsigned int w = width - 2, h = height - 1, wh = width * (height - 3);
819 rr = (r >> 2) + (r >> 1);
822 gg = (g >> 2) + (g >> 1);
825 bb = (b >> 2) + (b >> 1);
857 rr = (r >> 2) + (r >> 1);
860 gg = (g >> 2) + (g >> 1);
863 bb = (b >> 2) + (b >> 1);
876 void BImage::invert(void) {
877 register unsigned int i, j, wh = (width * height) - 1;
880 for (i = 0, j = wh; j > i; j--, i++) {
882 *(red + j) = *(red + i);
886 *(green + j) = *(green + i);
890 *(blue + j) = *(blue + i);
896 void BImage::dgradient(void) {
897 // diagonal gradient code was written by Mike Cole <mike@mydot.com>
898 // modified for interlacing by Brad Hughes
900 float drx, dgx, dbx, dry, dgy, dby, yr = 0.0, yg = 0.0, yb = 0.0,
901 xr = (float) from->getRed(),
902 xg = (float) from->getGreen(),
903 xb = (float) from->getBlue();
904 unsigned char *pr = red, *pg = green, *pb = blue;
905 unsigned int w = width * 2, h = height * 2, *xt = xtable, *yt = ytable;
907 register unsigned int x, y;
909 dry = drx = (float) (to->getRed() - from->getRed());
910 dgy = dgx = (float) (to->getGreen() - from->getGreen());
911 dby = dbx = (float) (to->getBlue() - from->getBlue());
918 for (x = 0; x < width; x++) {
919 *(xt++) = (unsigned char) (xr);
920 *(xt++) = (unsigned char) (xg);
921 *(xt++) = (unsigned char) (xb);
933 for (y = 0; y < height; y++) {
934 *(yt++) = ((unsigned char) yr);
935 *(yt++) = ((unsigned char) yg);
936 *(yt++) = ((unsigned char) yb);
943 // Combine tables to create gradient
950 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
951 for (xt = xtable, x = 0; x < width; x++) {
952 *(pr++) = *(xt++) + *(yt);
953 *(pg++) = *(xt++) + *(yt + 1);
954 *(pb++) = *(xt++) + *(yt + 2);
960 // faked interlacing effect
961 unsigned char channel, channel2;
963 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
964 for (xt = xtable, x = 0; x < width; x++) {
966 channel = *(xt++) + *(yt);
967 channel2 = (channel >> 1) + (channel >> 2);
968 if (channel2 > channel) channel2 = 0;
971 channel = *(xt++) + *(yt + 1);
972 channel2 = (channel >> 1) + (channel >> 2);
973 if (channel2 > channel) channel2 = 0;
976 channel = *(xt++) + *(yt + 2);
977 channel2 = (channel >> 1) + (channel >> 2);
978 if (channel2 > channel) channel2 = 0;
981 channel = *(xt++) + *(yt);
982 channel2 = channel + (channel >> 3);
983 if (channel2 < channel) channel2 = ~0;
986 channel = *(xt++) + *(yt + 1);
987 channel2 = channel + (channel >> 3);
988 if (channel2 < channel) channel2 = ~0;
991 channel = *(xt++) + *(yt + 2);
992 channel2 = channel + (channel >> 3);
993 if (channel2 < channel) channel2 = ~0;
1004 void BImage::hgradient(void) {
1005 float drx, dgx, dbx,
1006 xr = (float) from->getRed(),
1007 xg = (float) from->getGreen(),
1008 xb = (float) from->getBlue();
1009 unsigned char *pr = red, *pg = green, *pb = blue;
1011 register unsigned int x, y;
1013 drx = (float) (to->getRed() - from->getRed());
1014 dgx = (float) (to->getGreen() - from->getGreen());
1015 dbx = (float) (to->getBlue() - from->getBlue());
1022 if (interlaced && height > 2) {
1023 // faked interlacing effect
1024 unsigned char channel, channel2;
1026 for (x = 0; x < width; x++, pr++, pg++, pb++) {
1027 channel = (unsigned char) xr;
1028 channel2 = (channel >> 1) + (channel >> 2);
1029 if (channel2 > channel) channel2 = 0;
1032 channel = (unsigned char) xg;
1033 channel2 = (channel >> 1) + (channel >> 2);
1034 if (channel2 > channel) channel2 = 0;
1037 channel = (unsigned char) xb;
1038 channel2 = (channel >> 1) + (channel >> 2);
1039 if (channel2 > channel) channel2 = 0;
1043 channel = (unsigned char) xr;
1044 channel2 = channel + (channel >> 3);
1045 if (channel2 < channel) channel2 = ~0;
1046 *(pr + width) = channel2;
1048 channel = (unsigned char) xg;
1049 channel2 = channel + (channel >> 3);
1050 if (channel2 < channel) channel2 = ~0;
1051 *(pg + width) = channel2;
1053 channel = (unsigned char) xb;
1054 channel2 = channel + (channel >> 3);
1055 if (channel2 < channel) channel2 = ~0;
1056 *(pb + width) = channel2;
1069 for (y = 2; y < height; y++, pr += width, pg += width, pb += width) {
1070 if (y & 1) offset = width; else offset = 0;
1072 memcpy(pr, (red + offset), width);
1073 memcpy(pg, (green + offset), width);
1074 memcpy(pb, (blue + offset), width);
1080 for (x = 0; x < width; x++) {
1081 *(pr++) = (unsigned char) (xr);
1082 *(pg++) = (unsigned char) (xg);
1083 *(pb++) = (unsigned char) (xb);
1090 for (y = 1; y < height; y++, pr += width, pg += width, pb += width) {
1091 memcpy(pr, red, width);
1092 memcpy(pg, green, width);
1093 memcpy(pb, blue, width);
1103 void BImage::vgradient(void) {
1104 float dry, dgy, dby,
1105 yr = (float) from->getRed(),
1106 yg = (float) from->getGreen(),
1107 yb = (float) from->getBlue();
1108 unsigned char *pr = red, *pg = green, *pb = blue;
1110 register unsigned int y;
1112 dry = (float) (to->getRed() - from->getRed());
1113 dgy = (float) (to->getGreen() - from->getGreen());
1114 dby = (float) (to->getBlue() - from->getBlue());
1122 // faked interlacing effect
1123 unsigned char channel, channel2;
1125 for (y = 0; y < height; y++, pr += width, pg += width, pb += width) {
1127 channel = (unsigned char) yr;
1128 channel2 = (channel >> 1) + (channel >> 2);
1129 if (channel2 > channel) channel2 = 0;
1130 memset(pr, channel2, width);
1132 channel = (unsigned char) yg;
1133 channel2 = (channel >> 1) + (channel >> 2);
1134 if (channel2 > channel) channel2 = 0;
1135 memset(pg, channel2, width);
1137 channel = (unsigned char) yb;
1138 channel2 = (channel >> 1) + (channel >> 2);
1139 if (channel2 > channel) channel2 = 0;
1140 memset(pb, channel2, width);
1142 channel = (unsigned char) yr;
1143 channel2 = channel + (channel >> 3);
1144 if (channel2 < channel) channel2 = ~0;
1145 memset(pr, channel2, width);
1147 channel = (unsigned char) yg;
1148 channel2 = channel + (channel >> 3);
1149 if (channel2 < channel) channel2 = ~0;
1150 memset(pg, channel2, width);
1152 channel = (unsigned char) yb;
1153 channel2 = channel + (channel >> 3);
1154 if (channel2 < channel) channel2 = ~0;
1155 memset(pb, channel2, width);
1166 for (y = 0; y < height; y++, pr += width, pg += width, pb += width) {
1167 memset(pr, (unsigned char) yr, width);
1168 memset(pg, (unsigned char) yg, width);
1169 memset(pb, (unsigned char) yb, width);
1183 void BImage::pgradient(void) {
1184 // pyramid gradient - based on original dgradient, written by
1185 // Mosfet (mosfet@kde.org)
1186 // adapted from kde sources for Openbox by Brad Hughes
1188 float yr, yg, yb, drx, dgx, dbx, dry, dgy, dby,
1190 int rsign, gsign, bsign;
1191 unsigned char *pr = red, *pg = green, *pb = blue;
1192 unsigned int tr = to->getRed(), tg = to->getGreen(), tb = to->getBlue(),
1193 *xt = xtable, *yt = ytable;
1195 register unsigned int x, y;
1197 dry = drx = (float) (to->getRed() - from->getRed());
1198 dgy = dgx = (float) (to->getGreen() - from->getGreen());
1199 dby = dbx = (float) (to->getBlue() - from->getBlue());
1201 rsign = (drx < 0) ? -1 : 1;
1202 gsign = (dgx < 0) ? -1 : 1;
1203 bsign = (dbx < 0) ? -1 : 1;
1205 xr = yr = (drx / 2);
1206 xg = yg = (dgx / 2);
1207 xb = yb = (dbx / 2);
1214 for (x = 0; x < width; x++) {
1215 *(xt++) = (unsigned char) ((xr < 0) ? -xr : xr);
1216 *(xt++) = (unsigned char) ((xg < 0) ? -xg : xg);
1217 *(xt++) = (unsigned char) ((xb < 0) ? -xb : xb);
1229 for (y = 0; y < height; y++) {
1230 *(yt++) = ((unsigned char) ((yr < 0) ? -yr : yr));
1231 *(yt++) = ((unsigned char) ((yg < 0) ? -yg : yg));
1232 *(yt++) = ((unsigned char) ((yb < 0) ? -yb : yb));
1239 // Combine tables to create gradient
1246 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1247 for (xt = xtable, x = 0; x < width; x++) {
1248 *(pr++) = (unsigned char) (tr - (rsign * (*(xt++) + *(yt))));
1249 *(pg++) = (unsigned char) (tg - (gsign * (*(xt++) + *(yt + 1))));
1250 *(pb++) = (unsigned char) (tb - (bsign * (*(xt++) + *(yt + 2))));
1256 // faked interlacing effect
1257 unsigned char channel, channel2;
1259 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1260 for (xt = xtable, x = 0; x < width; x++) {
1262 channel = (unsigned char) (tr - (rsign * (*(xt++) + *(yt))));
1263 channel2 = (channel >> 1) + (channel >> 2);
1264 if (channel2 > channel) channel2 = 0;
1267 channel = (unsigned char) (tg - (gsign * (*(xt++) + *(yt + 1))));
1268 channel2 = (channel >> 1) + (channel >> 2);
1269 if (channel2 > channel) channel2 = 0;
1272 channel = (unsigned char) (tb - (bsign * (*(xt++) + *(yt + 2))));
1273 channel2 = (channel >> 1) + (channel >> 2);
1274 if (channel2 > channel) channel2 = 0;
1277 channel = (unsigned char) (tr - (rsign * (*(xt++) + *(yt))));
1278 channel2 = channel + (channel >> 3);
1279 if (channel2 < channel) channel2 = ~0;
1282 channel = (unsigned char) (tg - (gsign * (*(xt++) + *(yt + 1))));
1283 channel2 = channel + (channel >> 3);
1284 if (channel2 < channel) channel2 = ~0;
1287 channel = (unsigned char) (tb - (bsign * (*(xt++) + *(yt + 2))));
1288 channel2 = channel + (channel >> 3);
1289 if (channel2 < channel) channel2 = ~0;
1299 void BImage::rgradient(void) {
1300 // rectangle gradient - based on original dgradient, written by
1301 // Mosfet (mosfet@kde.org)
1302 // adapted from kde sources for Openbox by Brad Hughes
1304 float drx, dgx, dbx, dry, dgy, dby, xr, xg, xb, yr, yg, yb;
1305 int rsign, gsign, bsign;
1306 unsigned char *pr = red, *pg = green, *pb = blue;
1307 unsigned int tr = to->getRed(), tg = to->getGreen(), tb = to->getBlue(),
1308 *xt = xtable, *yt = ytable;
1310 register unsigned int x, y;
1312 dry = drx = (float) (to->getRed() - from->getRed());
1313 dgy = dgx = (float) (to->getGreen() - from->getGreen());
1314 dby = dbx = (float) (to->getBlue() - from->getBlue());
1316 rsign = (drx < 0) ? -2 : 2;
1317 gsign = (dgx < 0) ? -2 : 2;
1318 bsign = (dbx < 0) ? -2 : 2;
1320 xr = yr = (drx / 2);
1321 xg = yg = (dgx / 2);
1322 xb = yb = (dbx / 2);
1329 for (x = 0; x < width; x++) {
1330 *(xt++) = (unsigned char) ((xr < 0) ? -xr : xr);
1331 *(xt++) = (unsigned char) ((xg < 0) ? -xg : xg);
1332 *(xt++) = (unsigned char) ((xb < 0) ? -xb : xb);
1344 for (y = 0; y < height; y++) {
1345 *(yt++) = ((unsigned char) ((yr < 0) ? -yr : yr));
1346 *(yt++) = ((unsigned char) ((yg < 0) ? -yg : yg));
1347 *(yt++) = ((unsigned char) ((yb < 0) ? -yb : yb));
1354 // Combine tables to create gradient
1361 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1362 for (xt = xtable, x = 0; x < width; x++) {
1363 *(pr++) = (unsigned char) (tr - (rsign * max(*(xt++), *(yt))));
1364 *(pg++) = (unsigned char) (tg - (gsign * max(*(xt++), *(yt + 1))));
1365 *(pb++) = (unsigned char) (tb - (bsign * max(*(xt++), *(yt + 2))));
1371 // faked interlacing effect
1372 unsigned char channel, channel2;
1374 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1375 for (xt = xtable, x = 0; x < width; x++) {
1377 channel = (unsigned char) (tr - (rsign * max(*(xt++), *(yt))));
1378 channel2 = (channel >> 1) + (channel >> 2);
1379 if (channel2 > channel) channel2 = 0;
1382 channel = (unsigned char) (tg - (gsign * max(*(xt++), *(yt + 1))));
1383 channel2 = (channel >> 1) + (channel >> 2);
1384 if (channel2 > channel) channel2 = 0;
1387 channel = (unsigned char) (tb - (bsign * max(*(xt++), *(yt + 2))));
1388 channel2 = (channel >> 1) + (channel >> 2);
1389 if (channel2 > channel) channel2 = 0;
1392 channel = (unsigned char) (tr - (rsign * max(*(xt++), *(yt))));
1393 channel2 = channel + (channel >> 3);
1394 if (channel2 < channel) channel2 = ~0;
1397 channel = (unsigned char) (tg - (gsign * max(*(xt++), *(yt + 1))));
1398 channel2 = channel + (channel >> 3);
1399 if (channel2 < channel) channel2 = ~0;
1402 channel = (unsigned char) (tb - (bsign * max(*(xt++), *(yt + 2))));
1403 channel2 = channel + (channel >> 3);
1404 if (channel2 < channel) channel2 = ~0;
1414 void BImage::egradient(void) {
1415 // elliptic gradient - based on original dgradient, written by
1416 // Mosfet (mosfet@kde.org)
1417 // adapted from kde sources for Openbox by Brad Hughes
1419 float drx, dgx, dbx, dry, dgy, dby, yr, yg, yb, xr, xg, xb;
1420 int rsign, gsign, bsign;
1421 unsigned char *pr = red, *pg = green, *pb = blue;
1422 unsigned int *xt = xtable, *yt = ytable,
1423 tr = (unsigned long) to->getRed(),
1424 tg = (unsigned long) to->getGreen(),
1425 tb = (unsigned long) to->getBlue();
1427 register unsigned int x, y;
1429 dry = drx = (float) (to->getRed() - from->getRed());
1430 dgy = dgx = (float) (to->getGreen() - from->getGreen());
1431 dby = dbx = (float) (to->getBlue() - from->getBlue());
1433 rsign = (drx < 0) ? -1 : 1;
1434 gsign = (dgx < 0) ? -1 : 1;
1435 bsign = (dbx < 0) ? -1 : 1;
1437 xr = yr = (drx / 2);
1438 xg = yg = (dgx / 2);
1439 xb = yb = (dbx / 2);
1446 for (x = 0; x < width; x++) {
1447 *(xt++) = (unsigned long) (xr * xr);
1448 *(xt++) = (unsigned long) (xg * xg);
1449 *(xt++) = (unsigned long) (xb * xb);
1461 for (y = 0; y < height; y++) {
1462 *(yt++) = (unsigned long) (yr * yr);
1463 *(yt++) = (unsigned long) (yg * yg);
1464 *(yt++) = (unsigned long) (yb * yb);
1471 // Combine tables to create gradient
1478 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1479 for (xt = xtable, x = 0; x < width; x++) {
1480 *(pr++) = (unsigned char)
1481 (tr - (rsign * control->getSqrt(*(xt++) + *(yt))));
1482 *(pg++) = (unsigned char)
1483 (tg - (gsign * control->getSqrt(*(xt++) + *(yt + 1))));
1484 *(pb++) = (unsigned char)
1485 (tb - (bsign * control->getSqrt(*(xt++) + *(yt + 2))));
1491 // faked interlacing effect
1492 unsigned char channel, channel2;
1494 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1495 for (xt = xtable, x = 0; x < width; x++) {
1497 channel = (unsigned char)
1498 (tr - (rsign * control->getSqrt(*(xt++) + *(yt))));
1499 channel2 = (channel >> 1) + (channel >> 2);
1500 if (channel2 > channel) channel2 = 0;
1503 channel = (unsigned char)
1504 (tg - (gsign * control->getSqrt(*(xt++) + *(yt + 1))));
1505 channel2 = (channel >> 1) + (channel >> 2);
1506 if (channel2 > channel) channel2 = 0;
1509 channel = (unsigned char)
1510 (tb - (bsign * control->getSqrt(*(xt++) + *(yt + 2))));
1511 channel2 = (channel >> 1) + (channel >> 2);
1512 if (channel2 > channel) channel2 = 0;
1515 channel = (unsigned char)
1516 (tr - (rsign * control->getSqrt(*(xt++) + *(yt))));
1517 channel2 = channel + (channel >> 3);
1518 if (channel2 < channel) channel2 = ~0;
1521 channel = (unsigned char)
1522 (tg - (gsign * control->getSqrt(*(xt++) + *(yt + 1))));
1523 channel2 = channel + (channel >> 3);
1524 if (channel2 < channel) channel2 = ~0;
1527 channel = (unsigned char)
1528 (tb - (bsign * control->getSqrt(*(xt++) + *(yt + 2))));
1529 channel2 = channel + (channel >> 3);
1530 if (channel2 < channel) channel2 = ~0;
1540 void BImage::pcgradient(void) {
1541 // pipe cross gradient - based on original dgradient, written by
1542 // Mosfet (mosfet@kde.org)
1543 // adapted from kde sources for Openbox by Brad Hughes
1545 float drx, dgx, dbx, dry, dgy, dby, xr, xg, xb, yr, yg, yb;
1546 int rsign, gsign, bsign;
1547 unsigned char *pr = red, *pg = green, *pb = blue;
1548 unsigned int *xt = xtable, *yt = ytable,
1550 tg = to->getGreen(),
1553 register unsigned int x, y;
1555 dry = drx = (float) (to->getRed() - from->getRed());
1556 dgy = dgx = (float) (to->getGreen() - from->getGreen());
1557 dby = dbx = (float) (to->getBlue() - from->getBlue());
1559 rsign = (drx < 0) ? -2 : 2;
1560 gsign = (dgx < 0) ? -2 : 2;
1561 bsign = (dbx < 0) ? -2 : 2;
1563 xr = yr = (drx / 2);
1564 xg = yg = (dgx / 2);
1565 xb = yb = (dbx / 2);
1572 for (x = 0; x < width; x++) {
1573 *(xt++) = (unsigned char) ((xr < 0) ? -xr : xr);
1574 *(xt++) = (unsigned char) ((xg < 0) ? -xg : xg);
1575 *(xt++) = (unsigned char) ((xb < 0) ? -xb : xb);
1587 for (y = 0; y < height; y++) {
1588 *(yt++) = ((unsigned char) ((yr < 0) ? -yr : yr));
1589 *(yt++) = ((unsigned char) ((yg < 0) ? -yg : yg));
1590 *(yt++) = ((unsigned char) ((yb < 0) ? -yb : yb));
1597 // Combine tables to create gradient
1603 // normal pcgradient
1604 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1605 for (xt = xtable, x = 0; x < width; x++) {
1606 *(pr++) = (unsigned char) (tr - (rsign * min(*(xt++), *(yt))));
1607 *(pg++) = (unsigned char) (tg - (gsign * min(*(xt++), *(yt + 1))));
1608 *(pb++) = (unsigned char) (tb - (bsign * min(*(xt++), *(yt + 2))));
1614 // faked interlacing effect
1615 unsigned char channel, channel2;
1617 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1618 for (xt = xtable, x = 0; x < width; x++) {
1620 channel = (unsigned char) (tr - (rsign * min(*(xt++), *(yt))));
1621 channel2 = (channel >> 1) + (channel >> 2);
1622 if (channel2 > channel) channel2 = 0;
1625 channel = (unsigned char) (tg - (bsign * min(*(xt++), *(yt + 1))));
1626 channel2 = (channel >> 1) + (channel >> 2);
1627 if (channel2 > channel) channel2 = 0;
1630 channel = (unsigned char) (tb - (gsign * min(*(xt++), *(yt + 2))));
1631 channel2 = (channel >> 1) + (channel >> 2);
1632 if (channel2 > channel) channel2 = 0;
1635 channel = (unsigned char) (tr - (rsign * min(*(xt++), *(yt))));
1636 channel2 = channel + (channel >> 3);
1637 if (channel2 < channel) channel2 = ~0;
1640 channel = (unsigned char) (tg - (gsign * min(*(xt++), *(yt + 1))));
1641 channel2 = channel + (channel >> 3);
1642 if (channel2 < channel) channel2 = ~0;
1645 channel = (unsigned char) (tb - (bsign * min(*(xt++), *(yt + 2))));
1646 channel2 = channel + (channel >> 3);
1647 if (channel2 < channel) channel2 = ~0;
1657 void BImage::cdgradient(void) {
1658 // cross diagonal gradient - based on original dgradient, written by
1659 // Mosfet (mosfet@kde.org)
1660 // adapted from kde sources for Openbox by Brad Hughes
1662 float drx, dgx, dbx, dry, dgy, dby, yr = 0.0, yg = 0.0, yb = 0.0,
1663 xr = (float) from->getRed(),
1664 xg = (float) from->getGreen(),
1665 xb = (float) from->getBlue();
1666 unsigned char *pr = red, *pg = green, *pb = blue;
1667 unsigned int w = width * 2, h = height * 2, *xt, *yt;
1669 register unsigned int x, y;
1671 dry = drx = (float) (to->getRed() - from->getRed());
1672 dgy = dgx = (float) (to->getGreen() - from->getGreen());
1673 dby = dbx = (float) (to->getBlue() - from->getBlue());
1680 for (xt = (xtable + (width * 3) - 1), x = 0; x < width; x++) {
1681 *(xt--) = (unsigned char) xb;
1682 *(xt--) = (unsigned char) xg;
1683 *(xt--) = (unsigned char) xr;
1695 for (yt = ytable, y = 0; y < height; y++) {
1696 *(yt++) = (unsigned char) yr;
1697 *(yt++) = (unsigned char) yg;
1698 *(yt++) = (unsigned char) yb;
1705 // Combine tables to create gradient
1711 // normal cdgradient
1712 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1713 for (xt = xtable, x = 0; x < width; x++) {
1714 *(pr++) = *(xt++) + *(yt);
1715 *(pg++) = *(xt++) + *(yt + 1);
1716 *(pb++) = *(xt++) + *(yt + 2);
1722 // faked interlacing effect
1723 unsigned char channel, channel2;
1725 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1726 for (xt = xtable, x = 0; x < width; x++) {
1728 channel = *(xt++) + *(yt);
1729 channel2 = (channel >> 1) + (channel >> 2);
1730 if (channel2 > channel) channel2 = 0;
1733 channel = *(xt++) + *(yt + 1);
1734 channel2 = (channel >> 1) + (channel >> 2);
1735 if (channel2 > channel) channel2 = 0;
1738 channel = *(xt++) + *(yt + 2);
1739 channel2 = (channel >> 1) + (channel >> 2);
1740 if (channel2 > channel) channel2 = 0;
1743 channel = *(xt++) + *(yt);
1744 channel2 = channel + (channel >> 3);
1745 if (channel2 < channel) channel2 = ~0;
1748 channel = *(xt++) + *(yt + 1);
1749 channel2 = channel + (channel >> 3);
1750 if (channel2 < channel) channel2 = ~0;
1753 channel = *(xt++) + *(yt + 2);
1754 channel2 = channel + (channel >> 3);
1755 if (channel2 < channel) channel2 = ~0;
1765 BImageControl::BImageControl(BaseDisplay *dpy, ScreenInfo *scrn, Bool _dither,
1766 int _cpc, unsigned long cache_timeout,
1772 setColorsPerChannel(_cpc);
1776 if (cache_timeout) {
1777 timer = new BTimer(basedisplay, this);
1778 timer->setTimeout(cache_timeout);
1781 timer = (BTimer *) 0;
1782 #endif // TIMEDCACHE
1784 colors = (XColor *) 0;
1787 grad_xbuffer = grad_ybuffer = (unsigned int *) 0;
1788 grad_buffer_width = grad_buffer_height = 0;
1790 sqrt_table = (unsigned long *) 0;
1792 screen_depth = screeninfo->getDepth();
1793 window = screeninfo->getRootWindow();
1794 screen_number = screeninfo->getScreenNumber();
1797 XPixmapFormatValues *pmv = XListPixmapFormats(basedisplay->getXDisplay(),
1799 colormap = screeninfo->getColormap();
1803 for (int i = 0; i < count; i++)
1804 if (pmv[i].depth == screen_depth) {
1805 bits_per_pixel = pmv[i].bits_per_pixel;
1812 if (bits_per_pixel == 0) bits_per_pixel = screen_depth;
1813 if (bits_per_pixel >= 24) setDither(False);
1815 red_offset = green_offset = blue_offset = 0;
1817 switch (getVisual()->c_class) {
1822 // compute color tables
1823 unsigned long red_mask = getVisual()->red_mask,
1824 green_mask = getVisual()->green_mask,
1825 blue_mask = getVisual()->blue_mask;
1827 while (! (red_mask & 1)) { red_offset++; red_mask >>= 1; }
1828 while (! (green_mask & 1)) { green_offset++; green_mask >>= 1; }
1829 while (! (blue_mask & 1)) { blue_offset++; blue_mask >>= 1; }
1831 red_bits = 255 / red_mask;
1832 green_bits = 255 / green_mask;
1833 blue_bits = 255 / blue_mask;
1835 for (i = 0; i < 256; i++) {
1836 red_color_table[i] = i / red_bits;
1837 green_color_table[i] = i / green_bits;
1838 blue_color_table[i] = i / blue_bits;
1847 ncolors = colors_per_channel * colors_per_channel * colors_per_channel;
1849 if (ncolors > (1 << screen_depth)) {
1850 colors_per_channel = (1 << screen_depth) / 3;
1851 ncolors = colors_per_channel * colors_per_channel * colors_per_channel;
1854 if (colors_per_channel < 2 || ncolors > (1 << screen_depth)) {
1855 fprintf(stderr, i18n->getMessage(ImageSet, ImageInvalidColormapSize,
1856 "BImageControl::BImageControl: invalid colormap size %d "
1857 "(%d/%d/%d) - reducing"),
1858 ncolors, colors_per_channel, colors_per_channel,
1859 colors_per_channel);
1861 colors_per_channel = (1 << screen_depth) / 3;
1864 colors = new XColor[ncolors];
1866 fprintf(stderr, i18n->getMessage(ImageSet,
1867 ImageErrorAllocatingColormap,
1868 "BImageControl::BImageControl: error allocating "
1873 int i = 0, ii, p, r, g, b,
1875 #ifdef ORDEREDPSEUDO
1876 bits = 256 / colors_per_channel;
1877 #else // !ORDEREDPSEUDO
1878 bits = 255 / (colors_per_channel - 1);
1879 #endif // ORDEREDPSEUDO
1881 red_bits = green_bits = blue_bits = bits;
1883 for (i = 0; i < 256; i++)
1884 red_color_table[i] = green_color_table[i] = blue_color_table[i] =
1887 for (r = 0, i = 0; r < colors_per_channel; r++)
1888 for (g = 0; g < colors_per_channel; g++)
1889 for (b = 0; b < colors_per_channel; b++, i++) {
1890 colors[i].red = (r * 0xffff) / (colors_per_channel - 1);
1891 colors[i].green = (g * 0xffff) / (colors_per_channel - 1);
1892 colors[i].blue = (b * 0xffff) / (colors_per_channel - 1);;
1893 colors[i].flags = DoRed|DoGreen|DoBlue;
1896 basedisplay->grab();
1898 for (i = 0; i < ncolors; i++)
1899 if (! XAllocColor(basedisplay->getXDisplay(), colormap, &colors[i])) {
1900 fprintf(stderr, i18n->getMessage(ImageSet, ImageColorAllocFail,
1901 "couldn't alloc color %i %i %i\n"),
1902 colors[i].red, colors[i].green, colors[i].blue);
1903 colors[i].flags = 0;
1905 colors[i].flags = DoRed|DoGreen|DoBlue;
1907 basedisplay->ungrab();
1909 XColor icolors[256];
1910 int incolors = (((1 << screen_depth) > 256) ? 256 : (1 << screen_depth));
1912 for (i = 0; i < incolors; i++)
1913 icolors[i].pixel = i;
1915 XQueryColors(basedisplay->getXDisplay(), colormap, icolors, incolors);
1916 for (i = 0; i < ncolors; i++) {
1917 if (! colors[i].flags) {
1918 unsigned long chk = 0xffffffff, pixel, close = 0;
1922 for (ii = 0; ii < incolors; ii++) {
1923 r = (colors[i].red - icolors[i].red) >> 8;
1924 g = (colors[i].green - icolors[i].green) >> 8;
1925 b = (colors[i].blue - icolors[i].blue) >> 8;
1926 pixel = (r * r) + (g * g) + (b * b);
1933 colors[i].red = icolors[close].red;
1934 colors[i].green = icolors[close].green;
1935 colors[i].blue = icolors[close].blue;
1937 if (XAllocColor(basedisplay->getXDisplay(), colormap,
1939 colors[i].flags = DoRed|DoGreen|DoBlue;
1954 if (getVisual()->c_class == StaticGray) {
1955 ncolors = 1 << screen_depth;
1957 ncolors = colors_per_channel * colors_per_channel * colors_per_channel;
1959 if (ncolors > (1 << screen_depth)) {
1960 colors_per_channel = (1 << screen_depth) / 3;
1962 colors_per_channel * colors_per_channel * colors_per_channel;
1966 if (colors_per_channel < 2 || ncolors > (1 << screen_depth)) {
1967 fprintf(stderr, i18n->getMessage(ImageSet, ImageInvalidColormapSize,
1968 "BImageControl::BImageControl: invalid colormap size %d "
1969 "(%d/%d/%d) - reducing"),
1970 ncolors, colors_per_channel, colors_per_channel,
1971 colors_per_channel);
1973 colors_per_channel = (1 << screen_depth) / 3;
1976 colors = new XColor[ncolors];
1978 fprintf(stderr, i18n->getMessage(ImageSet,
1979 ImageErrorAllocatingColormap,
1980 "BImageControl::BImageControl: error allocating "
1985 int i = 0, ii, p, bits = 255 / (colors_per_channel - 1);
1986 red_bits = green_bits = blue_bits = bits;
1988 for (i = 0; i < 256; i++)
1989 red_color_table[i] = green_color_table[i] = blue_color_table[i] =
1992 basedisplay->grab();
1993 for (i = 0; i < ncolors; i++) {
1994 colors[i].red = (i * 0xffff) / (colors_per_channel - 1);
1995 colors[i].green = (i * 0xffff) / (colors_per_channel - 1);
1996 colors[i].blue = (i * 0xffff) / (colors_per_channel - 1);;
1997 colors[i].flags = DoRed|DoGreen|DoBlue;
1999 if (! XAllocColor(basedisplay->getXDisplay(), colormap,
2001 fprintf(stderr, i18n->getMessage(ImageSet, ImageColorAllocFail,
2002 "couldn't alloc color %i %i %i\n"),
2003 colors[i].red, colors[i].green, colors[i].blue);
2004 colors[i].flags = 0;
2006 colors[i].flags = DoRed|DoGreen|DoBlue;
2009 basedisplay->ungrab();
2011 XColor icolors[256];
2012 int incolors = (((1 << screen_depth) > 256) ? 256 :
2013 (1 << screen_depth));
2015 for (i = 0; i < incolors; i++)
2016 icolors[i].pixel = i;
2018 XQueryColors(basedisplay->getXDisplay(), colormap, icolors, incolors);
2019 for (i = 0; i < ncolors; i++) {
2020 if (! colors[i].flags) {
2021 unsigned long chk = 0xffffffff, pixel, close = 0;
2025 for (ii = 0; ii < incolors; ii++) {
2026 int r = (colors[i].red - icolors[i].red) >> 8;
2027 int g = (colors[i].green - icolors[i].green) >> 8;
2028 int b = (colors[i].blue - icolors[i].blue) >> 8;
2029 pixel = (r * r) + (g * g) + (b * b);
2036 colors[i].red = icolors[close].red;
2037 colors[i].green = icolors[close].green;
2038 colors[i].blue = icolors[close].blue;
2040 if (XAllocColor(basedisplay->getXDisplay(), colormap,
2042 colors[i].flags = DoRed|DoGreen|DoBlue;
2054 fprintf(stderr, i18n->getMessage(ImageSet, ImageUnsupVisual,
2055 "BImageControl::BImageControl: unsupported visual %d\n"),
2056 getVisual()->c_class);
2060 cache = new LinkedList<Cache>;
2064 BImageControl::~BImageControl(void) {
2066 delete [] sqrt_table;
2070 delete [] grad_xbuffer;
2074 delete [] grad_ybuffer;
2078 unsigned long *pixels = new unsigned long [ncolors];
2081 for (i = 0; i < ncolors; i++)
2082 *(pixels + i) = (*(colors + i)).pixel;
2084 XFreeColors(basedisplay->getXDisplay(), colormap, pixels, ncolors, 0);
2089 if (cache->count()) {
2090 int i, n = cache->count();
2091 fprintf(stderr, i18n->getMessage(ImageSet, ImagePixmapRelease,
2092 "BImageContol::~BImageControl: pixmap cache - "
2093 "releasing %d pixmaps\n"), n);
2095 for (i = 0; i < n; i++) {
2096 Cache *tmp = cache->first();
2097 XFreePixmap(basedisplay->getXDisplay(), tmp->pixmap);
2107 #endif // TIMEDCACHE
2114 Pixmap BImageControl::searchCache(unsigned int width, unsigned int height,
2115 unsigned long texture,
2116 BColor *c1, BColor *c2) {
2117 if (cache->count()) {
2118 LinkedListIterator<Cache> it(cache);
2120 for (Cache *tmp = it.current(); tmp; it++, tmp = it.current()) {
2121 if ((tmp->width == width) && (tmp->height == height) &&
2122 (tmp->texture == texture) && (tmp->pixel1 == c1->getPixel()))
2123 if (texture & BImage_Gradient) {
2124 if (tmp->pixel2 == c2->getPixel()) {
2139 Pixmap BImageControl::renderImage(unsigned int width, unsigned int height,
2140 BTexture *texture) {
2141 if (texture->getTexture() & BImage_ParentRelative) return ParentRelative;
2143 Pixmap pixmap = searchCache(width, height, texture->getTexture(),
2144 texture->getColor(), texture->getColorTo());
2145 if (pixmap) return pixmap;
2147 BImage image(this, width, height);
2148 pixmap = image.render(texture);
2151 Cache *tmp = new Cache;
2153 tmp->pixmap = pixmap;
2155 tmp->height = height;
2157 tmp->texture = texture->getTexture();
2158 tmp->pixel1 = texture->getColor()->getPixel();
2160 if (texture->getTexture() & BImage_Gradient)
2161 tmp->pixel2 = texture->getColorTo()->getPixel();
2167 if ((unsigned) cache->count() > cache_max) {
2169 fprintf(stderr, i18n->getMessage(ImageSet, ImagePixmapCacheLarge,
2170 "BImageControl::renderImage: cache is large, "
2171 "forcing cleanout\n"));
2184 void BImageControl::removeImage(Pixmap pixmap) {
2186 LinkedListIterator<Cache> it(cache);
2187 for (Cache *tmp = it.current(); tmp; it++, tmp = it.current()) {
2188 if (tmp->pixmap == pixmap) {
2193 if (! timer) timeout();
2194 #else // !TIMEDCACHE
2195 if (! tmp->count) timeout();
2196 #endif // TIMEDCACHE
2206 unsigned long BImageControl::getColor(const char *colorname,
2207 unsigned char *r, unsigned char *g,
2213 if (! XParseColor(basedisplay->getXDisplay(), colormap, colorname, &color))
2214 fprintf(stderr, "BImageControl::getColor: color parse error: \"%s\"\n",
2216 else if (! XAllocColor(basedisplay->getXDisplay(), colormap, &color))
2217 fprintf(stderr, "BImageControl::getColor: color alloc error: \"%s\"\n",
2220 if (color.red == 65535) *r = 0xff;
2221 else *r = (unsigned char) (color.red / 0xff);
2222 if (color.green == 65535) *g = 0xff;
2223 else *g = (unsigned char) (color.green / 0xff);
2224 if (color.blue == 65535) *b = 0xff;
2225 else *b = (unsigned char) (color.blue / 0xff);
2231 unsigned long BImageControl::getColor(const char *colorname) {
2235 if (! XParseColor(basedisplay->getXDisplay(), colormap, colorname, &color))
2236 fprintf(stderr, "BImageControl::getColor: color parse error: \"%s\"\n",
2238 else if (! XAllocColor(basedisplay->getXDisplay(), colormap, &color))
2239 fprintf(stderr, "BImageControl::getColor: color alloc error: \"%s\"\n",
2246 void BImageControl::getColorTables(unsigned char **rmt, unsigned char **gmt,
2247 unsigned char **bmt,
2248 int *roff, int *goff, int *boff,
2249 int *rbit, int *gbit, int *bbit) {
2250 if (rmt) *rmt = red_color_table;
2251 if (gmt) *gmt = green_color_table;
2252 if (bmt) *bmt = blue_color_table;
2254 if (roff) *roff = red_offset;
2255 if (goff) *goff = green_offset;
2256 if (boff) *boff = blue_offset;
2258 if (rbit) *rbit = red_bits;
2259 if (gbit) *gbit = green_bits;
2260 if (bbit) *bbit = blue_bits;
2264 void BImageControl::getXColorTable(XColor **c, int *n) {
2266 if (n) *n = ncolors;
2270 void BImageControl::getGradientBuffers(unsigned int w,
2272 unsigned int **xbuf,
2273 unsigned int **ybuf)
2275 if (w > grad_buffer_width) {
2277 delete [] grad_xbuffer;
2280 grad_buffer_width = w;
2282 grad_xbuffer = new unsigned int[grad_buffer_width * 3];
2285 if (h > grad_buffer_height) {
2287 delete [] grad_ybuffer;
2290 grad_buffer_height = h;
2292 grad_ybuffer = new unsigned int[grad_buffer_height * 3];
2295 *xbuf = grad_xbuffer;
2296 *ybuf = grad_ybuffer;
2300 void BImageControl::installRootColormap(void) {
2301 basedisplay->grab();
2303 Bool install = True;
2304 int i = 0, ncmap = 0;
2306 XListInstalledColormaps(basedisplay->getXDisplay(), window, &ncmap);
2309 for (i = 0; i < ncmap; i++)
2310 if (*(cmaps + i) == colormap)
2314 XInstallColormap(basedisplay->getXDisplay(), colormap);
2319 basedisplay->ungrab();
2323 void BImageControl::setColorsPerChannel(int cpc) {
2324 if (cpc < 2) cpc = 2;
2325 if (cpc > 6) cpc = 6;
2327 colors_per_channel = cpc;
2331 unsigned long BImageControl::getSqrt(unsigned int x) {
2333 // build sqrt table for use with elliptic gradient
2335 sqrt_table = new unsigned long[(256 * 256 * 2) + 1];
2338 for (; i < (256 * 256 * 2); i++)
2339 *(sqrt_table + i) = bsqrt(i);
2342 return (*(sqrt_table + x));
2346 void BImageControl::parseTexture(BTexture *texture, const char *t) {
2347 if ((! texture) || (! t)) return;
2349 int t_len = strlen(t) + 1, i;
2350 char *ts = new char[t_len];
2353 // convert to lower case
2354 for (i = 0; i < t_len; i++)
2355 *(ts + i) = tolower(*(t + i));
2357 if (strstr(ts, "parentrelative")) {
2358 texture->setTexture(BImage_ParentRelative);
2360 texture->setTexture(0);
2362 if (strstr(ts, "solid"))
2363 texture->addTexture(BImage_Solid);
2364 else if (strstr(ts, "gradient")) {
2365 texture->addTexture(BImage_Gradient);
2366 if (strstr(ts, "crossdiagonal"))
2367 texture->addTexture(BImage_CrossDiagonal);
2368 else if (strstr(ts, "rectangle"))
2369 texture->addTexture(BImage_Rectangle);
2370 else if (strstr(ts, "pyramid"))
2371 texture->addTexture(BImage_Pyramid);
2372 else if (strstr(ts, "pipecross"))
2373 texture->addTexture(BImage_PipeCross);
2374 else if (strstr(ts, "elliptic"))
2375 texture->addTexture(BImage_Elliptic);
2376 else if (strstr(ts, "diagonal"))
2377 texture->addTexture(BImage_Diagonal);
2378 else if (strstr(ts, "horizontal"))
2379 texture->addTexture(BImage_Horizontal);
2380 else if (strstr(ts, "vertical"))
2381 texture->addTexture(BImage_Vertical);
2383 texture->addTexture(BImage_Diagonal);
2385 texture->addTexture(BImage_Solid);
2387 if (strstr(ts, "raised"))
2388 texture->addTexture(BImage_Raised);
2389 else if (strstr(ts, "sunken"))
2390 texture->addTexture(BImage_Sunken);
2391 else if (strstr(ts, "flat"))
2392 texture->addTexture(BImage_Flat);
2394 texture->addTexture(BImage_Raised);
2396 if (! (texture->getTexture() & BImage_Flat))
2397 if (strstr(ts, "bevel2"))
2398 texture->addTexture(BImage_Bevel2);
2400 texture->addTexture(BImage_Bevel1);
2403 if (strstr(ts, "interlaced"))
2404 texture->addTexture(BImage_Interlaced);
2412 void BImageControl::parseColor(BColor *color, const char *c) {
2413 if (! color) return;
2415 if (color->isAllocated()) {
2416 unsigned long pixel = color->getPixel();
2418 XFreeColors(basedisplay->getXDisplay(), colormap, &pixel, 1, 0);
2420 color->setPixel(0l);
2421 color->setRGB(0, 0, 0);
2422 color->setAllocated(False);
2426 unsigned char r, g, b;
2428 color->setPixel(getColor(c, &r, &g, &b));
2429 color->setRGB(r, g, b);
2430 color->setAllocated(True);
2435 void BImageControl::timeout(void) {
2436 LinkedListIterator<Cache> it(cache);
2437 for (Cache *tmp = it.current(); tmp; it++, tmp = it.current()) {
2438 if (tmp->count <= 0) {
2439 XFreePixmap(basedisplay->getXDisplay(), tmp->pixmap);