Color cursor support, take 2

Duane Clark dclark at akamail.com
Sat Dec 22 20:14:33 CST 2001


Here is another attempt at color cursor support, still only for 24 bit 
color cursors. If anyone knows of an app with color cursors at another 
depth, let me know and I will try to add support for it. This patch 
should print out a fixme with the depth of the requested cursor for 
unsupported depths.

ChangeLog:

	* windows/cursoricon.c
                 Destroying cursor is not neccesarily an error
	* dlls/x11drv/mouse.c
                 Add color cursor support

Duane



-------------- next part --------------
Index: windows/cursoricon.c
===================================================================
RCS file: /home/wine/wine/windows/cursoricon.c,v
retrieving revision 1.38
diff -u -r1.38 cursoricon.c
--- windows/cursoricon.c	2001/12/17 21:40:57	1.38
+++ windows/cursoricon.c	2001/12/23 00:22:59
@@ -1303,7 +1303,7 @@
 
     if ( hActiveCursor == handle )
     {
-        ERR_(cursor)("Destroying active cursor!\n" );
+        WARN_(cursor)("Destroying active cursor!\n" );
         SetCursor( 0 );
     }
 
Index: dlls/x11drv/mouse.c
===================================================================
RCS file: /home/wine/wine/dlls/x11drv/mouse.c,v
retrieving revision 1.1
diff -u -r1.1 mouse.c
--- dlls/x11drv/mouse.c	2001/10/18 21:38:59	1.1
+++ dlls/x11drv/mouse.c	2001/12/23 00:23:00
@@ -145,13 +145,10 @@
     {
         XImage *image;
         GC gc;
-
-        if (ptr->bPlanes * ptr->bBitsPerPixel != 1)
-        {
-            WARN("Cursor has more than 1 bpp!\n" );
-            return 0;
-        }
-
+        
+        TRACE("Bitmap %dx%d planes=%d bpp=%d bytesperline=%d\n",
+            ptr->nWidth, ptr->nHeight, ptr->bPlanes, ptr->bBitsPerPixel,
+            ptr->nWidthBytes);
         /* Create a pixmap and transfer all the bits to it */
 
         /* NOTE: Following hack works, but only because XFree depth
@@ -159,19 +156,143 @@
          *       as the Windows cursor data). Perhaps use a more generic
          *       algorithm here.
          */
+        /* This pixmap will be written with two bitmaps. The first is
+         *  the mask and the second is the image.
+         */
         if (!(pixmapAll = XCreatePixmap( display, root_window,
-                                         ptr->nWidth, ptr->nHeight * 2, 1 ))) return 0;
+                  ptr->nWidth, ptr->nHeight * 2, 1 ))) 
+            return 0;
         if (!(image = XCreateImage( display, visual,
-                                    1, ZPixmap, 0, (char *)(ptr + 1), ptr->nWidth,
-                                    ptr->nHeight * 2, 16, ptr->nWidthBytes))) return 0;
+                1, ZPixmap, 0, (char *)(ptr + 1), ptr->nWidth,
+                ptr->nHeight * 2, 16, ptr->nWidthBytes/ptr->bBitsPerPixel))) 
+        {
+            XFreePixmap( display, pixmapAll );
+            return 0;
+        }
         gc = XCreateGC( display, pixmapAll, 0, NULL );
         XSetGraphicsExposures( display, gc, False );
         image->byte_order = MSBFirst;
         image->bitmap_bit_order = MSBFirst;
         image->bitmap_unit = 16;
         _XInitImageFuncPtrs(image);
-        XPutImage( display, pixmapAll, gc, image,
-                   0, 0, 0, 0, ptr->nWidth, ptr->nHeight * 2 );
+        if (ptr->bPlanes * ptr->bBitsPerPixel == 1)
+        {
+            /* A plain old white on black cursor. */
+            fg.red = fg.green = fg.blue = 0xffff;
+            bg.red = bg.green = bg.blue = 0x0000;
+            XPutImage( display, pixmapAll, gc, image,
+                0, 0, 0, 0, ptr->nWidth, ptr->nHeight * 2 );
+        }
+        else
+        {
+            int     rbits, gbits, bbits, red, green, blue;
+            int     rfg, gfg, bfg, rbg, gbg, bbg;
+            int     rscale, gscale, bscale;
+            int     x, y, xmax, ymax, bitIndex, byteIndex, xorIndex;
+            unsigned char *theMask, *theImage, theChar;
+            int     threshold, fgBits, bgBits, bitShifted;
+            BYTE    pXorBits[128];   /* Up to 32x32 icons */
+            
+            switch (ptr->bBitsPerPixel)
+            {
+            case 24:
+                rbits = 8;
+                gbits = 8;
+                bbits = 8;
+                threshold = 0x40;
+                break;
+            default:
+                FIXME("Currently no support for cursors with %d bits per pixel\n",
+                  ptr->bBitsPerPixel);
+                XFreePixmap( display, pixmapAll );
+                XFreeGC( display, gc );
+                image->data = NULL;
+                XDestroyImage( image );
+                return 0;
+            }
+            /* The location of the mask. */
+            theMask = (char *)(ptr + 1);
+            /* The mask should still be 1 bit per pixel. The color image
+             * should immediately follow the mask. 
+             */
+            theImage = &theMask[ptr->nWidth/8 * ptr->nHeight];
+            rfg = gfg = bfg = rbg = gbg = bbg = 0;
+            bitIndex = 0;
+            byteIndex = 0;
+            xorIndex = 0;
+            fgBits = 0;
+            bitShifted = 0x01;
+            xmax = (ptr->nWidth > 32) ? 32 : ptr->nWidth;
+            if (ptr->nWidth > 32) {
+                ERR("Got a %dx%d cursor. Cannot handle larger than 32x32.\n",
+                  ptr->nWidth, ptr->nHeight);
+            }
+            ymax = (ptr->nHeight > 32) ? 32 : ptr->nHeight;
+            
+            memset(pXorBits, 0, 128);
+            for (y=0; y<ymax; y++)
+            {
+                for (x=0; x<xmax; x++)
+                {
+                    theChar = theImage[byteIndex++];
+                    red = green = blue = 0;
+                    blue = theChar;
+                    theChar = theImage[byteIndex++];
+                    green = theChar;
+                    theChar = theImage[byteIndex++];
+                    red = theChar;
+                    if (red+green+blue > threshold)
+                    {
+                        rfg += red;
+                        gfg += green;
+                        bfg += blue;
+                        fgBits++;
+                        pXorBits[xorIndex] |= bitShifted;
+                    }
+                    else
+                    {
+                        rbg += red;
+                        gbg += green;
+                        bbg += blue;
+                    }
+                    if (x%8 == 7)
+                    {
+                        bitShifted = 0x01;
+                        xorIndex++;
+                    }
+                    else
+                        bitShifted = bitShifted << 1;
+                }
+            }
+            rscale = 1 << (16 - rbits);
+            gscale = 1 << (16 - gbits);
+            bscale = 1 << (16 - bbits);
+            fg.red   = rfg * rscale / fgBits;
+            fg.green = gfg * gscale / fgBits;
+            fg.blue  = bfg * bscale / fgBits;
+            bgBits = xmax * ymax - fgBits;
+            bg.red   = rbg * rscale / bgBits;
+            bg.green = gbg * gscale / bgBits;
+            bg.blue  = bbg * bscale / bgBits;
+            pixmapBits = XCreateBitmapFromData( display, root_window, pXorBits, xmax, ymax );
+            if (!pixmapBits)
+            {
+                XFreePixmap( display, pixmapAll );
+                XFreeGC( display, gc );
+                image->data = NULL;
+                XDestroyImage( image );
+                return 0;
+            }
+            
+            /* Put the mask. */
+            XPutImage( display, pixmapAll, gc, image,
+                   0, 0, 0, 0, ptr->nWidth, ptr->nHeight );
+            XSetFunction( display, gc, GXcopy );
+            /* Put the image */
+            XCopyArea( display, pixmapBits, pixmapAll, gc,
+                       0, 0, xmax, ymax, 0, ptr->nHeight );
+            XFreePixmap( display, pixmapBits );
+        }
         image->data = NULL;
         XDestroyImage( image );
 
@@ -230,8 +351,6 @@
             XCopyArea( display, pixmapMaskInv, pixmapBits, gc,
                        0, 0, ptr->nWidth, ptr->nHeight, 1, 1 );
             XSetFunction( display, gc, GXcopy );
-            fg.red = fg.green = fg.blue = 0xffff;
-            bg.red = bg.green = bg.blue = 0x0000;
             cursor = XCreatePixmapCursor( display, pixmapBits, pixmapMask,
                                 &fg, &bg, ptr->ptHotSpot.x, ptr->ptHotSpot.y );
         }


More information about the wine-patches mailing list