Added color cursor support.
This commit is contained in:
parent
1a399a2bb9
commit
3169072b2f
|
@ -145,13 +145,10 @@ Cursor X11DRV_GetCursor( Display *display, CURSORICONINFO *ptr )
|
||||||
{
|
{
|
||||||
XImage *image;
|
XImage *image;
|
||||||
GC gc;
|
GC gc;
|
||||||
|
|
||||||
if (ptr->bPlanes * ptr->bBitsPerPixel != 1)
|
TRACE("Bitmap %dx%d planes=%d bpp=%d bytesperline=%d\n",
|
||||||
{
|
ptr->nWidth, ptr->nHeight, ptr->bPlanes, ptr->bBitsPerPixel,
|
||||||
WARN("Cursor has more than 1 bpp!\n" );
|
ptr->nWidthBytes);
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create a pixmap and transfer all the bits to it */
|
/* Create a pixmap and transfer all the bits to it */
|
||||||
|
|
||||||
/* NOTE: Following hack works, but only because XFree depth
|
/* 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
|
* as the Windows cursor data). Perhaps use a more generic
|
||||||
* algorithm here.
|
* 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,
|
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,
|
if (!(image = XCreateImage( display, visual,
|
||||||
1, ZPixmap, 0, (char *)(ptr + 1), ptr->nWidth,
|
1, ZPixmap, 0, (char *)(ptr + 1), ptr->nWidth,
|
||||||
ptr->nHeight * 2, 16, ptr->nWidthBytes))) return 0;
|
ptr->nHeight * 2, 16, ptr->nWidthBytes/ptr->bBitsPerPixel)))
|
||||||
|
{
|
||||||
|
XFreePixmap( display, pixmapAll );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
gc = XCreateGC( display, pixmapAll, 0, NULL );
|
gc = XCreateGC( display, pixmapAll, 0, NULL );
|
||||||
XSetGraphicsExposures( display, gc, False );
|
XSetGraphicsExposures( display, gc, False );
|
||||||
image->byte_order = MSBFirst;
|
image->byte_order = MSBFirst;
|
||||||
image->bitmap_bit_order = MSBFirst;
|
image->bitmap_bit_order = MSBFirst;
|
||||||
image->bitmap_unit = 16;
|
image->bitmap_unit = 16;
|
||||||
_XInitImageFuncPtrs(image);
|
_XInitImageFuncPtrs(image);
|
||||||
XPutImage( display, pixmapAll, gc, image,
|
if (ptr->bPlanes * ptr->bBitsPerPixel == 1)
|
||||||
0, 0, 0, 0, ptr->nWidth, ptr->nHeight * 2 );
|
{
|
||||||
|
/* 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;
|
image->data = NULL;
|
||||||
XDestroyImage( image );
|
XDestroyImage( image );
|
||||||
|
|
||||||
|
@ -230,8 +351,6 @@ Cursor X11DRV_GetCursor( Display *display, CURSORICONINFO *ptr )
|
||||||
XCopyArea( display, pixmapMaskInv, pixmapBits, gc,
|
XCopyArea( display, pixmapMaskInv, pixmapBits, gc,
|
||||||
0, 0, ptr->nWidth, ptr->nHeight, 1, 1 );
|
0, 0, ptr->nWidth, ptr->nHeight, 1, 1 );
|
||||||
XSetFunction( display, gc, GXcopy );
|
XSetFunction( display, gc, GXcopy );
|
||||||
fg.red = fg.green = fg.blue = 0xffff;
|
|
||||||
bg.red = bg.green = bg.blue = 0x0000;
|
|
||||||
cursor = XCreatePixmapCursor( display, pixmapBits, pixmapMask,
|
cursor = XCreatePixmapCursor( display, pixmapBits, pixmapMask,
|
||||||
&fg, &bg, ptr->ptHotSpot.x, ptr->ptHotSpot.y );
|
&fg, &bg, ptr->ptHotSpot.x, ptr->ptHotSpot.y );
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue