fix for bug 5486

Patch makes it possible to load and display 32bit rgba cursor. I have
made tested the code with Football Manager 2006. The ealier version of
patch was confimed loading 32bit cursors from Guild Wars. 

I would like to hear comments how to improve the code. Is there chance
that this could be included to wine? (without huge modifications)

The code is a hack and not perfect solution. But hack is better than
invisible cursor.

Index: dlls/winex11.drv/mouse.c
===================================================================
RCS file: /home/wine/wine/dlls/winex11.drv/mouse.c,v
retrieving revision 1.1
diff -u -p -t -r1.1 mouse.c
--- dlls/winex11.drv/mouse.c	16 Jun 2006 13:19:17 -0000	1.1
+++ dlls/winex11.drv/mouse.c	24 Jun 2006 22:25:07 -0000
@@ -422,16 +422,19 @@ static Cursor create_cursor( Display *di
         }
         else
         {
-            int     rbits, gbits, bbits, red, green, blue;
+            int     rbits, gbits, bbits,abits, red, green, blue, alpha;
             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 */
+            BYTE    pXorBits[128], pAndBits[128];   /* Up to 32x32 icons; could use same array but ...  */
+            int failure = 0;
 
             switch (ptr->bBitsPerPixel)
             {
+            case 32:
+                abits = 8;
             case 24:
                 rbits = 8;
                 gbits = 8;
@@ -473,13 +476,16 @@ static Cursor create_cursor( Display *di
             ymax = (ptr->nHeight > 32) ? 32 : ptr->nHeight;
 
             memset(pXorBits, 0, 128);
+            memset(pAndBits, 0, 128);
             for (y=0; y<ymax; y++)
             {
                 for (x=0; x<xmax; x++)
                 {
                         red = green = blue = 0;
+                        alpha = 255;   // This is vissible?
                         switch (ptr->bBitsPerPixel)
                         {
+                        case 32:
                         case 24:
                             theChar = theImage[byteIndex++];
                             blue = theChar;
@@ -487,6 +493,11 @@ static Cursor create_cursor( Display *di
                             green = theChar;
                             theChar = theImage[byteIndex++];
                             red = theChar;
+                            if (ptr->bBitsPerPixel == 32)
+                            {
+                                theChar = theImage[byteIndex++];
+                                alpha = theChar;
+                            }
                             break;
                         case 16:
                             theChar = theImage[byteIndex++];
@@ -498,8 +509,19 @@ static Cursor create_cursor( Display *di
                             break;
                         }
 
-                    if (red+green+blue > threshold)
+                    
+                    //bg or fg?
+                    // If there is alpha for fg color then we should calculate avarange
+                    // alpha and use that to create transperancy for cursor (at least my gnome 
+                    // has transperancy with xorg 7)
+                    if (alpha < threshold>>3)
+                    {
+                        // Transperant
+                        pAndBits[xorIndex] |= bitShifted;
+                    }
+                    else if (red+green+blue > threshold)
                     {
+                        // Foreground
                         rfg += red;
                         gfg += green;
                         bfg += blue;
@@ -508,10 +530,18 @@ static Cursor create_cursor( Display *di
                     }
                     else
                     {
+                        // Background
                         rbg += red;
                         gbg += green;
                         bbg += blue;
                     }
+/*                  // What is going on?
+                    TRACE("Cursor file pixel, red=%d green=%d blue=%d alpha=%d Xor=%d\n",
+                        red,
+                        green,
+                        blue,
+                        alpha,
+                        pXorBits[xorIndex]&bitShifted);*/
                     if (x%8 == 7)
                     {
                         bitShifted = 0x01;
@@ -540,7 +570,19 @@ static Cursor create_cursor( Display *di
             }
             else bg.red = bg.green = bg.blue = 0;
             pixmapBits = XCreateBitmapFromData( display, root_window, (char *)pXorBits, xmax, ymax );
-            if (!pixmapBits)
+            if (ptr->bBitsPerPixel == 32)
+            {
+                pixmapMask = XCreateBitmapFromData( display, root_window, (char *)pAndBits, xmax, ymax );
+
+                if (!pixmapMask)
+                {
+                        XFreePixmap( display, pixmapAll );
+                        failure = 1;
+                }
+
+            }
+            if (!pixmapBits 
+                && failure)
             {
                 XFreePixmap( display, pixmapAll );
                 XFreeGC( display, gc );
@@ -556,6 +598,12 @@ static Cursor create_cursor( Display *di
             /* Put the image */
             XCopyArea( display, pixmapBits, pixmapAll, gc,
                        0, 0, xmax, ymax, 0, ptr->nHeight );
+            if (ptr->bBitsPerPixel == 32)
+            {
+                XCopyArea( display, pixmapMask, pixmapAll, gc,
+                        0, 0, xmax, ymax, 0, 0);
+                XFreePixmap( display, pixmapMask );
+            }
             XFreePixmap( display, pixmapBits );
         }
         image->data = NULL;


Reply via email to