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, unsigned int w, unsigned 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::Bevel1) {
111 if (texture.texture() & BTexture::Raised) {
112 XDrawLine(display, pixmap, penshadow.gc(),
113 0, height - 1, width - 1, height - 1);
114 XDrawLine(display, pixmap, penshadow.gc(),
115 width - 1, height - 1, width - 1, 0);
117 XDrawLine(display, pixmap, penlight.gc(),
119 XDrawLine(display, pixmap, penlight.gc(),
120 0, height - 1, 0, 0);
121 } else if (texture.texture() & BTexture::Sunken) {
122 XDrawLine(display, pixmap, penlight.gc(),
123 0, height - 1, width - 1, height - 1);
124 XDrawLine(display, pixmap, penlight.gc(),
125 width - 1, height - 1, width - 1, 0);
127 XDrawLine(display, pixmap, penshadow.gc(),
129 XDrawLine(display, pixmap, penshadow.gc(),
130 0, height - 1, 0, 0);
132 } else if (texture.texture() & BTexture::Bevel2) {
133 if (texture.texture() & BTexture::Raised) {
134 XDrawLine(display, pixmap, penshadow.gc(),
135 1, height - 3, width - 3, height - 3);
136 XDrawLine(display, pixmap, penshadow.gc(),
137 width - 3, height - 3, width - 3, 1);
139 XDrawLine(display, pixmap, penlight.gc(),
141 XDrawLine(display, pixmap, penlight.gc(),
142 1, height - 3, 1, 1);
143 } else if (texture.texture() & BTexture::Sunken) {
144 XDrawLine(display, pixmap, penlight.gc(),
145 1, height - 3, width - 3, height - 3);
146 XDrawLine(display, pixmap, penlight.gc(),
147 width - 3, height - 3, width - 3, 1);
149 XDrawLine(display, pixmap, penshadow.gc(),
151 XDrawLine(display, pixmap, penshadow.gc(),
152 1, height - 3, 1, 1);
160 Pixmap BImage::render_gradient(const BTexture &texture) {
161 bool inverted = False;
163 interlaced = texture.texture() & BTexture::Interlaced;
165 if (texture.texture() & BTexture::Sunken) {
166 from = texture.colorTo();
167 to = texture.color();
169 if (! (texture.texture() & BTexture::Invert)) inverted = True;
171 from = texture.color();
172 to = texture.colorTo();
174 if (texture.texture() & BTexture::Invert) inverted = True;
177 control->getGradientBuffers(width, height, &xtable, &ytable);
179 if (texture.texture() & BTexture::Diagonal) dgradient();
180 else if (texture.texture() & BTexture::Elliptic) egradient();
181 else if (texture.texture() & BTexture::Horizontal) hgradient();
182 else if (texture.texture() & BTexture::Pyramid) pgradient();
183 else if (texture.texture() & BTexture::Rectangle) rgradient();
184 else if (texture.texture() & BTexture::Vertical) vgradient();
185 else if (texture.texture() & BTexture::CrossDiagonal) cdgradient();
186 else if (texture.texture() & BTexture::PipeCross) pcgradient();
188 if (texture.texture() & BTexture::Bevel1) bevel1();
189 else if (texture.texture() & BTexture::Bevel2) bevel2();
191 if (inverted) invert();
193 return renderPixmap();
198 static const unsigned char dither4[4][4] = {
207 * Helper function for TrueColorDither and renderXImage
209 * This handles the proper setting of the image data based on the image depth
210 * and the machine's byte ordering
213 void assignPixelData(unsigned int bit_depth, unsigned char **data,
214 unsigned long pixel) {
215 unsigned char *pixel_data = *data;
218 *pixel_data++ = pixel;
221 case 16: // 16bpp LSB
222 *pixel_data++ = pixel;
223 *pixel_data++ = pixel >> 8;
226 case 17: // 16bpp MSB
227 *pixel_data++ = pixel >> 8;
228 *pixel_data++ = pixel;
231 case 24: // 24bpp LSB
232 *pixel_data++ = pixel;
233 *pixel_data++ = pixel >> 8;
234 *pixel_data++ = pixel >> 16;
237 case 25: // 24bpp MSB
238 *pixel_data++ = pixel >> 16;
239 *pixel_data++ = pixel >> 8;
240 *pixel_data++ = pixel;
243 case 32: // 32bpp LSB
244 *pixel_data++ = pixel;
245 *pixel_data++ = pixel >> 8;
246 *pixel_data++ = pixel >> 16;
247 *pixel_data++ = pixel >> 24;
250 case 33: // 32bpp MSB
251 *pixel_data++ = pixel >> 24;
252 *pixel_data++ = pixel >> 16;
253 *pixel_data++ = pixel >> 8;
254 *pixel_data++ = pixel;
257 *data = pixel_data; // assign back so we don't lose our place
261 // algorithm: ordered dithering... many many thanks to rasterman
262 // (raster@rasterman.com) for telling me about this... portions of this
263 // code is based off of his code in Imlib
264 void BImage::TrueColorDither(unsigned int bit_depth, int bytes_per_line,
265 unsigned char *pixel_data) {
266 unsigned int x, y, dithx, dithy, r, g, b, er, eg, eb, offset;
267 unsigned char *ppixel_data = pixel_data;
270 for (y = 0, offset = 0; y < height; y++) {
273 for (x = 0; x < width; x++, offset++) {
279 er = r & (red_bits - 1);
280 eg = g & (green_bits - 1);
281 eb = b & (blue_bits - 1);
287 if ((dither4[dithy][dithx] < er) && (r < red_table[255])) r++;
288 if ((dither4[dithy][dithx] < eg) && (g < green_table[255])) g++;
289 if ((dither4[dithy][dithx] < eb) && (b < blue_table[255])) b++;
291 pixel = (r << red_offset) | (g << green_offset) | (b << blue_offset);
292 assignPixelData(bit_depth, &pixel_data, pixel);
295 pixel_data = (ppixel_data += bytes_per_line);
300 const static unsigned char dither8[8][8] = {
301 { 0, 32, 8, 40, 2, 34, 10, 42},
302 { 48, 16, 56, 24, 50, 18, 58, 26},
303 { 12, 44, 4, 36, 14, 46, 6, 38},
304 { 60, 28, 52, 20, 62, 30, 54, 22},
305 { 3, 35, 11, 43, 1, 33, 9, 41},
306 { 51, 19, 59, 27, 49, 17, 57, 25},
307 { 15, 47, 7, 39, 13, 45, 5, 37},
308 { 63, 31, 55, 23, 61, 29, 53, 21}
311 void BImage::OrderedPseudoColorDither(int bytes_per_line,
312 unsigned char *pixel_data) {
313 unsigned int x, y, dithx, dithy, r, g, b, er, eg, eb, offset;
315 unsigned char *ppixel_data = pixel_data;
317 for (y = 0, offset = 0; y < height; y++) {
320 for (x = 0; x < width; x++, offset++) {
327 er = r & (red_bits - 1);
328 eg = g & (green_bits - 1);
329 eb = b & (blue_bits - 1);
335 if ((dither8[dithy][dithx] < er) && (r < red_table[255])) r++;
336 if ((dither8[dithy][dithx] < eg) && (g < green_table[255])) g++;
337 if ((dither8[dithy][dithx] < eb) && (b < blue_table[255])) b++;
339 pixel = (r * cpccpc) + (g * cpc) + b;
340 *(pixel_data++) = colors[pixel].pixel;
343 pixel_data = (ppixel_data += bytes_per_line);
348 void BImage::PseudoColorDither(int bytes_per_line, unsigned char *pixel_data) {
350 *rerr = new short[width + 2],
351 *gerr = new short[width + 2],
352 *berr = new short[width + 2],
353 *nrerr = new short[width + 2],
354 *ngerr = new short[width + 2],
355 *nberr = new short[width + 2];
357 int rr, gg, bb, rer, ger, ber;
358 int dd = 255 / control->getColorsPerChannel();
359 unsigned int x, y, r, g, b, offset;
361 unsigned char *ppixel_data = pixel_data;
363 for (x = 0; x < width; x++) {
364 *(rerr + x) = *(red + x);
365 *(gerr + x) = *(green + x);
366 *(berr + x) = *(blue + x);
369 *(rerr + x) = *(gerr + x) = *(berr + x) = 0;
371 for (y = 0, offset = 0; y < height; y++) {
372 if (y < (height - 1)) {
373 int i = offset + width;
374 for (x = 0; x < width; x++, i++) {
375 *(nrerr + x) = *(red + i);
376 *(ngerr + x) = *(green + i);
377 *(nberr + x) = *(blue + i);
380 *(nrerr + x) = *(red + (--i));
381 *(ngerr + x) = *(green + i);
382 *(nberr + x) = *(blue + i);
385 for (x = 0; x < width; x++) {
390 if (rr > 255) rr = 255; else if (rr < 0) rr = 0;
391 if (gg > 255) gg = 255; else if (gg < 0) gg = 0;
392 if (bb > 255) bb = 255; else if (bb < 0) bb = 0;
398 rer = rerr[x] - r*dd;
399 ger = gerr[x] - g*dd;
400 ber = berr[x] - b*dd;
402 pixel = (r * cpccpc) + (g * cpc) + b;
403 *pixel_data++ = colors[pixel].pixel;
418 pixel_data = (ppixel_data += bytes_per_line);
441 XImage *BImage::renderXImage(void) {
443 XCreateImage(control->getBaseDisplay()->getXDisplay(),
444 control->getVisual(), control->getDepth(), ZPixmap, 0, 0,
445 width, height, 32, 0);
448 fprintf(stderr, i18n(ImageSet, ImageErrorCreatingXImage,
449 "BImage::renderXImage: error creating XImage\n"));
454 image->data = (char *) 0;
456 unsigned char *d = new unsigned char[image->bytes_per_line * (height + 1)];
458 unsigned int o = image->bits_per_pixel +
459 ((image->byte_order == MSBFirst) ? 1 : 0);
461 bool unsupported = False;
463 if (control->doDither() && width > 1 && height > 1) {
464 switch (control->getVisual()->c_class) {
466 TrueColorDither(o, image->bytes_per_line, d);
472 OrderedPseudoColorDither(image->bytes_per_line, d);
474 PseudoColorDither(image->bytes_per_line, d);
483 unsigned int x, y, r, g, b, offset;
484 unsigned char *pixel_data = d, *ppixel_data = d;
487 switch (control->getVisual()->c_class) {
490 for (y = 0, offset = 0; y < height; ++y) {
491 for (x = 0; x < width; ++x, ++offset) {
492 r = red_table[red[offset]];
493 g = green_table[green[offset]];
494 b = blue_table[blue[offset]];
496 pixel = (r * cpccpc) + (g * cpc) + b;
497 *pixel_data++ = colors[pixel].pixel;
500 pixel_data = (ppixel_data += image->bytes_per_line);
506 for (y = 0, offset = 0; y < height; y++) {
507 for (x = 0; x < width; x++, offset++) {
508 r = red_table[red[offset]];
509 g = green_table[green[offset]];
510 b = blue_table[blue[offset]];
512 pixel = (r << red_offset) | (g << green_offset) | (b << blue_offset);
513 assignPixelData(o, &pixel_data, pixel);
516 pixel_data = (ppixel_data += image->bytes_per_line);
523 for (y = 0, offset = 0; y < height; y++) {
524 for (x = 0; x < width; x++, offset++) {
525 r = *(red_table + *(red + offset));
526 g = *(green_table + *(green + offset));
527 b = *(blue_table + *(blue + offset));
529 g = ((r * 30) + (g * 59) + (b * 11)) / 100;
530 *pixel_data++ = colors[g].pixel;
533 pixel_data = (ppixel_data += image->bytes_per_line);
544 fprintf(stderr, i18n(ImageSet, ImageUnsupVisual,
545 "BImage::renderXImage: unsupported visual\n"));
547 XDestroyImage(image);
551 image->data = (char *) d;
557 Pixmap BImage::renderPixmap(void) {
559 XCreatePixmap(control->getBaseDisplay()->getXDisplay(),
560 control->getDrawable(), width, height, control->getDepth());
562 if (pixmap == None) {
563 fprintf(stderr, i18n(ImageSet, ImageErrorCreatingPixmap,
564 "BImage::renderPixmap: error creating pixmap\n"));
568 XImage *image = renderXImage();
571 XFreePixmap(control->getBaseDisplay()->getXDisplay(), pixmap);
576 XDestroyImage(image);
577 XFreePixmap(control->getBaseDisplay()->getXDisplay(), pixmap);
581 XPutImage(control->getBaseDisplay()->getXDisplay(), pixmap,
582 DefaultGC(control->getBaseDisplay()->getXDisplay(),
583 control->getScreenInfo()->getScreenNumber()),
584 image, 0, 0, 0, 0, width, height);
587 delete [] image->data;
591 XDestroyImage(image);
597 void BImage::bevel1(void) {
598 if (width > 2 && height > 2) {
599 unsigned char *pr = red, *pg = green, *pb = blue;
601 register unsigned char r, g, b, rr ,gg ,bb;
602 register unsigned int w = width, h = height - 1, wh = w * h;
620 rr = (r >> 2) + (r >> 1);
623 gg = (g >> 2) + (g >> 1);
626 bb = (b >> 2) + (b >> 1);
649 rr = (r >> 2) + (r >> 1);
652 gg = (g >> 2) + (g >> 1);
655 bb = (b >> 2) + (b >> 1);
686 rr = (r >> 2) + (r >> 1);
689 gg = (g >> 2) + (g >> 1);
692 bb = (b >> 2) + (b >> 1);
719 rr = (r >> 2) + (r >> 1);
722 gg = (g >> 2) + (g >> 1);
725 bb = (b >> 2) + (b >> 1);
735 void BImage::bevel2(void) {
736 if (width > 4 && height > 4) {
737 unsigned char r, g, b, rr ,gg ,bb, *pr = red + width + 1,
738 *pg = green + width + 1, *pb = blue + width + 1;
739 unsigned int w = width - 2, h = height - 1, wh = width * (height - 3);
757 rr = (r >> 2) + (r >> 1);
760 gg = (g >> 2) + (g >> 1);
763 bb = (b >> 2) + (b >> 1);
795 rr = (r >> 2) + (r >> 1);
798 gg = (g >> 2) + (g >> 1);
801 bb = (b >> 2) + (b >> 1);
814 void BImage::invert(void) {
815 register unsigned int i, j, wh = (width * height) - 1;
818 for (i = 0, j = wh; j > i; j--, i++) {
820 *(red + j) = *(red + i);
824 *(green + j) = *(green + i);
828 *(blue + j) = *(blue + i);
834 void BImage::dgradient(void) {
835 // diagonal gradient code was written by Mike Cole <mike@mydot.com>
836 // modified for interlacing by Brad Hughes
838 float drx, dgx, dbx, dry, dgy, dby, yr = 0.0, yg = 0.0, yb = 0.0,
839 xr = (float) from.red(),
840 xg = (float) from.green(),
841 xb = (float) from.blue();
842 unsigned char *pr = red, *pg = green, *pb = blue;
843 unsigned int w = width * 2, h = height * 2, *xt = xtable, *yt = ytable;
845 register unsigned int x, y;
847 dry = drx = (float) (to.red() - from.red());
848 dgy = dgx = (float) (to.green() - from.green());
849 dby = dbx = (float) (to.blue() - from.blue());
856 for (x = 0; x < width; x++) {
857 *(xt++) = (unsigned char) (xr);
858 *(xt++) = (unsigned char) (xg);
859 *(xt++) = (unsigned char) (xb);
871 for (y = 0; y < height; y++) {
872 *(yt++) = ((unsigned char) yr);
873 *(yt++) = ((unsigned char) yg);
874 *(yt++) = ((unsigned char) yb);
881 // Combine tables to create gradient
885 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
886 for (xt = xtable, x = 0; x < width; x++) {
887 *(pr++) = *(xt++) + *(yt);
888 *(pg++) = *(xt++) + *(yt + 1);
889 *(pb++) = *(xt++) + *(yt + 2);
893 // faked interlacing effect
894 unsigned char channel, channel2;
896 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
897 for (xt = xtable, x = 0; x < width; x++) {
899 channel = *(xt++) + *(yt);
900 channel2 = (channel >> 1) + (channel >> 2);
901 if (channel2 > channel) channel2 = 0;
904 channel = *(xt++) + *(yt + 1);
905 channel2 = (channel >> 1) + (channel >> 2);
906 if (channel2 > channel) channel2 = 0;
909 channel = *(xt++) + *(yt + 2);
910 channel2 = (channel >> 1) + (channel >> 2);
911 if (channel2 > channel) channel2 = 0;
914 channel = *(xt++) + *(yt);
915 channel2 = channel + (channel >> 3);
916 if (channel2 < channel) channel2 = ~0;
919 channel = *(xt++) + *(yt + 1);
920 channel2 = channel + (channel >> 3);
921 if (channel2 < channel) channel2 = ~0;
924 channel = *(xt++) + *(yt + 2);
925 channel2 = channel + (channel >> 3);
926 if (channel2 < channel) channel2 = ~0;
935 void BImage::hgradient(void) {
937 xr = (float) from.red(),
938 xg = (float) from.green(),
939 xb = (float) from.blue();
940 unsigned char *pr = red, *pg = green, *pb = blue;
942 register unsigned int x, y;
944 drx = (float) (to.red() - from.red());
945 dgx = (float) (to.green() - from.green());
946 dbx = (float) (to.blue() - from.blue());
952 if (interlaced && height > 2) {
953 // faked interlacing effect
954 unsigned char channel, channel2;
956 for (x = 0; x < width; x++, pr++, pg++, pb++) {
957 channel = (unsigned char) xr;
958 channel2 = (channel >> 1) + (channel >> 2);
959 if (channel2 > channel) channel2 = 0;
962 channel = (unsigned char) xg;
963 channel2 = (channel >> 1) + (channel >> 2);
964 if (channel2 > channel) channel2 = 0;
967 channel = (unsigned char) xb;
968 channel2 = (channel >> 1) + (channel >> 2);
969 if (channel2 > channel) channel2 = 0;
973 channel = (unsigned char) xr;
974 channel2 = channel + (channel >> 3);
975 if (channel2 < channel) channel2 = ~0;
976 *(pr + width) = channel2;
978 channel = (unsigned char) xg;
979 channel2 = channel + (channel >> 3);
980 if (channel2 < channel) channel2 = ~0;
981 *(pg + width) = channel2;
983 channel = (unsigned char) xb;
984 channel2 = channel + (channel >> 3);
985 if (channel2 < channel) channel2 = ~0;
986 *(pb + width) = channel2;
999 for (y = 2; y < height; y++, pr += width, pg += width, pb += width) {
1000 if (y & 1) offset = width; else offset = 0;
1002 memcpy(pr, (red + offset), width);
1003 memcpy(pg, (green + offset), width);
1004 memcpy(pb, (blue + offset), width);
1008 for (x = 0; x < width; x++) {
1009 *(pr++) = (unsigned char) (xr);
1010 *(pg++) = (unsigned char) (xg);
1011 *(pb++) = (unsigned char) (xb);
1018 for (y = 1; y < height; y++, pr += width, pg += width, pb += width) {
1019 memcpy(pr, red, width);
1020 memcpy(pg, green, width);
1021 memcpy(pb, blue, width);
1027 void BImage::vgradient(void) {
1028 float dry, dgy, dby,
1029 yr = (float) from.red(),
1030 yg = (float) from.green(),
1031 yb = (float) from.blue();
1032 unsigned char *pr = red, *pg = green, *pb = blue;
1034 register unsigned int y;
1036 dry = (float) (to.red() - from.red());
1037 dgy = (float) (to.green() - from.green());
1038 dby = (float) (to.blue() - from.blue());
1045 // faked interlacing effect
1046 unsigned char channel, channel2;
1048 for (y = 0; y < height; y++, pr += width, pg += width, pb += width) {
1050 channel = (unsigned char) yr;
1051 channel2 = (channel >> 1) + (channel >> 2);
1052 if (channel2 > channel) channel2 = 0;
1053 memset(pr, channel2, width);
1055 channel = (unsigned char) yg;
1056 channel2 = (channel >> 1) + (channel >> 2);
1057 if (channel2 > channel) channel2 = 0;
1058 memset(pg, channel2, width);
1060 channel = (unsigned char) yb;
1061 channel2 = (channel >> 1) + (channel >> 2);
1062 if (channel2 > channel) channel2 = 0;
1063 memset(pb, channel2, width);
1065 channel = (unsigned char) yr;
1066 channel2 = channel + (channel >> 3);
1067 if (channel2 < channel) channel2 = ~0;
1068 memset(pr, channel2, width);
1070 channel = (unsigned char) yg;
1071 channel2 = channel + (channel >> 3);
1072 if (channel2 < channel) channel2 = ~0;
1073 memset(pg, channel2, width);
1075 channel = (unsigned char) yb;
1076 channel2 = channel + (channel >> 3);
1077 if (channel2 < channel) channel2 = ~0;
1078 memset(pb, channel2, width);
1087 for (y = 0; y < height; y++, pr += width, pg += width, pb += width) {
1088 memset(pr, (unsigned char) yr, width);
1089 memset(pg, (unsigned char) yg, width);
1090 memset(pb, (unsigned char) yb, width);
1100 void BImage::pgradient(void) {
1101 // pyramid gradient - based on original dgradient, written by
1102 // Mosfet (mosfet@kde.org)
1103 // adapted from kde sources for Blackbox by Brad Hughes
1105 float yr, yg, yb, drx, dgx, dbx, dry, dgy, dby,
1107 int rsign, gsign, bsign;
1108 unsigned char *pr = red, *pg = green, *pb = blue;
1109 unsigned int tr = to.red(), tg = to.green(), tb = to.blue(),
1110 *xt = xtable, *yt = ytable;
1112 register unsigned int x, y;
1114 dry = drx = (float) (to.red() - from.red());
1115 dgy = dgx = (float) (to.green() - from.green());
1116 dby = dbx = (float) (to.blue() - from.blue());
1118 rsign = (drx < 0) ? -1 : 1;
1119 gsign = (dgx < 0) ? -1 : 1;
1120 bsign = (dbx < 0) ? -1 : 1;
1122 xr = yr = (drx / 2);
1123 xg = yg = (dgx / 2);
1124 xb = yb = (dbx / 2);
1131 for (x = 0; x < width; x++) {
1132 *(xt++) = (unsigned char) ((xr < 0) ? -xr : xr);
1133 *(xt++) = (unsigned char) ((xg < 0) ? -xg : xg);
1134 *(xt++) = (unsigned char) ((xb < 0) ? -xb : xb);
1146 for (y = 0; y < height; y++) {
1147 *(yt++) = ((unsigned char) ((yr < 0) ? -yr : yr));
1148 *(yt++) = ((unsigned char) ((yg < 0) ? -yg : yg));
1149 *(yt++) = ((unsigned char) ((yb < 0) ? -yb : yb));
1156 // Combine tables to create gradient
1160 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1161 for (xt = xtable, x = 0; x < width; x++) {
1162 *(pr++) = (unsigned char) (tr - (rsign * (*(xt++) + *(yt))));
1163 *(pg++) = (unsigned char) (tg - (gsign * (*(xt++) + *(yt + 1))));
1164 *(pb++) = (unsigned char) (tb - (bsign * (*(xt++) + *(yt + 2))));
1168 // faked interlacing effect
1169 unsigned char channel, channel2;
1171 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1172 for (xt = xtable, x = 0; x < width; x++) {
1174 channel = (unsigned char) (tr - (rsign * (*(xt++) + *(yt))));
1175 channel2 = (channel >> 1) + (channel >> 2);
1176 if (channel2 > channel) channel2 = 0;
1179 channel = (unsigned char) (tg - (gsign * (*(xt++) + *(yt + 1))));
1180 channel2 = (channel >> 1) + (channel >> 2);
1181 if (channel2 > channel) channel2 = 0;
1184 channel = (unsigned char) (tb - (bsign * (*(xt++) + *(yt + 2))));
1185 channel2 = (channel >> 1) + (channel >> 2);
1186 if (channel2 > channel) channel2 = 0;
1189 channel = (unsigned char) (tr - (rsign * (*(xt++) + *(yt))));
1190 channel2 = channel + (channel >> 3);
1191 if (channel2 < channel) channel2 = ~0;
1194 channel = (unsigned char) (tg - (gsign * (*(xt++) + *(yt + 1))));
1195 channel2 = channel + (channel >> 3);
1196 if (channel2 < channel) channel2 = ~0;
1199 channel = (unsigned char) (tb - (bsign * (*(xt++) + *(yt + 2))));
1200 channel2 = channel + (channel >> 3);
1201 if (channel2 < channel) channel2 = ~0;
1210 void BImage::rgradient(void) {
1211 // rectangle gradient - based on original dgradient, written by
1212 // Mosfet (mosfet@kde.org)
1213 // adapted from kde sources for Blackbox by Brad Hughes
1215 float drx, dgx, dbx, dry, dgy, dby, xr, xg, xb, yr, yg, yb;
1216 int rsign, gsign, bsign;
1217 unsigned char *pr = red, *pg = green, *pb = blue;
1218 unsigned int tr = to.red(), tg = to.green(), tb = to.blue(),
1219 *xt = xtable, *yt = ytable;
1221 register unsigned int x, y;
1223 dry = drx = (float) (to.red() - from.red());
1224 dgy = dgx = (float) (to.green() - from.green());
1225 dby = dbx = (float) (to.blue() - from.blue());
1227 rsign = (drx < 0) ? -2 : 2;
1228 gsign = (dgx < 0) ? -2 : 2;
1229 bsign = (dbx < 0) ? -2 : 2;
1231 xr = yr = (drx / 2);
1232 xg = yg = (dgx / 2);
1233 xb = yb = (dbx / 2);
1240 for (x = 0; x < width; x++) {
1241 *(xt++) = (unsigned char) ((xr < 0) ? -xr : xr);
1242 *(xt++) = (unsigned char) ((xg < 0) ? -xg : xg);
1243 *(xt++) = (unsigned char) ((xb < 0) ? -xb : xb);
1255 for (y = 0; y < height; y++) {
1256 *(yt++) = ((unsigned char) ((yr < 0) ? -yr : yr));
1257 *(yt++) = ((unsigned char) ((yg < 0) ? -yg : yg));
1258 *(yt++) = ((unsigned char) ((yb < 0) ? -yb : yb));
1265 // Combine tables to create gradient
1269 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1270 for (xt = xtable, x = 0; x < width; x++) {
1271 *(pr++) = (unsigned char) (tr - (rsign * max(*(xt++), *(yt))));
1272 *(pg++) = (unsigned char) (tg - (gsign * max(*(xt++), *(yt + 1))));
1273 *(pb++) = (unsigned char) (tb - (bsign * max(*(xt++), *(yt + 2))));
1277 // faked interlacing effect
1278 unsigned char channel, channel2;
1280 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1281 for (xt = xtable, x = 0; x < width; x++) {
1283 channel = (unsigned char) (tr - (rsign * max(*(xt++), *(yt))));
1284 channel2 = (channel >> 1) + (channel >> 2);
1285 if (channel2 > channel) channel2 = 0;
1288 channel = (unsigned char) (tg - (gsign * max(*(xt++), *(yt + 1))));
1289 channel2 = (channel >> 1) + (channel >> 2);
1290 if (channel2 > channel) channel2 = 0;
1293 channel = (unsigned char) (tb - (bsign * max(*(xt++), *(yt + 2))));
1294 channel2 = (channel >> 1) + (channel >> 2);
1295 if (channel2 > channel) channel2 = 0;
1298 channel = (unsigned char) (tr - (rsign * max(*(xt++), *(yt))));
1299 channel2 = channel + (channel >> 3);
1300 if (channel2 < channel) channel2 = ~0;
1303 channel = (unsigned char) (tg - (gsign * max(*(xt++), *(yt + 1))));
1304 channel2 = channel + (channel >> 3);
1305 if (channel2 < channel) channel2 = ~0;
1308 channel = (unsigned char) (tb - (bsign * max(*(xt++), *(yt + 2))));
1309 channel2 = channel + (channel >> 3);
1310 if (channel2 < channel) channel2 = ~0;
1319 void BImage::egradient(void) {
1320 // elliptic gradient - based on original dgradient, written by
1321 // Mosfet (mosfet@kde.org)
1322 // adapted from kde sources for Blackbox by Brad Hughes
1324 float drx, dgx, dbx, dry, dgy, dby, yr, yg, yb, xr, xg, xb;
1325 int rsign, gsign, bsign;
1326 unsigned char *pr = red, *pg = green, *pb = blue;
1327 unsigned int *xt = xtable, *yt = ytable,
1328 tr = (unsigned long) to.red(),
1329 tg = (unsigned long) to.green(),
1330 tb = (unsigned long) to.blue();
1332 register unsigned int x, y;
1334 dry = drx = (float) (to.red() - from.red());
1335 dgy = dgx = (float) (to.green() - from.green());
1336 dby = dbx = (float) (to.blue() - from.blue());
1338 rsign = (drx < 0) ? -1 : 1;
1339 gsign = (dgx < 0) ? -1 : 1;
1340 bsign = (dbx < 0) ? -1 : 1;
1342 xr = yr = (drx / 2);
1343 xg = yg = (dgx / 2);
1344 xb = yb = (dbx / 2);
1351 for (x = 0; x < width; x++) {
1352 *(xt++) = (unsigned long) (xr * xr);
1353 *(xt++) = (unsigned long) (xg * xg);
1354 *(xt++) = (unsigned long) (xb * xb);
1366 for (y = 0; y < height; y++) {
1367 *(yt++) = (unsigned long) (yr * yr);
1368 *(yt++) = (unsigned long) (yg * yg);
1369 *(yt++) = (unsigned long) (yb * yb);
1376 // Combine tables to create gradient
1380 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1381 for (xt = xtable, x = 0; x < width; x++) {
1382 *(pr++) = (unsigned char)
1383 (tr - (rsign * control->getSqrt(*(xt++) + *(yt))));
1384 *(pg++) = (unsigned char)
1385 (tg - (gsign * control->getSqrt(*(xt++) + *(yt + 1))));
1386 *(pb++) = (unsigned char)
1387 (tb - (bsign * control->getSqrt(*(xt++) + *(yt + 2))));
1391 // faked interlacing effect
1392 unsigned char channel, channel2;
1394 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1395 for (xt = xtable, x = 0; x < width; x++) {
1397 channel = (unsigned char)
1398 (tr - (rsign * control->getSqrt(*(xt++) + *(yt))));
1399 channel2 = (channel >> 1) + (channel >> 2);
1400 if (channel2 > channel) channel2 = 0;
1403 channel = (unsigned char)
1404 (tg - (gsign * control->getSqrt(*(xt++) + *(yt + 1))));
1405 channel2 = (channel >> 1) + (channel >> 2);
1406 if (channel2 > channel) channel2 = 0;
1409 channel = (unsigned char)
1410 (tb - (bsign * control->getSqrt(*(xt++) + *(yt + 2))));
1411 channel2 = (channel >> 1) + (channel >> 2);
1412 if (channel2 > channel) channel2 = 0;
1415 channel = (unsigned char)
1416 (tr - (rsign * control->getSqrt(*(xt++) + *(yt))));
1417 channel2 = channel + (channel >> 3);
1418 if (channel2 < channel) channel2 = ~0;
1421 channel = (unsigned char)
1422 (tg - (gsign * control->getSqrt(*(xt++) + *(yt + 1))));
1423 channel2 = channel + (channel >> 3);
1424 if (channel2 < channel) channel2 = ~0;
1427 channel = (unsigned char)
1428 (tb - (bsign * control->getSqrt(*(xt++) + *(yt + 2))));
1429 channel2 = channel + (channel >> 3);
1430 if (channel2 < channel) channel2 = ~0;
1439 void BImage::pcgradient(void) {
1440 // pipe cross gradient - based on original dgradient, written by
1441 // Mosfet (mosfet@kde.org)
1442 // adapted from kde sources for Blackbox by Brad Hughes
1444 float drx, dgx, dbx, dry, dgy, dby, xr, xg, xb, yr, yg, yb;
1445 int rsign, gsign, bsign;
1446 unsigned char *pr = red, *pg = green, *pb = blue;
1447 unsigned int *xt = xtable, *yt = ytable,
1452 register unsigned int x, y;
1454 dry = drx = (float) (to.red() - from.red());
1455 dgy = dgx = (float) (to.green() - from.green());
1456 dby = dbx = (float) (to.blue() - from.blue());
1458 rsign = (drx < 0) ? -2 : 2;
1459 gsign = (dgx < 0) ? -2 : 2;
1460 bsign = (dbx < 0) ? -2 : 2;
1462 xr = yr = (drx / 2);
1463 xg = yg = (dgx / 2);
1464 xb = yb = (dbx / 2);
1471 for (x = 0; x < width; x++) {
1472 *(xt++) = (unsigned char) ((xr < 0) ? -xr : xr);
1473 *(xt++) = (unsigned char) ((xg < 0) ? -xg : xg);
1474 *(xt++) = (unsigned char) ((xb < 0) ? -xb : xb);
1486 for (y = 0; y < height; y++) {
1487 *(yt++) = ((unsigned char) ((yr < 0) ? -yr : yr));
1488 *(yt++) = ((unsigned char) ((yg < 0) ? -yg : yg));
1489 *(yt++) = ((unsigned char) ((yb < 0) ? -yb : yb));
1496 // Combine tables to create gradient
1499 // normal pcgradient
1500 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1501 for (xt = xtable, x = 0; x < width; x++) {
1502 *(pr++) = (unsigned char) (tr - (rsign * min(*(xt++), *(yt))));
1503 *(pg++) = (unsigned char) (tg - (gsign * min(*(xt++), *(yt + 1))));
1504 *(pb++) = (unsigned char) (tb - (bsign * min(*(xt++), *(yt + 2))));
1508 // faked interlacing effect
1509 unsigned char channel, channel2;
1511 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1512 for (xt = xtable, x = 0; x < width; x++) {
1514 channel = (unsigned char) (tr - (rsign * min(*(xt++), *(yt))));
1515 channel2 = (channel >> 1) + (channel >> 2);
1516 if (channel2 > channel) channel2 = 0;
1519 channel = (unsigned char) (tg - (bsign * min(*(xt++), *(yt + 1))));
1520 channel2 = (channel >> 1) + (channel >> 2);
1521 if (channel2 > channel) channel2 = 0;
1524 channel = (unsigned char) (tb - (gsign * min(*(xt++), *(yt + 2))));
1525 channel2 = (channel >> 1) + (channel >> 2);
1526 if (channel2 > channel) channel2 = 0;
1529 channel = (unsigned char) (tr - (rsign * min(*(xt++), *(yt))));
1530 channel2 = channel + (channel >> 3);
1531 if (channel2 < channel) channel2 = ~0;
1534 channel = (unsigned char) (tg - (gsign * min(*(xt++), *(yt + 1))));
1535 channel2 = channel + (channel >> 3);
1536 if (channel2 < channel) channel2 = ~0;
1539 channel = (unsigned char) (tb - (bsign * min(*(xt++), *(yt + 2))));
1540 channel2 = channel + (channel >> 3);
1541 if (channel2 < channel) channel2 = ~0;
1550 void BImage::cdgradient(void) {
1551 // cross diagonal gradient - based on original dgradient, written by
1552 // Mosfet (mosfet@kde.org)
1553 // adapted from kde sources for Blackbox by Brad Hughes
1555 float drx, dgx, dbx, dry, dgy, dby, yr = 0.0, yg = 0.0, yb = 0.0,
1556 xr = (float) from.red(),
1557 xg = (float) from.green(),
1558 xb = (float) from.blue();
1559 unsigned char *pr = red, *pg = green, *pb = blue;
1560 unsigned int w = width * 2, h = height * 2, *xt, *yt;
1562 register unsigned int x, y;
1564 dry = drx = (float) (to.red() - from.red());
1565 dgy = dgx = (float) (to.green() - from.green());
1566 dby = dbx = (float) (to.blue() - from.blue());
1573 for (xt = (xtable + (width * 3) - 1), x = 0; x < width; x++) {
1574 *(xt--) = (unsigned char) xb;
1575 *(xt--) = (unsigned char) xg;
1576 *(xt--) = (unsigned char) xr;
1588 for (yt = ytable, y = 0; y < height; y++) {
1589 *(yt++) = (unsigned char) yr;
1590 *(yt++) = (unsigned char) yg;
1591 *(yt++) = (unsigned char) yb;
1598 // Combine tables to create gradient
1601 // normal cdgradient
1602 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1603 for (xt = xtable, x = 0; x < width; x++) {
1604 *(pr++) = *(xt++) + *(yt);
1605 *(pg++) = *(xt++) + *(yt + 1);
1606 *(pb++) = *(xt++) + *(yt + 2);
1610 // faked interlacing effect
1611 unsigned char channel, channel2;
1613 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1614 for (xt = xtable, x = 0; x < width; x++) {
1616 channel = *(xt++) + *(yt);
1617 channel2 = (channel >> 1) + (channel >> 2);
1618 if (channel2 > channel) channel2 = 0;
1621 channel = *(xt++) + *(yt + 1);
1622 channel2 = (channel >> 1) + (channel >> 2);
1623 if (channel2 > channel) channel2 = 0;
1626 channel = *(xt++) + *(yt + 2);
1627 channel2 = (channel >> 1) + (channel >> 2);
1628 if (channel2 > channel) channel2 = 0;
1631 channel = *(xt++) + *(yt);
1632 channel2 = channel + (channel >> 3);
1633 if (channel2 < channel) channel2 = ~0;
1636 channel = *(xt++) + *(yt + 1);
1637 channel2 = channel + (channel >> 3);
1638 if (channel2 < channel) channel2 = ~0;
1641 channel = *(xt++) + *(yt + 2);
1642 channel2 = channel + (channel >> 3);
1643 if (channel2 < channel) channel2 = ~0;