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 if (texture.texture() & BTexture::FlatBorder) {
111 BPen penborder(texture.colorTo());
112 XDrawRectangle(display, pixmap, penborder.gc(), 0, 0, width-1, height-1);
115 if (texture.texture() & BTexture::Bevel1) {
116 if (texture.texture() & BTexture::Raised) {
117 XDrawLine(display, pixmap, penshadow.gc(),
118 0, height - 1, width - 1, height - 1);
119 XDrawLine(display, pixmap, penshadow.gc(),
120 width - 1, height - 1, width - 1, 0);
122 XDrawLine(display, pixmap, penlight.gc(),
124 XDrawLine(display, pixmap, penlight.gc(),
125 0, height - 1, 0, 0);
126 } else if (texture.texture() & BTexture::Sunken) {
127 XDrawLine(display, pixmap, penlight.gc(),
128 0, height - 1, width - 1, height - 1);
129 XDrawLine(display, pixmap, penlight.gc(),
130 width - 1, height - 1, width - 1, 0);
132 XDrawLine(display, pixmap, penshadow.gc(),
134 XDrawLine(display, pixmap, penshadow.gc(),
135 0, height - 1, 0, 0);
137 } else if (texture.texture() & BTexture::Bevel2) {
138 if (texture.texture() & BTexture::Raised) {
139 XDrawLine(display, pixmap, penshadow.gc(),
140 1, height - 3, width - 3, height - 3);
141 XDrawLine(display, pixmap, penshadow.gc(),
142 width - 3, height - 3, width - 3, 1);
144 XDrawLine(display, pixmap, penlight.gc(),
146 XDrawLine(display, pixmap, penlight.gc(),
147 1, height - 3, 1, 1);
148 } else if (texture.texture() & BTexture::Sunken) {
149 XDrawLine(display, pixmap, penlight.gc(),
150 1, height - 3, width - 3, height - 3);
151 XDrawLine(display, pixmap, penlight.gc(),
152 width - 3, height - 3, width - 3, 1);
154 XDrawLine(display, pixmap, penshadow.gc(),
156 XDrawLine(display, pixmap, penshadow.gc(),
157 1, height - 3, 1, 1);
165 Pixmap BImage::render_gradient(const BTexture &texture) {
166 bool inverted = False;
168 interlaced = texture.texture() & BTexture::Interlaced;
170 if (texture.texture() & BTexture::Sunken) {
171 from = texture.colorTo();
172 to = texture.color();
174 if (! (texture.texture() & BTexture::Invert)) inverted = True;
176 from = texture.color();
177 to = texture.colorTo();
179 if (texture.texture() & BTexture::Invert) inverted = True;
182 control->getGradientBuffers(width, height, &xtable, &ytable);
184 if (texture.texture() & BTexture::Diagonal) dgradient();
185 else if (texture.texture() & BTexture::Elliptic) egradient();
186 else if (texture.texture() & BTexture::Horizontal) hgradient();
187 else if (texture.texture() & BTexture::Pyramid) pgradient();
188 else if (texture.texture() & BTexture::Rectangle) rgradient();
189 else if (texture.texture() & BTexture::Vertical) vgradient();
190 else if (texture.texture() & BTexture::CrossDiagonal) cdgradient();
191 else if (texture.texture() & BTexture::PipeCross) pcgradient();
193 if (texture.texture() & BTexture::Bevel1) bevel1();
194 else if (texture.texture() & BTexture::Bevel2) bevel2();
196 if (inverted) invert();
198 return renderPixmap();
203 static const unsigned char dither4[4][4] = {
212 * Helper function for TrueColorDither and renderXImage
214 * This handles the proper setting of the image data based on the image depth
215 * and the machine's byte ordering
218 void assignPixelData(unsigned int bit_depth, unsigned char **data,
219 unsigned long pixel) {
220 unsigned char *pixel_data = *data;
223 *pixel_data++ = pixel;
226 case 16: // 16bpp LSB
227 *pixel_data++ = pixel;
228 *pixel_data++ = pixel >> 8;
231 case 17: // 16bpp MSB
232 *pixel_data++ = pixel >> 8;
233 *pixel_data++ = pixel;
236 case 24: // 24bpp LSB
237 *pixel_data++ = pixel;
238 *pixel_data++ = pixel >> 8;
239 *pixel_data++ = pixel >> 16;
242 case 25: // 24bpp MSB
243 *pixel_data++ = pixel >> 16;
244 *pixel_data++ = pixel >> 8;
245 *pixel_data++ = pixel;
248 case 32: // 32bpp LSB
249 *pixel_data++ = pixel;
250 *pixel_data++ = pixel >> 8;
251 *pixel_data++ = pixel >> 16;
252 *pixel_data++ = pixel >> 24;
255 case 33: // 32bpp MSB
256 *pixel_data++ = pixel >> 24;
257 *pixel_data++ = pixel >> 16;
258 *pixel_data++ = pixel >> 8;
259 *pixel_data++ = pixel;
262 *data = pixel_data; // assign back so we don't lose our place
266 // algorithm: ordered dithering... many many thanks to rasterman
267 // (raster@rasterman.com) for telling me about this... portions of this
268 // code is based off of his code in Imlib
269 void BImage::TrueColorDither(unsigned int bit_depth, int bytes_per_line,
270 unsigned char *pixel_data) {
271 unsigned int x, y, dithx, dithy, r, g, b, er, eg, eb, offset;
272 unsigned char *ppixel_data = pixel_data;
275 for (y = 0, offset = 0; y < height; y++) {
278 for (x = 0; x < width; x++, offset++) {
284 er = r & (red_bits - 1);
285 eg = g & (green_bits - 1);
286 eb = b & (blue_bits - 1);
292 if ((dither4[dithy][dithx] < er) && (r < red_table[255])) r++;
293 if ((dither4[dithy][dithx] < eg) && (g < green_table[255])) g++;
294 if ((dither4[dithy][dithx] < eb) && (b < blue_table[255])) b++;
296 pixel = (r << red_offset) | (g << green_offset) | (b << blue_offset);
297 assignPixelData(bit_depth, &pixel_data, pixel);
300 pixel_data = (ppixel_data += bytes_per_line);
305 const static unsigned char dither8[8][8] = {
306 { 0, 32, 8, 40, 2, 34, 10, 42},
307 { 48, 16, 56, 24, 50, 18, 58, 26},
308 { 12, 44, 4, 36, 14, 46, 6, 38},
309 { 60, 28, 52, 20, 62, 30, 54, 22},
310 { 3, 35, 11, 43, 1, 33, 9, 41},
311 { 51, 19, 59, 27, 49, 17, 57, 25},
312 { 15, 47, 7, 39, 13, 45, 5, 37},
313 { 63, 31, 55, 23, 61, 29, 53, 21}
316 void BImage::OrderedPseudoColorDither(int bytes_per_line,
317 unsigned char *pixel_data) {
318 unsigned int x, y, dithx, dithy, r, g, b, er, eg, eb, offset;
320 unsigned char *ppixel_data = pixel_data;
322 for (y = 0, offset = 0; y < height; y++) {
325 for (x = 0; x < width; x++, offset++) {
332 er = r & (red_bits - 1);
333 eg = g & (green_bits - 1);
334 eb = b & (blue_bits - 1);
340 if ((dither8[dithy][dithx] < er) && (r < red_table[255])) r++;
341 if ((dither8[dithy][dithx] < eg) && (g < green_table[255])) g++;
342 if ((dither8[dithy][dithx] < eb) && (b < blue_table[255])) b++;
344 pixel = (r * cpccpc) + (g * cpc) + b;
345 *(pixel_data++) = colors[pixel].pixel;
348 pixel_data = (ppixel_data += bytes_per_line);
353 void BImage::PseudoColorDither(int bytes_per_line, unsigned char *pixel_data) {
355 *rerr = new short[width + 2],
356 *gerr = new short[width + 2],
357 *berr = new short[width + 2],
358 *nrerr = new short[width + 2],
359 *ngerr = new short[width + 2],
360 *nberr = new short[width + 2];
362 int rr, gg, bb, rer, ger, ber;
363 int dd = 255 / control->getColorsPerChannel();
364 unsigned int x, y, r, g, b, offset;
366 unsigned char *ppixel_data = pixel_data;
368 for (x = 0; x < width; x++) {
369 *(rerr + x) = *(red + x);
370 *(gerr + x) = *(green + x);
371 *(berr + x) = *(blue + x);
374 *(rerr + x) = *(gerr + x) = *(berr + x) = 0;
376 for (y = 0, offset = 0; y < height; y++) {
377 if (y < (height - 1)) {
378 int i = offset + width;
379 for (x = 0; x < width; x++, i++) {
380 *(nrerr + x) = *(red + i);
381 *(ngerr + x) = *(green + i);
382 *(nberr + x) = *(blue + i);
385 *(nrerr + x) = *(red + (--i));
386 *(ngerr + x) = *(green + i);
387 *(nberr + x) = *(blue + i);
390 for (x = 0; x < width; x++) {
395 if (rr > 255) rr = 255; else if (rr < 0) rr = 0;
396 if (gg > 255) gg = 255; else if (gg < 0) gg = 0;
397 if (bb > 255) bb = 255; else if (bb < 0) bb = 0;
403 rer = rerr[x] - r*dd;
404 ger = gerr[x] - g*dd;
405 ber = berr[x] - b*dd;
407 pixel = (r * cpccpc) + (g * cpc) + b;
408 *pixel_data++ = colors[pixel].pixel;
423 pixel_data = (ppixel_data += bytes_per_line);
446 XImage *BImage::renderXImage(void) {
448 XCreateImage(control->getBaseDisplay()->getXDisplay(),
449 control->getVisual(), control->getDepth(), ZPixmap, 0, 0,
450 width, height, 32, 0);
453 fprintf(stderr, i18n(ImageSet, ImageErrorCreatingXImage,
454 "BImage::renderXImage: error creating XImage\n"));
459 image->data = (char *) 0;
461 unsigned char *d = new unsigned char[image->bytes_per_line * (height + 1)];
463 unsigned int o = image->bits_per_pixel +
464 ((image->byte_order == MSBFirst) ? 1 : 0);
466 bool unsupported = False;
468 if (control->doDither() && width > 1 && height > 1) {
469 switch (control->getVisual()->c_class) {
471 TrueColorDither(o, image->bytes_per_line, d);
477 OrderedPseudoColorDither(image->bytes_per_line, d);
479 PseudoColorDither(image->bytes_per_line, d);
488 unsigned int x, y, r, g, b, offset;
489 unsigned char *pixel_data = d, *ppixel_data = d;
492 switch (control->getVisual()->c_class) {
495 for (y = 0, offset = 0; y < height; ++y) {
496 for (x = 0; x < width; ++x, ++offset) {
497 r = red_table[red[offset]];
498 g = green_table[green[offset]];
499 b = blue_table[blue[offset]];
501 pixel = (r * cpccpc) + (g * cpc) + b;
502 *pixel_data++ = colors[pixel].pixel;
505 pixel_data = (ppixel_data += image->bytes_per_line);
511 for (y = 0, offset = 0; y < height; y++) {
512 for (x = 0; x < width; x++, offset++) {
513 r = red_table[red[offset]];
514 g = green_table[green[offset]];
515 b = blue_table[blue[offset]];
517 pixel = (r << red_offset) | (g << green_offset) | (b << blue_offset);
518 assignPixelData(o, &pixel_data, pixel);
521 pixel_data = (ppixel_data += image->bytes_per_line);
528 for (y = 0, offset = 0; y < height; y++) {
529 for (x = 0; x < width; x++, offset++) {
530 r = *(red_table + *(red + offset));
531 g = *(green_table + *(green + offset));
532 b = *(blue_table + *(blue + offset));
534 g = ((r * 30) + (g * 59) + (b * 11)) / 100;
535 *pixel_data++ = colors[g].pixel;
538 pixel_data = (ppixel_data += image->bytes_per_line);
549 fprintf(stderr, i18n(ImageSet, ImageUnsupVisual,
550 "BImage::renderXImage: unsupported visual\n"));
552 XDestroyImage(image);
556 image->data = (char *) d;
562 Pixmap BImage::renderPixmap(void) {
564 XCreatePixmap(control->getBaseDisplay()->getXDisplay(),
565 control->getDrawable(), width, height, control->getDepth());
567 if (pixmap == None) {
568 fprintf(stderr, i18n(ImageSet, ImageErrorCreatingPixmap,
569 "BImage::renderPixmap: error creating pixmap\n"));
573 XImage *image = renderXImage();
576 XFreePixmap(control->getBaseDisplay()->getXDisplay(), pixmap);
581 XDestroyImage(image);
582 XFreePixmap(control->getBaseDisplay()->getXDisplay(), pixmap);
586 XPutImage(control->getBaseDisplay()->getXDisplay(), pixmap,
587 DefaultGC(control->getBaseDisplay()->getXDisplay(),
588 control->getScreenInfo()->getScreenNumber()),
589 image, 0, 0, 0, 0, width, height);
592 delete [] image->data;
596 XDestroyImage(image);
602 void BImage::bevel1(void) {
603 if (width > 2 && height > 2) {
604 unsigned char *pr = red, *pg = green, *pb = blue;
606 register unsigned char r, g, b, rr ,gg ,bb;
607 register unsigned int w = width, h = height - 1, wh = w * h;
625 rr = (r >> 2) + (r >> 1);
628 gg = (g >> 2) + (g >> 1);
631 bb = (b >> 2) + (b >> 1);
654 rr = (r >> 2) + (r >> 1);
657 gg = (g >> 2) + (g >> 1);
660 bb = (b >> 2) + (b >> 1);
691 rr = (r >> 2) + (r >> 1);
694 gg = (g >> 2) + (g >> 1);
697 bb = (b >> 2) + (b >> 1);
724 rr = (r >> 2) + (r >> 1);
727 gg = (g >> 2) + (g >> 1);
730 bb = (b >> 2) + (b >> 1);
740 void BImage::bevel2(void) {
741 if (width > 4 && height > 4) {
742 unsigned char r, g, b, rr ,gg ,bb, *pr = red + width + 1,
743 *pg = green + width + 1, *pb = blue + width + 1;
744 unsigned int w = width - 2, h = height - 1, wh = width * (height - 3);
762 rr = (r >> 2) + (r >> 1);
765 gg = (g >> 2) + (g >> 1);
768 bb = (b >> 2) + (b >> 1);
800 rr = (r >> 2) + (r >> 1);
803 gg = (g >> 2) + (g >> 1);
806 bb = (b >> 2) + (b >> 1);
819 void BImage::invert(void) {
820 register unsigned int i, j, wh = (width * height) - 1;
823 for (i = 0, j = wh; j > i; j--, i++) {
825 *(red + j) = *(red + i);
829 *(green + j) = *(green + i);
833 *(blue + j) = *(blue + i);
839 void BImage::dgradient(void) {
840 // diagonal gradient code was written by Mike Cole <mike@mydot.com>
841 // modified for interlacing by Brad Hughes
843 float drx, dgx, dbx, dry, dgy, dby, yr = 0.0, yg = 0.0, yb = 0.0,
844 xr = (float) from.red(),
845 xg = (float) from.green(),
846 xb = (float) from.blue();
847 unsigned char *pr = red, *pg = green, *pb = blue;
848 unsigned int w = width * 2, h = height * 2, *xt = xtable, *yt = ytable;
850 register unsigned int x, y;
852 dry = drx = (float) (to.red() - from.red());
853 dgy = dgx = (float) (to.green() - from.green());
854 dby = dbx = (float) (to.blue() - from.blue());
861 for (x = 0; x < width; x++) {
862 *(xt++) = (unsigned char) (xr);
863 *(xt++) = (unsigned char) (xg);
864 *(xt++) = (unsigned char) (xb);
876 for (y = 0; y < height; y++) {
877 *(yt++) = ((unsigned char) yr);
878 *(yt++) = ((unsigned char) yg);
879 *(yt++) = ((unsigned char) yb);
886 // Combine tables to create gradient
890 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
891 for (xt = xtable, x = 0; x < width; x++) {
892 *(pr++) = *(xt++) + *(yt);
893 *(pg++) = *(xt++) + *(yt + 1);
894 *(pb++) = *(xt++) + *(yt + 2);
898 // faked interlacing effect
899 unsigned char channel, channel2;
901 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
902 for (xt = xtable, x = 0; x < width; x++) {
904 channel = *(xt++) + *(yt);
905 channel2 = (channel >> 1) + (channel >> 2);
906 if (channel2 > channel) channel2 = 0;
909 channel = *(xt++) + *(yt + 1);
910 channel2 = (channel >> 1) + (channel >> 2);
911 if (channel2 > channel) channel2 = 0;
914 channel = *(xt++) + *(yt + 2);
915 channel2 = (channel >> 1) + (channel >> 2);
916 if (channel2 > channel) channel2 = 0;
919 channel = *(xt++) + *(yt);
920 channel2 = channel + (channel >> 3);
921 if (channel2 < channel) channel2 = ~0;
924 channel = *(xt++) + *(yt + 1);
925 channel2 = channel + (channel >> 3);
926 if (channel2 < channel) channel2 = ~0;
929 channel = *(xt++) + *(yt + 2);
930 channel2 = channel + (channel >> 3);
931 if (channel2 < channel) channel2 = ~0;
940 void BImage::hgradient(void) {
942 xr = (float) from.red(),
943 xg = (float) from.green(),
944 xb = (float) from.blue();
945 unsigned char *pr = red, *pg = green, *pb = blue;
947 register unsigned int x, y;
949 drx = (float) (to.red() - from.red());
950 dgx = (float) (to.green() - from.green());
951 dbx = (float) (to.blue() - from.blue());
957 if (interlaced && height > 2) {
958 // faked interlacing effect
959 unsigned char channel, channel2;
961 for (x = 0; x < width; x++, pr++, pg++, pb++) {
962 channel = (unsigned char) xr;
963 channel2 = (channel >> 1) + (channel >> 2);
964 if (channel2 > channel) channel2 = 0;
967 channel = (unsigned char) xg;
968 channel2 = (channel >> 1) + (channel >> 2);
969 if (channel2 > channel) channel2 = 0;
972 channel = (unsigned char) xb;
973 channel2 = (channel >> 1) + (channel >> 2);
974 if (channel2 > channel) channel2 = 0;
978 channel = (unsigned char) xr;
979 channel2 = channel + (channel >> 3);
980 if (channel2 < channel) channel2 = ~0;
981 *(pr + width) = channel2;
983 channel = (unsigned char) xg;
984 channel2 = channel + (channel >> 3);
985 if (channel2 < channel) channel2 = ~0;
986 *(pg + width) = channel2;
988 channel = (unsigned char) xb;
989 channel2 = channel + (channel >> 3);
990 if (channel2 < channel) channel2 = ~0;
991 *(pb + width) = channel2;
1004 for (y = 2; y < height; y++, pr += width, pg += width, pb += width) {
1005 if (y & 1) offset = width; else offset = 0;
1007 memcpy(pr, (red + offset), width);
1008 memcpy(pg, (green + offset), width);
1009 memcpy(pb, (blue + offset), width);
1013 for (x = 0; x < width; x++) {
1014 *(pr++) = (unsigned char) (xr);
1015 *(pg++) = (unsigned char) (xg);
1016 *(pb++) = (unsigned char) (xb);
1023 for (y = 1; y < height; y++, pr += width, pg += width, pb += width) {
1024 memcpy(pr, red, width);
1025 memcpy(pg, green, width);
1026 memcpy(pb, blue, width);
1032 void BImage::vgradient(void) {
1033 float dry, dgy, dby,
1034 yr = (float) from.red(),
1035 yg = (float) from.green(),
1036 yb = (float) from.blue();
1037 unsigned char *pr = red, *pg = green, *pb = blue;
1039 register unsigned int y;
1041 dry = (float) (to.red() - from.red());
1042 dgy = (float) (to.green() - from.green());
1043 dby = (float) (to.blue() - from.blue());
1050 // faked interlacing effect
1051 unsigned char channel, channel2;
1053 for (y = 0; y < height; y++, pr += width, pg += width, pb += width) {
1055 channel = (unsigned char) yr;
1056 channel2 = (channel >> 1) + (channel >> 2);
1057 if (channel2 > channel) channel2 = 0;
1058 memset(pr, channel2, width);
1060 channel = (unsigned char) yg;
1061 channel2 = (channel >> 1) + (channel >> 2);
1062 if (channel2 > channel) channel2 = 0;
1063 memset(pg, channel2, width);
1065 channel = (unsigned char) yb;
1066 channel2 = (channel >> 1) + (channel >> 2);
1067 if (channel2 > channel) channel2 = 0;
1068 memset(pb, channel2, width);
1070 channel = (unsigned char) yr;
1071 channel2 = channel + (channel >> 3);
1072 if (channel2 < channel) channel2 = ~0;
1073 memset(pr, channel2, width);
1075 channel = (unsigned char) yg;
1076 channel2 = channel + (channel >> 3);
1077 if (channel2 < channel) channel2 = ~0;
1078 memset(pg, channel2, width);
1080 channel = (unsigned char) yb;
1081 channel2 = channel + (channel >> 3);
1082 if (channel2 < channel) channel2 = ~0;
1083 memset(pb, channel2, width);
1092 for (y = 0; y < height; y++, pr += width, pg += width, pb += width) {
1093 memset(pr, (unsigned char) yr, width);
1094 memset(pg, (unsigned char) yg, width);
1095 memset(pb, (unsigned char) yb, width);
1105 void BImage::pgradient(void) {
1106 // pyramid gradient - based on original dgradient, written by
1107 // Mosfet (mosfet@kde.org)
1108 // adapted from kde sources for Blackbox by Brad Hughes
1110 float yr, yg, yb, drx, dgx, dbx, dry, dgy, dby,
1112 int rsign, gsign, bsign;
1113 unsigned char *pr = red, *pg = green, *pb = blue;
1114 unsigned int tr = to.red(), tg = to.green(), tb = to.blue(),
1115 *xt = xtable, *yt = ytable;
1117 register unsigned int x, y;
1119 dry = drx = (float) (to.red() - from.red());
1120 dgy = dgx = (float) (to.green() - from.green());
1121 dby = dbx = (float) (to.blue() - from.blue());
1123 rsign = (drx < 0) ? -1 : 1;
1124 gsign = (dgx < 0) ? -1 : 1;
1125 bsign = (dbx < 0) ? -1 : 1;
1127 xr = yr = (drx / 2);
1128 xg = yg = (dgx / 2);
1129 xb = yb = (dbx / 2);
1136 for (x = 0; x < width; x++) {
1137 *(xt++) = (unsigned char) ((xr < 0) ? -xr : xr);
1138 *(xt++) = (unsigned char) ((xg < 0) ? -xg : xg);
1139 *(xt++) = (unsigned char) ((xb < 0) ? -xb : xb);
1151 for (y = 0; y < height; y++) {
1152 *(yt++) = ((unsigned char) ((yr < 0) ? -yr : yr));
1153 *(yt++) = ((unsigned char) ((yg < 0) ? -yg : yg));
1154 *(yt++) = ((unsigned char) ((yb < 0) ? -yb : yb));
1161 // Combine tables to create gradient
1165 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1166 for (xt = xtable, x = 0; x < width; x++) {
1167 *(pr++) = (unsigned char) (tr - (rsign * (*(xt++) + *(yt))));
1168 *(pg++) = (unsigned char) (tg - (gsign * (*(xt++) + *(yt + 1))));
1169 *(pb++) = (unsigned char) (tb - (bsign * (*(xt++) + *(yt + 2))));
1173 // faked interlacing effect
1174 unsigned char channel, channel2;
1176 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1177 for (xt = xtable, x = 0; x < width; x++) {
1179 channel = (unsigned char) (tr - (rsign * (*(xt++) + *(yt))));
1180 channel2 = (channel >> 1) + (channel >> 2);
1181 if (channel2 > channel) channel2 = 0;
1184 channel = (unsigned char) (tg - (gsign * (*(xt++) + *(yt + 1))));
1185 channel2 = (channel >> 1) + (channel >> 2);
1186 if (channel2 > channel) channel2 = 0;
1189 channel = (unsigned char) (tb - (bsign * (*(xt++) + *(yt + 2))));
1190 channel2 = (channel >> 1) + (channel >> 2);
1191 if (channel2 > channel) channel2 = 0;
1194 channel = (unsigned char) (tr - (rsign * (*(xt++) + *(yt))));
1195 channel2 = channel + (channel >> 3);
1196 if (channel2 < channel) channel2 = ~0;
1199 channel = (unsigned char) (tg - (gsign * (*(xt++) + *(yt + 1))));
1200 channel2 = channel + (channel >> 3);
1201 if (channel2 < channel) channel2 = ~0;
1204 channel = (unsigned char) (tb - (bsign * (*(xt++) + *(yt + 2))));
1205 channel2 = channel + (channel >> 3);
1206 if (channel2 < channel) channel2 = ~0;
1215 void BImage::rgradient(void) {
1216 // rectangle gradient - based on original dgradient, written by
1217 // Mosfet (mosfet@kde.org)
1218 // adapted from kde sources for Blackbox by Brad Hughes
1220 float drx, dgx, dbx, dry, dgy, dby, xr, xg, xb, yr, yg, yb;
1221 int rsign, gsign, bsign;
1222 unsigned char *pr = red, *pg = green, *pb = blue;
1223 unsigned int tr = to.red(), tg = to.green(), tb = to.blue(),
1224 *xt = xtable, *yt = ytable;
1226 register unsigned int x, y;
1228 dry = drx = (float) (to.red() - from.red());
1229 dgy = dgx = (float) (to.green() - from.green());
1230 dby = dbx = (float) (to.blue() - from.blue());
1232 rsign = (drx < 0) ? -2 : 2;
1233 gsign = (dgx < 0) ? -2 : 2;
1234 bsign = (dbx < 0) ? -2 : 2;
1236 xr = yr = (drx / 2);
1237 xg = yg = (dgx / 2);
1238 xb = yb = (dbx / 2);
1245 for (x = 0; x < width; x++) {
1246 *(xt++) = (unsigned char) ((xr < 0) ? -xr : xr);
1247 *(xt++) = (unsigned char) ((xg < 0) ? -xg : xg);
1248 *(xt++) = (unsigned char) ((xb < 0) ? -xb : xb);
1260 for (y = 0; y < height; y++) {
1261 *(yt++) = ((unsigned char) ((yr < 0) ? -yr : yr));
1262 *(yt++) = ((unsigned char) ((yg < 0) ? -yg : yg));
1263 *(yt++) = ((unsigned char) ((yb < 0) ? -yb : yb));
1270 // Combine tables to create gradient
1274 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1275 for (xt = xtable, x = 0; x < width; x++) {
1276 *(pr++) = (unsigned char) (tr - (rsign * max(*(xt++), *(yt))));
1277 *(pg++) = (unsigned char) (tg - (gsign * max(*(xt++), *(yt + 1))));
1278 *(pb++) = (unsigned char) (tb - (bsign * max(*(xt++), *(yt + 2))));
1282 // faked interlacing effect
1283 unsigned char channel, channel2;
1285 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1286 for (xt = xtable, x = 0; x < width; x++) {
1288 channel = (unsigned char) (tr - (rsign * max(*(xt++), *(yt))));
1289 channel2 = (channel >> 1) + (channel >> 2);
1290 if (channel2 > channel) channel2 = 0;
1293 channel = (unsigned char) (tg - (gsign * max(*(xt++), *(yt + 1))));
1294 channel2 = (channel >> 1) + (channel >> 2);
1295 if (channel2 > channel) channel2 = 0;
1298 channel = (unsigned char) (tb - (bsign * max(*(xt++), *(yt + 2))));
1299 channel2 = (channel >> 1) + (channel >> 2);
1300 if (channel2 > channel) channel2 = 0;
1303 channel = (unsigned char) (tr - (rsign * max(*(xt++), *(yt))));
1304 channel2 = channel + (channel >> 3);
1305 if (channel2 < channel) channel2 = ~0;
1308 channel = (unsigned char) (tg - (gsign * max(*(xt++), *(yt + 1))));
1309 channel2 = channel + (channel >> 3);
1310 if (channel2 < channel) channel2 = ~0;
1313 channel = (unsigned char) (tb - (bsign * max(*(xt++), *(yt + 2))));
1314 channel2 = channel + (channel >> 3);
1315 if (channel2 < channel) channel2 = ~0;
1324 void BImage::egradient(void) {
1325 // elliptic gradient - based on original dgradient, written by
1326 // Mosfet (mosfet@kde.org)
1327 // adapted from kde sources for Blackbox by Brad Hughes
1329 float drx, dgx, dbx, dry, dgy, dby, yr, yg, yb, xr, xg, xb;
1330 int rsign, gsign, bsign;
1331 unsigned char *pr = red, *pg = green, *pb = blue;
1332 unsigned int *xt = xtable, *yt = ytable,
1333 tr = (unsigned long) to.red(),
1334 tg = (unsigned long) to.green(),
1335 tb = (unsigned long) to.blue();
1337 register unsigned int x, y;
1339 dry = drx = (float) (to.red() - from.red());
1340 dgy = dgx = (float) (to.green() - from.green());
1341 dby = dbx = (float) (to.blue() - from.blue());
1343 rsign = (drx < 0) ? -1 : 1;
1344 gsign = (dgx < 0) ? -1 : 1;
1345 bsign = (dbx < 0) ? -1 : 1;
1347 xr = yr = (drx / 2);
1348 xg = yg = (dgx / 2);
1349 xb = yb = (dbx / 2);
1356 for (x = 0; x < width; x++) {
1357 *(xt++) = (unsigned long) (xr * xr);
1358 *(xt++) = (unsigned long) (xg * xg);
1359 *(xt++) = (unsigned long) (xb * xb);
1371 for (y = 0; y < height; y++) {
1372 *(yt++) = (unsigned long) (yr * yr);
1373 *(yt++) = (unsigned long) (yg * yg);
1374 *(yt++) = (unsigned long) (yb * yb);
1381 // Combine tables to create gradient
1385 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1386 for (xt = xtable, x = 0; x < width; x++) {
1387 *(pr++) = (unsigned char)
1388 (tr - (rsign * control->getSqrt(*(xt++) + *(yt))));
1389 *(pg++) = (unsigned char)
1390 (tg - (gsign * control->getSqrt(*(xt++) + *(yt + 1))));
1391 *(pb++) = (unsigned char)
1392 (tb - (bsign * control->getSqrt(*(xt++) + *(yt + 2))));
1396 // faked interlacing effect
1397 unsigned char channel, channel2;
1399 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1400 for (xt = xtable, x = 0; x < width; x++) {
1402 channel = (unsigned char)
1403 (tr - (rsign * control->getSqrt(*(xt++) + *(yt))));
1404 channel2 = (channel >> 1) + (channel >> 2);
1405 if (channel2 > channel) channel2 = 0;
1408 channel = (unsigned char)
1409 (tg - (gsign * control->getSqrt(*(xt++) + *(yt + 1))));
1410 channel2 = (channel >> 1) + (channel >> 2);
1411 if (channel2 > channel) channel2 = 0;
1414 channel = (unsigned char)
1415 (tb - (bsign * control->getSqrt(*(xt++) + *(yt + 2))));
1416 channel2 = (channel >> 1) + (channel >> 2);
1417 if (channel2 > channel) channel2 = 0;
1420 channel = (unsigned char)
1421 (tr - (rsign * control->getSqrt(*(xt++) + *(yt))));
1422 channel2 = channel + (channel >> 3);
1423 if (channel2 < channel) channel2 = ~0;
1426 channel = (unsigned char)
1427 (tg - (gsign * control->getSqrt(*(xt++) + *(yt + 1))));
1428 channel2 = channel + (channel >> 3);
1429 if (channel2 < channel) channel2 = ~0;
1432 channel = (unsigned char)
1433 (tb - (bsign * control->getSqrt(*(xt++) + *(yt + 2))));
1434 channel2 = channel + (channel >> 3);
1435 if (channel2 < channel) channel2 = ~0;
1444 void BImage::pcgradient(void) {
1445 // pipe cross gradient - based on original dgradient, written by
1446 // Mosfet (mosfet@kde.org)
1447 // adapted from kde sources for Blackbox by Brad Hughes
1449 float drx, dgx, dbx, dry, dgy, dby, xr, xg, xb, yr, yg, yb;
1450 int rsign, gsign, bsign;
1451 unsigned char *pr = red, *pg = green, *pb = blue;
1452 unsigned int *xt = xtable, *yt = ytable,
1457 register unsigned int x, y;
1459 dry = drx = (float) (to.red() - from.red());
1460 dgy = dgx = (float) (to.green() - from.green());
1461 dby = dbx = (float) (to.blue() - from.blue());
1463 rsign = (drx < 0) ? -2 : 2;
1464 gsign = (dgx < 0) ? -2 : 2;
1465 bsign = (dbx < 0) ? -2 : 2;
1467 xr = yr = (drx / 2);
1468 xg = yg = (dgx / 2);
1469 xb = yb = (dbx / 2);
1476 for (x = 0; x < width; x++) {
1477 *(xt++) = (unsigned char) ((xr < 0) ? -xr : xr);
1478 *(xt++) = (unsigned char) ((xg < 0) ? -xg : xg);
1479 *(xt++) = (unsigned char) ((xb < 0) ? -xb : xb);
1491 for (y = 0; y < height; y++) {
1492 *(yt++) = ((unsigned char) ((yr < 0) ? -yr : yr));
1493 *(yt++) = ((unsigned char) ((yg < 0) ? -yg : yg));
1494 *(yt++) = ((unsigned char) ((yb < 0) ? -yb : yb));
1501 // Combine tables to create gradient
1504 // normal pcgradient
1505 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1506 for (xt = xtable, x = 0; x < width; x++) {
1507 *(pr++) = (unsigned char) (tr - (rsign * min(*(xt++), *(yt))));
1508 *(pg++) = (unsigned char) (tg - (gsign * min(*(xt++), *(yt + 1))));
1509 *(pb++) = (unsigned char) (tb - (bsign * min(*(xt++), *(yt + 2))));
1513 // faked interlacing effect
1514 unsigned char channel, channel2;
1516 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1517 for (xt = xtable, x = 0; x < width; x++) {
1519 channel = (unsigned char) (tr - (rsign * min(*(xt++), *(yt))));
1520 channel2 = (channel >> 1) + (channel >> 2);
1521 if (channel2 > channel) channel2 = 0;
1524 channel = (unsigned char) (tg - (bsign * min(*(xt++), *(yt + 1))));
1525 channel2 = (channel >> 1) + (channel >> 2);
1526 if (channel2 > channel) channel2 = 0;
1529 channel = (unsigned char) (tb - (gsign * min(*(xt++), *(yt + 2))));
1530 channel2 = (channel >> 1) + (channel >> 2);
1531 if (channel2 > channel) channel2 = 0;
1534 channel = (unsigned char) (tr - (rsign * min(*(xt++), *(yt))));
1535 channel2 = channel + (channel >> 3);
1536 if (channel2 < channel) channel2 = ~0;
1539 channel = (unsigned char) (tg - (gsign * min(*(xt++), *(yt + 1))));
1540 channel2 = channel + (channel >> 3);
1541 if (channel2 < channel) channel2 = ~0;
1544 channel = (unsigned char) (tb - (bsign * min(*(xt++), *(yt + 2))));
1545 channel2 = channel + (channel >> 3);
1546 if (channel2 < channel) channel2 = ~0;
1555 void BImage::cdgradient(void) {
1556 // cross diagonal gradient - based on original dgradient, written by
1557 // Mosfet (mosfet@kde.org)
1558 // adapted from kde sources for Blackbox by Brad Hughes
1560 float drx, dgx, dbx, dry, dgy, dby, yr = 0.0, yg = 0.0, yb = 0.0,
1561 xr = (float) from.red(),
1562 xg = (float) from.green(),
1563 xb = (float) from.blue();
1564 unsigned char *pr = red, *pg = green, *pb = blue;
1565 unsigned int w = width * 2, h = height * 2, *xt, *yt;
1567 register unsigned int x, y;
1569 dry = drx = (float) (to.red() - from.red());
1570 dgy = dgx = (float) (to.green() - from.green());
1571 dby = dbx = (float) (to.blue() - from.blue());
1578 for (xt = (xtable + (width * 3) - 1), x = 0; x < width; x++) {
1579 *(xt--) = (unsigned char) xb;
1580 *(xt--) = (unsigned char) xg;
1581 *(xt--) = (unsigned char) xr;
1593 for (yt = ytable, y = 0; y < height; y++) {
1594 *(yt++) = (unsigned char) yr;
1595 *(yt++) = (unsigned char) yg;
1596 *(yt++) = (unsigned char) yb;
1603 // Combine tables to create gradient
1606 // normal cdgradient
1607 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1608 for (xt = xtable, x = 0; x < width; x++) {
1609 *(pr++) = *(xt++) + *(yt);
1610 *(pg++) = *(xt++) + *(yt + 1);
1611 *(pb++) = *(xt++) + *(yt + 2);
1615 // faked interlacing effect
1616 unsigned char channel, channel2;
1618 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1619 for (xt = xtable, x = 0; x < width; x++) {
1621 channel = *(xt++) + *(yt);
1622 channel2 = (channel >> 1) + (channel >> 2);
1623 if (channel2 > channel) channel2 = 0;
1626 channel = *(xt++) + *(yt + 1);
1627 channel2 = (channel >> 1) + (channel >> 2);
1628 if (channel2 > channel) channel2 = 0;
1631 channel = *(xt++) + *(yt + 2);
1632 channel2 = (channel >> 1) + (channel >> 2);
1633 if (channel2 > channel) channel2 = 0;
1636 channel = *(xt++) + *(yt);
1637 channel2 = channel + (channel >> 3);
1638 if (channel2 < channel) channel2 = ~0;
1641 channel = *(xt++) + *(yt + 1);
1642 channel2 = channel + (channel >> 3);
1643 if (channel2 < channel) channel2 = ~0;
1646 channel = *(xt++) + *(yt + 2);
1647 channel2 = channel + (channel >> 3);
1648 if (channel2 < channel) channel2 = ~0;