utils: Load Xcursor themes using QFile

This improves the integration of the XcursorTheme class with the rest of
the Qt ecosystem, for example it should be possible to load cursor themes
from Qt resources.
This commit is contained in:
Vlad Zahorodnii 2024-05-21 15:10:41 +03:00
parent d655b5a994
commit 586a775d5b
3 changed files with 38 additions and 56 deletions

View file

@ -180,14 +180,6 @@ typedef struct _XcursorComment {
#define XCURSOR_IMAGE_HEADER_LEN (XCURSOR_CHUNK_HEADER_LEN + (5*4))
#define XCURSOR_IMAGE_MAX_SIZE 0x7fff /* 32767x32767 max cursor size */
typedef struct _XcursorFile XcursorFile;
struct _XcursorFile {
void *closure;
int (*read) (XcursorFile *file, unsigned char *buf, int len);
int (*seek) (XcursorFile *file, long offset, int whence);
};
typedef struct _XcursorComments {
int ncomment; /* number of comments */
XcursorComment **comments; /* array of XcursorComment pointers */
@ -256,7 +248,7 @@ XcursorImagesDestroy (XcursorImages *images)
static XcursorBool
_XcursorReadUInt (XcursorFile *file, XcursorUInt *u)
{
unsigned char bytes[4];
uint8_t bytes[4];
if (!file || !u)
return XcursorFalse;
@ -318,7 +310,7 @@ _XcursorReadFileHeader (XcursorFile *file)
return NULL;
skip = head.header - XCURSOR_FILE_HEADER_LEN;
if (skip)
if ((*file->seek) (file, skip, SEEK_CUR) == EOF)
if (!(*file->skip) (file, skip))
return NULL;
fileHeader = _XcursorFileHeaderCreate (head.ntoc);
if (!fileHeader)
@ -349,10 +341,9 @@ _XcursorSeekToToc (XcursorFile *file,
XcursorFileHeader *fileHeader,
int toc)
{
if (!file || !fileHeader || \
(*file->seek) (file, fileHeader->tocs[toc].position, SEEK_SET) == EOF)
return XcursorFalse;
return XcursorTrue;
if (!file || !fileHeader)
return XcursorFalse;
return (*file->seek) (file, fileHeader->tocs[toc].position);
}
static XcursorBool
@ -498,7 +489,7 @@ _XcursorReadImage (XcursorFile *file,
return image;
}
static XcursorImages *
XcursorImages *
XcursorXcFileLoadImages (XcursorFile *file, int size)
{
XcursorFileHeader *fileHeader;
@ -544,42 +535,3 @@ XcursorXcFileLoadImages (XcursorFile *file, int size)
}
return images;
}
static int
_XcursorStdioFileRead (XcursorFile *file, unsigned char *buf, int len)
{
FILE *f = file->closure;
return fread (buf, 1, len, f);
}
static int
_XcursorStdioFileSeek (XcursorFile *file, long offset, int whence)
{
FILE *f = file->closure;
return fseek (f, offset, whence);
}
static void
_XcursorStdioFileInitialize (FILE *stdfile, XcursorFile *file)
{
file->closure = stdfile;
file->read = _XcursorStdioFileRead;
file->seek = _XcursorStdioFileSeek;
}
XcursorImages *
XcursorFileLoadImages (const char *file, int size)
{
XcursorFile f;
XcursorImages *images;
FILE *fp = fopen(file, "r");
if (!fp)
return NULL;
_XcursorStdioFileInitialize (fp, &f);
images = XcursorXcFileLoadImages (&f, size);
fclose(fp);
return images;
}

View file

@ -57,8 +57,17 @@ typedef struct _XcursorImages {
XcursorImage **images; /* array of XcursorImage pointers */
} XcursorImages;
typedef struct _XcursorFile XcursorFile;
struct _XcursorFile {
void *closure;
int (*read) (XcursorFile *file, uint8_t *buf, int len);
XcursorBool (*skip) (XcursorFile *file, long offset);
XcursorBool (*seek) (XcursorFile *file, long offset);
};
XcursorImages *
XcursorFileLoadImages (const char *file, int size);
XcursorXcFileLoadImages (XcursorFile *file, int size);
void
XcursorImagesDestroy (XcursorImages *images);

View file

@ -83,7 +83,28 @@ std::chrono::milliseconds KXcursorSprite::delay() const
static QList<KXcursorSprite> loadCursor(const QString &filePath, int desiredSize, qreal devicePixelRatio)
{
XcursorImages *images = XcursorFileLoadImages(QFile::encodeName(filePath), desiredSize * devicePixelRatio);
QFile file(filePath);
if (!file.open(QFile::ReadOnly)) {
return {};
}
XcursorFile reader {
.closure = &file,
.read = [](XcursorFile *file, uint8_t *buffer, int len) -> int {
QFile *device = static_cast<QFile *>(file->closure);
return device->read(reinterpret_cast<char *>(buffer), len);
},
.skip = [](XcursorFile *file, long offset) -> XcursorBool {
QFile *device = static_cast<QFile *>(file->closure);
return device->skip(offset) != -1;
},
.seek = [](XcursorFile *file, long offset) -> XcursorBool {
QFile *device = static_cast<QFile *>(file->closure);
return device->seek(offset);
},
};
XcursorImages *images = XcursorXcFileLoadImages(&reader, desiredSize * devicePixelRatio);
if (!images) {
return {};
}