1 // -*- mode: C++; indent-tabs-mode: nil; -*-
2 // Image.cc for Blackbox - an X11 Window manager
3 // Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
4 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
6 // Permission is hereby granted, free of charge, to any person obtaining a
7 // copy of this software and associated documentation files (the "Software"),
8 // to deal in the Software without restriction, including without limitation
9 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 // and/or sell copies of the Software, and to permit persons to whom the
11 // Software is furnished to do so, subject to the following conditions:
13 // The above copyright notice and this permission notice shall be included in
14 // all copies or substantial portions of the Software.
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 // DEALINGS IN THE SOFTWARE.
25 # include "../config.h"
26 #endif // HAVE_CONFIG_H
30 #endif // HAVE_STDIO_H
36 #include "blackbox.hh"
38 #include "BaseDisplay.hh"
44 BImage::BImage(BImageControl *c, int w, int h) {
47 width = (w > 0) ? w : 1;
48 height = (h > 0) ? h : 1;
50 red = new unsigned char[width * height];
51 green = new unsigned char[width * height];
52 blue = new unsigned char[width * height];
54 xtable = ytable = (unsigned int *) 0;
56 cpc = control->getColorsPerChannel();
59 control->getColorTables(&red_table, &green_table, &blue_table,
60 &red_offset, &green_offset, &blue_offset,
61 &red_bits, &green_bits, &blue_bits);
63 if (control->getVisual()->c_class != TrueColor)
64 control->getXColorTable(&colors, &ncolors);
68 BImage::~BImage(void) {
75 Pixmap BImage::render(const BTexture &texture) {
76 if (texture.texture() & BTexture::Parent_Relative)
77 return ParentRelative;
78 else if (texture.texture() & BTexture::Solid)
79 return render_solid(texture);
80 else if (texture.texture() & BTexture::Gradient)
81 return render_gradient(texture);
86 Pixmap BImage::render_solid(const BTexture &texture) {
87 Pixmap pixmap = XCreatePixmap(control->getBaseDisplay()->getXDisplay(),
88 control->getDrawable(), width,
89 height, control->getDepth());
91 fprintf(stderr, i18n(ImageSet, ImageErrorCreatingSolidPixmap,
92 "BImage::render_solid: error creating pixmap\n"));
96 Display *display = control->getBaseDisplay()->getXDisplay();
98 BPen pen(texture.color());
99 BPen penlight(texture.lightColor());
100 BPen penshadow(texture.shadowColor());
102 XFillRectangle(display, pixmap, pen.gc(), 0, 0, width, height);
104 if (texture.texture() & BTexture::Interlaced) {
105 BPen peninterlace(texture.colorTo());
106 for (unsigned int i = 0; i < height; i += 2)
107 XDrawLine(display, pixmap, peninterlace.gc(), 0, i, width, i);
110 int left = 0, top = 0, right = width - 1, bottom = height - 1;
112 if (texture.texture() & BTexture::Border) {
113 BPen penborder(texture.borderColor());
114 XDrawRectangle(display, pixmap, penborder.gc(),
115 left, top, right, bottom);
118 if (texture.texture() & BTexture::Bevel1) {
119 if (texture.texture() & BTexture::Raised) {
120 XDrawLine(display, pixmap, penshadow.gc(),
121 left, bottom, right, bottom);
122 XDrawLine(display, pixmap, penshadow.gc(),
123 right, bottom, right, top);
125 XDrawLine(display, pixmap, penlight.gc(),
126 left, top, right, top);
127 XDrawLine(display, pixmap, penlight.gc(),
128 left, bottom, left, top);
129 } else if (texture.texture() & BTexture::Sunken) {
130 XDrawLine(display, pixmap, penlight.gc(),
131 left, bottom, right, bottom);
132 XDrawLine(display, pixmap, penlight.gc(),
133 right, bottom, right, top);
135 XDrawLine(display, pixmap, penshadow.gc(),
136 left, top, right, top);
137 XDrawLine(display, pixmap, penshadow.gc(),
138 left, bottom, left, top);
140 } else if (texture.texture() & BTexture::Bevel2) {
141 if (texture.texture() & BTexture::Raised) {
142 XDrawLine(display, pixmap, penshadow.gc(),
143 left + 1, bottom - 2, right - 2, bottom - 2);
144 XDrawLine(display, pixmap, penshadow.gc(),
145 right - 2, bottom - 2, right - 2, top + 1);
147 XDrawLine(display, pixmap, penlight.gc(),
148 left + 1, top + 1, right - 2, top + 1);
149 XDrawLine(display, pixmap, penlight.gc(),
150 left + 1, bottom - 2, left + 1, top + 1);
151 } else if (texture.texture() & BTexture::Sunken) {
152 XDrawLine(display, pixmap, penlight.gc(),
153 left + 1, bottom - 2, right - 2, bottom - 2);
154 XDrawLine(display, pixmap, penlight.gc(),
155 right - 2, bottom - 2, right - 2, top + 1);
157 XDrawLine(display, pixmap, penshadow.gc(),
158 left + 1, top + 1, right - 2, top + 1);
159 XDrawLine(display, pixmap, penshadow.gc(),
160 left + 1, bottom - 2, left + 1, top + 1);
168 Pixmap BImage::render_gradient(const BTexture &texture) {
169 bool inverted = False;
171 interlaced = texture.texture() & BTexture::Interlaced;
173 if (texture.texture() & BTexture::Sunken) {
174 from = texture.colorTo();
175 to = texture.color();
177 if (! (texture.texture() & BTexture::Invert)) inverted = True;
179 from = texture.color();
180 to = texture.colorTo();
182 if (texture.texture() & BTexture::Invert) inverted = True;
185 control->getGradientBuffers(width, height, &xtable, &ytable);
187 if (texture.texture() & BTexture::Diagonal) dgradient();
188 else if (texture.texture() & BTexture::Elliptic) egradient();
189 else if (texture.texture() & BTexture::Horizontal) hgradient();
190 else if (texture.texture() & BTexture::Pyramid) pgradient();
191 else if (texture.texture() & BTexture::Rectangle) rgradient();
192 else if (texture.texture() & BTexture::Vertical) vgradient();
193 else if (texture.texture() & BTexture::CrossDiagonal) cdgradient();
194 else if (texture.texture() & BTexture::PipeCross) pcgradient();
196 if (texture.texture() & BTexture::Bevel1) bevel1();
197 else if (texture.texture() & BTexture::Bevel2) bevel2();
199 if (texture.texture() & BTexture::Border) border(texture);
201 if (inverted) invert();
203 return renderPixmap();
208 static const unsigned char dither4[4][4] = {
217 * Helper function for TrueColorDither and renderXImage
219 * This handles the proper setting of the image data based on the image depth
220 * and the machine's byte ordering
223 void assignPixelData(unsigned int bit_depth, unsigned char **data,
224 unsigned long pixel) {
225 unsigned char *pixel_data = *data;
228 *pixel_data++ = pixel;
231 case 16: // 16bpp LSB
232 *pixel_data++ = pixel;
233 *pixel_data++ = pixel >> 8;
236 case 17: // 16bpp MSB
237 *pixel_data++ = pixel >> 8;
238 *pixel_data++ = pixel;
241 case 24: // 24bpp LSB
242 *pixel_data++ = pixel;
243 *pixel_data++ = pixel >> 8;
244 *pixel_data++ = pixel >> 16;
247 case 25: // 24bpp MSB
248 *pixel_data++ = pixel >> 16;
249 *pixel_data++ = pixel >> 8;
250 *pixel_data++ = pixel;
253 case 32: // 32bpp LSB
254 *pixel_data++ = pixel;
255 *pixel_data++ = pixel >> 8;
256 *pixel_data++ = pixel >> 16;
257 *pixel_data++ = pixel >> 24;
260 case 33: // 32bpp MSB
261 *pixel_data++ = pixel >> 24;
262 *pixel_data++ = pixel >> 16;
263 *pixel_data++ = pixel >> 8;
264 *pixel_data++ = pixel;
267 *data = pixel_data; // assign back so we don't lose our place
271 // algorithm: ordered dithering... many many thanks to rasterman
272 // (raster@rasterman.com) for telling me about this... portions of this
273 // code is based off of his code in Imlib
274 void BImage::TrueColorDither(unsigned int bit_depth, int bytes_per_line,
275 unsigned char *pixel_data) {
276 unsigned int x, y, dithx, dithy, r, g, b, er, eg, eb, offset;
277 unsigned char *ppixel_data = pixel_data;
280 for (y = 0, offset = 0; y < height; y++) {
283 for (x = 0; x < width; x++, offset++) {
289 er = r & (red_bits - 1);
290 eg = g & (green_bits - 1);
291 eb = b & (blue_bits - 1);
297 if ((dither4[dithy][dithx] < er) && (r < red_table[255])) r++;
298 if ((dither4[dithy][dithx] < eg) && (g < green_table[255])) g++;
299 if ((dither4[dithy][dithx] < eb) && (b < blue_table[255])) b++;
301 pixel = (r << red_offset) | (g << green_offset) | (b << blue_offset);
302 assignPixelData(bit_depth, &pixel_data, pixel);
305 pixel_data = (ppixel_data += bytes_per_line);
310 const static unsigned char dither8[8][8] = {
311 { 0, 32, 8, 40, 2, 34, 10, 42},
312 { 48, 16, 56, 24, 50, 18, 58, 26},
313 { 12, 44, 4, 36, 14, 46, 6, 38},
314 { 60, 28, 52, 20, 62, 30, 54, 22},
315 { 3, 35, 11, 43, 1, 33, 9, 41},
316 { 51, 19, 59, 27, 49, 17, 57, 25},
317 { 15, 47, 7, 39, 13, 45, 5, 37},
318 { 63, 31, 55, 23, 61, 29, 53, 21}
321 void BImage::OrderedPseudoColorDither(int bytes_per_line,
322 unsigned char *pixel_data) {
323 unsigned int x, y, dithx, dithy, r, g, b, er, eg, eb, offset;
325 unsigned char *ppixel_data = pixel_data;
327 for (y = 0, offset = 0; y < height; y++) {
330 for (x = 0; x < width; x++, offset++) {
337 er = r & (red_bits - 1);
338 eg = g & (green_bits - 1);
339 eb = b & (blue_bits - 1);
345 if ((dither8[dithy][dithx] < er) && (r < red_table[255])) r++;
346 if ((dither8[dithy][dithx] < eg) && (g < green_table[255])) g++;
347 if ((dither8[dithy][dithx] < eb) && (b < blue_table[255])) b++;
349 pixel = (r * cpccpc) + (g * cpc) + b;
350 *(pixel_data++) = colors[pixel].pixel;
353 pixel_data = (ppixel_data += bytes_per_line);
358 void BImage::PseudoColorDither(int bytes_per_line, unsigned char *pixel_data) {
360 *rerr = new short[width + 2],
361 *gerr = new short[width + 2],
362 *berr = new short[width + 2],
363 *nrerr = new short[width + 2],
364 *ngerr = new short[width + 2],
365 *nberr = new short[width + 2];
367 int rr, gg, bb, rer, ger, ber;
368 int dd = 255 / control->getColorsPerChannel();
369 unsigned int x, y, r, g, b, offset;
371 unsigned char *ppixel_data = pixel_data;
373 for (x = 0; x < width; x++) {
374 *(rerr + x) = *(red + x);
375 *(gerr + x) = *(green + x);
376 *(berr + x) = *(blue + x);
379 *(rerr + x) = *(gerr + x) = *(berr + x) = 0;
381 for (y = 0, offset = 0; y < height; y++) {
382 if (y < (height - 1)) {
383 int i = offset + width;
384 for (x = 0; x < width; x++, i++) {
385 *(nrerr + x) = *(red + i);
386 *(ngerr + x) = *(green + i);
387 *(nberr + x) = *(blue + i);
390 *(nrerr + x) = *(red + (--i));
391 *(ngerr + x) = *(green + i);
392 *(nberr + x) = *(blue + i);
395 for (x = 0; x < width; x++) {
400 if (rr > 255) rr = 255; else if (rr < 0) rr = 0;
401 if (gg > 255) gg = 255; else if (gg < 0) gg = 0;
402 if (bb > 255) bb = 255; else if (bb < 0) bb = 0;
408 rer = rerr[x] - r*dd;
409 ger = gerr[x] - g*dd;
410 ber = berr[x] - b*dd;
412 pixel = (r * cpccpc) + (g * cpc) + b;
413 *pixel_data++ = colors[pixel].pixel;
428 pixel_data = (ppixel_data += bytes_per_line);
451 XImage *BImage::renderXImage(void) {
453 XCreateImage(control->getBaseDisplay()->getXDisplay(),
454 control->getVisual(), control->getDepth(), ZPixmap, 0, 0,
455 width, height, 32, 0);
458 fprintf(stderr, i18n(ImageSet, ImageErrorCreatingXImage,
459 "BImage::renderXImage: error creating XImage\n"));
464 image->data = (char *) 0;
466 unsigned char *d = new unsigned char[image->bytes_per_line * (height + 1)];
468 unsigned int o = image->bits_per_pixel +
469 ((image->byte_order == MSBFirst) ? 1 : 0);
471 bool unsupported = False;
473 if (control->doDither() && width > 1 && height > 1) {
474 switch (control->getVisual()->c_class) {
476 TrueColorDither(o, image->bytes_per_line, d);
482 OrderedPseudoColorDither(image->bytes_per_line, d);
484 PseudoColorDither(image->bytes_per_line, d);
493 unsigned int x, y, r, g, b, offset;
494 unsigned char *pixel_data = d, *ppixel_data = d;
497 switch (control->getVisual()->c_class) {
500 for (y = 0, offset = 0; y < height; ++y) {
501 for (x = 0; x < width; ++x, ++offset) {
502 r = red_table[red[offset]];
503 g = green_table[green[offset]];
504 b = blue_table[blue[offset]];
506 pixel = (r * cpccpc) + (g * cpc) + b;
507 *pixel_data++ = colors[pixel].pixel;
510 pixel_data = (ppixel_data += image->bytes_per_line);
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 << red_offset) | (g << green_offset) | (b << blue_offset);
523 assignPixelData(o, &pixel_data, pixel);
526 pixel_data = (ppixel_data += image->bytes_per_line);
533 for (y = 0, offset = 0; y < height; y++) {
534 for (x = 0; x < width; x++, offset++) {
535 r = *(red_table + *(red + offset));
536 g = *(green_table + *(green + offset));
537 b = *(blue_table + *(blue + offset));
539 g = ((r * 30) + (g * 59) + (b * 11)) / 100;
540 *pixel_data++ = colors[g].pixel;
543 pixel_data = (ppixel_data += image->bytes_per_line);
554 fprintf(stderr, i18n(ImageSet, ImageUnsupVisual,
555 "BImage::renderXImage: unsupported visual\n"));
557 XDestroyImage(image);
561 image->data = (char *) d;
567 Pixmap BImage::renderPixmap(void) {
569 XCreatePixmap(control->getBaseDisplay()->getXDisplay(),
570 control->getDrawable(), width, height, control->getDepth());
572 if (pixmap == None) {
573 fprintf(stderr, i18n(ImageSet, ImageErrorCreatingPixmap,
574 "BImage::renderPixmap: error creating pixmap\n"));
578 XImage *image = renderXImage();
581 XFreePixmap(control->getBaseDisplay()->getXDisplay(), pixmap);
586 XDestroyImage(image);
587 XFreePixmap(control->getBaseDisplay()->getXDisplay(), pixmap);
591 XPutImage(control->getBaseDisplay()->getXDisplay(), pixmap,
592 DefaultGC(control->getBaseDisplay()->getXDisplay(),
593 control->getScreenInfo()->getScreenNumber()),
594 image, 0, 0, 0, 0, width, height);
597 delete [] image->data;
601 XDestroyImage(image);
607 void BImage::bevel1(void) {
608 if (width > 2 && height > 2) {
609 unsigned char *pr = red, *pg = green, *pb = blue;
611 register unsigned char r, g, b, rr ,gg ,bb;
612 register unsigned int w = width, h = height - 1, wh = w * h;
630 rr = (r >> 2) + (r >> 1);
633 gg = (g >> 2) + (g >> 1);
636 bb = (b >> 2) + (b >> 1);
659 rr = (r >> 2) + (r >> 1);
662 gg = (g >> 2) + (g >> 1);
665 bb = (b >> 2) + (b >> 1);
696 rr = (r >> 2) + (r >> 1);
699 gg = (g >> 2) + (g >> 1);
702 bb = (b >> 2) + (b >> 1);
729 rr = (r >> 2) + (r >> 1);
732 gg = (g >> 2) + (g >> 1);
735 bb = (b >> 2) + (b >> 1);
745 void BImage::bevel2(void) {
746 if (width > 4 && height > 4) {
747 unsigned char r, g, b, rr ,gg ,bb, *pr = red + width + 1,
748 *pg = green + width + 1, *pb = blue + width + 1;
749 unsigned int w = width - 2, h = height - 1, wh = width * (height - 3);
767 rr = (r >> 2) + (r >> 1);
770 gg = (g >> 2) + (g >> 1);
773 bb = (b >> 2) + (b >> 1);
805 rr = (r >> 2) + (r >> 1);
808 gg = (g >> 2) + (g >> 1);
811 bb = (b >> 2) + (b >> 1);
824 void BImage::border(const BTexture &texture) {
825 register unsigned int i;
826 int r = texture.borderColor().red(),
827 g = texture.borderColor().green(),
828 b = texture.borderColor().blue();
830 unsigned char *pr, *pg, *pb;
836 for (i = 0; i < width; ++i) {
842 // left and right lines (pr,pg,pb are already lined up)
843 for (i = 1; i < height - 1; ++i) {
855 // bottom line (pr,pg,pb are already lined up)
856 for (i = 0; i < width; ++i) {
864 void BImage::invert(void) {
865 register unsigned int i, j, wh = (width * height) - 1;
868 for (i = 0, j = wh; j > i; j--, i++) {
870 *(red + j) = *(red + i);
874 *(green + j) = *(green + i);
878 *(blue + j) = *(blue + i);
884 void BImage::dgradient(void) {
885 // diagonal gradient code was written by Mike Cole <mike@mydot.com>
886 // modified for interlacing by Brad Hughes
888 float drx, dgx, dbx, dry, dgy, dby, yr = 0.0, yg = 0.0, yb = 0.0,
889 xr = (float) from.red(),
890 xg = (float) from.green(),
891 xb = (float) from.blue();
892 unsigned char *pr = red, *pg = green, *pb = blue;
893 unsigned int w = width * 2, h = height * 2, *xt = xtable, *yt = ytable;
895 register unsigned int x, y;
897 dry = drx = (float) (to.red() - from.red());
898 dgy = dgx = (float) (to.green() - from.green());
899 dby = dbx = (float) (to.blue() - from.blue());
906 for (x = 0; x < width; x++) {
907 *(xt++) = (unsigned char) (xr);
908 *(xt++) = (unsigned char) (xg);
909 *(xt++) = (unsigned char) (xb);
921 for (y = 0; y < height; y++) {
922 *(yt++) = ((unsigned char) yr);
923 *(yt++) = ((unsigned char) yg);
924 *(yt++) = ((unsigned char) yb);
931 // Combine tables to create gradient
935 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
936 for (xt = xtable, x = 0; x < width; x++) {
937 *(pr++) = *(xt++) + *(yt);
938 *(pg++) = *(xt++) + *(yt + 1);
939 *(pb++) = *(xt++) + *(yt + 2);
943 // faked interlacing effect
944 unsigned char channel, channel2;
946 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
947 for (xt = xtable, x = 0; x < width; x++) {
949 channel = *(xt++) + *(yt);
950 channel2 = (channel >> 1) + (channel >> 2);
951 if (channel2 > channel) channel2 = 0;
954 channel = *(xt++) + *(yt + 1);
955 channel2 = (channel >> 1) + (channel >> 2);
956 if (channel2 > channel) channel2 = 0;
959 channel = *(xt++) + *(yt + 2);
960 channel2 = (channel >> 1) + (channel >> 2);
961 if (channel2 > channel) channel2 = 0;
964 channel = *(xt++) + *(yt);
965 channel2 = channel + (channel >> 3);
966 if (channel2 < channel) channel2 = ~0;
969 channel = *(xt++) + *(yt + 1);
970 channel2 = channel + (channel >> 3);
971 if (channel2 < channel) channel2 = ~0;
974 channel = *(xt++) + *(yt + 2);
975 channel2 = channel + (channel >> 3);
976 if (channel2 < channel) channel2 = ~0;
985 void BImage::hgradient(void) {
987 xr = (float) from.red(),
988 xg = (float) from.green(),
989 xb = (float) from.blue();
990 unsigned char *pr = red, *pg = green, *pb = blue;
992 register unsigned int x, y;
994 drx = (float) (to.red() - from.red());
995 dgx = (float) (to.green() - from.green());
996 dbx = (float) (to.blue() - from.blue());
1002 if (interlaced && height > 2) {
1003 // faked interlacing effect
1004 unsigned char channel, channel2;
1006 for (x = 0; x < width; x++, pr++, pg++, pb++) {
1007 channel = (unsigned char) xr;
1008 channel2 = (channel >> 1) + (channel >> 2);
1009 if (channel2 > channel) channel2 = 0;
1012 channel = (unsigned char) xg;
1013 channel2 = (channel >> 1) + (channel >> 2);
1014 if (channel2 > channel) channel2 = 0;
1017 channel = (unsigned char) xb;
1018 channel2 = (channel >> 1) + (channel >> 2);
1019 if (channel2 > channel) channel2 = 0;
1023 channel = (unsigned char) xr;
1024 channel2 = channel + (channel >> 3);
1025 if (channel2 < channel) channel2 = ~0;
1026 *(pr + width) = channel2;
1028 channel = (unsigned char) xg;
1029 channel2 = channel + (channel >> 3);
1030 if (channel2 < channel) channel2 = ~0;
1031 *(pg + width) = channel2;
1033 channel = (unsigned char) xb;
1034 channel2 = channel + (channel >> 3);
1035 if (channel2 < channel) channel2 = ~0;
1036 *(pb + width) = channel2;
1049 for (y = 2; y < height; y++, pr += width, pg += width, pb += width) {
1050 if (y & 1) offset = width; else offset = 0;
1052 memcpy(pr, (red + offset), width);
1053 memcpy(pg, (green + offset), width);
1054 memcpy(pb, (blue + offset), width);
1058 for (x = 0; x < width; x++) {
1059 *(pr++) = (unsigned char) (xr);
1060 *(pg++) = (unsigned char) (xg);
1061 *(pb++) = (unsigned char) (xb);
1068 for (y = 1; y < height; y++, pr += width, pg += width, pb += width) {
1069 memcpy(pr, red, width);
1070 memcpy(pg, green, width);
1071 memcpy(pb, blue, width);
1077 void BImage::vgradient(void) {
1078 float dry, dgy, dby,
1079 yr = (float) from.red(),
1080 yg = (float) from.green(),
1081 yb = (float) from.blue();
1082 unsigned char *pr = red, *pg = green, *pb = blue;
1084 register unsigned int y;
1086 dry = (float) (to.red() - from.red());
1087 dgy = (float) (to.green() - from.green());
1088 dby = (float) (to.blue() - from.blue());
1095 // faked interlacing effect
1096 unsigned char channel, channel2;
1098 for (y = 0; y < height; y++, pr += width, pg += width, pb += width) {
1100 channel = (unsigned char) yr;
1101 channel2 = (channel >> 1) + (channel >> 2);
1102 if (channel2 > channel) channel2 = 0;
1103 memset(pr, channel2, width);
1105 channel = (unsigned char) yg;
1106 channel2 = (channel >> 1) + (channel >> 2);
1107 if (channel2 > channel) channel2 = 0;
1108 memset(pg, channel2, width);
1110 channel = (unsigned char) yb;
1111 channel2 = (channel >> 1) + (channel >> 2);
1112 if (channel2 > channel) channel2 = 0;
1113 memset(pb, channel2, width);
1115 channel = (unsigned char) yr;
1116 channel2 = channel + (channel >> 3);
1117 if (channel2 < channel) channel2 = ~0;
1118 memset(pr, channel2, width);
1120 channel = (unsigned char) yg;
1121 channel2 = channel + (channel >> 3);
1122 if (channel2 < channel) channel2 = ~0;
1123 memset(pg, channel2, width);
1125 channel = (unsigned char) yb;
1126 channel2 = channel + (channel >> 3);
1127 if (channel2 < channel) channel2 = ~0;
1128 memset(pb, channel2, width);
1137 for (y = 0; y < height; y++, pr += width, pg += width, pb += width) {
1138 memset(pr, (unsigned char) yr, width);
1139 memset(pg, (unsigned char) yg, width);
1140 memset(pb, (unsigned char) yb, width);
1150 void BImage::pgradient(void) {
1151 // pyramid gradient - based on original dgradient, written by
1152 // Mosfet (mosfet@kde.org)
1153 // adapted from kde sources for Blackbox by Brad Hughes
1155 float yr, yg, yb, drx, dgx, dbx, dry, dgy, dby,
1157 int rsign, gsign, bsign;
1158 unsigned char *pr = red, *pg = green, *pb = blue;
1159 unsigned int tr = to.red(), tg = to.green(), tb = to.blue(),
1160 *xt = xtable, *yt = ytable;
1162 register unsigned int x, y;
1164 dry = drx = (float) (to.red() - from.red());
1165 dgy = dgx = (float) (to.green() - from.green());
1166 dby = dbx = (float) (to.blue() - from.blue());
1168 rsign = (drx < 0) ? -1 : 1;
1169 gsign = (dgx < 0) ? -1 : 1;
1170 bsign = (dbx < 0) ? -1 : 1;
1172 xr = yr = (drx / 2);
1173 xg = yg = (dgx / 2);
1174 xb = yb = (dbx / 2);
1181 for (x = 0; x < width; x++) {
1182 *(xt++) = (unsigned char) ((xr < 0) ? -xr : xr);
1183 *(xt++) = (unsigned char) ((xg < 0) ? -xg : xg);
1184 *(xt++) = (unsigned char) ((xb < 0) ? -xb : xb);
1196 for (y = 0; y < height; y++) {
1197 *(yt++) = ((unsigned char) ((yr < 0) ? -yr : yr));
1198 *(yt++) = ((unsigned char) ((yg < 0) ? -yg : yg));
1199 *(yt++) = ((unsigned char) ((yb < 0) ? -yb : yb));
1206 // Combine tables to create gradient
1210 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1211 for (xt = xtable, x = 0; x < width; x++) {
1212 *(pr++) = (unsigned char) (tr - (rsign * (*(xt++) + *(yt))));
1213 *(pg++) = (unsigned char) (tg - (gsign * (*(xt++) + *(yt + 1))));
1214 *(pb++) = (unsigned char) (tb - (bsign * (*(xt++) + *(yt + 2))));
1218 // faked interlacing effect
1219 unsigned char channel, channel2;
1221 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1222 for (xt = xtable, x = 0; x < width; x++) {
1224 channel = (unsigned char) (tr - (rsign * (*(xt++) + *(yt))));
1225 channel2 = (channel >> 1) + (channel >> 2);
1226 if (channel2 > channel) channel2 = 0;
1229 channel = (unsigned char) (tg - (gsign * (*(xt++) + *(yt + 1))));
1230 channel2 = (channel >> 1) + (channel >> 2);
1231 if (channel2 > channel) channel2 = 0;
1234 channel = (unsigned char) (tb - (bsign * (*(xt++) + *(yt + 2))));
1235 channel2 = (channel >> 1) + (channel >> 2);
1236 if (channel2 > channel) channel2 = 0;
1239 channel = (unsigned char) (tr - (rsign * (*(xt++) + *(yt))));
1240 channel2 = channel + (channel >> 3);
1241 if (channel2 < channel) channel2 = ~0;
1244 channel = (unsigned char) (tg - (gsign * (*(xt++) + *(yt + 1))));
1245 channel2 = channel + (channel >> 3);
1246 if (channel2 < channel) channel2 = ~0;
1249 channel = (unsigned char) (tb - (bsign * (*(xt++) + *(yt + 2))));
1250 channel2 = channel + (channel >> 3);
1251 if (channel2 < channel) channel2 = ~0;
1260 void BImage::rgradient(void) {
1261 // rectangle gradient - based on original dgradient, written by
1262 // Mosfet (mosfet@kde.org)
1263 // adapted from kde sources for Blackbox by Brad Hughes
1265 float drx, dgx, dbx, dry, dgy, dby, xr, xg, xb, yr, yg, yb;
1266 int rsign, gsign, bsign;
1267 unsigned char *pr = red, *pg = green, *pb = blue;
1268 unsigned int tr = to.red(), tg = to.green(), tb = to.blue(),
1269 *xt = xtable, *yt = ytable;
1271 register unsigned int x, y;
1273 dry = drx = (float) (to.red() - from.red());
1274 dgy = dgx = (float) (to.green() - from.green());
1275 dby = dbx = (float) (to.blue() - from.blue());
1277 rsign = (drx < 0) ? -2 : 2;
1278 gsign = (dgx < 0) ? -2 : 2;
1279 bsign = (dbx < 0) ? -2 : 2;
1281 xr = yr = (drx / 2);
1282 xg = yg = (dgx / 2);
1283 xb = yb = (dbx / 2);
1290 for (x = 0; x < width; x++) {
1291 *(xt++) = (unsigned char) ((xr < 0) ? -xr : xr);
1292 *(xt++) = (unsigned char) ((xg < 0) ? -xg : xg);
1293 *(xt++) = (unsigned char) ((xb < 0) ? -xb : xb);
1305 for (y = 0; y < height; y++) {
1306 *(yt++) = ((unsigned char) ((yr < 0) ? -yr : yr));
1307 *(yt++) = ((unsigned char) ((yg < 0) ? -yg : yg));
1308 *(yt++) = ((unsigned char) ((yb < 0) ? -yb : yb));
1315 // Combine tables to create gradient
1319 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1320 for (xt = xtable, x = 0; x < width; x++) {
1321 *(pr++) = (unsigned char) (tr - (rsign * max(*(xt++), *(yt))));
1322 *(pg++) = (unsigned char) (tg - (gsign * max(*(xt++), *(yt + 1))));
1323 *(pb++) = (unsigned char) (tb - (bsign * max(*(xt++), *(yt + 2))));
1327 // faked interlacing effect
1328 unsigned char channel, channel2;
1330 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1331 for (xt = xtable, x = 0; x < width; x++) {
1333 channel = (unsigned char) (tr - (rsign * max(*(xt++), *(yt))));
1334 channel2 = (channel >> 1) + (channel >> 2);
1335 if (channel2 > channel) channel2 = 0;
1338 channel = (unsigned char) (tg - (gsign * max(*(xt++), *(yt + 1))));
1339 channel2 = (channel >> 1) + (channel >> 2);
1340 if (channel2 > channel) channel2 = 0;
1343 channel = (unsigned char) (tb - (bsign * max(*(xt++), *(yt + 2))));
1344 channel2 = (channel >> 1) + (channel >> 2);
1345 if (channel2 > channel) channel2 = 0;
1348 channel = (unsigned char) (tr - (rsign * max(*(xt++), *(yt))));
1349 channel2 = channel + (channel >> 3);
1350 if (channel2 < channel) channel2 = ~0;
1353 channel = (unsigned char) (tg - (gsign * max(*(xt++), *(yt + 1))));
1354 channel2 = channel + (channel >> 3);
1355 if (channel2 < channel) channel2 = ~0;
1358 channel = (unsigned char) (tb - (bsign * max(*(xt++), *(yt + 2))));
1359 channel2 = channel + (channel >> 3);
1360 if (channel2 < channel) channel2 = ~0;
1369 void BImage::egradient(void) {
1370 // elliptic gradient - based on original dgradient, written by
1371 // Mosfet (mosfet@kde.org)
1372 // adapted from kde sources for Blackbox by Brad Hughes
1374 float drx, dgx, dbx, dry, dgy, dby, yr, yg, yb, xr, xg, xb;
1375 int rsign, gsign, bsign;
1376 unsigned char *pr = red, *pg = green, *pb = blue;
1377 unsigned int *xt = xtable, *yt = ytable,
1378 tr = (unsigned long) to.red(),
1379 tg = (unsigned long) to.green(),
1380 tb = (unsigned long) to.blue();
1382 register unsigned int x, y;
1384 dry = drx = (float) (to.red() - from.red());
1385 dgy = dgx = (float) (to.green() - from.green());
1386 dby = dbx = (float) (to.blue() - from.blue());
1388 rsign = (drx < 0) ? -1 : 1;
1389 gsign = (dgx < 0) ? -1 : 1;
1390 bsign = (dbx < 0) ? -1 : 1;
1392 xr = yr = (drx / 2);
1393 xg = yg = (dgx / 2);
1394 xb = yb = (dbx / 2);
1401 for (x = 0; x < width; x++) {
1402 *(xt++) = (unsigned long) (xr * xr);
1403 *(xt++) = (unsigned long) (xg * xg);
1404 *(xt++) = (unsigned long) (xb * xb);
1416 for (y = 0; y < height; y++) {
1417 *(yt++) = (unsigned long) (yr * yr);
1418 *(yt++) = (unsigned long) (yg * yg);
1419 *(yt++) = (unsigned long) (yb * yb);
1426 // Combine tables to create gradient
1430 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1431 for (xt = xtable, x = 0; x < width; x++) {
1432 *(pr++) = (unsigned char)
1433 (tr - (rsign * control->getSqrt(*(xt++) + *(yt))));
1434 *(pg++) = (unsigned char)
1435 (tg - (gsign * control->getSqrt(*(xt++) + *(yt + 1))));
1436 *(pb++) = (unsigned char)
1437 (tb - (bsign * control->getSqrt(*(xt++) + *(yt + 2))));
1441 // faked interlacing effect
1442 unsigned char channel, channel2;
1444 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1445 for (xt = xtable, x = 0; x < width; x++) {
1447 channel = (unsigned char)
1448 (tr - (rsign * control->getSqrt(*(xt++) + *(yt))));
1449 channel2 = (channel >> 1) + (channel >> 2);
1450 if (channel2 > channel) channel2 = 0;
1453 channel = (unsigned char)
1454 (tg - (gsign * control->getSqrt(*(xt++) + *(yt + 1))));
1455 channel2 = (channel >> 1) + (channel >> 2);
1456 if (channel2 > channel) channel2 = 0;
1459 channel = (unsigned char)
1460 (tb - (bsign * control->getSqrt(*(xt++) + *(yt + 2))));
1461 channel2 = (channel >> 1) + (channel >> 2);
1462 if (channel2 > channel) channel2 = 0;
1465 channel = (unsigned char)
1466 (tr - (rsign * control->getSqrt(*(xt++) + *(yt))));
1467 channel2 = channel + (channel >> 3);
1468 if (channel2 < channel) channel2 = ~0;
1471 channel = (unsigned char)
1472 (tg - (gsign * control->getSqrt(*(xt++) + *(yt + 1))));
1473 channel2 = channel + (channel >> 3);
1474 if (channel2 < channel) channel2 = ~0;
1477 channel = (unsigned char)
1478 (tb - (bsign * control->getSqrt(*(xt++) + *(yt + 2))));
1479 channel2 = channel + (channel >> 3);
1480 if (channel2 < channel) channel2 = ~0;
1489 void BImage::pcgradient(void) {
1490 // pipe cross gradient - based on original dgradient, written by
1491 // Mosfet (mosfet@kde.org)
1492 // adapted from kde sources for Blackbox by Brad Hughes
1494 float drx, dgx, dbx, dry, dgy, dby, xr, xg, xb, yr, yg, yb;
1495 int rsign, gsign, bsign;
1496 unsigned char *pr = red, *pg = green, *pb = blue;
1497 unsigned int *xt = xtable, *yt = ytable,
1502 register unsigned int x, y;
1504 dry = drx = (float) (to.red() - from.red());
1505 dgy = dgx = (float) (to.green() - from.green());
1506 dby = dbx = (float) (to.blue() - from.blue());
1508 rsign = (drx < 0) ? -2 : 2;
1509 gsign = (dgx < 0) ? -2 : 2;
1510 bsign = (dbx < 0) ? -2 : 2;
1512 xr = yr = (drx / 2);
1513 xg = yg = (dgx / 2);
1514 xb = yb = (dbx / 2);
1521 for (x = 0; x < width; x++) {
1522 *(xt++) = (unsigned char) ((xr < 0) ? -xr : xr);
1523 *(xt++) = (unsigned char) ((xg < 0) ? -xg : xg);
1524 *(xt++) = (unsigned char) ((xb < 0) ? -xb : xb);
1536 for (y = 0; y < height; y++) {
1537 *(yt++) = ((unsigned char) ((yr < 0) ? -yr : yr));
1538 *(yt++) = ((unsigned char) ((yg < 0) ? -yg : yg));
1539 *(yt++) = ((unsigned char) ((yb < 0) ? -yb : yb));
1546 // Combine tables to create gradient
1549 // normal pcgradient
1550 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1551 for (xt = xtable, x = 0; x < width; x++) {
1552 *(pr++) = (unsigned char) (tr - (rsign * min(*(xt++), *(yt))));
1553 *(pg++) = (unsigned char) (tg - (gsign * min(*(xt++), *(yt + 1))));
1554 *(pb++) = (unsigned char) (tb - (bsign * min(*(xt++), *(yt + 2))));
1558 // faked interlacing effect
1559 unsigned char channel, channel2;
1561 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1562 for (xt = xtable, x = 0; x < width; x++) {
1564 channel = (unsigned char) (tr - (rsign * min(*(xt++), *(yt))));
1565 channel2 = (channel >> 1) + (channel >> 2);
1566 if (channel2 > channel) channel2 = 0;
1569 channel = (unsigned char) (tg - (bsign * min(*(xt++), *(yt + 1))));
1570 channel2 = (channel >> 1) + (channel >> 2);
1571 if (channel2 > channel) channel2 = 0;
1574 channel = (unsigned char) (tb - (gsign * min(*(xt++), *(yt + 2))));
1575 channel2 = (channel >> 1) + (channel >> 2);
1576 if (channel2 > channel) channel2 = 0;
1579 channel = (unsigned char) (tr - (rsign * min(*(xt++), *(yt))));
1580 channel2 = channel + (channel >> 3);
1581 if (channel2 < channel) channel2 = ~0;
1584 channel = (unsigned char) (tg - (gsign * min(*(xt++), *(yt + 1))));
1585 channel2 = channel + (channel >> 3);
1586 if (channel2 < channel) channel2 = ~0;
1589 channel = (unsigned char) (tb - (bsign * min(*(xt++), *(yt + 2))));
1590 channel2 = channel + (channel >> 3);
1591 if (channel2 < channel) channel2 = ~0;
1600 void BImage::cdgradient(void) {
1601 // cross diagonal gradient - based on original dgradient, written by
1602 // Mosfet (mosfet@kde.org)
1603 // adapted from kde sources for Blackbox by Brad Hughes
1605 float drx, dgx, dbx, dry, dgy, dby, yr = 0.0, yg = 0.0, yb = 0.0,
1606 xr = (float) from.red(),
1607 xg = (float) from.green(),
1608 xb = (float) from.blue();
1609 unsigned char *pr = red, *pg = green, *pb = blue;
1610 unsigned int w = width * 2, h = height * 2, *xt, *yt;
1612 register unsigned int x, y;
1614 dry = drx = (float) (to.red() - from.red());
1615 dgy = dgx = (float) (to.green() - from.green());
1616 dby = dbx = (float) (to.blue() - from.blue());
1623 for (xt = (xtable + (width * 3) - 1), x = 0; x < width; x++) {
1624 *(xt--) = (unsigned char) xb;
1625 *(xt--) = (unsigned char) xg;
1626 *(xt--) = (unsigned char) xr;
1638 for (yt = ytable, y = 0; y < height; y++) {
1639 *(yt++) = (unsigned char) yr;
1640 *(yt++) = (unsigned char) yg;
1641 *(yt++) = (unsigned char) yb;
1648 // Combine tables to create gradient
1651 // normal cdgradient
1652 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1653 for (xt = xtable, x = 0; x < width; x++) {
1654 *(pr++) = *(xt++) + *(yt);
1655 *(pg++) = *(xt++) + *(yt + 1);
1656 *(pb++) = *(xt++) + *(yt + 2);
1660 // faked interlacing effect
1661 unsigned char channel, channel2;
1663 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1664 for (xt = xtable, x = 0; x < width; x++) {
1666 channel = *(xt++) + *(yt);
1667 channel2 = (channel >> 1) + (channel >> 2);
1668 if (channel2 > channel) channel2 = 0;
1671 channel = *(xt++) + *(yt + 1);
1672 channel2 = (channel >> 1) + (channel >> 2);
1673 if (channel2 > channel) channel2 = 0;
1676 channel = *(xt++) + *(yt + 2);
1677 channel2 = (channel >> 1) + (channel >> 2);
1678 if (channel2 > channel) channel2 = 0;
1681 channel = *(xt++) + *(yt);
1682 channel2 = channel + (channel >> 3);
1683 if (channel2 < channel) channel2 = ~0;
1686 channel = *(xt++) + *(yt + 1);
1687 channel2 = channel + (channel >> 3);
1688 if (channel2 < channel) channel2 = ~0;
1691 channel = *(xt++) + *(yt + 2);
1692 channel2 = channel + (channel >> 3);
1693 if (channel2 < channel) channel2 = ~0;