/* * PCF font engine for Microwindows * Copyright (c) 2002, 2003 Greg Haerr * Copyright (c) 2001, 2002 by Century Embedded Technologies * * Supports dynamically loading .pcf and pcf.gz X11 fonts * * Written by Jordan Crouse * Bugfixed by Greg Haerr * Partly rewritten by Andreas Foedrowitz * * 28.01.2003: * Patch for big-endian-machines by Klaus Fuerth * 2006mar13: Andreas Foedrowitz * Partly rewritten to fix following bugs : * - bit order and byte order for bitmap had been lumped together * - byte order was permanently set to LSBfirst. Actually, byte order is bit in format * field, there's one format field per block * - the only place where byte order bit in format was used, it was wrong ! * see http://fontforge.sourceforge.net/pcf-format.html for more information */ #include #include #include #include #include "swap.h" #include "device.h" #include "devfont.h" #include "../drivers/genfont.h" #define HELLO printf("HELLO : %s:%d\n", __FILE__,__LINE__); //#define DPRINTF printf extern MWPIXELVAL gr_background; extern MWBOOL gr_usebg; /* The user hase the option including ZLIB and being able to */ /* directly read compressed .pcf files, or to omit it and save */ /* space. The following defines make life much easier */ #if HAVE_PCFGZ_SUPPORT #include #define FILEP gzFile #define FOPEN(path, mode) gzopen(path, mode) #define FREAD(file, buffer, size) gzread(file, buffer, size) #define FSEEK(file, offset, whence) gzseek(file, offset, whence) #define FCLOSE(file) gzclose(file) #else #define FILEP FILE * #define FOPEN(path, mode) fopen(path, mode) #define FREAD(file, buffer, size) fread(buffer, 1, size, file) #define FSEEK(file, offset, whence) fseek(file, offset, whence) #define FCLOSE(file) fclose(file) #endif /* Handling routines for PCF fonts, use MWCOREFONT structure */ static void pcf_unloadfont(PMWFONT font); /* these procs used when font ASCII indexed*/ static MWFONTPROCS pcf_fontprocs = { MWTF_ASCII, gen_getfontinfo, gen_gettextsize, gen_gettextbits, pcf_unloadfont, corefont_drawtext, NULL, /* setfontsize */ NULL, /* setfontrotation */ NULL, /* setfontattr */ }; /* these procs used when font requires UC16 index*/ static MWFONTPROCS pcf_fontprocs16 = { MWTF_UC16, /* routines expect unicode 16 */ gen_getfontinfo, gen16_gettextsize, gen_gettextbits, pcf_unloadfont, gen16_drawtext, NULL, /* setfontsize */ NULL, /* setfontrotation */ NULL, /* setfontattr */ NULL, /* duplicate not yet implemented */ }; /* These are maintained statically for ease FIXME*/ static struct toc_entry *toc; static unsigned long toc_size; /* Various definitions from the Free86 PCF code */ #define PCF_FILE_VERSION (('p'<<24)|('c'<<16)|('f'<<8)|1) #define PCF_PROPERTIES (1 << 0) #define PCF_ACCELERATORS (1 << 1) #define PCF_METRICS (1 << 2) #define PCF_BITMAPS (1 << 3) #define PCF_INK_METRICS (1 << 4) #define PCF_BDF_ENCODINGS (1 << 5) #define PCF_SWIDTHS (1 << 6) #define PCF_GLYPH_NAMES (1 << 7) #define PCF_BDF_ACCELERATORS (1 << 8) #define PCF_FORMAT_MASK 0xFFFFFF00 #define PCF_DEFAULT_FORMAT 0x00000000 #define PCF_INKBOUNDS 0x00000200 #define PCF_ACCEL_W_INKBOUNDS 0x00000100 #define PCF_COMPRESSED_METRICS 0x00000100 #define PCF_GLYPH_PAD_MASK (3<<0) #define PCF_BYTE_MASK (1<<2) #define PCF_BIT_MASK (1<<3) #define PCF_SCAN_UNIT_MASK (3<<4) #define PCF_SCAN_UNIT_RSHIFT 4 #define GLYPHPADOPTIONS 4 #define PCF_LSB_FIRST 0 #define PCF_MSB_FIRST 1 #define PCF_SCAN_UNIT_BYTE 0 #define PCF_SCAN_UNIT_SHORT 1 #define PCF_SCAN_UNIT_INT 2 /* A few structures that define the various fields within the file */ struct toc_entry { int type; int format; int size; int offset; }; struct prop_entry { unsigned int name; unsigned char is_string; unsigned int value; }; struct string_table { unsigned char *name; unsigned char *value; }; struct metric_entry { short leftBearing; short rightBearing; short width; short ascent; short descent; short attributes; }; struct encoding_entry { unsigned short min_byte2; /* min_char or min_byte2 */ unsigned short max_byte2; /* max_char or max_byte2 */ unsigned short min_byte1; /* min_byte1 (hi order) */ unsigned short max_byte1; /* max_byte1 (hi order) */ unsigned short defaultchar; unsigned long count; /* count of map entries */ unsigned short *map; /* font index -> glyph index */ }; /* This is used to quickly reverse the bits in a field */ static unsigned char _reverse_byte[0x100] = { 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff }; /*** Convert bitmap table. All bitmaps are in a contiguous table, the byte- and bit-order are declared in the "flags" field at the beginning of the block, read in read_bitmaps() before calling convert_bitmaps(). ***/ #if 0 static void convert_bitmaps(unsigned char *buf, int bufSize, int endian, int bitEndian, int pad, int scanUnit) { DPRINTF("convert_bitmaps(buf=%p, bufSize=%d, endian=%d, bitEndian=%d, pad=%d, scanUnit=%d)\n", buf, bufSize, endian, bitEndian, pad, scanUnit); /* byte endian is independent from bitEndian. All bitmaps in Nano-X are MSBit first */ /* convert bits first ... */ if (bitEndian != PCF_MSB_FIRST) { register unsigned char *ptr=buf; register unsigned char *end=buf + bufSize; while (ptr < end) { *ptr=(_reverse_byte[*ptr]); ++ptr; /* could be done as "*(ptr++)=(_reverse_byte[*ptr]);" but that issues a warning */ } } /* ... then convert bytes, if byte unit > 8 bits */ /* Foedrowitz 2006mar17 every source code I've seen so far (XWin, freetype) treats bitmaps data as UInt32. So will I ... */ scanUnit=PCF_SCAN_UNIT_INT; if (scanUnit != PCF_SCAN_UNIT_BYTE) { #ifdef MW_CPU_BIG_ENDIAN int swapD=(endian != PCF_MSB_FIRST); #else int swapD=(endian != PCF_LSB_FIRST); #endif printf("swapD=%d\n", swapD); swapD=0; if (swapD) { register unsigned char *ptr=buf; register unsigned char *end=buf + bufSize; register unsigned char d; if (scanUnit == PCF_SCAN_UNIT_SHORT) { while (ptr < end) { d=ptr[0]; ptr[0]=ptr[1]; ptr[1]=d; ptr += 2; } } else if (scanUnit == PCF_SCAN_UNIT_INT) { while (ptr < end) { d=ptr[0]; ptr[0]=ptr[3]; ptr[3]=d; d=ptr[1]; ptr[1]=ptr[2]; ptr[2]=d; ptr += 4; } } } } } #endif static void convert_bitmaps(unsigned char *buf, int bufSize, int endian, int bitEndian, int pad, int scanUnit) { DPRINTF("convert_bitmaps(buf=%p, bufSize=%d, endian=%d, bitEndian=%d, pad=%d, scanUnit=%d)\n", buf, bufSize, endian, bitEndian, pad, scanUnit); /* byte endian is independent from bitEndian. All bitmaps in Nano-X are MSBit first */ /* convert bits first ... */ if (bitEndian != PCF_MSB_FIRST) { register unsigned char *ptr=buf; register unsigned char *end=buf + bufSize; while (ptr < end) { *ptr=(_reverse_byte[*ptr]); ++ptr; /* could be done as "*(ptr++)=(_reverse_byte[*ptr]);" but that issues a warning */ } } /* ... then convert bytes, if byte unit > 8 bits */ /* Foedrowitz 2006mar17 every source code I've seen so far (XWin, freetype) treats bitmap data as UInt32. So will I ... */ #ifdef MW_CPU_BIG_ENDIAN #else { register unsigned char *ptr=buf; register unsigned char *end=buf + bufSize; register unsigned char d; { while (ptr < end) { d=ptr[0]; ptr[0]=ptr[1]; ptr[1]=d; ptr += 2; } } } #endif } /* read an 8 bit byte*/ static unsigned short readINT8(FILEP file) { unsigned char b; FREAD(file, &b, sizeof(b)); return b; } /* read a 16 bit short */ static unsigned short readINT16(FILEP file, int endian) { unsigned char buf[2]; FREAD(file, buf, sizeof(buf)); return (endian == PCF_LSB_FIRST) ? (buf[0] | (buf[1] << 8)) : (buf[1] | (buf[0] << 8)); } /* read a 32 bit long */ static unsigned long readINT32(FILEP file, int endian) { unsigned char buf[4]; FREAD(file, buf, sizeof(buf)); return (endian == PCF_LSB_FIRST) ? (buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24)) : (buf[3] | (buf[2] << 8) | (buf[1] << 16) | (buf[0] << 24)); } /* read a 32 bit long LSB first */ static unsigned long readLSB32(FILEP file) { return readINT32(file, PCF_LSB_FIRST); } /* Get the offset of the given field */ static int pcf_get_offset(int item) { int i; for (i = 0; i < toc_size; i++) if (item == toc[i].type) return toc[i].offset; return -1; } #if LATER /* Read the properties from the file */ static int pcf_readprops(FILEP file, struct prop_entry **prop, struct string_table **strings) { long offset; unsigned long format; unsigned long num_props; unsigned long ssize; unsigned long i; struct string_table *s; struct prop_entry *p; unsigned char *string_buffer, *spos; if ((offset = pcf_get_offset(PCF_PROPERTIES)) == -1) return (-1); FSEEK(file, offset, SEEK_SET); format = readLSB32(file); num_props = readLSB32(file); p = *prop = (struct prop_entry *) malloc(num_props * sizeof(struct prop_entry)); for (i = 0; i < num_props; i++) { p[i].name = readLSB32(file); p[i].is_string = readINT8(file); p[i].value = readLSB32(file); } /* Pad to 32 bit multiples */ if (num_props & 3) FSEEK(file, 4 - (num_props & 3), SEEK_CUR); /* Read the entire set of strings into memory */ ssize = readLSB32(file); spos = string_buffer = (unsigned char *) ALLOCA(ssize); FREAD(file, string_buffer, ssize); /* Allocate the group of strings */ s = *strings = (struct string_table *) ALLOCA(num_props * sizeof(struct string_table)); for (i = 0; i < num_props; i++) { s[i].name = (unsigned char *) strdup(spos); spos += strlen(s[i].name) + 1; if (p[i].is_string) { s[i].value = (unsigned char *) strdup(spos); spos += strlen(s[i].value) + 1; } else s[i].value = 0; } FREEA(string_buffer); return num_props; } #endif /* Read the actual bitmaps into memory */ static int pcf_readbitmaps(FILEP file, unsigned char **bits, int *bits_size, unsigned long **offsets) { long offset; unsigned long format; unsigned long num_glyphs; unsigned long pad; unsigned int i; int endian, bitEndian, scanUnit; /* format of block data */ unsigned long *o; unsigned char *b; unsigned long bmsize[GLYPHPADOPTIONS]; if ((offset = pcf_get_offset(PCF_BITMAPS)) == -1) return -1; FSEEK(file, offset, SEEK_SET); format = readLSB32(file); /* first UInt32 is always LSB first */ endian = (format & PCF_BYTE_MASK)? PCF_MSB_FIRST : PCF_LSB_FIRST; bitEndian=(format & PCF_BIT_MASK)? PCF_MSB_FIRST : PCF_LSB_FIRST; pad = format & PCF_GLYPH_PAD_MASK; scanUnit= (format & PCF_SCAN_UNIT_MASK) >> PCF_SCAN_UNIT_RSHIFT; DPRINTF("endian : %s\n", endian == PCF_LSB_FIRST ? "LSB" : "MSB"); num_glyphs = readINT32(file, endian); DPRINTF("numglyphs=%d\n", num_glyphs); o = *offsets = (unsigned long *)malloc(num_glyphs * sizeof(unsigned long)); for (i=0; i < num_glyphs; ++i) o[i] = readINT32(file, endian); for (i=0; i < GLYPHPADOPTIONS; ++i) { bmsize[i] = readINT32(file, endian); DPRINTF("bmsize[%d]=%d\n", i, bmsize[i]); } *bits_size = bmsize[pad]? bmsize[pad] : 1; DPRINTF("*pad=%d bits_size=%d\n", pad, *bits_size); /* alloc and read bitmap data*/ b = *bits = (unsigned char *) malloc(*bits_size); FREAD(file, b, *bits_size); /* convert bitmaps*/ convert_bitmaps(b, *bits_size, endian, bitEndian, pad, scanUnit); return num_glyphs; } /* read character metric data*/ static int pcf_readmetrics(FILE * file, struct metric_entry **metrics) { long i, size, offset; unsigned long format; int endian, compressed; struct metric_entry *m; if ((offset = pcf_get_offset(PCF_METRICS)) == -1) return -1; FSEEK(file, offset, SEEK_SET); format = readLSB32(file); /* first UInt32 is always LSB first */ endian = (format & PCF_BYTE_MASK)? PCF_MSB_FIRST : PCF_LSB_FIRST; compressed=((format & PCF_COMPRESSED_METRICS) != 0); if (compressed) { size = readINT16(file, endian); /* 16 bits - Number of metrics*/ m = *metrics = (struct metric_entry *) malloc(size * sizeof(struct metric_entry)); for (i = 0; i < size; i++) { m[i].leftBearing = readINT8(file) - 0x80; m[i].rightBearing = readINT8(file) - 0x80; m[i].width = readINT8(file) - 0x80; m[i].ascent = readINT8(file) - 0x80; m[i].descent = readINT8(file) - 0x80; } } else { size = readINT32(file, endian); /* 32 bits - Number of metrics*/ m = *metrics = (struct metric_entry *) malloc(size * sizeof(struct metric_entry)); for (i=0; i < size; i++) { m[i].leftBearing = readINT16(file, endian); m[i].rightBearing = readINT16(file, endian); m[i].width = readINT16(file, endian); m[i].ascent = readINT16(file, endian); m[i].descent = readINT16(file, endian); m[i].attributes = readINT16(file, endian); } } return size; } /* read encoding table*/ static int pcf_read_encoding(FILE * file, struct encoding_entry **encoding) { long offset, n; unsigned long format; int endian; struct encoding_entry *e; if ((offset = pcf_get_offset(PCF_BDF_ENCODINGS)) == -1) return -1; FSEEK(file, offset, SEEK_SET); format = readLSB32(file); /* first UInt32 is always LSB first */ endian = (format & PCF_BYTE_MASK)? PCF_MSB_FIRST : PCF_LSB_FIRST; e = *encoding = (struct encoding_entry *) malloc(sizeof(struct encoding_entry)); e->min_byte2 = readINT16(file, endian); e->max_byte2 = readINT16(file, endian); e->min_byte1 = readINT16(file, endian); e->max_byte1 = readINT16(file, endian); e->defaultchar = readINT16(file, endian); e->count = (e->max_byte2 - e->min_byte2 + 1) * (e->max_byte1 - e->min_byte1 + 1); e->map = (unsigned short *) malloc(e->count * sizeof(unsigned short)); DPRINTF("def char %d (%x)\n", e->defaultchar, e->defaultchar); for (n = 0; n < e->count; ++n) { e->map[n] = readINT16(file, endian); } DPRINTF("size %d byte1 %d,%d byte2 %d,%d\n", e->count, e->min_byte1, e->max_byte1, e->min_byte2, e->max_byte2); return e->count; } static int pcf_read_toc(FILE * file, struct toc_entry **toc, unsigned long *size) { /* all data within the TableOfContents block is LSB first */ long i; unsigned long version; struct toc_entry *t; FSEEK(file, 0, SEEK_SET); /* Verify the version */ version = readLSB32(file); if (version != PCF_FILE_VERSION) return -1; *size = readLSB32(file); t = *toc = (struct toc_entry *) calloc(sizeof(struct toc_entry), *size); if (!t) return -1; /* Read in the entire table of contents */ for (i=0; i<*size; ++i) { t[i].type = readLSB32(file); t[i].format = readLSB32(file); t[i].size = readLSB32(file); t[i].offset = readLSB32(file); } return 0; } PMWCOREFONT pcf_createfont(const char *name, MWCOORD height, int attr) { FILE *file = 0; MWCOREFONT *pf = 0; int offset; int i; int count; int bsize; int bwidth; int err = 0; struct metric_entry *metrics = 0; struct encoding_entry *encoding = 0; MWIMAGEBITS *output; unsigned char *glyphs = 0; unsigned long *glyphs_offsets = 0; int max_width = 0, max_descent = 0, max_ascent = 0, max_height = 0; int glyph_count; unsigned long *goffset = NULL; unsigned char *gwidth = NULL; int uc16; char fname[256]; /* Try to open the file */ DPRINTF("pcf_createfont : opening file %s\n", name); file = FOPEN(name, "rb"); if (!file) { strcpy(fname, PCF_FONT_DIR "/"); strcpy(fname + sizeof(PCF_FONT_DIR), name); DPRINTF("pcf_createfont : opening file %s\n", fname); file = FOPEN(fname, "rb"); } if (!file) return NULL; DPRINTF("pcf_createfont : file opened\n"); if (!(pf = (MWCOREFONT *) malloc(sizeof(MWCOREFONT)))) { err = -1; EPRINTF("error : %s:%d\n", __FILE__,__LINE__); goto leave_func; } if (!(pf->cfont = (PMWCFONT) calloc(sizeof(MWCFONT), 1))) { err = -1; EPRINTF("error : %s:%d\n", __FILE__,__LINE__); goto leave_func; } /* Read the table of contents */ if (pcf_read_toc(file, &toc, &toc_size) == -1) { err = -1; EPRINTF("error : %s:%d\n", __FILE__,__LINE__); goto leave_func; } /* Now, read in the bitmaps */ glyph_count = pcf_readbitmaps(file, &glyphs, &bsize, &glyphs_offsets); DPRINTF("glyph_count = %d (%x)\n", glyph_count, glyph_count); if (glyph_count == -1) { err = -1; EPRINTF("error : %s:%d\n", __FILE__,__LINE__); goto leave_func; } if (pcf_read_encoding(file, &encoding) == -1) { err = -1; EPRINTF("error : %s:%d\n", __FILE__,__LINE__); goto leave_func; } pf->cfont->firstchar = encoding->min_byte2 * (encoding->min_byte1 + 1); /* Read in the metrics */ count = pcf_readmetrics(file, &metrics); /* Calculate various maximum values */ for (i = 0; i < count; i++) { if (metrics[i].width > max_width) max_width = metrics[i].width; if (metrics[i].ascent > max_ascent) max_ascent = metrics[i].ascent; if (metrics[i].descent > max_descent) max_descent = metrics[i].descent; } max_height = max_ascent + max_descent; pf->cfont->maxwidth = max_width; pf->cfont->height = max_height; pf->cfont->ascent = max_ascent; /* Allocate enough room to hold all of the bits and the offsets */ bwidth = (max_width + 15) / 16; pf->cfont->bits = (MWIMAGEBITS *) calloc((max_height * (sizeof(MWIMAGEBITS) * bwidth)), glyph_count); goffset = (unsigned long *) malloc(glyph_count * sizeof(unsigned long)); gwidth = (unsigned char *) malloc(glyph_count * sizeof(unsigned char)); output = (MWIMAGEBITS *) pf->cfont->bits; offset = 0; /* copy and convert from packed BDF format to MWCFONT format*/ for (i = 0; i < glyph_count; i++) { int h, w; int y = max_height; unsigned long *ptr = (unsigned long *) (glyphs + glyphs_offsets[i]); /* # words image width*/ int lwidth = (metrics[i].width + 15) / 16; /* # words image width, corrected for bounding box problem*/ int xwidth = (metrics[i].rightBearing - metrics[i].leftBearing + 15) / 16; gwidth[i] = (unsigned char) metrics[i].width; goffset[i] = offset; offset += (lwidth * max_height); for (h = 0; h < (max_ascent - metrics[i].ascent); h++) { for (w = 0; w < lwidth; w++) *output++ = 0; y--; } for (h = 0; h < (metrics[i].ascent + metrics[i].descent); h++) { unsigned short *val = (unsigned short *) ptr; int bearing, carry_shift; unsigned short carry = 0; /* leftBearing correction*/ bearing = metrics[i].leftBearing; if (bearing < 0) /* negative bearing not handled yet*/ bearing = 0; carry_shift = 16 - bearing; for (w = 0; w < lwidth; w++) { *output++ = (val[w] >> bearing) | carry; carry = val[w] << carry_shift; } ptr += (xwidth + 1) / 2; y--; } for (; y > 0; y--) for (w = 0; w < lwidth; w++) *output++ = 0; } DPRINTF("size(offsets)=%d size(width)=%d\n", encoding->count * sizeof(unsigned long), encoding->count * sizeof(unsigned char)); /* reorder offsets and width according to encoding map */ pf->cfont->offset = (unsigned long *) malloc(encoding->count * sizeof(unsigned long)); pf->cfont->width = (unsigned char *) malloc(encoding->count * sizeof(unsigned char)); for (i = 0; i < encoding->count; ++i) { unsigned short n = encoding->map[i]; if (n >= glyph_count) /* Foedrowitz 2006mar17 map non-existent chars to default char */ n = encoding->map[encoding->defaultchar]; if (n >= glyph_count) /* Foedrowitz 2006mar17 still screwed up ==> reset to 0 */ n=0; ((unsigned long *)pf->cfont->offset)[i] = goffset[n]; ((unsigned char *)pf->cfont->width)[i] = gwidth[n]; } pf->cfont->size = encoding->count; uc16 = pf->cfont->firstchar > 255 || (pf->cfont->firstchar + pf->cfont->size) > 255; pf->fontprocs = uc16? &pcf_fontprocs16: &pcf_fontprocs; pf->fontsize = pf->fontrotation = pf->fontattr = 0; pf->name = "PCF"; leave_func: if (goffset) free(goffset); if (gwidth) free(gwidth); if (encoding) { if (encoding->map) free(encoding->map); free(encoding); } if (metrics) free(metrics); if (glyphs) free(glyphs); if (glyphs_offsets) free(glyphs_offsets); if (toc) free(toc); toc = 0; toc_size = 0; if (file) FCLOSE(file); if (err == 0 && pf) return pf; pcf_unloadfont((PMWFONT)pf); return 0; } void pcf_unloadfont(PMWFONT font) { PMWCOREFONT pf = (PMWCOREFONT) font; PMWCFONT pfc = pf->cfont; if (pfc) { if (pfc->width) free((char *)pf->cfont->width); if (pfc->offset) free((char *)pf->cfont->offset); if (pfc->bits) free((char *)pf->cfont->bits); free(pf->cfont); } free(font); }