]> Dogcows Code - chaz/openbox/commitdiff
make icons use pixel32 data, and image_draw takes pixel32 data.
authorDana Jansens <danakj@orodu.net>
Sun, 18 May 2003 23:06:11 +0000 (23:06 +0000)
committerDana Jansens <danakj@orodu.net>
Sun, 18 May 2003 23:06:11 +0000 (23:06 +0000)
client.c gets pixmap icons as a backup to netwm ones, and they are converted into pixel32 data.

openbox/client.c
openbox/client.h
render/color.c
render/color.h
render/image.c
render/render.c
render/render.h

index 0e5a59f0ab65dbee51408124b9328d6fc18dc011..8efed96abe5ef532bb6f6dca915311e8e4aa8a42 100644 (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],
-                                  &self->icons[self->nicons-1].width,
-                                  &self->icons[self->nicons-1].height,
-                                  &self->icons[self->nicons-1].data);
+            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)) {
+                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)
index 7545b8600f3d212e79f6578f68d5ab4e598e59ee..b4e0494d68aeb2fea623448974dce2f2de453b88 100644 (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
index 3a5b6cdb2234b39c826841b535ac13b857326181..b9bafe32fefd06f3d0ccd3d1e24de44cbe7591d8 100644 (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");
+    }
+}
index a2970e4bed2180df72788af2f73d828517876546..fb669fb54f5c5ff910ad8684921141efc7a4c26b 100644 (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 */
index 7b58712bde9bd3a890249cc440d00ef5ed8f40d7..feb259703d3d96bc6be2f62b4044c0879b11917c 100644 (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;
index a1022bd0594fddaec218b7d3accbd0dcf8acc383..cfad7143f5bc8db961b244589e86e13f93e1fcac 100644 (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;
 }
index 3fbf324958df65d20cbf6ccdfba5883f7ce3dbb8..68fec4681ab1c9a06f437894d9844b1354432dea 100644 (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*/
This page took 0.037982 seconds and 4 git commands to generate.