make icons use pixel32 data, and image_draw takes pixel32 data.

client.c gets pixmap icons as a backup to netwm ones, and they are converted into pixel32 data.
This commit is contained in:
Dana Jansens 2003-05-18 23:06:11 +00:00
parent f41d06f583
commit a18c1697b1
7 changed files with 255 additions and 36 deletions

View file

@ -1142,6 +1142,9 @@ void client_update_wmhints(Client *self)
it->data);
}
/* the WM_HINTS can contain an icon */
client_update_icons(self);
/* because the self->transient flag wont change from this call,
we don't need to update the window's type and such, only its
transient_for, and the transients lists of other windows in
@ -1317,11 +1320,23 @@ void client_update_icons(Client *self)
/* store the icons */
i = 0;
for (j = 0; j < self->nicons; ++j) {
guint x, y, t;
w = self->icons[j].width = data[i++];
h = self->icons[j].height = data[i++];
self->icons[j].data =
g_memdup(&data[i], w * h * sizeof(gulong));
i += w * h;
self->icons[j].data = g_new(pixel32, w * h);
for (x = 0, y = 0, t = 0; t < w * h; ++t, ++x, ++i) {
if (x >= w) {
x = 0;
++y;
}
self->icons[j].data[t] =
(((data[i] >> 24) & 0xff) << default_alpha_offset) +
(((data[i] >> 16) & 0xff) << default_red_offset) +
(((data[i] >> 8) & 0xff) << default_green_offset) +
(((data[i] >> 0) & 0xff) << default_blue_offset);
}
g_assert(i <= num);
}
@ -1331,13 +1346,34 @@ void client_update_icons(Client *self)
if (num == 2) {
self->nicons++;
self->icons = g_new(Icon, self->nicons);
/* XXX WHAT IF THIS FAILS YOU TWIT!@!*()@ */
render_pixmap_to_rgba(data[0], data[1],
if (!render_pixmap_to_rgba(data[0], data[1],
&self->icons[self->nicons-1].width,
&self->icons[self->nicons-1].height,
&self->icons[self->nicons-1].data);
&self->icons[self->nicons-1].data)) {
g_free(&self->icons[self->nicons-1]);
self->nicons--;
}
}
g_free(data);
} else {
XWMHints *hints;
if ((hints = XGetWMHints(ob_display, self->window))) {
if (hints->flags & IconPixmapHint) {
self->nicons++;
self->icons = g_new(Icon, self->nicons);
if (!render_pixmap_to_rgba(hints->icon_pixmap,
(hints->flags & IconMaskHint ?
hints->icon_mask : None),
&self->icons[self->nicons-1].width,
&self->icons[self->nicons-1].height,
&self->icons[self->nicons-1].data)){
g_free(&self->icons[self->nicons-1]);
self->nicons--;
}
}
XFree(hints);
}
}
if (self->frame)

View file

@ -3,6 +3,8 @@
#include "geom.h"
#include "stacking.h"
#include "render/color.h"
#include <glib.h>
#include <X11/Xlib.h>
@ -16,7 +18,7 @@ struct Group;
/*! Holds an icon in ARGB format */
typedef struct Icon {
int width, height;
gulong *data;
pixel32 *data;
} Icon;
/*! The MWM Hints as retrieved from the window property

View file

@ -1,5 +1,6 @@
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <string.h>
#include "render.h"
#include "color.h"
#include "../kernel/openbox.h"
@ -82,9 +83,9 @@ void reduce_depth(pixel32 *data, XImage *im)
r = (data[x] >> default_red_offset) & 0xFF;
g = (data[x] >> default_green_offset) & 0xFF;
b = (data[x] >> default_blue_offset) & 0xFF;
p32[x] = (r << render_red_offset)
+ (g << render_green_offset)
+ (b << render_blue_offset);
p32[x] = (r << render_red_shift)
+ (g << render_green_shift)
+ (b << render_blue_shift);
}
data += im->width;
p32 += im->width;
@ -125,6 +126,7 @@ void reduce_depth(pixel32 *data, XImage *im)
g_message("your bit depth is currently unhandled\n");
}
}
XColor *pickColor(int r, int g, int b)
{
r = (r & 0xff) >> (8-pseudo_bpc);
@ -132,3 +134,130 @@ XColor *pickColor(int r, int g, int b)
b = (b & 0xff) >> (8-pseudo_bpc);
return &pseudo_colors[(r << (2*pseudo_bpc)) + (g << (1*pseudo_bpc)) + b];
}
static void swap_byte_order(XImage *im)
{
int x, y, di;
g_message("SWAPPING BYTE ORDER");
di = 0;
for (y = 0; y < im->height; ++y) {
for (x = 0; x < im->height; ++x) {
char *c = &im->data[di + x * im->bits_per_pixel / 8];
char t;
switch (im->bits_per_pixel) {
case 32:
t = c[2];
c[2] = c[3];
c[3] = t;
case 16:
t = c[0];
c[0] = c[1];
c[1] = t;
case 8:
break;
default:
g_message("your bit depth is currently unhandled\n");
}
}
di += im->bytes_per_line;
}
if (im->byte_order == LSBFirst)
im->byte_order = MSBFirst;
else
im->byte_order = LSBFirst;
}
void increase_depth(pixel32 *data, XImage *im)
{
int r, g, b;
int x,y;
pixel32 *p32 = (pixel32 *) im->data;
pixel16 *p16 = (pixel16 *) im->data;
unsigned char *p8 = (unsigned char *)im->data;
if (im->byte_order != render_endian)
swap_byte_order(im);
switch (im->bits_per_pixel) {
case 32:
for (y = 0; y < im->height; y++) {
for (x = 0; x < im->width; x++) {
r = (p32[x] >> render_red_offset) & 0xff;
g = (p32[x] >> render_green_offset) & 0xff;
b = (p32[x] >> render_blue_offset) & 0xff;
data[x] = (r << default_red_offset)
+ (g << default_green_offset)
+ (b << default_blue_offset)
+ (0xff << default_alpha_offset);
}
data += im->width;
p32 += im->bytes_per_line/4;
}
break;
case 16:
for (y = 0; y < im->height; y++) {
for (x = 0; x < im->width; x++) {
r = (p16[x] & render_red_mask) >> render_red_offset <<
render_red_shift;
g = (p16[x] & render_green_mask) >> render_green_offset <<
render_green_shift;
b = (p16[x] & render_blue_mask) >> render_blue_offset <<
render_blue_shift;
data[x] = (r << default_red_offset)
+ (g << default_green_offset)
+ (b << default_blue_offset)
+ (0xff << default_alpha_offset);
}
data += im->width;
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++) {
XColor icolor;
int ii, r, g, b;
gulong dev, closest = 0xffffffff, close = 0;
icolor.pixel = p8[x];
XQueryColor(ob_display, render_colormap, &icolor);
/* find the nearest color match */
for (ii = 0; ii < pseudo_ncolors(); ii++) {
/* find deviations */
r = (pseudo_colors[ii].red - icolor.red) & 0xff;
g = (pseudo_colors[ii].green - icolor.green) & 0xff;
b = (pseudo_colors[ii].blue - icolor.blue) & 0xff;
/* find a weighted absolute deviation */
dev = (r * r) * (0xff - (icolor.red & 0xff)) +
(g * g) * (0xff - (icolor.green & 0xff)) +
(b * b) * (0xff - (icolor.blue & 0xff));
if (dev < closest) {
closest = dev;
close = ii;
}
}
data[x] =
(pseudo_colors[close].red & 0xff <<
default_red_offset) +
(pseudo_colors[close].green & 0xff <<
default_green_offset) +
(pseudo_colors[close].blue & 0xff <<
default_blue_offset) +
(0xff << default_alpha_offset);
}
data += im->width;
p8 += im->bytes_per_line;
}
break;
default:
g_message("your bit depth is currently unhandled\n");
}
}

View file

@ -25,12 +25,14 @@ typedef u_int16_t pixel16;
#define default_red_offset 0
#define default_green_offset 8
#define default_blue_offset 16
#define endian MSBFirst
#define default_alpha_offset 24
#define render_endian MSBFirst
#else
#define default_alpha_offset 24
#define default_red_offset 16
#define default_green_offset 8
#define default_blue_offset 0
#define endian LSBFirst
#define render_endian LSBFirst
#endif /* G_BYTE_ORDER == G_BIG_ENDIAN */
@ -48,6 +50,7 @@ color_rgb *color_parse(char *colorname);
color_rgb *color_new(int r, int g, int b);
void color_free(color_rgb *in);
void reduce_depth(pixel32 *data, XImage *im);
void increase_depth(pixel32 *data, XImage *im);
extern int render_red_offset;
extern int render_green_offset;
@ -57,6 +60,11 @@ extern int render_red_shift;
extern int render_green_shift;
extern int render_blue_shift;
extern int render_red_mask;
extern int render_green_mask;
extern int render_blue_mask;
extern int pseudo_bpc;
#define pseudo_ncolors() (1 << (pseudo_bpc * 3))
extern XColor *pseudo_colors;
#endif /* __color_h */

View file

@ -5,7 +5,7 @@
void image_draw(pixel32 *target, TextureRGBA *rgba, Rect *position,
Rect *surarea)
{
gulong *draw = rgba->data;
pixel32 *draw = rgba->data;
guint c, i, e, t, sfw, sfh;
sfw = position->width;
sfh = position->height;
@ -50,10 +50,10 @@ void image_draw(pixel32 *target, TextureRGBA *rgba, Rect *position,
for (i = 0, c = 0, t = position->x, e = sfw*sfh; i < e; ++i, ++t) {
guchar alpha, r, g, b, bgr, bgg, bgb;
alpha = draw[i] >> 24;
r = draw[i] >> 16;
g = draw[i] >> 8;
b = draw[i];
alpha = draw[i] >> default_alpha_offset;
r = draw[i] >> default_red_offset;
g = draw[i] >> default_green_offset;
b = draw[i] >> default_blue_offset;
if (c >= sfw) {
c = 0;

View file

@ -19,6 +19,7 @@ Visual *render_visual;
Colormap render_colormap;
int render_red_offset = 0, render_green_offset = 0, render_blue_offset = 0;
int render_red_shift, render_green_shift, render_blue_shift;
int render_red_mask, render_green_mask, render_blue_mask;
void render_startup(void)
{
@ -87,9 +88,9 @@ void truecolor_startup(void)
ZPixmap, 0, NULL, 1, 1, 32, 0);
g_assert(timage != NULL);
/* find the offsets for each color in the visual's masks */
red_mask = timage->red_mask;
green_mask = timage->green_mask;
blue_mask = timage->blue_mask;
render_red_mask = red_mask = timage->red_mask;
render_green_mask = green_mask = timage->green_mask;
render_blue_mask = blue_mask = timage->blue_mask;
render_red_offset = 0;
render_green_offset = 0;
@ -117,7 +118,7 @@ void pseudocolor_startup(void)
/* 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);
_ncolors = pseudo_ncolors();
if (_ncolors > 1 << render_depth) {
g_warning("PseudoRenderControl: Invalid colormap size. Resizing.\n");
@ -166,7 +167,9 @@ void pseudocolor_startup(void)
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);
dev = (r * r) * (0xff - (icolors[ii].red & 0xff)) +
(g * g) * (0xff - (icolors[ii].green & 0xff)) +
(b * b) * (0xff - (icolors[ii].blue & 0xff));
if (dev < closest) {
closest = dev;
@ -400,23 +403,23 @@ void appearance_free(Appearance *a)
void pixel32_to_pixmap(pixel32 *in, Pixmap out, int x, int y, int w, int h)
{
unsigned char *scratch;
pixel32 *scratch;
XImage *im = NULL;
im = XCreateImage(ob_display, render_visual, render_depth,
ZPixmap, 0, NULL, w, h, 32, 0);
g_assert(im != NULL);
im->byte_order = endian;
im->byte_order = render_endian;
/* this malloc is a complete waste of time on normal 32bpp
as reduce_depth just sets im->data = data and returns
*/
scratch = malloc(im->width * im->height * sizeof(pixel32));
scratch = g_new(pixel32, im->width * im->height);
im->data = (char*) scratch;
reduce_depth(in, im);
XPutImage(ob_display, out, DefaultGC(ob_display, ob_screen),
im, 0, 0, x, y, w, h);
im->data = NULL;
XDestroyImage(im);
free(scratch);
g_free(scratch);
}
void appearance_minsize(Appearance *l, int *w, int *h)
@ -468,9 +471,50 @@ void appearance_minsize(Appearance *l, int *w, int *h)
}
}
void render_pixmap_to_rgba(Pixmap pmap, Pixmap mask,
int *w, int *h, gulong **data)
gboolean render_pixmap_to_rgba(Pixmap pmap, Pixmap mask,
int *w, int *h, pixel32 **data)
{
*w = *h = 0;
*data = NULL;
Window xr;
int xx, xy;
guint pw, ph, mw, mh, xb, xd, i, x, y, di;
XImage *xi, *xm = NULL;
if (!XGetGeometry(ob_display, pmap, &xr, &xx, &xy, &pw, &ph, &xb, &xd))
return FALSE;
if (mask) {
if (!XGetGeometry(ob_display, mask, &xr, &xx, &xy, &mw, &mh, &xb, &xd))
return FALSE;
if (pw != mw || ph != mh || xd != 1)
return FALSE;
}
xi = XGetImage(ob_display, pmap, 0, 0, pw, ph, 0xffffffff, ZPixmap);
if (!xi)
return FALSE;
if (mask) {
xm = XGetImage(ob_display, mask, 0, 0, mw, mh, 0xffffffff, ZPixmap);
if (!xm)
return FALSE;
}
*data = g_new(pixel32, pw * ph);
increase_depth(*data, xi);
if (mask) {
/* apply transparency from the mask */
di = 0;
for (i = 0, y = 0; y < ph; ++y) {
for (x = 0; x < pw; ++x, ++i) {
if (!((((unsigned)xm->data[di + x / 8]) >> (x % 8)) & 0x1))
(*data)[i] &= ~(0xff << default_alpha_offset);
}
di += xm->bytes_per_line;
}
}
*w = pw;
*h = ph;
return TRUE;
}

View file

@ -112,11 +112,11 @@ typedef struct TextureMask {
typedef struct TextureRGBA {
guint width;
guint height;
unsigned long *data;
pixel32 *data;
/* cached scaled so we don't have to scale often */
guint cwidth;
guint cheight;
unsigned long *cache;
pixel32 *cache;
} TextureRGBA;
typedef union {
@ -159,7 +159,7 @@ void pixel32_to_pixmap(pixel32 *in, Pixmap out, int x, int y, int w, int h);
void appearance_minsize(Appearance *l, int *w, int *h);
void render_pixmap_to_rgba(Pixmap pmap, Pixmap mask,
int *w, int *h, gulong **data);
gboolean render_pixmap_to_rgba(Pixmap pmap, Pixmap mask,
int *w, int *h, pixel32 **data);
#endif /*__render_h*/