unsigned short frames, leadin;
unsigned short palstart, palcount;
- FILE *f;
- long foff, paloff;
+ const struct lbx_file_ops *fops;
+ int (*dtor)(void *handle);
+ void *f;
+
+ long paloff;
int currentframe;
int currentx, currenty;
return img;
}
-struct lbx_image *lbximg_fopen(FILE *f)
+struct lbx_image *lbximg_open(void *f, const struct lbx_file_ops *fops,
+ int (*destructor)(void *))
{
unsigned char hdr_buf[HDR_LEN];
struct lbx_image *img;
- size_t rc;
- if (fread(hdr_buf, 1, sizeof hdr_buf, f) != sizeof hdr_buf) {
+ if (fops->read(hdr_buf, sizeof hdr_buf, f) != sizeof hdr_buf) {
lbx_errno = -errno;
- if (feof(f))
+ if (fops->eof(f))
lbx_errno = LBX_EEOF;
return NULL;
}
return NULL;
img->f = f;
- img->foff = sizeof hdr_buf;
+ img->fops = fops;
+ img->dtor = destructor;
/*
* DEBUG ONLY. These assertions exist to catch otherwise valid image
for (unsigned i = 0; i <= img->frames; i++) {
unsigned char buf[4];
- if (fread(buf, 1, sizeof buf, f) != sizeof buf) {
+ if (fops->read(buf, sizeof buf, f) != sizeof buf) {
lbx_errno = -errno;
- if (feof(f))
+ if (fops->eof(f))
lbx_errno = LBX_EEOF;
free(img);
return NULL;
}
img->offsets[i] = unpack_32_le(buf);
- img->foff += 4;
}
if (img->flags & FLAG_PALETTE) {
unsigned char buf[4];
- if (fread(buf, 1, sizeof buf, f) != sizeof buf) {
+ if (fops->read(buf, sizeof buf, f) != sizeof buf) {
lbx_errno = -errno;
- if (feof(f))
+ if (fops->eof(f))
lbx_errno = LBX_EEOF;
free(img);
return NULL;
img->palstart = unpack_16_le(buf+0);
img->palcount = unpack_16_le(buf+2);
- img->foff += sizeof buf;
- img->paloff = img->foff;
+ img->paloff = fops->tell(f);
if (img->palstart + img->palcount > 256) {
lbx_errno = LBX_EFORMAT;
return img;
}
+struct lbx_image *lbximg_fopen(FILE *f)
+{
+ return lbximg_open(f, &lbx_default_fops, NULL);
+}
+
static int _lbx_drawrow(int first, struct lbx_image *img)
{
unsigned short type, count, yval, xval;
assert(img->framedata);
assert(img->mask);
- if (fread(buf, 1, sizeof buf, img->f) != sizeof buf)
+ if (img->fops->read(buf, sizeof buf, img->f) != sizeof buf)
goto readerr;
- img->foff += 4;
type = unpack_16_le(buf+0);
if (first) {
if (yval == 1000)
return 1;
- if (fread(buf, 1, sizeof buf, img->f) != sizeof buf)
+ if (img->fops->read(buf, sizeof buf, img->f) != sizeof buf)
goto readerr;
- img->foff += 4;
count = unpack_16_le(buf+0);
xval = unpack_16_le(buf+2);
memset(&img->mask[img->currenty][img->currentx], 1, count);
pos = &img->framedata[img->currenty][img->currentx];
- rc = fread(pos, 1, count, img->f);
+ rc = img->fops->read(pos, count, img->f);
img->currentx += rc;
- img->foff += rc;
if (rc < count)
goto readerr;
if (count % 2) {
- if (fread(buf, 1, 1, img->f) != 1)
+ if (img->fops->read(buf, 1, img->f) != 1)
goto readerr;
- img->foff += 1;
}
return 0;
readerr:
- if (feof(img->f)) {
+ lbx_errno = -errno;
+ if (img->fops->eof(img->f))
lbx_errno = LBX_EEOF;
- } else {
- lbx_errno = -errno;
- }
return -1;
}
if (img->currentframe != frame) {
int rc, first = 1;
- if (_lbx_fseek(img->f, &img->foff, img->offsets[frame]) == -1)
+ if (img->fops->seek(img->f, img->offsets[frame], SEEK_SET)) {
+ lbx_errno = -errno;
return NULL;
+ }
do {
rc = _lbx_drawrow(first, img);
return NULL;
first = 0;
- if (!rc && img->foff > img->offsets[frame+1]) {
+ if (img->fops->tell(img->f) > img->offsets[frame+1]) {
lbx_errno = LBX_EFORMAT;
return NULL;
}
if (!(img->flags & FLAG_PALETTE))
return 0;
- if (_lbx_fseek(img->f, &img->foff, img->paloff) == -1)
+ if (img->fops->seek(img->f, img->paloff, SEEK_SET)) {
+ lbx_errno = -errno;
return -1;
+ }
for (i = 0; i < img->palcount; i++) {
- rc = fread(entry, 1, sizeof entry, img->f);
- img->foff += rc;
+ rc = img->fops->read(entry, sizeof entry, img->f);
if (rc < sizeof entry) {
goto readerr;
return 0;
readerr:
- lbx_errno = feof(img->f) ? LBX_EEOF : -errno;
+ lbx_errno = img->fops->eof(img->f) ? LBX_EEOF : -errno;
return -1;
}
return img->mask;
}
-void lbximg_close(struct lbx_image *img)
+int lbximg_close(struct lbx_image *img)
{
- if (!img) return;
+ int rc = 0;
- if (img->framedata) {
- free(img->framedata[0]);
- free(img->framedata);
- }
+ if (img) {
+ if (img->framedata) {
+ free(img->framedata[0]);
+ free(img->framedata);
+ }
- if (img->mask) {
- free(img->mask[0]);
- free(img->mask);
- }
+ if (img->mask) {
+ free(img->mask[0]);
+ free(img->mask);
+ }
+
+ if (img && img->dtor) {
+ rc = img->dtor(img->f);
+ }
- if (img->f) {
- fclose(img->f);
+ free(img);
}
- free(img);
+ return rc;
}