* Tue Nov 26 2002 Adrian Havill - re-write font loader so it can load uncompressed or gzipped files --- bogl-0.1.18/bterm.c.gzip-fonts 2006-11-05 15:59:28.000000000 +0100 +++ bogl-0.1.18/bterm.c 2006-11-05 15:59:28.000000000 +0100 @@ -186,7 +186,7 @@ { struct bogl_font *font; - font = bogl_mmap_font (font_name); + font = bogl_load_font (font_name); if (font == NULL) { fprintf(stderr, "Bad font\n"); @@ -260,7 +260,7 @@ return 1; } - if ((font = bogl_mmap_font(font_name)) == NULL) { + if ((font = bogl_load_font(font_name)) == NULL) { fprintf(stderr, "Bad font\n"); return 1; } --- bogl-0.1.18/bogl-bgf.c.gzip-fonts 2001-12-01 18:04:42.000000000 +0100 +++ bogl-0.1.18/bogl-bgf.c 2006-11-05 15:59:28.000000000 +0100 @@ -1,44 +1,130 @@ -#include +#include +#include +#include +#include #include -#include -#include -#include -#include +#include +#include +#include "bogl-bgf.h" #include "bogl.h" -#include "bogl-font.h" -struct bogl_font *bogl_mmap_font(char *file) -{ - int fd; - struct stat buf; - void *f; - struct bogl_font *font; - - fd = open(file, O_RDONLY); - if (fd == -1) - return 0; - - if (fstat(fd, &buf)) - return 0; - - f = mmap(0, buf.st_size, PROT_READ, MAP_SHARED, fd, 0); - if (f == (void *)-1) - return 0; - - if (memcmp("BGF1", f, 4)) - return 0; - - font = (struct bogl_font *)malloc(sizeof(struct bogl_font)); - if (!font) - return 0; - - memcpy(font, f + 4, sizeof(*font)); - font->name = ((void *)font->name - (void *)0) + f; - font->offset = ((void *)font->offset - (void *)0) + f; - font->index = ((void *)font->index - (void *)0) + f; - font->content = ((void *)font->content - (void *)0) + f; +#define FONT_SIGNATURE "BGF1" - return font; +static size_t get_gz_file_size(const char *path) { + size_t size = 0; + unsigned char buffer[4] = { 0 }; + FILE *stream = NULL; + + stream = fopen(path, "rb"); + if (stream == NULL) { + perror(path); + return -1; + } + if (fread(buffer, sizeof(char), 2, stream) != 2) { + if (ferror(stream)) { + perror(path); + return -1; + } + } + if (memcmp(buffer, "\037\213", 2) == 0) { + uint32_t isize = 0; + + if (fseek(stream, -4L, SEEK_END) == EOF) { + perror(path); + return -1; + } + if (fread(buffer, sizeof(char), (size_t) 4, stream) != 4) { + if (ferror(stream)) { + perror(path); + return -1; + } + else { + fprintf(stderr, "%s: invalid gzip file\n", path); + return -1; + } + } + isize = buffer[0]; + isize |= buffer[1] << 8; + isize |= buffer[2] << 16; + isize |= buffer[3] << 24; + + /* FIXME: ISIZE is not a reliable indicator of size for files >4GB. + * On the other hand, if you have a font >4GB, you've got issues. + */ + size = (size_t) isize; + } + else { + if (fseek(stream, 0L, SEEK_END) == EOF) { + perror(path); + return -1; + } + if ((int) (size = (size_t) ftell(stream)) == EOF) { + perror(path); + return -1; + } + } + if (fclose(stream) == EOF) { + perror(path); + return -1; + } + return size; +} + +struct bogl_font *bogl_load_font(const char *path) { + size_t size; + int errnum; + gzFile file; + void *bgf; + struct bogl_font *font; + + size = (size_t) get_gz_file_size(path); + if (size == (size_t) -1) + return NULL; + if ((bgf = malloc(size)) == NULL) { + perror(path); + return NULL; + } + file = gzopen(path, "rb"); + if (file == NULL) { + if (errno == 0) { + errno = ENOMEM; // if 0 then zlib error == Z_MEM_ERROR + } + perror(path); + return NULL; + } + if (gzread(file, bgf, size) == -1) { + const char *msg = gzerror(file, &errnum); + + if (errnum == Z_ERRNO) { + msg = strerror(errno); + } + fprintf(stderr, "%s: %s\n", path, msg); + return NULL; + } + if (gzclose(file) < 0) { + const char *msg = gzerror(file, &errnum); + + if (errnum == Z_ERRNO) { + msg = strerror(errno); + } + fprintf(stderr, "%s: %s\n", path, msg); + return NULL; + } + if (memcmp(FONT_SIGNATURE, bgf, strlen(FONT_SIGNATURE)) != 0) { + fprintf(stderr, "%s: not a BGF font\n", path); + return NULL; + } + font = (struct bogl_font *) malloc(sizeof(struct bogl_font)); + if (font == NULL) { + perror(path); + return NULL; + } + memcpy(font, bgf + strlen(FONT_SIGNATURE), sizeof(struct bogl_font)); + font->name = bgf + (ptrdiff_t) font->name; + font->offset = bgf + (ptrdiff_t) font->offset; + font->index = bgf + (ptrdiff_t) font->index; + font->content = bgf + (ptrdiff_t) font->content; + return font; } --- bogl-0.1.18/bogl-bgf.h.gzip-fonts 2001-12-01 18:04:42.000000000 +0100 +++ bogl-0.1.18/bogl-bgf.h 2006-11-05 15:59:28.000000000 +0100 @@ -1,2 +1,2 @@ -struct bogl_font *bogl_mmap_font(char *file); +struct bogl_font *bogl_load_font(const char *file); --- bogl-0.1.18/Makefile.gzip-fonts 2006-11-05 15:59:44.000000000 +0100 +++ bogl-0.1.18/Makefile 2006-11-05 15:59:57.000000000 +0100 @@ -79,7 +79,7 @@ $(CC) -DSTANDALONE_TEST $(ALLCFLAGS) bowl-boxes.c $(LIBOBJECTS) -o bowl-boxes bterm: $(LIB) bterm.o bogl-term.o bogl-bgf.o - $(CC) $+ $(LIB) -o bterm + $(CC) $+ $(LIB) -lz -o bterm bdftobogl: $(LIBBOGLOBJECTS) %.c: %.bdf bdftobogl