remove the old blackbox bullshit
This commit is contained in:
parent
104c1a164b
commit
f2e005f4d9
11 changed files with 0 additions and 3700 deletions
215
otk/color.cc
215
otk/color.cc
|
@ -1,215 +0,0 @@
|
||||||
// -*- 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 "display.hh"
|
|
||||||
#include "screeninfo.hh"
|
|
||||||
|
|
||||||
namespace otk {
|
|
||||||
|
|
||||||
Color::ColorCache Color::colorcache;
|
|
||||||
bool Color::cleancache = false;
|
|
||||||
|
|
||||||
Color::Color(unsigned int _screen)
|
|
||||||
: allocated(false), r(-1), g(-1), b(-1), p(0), scrn(_screen)
|
|
||||||
{}
|
|
||||||
|
|
||||||
Color::Color(int _r, int _g, int _b, unsigned int _screen)
|
|
||||||
: allocated(false), r(_r), g(_g), b(_b), p(0), scrn(_screen)
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
Color::Color(const std::string &_name, unsigned int _screen)
|
|
||||||
: allocated(false), r(-1), g(-1), b(-1), p(0), scrn(_screen),
|
|
||||||
colorname(_name) {
|
|
||||||
parseColorName();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Color::~Color(void) {
|
|
||||||
deallocate();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Color::setScreen(unsigned int _screen) {
|
|
||||||
if (_screen == screen()) {
|
|
||||||
// nothing to do
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
deallocate();
|
|
||||||
|
|
||||||
scrn = _screen;
|
|
||||||
|
|
||||||
if (! colorname.empty()) {
|
|
||||||
parseColorName();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
unsigned long Color::pixel(void) const {
|
|
||||||
if (! allocated) {
|
|
||||||
// mutable
|
|
||||||
Color *that = (Color *) this;
|
|
||||||
that->allocate();
|
|
||||||
}
|
|
||||||
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Color::parseColorName(void) {
|
|
||||||
if (colorname.empty()) {
|
|
||||||
fprintf(stderr, "Color: empty colorname, cannot parse (using black)\n");
|
|
||||||
setRGB(0, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scrn == ~(0u))
|
|
||||||
scrn = DefaultScreen(**display);
|
|
||||||
Colormap colormap = display->screenInfo(scrn)->colormap();
|
|
||||||
|
|
||||||
// get rgb values from colorname
|
|
||||||
XColor xcol;
|
|
||||||
xcol.red = 0;
|
|
||||||
xcol.green = 0;
|
|
||||||
xcol.blue = 0;
|
|
||||||
xcol.pixel = 0;
|
|
||||||
|
|
||||||
if (! XParseColor(**display, colormap,
|
|
||||||
colorname.c_str(), &xcol)) {
|
|
||||||
fprintf(stderr, "Color::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 Color::allocate(void) {
|
|
||||||
if (scrn == ~(0u)) scrn = DefaultScreen(**display);
|
|
||||||
Colormap colormap = display->screenInfo(scrn)->colormap();
|
|
||||||
|
|
||||||
if (! isValid()) {
|
|
||||||
if (colorname.empty()) {
|
|
||||||
fprintf(stderr, "Color: cannot allocate invalid color (using black)\n");
|
|
||||||
setRGB(0, 0, 0);
|
|
||||||
} else {
|
|
||||||
parseColorName();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// see if we have allocated this color before
|
|
||||||
RGB rgb(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, colormap, &xcol)) {
|
|
||||||
fprintf(stderr, "Color::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 Color::deallocate(void) {
|
|
||||||
if (! allocated)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ColorCache::iterator it = colorcache.find(RGB(scrn, r, g, b));
|
|
||||||
if (it != colorcache.end()) {
|
|
||||||
if ((*it).second.count >= 1)
|
|
||||||
(*it).second.count--;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cleancache)
|
|
||||||
doCacheCleanup();
|
|
||||||
|
|
||||||
allocated = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Color &Color::operator=(const Color &c) {
|
|
||||||
deallocate();
|
|
||||||
|
|
||||||
setRGB(c.r, c.g, c.b);
|
|
||||||
colorname = c.colorname;
|
|
||||||
scrn = c.scrn;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Color::cleanupColorCache(void) {
|
|
||||||
cleancache = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Color::doCacheCleanup(void) {
|
|
||||||
// ### TODO - support multiple displays!
|
|
||||||
ColorCache::iterator it = colorcache.begin();
|
|
||||||
if (it == colorcache.end()) {
|
|
||||||
// nothing to do
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned long *pixels = new unsigned long[ colorcache.size() ];
|
|
||||||
int i;
|
|
||||||
unsigned count;
|
|
||||||
|
|
||||||
for (i = 0; i < ScreenCount(**display); 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, display->screenInfo(i)->colormap(),
|
|
||||||
pixels, count, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
delete [] pixels;
|
|
||||||
cleancache = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
102
otk/color.hh
102
otk/color.hh
|
@ -1,102 +0,0 @@
|
||||||
// -*- 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>
|
|
||||||
|
|
||||||
namespace otk {
|
|
||||||
|
|
||||||
class Color {
|
|
||||||
public:
|
|
||||||
Color(unsigned int _screen = ~(0u));
|
|
||||||
Color(int _r, int _g, int _b, unsigned int _screen = ~(0u));
|
|
||||||
Color(const std::string &_name, unsigned int _screen = ~(0u));
|
|
||||||
~Color(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 unsigned int screen(void) const { return scrn; }
|
|
||||||
void setScreen(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
|
|
||||||
#ifndef SWIG
|
|
||||||
Color &operator=(const Color &c);
|
|
||||||
#endif
|
|
||||||
inline bool operator==(const Color &c) const
|
|
||||||
{ return (r == c.r && b == c.b && b == c.b); }
|
|
||||||
inline bool operator!=(const Color &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;
|
|
||||||
unsigned int scrn;
|
|
||||||
std::string colorname;
|
|
||||||
|
|
||||||
// global color allocator/deallocator
|
|
||||||
struct RGB {
|
|
||||||
const int screen;
|
|
||||||
const int r, g, b;
|
|
||||||
|
|
||||||
RGB(void) : screen(~(0u)), r(-1), g(-1), b(-1) { }
|
|
||||||
RGB(const int b, const int x, const int y, const int z)
|
|
||||||
: screen(b), r(x), g(y), b(z) {}
|
|
||||||
RGB(const RGB &x)
|
|
||||||
: screen(x.screen), r(x.r), g(x.g), b(x.b) {}
|
|
||||||
|
|
||||||
inline bool operator==(const RGB &x) const {
|
|
||||||
return 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
|
|
191
otk/gccache.cc
191
otk/gccache.cc
|
@ -1,191 +0,0 @@
|
||||||
// -*- 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 <algorithm>
|
|
||||||
|
|
||||||
#include "gccache.hh"
|
|
||||||
#include "color.hh"
|
|
||||||
#include "assassin.hh"
|
|
||||||
#include "screeninfo.hh"
|
|
||||||
|
|
||||||
namespace otk {
|
|
||||||
|
|
||||||
GCCacheContext::~GCCacheContext(void) {
|
|
||||||
if (gc)
|
|
||||||
XFreeGC(**display, gc);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void GCCacheContext::set(const Color &_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, gc, mask, &gcv);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void GCCacheContext::set(const XFontStruct * const _font) {
|
|
||||||
if (! _font) {
|
|
||||||
fontid = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
XGCValues gcv;
|
|
||||||
fontid = gcv.font = _font->fid;
|
|
||||||
XChangeGC(**display, gc, GCFont, &gcv);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
GCCache::GCCache(unsigned int screen_count)
|
|
||||||
: context_count(128u), cache_size(16u), cache_buckets(8u * screen_count),
|
|
||||||
cache_total_size(cache_size * cache_buckets) {
|
|
||||||
|
|
||||||
contexts = new GCCacheContext*[context_count];
|
|
||||||
unsigned int i;
|
|
||||||
for (i = 0; i < context_count; i++) {
|
|
||||||
contexts[i] = new GCCacheContext();
|
|
||||||
}
|
|
||||||
|
|
||||||
cache = new GCCacheItem*[cache_total_size];
|
|
||||||
for (i = 0; i < cache_total_size; ++i) {
|
|
||||||
cache[i] = new GCCacheItem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
GCCache::~GCCache(void) {
|
|
||||||
std::for_each(contexts, contexts + context_count, PointerAssassin());
|
|
||||||
std::for_each(cache, cache + cache_total_size, PointerAssassin());
|
|
||||||
delete [] cache;
|
|
||||||
delete [] contexts;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
GCCacheContext *GCCache::nextContext(unsigned int scr) {
|
|
||||||
Window hd = display->screenInfo(scr)->rootWindow();
|
|
||||||
|
|
||||||
GCCacheContext *c;
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < context_count; ++i) {
|
|
||||||
c = contexts[i];
|
|
||||||
|
|
||||||
if (! c->gc) {
|
|
||||||
c->gc = XCreateGC(**display, hd, 0, 0);
|
|
||||||
c->used = false;
|
|
||||||
c->screen = scr;
|
|
||||||
}
|
|
||||||
if (! c->used && c->screen == scr)
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(stderr, "GCCache: context fault!\n");
|
|
||||||
abort();
|
|
||||||
return (GCCacheContext*) 0; // not reached
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void GCCache::release(GCCacheContext *ctx) {
|
|
||||||
ctx->used = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
GCCacheItem *GCCache::find(const Color &_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
|
|
||||||
GCCacheItem *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, "GCCache: 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 GCCache::release(GCCacheItem *_item) {
|
|
||||||
_item->count--;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void GCCache::purge(void) {
|
|
||||||
for (unsigned int i = 0; i < cache_total_size; ++i) {
|
|
||||||
GCCacheItem *d = cache[ i ];
|
|
||||||
|
|
||||||
if (d->ctx && d->count == 0) {
|
|
||||||
release(d->ctx);
|
|
||||||
d->ctx = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
119
otk/gccache.hh
119
otk/gccache.hh
|
@ -1,119 +0,0 @@
|
||||||
// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
|
|
||||||
#ifndef __gccache_hh
|
|
||||||
#define __gccache_hh
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include <X11/Xlib.h>
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "display.hh"
|
|
||||||
#include "color.hh"
|
|
||||||
|
|
||||||
namespace otk {
|
|
||||||
|
|
||||||
class GCCacheItem;
|
|
||||||
|
|
||||||
class GCCacheContext {
|
|
||||||
public:
|
|
||||||
void set(const Color &_color, const XFontStruct * const _font,
|
|
||||||
const int _function, const int _subwindow, const int _linewidth);
|
|
||||||
void set(const XFontStruct * const _font);
|
|
||||||
|
|
||||||
~GCCacheContext(void);
|
|
||||||
|
|
||||||
private:
|
|
||||||
GCCacheContext()
|
|
||||||
: gc(0), pixel(0ul), fontid(0ul),
|
|
||||||
function(0), subwindow(0), used(false), screen(~(0u)), linewidth(0) {}
|
|
||||||
|
|
||||||
GC gc;
|
|
||||||
unsigned long pixel;
|
|
||||||
unsigned long fontid;
|
|
||||||
int function;
|
|
||||||
int subwindow;
|
|
||||||
bool used;
|
|
||||||
unsigned int screen;
|
|
||||||
int linewidth;
|
|
||||||
|
|
||||||
GCCacheContext(const GCCacheContext &_nocopy);
|
|
||||||
GCCacheContext &operator=(const GCCacheContext &_nocopy);
|
|
||||||
|
|
||||||
friend class GCCache;
|
|
||||||
friend class GCCacheItem;
|
|
||||||
};
|
|
||||||
|
|
||||||
class GCCacheItem {
|
|
||||||
public:
|
|
||||||
inline const GC &gc(void) const { return ctx->gc; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
GCCacheItem(void) : ctx(0), count(0), hits(0), fault(false) { }
|
|
||||||
|
|
||||||
GCCacheContext *ctx;
|
|
||||||
unsigned int count;
|
|
||||||
unsigned int hits;
|
|
||||||
bool fault;
|
|
||||||
|
|
||||||
GCCacheItem(const GCCacheItem &_nocopy);
|
|
||||||
GCCacheItem &operator=(const GCCacheItem &_nocopy);
|
|
||||||
|
|
||||||
friend class GCCache;
|
|
||||||
};
|
|
||||||
|
|
||||||
class GCCache {
|
|
||||||
public:
|
|
||||||
GCCache(unsigned int screen_count);
|
|
||||||
~GCCache(void);
|
|
||||||
|
|
||||||
// cleans up the cache
|
|
||||||
void purge(void);
|
|
||||||
|
|
||||||
GCCacheItem *find(const Color &_color, const XFontStruct * const _font = 0,
|
|
||||||
int _function = GXcopy, int _subwindow = ClipByChildren,
|
|
||||||
int _linewidth = 0);
|
|
||||||
void release(GCCacheItem *_item);
|
|
||||||
|
|
||||||
private:
|
|
||||||
GCCacheContext *nextContext(unsigned int _screen);
|
|
||||||
void release(GCCacheContext *ctx);
|
|
||||||
|
|
||||||
// this is closely modelled after the Qt GC cache, but with some of the
|
|
||||||
// complexity stripped out
|
|
||||||
const unsigned int context_count;
|
|
||||||
const unsigned int cache_size;
|
|
||||||
const unsigned int cache_buckets;
|
|
||||||
const unsigned int cache_total_size;
|
|
||||||
GCCacheContext **contexts;
|
|
||||||
GCCacheItem **cache;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Pen {
|
|
||||||
public:
|
|
||||||
inline Pen(const Color &_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(display->gcCache()), item(0) { }
|
|
||||||
|
|
||||||
inline ~Pen(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 Color &color;
|
|
||||||
const XFontStruct *font;
|
|
||||||
int linewidth;
|
|
||||||
int function;
|
|
||||||
int subwindow;
|
|
||||||
|
|
||||||
mutable GCCache *cache;
|
|
||||||
mutable GCCacheItem *item;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // __gccache_hh
|
|
1674
otk/image.cc
1674
otk/image.cc
File diff suppressed because it is too large
Load diff
147
otk/image.hh
147
otk/image.hh
|
@ -1,147 +0,0 @@
|
||||||
// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
|
|
||||||
#ifndef __image_hh
|
|
||||||
#define __image_hh
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include <X11/Xlib.h>
|
|
||||||
#include <X11/Xutil.h>
|
|
||||||
}
|
|
||||||
|
|
||||||
#include <list>
|
|
||||||
|
|
||||||
#include "color.hh"
|
|
||||||
#include "screeninfo.hh"
|
|
||||||
#include "timer.hh"
|
|
||||||
|
|
||||||
namespace otk {
|
|
||||||
|
|
||||||
class ImageControl;
|
|
||||||
class Texture;
|
|
||||||
class ScreenInfo;
|
|
||||||
|
|
||||||
class Image {
|
|
||||||
private:
|
|
||||||
ImageControl *control;
|
|
||||||
bool interlaced;
|
|
||||||
XColor *colors;
|
|
||||||
|
|
||||||
Color 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 Texture &texture);
|
|
||||||
Pixmap render_gradient(const Texture &texture);
|
|
||||||
|
|
||||||
XImage *renderXImage(void);
|
|
||||||
|
|
||||||
void invert(void);
|
|
||||||
void bevel1(void);
|
|
||||||
void bevel2(void);
|
|
||||||
void border(const Texture &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:
|
|
||||||
Image(ImageControl *c, int w, int h);
|
|
||||||
~Image(void);
|
|
||||||
|
|
||||||
Pixmap render(const Texture &texture);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class ImageControl {
|
|
||||||
public:
|
|
||||||
#ifndef SWIG
|
|
||||||
struct CachedImage {
|
|
||||||
Pixmap pixmap;
|
|
||||||
|
|
||||||
unsigned int count, width, height;
|
|
||||||
unsigned long pixel1, pixel2, texture;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ImageControl(const otk::ScreenInfo *scrn,
|
|
||||||
bool _dither= False, int _cpc = 4,
|
|
||||||
unsigned long cache_timeout = 300000l,
|
|
||||||
unsigned long cmax = 200l);
|
|
||||||
virtual ~ImageControl(void);
|
|
||||||
|
|
||||||
inline bool doDither(void) { return dither; }
|
|
||||||
|
|
||||||
inline const ScreenInfo* getScreenInfo() const { return screeninfo; }
|
|
||||||
|
|
||||||
inline Window getDrawable(void) const { return window; }
|
|
||||||
|
|
||||||
inline Visual *getVisual(void) { return screeninfo->visual(); }
|
|
||||||
|
|
||||||
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 Texture &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);
|
|
||||||
|
|
||||||
static void timeout(ImageControl *t);
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool dither;
|
|
||||||
const ScreenInfo *screeninfo;
|
|
||||||
Timer *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 Color &c1, const Color &c2);
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // __image_hh
|
|
||||||
|
|
|
@ -1,556 +0,0 @@
|
||||||
// -*- 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_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 "display.hh"
|
|
||||||
#include "color.hh"
|
|
||||||
#include "image.hh"
|
|
||||||
#include "texture.hh"
|
|
||||||
|
|
||||||
namespace otk {
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImageControl *ctrl = 0;
|
|
||||||
|
|
||||||
ImageControl::ImageControl(const ScreenInfo *scrn,
|
|
||||||
bool _dither, int _cpc,
|
|
||||||
unsigned long cache_timeout,
|
|
||||||
unsigned long cmax) {
|
|
||||||
if (! ctrl) ctrl = this;
|
|
||||||
|
|
||||||
screeninfo = scrn;
|
|
||||||
setDither(_dither);
|
|
||||||
setColorsPerChannel(_cpc);
|
|
||||||
|
|
||||||
cache_max = cmax;
|
|
||||||
if (cache_timeout)
|
|
||||||
timer = new Timer(cache_timeout, (Timer::TimeoutHandler)timeout, this);
|
|
||||||
else
|
|
||||||
timer = (Timer *) 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->depth();
|
|
||||||
window = screeninfo->rootWindow();
|
|
||||||
screen_number = screeninfo->screen();
|
|
||||||
colormap = screeninfo->colormap();
|
|
||||||
|
|
||||||
int count;
|
|
||||||
XPixmapFormatValues *pmv = XListPixmapFormats(**display,
|
|
||||||
&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,
|
|
||||||
"ImageControl::ImageControl: 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, "ImageControl::ImageControl: 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(**display, 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(**display, 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(**display, 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,
|
|
||||||
"ImageControl::ImageControl: 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,
|
|
||||||
"ImageControl::ImageControl: 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(**display, 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(**display, 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(**display, colormap,
|
|
||||||
&colors[i])) {
|
|
||||||
colors[i].flags = DoRed|DoGreen|DoBlue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
fprintf(stderr, "ImageControl::ImageControl: unsupported visual %d\n",
|
|
||||||
getVisual()->c_class);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ImageControl::~ImageControl(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(**display, colormap, pixels, ncolors, 0);
|
|
||||||
|
|
||||||
delete [] colors;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! cache.empty()) {
|
|
||||||
//#ifdef DEBUG
|
|
||||||
fprintf(stderr, "ImageContol::~ImageControl: 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(**display, it->pixmap);
|
|
||||||
}
|
|
||||||
if (timer)
|
|
||||||
delete timer;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Pixmap ImageControl::searchCache(const unsigned int width,
|
|
||||||
const unsigned int height,
|
|
||||||
const unsigned long texture,
|
|
||||||
const Color &c1, const Color &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 & Texture::Gradient) {
|
|
||||||
if (tmp.pixel2 == c2.pixel()) {
|
|
||||||
tmp.count++;
|
|
||||||
return tmp.pixmap;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
tmp.count++;
|
|
||||||
return tmp.pixmap;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Pixmap ImageControl::renderImage(unsigned int width, unsigned int height,
|
|
||||||
const Texture &texture) {
|
|
||||||
if (texture.texture() & Texture::Parent_Relative) return ParentRelative;
|
|
||||||
|
|
||||||
Pixmap pixmap = searchCache(width, height, texture.texture(),
|
|
||||||
texture.color(), texture.colorTo());
|
|
||||||
if (pixmap) return pixmap;
|
|
||||||
|
|
||||||
Image 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() & Texture::Gradient)
|
|
||||||
tmp.pixel2 = texture.colorTo().pixel();
|
|
||||||
else
|
|
||||||
tmp.pixel2 = 0l;
|
|
||||||
|
|
||||||
cache.push_back(tmp);
|
|
||||||
|
|
||||||
if (cache.size() > cache_max) {
|
|
||||||
#ifdef DEBUG
|
|
||||||
fprintf(stderr, "ImageControl::renderImage: cache is large, "
|
|
||||||
"forcing cleanout\n");
|
|
||||||
#endif // DEBUG
|
|
||||||
|
|
||||||
timeout(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
return pixmap;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ImageControl::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(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ImageControl::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 ImageControl::getXColorTable(XColor **c, int *n) {
|
|
||||||
if (c) *c = colors;
|
|
||||||
if (n) *n = ncolors;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ImageControl::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 ImageControl::installRootColormap(void) {
|
|
||||||
int ncmap = 0;
|
|
||||||
Colormap *cmaps =
|
|
||||||
XListInstalledColormaps(**display, window, &ncmap);
|
|
||||||
|
|
||||||
if (cmaps) {
|
|
||||||
bool install = True;
|
|
||||||
for (int i = 0; i < ncmap; i++)
|
|
||||||
if (*(cmaps + i) == colormap)
|
|
||||||
install = False;
|
|
||||||
|
|
||||||
if (install)
|
|
||||||
XInstallColormap(**display, colormap);
|
|
||||||
|
|
||||||
XFree(cmaps);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ImageControl::setColorsPerChannel(int cpc) {
|
|
||||||
if (cpc < 2) cpc = 2;
|
|
||||||
if (cpc > 6) cpc = 6;
|
|
||||||
|
|
||||||
colors_per_channel = cpc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
unsigned long ImageControl::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 ImageControl::CachedImage &image) const {
|
|
||||||
return (image.count == 0);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CacheCleaner {
|
|
||||||
ZeroRefCheck ref_check;
|
|
||||||
CacheCleaner() {}
|
|
||||||
inline void operator()(const ImageControl::CachedImage& image) const {
|
|
||||||
if (ref_check(image))
|
|
||||||
XFreePixmap(**display, image.pixmap);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
void ImageControl::timeout(ImageControl *t) {
|
|
||||||
CacheCleaner cleaner;
|
|
||||||
std::for_each(t->cache.begin(), t->cache.end(), cleaner);
|
|
||||||
t->cache.remove_if(cleaner.ref_check);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
273
otk/style.cc
273
otk/style.cc
|
@ -1,273 +0,0 @@
|
||||||
// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
# include "../config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include "display.hh"
|
|
||||||
#include "util.hh"
|
|
||||||
#include "style.hh"
|
|
||||||
|
|
||||||
namespace otk {
|
|
||||||
|
|
||||||
Style::Style() : font(NULL)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Style::Style(ImageControl *ctrl)
|
|
||||||
: image_control(ctrl), font(0),
|
|
||||||
screen_number(ctrl->getScreenInfo()->screen())
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Style::~Style() {
|
|
||||||
if (font)
|
|
||||||
delete font;
|
|
||||||
|
|
||||||
if (close_button.mask != None)
|
|
||||||
XFreePixmap(**display, close_button.mask);
|
|
||||||
if (max_button.mask != None)
|
|
||||||
XFreePixmap(**display, max_button.mask);
|
|
||||||
if (icon_button.mask != None)
|
|
||||||
XFreePixmap(**display, icon_button.mask);
|
|
||||||
if (stick_button.mask != None)
|
|
||||||
XFreePixmap(**display, stick_button.mask);
|
|
||||||
|
|
||||||
max_button.mask = None;
|
|
||||||
close_button.mask = None;
|
|
||||||
icon_button.mask = None;
|
|
||||||
stick_button.mask = None;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Style::load(const Configuration &style) {
|
|
||||||
std::string s;
|
|
||||||
|
|
||||||
// load fonts/fontsets
|
|
||||||
if (font)
|
|
||||||
delete font;
|
|
||||||
|
|
||||||
font = readDatabaseFont("window.", style);
|
|
||||||
|
|
||||||
// load window config
|
|
||||||
t_focus = readDatabaseTexture("window.title.focus", "white", style);
|
|
||||||
t_unfocus = readDatabaseTexture("window.title.unfocus", "black", style);
|
|
||||||
|
|
||||||
l_focus = readDatabaseTexture("window.label.focus", "white", style);
|
|
||||||
l_unfocus = readDatabaseTexture("window.label.unfocus", "black", style);
|
|
||||||
|
|
||||||
h_focus = readDatabaseTexture("window.handle.focus", "white", style);
|
|
||||||
h_unfocus = readDatabaseTexture("window.handle.unfocus", "black", style);
|
|
||||||
|
|
||||||
g_focus = readDatabaseTexture("window.grip.focus", "white", style);
|
|
||||||
g_unfocus = readDatabaseTexture("window.grip.unfocus", "black", style);
|
|
||||||
|
|
||||||
b_focus = readDatabaseTexture("window.button.focus", "white", style);
|
|
||||||
b_unfocus = readDatabaseTexture("window.button.unfocus", "black", style);
|
|
||||||
|
|
||||||
//if neither of these can be found, we will use the previous resource
|
|
||||||
b_pressed_focus = readDatabaseTexture("window.button.pressed.focus",
|
|
||||||
"black", style, true);
|
|
||||||
if (b_pressed_focus.texture() == Texture::NoTexture) {
|
|
||||||
b_pressed_focus = readDatabaseTexture("window.button.pressed", "black",
|
|
||||||
style);
|
|
||||||
}
|
|
||||||
|
|
||||||
b_pressed_unfocus = readDatabaseTexture("window.button.pressed.unfocus",
|
|
||||||
"black", style, true);
|
|
||||||
if (b_pressed_unfocus.texture() == Texture::NoTexture) {
|
|
||||||
b_pressed_unfocus = readDatabaseTexture("window.button.pressed", "black",
|
|
||||||
style);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (close_button.mask != None)
|
|
||||||
XFreePixmap(**display, close_button.mask);
|
|
||||||
if (max_button.mask != None)
|
|
||||||
XFreePixmap(**display, max_button.mask);
|
|
||||||
if (icon_button.mask != None)
|
|
||||||
XFreePixmap(**display, icon_button.mask);
|
|
||||||
if (stick_button.mask != None)
|
|
||||||
XFreePixmap(**display, stick_button.mask);
|
|
||||||
|
|
||||||
close_button.mask = max_button.mask = icon_button.mask
|
|
||||||
= icon_button.mask = None;
|
|
||||||
|
|
||||||
readDatabaseMask("window.button.close.mask", close_button, style);
|
|
||||||
readDatabaseMask("window.button.max.mask", max_button, style);
|
|
||||||
readDatabaseMask("window.button.icon.mask", icon_button, style);
|
|
||||||
readDatabaseMask("window.button.stick.mask", stick_button, style);
|
|
||||||
|
|
||||||
// we create the window.frame texture by hand because it exists only to
|
|
||||||
// make the code cleaner and is not actually used for display
|
|
||||||
Color color = readDatabaseColor("window.frame.focusColor", "white",
|
|
||||||
style);
|
|
||||||
f_focus = Texture("solid flat", screen_number, image_control);
|
|
||||||
f_focus.setColor(color);
|
|
||||||
|
|
||||||
color = readDatabaseColor("window.frame.unfocusColor", "white", style);
|
|
||||||
f_unfocus = Texture("solid flat", screen_number, image_control);
|
|
||||||
f_unfocus.setColor(color);
|
|
||||||
|
|
||||||
l_text_focus = readDatabaseColor("window.label.focus.textColor",
|
|
||||||
"black", style);
|
|
||||||
l_text_unfocus = readDatabaseColor("window.label.unfocus.textColor",
|
|
||||||
"white", style);
|
|
||||||
|
|
||||||
b_pic_focus = readDatabaseColor("window.button.focus.picColor",
|
|
||||||
"black", style);
|
|
||||||
b_pic_unfocus = readDatabaseColor("window.button.unfocus.picColor",
|
|
||||||
"white", style);
|
|
||||||
|
|
||||||
justify = LeftJustify;
|
|
||||||
|
|
||||||
if (style.getValue("window.justify", s)) {
|
|
||||||
if (s == "right" || s == "Right")
|
|
||||||
justify = RightJustify;
|
|
||||||
else if (s == "center" || s == "Center")
|
|
||||||
justify = CenterJustify;
|
|
||||||
}
|
|
||||||
|
|
||||||
// sanity checks
|
|
||||||
if (t_focus.texture() == Texture::Parent_Relative)
|
|
||||||
t_focus = f_focus;
|
|
||||||
if (t_unfocus.texture() == Texture::Parent_Relative)
|
|
||||||
t_unfocus = f_unfocus;
|
|
||||||
if (h_focus.texture() == Texture::Parent_Relative)
|
|
||||||
h_focus = f_focus;
|
|
||||||
if (h_unfocus.texture() == Texture::Parent_Relative)
|
|
||||||
h_unfocus = f_unfocus;
|
|
||||||
|
|
||||||
border_color = readDatabaseColor("borderColor", "black", style);
|
|
||||||
|
|
||||||
// load bevel, border and handle widths
|
|
||||||
|
|
||||||
const ScreenInfo *s_info = display->screenInfo(screen_number);
|
|
||||||
unsigned int width = s_info->rect().width();
|
|
||||||
|
|
||||||
if (! style.getValue("handleWidth", handle_width) ||
|
|
||||||
handle_width > width/2 || handle_width == 0)
|
|
||||||
handle_width = 6;
|
|
||||||
|
|
||||||
if (! style.getValue("borderWidth", border_width))
|
|
||||||
border_width = 1;
|
|
||||||
|
|
||||||
if (! style.getValue("bevelWidth", bevel_width)
|
|
||||||
|| bevel_width > width/2 || bevel_width == 0)
|
|
||||||
bevel_width = 3;
|
|
||||||
|
|
||||||
if (! style.getValue("frameWidth", frame_width)
|
|
||||||
|| frame_width > width/2)
|
|
||||||
frame_width = bevel_width;
|
|
||||||
|
|
||||||
if (style.getValue("rootCommand", s))
|
|
||||||
bexec(s, s_info->displayString());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Style::readDatabaseMask(const std::string &rname, PixmapMask &pixmapMask,
|
|
||||||
const Configuration &style) {
|
|
||||||
Window root_window = display->screenInfo(screen_number)->rootWindow();
|
|
||||||
std::string s;
|
|
||||||
int hx, hy; //ignored
|
|
||||||
int ret = BitmapOpenFailed; //default to failure.
|
|
||||||
|
|
||||||
if (style.getValue(rname, s)) {
|
|
||||||
if (s[0] != '/' && s[0] != '~') {
|
|
||||||
std::string xbmFile = std::string("~/.openbox/buttons/") + s;
|
|
||||||
ret = XReadBitmapFile(**display, root_window,
|
|
||||||
expandTilde(xbmFile).c_str(), &pixmapMask.w,
|
|
||||||
&pixmapMask.h, &pixmapMask.mask, &hx, &hy);
|
|
||||||
if (ret != BitmapSuccess) {
|
|
||||||
xbmFile = std::string(BUTTONSDIR) + "/" + s;
|
|
||||||
ret = XReadBitmapFile(**display, root_window,
|
|
||||||
xbmFile.c_str(), &pixmapMask.w,
|
|
||||||
&pixmapMask.h, &pixmapMask.mask, &hx, &hy);
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
ret = XReadBitmapFile(**display, root_window,
|
|
||||||
expandTilde(s).c_str(), &pixmapMask.w,
|
|
||||||
&pixmapMask.h, &pixmapMask.mask, &hx, &hy);
|
|
||||||
|
|
||||||
if (ret == BitmapSuccess)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
pixmapMask.mask = None;
|
|
||||||
pixmapMask.w = pixmapMask.h = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Texture Style::readDatabaseTexture(const std::string &rname,
|
|
||||||
const std::string &default_color,
|
|
||||||
const Configuration &style,
|
|
||||||
bool allowNoTexture)
|
|
||||||
{
|
|
||||||
Texture texture;
|
|
||||||
std::string s;
|
|
||||||
|
|
||||||
if (style.getValue(rname, s))
|
|
||||||
texture = Texture(s);
|
|
||||||
else if (allowNoTexture) //no default
|
|
||||||
texture.setTexture(Texture::NoTexture);
|
|
||||||
else
|
|
||||||
texture.setTexture(Texture::Solid | Texture::Flat);
|
|
||||||
|
|
||||||
// associate this texture with this screen
|
|
||||||
texture.setScreen(screen_number);
|
|
||||||
texture.setImageControl(image_control);
|
|
||||||
|
|
||||||
if (texture.texture() != Texture::NoTexture) {
|
|
||||||
texture.setColor(readDatabaseColor(rname + ".color", default_color,
|
|
||||||
style));
|
|
||||||
texture.setColorTo(readDatabaseColor(rname + ".colorTo", default_color,
|
|
||||||
style));
|
|
||||||
texture.setBorderColor(readDatabaseColor(rname + ".borderColor",
|
|
||||||
default_color, style));
|
|
||||||
}
|
|
||||||
|
|
||||||
return texture;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Color Style::readDatabaseColor(const std::string &rname,
|
|
||||||
const std::string &default_color,
|
|
||||||
const Configuration &style) {
|
|
||||||
Color color;
|
|
||||||
std::string s;
|
|
||||||
if (style.getValue(rname, s))
|
|
||||||
color = Color(s, screen_number);
|
|
||||||
else
|
|
||||||
color = Color(default_color, screen_number);
|
|
||||||
return color;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Font *Style::readDatabaseFont(const std::string &rbasename,
|
|
||||||
const Configuration &style) {
|
|
||||||
std::string fontstring, s;
|
|
||||||
|
|
||||||
// XXX: load all this font stuff from the style...
|
|
||||||
|
|
||||||
bool dropShadow = True;
|
|
||||||
|
|
||||||
unsigned char offset = 1;
|
|
||||||
if (style.getValue(rbasename + "xft.shadow.offset", s)) {
|
|
||||||
offset = atoi(s.c_str()); //doesn't detect errors
|
|
||||||
if (offset > CHAR_MAX)
|
|
||||||
offset = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char tint = 0x40;
|
|
||||||
if (style.getValue(rbasename + "xft.shadow.tint", s)) {
|
|
||||||
tint = atoi(s.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
fontstring = "Arial,Sans-9:bold";
|
|
||||||
|
|
||||||
// if this fails, it ::exit()'s
|
|
||||||
return new Font(screen_number, fontstring, dropShadow, offset, tint);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
151
otk/style.hh
151
otk/style.hh
|
@ -1,151 +0,0 @@
|
||||||
// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
|
|
||||||
#ifndef __style_hh
|
|
||||||
#define __style_hh
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "color.hh"
|
|
||||||
#include "font.hh"
|
|
||||||
#include "texture.hh"
|
|
||||||
#include "image.hh"
|
|
||||||
#include "configuration.hh"
|
|
||||||
|
|
||||||
// XXX: document
|
|
||||||
|
|
||||||
namespace otk {
|
|
||||||
|
|
||||||
struct PixmapMask {
|
|
||||||
Pixmap mask;
|
|
||||||
unsigned int w, h;
|
|
||||||
PixmapMask() { mask = None; w = h = 0; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class Style {
|
|
||||||
public:
|
|
||||||
|
|
||||||
enum Type { ButtonFocus, ButtonUnfocus, TitleFocus, TitleUnfocus,
|
|
||||||
LabelFocus, LabelUnfocus, HandleFocus, HandleUnfocus,
|
|
||||||
GripFocus, GripUnfocus };
|
|
||||||
|
|
||||||
enum TextJustify { LeftJustify = 1, RightJustify, CenterJustify };
|
|
||||||
enum BulletType { RoundBullet = 1, TriangleBullet, SquareBullet, NoBullet };
|
|
||||||
|
|
||||||
// private:
|
|
||||||
|
|
||||||
ImageControl *image_control;
|
|
||||||
|
|
||||||
Color
|
|
||||||
l_text_focus, l_text_unfocus,
|
|
||||||
b_pic_focus, b_pic_unfocus;
|
|
||||||
|
|
||||||
Color border_color;
|
|
||||||
|
|
||||||
Font *font;
|
|
||||||
|
|
||||||
Texture
|
|
||||||
f_focus, f_unfocus,
|
|
||||||
t_focus, t_unfocus,
|
|
||||||
l_focus, l_unfocus,
|
|
||||||
h_focus, h_unfocus,
|
|
||||||
b_focus, b_unfocus,
|
|
||||||
b_pressed_focus, b_pressed_unfocus,
|
|
||||||
g_focus, g_unfocus;
|
|
||||||
|
|
||||||
PixmapMask close_button, max_button, icon_button, stick_button;
|
|
||||||
TextJustify justify;
|
|
||||||
BulletType bullet_type;
|
|
||||||
|
|
||||||
unsigned int handle_width, bevel_width, frame_width, border_width;
|
|
||||||
|
|
||||||
unsigned int screen_number;
|
|
||||||
|
|
||||||
bool shadow_fonts, aa_fonts;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
Style();
|
|
||||||
Style(ImageControl *);
|
|
||||||
~Style();
|
|
||||||
|
|
||||||
void readDatabaseMask(const std::string &rname,
|
|
||||||
PixmapMask &pixmapMask,
|
|
||||||
const Configuration &style);
|
|
||||||
|
|
||||||
Texture readDatabaseTexture(const std::string &rname,
|
|
||||||
const std::string &default_color,
|
|
||||||
const Configuration &style,
|
|
||||||
bool allowNoTexture = false);
|
|
||||||
|
|
||||||
Color readDatabaseColor(const std::string &rname,
|
|
||||||
const std::string &default_color,
|
|
||||||
const Configuration &style);
|
|
||||||
|
|
||||||
Font *readDatabaseFont(const std::string &rbasename,
|
|
||||||
const Configuration &style);
|
|
||||||
|
|
||||||
void load(const Configuration &style);
|
|
||||||
|
|
||||||
inline PixmapMask *getCloseButtonMask(void) { return &close_button; }
|
|
||||||
inline PixmapMask *getMaximizeButtonMask(void) { return &max_button; }
|
|
||||||
inline PixmapMask *getIconifyButtonMask(void) { return &icon_button; }
|
|
||||||
inline PixmapMask *getStickyButtonMask(void) { return &stick_button; }
|
|
||||||
|
|
||||||
inline Color *getTextFocus(void) { return &l_text_focus; }
|
|
||||||
inline Color *getTextUnfocus(void) { return &l_text_unfocus; }
|
|
||||||
|
|
||||||
inline Color *getButtonPicFocus(void) { return &b_pic_focus; }
|
|
||||||
inline Color *getButtonPicUnfocus(void) { return &b_pic_unfocus; }
|
|
||||||
|
|
||||||
inline Texture *getTitleFocus(void) { return &t_focus; }
|
|
||||||
inline Texture *getTitleUnfocus(void) { return &t_unfocus; }
|
|
||||||
|
|
||||||
inline Texture *getLabelFocus(void) { return &l_focus; }
|
|
||||||
inline Texture *getLabelUnfocus(void) { return &l_unfocus; }
|
|
||||||
|
|
||||||
inline Texture *getHandleFocus(void) { return &h_focus; }
|
|
||||||
inline Texture *getHandleUnfocus(void) { return &h_unfocus; }
|
|
||||||
|
|
||||||
inline Texture *getButtonFocus(void) { return &b_focus; }
|
|
||||||
inline Texture *getButtonUnfocus(void) { return &b_unfocus; }
|
|
||||||
|
|
||||||
inline Texture *getButtonPressedFocus(void)
|
|
||||||
{ return &b_pressed_focus; }
|
|
||||||
inline Texture *getButtonPressedUnfocus(void)
|
|
||||||
{ return &b_pressed_unfocus; }
|
|
||||||
|
|
||||||
inline Texture *getGripFocus(void) { return &g_focus; }
|
|
||||||
inline Texture *getGripUnfocus(void) { return &g_unfocus; }
|
|
||||||
|
|
||||||
inline unsigned int getHandleWidth(void) const { return handle_width; }
|
|
||||||
inline unsigned int getBevelWidth(void) const { return bevel_width; }
|
|
||||||
inline unsigned int getFrameWidth(void) const { return frame_width; }
|
|
||||||
inline unsigned int getBorderWidth(void) const { return border_width; }
|
|
||||||
|
|
||||||
inline const Font *getFont() const { return font; }
|
|
||||||
|
|
||||||
inline void setShadowFonts(bool fonts) { shadow_fonts = fonts; }
|
|
||||||
inline bool hasShadowFonts(void) const { return shadow_fonts; }
|
|
||||||
|
|
||||||
inline void setAAFonts(bool fonts) { aa_fonts = fonts; }
|
|
||||||
inline bool hasAAFonts(void) const { return aa_fonts; }
|
|
||||||
|
|
||||||
inline TextJustify textJustify(void) { return justify; }
|
|
||||||
inline BulletType bulletType(void) { return bullet_type; }
|
|
||||||
|
|
||||||
inline const Color *getBorderColor() const { return &border_color; }
|
|
||||||
|
|
||||||
inline const Texture *getFrameFocus() const { return &f_focus; }
|
|
||||||
inline const Texture *getFrameUnfocus() const { return &f_unfocus; }
|
|
||||||
|
|
||||||
inline void setImageControl(ImageControl *c) {
|
|
||||||
image_control = c;
|
|
||||||
screen_number = c->getScreenInfo()->screen();
|
|
||||||
}
|
|
||||||
inline unsigned int getScreen(void) { return screen_number; }
|
|
||||||
|
|
||||||
// XXX add inline accessors for the rest of the bummy
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // __style_hh
|
|
178
otk/texture.cc
178
otk/texture.cc
|
@ -1,178 +0,0 @@
|
||||||
// -*- 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 "display.hh"
|
|
||||||
#include "image.hh"
|
|
||||||
|
|
||||||
using std::string;
|
|
||||||
|
|
||||||
namespace otk {
|
|
||||||
|
|
||||||
Texture::Texture(unsigned int _screen, ImageControl* _ctrl)
|
|
||||||
: c(_screen), ct(_screen),
|
|
||||||
lc(_screen), sc(_screen), bc(_screen), t(0),
|
|
||||||
ctrl(_ctrl), scrn(_screen) { }
|
|
||||||
|
|
||||||
|
|
||||||
Texture::Texture(const string &d,unsigned int _screen, ImageControl* _ctrl)
|
|
||||||
: c(_screen), ct(_screen),
|
|
||||||
lc(_screen), sc(_screen), bc(_screen), t(0),
|
|
||||||
ctrl(_ctrl), scrn(_screen) {
|
|
||||||
setDescription(d);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Texture::setColor(const Color &cc) {
|
|
||||||
c = cc;
|
|
||||||
c.setScreen(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 = Color(rr, gg, bb, 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 = Color(rr, gg, bb, screen());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Texture::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(Texture::Parent_Relative);
|
|
||||||
} else {
|
|
||||||
setTexture(0);
|
|
||||||
|
|
||||||
if (descr.find("gradient") != string::npos) {
|
|
||||||
addTexture(Texture::Gradient);
|
|
||||||
if (descr.find("crossdiagonal") != string::npos)
|
|
||||||
addTexture(Texture::CrossDiagonal);
|
|
||||||
else if (descr.find("rectangle") != string::npos)
|
|
||||||
addTexture(Texture::Rectangle);
|
|
||||||
else if (descr.find("pyramid") != string::npos)
|
|
||||||
addTexture(Texture::Pyramid);
|
|
||||||
else if (descr.find("pipecross") != string::npos)
|
|
||||||
addTexture(Texture::PipeCross);
|
|
||||||
else if (descr.find("elliptic") != string::npos)
|
|
||||||
addTexture(Texture::Elliptic);
|
|
||||||
else if (descr.find("horizontal") != string::npos)
|
|
||||||
addTexture(Texture::Horizontal);
|
|
||||||
else if (descr.find("vertical") != string::npos)
|
|
||||||
addTexture(Texture::Vertical);
|
|
||||||
else
|
|
||||||
addTexture(Texture::Diagonal);
|
|
||||||
} else {
|
|
||||||
addTexture(Texture::Solid);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (descr.find("sunken") != string::npos)
|
|
||||||
addTexture(Texture::Sunken);
|
|
||||||
else if (descr.find("flat") != string::npos)
|
|
||||||
addTexture(Texture::Flat);
|
|
||||||
else
|
|
||||||
addTexture(Texture::Raised);
|
|
||||||
|
|
||||||
if (texture() & Texture::Flat) {
|
|
||||||
if (descr.find("border") != string::npos)
|
|
||||||
addTexture(Texture::Border);
|
|
||||||
} else {
|
|
||||||
if (descr.find("bevel2") != string::npos)
|
|
||||||
addTexture(Texture::Bevel2);
|
|
||||||
else
|
|
||||||
addTexture(Texture::Bevel1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (descr.find("interlaced") != string::npos)
|
|
||||||
addTexture(Texture::Interlaced);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Texture::setScreen(const unsigned int _screen) {
|
|
||||||
if (_screen == screen()) {
|
|
||||||
// nothing to do
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
scrn = _screen;
|
|
||||||
c.setScreen(_screen);
|
|
||||||
ct.setScreen(_screen);
|
|
||||||
lc.setScreen(_screen);
|
|
||||||
sc.setScreen(_screen);
|
|
||||||
bc.setScreen(_screen);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Texture& Texture::operator=(const Texture &tt) {
|
|
||||||
c = tt.c;
|
|
||||||
ct = tt.ct;
|
|
||||||
lc = tt.lc;
|
|
||||||
sc = tt.sc;
|
|
||||||
bc = tt.bc;
|
|
||||||
descr = tt.descr;
|
|
||||||
t = tt.t;
|
|
||||||
scrn = tt.scrn;
|
|
||||||
ctrl = tt.ctrl;
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Pixmap Texture::render(const unsigned int width, const unsigned int height,
|
|
||||||
const Pixmap old) {
|
|
||||||
assert(texture() != Texture::NoTexture);
|
|
||||||
|
|
||||||
// if (texture() == (Texture::Flat | Texture::Solid))
|
|
||||||
// return None;
|
|
||||||
if (texture() == Texture::Parent_Relative)
|
|
||||||
return ParentRelative;
|
|
||||||
|
|
||||||
if (screen() == ~(0u))
|
|
||||||
scrn = DefaultScreen(**display);
|
|
||||||
|
|
||||||
assert(ctrl != 0);
|
|
||||||
Pixmap ret = ctrl->renderImage(width, height, *this);
|
|
||||||
|
|
||||||
if (old)
|
|
||||||
ctrl->removeImage(old);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,94 +0,0 @@
|
||||||
// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
|
|
||||||
#ifndef TEXTURE_HH
|
|
||||||
#define TEXTURE_HH
|
|
||||||
|
|
||||||
#include "color.hh"
|
|
||||||
#include "util.hh"
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace otk {
|
|
||||||
|
|
||||||
class ImageControl;
|
|
||||||
|
|
||||||
class Texture {
|
|
||||||
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)
|
|
||||||
};
|
|
||||||
|
|
||||||
Texture(unsigned int _screen = ~(0u), ImageControl* _ctrl = 0);
|
|
||||||
Texture(const std::string &_description,
|
|
||||||
unsigned int _screen = ~(0u), ImageControl* _ctrl = 0);
|
|
||||||
|
|
||||||
void setColor(const Color &_color);
|
|
||||||
void setColorTo(const Color &_colorTo) { ct = _colorTo; }
|
|
||||||
void setBorderColor(const Color &_borderColor) { bc = _borderColor; }
|
|
||||||
|
|
||||||
const Color &color(void) const { return c; }
|
|
||||||
const Color &colorTo(void) const { return ct; }
|
|
||||||
const Color &lightColor(void) const { return lc; }
|
|
||||||
const Color &shadowColor(void) const { return sc; }
|
|
||||||
const Color &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; }
|
|
||||||
|
|
||||||
#ifndef SWIG
|
|
||||||
Texture &operator=(const Texture &tt);
|
|
||||||
#endif
|
|
||||||
inline bool operator==(const Texture &tt)
|
|
||||||
{ return (c == tt.c && ct == tt.ct && lc == tt.lc &&
|
|
||||||
sc == tt.sc && t == tt.t); }
|
|
||||||
inline bool operator!=(const Texture &tt)
|
|
||||||
{ return (! operator==(tt)); }
|
|
||||||
|
|
||||||
unsigned int screen(void) const { return scrn; }
|
|
||||||
void setScreen(const unsigned int _screen);
|
|
||||||
void setImageControl(ImageControl* _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:
|
|
||||||
Color c, ct, lc, sc, bc;
|
|
||||||
std::string descr;
|
|
||||||
unsigned long t;
|
|
||||||
ImageControl *ctrl;
|
|
||||||
unsigned int scrn;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // TEXTURE_HH
|
|
Loading…
Reference in a new issue