adding toolkit beginnings
This commit is contained in:
parent
a7c71b3684
commit
85c41a1aec
16 changed files with 3538 additions and 0 deletions
35
otk/Makefile.am
Normal file
35
otk/Makefile.am
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
DEFAULT_MENU=$(pkgdatadir)/menu
|
||||||
|
DEFAULT_STYLE=$(pkgdatadir)/styles/mbdtex
|
||||||
|
|
||||||
|
CXXFLAGS=`pkg-config --cflags xft` @CXXFLAGS@ \
|
||||||
|
-DDEFAULTMENU=\"$(DEFAULT_MENU)\" \
|
||||||
|
-DDEFAULTSTYLE=\"$(DEFAULT_STYLE)\" \
|
||||||
|
-Dmultibyte\(\)=True
|
||||||
|
|
||||||
|
INCLUDES= -I../src
|
||||||
|
|
||||||
|
LDFLAGS=`pkg-config --libs xft`
|
||||||
|
|
||||||
|
noinst_LIBRARIES=libotk.a
|
||||||
|
|
||||||
|
libotk_a_SOURCES= color.cc font.cc gccache.cc image.cc imagecontrol.cc texture.cc
|
||||||
|
|
||||||
|
MAINTAINERCLEANFILES= Makefile.in
|
||||||
|
|
||||||
|
distclean-local:
|
||||||
|
rm -f *\~ *.orig *.rej .\#*
|
||||||
|
|
||||||
|
# local dependencies
|
||||||
|
color.o: color.cc color.hh ../src/basedisplay.hh ../src/timer.hh ../src/util.hh
|
||||||
|
font.o: font.cc font.hh ../src/screen.hh color.hh texture.hh ../src/util.hh image.hh \
|
||||||
|
../src/timer.hh ../src/basedisplay.hh ../src/workspace.hh ../src/xatom.hh ../src/blackbox.hh \
|
||||||
|
../src/configuration.hh gccache.hh
|
||||||
|
gccache.o: gccache.cc gccache.hh ../src/basedisplay.hh ../src/timer.hh ../src/util.hh \
|
||||||
|
color.hh
|
||||||
|
image.o: image.cc ../src/blackbox.hh ../src/basedisplay.hh ../src/timer.hh ../src/util.hh \
|
||||||
|
../src/configuration.hh ../src/xatom.hh gccache.hh color.hh image.hh texture.hh
|
||||||
|
imagecontrol.o: imagecontrol.cc ../src/blackbox.hh ../src/basedisplay.hh ../src/timer.hh \
|
||||||
|
../src/util.hh ../src/configuration.hh ../src/xatom.hh color.hh image.hh texture.hh
|
||||||
|
texture.o: texture.cc texture.hh color.hh ../src/util.hh ../src/basedisplay.hh \
|
||||||
|
../src/timer.hh image.hh ../src/screen.hh ../src/workspace.hh ../src/xatom.hh \
|
||||||
|
../src/blackbox.hh ../src/configuration.hh
|
223
otk/color.cc
Normal file
223
otk/color.cc
Normal file
|
@ -0,0 +1,223 @@
|
||||||
|
// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "../config.h"
|
||||||
|
#endif // HAVE_CONFIG_H
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <stdio.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "color.hh"
|
||||||
|
#include "basedisplay.hh"
|
||||||
|
|
||||||
|
|
||||||
|
BColor::ColorCache BColor::colorcache;
|
||||||
|
bool BColor::cleancache = false;
|
||||||
|
|
||||||
|
BColor::BColor(const BaseDisplay * const _display, unsigned int _screen)
|
||||||
|
: allocated(false), r(-1), g(-1), b(-1), p(0), dpy(_display), scrn(_screen)
|
||||||
|
{}
|
||||||
|
|
||||||
|
BColor::BColor(int _r, int _g, int _b,
|
||||||
|
const BaseDisplay * const _display, unsigned int _screen)
|
||||||
|
: allocated(false), r(_r), g(_g), b(_b), p(0), dpy(_display), scrn(_screen)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
BColor::BColor(const std::string &_name,
|
||||||
|
const BaseDisplay * const _display, unsigned int _screen)
|
||||||
|
: allocated(false), r(-1), g(-1), b(-1), p(0), dpy(_display), scrn(_screen),
|
||||||
|
colorname(_name) {
|
||||||
|
parseColorName();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BColor::~BColor(void) {
|
||||||
|
deallocate();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BColor::setDisplay(const BaseDisplay * const _display,
|
||||||
|
unsigned int _screen) {
|
||||||
|
if (_display == display() && _screen == screen()) {
|
||||||
|
// nothing to do
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
deallocate();
|
||||||
|
|
||||||
|
dpy = _display;
|
||||||
|
scrn = _screen;
|
||||||
|
|
||||||
|
if (! colorname.empty()) {
|
||||||
|
parseColorName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned long BColor::pixel(void) const {
|
||||||
|
if (! allocated) {
|
||||||
|
// mutable
|
||||||
|
BColor *that = (BColor *) this;
|
||||||
|
that->allocate();
|
||||||
|
}
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BColor::parseColorName(void) {
|
||||||
|
assert(dpy != 0);
|
||||||
|
|
||||||
|
if (colorname.empty()) {
|
||||||
|
fprintf(stderr, "BColor: empty colorname, cannot parse (using black)\n");
|
||||||
|
setRGB(0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scrn == ~(0u))
|
||||||
|
scrn = DefaultScreen(display()->getXDisplay());
|
||||||
|
Colormap colormap = display()->getScreenInfo(scrn)->getColormap();
|
||||||
|
|
||||||
|
// get rgb values from colorname
|
||||||
|
XColor xcol;
|
||||||
|
xcol.red = 0;
|
||||||
|
xcol.green = 0;
|
||||||
|
xcol.blue = 0;
|
||||||
|
xcol.pixel = 0;
|
||||||
|
|
||||||
|
if (! XParseColor(display()->getXDisplay(), colormap,
|
||||||
|
colorname.c_str(), &xcol)) {
|
||||||
|
fprintf(stderr, "BColor::allocate: color parse error: \"%s\"\n",
|
||||||
|
colorname.c_str());
|
||||||
|
setRGB(0, 0, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setRGB(xcol.red >> 8, xcol.green >> 8, xcol.blue >> 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BColor::allocate(void) {
|
||||||
|
assert(dpy != 0);
|
||||||
|
|
||||||
|
if (scrn == ~(0u)) scrn = DefaultScreen(display()->getXDisplay());
|
||||||
|
Colormap colormap = display()->getScreenInfo(scrn)->getColormap();
|
||||||
|
|
||||||
|
if (! isValid()) {
|
||||||
|
if (colorname.empty()) {
|
||||||
|
fprintf(stderr, "BColor: cannot allocate invalid color (using black)\n");
|
||||||
|
setRGB(0, 0, 0);
|
||||||
|
} else {
|
||||||
|
parseColorName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see if we have allocated this color before
|
||||||
|
RGB rgb(display(), scrn, r, g, b);
|
||||||
|
ColorCache::iterator it = colorcache.find(rgb);
|
||||||
|
if (it != colorcache.end()) {
|
||||||
|
// found
|
||||||
|
allocated = true;
|
||||||
|
p = (*it).second.p;
|
||||||
|
(*it).second.count++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// allocate color from rgb values
|
||||||
|
XColor xcol;
|
||||||
|
xcol.red = r | r << 8;
|
||||||
|
xcol.green = g | g << 8;
|
||||||
|
xcol.blue = b | b << 8;
|
||||||
|
xcol.pixel = 0;
|
||||||
|
|
||||||
|
if (! XAllocColor(display()->getXDisplay(), colormap, &xcol)) {
|
||||||
|
fprintf(stderr, "BColor::allocate: color alloc error: rgb:%x/%x/%x\n",
|
||||||
|
r, g, b);
|
||||||
|
xcol.pixel = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = xcol.pixel;
|
||||||
|
allocated = true;
|
||||||
|
|
||||||
|
colorcache.insert(ColorCacheItem(rgb, PixelRef(p)));
|
||||||
|
|
||||||
|
if (cleancache)
|
||||||
|
doCacheCleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BColor::deallocate(void) {
|
||||||
|
if (! allocated)
|
||||||
|
return;
|
||||||
|
|
||||||
|
assert(dpy != 0);
|
||||||
|
|
||||||
|
ColorCache::iterator it = colorcache.find(RGB(display(), scrn, r, g, b));
|
||||||
|
if (it != colorcache.end()) {
|
||||||
|
if ((*it).second.count >= 1)
|
||||||
|
(*it).second.count--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cleancache)
|
||||||
|
doCacheCleanup();
|
||||||
|
|
||||||
|
allocated = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BColor &BColor::operator=(const BColor &c) {
|
||||||
|
deallocate();
|
||||||
|
|
||||||
|
setRGB(c.r, c.g, c.b);
|
||||||
|
colorname = c.colorname;
|
||||||
|
dpy = c.dpy;
|
||||||
|
scrn = c.scrn;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BColor::cleanupColorCache(void) {
|
||||||
|
cleancache = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BColor::doCacheCleanup(void) {
|
||||||
|
// ### TODO - support multiple displays!
|
||||||
|
ColorCache::iterator it = colorcache.begin();
|
||||||
|
if (it == colorcache.end()) {
|
||||||
|
// nothing to do
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const BaseDisplay* const display = (*it).first.display;
|
||||||
|
unsigned long *pixels = new unsigned long[ colorcache.size() ];
|
||||||
|
unsigned int i, count;
|
||||||
|
|
||||||
|
for (i = 0; i < display->getNumberOfScreens(); i++) {
|
||||||
|
count = 0;
|
||||||
|
it = colorcache.begin();
|
||||||
|
|
||||||
|
while (it != colorcache.end()) {
|
||||||
|
if ((*it).second.count != 0 || (*it).first.screen != i) {
|
||||||
|
++it;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
pixels[ count++ ] = (*it).second.p;
|
||||||
|
ColorCache::iterator it2 = it;
|
||||||
|
++it;
|
||||||
|
colorcache.erase(it2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count > 0)
|
||||||
|
XFreeColors(display->getXDisplay(),
|
||||||
|
display->getScreenInfo(i)->getColormap(),
|
||||||
|
pixels, count, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete [] pixels;
|
||||||
|
cleancache = false;
|
||||||
|
}
|
106
otk/color.hh
Normal file
106
otk/color.hh
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
|
||||||
|
#ifndef COLOR_HH
|
||||||
|
#define COLOR_HH
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class BaseDisplay;
|
||||||
|
|
||||||
|
class BColor {
|
||||||
|
public:
|
||||||
|
BColor(const BaseDisplay * const _display = 0, unsigned int _screen = ~(0u));
|
||||||
|
BColor(int _r, int _g, int _b,
|
||||||
|
const BaseDisplay * const _display, unsigned int _screen = ~(0u));
|
||||||
|
BColor(const std::string &_name,
|
||||||
|
const BaseDisplay * const _display, unsigned int _screen = ~(0u));
|
||||||
|
~BColor(void);
|
||||||
|
|
||||||
|
inline const std::string &name(void) const { return colorname; }
|
||||||
|
|
||||||
|
inline int red(void) const { return r; }
|
||||||
|
inline int green(void) const { return g; }
|
||||||
|
inline int blue(void) const { return b; }
|
||||||
|
void setRGB(int _r, int _g, int _b) {
|
||||||
|
deallocate();
|
||||||
|
r = _r;
|
||||||
|
g = _g;
|
||||||
|
b = _b;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const BaseDisplay *display(void) const { return dpy; }
|
||||||
|
inline unsigned int screen(void) const { return scrn; }
|
||||||
|
void setDisplay(const BaseDisplay * const _display,
|
||||||
|
unsigned int _screen = ~(0u));
|
||||||
|
|
||||||
|
inline bool isAllocated(void) const { return allocated; }
|
||||||
|
|
||||||
|
inline bool isValid(void) const { return r != -1 && g != -1 && b != -1; }
|
||||||
|
|
||||||
|
unsigned long pixel(void) const;
|
||||||
|
|
||||||
|
// operators
|
||||||
|
BColor &operator=(const BColor &c);
|
||||||
|
inline bool operator==(const BColor &c) const
|
||||||
|
{ return (r == c.r && b == c.b && b == c.b); }
|
||||||
|
inline bool operator!=(const BColor &c) const
|
||||||
|
{ return (! operator==(c)); }
|
||||||
|
|
||||||
|
static void cleanupColorCache(void);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void parseColorName(void);
|
||||||
|
void allocate(void);
|
||||||
|
void deallocate(void);
|
||||||
|
|
||||||
|
bool allocated;
|
||||||
|
int r, g, b;
|
||||||
|
unsigned long p;
|
||||||
|
const BaseDisplay *dpy;
|
||||||
|
unsigned int scrn;
|
||||||
|
std::string colorname;
|
||||||
|
|
||||||
|
// global color allocator/deallocator
|
||||||
|
struct RGB {
|
||||||
|
const BaseDisplay* const display;
|
||||||
|
const unsigned int screen;
|
||||||
|
const int r, g, b;
|
||||||
|
|
||||||
|
RGB(void) : display(0), screen(~(0u)), r(-1), g(-1), b(-1) { }
|
||||||
|
RGB(const BaseDisplay * const a, const unsigned int b,
|
||||||
|
const int x, const int y, const int z)
|
||||||
|
: display(a), screen(b), r(x), g(y), b(z) {}
|
||||||
|
RGB(const RGB &x)
|
||||||
|
: display(x.display), screen(x.screen), r(x.r), g(x.g), b(x.b) {}
|
||||||
|
|
||||||
|
inline bool operator==(const RGB &x) const {
|
||||||
|
return display == x.display &&
|
||||||
|
screen == x.screen &&
|
||||||
|
r == x.r && g == x.g && b == x.b;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator<(const RGB &x) const {
|
||||||
|
unsigned long p1, p2;
|
||||||
|
p1 = (screen << 24 | r << 16 | g << 8 | b) & 0x00ffffff;
|
||||||
|
p2 = (x.screen << 24 | x.r << 16 | x.g << 8 | x.b) & 0x00ffffff;
|
||||||
|
return p1 < p2;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
struct PixelRef {
|
||||||
|
const unsigned long p;
|
||||||
|
unsigned int count;
|
||||||
|
inline PixelRef(void) : p(0), count(0) { }
|
||||||
|
inline PixelRef(const unsigned long x) : p(x), count(1) { }
|
||||||
|
};
|
||||||
|
typedef std::map<RGB,PixelRef> ColorCache;
|
||||||
|
typedef ColorCache::value_type ColorCacheItem;
|
||||||
|
static ColorCache colorcache;
|
||||||
|
static bool cleancache;
|
||||||
|
static void doCacheCleanup(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // COLOR_HH
|
BIN
otk/color.o
Normal file
BIN
otk/color.o
Normal file
Binary file not shown.
128
otk/font.cc
Normal file
128
otk/font.cc
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "../config.h"
|
||||||
|
#endif // HAVE_CONFIG_H
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#ifdef HAVE_STDLIB_H
|
||||||
|
# include <stdlib.h>
|
||||||
|
#endif // HAVE_STDLIB_H
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
using std::cerr;
|
||||||
|
using std::endl;
|
||||||
|
|
||||||
|
#include "font.hh"
|
||||||
|
#include "util.hh"
|
||||||
|
#include "gccache.hh"
|
||||||
|
#include "color.hh"
|
||||||
|
|
||||||
|
string BFont::_fallback_font = "fixed";
|
||||||
|
|
||||||
|
BFont::BFont(Display *d, BScreen *screen, const string &family, int size,
|
||||||
|
bool bold, bool italic, bool shadow, unsigned char offset,
|
||||||
|
unsigned char tint, bool antialias) :
|
||||||
|
_display(d),
|
||||||
|
_screen(screen),
|
||||||
|
_family(family),
|
||||||
|
_simplename(False),
|
||||||
|
_size(size),
|
||||||
|
_bold(bold),
|
||||||
|
_italic(italic),
|
||||||
|
_antialias(antialias),
|
||||||
|
_shadow(shadow),
|
||||||
|
_offset(offset),
|
||||||
|
_tint(tint),
|
||||||
|
_xftfont(0) {
|
||||||
|
_valid = False;
|
||||||
|
|
||||||
|
_xftfont = XftFontOpen(_display, _screen->getScreenNumber(),
|
||||||
|
XFT_FAMILY, XftTypeString, _family.c_str(),
|
||||||
|
XFT_SIZE, XftTypeInteger, _size,
|
||||||
|
XFT_WEIGHT, XftTypeInteger, (_bold ?
|
||||||
|
XFT_WEIGHT_BOLD :
|
||||||
|
XFT_WEIGHT_MEDIUM),
|
||||||
|
XFT_SLANT, XftTypeInteger, (_italic ?
|
||||||
|
XFT_SLANT_ITALIC :
|
||||||
|
XFT_SLANT_ROMAN),
|
||||||
|
XFT_ANTIALIAS, XftTypeBool, _antialias,
|
||||||
|
0);
|
||||||
|
if (! _xftfont)
|
||||||
|
return; // failure
|
||||||
|
|
||||||
|
_valid = True;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BFont::~BFont(void) {
|
||||||
|
if (_xftfont)
|
||||||
|
XftFontClose(_display, _xftfont);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BFont::drawString(Drawable d, int x, int y, const BColor &color,
|
||||||
|
const string &string) const {
|
||||||
|
assert(_valid);
|
||||||
|
|
||||||
|
XftDraw *draw = XftDrawCreate(_display, d, _screen->getVisual(),
|
||||||
|
_screen->getColormap());
|
||||||
|
assert(draw);
|
||||||
|
|
||||||
|
if (_shadow) {
|
||||||
|
XftColor c;
|
||||||
|
c.color.red = 0;
|
||||||
|
c.color.green = 0;
|
||||||
|
c.color.blue = 0;
|
||||||
|
c.color.alpha = _tint | _tint << 8; // transparent shadow
|
||||||
|
c.pixel = BlackPixel(_display, _screen->getScreenNumber());
|
||||||
|
|
||||||
|
XftDrawStringUtf8(draw, &c, _xftfont, x + _offset,
|
||||||
|
_xftfont->ascent + y + _offset,
|
||||||
|
(XftChar8 *) string.c_str(),
|
||||||
|
string.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
XftColor c;
|
||||||
|
c.color.red = color.red() | color.red() << 8;
|
||||||
|
c.color.green = color.green() | color.green() << 8;
|
||||||
|
c.color.blue = color.blue() | color.blue() << 8;
|
||||||
|
c.pixel = color.pixel();
|
||||||
|
c.color.alpha = 0xff | 0xff << 8; // no transparency in BColor yet
|
||||||
|
|
||||||
|
XftDrawStringUtf8(draw, &c, _xftfont, x, _xftfont->ascent + y,
|
||||||
|
(XftChar8 *) string.c_str(), string.size());
|
||||||
|
|
||||||
|
XftDrawDestroy(draw);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int BFont::measureString(const string &string) const {
|
||||||
|
assert(_valid);
|
||||||
|
|
||||||
|
XGlyphInfo info;
|
||||||
|
|
||||||
|
XftTextExtentsUtf8(_display, _xftfont, (XftChar8 *) string.c_str(),
|
||||||
|
string.size(), &info);
|
||||||
|
|
||||||
|
return info.xOff + (_shadow ? _offset : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int BFont::height(void) const {
|
||||||
|
assert(_valid);
|
||||||
|
|
||||||
|
return _xftfont->height + (_shadow ? _offset : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int BFont::maxCharWidth(void) const {
|
||||||
|
assert(_valid);
|
||||||
|
|
||||||
|
return _xftfont->max_advance_width;
|
||||||
|
}
|
82
otk/font.hh
Normal file
82
otk/font.hh
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
// -*- mode: C++; indent-tabs-mode: nil; -*-
|
||||||
|
#ifndef __Font_hh
|
||||||
|
#define __Font_hh
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
|
||||||
|
#include <X11/Xft/Xft.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class BGCCache;
|
||||||
|
class BGCCacheItem;
|
||||||
|
class BColor;
|
||||||
|
|
||||||
|
#include "screen.hh"
|
||||||
|
|
||||||
|
class BFont {
|
||||||
|
/*
|
||||||
|
* static members
|
||||||
|
*/
|
||||||
|
private:
|
||||||
|
static std::string _fallback_font;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// the fallback is only used for X fonts, not for Xft fonts, since it is
|
||||||
|
// assumed that X fonts will be the fallback from Xft.
|
||||||
|
inline static std::string fallbackFont(void) { return _fallback_font; }
|
||||||
|
inline static void setFallbackFont(const std::string &f)
|
||||||
|
{ _fallback_font = f; }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* instance members
|
||||||
|
*/
|
||||||
|
private:
|
||||||
|
Display *_display;
|
||||||
|
BScreen *_screen;
|
||||||
|
|
||||||
|
std::string _family;
|
||||||
|
bool _simplename; // true if not spec'd as a -*-* string
|
||||||
|
int _size;
|
||||||
|
bool _bold;
|
||||||
|
bool _italic;
|
||||||
|
|
||||||
|
bool _antialias;
|
||||||
|
bool _shadow;
|
||||||
|
unsigned char _offset;
|
||||||
|
unsigned char _tint;
|
||||||
|
|
||||||
|
XftFont *_xftfont;
|
||||||
|
|
||||||
|
bool createXftFont(void);
|
||||||
|
|
||||||
|
bool _valid;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// loads an Xft font
|
||||||
|
BFont(Display *d, BScreen *screen, const std::string &family, int size,
|
||||||
|
bool bold, bool italic, bool shadow, unsigned char offset,
|
||||||
|
unsigned char tint, bool antialias = True);
|
||||||
|
virtual ~BFont(void);
|
||||||
|
|
||||||
|
inline bool valid(void) const { return _valid; }
|
||||||
|
|
||||||
|
inline std::string family(void) const { assert(_valid); return _family; }
|
||||||
|
inline int size(void) const { assert(_valid); return _size; }
|
||||||
|
inline bool bold(void) const { assert(_valid); return _bold; }
|
||||||
|
inline bool italic(void) const { assert(_valid); return _italic; }
|
||||||
|
|
||||||
|
unsigned int height(void) const;
|
||||||
|
unsigned int maxCharWidth(void) const;
|
||||||
|
|
||||||
|
unsigned int measureString(const std::string &string) const;
|
||||||
|
|
||||||
|
void drawString(Drawable d, int x, int y, const BColor &color,
|
||||||
|
const std::string &string) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __Font_hh
|
BIN
otk/font.o
Normal file
BIN
otk/font.o
Normal file
Binary file not shown.
188
otk/gccache.cc
Normal file
188
otk/gccache.cc
Normal file
|
@ -0,0 +1,188 @@
|
||||||
|
// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "../config.h"
|
||||||
|
#endif // HAVE_CONFIG_H
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <stdio.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "gccache.hh"
|
||||||
|
#include "basedisplay.hh"
|
||||||
|
#include "color.hh"
|
||||||
|
#include "util.hh"
|
||||||
|
|
||||||
|
|
||||||
|
BGCCacheContext::~BGCCacheContext(void) {
|
||||||
|
if (gc)
|
||||||
|
XFreeGC(display->getXDisplay(), gc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BGCCacheContext::set(const BColor &_color,
|
||||||
|
const XFontStruct * const _font,
|
||||||
|
const int _function, const int _subwindow,
|
||||||
|
int _linewidth) {
|
||||||
|
XGCValues gcv;
|
||||||
|
pixel = gcv.foreground = _color.pixel();
|
||||||
|
function = gcv.function = _function;
|
||||||
|
subwindow = gcv.subwindow_mode = _subwindow;
|
||||||
|
linewidth = gcv.line_width = _linewidth;
|
||||||
|
gcv.cap_style = CapProjecting;
|
||||||
|
|
||||||
|
unsigned long mask = GCForeground | GCFunction | GCSubwindowMode |
|
||||||
|
GCLineWidth | GCCapStyle;
|
||||||
|
|
||||||
|
if (_font) {
|
||||||
|
fontid = gcv.font = _font->fid;
|
||||||
|
mask |= GCFont;
|
||||||
|
} else {
|
||||||
|
fontid = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
XChangeGC(display->getXDisplay(), gc, mask, &gcv);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BGCCacheContext::set(const XFontStruct * const _font) {
|
||||||
|
if (! _font) {
|
||||||
|
fontid = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
XGCValues gcv;
|
||||||
|
fontid = gcv.font = _font->fid;
|
||||||
|
XChangeGC(display->getXDisplay(), gc, GCFont, &gcv);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BGCCache::BGCCache(const BaseDisplay * const _display,
|
||||||
|
unsigned int screen_count)
|
||||||
|
: display(_display), context_count(128u),
|
||||||
|
cache_size(16u), cache_buckets(8u * screen_count),
|
||||||
|
cache_total_size(cache_size * cache_buckets) {
|
||||||
|
|
||||||
|
contexts = new BGCCacheContext*[context_count];
|
||||||
|
unsigned int i;
|
||||||
|
for (i = 0; i < context_count; i++) {
|
||||||
|
contexts[i] = new BGCCacheContext(display);
|
||||||
|
}
|
||||||
|
|
||||||
|
cache = new BGCCacheItem*[cache_total_size];
|
||||||
|
for (i = 0; i < cache_total_size; ++i) {
|
||||||
|
cache[i] = new BGCCacheItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BGCCache::~BGCCache(void) {
|
||||||
|
std::for_each(contexts, contexts + context_count, PointerAssassin());
|
||||||
|
std::for_each(cache, cache + cache_total_size, PointerAssassin());
|
||||||
|
delete [] cache;
|
||||||
|
delete [] contexts;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BGCCacheContext *BGCCache::nextContext(unsigned int scr) {
|
||||||
|
Window hd = display->getScreenInfo(scr)->getRootWindow();
|
||||||
|
|
||||||
|
BGCCacheContext *c;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < context_count; ++i) {
|
||||||
|
c = contexts[i];
|
||||||
|
|
||||||
|
if (! c->gc) {
|
||||||
|
c->gc = XCreateGC(display->getXDisplay(), hd, 0, 0);
|
||||||
|
c->used = false;
|
||||||
|
c->screen = scr;
|
||||||
|
}
|
||||||
|
if (! c->used && c->screen == scr)
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "BGCCache: context fault!\n");
|
||||||
|
abort();
|
||||||
|
return (BGCCacheContext*) 0; // not reached
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BGCCache::release(BGCCacheContext *ctx) {
|
||||||
|
ctx->used = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BGCCacheItem *BGCCache::find(const BColor &_color,
|
||||||
|
const XFontStruct * const _font,
|
||||||
|
int _function, int _subwindow, int _linewidth) {
|
||||||
|
const unsigned long pixel = _color.pixel();
|
||||||
|
const unsigned int screen = _color.screen();
|
||||||
|
const int key = _color.red() ^ _color.green() ^ _color.blue();
|
||||||
|
int k = (key % cache_size) * cache_buckets;
|
||||||
|
unsigned int i = 0; // loop variable
|
||||||
|
BGCCacheItem *c = cache[ k ], *prev = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
this will either loop cache_buckets times then return/abort or
|
||||||
|
it will stop matching
|
||||||
|
*/
|
||||||
|
while (c->ctx &&
|
||||||
|
(c->ctx->pixel != pixel || c->ctx->function != _function ||
|
||||||
|
c->ctx->subwindow != _subwindow || c->ctx->screen != screen ||
|
||||||
|
c->ctx->linewidth != _linewidth)) {
|
||||||
|
if (i < (cache_buckets - 1)) {
|
||||||
|
prev = c;
|
||||||
|
c = cache[ ++k ];
|
||||||
|
++i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (c->count == 0 && c->ctx->screen == screen) {
|
||||||
|
// use this cache item
|
||||||
|
c->ctx->set(_color, _font, _function, _subwindow, _linewidth);
|
||||||
|
c->ctx->used = true;
|
||||||
|
c->count = 1;
|
||||||
|
c->hits = 1;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
// cache fault!
|
||||||
|
fprintf(stderr, "BGCCache: cache fault, count: %d, screen: %d, item screen: %d\n", c->count, screen, c->ctx->screen);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c->ctx) {
|
||||||
|
// reuse existing context
|
||||||
|
if (_font && _font->fid && _font->fid != c->ctx->fontid)
|
||||||
|
c->ctx->set(_font);
|
||||||
|
c->count++;
|
||||||
|
c->hits++;
|
||||||
|
if (prev && c->hits > prev->hits) {
|
||||||
|
cache[ k ] = prev;
|
||||||
|
cache[ k - 1 ] = c;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
c->ctx = nextContext(screen);
|
||||||
|
c->ctx->set(_color, _font, _function, _subwindow, _linewidth);
|
||||||
|
c->ctx->used = true;
|
||||||
|
c->count = 1;
|
||||||
|
c->hits = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BGCCache::release(BGCCacheItem *_item) {
|
||||||
|
_item->count--;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BGCCache::purge(void) {
|
||||||
|
for (unsigned int i = 0; i < cache_total_size; ++i) {
|
||||||
|
BGCCacheItem *d = cache[ i ];
|
||||||
|
|
||||||
|
if (d->ctx && d->count == 0) {
|
||||||
|
release(d->ctx);
|
||||||
|
d->ctx = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
119
otk/gccache.hh
Normal file
119
otk/gccache.hh
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
|
||||||
|
#ifndef GCCACHE_HH
|
||||||
|
#define GCCACHE_HH
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "basedisplay.hh"
|
||||||
|
#include "color.hh"
|
||||||
|
|
||||||
|
class BGCCacheItem;
|
||||||
|
|
||||||
|
class BGCCacheContext {
|
||||||
|
public:
|
||||||
|
void set(const BColor &_color, const XFontStruct * const _font,
|
||||||
|
const int _function, const int _subwindow, const int _linewidth);
|
||||||
|
void set(const XFontStruct * const _font);
|
||||||
|
|
||||||
|
~BGCCacheContext(void);
|
||||||
|
|
||||||
|
private:
|
||||||
|
BGCCacheContext(const BaseDisplay * const _display)
|
||||||
|
: display(_display), gc(0), pixel(0ul), fontid(0ul),
|
||||||
|
function(0), subwindow(0), used(false), screen(~(0u)), linewidth(0) {}
|
||||||
|
|
||||||
|
const BaseDisplay *display;
|
||||||
|
GC gc;
|
||||||
|
unsigned long pixel;
|
||||||
|
unsigned long fontid;
|
||||||
|
int function;
|
||||||
|
int subwindow;
|
||||||
|
bool used;
|
||||||
|
unsigned int screen;
|
||||||
|
int linewidth;
|
||||||
|
|
||||||
|
BGCCacheContext(const BGCCacheContext &_nocopy);
|
||||||
|
BGCCacheContext &operator=(const BGCCacheContext &_nocopy);
|
||||||
|
|
||||||
|
friend class BGCCache;
|
||||||
|
friend class BGCCacheItem;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BGCCacheItem {
|
||||||
|
public:
|
||||||
|
inline const GC &gc(void) const { return ctx->gc; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
BGCCacheItem(void) : ctx(0), count(0), hits(0), fault(false) { }
|
||||||
|
|
||||||
|
BGCCacheContext *ctx;
|
||||||
|
unsigned int count;
|
||||||
|
unsigned int hits;
|
||||||
|
bool fault;
|
||||||
|
|
||||||
|
BGCCacheItem(const BGCCacheItem &_nocopy);
|
||||||
|
BGCCacheItem &operator=(const BGCCacheItem &_nocopy);
|
||||||
|
|
||||||
|
friend class BGCCache;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BGCCache {
|
||||||
|
public:
|
||||||
|
BGCCache(const BaseDisplay * const _display, unsigned int screen_count);
|
||||||
|
~BGCCache(void);
|
||||||
|
|
||||||
|
// cleans up the cache
|
||||||
|
void purge(void);
|
||||||
|
|
||||||
|
BGCCacheItem *find(const BColor &_color, const XFontStruct * const _font = 0,
|
||||||
|
int _function = GXcopy, int _subwindow = ClipByChildren,
|
||||||
|
int _linewidth = 0);
|
||||||
|
void release(BGCCacheItem *_item);
|
||||||
|
|
||||||
|
private:
|
||||||
|
BGCCacheContext *nextContext(unsigned int _screen);
|
||||||
|
void release(BGCCacheContext *ctx);
|
||||||
|
|
||||||
|
// this is closely modelled after the Qt GC cache, but with some of the
|
||||||
|
// complexity stripped out
|
||||||
|
const BaseDisplay *display;
|
||||||
|
|
||||||
|
const unsigned int context_count;
|
||||||
|
const unsigned int cache_size;
|
||||||
|
const unsigned int cache_buckets;
|
||||||
|
const unsigned int cache_total_size;
|
||||||
|
BGCCacheContext **contexts;
|
||||||
|
BGCCacheItem **cache;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BPen {
|
||||||
|
public:
|
||||||
|
inline BPen(const BColor &_color, const XFontStruct * const _font = 0,
|
||||||
|
int _linewidth = 0, int _function = GXcopy,
|
||||||
|
int _subwindow = ClipByChildren)
|
||||||
|
: color(_color), font(_font), linewidth(_linewidth), function(_function),
|
||||||
|
subwindow(_subwindow), cache(_color.display()->gcCache()), item(0) { }
|
||||||
|
|
||||||
|
inline ~BPen(void) { if (item) cache->release(item); }
|
||||||
|
|
||||||
|
inline const GC &gc(void) const {
|
||||||
|
if (! item) item = cache->find(color, font, function, subwindow,
|
||||||
|
linewidth);
|
||||||
|
return item->gc();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const BColor &color;
|
||||||
|
const XFontStruct *font;
|
||||||
|
int linewidth;
|
||||||
|
int function;
|
||||||
|
int subwindow;
|
||||||
|
|
||||||
|
mutable BGCCache *cache;
|
||||||
|
mutable BGCCacheItem *item;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // GCCACHE_HH
|
BIN
otk/gccache.o
Normal file
BIN
otk/gccache.o
Normal file
Binary file not shown.
1677
otk/image.cc
Normal file
1677
otk/image.cc
Normal file
File diff suppressed because it is too large
Load diff
144
otk/image.hh
Normal file
144
otk/image.hh
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
// -*- mode: C++; indent-tabs-mode: nil; -*-
|
||||||
|
#ifndef __Image_hh
|
||||||
|
#define __Image_hh
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <X11/Xutil.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
#include "timer.hh"
|
||||||
|
#include "basedisplay.hh"
|
||||||
|
#include "color.hh"
|
||||||
|
|
||||||
|
class BImageControl;
|
||||||
|
class BTexture;
|
||||||
|
|
||||||
|
class BImage {
|
||||||
|
private:
|
||||||
|
BImageControl *control;
|
||||||
|
bool interlaced;
|
||||||
|
XColor *colors;
|
||||||
|
|
||||||
|
BColor from, to;
|
||||||
|
int red_offset, green_offset, blue_offset, red_bits, green_bits, blue_bits,
|
||||||
|
ncolors, cpc, cpccpc;
|
||||||
|
unsigned char *red, *green, *blue, *red_table, *green_table, *blue_table;
|
||||||
|
unsigned int width, height, *xtable, *ytable;
|
||||||
|
|
||||||
|
void TrueColorDither(unsigned int bit_depth, int bytes_per_line,
|
||||||
|
unsigned char *pixel_data);
|
||||||
|
void PseudoColorDither(int bytes_per_line, unsigned char *pixel_data);
|
||||||
|
#ifdef ORDEREDPSEUDO
|
||||||
|
void OrderedPseudoColorDither(int bytes_per_line, unsigned char *pixel_data);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Pixmap renderPixmap(void);
|
||||||
|
Pixmap render_solid(const BTexture &texture);
|
||||||
|
Pixmap render_gradient(const BTexture &texture);
|
||||||
|
|
||||||
|
XImage *renderXImage(void);
|
||||||
|
|
||||||
|
void invert(void);
|
||||||
|
void bevel1(void);
|
||||||
|
void bevel2(void);
|
||||||
|
void border(const BTexture &texture);
|
||||||
|
void dgradient(void);
|
||||||
|
void egradient(void);
|
||||||
|
void hgradient(void);
|
||||||
|
void pgradient(void);
|
||||||
|
void rgradient(void);
|
||||||
|
void vgradient(void);
|
||||||
|
void cdgradient(void);
|
||||||
|
void pcgradient(void);
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
BImage(BImageControl *c, int w, int h);
|
||||||
|
~BImage(void);
|
||||||
|
|
||||||
|
Pixmap render(const BTexture &texture);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class BImageControl : public TimeoutHandler {
|
||||||
|
public:
|
||||||
|
struct CachedImage {
|
||||||
|
Pixmap pixmap;
|
||||||
|
|
||||||
|
unsigned int count, width, height;
|
||||||
|
unsigned long pixel1, pixel2, texture;
|
||||||
|
};
|
||||||
|
|
||||||
|
BImageControl(BaseDisplay *dpy, const ScreenInfo *scrn,
|
||||||
|
bool _dither= False, int _cpc = 4,
|
||||||
|
unsigned long cache_timeout = 300000l,
|
||||||
|
unsigned long cmax = 200l);
|
||||||
|
virtual ~BImageControl(void);
|
||||||
|
|
||||||
|
inline BaseDisplay *getBaseDisplay(void) const { return basedisplay; }
|
||||||
|
|
||||||
|
inline bool doDither(void) { return dither; }
|
||||||
|
|
||||||
|
inline const ScreenInfo *getScreenInfo(void) { return screeninfo; }
|
||||||
|
|
||||||
|
inline Window getDrawable(void) const { return window; }
|
||||||
|
|
||||||
|
inline Visual *getVisual(void) { return screeninfo->getVisual(); }
|
||||||
|
|
||||||
|
inline int getBitsPerPixel(void) const { return bits_per_pixel; }
|
||||||
|
inline int getDepth(void) const { return screen_depth; }
|
||||||
|
inline int getColorsPerChannel(void) const
|
||||||
|
{ return colors_per_channel; }
|
||||||
|
|
||||||
|
unsigned long getSqrt(unsigned int x);
|
||||||
|
|
||||||
|
Pixmap renderImage(unsigned int width, unsigned int height,
|
||||||
|
const BTexture &texture);
|
||||||
|
|
||||||
|
void installRootColormap(void);
|
||||||
|
void removeImage(Pixmap pixmap);
|
||||||
|
void getColorTables(unsigned char **rmt, unsigned char **gmt,
|
||||||
|
unsigned char **bmt,
|
||||||
|
int *roff, int *goff, int *boff,
|
||||||
|
int *rbit, int *gbit, int *bbit);
|
||||||
|
void getXColorTable(XColor **c, int *n);
|
||||||
|
void getGradientBuffers(unsigned int w, unsigned int h,
|
||||||
|
unsigned int **xbuf, unsigned int **ybuf);
|
||||||
|
void setDither(bool d) { dither = d; }
|
||||||
|
void setColorsPerChannel(int cpc);
|
||||||
|
|
||||||
|
virtual void timeout(void);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool dither;
|
||||||
|
BaseDisplay *basedisplay;
|
||||||
|
const ScreenInfo *screeninfo;
|
||||||
|
BTimer *timer;
|
||||||
|
|
||||||
|
Colormap colormap;
|
||||||
|
|
||||||
|
Window window;
|
||||||
|
XColor *colors;
|
||||||
|
int colors_per_channel, ncolors, screen_number, screen_depth,
|
||||||
|
bits_per_pixel, red_offset, green_offset, blue_offset,
|
||||||
|
red_bits, green_bits, blue_bits;
|
||||||
|
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;
|
||||||
|
unsigned long *sqrt_table, cache_max;
|
||||||
|
|
||||||
|
typedef std::list<CachedImage> CacheContainer;
|
||||||
|
CacheContainer cache;
|
||||||
|
|
||||||
|
Pixmap searchCache(const unsigned int width, const unsigned int height,
|
||||||
|
const unsigned long texture,
|
||||||
|
const BColor &c1, const BColor &c2);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // __Image_hh
|
||||||
|
|
BIN
otk/image.o
Normal file
BIN
otk/image.o
Normal file
Binary file not shown.
561
otk/imagecontrol.cc
Normal file
561
otk/imagecontrol.cc
Normal file
|
@ -0,0 +1,561 @@
|
||||||
|
// -*- mode: C++; indent-tabs-mode: nil; -*-
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "../config.h"
|
||||||
|
#endif // HAVE_CONFIG_H
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#ifdef HAVE_STDIO_H
|
||||||
|
# include <stdio.h>
|
||||||
|
#endif // HAVE_STDIO_H
|
||||||
|
|
||||||
|
#ifdef HAVE_CTYPE_H
|
||||||
|
# include <ctype.h>
|
||||||
|
#endif // HAVE_CTYPE_H
|
||||||
|
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "blackbox.hh"
|
||||||
|
#include "basedisplay.hh"
|
||||||
|
#include "color.hh"
|
||||||
|
#include "image.hh"
|
||||||
|
#include "texture.hh"
|
||||||
|
|
||||||
|
static 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 *ctrl = 0;
|
||||||
|
|
||||||
|
BImageControl::BImageControl(BaseDisplay *dpy, const ScreenInfo *scrn,
|
||||||
|
bool _dither, int _cpc,
|
||||||
|
unsigned long cache_timeout,
|
||||||
|
unsigned long cmax) {
|
||||||
|
if (! ctrl) ctrl = this;
|
||||||
|
|
||||||
|
basedisplay = dpy;
|
||||||
|
screeninfo = scrn;
|
||||||
|
setDither(_dither);
|
||||||
|
setColorsPerChannel(_cpc);
|
||||||
|
|
||||||
|
cache_max = cmax;
|
||||||
|
if (cache_timeout) {
|
||||||
|
timer = new BTimer(basedisplay, this);
|
||||||
|
timer->setTimeout(cache_timeout);
|
||||||
|
timer->start();
|
||||||
|
} else {
|
||||||
|
timer = (BTimer *) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
colors = (XColor *) 0;
|
||||||
|
ncolors = 0;
|
||||||
|
|
||||||
|
grad_xbuffer = grad_ybuffer = (unsigned int *) 0;
|
||||||
|
grad_buffer_width = grad_buffer_height = 0;
|
||||||
|
|
||||||
|
sqrt_table = (unsigned long *) 0;
|
||||||
|
|
||||||
|
screen_depth = screeninfo->getDepth();
|
||||||
|
window = screeninfo->getRootWindow();
|
||||||
|
screen_number = screeninfo->getScreenNumber();
|
||||||
|
colormap = screeninfo->getColormap();
|
||||||
|
|
||||||
|
int count;
|
||||||
|
XPixmapFormatValues *pmv = XListPixmapFormats(basedisplay->getXDisplay(),
|
||||||
|
&count);
|
||||||
|
if (pmv) {
|
||||||
|
bits_per_pixel = 0;
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
if (pmv[i].depth == screen_depth) {
|
||||||
|
bits_per_pixel = pmv[i].bits_per_pixel;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
XFree(pmv);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bits_per_pixel == 0) bits_per_pixel = screen_depth;
|
||||||
|
if (bits_per_pixel >= 24) setDither(False);
|
||||||
|
|
||||||
|
red_offset = green_offset = blue_offset = 0;
|
||||||
|
|
||||||
|
switch (getVisual()->c_class) {
|
||||||
|
case TrueColor: {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
// compute color tables
|
||||||
|
unsigned long red_mask = getVisual()->red_mask,
|
||||||
|
green_mask = getVisual()->green_mask,
|
||||||
|
blue_mask = getVisual()->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: {
|
||||||
|
ncolors = colors_per_channel * colors_per_channel * colors_per_channel;
|
||||||
|
|
||||||
|
if (ncolors > (1 << screen_depth)) {
|
||||||
|
colors_per_channel = (1 << screen_depth) / 3;
|
||||||
|
ncolors = colors_per_channel * colors_per_channel * colors_per_channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (colors_per_channel < 2 || ncolors > (1 << screen_depth)) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"BImageControl::BImageControl: invalid colormap size %d "
|
||||||
|
"(%d/%d/%d) - reducing",
|
||||||
|
ncolors, colors_per_channel, colors_per_channel,
|
||||||
|
colors_per_channel);
|
||||||
|
|
||||||
|
colors_per_channel = (1 << screen_depth) / 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
colors = new XColor[ncolors];
|
||||||
|
if (! colors) {
|
||||||
|
fprintf(stderr, "BImageControl::BImageControl: error allocating "
|
||||||
|
"colormap\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int i = 0, ii, p, r, g, b,
|
||||||
|
|
||||||
|
#ifdef ORDEREDPSEUDO
|
||||||
|
bits = 256 / colors_per_channel;
|
||||||
|
#else // !ORDEREDPSEUDO
|
||||||
|
bits = 255 / (colors_per_channel - 1);
|
||||||
|
#endif // ORDEREDPSEUDO
|
||||||
|
|
||||||
|
red_bits = green_bits = blue_bits = bits;
|
||||||
|
|
||||||
|
for (i = 0; i < 256; i++)
|
||||||
|
red_color_table[i] = green_color_table[i] = blue_color_table[i] =
|
||||||
|
i / bits;
|
||||||
|
|
||||||
|
for (r = 0, i = 0; r < colors_per_channel; r++)
|
||||||
|
for (g = 0; g < colors_per_channel; g++)
|
||||||
|
for (b = 0; b < colors_per_channel; b++, i++) {
|
||||||
|
colors[i].red = (r * 0xffff) / (colors_per_channel - 1);
|
||||||
|
colors[i].green = (g * 0xffff) / (colors_per_channel - 1);
|
||||||
|
colors[i].blue = (b * 0xffff) / (colors_per_channel - 1);;
|
||||||
|
colors[i].flags = DoRed|DoGreen|DoBlue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < ncolors; i++) {
|
||||||
|
if (! XAllocColor(basedisplay->getXDisplay(), colormap, &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;
|
||||||
|
} else {
|
||||||
|
colors[i].flags = DoRed|DoGreen|DoBlue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
XColor icolors[256];
|
||||||
|
int incolors = (((1 << screen_depth) > 256) ? 256 : (1 << screen_depth));
|
||||||
|
|
||||||
|
for (i = 0; i < incolors; i++)
|
||||||
|
icolors[i].pixel = i;
|
||||||
|
|
||||||
|
XQueryColors(basedisplay->getXDisplay(), colormap, icolors, incolors);
|
||||||
|
for (i = 0; i < ncolors; i++) {
|
||||||
|
if (! colors[i].flags) {
|
||||||
|
unsigned long chk = 0xffffffff, pixel, close = 0;
|
||||||
|
|
||||||
|
p = 2;
|
||||||
|
while (p--) {
|
||||||
|
for (ii = 0; ii < incolors; ii++) {
|
||||||
|
r = (colors[i].red - icolors[i].red) >> 8;
|
||||||
|
g = (colors[i].green - icolors[i].green) >> 8;
|
||||||
|
b = (colors[i].blue - icolors[i].blue) >> 8;
|
||||||
|
pixel = (r * r) + (g * g) + (b * b);
|
||||||
|
|
||||||
|
if (pixel < chk) {
|
||||||
|
chk = pixel;
|
||||||
|
close = ii;
|
||||||
|
}
|
||||||
|
|
||||||
|
colors[i].red = icolors[close].red;
|
||||||
|
colors[i].green = icolors[close].green;
|
||||||
|
colors[i].blue = icolors[close].blue;
|
||||||
|
|
||||||
|
if (XAllocColor(basedisplay->getXDisplay(), colormap,
|
||||||
|
&colors[i])) {
|
||||||
|
colors[i].flags = DoRed|DoGreen|DoBlue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case GrayScale:
|
||||||
|
case StaticGray: {
|
||||||
|
if (getVisual()->c_class == StaticGray) {
|
||||||
|
ncolors = 1 << screen_depth;
|
||||||
|
} else {
|
||||||
|
ncolors = colors_per_channel * colors_per_channel * colors_per_channel;
|
||||||
|
|
||||||
|
if (ncolors > (1 << screen_depth)) {
|
||||||
|
colors_per_channel = (1 << screen_depth) / 3;
|
||||||
|
ncolors =
|
||||||
|
colors_per_channel * colors_per_channel * colors_per_channel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (colors_per_channel < 2 || ncolors > (1 << screen_depth)) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"BImageControl::BImageControl: invalid colormap size %d "
|
||||||
|
"(%d/%d/%d) - reducing",
|
||||||
|
ncolors, colors_per_channel, colors_per_channel,
|
||||||
|
colors_per_channel);
|
||||||
|
|
||||||
|
colors_per_channel = (1 << screen_depth) / 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
colors = new XColor[ncolors];
|
||||||
|
if (! colors) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"BImageControl::BImageControl: error allocating colormap\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int i = 0, ii, p, bits = 255 / (colors_per_channel - 1);
|
||||||
|
red_bits = green_bits = blue_bits = bits;
|
||||||
|
|
||||||
|
for (i = 0; i < 256; i++)
|
||||||
|
red_color_table[i] = green_color_table[i] = blue_color_table[i] =
|
||||||
|
i / bits;
|
||||||
|
|
||||||
|
for (i = 0; i < ncolors; i++) {
|
||||||
|
colors[i].red = (i * 0xffff) / (colors_per_channel - 1);
|
||||||
|
colors[i].green = (i * 0xffff) / (colors_per_channel - 1);
|
||||||
|
colors[i].blue = (i * 0xffff) / (colors_per_channel - 1);;
|
||||||
|
colors[i].flags = DoRed|DoGreen|DoBlue;
|
||||||
|
|
||||||
|
if (! XAllocColor(basedisplay->getXDisplay(), colormap,
|
||||||
|
&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;
|
||||||
|
} else {
|
||||||
|
colors[i].flags = DoRed|DoGreen|DoBlue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
XColor icolors[256];
|
||||||
|
int incolors = (((1 << screen_depth) > 256) ? 256 :
|
||||||
|
(1 << screen_depth));
|
||||||
|
|
||||||
|
for (i = 0; i < incolors; i++)
|
||||||
|
icolors[i].pixel = i;
|
||||||
|
|
||||||
|
XQueryColors(basedisplay->getXDisplay(), colormap, icolors, incolors);
|
||||||
|
for (i = 0; i < ncolors; i++) {
|
||||||
|
if (! colors[i].flags) {
|
||||||
|
unsigned long chk = 0xffffffff, pixel, close = 0;
|
||||||
|
|
||||||
|
p = 2;
|
||||||
|
while (p--) {
|
||||||
|
for (ii = 0; ii < incolors; 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;
|
||||||
|
pixel = (r * r) + (g * g) + (b * b);
|
||||||
|
|
||||||
|
if (pixel < chk) {
|
||||||
|
chk = pixel;
|
||||||
|
close = ii;
|
||||||
|
}
|
||||||
|
|
||||||
|
colors[i].red = icolors[close].red;
|
||||||
|
colors[i].green = icolors[close].green;
|
||||||
|
colors[i].blue = icolors[close].blue;
|
||||||
|
|
||||||
|
if (XAllocColor(basedisplay->getXDisplay(), colormap,
|
||||||
|
&colors[i])) {
|
||||||
|
colors[i].flags = DoRed|DoGreen|DoBlue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "BImageControl::BImageControl: unsupported visual %d\n",
|
||||||
|
getVisual()->c_class);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BImageControl::~BImageControl(void) {
|
||||||
|
delete [] sqrt_table;
|
||||||
|
|
||||||
|
delete [] grad_xbuffer;
|
||||||
|
|
||||||
|
delete [] grad_ybuffer;
|
||||||
|
|
||||||
|
if (colors) {
|
||||||
|
unsigned long *pixels = new unsigned long [ncolors];
|
||||||
|
|
||||||
|
for (int i = 0; i < ncolors; i++)
|
||||||
|
*(pixels + i) = (*(colors + i)).pixel;
|
||||||
|
|
||||||
|
XFreeColors(basedisplay->getXDisplay(), colormap, pixels, ncolors, 0);
|
||||||
|
|
||||||
|
delete [] colors;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! cache.empty()) {
|
||||||
|
//#ifdef DEBUG
|
||||||
|
fprintf(stderr, "BImageContol::~BImageControl: pixmap cache - "
|
||||||
|
"releasing %d pixmaps\n", cache.size());
|
||||||
|
//#endif
|
||||||
|
CacheContainer::iterator it = cache.begin();
|
||||||
|
const CacheContainer::iterator end = cache.end();
|
||||||
|
for (; it != end; ++it)
|
||||||
|
XFreePixmap(basedisplay->getXDisplay(), it->pixmap);
|
||||||
|
}
|
||||||
|
if (timer) {
|
||||||
|
timer->stop();
|
||||||
|
delete timer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Pixmap BImageControl::searchCache(const unsigned int width,
|
||||||
|
const unsigned int height,
|
||||||
|
const unsigned long texture,
|
||||||
|
const BColor &c1, const BColor &c2) {
|
||||||
|
if (cache.empty())
|
||||||
|
return None;
|
||||||
|
|
||||||
|
CacheContainer::iterator it = cache.begin();
|
||||||
|
const CacheContainer::iterator end = cache.end();
|
||||||
|
for (; it != end; ++it) {
|
||||||
|
CachedImage& tmp = *it;
|
||||||
|
if (tmp.width == width && tmp.height == height &&
|
||||||
|
tmp.texture == texture && tmp.pixel1 == c1.pixel())
|
||||||
|
if (texture & BTexture::Gradient) {
|
||||||
|
if (tmp.pixel2 == c2.pixel()) {
|
||||||
|
tmp.count++;
|
||||||
|
return tmp.pixmap;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tmp.count++;
|
||||||
|
return tmp.pixmap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Pixmap BImageControl::renderImage(unsigned int width, unsigned int height,
|
||||||
|
const BTexture &texture) {
|
||||||
|
if (texture.texture() & BTexture::Parent_Relative) return ParentRelative;
|
||||||
|
|
||||||
|
Pixmap pixmap = searchCache(width, height, texture.texture(),
|
||||||
|
texture.color(), texture.colorTo());
|
||||||
|
if (pixmap) return pixmap;
|
||||||
|
|
||||||
|
BImage image(this, width, height);
|
||||||
|
pixmap = image.render(texture);
|
||||||
|
|
||||||
|
if (! pixmap)
|
||||||
|
return None;
|
||||||
|
|
||||||
|
CachedImage tmp;
|
||||||
|
|
||||||
|
tmp.pixmap = pixmap;
|
||||||
|
tmp.width = width;
|
||||||
|
tmp.height = height;
|
||||||
|
tmp.count = 1;
|
||||||
|
tmp.texture = texture.texture();
|
||||||
|
tmp.pixel1 = texture.color().pixel();
|
||||||
|
|
||||||
|
if (texture.texture() & BTexture::Gradient)
|
||||||
|
tmp.pixel2 = texture.colorTo().pixel();
|
||||||
|
else
|
||||||
|
tmp.pixel2 = 0l;
|
||||||
|
|
||||||
|
cache.push_back(tmp);
|
||||||
|
|
||||||
|
if (cache.size() > cache_max) {
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf(stderr, "BImageControl::renderImage: cache is large, "
|
||||||
|
"forcing cleanout\n");
|
||||||
|
#endif // DEBUG
|
||||||
|
|
||||||
|
timeout();
|
||||||
|
}
|
||||||
|
|
||||||
|
return pixmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BImageControl::removeImage(Pixmap pixmap) {
|
||||||
|
if (! pixmap)
|
||||||
|
return;
|
||||||
|
|
||||||
|
CacheContainer::iterator it = cache.begin();
|
||||||
|
const CacheContainer::iterator end = cache.end();
|
||||||
|
for (; it != end; ++it) {
|
||||||
|
CachedImage &tmp = *it;
|
||||||
|
if (tmp.pixmap == pixmap && tmp.count > 0)
|
||||||
|
tmp.count--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! timer)
|
||||||
|
timeout();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BImageControl::getColorTables(unsigned char **rmt, unsigned char **gmt,
|
||||||
|
unsigned char **bmt,
|
||||||
|
int *roff, int *goff, int *boff,
|
||||||
|
int *rbit, int *gbit, int *bbit) {
|
||||||
|
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 = colors;
|
||||||
|
if (n) *n = ncolors;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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(void) {
|
||||||
|
int ncmap = 0;
|
||||||
|
Colormap *cmaps =
|
||||||
|
XListInstalledColormaps(basedisplay->getXDisplay(), window, &ncmap);
|
||||||
|
|
||||||
|
if (cmaps) {
|
||||||
|
bool install = True;
|
||||||
|
for (int i = 0; i < ncmap; i++)
|
||||||
|
if (*(cmaps + i) == colormap)
|
||||||
|
install = False;
|
||||||
|
|
||||||
|
if (install)
|
||||||
|
XInstallColormap(basedisplay->getXDisplay(), colormap);
|
||||||
|
|
||||||
|
XFree(cmaps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BImageControl::setColorsPerChannel(int cpc) {
|
||||||
|
if (cpc < 2) cpc = 2;
|
||||||
|
if (cpc > 6) cpc = 6;
|
||||||
|
|
||||||
|
colors_per_channel = cpc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned long BImageControl::getSqrt(unsigned int x) {
|
||||||
|
if (! sqrt_table) {
|
||||||
|
// build sqrt table for use with elliptic gradient
|
||||||
|
|
||||||
|
sqrt_table = new unsigned long[(256 * 256 * 2) + 1];
|
||||||
|
|
||||||
|
for (int i = 0; i < (256 * 256 * 2); i++)
|
||||||
|
*(sqrt_table + i) = bsqrt(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (*(sqrt_table + x));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct ZeroRefCheck {
|
||||||
|
inline bool operator()(const BImageControl::CachedImage &image) const {
|
||||||
|
return (image.count == 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CacheCleaner {
|
||||||
|
Display *display;
|
||||||
|
ZeroRefCheck ref_check;
|
||||||
|
CacheCleaner(Display *d): display(d) {}
|
||||||
|
inline void operator()(const BImageControl::CachedImage& image) const {
|
||||||
|
if (ref_check(image))
|
||||||
|
XFreePixmap(display, image.pixmap);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void BImageControl::timeout(void) {
|
||||||
|
CacheCleaner cleaner(basedisplay->getXDisplay());
|
||||||
|
std::for_each(cache.begin(), cache.end(), cleaner);
|
||||||
|
cache.remove_if(cleaner.ref_check);
|
||||||
|
}
|
||||||
|
|
183
otk/texture.cc
Normal file
183
otk/texture.cc
Normal file
|
@ -0,0 +1,183 @@
|
||||||
|
// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "../config.h"
|
||||||
|
#endif // HAVE_CONFIG_H
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <stdio.h>
|
||||||
|
#ifdef HAVE_CTYPE_H
|
||||||
|
#include <ctype.h>
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "texture.hh"
|
||||||
|
#include "basedisplay.hh"
|
||||||
|
#include "image.hh"
|
||||||
|
#include "screen.hh"
|
||||||
|
#include "blackbox.hh"
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
|
||||||
|
|
||||||
|
BTexture::BTexture(const BaseDisplay * const _display,
|
||||||
|
unsigned int _screen, BImageControl* _ctrl)
|
||||||
|
: c(_display, _screen), ct(_display, _screen),
|
||||||
|
lc(_display, _screen), sc(_display, _screen), bc(_display, _screen), t(0),
|
||||||
|
dpy(_display), ctrl(_ctrl), scrn(_screen) { }
|
||||||
|
|
||||||
|
|
||||||
|
BTexture::BTexture(const string &d, const BaseDisplay * const _display,
|
||||||
|
unsigned int _screen, BImageControl* _ctrl)
|
||||||
|
: c(_display, _screen), ct(_display, _screen),
|
||||||
|
lc(_display, _screen), sc(_display, _screen), bc(_display, _screen), t(0),
|
||||||
|
dpy(_display), ctrl(_ctrl), scrn(_screen) {
|
||||||
|
setDescription(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BTexture::setColor(const BColor &cc) {
|
||||||
|
c = cc;
|
||||||
|
c.setDisplay(display(), screen());
|
||||||
|
|
||||||
|
unsigned char r, g, b, rr, gg, bb;
|
||||||
|
|
||||||
|
// calculate the light color
|
||||||
|
r = c.red();
|
||||||
|
g = c.green();
|
||||||
|
b = c.blue();
|
||||||
|
rr = r + (r >> 1);
|
||||||
|
gg = g + (g >> 1);
|
||||||
|
bb = b + (b >> 1);
|
||||||
|
if (rr < r) rr = ~0;
|
||||||
|
if (gg < g) gg = ~0;
|
||||||
|
if (bb < b) bb = ~0;
|
||||||
|
lc = BColor(rr, gg, bb, display(), screen());
|
||||||
|
|
||||||
|
// calculate the shadow color
|
||||||
|
r = c.red();
|
||||||
|
g = c.green();
|
||||||
|
b = c.blue();
|
||||||
|
rr = (r >> 2) + (r >> 1);
|
||||||
|
gg = (g >> 2) + (g >> 1);
|
||||||
|
bb = (b >> 2) + (b >> 1);
|
||||||
|
if (rr > r) rr = 0;
|
||||||
|
if (gg > g) gg = 0;
|
||||||
|
if (bb > b) bb = 0;
|
||||||
|
sc = BColor(rr, gg, bb, display(), screen());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BTexture::setDescription(const string &d) {
|
||||||
|
descr.erase();
|
||||||
|
descr.reserve(d.length());
|
||||||
|
|
||||||
|
string::const_iterator it = d.begin(), end = d.end();
|
||||||
|
for (; it != end; ++it)
|
||||||
|
descr += tolower(*it);
|
||||||
|
|
||||||
|
if (descr.find("parentrelative") != string::npos) {
|
||||||
|
setTexture(BTexture::Parent_Relative);
|
||||||
|
} else {
|
||||||
|
setTexture(0);
|
||||||
|
|
||||||
|
if (descr.find("gradient") != string::npos) {
|
||||||
|
addTexture(BTexture::Gradient);
|
||||||
|
if (descr.find("crossdiagonal") != string::npos)
|
||||||
|
addTexture(BTexture::CrossDiagonal);
|
||||||
|
else if (descr.find("rectangle") != string::npos)
|
||||||
|
addTexture(BTexture::Rectangle);
|
||||||
|
else if (descr.find("pyramid") != string::npos)
|
||||||
|
addTexture(BTexture::Pyramid);
|
||||||
|
else if (descr.find("pipecross") != string::npos)
|
||||||
|
addTexture(BTexture::PipeCross);
|
||||||
|
else if (descr.find("elliptic") != string::npos)
|
||||||
|
addTexture(BTexture::Elliptic);
|
||||||
|
else if (descr.find("horizontal") != string::npos)
|
||||||
|
addTexture(BTexture::Horizontal);
|
||||||
|
else if (descr.find("vertical") != string::npos)
|
||||||
|
addTexture(BTexture::Vertical);
|
||||||
|
else
|
||||||
|
addTexture(BTexture::Diagonal);
|
||||||
|
} else {
|
||||||
|
addTexture(BTexture::Solid);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (descr.find("sunken") != string::npos)
|
||||||
|
addTexture(BTexture::Sunken);
|
||||||
|
else if (descr.find("flat") != string::npos)
|
||||||
|
addTexture(BTexture::Flat);
|
||||||
|
else
|
||||||
|
addTexture(BTexture::Raised);
|
||||||
|
|
||||||
|
if (texture() & BTexture::Flat) {
|
||||||
|
if (descr.find("border") != string::npos)
|
||||||
|
addTexture(BTexture::Border);
|
||||||
|
} else {
|
||||||
|
if (descr.find("bevel2") != string::npos)
|
||||||
|
addTexture(BTexture::Bevel2);
|
||||||
|
else
|
||||||
|
addTexture(BTexture::Bevel1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (descr.find("interlaced") != string::npos)
|
||||||
|
addTexture(BTexture::Interlaced);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BTexture::setDisplay(const BaseDisplay * const _display,
|
||||||
|
const unsigned int _screen) {
|
||||||
|
if (_display == display() && _screen == screen()) {
|
||||||
|
// nothing to do
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dpy = _display;
|
||||||
|
scrn = _screen;
|
||||||
|
c.setDisplay(_display, _screen);
|
||||||
|
ct.setDisplay(_display, _screen);
|
||||||
|
lc.setDisplay(_display, _screen);
|
||||||
|
sc.setDisplay(_display, _screen);
|
||||||
|
bc.setDisplay(_display, _screen);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BTexture& BTexture::operator=(const BTexture &tt) {
|
||||||
|
c = tt.c;
|
||||||
|
ct = tt.ct;
|
||||||
|
lc = tt.lc;
|
||||||
|
sc = tt.sc;
|
||||||
|
bc = tt.bc;
|
||||||
|
descr = tt.descr;
|
||||||
|
t = tt.t;
|
||||||
|
dpy = tt.dpy;
|
||||||
|
scrn = tt.scrn;
|
||||||
|
ctrl = tt.ctrl;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Pixmap BTexture::render(const unsigned int width, const unsigned int height,
|
||||||
|
const Pixmap old) {
|
||||||
|
assert(display() != 0);
|
||||||
|
assert(texture() != BTexture::NoTexture);
|
||||||
|
|
||||||
|
if (texture() == (BTexture::Flat | BTexture::Solid))
|
||||||
|
return None;
|
||||||
|
if (texture() == BTexture::Parent_Relative)
|
||||||
|
return ParentRelative;
|
||||||
|
|
||||||
|
if (screen() == ~(0u))
|
||||||
|
scrn = DefaultScreen(display()->getXDisplay());
|
||||||
|
|
||||||
|
assert(ctrl != 0);
|
||||||
|
Pixmap ret = ctrl->renderImage(width, height, *this);
|
||||||
|
|
||||||
|
if (old)
|
||||||
|
ctrl->removeImage(old);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
92
otk/texture.hh
Normal file
92
otk/texture.hh
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
|
||||||
|
#ifndef TEXTURE_HH
|
||||||
|
#define TEXTURE_HH
|
||||||
|
|
||||||
|
#include "color.hh"
|
||||||
|
#include "util.hh"
|
||||||
|
class BImageControl;
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class BTexture {
|
||||||
|
public:
|
||||||
|
enum Type {
|
||||||
|
// No texture
|
||||||
|
NoTexture = (0),
|
||||||
|
// bevel options
|
||||||
|
Flat = (1l<<0),
|
||||||
|
Sunken = (1l<<1),
|
||||||
|
Raised = (1l<<2),
|
||||||
|
// textures
|
||||||
|
Solid = (1l<<3),
|
||||||
|
Gradient = (1l<<4),
|
||||||
|
// gradients
|
||||||
|
Horizontal = (1l<<5),
|
||||||
|
Vertical = (1l<<6),
|
||||||
|
Diagonal = (1l<<7),
|
||||||
|
CrossDiagonal = (1l<<8),
|
||||||
|
Rectangle = (1l<<9),
|
||||||
|
Pyramid = (1l<<10),
|
||||||
|
PipeCross = (1l<<11),
|
||||||
|
Elliptic = (1l<<12),
|
||||||
|
// bevel types
|
||||||
|
Bevel1 = (1l<<13),
|
||||||
|
Bevel2 = (1l<<14),
|
||||||
|
// flat border
|
||||||
|
Border = (1l<<15),
|
||||||
|
// inverted image
|
||||||
|
Invert = (1l<<16),
|
||||||
|
// parent relative image
|
||||||
|
Parent_Relative = (1l<<17),
|
||||||
|
// fake interlaced image
|
||||||
|
Interlaced = (1l<<18)
|
||||||
|
};
|
||||||
|
|
||||||
|
BTexture(const BaseDisplay * const _display = 0,
|
||||||
|
unsigned int _screen = ~(0u), BImageControl* _ctrl = 0);
|
||||||
|
BTexture(const std::string &_description,
|
||||||
|
const BaseDisplay * const _display = 0,
|
||||||
|
unsigned int _screen = ~(0u), BImageControl* _ctrl = 0);
|
||||||
|
|
||||||
|
void setColor(const BColor &_color);
|
||||||
|
void setColorTo(const BColor &_colorTo) { ct = _colorTo; }
|
||||||
|
void setBorderColor(const BColor &_borderColor) { bc = _borderColor; }
|
||||||
|
|
||||||
|
const BColor &color(void) const { return c; }
|
||||||
|
const BColor &colorTo(void) const { return ct; }
|
||||||
|
const BColor &lightColor(void) const { return lc; }
|
||||||
|
const BColor &shadowColor(void) const { return sc; }
|
||||||
|
const BColor &borderColor(void) const { return bc; }
|
||||||
|
|
||||||
|
unsigned long texture(void) const { return t; }
|
||||||
|
void setTexture(const unsigned long _texture) { t = _texture; }
|
||||||
|
void addTexture(const unsigned long _texture) { t |= _texture; }
|
||||||
|
|
||||||
|
BTexture &operator=(const BTexture &tt);
|
||||||
|
inline bool operator==(const BTexture &tt)
|
||||||
|
{ return (c == tt.c && ct == tt.ct && lc == tt.lc &&
|
||||||
|
sc == tt.sc && t == tt.t); }
|
||||||
|
inline bool operator!=(const BTexture &tt)
|
||||||
|
{ return (! operator==(tt)); }
|
||||||
|
|
||||||
|
const BaseDisplay *display(void) const { return dpy; }
|
||||||
|
unsigned int screen(void) const { return scrn; }
|
||||||
|
void setDisplay(const BaseDisplay * const _display,
|
||||||
|
const unsigned int _screen);
|
||||||
|
void setImageControl(BImageControl* _ctrl) { ctrl = _ctrl; }
|
||||||
|
const std::string &description(void) const { return descr; }
|
||||||
|
void setDescription(const std::string &d);
|
||||||
|
|
||||||
|
Pixmap render(const unsigned int width, const unsigned int height,
|
||||||
|
const Pixmap old = 0);
|
||||||
|
|
||||||
|
private:
|
||||||
|
BColor c, ct, lc, sc, bc;
|
||||||
|
std::string descr;
|
||||||
|
unsigned long t;
|
||||||
|
const BaseDisplay *dpy;
|
||||||
|
BImageControl *ctrl;
|
||||||
|
unsigned int scrn;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // TEXTURE_HH
|
Loading…
Reference in a new issue