1 // -*- mode: C++; indent-tabs-mode: nil; -*-
4 # include "../config.h"
5 #endif // HAVE_CONFIG_H
15 #include "blackbox.hh"
16 #include "basedisplay.hh"
22 BImage::BImage(BImageControl *c, int w, int h) {
25 width = (w > 0) ? w : 1;
26 height = (h > 0) ? h : 1;
28 red = new unsigned char[width * height];
29 green = new unsigned char[width * height];
30 blue = new unsigned char[width * height];
32 xtable = ytable = (unsigned int *) 0;
34 cpc = control->getColorsPerChannel();
37 control->getColorTables(&red_table, &green_table, &blue_table,
38 &red_offset, &green_offset, &blue_offset,
39 &red_bits, &green_bits, &blue_bits);
41 if (control->getVisual()->c_class != TrueColor)
42 control->getXColorTable(&colors, &ncolors);
46 BImage::~BImage(void) {
53 Pixmap BImage::render(const BTexture &texture) {
54 if (texture.texture() & BTexture::Parent_Relative)
55 return ParentRelative;
56 else if (texture.texture() & BTexture::Solid)
57 return render_solid(texture);
58 else if (texture.texture() & BTexture::Gradient)
59 return render_gradient(texture);
64 Pixmap BImage::render_solid(const BTexture &texture) {
65 Pixmap pixmap = XCreatePixmap(control->getBaseDisplay()->getXDisplay(),
66 control->getDrawable(), width,
67 height, control->getDepth());
69 fprintf(stderr, "BImage::render_solid: error creating pixmap\n");
73 Display *display = control->getBaseDisplay()->getXDisplay();
75 BPen pen(texture.color());
76 BPen penlight(texture.lightColor());
77 BPen penshadow(texture.shadowColor());
79 XFillRectangle(display, pixmap, pen.gc(), 0, 0, width, height);
81 if (texture.texture() & BTexture::Interlaced) {
82 BPen peninterlace(texture.colorTo());
83 for (unsigned int i = 0; i < height; i += 2)
84 XDrawLine(display, pixmap, peninterlace.gc(), 0, i, width, i);
87 int left = 0, top = 0, right = width - 1, bottom = height - 1;
89 if (texture.texture() & BTexture::Border) {
90 BPen penborder(texture.borderColor());
91 XDrawRectangle(display, pixmap, penborder.gc(),
92 left, top, right, bottom);
95 if (texture.texture() & BTexture::Bevel1) {
96 if (texture.texture() & BTexture::Raised) {
97 XDrawLine(display, pixmap, penshadow.gc(),
98 left, bottom, right, bottom);
99 XDrawLine(display, pixmap, penshadow.gc(),
100 right, bottom, right, top);
102 XDrawLine(display, pixmap, penlight.gc(),
103 left, top, right, top);
104 XDrawLine(display, pixmap, penlight.gc(),
105 left, bottom, left, top);
106 } else if (texture.texture() & BTexture::Sunken) {
107 XDrawLine(display, pixmap, penlight.gc(),
108 left, bottom, right, bottom);
109 XDrawLine(display, pixmap, penlight.gc(),
110 right, bottom, right, top);
112 XDrawLine(display, pixmap, penshadow.gc(),
113 left, top, right, top);
114 XDrawLine(display, pixmap, penshadow.gc(),
115 left, bottom, left, top);
117 } else if (texture.texture() & BTexture::Bevel2) {
118 if (texture.texture() & BTexture::Raised) {
119 XDrawLine(display, pixmap, penshadow.gc(),
120 left + 1, bottom - 2, right - 2, bottom - 2);
121 XDrawLine(display, pixmap, penshadow.gc(),
122 right - 2, bottom - 2, right - 2, top + 1);
124 XDrawLine(display, pixmap, penlight.gc(),
125 left + 1, top + 1, right - 2, top + 1);
126 XDrawLine(display, pixmap, penlight.gc(),
127 left + 1, bottom - 2, left + 1, top + 1);
128 } else if (texture.texture() & BTexture::Sunken) {
129 XDrawLine(display, pixmap, penlight.gc(),
130 left + 1, bottom - 2, right - 2, bottom - 2);
131 XDrawLine(display, pixmap, penlight.gc(),
132 right - 2, bottom - 2, right - 2, top + 1);
134 XDrawLine(display, pixmap, penshadow.gc(),
135 left + 1, top + 1, right - 2, top + 1);
136 XDrawLine(display, pixmap, penshadow.gc(),
137 left + 1, bottom - 2, left + 1, top + 1);
145 Pixmap BImage::render_gradient(const BTexture &texture) {
146 bool inverted = False;
148 interlaced = texture.texture() & BTexture::Interlaced;
150 if (texture.texture() & BTexture::Sunken) {
151 from = texture.colorTo();
152 to = texture.color();
154 if (! (texture.texture() & BTexture::Invert)) inverted = True;
156 from = texture.color();
157 to = texture.colorTo();
159 if (texture.texture() & BTexture::Invert) inverted = True;
162 control->getGradientBuffers(width, height, &xtable, &ytable);
164 if (texture.texture() & BTexture::Diagonal) dgradient();
165 else if (texture.texture() & BTexture::Elliptic) egradient();
166 else if (texture.texture() & BTexture::Horizontal) hgradient();
167 else if (texture.texture() & BTexture::Pyramid) pgradient();
168 else if (texture.texture() & BTexture::Rectangle) rgradient();
169 else if (texture.texture() & BTexture::Vertical) vgradient();
170 else if (texture.texture() & BTexture::CrossDiagonal) cdgradient();
171 else if (texture.texture() & BTexture::PipeCross) pcgradient();
173 if (texture.texture() & BTexture::Bevel1) bevel1();
174 else if (texture.texture() & BTexture::Bevel2) bevel2();
176 if (texture.texture() & BTexture::Border) border(texture);
178 if (inverted) invert();
180 return renderPixmap();
185 static const unsigned char dither4[4][4] = {
194 * Helper function for TrueColorDither and renderXImage
196 * This handles the proper setting of the image data based on the image depth
197 * and the machine's byte ordering
200 void assignPixelData(unsigned int bit_depth, unsigned char **data,
201 unsigned long pixel) {
202 unsigned char *pixel_data = *data;
205 *pixel_data++ = pixel;
208 case 16: // 16bpp LSB
209 *pixel_data++ = pixel;
210 *pixel_data++ = pixel >> 8;
213 case 17: // 16bpp MSB
214 *pixel_data++ = pixel >> 8;
215 *pixel_data++ = pixel;
218 case 24: // 24bpp LSB
219 *pixel_data++ = pixel;
220 *pixel_data++ = pixel >> 8;
221 *pixel_data++ = pixel >> 16;
224 case 25: // 24bpp MSB
225 *pixel_data++ = pixel >> 16;
226 *pixel_data++ = pixel >> 8;
227 *pixel_data++ = pixel;
230 case 32: // 32bpp LSB
231 *pixel_data++ = pixel;
232 *pixel_data++ = pixel >> 8;
233 *pixel_data++ = pixel >> 16;
234 *pixel_data++ = pixel >> 24;
237 case 33: // 32bpp MSB
238 *pixel_data++ = pixel >> 24;
239 *pixel_data++ = pixel >> 16;
240 *pixel_data++ = pixel >> 8;
241 *pixel_data++ = pixel;
244 *data = pixel_data; // assign back so we don't lose our place
248 // algorithm: ordered dithering... many many thanks to rasterman
249 // (raster@rasterman.com) for telling me about this... portions of this
250 // code is based off of his code in Imlib
251 void BImage::TrueColorDither(unsigned int bit_depth, int bytes_per_line,
252 unsigned char *pixel_data) {
253 unsigned int x, y, dithx, dithy, r, g, b, er, eg, eb, offset;
254 unsigned char *ppixel_data = pixel_data;
257 for (y = 0, offset = 0; y < height; y++) {
260 for (x = 0; x < width; x++, offset++) {
266 er = r & (red_bits - 1);
267 eg = g & (green_bits - 1);
268 eb = b & (blue_bits - 1);
274 if ((dither4[dithy][dithx] < er) && (r < red_table[255])) r++;
275 if ((dither4[dithy][dithx] < eg) && (g < green_table[255])) g++;
276 if ((dither4[dithy][dithx] < eb) && (b < blue_table[255])) b++;
278 pixel = (r << red_offset) | (g << green_offset) | (b << blue_offset);
279 assignPixelData(bit_depth, &pixel_data, pixel);
282 pixel_data = (ppixel_data += bytes_per_line);
287 const static unsigned char dither8[8][8] = {
288 { 0, 32, 8, 40, 2, 34, 10, 42},
289 { 48, 16, 56, 24, 50, 18, 58, 26},
290 { 12, 44, 4, 36, 14, 46, 6, 38},
291 { 60, 28, 52, 20, 62, 30, 54, 22},
292 { 3, 35, 11, 43, 1, 33, 9, 41},
293 { 51, 19, 59, 27, 49, 17, 57, 25},
294 { 15, 47, 7, 39, 13, 45, 5, 37},
295 { 63, 31, 55, 23, 61, 29, 53, 21}
298 void BImage::OrderedPseudoColorDither(int bytes_per_line,
299 unsigned char *pixel_data) {
300 unsigned int x, y, dithx, dithy, r, g, b, er, eg, eb, offset;
302 unsigned char *ppixel_data = pixel_data;
304 for (y = 0, offset = 0; y < height; y++) {
307 for (x = 0; x < width; x++, offset++) {
314 er = r & (red_bits - 1);
315 eg = g & (green_bits - 1);
316 eb = b & (blue_bits - 1);
322 if ((dither8[dithy][dithx] < er) && (r < red_table[255])) r++;
323 if ((dither8[dithy][dithx] < eg) && (g < green_table[255])) g++;
324 if ((dither8[dithy][dithx] < eb) && (b < blue_table[255])) b++;
326 pixel = (r * cpccpc) + (g * cpc) + b;
327 *(pixel_data++) = colors[pixel].pixel;
330 pixel_data = (ppixel_data += bytes_per_line);
335 void BImage::PseudoColorDither(int bytes_per_line, unsigned char *pixel_data) {
337 *rerr = new short[width + 2],
338 *gerr = new short[width + 2],
339 *berr = new short[width + 2],
340 *nrerr = new short[width + 2],
341 *ngerr = new short[width + 2],
342 *nberr = new short[width + 2];
344 int rr, gg, bb, rer, ger, ber;
345 int dd = 255 / control->getColorsPerChannel();
346 unsigned int x, y, r, g, b, offset;
348 unsigned char *ppixel_data = pixel_data;
350 for (x = 0; x < width; x++) {
351 *(rerr + x) = *(red + x);
352 *(gerr + x) = *(green + x);
353 *(berr + x) = *(blue + x);
356 *(rerr + x) = *(gerr + x) = *(berr + x) = 0;
358 for (y = 0, offset = 0; y < height; y++) {
359 if (y < (height - 1)) {
360 int i = offset + width;
361 for (x = 0; x < width; x++, i++) {
362 *(nrerr + x) = *(red + i);
363 *(ngerr + x) = *(green + i);
364 *(nberr + x) = *(blue + i);
367 *(nrerr + x) = *(red + (--i));
368 *(ngerr + x) = *(green + i);
369 *(nberr + x) = *(blue + i);
372 for (x = 0; x < width; x++) {
377 if (rr > 255) rr = 255; else if (rr < 0) rr = 0;
378 if (gg > 255) gg = 255; else if (gg < 0) gg = 0;
379 if (bb > 255) bb = 255; else if (bb < 0) bb = 0;
385 rer = rerr[x] - r*dd;
386 ger = gerr[x] - g*dd;
387 ber = berr[x] - b*dd;
389 pixel = (r * cpccpc) + (g * cpc) + b;
390 *pixel_data++ = colors[pixel].pixel;
405 pixel_data = (ppixel_data += bytes_per_line);
428 XImage *BImage::renderXImage(void) {
430 XCreateImage(control->getBaseDisplay()->getXDisplay(),
431 control->getVisual(), control->getDepth(), ZPixmap, 0, 0,
432 width, height, 32, 0);
435 fprintf(stderr, "BImage::renderXImage: error creating XImage\n");
440 image->data = (char *) 0;
442 unsigned char *d = new unsigned char[image->bytes_per_line * (height + 1)];
444 unsigned int o = image->bits_per_pixel +
445 ((image->byte_order == MSBFirst) ? 1 : 0);
447 bool unsupported = False;
449 if (control->doDither() && width > 1 && height > 1) {
450 switch (control->getVisual()->c_class) {
452 TrueColorDither(o, image->bytes_per_line, d);
458 OrderedPseudoColorDither(image->bytes_per_line, d);
460 PseudoColorDither(image->bytes_per_line, d);
469 unsigned int x, y, r, g, b, offset;
470 unsigned char *pixel_data = d, *ppixel_data = d;
473 switch (control->getVisual()->c_class) {
476 for (y = 0, offset = 0; y < height; ++y) {
477 for (x = 0; x < width; ++x, ++offset) {
478 r = red_table[red[offset]];
479 g = green_table[green[offset]];
480 b = blue_table[blue[offset]];
482 pixel = (r * cpccpc) + (g * cpc) + b;
483 *pixel_data++ = colors[pixel].pixel;
486 pixel_data = (ppixel_data += image->bytes_per_line);
492 for (y = 0, offset = 0; y < height; y++) {
493 for (x = 0; x < width; x++, offset++) {
494 r = red_table[red[offset]];
495 g = green_table[green[offset]];
496 b = blue_table[blue[offset]];
498 pixel = (r << red_offset) | (g << green_offset) | (b << blue_offset);
499 assignPixelData(o, &pixel_data, pixel);
502 pixel_data = (ppixel_data += image->bytes_per_line);
509 for (y = 0, offset = 0; y < height; y++) {
510 for (x = 0; x < width; x++, offset++) {
511 r = *(red_table + *(red + offset));
512 g = *(green_table + *(green + offset));
513 b = *(blue_table + *(blue + offset));
515 g = ((r * 30) + (g * 59) + (b * 11)) / 100;
516 *pixel_data++ = colors[g].pixel;
519 pixel_data = (ppixel_data += image->bytes_per_line);
530 fprintf(stderr, "BImage::renderXImage: unsupported visual\n");
532 XDestroyImage(image);
536 image->data = (char *) d;
542 Pixmap BImage::renderPixmap(void) {
544 XCreatePixmap(control->getBaseDisplay()->getXDisplay(),
545 control->getDrawable(), width, height, control->getDepth());
547 if (pixmap == None) {
548 fprintf(stderr, "BImage::renderPixmap: error creating pixmap\n");
552 XImage *image = renderXImage();
555 XFreePixmap(control->getBaseDisplay()->getXDisplay(), pixmap);
560 XDestroyImage(image);
561 XFreePixmap(control->getBaseDisplay()->getXDisplay(), pixmap);
565 XPutImage(control->getBaseDisplay()->getXDisplay(), pixmap,
566 DefaultGC(control->getBaseDisplay()->getXDisplay(),
567 control->getScreenInfo()->getScreenNumber()),
568 image, 0, 0, 0, 0, width, height);
571 delete [] image->data;
575 XDestroyImage(image);
581 void BImage::bevel1(void) {
582 if (width > 2 && height > 2) {
583 unsigned char *pr = red, *pg = green, *pb = blue;
585 register unsigned char r, g, b, rr ,gg ,bb;
586 register unsigned int w = width, h = height - 1, wh = w * h;
604 rr = (r >> 2) + (r >> 1);
607 gg = (g >> 2) + (g >> 1);
610 bb = (b >> 2) + (b >> 1);
633 rr = (r >> 2) + (r >> 1);
636 gg = (g >> 2) + (g >> 1);
639 bb = (b >> 2) + (b >> 1);
670 rr = (r >> 2) + (r >> 1);
673 gg = (g >> 2) + (g >> 1);
676 bb = (b >> 2) + (b >> 1);
703 rr = (r >> 2) + (r >> 1);
706 gg = (g >> 2) + (g >> 1);
709 bb = (b >> 2) + (b >> 1);
719 void BImage::bevel2(void) {
720 if (width > 4 && height > 4) {
721 unsigned char r, g, b, rr ,gg ,bb, *pr = red + width + 1,
722 *pg = green + width + 1, *pb = blue + width + 1;
723 unsigned int w = width - 2, h = height - 1, wh = width * (height - 3);
741 rr = (r >> 2) + (r >> 1);
744 gg = (g >> 2) + (g >> 1);
747 bb = (b >> 2) + (b >> 1);
779 rr = (r >> 2) + (r >> 1);
782 gg = (g >> 2) + (g >> 1);
785 bb = (b >> 2) + (b >> 1);
798 void BImage::border(const BTexture &texture) {
799 if (width < 2 || height < 2) return;
801 register unsigned int i;
802 int r = texture.borderColor().red(),
803 g = texture.borderColor().green(),
804 b = texture.borderColor().blue();
806 unsigned char *pr, *pg, *pb;
812 for (i = 0; i < width; ++i) {
819 // left and right lines (pr,pg,pb are already lined up)
820 for (i = 1; i < height - 1; ++i) {
833 // bottom line (pr,pg,pb are already lined up)
834 for (i = 0; i < width; ++i) {
842 void BImage::invert(void) {
843 register unsigned int i, j, wh = (width * height) - 1;
846 for (i = 0, j = wh; j > i; j--, i++) {
848 *(red + j) = *(red + i);
852 *(green + j) = *(green + i);
856 *(blue + j) = *(blue + i);
862 void BImage::dgradient(void) {
863 // diagonal gradient code was written by Mike Cole <mike@mydot.com>
864 // modified for interlacing by Brad Hughes
866 float drx, dgx, dbx, dry, dgy, dby, yr = 0.0, yg = 0.0, yb = 0.0,
867 xr = (float) from.red(),
868 xg = (float) from.green(),
869 xb = (float) from.blue();
870 unsigned char *pr = red, *pg = green, *pb = blue;
871 unsigned int w = width * 2, h = height * 2, *xt = xtable, *yt = ytable;
873 register unsigned int x, y;
875 dry = drx = (float) (to.red() - from.red());
876 dgy = dgx = (float) (to.green() - from.green());
877 dby = dbx = (float) (to.blue() - from.blue());
884 for (x = 0; x < width; x++) {
885 *(xt++) = (unsigned char) (xr);
886 *(xt++) = (unsigned char) (xg);
887 *(xt++) = (unsigned char) (xb);
899 for (y = 0; y < height; y++) {
900 *(yt++) = ((unsigned char) yr);
901 *(yt++) = ((unsigned char) yg);
902 *(yt++) = ((unsigned char) yb);
909 // Combine tables to create gradient
913 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
914 for (xt = xtable, x = 0; x < width; x++) {
915 *(pr++) = *(xt++) + *(yt);
916 *(pg++) = *(xt++) + *(yt + 1);
917 *(pb++) = *(xt++) + *(yt + 2);
921 // faked interlacing effect
922 unsigned char channel, channel2;
924 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
925 for (xt = xtable, x = 0; x < width; x++) {
927 channel = *(xt++) + *(yt);
928 channel2 = (channel >> 1) + (channel >> 2);
929 if (channel2 > channel) channel2 = 0;
932 channel = *(xt++) + *(yt + 1);
933 channel2 = (channel >> 1) + (channel >> 2);
934 if (channel2 > channel) channel2 = 0;
937 channel = *(xt++) + *(yt + 2);
938 channel2 = (channel >> 1) + (channel >> 2);
939 if (channel2 > channel) channel2 = 0;
942 channel = *(xt++) + *(yt);
943 channel2 = channel + (channel >> 3);
944 if (channel2 < channel) channel2 = ~0;
947 channel = *(xt++) + *(yt + 1);
948 channel2 = channel + (channel >> 3);
949 if (channel2 < channel) channel2 = ~0;
952 channel = *(xt++) + *(yt + 2);
953 channel2 = channel + (channel >> 3);
954 if (channel2 < channel) channel2 = ~0;
963 void BImage::hgradient(void) {
965 xr = (float) from.red(),
966 xg = (float) from.green(),
967 xb = (float) from.blue();
968 unsigned char *pr = red, *pg = green, *pb = blue;
970 register unsigned int x, y;
972 drx = (float) (to.red() - from.red());
973 dgx = (float) (to.green() - from.green());
974 dbx = (float) (to.blue() - from.blue());
980 if (interlaced && height > 2) {
981 // faked interlacing effect
982 unsigned char channel, channel2;
984 for (x = 0; x < width; x++, pr++, pg++, pb++) {
985 channel = (unsigned char) xr;
986 channel2 = (channel >> 1) + (channel >> 2);
987 if (channel2 > channel) channel2 = 0;
990 channel = (unsigned char) xg;
991 channel2 = (channel >> 1) + (channel >> 2);
992 if (channel2 > channel) channel2 = 0;
995 channel = (unsigned char) xb;
996 channel2 = (channel >> 1) + (channel >> 2);
997 if (channel2 > channel) channel2 = 0;
1001 channel = (unsigned char) xr;
1002 channel2 = channel + (channel >> 3);
1003 if (channel2 < channel) channel2 = ~0;
1004 *(pr + width) = channel2;
1006 channel = (unsigned char) xg;
1007 channel2 = channel + (channel >> 3);
1008 if (channel2 < channel) channel2 = ~0;
1009 *(pg + width) = channel2;
1011 channel = (unsigned char) xb;
1012 channel2 = channel + (channel >> 3);
1013 if (channel2 < channel) channel2 = ~0;
1014 *(pb + width) = channel2;
1027 for (y = 2; y < height; y++, pr += width, pg += width, pb += width) {
1028 if (y & 1) offset = width; else offset = 0;
1030 memcpy(pr, (red + offset), width);
1031 memcpy(pg, (green + offset), width);
1032 memcpy(pb, (blue + offset), width);
1036 for (x = 0; x < width; x++) {
1037 *(pr++) = (unsigned char) (xr);
1038 *(pg++) = (unsigned char) (xg);
1039 *(pb++) = (unsigned char) (xb);
1046 for (y = 1; y < height; y++, pr += width, pg += width, pb += width) {
1047 memcpy(pr, red, width);
1048 memcpy(pg, green, width);
1049 memcpy(pb, blue, width);
1055 void BImage::vgradient(void) {
1056 float dry, dgy, dby,
1057 yr = (float) from.red(),
1058 yg = (float) from.green(),
1059 yb = (float) from.blue();
1060 unsigned char *pr = red, *pg = green, *pb = blue;
1062 register unsigned int y;
1064 dry = (float) (to.red() - from.red());
1065 dgy = (float) (to.green() - from.green());
1066 dby = (float) (to.blue() - from.blue());
1073 // faked interlacing effect
1074 unsigned char channel, channel2;
1076 for (y = 0; y < height; y++, pr += width, pg += width, pb += width) {
1078 channel = (unsigned char) yr;
1079 channel2 = (channel >> 1) + (channel >> 2);
1080 if (channel2 > channel) channel2 = 0;
1081 memset(pr, channel2, width);
1083 channel = (unsigned char) yg;
1084 channel2 = (channel >> 1) + (channel >> 2);
1085 if (channel2 > channel) channel2 = 0;
1086 memset(pg, channel2, width);
1088 channel = (unsigned char) yb;
1089 channel2 = (channel >> 1) + (channel >> 2);
1090 if (channel2 > channel) channel2 = 0;
1091 memset(pb, channel2, width);
1093 channel = (unsigned char) yr;
1094 channel2 = channel + (channel >> 3);
1095 if (channel2 < channel) channel2 = ~0;
1096 memset(pr, channel2, width);
1098 channel = (unsigned char) yg;
1099 channel2 = channel + (channel >> 3);
1100 if (channel2 < channel) channel2 = ~0;
1101 memset(pg, channel2, width);
1103 channel = (unsigned char) yb;
1104 channel2 = channel + (channel >> 3);
1105 if (channel2 < channel) channel2 = ~0;
1106 memset(pb, channel2, width);
1115 for (y = 0; y < height; y++, pr += width, pg += width, pb += width) {
1116 memset(pr, (unsigned char) yr, width);
1117 memset(pg, (unsigned char) yg, width);
1118 memset(pb, (unsigned char) yb, width);
1128 void BImage::pgradient(void) {
1129 // pyramid gradient - based on original dgradient, written by
1130 // Mosfet (mosfet@kde.org)
1131 // adapted from kde sources for Blackbox by Brad Hughes
1133 float yr, yg, yb, drx, dgx, dbx, dry, dgy, dby,
1135 int rsign, gsign, bsign;
1136 unsigned char *pr = red, *pg = green, *pb = blue;
1137 unsigned int tr = to.red(), tg = to.green(), tb = to.blue(),
1138 *xt = xtable, *yt = ytable;
1140 register unsigned int x, y;
1142 dry = drx = (float) (to.red() - from.red());
1143 dgy = dgx = (float) (to.green() - from.green());
1144 dby = dbx = (float) (to.blue() - from.blue());
1146 rsign = (drx < 0) ? -1 : 1;
1147 gsign = (dgx < 0) ? -1 : 1;
1148 bsign = (dbx < 0) ? -1 : 1;
1150 xr = yr = (drx / 2);
1151 xg = yg = (dgx / 2);
1152 xb = yb = (dbx / 2);
1159 for (x = 0; x < width; x++) {
1160 *(xt++) = (unsigned char) ((xr < 0) ? -xr : xr);
1161 *(xt++) = (unsigned char) ((xg < 0) ? -xg : xg);
1162 *(xt++) = (unsigned char) ((xb < 0) ? -xb : xb);
1174 for (y = 0; y < height; y++) {
1175 *(yt++) = ((unsigned char) ((yr < 0) ? -yr : yr));
1176 *(yt++) = ((unsigned char) ((yg < 0) ? -yg : yg));
1177 *(yt++) = ((unsigned char) ((yb < 0) ? -yb : yb));
1184 // Combine tables to create gradient
1188 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1189 for (xt = xtable, x = 0; x < width; x++) {
1190 *(pr++) = (unsigned char) (tr - (rsign * (*(xt++) + *(yt))));
1191 *(pg++) = (unsigned char) (tg - (gsign * (*(xt++) + *(yt + 1))));
1192 *(pb++) = (unsigned char) (tb - (bsign * (*(xt++) + *(yt + 2))));
1196 // faked interlacing effect
1197 unsigned char channel, channel2;
1199 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1200 for (xt = xtable, x = 0; x < width; x++) {
1202 channel = (unsigned char) (tr - (rsign * (*(xt++) + *(yt))));
1203 channel2 = (channel >> 1) + (channel >> 2);
1204 if (channel2 > channel) channel2 = 0;
1207 channel = (unsigned char) (tg - (gsign * (*(xt++) + *(yt + 1))));
1208 channel2 = (channel >> 1) + (channel >> 2);
1209 if (channel2 > channel) channel2 = 0;
1212 channel = (unsigned char) (tb - (bsign * (*(xt++) + *(yt + 2))));
1213 channel2 = (channel >> 1) + (channel >> 2);
1214 if (channel2 > channel) channel2 = 0;
1217 channel = (unsigned char) (tr - (rsign * (*(xt++) + *(yt))));
1218 channel2 = channel + (channel >> 3);
1219 if (channel2 < channel) channel2 = ~0;
1222 channel = (unsigned char) (tg - (gsign * (*(xt++) + *(yt + 1))));
1223 channel2 = channel + (channel >> 3);
1224 if (channel2 < channel) channel2 = ~0;
1227 channel = (unsigned char) (tb - (bsign * (*(xt++) + *(yt + 2))));
1228 channel2 = channel + (channel >> 3);
1229 if (channel2 < channel) channel2 = ~0;
1238 void BImage::rgradient(void) {
1239 // rectangle gradient - based on original dgradient, written by
1240 // Mosfet (mosfet@kde.org)
1241 // adapted from kde sources for Blackbox by Brad Hughes
1243 float drx, dgx, dbx, dry, dgy, dby, xr, xg, xb, yr, yg, yb;
1244 int rsign, gsign, bsign;
1245 unsigned char *pr = red, *pg = green, *pb = blue;
1246 unsigned int tr = to.red(), tg = to.green(), tb = to.blue(),
1247 *xt = xtable, *yt = ytable;
1249 register unsigned int x, y;
1251 dry = drx = (float) (to.red() - from.red());
1252 dgy = dgx = (float) (to.green() - from.green());
1253 dby = dbx = (float) (to.blue() - from.blue());
1255 rsign = (drx < 0) ? -2 : 2;
1256 gsign = (dgx < 0) ? -2 : 2;
1257 bsign = (dbx < 0) ? -2 : 2;
1259 xr = yr = (drx / 2);
1260 xg = yg = (dgx / 2);
1261 xb = yb = (dbx / 2);
1268 for (x = 0; x < width; x++) {
1269 *(xt++) = (unsigned char) ((xr < 0) ? -xr : xr);
1270 *(xt++) = (unsigned char) ((xg < 0) ? -xg : xg);
1271 *(xt++) = (unsigned char) ((xb < 0) ? -xb : xb);
1283 for (y = 0; y < height; y++) {
1284 *(yt++) = ((unsigned char) ((yr < 0) ? -yr : yr));
1285 *(yt++) = ((unsigned char) ((yg < 0) ? -yg : yg));
1286 *(yt++) = ((unsigned char) ((yb < 0) ? -yb : yb));
1293 // Combine tables to create gradient
1297 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1298 for (xt = xtable, x = 0; x < width; x++) {
1299 *(pr++) = (unsigned char) (tr - (rsign * max(*(xt++), *(yt))));
1300 *(pg++) = (unsigned char) (tg - (gsign * max(*(xt++), *(yt + 1))));
1301 *(pb++) = (unsigned char) (tb - (bsign * max(*(xt++), *(yt + 2))));
1305 // faked interlacing effect
1306 unsigned char channel, channel2;
1308 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1309 for (xt = xtable, x = 0; x < width; x++) {
1311 channel = (unsigned char) (tr - (rsign * max(*(xt++), *(yt))));
1312 channel2 = (channel >> 1) + (channel >> 2);
1313 if (channel2 > channel) channel2 = 0;
1316 channel = (unsigned char) (tg - (gsign * max(*(xt++), *(yt + 1))));
1317 channel2 = (channel >> 1) + (channel >> 2);
1318 if (channel2 > channel) channel2 = 0;
1321 channel = (unsigned char) (tb - (bsign * max(*(xt++), *(yt + 2))));
1322 channel2 = (channel >> 1) + (channel >> 2);
1323 if (channel2 > channel) channel2 = 0;
1326 channel = (unsigned char) (tr - (rsign * max(*(xt++), *(yt))));
1327 channel2 = channel + (channel >> 3);
1328 if (channel2 < channel) channel2 = ~0;
1331 channel = (unsigned char) (tg - (gsign * max(*(xt++), *(yt + 1))));
1332 channel2 = channel + (channel >> 3);
1333 if (channel2 < channel) channel2 = ~0;
1336 channel = (unsigned char) (tb - (bsign * max(*(xt++), *(yt + 2))));
1337 channel2 = channel + (channel >> 3);
1338 if (channel2 < channel) channel2 = ~0;
1347 void BImage::egradient(void) {
1348 // elliptic gradient - based on original dgradient, written by
1349 // Mosfet (mosfet@kde.org)
1350 // adapted from kde sources for Blackbox by Brad Hughes
1352 float drx, dgx, dbx, dry, dgy, dby, yr, yg, yb, xr, xg, xb;
1353 int rsign, gsign, bsign;
1354 unsigned char *pr = red, *pg = green, *pb = blue;
1355 unsigned int *xt = xtable, *yt = ytable,
1356 tr = (unsigned long) to.red(),
1357 tg = (unsigned long) to.green(),
1358 tb = (unsigned long) to.blue();
1360 register unsigned int x, y;
1362 dry = drx = (float) (to.red() - from.red());
1363 dgy = dgx = (float) (to.green() - from.green());
1364 dby = dbx = (float) (to.blue() - from.blue());
1366 rsign = (drx < 0) ? -1 : 1;
1367 gsign = (dgx < 0) ? -1 : 1;
1368 bsign = (dbx < 0) ? -1 : 1;
1370 xr = yr = (drx / 2);
1371 xg = yg = (dgx / 2);
1372 xb = yb = (dbx / 2);
1379 for (x = 0; x < width; x++) {
1380 *(xt++) = (unsigned long) (xr * xr);
1381 *(xt++) = (unsigned long) (xg * xg);
1382 *(xt++) = (unsigned long) (xb * xb);
1394 for (y = 0; y < height; y++) {
1395 *(yt++) = (unsigned long) (yr * yr);
1396 *(yt++) = (unsigned long) (yg * yg);
1397 *(yt++) = (unsigned long) (yb * yb);
1404 // Combine tables to create gradient
1408 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1409 for (xt = xtable, x = 0; x < width; x++) {
1410 *(pr++) = (unsigned char)
1411 (tr - (rsign * control->getSqrt(*(xt++) + *(yt))));
1412 *(pg++) = (unsigned char)
1413 (tg - (gsign * control->getSqrt(*(xt++) + *(yt + 1))));
1414 *(pb++) = (unsigned char)
1415 (tb - (bsign * control->getSqrt(*(xt++) + *(yt + 2))));
1419 // faked interlacing effect
1420 unsigned char channel, channel2;
1422 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1423 for (xt = xtable, x = 0; x < width; x++) {
1425 channel = (unsigned char)
1426 (tr - (rsign * control->getSqrt(*(xt++) + *(yt))));
1427 channel2 = (channel >> 1) + (channel >> 2);
1428 if (channel2 > channel) channel2 = 0;
1431 channel = (unsigned char)
1432 (tg - (gsign * control->getSqrt(*(xt++) + *(yt + 1))));
1433 channel2 = (channel >> 1) + (channel >> 2);
1434 if (channel2 > channel) channel2 = 0;
1437 channel = (unsigned char)
1438 (tb - (bsign * control->getSqrt(*(xt++) + *(yt + 2))));
1439 channel2 = (channel >> 1) + (channel >> 2);
1440 if (channel2 > channel) channel2 = 0;
1443 channel = (unsigned char)
1444 (tr - (rsign * control->getSqrt(*(xt++) + *(yt))));
1445 channel2 = channel + (channel >> 3);
1446 if (channel2 < channel) channel2 = ~0;
1449 channel = (unsigned char)
1450 (tg - (gsign * control->getSqrt(*(xt++) + *(yt + 1))));
1451 channel2 = channel + (channel >> 3);
1452 if (channel2 < channel) channel2 = ~0;
1455 channel = (unsigned char)
1456 (tb - (bsign * control->getSqrt(*(xt++) + *(yt + 2))));
1457 channel2 = channel + (channel >> 3);
1458 if (channel2 < channel) channel2 = ~0;
1467 void BImage::pcgradient(void) {
1468 // pipe cross gradient - based on original dgradient, written by
1469 // Mosfet (mosfet@kde.org)
1470 // adapted from kde sources for Blackbox by Brad Hughes
1472 float drx, dgx, dbx, dry, dgy, dby, xr, xg, xb, yr, yg, yb;
1473 int rsign, gsign, bsign;
1474 unsigned char *pr = red, *pg = green, *pb = blue;
1475 unsigned int *xt = xtable, *yt = ytable,
1480 register unsigned int x, y;
1482 dry = drx = (float) (to.red() - from.red());
1483 dgy = dgx = (float) (to.green() - from.green());
1484 dby = dbx = (float) (to.blue() - from.blue());
1486 rsign = (drx < 0) ? -2 : 2;
1487 gsign = (dgx < 0) ? -2 : 2;
1488 bsign = (dbx < 0) ? -2 : 2;
1490 xr = yr = (drx / 2);
1491 xg = yg = (dgx / 2);
1492 xb = yb = (dbx / 2);
1499 for (x = 0; x < width; x++) {
1500 *(xt++) = (unsigned char) ((xr < 0) ? -xr : xr);
1501 *(xt++) = (unsigned char) ((xg < 0) ? -xg : xg);
1502 *(xt++) = (unsigned char) ((xb < 0) ? -xb : xb);
1514 for (y = 0; y < height; y++) {
1515 *(yt++) = ((unsigned char) ((yr < 0) ? -yr : yr));
1516 *(yt++) = ((unsigned char) ((yg < 0) ? -yg : yg));
1517 *(yt++) = ((unsigned char) ((yb < 0) ? -yb : yb));
1524 // Combine tables to create gradient
1527 // normal pcgradient
1528 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1529 for (xt = xtable, x = 0; x < width; x++) {
1530 *(pr++) = (unsigned char) (tr - (rsign * min(*(xt++), *(yt))));
1531 *(pg++) = (unsigned char) (tg - (gsign * min(*(xt++), *(yt + 1))));
1532 *(pb++) = (unsigned char) (tb - (bsign * min(*(xt++), *(yt + 2))));
1536 // faked interlacing effect
1537 unsigned char channel, channel2;
1539 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1540 for (xt = xtable, x = 0; x < width; x++) {
1542 channel = (unsigned char) (tr - (rsign * min(*(xt++), *(yt))));
1543 channel2 = (channel >> 1) + (channel >> 2);
1544 if (channel2 > channel) channel2 = 0;
1547 channel = (unsigned char) (tg - (bsign * min(*(xt++), *(yt + 1))));
1548 channel2 = (channel >> 1) + (channel >> 2);
1549 if (channel2 > channel) channel2 = 0;
1552 channel = (unsigned char) (tb - (gsign * min(*(xt++), *(yt + 2))));
1553 channel2 = (channel >> 1) + (channel >> 2);
1554 if (channel2 > channel) channel2 = 0;
1557 channel = (unsigned char) (tr - (rsign * min(*(xt++), *(yt))));
1558 channel2 = channel + (channel >> 3);
1559 if (channel2 < channel) channel2 = ~0;
1562 channel = (unsigned char) (tg - (gsign * min(*(xt++), *(yt + 1))));
1563 channel2 = channel + (channel >> 3);
1564 if (channel2 < channel) channel2 = ~0;
1567 channel = (unsigned char) (tb - (bsign * min(*(xt++), *(yt + 2))));
1568 channel2 = channel + (channel >> 3);
1569 if (channel2 < channel) channel2 = ~0;
1578 void BImage::cdgradient(void) {
1579 // cross diagonal gradient - based on original dgradient, written by
1580 // Mosfet (mosfet@kde.org)
1581 // adapted from kde sources for Blackbox by Brad Hughes
1583 float drx, dgx, dbx, dry, dgy, dby, yr = 0.0, yg = 0.0, yb = 0.0,
1584 xr = (float) from.red(),
1585 xg = (float) from.green(),
1586 xb = (float) from.blue();
1587 unsigned char *pr = red, *pg = green, *pb = blue;
1588 unsigned int w = width * 2, h = height * 2, *xt, *yt;
1590 register unsigned int x, y;
1592 dry = drx = (float) (to.red() - from.red());
1593 dgy = dgx = (float) (to.green() - from.green());
1594 dby = dbx = (float) (to.blue() - from.blue());
1601 for (xt = (xtable + (width * 3) - 1), x = 0; x < width; x++) {
1602 *(xt--) = (unsigned char) xb;
1603 *(xt--) = (unsigned char) xg;
1604 *(xt--) = (unsigned char) xr;
1616 for (yt = ytable, y = 0; y < height; y++) {
1617 *(yt++) = (unsigned char) yr;
1618 *(yt++) = (unsigned char) yg;
1619 *(yt++) = (unsigned char) yb;
1626 // Combine tables to create gradient
1629 // normal cdgradient
1630 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1631 for (xt = xtable, x = 0; x < width; x++) {
1632 *(pr++) = *(xt++) + *(yt);
1633 *(pg++) = *(xt++) + *(yt + 1);
1634 *(pb++) = *(xt++) + *(yt + 2);
1638 // faked interlacing effect
1639 unsigned char channel, channel2;
1641 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1642 for (xt = xtable, x = 0; x < width; x++) {
1644 channel = *(xt++) + *(yt);
1645 channel2 = (channel >> 1) + (channel >> 2);
1646 if (channel2 > channel) channel2 = 0;
1649 channel = *(xt++) + *(yt + 1);
1650 channel2 = (channel >> 1) + (channel >> 2);
1651 if (channel2 > channel) channel2 = 0;
1654 channel = *(xt++) + *(yt + 2);
1655 channel2 = (channel >> 1) + (channel >> 2);
1656 if (channel2 > channel) channel2 = 0;
1659 channel = *(xt++) + *(yt);
1660 channel2 = channel + (channel >> 3);
1661 if (channel2 < channel) channel2 = ~0;
1664 channel = *(xt++) + *(yt + 1);
1665 channel2 = channel + (channel >> 3);
1666 if (channel2 < channel) channel2 = ~0;
1669 channel = *(xt++) + *(yt + 2);
1670 channel2 = channel + (channel >> 3);
1671 if (channel2 < channel) channel2 = ~0;