mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-30 16:58:40 -04:00
X11: fix .ico cursor bug. Support PNG-compressed .ico files.
This commit is contained in:
parent
a973107bd9
commit
7c45e891f5
@ -41,6 +41,7 @@ This issue fixes several bugs that were still found in 1.9.2.
|
|||||||
* Fix tinydisplay texture errors on shutdown
|
* Fix tinydisplay texture errors on shutdown
|
||||||
* Fix mipmap filtering issues in tinydisplay renderer
|
* Fix mipmap filtering issues in tinydisplay renderer
|
||||||
* Fix exception when creating intervals before ShowBase is started
|
* Fix exception when creating intervals before ShowBase is started
|
||||||
|
* Fix rare X11 .ico cursor bug; also now supports PNG-compressed icons
|
||||||
|
|
||||||
------------------------ RELEASE 1.9.2 ------------------------
|
------------------------ RELEASE 1.9.2 ------------------------
|
||||||
|
|
||||||
|
@ -28,6 +28,8 @@
|
|||||||
#include "nativeWindowHandle.h"
|
#include "nativeWindowHandle.h"
|
||||||
#include "virtualFileSystem.h"
|
#include "virtualFileSystem.h"
|
||||||
#include "get_x11.h"
|
#include "get_x11.h"
|
||||||
|
#include "pnmImage.h"
|
||||||
|
#include "pnmFileTypeRegistry.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@ -2303,11 +2305,41 @@ read_ico(istream &ico) {
|
|||||||
// Seek to the image in the ICO.
|
// Seek to the image in the ICO.
|
||||||
ico.seekg(entries[entry].offset);
|
ico.seekg(entries[entry].offset);
|
||||||
if (!ico.good()) goto cleanup;
|
if (!ico.good()) goto cleanup;
|
||||||
|
|
||||||
|
if (ico.peek() == 0x89) {
|
||||||
|
// Hang on, this is actually a PNG header.
|
||||||
|
PNMImage img;
|
||||||
|
PNMFileTypeRegistry *reg = PNMFileTypeRegistry::get_global_ptr();
|
||||||
|
if (!img.read(ico, "", reg->get_type_from_extension("png"))) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
img.set_maxval(255);
|
||||||
|
|
||||||
|
image = XcursorImageCreate(img.get_x_size(), img.get_y_size());
|
||||||
|
|
||||||
|
xel *ptr = img.get_array();
|
||||||
|
xelval *alpha = img.get_alpha_array();
|
||||||
|
size_t num_pixels = (size_t)img.get_x_size() * (size_t)img.get_y_size();
|
||||||
|
unsigned int *dest = image->pixels;
|
||||||
|
|
||||||
|
if (alpha != NULL) {
|
||||||
|
for (size_t p = 0; p < num_pixels; ++p) {
|
||||||
|
*dest++ = (*alpha << 24U) | (ptr->r << 16U) | (ptr->g << 8U) | (ptr->b);
|
||||||
|
++ptr;
|
||||||
|
++alpha;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (size_t p = 0; p < num_pixels; ++p) {
|
||||||
|
*dest++ = 0xff000000U | (ptr->r << 16U) | (ptr->g << 8U) | (ptr->b);
|
||||||
|
++ptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
ico.read(reinterpret_cast<char *>(&infoHeader), sizeof(IcoInfoHeader));
|
ico.read(reinterpret_cast<char *>(&infoHeader), sizeof(IcoInfoHeader));
|
||||||
if (!ico.good()) goto cleanup;
|
if (!ico.good()) goto cleanup;
|
||||||
bitsPerPixel = infoHeader.bitsPerPixel;
|
bitsPerPixel = infoHeader.bitsPerPixel;
|
||||||
|
|
||||||
// TODO: Support PNG compressed ICOs.
|
|
||||||
if (infoHeader.compression != 0) goto cleanup;
|
if (infoHeader.compression != 0) goto cleanup;
|
||||||
|
|
||||||
// Load the color palette, if one exists.
|
// Load the color palette, if one exists.
|
||||||
@ -2328,12 +2360,9 @@ read_ico(istream &ico) {
|
|||||||
ico.read(andBmp, andBmpSize);
|
ico.read(andBmp, andBmpSize);
|
||||||
if (!ico.good()) goto cleanup;
|
if (!ico.good()) goto cleanup;
|
||||||
|
|
||||||
// If this is an actual CUR not an ICO set up the hotspot properly.
|
|
||||||
image = XcursorImageCreate(infoHeader.width, infoHeader.height / 2);
|
image = XcursorImageCreate(infoHeader.width, infoHeader.height / 2);
|
||||||
if (header.type == 2) { image->xhot = entries[entry].xhot; image->yhot = entries[entry].yhot; }
|
|
||||||
|
|
||||||
// Support all the formats that GIMP supports, minus PNG compressed ICOs.
|
// Support all the formats that GIMP supports.
|
||||||
// Would need to use libpng to decode the compressed ones.
|
|
||||||
switch (bitsPerPixel) {
|
switch (bitsPerPixel) {
|
||||||
case 1:
|
case 1:
|
||||||
case 4:
|
case 4:
|
||||||
@ -2365,8 +2394,8 @@ read_ico(istream &ico) {
|
|||||||
curAnd++;
|
curAnd++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 24:
|
case 24:
|
||||||
// Pack each of the three bytes into a single color, BGR -> 0RGB
|
// Pack each of the three bytes into a single color, BGR -> 0RGB
|
||||||
for (i = image->height - 1; i >= 0; i--) {
|
for (i = image->height - 1; i >= 0; i--) {
|
||||||
@ -2386,10 +2415,9 @@ read_ico(istream &ico) {
|
|||||||
|
|
||||||
curAnd++;
|
curAnd++;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 32:
|
case 32:
|
||||||
// Pack each of the four bytes into a single color, BGRA -> ARGB
|
// Pack each of the four bytes into a single color, BGRA -> ARGB
|
||||||
for (i = image->height - 1; i >= 0; i--) {
|
for (i = image->height - 1; i >= 0; i--) {
|
||||||
@ -2401,11 +2429,20 @@ read_ico(istream &ico) {
|
|||||||
curXor += 4;
|
curXor += 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
break;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this is an actual CUR not an ICO set up the hotspot properly.
|
||||||
|
if (header.type == 2) {
|
||||||
|
image->xhot = entries[entry].xhot;
|
||||||
|
image->yhot = entries[entry].yhot;
|
||||||
|
} else {
|
||||||
|
image->xhot = 0;
|
||||||
|
image->yhot = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = XcursorImageLoadCursor(_display, image);
|
ret = XcursorImageLoadCursor(_display, image);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user