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); it->data);
} }
/* the WM_HINTS can contain an icon */
client_update_icons(self);
/* because the self->transient flag wont change from this call, /* because the self->transient flag wont change from this call,
we don't need to update the window's type and such, only its we don't need to update the window's type and such, only its
transient_for, and the transients lists of other windows in transient_for, and the transients lists of other windows in
@ -1317,11 +1320,23 @@ void client_update_icons(Client *self)
/* store the icons */ /* store the icons */
i = 0; i = 0;
for (j = 0; j < self->nicons; ++j) { for (j = 0; j < self->nicons; ++j) {
guint x, y, t;
w = self->icons[j].width = data[i++]; w = self->icons[j].width = data[i++];
h = self->icons[j].height = data[i++]; h = self->icons[j].height = data[i++];
self->icons[j].data =
g_memdup(&data[i], w * h * sizeof(gulong)); self->icons[j].data = g_new(pixel32, w * h);
i += 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); g_assert(i <= num);
} }
@ -1331,13 +1346,34 @@ void client_update_icons(Client *self)
if (num == 2) { if (num == 2) {
self->nicons++; self->nicons++;
self->icons = g_new(Icon, self->nicons); self->icons = g_new(Icon, self->nicons);
/* XXX WHAT IF THIS FAILS YOU TWIT!@!*()@ */ if (!render_pixmap_to_rgba(data[0], data[1],
render_pixmap_to_rgba(data[0], data[1], &self->icons[self->nicons-1].width,
&self->icons[self->nicons-1].width, &self->icons[self->nicons-1].height,
&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); 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) if (self->frame)

View file

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

View file

@ -1,5 +1,6 @@
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/Xutil.h> #include <X11/Xutil.h>
#include <string.h>
#include "render.h" #include "render.h"
#include "color.h" #include "color.h"
#include "../kernel/openbox.h" #include "../kernel/openbox.h"
@ -82,9 +83,9 @@ void reduce_depth(pixel32 *data, XImage *im)
r = (data[x] >> default_red_offset) & 0xFF; r = (data[x] >> default_red_offset) & 0xFF;
g = (data[x] >> default_green_offset) & 0xFF; g = (data[x] >> default_green_offset) & 0xFF;
b = (data[x] >> default_blue_offset) & 0xFF; b = (data[x] >> default_blue_offset) & 0xFF;
p32[x] = (r << render_red_offset) p32[x] = (r << render_red_shift)
+ (g << render_green_offset) + (g << render_green_shift)
+ (b << render_blue_offset); + (b << render_blue_shift);
} }
data += im->width; data += im->width;
p32 += 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"); g_message("your bit depth is currently unhandled\n");
} }
} }
XColor *pickColor(int r, int g, int b) XColor *pickColor(int r, int g, int b)
{ {
r = (r & 0xff) >> (8-pseudo_bpc); r = (r & 0xff) >> (8-pseudo_bpc);
@ -132,3 +134,130 @@ XColor *pickColor(int r, int g, int b)
b = (b & 0xff) >> (8-pseudo_bpc); b = (b & 0xff) >> (8-pseudo_bpc);
return &pseudo_colors[(r << (2*pseudo_bpc)) + (g << (1*pseudo_bpc)) + b]; 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_red_offset 0
#define default_green_offset 8 #define default_green_offset 8
#define default_blue_offset 16 #define default_blue_offset 16
#define endian MSBFirst #define default_alpha_offset 24
#define render_endian MSBFirst
#else #else
#define default_alpha_offset 24
#define default_red_offset 16 #define default_red_offset 16
#define default_green_offset 8 #define default_green_offset 8
#define default_blue_offset 0 #define default_blue_offset 0
#define endian LSBFirst #define render_endian LSBFirst
#endif /* G_BYTE_ORDER == G_BIG_ENDIAN */ #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); color_rgb *color_new(int r, int g, int b);
void color_free(color_rgb *in); void color_free(color_rgb *in);
void reduce_depth(pixel32 *data, XImage *im); void reduce_depth(pixel32 *data, XImage *im);
void increase_depth(pixel32 *data, XImage *im);
extern int render_red_offset; extern int render_red_offset;
extern int render_green_offset; extern int render_green_offset;
@ -57,6 +60,11 @@ extern int render_red_shift;
extern int render_green_shift; extern int render_green_shift;
extern int render_blue_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; extern int pseudo_bpc;
#define pseudo_ncolors() (1 << (pseudo_bpc * 3))
extern XColor *pseudo_colors; extern XColor *pseudo_colors;
#endif /* __color_h */ #endif /* __color_h */

View file

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

View file

@ -19,6 +19,7 @@ Visual *render_visual;
Colormap render_colormap; Colormap render_colormap;
int render_red_offset = 0, render_green_offset = 0, render_blue_offset = 0; 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_shift, render_green_shift, render_blue_shift;
int render_red_mask, render_green_mask, render_blue_mask;
void render_startup(void) void render_startup(void)
{ {
@ -87,9 +88,9 @@ void truecolor_startup(void)
ZPixmap, 0, NULL, 1, 1, 32, 0); ZPixmap, 0, NULL, 1, 1, 32, 0);
g_assert(timage != NULL); g_assert(timage != NULL);
/* find the offsets for each color in the visual's masks */ /* find the offsets for each color in the visual's masks */
red_mask = timage->red_mask; render_red_mask = red_mask = timage->red_mask;
green_mask = timage->green_mask; render_green_mask = green_mask = timage->green_mask;
blue_mask = timage->blue_mask; render_blue_mask = blue_mask = timage->blue_mask;
render_red_offset = 0; render_red_offset = 0;
render_green_offset = 0; render_green_offset = 0;
@ -117,7 +118,7 @@ void pseudocolor_startup(void)
/* determine the number of colors and the bits-per-color */ /* determine the number of colors and the bits-per-color */
pseudo_bpc = 2; /* XXX THIS SHOULD BE A USER OPTION */ pseudo_bpc = 2; /* XXX THIS SHOULD BE A USER OPTION */
g_assert(pseudo_bpc >= 1); g_assert(pseudo_bpc >= 1);
_ncolors = 1 << (pseudo_bpc * 3); _ncolors = pseudo_ncolors();
if (_ncolors > 1 << render_depth) { if (_ncolors > 1 << render_depth) {
g_warning("PseudoRenderControl: Invalid colormap size. Resizing.\n"); 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; g = (pseudo_colors[i].green - icolors[ii].green) & 0xff;
b = (pseudo_colors[i].blue - icolors[ii].blue) & 0xff; b = (pseudo_colors[i].blue - icolors[ii].blue) & 0xff;
/* find a weighted absolute deviation */ /* 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) { if (dev < closest) {
closest = dev; 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) void pixel32_to_pixmap(pixel32 *in, Pixmap out, int x, int y, int w, int h)
{ {
unsigned char *scratch; pixel32 *scratch;
XImage *im = NULL; XImage *im = NULL;
im = XCreateImage(ob_display, render_visual, render_depth, im = XCreateImage(ob_display, render_visual, render_depth,
ZPixmap, 0, NULL, w, h, 32, 0); ZPixmap, 0, NULL, w, h, 32, 0);
g_assert(im != NULL); g_assert(im != NULL);
im->byte_order = endian; im->byte_order = render_endian;
/* this malloc is a complete waste of time on normal 32bpp /* this malloc is a complete waste of time on normal 32bpp
as reduce_depth just sets im->data = data and returns 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; im->data = (char*) scratch;
reduce_depth(in, im); reduce_depth(in, im);
XPutImage(ob_display, out, DefaultGC(ob_display, ob_screen), XPutImage(ob_display, out, DefaultGC(ob_display, ob_screen),
im, 0, 0, x, y, w, h); im, 0, 0, x, y, w, h);
im->data = NULL; im->data = NULL;
XDestroyImage(im); XDestroyImage(im);
free(scratch); g_free(scratch);
} }
void appearance_minsize(Appearance *l, int *w, int *h) 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, gboolean render_pixmap_to_rgba(Pixmap pmap, Pixmap mask,
int *w, int *h, gulong **data) int *w, int *h, pixel32 **data)
{ {
*w = *h = 0; Window xr;
*data = NULL; 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 { typedef struct TextureRGBA {
guint width; guint width;
guint height; guint height;
unsigned long *data; pixel32 *data;
/* cached scaled so we don't have to scale often */ /* cached scaled so we don't have to scale often */
guint cwidth; guint cwidth;
guint cheight; guint cheight;
unsigned long *cache; pixel32 *cache;
} TextureRGBA; } TextureRGBA;
typedef union { 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 appearance_minsize(Appearance *l, int *w, int *h);
void render_pixmap_to_rgba(Pixmap pmap, Pixmap mask, gboolean render_pixmap_to_rgba(Pixmap pmap, Pixmap mask,
int *w, int *h, gulong **data); int *w, int *h, pixel32 **data);
#endif /*__render_h*/ #endif /*__render_h*/