From e84c64f7be701e04ec2a2e0fbf980aa4fc9685ad Mon Sep 17 00:00:00 2001 From: Mathias Gumz Date: Fri, 17 Sep 2010 15:34:12 +0200 Subject: 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 --- src/FbTk/ImageControl.cc | 334 +++---- src/FbTk/ImageControl.hh | 19 +- src/FbTk/TextureRender.cc | 2196 ++++++++++++++++++++++++--------------------- src/FbTk/TextureRender.hh | 27 +- 4 files changed, 1299 insertions(+), 1277 deletions(-) diff --git a/src/FbTk/ImageControl.cc b/src/FbTk/ImageControl.cc index 39fb4a7..19d8793 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) { + + 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) { -inline unsigned long bsqrt(unsigned long x) { - if (x <= 0) return 0; - if (x == 1) return 1; + unsigned int i; - unsigned long r = x >> 1; - unsigned long q; + bool done = true; - while (1) { - q = x / r; - if (q >= r) return r; - r = (r + q) >> 1; + // 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]; - - for (unsigned int color = 0; color < m_num_colors; color++) - *(pixels + color) = (*(m_colors + color)).pixel; + if (!m_colors.empty()) { + std::vector pixels; - XFreeColors(disp, m_colormap, pixels, m_num_colors, 0); + for (unsigned int i = 0; i < m_colors.size(); i++) + pixels[i] = m_colors[i].pixel; - 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; - } - - grad_buffer_width = w; - - grad_xbuffer = new unsigned int[grad_buffer_width * 3]; - } - - if (h > grad_buffer_height) { - if (grad_ybuffer) { - delete [] grad_ybuffer; - } + if (w > grad_xbuffer.size()) + grad_xbuffer.resize(w * 3); - grad_buffer_height = h; + if (h > grad_ybuffer.size()) + grad_ybuffer.resize(h * 3); - 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 b7b90f7..747525b 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 116142d..1fb38c6 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,689 +61,770 @@ 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")<> 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; + } + } + } - imgctrl.colorTables(&red_table, &green_table, &blue_table, - &red_offset, &green_offset, &blue_offset, - &red_bits, &green_bits, &blue_bits); + 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); } -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 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) { -void TextureRender::allocateColorTables() { + if (! (width > 2 && height > 2)) + return; - _FB_USES_NLS; + unsigned char *pr = red, *pg = green, *pb = blue; - const size_t size = width * height; - red = FB_new_nothrow unsigned char[size]; + register unsigned char r, g, b, rr ,gg ,bb; + register unsigned int w = width, h = height - 1, wh = w * h; - 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)); - } + while (--w) { + r = *pr; + rr = r + (r >> 1); + if (rr < r) rr = ~0; + g = *pg; + gg = g + (g >> 1); + if (gg < g) gg = ~0; + b = *pb; + bb = b + (b >> 1); + if (bb < b) bb = ~0; + *pr = rr; + *pg = gg; + *pb = bb; - 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)); - } + r = *(pr + wh); + rr = (r >> 2) + (r >> 1); + if (rr > r) rr = 0; + g = *(pg + wh); + gg = (g >> 2) + (g >> 1); + if (gg > g) gg = 0; + b = *(pb + wh); + bb = (b >> 2) + (b >> 1); + if (bb > b) bb = 0; - 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)); + *((pr++) + wh) = rr; + *((pg++) + wh) = gg; + *((pb++) + wh) = bb; } + r = *pr; + rr = r + (r >> 1); + if (rr < r) rr = ~0; + g = *pg; + gg = g + (g >> 1); + if (gg < g) gg = ~0; + b = *pb; + bb = b + (b >> 1); + if (bb < b) bb = ~0; -} - -Pixmap TextureRender::renderSolid(const FbTk::Texture &texture) { + *pr = rr; + *pg = gg; + *pb = bb; - FbPixmap pixmap(RootWindow(FbTk::App::instance()->display(), - control.screenNumber()), - width, height, - control.depth()); + r = *(pr + wh); + rr = (r >> 2) + (r >> 1); + if (rr > r) rr = 0; + g = *(pg + wh); + gg = (g >> 2) + (g >> 1); + if (gg > g) gg = 0; + b = *(pb + wh); + bb = (b >> 2) + (b >> 1); + if (bb > b) bb = 0; - 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")<> 1); + if (rr < r) rr = ~0; + g = *pg; + gg = g + (g >> 1); + if (gg < g) gg = ~0; + b = *pb; + bb = b + (b >> 1); + if (bb < b) bb = ~0; - gc.setForeground(texture.color()); - gc.setFillStyle(FillSolid); + *pr = rr; + *pg = gg; + *pb = bb; - hgc.setForeground(texture.hiColor()); + pr += width - 1; + pg += width - 1; + pb += width - 1; - pixmap.fillRectangle(gc.gc(), 0, 0, width, height); + r = *pr; + rr = (r >> 2) + (r >> 1); + if (rr > r) rr = 0; + g = *pg; + gg = (g >> 2) + (g >> 1); + if (gg > g) gg = 0; + b = *pb; + bb = (b >> 2) + (b >> 1); + if (bb > b) bb = 0; - using namespace FbTk; + *(pr++) = rr; + *(pg++) = gg; + *(pb++) = bb; + } - 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); + r = *pr; + rr = r + (r >> 1); + if (rr < r) rr = ~0; + g = *pg; + gg = g + (g >> 1); + if (gg < g) gg = ~0; + b = *pb; + bb = b + (b >> 1); + if (bb < b) bb = ~0; - } + *pr = rr; + *pg = gg; + *pb = bb; - lgc.setForeground(texture.loColor()); + pr += width - 1; + pg += width - 1; + pb += width - 1; - 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); - } - } + r = *pr; + rr = (r >> 2) + (r >> 1); + if (rr > r) rr = 0; + g = *pg; + gg = (g >> 2) + (g >> 1); + if (gg > g) gg = 0; + b = *pb; + bb = (b >> 2) + (b >> 1); + if (bb > b) bb = 0; - return pixmap.release(); + *pr = rr; + *pg = gg; + *pb = bb; } -Pixmap TextureRender::renderGradient(const FbTk::Texture &texture) { - bool inverted = false; +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) { - // invert our width and height if necessary - translateSize(orientation, width, height); + if (! (width > 4 && height > 4)) + return; - using namespace FbTk; + unsigned char r, g, b, rr ,gg ,bb, *pr = red + width + 1, + *pg = green + width + 1, *pb = blue + width + 1; + unsigned int w = width - 2, h = height - 1, wh = width * (height - 3); - interlaced = texture.type() & Texture::INTERLACED; + while (--w) { + r = *pr; + rr = r + (r >> 1); + if (rr < r) rr = ~0; + g = *pg; + gg = g + (g >> 1); + if (gg < g) gg = ~0; + b = *pb; + bb = b + (b >> 1); + if (bb < b) bb = ~0; - if (texture.type() & Texture::SUNKEN) { - from = &(texture.colorTo()); - to = &(texture.color()); + *pr = rr; + *pg = gg; + *pb = bb; - if (! (texture.type() & Texture::INVERT)) - inverted = true; - } else { - from = &(texture.color()); - to = &(texture.colorTo()); + r = *(pr + wh); + rr = (r >> 2) + (r >> 1); + if (rr > r) rr = 0; + g = *(pg + wh); + gg = (g >> 2) + (g >> 1); + if (gg > g) gg = 0; + b = *(pb + wh); + bb = (b >> 2) + (b >> 1); + if (bb > b) bb = 0; - if (texture.type() & Texture::INVERT) - inverted = true; + *((pr++) + wh) = rr; + *((pg++) + wh) = gg; + *((pb++) + wh) = bb; } - 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(); - - if (texture.type() & Texture::BEVEL1) - bevel1(); - else if (texture.type() & Texture::BEVEL2) - bevel2(); - - if (inverted) - invert(); + pr = red + width; + pg = green + width; + pb = blue + width; - return renderPixmap(); + while (--h) { + r = *pr; + rr = r + (r >> 1); + if (rr < r) rr = ~0; + g = *pg; + gg = g + (g >> 1); + if (gg < g) gg = ~0; + b = *pb; + bb = b + (b >> 1); + if (bb < b) bb = ~0; -} + *(++pr) = rr; + *(++pg) = gg; + *(++pb) = bb; -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()) { + pr += width - 3; + pg += width - 3; + pb += width - 3; - // copy src_texture's pixmap and - // scale/tile to fit our size - FbPixmap new_pm(src_texture.pixmap()); + r = *pr; + rr = (r >> 2) + (r >> 1); + if (rr > r) rr = 0; + g = *pg; + gg = (g >> 2) + (g >> 1); + if (gg > g) gg = 0; + b = *pb; + bb = (b >> 2) + (b >> 1); + if (bb > b) bb = 0; - 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); + *(pr++) = rr; + *(pg++) = gg; + *(pb++) = bb; - return pm_copy.release(); + pr++; pg++; pb++; + } } -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; +void invertRGB(unsigned int w, unsigned int h, + unsigned char* r, unsigned char* g, unsigned char* b) { - o = image->bits_per_pixel + ((image->byte_order == MSBFirst) ? 1 : 0); + register unsigned int i, j, wh = (w * h) - 1; - 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]]; + 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)); + } +} - pixel = (r * cpccpc) + (g * cpc) + b; - *pixel_data++ = colors[pixel].pixel; - } - pixel_data = (ppixel_data += image->bytes_per_line); - } +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) { - break; + float drx, dgx, dbx, + xr = (float) from->red(), + xg = (float) from->green(), + xb = (float) from->blue(); - 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]]; + unsigned char* red = r; + unsigned char* green = g; + unsigned char* blue = b; + unsigned int* xtable; + unsigned int* ytable; + register unsigned int x, y; - pixel = (r << red_offset) | (g << green_offset) | (b << blue_offset); + imgctrl.getGradientBuffers(width, height, &xtable, &ytable); - switch (o) { - case 8: // 8bpp - *pixel_data++ = pixel; - break; - case 16: // 16bpp LSB - *pixel_data++ = pixel; - *pixel_data++ = pixel >> 8; - break; + drx = (float) (to->red() - from->red()); + dgx = (float) (to->green() - from->green()); + dbx = (float) (to->blue() - from->blue()); - case 17: // 16bpp MSB - *pixel_data++ = pixel >> 8; - *pixel_data++ = pixel; - break; + drx /= width; + dgx /= width; + dbx /= width; - case 24: // 24bpp LSB - *pixel_data++ = pixel; - *pixel_data++ = pixel >> 8; - *pixel_data++ = pixel >> 16; - break; + if (interlaced && height > 2) { + // faked interlacing effect + unsigned char channel, channel2; - case 25: // 24bpp MSB - *pixel_data++ = pixel >> 16; - *pixel_data++ = pixel >> 8; - *pixel_data++ = pixel; - break; + for (x = 0; x < width; x++, r++, g++, b++) { + channel = (unsigned char) xr; + channel2 = (channel >> 1) + (channel >> 2); + if (channel2 > channel) channel2 = 0; + *r = channel2; - case 32: // 32bpp LSB - *pixel_data++ = pixel; - *pixel_data++ = pixel >> 8; - *pixel_data++ = pixel >> 16; - *pixel_data++ = pixel >> 24; - break; + channel = (unsigned char) xg; + channel2 = (channel >> 1) + (channel >> 2); + if (channel2 > channel) channel2 = 0; + *g = channel2; - case 33: // 32bpp MSB - *pixel_data++ = pixel >> 24; - *pixel_data++ = pixel >> 16; - *pixel_data++ = pixel >> 8; - *pixel_data++ = pixel; - break; - } - } + channel = (unsigned char) xb; + channel2 = (channel >> 1) + (channel >> 2); + if (channel2 > channel) channel2 = 0; + *b = channel2; - pixel_data = (ppixel_data += image->bytes_per_line); - } - break; + channel = (unsigned char) xr; + channel2 = channel + (channel >> 3); + if (channel2 < channel) channel2 = ~0; + *(r + width) = channel2; - 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)); + channel = (unsigned char) xg; + channel2 = channel + (channel >> 3); + if (channel2 < channel) channel2 = ~0; + *(g + width) = channel2; - g = ((r * 30) + (g * 59) + (b * 11)) / 100; - *pixel_data++ = colors[g].pixel; - } + channel = (unsigned char) xb; + channel2 = channel + (channel >> 3); + if (channel2 < channel) channel2 = ~0; + *(b + width) = channel2; - pixel_data = (ppixel_data += image->bytes_per_line); + xr += drx; + xg += dgx; + xb += dbx; } - break; + r += width; + g += width; + b += width; - 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; - } + int offset; - image->data = (char *) d; - return image; -} + for (y = 2; y < height; y++, r += width, g += width, b += width) { + if (y & 1) offset = width; else offset = 0; + memcpy(r, (red + offset), width); + memcpy(g, (green + offset), width); + memcpy(b, (blue + offset), width); + } + } else { -Pixmap TextureRender::renderPixmap() { - Display *disp = FbTk::App::instance()->display(); - FbPixmap pixmap(RootWindow(disp, control.screenNumber()), - width, height, control.depth()); + // normal hgradient + for (x = 0; x < width; x++) { + *(r++) = (unsigned char) (xr); + *(g++) = (unsigned char) (xg); + *(b++) = (unsigned char) (xb); - 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; - } +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) { - XDestroyImage(image); + float dry, dgy, dby, + yr = (float) from->red(), + yg = (float) from->green(), + yb = (float) from->blue(); - pixmap.rotate(orientation); + register unsigned int y; - return pixmap.release(); -} + unsigned int* xtable; + unsigned int* ytable; + imgctrl.getGradientBuffers(width, height, &xtable, &ytable); -void TextureRender::bevel1() { - if (! (width > 2 && height > 2)) - return; + dry = (float) (to->red() - from->red()); + dgy = (float) (to->green() - from->green()); + dby = (float) (to->blue() - from->blue()); - unsigned char *pr = red, *pg = green, *pb = blue; + dry /= height; + dgy /= height; + dby /= height; - register unsigned char r, g, b, rr ,gg ,bb; - register unsigned int w = width, h = height - 1, wh = w * h; + if (interlaced) { + // faked interlacing effect + unsigned char channel, channel2; - while (--w) { - r = *pr; - rr = r + (r >> 1); - if (rr < r) rr = ~0; - g = *pg; - gg = g + (g >> 1); - if (gg < g) gg = ~0; - b = *pb; - bb = b + (b >> 1); - if (bb < b) bb = ~0; + 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(r, channel2, width); - *pr = rr; - *pg = gg; - *pb = bb; + channel = (unsigned char) yg; + channel2 = (channel >> 1) + (channel >> 2); + if (channel2 > channel) channel2 = 0; + memset(g, channel2, width); - r = *(pr + wh); - rr = (r >> 2) + (r >> 1); - if (rr > r) rr = 0; - g = *(pg + wh); - gg = (g >> 2) + (g >> 1); - if (gg > g) gg = 0; - b = *(pb + wh); - bb = (b >> 2) + (b >> 1); - if (bb > b) bb = 0; + channel = (unsigned char) yb; + channel2 = (channel >> 1) + (channel >> 2); + if (channel2 > channel) channel2 = 0; + memset(b, channel2, width); + } else { + channel = (unsigned char) yr; + channel2 = channel + (channel >> 3); + if (channel2 < channel) channel2 = ~0; + memset(r, channel2, width); - *((pr++) + wh) = rr; - *((pg++) + wh) = gg; - *((pb++) + wh) = bb; + channel = (unsigned char) yg; + channel2 = channel + (channel >> 3); + if (channel2 < channel) channel2 = ~0; + memset(g, channel2, width); + + channel = (unsigned char) yb; + channel2 = channel + (channel >> 3); + if (channel2 < channel) channel2 = ~0; + memset(b, channel2, width); + } + + yr += dry; + yg += dgy; + yb += dby; + } + } else { + + // normal vgradient + 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; + yb += dby; + } } - r = *pr; - rr = r + (r >> 1); - if (rr < r) rr = ~0; - g = *pg; - gg = g + (g >> 1); - if (gg < g) gg = ~0; - b = *pb; - bb = b + (b >> 1); - if (bb < b) bb = ~0; - *pr = rr; - *pg = gg; - *pb = bb; +} - r = *(pr + wh); - rr = (r >> 2) + (r >> 1); - if (rr > r) rr = 0; - g = *(pg + wh); - gg = (g >> 2) + (g >> 1); - if (gg > g) gg = 0; - b = *(pb + wh); - bb = (b >> 2) + (b >> 1); - if (bb > b) bb = 0; - *(pr + wh) = rr; - *(pg + wh) = gg; - *(pb + wh) = bb; +// 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) { - pr = red + width; - pg = green + width; - pb = blue + width; + float yr, yg, yb, drx, dgx, dbx, dry, dgy, dby, + xr, xg, xb; + int rsign, gsign, bsign; + unsigned int tr = to->red(), tg = to->green(), tb = to->blue(); + unsigned int* xtable; + unsigned int* ytable; + unsigned int* xt; + unsigned int* yt; - while (--h) { - r = *pr; - rr = r + (r >> 1); - if (rr < r) rr = ~0; - g = *pg; - gg = g + (g >> 1); - if (gg < g) gg = ~0; - b = *pb; - bb = b + (b >> 1); - if (bb < b) bb = ~0; + register unsigned int x, y; - *pr = rr; - *pg = gg; - *pb = bb; + imgctrl.getGradientBuffers(width, height, &xtable, &ytable); + xt = xtable; + yt = ytable; - pr += width - 1; - pg += width - 1; - pb += width - 1; + dry = drx = (float) (to->red() - from->red()); + dgy = dgx = (float) (to->green() - from->green()); + dby = dbx = (float) (to->blue() - from->blue()); - r = *pr; - rr = (r >> 2) + (r >> 1); - if (rr > r) rr = 0; - g = *pg; - gg = (g >> 2) + (g >> 1); - if (gg > g) gg = 0; - b = *pb; - bb = (b >> 2) + (b >> 1); - if (bb > b) bb = 0; + rsign = (drx < 0) ? -1 : 1; + gsign = (dgx < 0) ? -1 : 1; + bsign = (dbx < 0) ? -1 : 1; - *(pr++) = rr; - *(pg++) = gg; - *(pb++) = bb; + xr = yr = (drx / 2); + xg = yg = (dgx / 2); + xb = yb = (dbx / 2); + + // Create X table + drx /= width; + dgx /= width; + dbx /= width; + + for (x = 0; x < width; x++) { + *(xt++) = (unsigned char) ((xr < 0) ? -xr : xr); + *(xt++) = (unsigned char) ((xg < 0) ? -xg : xg); + *(xt++) = (unsigned char) ((xb < 0) ? -xb : xb); + + xr -= drx; + xg -= dgx; + xb -= dbx; } - r = *pr; - rr = r + (r >> 1); - if (rr < r) rr = ~0; - g = *pg; - gg = g + (g >> 1); - if (gg < g) gg = ~0; - b = *pb; - bb = b + (b >> 1); - if (bb < b) bb = ~0; + // Create Y table + dry /= height; + dgy /= height; + dby /= height; - *pr = rr; - *pg = gg; - *pb = bb; + for (y = 0; y < height; y++) { + *(yt++) = ((unsigned char) ((yr < 0) ? -yr : yr)); + *(yt++) = ((unsigned char) ((yg < 0) ? -yg : yg)); + *(yt++) = ((unsigned char) ((yb < 0) ? -yb : yb)); - pr += width - 1; - pg += width - 1; - pb += width - 1; + yr -= dry; + yg -= dgy; + yb -= dby; + } - r = *pr; - rr = (r >> 2) + (r >> 1); - if (rr > r) rr = 0; - g = *pg; - gg = (g >> 2) + (g >> 1); - if (gg > g) gg = 0; - b = *pb; - bb = (b >> 2) + (b >> 1); - if (bb > b) bb = 0; + // Combine tables to create gradient - *pr = rr; - *pg = gg; - *pb = bb; -} + if (! interlaced) { -void TextureRender::bevel2() { - if (! (width > 4 && height > 4)) - return; + // normal pgradient + for (yt = ytable, y = 0; y < height; y++, yt += 3) { + for (xt = xtable, x = 0; x < width; x++) { + *(r++) = (unsigned char) (tr - (rsign * (*(xt++) + *(yt)))); + *(g++) = (unsigned char) (tg - (gsign * (*(xt++) + *(yt + 1)))); + *(b++) = (unsigned char) (tb - (bsign * (*(xt++) + *(yt + 2)))); + } + } - unsigned char r, g, b, rr ,gg ,bb, *pr = red + width + 1, - *pg = green + width + 1, *pb = blue + width + 1; - unsigned int w = width - 2, h = height - 1, wh = width * (height - 3); + } else { + // faked interlacing effect + unsigned char channel, channel2; - while (--w) { - r = *pr; - rr = r + (r >> 1); - if (rr < r) rr = ~0; - g = *pg; - gg = g + (g >> 1); - if (gg < g) gg = ~0; - b = *pb; - bb = b + (b >> 1); - if (bb < b) bb = ~0; + for (yt = ytable, y = 0; y < height; y++, yt += 3) { + for (xt = xtable, x = 0; x < width; x++) { + if (y & 1) { + channel = (unsigned char) (tr - (rsign * (*(xt++) + *(yt)))); + channel2 = (channel >> 1) + (channel >> 2); + if (channel2 > channel) channel2 = 0; + *(r++) = channel2; - *pr = rr; - *pg = gg; - *pb = bb; + channel = (unsigned char) (tg - (gsign * (*(xt++) + *(yt + 1)))); + channel2 = (channel >> 1) + (channel >> 2); + if (channel2 > channel) channel2 = 0; + *(g++) = channel2; - r = *(pr + wh); - rr = (r >> 2) + (r >> 1); - if (rr > r) rr = 0; - g = *(pg + wh); - gg = (g >> 2) + (g >> 1); - if (gg > g) gg = 0; - b = *(pb + wh); - bb = (b >> 2) + (b >> 1); - if (bb > b) bb = 0; + channel = (unsigned char) (tb - (bsign * (*(xt++) + *(yt + 2)))); + channel2 = (channel >> 1) + (channel >> 2); + if (channel2 > channel) channel2 = 0; + *(b++) = channel2; + } else { + channel = (unsigned char) (tr - (rsign * (*(xt++) + *(yt)))); + channel2 = channel + (channel >> 3); + if (channel2 < channel) channel2 = ~0; + *(r++) = channel2; - *((pr++) + wh) = rr; - *((pg++) + wh) = gg; - *((pb++) + wh) = bb; + channel = (unsigned char) (tg - (gsign * (*(xt++) + *(yt + 1)))); + channel2 = channel + (channel >> 3); + if (channel2 < channel) channel2 = ~0; + *(g++) = channel2; + + channel = (unsigned char) (tb - (bsign * (*(xt++) + *(yt + 2)))); + channel2 = channel + (channel >> 3); + if (channel2 < channel) channel2 = ~0; + *(b++) = channel2; + } + } + } } - pr = red + width; - pg = green + width; - pb = blue + width; +} - while (--h) { - r = *pr; - rr = r + (r >> 1); - if (rr < r) rr = ~0; - g = *pg; - gg = g + (g >> 1); - if (gg < g) gg = ~0; - b = *pb; - bb = b + (b >> 1); - if (bb < b) bb = ~0; - *(++pr) = rr; - *(++pg) = gg; - *(++pb) = bb; - pr += width - 3; - pg += width - 3; - pb += width - 3; +// 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) { - r = *pr; - rr = (r >> 2) + (r >> 1); - if (rr > r) rr = 0; - g = *pg; - gg = (g >> 2) + (g >> 1); - if (gg > g) gg = 0; - b = *pb; - bb = (b >> 2) + (b >> 1); - if (bb > b) bb = 0; + float drx, dgx, dbx, dry, dgy, dby, xr, xg, xb, yr, yg, yb; + int rsign, gsign, bsign; + unsigned int tr = to->red(), tg = to->green(), tb = to->blue(); + unsigned int* xtable; + unsigned int* ytable; + unsigned int* xt; + unsigned int* yt; - *(pr++) = rr; - *(pg++) = gg; - *(pb++) = bb; + register unsigned int x, y; - pr++; pg++; pb++; + 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()); + + rsign = (drx < 0) ? -2 : 2; + gsign = (dgx < 0) ? -2 : 2; + bsign = (dbx < 0) ? -2 : 2; + + xr = yr = (drx / 2); + xg = yg = (dgx / 2); + xb = yb = (dbx / 2); + + // Create X table + drx /= width; + dgx /= width; + dbx /= width; + + for (x = 0; x < width; x++) { + *(xt++) = (unsigned char) ((xr < 0) ? -xr : xr); + *(xt++) = (unsigned char) ((xg < 0) ? -xg : xg); + *(xt++) = (unsigned char) ((xb < 0) ? -xb : xb); + + xr -= drx; + xg -= dgx; + xb -= dbx; } -} + // Create Y table + dry /= height; + dgy /= height; + dby /= height; + + for (y = 0; y < height; y++) { + *(yt++) = ((unsigned char) ((yr < 0) ? -yr : yr)); + *(yt++) = ((unsigned char) ((yg < 0) ? -yg : yg)); + *(yt++) = ((unsigned char) ((yb < 0) ? -yb : yb)); + + yr -= dry; + yg -= dgy; + yb -= dby; + } -void TextureRender::invert() { - register unsigned int i, j, wh = (width * height) - 1; - unsigned char tmp; + // Combine tables to create gradient - 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; + if (! interlaced) { - tmp = *(blue + j); - *(blue + j) = *(blue + i); - *(blue + i) = tmp; + // normal rgradient + for (yt = ytable, y = 0; y < height; y++, yt += 3) { + for (xt = xtable, x = 0; x < width; x++) { + *(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)))); + } + } + + } else { + // faked interlacing effect + unsigned char channel, channel2; + + for (yt = ytable, y = 0; y < height; y++, yt += 3) { + for (xt = xtable, x = 0; x < width; x++) { + if (y & 1) { + channel = (unsigned char) (tr - (rsign * max(*(xt++), *(yt)))); + channel2 = (channel >> 1) + (channel >> 2); + if (channel2 > channel) channel2 = 0; + *(r++) = channel2; + + channel = (unsigned char) (tg - (gsign * max(*(xt++), *(yt + 1)))); + channel2 = (channel >> 1) + (channel >> 2); + if (channel2 > channel) channel2 = 0; + *(g++) = channel2; + + channel = (unsigned char) (tb - (bsign * max(*(xt++), *(yt + 2)))); + channel2 = (channel >> 1) + (channel >> 2); + if (channel2 > channel) channel2 = 0; + *(b++) = channel2; + } else { + channel = (unsigned char) (tr - (rsign * max(*(xt++), *(yt)))); + channel2 = channel + (channel >> 3); + if (channel2 < channel) channel2 = ~0; + *(r++) = channel2; + + channel = (unsigned char) (tg - (gsign * max(*(xt++), *(yt + 1)))); + channel2 = channel + (channel >> 3); + if (channel2 < channel) channel2 = ~0; + *(g++) = channel2; + + channel = (unsigned char) (tb - (bsign * max(*(xt++), *(yt + 2)))); + channel2 = channel + (channel >> 3); + if (channel2 < channel) channel2 = ~0; + *(b++) = channel2; + } + } + } } } -void TextureRender::dgradient() { - // diagonal gradient code was written by Mike Cole - // modified for interlacing by Brad Hughes + + +// 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 char *pr = red, *pg = green, *pb = blue; - unsigned int w = width * 2, h = height * 2; - unsigned int *xt = xtable, *yt = ytable; + 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()); @@ -778,17 +860,14 @@ void TextureRender::dgradient() { } // 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); + *(r++) = *(xt++) + *(yt); + *(g++) = *(xt++) + *(yt + 1); + *(b++) = *(xt++) + *(yt + 2); } } @@ -802,32 +881,32 @@ void TextureRender::dgradient() { 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; } } } @@ -837,198 +916,171 @@ void TextureRender::dgradient() { } -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()); - dbx = (float) (to->blue() - from->blue()); - - drx /= width; - dgx /= width; - dbx /= width; - - if (interlaced && height > 2) { - // faked interlacing effect - unsigned char channel, channel2; - - for (x = 0; x < width; x++, pr++, pg++, pb++) { - channel = (unsigned char) xr; - channel2 = (channel >> 1) + (channel >> 2); - if (channel2 > channel) channel2 = 0; - *pr = channel2; - - channel = (unsigned char) xg; - channel2 = (channel >> 1) + (channel >> 2); - if (channel2 > channel) channel2 = 0; - *pg = channel2; - - channel = (unsigned char) xb; - channel2 = (channel >> 1) + (channel >> 2); - if (channel2 > channel) channel2 = 0; - *pb = channel2; - - - channel = (unsigned char) xr; - channel2 = channel + (channel >> 3); - if (channel2 < channel) channel2 = ~0; - *(pr + width) = channel2; - channel = (unsigned char) xg; - channel2 = channel + (channel >> 3); - if (channel2 < channel) channel2 = ~0; - *(pg + width) = channel2; - channel = (unsigned char) xb; - channel2 = channel + (channel >> 3); - if (channel2 < channel) channel2 = ~0; - *(pb + width) = channel2; +// 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) { - xr += drx; - xg += dgx; - xb += dbx; - } + float drx, dgx, dbx, dry, dgy, dby, yr, yg, yb, xr, xg, xb; + int rsign, gsign, bsign; + 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; - pr += width; - pg += width; - pb += width; - int offset; + imgctrl.getGradientBuffers(width, height, &xtable, &ytable); + xt = xtable; + yt = ytable; - for (y = 2; y < height; y++, pr += width, pg += width, pb += width) { - if (y & 1) offset = width; else offset = 0; + dry = drx = (float) (to->red() - from->red()); + dgy = dgx = (float) (to->green() - from->green()); + dby = dbx = (float) (to->blue() - from->blue()); - memcpy(pr, (red + offset), width); - memcpy(pg, (green + offset), width); - memcpy(pb, (blue + offset), width); - } - } else { + rsign = (drx < 0) ? -1 : 1; + gsign = (dgx < 0) ? -1 : 1; + bsign = (dbx < 0) ? -1 : 1; - // normal hgradient - for (x = 0; x < width; x++) { - *(pr++) = (unsigned char) (xr); - *(pg++) = (unsigned char) (xg); - *(pb++) = (unsigned char) (xb); + xr = yr = (drx / 2); + xg = yg = (dgx / 2); + xb = yb = (dbx / 2); - xr += drx; - xg += dgx; - xb += dbx; - } + // Create X table + drx /= width; + dgx /= width; + dbx /= width; - 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 (x = 0; x < width; x++) { + *(xt++) = (unsigned long) (xr * xr); + *(xt++) = (unsigned long) (xg * xg); + *(xt++) = (unsigned long) (xb * xb); + xr -= drx; + xg -= dgx; + xb -= dbx; } -} - - -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; - - dry = (float) (to->red() - from->red()); - dgy = (float) (to->green() - from->green()); - dby = (float) (to->blue() - from->blue()); - + // Create Y table dry /= height; dgy /= height; dby /= height; - if (interlaced) { - // faked interlacing effect - unsigned char channel, channel2; + for (y = 0; y < height; y++) { + *(yt++) = (unsigned long) (yr * yr); + *(yt++) = (unsigned long) (yg * yg); + *(yt++) = (unsigned long) (yb * yb); - for (y = 0; y < height; y++, pr += width, pg += width, pb += width) { - if (y & 1) { - channel = (unsigned char) yr; - channel2 = (channel >> 1) + (channel >> 2); - if (channel2 > channel) channel2 = 0; - memset(pr, channel2, width); + yr -= dry; + yg -= dgy; + yb -= dby; + } - channel = (unsigned char) yg; - channel2 = (channel >> 1) + (channel >> 2); - if (channel2 > channel) channel2 = 0; - memset(pg, channel2, width); + // Combine tables to create gradient + if (! interlaced) { + // normal egradient + for (yt = ytable, y = 0; y < height; y++, yt += 3) { + for (xt = xtable, x = 0; x < width; x++) { + *(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)))); + } + } - channel = (unsigned char) yb; - channel2 = (channel >> 1) + (channel >> 2); - if (channel2 > channel) channel2 = 0; - memset(pb, channel2, width); - } else { - channel = (unsigned char) yr; - channel2 = channel + (channel >> 3); - if (channel2 < channel) channel2 = ~0; - memset(pr, channel2, width); + } else { + // faked interlacing effect + unsigned char channel, channel2; - channel = (unsigned char) yg; - channel2 = channel + (channel >> 3); - if (channel2 < channel) channel2 = ~0; - memset(pg, channel2, width); + 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 * bsqrt(*(xt++) + *(yt)))); + channel2 = (channel >> 1) + (channel >> 2); + if (channel2 > channel) channel2 = 0; + *(r++) = channel2; - channel = (unsigned char) yb; - channel2 = channel + (channel >> 3); - if (channel2 < channel) channel2 = ~0; - memset(pb, channel2, width); - } + channel = (unsigned char) + (tg - (gsign * bsqrt(*(xt++) + *(yt + 1)))); + channel2 = (channel >> 1) + (channel >> 2); + if (channel2 > channel) channel2 = 0; + *(g++) = channel2; - yr += dry; - yg += dgy; - yb += dby; - } - } else { + channel = (unsigned char) + (tb - (bsign * bsqrt(*(xt++) + *(yt + 2)))); + channel2 = (channel >> 1) + (channel >> 2); + if (channel2 > channel) channel2 = 0; + *(b++) = channel2; + } else { + channel = (unsigned char) + (tr - (rsign * bsqrt(*(xt++) + *(yt)))); + channel2 = channel + (channel >> 3); + if (channel2 < channel) channel2 = ~0; + *(r++) = channel2; - // 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); + channel = (unsigned char) + (tg - (gsign * bsqrt(*(xt++) + *(yt + 1)))); + channel2 = channel + (channel >> 3); + if (channel2 < channel) channel2 = ~0; + *(g++) = channel2; - yr += dry; - yg += dgy; - yb += dby; + channel = (unsigned char) + (tb - (bsign * bsqrt(*(xt++) + *(yt + 2)))); + channel2 = channel + (channel >> 3); + if (channel2 < channel) channel2 = ~0; + *(b++) = channel2; + } + } } } - } -void TextureRender::pgradient() { - // pyramid gradient - based on original dgradient, written by - // Mosfet (mosfet@kde.org) - // adapted from kde sources for Blackbox by Brad Hughes - float yr, yg, yb, drx, dgx, dbx, dry, dgy, dby, - xr, xg, xb; - int rsign, gsign, bsign; - unsigned char *pr = red, *pg = green, *pb = blue; - unsigned int tr = to->red(), tg = to->green(), tb = to->blue(); - unsigned int *xt = xtable, *yt = ytable; +// 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 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()); - rsign = (drx < 0) ? -1 : 1; - gsign = (dgx < 0) ? -1 : 1; - bsign = (dbx < 0) ? -1 : 1; + rsign = (drx < 0) ? -2 : 2; + gsign = (dgx < 0) ? -2 : 2; + bsign = (dbx < 0) ? -2 : 2; xr = yr = (drx / 2); xg = yg = (dgx / 2); @@ -1065,16 +1117,14 @@ void TextureRender::pgradient() { } // Combine tables to create gradient - - if (! interlaced) { - // normal pgradient + // 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 * (*(xt++) + *(yt)))); - *(pg++) = (unsigned char) (tg - (gsign * (*(xt++) + *(yt + 1)))); - *(pb++) = (unsigned char) (tb - (bsign * (*(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)))); } } @@ -1085,109 +1135,110 @@ void TextureRender::pgradient() { for (yt = ytable, y = 0; y < height; y++, yt += 3) { for (xt = xtable, x = 0; x < width; x++) { if (y & 1) { - channel = (unsigned char) (tr - (rsign * (*(xt++) + *(yt)))); + 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 - (gsign * (*(xt++) + *(yt + 1)))); + 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 - (bsign * (*(xt++) + *(yt + 2)))); + 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 * (*(xt++) + *(yt)))); + 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 * (*(xt++) + *(yt + 1)))); + 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 * (*(xt++) + *(yt + 2)))); + channel = (unsigned char) (tb - (bsign * min(*(xt++), *(yt + 2)))); channel2 = channel + (channel >> 3); if (channel2 < channel) channel2 = ~0; - *(pb++) = channel2; + *(b++) = channel2; } } } } - } -void TextureRender::rgradient() { - // rectangle 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, 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; + 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, 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()); - rsign = (drx < 0) ? -2 : 2; - gsign = (dgx < 0) ? -2 : 2; - bsign = (dbx < 0) ? -2 : 2; - - xr = yr = (drx / 2); - xg = yg = (dgx / 2); - xb = yb = (dbx / 2); - // Create X table - drx /= width; - dgx /= width; - dbx /= width; + drx /= w; + dgx /= w; + dbx /= w; - for (x = 0; x < width; x++) { - *(xt++) = (unsigned char) ((xr < 0) ? -xr : xr); - *(xt++) = (unsigned char) ((xg < 0) ? -xg : xg); - *(xt++) = (unsigned char) ((xb < 0) ? -xb : xb); + for (xt = (xtable + (width * 3) - 1), x = 0; x < width; x++) { + *(xt--) = (unsigned char) xb; + *(xt--) = (unsigned char) xg; + *(xt--) = (unsigned char) xr; - xr -= drx; - xg -= dgx; - xb -= dbx; + xr += drx; + xg += dgx; + xb += dbx; } // Create Y table - dry /= height; - dgy /= height; - dby /= height; - - for (y = 0; y < height; y++) { - *(yt++) = ((unsigned char) ((yr < 0) ? -yr : yr)); - *(yt++) = ((unsigned char) ((yg < 0) ? -yg : yg)); - *(yt++) = ((unsigned char) ((yb < 0) ? -yb : yb)); + dry /= h; + dgy /= h; + dby /= h; - yr -= dry; - yg -= dgy; - yb -= dby; + for (yt = ytable, y = 0; y < height; y++) { + *(yt++) = (unsigned char) yr; + *(yt++) = (unsigned char) yg; + *(yt++) = (unsigned char) yb; + + yr += dry; + yg += dgy; + yb += dby; } // Combine tables to create gradient - if (! interlaced) { - - // normal rgradient + // normal cdgradient 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++) = *(xt++) + *(yt); + *(g++) = *(xt++) + *(yt + 1); + *(b++) = *(xt++) + *(yt + 2); } } @@ -1198,378 +1249,447 @@ void TextureRender::rgradient() { for (yt = ytable, y = 0; y < height; y++, yt += 3) { for (xt = xtable, x = 0; x < width; x++) { if (y & 1) { - channel = (unsigned char) (tr - (rsign * max(*(xt++), *(yt)))); + channel = *(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)))); + channel = *(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)))); + channel = *(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)))); + channel = *(xt++) + *(yt); channel2 = channel + (channel >> 3); if (channel2 < channel) channel2 = ~0; - *(pr++) = channel2; + *(r++) = channel2; - channel = (unsigned char) (tg - (gsign * max(*(xt++), *(yt + 1)))); + channel = *(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)))); + 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 { -void TextureRender::egradient() { - // elliptic gradient - based on original dgradient, written by - // Mosfet (mosfet@kde.org) - // adapted from kde sources for Blackbox by Brad Hughes +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) { - 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 tr = (unsigned long) to->red(), - tg = (unsigned long) to->green(), - tb = (unsigned long) to->blue(); + Display* d = App::instance()->display(); + Screen* s = ScreenOfDisplay(d, imgctrl.screenNumber()); - register unsigned int x, y; + unsigned int texture_max_width = WidthOfScreen(s) * 2; + unsigned int texture_max_height = HeightOfScreen(s) * 2; - dry = drx = (float) (to->red() - from->red()); - dgy = dgx = (float) (to->green() - from->green()); - dby = dbx = (float) (to->blue() - from->blue()); + _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")<> 1) + (channel >> 2); - if (channel2 > channel) channel2 = 0; - *(pr++) = channel2; + 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); + } - channel = (unsigned char) - (tg - (gsign * control.getSqrt(*(xt++) + *(yt + 1)))); - channel2 = (channel >> 1) + (channel >> 2); - if (channel2 > channel) channel2 = 0; - *(pg++) = channel2; - channel = (unsigned char) - (tb - (bsign * control.getSqrt(*(xt++) + *(yt + 2)))); - channel2 = (channel >> 1) + (channel >> 2); - if (channel2 > channel) channel2 = 0; - *(pb++) = channel2; - } else { - channel = (unsigned char) - (tr - (rsign * control.getSqrt(*(xt++) + *(yt)))); - channel2 = channel + (channel >> 3); - if (channel2 < channel) channel2 = ~0; - *(pr++) = channel2; +} - channel = (unsigned char) - (tg - (gsign * control.getSqrt(*(xt++) + *(yt + 1)))); - channel2 = channel + (channel >> 3); - if (channel2 < channel) channel2 = ~0; - *(pg++) = channel2; +Pixmap TextureRender::renderSolid(const FbTk::Texture &texture) { - channel = (unsigned char) - (tb - (bsign * control.getSqrt(*(xt++) + *(yt + 2)))); - channel2 = channel + (channel >> 3); - if (channel2 < channel) channel2 = ~0; - *(pb++) = channel2; - } - } + 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")<red(), - tg = to->green(), - tb = to->blue(); + // invert our width and height if necessary + translateSize(orientation, width, height); - register unsigned int x, y; + bool inverted = texture.type() & Texture::SUNKEN; + const Color* from = &(texture.color()); + const Color* to = &(texture.colorTo()); - dry = drx = (float) (to->red() - from->red()); - dgy = dgx = (float) (to->green() - from->green()); - dby = dbx = (float) (to->blue() - from->blue()); + if (texture.type() & Texture::SUNKEN) { + std::swap(from, to); + inverted = !inverted; + } - rsign = (drx < 0) ? -2 : 2; - gsign = (dgx < 0) ? -2 : 2; - bsign = (dbx < 0) ? -2 : 2; + 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; + } + } - xr = yr = (drx / 2); - xg = yg = (dgx / 2); - xb = yb = (dbx / 2); + // 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); - // Create X table - drx /= width; - dgx /= width; - dbx /= width; + return pm_copy.release(); +} - for (x = 0; x < width; x++) { - *(xt++) = (unsigned char) ((xr < 0) ? -xr : xr); - *(xt++) = (unsigned char) ((xg < 0) ? -xg : xg); - *(xt++) = (unsigned char) ((xb < 0) ? -xb : xb); +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); - xr -= drx; - xg -= dgx; - xb -= dbx; + 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; } - // Create Y table - dry /= height; - dgy /= height; - dby /= height; + image->data = 0; - for (y = 0; y < height; y++) { - *(yt++) = ((unsigned char) ((yr < 0) ? -yr : yr)); - *(yt++) = ((unsigned char) ((yg < 0) ? -yg : yg)); - *(yt++) = ((unsigned char) ((yb < 0) ? -yb : yb)); + unsigned char *d = new unsigned char[image->bytes_per_line * (height + 1)]; + register unsigned int x, y, r, g, b, o, offset; - yr -= dry; - yg -= dgy; - yb -= dby; - } + unsigned char *pixel_data = d, *ppixel_data = d; + unsigned long pixel; - // Combine tables to create gradient - if (! interlaced) { + o = image->bits_per_pixel + ((image->byte_order == MSBFirst) ? 1 : 0); - // 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)))); + 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; } - } - } else { - // faked interlacing effect - unsigned char channel, channel2; + pixel_data = (ppixel_data += image->bytes_per_line); + } - for (yt = ytable, y = 0; y < height; y++, yt += 3) { - for (xt = xtable, x = 0; x < width; x++) { - if (y & 1) { - channel = (unsigned char) (tr - (rsign * min(*(xt++), *(yt)))); - channel2 = (channel >> 1) + (channel >> 2); - if (channel2 > channel) channel2 = 0; - *(pr++) = channel2; + break; - channel = (unsigned char) (tg - (bsign * min(*(xt++), *(yt + 1)))); - channel2 = (channel >> 1) + (channel >> 2); - if (channel2 > channel) channel2 = 0; - *(pg++) = channel2; + 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]]; - channel = (unsigned char) (tb - (gsign * min(*(xt++), *(yt + 2)))); - channel2 = (channel >> 1) + (channel >> 2); - if (channel2 > channel) channel2 = 0; - *(pb++) = channel2; - } else { - channel = (unsigned char) (tr - (rsign * min(*(xt++), *(yt)))); - channel2 = channel + (channel >> 3); - if (channel2 < channel) channel2 = ~0; - *(pr++) = channel2; + pixel = (r << red_offset) | (g << green_offset) | (b << blue_offset); - channel = (unsigned char) (tg - (gsign * min(*(xt++), *(yt + 1)))); - channel2 = channel + (channel >> 3); - if (channel2 < channel) channel2 = ~0; - *(pg++) = channel2; + switch (o) { + case 8: // 8bpp + *pixel_data++ = pixel; + break; - channel = (unsigned char) (tb - (bsign * min(*(xt++), *(yt + 2)))); - channel2 = channel + (channel >> 3); - if (channel2 < channel) channel2 = ~0; - *(pb++) = channel2; - } - } - } - } + 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; -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 + case 25: // 24bpp MSB + *pixel_data++ = pixel >> 16; + *pixel_data++ = pixel >> 8; + *pixel_data++ = pixel; + break; - 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; + case 32: // 32bpp LSB + *pixel_data++ = pixel; + *pixel_data++ = pixel >> 8; + *pixel_data++ = pixel >> 16; + *pixel_data++ = pixel >> 24; + break; - register unsigned int x, y; + case 33: // 32bpp MSB + *pixel_data++ = pixel >> 24; + *pixel_data++ = pixel >> 16; + *pixel_data++ = pixel >> 8; + *pixel_data++ = pixel; + break; + } + } - dry = drx = (float) (to->red() - from->red()); - dgy = dgx = (float) (to->green() - from->green()); - dby = dbx = (float) (to->blue() - from->blue()); + pixel_data = (ppixel_data += image->bytes_per_line); + } - // Create X table - drx /= w; - dgx /= w; - dbx /= w; + break; - for (xt = (xtable + (width * 3) - 1), x = 0; x < width; x++) { - *(xt--) = (unsigned char) xb; - *(xt--) = (unsigned char) xg; - *(xt--) = (unsigned char) xr; + 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)); - xr += drx; - xg += dgx; - xb += dbx; - } + g = ((r * 30) + (g * 59) + (b * 11)) / 100; + *pixel_data++ = control.colors()[g].pixel; + } - // Create Y table - dry /= h; - dgy /= h; - dby /= h; + pixel_data = (ppixel_data += image->bytes_per_line); + } - for (yt = ytable, y = 0; y < height; y++) { - *(yt++) = (unsigned char) yr; - *(yt++) = (unsigned char) yg; - *(yt++) = (unsigned char) yb; + break; - yr += dry; - yg += dgy; - yb += dby; + 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; } - // Combine tables to create gradient + image->data = (char *) d; + return image; +} - if (! interlaced) { - // normal cdgradient - for (yt = ytable, y = 0; y < height; y++, yt += 3) { - for (xt = xtable, x = 0; x < width; x++) { - *(pr++) = *(xt++) + *(yt); - *(pg++) = *(xt++) + *(yt + 1); - *(pb++) = *(xt++) + *(yt + 2); - } - } - } else { - // faked interlacing effect - unsigned char channel, channel2; +Pixmap TextureRender::renderPixmap() { + Display *disp = FbTk::App::instance()->display(); + FbPixmap pixmap(RootWindow(disp, control.screenNumber()), + width, height, control.depth()); - 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; + 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")<> 1) + (channel >> 2); - if (channel2 > channel) channel2 = 0; - *(pg++) = channel2; + XImage *image = renderXImage(); - 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; + if (! image) { + return None; + } else if (! image->data) { + XDestroyImage(image); + return None; + } - channel = *(xt++) + *(yt + 1); - channel2 = channel + (channel >> 3); - if (channel2 < channel) channel2 = ~0; - *(pg++) = channel2; + XPutImage(disp, pixmap.drawable(), + DefaultGC(disp, control.screenNumber()), + image, 0, 0, 0, 0, width, height); - channel = *(xt++) + *(yt + 2); - channel2 = channel + (channel >> 3); - if (channel2 < channel) channel2 = ~0; - *(pb++) = channel2; - } - } - } + 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 158625e..7896c06 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 -- cgit v0.11.2