all repos — openbox @ 214fa8714ea0d2182c155eeb4b32ec32d7df337f

openbox fork - make it a bit more like ryudo

added superb pseudo-color (8bpp) support
Derek Foreman manmower@gmail.com
commit

214fa8714ea0d2182c155eeb4b32ec32d7df337f

parent

26034c374255eb6a35a71009585e194763472905

4 files changed, 131 insertions(+), 5 deletions(-)

jump to
M render/color.crender/color.c

@@ -3,6 +3,10 @@ #include <X11/Xutil.h>

#include "render.h" #include "color.h" #include "../kernel/openbox.h" + +XColor *pseudo_colors; +int pseudo_bpc; + void color_allocate_gc(color_rgb *in) { XGCValues gcv;

@@ -65,7 +69,8 @@ /* since pixel32 is the largest possible pixel size, we can share the

array*/ int r, g, b; int x,y; - pixel16 *p = (pixel16*) data; + pixel16 *p16 = (pixel16*) data; + unsigned char *p8 = (unsigned char *)data; switch (im->bits_per_pixel) { case 32: if ((render_red_offset != default_red_shift) ||

@@ -92,15 +97,35 @@ g = (data[x] >> default_green_shift) & 0xFF;

g = g >> render_green_shift; b = (data[x] >> default_blue_shift) & 0xFF; b = b >> render_blue_shift; - p[x] = (r << render_red_offset) + p16[x] = (r << render_red_offset) + (g << render_green_offset) + (b << render_blue_offset); } data += im->width; - p += im->bytes_per_line/2; + p16 += im->bytes_per_line/2; + } + break; + case 8: + g_assert(render_visual->class != TrueColor); + for (y = 0; y < im->height; y++) { + for (x = 0; x < im->width; x++) { + p8[x] = pickColor(data[x] >> default_red_shift, + data[x] >> default_green_shift, + data[x] >> default_blue_shift)->pixel; } - break; + data += im->width; + p8 += im->bytes_per_line; + } + + break; default: g_message("your bit depth is currently unhandled\n"); } } +XColor *pickColor(int r, int g, int b) +{ + r = (r & 0xff) >> (8-pseudo_bpc); + g = (g & 0xff) >> (8-pseudo_bpc); + b = (b & 0xff) >> (8-pseudo_bpc); + return &pseudo_colors[(r << (2*pseudo_bpc)) + (g << (1*pseudo_bpc)) + b]; +}
M render/color.hrender/color.h

@@ -43,6 +43,7 @@ GC gc;

} color_rgb; void color_allocate_gc(color_rgb *in); +XColor *pickColor(int r, int g, int b); color_rgb *color_parse(char *colorname); color_rgb *color_new(int r, int g, int b); void color_free(color_rgb *in);

@@ -56,4 +57,6 @@ extern int render_red_shift;

extern int render_green_shift; extern int render_blue_shift; +extern int pseudo_bpc; +extern XColor *pseudo_colors; #endif /* __color_h */
M render/render.crender/render.c

@@ -56,7 +56,21 @@ AllocNone);

} XFree(vinfo_return); } - truecolor_startup(); + switch (render_visual->class) { + case TrueColor: + truecolor_startup(); + break; + case PseudoColor: + case StaticColor: + case GrayScale: + case StaticGray: + pseudocolor_startup(); + break; + default: + g_critical("unsupported visual class.\n"); + exit(EXIT_FAILURE); + + } } void truecolor_startup(void)

@@ -85,6 +99,89 @@ while (red_mask) { red_mask >>= 1; render_red_shift--; }

while (green_mask) { green_mask >>= 1; render_green_shift--; } while (blue_mask) { blue_mask >>= 1; render_blue_shift--; } XFree(timage); +} + +void pseudocolor_startup(void) +{ + XColor icolors[256]; + int tr, tg, tb, n, r, g, b, i, incolors, ii; + unsigned long dev; + int cpc, _ncolors; + g_message("Initializing PseudoColor RenderControl\n"); + + /* determine the number of colors and the bits-per-color */ + pseudo_bpc = 2; /* XXX THIS SHOULD BE A USER OPTION */ + g_assert(pseudo_bpc >= 1); + _ncolors = 1 << (pseudo_bpc * 3); + + if (_ncolors > 1 << render_depth) { + g_warning("PseudoRenderControl: Invalid colormap size. Resizing.\n"); + pseudo_bpc = 1 << (render_depth/3) >> 3; + _ncolors = 1 << (pseudo_bpc * 3); + } + + /* build a color cube */ + pseudo_colors = malloc(_ncolors * sizeof(XColor)); + cpc = 1 << pseudo_bpc; /* colors per channel */ + + for (n = 0, r = 0; r < cpc; r++) + for (g = 0; g < cpc; g++) + for (b = 0; b < cpc; b++, n++) { + tr = (int)(((float)(r)/(float)(cpc-1)) * 0xFF); + tg = (int)(((float)(g)/(float)(cpc-1)) * 0xFF); + tb = (int)(((float)(b)/(float)(cpc-1)) * 0xFF); + pseudo_colors[n].red = tr | tr << 8; + pseudo_colors[n].green = tg | tg << 8; + pseudo_colors[n].blue = tb | tb << 8; + pseudo_colors[n].flags = DoRed|DoGreen|DoBlue; /* used to track + allocation */ + } + + /* allocate the colors */ + for (i = 0; i < _ncolors; i++) + if (!XAllocColor(ob_display, render_colormap, &pseudo_colors[i])) + pseudo_colors[i].flags = 0; /* mark it as unallocated */ + + /* try allocate any colors that failed allocation above */ + + /* get the allocated values from the X server (only the first 256 XXX why!?) + */ + incolors = (((1 << render_depth) > 256) ? 256 : (1 << render_depth)); + for (i = 0; i < incolors; i++) + icolors[i].pixel = i; + XQueryColors(ob_display, render_colormap, icolors, incolors); + + /* try match unallocated ones */ + for (i = 0; i < _ncolors; i++) { + if (!pseudo_colors[i].flags) { /* if it wasn't allocated... */ + unsigned long closest = 0xffffffff, close = 0; + for (ii = 0; ii < incolors; ii++) { + /* find deviations */ + r = (pseudo_colors[i].red - icolors[ii].red) & 0xff; + g = (pseudo_colors[i].green - icolors[ii].green) & 0xff; + b = (pseudo_colors[i].blue - icolors[ii].blue) & 0xff; + /* find a weighted absolute deviation */ + dev = (r * r) + (g * g) + (b * b); + + if (dev < closest) { + closest = dev; + close = ii; + } + } + + pseudo_colors[i].red = icolors[close].red; + pseudo_colors[i].green = icolors[close].green; + pseudo_colors[i].blue = icolors[close].blue; + pseudo_colors[i].pixel = icolors[close].pixel; + + /* try alloc this closest color, it had better succeed! */ + if (XAllocColor(ob_display, render_colormap, &pseudo_colors[i])) + pseudo_colors[i].flags = DoRed|DoGreen|DoBlue; /* mark as alloced */ + else + g_assert(FALSE); /* wtf has gone wrong, its already alloced for + chissake! */ + } + } } void x_paint(Window win, Appearance *l)
M render/render.hrender/render.h

@@ -153,6 +153,7 @@ Appearance *appearance_new(SurfaceType type, int numtex);

Appearance *appearance_copy(Appearance *a); void appearance_free(Appearance *a); void truecolor_startup(void); +void pseudocolor_startup(void); void pixel32_to_pixmap(pixel32 *in, Pixmap out, int x, int y, int w, int h); #endif /*__render_h*/