/** ** fdv_win.c -- driver for Windows resource font file format ** ** Copyright (C) 2003 Dimitar Zhekov ** [e-mail: jimmy@is-vn.bg] ** ** This file is part of the GRX graphics library. ** ** The GRX graphics library is free software; you can redistribute it ** and/or modify it under some conditions; see the "copying.grx" file ** for details. ** ** This library is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ** **/ #include #include #include #include #include "libgrx.h" #include "grfontdv.h" #include "arith.h" #include "allocate.h" #include "fonts/fdv_win.h" #ifndef SEEK_SET #define SEEK_SET 0 #endif static FILE *fontfp = NULL; static int offset = 0; static GrResourceFileHeaderWIN rhdr; static GrFontFileHeaderWIN fhdr; static GrCharHeaderWIN *ctable = NULL; #if BYTE_ORDER==BIG_ENDIAN #include "ordswap.h" static void swap_resource(void) { GRX_ENTER(); _GR_swap16u(&rhdr.type_id); _GR_swap16u(&rhdr.name_id); _GR_swap16u(&rhdr.flags); _GR_swap32u(&rhdr.size); GRX_LEAVE(); } static void swap_header(void) { GRX_ENTER(); _GR_swap16u(&fhdr.version); _GR_swap32u(&fhdr.size); _GR_swap16u(&fhdr.type); _GR_swap16u(&fhdr.points); _GR_swap16u(&fhdr.vert_res); _GR_swap16u(&fhdr.horiz_res); _GR_swap16u(&fhdr.ascent); _GR_swap16u(&fhdr.internal_leading); _GR_swap16u(&fhdr.external_leading); _GR_swap16u(&fhdr.weight); _GR_swap16u(&fhdr.pix_width); _GR_swap16u(&fhdr.pix_height); _GR_swap16u(&fhdr.avg_width); _GR_swap16u(&fhdr.max_width); _GR_swap16u(&fhdr.width_bytes); _GR_swap32u(&fhdr.device); _GR_swap32u(&fhdr.face); _GR_swap32u(&fhdr.bits_pointer); _GR_swap32u(&fhdr.bits_offset); GRX_LEAVE(); } static void swap_ctable(void) { int i; GRX_ENTER(); for(i = 0; i < fhdr.last_char - fhdr.first_char + 2; i++) { _GR_swap16u(&ctable[i].width); _GR_swap16u(&ctable[i].offset); } GRX_LEAVE(); } #endif static void cleanup(void) { GRX_ENTER(); if(fontfp != NULL) fclose(fontfp); if(ctable != NULL) farfree(ctable); fontfp = NULL; ctable = NULL; offset = 0; GRX_LEAVE(); } static int openfile(char *fname) { int res; unsigned size; GRX_ENTER(); res = FALSE; cleanup(); /* open and test the file */ fontfp = fopen(fname, "rb"); if(fontfp == NULL) { DBGPRINTF(DBG_FONT, ("fopen(\"%s\") failed\n", fname)); goto done; } if(fread(&rhdr, 1, sizeof rhdr, fontfp) != sizeof rhdr) { DBGPRINTF(DBG_FONT, ("read resource failed\n", fname)); goto done; } if(rhdr.type_ff == 0xFF) { #if BYTE_ORDER==BIG_ENDIAN DBGPRINTF(DBG_FONT, ("swapping resource byte order\n")); swap_resource(); #endif if(rhdr.type_id != 0x0008 || rhdr.name_ff != 0xFF) { DBGPRINTF(DBG_FONT, ("invalid or unsupported resource header\n")); goto done; } offset = sizeof rhdr; } else if(fseek(fontfp, 0, SEEK_SET < 0)) { DBGPRINTF(DBG_FONT, ("rewind failed")); goto done; } if(fread(&fhdr, 1, sizeof fhdr, fontfp) != sizeof fhdr) { DBGPRINTF(DBG_FONT, ("read header failed\n")); goto done; } #if BYTE_ORDER==BIG_ENDIAN DBGPRINTF(DBG_FONT, ("swapping header byte order\n")); swap_header(); #endif if(fhdr.version != 0x0200 || fhdr.type != 0) { DBGPRINTF(DBG_FONT, ("unrecognized font header\n")); goto done; } /* allocate and read the ctable */ size = (fhdr.last_char - fhdr.first_char + 2) * sizeof *ctable; if((ctable = farmalloc(size)) == NULL) { DBGPRINTF(DBG_FONT, ("allocate ctable failed\n")); goto done; } if(fread(ctable, 1, size, fontfp) != size) { DBGPRINTF(DBG_FONT, ("read ctable failed\n")); goto done; } #if BYTE_ORDER==BIG_ENDIAN DBGPRINTF(DBG_FONT, ("swapping ctable byte order\n")); swap_ctable(); #endif res = TRUE; done: if(!res) cleanup(); GRX_RETURN(res); } static char *families[] = { "Unknown", "Roman", "Swiss", "Modern", "Script", "Decorative" }; static int header(GrFontHeader *hdr) { int res; int c; char *s; GRX_ENTER(); res = FALSE; if(fontfp != NULL) { if((c = fhdr.pitch_and_family >> 4) <= 5) strcpy(hdr->family, families[c]); else sprintf(hdr->family, "0x%x", fhdr.pitch_and_family); if(fhdr.face) { s = hdr->name; if(fseek(fontfp, offset + fhdr.face, SEEK_SET) < 0) goto done; do { if((c = fgetc(fontfp)) == EOF) goto done; *(s++) = c; } while(c && s - hdr->name < 99); if(c) *s = '\0'; } else sprintf(hdr->name, "%s-%d", hdr->family, fhdr.pix_height); hdr->proportional = fhdr.pix_width == 0; hdr->scalable = FALSE; hdr->preloaded = FALSE; hdr->modified = GR_FONTCVT_NONE; hdr->width = hdr->proportional ? fhdr.avg_width : fhdr.pix_width; hdr->height = fhdr.pix_height; hdr->baseline = fhdr.ascent; hdr->ulheight = imax(1, hdr->height / 15); hdr->ulpos = hdr->height - hdr->ulheight; hdr->minchar = fhdr.first_char; hdr->numchars = fhdr.last_char - fhdr.first_char + 1; hdr->encoding = 0; /* GR_FONTENC_UNKNOWN */ res = TRUE; } done: GRX_RETURN(res); } static int charwdt(int chr) { int res; GRX_ENTER(); res = -1; if(fontfp != NULL && chr >= fhdr.first_char && chr <= fhdr.last_char) res = ctable[chr - fhdr.first_char].width; GRX_RETURN(res); } static int bitmap(int chr, int w, int h, char *buffer) { int res; int i, y; int bytes; GRX_ENTER(); res = FALSE; if(w != charwdt(chr) || h != fhdr.pix_height) goto done; bytes = (w - 1) / 8 + 1; if(fseek(fontfp, offset + ctable[chr - fhdr.first_char].offset, SEEK_SET) < 0) goto done; for(i = 0; i < bytes; i++) for(y = 0; y < h; y++) if(fread(buffer + bytes * y + i, 1, 1, fontfp) != 1) goto done; res = TRUE; done: GRX_RETURN(res); } GrFontDriver _GrFontDriverWIN = { "WIN", /* driver name (doc only) */ ".res", /* font file extension */ FALSE, /* scalable */ openfile, /* file open and check routine */ header, /* font header reader routine */ charwdt, /* character width reader routine */ bitmap, /* character bitmap reader routine */ cleanup /* cleanup routine */ };