pcfread.c revision 4b1cd807
123a0898aSmrg/* 223a0898aSmrg 323a0898aSmrgCopyright 1990, 1998 The Open Group 423a0898aSmrg 523a0898aSmrgPermission to use, copy, modify, distribute, and sell this software and its 623a0898aSmrgdocumentation for any purpose is hereby granted without fee, provided that 723a0898aSmrgthe above copyright notice appear in all copies and that both that 823a0898aSmrgcopyright notice and this permission notice appear in supporting 923a0898aSmrgdocumentation. 1023a0898aSmrg 1123a0898aSmrgThe above copyright notice and this permission notice shall be included 1223a0898aSmrgin all copies or substantial portions of the Software. 1323a0898aSmrg 1423a0898aSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 1523a0898aSmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 1623a0898aSmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 1723a0898aSmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 1823a0898aSmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 1923a0898aSmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 2023a0898aSmrgOTHER DEALINGS IN THE SOFTWARE. 2123a0898aSmrg 2223a0898aSmrgExcept as contained in this notice, the name of The Open Group shall 2323a0898aSmrgnot be used in advertising or otherwise to promote the sale, use or 2423a0898aSmrgother dealings in this Software without prior written authorization 2523a0898aSmrgfrom The Open Group. 2623a0898aSmrg 2723a0898aSmrg*/ 2823a0898aSmrg/* $XFree86: xc/lib/font/bitmap/pcfread.c,v 1.21 2003/11/17 22:20:22 dawes Exp $ */ 2923a0898aSmrg 3023a0898aSmrg/* 3123a0898aSmrg * Author: Keith Packard, MIT X Consortium 3223a0898aSmrg */ 3323a0898aSmrg 3423a0898aSmrg#ifdef HAVE_CONFIG_H 3523a0898aSmrg#include <config.h> 3623a0898aSmrg#endif 3723a0898aSmrg 3823a0898aSmrg#include <X11/fonts/fntfilst.h> 3923a0898aSmrg#include <X11/fonts/bitmap.h> 4023a0898aSmrg#include <X11/fonts/pcf.h> 4123a0898aSmrg 4223a0898aSmrg#ifndef MAX 4323a0898aSmrg#define MAX(a,b) (((a)>(b)) ? a : b) 4423a0898aSmrg#endif 4523a0898aSmrg 4623a0898aSmrg#include <stdarg.h> 4723a0898aSmrg#include <stdint.h> 4823a0898aSmrg 4923a0898aSmrgvoid 5023a0898aSmrgpcfError(const char* message, ...) 5123a0898aSmrg{ 5223a0898aSmrg va_list args; 5323a0898aSmrg 5423a0898aSmrg va_start(args, message); 5523a0898aSmrg 5623a0898aSmrg fprintf(stderr, "PCF Error: "); 5723a0898aSmrg vfprintf(stderr, message, args); 5823a0898aSmrg va_end(args); 5923a0898aSmrg} 6023a0898aSmrg 6123a0898aSmrg/* Read PCF font files */ 6223a0898aSmrg 6323a0898aSmrgstatic void pcfUnloadFont ( FontPtr pFont ); 6423a0898aSmrgstatic int position; 6523a0898aSmrg 6623a0898aSmrg 6723a0898aSmrg#define IS_EOF(file) ((file)->eof == BUFFILEEOF) 6823a0898aSmrg 6923a0898aSmrg#define FONT_FILE_GETC_ERR(f) (tmp = FontFileGetc(f), BAIL_ON_EOF) 7023a0898aSmrg 7123a0898aSmrgstatic int 7223a0898aSmrgpcfGetLSB32(FontFilePtr file) 7323a0898aSmrg{ 7423a0898aSmrg int c; 7523a0898aSmrg 7623a0898aSmrg c = FontFileGetc(file); 7723a0898aSmrg c |= FontFileGetc(file) << 8; 7823a0898aSmrg c |= FontFileGetc(file) << 16; 7923a0898aSmrg c |= FontFileGetc(file) << 24; 8023a0898aSmrg position += 4; 8123a0898aSmrg return c; 8223a0898aSmrg} 8323a0898aSmrg 8423a0898aSmrgstatic int 8523a0898aSmrgpcfGetINT32(FontFilePtr file, CARD32 format) 8623a0898aSmrg{ 8723a0898aSmrg int c; 8823a0898aSmrg 8923a0898aSmrg if (PCF_BYTE_ORDER(format) == MSBFirst) { 9023a0898aSmrg c = FontFileGetc(file) << 24; 9123a0898aSmrg c |= FontFileGetc(file) << 16; 9223a0898aSmrg c |= FontFileGetc(file) << 8; 9323a0898aSmrg c |= FontFileGetc(file); 9423a0898aSmrg } else { 9523a0898aSmrg c = FontFileGetc(file); 9623a0898aSmrg c |= FontFileGetc(file) << 8; 9723a0898aSmrg c |= FontFileGetc(file) << 16; 9823a0898aSmrg c |= FontFileGetc(file) << 24; 9923a0898aSmrg } 10023a0898aSmrg position += 4; 10123a0898aSmrg return c; 10223a0898aSmrg} 10323a0898aSmrg 10423a0898aSmrgstatic int 10523a0898aSmrgpcfGetINT16(FontFilePtr file, CARD32 format) 10623a0898aSmrg{ 10723a0898aSmrg int c; 10823a0898aSmrg 10923a0898aSmrg if (PCF_BYTE_ORDER(format) == MSBFirst) { 11023a0898aSmrg c = FontFileGetc(file) << 8; 11123a0898aSmrg c |= FontFileGetc(file); 11223a0898aSmrg } else { 11323a0898aSmrg c = FontFileGetc(file); 11423a0898aSmrg c |= FontFileGetc(file) << 8; 11523a0898aSmrg } 11623a0898aSmrg position += 2; 11723a0898aSmrg return c; 11823a0898aSmrg} 11923a0898aSmrg 12023a0898aSmrg#define pcfGetINT8(file, format) (position++, FontFileGetc(file)) 12123a0898aSmrg 12223a0898aSmrgstatic PCFTablePtr 12323a0898aSmrgpcfReadTOC(FontFilePtr file, int *countp) 12423a0898aSmrg{ 12523a0898aSmrg CARD32 version; 12623a0898aSmrg PCFTablePtr tables; 12723a0898aSmrg int count; 12823a0898aSmrg int i; 12923a0898aSmrg 13023a0898aSmrg position = 0; 13123a0898aSmrg version = pcfGetLSB32(file); 13223a0898aSmrg if (version != PCF_FILE_VERSION) 13323a0898aSmrg return (PCFTablePtr) NULL; 13423a0898aSmrg count = pcfGetLSB32(file); 13523a0898aSmrg if (IS_EOF(file)) return (PCFTablePtr) NULL; 13623a0898aSmrg if (count < 0 || count > INT32_MAX / sizeof(PCFTableRec)) { 13723a0898aSmrg pcfError("pcfReadTOC(): invalid file format\n"); 13823a0898aSmrg return NULL; 13923a0898aSmrg } 1407f7f5e4eSmrg tables = malloc(count * sizeof(PCFTableRec)); 14123a0898aSmrg if (!tables) { 14223a0898aSmrg pcfError("pcfReadTOC(): Couldn't allocate tables (%d*%d)\n", count, sizeof(PCFTableRec)); 14323a0898aSmrg return (PCFTablePtr) NULL; 14423a0898aSmrg } 14523a0898aSmrg for (i = 0; i < count; i++) { 14623a0898aSmrg tables[i].type = pcfGetLSB32(file); 14723a0898aSmrg tables[i].format = pcfGetLSB32(file); 14823a0898aSmrg tables[i].size = pcfGetLSB32(file); 14923a0898aSmrg tables[i].offset = pcfGetLSB32(file); 15023a0898aSmrg if (IS_EOF(file)) goto Bail; 15123a0898aSmrg } 15223a0898aSmrg 15323a0898aSmrg *countp = count; 15423a0898aSmrg return tables; 15523a0898aSmrg 15623a0898aSmrg Bail: 1577f7f5e4eSmrg free(tables); 15823a0898aSmrg return (PCFTablePtr) NULL; 15923a0898aSmrg} 16023a0898aSmrg 16123a0898aSmrg/* 16223a0898aSmrg * PCF supports two formats for metrics, both the regular 16323a0898aSmrg * jumbo size, and 'lite' metrics, which are useful 16423a0898aSmrg * for most fonts which have even vaguely reasonable 16523a0898aSmrg * metrics 16623a0898aSmrg */ 16723a0898aSmrg 16823a0898aSmrgstatic Bool 16923a0898aSmrgpcfGetMetric(FontFilePtr file, CARD32 format, xCharInfo *metric) 17023a0898aSmrg{ 17123a0898aSmrg metric->leftSideBearing = pcfGetINT16(file, format); 17223a0898aSmrg metric->rightSideBearing = pcfGetINT16(file, format); 17323a0898aSmrg metric->characterWidth = pcfGetINT16(file, format); 17423a0898aSmrg metric->ascent = pcfGetINT16(file, format); 17523a0898aSmrg metric->descent = pcfGetINT16(file, format); 17623a0898aSmrg metric->attributes = pcfGetINT16(file, format); 17723a0898aSmrg if (IS_EOF(file)) return FALSE; 17823a0898aSmrg 17923a0898aSmrg return TRUE; 18023a0898aSmrg} 18123a0898aSmrg 18223a0898aSmrgstatic Bool 18323a0898aSmrgpcfGetCompressedMetric(FontFilePtr file, CARD32 format, xCharInfo *metric) 18423a0898aSmrg{ 18523a0898aSmrg metric->leftSideBearing = pcfGetINT8(file, format) - 0x80; 18623a0898aSmrg metric->rightSideBearing = pcfGetINT8(file, format) - 0x80; 18723a0898aSmrg metric->characterWidth = pcfGetINT8(file, format) - 0x80; 18823a0898aSmrg metric->ascent = pcfGetINT8(file, format) - 0x80; 18923a0898aSmrg metric->descent = pcfGetINT8(file, format) - 0x80; 19023a0898aSmrg metric->attributes = 0; 19123a0898aSmrg if (IS_EOF(file)) return FALSE; 19223a0898aSmrg 19323a0898aSmrg return TRUE; 19423a0898aSmrg} 19523a0898aSmrg 19623a0898aSmrg/* 19723a0898aSmrg * Position the file to the begining of the specified table 19823a0898aSmrg * in the font file 19923a0898aSmrg */ 20023a0898aSmrgstatic Bool 20123a0898aSmrgpcfSeekToType(FontFilePtr file, PCFTablePtr tables, int ntables, 20223a0898aSmrg CARD32 type, CARD32 *formatp, CARD32 *sizep) 20323a0898aSmrg{ 20423a0898aSmrg int i; 20523a0898aSmrg 20623a0898aSmrg for (i = 0; i < ntables; i++) 20723a0898aSmrg if (tables[i].type == type) { 20823a0898aSmrg if (position > tables[i].offset) 20923a0898aSmrg return FALSE; 21023a0898aSmrg if (!FontFileSkip(file, tables[i].offset - position)) 21123a0898aSmrg return FALSE; 21223a0898aSmrg position = tables[i].offset; 21323a0898aSmrg *sizep = tables[i].size; 21423a0898aSmrg *formatp = tables[i].format; 21523a0898aSmrg return TRUE; 21623a0898aSmrg } 21723a0898aSmrg return FALSE; 21823a0898aSmrg} 21923a0898aSmrg 22023a0898aSmrgstatic Bool 22123a0898aSmrgpcfHasType (PCFTablePtr tables, int ntables, CARD32 type) 22223a0898aSmrg{ 22323a0898aSmrg int i; 22423a0898aSmrg 22523a0898aSmrg for (i = 0; i < ntables; i++) 22623a0898aSmrg if (tables[i].type == type) 22723a0898aSmrg return TRUE; 22823a0898aSmrg return FALSE; 22923a0898aSmrg} 23023a0898aSmrg 23123a0898aSmrg/* 23223a0898aSmrg * pcfGetProperties 23323a0898aSmrg * 23423a0898aSmrg * Reads the font properties from the font file, filling in the FontInfo rec 23523a0898aSmrg * supplied. Used by by both ReadFont and ReadFontInfo routines. 23623a0898aSmrg */ 23723a0898aSmrg 23823a0898aSmrgstatic Bool 23923a0898aSmrgpcfGetProperties(FontInfoPtr pFontInfo, FontFilePtr file, 24023a0898aSmrg PCFTablePtr tables, int ntables) 24123a0898aSmrg{ 24223a0898aSmrg FontPropPtr props = 0; 24323a0898aSmrg int nprops; 24423a0898aSmrg char *isStringProp = 0; 24523a0898aSmrg CARD32 format; 24623a0898aSmrg int i; 24723a0898aSmrg CARD32 size; 24823a0898aSmrg int string_size; 24923a0898aSmrg char *strings; 25023a0898aSmrg 25123a0898aSmrg /* font properties */ 25223a0898aSmrg 25323a0898aSmrg if (!pcfSeekToType(file, tables, ntables, PCF_PROPERTIES, &format, &size)) 25423a0898aSmrg goto Bail; 25523a0898aSmrg format = pcfGetLSB32(file); 25623a0898aSmrg if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) 25723a0898aSmrg goto Bail; 25823a0898aSmrg nprops = pcfGetINT32(file, format); 25923a0898aSmrg if (nprops <= 0 || nprops > INT32_MAX / sizeof(FontPropRec)) { 26023a0898aSmrg pcfError("pcfGetProperties(): invalid nprops value (%d)\n", nprops); 26123a0898aSmrg goto Bail; 26223a0898aSmrg } 26323a0898aSmrg if (IS_EOF(file)) goto Bail; 2647f7f5e4eSmrg props = malloc(nprops * sizeof(FontPropRec)); 26523a0898aSmrg if (!props) { 26623a0898aSmrg pcfError("pcfGetProperties(): Couldn't allocate props (%d*%d)\n", nprops, sizeof(FontPropRec)); 26723a0898aSmrg goto Bail; 26823a0898aSmrg } 2697f7f5e4eSmrg isStringProp = malloc(nprops * sizeof(char)); 27023a0898aSmrg if (!isStringProp) { 27123a0898aSmrg pcfError("pcfGetProperties(): Couldn't allocate isStringProp (%d*%d)\n", nprops, sizeof(char)); 27223a0898aSmrg goto Bail; 27323a0898aSmrg } 27423a0898aSmrg for (i = 0; i < nprops; i++) { 27523a0898aSmrg props[i].name = pcfGetINT32(file, format); 27623a0898aSmrg isStringProp[i] = pcfGetINT8(file, format); 27723a0898aSmrg props[i].value = pcfGetINT32(file, format); 27823a0898aSmrg if (props[i].name < 0 27923a0898aSmrg || (isStringProp[i] != 0 && isStringProp[i] != 1) 28023a0898aSmrg || (isStringProp[i] && props[i].value < 0)) { 28123a0898aSmrg pcfError("pcfGetProperties(): invalid file format %d %d %d\n", 28223a0898aSmrg props[i].name, isStringProp[i], props[i].value); 28323a0898aSmrg goto Bail; 28423a0898aSmrg } 28523a0898aSmrg if (IS_EOF(file)) goto Bail; 28623a0898aSmrg } 28723a0898aSmrg /* pad the property array */ 28823a0898aSmrg /* 28923a0898aSmrg * clever here - nprops is the same as the number of odd-units read, as 29023a0898aSmrg * only isStringProp are odd length 29123a0898aSmrg */ 29223a0898aSmrg if (nprops & 3) 29323a0898aSmrg { 29423a0898aSmrg i = 4 - (nprops & 3); 29523a0898aSmrg (void)FontFileSkip(file, i); 29623a0898aSmrg position += i; 29723a0898aSmrg } 29823a0898aSmrg if (IS_EOF(file)) goto Bail; 29923a0898aSmrg string_size = pcfGetINT32(file, format); 30023a0898aSmrg if (string_size < 0) goto Bail; 30123a0898aSmrg if (IS_EOF(file)) goto Bail; 3027f7f5e4eSmrg strings = malloc(string_size); 30323a0898aSmrg if (!strings) { 30423a0898aSmrg pcfError("pcfGetProperties(): Couldn't allocate strings (%d)\n", string_size); 30523a0898aSmrg goto Bail; 30623a0898aSmrg } 30723a0898aSmrg FontFileRead(file, strings, string_size); 30823a0898aSmrg if (IS_EOF(file)) goto Bail; 30923a0898aSmrg position += string_size; 31023a0898aSmrg for (i = 0; i < nprops; i++) { 31123a0898aSmrg props[i].name = MakeAtom(strings + props[i].name, 31223a0898aSmrg strlen(strings + props[i].name), TRUE); 31323a0898aSmrg if (isStringProp[i]) { 31423a0898aSmrg props[i].value = MakeAtom(strings + props[i].value, 31523a0898aSmrg strlen(strings + props[i].value), TRUE); 31623a0898aSmrg } 31723a0898aSmrg } 3187f7f5e4eSmrg free(strings); 31923a0898aSmrg pFontInfo->isStringProp = isStringProp; 32023a0898aSmrg pFontInfo->props = props; 32123a0898aSmrg pFontInfo->nprops = nprops; 32223a0898aSmrg return TRUE; 32323a0898aSmrgBail: 3247f7f5e4eSmrg free(isStringProp); 3257f7f5e4eSmrg free(props); 32623a0898aSmrg return FALSE; 32723a0898aSmrg} 32823a0898aSmrg 32923a0898aSmrg 33023a0898aSmrg/* 33123a0898aSmrg * pcfReadAccel 33223a0898aSmrg * 33323a0898aSmrg * Fill in the accelerator information from the font file; used 33423a0898aSmrg * to read both BDF_ACCELERATORS and old style ACCELERATORS 33523a0898aSmrg */ 33623a0898aSmrg 33723a0898aSmrgstatic Bool 33823a0898aSmrgpcfGetAccel(FontInfoPtr pFontInfo, FontFilePtr file, 33923a0898aSmrg PCFTablePtr tables, int ntables, CARD32 type) 34023a0898aSmrg{ 34123a0898aSmrg CARD32 format; 34223a0898aSmrg CARD32 size; 34323a0898aSmrg 34423a0898aSmrg if (!pcfSeekToType(file, tables, ntables, type, &format, &size) || 34523a0898aSmrg IS_EOF(file)) 34623a0898aSmrg goto Bail; 34723a0898aSmrg format = pcfGetLSB32(file); 34823a0898aSmrg if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT) && 34923a0898aSmrg !PCF_FORMAT_MATCH(format, PCF_ACCEL_W_INKBOUNDS)) 35023a0898aSmrg { 35123a0898aSmrg goto Bail; 35223a0898aSmrg } 35323a0898aSmrg pFontInfo->noOverlap = pcfGetINT8(file, format); 35423a0898aSmrg pFontInfo->constantMetrics = pcfGetINT8(file, format); 35523a0898aSmrg pFontInfo->terminalFont = pcfGetINT8(file, format); 35623a0898aSmrg pFontInfo->constantWidth = pcfGetINT8(file, format); 35723a0898aSmrg pFontInfo->inkInside = pcfGetINT8(file, format); 35823a0898aSmrg pFontInfo->inkMetrics = pcfGetINT8(file, format); 35923a0898aSmrg pFontInfo->drawDirection = pcfGetINT8(file, format); 36023a0898aSmrg pFontInfo->anamorphic = FALSE; 36123a0898aSmrg pFontInfo->cachable = TRUE; 36223a0898aSmrg /* natural alignment */ pcfGetINT8(file, format); 36323a0898aSmrg pFontInfo->fontAscent = pcfGetINT32(file, format); 36423a0898aSmrg pFontInfo->fontDescent = pcfGetINT32(file, format); 36523a0898aSmrg pFontInfo->maxOverlap = pcfGetINT32(file, format); 36623a0898aSmrg if (IS_EOF(file)) goto Bail; 36723a0898aSmrg if (!pcfGetMetric(file, format, &pFontInfo->minbounds)) 36823a0898aSmrg goto Bail; 36923a0898aSmrg if (!pcfGetMetric(file, format, &pFontInfo->maxbounds)) 37023a0898aSmrg goto Bail; 37123a0898aSmrg if (PCF_FORMAT_MATCH(format, PCF_ACCEL_W_INKBOUNDS)) { 37223a0898aSmrg if (!pcfGetMetric(file, format, &pFontInfo->ink_minbounds)) 37323a0898aSmrg goto Bail; 37423a0898aSmrg if (!pcfGetMetric(file, format, &pFontInfo->ink_maxbounds)) 37523a0898aSmrg goto Bail; 37623a0898aSmrg } else { 37723a0898aSmrg pFontInfo->ink_minbounds = pFontInfo->minbounds; 37823a0898aSmrg pFontInfo->ink_maxbounds = pFontInfo->maxbounds; 37923a0898aSmrg } 38023a0898aSmrg return TRUE; 38123a0898aSmrgBail: 38223a0898aSmrg return FALSE; 38323a0898aSmrg} 38423a0898aSmrg 38523a0898aSmrgint 38623a0898aSmrgpcfReadFont(FontPtr pFont, FontFilePtr file, 38723a0898aSmrg int bit, int byte, int glyph, int scan) 38823a0898aSmrg{ 38923a0898aSmrg CARD32 format; 39023a0898aSmrg CARD32 size; 39123a0898aSmrg BitmapFontPtr bitmapFont = 0; 39223a0898aSmrg int i; 39323a0898aSmrg PCFTablePtr tables = 0; 39423a0898aSmrg int ntables; 39523a0898aSmrg int nmetrics; 39623a0898aSmrg int nbitmaps; 39723a0898aSmrg int sizebitmaps; 39823a0898aSmrg int nink_metrics; 39923a0898aSmrg CharInfoPtr metrics = 0; 40023a0898aSmrg xCharInfo *ink_metrics = 0; 40123a0898aSmrg char *bitmaps = 0; 40223a0898aSmrg CharInfoPtr **encoding = 0; 40323a0898aSmrg int nencoding = 0; 40423a0898aSmrg int encodingOffset; 40523a0898aSmrg CARD32 bitmapSizes[GLYPHPADOPTIONS]; 40623a0898aSmrg CARD32 *offsets = 0; 40723a0898aSmrg Bool hasBDFAccelerators; 40823a0898aSmrg 40923a0898aSmrg pFont->info.nprops = 0; 41023a0898aSmrg pFont->info.props = 0; 4114b1cd807Scheusov pFont->info.isStringProp=0; 4124b1cd807Scheusov 41323a0898aSmrg if (!(tables = pcfReadTOC(file, &ntables))) 41423a0898aSmrg goto Bail; 41523a0898aSmrg 41623a0898aSmrg /* properties */ 41723a0898aSmrg 41823a0898aSmrg if (!pcfGetProperties(&pFont->info, file, tables, ntables)) 41923a0898aSmrg goto Bail; 42023a0898aSmrg 42123a0898aSmrg /* Use the old accelerators if no BDF accelerators are in the file */ 42223a0898aSmrg 42323a0898aSmrg hasBDFAccelerators = pcfHasType (tables, ntables, PCF_BDF_ACCELERATORS); 42423a0898aSmrg if (!hasBDFAccelerators) 42523a0898aSmrg if (!pcfGetAccel (&pFont->info, file, tables, ntables, PCF_ACCELERATORS)) 42623a0898aSmrg goto Bail; 42723a0898aSmrg 42823a0898aSmrg /* metrics */ 42923a0898aSmrg 43023a0898aSmrg if (!pcfSeekToType(file, tables, ntables, PCF_METRICS, &format, &size)) { 43123a0898aSmrg goto Bail; 43223a0898aSmrg } 43323a0898aSmrg format = pcfGetLSB32(file); 43423a0898aSmrg if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT) && 43523a0898aSmrg !PCF_FORMAT_MATCH(format, PCF_COMPRESSED_METRICS)) { 43623a0898aSmrg goto Bail; 43723a0898aSmrg } 43823a0898aSmrg if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) 43923a0898aSmrg nmetrics = pcfGetINT32(file, format); 44023a0898aSmrg else 44123a0898aSmrg nmetrics = pcfGetINT16(file, format); 44223a0898aSmrg if (IS_EOF(file)) goto Bail; 44323a0898aSmrg if (nmetrics < 0 || nmetrics > INT32_MAX / sizeof(CharInfoRec)) { 44423a0898aSmrg pcfError("pcfReadFont(): invalid file format\n"); 44523a0898aSmrg goto Bail; 44623a0898aSmrg } 4477f7f5e4eSmrg metrics = malloc(nmetrics * sizeof(CharInfoRec)); 44823a0898aSmrg if (!metrics) { 44923a0898aSmrg pcfError("pcfReadFont(): Couldn't allocate metrics (%d*%d)\n", nmetrics, sizeof(CharInfoRec)); 45023a0898aSmrg goto Bail; 45123a0898aSmrg } 45223a0898aSmrg for (i = 0; i < nmetrics; i++) 45323a0898aSmrg if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) { 45423a0898aSmrg if (!pcfGetMetric(file, format, &(metrics + i)->metrics)) 45523a0898aSmrg goto Bail; 45623a0898aSmrg } else { 45723a0898aSmrg if (!pcfGetCompressedMetric(file, format, &(metrics + i)->metrics)) 45823a0898aSmrg goto Bail; 45923a0898aSmrg } 46023a0898aSmrg 46123a0898aSmrg /* bitmaps */ 46223a0898aSmrg 46323a0898aSmrg if (!pcfSeekToType(file, tables, ntables, PCF_BITMAPS, &format, &size)) 46423a0898aSmrg goto Bail; 46523a0898aSmrg format = pcfGetLSB32(file); 46623a0898aSmrg if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) 46723a0898aSmrg goto Bail; 46823a0898aSmrg 46923a0898aSmrg nbitmaps = pcfGetINT32(file, format); 47023a0898aSmrg if (nbitmaps != nmetrics || IS_EOF(file)) 47123a0898aSmrg goto Bail; 47223a0898aSmrg /* nmetrics is already ok, so nbitmap also is */ 4737f7f5e4eSmrg offsets = malloc(nbitmaps * sizeof(CARD32)); 47423a0898aSmrg if (!offsets) { 47523a0898aSmrg pcfError("pcfReadFont(): Couldn't allocate offsets (%d*%d)\n", nbitmaps, sizeof(CARD32)); 47623a0898aSmrg goto Bail; 47723a0898aSmrg } 47823a0898aSmrg for (i = 0; i < nbitmaps; i++) { 47923a0898aSmrg offsets[i] = pcfGetINT32(file, format); 48023a0898aSmrg if (IS_EOF(file)) goto Bail; 48123a0898aSmrg } 48223a0898aSmrg 48323a0898aSmrg for (i = 0; i < GLYPHPADOPTIONS; i++) { 48423a0898aSmrg bitmapSizes[i] = pcfGetINT32(file, format); 48523a0898aSmrg if (IS_EOF(file)) goto Bail; 48623a0898aSmrg if (bitmapSizes[i] < 0) goto Bail; 48723a0898aSmrg } 48823a0898aSmrg 48923a0898aSmrg sizebitmaps = bitmapSizes[PCF_GLYPH_PAD_INDEX(format)]; 49023a0898aSmrg /* guard against completely empty font */ 4917f7f5e4eSmrg bitmaps = malloc(sizebitmaps ? sizebitmaps : 1); 49223a0898aSmrg if (!bitmaps) { 49323a0898aSmrg pcfError("pcfReadFont(): Couldn't allocate bitmaps (%d)\n", sizebitmaps ? sizebitmaps : 1); 49423a0898aSmrg goto Bail; 49523a0898aSmrg } 49623a0898aSmrg FontFileRead(file, bitmaps, sizebitmaps); 49723a0898aSmrg if (IS_EOF(file)) goto Bail; 49823a0898aSmrg position += sizebitmaps; 49923a0898aSmrg 50023a0898aSmrg if (PCF_BIT_ORDER(format) != bit) 50123a0898aSmrg BitOrderInvert((unsigned char *)bitmaps, sizebitmaps); 50223a0898aSmrg if ((PCF_BYTE_ORDER(format) == PCF_BIT_ORDER(format)) != (bit == byte)) { 50323a0898aSmrg switch (bit == byte ? PCF_SCAN_UNIT(format) : scan) { 50423a0898aSmrg case 1: 50523a0898aSmrg break; 50623a0898aSmrg case 2: 50723a0898aSmrg TwoByteSwap((unsigned char *)bitmaps, sizebitmaps); 50823a0898aSmrg break; 50923a0898aSmrg case 4: 51023a0898aSmrg FourByteSwap((unsigned char *)bitmaps, sizebitmaps); 51123a0898aSmrg break; 51223a0898aSmrg } 51323a0898aSmrg } 51423a0898aSmrg if (PCF_GLYPH_PAD(format) != glyph) { 51523a0898aSmrg char *padbitmaps; 51623a0898aSmrg int sizepadbitmaps; 51723a0898aSmrg int old, 51823a0898aSmrg new; 51923a0898aSmrg xCharInfo *metric; 52023a0898aSmrg 52123a0898aSmrg sizepadbitmaps = bitmapSizes[PCF_SIZE_TO_INDEX(glyph)]; 5227f7f5e4eSmrg padbitmaps = malloc(sizepadbitmaps); 52323a0898aSmrg if (!padbitmaps) { 52423a0898aSmrg pcfError("pcfReadFont(): Couldn't allocate padbitmaps (%d)\n", sizepadbitmaps); 52523a0898aSmrg goto Bail; 52623a0898aSmrg } 52723a0898aSmrg new = 0; 52823a0898aSmrg for (i = 0; i < nbitmaps; i++) { 52923a0898aSmrg old = offsets[i]; 53023a0898aSmrg metric = &metrics[i].metrics; 53123a0898aSmrg offsets[i] = new; 53223a0898aSmrg new += RepadBitmap(bitmaps + old, padbitmaps + new, 53323a0898aSmrg PCF_GLYPH_PAD(format), glyph, 53423a0898aSmrg metric->rightSideBearing - metric->leftSideBearing, 53523a0898aSmrg metric->ascent + metric->descent); 53623a0898aSmrg } 5377f7f5e4eSmrg free(bitmaps); 53823a0898aSmrg bitmaps = padbitmaps; 53923a0898aSmrg } 54023a0898aSmrg for (i = 0; i < nbitmaps; i++) 54123a0898aSmrg metrics[i].bits = bitmaps + offsets[i]; 54223a0898aSmrg 5437f7f5e4eSmrg free(offsets); 54423a0898aSmrg offsets = NULL; 54523a0898aSmrg 54623a0898aSmrg /* ink metrics ? */ 54723a0898aSmrg 54823a0898aSmrg ink_metrics = NULL; 54923a0898aSmrg if (pcfSeekToType(file, tables, ntables, PCF_INK_METRICS, &format, &size)) { 55023a0898aSmrg format = pcfGetLSB32(file); 55123a0898aSmrg if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT) && 55223a0898aSmrg !PCF_FORMAT_MATCH(format, PCF_COMPRESSED_METRICS)) { 55323a0898aSmrg goto Bail; 55423a0898aSmrg } 55523a0898aSmrg if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) 55623a0898aSmrg nink_metrics = pcfGetINT32(file, format); 55723a0898aSmrg else 55823a0898aSmrg nink_metrics = pcfGetINT16(file, format); 55923a0898aSmrg if (IS_EOF(file)) goto Bail; 56023a0898aSmrg if (nink_metrics != nmetrics) 56123a0898aSmrg goto Bail; 56223a0898aSmrg /* nmetrics already checked */ 5637f7f5e4eSmrg ink_metrics = malloc(nink_metrics * sizeof(xCharInfo)); 56423a0898aSmrg if (!ink_metrics) { 56523a0898aSmrg pcfError("pcfReadFont(): Couldn't allocate ink_metrics (%d*%d)\n", nink_metrics, sizeof(xCharInfo)); 56623a0898aSmrg goto Bail; 56723a0898aSmrg } 56823a0898aSmrg for (i = 0; i < nink_metrics; i++) 56923a0898aSmrg if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) { 57023a0898aSmrg if (!pcfGetMetric(file, format, ink_metrics + i)) 57123a0898aSmrg goto Bail; 57223a0898aSmrg } else { 57323a0898aSmrg if (!pcfGetCompressedMetric(file, format, ink_metrics + i)) 57423a0898aSmrg goto Bail; 57523a0898aSmrg } 57623a0898aSmrg } 57723a0898aSmrg 57823a0898aSmrg /* encoding */ 57923a0898aSmrg 58023a0898aSmrg if (!pcfSeekToType(file, tables, ntables, PCF_BDF_ENCODINGS, &format, &size)) 58123a0898aSmrg goto Bail; 58223a0898aSmrg format = pcfGetLSB32(file); 58323a0898aSmrg if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) 58423a0898aSmrg goto Bail; 58523a0898aSmrg 58623a0898aSmrg pFont->info.firstCol = pcfGetINT16(file, format); 58723a0898aSmrg pFont->info.lastCol = pcfGetINT16(file, format); 58823a0898aSmrg pFont->info.firstRow = pcfGetINT16(file, format); 58923a0898aSmrg pFont->info.lastRow = pcfGetINT16(file, format); 59023a0898aSmrg pFont->info.defaultCh = pcfGetINT16(file, format); 59123a0898aSmrg if (IS_EOF(file)) goto Bail; 59223a0898aSmrg if (pFont->info.firstCol > pFont->info.lastCol || 59323a0898aSmrg pFont->info.firstRow > pFont->info.lastRow || 59423a0898aSmrg pFont->info.lastCol-pFont->info.firstCol > 255) goto Bail; 59523a0898aSmrg 59623a0898aSmrg nencoding = (pFont->info.lastCol - pFont->info.firstCol + 1) * 59723a0898aSmrg (pFont->info.lastRow - pFont->info.firstRow + 1); 59823a0898aSmrg 5997f7f5e4eSmrg encoding = calloc(NUM_SEGMENTS(nencoding), sizeof(CharInfoPtr*)); 60023a0898aSmrg if (!encoding) { 60123a0898aSmrg pcfError("pcfReadFont(): Couldn't allocate encoding (%d*%d)\n", nencoding, sizeof(CharInfoPtr)); 60223a0898aSmrg goto Bail; 60323a0898aSmrg } 60423a0898aSmrg 60523a0898aSmrg pFont->info.allExist = TRUE; 60623a0898aSmrg for (i = 0; i < nencoding; i++) { 60723a0898aSmrg encodingOffset = pcfGetINT16(file, format); 60823a0898aSmrg if (IS_EOF(file)) goto Bail; 60923a0898aSmrg if (encodingOffset == 0xFFFF) { 61023a0898aSmrg pFont->info.allExist = FALSE; 61123a0898aSmrg } else { 61223a0898aSmrg if(!encoding[SEGMENT_MAJOR(i)]) { 61323a0898aSmrg encoding[SEGMENT_MAJOR(i)]= 6147f7f5e4eSmrg calloc(BITMAP_FONT_SEGMENT_SIZE, sizeof(CharInfoPtr)); 61523a0898aSmrg if(!encoding[SEGMENT_MAJOR(i)]) 61623a0898aSmrg goto Bail; 61723a0898aSmrg } 61823a0898aSmrg ACCESSENCODINGL(encoding, i) = metrics + encodingOffset; 61923a0898aSmrg } 62023a0898aSmrg } 62123a0898aSmrg 62223a0898aSmrg /* BDF style accelerators (i.e. bounds based on encoded glyphs) */ 62323a0898aSmrg 62423a0898aSmrg if (hasBDFAccelerators) 62523a0898aSmrg if (!pcfGetAccel (&pFont->info, file, tables, ntables, PCF_BDF_ACCELERATORS)) 62623a0898aSmrg goto Bail; 62723a0898aSmrg 6287f7f5e4eSmrg bitmapFont = malloc(sizeof *bitmapFont); 62923a0898aSmrg if (!bitmapFont) { 63023a0898aSmrg pcfError("pcfReadFont(): Couldn't allocate bitmapFont (%d)\n", sizeof *bitmapFont); 63123a0898aSmrg goto Bail; 63223a0898aSmrg } 63323a0898aSmrg 63423a0898aSmrg bitmapFont->version_num = PCF_FILE_VERSION; 63523a0898aSmrg bitmapFont->num_chars = nmetrics; 63623a0898aSmrg bitmapFont->num_tables = ntables; 63723a0898aSmrg bitmapFont->metrics = metrics; 63823a0898aSmrg bitmapFont->ink_metrics = ink_metrics; 63923a0898aSmrg bitmapFont->bitmaps = bitmaps; 64023a0898aSmrg bitmapFont->encoding = encoding; 64123a0898aSmrg bitmapFont->pDefault = (CharInfoPtr) 0; 64223a0898aSmrg if (pFont->info.defaultCh != (unsigned short) NO_SUCH_CHAR) { 64323a0898aSmrg unsigned int r, 64423a0898aSmrg c, 64523a0898aSmrg cols; 64623a0898aSmrg 64723a0898aSmrg r = pFont->info.defaultCh >> 8; 64823a0898aSmrg c = pFont->info.defaultCh & 0xFF; 64923a0898aSmrg if (pFont->info.firstRow <= r && r <= pFont->info.lastRow && 65023a0898aSmrg pFont->info.firstCol <= c && c <= pFont->info.lastCol) { 65123a0898aSmrg cols = pFont->info.lastCol - pFont->info.firstCol + 1; 65223a0898aSmrg r = r - pFont->info.firstRow; 65323a0898aSmrg c = c - pFont->info.firstCol; 65423a0898aSmrg bitmapFont->pDefault = ACCESSENCODING(encoding, r * cols + c); 65523a0898aSmrg } 65623a0898aSmrg } 65723a0898aSmrg bitmapFont->bitmapExtra = (BitmapExtraPtr) 0; 65823a0898aSmrg pFont->fontPrivate = (pointer) bitmapFont; 65923a0898aSmrg pFont->get_glyphs = bitmapGetGlyphs; 66023a0898aSmrg pFont->get_metrics = bitmapGetMetrics; 66123a0898aSmrg pFont->unload_font = pcfUnloadFont; 66223a0898aSmrg pFont->unload_glyphs = NULL; 66323a0898aSmrg pFont->bit = bit; 66423a0898aSmrg pFont->byte = byte; 66523a0898aSmrg pFont->glyph = glyph; 66623a0898aSmrg pFont->scan = scan; 6677f7f5e4eSmrg free(tables); 66823a0898aSmrg return Successful; 66923a0898aSmrgBail: 6707f7f5e4eSmrg free(ink_metrics); 67123a0898aSmrg if(encoding) { 67223a0898aSmrg for(i=0; i<NUM_SEGMENTS(nencoding); i++) 6737f7f5e4eSmrg free(encoding[i]); 67423a0898aSmrg } 6757f7f5e4eSmrg free(encoding); 6767f7f5e4eSmrg free(bitmaps); 6777f7f5e4eSmrg free(metrics); 6787f7f5e4eSmrg free(pFont->info.props); 67923a0898aSmrg pFont->info.nprops = 0; 68023a0898aSmrg pFont->info.props = 0; 6817f7f5e4eSmrg free (pFont->info.isStringProp); 6827f7f5e4eSmrg free(bitmapFont); 6837f7f5e4eSmrg free(tables); 6847f7f5e4eSmrg free(offsets); 68523a0898aSmrg return AllocError; 68623a0898aSmrg} 68723a0898aSmrg 68823a0898aSmrgint 68923a0898aSmrgpcfReadFontInfo(FontInfoPtr pFontInfo, FontFilePtr file) 69023a0898aSmrg{ 69123a0898aSmrg PCFTablePtr tables; 69223a0898aSmrg int ntables; 69323a0898aSmrg CARD32 format; 69423a0898aSmrg CARD32 size; 69523a0898aSmrg int nencoding; 69623a0898aSmrg Bool hasBDFAccelerators; 69723a0898aSmrg 69823a0898aSmrg pFontInfo->isStringProp = NULL; 69923a0898aSmrg pFontInfo->props = NULL; 70023a0898aSmrg pFontInfo->nprops = 0; 70123a0898aSmrg 70223a0898aSmrg if (!(tables = pcfReadTOC(file, &ntables))) 70323a0898aSmrg goto Bail; 70423a0898aSmrg 70523a0898aSmrg /* properties */ 70623a0898aSmrg 70723a0898aSmrg if (!pcfGetProperties(pFontInfo, file, tables, ntables)) 70823a0898aSmrg goto Bail; 70923a0898aSmrg 71023a0898aSmrg /* Use the old accelerators if no BDF accelerators are in the file */ 71123a0898aSmrg 71223a0898aSmrg hasBDFAccelerators = pcfHasType (tables, ntables, PCF_BDF_ACCELERATORS); 71323a0898aSmrg if (!hasBDFAccelerators) 71423a0898aSmrg if (!pcfGetAccel (pFontInfo, file, tables, ntables, PCF_ACCELERATORS)) 71523a0898aSmrg goto Bail; 71623a0898aSmrg 71723a0898aSmrg /* encoding */ 71823a0898aSmrg 71923a0898aSmrg if (!pcfSeekToType(file, tables, ntables, PCF_BDF_ENCODINGS, &format, &size)) 72023a0898aSmrg goto Bail; 72123a0898aSmrg format = pcfGetLSB32(file); 72223a0898aSmrg if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) 72323a0898aSmrg goto Bail; 72423a0898aSmrg 72523a0898aSmrg pFontInfo->firstCol = pcfGetINT16(file, format); 72623a0898aSmrg pFontInfo->lastCol = pcfGetINT16(file, format); 72723a0898aSmrg pFontInfo->firstRow = pcfGetINT16(file, format); 72823a0898aSmrg pFontInfo->lastRow = pcfGetINT16(file, format); 72923a0898aSmrg pFontInfo->defaultCh = pcfGetINT16(file, format); 73023a0898aSmrg if (IS_EOF(file)) goto Bail; 73123a0898aSmrg if (pFontInfo->firstCol > pFontInfo->lastCol || 73223a0898aSmrg pFontInfo->firstRow > pFontInfo->lastRow || 73323a0898aSmrg pFontInfo->lastCol-pFontInfo->firstCol > 255) goto Bail; 73423a0898aSmrg 73523a0898aSmrg nencoding = (pFontInfo->lastCol - pFontInfo->firstCol + 1) * 73623a0898aSmrg (pFontInfo->lastRow - pFontInfo->firstRow + 1); 73723a0898aSmrg 73823a0898aSmrg pFontInfo->allExist = TRUE; 73923a0898aSmrg while (nencoding--) { 74023a0898aSmrg if (pcfGetINT16(file, format) == 0xFFFF) 74123a0898aSmrg pFontInfo->allExist = FALSE; 74223a0898aSmrg if (IS_EOF(file)) goto Bail; 74323a0898aSmrg } 74423a0898aSmrg if (IS_EOF(file)) goto Bail; 74523a0898aSmrg 74623a0898aSmrg /* BDF style accelerators (i.e. bounds based on encoded glyphs) */ 74723a0898aSmrg 74823a0898aSmrg if (hasBDFAccelerators) 74923a0898aSmrg if (!pcfGetAccel (pFontInfo, file, tables, ntables, PCF_BDF_ACCELERATORS)) 75023a0898aSmrg goto Bail; 75123a0898aSmrg 7527f7f5e4eSmrg free(tables); 75323a0898aSmrg return Successful; 75423a0898aSmrgBail: 75523a0898aSmrg pFontInfo->nprops = 0; 7567f7f5e4eSmrg free (pFontInfo->props); 7577f7f5e4eSmrg free (pFontInfo->isStringProp); 7587f7f5e4eSmrg free(tables); 75923a0898aSmrg return AllocError; 76023a0898aSmrg} 76123a0898aSmrg 76223a0898aSmrgstatic void 76323a0898aSmrgpcfUnloadFont(FontPtr pFont) 76423a0898aSmrg{ 76523a0898aSmrg BitmapFontPtr bitmapFont; 76623a0898aSmrg int i,nencoding; 76723a0898aSmrg 76823a0898aSmrg bitmapFont = (BitmapFontPtr) pFont->fontPrivate; 7697f7f5e4eSmrg free(bitmapFont->ink_metrics); 77023a0898aSmrg if(bitmapFont->encoding) { 77123a0898aSmrg nencoding = (pFont->info.lastCol - pFont->info.firstCol + 1) * 77223a0898aSmrg (pFont->info.lastRow - pFont->info.firstRow + 1); 77323a0898aSmrg for(i=0; i<NUM_SEGMENTS(nencoding); i++) 7747f7f5e4eSmrg free(bitmapFont->encoding[i]); 7757f7f5e4eSmrg } 7767f7f5e4eSmrg free(bitmapFont->encoding); 7777f7f5e4eSmrg free(bitmapFont->bitmaps); 7787f7f5e4eSmrg free(bitmapFont->metrics); 7797f7f5e4eSmrg free(pFont->info.isStringProp); 7807f7f5e4eSmrg free(pFont->info.props); 7817f7f5e4eSmrg free(bitmapFont); 78223a0898aSmrg DestroyFontRec(pFont); 78323a0898aSmrg} 784