From 49491d32b6385634227f779828bb6de97449f273 Mon Sep 17 00:00:00 2001
From: fluxgen <fluxgen>
Date: Sat, 30 Nov 2002 20:07:06 +0000
Subject: moved from Image.hh/cc

---
 src/ImageControl.cc | 636 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/ImageControl.hh | 125 +++++++++++
 2 files changed, 761 insertions(+)
 create mode 100644 src/ImageControl.cc
 create mode 100644 src/ImageControl.hh

diff --git a/src/ImageControl.cc b/src/ImageControl.cc
new file mode 100644
index 0000000..8a60461
--- /dev/null
+++ b/src/ImageControl.cc
@@ -0,0 +1,636 @@
+// ImageControl.cc for Fluxbox Window Manager 
+// Copyright (c) 2001 - 2002 Henrik Kinnunen (fluxbox at linuxmail.org)
+//
+// Image.cc for Blackbox - an X11 Window manager
+// Copyright (c) 1997 - 2000 Brad Hughes (bhughes at tcac.net)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+// $Id: ImageControl.cc,v 1.1 2002/11/30 20:07:06 fluxgen Exp $
+
+#include "ImageControl.hh"
+
+#include "TextureRender.hh"
+#include "App.hh"
+
+//use GNU extensions
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif // _GNU_SOURCE
+
+#include "i18n.hh"
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif // HAVE_SYS_TYPES_H
+
+#include <cstdlib>
+#include <cstring>
+#include <cstdio>
+
+#ifdef HAVE_CTYPE_H
+#include <ctype.h>
+#endif // HAVE_CTYPE_H
+
+#include <iostream>
+
+using namespace std;
+
+// lookup table for texture
+unsigned long *BImageControl::sqrt_table = 0;
+
+namespace { // anonymous
+
+unsigned long bsqrt(unsigned long x) {
+	if (x <= 0) return 0;
+	if (x == 1) return 1;
+
+	unsigned long r = x >> 1;
+	unsigned long q;
+
+	while (1) {
+		q = x / r;
+		if (q >= r) return r;
+		r = (r + q) >> 1;
+	}
+}
+
+};
+
+
+BImageControl::BImageControl(int screen_num, bool dither,
+		int cpc, unsigned long cache_timeout, unsigned long cmax):
+m_dither(dither),
+m_timer(this),
+m_colors(0),
+m_num_colors(0),
+m_colors_per_channel(cpc) {
+
+	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);
+
+	cache_max = cmax;
+#ifdef TIMEDCACHE
+	if (cache_timeout) {
+		m_timer.setTimeout(cache_timeout);
+		m_timer.start();
+	}
+#endif // TIMEDCACHE
+	
+	createColorTable();
+}
+
+
+BImageControl::~BImageControl() {
+	if (sqrt_table) {
+		delete [] sqrt_table;
+	}
+
+	if (grad_xbuffer) {
+		delete [] grad_xbuffer;
+	}
+
+	if (grad_ybuffer) {
+		delete [] grad_ybuffer;
+	}
+
+	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;
+
+		XFreeColors(FbTk::App::instance()->display(), m_colormap, pixels, m_num_colors, 0);
+
+		delete [] m_colors;
+	}
+
+	if (cache.size() > 0) {
+		fprintf(stderr,
+			I18n::instance()->
+				getMessage(
+					 FBNLS::ImageSet, FBNLS::ImagePixmapRelease,
+				 "BImageContol::~BImageControl: pixmap cache - "
+				 "releasing %d pixmaps\n"), cache.size());
+
+		CacheList::iterator it = cache.begin();
+		CacheList::iterator it_end = cache.end();
+		Display *disp = FbTk::App::instance()->display();
+		for (; it != it_end; ++it) {
+			XFreePixmap(disp, (*it)->pixmap);
+			delete (*it);
+		}
+
+	}
+}
+
+
+Pixmap BImageControl::searchCache(unsigned int width, unsigned int height,
+			unsigned long texture_type,
+			const FbTk::Color &color, const FbTk::Color &color_to) const {
+	CacheList::iterator it = cache.begin();
+	CacheList::iterator it_end = cache.end();
+	for (; it != it_end; ++it) {
+		if (((*it)->width == width) &&
+				((*it)->height == height) &&
+				((*it)->texture == texture_type) &&
+				((*it)->pixel1 == color.pixel())) {
+			if (texture_type & FbTk::Texture::GRADIENT) {
+				if ((*it)->pixel2 == color_to.pixel()) {
+					(*it)->count++;
+					return (*it)->pixmap;
+				}
+			} else {
+				(*it)->count++;
+				return (*it)->pixmap;
+			}
+		}
+	}
+
+	return None;
+}
+
+
+Pixmap BImageControl::renderImage(unsigned int width, unsigned int height,
+			const FbTk::Texture &texture) {
+
+	if (texture.type() & FbTk::Texture::PARENTRELATIVE)
+		return ParentRelative;
+
+	// search cache first
+	Pixmap pixmap = searchCache(width, height, texture.type(),
+						texture.color(), texture.colorTo());
+	if (pixmap)
+		return pixmap; // return cache item
+
+	// render new image
+	TextureRender image(*this, width, height);
+	pixmap = image.render(texture);
+
+	if (pixmap) {
+		// create new cache item and add it to cache list
+
+		Cache *tmp = new Cache;
+
+		tmp->pixmap = pixmap;
+		tmp->width = width;
+		tmp->height = height;
+		tmp->count = 1;
+		tmp->texture = texture.type();
+		tmp->pixel1 = texture.color().pixel();
+
+		if (texture.type() & FbTk::Texture::GRADIENT)
+			tmp->pixel2 = texture.colorTo().pixel();
+		else
+			tmp->pixel2 = 0l;
+
+		cache.push_back(tmp); 
+
+		if ((unsigned) cache.size() > cache_max) {
+#ifdef DEBUG
+			cerr<<I18n::instance()->
+					getMessage(
+						FBNLS::ImageSet, FBNLS::ImagePixmapCacheLarge,
+						"BImageControl::renderImage: cache is large, "
+						"forcing cleanout\n")<<endl;
+#endif // DEBUG
+			timeout();
+		}
+
+		return pixmap;
+	}
+
+	return None;
+}
+
+
+void BImageControl::removeImage(Pixmap pixmap) {
+	if (!pixmap)
+		return;
+
+	CacheList::iterator it = cache.begin();
+	CacheList::iterator it_end = cache.end();
+	for (; it != it_end; ++it) {
+		if ((*it)->pixmap == pixmap) {
+			if ((*it)->count) {
+				(*it)->count--;
+
+#ifdef TIMEDCACHE
+				timeout();
+#else // !TIMEDCACHE
+				if (! (*it)->count) timeout();
+#endif // TIMEDCACHE
+			}
+
+			return;
+		}
+	}
+}
+
+
+void BImageControl::colorTables(const unsigned char **rmt, const unsigned char **gmt,
+	const unsigned char **bmt,
+	int *roff, int *goff, int *boff,
+	int *rbit, int *gbit, int *bbit) const {
+
+	if (rmt) *rmt = red_color_table;
+	if (gmt) *gmt = green_color_table;
+	if (bmt) *bmt = blue_color_table;
+
+	if (roff) *roff = red_offset;
+	if (goff) *goff = green_offset;
+	if (boff) *boff = blue_offset;
+
+	if (rbit) *rbit = red_bits;
+	if (gbit) *gbit = green_bits;
+	if (bbit) *bbit = blue_bits;
+}
+
+
+void BImageControl::getXColorTable(XColor **c, int *n) {
+	if (c) *c = m_colors;
+	if (n) *n = m_num_colors;
+}
+
+
+void BImageControl::getGradientBuffers(unsigned int w,
+	unsigned int h,
+	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;
+		}
+
+		grad_buffer_height = h;
+
+		grad_ybuffer = new unsigned int[grad_buffer_height * 3];
+	}
+
+	*xbuf = grad_xbuffer;
+	*ybuf = grad_ybuffer;
+}
+
+
+void BImageControl::installRootColormap() {
+	XGrabServer(FbTk::App::instance()->display());
+
+
+	Display *disp = FbTk::App::instance()->display();
+	bool install = true;
+	int i = 0, ncmap = 0;
+	Colormap *cmaps =
+		XListInstalledColormaps(disp, m_root_window, &ncmap);
+
+	if (cmaps) {
+		for (i = 0; i < ncmap; i++) {
+			if (*(cmaps + i) == m_colormap)
+				install = false;
+		}
+		
+		if (install)
+			XInstallColormap(disp, m_colormap);
+
+		XFree(cmaps);
+	}
+
+	XUngrabServer(FbTk::App::instance()->display());
+}
+
+
+void BImageControl::setColorsPerChannel(int cpc) {
+	if (cpc < 2) cpc = 2;
+	if (cpc > 6) cpc = 6;
+
+	m_colors_per_channel = cpc;
+}
+
+
+unsigned long BImageControl::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 BImageControl::timeout() {
+	Display *disp = FbTk::App::instance()->display();
+	CacheList::iterator it = cache.begin();
+	CacheList::iterator it_end = cache.end();
+	for (; it != it_end; ++it) {
+		Cache *tmp = (*it);
+
+		if (tmp->count <= 0) {
+			XFreePixmap(disp, tmp->pixmap);
+			it = cache.erase(it);
+			delete tmp;
+			if (it == it_end) break;
+		}
+	}
+}
+
+void BImageControl::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);
+
+	if (pmv) {
+		bits_per_pixel = 0;
+		for (int i = 0; i < count; i++) {
+			if (pmv[i].depth == m_screen_depth) {
+				bits_per_pixel = pmv[i].bits_per_pixel;
+				break;
+			}
+		}
+
+		XFree(pmv);
+	}
+
+	if (bits_per_pixel == 0)
+		bits_per_pixel = m_screen_depth;
+	if (bits_per_pixel >= 24)
+		setDither(false);
+
+	red_offset = green_offset = blue_offset = 0;
+	I18n *i18n = I18n::instance();
+	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;
+
+		while (! (red_mask & 1)) { red_offset++; red_mask >>= 1; }
+		while (! (green_mask & 1)) { green_offset++; green_mask >>= 1; }
+		while (! (blue_mask & 1)) { blue_offset++; blue_mask >>= 1; }
+
+		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;
+		}
+	}
+
+	break;
+
+	case PseudoColor:
+	case StaticColor: {
+
+		m_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)) {
+			m_colors_per_channel = (1 << m_screen_depth) / 3;
+			m_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,
+				i18n->
+				getMessage(
+					FBNLS::ImageSet, FBNLS::ImageInvalidColormapSize,
+					"BImageControl::BImageControl: invalid colormap size %d "
+					"(%d/%d/%d) - reducing"),
+					m_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];
+
+		int bits = 256 / m_colors_per_channel;
+
+#ifndef ORDEREDPSEUDO
+		bits = 255 / (m_colors_per_channel - 1);
+#endif // ORDEREDPSEUDO
+
+		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;
+		}
+
+		for (int r = 0, i = 0; r < m_colors_per_channel; r++) {
+			for (int g = 0; g < m_colors_per_channel; g++) {
+				for (int b = 0; b < m_colors_per_channel; b++, i++) {
+					m_colors[i].red = (r * 0xffff) / (m_colors_per_channel - 1);
+					m_colors[i].green = (g * 0xffff) / (m_colors_per_channel - 1);
+					m_colors[i].blue = (b * 0xffff) / (m_colors_per_channel - 1);;
+					m_colors[i].flags = DoRed|DoGreen|DoBlue;
+				}
+			}
+		}
+		
+		for (unsigned int i = 0; i < m_num_colors; i++) {
+			if (! XAllocColor(disp, m_colormap, &m_colors[i])) {
+				fprintf(stderr,
+				i18n->getMessage(
+					FBNLS::ImageSet, FBNLS::ImageColorAllocFail,
+					"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;
+						}
+					}
+				}
+			}
+		}
+
+	 break;
+	}
+
+	case GrayScale:
+	case StaticGray:
+	{
+
+		if (visual()->c_class == StaticGray) {
+			m_num_colors = 1 << m_screen_depth;
+		} else {
+			m_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)) {
+				m_colors_per_channel = (1 << m_screen_depth) / 3;
+				m_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,
+				i18n->
+				getMessage(
+					FBNLS::ImageSet, FBNLS::ImageInvalidColormapSize,
+					"BImageControl::BImageControl: invalid colormap size %d "
+					"(%d/%d/%d) - reducing"),
+			m_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];
+
+		int p, 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;
+
+		for (unsigned int i = 0; i < m_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,
+					i18n->
+					getMessage(
+						FBNLS::ImageSet, FBNLS::ImageColorAllocFail,
+						"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;
+						}
+					}
+				}
+			}
+		}
+
+		break;
+		}
+
+	default:
+		throw string(i18n->
+			getMessage(
+				FBNLS::ImageSet, FBNLS::ImageUnsupVisual,
+				"BImageControl::BImageControl: unsupported visual"));
+	
+	}
+}
diff --git a/src/ImageControl.hh b/src/ImageControl.hh
new file mode 100644
index 0000000..ec89c8d
--- /dev/null
+++ b/src/ImageControl.hh
@@ -0,0 +1,125 @@
+// ImageControl.hh for Fluxbox Window Manager
+// Copyright (c) 2001 - 2002 Henrik Kinnunen (fluxbox at linuxmail.org)
+//
+// Image.hh for Blackbox - an X11 Window manager
+// Copyright (c) 1997 - 2000 Brad Hughes (bhughes at tcac.net)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+// $Id: ImageControl.hh,v 1.1 2002/11/30 20:07:06 fluxgen Exp $
+
+#ifndef	 IMAGECONTROL_HH
+#define	 IMAGECONTROL_HH
+
+#include "Texture.hh"
+#include "Timer.hh"
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <list>
+
+/**
+	Holds screen info and color tables	
+*/
+class BImageControl : public TimeoutHandler {
+public:
+	BImageControl(int screen_num, bool dither = false, int colors_per_channel = 4,
+		unsigned long cache_timeout = 300000l, unsigned long cache_max = 200l);
+	virtual ~BImageControl();
+
+	inline bool doDither() const { return m_dither; }
+	inline int bitsPerPixel() const { return bits_per_pixel; }
+	inline int depth() const { return m_screen_depth; }
+	inline int colorsPerChannel() const	{ return m_colors_per_channel; }
+	int screenNum() const { return m_screen_num; }
+	Visual *visual() const { return m_visual; }
+	unsigned long getSqrt(unsigned int val) const;
+
+	/**
+		Render to pixmap
+		@param width width of pixmap
+		@param height height of pixmap
+		@param src_texture texture type to render
+		@return pixmap of the rendered image, on failure None
+	*/
+	Pixmap renderImage(unsigned int width, unsigned int height,
+		const FbTk::Texture &src_texture);
+
+	void installRootColormap();
+	void removeImage(Pixmap thepix);
+	void colorTables(const unsigned char **, const unsigned char **, const unsigned char **,
+			int *, int *, int *, int *, int *, int *) const;
+	void getXColorTable(XColor **, int *);
+	void getGradientBuffers(unsigned int, unsigned int,
+			unsigned int **, unsigned int **);
+	void setDither(bool d) { m_dither = d; }
+	void setColorsPerChannel(int cpc);
+
+	virtual void timeout();
+
+private:
+	/** 
+		Search cache for a specific pixmap
+		@return None if no cache was found
+	*/
+	Pixmap searchCache(unsigned int width, unsigned int height, unsigned long texture_type, 
+		const FbTk::Color &color, const FbTk::Color &color_to) const;
+
+	void createColorTable();
+	bool m_dither;
+
+	BTimer 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
+
+	Visual *m_visual;
+
+	int bits_per_pixel, 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], green_color_table[256],
+		blue_color_table[256];
+	unsigned int *grad_xbuffer, *grad_ybuffer, grad_buffer_width,
+		grad_buffer_height;
+
+	static unsigned long *sqrt_table; /// sqrt lookup table
+
+	typedef struct Cache {
+		Pixmap pixmap;
+
+		unsigned int count, width, height;
+		unsigned long pixel1, pixel2, texture;
+	} Cache;
+	
+	unsigned long cache_max;
+	typedef std::list<Cache *> CacheList;
+
+	mutable CacheList cache;
+};
+
+
+#endif // IMAGECONTROL_HH
+
-- 
cgit v0.11.2