diff --git a/src/FbTk/ImageControl.cc b/src/FbTk/ImageControl.cc index 39fb4a72..19d8793d 100644 --- a/src/FbTk/ImageControl.cc +++ b/src/FbTk/ImageControl.cc @@ -49,11 +49,6 @@ #else #include #endif -#ifdef HAVE_CSTRING - #include -#else - #include -#endif #ifdef HAVE_CSTDIO #include #else @@ -70,8 +65,6 @@ namespace FbTk { namespace { // anonymous -static unsigned long *sqrt_table = 0; /// lookup table - #ifdef TIMEDCACHE bool s_timed_cache = true; #else @@ -79,21 +72,98 @@ bool s_timed_cache = false; #endif // TIMEDCACHE +void initColortables(unsigned char red[256], unsigned char green[256], unsigned char blue[256], + int red_bits, int green_bits, int blue_bits) { -inline unsigned long bsqrt(unsigned long x) { - if (x <= 0) return 0; - if (x == 1) return 1; - - unsigned long r = x >> 1; - unsigned long q; - - while (1) { - q = x / r; - if (q >= r) return r; - r = (r + q) >> 1; + for (unsigned int i = 0; i < 256; i++) { + red[i] = i / red_bits; + green[i] = i / green_bits; + blue[i] = i / blue_bits; } } +// tries to allocate all unallocated 'colors' by finding a close color based +// upon entries in the colormap. +// +void allocateUnallocatedColors(std::vector colors, Display* dpy, Colormap cmap, int screen_depth) { + + unsigned int i; + + bool done = true; + + // first run, just try to allocate the colors + for (i = 0; i < colors.size(); i++) { + + if (colors[i].flags == 0) { + if (! XAllocColor(dpy, cmap, &colors[i])) { + fprintf(stderr, "couldn't alloc color %i %i %i\n", + colors[i].red, colors[i].green, colors[i].blue); + colors[i].flags = 0; + done = false; + } else + colors[i].flags = DoRed|DoGreen|DoBlue; + } + } + + if (done) + return; + + // 'icolors' will hold the first 'nr_icolors' colors of the + // given (indexed) colormap. + const size_t nr_icolors = std::min(256, 1 << screen_depth); + XColor icolors[nr_icolors]; + + // give each icolor an index + for (i = 0; i < nr_icolors; i++) + icolors[i].pixel = i; + + // query the colors of the colormap and store them into 'icolors' + XQueryColors(dpy, cmap, icolors, nr_icolors); + + // try to find a close color for all not allocated colors + for (i = 0; i < colors.size(); i++) { + + if (colors[i].flags == 0) { // color is not allocated + + unsigned long chk = 0xffffffff; + unsigned long close = 0; + + // iterate over the indexed colors 'icolors' and find + // a close color. + // + // 2 passes to improve the result of the first pass + + char pass = 2; + while (pass--) { + for (unsigned int ii = 0; ii < nr_icolors; ii++) { + + int r = (colors[i].red - icolors[i].red) >> 8; + int g = (colors[i].green - icolors[i].green) >> 8; + int b = (colors[i].blue - icolors[i].blue) >> 8; + unsigned long pixel = (r * r) + (g * g) + (b * b); + + if (pixel < chk) { + chk = pixel; + close = ii; + } + + // store the indexed color + colors[i].red = icolors[close].red; + colors[i].green = icolors[close].green; + colors[i].blue = icolors[close].blue; + + // try to allocate it + if (XAllocColor(dpy, cmap, &colors[i])) { + colors[i].flags = DoRed|DoGreen|DoBlue; // mark it allocated + break; + } + } + } + } + } +} + + } // end anonymous namespace struct ImageControl::Cache { @@ -106,15 +176,12 @@ struct ImageControl::Cache { ImageControl::ImageControl(int screen_num, int cpc, unsigned long cache_timeout, unsigned long cmax): - m_colors(0), - m_num_colors(0), - m_colors_per_channel(cpc) { + m_colors_per_channel(cpc), + m_screen_num(screen_num) { Display *disp = FbTk::App::instance()->display(); m_screen_depth = DefaultDepth(disp, screen_num); - m_screen_num = screen_num; - m_root_window = RootWindow(disp, screen_num); m_visual = DefaultVisual(disp, screen_num); m_colormap = DefaultColormap(disp, screen_num); @@ -132,30 +199,16 @@ ImageControl::ImageControl(int screen_num, ImageControl::~ImageControl() { - if (sqrt_table) { - delete [] sqrt_table; - sqrt_table = 0; - } - - if (grad_xbuffer) { - delete [] grad_xbuffer; - } - - if (grad_ybuffer) { - delete [] grad_ybuffer; - } Display *disp = FbTk::App::instance()->display(); - if (m_colors) { - unsigned long *pixels = new unsigned long [m_num_colors]; + if (!m_colors.empty()) { + std::vector pixels; - for (unsigned int color = 0; color < m_num_colors; color++) - *(pixels + color) = (*(m_colors + color)).pixel; + for (unsigned int i = 0; i < m_colors.size(); i++) + pixels[i] = m_colors[i].pixel; - XFreeColors(disp, m_colormap, pixels, m_num_colors, 0); - - delete [] m_colors; + XFreeColors(disp, m_colormap, &pixels[0], m_colors.size(), 0); } if (!cache.empty()) { @@ -165,9 +218,7 @@ ImageControl::~ImageControl() { XFreePixmap(disp, (*it)->pixmap); delete (*it); } - } - } @@ -235,7 +286,7 @@ Pixmap ImageControl::renderImage(unsigned int width, unsigned int height, // If we are not suppose to cache this pixmap, just render and return it if ( ! use_cache) { - TextureRender image(*this, width, height, orient, m_colors, m_num_colors); + TextureRender image(*this, width, height, orient); return image.render(texture); } @@ -247,7 +298,7 @@ Pixmap ImageControl::renderImage(unsigned int width, unsigned int height, // render new image - TextureRender image(*this, width, height, orient, m_colors, m_num_colors); + TextureRender image(*this, width, height, orient); pixmap = image.render(texture); if (pixmap) { @@ -329,28 +380,14 @@ void ImageControl::getGradientBuffers(unsigned int w, unsigned int **xbuf, unsigned int **ybuf) { - if (w > grad_buffer_width) { - if (grad_xbuffer) { - delete [] grad_xbuffer; - } + if (w > grad_xbuffer.size()) + grad_xbuffer.resize(w * 3); - grad_buffer_width = w; + if (h > grad_ybuffer.size()) + grad_ybuffer.resize(h * 3); - grad_xbuffer = new unsigned int[grad_buffer_width * 3]; - } - - if (h > grad_buffer_height) { - if (grad_ybuffer) { - delete [] grad_ybuffer; - } - - grad_buffer_height = h; - - grad_ybuffer = new unsigned int[grad_buffer_height * 3]; - } - - *xbuf = grad_xbuffer; - *ybuf = grad_ybuffer; + *xbuf = &grad_xbuffer[0]; + *ybuf = &grad_ybuffer[0]; } @@ -362,7 +399,7 @@ void ImageControl::installRootColormap() { bool install = true; int i = 0, ncmap = 0; Colormap *cmaps = - XListInstalledColormaps(disp, m_root_window, &ncmap); + XListInstalledColormaps(disp, RootWindow(disp, screenNumber()), &ncmap); if (cmaps) { for (i = 0; i < ncmap; i++) { @@ -379,19 +416,7 @@ void ImageControl::installRootColormap() { XUngrabServer(disp); } -unsigned long ImageControl::getSqrt(unsigned int x) const { - if (! sqrt_table) { - // build sqrt table for use with elliptic gradient - sqrt_table = new unsigned long[256 * 256 * 2 + 1]; - int i = 0; - - for (; i < (256 * 256 * 2); i++) - sqrt_table[i] = bsqrt(i); - } - - return sqrt_table[x]; -} void ImageControl::cleanCache() { Display *disp = FbTk::App::instance()->display(); @@ -419,9 +444,6 @@ void ImageControl::cleanCache() { void ImageControl::createColorTable() { Display *disp = FbTk::App::instance()->display(); - grad_xbuffer = grad_ybuffer = (unsigned int *) 0; - grad_buffer_width = grad_buffer_height = 0; - int count; XPixmapFormatValues *pmv = XListPixmapFormats(disp, &count); @@ -444,9 +466,6 @@ void ImageControl::createColorTable() { switch (visual()->c_class) { case TrueColor: { - int i; - - // compute color tables unsigned long red_mask = visual()->red_mask, green_mask = visual()->green_mask, blue_mask = visual()->blue_mask; @@ -459,11 +478,8 @@ void ImageControl::createColorTable() { green_bits = 255 / green_mask; blue_bits = 255 / blue_mask; - for (i = 0; i < 256; i++) { - red_color_table[i] = i / red_bits; - green_color_table[i] = i / green_bits; - blue_color_table[i] = i / blue_bits; - } + initColortables(red_color_table, green_color_table, blue_color_table, + red_bits, green_bits, blue_bits); } break; @@ -471,31 +487,29 @@ void ImageControl::createColorTable() { case PseudoColor: case StaticColor: { - m_num_colors = m_colors_per_channel * m_colors_per_channel * m_colors_per_channel; + size_t num_colors = m_colors_per_channel * m_colors_per_channel * m_colors_per_channel; - if (m_num_colors > static_cast(1 << m_screen_depth)) { + if (num_colors > static_cast(1 << m_screen_depth)) { m_colors_per_channel = (1 << m_screen_depth) / 3; - m_num_colors = m_colors_per_channel * m_colors_per_channel * m_colors_per_channel; + num_colors = m_colors_per_channel * m_colors_per_channel * m_colors_per_channel; } - if (m_colors_per_channel < 2 || m_num_colors > static_cast(1 << m_screen_depth)) { - fprintf(stderr, "ImageControl::ImageControl: invalid colormap size %d " + if (m_colors_per_channel < 2 || num_colors > static_cast(1 << m_screen_depth)) { + fprintf(stderr, "ImageControl::ImageControl: invalid colormap size %ld " "(%d/%d/%d) - reducing", - m_num_colors, m_colors_per_channel, m_colors_per_channel, + num_colors, m_colors_per_channel, m_colors_per_channel, m_colors_per_channel); m_colors_per_channel = (1 << m_screen_depth) / 3; } - m_colors = new XColor[m_num_colors]; + m_colors.resize(num_colors); int bits = 255 / (m_colors_per_channel - 1); red_bits = green_bits = blue_bits = bits; - for (unsigned int i = 0; i < 256; i++) { - red_color_table[i] = green_color_table[i] = blue_color_table[i] = - i / bits; - } + initColortables(red_color_table, green_color_table, blue_color_table, + red_bits, green_bits, blue_bits); for (int r = 0, i = 0; r < m_colors_per_channel; r++) { for (int g = 0; g < m_colors_per_channel; g++) { @@ -508,143 +522,51 @@ void ImageControl::createColorTable() { } } - for (unsigned int i = 0; i < m_num_colors; i++) { - if (! XAllocColor(disp, m_colormap, &m_colors[i])) { - fprintf(stderr, "couldn't alloc color %i %i %i\n", - m_colors[i].red, m_colors[i].green, m_colors[i].blue); - m_colors[i].flags = 0; - } else - m_colors[i].flags = DoRed|DoGreen|DoBlue; - } - - XColor icolors[256]; - unsigned int incolors = (((1 << m_screen_depth) > 256) ? 256 : (1 << m_screen_depth)); - - for (unsigned int i = 0; i < incolors; i++) - icolors[i].pixel = i; - - XQueryColors(disp, m_colormap, icolors, incolors); - for (unsigned int i = 0; i < m_num_colors; i++) { - if (! m_colors[i].flags) { - unsigned long chk = 0xffffffff, pixel, close = 0; - char p = 2; - - while (p--) { - for (unsigned int ii = 0; ii < incolors; ii++) { - int r = (m_colors[i].red - icolors[i].red) >> 8; - int g = (m_colors[i].green - icolors[i].green) >> 8; - int b = (m_colors[i].blue - icolors[i].blue) >> 8; - pixel = (r * r) + (g * g) + (b * b); - - if (pixel < chk) { - chk = pixel; - close = ii; - } - - m_colors[i].red = icolors[close].red; - m_colors[i].green = icolors[close].green; - m_colors[i].blue = icolors[close].blue; - - if (XAllocColor(disp, m_colormap, - &m_colors[i])) { - m_colors[i].flags = DoRed|DoGreen|DoBlue; - break; - } - } - } - } - } - + allocateUnallocatedColors(m_colors, disp, m_colormap, m_screen_depth); break; } case GrayScale: case StaticGray: { + size_t num_colors; if (visual()->c_class == StaticGray) { - m_num_colors = 1 << m_screen_depth; + num_colors = 1 << m_screen_depth; } else { - m_num_colors = m_colors_per_channel * m_colors_per_channel * m_colors_per_channel; + num_colors = m_colors_per_channel * m_colors_per_channel * m_colors_per_channel; - if (m_num_colors > static_cast(1 << m_screen_depth)) { + if (num_colors > static_cast(1 << m_screen_depth)) { m_colors_per_channel = (1 << m_screen_depth) / 3; - m_num_colors = m_colors_per_channel * m_colors_per_channel * m_colors_per_channel; + num_colors = m_colors_per_channel * m_colors_per_channel * m_colors_per_channel; } } - if (m_colors_per_channel < 2 || m_num_colors > static_cast(1 << m_screen_depth)) { - fprintf(stderr,"FbTk::ImageControl: invalid colormap size %d " + if (m_colors_per_channel < 2 || num_colors > static_cast(1 << m_screen_depth)) { + fprintf(stderr,"FbTk::ImageControl: invalid colormap size %ld " "(%d/%d/%d) - reducing", - m_num_colors, m_colors_per_channel, m_colors_per_channel, + num_colors, m_colors_per_channel, m_colors_per_channel, m_colors_per_channel); m_colors_per_channel = (1 << m_screen_depth) / 3; } - m_colors = new XColor[m_num_colors]; + m_colors.resize(num_colors); - int p, bits = 255 / (m_colors_per_channel - 1); + int bits = 255 / (m_colors_per_channel - 1); red_bits = green_bits = blue_bits = bits; - for (unsigned int i = 0; i < 256; i++) - red_color_table[i] = green_color_table[i] = blue_color_table[i] = - i / bits; + initColortables(red_color_table, green_color_table, blue_color_table, + red_bits, green_bits, blue_bits); - for (unsigned int i = 0; i < m_num_colors; i++) { + for (unsigned int i = 0; i < num_colors; i++) { m_colors[i].red = (i * 0xffff) / (m_colors_per_channel - 1); m_colors[i].green = (i * 0xffff) / (m_colors_per_channel - 1); m_colors[i].blue = (i * 0xffff) / (m_colors_per_channel - 1); m_colors[i].flags = DoRed|DoGreen|DoBlue; - - if (! XAllocColor(disp, m_colormap, - &m_colors[i])) { - fprintf(stderr, "Couldn't alloc color %i %i %i\n", - m_colors[i].red, m_colors[i].green, m_colors[i].blue); - m_colors[i].flags = 0; - } else - m_colors[i].flags = DoRed|DoGreen|DoBlue; - } - - - XColor icolors[256]; - unsigned int incolors = (((1 << m_screen_depth) > 256) ? 256 : - (1 << m_screen_depth)); - - for (unsigned int i = 0; i < incolors; i++) - icolors[i].pixel = i; - - XQueryColors(disp, m_colormap, icolors, incolors); - for (unsigned int i = 0; i < m_num_colors; i++) { - if (! m_colors[i].flags) { - unsigned long chk = 0xffffffff, pixel, close = 0; - - p = 2; - while (p--) { - for (unsigned int ii = 0; ii < incolors; ii++) { - int r = (m_colors[i].red - icolors[i].red) >> 8; - int g = (m_colors[i].green - icolors[i].green) >> 8; - int b = (m_colors[i].blue - icolors[i].blue) >> 8; - pixel = (r * r) + (g * g) + (b * b); - - if (pixel < chk) { - chk = pixel; - close = ii; - } - - m_colors[i].red = icolors[close].red; - m_colors[i].green = icolors[close].green; - m_colors[i].blue = icolors[close].blue; - - if (XAllocColor(disp, m_colormap, &m_colors[i])) { - m_colors[i].flags = DoRed|DoGreen|DoBlue; - break; - } - } - } - } } + allocateUnallocatedColors(m_colors, disp, m_colormap, m_screen_depth); break; } diff --git a/src/FbTk/ImageControl.hh b/src/FbTk/ImageControl.hh index b7b90f7d..747525b4 100644 --- a/src/FbTk/ImageControl.hh +++ b/src/FbTk/ImageControl.hh @@ -30,7 +30,9 @@ #include "NotCopyable.hh" #include // for Visual* etc + #include +#include namespace FbTk { @@ -45,9 +47,10 @@ public: int depth() const { return m_screen_depth; } int colorsPerChannel() const { return m_colors_per_channel; } + size_t nrColors() const { return m_colors.size(); } + const XColor* colors() const { return &m_colors[0]; } int screenNumber() const { return m_screen_num; } Visual *visual() const { return m_visual; } - unsigned long getSqrt(unsigned int val) const; /** Render to pixmap @@ -84,24 +87,24 @@ private: Colormap m_colormap; - Window m_root_window; - - XColor *m_colors; ///< color table - unsigned int m_num_colors; ///< number of colors in color table + std::vector m_colors; ///< color table Visual *m_visual; - int bits_per_pixel, red_offset, green_offset, blue_offset, + int bits_per_pixel; + int red_offset, green_offset, blue_offset, red_bits, green_bits, blue_bits; int m_colors_per_channel; ///< number of colors per channel int m_screen_depth; ///< bit depth of screen int m_screen_num; ///< screen number + unsigned char red_color_table[256]; unsigned char green_color_table[256]; unsigned char blue_color_table[256]; - unsigned int *grad_xbuffer, *grad_ybuffer, grad_buffer_width, - grad_buffer_height; + // TextureRenderer uses these buffers + std::vector grad_xbuffer; + std::vector grad_ybuffer; struct Cache; typedef std::list CacheList; diff --git a/src/FbTk/TextureRender.cc b/src/FbTk/TextureRender.cc index 116142d6..1fb38c6d 100644 --- a/src/FbTk/TextureRender.cc +++ b/src/FbTk/TextureRender.cc @@ -31,11 +31,12 @@ #include "FbPixmap.hh" #include "GContext.hh" #include "I18n.hh" +#include "StringUtil.hh" #include #include -#include + #ifdef HAVE_CSTDIO #include #else @@ -60,437 +61,66 @@ using std::string; using std::max; using std::min; -namespace FbTk { +namespace { -TextureRender::TextureRender(ImageControl &imgctrl, - unsigned int w, unsigned int h, - FbTk::Orientation orient, - XColor *_colors, size_t num_colors): - control(imgctrl), - colors(_colors), - ncolors(static_cast(num_colors)), - cpc(imgctrl.colorsPerChannel()), - cpccpc(cpc * cpc), - red(0), green(0), blue(0), - orientation(orient), - width(static_cast((w > 0 ? w : 1))), height(static_cast(h > 0 ? h : 1)), - xtable(0), ytable(0) { +unsigned long bsqrt(unsigned int x) { - unsigned int texture_max_width = WidthOfScreen(ScreenOfDisplay(FbTk::App::instance()->display(), imgctrl.screenNumber())) * 2; - unsigned int texture_max_height = HeightOfScreen(ScreenOfDisplay(FbTk::App::instance()->display(), imgctrl.screenNumber())) * 2; + static const size_t SQRT_TABLE_ENTRIES = 256 * 256 * 2; - _FB_USES_NLS; - // clamp to "normal" size - if (width > texture_max_width) { - cerr<<"TextureRender: "<<_FBTK_CONSOLETEXT(Error, BigWidth, "Warning! Width > 3200 setting Width = 3200", "Image width seems too big, clamping")< texture_max_height) { - cerr<<"TextureRender: "<<_FBTK_CONSOLETEXT(Error, BigHeight, "Warning! Height > 3200 setting Height = 3200", "Image height seems too big, clamping")<display(), - control.screenNumber()), - width, height, - control.depth()); - - if (pixmap.drawable() == None) { - _FB_USES_NLS; - cerr<<"FbTk::TextureRender::render_solid(): "<<_FBTK_CONSOLETEXT(Error, CreatePixmap, "Error creating pixmap", "Couldn't create a pixmap - image - for some reason")<display(); - XImage *image = - XCreateImage(disp, - DefaultVisual(disp, control.screenNumber()), control.depth(), ZPixmap, 0, 0, - width, height, 32, 0); - - if (! image) { - _FB_USES_NLS; - cerr << "FbTk::TextureRender::renderXImage(): " << _FBTK_CONSOLETEXT(Error, CreateXImage, "Can't create XImage", "Couldn't create an XImage") << "." << endl; - return 0; - } - - image->data = 0; - - unsigned char *d = new unsigned char[image->bytes_per_line * (height + 1)]; - register unsigned int x, y, r, g, b, o, offset; - - unsigned char *pixel_data = d, *ppixel_data = d; - unsigned long pixel; - - o = image->bits_per_pixel + ((image->byte_order == MSBFirst) ? 1 : 0); - - switch (control.visual()->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); - - switch (o) { - 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; + unsigned long r = x >> 1; + unsigned long q; + for (x = 2; x < SQRT_TABLE_ENTRIES; x++) { + while (1) { + q = x / r; + if (q >= r) { + sqrt_table[x] = static_cast(r); break; } + r = (r + q) >> 1; } - - 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: - _FB_USES_NLS; - cerr << "TextureRender::renderXImage(): " << - _FBTK_CONSOLETEXT(Error, UnsupportedVisual, "Unsupported visual", "A visual is a technical term in X") << endl; - delete [] d; - XDestroyImage(image); - return (XImage *) 0; } - image->data = (char *) d; - return image; + return sqrt_table[std::min(static_cast(x), SQRT_TABLE_ENTRIES - 1)]; +} + +/* + + x1 y1 ---- gc1 ---- x2 y1 + | | + | | + gc2 gc1 + | | + | | + x1 y2 ---- gc2 ---- x2 y2 + + */ +void drawBevelRectangle(FbTk::FbDrawable& d, GC gc1, GC gc2, int x1, int y1, int x2, int y2) { + d.drawLine(gc1, x1, y1, x2, y1); + d.drawLine(gc1, x2, y1, x2, y2); + d.drawLine(gc2, x1, y2, x2, y2); + d.drawLine(gc2, x1, y1, x1, y2); } -Pixmap TextureRender::renderPixmap() { - Display *disp = FbTk::App::instance()->display(); - FbPixmap pixmap(RootWindow(disp, control.screenNumber()), - width, height, control.depth()); - - if (pixmap.drawable() == None) { - _FB_USES_NLS; - cerr<<"FbTk::TextureRender::renderPixmap(): "<<_FBTK_CONSOLETEXT(Error, CreatePixmap, "Error creating pixmap", "Couldn't create a pixmap - image - for some reason")<data) { - XDestroyImage(image); - return None; - } - - XPutImage(disp, pixmap.drawable(), - DefaultGC(disp, control.screenNumber()), - image, 0, 0, 0, 0, width, height); - - if (image->data != 0) { - delete [] image->data; - image->data = 0; - } - - XDestroyImage(image); - - pixmap.rotate(orientation); - - return pixmap.release(); -} -void TextureRender::bevel1() { + +void renderBevel1(bool interlaced, + unsigned int width, unsigned int height, + unsigned char* red, unsigned char* green, unsigned char* blue, + const FbTk::Color* from, const FbTk::Color* to, + FbTk::ImageControl& imgctrl) { + if (! (width > 2 && height > 2)) return; @@ -629,7 +259,13 @@ void TextureRender::bevel1() { } -void TextureRender::bevel2() { + +void renderBevel2(bool interlaced, + unsigned int width, unsigned int height, + unsigned char* red, unsigned char* green, unsigned char* blue, + const FbTk::Color* from, const FbTk::Color* to, + FbTk::ImageControl& imgctrl) { + if (! (width > 4 && height > 4)) return; @@ -709,143 +345,42 @@ void TextureRender::bevel2() { } -void TextureRender::invert() { - register unsigned int i, j, wh = (width * height) - 1; - unsigned char tmp; + + +void invertRGB(unsigned int w, unsigned int h, + unsigned char* r, unsigned char* g, unsigned char* b) { + + register unsigned int i, j, wh = (w * h) - 1; 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; + std::swap(*(r + j), *(r + i)); + std::swap(*(g + j), *(g + i)); + std::swap(*(b + j), *(b + i)); } } -void TextureRender::dgradient() { - // diagonal gradient code was written by Mike Cole - // modified for interlacing by Brad Hughes +void renderHGradient(bool interlaced, + unsigned int width, unsigned int height, + unsigned char* r, unsigned char* g, unsigned char* b, + const FbTk::Color* from, const FbTk::Color* to, + FbTk::ImageControl& imgctrl) { - 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; - unsigned int *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 TextureRender::hgradient() { float drx, dgx, dbx, xr = (float) from->red(), xg = (float) from->green(), xb = (float) from->blue(); - unsigned char *pr = red, *pg = green, *pb = blue; + unsigned char* red = r; + unsigned char* green = g; + unsigned char* blue = b; + unsigned int* xtable; + unsigned int* ytable; register unsigned int x, y; + imgctrl.getGradientBuffers(width, height, &xtable, &ytable); + + drx = (float) (to->red() - from->red()); dgx = (float) (to->green() - from->green()); dbx = (float) (to->blue() - from->blue()); @@ -858,89 +393,97 @@ void TextureRender::hgradient() { // faked interlacing effect unsigned char channel, channel2; - for (x = 0; x < width; x++, pr++, pg++, pb++) { + for (x = 0; x < width; x++, r++, g++, b++) { channel = (unsigned char) xr; channel2 = (channel >> 1) + (channel >> 2); if (channel2 > channel) channel2 = 0; - *pr = channel2; + *r = channel2; channel = (unsigned char) xg; channel2 = (channel >> 1) + (channel >> 2); if (channel2 > channel) channel2 = 0; - *pg = channel2; + *g = channel2; channel = (unsigned char) xb; channel2 = (channel >> 1) + (channel >> 2); if (channel2 > channel) channel2 = 0; - *pb = channel2; + *b = channel2; channel = (unsigned char) xr; channel2 = channel + (channel >> 3); if (channel2 < channel) channel2 = ~0; - *(pr + width) = channel2; + *(r + width) = channel2; channel = (unsigned char) xg; channel2 = channel + (channel >> 3); if (channel2 < channel) channel2 = ~0; - *(pg + width) = channel2; + *(g + width) = channel2; channel = (unsigned char) xb; channel2 = channel + (channel >> 3); if (channel2 < channel) channel2 = ~0; - *(pb + width) = channel2; + *(b + width) = channel2; xr += drx; xg += dgx; xb += dbx; } - pr += width; - pg += width; - pb += width; + r += width; + g += width; + b += width; int offset; - for (y = 2; y < height; y++, pr += width, pg += width, pb += width) { + for (y = 2; y < height; y++, r += width, g += width, b += width) { if (y & 1) offset = width; else offset = 0; - memcpy(pr, (red + offset), width); - memcpy(pg, (green + offset), width); - memcpy(pb, (blue + offset), width); + memcpy(r, (red + offset), width); + memcpy(g, (green + offset), width); + memcpy(b, (blue + offset), width); } } else { // normal hgradient for (x = 0; x < width; x++) { - *(pr++) = (unsigned char) (xr); - *(pg++) = (unsigned char) (xg); - *(pb++) = (unsigned char) (xb); + *(r++) = (unsigned char) (xr); + *(g++) = (unsigned char) (xg); + *(b++) = (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); + for (y = 1; y < height; y++, r += width, g += width, b += width) { + memcpy(r, red, width); + memcpy(g, green, width); + memcpy(b, blue, width); } } } +void renderVGradient(bool interlaced, + unsigned int width, unsigned int height, + unsigned char* r, unsigned char* g, unsigned char* b, + const FbTk::Color* from, const FbTk::Color* to, + FbTk::ImageControl& imgctrl) { -void TextureRender::vgradient() { 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; + unsigned int* xtable; + unsigned int* ytable; + + imgctrl.getGradientBuffers(width, height, &xtable, &ytable); + dry = (float) (to->red() - from->red()); dgy = (float) (to->green() - from->green()); dby = (float) (to->blue() - from->blue()); @@ -953,37 +496,37 @@ void TextureRender::vgradient() { // faked interlacing effect unsigned char channel, channel2; - for (y = 0; y < height; y++, pr += width, pg += width, pb += width) { + for (y = 0; y < height; y++, r += width, g += width, b += width) { if (y & 1) { channel = (unsigned char) yr; channel2 = (channel >> 1) + (channel >> 2); if (channel2 > channel) channel2 = 0; - memset(pr, channel2, width); + memset(r, channel2, width); channel = (unsigned char) yg; channel2 = (channel >> 1) + (channel >> 2); if (channel2 > channel) channel2 = 0; - memset(pg, channel2, width); + memset(g, channel2, width); channel = (unsigned char) yb; channel2 = (channel >> 1) + (channel >> 2); if (channel2 > channel) channel2 = 0; - memset(pb, channel2, width); + memset(b, channel2, width); } else { channel = (unsigned char) yr; channel2 = channel + (channel >> 3); if (channel2 < channel) channel2 = ~0; - memset(pr, channel2, width); + memset(r, channel2, width); channel = (unsigned char) yg; channel2 = channel + (channel >> 3); if (channel2 < channel) channel2 = ~0; - memset(pg, channel2, width); + memset(g, channel2, width); channel = (unsigned char) yb; channel2 = channel + (channel >> 3); if (channel2 < channel) channel2 = ~0; - memset(pb, channel2, width); + memset(b, channel2, width); } yr += dry; @@ -993,10 +536,10 @@ void TextureRender::vgradient() { } 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); + for (y = 0; y < height; y++, r += width, g += width, b += width) { + memset(r, (unsigned char) yr, width); + memset(g, (unsigned char) yg, width); + memset(b, (unsigned char) yb, width); yr += dry; yg += dgy; @@ -1008,20 +551,30 @@ void TextureRender::vgradient() { } -void TextureRender::pgradient() { - // pyramid gradient - based on original dgradient, written by - // Mosfet (mosfet@kde.org) - // adapted from kde sources for Blackbox by Brad Hughes +// pyramid gradient - based on original dgradient, written by +// Mosfet (mosfet@kde.org) +// adapted from kde sources for Blackbox by Brad Hughes +void renderPGradient(bool interlaced, + unsigned int width, unsigned int height, + unsigned char* r, unsigned char* g, unsigned char* b, + const FbTk::Color* from, const FbTk::Color* to, + FbTk::ImageControl& imgctrl) { 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(); - unsigned int *xt = xtable, *yt = ytable; + unsigned int* xtable; + unsigned int* ytable; + unsigned int* xt; + unsigned int* yt; register unsigned int x, y; + imgctrl.getGradientBuffers(width, height, &xtable, &ytable); + xt = xtable; + yt = ytable; + dry = drx = (float) (to->red() - from->red()); dgy = dgx = (float) (to->green() - from->green()); dby = dbx = (float) (to->blue() - from->blue()); @@ -1072,9 +625,9 @@ void TextureRender::pgradient() { // 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)))); + *(r++) = (unsigned char) (tr - (rsign * (*(xt++) + *(yt)))); + *(g++) = (unsigned char) (tg - (gsign * (*(xt++) + *(yt + 1)))); + *(b++) = (unsigned char) (tb - (bsign * (*(xt++) + *(yt + 2)))); } } @@ -1088,32 +641,32 @@ void TextureRender::pgradient() { channel = (unsigned char) (tr - (rsign * (*(xt++) + *(yt)))); channel2 = (channel >> 1) + (channel >> 2); if (channel2 > channel) channel2 = 0; - *(pr++) = channel2; + *(r++) = channel2; channel = (unsigned char) (tg - (gsign * (*(xt++) + *(yt + 1)))); channel2 = (channel >> 1) + (channel >> 2); if (channel2 > channel) channel2 = 0; - *(pg++) = channel2; + *(g++) = channel2; channel = (unsigned char) (tb - (bsign * (*(xt++) + *(yt + 2)))); channel2 = (channel >> 1) + (channel >> 2); if (channel2 > channel) channel2 = 0; - *(pb++) = channel2; + *(b++) = channel2; } else { channel = (unsigned char) (tr - (rsign * (*(xt++) + *(yt)))); channel2 = channel + (channel >> 3); if (channel2 < channel) channel2 = ~0; - *(pr++) = channel2; + *(r++) = channel2; channel = (unsigned char) (tg - (gsign * (*(xt++) + *(yt + 1)))); channel2 = channel + (channel >> 3); if (channel2 < channel) channel2 = ~0; - *(pg++) = channel2; + *(g++) = channel2; channel = (unsigned char) (tb - (bsign * (*(xt++) + *(yt + 2)))); channel2 = channel + (channel >> 3); if (channel2 < channel) channel2 = ~0; - *(pb++) = channel2; + *(b++) = channel2; } } } @@ -1122,19 +675,30 @@ void TextureRender::pgradient() { } -void TextureRender::rgradient() { - // rectangle gradient - based on original dgradient, written by - // Mosfet (mosfet@kde.org) - // adapted from kde sources for Blackbox by Brad Hughes + +// rectangle gradient - based on original dgradient, written by +// Mosfet (mosfet@kde.org) +// adapted from kde sources for Blackbox by Brad Hughes +void renderRGradient(bool interlaced, + unsigned int width, unsigned int height, + unsigned char* r, unsigned char* g, unsigned char* b, + const FbTk::Color* from, const FbTk::Color* to, + FbTk::ImageControl& imgctrl) { 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(); - unsigned int *xt = xtable, *yt = ytable; + unsigned int* xtable; + unsigned int* ytable; + unsigned int* xt; + unsigned int* yt; register unsigned int x, y; + imgctrl.getGradientBuffers(width, height, &xtable, &ytable); + xt = xtable; + yt = ytable; + dry = drx = (float) (to->red() - from->red()); dgy = dgx = (float) (to->green() - from->green()); dby = dbx = (float) (to->blue() - from->blue()); @@ -1185,9 +749,9 @@ void TextureRender::rgradient() { // 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)))); + *(r++) = (unsigned char) (tr - (rsign * max(*(xt++), *(yt)))); + *(g++) = (unsigned char) (tg - (gsign * max(*(xt++), *(yt + 1)))); + *(b++) = (unsigned char) (tb - (bsign * max(*(xt++), *(yt + 2)))); } } @@ -1201,55 +765,184 @@ void TextureRender::rgradient() { channel = (unsigned char) (tr - (rsign * max(*(xt++), *(yt)))); channel2 = (channel >> 1) + (channel >> 2); if (channel2 > channel) channel2 = 0; - *(pr++) = channel2; + *(r++) = channel2; channel = (unsigned char) (tg - (gsign * max(*(xt++), *(yt + 1)))); channel2 = (channel >> 1) + (channel >> 2); if (channel2 > channel) channel2 = 0; - *(pg++) = channel2; + *(g++) = channel2; channel = (unsigned char) (tb - (bsign * max(*(xt++), *(yt + 2)))); channel2 = (channel >> 1) + (channel >> 2); if (channel2 > channel) channel2 = 0; - *(pb++) = channel2; + *(b++) = channel2; } else { channel = (unsigned char) (tr - (rsign * max(*(xt++), *(yt)))); channel2 = channel + (channel >> 3); if (channel2 < channel) channel2 = ~0; - *(pr++) = channel2; + *(r++) = channel2; channel = (unsigned char) (tg - (gsign * max(*(xt++), *(yt + 1)))); channel2 = channel + (channel >> 3); if (channel2 < channel) channel2 = ~0; - *(pg++) = channel2; + *(g++) = channel2; channel = (unsigned char) (tb - (bsign * max(*(xt++), *(yt + 2)))); channel2 = channel + (channel >> 3); if (channel2 < channel) channel2 = ~0; - *(pb++) = channel2; + *(b++) = channel2; + } + } + } + } +} + + + + +// diagonal gradient code was written by Mike Cole +// modified for interlacing by Brad Hughes +void renderDGradient(bool interlaced, + unsigned int width, unsigned int height, + unsigned char* r, unsigned char* g, unsigned char* b, + const FbTk::Color* from, const FbTk::Color* to, + FbTk::ImageControl& imgctrl) { + + 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 int w = width * 2; + unsigned int h = height * 2; + unsigned int* xtable; + unsigned int* ytable; + unsigned int* xt; + unsigned int* yt; + register unsigned int x, y; + + imgctrl.getGradientBuffers(w, h, &xtable, &ytable); + xt = xtable; + yt = ytable; + + 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++) { + *(r++) = *(xt++) + *(yt); + *(g++) = *(xt++) + *(yt + 1); + *(b++) = *(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; + *(r++) = channel2; + + channel = *(xt++) + *(yt + 1); + channel2 = (channel >> 1) + (channel >> 2); + if (channel2 > channel) channel2 = 0; + *(g++) = channel2; + + channel = *(xt++) + *(yt + 2); + channel2 = (channel >> 1) + (channel >> 2); + if (channel2 > channel) channel2 = 0; + *(b++) = channel2; + } else { + channel = *(xt++) + *(yt); + channel2 = channel + (channel >> 3); + if (channel2 < channel) channel2 = ~0; + *(r++) = channel2; + + channel = *(xt++) + *(yt + 1); + channel2 = channel + (channel >> 3); + if (channel2 < channel) channel2 = ~0; + *(g++) = channel2; + + channel = *(xt++) + *(yt + 2); + channel2 = channel + (channel >> 3); + if (channel2 < channel) channel2 = ~0; + *(b++) = channel2; } } } } + } -void TextureRender::egradient() { - // elliptic gradient - based on original dgradient, written by - // Mosfet (mosfet@kde.org) - // adapted from kde sources for Blackbox by Brad Hughes + + +// elliptic gradient - based on original dgradient, written by +// Mosfet (mosfet@kde.org) +// adapted from kde sources for Blackbox by Brad Hughes +void renderEGradient(bool interlaced, + unsigned int width, unsigned int height, + unsigned char* r, unsigned char* g, unsigned char* b, + const FbTk::Color* from, const FbTk::Color* to, + FbTk::ImageControl& imgctrl) { 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; + unsigned int* xt; + unsigned int* xtable; + unsigned int* yt; + unsigned int* ytable; unsigned int tr = (unsigned long) to->red(), tg = (unsigned long) to->green(), tb = (unsigned long) to->blue(); - register unsigned int x, y; + + imgctrl.getGradientBuffers(width, height, &xtable, &ytable); + xt = xtable; + yt = ytable; + dry = drx = (float) (to->red() - from->red()); dgy = dgx = (float) (to->green() - from->green()); dby = dbx = (float) (to->blue() - from->blue()); @@ -1297,12 +990,12 @@ void TextureRender::egradient() { // 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)))); + *(r++) = (unsigned char) + (tr - (rsign * bsqrt(*(xt++) + *(yt)))); + *(g++) = (unsigned char) + (tg - (gsign * bsqrt(*(xt++) + *(yt + 1)))); + *(b++) = (unsigned char) + (tb - (bsign * bsqrt(*(xt++) + *(yt + 2)))); } } @@ -1314,40 +1007,40 @@ void TextureRender::egradient() { for (xt = xtable, x = 0; x < width; x++) { if (y & 1) { channel = (unsigned char) - (tr - (rsign * control.getSqrt(*(xt++) + *(yt)))); + (tr - (rsign * bsqrt(*(xt++) + *(yt)))); channel2 = (channel >> 1) + (channel >> 2); if (channel2 > channel) channel2 = 0; - *(pr++) = channel2; + *(r++) = channel2; channel = (unsigned char) - (tg - (gsign * control.getSqrt(*(xt++) + *(yt + 1)))); + (tg - (gsign * bsqrt(*(xt++) + *(yt + 1)))); channel2 = (channel >> 1) + (channel >> 2); if (channel2 > channel) channel2 = 0; - *(pg++) = channel2; + *(g++) = channel2; channel = (unsigned char) - (tb - (bsign * control.getSqrt(*(xt++) + *(yt + 2)))); + (tb - (bsign * bsqrt(*(xt++) + *(yt + 2)))); channel2 = (channel >> 1) + (channel >> 2); if (channel2 > channel) channel2 = 0; - *(pb++) = channel2; + *(b++) = channel2; } else { channel = (unsigned char) - (tr - (rsign * control.getSqrt(*(xt++) + *(yt)))); + (tr - (rsign * bsqrt(*(xt++) + *(yt)))); channel2 = channel + (channel >> 3); if (channel2 < channel) channel2 = ~0; - *(pr++) = channel2; + *(r++) = channel2; channel = (unsigned char) - (tg - (gsign * control.getSqrt(*(xt++) + *(yt + 1)))); + (tg - (gsign * bsqrt(*(xt++) + *(yt + 1)))); channel2 = channel + (channel >> 3); if (channel2 < channel) channel2 = ~0; - *(pg++) = channel2; + *(g++) = channel2; channel = (unsigned char) - (tb - (bsign * control.getSqrt(*(xt++) + *(yt + 2)))); + (tb - (bsign * bsqrt(*(xt++) + *(yt + 2)))); channel2 = channel + (channel >> 3); if (channel2 < channel) channel2 = ~0; - *(pb++) = channel2; + *(b++) = channel2; } } } @@ -1356,21 +1049,31 @@ void TextureRender::egradient() { } -void TextureRender::pcgradient() { - // pipe cross gradient - based on original dgradient, written by - // Mosfet (mosfet@kde.org) - // adapted from kde sources for Blackbox by Brad Hughes + +// pipe cross gradient - based on original dgradient, written by +// Mosfet (mosfet@kde.org) +// adapted from kde sources for Blackbox by Brad Hughes +void renderPCGradient(bool interlaced, + unsigned int width, unsigned int height, + unsigned char* r, unsigned char* g, unsigned char* b, + const FbTk::Color* from, const FbTk::Color* to, + FbTk::ImageControl& imgctrl) { 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; + unsigned int* xtable; + unsigned int* ytable; + unsigned int *xt; + unsigned int *yt; unsigned int tr = to->red(), tg = to->green(), tb = to->blue(); - register unsigned int x, y; + imgctrl.getGradientBuffers(width, height, &xtable, &ytable); + xt = xtable; + yt = ytable; + dry = drx = (float) (to->red() - from->red()); dgy = dgx = (float) (to->green() - from->green()); dby = dbx = (float) (to->blue() - from->blue()); @@ -1419,9 +1122,9 @@ void TextureRender::pcgradient() { // 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)))); + *(r++) = (unsigned char) (tr - (rsign * min(*(xt++), *(yt)))); + *(g++) = (unsigned char) (tg - (gsign * min(*(xt++), *(yt + 1)))); + *(b++) = (unsigned char) (tb - (bsign * min(*(xt++), *(yt + 2)))); } } @@ -1435,54 +1138,64 @@ void TextureRender::pcgradient() { channel = (unsigned char) (tr - (rsign * min(*(xt++), *(yt)))); channel2 = (channel >> 1) + (channel >> 2); if (channel2 > channel) channel2 = 0; - *(pr++) = channel2; + *(r++) = channel2; channel = (unsigned char) (tg - (bsign * min(*(xt++), *(yt + 1)))); channel2 = (channel >> 1) + (channel >> 2); if (channel2 > channel) channel2 = 0; - *(pg++) = channel2; + *(g++) = channel2; channel = (unsigned char) (tb - (gsign * min(*(xt++), *(yt + 2)))); channel2 = (channel >> 1) + (channel >> 2); if (channel2 > channel) channel2 = 0; - *(pb++) = channel2; + *(b++) = channel2; } else { channel = (unsigned char) (tr - (rsign * min(*(xt++), *(yt)))); channel2 = channel + (channel >> 3); if (channel2 < channel) channel2 = ~0; - *(pr++) = channel2; + *(r++) = channel2; channel = (unsigned char) (tg - (gsign * min(*(xt++), *(yt + 1)))); channel2 = channel + (channel >> 3); if (channel2 < channel) channel2 = ~0; - *(pg++) = channel2; + *(g++) = channel2; channel = (unsigned char) (tb - (bsign * min(*(xt++), *(yt + 2)))); channel2 = channel + (channel >> 3); if (channel2 < channel) channel2 = ~0; - *(pb++) = channel2; + *(b++) = channel2; } } } } - } -void TextureRender::cdgradient() { - // cross diagonal gradient - based on original dgradient, written by - // Mosfet (mosfet@kde.org) - // adapted from kde sources for Blackbox by Brad Hughes +// cross diagonal gradient - based on original dgradient, written by +// Mosfet (mosfet@kde.org) +// adapted from kde sources for Blackbox by Brad Hughes +void renderCDGradient(bool interlaced, + unsigned int width, unsigned int height, + unsigned char* r, unsigned char* g, unsigned char* b, + const FbTk::Color* from, const FbTk::Color* to, + FbTk::ImageControl& imgctrl) { - float drx, dgx, dbx, dry, dgy, dby, yr = 0.0, yg = 0.0, yb = 0.0, + 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; + unsigned int w = width * 2, h = height * 2; + unsigned int* xtable; + unsigned int* ytable; + unsigned int* xt; + unsigned int* yt; register unsigned int x, y; + imgctrl.getGradientBuffers(w, h, &xtable, &ytable); + xt = xtable; + yt = ytable; + dry = drx = (float) (to->red() - from->red()); dgy = dgx = (float) (to->green() - from->green()); dby = dbx = (float) (to->blue() - from->blue()); @@ -1523,9 +1236,9 @@ void TextureRender::cdgradient() { // 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); + *(r++) = *(xt++) + *(yt); + *(g++) = *(xt++) + *(yt + 1); + *(b++) = *(xt++) + *(yt + 2); } } @@ -1539,37 +1252,444 @@ void TextureRender::cdgradient() { channel = *(xt++) + *(yt); channel2 = (channel >> 1) + (channel >> 2); if (channel2 > channel) channel2 = 0; - *(pr++) = channel2; + *(r++) = channel2; channel = *(xt++) + *(yt + 1); channel2 = (channel >> 1) + (channel >> 2); if (channel2 > channel) channel2 = 0; - *(pg++) = channel2; + *(g++) = channel2; channel = *(xt++) + *(yt + 2); channel2 = (channel >> 1) + (channel >> 2); if (channel2 > channel) channel2 = 0; - *(pb++) = channel2; + *(b++) = channel2; } else { channel = *(xt++) + *(yt); channel2 = channel + (channel >> 3); if (channel2 < channel) channel2 = ~0; - *(pr++) = channel2; + *(r++) = channel2; channel = *(xt++) + *(yt + 1); channel2 = channel + (channel >> 3); if (channel2 < channel) channel2 = ~0; - *(pg++) = channel2; + *(g++) = channel2; channel = *(xt++) + *(yt + 2); channel2 = channel + (channel >> 3); if (channel2 < channel) channel2 = ~0; - *(pb++) = channel2; + *(b++) = channel2; } } } } +} + + + +struct RendererActions { + unsigned int type; + void (*render)(bool, unsigned int, unsigned int, + unsigned char*, unsigned char*, unsigned char*, + const FbTk::Color*, const FbTk::Color*, + FbTk::ImageControl&); +}; + +const RendererActions render_gradient_actions[] = { + { FbTk::Texture::DIAGONAL, renderDGradient }, + { FbTk::Texture::ELLIPTIC, renderEGradient }, + { FbTk::Texture::HORIZONTAL, renderHGradient }, + { FbTk::Texture::PYRAMID, renderPGradient }, + { FbTk::Texture::RECTANGLE, renderRGradient }, + { FbTk::Texture::VERTICAL, renderVGradient }, + { FbTk::Texture::CROSSDIAGONAL, renderCDGradient }, + { FbTk::Texture::PIPECROSS, renderPCGradient } +}; + +const RendererActions render_bevel_actions[] = { + { FbTk::Texture::BEVEL1, renderBevel1 }, + { FbTk::Texture::BEVEL2, renderBevel2 } +}; } +namespace FbTk { + +TextureRender::TextureRender(ImageControl &imgctrl, + unsigned int w, unsigned int h, + FbTk::Orientation orient): + control(imgctrl), + cpc(imgctrl.colorsPerChannel()), + cpccpc(cpc * cpc), + red(0), green(0), blue(0), + orientation(orient), + width(w), + height(h) { + + Display* d = App::instance()->display(); + Screen* s = ScreenOfDisplay(d, imgctrl.screenNumber()); + + unsigned int texture_max_width = WidthOfScreen(s) * 2; + unsigned int texture_max_height = HeightOfScreen(s) * 2; + + _FB_USES_NLS; + // clamp to "normal" size + if (width > texture_max_width) { + cerr<<"TextureRender: "<<_FBTK_CONSOLETEXT(Error, BigWidth, "Warning! Width > 3200 setting Width = 3200", "Image width seems too big, clamping")< texture_max_height) { + cerr<<"TextureRender: "<<_FBTK_CONSOLETEXT(Error, BigHeight, "Warning! Height > 3200 setting Height = 3200", "Image height seems too big, clamping")<display(), + control.screenNumber()), + width, height, + control.depth()); + + if (pixmap.drawable() == None) { + _FB_USES_NLS; + cerr<<"FbTk::TextureRender::render_solid(): "<<_FBTK_CONSOLETEXT(Error, CreatePixmap, "Error creating pixmap", "Couldn't create a pixmap - image - for some reason")<display(); + XImage *image = + XCreateImage(disp, + DefaultVisual(disp, control.screenNumber()), control.depth(), ZPixmap, 0, 0, + width, height, 32, 0); + + if (! image) { + _FB_USES_NLS; + cerr << "FbTk::TextureRender::renderXImage(): " << _FBTK_CONSOLETEXT(Error, CreateXImage, "Can't create XImage", "Couldn't create an XImage") << "." << endl; + return 0; + } + + image->data = 0; + + unsigned char *d = new unsigned char[image->bytes_per_line * (height + 1)]; + register unsigned int x, y, r, g, b, o, offset; + + unsigned char *pixel_data = d, *ppixel_data = d; + unsigned long pixel; + + o = image->bits_per_pixel + ((image->byte_order == MSBFirst) ? 1 : 0); + + switch (control.visual()->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++ = control.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); + + switch (o) { + 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; + } + } + + 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++ = control.colors()[g].pixel; + } + + pixel_data = (ppixel_data += image->bytes_per_line); + } + + break; + + default: + _FB_USES_NLS; + cerr << "TextureRender::renderXImage(): " << + _FBTK_CONSOLETEXT(Error, UnsupportedVisual, "Unsupported visual", "A visual is a technical term in X") << endl; + delete [] d; + XDestroyImage(image); + return (XImage *) 0; + } + + image->data = (char *) d; + return image; +} + + +Pixmap TextureRender::renderPixmap() { + Display *disp = FbTk::App::instance()->display(); + FbPixmap pixmap(RootWindow(disp, control.screenNumber()), + width, height, control.depth()); + + if (pixmap.drawable() == None) { + _FB_USES_NLS; + cerr<<"FbTk::TextureRender::renderPixmap(): "<<_FBTK_CONSOLETEXT(Error, CreatePixmap, "Error creating pixmap", "Couldn't create a pixmap - image - for some reason")<data) { + XDestroyImage(image); + return None; + } + + XPutImage(disp, pixmap.drawable(), + DefaultGC(disp, control.screenNumber()), + image, 0, 0, 0, 0, width, height); + + if (image->data != 0) { + delete [] image->data; + image->data = 0; + } + + XDestroyImage(image); + + pixmap.rotate(orientation); + + return pixmap.release(); +} + + } // end namespace FbTk + diff --git a/src/FbTk/TextureRender.hh b/src/FbTk/TextureRender.hh index 158625eb..7896c06e 100644 --- a/src/FbTk/TextureRender.hh +++ b/src/FbTk/TextureRender.hh @@ -31,7 +31,6 @@ namespace FbTk { -class Color; class ImageControl; class Texture; @@ -42,8 +41,7 @@ class Texture; class TextureRender { public: TextureRender(ImageControl &ic, unsigned int width, unsigned int height, - Orientation orient = ROT0, - XColor *_colors=0, size_t num_colors=0); + Orientation orient = ROT0); ~TextureRender(); /// render to pixmap Pixmap render(const FbTk::Texture &src_texture); @@ -66,36 +64,15 @@ private: @returns allocated and rendered XImage, user is responsible to deallocate */ XImage *renderXImage(); - /** - @name render functions - */ - //@{ - void invert(); - void bevel1(); - void bevel2(); - void dgradient(); - void egradient(); - void hgradient(); - void pgradient(); - void rgradient(); - void vgradient(); - void cdgradient(); - void pcgradient(); - //@} ImageControl &control; - bool interlaced; - XColor *colors; // color table - - const FbTk::Color *from, *to; int red_offset, green_offset, blue_offset, red_bits, green_bits, blue_bits, - ncolors, cpc, cpccpc; + cpc, cpccpc; unsigned char *red, *green, *blue; const unsigned char *red_table, *green_table, *blue_table; Orientation orientation; unsigned int width, height; - unsigned int *xtable, *ytable; }; } // end namespace FbTk