Subject: CVS hippo: Improved CGradient

From: CVS <[email-masked]>
Date: Wed, 26 May 1999 09:50:06 -0500 (CDT)

CVSROOT:	/home/cvs/fvwm
Module name:	fvwm
Changes by:	hippo	99/05/26 09:50:06

Modified files:
	fvwm           : colors.c 

Log message:
Improved CGradient
Uses XCreateImage, works on solaris->Exceed, not sure about the other three
endian combinations.

--
Visit the official FVWM web page at <URL:http://www.fvwm.org/>.
To unsubscribe from the list, send "unsubscribe fvwm-workers" in the
body of a message to [email-masked].
To report problems, send mail to [email-masked]

---

From: Brad Giaccio <[email-masked]>
Date: Wed, 26 May 1999 11:13:29 -0400

Seems to work great for me on my Solaris sparc.  You left two fprintf's in 
the code in case you are interested in the values:
byte_order=1 bitmap_unit=32 bitmap_bit_order=1
bitmap_pad=32 bytes_per_line=1020 bits_per_pixel=32

-- 
--- There are two kinds of knowledge, you either know the answer or
			you know where to find it
		      -Kane, Johnson, and anonymous
--
Visit the official FVWM web page at <URL:http://www.fvwm.org/>.
To unsubscribe from the list, send "unsubscribe fvwm-workers" in the
body of a message to [email-masked].
To report problems, send mail to [email-masked]

---

From: Matthias Clasen <[email-masked]>
Date: Wed, 26 May 1999 18:41:36 +0200

Your mail made me aware of the existence of [CS]Gradient, and
I tried it with a CVS version of half an hour ago. First of
all, it doesn't work with ButtonStyle or MenuStyle. Is that intended
or just unfinished work ? I then tried it with DefaultBackground
and got a nice circular pattern from SGradient, but CGradient
doesn't work. It just creates a bar-code like pattern of black and
blue vertical stripes. This is on RH Linux 6.0, with the following 
X server:

bash$ xdpyinfo
name of display:    :0.0
version number:    11.0
vendor string:    The XFree86 Project, Inc
vendor release number:    3330
maximum request size:  4194300 bytes
motion buffer size:  256
bitmap unit, bit order, padding:    32, LSBFirst, 32
image byte order:    LSBFirst
number of supported pixmap formats:    2
supported pixmap formats:
    depth 1, bits_per_pixel 1, scanline_pad 32
    depth 16, bits_per_pixel 16, scanline_pad 32
keycode range:    minimum 8, maximum 134
focus:  window 0x640000e, revert to Parent
number of extensions:    19
    BIG-REQUESTS
    DOUBLE-BUFFER
    DPMS
    LBX
    MIT-SCREEN-SAVER
    MIT-SHM
    MIT-SUNDRY-NONSTANDARD
    RECORD
    SECURITY
    SHAPE
    SYNC
    XC-APPGROUP
    XC-MISC
    XFree86-DGA
    XFree86-Misc
    XFree86-VidModeExtension
    XInputExtension
    XKEYBOARD
    XTEST
default screen number:    0
number of screens:    1

screen #0:
  dimensions:    1280x1024 pixels (433x347 millimeters)
  resolution:    75x75 dots per inch
  depths (1):    16
  root window id:    0x26
  depth of root window:    16 planes
  number of colormaps:    minimum 1, maximum 1
  default colormap:    0x23
  default number of colormap cells:    64
  preallocated pixels:    black 0, white 65535
  options:    backing-store YES, save-unders YES
  largest cursor:    64x64
  current input event mask:    0xd8003d
    KeyPressMask             ButtonPressMask          ButtonReleaseMask        
    EnterWindowMask          LeaveWindowMask          SubstructureNotifyMask   
    SubstructureRedirectMask PropertyChangeMask       ColormapChangeMask       
  number of visuals:    1
  default visual id:  0x22
  visual:
    visual id:    0x22
    class:    TrueColor
    depth:    16 planes
    available colormap entries:    64 per subfield
    red, green, blue masks:    0xf800, 0x7e0, 0x1f
    significant bits in color specification:    6 bits

-- 
Matthias Clasen, 
Tel. 0761/203-5606
Email: [email-masked]
Mathematisches Institut, Albert-Ludwigs-Universitaet Freiburg
--
Visit the official FVWM web page at <URL:http://www.fvwm.org/>.
To unsubscribe from the list, send "unsubscribe fvwm-workers" in the
body of a message to [email-masked].
To report problems, send mail to [email-masked]

---

From: Tim Phipps <[email-masked]>
Date: Thu, 27 May 1999 11:03:04 +0100

Matthias Clasen wrote:
> or just unfinished work ?

It's intended at the moment but it should be possible to adapt all
instances of gradients to use The funtions I'm working on. Fpr the
moment it will only work with the DefaultBackground command.  The
results are best viewed with FvwmIdent (take all the
*FvwmIdent{Fore,Back,Font} lines out of your .fvwm2rc.

> I then tried it with DefaultBackground
> and got a nice circular pattern from SGradient,

Are you sure it's circular? SGradient is supposed to be a gradient of
concentric Squares, CGradient is concentric Circles.

> but CGradient
                                          ^^^
> image byte order:    LSBFirst
                       ^^^

This is what I was afraid of, I get MSBFirst on my server and it works
fine and very fast.  I'm not sure what to do about this.  It was very
slow with the previous method (XFillArc * number_of_colors_in_gradient)
or it left holes (XDrawArc). I have an idea that the XPM library may
have the answer to all this endian malarchy but that would mean that
having gradients would depend on having XPM compiled in.

Cheers,
Tim.

---

From: Brad Giaccio <[email-masked]>
Date: Thu, 27 May 1999 09:35:34 -0400

> having gradients would depend on having XPM compiled in.

Well I took your suggestion Tim to see how they do it in XPM lib. So
here is the patch the big difference is they create the XImage with NULL
as the data and then once they get bytes_per_line they malloc it.  And
then they have a series of XPutPixel based on depth and endian order
that I collapssed into one function if its to slow I can split it back
out but it should be okay.  

I tested on a MSBFirst 32 and 8 bit displays an it worked fine

Matthias I don't have a LSBFirst server so could you try this out
and see if it works.

Index: colors.c===================================================================
RCS file: /home/cvs/fvwm/fvwm/fvwm/colors.c,vretrieving revision 1.14diff -u -B -b -r1.14 colors.c--- colors.c    1999/05/26 14:50:05     1.14+++ colors.c    1999/05/27 13:34:21@@ -215,6 +215,68 @@ }

+/* handles the various endian orders and depths */
+#define ZINDEX32(x, y, img) ((y) * img->bytes_per_line) + ((x) << 2)
+#define ZINDEX16(x, y, img) ((y) * img->bytes_per_line) + ((x) << 1)
+#define ZINDEX8(x, y, img) ((y) * img->bytes_per_line) + (x)
+#define ZINDEX1(x, y, img) ((y) * img->bytes_per_line) + ((x) >> 3)+static unsigned long byteorderpixel = MSBFirst << 24;
+void PutPixel(XImage* ximage, int x, int y, unsigned long pixel)
+{
+  unsigned char *addr;+  if (ximage->bits_per_pixel == 32) 
+  {+     addr = &((unsigned char *)ximage->data) [ZINDEX32(x, y, ximage)];
+     if(*((char *)&byteorderpixel) == ximage->byte_order)
+     {
+       *((unsigned long *)addr) = pixel;
+     } else if(ximage->bitmap_bit_order == MSBFirst)
+     {
+       addr[0] = pixel >> 24;+       addr[1] = pixel >> 16;+       addr[2] = pixel >> 8;
+       addr[3] = pixel;+     } else +     {+       addr[3] = pixel >> 24; +       addr[2] = pixel >> 16;+       addr[1] = pixel >> 8;+       addr[0] = pixel;
+     }
+  } else if(ximage->bits_per_pixel == 16)
+  {
+     addr = &((unsigned char *)ximage->data) [ZINDEX16(x, y, ximage)];
+     if(ximage->bitmap_bit_order == MSBFirst)
+     {
+       addr[0] = pixel >> 8;+       addr[1] = pixel;
+     } else 
+     {
+       addr[1] = pixel >> 8;+       addr[0] = pixel;
+     }+  } else if(ximage->bits_per_pixel == 8)
+  {
+     ximage->data[ZINDEX8(x, y, ximage)] = pixel;
+     return;
+  } else if (ximage->bits_per_pixel == 1)
+  {
+     if(ximage->bitmap_bit_order == MSBFirst)
+     {
+       if (pixel & 1)
+         ximage->data[ZINDEX1(x, y, ximage)] |= 0x80 >> (x & 7);
+       else
+         ximage->data[ZINDEX1(x, y, ximage)] &= ~(0x80 >> (x & 7));
+      } else
+      {
+        if (pixel & 1)
+          ximage->data[ZINDEX1(x, y, ximage)] |= 1 << (x & 7);
+        else
+          ximage->data[ZINDEX1(x, y, ximage)] &= ~(1 << (x & 7));
+      }
+  }
+}
+
 /* Create a pixmap from a gradient specifier, width and height are hints
  * that are only used for gradients that can be tiled e.g. H or V types
  * types are HVDBSCRY for Horizontal, Vertical, Diagonal, Back-diagonal, Square,
@@ -236,6 +298,7 @@
   XGCValues xgcv;
   XImage *image;
   Pixel *imageData;
+  int bitmap_pad;
 
   /* translate the gradient string into an array of colors etc */
   if (0 == (ncolors = ParseGradient(action, &colors, &perc, &nsegs))) {
@@ -360,26 +423,43 @@
       XDrawPoint(dpy, pixmap, gc, i, i);
       break;
     case 'C':
+ 
+      /* first get bitmap_pad */
+      if (depth > 16)
+      bitmap_pad = 32;
+      else if (depth > 8)
+      bitmap_pad = 16;
+      else
+      bitmap_pad = 8;
+
       /* use the first one if the second fails */
-      imageData = (Pixel *)safemalloc(width * width * sizeof(Pixel));
       image = XCreateImage(dpy, Scr.viz, Scr.depth, ZPixmap, 0,
-                          (char *)imageData, width, width, sizeof(Pixel) * 8,
+                          (char *)0, width, width, bitmap_pad,
                           0);
       if (!image){
        fvwm_msg(ERR, me, "%cGradient couldn't get image", type);
-       if (imageData)
-         free(imageData);
        break;
       }
       fprintf(stderr, "byte_order=%d bitmap_unit=%d bitmap_bit_order=%d\n",
              image->byte_order, image->bitmap_unit, image->bitmap_bit_order);
       fprintf(stderr, "bitmap_pad=%d bytes_per_line=%d bits_per_pixel=%d\n",
              image->bitmap_pad, image->bytes_per_line, image->bits_per_pixel);
+      image->data =
+    (char *) malloc( image->bytes_per_line * width); /*really want height*/
+ 
+    if (!image->data) {
+      XDestroyImage(image);
+         fvwm_msg(ERR, me, "%cGradient couldn't create image data", type);
+      break;
+    }
+
+    imageData = (Pixel*)  image->data;
       for (i = 0; i < width; i++)
        for (j = 0; j < width; j++) {
          register int x = (i - width / 2), y = (j - width / 2);
          register long pixel = ncolors - 1 - sqrt((x * x + y * y) / 2);
-         imageData[i * width + j] = pixels[pixel];
+      PutPixel(image, i, j, pixel);
+         /*imageData[i * width + j] = pixels[pixel];*/
        }
       XPutImage(dpy, pixmap, gc, image, 0, 0, 0, 0, width, width);
       XDestroyImage(image);

---

From: Brad Giaccio <[email-masked]>
Date: Thu, 27 May 1999 09:37:37 -0400

the PutPixel function if it all works chould probablly go somewhere lese
either in the library or whatever for now I just left it in colors.c so
I wouldn't have to worry about diffing headers to.

Brad

---

From: Tim Phipps <[email-masked]>
Date: Thu, 27 May 1999 15:35:20 +0100

> out but it should be okay.

I had a look at it too. The malloc after XCreateImage works for me.  It
looked like they were using their own PutPixel functions as a speed up
over XPutPixel. I'm not sure but I would have thought that
XCreateImage() would have set up an image->f.putpixel() that is tuned
for the depth and bitmap order so I'm not sure how the XPM version
speeds it up.  Anyway I've got all the gradients working with XPutPixel
now and it seems fast enough.

Cheers,
Tim.

---

From: Brad Giaccio <[email-masked]>
Date: Thu, 27 May 1999 11:54:37 -0400

> now and it seems fast enough.

There XPutPixel actually does some unnecessary malloc'ing where the
version in XPM just does some ifing on pixel size and endian order.
What I did was collapse there 8 functions into one to see if that would
work.  If nothing else you need to make sure you use the malloc like
they did or I did in my patch, to handle different pixel sizes.  Since
you have one that works with XPutPixel maybe you could try some timing
tests to see which one is faster.  Since the X book does say that en
element copy is actually fster if you can do it instead of XPutPixel.

Brad