Added color cursor support.

This commit is contained in:
Duane Clark 2001-12-26 20:30:40 +00:00 committed by Alexandre Julliard
parent 1a399a2bb9
commit 3169072b2f

View file

@ -145,13 +145,10 @@ Cursor X11DRV_GetCursor( Display *display, CURSORICONINFO *ptr )
{
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 @@ Cursor X11DRV_GetCursor( Display *display, CURSORICONINFO *ptr )
* 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 @@ Cursor X11DRV_GetCursor( Display *display, CURSORICONINFO *ptr )
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 );
}