all repos — fluxbox @ e84c64f7be701e04ec2a2e0fbf980aa4fc9685ad

custom fork of the fluxbox windowmanager

lots of code cleanup, reordering, trimming public API, bugfixes

## FbTk/ImageControl.hh:

* moved 'getSqrt()' over to TextureRender.cc because it is used only there
* removed unused members m_root_window
* use std::vector<> for colors and for the gradient buffers.

## FbTk/ImageControl.cc:

* fixed memory leak in '~ImageControl', 'pixels' where not deleted[]
  at all. switched to std::vector, non-issue anymore.
* moved identical code into functions 'allocateUnallocatedColors', 'initColortables'

## FbTk/TextureRenderer:

* removed 'from', 'to', 'interlaced' from class, only used in
  'renderGradient()' and are actually part of the given
  texture.
* removed 'xtable', 'ytable' from class, only used in
  'renderGradient()'
* removed 'colors' from the class, is part of 'control'
* moved render actions (invert, bevel1, bevel2, *gradient), they need more
  love but for now this is sufficient
Mathias Gumz akira at fluxbox dot org
commit

e84c64f7be701e04ec2a2e0fbf980aa4fc9685ad

parent

603b36a2ccfb6f825dff7259c4d5397c896cc08e

4 files changed, 916 insertions(+), 894 deletions(-)

jump to
M src/FbTk/ImageControl.ccsrc/FbTk/ImageControl.cc

@@ -49,11 +49,6 @@ #include <cstdlib>

#else #include <stdlib.h> #endif -#ifdef HAVE_CSTRING - #include <cstring> -#else - #include <string.h> -#endif #ifdef HAVE_CSTDIO #include <cstdio> #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,20 +72,97 @@ 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; + for (unsigned int i = 0; i < 256; i++) { + red[i] = i / red_bits; + green[i] = i / green_bits; + blue[i] = i / blue_bits; + } +} - unsigned long r = x >> 1; - unsigned long q; +// tries to allocate all unallocated 'colors' by finding a close color based +// upon entries in the colormap. +// +void allocateUnallocatedColors(std::vector<XColor> 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; - while (1) { - q = x / r; - if (q >= r) return r; - r = (r + q) >> 1; + // try to allocate it + if (XAllocColor(dpy, cmap, &colors[i])) { + colors[i].flags = DoRed|DoGreen|DoBlue; // mark it allocated + break; + } + } + } + } } } + } // end anonymous namespace

@@ -106,15 +176,12 @@ };

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() { - 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<unsigned long> 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 @@ for (; it != it_end; ++it) {

XFreePixmap(disp, (*it)->pixmap); delete (*it); } - } - }

@@ -235,7 +286,7 @@ return ParentRelative;

// 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 @@ }

// 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 @@ unsigned int h,

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 @@

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 @@

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::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 @@ red_offset = green_offset = blue_offset = 0;

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 @@ red_bits = 255 / red_mask;

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 @@

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<unsigned int>(1 << m_screen_depth)) { + if (num_colors > static_cast<unsigned>(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<unsigned int>(1 << m_screen_depth)) { - fprintf(stderr, "ImageControl::ImageControl: invalid colormap size %d " + if (m_colors_per_channel < 2 || num_colors > static_cast<unsigned>(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 @@ }

} } - 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<unsigned int>(1 << m_screen_depth)) { + if (num_colors > static_cast<unsigned>(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<unsigned int>(1 << m_screen_depth)) { - fprintf(stderr,"FbTk::ImageControl: invalid colormap size %d " + if (m_colors_per_channel < 2 || num_colors > static_cast<unsigned>(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; }
M src/FbTk/ImageControl.hhsrc/FbTk/ImageControl.hh

@@ -30,7 +30,9 @@ #include "Timer.hh"

#include "NotCopyable.hh" #include <X11/Xlib.h> // for Visual* etc + #include <list> +#include <vector> namespace FbTk {

@@ -45,9 +47,10 @@ virtual ~ImageControl();

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 @@ Timer m_timer;

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<XColor> 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<unsigned int> grad_xbuffer; + std::vector<unsigned int> grad_ybuffer; struct Cache; typedef std::list<Cache *> CacheList;
M src/FbTk/TextureRender.ccsrc/FbTk/TextureRender.cc

@@ -31,11 +31,12 @@ #include "App.hh"

#include "FbPixmap.hh" #include "GContext.hh" #include "I18n.hh" +#include "StringUtil.hh" #include <X11/Xutil.h> #include <iostream> -#include <string> + #ifdef HAVE_CSTDIO #include <cstdio> #else

@@ -60,437 +61,66 @@ using std::string;

using std::max; using std::min; -namespace FbTk { - -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<int>(num_colors)), - cpc(imgctrl.colorsPerChannel()), - cpccpc(cpc * cpc), - red(0), green(0), blue(0), - orientation(orient), - width(static_cast<signed>((w > 0 ? w : 1))), height(static_cast<signed>(h > 0 ? h : 1)), - xtable(0), ytable(0) { - - 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; - - _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")<<endl; - width = texture_max_width; - } - - if (height > texture_max_height) { - cerr<<"TextureRender: "<<_FBTK_CONSOLETEXT(Error, BigHeight, "Warning! Height > 3200 setting Height = 3200", "Image height seems too big, clamping")<<endl; - height = texture_max_height; - } - - - imgctrl.colorTables(&red_table, &green_table, &blue_table, - &red_offset, &green_offset, &blue_offset, - &red_bits, &green_bits, &blue_bits); - -} - - -TextureRender::~TextureRender() { - if (red != 0) delete [] red; - if (green != 0) delete [] green; - if (blue != 0) delete [] blue; -} - - -Pixmap TextureRender::render(const FbTk::Texture &texture) { - if (texture.pixmap().drawable() != 0) - return renderPixmap(texture); - else if (texture.type() & FbTk::Texture::PARENTRELATIVE) - return ParentRelative; - else if (texture.type() & FbTk::Texture::SOLID) - return renderSolid(texture); - else if (texture.type() & FbTk::Texture::GRADIENT) { - allocateColorTables(); - return renderGradient(texture); - } - - return None; -} - -void TextureRender::allocateColorTables() { - - _FB_USES_NLS; - - const size_t size = width * height; - red = FB_new_nothrow unsigned char[size]; - - if (red == 0) { - char sbuf[128]; - sprintf(sbuf, "%ld", (long int) size); - throw string("TextureRender::TextureRender(): " + - string(_FBTK_CONSOLETEXT(Error, OutOfMemoryRed, "Out of memory while allocating red buffer.", "")) + string(sbuf)); - } - - - green = FB_new_nothrow unsigned char[size]; - if (green == 0) { - char sbuf[128]; - sprintf(sbuf, "%ld", (long int) size); - throw string("TextureRender::TextureRender(): " + - string(_FBTK_CONSOLETEXT(Error, OutOfMemoryGreen, "Out of memory while allocating green buffer.", ""))+ string(sbuf)); - } - - blue = FB_new_nothrow unsigned char[size]; - if (blue == 0) { - char sbuf[128]; - sprintf(sbuf, "%ld", (long int) size); - throw string("TextureRender::TextureRender(): " + - string(_FBTK_CONSOLETEXT(Error, OutOfMemoryBlue, "Out of memory while allocating blue buffer.", ""))+ string(sbuf)); - } - - -} - -Pixmap TextureRender::renderSolid(const FbTk::Texture &texture) { - - FbPixmap pixmap(RootWindow(FbTk::App::instance()->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")<<endl; - return None; - } - - - FbTk::GContext gc(pixmap), - hgc(pixmap), lgc(pixmap); - - gc.setForeground(texture.color()); - gc.setFillStyle(FillSolid); - - hgc.setForeground(texture.hiColor()); - - pixmap.fillRectangle(gc.gc(), 0, 0, width, height); - - using namespace FbTk; - - if (texture.type() & Texture::INTERLACED) { - lgc.setForeground(texture.colorTo()); - register unsigned int i = 0; - for (; i < height; i += 2) - pixmap.drawLine(lgc.gc(), 0, i, width, i); - - } - - lgc.setForeground(texture.loColor()); - - if (texture.type() & Texture::BEVEL1) { - if (texture.type() & Texture::RAISED) { - pixmap.drawLine(lgc.gc(), - 0, height - 1, width - 1, height - 1); - pixmap.drawLine(lgc.gc(), - width - 1, height - 1, width - 1, 0); - - pixmap.drawLine(hgc.gc(), - 0, 0, width - 1, 0); - pixmap.drawLine(hgc.gc(), - 0, height - 1, 0, 0); - } else if (texture.type() & Texture::SUNKEN) { - pixmap.drawLine(hgc.gc(), - 0, height - 1, width - 1, height - 1); - pixmap.drawLine(hgc.gc(), - width - 1, height - 1, width - 1, 0); - - pixmap.drawLine(lgc.gc(), - 0, 0, width - 1, 0); - pixmap.drawLine(lgc.gc(), - 0, height - 1, 0, 0); - } - } else if (texture.type() & Texture::BEVEL2) { - if (texture.type() & Texture::RAISED) { - pixmap.drawLine(lgc.gc(), - 1, height - 3, width - 3, height - 3); - pixmap.drawLine(lgc.gc(), - width - 3, height - 3, width - 3, 1); - - pixmap.drawLine(hgc.gc(), - 1, 1, width - 3, 1); - pixmap.drawLine(hgc.gc(), - 1, height - 3, 1, 1); - } else if (texture.type() & Texture::SUNKEN) { - pixmap.drawLine(hgc.gc(), - 1, height - 3, width - 3, height - 3); - pixmap.drawLine(hgc.gc(), - width - 3, height - 3, width - 3, 1); - - pixmap.drawLine(lgc.gc(), - 1, 1, width - 3, 1); - pixmap.drawLine(lgc.gc(), - 1, height - 3, 1, 1); - } - } - - return pixmap.release(); -} - - -Pixmap TextureRender::renderGradient(const FbTk::Texture &texture) { - - bool inverted = false; - - // invert our width and height if necessary - translateSize(orientation, width, height); - - using namespace FbTk; - - interlaced = texture.type() & Texture::INTERLACED; - - if (texture.type() & Texture::SUNKEN) { - from = &(texture.colorTo()); - to = &(texture.color()); - - if (! (texture.type() & Texture::INVERT)) - inverted = true; - } else { - from = &(texture.color()); - to = &(texture.colorTo()); - - if (texture.type() & Texture::INVERT) - inverted = true; - } - - control.getGradientBuffers(width, height, &xtable, &ytable); - - if (texture.type() & Texture::DIAGONAL) - dgradient(); - else if (texture.type() & Texture::ELLIPTIC) - egradient(); - else if (texture.type() & Texture::HORIZONTAL) - hgradient(); - else if (texture.type() & Texture::PYRAMID) - pgradient(); - else if (texture.type() & Texture::RECTANGLE) - rgradient(); - else if (texture.type() & Texture::VERTICAL) - vgradient(); - else if (texture.type() & Texture::CROSSDIAGONAL) - cdgradient(); - else if (texture.type() & Texture::PIPECROSS) - pcgradient(); +namespace { - if (texture.type() & Texture::BEVEL1) - bevel1(); - else if (texture.type() & Texture::BEVEL2) - bevel2(); +unsigned long bsqrt(unsigned int x) { - if (inverted) - invert(); + static const size_t SQRT_TABLE_ENTRIES = 256 * 256 * 2; - return renderPixmap(); + // '362' == bsqrt(256 * 256 * 2), fits into a short + static unsigned short sqrt_table[SQRT_TABLE_ENTRIES] = { 1 }; -} + // build sqrt table for use with elliptic gradient + // sqrt_table[0] is set to 0 after the initial run + if (sqrt_table[0] == 1) { + sqrt_table[0] = 0; + sqrt_table[1] = 1; -Pixmap TextureRender::renderPixmap(const FbTk::Texture &src_texture) { - unsigned int tmpw = width, tmph = height; - // we are given width and height in rotated form, we - // unrotate it here to render it - translateSize(orientation, tmpw, tmph); - if (tmpw != src_texture.pixmap().width() || - tmph != src_texture.pixmap().height()) { - - // copy src_texture's pixmap and - // scale/tile to fit our size - FbPixmap new_pm(src_texture.pixmap()); - - if ((src_texture.type() & Texture::TILED)) { - new_pm.tile(tmpw,tmph); - } else { - new_pm.scale(tmpw, tmph); - } - new_pm.rotate(orientation); - return new_pm.release(); - } - // return copy of pixmap - FbPixmap pm_copy = FbPixmap(src_texture.pixmap()); - pm_copy.rotate(orientation); - - return pm_copy.release(); -} - -XImage *TextureRender::renderXImage() { - Display *disp = FbTk::App::instance()->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<unsigned short>(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<size_t>(x), SQRT_TABLE_ENTRIES - 1)]; } - -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")<<endl; - return None; - } + x1 y1 ---- gc1 ---- x2 y1 + | | + | | + gc2 gc1 + | | + | | + x1 y2 ---- gc2 ---- x2 y2 - XImage *image = renderXImage(); + */ +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); +} - if (! image) { - return None; - } else if (! image->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); +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) { - return pixmap.release(); -} - - -void TextureRender::bevel1() { if (! (width > 2 && height > 2)) return;

@@ -629,7 +259,13 @@ *pb = bb;

} -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,142 +345,41 @@ }

} -void TextureRender::invert() { - 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; +void invertRGB(unsigned int w, unsigned int h, + unsigned char* r, unsigned char* g, unsigned char* b) { - tmp = *(green + j); - *(green + j) = *(green + i); - *(green + i) = tmp; + register unsigned int i, j, wh = (w * h) - 1; - tmp = *(blue + j); - *(blue + j) = *(blue + i); - *(blue + i) = tmp; + for (i = 0, j = wh; j > i; j--, i++) { + 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 <mike@mydot.com> - // 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, + 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 int w = width * 2, h = height * 2; - unsigned int *xt = xtable, *yt = ytable; + unsigned char* red = r; + unsigned char* green = g; + unsigned char* blue = b; + unsigned int* xtable; + unsigned int* 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); + imgctrl.getGradientBuffers(width, height, &xtable, &ytable); - 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; - - register unsigned int x, y; drx = (float) (to->red() - from->red()); dgx = (float) (to->green() - from->green());

@@ -858,88 +393,96 @@ if (interlaced && height > 2) {

// 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());

@@ -953,37 +496,37 @@ if (interlaced) {

// 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 @@ }

} 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,19 +551,29 @@

} -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());

@@ -1072,9 +625,9 @@

// 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 @@ if (y & 1) {

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::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 @@

// 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,54 +765,183 @@ if (y & 1) {

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 <mike@mydot.com> +// 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; - 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());

@@ -1297,12 +990,12 @@ 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)))); + *(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 @@ 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)))); + (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,20 +1049,30 @@

} -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; - 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());

@@ -1419,9 +1122,9 @@

// 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,53 +1138,63 @@ if (y & 1) {

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());

@@ -1523,9 +1236,9 @@ 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); + *(r++) = *(xt++) + *(yt); + *(g++) = *(xt++) + *(yt + 1); + *(b++) = *(xt++) + *(yt + 2); } }

@@ -1539,37 +1252,444 @@ if (y & 1) {

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")<<endl; + width = texture_max_width; + } + + if (height > texture_max_height) { + cerr<<"TextureRender: "<<_FBTK_CONSOLETEXT(Error, BigHeight, "Warning! Height > 3200 setting Height = 3200", "Image height seems too big, clamping")<<endl; + height = texture_max_height; + } + + imgctrl.colorTables(&red_table, &green_table, &blue_table, + &red_offset, &green_offset, &blue_offset, + &red_bits, &green_bits, &blue_bits); + +} + + +TextureRender::~TextureRender() { + if (red != 0) delete [] red; + if (green != 0) delete [] green; + if (blue != 0) delete [] blue; +} + + +Pixmap TextureRender::render(const FbTk::Texture &texture) { + if (texture.pixmap().drawable() != 0) + return renderPixmap(texture); + else if (texture.type() & FbTk::Texture::PARENTRELATIVE) + return ParentRelative; + else if (texture.type() & FbTk::Texture::SOLID) + return renderSolid(texture); + else if (texture.type() & FbTk::Texture::GRADIENT) { + allocateColorTables(); + return renderGradient(texture); + } + + return None; +} + +void TextureRender::allocateColorTables() { + + _FB_USES_NLS; + + const size_t size = width * height; + + red = FB_new_nothrow unsigned char[size]; + if (red == 0) { + throw string("TextureRender::TextureRender(): ") + + string(_FBTK_CONSOLETEXT(Error, OutOfMemoryRed, + "Out of memory while allocating red buffer.", "")) + + StringUtil::number2String(size); + } + + + green = FB_new_nothrow unsigned char[size]; + if (green == 0) { + throw string("TextureRender::TextureRender(): ") + + string(_FBTK_CONSOLETEXT(Error, OutOfMemoryGreen, + "Out of memory while allocating green buffer.", "")) + + StringUtil::number2String(size); + } + + blue = FB_new_nothrow unsigned char[size]; + if (blue == 0) { + throw string("TextureRender::TextureRender(): ") + + string(_FBTK_CONSOLETEXT(Error, OutOfMemoryBlue, + "Out of memory while allocating blue buffer.", "")) + + StringUtil::number2String(size); + } + + +} + +Pixmap TextureRender::renderSolid(const FbTk::Texture &texture) { + + FbPixmap pixmap(RootWindow(FbTk::App::instance()->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")<<endl; + return None; + } + + + FbTk::GContext gc(pixmap), + hgc(pixmap), lgc(pixmap); + + gc.setForeground(texture.color()); + gc.setFillStyle(FillSolid); + + hgc.setForeground(texture.hiColor()); + + pixmap.fillRectangle(gc.gc(), 0, 0, width, height); + + if (texture.type() & Texture::INTERLACED) { + lgc.setForeground(texture.colorTo()); + register unsigned int i = 0; + for (; i < height; i += 2) + pixmap.drawLine(lgc.gc(), 0, i, width, i); + + } + + lgc.setForeground(texture.loColor()); + + if (texture.type() & Texture::BEVEL1) { + if (texture.type() & Texture::RAISED) { + drawBevelRectangle(pixmap, lgc.gc(), hgc.gc(), 0, height - 1, width -1 , 0); + } else if (texture.type() & Texture::SUNKEN) { + drawBevelRectangle(pixmap, hgc.gc(), lgc.gc(), 0, height - 1, width - 1, 0); + } + } else if (texture.type() & Texture::BEVEL2) { + if (texture.type() & Texture::RAISED) { + drawBevelRectangle(pixmap, lgc.gc(), hgc.gc(), 1, height - 3, width - 3, 1); + } else if (texture.type() & Texture::SUNKEN) { + drawBevelRectangle(pixmap, hgc.gc(), lgc.gc(), 1, height - 3, width - 3, 1); + } + } + + return pixmap.release(); +} + + +Pixmap TextureRender::renderGradient(const FbTk::Texture &texture) { + + // invert our width and height if necessary + translateSize(orientation, width, height); + + bool inverted = texture.type() & Texture::SUNKEN; + const Color* from = &(texture.color()); + const Color* to = &(texture.colorTo()); + + if (texture.type() & Texture::SUNKEN) { + std::swap(from, to); + inverted = !inverted; + } + + size_t i; + // draw gradient + for (i = 0; i < sizeof(render_gradient_actions)/sizeof(RendererActions); ++i) { + if (render_gradient_actions[i].type & texture.type()) { + render_gradient_actions[i].render(texture.type() & Texture::INTERLACED, + width, height, red, green, blue, from, to, control); + break; + } + } + + // draw bevel + for (i = 0; i < sizeof(render_bevel_actions)/sizeof(RendererActions); ++i) { + if (render_bevel_actions[i].type & texture.type()) { + render_bevel_actions[i].render(texture.type() & Texture::INTERLACED, + width, height, red, green, blue, from, to, control); + break; + } + } + + if (inverted) + invertRGB(width, height, red, green, blue); + + return renderPixmap(); + +} + +Pixmap TextureRender::renderPixmap(const FbTk::Texture &src_texture) { + unsigned int tmpw = width, tmph = height; + // we are given width and height in rotated form, we + // unrotate it here to render it + translateSize(orientation, tmpw, tmph); + if (tmpw != src_texture.pixmap().width() || + tmph != src_texture.pixmap().height()) { + + // copy src_texture's pixmap and + // scale/tile to fit our size + FbPixmap new_pm(src_texture.pixmap()); + + if ((src_texture.type() & Texture::TILED)) { + new_pm.tile(tmpw,tmph); + } else { + new_pm.scale(tmpw, tmph); + } + new_pm.rotate(orientation); + return new_pm.release(); + } + // return copy of pixmap + FbPixmap pm_copy = FbPixmap(src_texture.pixmap()); + pm_copy.rotate(orientation); + + return pm_copy.release(); +} + +XImage *TextureRender::renderXImage() { + Display *disp = FbTk::App::instance()->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")<<endl; + return None; + } + + XImage *image = renderXImage(); + + if (! image) { + return None; + } else if (! image->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 +
M src/FbTk/TextureRender.hhsrc/FbTk/TextureRender.hh

@@ -31,7 +31,6 @@ #include <X11/Xlib.h>

namespace FbTk { -class Color; class ImageControl; class Texture;

@@ -42,8 +41,7 @@ */

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 @@ Render to XImage

@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