-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
-
-#ifdef HAVE_CONFIG_H
-# include "../config.h"
-#endif // HAVE_CONFIG_H
-
-#ifdef HAVE_STDIO_H
-# include <stdio.h>
-#endif // HAVE_STDIO_H
-
-#include <algorithm>
-using std::max;
-using std::min;
-
-#include "display.hh"
-#include "gccache.hh"
-#include "image.hh"
-#include "texture.hh"
-
-namespace otk {
-
-Image::Image(ImageControl *c, int w, int h) {
- control = c;
-
- width = (w > 0) ? w : 1;
- height = (h > 0) ? h : 1;
-
- red = new unsigned char[width * height];
- green = new unsigned char[width * height];
- blue = new unsigned char[width * height];
-
- xtable = ytable = (unsigned int *) 0;
-
- cpc = control->getColorsPerChannel();
- cpccpc = cpc * cpc;
-
- control->getColorTables(&red_table, &green_table, &blue_table,
- &red_offset, &green_offset, &blue_offset,
- &red_bits, &green_bits, &blue_bits);
-
- if (control->getVisual()->c_class != TrueColor)
- control->getXColorTable(&colors, &ncolors);
-}
-
-
-Image::~Image(void) {
- delete [] red;
- delete [] green;
- delete [] blue;
-}
-
-
-Pixmap Image::render(const Texture &texture) {
- if (texture.texture() & Texture::Parent_Relative)
- return ParentRelative;
- else if (texture.texture() & Texture::Solid)
- return render_solid(texture);
- else if (texture.texture() & Texture::Gradient)
- return render_gradient(texture);
- return None;
-}
-
-
-Pixmap Image::render_solid(const Texture &texture) {
- Pixmap pixmap = XCreatePixmap(**display, control->getDrawable(), width,
- height, control->getDepth());
- if (pixmap == None) {
- fprintf(stderr, "Image::render_solid: error creating pixmap\n");
- return None;
- }
-
- Pen pen(texture.color());
- Pen penlight(texture.lightColor());
- Pen penshadow(texture.shadowColor());
-
- XFillRectangle(**display, pixmap, pen.gc(), 0, 0, width, height);
-
- if (texture.texture() & Texture::Interlaced) {
- Pen peninterlace(texture.colorTo());
- for (unsigned int i = 0; i < height; i += 2)
- XDrawLine(**display, pixmap, peninterlace.gc(), 0, i, width, i);
- }
-
- int left = 0, top = 0, right = width - 1, bottom = height - 1;
-
- if (texture.texture() & Texture::Border) {
- Pen penborder(texture.borderColor());
- XDrawRectangle(**display, pixmap, penborder.gc(),
- left, top, right, bottom);
- }
-
- if (texture.texture() & Texture::Bevel1) {
- if (texture.texture() & Texture::Raised) {
- XDrawLine(**display, pixmap, penshadow.gc(),
- left, bottom, right, bottom);
- XDrawLine(**display, pixmap, penshadow.gc(),
- right, bottom, right, top);
-
- XDrawLine(**display, pixmap, penlight.gc(),
- left, top, right, top);
- XDrawLine(**display, pixmap, penlight.gc(),
- left, bottom, left, top);
- } else if (texture.texture() & Texture::Sunken) {
- XDrawLine(**display, pixmap, penlight.gc(),
- left, bottom, right, bottom);
- XDrawLine(**display, pixmap, penlight.gc(),
- right, bottom, right, top);
-
- XDrawLine(**display, pixmap, penshadow.gc(),
- left, top, right, top);
- XDrawLine(**display, pixmap, penshadow.gc(),
- left, bottom, left, top);
- }
- } else if (texture.texture() & Texture::Bevel2) {
- if (texture.texture() & Texture::Raised) {
- XDrawLine(**display, pixmap, penshadow.gc(),
- left + 1, bottom - 2, right - 2, bottom - 2);
- XDrawLine(**display, pixmap, penshadow.gc(),
- right - 2, bottom - 2, right - 2, top + 1);
-
- XDrawLine(**display, pixmap, penlight.gc(),
- left + 1, top + 1, right - 2, top + 1);
- XDrawLine(**display, pixmap, penlight.gc(),
- left + 1, bottom - 2, left + 1, top + 1);
- } else if (texture.texture() & Texture::Sunken) {
- XDrawLine(**display, pixmap, penlight.gc(),
- left + 1, bottom - 2, right - 2, bottom - 2);
- XDrawLine(**display, pixmap, penlight.gc(),
- right - 2, bottom - 2, right - 2, top + 1);
-
- XDrawLine(**display, pixmap, penshadow.gc(),
- left + 1, top + 1, right - 2, top + 1);
- XDrawLine(**display, pixmap, penshadow.gc(),
- left + 1, bottom - 2, left + 1, top + 1);
- }
- }
-
- return pixmap;
-}
-
-
-Pixmap Image::render_gradient(const Texture &texture) {
- bool inverted = False;
-
- interlaced = texture.texture() & Texture::Interlaced;
-
- if (texture.texture() & Texture::Sunken) {
- from = texture.colorTo();
- to = texture.color();
-
- if (! (texture.texture() & Texture::Invert)) inverted = True;
- } else {
- from = texture.color();
- to = texture.colorTo();
-
- if (texture.texture() & Texture::Invert) inverted = True;
- }
-
- control->getGradientBuffers(width, height, &xtable, &ytable);
-
- if (texture.texture() & Texture::Diagonal) dgradient();
- else if (texture.texture() & Texture::Elliptic) egradient();
- else if (texture.texture() & Texture::Horizontal) hgradient();
- else if (texture.texture() & Texture::Pyramid) pgradient();
- else if (texture.texture() & Texture::Rectangle) rgradient();
- else if (texture.texture() & Texture::Vertical) vgradient();
- else if (texture.texture() & Texture::CrossDiagonal) cdgradient();
- else if (texture.texture() & Texture::PipeCross) pcgradient();
-
- if (texture.texture() & Texture::Bevel1) bevel1();
- else if (texture.texture() & Texture::Bevel2) bevel2();
-
- if (texture.texture() & Texture::Border) border(texture);
-
- if (inverted) invert();
-
- return renderPixmap();
-
-}
-
-
-static const unsigned char dither4[4][4] = {
- {0, 4, 1, 5},
- {6, 2, 7, 3},
- {1, 5, 0, 4},
- {7, 3, 6, 2}
-};
-
-
-/*
- * Helper function for TrueColorDither and renderXImage
- *
- * This handles the proper setting of the image data based on the image depth
- * and the machine's byte ordering
- */
-static inline
-void assignPixelData(unsigned int bit_depth, unsigned char **data,
- unsigned long pixel) {
- unsigned char *pixel_data = *data;
- switch (bit_depth) {
- case 8: // 8bpp
- *pixel_data++ = pixel;
- break;
-
- case 16: // 16bpp LSB
- *pixel_data++ = pixel;
- *pixel_data++ = pixel >> 8;
- break;
-
- case 17: // 16bpp MSB
- *pixel_data++ = pixel >> 8;
- *pixel_data++ = pixel;
- break;
-
- case 24: // 24bpp LSB
- *pixel_data++ = pixel;
- *pixel_data++ = pixel >> 8;
- *pixel_data++ = pixel >> 16;
- break;
-
- case 25: // 24bpp MSB
- *pixel_data++ = pixel >> 16;
- *pixel_data++ = pixel >> 8;
- *pixel_data++ = pixel;
- break;
-
- case 32: // 32bpp LSB
- *pixel_data++ = pixel;
- *pixel_data++ = pixel >> 8;
- *pixel_data++ = pixel >> 16;
- *pixel_data++ = pixel >> 24;
- break;
-
- case 33: // 32bpp MSB
- *pixel_data++ = pixel >> 24;
- *pixel_data++ = pixel >> 16;
- *pixel_data++ = pixel >> 8;
- *pixel_data++ = pixel;
- break;
- }
- *data = pixel_data; // assign back so we don't lose our place
-}
-
-
-// algorithm: ordered dithering... many many thanks to rasterman
-// (raster@rasterman.com) for telling me about this... portions of this
-// code is based off of his code in Imlib
-void Image::TrueColorDither(unsigned int bit_depth, int bytes_per_line,
- unsigned char *pixel_data) {
- unsigned int x, y, dithx, dithy, r, g, b, er, eg, eb, offset;
- unsigned char *ppixel_data = pixel_data;
- unsigned long pixel;
-
- for (y = 0, offset = 0; y < height; y++) {
- dithy = y & 0x3;
-
- for (x = 0; x < width; x++, offset++) {
- dithx = x & 0x3;
- r = red[offset];
- g = green[offset];
- b = blue[offset];
-
- er = r & (red_bits - 1);
- eg = g & (green_bits - 1);
- eb = b & (blue_bits - 1);
-
- r = red_table[r];
- g = green_table[g];
- b = blue_table[b];
-
- if ((dither4[dithy][dithx] < er) && (r < red_table[255])) r++;
- if ((dither4[dithy][dithx] < eg) && (g < green_table[255])) g++;
- if ((dither4[dithy][dithx] < eb) && (b < blue_table[255])) b++;
-
- pixel = (r << red_offset) | (g << green_offset) | (b << blue_offset);
- assignPixelData(bit_depth, &pixel_data, pixel);
- }
-
- pixel_data = (ppixel_data += bytes_per_line);
- }
-}
-
-#ifdef ORDEREDPSEUDO
-const static unsigned char dither8[8][8] = {
- { 0, 32, 8, 40, 2, 34, 10, 42},
- { 48, 16, 56, 24, 50, 18, 58, 26},
- { 12, 44, 4, 36, 14, 46, 6, 38},
- { 60, 28, 52, 20, 62, 30, 54, 22},
- { 3, 35, 11, 43, 1, 33, 9, 41},
- { 51, 19, 59, 27, 49, 17, 57, 25},
- { 15, 47, 7, 39, 13, 45, 5, 37},
- { 63, 31, 55, 23, 61, 29, 53, 21}
-};
-
-void Image::OrderedPseudoColorDither(int bytes_per_line,
- unsigned char *pixel_data) {
- unsigned int x, y, dithx, dithy, r, g, b, er, eg, eb, offset;
- unsigned long pixel;
- unsigned char *ppixel_data = pixel_data;
-
- for (y = 0, offset = 0; y < height; y++) {
- dithy = y & 7;
-
- for (x = 0; x < width; x++, offset++) {
- dithx = x & 7;
-
- r = red[offset];
- g = green[offset];
- b = blue[offset];
-
- er = r & (red_bits - 1);
- eg = g & (green_bits - 1);
- eb = b & (blue_bits - 1);
-
- r = red_table[r];
- g = green_table[g];
- b = blue_table[b];
-
- if ((dither8[dithy][dithx] < er) && (r < red_table[255])) r++;
- if ((dither8[dithy][dithx] < eg) && (g < green_table[255])) g++;
- if ((dither8[dithy][dithx] < eb) && (b < blue_table[255])) b++;
-
- pixel = (r * cpccpc) + (g * cpc) + b;
- *(pixel_data++) = colors[pixel].pixel;
- }
-
- pixel_data = (ppixel_data += bytes_per_line);
- }
-}
-#endif
-
-void Image::PseudoColorDither(int bytes_per_line, unsigned char *pixel_data) {
- short *terr,
- *rerr = new short[width + 2],
- *gerr = new short[width + 2],
- *berr = new short[width + 2],
- *nrerr = new short[width + 2],
- *ngerr = new short[width + 2],
- *nberr = new short[width + 2];
-
- int rr, gg, bb, rer, ger, ber;
- int dd = 255 / control->getColorsPerChannel();
- unsigned int x, y, r, g, b, offset;
- unsigned long pixel;
- unsigned char *ppixel_data = pixel_data;
-
- for (x = 0; x < width; x++) {
- *(rerr + x) = *(red + x);
- *(gerr + x) = *(green + x);
- *(berr + x) = *(blue + x);
- }
-
- *(rerr + x) = *(gerr + x) = *(berr + x) = 0;
-
- for (y = 0, offset = 0; y < height; y++) {
- if (y < (height - 1)) {
- int i = offset + width;
- for (x = 0; x < width; x++, i++) {
- *(nrerr + x) = *(red + i);
- *(ngerr + x) = *(green + i);
- *(nberr + x) = *(blue + i);
- }
-
- *(nrerr + x) = *(red + (--i));
- *(ngerr + x) = *(green + i);
- *(nberr + x) = *(blue + i);
- }
-
- for (x = 0; x < width; x++) {
- rr = rerr[x];
- gg = gerr[x];
- bb = berr[x];
-
- if (rr > 255) rr = 255; else if (rr < 0) rr = 0;
- if (gg > 255) gg = 255; else if (gg < 0) gg = 0;
- if (bb > 255) bb = 255; else if (bb < 0) bb = 0;
-
- r = red_table[rr];
- g = green_table[gg];
- b = blue_table[bb];
-
- rer = rerr[x] - r*dd;
- ger = gerr[x] - g*dd;
- ber = berr[x] - b*dd;
-
- pixel = (r * cpccpc) + (g * cpc) + b;
- *pixel_data++ = colors[pixel].pixel;
-
- r = rer >> 1;
- g = ger >> 1;
- b = ber >> 1;
- rerr[x+1] += r;
- gerr[x+1] += g;
- berr[x+1] += b;
- nrerr[x] += r;
- ngerr[x] += g;
- nberr[x] += b;
- }
-
- offset += width;
-
- pixel_data = (ppixel_data += bytes_per_line);
-
- terr = rerr;
- rerr = nrerr;
- nrerr = terr;
-
- terr = gerr;
- gerr = ngerr;
- ngerr = terr;
-
- terr = berr;
- berr = nberr;
- nberr = terr;
- }
-
- delete [] rerr;
- delete [] gerr;
- delete [] berr;
- delete [] nrerr;
- delete [] ngerr;
- delete [] nberr;
-}
-
-XImage *Image::renderXImage(void) {
- XImage *image =
- XCreateImage(**display, control->getVisual(), control->getDepth(),
- ZPixmap, 0, 0,width, height, 32, 0);
-
- if (! image) {
- fprintf(stderr, "Image::renderXImage: error creating XImage\n");
- return (XImage *) 0;
- }
-
- // insurance policy
- image->data = (char *) 0;
-
- unsigned char *d = new unsigned char[image->bytes_per_line * (height + 1)];
-
- unsigned int o = image->bits_per_pixel +
- ((image->byte_order == MSBFirst) ? 1 : 0);
-
- bool unsupported = False;
-
- if (control->doDither() && width > 1 && height > 1) {
- switch (control->getVisual()->c_class) {
- case TrueColor:
- TrueColorDither(o, image->bytes_per_line, d);
- break;
-
- case StaticColor:
- case PseudoColor: {
-#ifdef ORDEREDPSEUDO
- OrderedPseudoColorDither(image->bytes_per_line, d);
-#else
- PseudoColorDither(image->bytes_per_line, d);
-#endif
- break;
- }
-
- default:
- unsupported = True;
- }
- } else {
- unsigned int x, y, r, g, b, offset;
- unsigned char *pixel_data = d, *ppixel_data = d;
- unsigned long pixel;
-
- switch (control->getVisual()->c_class) {
- case StaticColor:
- case PseudoColor:
- for (y = 0, offset = 0; y < height; ++y) {
- for (x = 0; x < width; ++x, ++offset) {
- r = red_table[red[offset]];
- g = green_table[green[offset]];
- b = blue_table[blue[offset]];
-
- pixel = (r * cpccpc) + (g * cpc) + b;
- *pixel_data++ = colors[pixel].pixel;
- }
-
- pixel_data = (ppixel_data += image->bytes_per_line);
- }
-
- break;
-
- case TrueColor:
- for (y = 0, offset = 0; y < height; y++) {
- for (x = 0; x < width; x++, offset++) {
- r = red_table[red[offset]];
- g = green_table[green[offset]];
- b = blue_table[blue[offset]];
-
- pixel = (r << red_offset) | (g << green_offset) | (b << blue_offset);
- assignPixelData(o, &pixel_data, pixel);
- }
-
- pixel_data = (ppixel_data += image->bytes_per_line);
- }
-
- break;
-
- case StaticGray:
- case GrayScale:
- for (y = 0, offset = 0; y < height; y++) {
- for (x = 0; x < width; x++, offset++) {
- r = *(red_table + *(red + offset));
- g = *(green_table + *(green + offset));
- b = *(blue_table + *(blue + offset));
-
- g = ((r * 30) + (g * 59) + (b * 11)) / 100;
- *pixel_data++ = colors[g].pixel;
- }
-
- pixel_data = (ppixel_data += image->bytes_per_line);
- }
-
- break;
-
- default:
- unsupported = True;
- }
- }
-
- if (unsupported) {
- fprintf(stderr, "Image::renderXImage: unsupported visual\n");
- delete [] d;
- XDestroyImage(image);
- return (XImage *) 0;
- }
-
- image->data = (char *) d;
-
- return image;
-}
-
-
-Pixmap Image::renderPixmap(void) {
- Pixmap pixmap =
- XCreatePixmap(**display, control->getDrawable(), width, height,
- control->getDepth());
-
- if (pixmap == None) {
- fprintf(stderr, "Image::renderPixmap: error creating pixmap\n");
- return None;
- }
-
- XImage *image = renderXImage();
-
- if (! image) {
- XFreePixmap(**display, pixmap);
- return None;
- }
-
- if (! image->data) {
- XDestroyImage(image);
- XFreePixmap(**display, pixmap);
- return None;
- }
-
- XPutImage(**display, pixmap,
- DefaultGC(**display, control->getScreenInfo()->screen()),
- image, 0, 0, 0, 0, width, height);
-
- if (image->data) {
- delete [] image->data;
- image->data = NULL;
- }
-
- XDestroyImage(image);
-
- return pixmap;
-}
-
-
-void Image::bevel1(void) {
- if (width > 2 && height > 2) {
- unsigned char *pr = red, *pg = green, *pb = blue;
-
- register unsigned char r, g, b, rr ,gg ,bb;
- register unsigned int w = width, h = height - 1, wh = w * h;
-
- while (--w) {
- r = *pr;
- rr = r + (r >> 1);
- if (rr < r) rr = ~0;
- g = *pg;
- gg = g + (g >> 1);
- if (gg < g) gg = ~0;
- b = *pb;
- bb = b + (b >> 1);
- if (bb < b) bb = ~0;
-
- *pr = rr;
- *pg = gg;
- *pb = bb;
-
- r = *(pr + wh);
- rr = (r >> 2) + (r >> 1);
- if (rr > r) rr = 0;
- g = *(pg + wh);
- gg = (g >> 2) + (g >> 1);
- if (gg > g) gg = 0;
- b = *(pb + wh);
- bb = (b >> 2) + (b >> 1);
- if (bb > b) bb = 0;
-
- *((pr++) + wh) = rr;
- *((pg++) + wh) = gg;
- *((pb++) + wh) = bb;
- }
-
- r = *pr;
- rr = r + (r >> 1);
- if (rr < r) rr = ~0;
- g = *pg;
- gg = g + (g >> 1);
- if (gg < g) gg = ~0;
- b = *pb;
- bb = b + (b >> 1);
- if (bb < b) bb = ~0;
-
- *pr = rr;
- *pg = gg;
- *pb = bb;
-
- r = *(pr + wh);
- rr = (r >> 2) + (r >> 1);
- if (rr > r) rr = 0;
- g = *(pg + wh);
- gg = (g >> 2) + (g >> 1);
- if (gg > g) gg = 0;
- b = *(pb + wh);
- bb = (b >> 2) + (b >> 1);
- if (bb > b) bb = 0;
-
- *(pr + wh) = rr;
- *(pg + wh) = gg;
- *(pb + wh) = bb;
-
- pr = red + width;
- pg = green + width;
- pb = blue + width;
-
- while (--h) {
- r = *pr;
- rr = r + (r >> 1);
- if (rr < r) rr = ~0;
- g = *pg;
- gg = g + (g >> 1);
- if (gg < g) gg = ~0;
- b = *pb;
- bb = b + (b >> 1);
- if (bb < b) bb = ~0;
-
- *pr = rr;
- *pg = gg;
- *pb = bb;
-
- pr += width - 1;
- pg += width - 1;
- pb += width - 1;
-
- r = *pr;
- rr = (r >> 2) + (r >> 1);
- if (rr > r) rr = 0;
- g = *pg;
- gg = (g >> 2) + (g >> 1);
- if (gg > g) gg = 0;
- b = *pb;
- bb = (b >> 2) + (b >> 1);
- if (bb > b) bb = 0;
-
- *(pr++) = rr;
- *(pg++) = gg;
- *(pb++) = bb;
- }
-
- r = *pr;
- rr = r + (r >> 1);
- if (rr < r) rr = ~0;
- g = *pg;
- gg = g + (g >> 1);
- if (gg < g) gg = ~0;
- b = *pb;
- bb = b + (b >> 1);
- if (bb < b) bb = ~0;
-
- *pr = rr;
- *pg = gg;
- *pb = bb;
-
- pr += width - 1;
- pg += width - 1;
- pb += width - 1;
-
- r = *pr;
- rr = (r >> 2) + (r >> 1);
- if (rr > r) rr = 0;
- g = *pg;
- gg = (g >> 2) + (g >> 1);
- if (gg > g) gg = 0;
- b = *pb;
- bb = (b >> 2) + (b >> 1);
- if (bb > b) bb = 0;
-
- *pr = rr;
- *pg = gg;
- *pb = bb;
- }
-}
-
-
-void Image::bevel2(void) {
- if (width > 4 && height > 4) {
- unsigned char r, g, b, rr ,gg ,bb, *pr = red + width + 1,
- *pg = green + width + 1, *pb = blue + width + 1;
- unsigned int w = width - 2, h = height - 1, wh = width * (height - 3);
-
- while (--w) {
- r = *pr;
- rr = r + (r >> 1);
- if (rr < r) rr = ~0;
- g = *pg;
- gg = g + (g >> 1);
- if (gg < g) gg = ~0;
- b = *pb;
- bb = b + (b >> 1);
- if (bb < b) bb = ~0;
-
- *pr = rr;
- *pg = gg;
- *pb = bb;
-
- r = *(pr + wh);
- rr = (r >> 2) + (r >> 1);
- if (rr > r) rr = 0;
- g = *(pg + wh);
- gg = (g >> 2) + (g >> 1);
- if (gg > g) gg = 0;
- b = *(pb + wh);
- bb = (b >> 2) + (b >> 1);
- if (bb > b) bb = 0;
-
- *((pr++) + wh) = rr;
- *((pg++) + wh) = gg;
- *((pb++) + wh) = bb;
- }
-
- pr = red + width;
- pg = green + width;
- pb = blue + width;
-
- while (--h) {
- r = *pr;
- rr = r + (r >> 1);
- if (rr < r) rr = ~0;
- g = *pg;
- gg = g + (g >> 1);
- if (gg < g) gg = ~0;
- b = *pb;
- bb = b + (b >> 1);
- if (bb < b) bb = ~0;
-
- *(++pr) = rr;
- *(++pg) = gg;
- *(++pb) = bb;
-
- pr += width - 3;
- pg += width - 3;
- pb += width - 3;
-
- r = *pr;
- rr = (r >> 2) + (r >> 1);
- if (rr > r) rr = 0;
- g = *pg;
- gg = (g >> 2) + (g >> 1);
- if (gg > g) gg = 0;
- b = *pb;
- bb = (b >> 2) + (b >> 1);
- if (bb > b) bb = 0;
-
- *(pr++) = rr;
- *(pg++) = gg;
- *(pb++) = bb;
-
- pr++; pg++; pb++;
- }
- }
-}
-
-
-void Image::border(const Texture &texture) {
- if (width < 2 || height < 2) return;
-
- register unsigned int i;
- int r = texture.borderColor().red(),
- g = texture.borderColor().green(),
- b = texture.borderColor().blue();
-
- unsigned char *pr, *pg, *pb;
-
- // top line
- pr = red;
- pg = green;
- pb = blue;
- for (i = 0; i < width; ++i) {
- *pr++ = r;
- *pg++ = g;
- *pb++ = b;
- }
-
- if (height > 2) {
- // left and right lines (pr,pg,pb are already lined up)
- for (i = 1; i < height - 1; ++i) {
- *pr = r;
- *pg = g;
- *pb = b;
- pr += width - 1;
- pg += width - 1;
- pb += width - 1;
- *pr++ = r;
- *pg++ = g;
- *pb++ = b;
- }
- }
-
- // bottom line (pr,pg,pb are already lined up)
- for (i = 0; i < width; ++i) {
- *pr++ = r;
- *pg++ = g;
- *pb++ = b;
- }
-}
-
-
-void Image::invert(void) {
- register unsigned int i, j, wh = (width * height) - 1;
- unsigned char tmp;
-
- for (i = 0, j = wh; j > i; j--, i++) {
- tmp = *(red + j);
- *(red + j) = *(red + i);
- *(red + i) = tmp;
-
- tmp = *(green + j);
- *(green + j) = *(green + i);
- *(green + i) = tmp;
-
- tmp = *(blue + j);
- *(blue + j) = *(blue + i);
- *(blue + i) = tmp;
- }
-}
-
-
-void Image::dgradient(void) {
- // diagonal gradient code was written by Mike Cole <mike@mydot.com>
- // modified for interlacing by Brad Hughes
-
- float drx, dgx, dbx, dry, dgy, dby, yr = 0.0, yg = 0.0, yb = 0.0,
- xr = (float) from.red(),
- xg = (float) from.green(),
- xb = (float) from.blue();
- unsigned char *pr = red, *pg = green, *pb = blue;
- unsigned int w = width * 2, h = height * 2, *xt = xtable, *yt = ytable;
-
- register unsigned int x, y;
-
- dry = drx = (float) (to.red() - from.red());
- dgy = dgx = (float) (to.green() - from.green());
- dby = dbx = (float) (to.blue() - from.blue());
-
- // Create X table
- drx /= w;
- dgx /= w;
- dbx /= w;
-
- for (x = 0; x < width; x++) {
- *(xt++) = (unsigned char) (xr);
- *(xt++) = (unsigned char) (xg);
- *(xt++) = (unsigned char) (xb);
-
- xr += drx;
- xg += dgx;
- xb += dbx;
- }
-
- // Create Y table
- dry /= h;
- dgy /= h;
- dby /= h;
-
- for (y = 0; y < height; y++) {
- *(yt++) = ((unsigned char) yr);
- *(yt++) = ((unsigned char) yg);
- *(yt++) = ((unsigned char) yb);
-
- yr += dry;
- yg += dgy;
- yb += dby;
- }
-
- // Combine tables to create gradient
-
- if (! interlaced) {
- // normal dgradient
- for (yt = ytable, y = 0; y < height; y++, yt += 3) {
- for (xt = xtable, x = 0; x < width; x++) {
- *(pr++) = *(xt++) + *(yt);
- *(pg++) = *(xt++) + *(yt + 1);
- *(pb++) = *(xt++) + *(yt + 2);
- }
- }
- } else {
- // faked interlacing effect
- unsigned char channel, channel2;
-
- for (yt = ytable, y = 0; y < height; y++, yt += 3) {
- for (xt = xtable, x = 0; x < width; x++) {
- if (y & 1) {
- channel = *(xt++) + *(yt);
- channel2 = (channel >> 1) + (channel >> 2);
- if (channel2 > channel) channel2 = 0;
- *(pr++) = channel2;
-
- channel = *(xt++) + *(yt + 1);
- channel2 = (channel >> 1) + (channel >> 2);
- if (channel2 > channel) channel2 = 0;
- *(pg++) = channel2;
-
- channel = *(xt++) + *(yt + 2);
- channel2 = (channel >> 1) + (channel >> 2);
- if (channel2 > channel) channel2 = 0;
- *(pb++) = channel2;
- } else {
- channel = *(xt++) + *(yt);
- channel2 = channel + (channel >> 3);
- if (channel2 < channel) channel2 = ~0;
- *(pr++) = channel2;
-
- channel = *(xt++) + *(yt + 1);
- channel2 = channel + (channel >> 3);
- if (channel2 < channel) channel2 = ~0;
- *(pg++) = channel2;
-
- channel = *(xt++) + *(yt + 2);
- channel2 = channel + (channel >> 3);
- if (channel2 < channel) channel2 = ~0;
- *(pb++) = channel2;
- }
- }
- }
- }
-}
-
-
-void Image::hgradient(void) {
- float drx, dgx, dbx,
- xr = (float) from.red(),
- xg = (float) from.green(),
- xb = (float) from.blue();
- unsigned char *pr = red, *pg = green, *pb = blue;
-
- register unsigned int x, y;
-
- drx = (float) (to.red() - from.red());
- dgx = (float) (to.green() - from.green());
- dbx = (float) (to.blue() - from.blue());
-
- drx /= width;
- dgx /= width;
- dbx /= width;
-
- if (interlaced && height > 2) {
- // faked interlacing effect
- unsigned char channel, channel2;
-
- for (x = 0; x < width; x++, pr++, pg++, pb++) {
- channel = (unsigned char) xr;
- channel2 = (channel >> 1) + (channel >> 2);
- if (channel2 > channel) channel2 = 0;
- *pr = channel2;
-
- channel = (unsigned char) xg;
- channel2 = (channel >> 1) + (channel >> 2);
- if (channel2 > channel) channel2 = 0;
- *pg = channel2;
-
- channel = (unsigned char) xb;
- channel2 = (channel >> 1) + (channel >> 2);
- if (channel2 > channel) channel2 = 0;
- *pb = channel2;
-
-
- channel = (unsigned char) xr;
- channel2 = channel + (channel >> 3);
- if (channel2 < channel) channel2 = ~0;
- *(pr + width) = channel2;
-
- channel = (unsigned char) xg;
- channel2 = channel + (channel >> 3);
- if (channel2 < channel) channel2 = ~0;
- *(pg + width) = channel2;
-
- channel = (unsigned char) xb;
- channel2 = channel + (channel >> 3);
- if (channel2 < channel) channel2 = ~0;
- *(pb + width) = channel2;
-
- xr += drx;
- xg += dgx;
- xb += dbx;
- }
-
- pr += width;
- pg += width;
- pb += width;
-
- int offset;
-
- for (y = 2; y < height; y++, pr += width, pg += width, pb += width) {
- if (y & 1) offset = width; else offset = 0;
-
- memcpy(pr, (red + offset), width);
- memcpy(pg, (green + offset), width);
- memcpy(pb, (blue + offset), width);
- }
- } else {
- // normal hgradient
- for (x = 0; x < width; x++) {
- *(pr++) = (unsigned char) (xr);
- *(pg++) = (unsigned char) (xg);
- *(pb++) = (unsigned char) (xb);
-
- xr += drx;
- xg += dgx;
- xb += dbx;
- }
-
- for (y = 1; y < height; y++, pr += width, pg += width, pb += width) {
- memcpy(pr, red, width);
- memcpy(pg, green, width);
- memcpy(pb, blue, width);
- }
- }
-}
-
-
-void Image::vgradient(void) {
- float dry, dgy, dby,
- yr = (float) from.red(),
- yg = (float) from.green(),
- yb = (float) from.blue();
- unsigned char *pr = red, *pg = green, *pb = blue;
-
- register unsigned int y;
-
- dry = (float) (to.red() - from.red());
- dgy = (float) (to.green() - from.green());
- dby = (float) (to.blue() - from.blue());
-
- dry /= height;
- dgy /= height;
- dby /= height;
-
- if (interlaced) {
- // faked interlacing effect
- unsigned char channel, channel2;
-
- for (y = 0; y < height; y++, pr += width, pg += width, pb += width) {
- if (y & 1) {
- channel = (unsigned char) yr;
- channel2 = (channel >> 1) + (channel >> 2);
- if (channel2 > channel) channel2 = 0;
- memset(pr, channel2, width);
-
- channel = (unsigned char) yg;
- channel2 = (channel >> 1) + (channel >> 2);
- if (channel2 > channel) channel2 = 0;
- memset(pg, channel2, width);
-
- channel = (unsigned char) yb;
- channel2 = (channel >> 1) + (channel >> 2);
- if (channel2 > channel) channel2 = 0;
- memset(pb, channel2, width);
- } else {
- channel = (unsigned char) yr;
- channel2 = channel + (channel >> 3);
- if (channel2 < channel) channel2 = ~0;
- memset(pr, channel2, width);
-
- channel = (unsigned char) yg;
- channel2 = channel + (channel >> 3);
- if (channel2 < channel) channel2 = ~0;
- memset(pg, channel2, width);
-
- channel = (unsigned char) yb;
- channel2 = channel + (channel >> 3);
- if (channel2 < channel) channel2 = ~0;
- memset(pb, channel2, width);
- }
-
- yr += dry;
- yg += dgy;
- yb += dby;
- }
- } else {
- // normal vgradient
- for (y = 0; y < height; y++, pr += width, pg += width, pb += width) {
- memset(pr, (unsigned char) yr, width);
- memset(pg, (unsigned char) yg, width);
- memset(pb, (unsigned char) yb, width);
-
- yr += dry;
- yg += dgy;
- yb += dby;
- }
- }
-}
-
-
-void Image::pgradient(void) {
- // pyramid gradient - based on original dgradient, written by
- // Mosfet (mosfet@kde.org)
- // adapted from kde sources for Blackbox by Brad Hughes
-
- float yr, yg, yb, drx, dgx, dbx, dry, dgy, dby,
- xr, xg, xb;
- int rsign, gsign, bsign;
- unsigned char *pr = red, *pg = green, *pb = blue;
- unsigned int tr = to.red(), tg = to.green(), tb = to.blue(),
- *xt = xtable, *yt = ytable;
-
- register unsigned int x, y;
-
- dry = drx = (float) (to.red() - from.red());
- dgy = dgx = (float) (to.green() - from.green());
- dby = dbx = (float) (to.blue() - from.blue());
-
- rsign = (drx < 0) ? -1 : 1;
- gsign = (dgx < 0) ? -1 : 1;
- bsign = (dbx < 0) ? -1 : 1;
-
- xr = yr = (drx / 2);
- xg = yg = (dgx / 2);
- xb = yb = (dbx / 2);
-
- // Create X table
- drx /= width;
- dgx /= width;
- dbx /= width;
-
- for (x = 0; x < width; x++) {
- *(xt++) = (unsigned char) ((xr < 0) ? -xr : xr);
- *(xt++) = (unsigned char) ((xg < 0) ? -xg : xg);
- *(xt++) = (unsigned char) ((xb < 0) ? -xb : xb);
-
- xr -= drx;
- xg -= dgx;
- xb -= dbx;
- }
-
- // Create Y table
- dry /= height;
- dgy /= height;
- dby /= height;
-
- for (y = 0; y < height; y++) {
- *(yt++) = ((unsigned char) ((yr < 0) ? -yr : yr));
- *(yt++) = ((unsigned char) ((yg < 0) ? -yg : yg));
- *(yt++) = ((unsigned char) ((yb < 0) ? -yb : yb));
-
- yr -= dry;
- yg -= dgy;
- yb -= dby;
- }
-
- // Combine tables to create gradient
-
- if (! interlaced) {
- // normal pgradient
- for (yt = ytable, y = 0; y < height; y++, yt += 3) {
- for (xt = xtable, x = 0; x < width; x++) {
- *(pr++) = (unsigned char) (tr - (rsign * (*(xt++) + *(yt))));
- *(pg++) = (unsigned char) (tg - (gsign * (*(xt++) + *(yt + 1))));
- *(pb++) = (unsigned char) (tb - (bsign * (*(xt++) + *(yt + 2))));
- }
- }
- } else {
- // faked interlacing effect
- unsigned char channel, channel2;
-
- for (yt = ytable, y = 0; y < height; y++, yt += 3) {
- for (xt = xtable, x = 0; x < width; x++) {
- if (y & 1) {
- channel = (unsigned char) (tr - (rsign * (*(xt++) + *(yt))));
- channel2 = (channel >> 1) + (channel >> 2);
- if (channel2 > channel) channel2 = 0;
- *(pr++) = channel2;
-
- channel = (unsigned char) (tg - (gsign * (*(xt++) + *(yt + 1))));
- channel2 = (channel >> 1) + (channel >> 2);
- if (channel2 > channel) channel2 = 0;
- *(pg++) = channel2;
-
- channel = (unsigned char) (tb - (bsign * (*(xt++) + *(yt + 2))));
- channel2 = (channel >> 1) + (channel >> 2);
- if (channel2 > channel) channel2 = 0;
- *(pb++) = channel2;
- } else {
- channel = (unsigned char) (tr - (rsign * (*(xt++) + *(yt))));
- channel2 = channel + (channel >> 3);
- if (channel2 < channel) channel2 = ~0;
- *(pr++) = channel2;
-
- channel = (unsigned char) (tg - (gsign * (*(xt++) + *(yt + 1))));
- channel2 = channel + (channel >> 3);
- if (channel2 < channel) channel2 = ~0;
- *(pg++) = channel2;
-
- channel = (unsigned char) (tb - (bsign * (*(xt++) + *(yt + 2))));
- channel2 = channel + (channel >> 3);
- if (channel2 < channel) channel2 = ~0;
- *(pb++) = channel2;
- }
- }
- }
- }
-}
-
-
-void Image::rgradient(void) {
- // rectangle gradient - based on original dgradient, written by
- // Mosfet (mosfet@kde.org)
- // adapted from kde sources for Blackbox by Brad Hughes
-
- float drx, dgx, dbx, dry, dgy, dby, xr, xg, xb, yr, yg, yb;
- int rsign, gsign, bsign;
- unsigned char *pr = red, *pg = green, *pb = blue;
- unsigned int tr = to.red(), tg = to.green(), tb = to.blue(),
- *xt = xtable, *yt = ytable;
-
- register unsigned int x, y;
-
- dry = drx = (float) (to.red() - from.red());
- dgy = dgx = (float) (to.green() - from.green());
- dby = dbx = (float) (to.blue() - from.blue());
-
- rsign = (drx < 0) ? -2 : 2;
- gsign = (dgx < 0) ? -2 : 2;
- bsign = (dbx < 0) ? -2 : 2;
-
- xr = yr = (drx / 2);
- xg = yg = (dgx / 2);
- xb = yb = (dbx / 2);
-
- // Create X table
- drx /= width;
- dgx /= width;
- dbx /= width;
-
- for (x = 0; x < width; x++) {
- *(xt++) = (unsigned char) ((xr < 0) ? -xr : xr);
- *(xt++) = (unsigned char) ((xg < 0) ? -xg : xg);
- *(xt++) = (unsigned char) ((xb < 0) ? -xb : xb);
-
- xr -= drx;
- xg -= dgx;
- xb -= dbx;
- }
-
- // Create Y table
- dry /= height;
- dgy /= height;
- dby /= height;
-
- for (y = 0; y < height; y++) {
- *(yt++) = ((unsigned char) ((yr < 0) ? -yr : yr));
- *(yt++) = ((unsigned char) ((yg < 0) ? -yg : yg));
- *(yt++) = ((unsigned char) ((yb < 0) ? -yb : yb));
-
- yr -= dry;
- yg -= dgy;
- yb -= dby;
- }
-
- // Combine tables to create gradient
-
- if (! interlaced) {
- // normal rgradient
- for (yt = ytable, y = 0; y < height; y++, yt += 3) {
- for (xt = xtable, x = 0; x < width; x++) {
- *(pr++) = (unsigned char) (tr - (rsign * max(*(xt++), *(yt))));
- *(pg++) = (unsigned char) (tg - (gsign * max(*(xt++), *(yt + 1))));
- *(pb++) = (unsigned char) (tb - (bsign * max(*(xt++), *(yt + 2))));
- }
- }
- } else {
- // faked interlacing effect
- unsigned char channel, channel2;
-
- for (yt = ytable, y = 0; y < height; y++, yt += 3) {
- for (xt = xtable, x = 0; x < width; x++) {
- if (y & 1) {
- channel = (unsigned char) (tr - (rsign * max(*(xt++), *(yt))));
- channel2 = (channel >> 1) + (channel >> 2);
- if (channel2 > channel) channel2 = 0;
- *(pr++) = channel2;
-
- channel = (unsigned char) (tg - (gsign * max(*(xt++), *(yt + 1))));
- channel2 = (channel >> 1) + (channel >> 2);
- if (channel2 > channel) channel2 = 0;
- *(pg++) = channel2;
-
- channel = (unsigned char) (tb - (bsign * max(*(xt++), *(yt + 2))));
- channel2 = (channel >> 1) + (channel >> 2);
- if (channel2 > channel) channel2 = 0;
- *(pb++) = channel2;
- } else {
- channel = (unsigned char) (tr - (rsign * max(*(xt++), *(yt))));
- channel2 = channel + (channel >> 3);
- if (channel2 < channel) channel2 = ~0;
- *(pr++) = channel2;
-
- channel = (unsigned char) (tg - (gsign * max(*(xt++), *(yt + 1))));
- channel2 = channel + (channel >> 3);
- if (channel2 < channel) channel2 = ~0;
- *(pg++) = channel2;
-
- channel = (unsigned char) (tb - (bsign * max(*(xt++), *(yt + 2))));
- channel2 = channel + (channel >> 3);
- if (channel2 < channel) channel2 = ~0;
- *(pb++) = channel2;
- }
- }
- }
- }
-}
-
-
-void Image::egradient(void) {
- // elliptic gradient - based on original dgradient, written by
- // Mosfet (mosfet@kde.org)
- // adapted from kde sources for Blackbox by Brad Hughes
-
- float drx, dgx, dbx, dry, dgy, dby, yr, yg, yb, xr, xg, xb;
- int rsign, gsign, bsign;
- unsigned char *pr = red, *pg = green, *pb = blue;
- unsigned int *xt = xtable, *yt = ytable,
- tr = (unsigned long) to.red(),
- tg = (unsigned long) to.green(),
- tb = (unsigned long) to.blue();
-
- register unsigned int x, y;
-
- dry = drx = (float) (to.red() - from.red());
- dgy = dgx = (float) (to.green() - from.green());
- dby = dbx = (float) (to.blue() - from.blue());
-
- rsign = (drx < 0) ? -1 : 1;
- gsign = (dgx < 0) ? -1 : 1;
- bsign = (dbx < 0) ? -1 : 1;
-
- xr = yr = (drx / 2);
- xg = yg = (dgx / 2);
- xb = yb = (dbx / 2);
-
- // Create X table
- drx /= width;
- dgx /= width;
- dbx /= width;
-
- for (x = 0; x < width; x++) {
- *(xt++) = (unsigned long) (xr * xr);
- *(xt++) = (unsigned long) (xg * xg);
- *(xt++) = (unsigned long) (xb * xb);
-
- xr -= drx;
- xg -= dgx;
- xb -= dbx;
- }
-
- // Create Y table
- dry /= height;
- dgy /= height;
- dby /= height;
-
- for (y = 0; y < height; y++) {
- *(yt++) = (unsigned long) (yr * yr);
- *(yt++) = (unsigned long) (yg * yg);
- *(yt++) = (unsigned long) (yb * yb);
-
- yr -= dry;
- yg -= dgy;
- yb -= dby;
- }
-
- // Combine tables to create gradient
-
- if (! interlaced) {
- // normal egradient
- for (yt = ytable, y = 0; y < height; y++, yt += 3) {
- for (xt = xtable, x = 0; x < width; x++) {
- *(pr++) = (unsigned char)
- (tr - (rsign * control->getSqrt(*(xt++) + *(yt))));
- *(pg++) = (unsigned char)
- (tg - (gsign * control->getSqrt(*(xt++) + *(yt + 1))));
- *(pb++) = (unsigned char)
- (tb - (bsign * control->getSqrt(*(xt++) + *(yt + 2))));
- }
- }
- } else {
- // faked interlacing effect
- unsigned char channel, channel2;
-
- for (yt = ytable, y = 0; y < height; y++, yt += 3) {
- for (xt = xtable, x = 0; x < width; x++) {
- if (y & 1) {
- channel = (unsigned char)
- (tr - (rsign * control->getSqrt(*(xt++) + *(yt))));
- channel2 = (channel >> 1) + (channel >> 2);
- if (channel2 > channel) channel2 = 0;
- *(pr++) = channel2;
-
- channel = (unsigned char)
- (tg - (gsign * control->getSqrt(*(xt++) + *(yt + 1))));
- channel2 = (channel >> 1) + (channel >> 2);
- if (channel2 > channel) channel2 = 0;
- *(pg++) = channel2;
-
- channel = (unsigned char)
- (tb - (bsign * control->getSqrt(*(xt++) + *(yt + 2))));
- channel2 = (channel >> 1) + (channel >> 2);
- if (channel2 > channel) channel2 = 0;
- *(pb++) = channel2;
- } else {
- channel = (unsigned char)
- (tr - (rsign * control->getSqrt(*(xt++) + *(yt))));
- channel2 = channel + (channel >> 3);
- if (channel2 < channel) channel2 = ~0;
- *(pr++) = channel2;
-
- channel = (unsigned char)
- (tg - (gsign * control->getSqrt(*(xt++) + *(yt + 1))));
- channel2 = channel + (channel >> 3);
- if (channel2 < channel) channel2 = ~0;
- *(pg++) = channel2;
-
- channel = (unsigned char)
- (tb - (bsign * control->getSqrt(*(xt++) + *(yt + 2))));
- channel2 = channel + (channel >> 3);
- if (channel2 < channel) channel2 = ~0;
- *(pb++) = channel2;
- }
- }
- }
- }
-}
-
-
-void Image::pcgradient(void) {
- // pipe cross gradient - based on original dgradient, written by
- // Mosfet (mosfet@kde.org)
- // adapted from kde sources for Blackbox by Brad Hughes
-
- float drx, dgx, dbx, dry, dgy, dby, xr, xg, xb, yr, yg, yb;
- int rsign, gsign, bsign;
- unsigned char *pr = red, *pg = green, *pb = blue;
- unsigned int *xt = xtable, *yt = ytable,
- tr = to.red(),
- tg = to.green(),
- tb = to.blue();
-
- register unsigned int x, y;
-
- dry = drx = (float) (to.red() - from.red());
- dgy = dgx = (float) (to.green() - from.green());
- dby = dbx = (float) (to.blue() - from.blue());
-
- rsign = (drx < 0) ? -2 : 2;
- gsign = (dgx < 0) ? -2 : 2;
- bsign = (dbx < 0) ? -2 : 2;
-
- xr = yr = (drx / 2);
- xg = yg = (dgx / 2);
- xb = yb = (dbx / 2);
-
- // Create X table
- drx /= width;
- dgx /= width;
- dbx /= width;
-
- for (x = 0; x < width; x++) {
- *(xt++) = (unsigned char) ((xr < 0) ? -xr : xr);
- *(xt++) = (unsigned char) ((xg < 0) ? -xg : xg);
- *(xt++) = (unsigned char) ((xb < 0) ? -xb : xb);
-
- xr -= drx;
- xg -= dgx;
- xb -= dbx;
- }
-
- // Create Y table
- dry /= height;
- dgy /= height;
- dby /= height;
-
- for (y = 0; y < height; y++) {
- *(yt++) = ((unsigned char) ((yr < 0) ? -yr : yr));
- *(yt++) = ((unsigned char) ((yg < 0) ? -yg : yg));
- *(yt++) = ((unsigned char) ((yb < 0) ? -yb : yb));
-
- yr -= dry;
- yg -= dgy;
- yb -= dby;
- }
-
- // Combine tables to create gradient
-
- if (! interlaced) {
- // normal pcgradient
- for (yt = ytable, y = 0; y < height; y++, yt += 3) {
- for (xt = xtable, x = 0; x < width; x++) {
- *(pr++) = (unsigned char) (tr - (rsign * min(*(xt++), *(yt))));
- *(pg++) = (unsigned char) (tg - (gsign * min(*(xt++), *(yt + 1))));
- *(pb++) = (unsigned char) (tb - (bsign * min(*(xt++), *(yt + 2))));
- }
- }
- } else {
- // faked interlacing effect
- unsigned char channel, channel2;
-
- for (yt = ytable, y = 0; y < height; y++, yt += 3) {
- for (xt = xtable, x = 0; x < width; x++) {
- if (y & 1) {
- channel = (unsigned char) (tr - (rsign * min(*(xt++), *(yt))));
- channel2 = (channel >> 1) + (channel >> 2);
- if (channel2 > channel) channel2 = 0;
- *(pr++) = channel2;
-
- channel = (unsigned char) (tg - (bsign * min(*(xt++), *(yt + 1))));
- channel2 = (channel >> 1) + (channel >> 2);
- if (channel2 > channel) channel2 = 0;
- *(pg++) = channel2;
-
- channel = (unsigned char) (tb - (gsign * min(*(xt++), *(yt + 2))));
- channel2 = (channel >> 1) + (channel >> 2);
- if (channel2 > channel) channel2 = 0;
- *(pb++) = channel2;
- } else {
- channel = (unsigned char) (tr - (rsign * min(*(xt++), *(yt))));
- channel2 = channel + (channel >> 3);
- if (channel2 < channel) channel2 = ~0;
- *(pr++) = channel2;
-
- channel = (unsigned char) (tg - (gsign * min(*(xt++), *(yt + 1))));
- channel2 = channel + (channel >> 3);
- if (channel2 < channel) channel2 = ~0;
- *(pg++) = channel2;
-
- channel = (unsigned char) (tb - (bsign * min(*(xt++), *(yt + 2))));
- channel2 = channel + (channel >> 3);
- if (channel2 < channel) channel2 = ~0;
- *(pb++) = channel2;
- }
- }
- }
- }
-}
-
-
-void Image::cdgradient(void) {
- // cross diagonal gradient - based on original dgradient, written by
- // Mosfet (mosfet@kde.org)
- // adapted from kde sources for Blackbox by Brad Hughes
-
- float drx, dgx, dbx, dry, dgy, dby, yr = 0.0, yg = 0.0, yb = 0.0,
- xr = (float) from.red(),
- xg = (float) from.green(),
- xb = (float) from.blue();
- unsigned char *pr = red, *pg = green, *pb = blue;
- unsigned int w = width * 2, h = height * 2, *xt, *yt;
-
- register unsigned int x, y;
-
- dry = drx = (float) (to.red() - from.red());
- dgy = dgx = (float) (to.green() - from.green());
- dby = dbx = (float) (to.blue() - from.blue());
-
- // Create X table
- drx /= w;
- dgx /= w;
- dbx /= w;
-
- for (xt = (xtable + (width * 3) - 1), x = 0; x < width; x++) {
- *(xt--) = (unsigned char) xb;
- *(xt--) = (unsigned char) xg;
- *(xt--) = (unsigned char) xr;
-
- xr += drx;
- xg += dgx;
- xb += dbx;
- }
-
- // Create Y table
- dry /= h;
- dgy /= h;
- dby /= h;
-
- for (yt = ytable, y = 0; y < height; y++) {
- *(yt++) = (unsigned char) yr;
- *(yt++) = (unsigned char) yg;
- *(yt++) = (unsigned char) yb;
-
- yr += dry;
- yg += dgy;
- yb += dby;
- }
-
- // Combine tables to create gradient
-
- if (! interlaced) {
- // normal cdgradient
- for (yt = ytable, y = 0; y < height; y++, yt += 3) {
- for (xt = xtable, x = 0; x < width; x++) {
- *(pr++) = *(xt++) + *(yt);
- *(pg++) = *(xt++) + *(yt + 1);
- *(pb++) = *(xt++) + *(yt + 2);
- }
- }
- } else {
- // faked interlacing effect
- unsigned char channel, channel2;
-
- for (yt = ytable, y = 0; y < height; y++, yt += 3) {
- for (xt = xtable, x = 0; x < width; x++) {
- if (y & 1) {
- channel = *(xt++) + *(yt);
- channel2 = (channel >> 1) + (channel >> 2);
- if (channel2 > channel) channel2 = 0;
- *(pr++) = channel2;
-
- channel = *(xt++) + *(yt + 1);
- channel2 = (channel >> 1) + (channel >> 2);
- if (channel2 > channel) channel2 = 0;
- *(pg++) = channel2;
-
- channel = *(xt++) + *(yt + 2);
- channel2 = (channel >> 1) + (channel >> 2);
- if (channel2 > channel) channel2 = 0;
- *(pb++) = channel2;
- } else {
- channel = *(xt++) + *(yt);
- channel2 = channel + (channel >> 3);
- if (channel2 < channel) channel2 = ~0;
- *(pr++) = channel2;
-
- channel = *(xt++) + *(yt + 1);
- channel2 = channel + (channel >> 3);
- if (channel2 < channel) channel2 = ~0;
- *(pg++) = channel2;
-
- channel = *(xt++) + *(yt + 2);
- channel2 = channel + (channel >> 3);
- if (channel2 < channel) channel2 = ~0;
- *(pb++) = channel2;
- }
- }
- }
- }
-}
-
-}