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 2923a0898aSmrg/* 3023a0898aSmrg * Author: Keith Packard, MIT X Consortium 3123a0898aSmrg */ 3223a0898aSmrg 3323a0898aSmrg#ifdef HAVE_CONFIG_H 3423a0898aSmrg#include <config.h> 3523a0898aSmrg#endif 3623a0898aSmrg 3723a0898aSmrg#include <X11/fonts/fntfilst.h> 3823a0898aSmrg#include <X11/fonts/bitmap.h> 3923a0898aSmrg#include <X11/fonts/pcf.h> 4023a0898aSmrg 4123a0898aSmrg#ifndef MAX 4223a0898aSmrg#define MAX(a,b) (((a)>(b)) ? a : b) 4323a0898aSmrg#endif 4423a0898aSmrg 4523a0898aSmrg#include <stdarg.h> 4623a0898aSmrg#include <stdint.h> 47f262af57Smrg#include <string.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} 601a17810dSmrg 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) { 1421a17810dSmrg pcfError("pcfReadTOC(): Couldn't allocate tables (%d*%d)\n", 1431a17810dSmrg count, (int) sizeof(PCFTableRec)); 14423a0898aSmrg return (PCFTablePtr) NULL; 14523a0898aSmrg } 14623a0898aSmrg for (i = 0; i < count; i++) { 14723a0898aSmrg tables[i].type = pcfGetLSB32(file); 14823a0898aSmrg tables[i].format = pcfGetLSB32(file); 14923a0898aSmrg tables[i].size = pcfGetLSB32(file); 15023a0898aSmrg tables[i].offset = pcfGetLSB32(file); 15123a0898aSmrg if (IS_EOF(file)) goto Bail; 15223a0898aSmrg } 15323a0898aSmrg 15423a0898aSmrg *countp = count; 15523a0898aSmrg return tables; 15623a0898aSmrg 15723a0898aSmrg Bail: 1587f7f5e4eSmrg free(tables); 15923a0898aSmrg return (PCFTablePtr) NULL; 16023a0898aSmrg} 16123a0898aSmrg 16223a0898aSmrg/* 16323a0898aSmrg * PCF supports two formats for metrics, both the regular 16423a0898aSmrg * jumbo size, and 'lite' metrics, which are useful 16523a0898aSmrg * for most fonts which have even vaguely reasonable 16623a0898aSmrg * metrics 16723a0898aSmrg */ 16823a0898aSmrg 16923a0898aSmrgstatic Bool 17023a0898aSmrgpcfGetMetric(FontFilePtr file, CARD32 format, xCharInfo *metric) 17123a0898aSmrg{ 17223a0898aSmrg metric->leftSideBearing = pcfGetINT16(file, format); 17323a0898aSmrg metric->rightSideBearing = pcfGetINT16(file, format); 17423a0898aSmrg metric->characterWidth = pcfGetINT16(file, format); 17523a0898aSmrg metric->ascent = pcfGetINT16(file, format); 17623a0898aSmrg metric->descent = pcfGetINT16(file, format); 17723a0898aSmrg metric->attributes = pcfGetINT16(file, format); 17823a0898aSmrg if (IS_EOF(file)) return FALSE; 17923a0898aSmrg 18023a0898aSmrg return TRUE; 18123a0898aSmrg} 18223a0898aSmrg 18323a0898aSmrgstatic Bool 18423a0898aSmrgpcfGetCompressedMetric(FontFilePtr file, CARD32 format, xCharInfo *metric) 18523a0898aSmrg{ 18623a0898aSmrg metric->leftSideBearing = pcfGetINT8(file, format) - 0x80; 18723a0898aSmrg metric->rightSideBearing = pcfGetINT8(file, format) - 0x80; 18823a0898aSmrg metric->characterWidth = pcfGetINT8(file, format) - 0x80; 18923a0898aSmrg metric->ascent = pcfGetINT8(file, format) - 0x80; 19023a0898aSmrg metric->descent = pcfGetINT8(file, format) - 0x80; 19123a0898aSmrg metric->attributes = 0; 19223a0898aSmrg if (IS_EOF(file)) return FALSE; 19323a0898aSmrg 19423a0898aSmrg return TRUE; 19523a0898aSmrg} 19623a0898aSmrg 19723a0898aSmrg/* 19823a0898aSmrg * Position the file to the begining of the specified table 19923a0898aSmrg * in the font file 20023a0898aSmrg */ 20123a0898aSmrgstatic Bool 2021a17810dSmrgpcfSeekToType(FontFilePtr file, PCFTablePtr tables, int ntables, 20323a0898aSmrg CARD32 type, CARD32 *formatp, CARD32 *sizep) 20423a0898aSmrg{ 20523a0898aSmrg int i; 20623a0898aSmrg 20723a0898aSmrg for (i = 0; i < ntables; i++) 20823a0898aSmrg if (tables[i].type == type) { 20923a0898aSmrg if (position > tables[i].offset) 21023a0898aSmrg return FALSE; 21123a0898aSmrg if (!FontFileSkip(file, tables[i].offset - position)) 21223a0898aSmrg return FALSE; 21323a0898aSmrg position = tables[i].offset; 21423a0898aSmrg *sizep = tables[i].size; 21523a0898aSmrg *formatp = tables[i].format; 21623a0898aSmrg return TRUE; 21723a0898aSmrg } 21823a0898aSmrg return FALSE; 21923a0898aSmrg} 22023a0898aSmrg 22123a0898aSmrgstatic Bool 22223a0898aSmrgpcfHasType (PCFTablePtr tables, int ntables, CARD32 type) 22323a0898aSmrg{ 22423a0898aSmrg int i; 22523a0898aSmrg 22623a0898aSmrg for (i = 0; i < ntables; i++) 22723a0898aSmrg if (tables[i].type == type) 22823a0898aSmrg return TRUE; 22923a0898aSmrg return FALSE; 23023a0898aSmrg} 23123a0898aSmrg 23223a0898aSmrg/* 2331a17810dSmrg * pcfGetProperties 23423a0898aSmrg * 23523a0898aSmrg * Reads the font properties from the font file, filling in the FontInfo rec 23623a0898aSmrg * supplied. Used by by both ReadFont and ReadFontInfo routines. 23723a0898aSmrg */ 23823a0898aSmrg 23923a0898aSmrgstatic Bool 2401a17810dSmrgpcfGetProperties(FontInfoPtr pFontInfo, FontFilePtr file, 24123a0898aSmrg PCFTablePtr tables, int ntables) 24223a0898aSmrg{ 24323a0898aSmrg FontPropPtr props = 0; 24423a0898aSmrg int nprops; 24523a0898aSmrg char *isStringProp = 0; 24623a0898aSmrg CARD32 format; 24723a0898aSmrg int i; 24823a0898aSmrg CARD32 size; 24923a0898aSmrg int string_size; 25023a0898aSmrg char *strings; 25123a0898aSmrg 25223a0898aSmrg /* font properties */ 25323a0898aSmrg 25423a0898aSmrg if (!pcfSeekToType(file, tables, ntables, PCF_PROPERTIES, &format, &size)) 25523a0898aSmrg goto Bail; 25623a0898aSmrg format = pcfGetLSB32(file); 25723a0898aSmrg if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) 25823a0898aSmrg goto Bail; 25923a0898aSmrg nprops = pcfGetINT32(file, format); 26023a0898aSmrg if (nprops <= 0 || nprops > INT32_MAX / sizeof(FontPropRec)) { 26123a0898aSmrg pcfError("pcfGetProperties(): invalid nprops value (%d)\n", nprops); 26223a0898aSmrg goto Bail; 26323a0898aSmrg } 26423a0898aSmrg if (IS_EOF(file)) goto Bail; 2657f7f5e4eSmrg props = malloc(nprops * sizeof(FontPropRec)); 26623a0898aSmrg if (!props) { 2671a17810dSmrg pcfError("pcfGetProperties(): Couldn't allocate props (%d*%d)\n", 2681a17810dSmrg nprops, (int) sizeof(FontPropRec)); 26923a0898aSmrg goto Bail; 27023a0898aSmrg } 2717f7f5e4eSmrg isStringProp = malloc(nprops * sizeof(char)); 27223a0898aSmrg if (!isStringProp) { 2731a17810dSmrg pcfError("pcfGetProperties(): Couldn't allocate isStringProp (%d*%d)\n", 2741a17810dSmrg nprops, (int) sizeof(char)); 27523a0898aSmrg goto Bail; 27623a0898aSmrg } 27723a0898aSmrg for (i = 0; i < nprops; i++) { 27823a0898aSmrg props[i].name = pcfGetINT32(file, format); 27923a0898aSmrg isStringProp[i] = pcfGetINT8(file, format); 28023a0898aSmrg props[i].value = pcfGetINT32(file, format); 2811a17810dSmrg if (props[i].name < 0 28223a0898aSmrg || (isStringProp[i] != 0 && isStringProp[i] != 1) 28323a0898aSmrg || (isStringProp[i] && props[i].value < 0)) { 2841a17810dSmrg pcfError("pcfGetProperties(): invalid file format %ld %d %ld\n", 28523a0898aSmrg props[i].name, isStringProp[i], props[i].value); 28623a0898aSmrg goto Bail; 28723a0898aSmrg } 28823a0898aSmrg if (IS_EOF(file)) goto Bail; 28923a0898aSmrg } 29023a0898aSmrg /* pad the property array */ 29123a0898aSmrg /* 29223a0898aSmrg * clever here - nprops is the same as the number of odd-units read, as 29323a0898aSmrg * only isStringProp are odd length 29423a0898aSmrg */ 29523a0898aSmrg if (nprops & 3) 29623a0898aSmrg { 29723a0898aSmrg i = 4 - (nprops & 3); 29823a0898aSmrg (void)FontFileSkip(file, i); 29923a0898aSmrg position += i; 30023a0898aSmrg } 30123a0898aSmrg if (IS_EOF(file)) goto Bail; 30223a0898aSmrg string_size = pcfGetINT32(file, format); 30323a0898aSmrg if (string_size < 0) goto Bail; 30423a0898aSmrg if (IS_EOF(file)) goto Bail; 3057f7f5e4eSmrg strings = malloc(string_size); 30623a0898aSmrg if (!strings) { 30723a0898aSmrg pcfError("pcfGetProperties(): Couldn't allocate strings (%d)\n", string_size); 30823a0898aSmrg goto Bail; 30923a0898aSmrg } 31023a0898aSmrg FontFileRead(file, strings, string_size); 31123a0898aSmrg if (IS_EOF(file)) goto Bail; 31223a0898aSmrg position += string_size; 31323a0898aSmrg for (i = 0; i < nprops; i++) { 314f262af57Smrg if (props[i].name >= string_size) { 315f262af57Smrg pcfError("pcfGetProperties(): String starts out of bounds (%ld/%d)\n", props[i].name, string_size); 316f262af57Smrg goto Bail; 317f262af57Smrg } 31823a0898aSmrg props[i].name = MakeAtom(strings + props[i].name, 319f262af57Smrg strnlen(strings + props[i].name, string_size - props[i].name), TRUE); 32023a0898aSmrg if (isStringProp[i]) { 321f262af57Smrg if (props[i].value >= string_size) { 322f262af57Smrg pcfError("pcfGetProperties(): String starts out of bounds (%ld/%d)\n", props[i].value, string_size); 323f262af57Smrg goto Bail; 324f262af57Smrg } 32523a0898aSmrg props[i].value = MakeAtom(strings + props[i].value, 326f262af57Smrg strnlen(strings + props[i].value, string_size - props[i].value), TRUE); 32723a0898aSmrg } 32823a0898aSmrg } 3297f7f5e4eSmrg free(strings); 33023a0898aSmrg pFontInfo->isStringProp = isStringProp; 33123a0898aSmrg pFontInfo->props = props; 33223a0898aSmrg pFontInfo->nprops = nprops; 33323a0898aSmrg return TRUE; 33423a0898aSmrgBail: 3357f7f5e4eSmrg free(isStringProp); 3367f7f5e4eSmrg free(props); 33723a0898aSmrg return FALSE; 33823a0898aSmrg} 33923a0898aSmrg 34023a0898aSmrg 34123a0898aSmrg/* 34223a0898aSmrg * pcfReadAccel 34323a0898aSmrg * 34423a0898aSmrg * Fill in the accelerator information from the font file; used 34523a0898aSmrg * to read both BDF_ACCELERATORS and old style ACCELERATORS 34623a0898aSmrg */ 34723a0898aSmrg 34823a0898aSmrgstatic Bool 3491a17810dSmrgpcfGetAccel(FontInfoPtr pFontInfo, FontFilePtr file, 35023a0898aSmrg PCFTablePtr tables, int ntables, CARD32 type) 35123a0898aSmrg{ 35223a0898aSmrg CARD32 format; 35323a0898aSmrg CARD32 size; 35423a0898aSmrg 35523a0898aSmrg if (!pcfSeekToType(file, tables, ntables, type, &format, &size) || 35623a0898aSmrg IS_EOF(file)) 35723a0898aSmrg goto Bail; 35823a0898aSmrg format = pcfGetLSB32(file); 35923a0898aSmrg if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT) && 3601a17810dSmrg !PCF_FORMAT_MATCH(format, PCF_ACCEL_W_INKBOUNDS)) 36123a0898aSmrg { 36223a0898aSmrg goto Bail; 36323a0898aSmrg } 36423a0898aSmrg pFontInfo->noOverlap = pcfGetINT8(file, format); 36523a0898aSmrg pFontInfo->constantMetrics = pcfGetINT8(file, format); 36623a0898aSmrg pFontInfo->terminalFont = pcfGetINT8(file, format); 36723a0898aSmrg pFontInfo->constantWidth = pcfGetINT8(file, format); 36823a0898aSmrg pFontInfo->inkInside = pcfGetINT8(file, format); 36923a0898aSmrg pFontInfo->inkMetrics = pcfGetINT8(file, format); 37023a0898aSmrg pFontInfo->drawDirection = pcfGetINT8(file, format); 37123a0898aSmrg pFontInfo->anamorphic = FALSE; 37223a0898aSmrg pFontInfo->cachable = TRUE; 37323a0898aSmrg /* natural alignment */ pcfGetINT8(file, format); 37423a0898aSmrg pFontInfo->fontAscent = pcfGetINT32(file, format); 37523a0898aSmrg pFontInfo->fontDescent = pcfGetINT32(file, format); 37623a0898aSmrg pFontInfo->maxOverlap = pcfGetINT32(file, format); 37723a0898aSmrg if (IS_EOF(file)) goto Bail; 37823a0898aSmrg if (!pcfGetMetric(file, format, &pFontInfo->minbounds)) 37923a0898aSmrg goto Bail; 38023a0898aSmrg if (!pcfGetMetric(file, format, &pFontInfo->maxbounds)) 38123a0898aSmrg goto Bail; 38223a0898aSmrg if (PCF_FORMAT_MATCH(format, PCF_ACCEL_W_INKBOUNDS)) { 38323a0898aSmrg if (!pcfGetMetric(file, format, &pFontInfo->ink_minbounds)) 38423a0898aSmrg goto Bail; 38523a0898aSmrg if (!pcfGetMetric(file, format, &pFontInfo->ink_maxbounds)) 38623a0898aSmrg goto Bail; 38723a0898aSmrg } else { 38823a0898aSmrg pFontInfo->ink_minbounds = pFontInfo->minbounds; 38923a0898aSmrg pFontInfo->ink_maxbounds = pFontInfo->maxbounds; 39023a0898aSmrg } 39123a0898aSmrg return TRUE; 39223a0898aSmrgBail: 39323a0898aSmrg return FALSE; 39423a0898aSmrg} 39523a0898aSmrg 39623a0898aSmrgint 3971a17810dSmrgpcfReadFont(FontPtr pFont, FontFilePtr file, 39823a0898aSmrg int bit, int byte, int glyph, int scan) 39923a0898aSmrg{ 40023a0898aSmrg CARD32 format; 40123a0898aSmrg CARD32 size; 40223a0898aSmrg BitmapFontPtr bitmapFont = 0; 40323a0898aSmrg int i; 40423a0898aSmrg PCFTablePtr tables = 0; 40523a0898aSmrg int ntables; 40623a0898aSmrg int nmetrics; 40723a0898aSmrg int nbitmaps; 40823a0898aSmrg int sizebitmaps; 40923a0898aSmrg int nink_metrics; 41023a0898aSmrg CharInfoPtr metrics = 0; 41123a0898aSmrg xCharInfo *ink_metrics = 0; 41223a0898aSmrg char *bitmaps = 0; 41323a0898aSmrg CharInfoPtr **encoding = 0; 41423a0898aSmrg int nencoding = 0; 41523a0898aSmrg int encodingOffset; 41623a0898aSmrg CARD32 bitmapSizes[GLYPHPADOPTIONS]; 41723a0898aSmrg CARD32 *offsets = 0; 41823a0898aSmrg Bool hasBDFAccelerators; 41923a0898aSmrg 42023a0898aSmrg pFont->info.nprops = 0; 42123a0898aSmrg pFont->info.props = 0; 4224b1cd807Scheusov pFont->info.isStringProp=0; 4234b1cd807Scheusov 42423a0898aSmrg if (!(tables = pcfReadTOC(file, &ntables))) 42523a0898aSmrg goto Bail; 42623a0898aSmrg 42723a0898aSmrg /* properties */ 42823a0898aSmrg 42923a0898aSmrg if (!pcfGetProperties(&pFont->info, file, tables, ntables)) 43023a0898aSmrg goto Bail; 43123a0898aSmrg 43223a0898aSmrg /* Use the old accelerators if no BDF accelerators are in the file */ 43323a0898aSmrg 43423a0898aSmrg hasBDFAccelerators = pcfHasType (tables, ntables, PCF_BDF_ACCELERATORS); 43523a0898aSmrg if (!hasBDFAccelerators) 43623a0898aSmrg if (!pcfGetAccel (&pFont->info, file, tables, ntables, PCF_ACCELERATORS)) 43723a0898aSmrg goto Bail; 43823a0898aSmrg 43923a0898aSmrg /* metrics */ 44023a0898aSmrg 44123a0898aSmrg if (!pcfSeekToType(file, tables, ntables, PCF_METRICS, &format, &size)) { 44223a0898aSmrg goto Bail; 44323a0898aSmrg } 44423a0898aSmrg format = pcfGetLSB32(file); 44523a0898aSmrg if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT) && 44623a0898aSmrg !PCF_FORMAT_MATCH(format, PCF_COMPRESSED_METRICS)) { 44723a0898aSmrg goto Bail; 44823a0898aSmrg } 44923a0898aSmrg if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) 45023a0898aSmrg nmetrics = pcfGetINT32(file, format); 45123a0898aSmrg else 45223a0898aSmrg nmetrics = pcfGetINT16(file, format); 45323a0898aSmrg if (IS_EOF(file)) goto Bail; 45423a0898aSmrg if (nmetrics < 0 || nmetrics > INT32_MAX / sizeof(CharInfoRec)) { 45523a0898aSmrg pcfError("pcfReadFont(): invalid file format\n"); 45623a0898aSmrg goto Bail; 45723a0898aSmrg } 4587f7f5e4eSmrg metrics = malloc(nmetrics * sizeof(CharInfoRec)); 45923a0898aSmrg if (!metrics) { 4601a17810dSmrg pcfError("pcfReadFont(): Couldn't allocate metrics (%d*%d)\n", 4611a17810dSmrg nmetrics, (int) sizeof(CharInfoRec)); 46223a0898aSmrg goto Bail; 46323a0898aSmrg } 46423a0898aSmrg for (i = 0; i < nmetrics; i++) 46523a0898aSmrg if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) { 46623a0898aSmrg if (!pcfGetMetric(file, format, &(metrics + i)->metrics)) 46723a0898aSmrg goto Bail; 46823a0898aSmrg } else { 46923a0898aSmrg if (!pcfGetCompressedMetric(file, format, &(metrics + i)->metrics)) 47023a0898aSmrg goto Bail; 47123a0898aSmrg } 4721a17810dSmrg 47323a0898aSmrg /* bitmaps */ 47423a0898aSmrg 47523a0898aSmrg if (!pcfSeekToType(file, tables, ntables, PCF_BITMAPS, &format, &size)) 47623a0898aSmrg goto Bail; 47723a0898aSmrg format = pcfGetLSB32(file); 47823a0898aSmrg if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) 47923a0898aSmrg goto Bail; 48023a0898aSmrg 48123a0898aSmrg nbitmaps = pcfGetINT32(file, format); 48223a0898aSmrg if (nbitmaps != nmetrics || IS_EOF(file)) 48323a0898aSmrg goto Bail; 48423a0898aSmrg /* nmetrics is already ok, so nbitmap also is */ 4857f7f5e4eSmrg offsets = malloc(nbitmaps * sizeof(CARD32)); 48623a0898aSmrg if (!offsets) { 4871a17810dSmrg pcfError("pcfReadFont(): Couldn't allocate offsets (%d*%d)\n", 4881a17810dSmrg nbitmaps, (int) sizeof(CARD32)); 48923a0898aSmrg goto Bail; 49023a0898aSmrg } 49123a0898aSmrg for (i = 0; i < nbitmaps; i++) { 49223a0898aSmrg offsets[i] = pcfGetINT32(file, format); 49323a0898aSmrg if (IS_EOF(file)) goto Bail; 49423a0898aSmrg } 49523a0898aSmrg 49623a0898aSmrg for (i = 0; i < GLYPHPADOPTIONS; i++) { 49723a0898aSmrg bitmapSizes[i] = pcfGetINT32(file, format); 49823a0898aSmrg if (IS_EOF(file)) goto Bail; 49923a0898aSmrg } 5001a17810dSmrg 50123a0898aSmrg sizebitmaps = bitmapSizes[PCF_GLYPH_PAD_INDEX(format)]; 50223a0898aSmrg /* guard against completely empty font */ 5037f7f5e4eSmrg bitmaps = malloc(sizebitmaps ? sizebitmaps : 1); 50423a0898aSmrg if (!bitmaps) { 50523a0898aSmrg pcfError("pcfReadFont(): Couldn't allocate bitmaps (%d)\n", sizebitmaps ? sizebitmaps : 1); 50623a0898aSmrg goto Bail; 50723a0898aSmrg } 50823a0898aSmrg FontFileRead(file, bitmaps, sizebitmaps); 50923a0898aSmrg if (IS_EOF(file)) goto Bail; 51023a0898aSmrg position += sizebitmaps; 51123a0898aSmrg 51223a0898aSmrg if (PCF_BIT_ORDER(format) != bit) 51323a0898aSmrg BitOrderInvert((unsigned char *)bitmaps, sizebitmaps); 51423a0898aSmrg if ((PCF_BYTE_ORDER(format) == PCF_BIT_ORDER(format)) != (bit == byte)) { 51523a0898aSmrg switch (bit == byte ? PCF_SCAN_UNIT(format) : scan) { 51623a0898aSmrg case 1: 51723a0898aSmrg break; 51823a0898aSmrg case 2: 51923a0898aSmrg TwoByteSwap((unsigned char *)bitmaps, sizebitmaps); 52023a0898aSmrg break; 52123a0898aSmrg case 4: 52223a0898aSmrg FourByteSwap((unsigned char *)bitmaps, sizebitmaps); 52323a0898aSmrg break; 52423a0898aSmrg } 52523a0898aSmrg } 52623a0898aSmrg if (PCF_GLYPH_PAD(format) != glyph) { 52723a0898aSmrg char *padbitmaps; 52823a0898aSmrg int sizepadbitmaps; 52923a0898aSmrg int old, 53023a0898aSmrg new; 53123a0898aSmrg xCharInfo *metric; 53223a0898aSmrg 53323a0898aSmrg sizepadbitmaps = bitmapSizes[PCF_SIZE_TO_INDEX(glyph)]; 5347f7f5e4eSmrg padbitmaps = malloc(sizepadbitmaps); 53523a0898aSmrg if (!padbitmaps) { 53623a0898aSmrg pcfError("pcfReadFont(): Couldn't allocate padbitmaps (%d)\n", sizepadbitmaps); 53723a0898aSmrg goto Bail; 53823a0898aSmrg } 53923a0898aSmrg new = 0; 54023a0898aSmrg for (i = 0; i < nbitmaps; i++) { 54123a0898aSmrg old = offsets[i]; 54223a0898aSmrg metric = &metrics[i].metrics; 54323a0898aSmrg offsets[i] = new; 54423a0898aSmrg new += RepadBitmap(bitmaps + old, padbitmaps + new, 54523a0898aSmrg PCF_GLYPH_PAD(format), glyph, 54623a0898aSmrg metric->rightSideBearing - metric->leftSideBearing, 54723a0898aSmrg metric->ascent + metric->descent); 54823a0898aSmrg } 5497f7f5e4eSmrg free(bitmaps); 55023a0898aSmrg bitmaps = padbitmaps; 55123a0898aSmrg } 55223a0898aSmrg for (i = 0; i < nbitmaps; i++) 55323a0898aSmrg metrics[i].bits = bitmaps + offsets[i]; 55423a0898aSmrg 5557f7f5e4eSmrg free(offsets); 55623a0898aSmrg offsets = NULL; 55723a0898aSmrg 55823a0898aSmrg /* ink metrics ? */ 55923a0898aSmrg 56023a0898aSmrg ink_metrics = NULL; 56123a0898aSmrg if (pcfSeekToType(file, tables, ntables, PCF_INK_METRICS, &format, &size)) { 56223a0898aSmrg format = pcfGetLSB32(file); 56323a0898aSmrg if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT) && 56423a0898aSmrg !PCF_FORMAT_MATCH(format, PCF_COMPRESSED_METRICS)) { 56523a0898aSmrg goto Bail; 56623a0898aSmrg } 56723a0898aSmrg if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) 56823a0898aSmrg nink_metrics = pcfGetINT32(file, format); 56923a0898aSmrg else 57023a0898aSmrg nink_metrics = pcfGetINT16(file, format); 57123a0898aSmrg if (IS_EOF(file)) goto Bail; 57223a0898aSmrg if (nink_metrics != nmetrics) 57323a0898aSmrg goto Bail; 57423a0898aSmrg /* nmetrics already checked */ 5757f7f5e4eSmrg ink_metrics = malloc(nink_metrics * sizeof(xCharInfo)); 5761a17810dSmrg if (!ink_metrics) { 5771a17810dSmrg pcfError("pcfReadFont(): Couldn't allocate ink_metrics (%d*%d)\n", 5781a17810dSmrg nink_metrics, (int) sizeof(xCharInfo)); 57923a0898aSmrg goto Bail; 5801a17810dSmrg } 58123a0898aSmrg for (i = 0; i < nink_metrics; i++) 58223a0898aSmrg if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) { 58323a0898aSmrg if (!pcfGetMetric(file, format, ink_metrics + i)) 58423a0898aSmrg goto Bail; 58523a0898aSmrg } else { 58623a0898aSmrg if (!pcfGetCompressedMetric(file, format, ink_metrics + i)) 58723a0898aSmrg goto Bail; 58823a0898aSmrg } 58923a0898aSmrg } 59023a0898aSmrg 59123a0898aSmrg /* encoding */ 59223a0898aSmrg 59323a0898aSmrg if (!pcfSeekToType(file, tables, ntables, PCF_BDF_ENCODINGS, &format, &size)) 59423a0898aSmrg goto Bail; 59523a0898aSmrg format = pcfGetLSB32(file); 59623a0898aSmrg if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) 59723a0898aSmrg goto Bail; 59823a0898aSmrg 59923a0898aSmrg pFont->info.firstCol = pcfGetINT16(file, format); 60023a0898aSmrg pFont->info.lastCol = pcfGetINT16(file, format); 60123a0898aSmrg pFont->info.firstRow = pcfGetINT16(file, format); 60223a0898aSmrg pFont->info.lastRow = pcfGetINT16(file, format); 60323a0898aSmrg pFont->info.defaultCh = pcfGetINT16(file, format); 60423a0898aSmrg if (IS_EOF(file)) goto Bail; 60523a0898aSmrg if (pFont->info.firstCol > pFont->info.lastCol || 60623a0898aSmrg pFont->info.firstRow > pFont->info.lastRow || 60723a0898aSmrg pFont->info.lastCol-pFont->info.firstCol > 255) goto Bail; 60823a0898aSmrg 60923a0898aSmrg nencoding = (pFont->info.lastCol - pFont->info.firstCol + 1) * 61023a0898aSmrg (pFont->info.lastRow - pFont->info.firstRow + 1); 61123a0898aSmrg 6127f7f5e4eSmrg encoding = calloc(NUM_SEGMENTS(nencoding), sizeof(CharInfoPtr*)); 61323a0898aSmrg if (!encoding) { 6141a17810dSmrg pcfError("pcfReadFont(): Couldn't allocate encoding (%d*%d)\n", 6151a17810dSmrg nencoding, (int) sizeof(CharInfoPtr)); 61623a0898aSmrg goto Bail; 61723a0898aSmrg } 6181a17810dSmrg 61923a0898aSmrg pFont->info.allExist = TRUE; 62023a0898aSmrg for (i = 0; i < nencoding; i++) { 62123a0898aSmrg encodingOffset = pcfGetINT16(file, format); 62223a0898aSmrg if (IS_EOF(file)) goto Bail; 62323a0898aSmrg if (encodingOffset == 0xFFFF) { 62423a0898aSmrg pFont->info.allExist = FALSE; 62523a0898aSmrg } else { 62623a0898aSmrg if(!encoding[SEGMENT_MAJOR(i)]) { 62723a0898aSmrg encoding[SEGMENT_MAJOR(i)]= 6287f7f5e4eSmrg calloc(BITMAP_FONT_SEGMENT_SIZE, sizeof(CharInfoPtr)); 62923a0898aSmrg if(!encoding[SEGMENT_MAJOR(i)]) 63023a0898aSmrg goto Bail; 63123a0898aSmrg } 63223a0898aSmrg ACCESSENCODINGL(encoding, i) = metrics + encodingOffset; 63323a0898aSmrg } 63423a0898aSmrg } 63523a0898aSmrg 63623a0898aSmrg /* BDF style accelerators (i.e. bounds based on encoded glyphs) */ 63723a0898aSmrg 63823a0898aSmrg if (hasBDFAccelerators) 63923a0898aSmrg if (!pcfGetAccel (&pFont->info, file, tables, ntables, PCF_BDF_ACCELERATORS)) 64023a0898aSmrg goto Bail; 64123a0898aSmrg 6427f7f5e4eSmrg bitmapFont = malloc(sizeof *bitmapFont); 64323a0898aSmrg if (!bitmapFont) { 6441a17810dSmrg pcfError("pcfReadFont(): Couldn't allocate bitmapFont (%d)\n", 6451a17810dSmrg (int) sizeof *bitmapFont); 64623a0898aSmrg goto Bail; 64723a0898aSmrg } 64823a0898aSmrg 64923a0898aSmrg bitmapFont->version_num = PCF_FILE_VERSION; 65023a0898aSmrg bitmapFont->num_chars = nmetrics; 65123a0898aSmrg bitmapFont->num_tables = ntables; 65223a0898aSmrg bitmapFont->metrics = metrics; 65323a0898aSmrg bitmapFont->ink_metrics = ink_metrics; 65423a0898aSmrg bitmapFont->bitmaps = bitmaps; 65523a0898aSmrg bitmapFont->encoding = encoding; 65623a0898aSmrg bitmapFont->pDefault = (CharInfoPtr) 0; 65723a0898aSmrg if (pFont->info.defaultCh != (unsigned short) NO_SUCH_CHAR) { 65823a0898aSmrg unsigned int r, 65923a0898aSmrg c, 66023a0898aSmrg cols; 66123a0898aSmrg 66223a0898aSmrg r = pFont->info.defaultCh >> 8; 66323a0898aSmrg c = pFont->info.defaultCh & 0xFF; 66423a0898aSmrg if (pFont->info.firstRow <= r && r <= pFont->info.lastRow && 66523a0898aSmrg pFont->info.firstCol <= c && c <= pFont->info.lastCol) { 66623a0898aSmrg cols = pFont->info.lastCol - pFont->info.firstCol + 1; 66723a0898aSmrg r = r - pFont->info.firstRow; 66823a0898aSmrg c = c - pFont->info.firstCol; 66923a0898aSmrg bitmapFont->pDefault = ACCESSENCODING(encoding, r * cols + c); 67023a0898aSmrg } 67123a0898aSmrg } 67223a0898aSmrg bitmapFont->bitmapExtra = (BitmapExtraPtr) 0; 67323a0898aSmrg pFont->fontPrivate = (pointer) bitmapFont; 67423a0898aSmrg pFont->get_glyphs = bitmapGetGlyphs; 67523a0898aSmrg pFont->get_metrics = bitmapGetMetrics; 67623a0898aSmrg pFont->unload_font = pcfUnloadFont; 67723a0898aSmrg pFont->unload_glyphs = NULL; 67823a0898aSmrg pFont->bit = bit; 67923a0898aSmrg pFont->byte = byte; 68023a0898aSmrg pFont->glyph = glyph; 68123a0898aSmrg pFont->scan = scan; 6827f7f5e4eSmrg free(tables); 68323a0898aSmrg return Successful; 68423a0898aSmrgBail: 6857f7f5e4eSmrg free(ink_metrics); 68623a0898aSmrg if(encoding) { 68723a0898aSmrg for(i=0; i<NUM_SEGMENTS(nencoding); i++) 6887f7f5e4eSmrg free(encoding[i]); 68923a0898aSmrg } 6907f7f5e4eSmrg free(encoding); 6917f7f5e4eSmrg free(bitmaps); 6927f7f5e4eSmrg free(metrics); 6937f7f5e4eSmrg free(pFont->info.props); 69423a0898aSmrg pFont->info.nprops = 0; 69523a0898aSmrg pFont->info.props = 0; 6967f7f5e4eSmrg free (pFont->info.isStringProp); 6977f7f5e4eSmrg free(bitmapFont); 6987f7f5e4eSmrg free(tables); 6997f7f5e4eSmrg free(offsets); 70023a0898aSmrg return AllocError; 70123a0898aSmrg} 70223a0898aSmrg 70323a0898aSmrgint 70423a0898aSmrgpcfReadFontInfo(FontInfoPtr pFontInfo, FontFilePtr file) 70523a0898aSmrg{ 70623a0898aSmrg PCFTablePtr tables; 70723a0898aSmrg int ntables; 70823a0898aSmrg CARD32 format; 70923a0898aSmrg CARD32 size; 71023a0898aSmrg int nencoding; 71123a0898aSmrg Bool hasBDFAccelerators; 71223a0898aSmrg 71323a0898aSmrg pFontInfo->isStringProp = NULL; 71423a0898aSmrg pFontInfo->props = NULL; 71523a0898aSmrg pFontInfo->nprops = 0; 71623a0898aSmrg 71723a0898aSmrg if (!(tables = pcfReadTOC(file, &ntables))) 71823a0898aSmrg goto Bail; 71923a0898aSmrg 72023a0898aSmrg /* properties */ 72123a0898aSmrg 72223a0898aSmrg if (!pcfGetProperties(pFontInfo, file, tables, ntables)) 72323a0898aSmrg goto Bail; 72423a0898aSmrg 72523a0898aSmrg /* Use the old accelerators if no BDF accelerators are in the file */ 72623a0898aSmrg 72723a0898aSmrg hasBDFAccelerators = pcfHasType (tables, ntables, PCF_BDF_ACCELERATORS); 72823a0898aSmrg if (!hasBDFAccelerators) 72923a0898aSmrg if (!pcfGetAccel (pFontInfo, file, tables, ntables, PCF_ACCELERATORS)) 73023a0898aSmrg goto Bail; 73123a0898aSmrg 73223a0898aSmrg /* encoding */ 73323a0898aSmrg 73423a0898aSmrg if (!pcfSeekToType(file, tables, ntables, PCF_BDF_ENCODINGS, &format, &size)) 73523a0898aSmrg goto Bail; 73623a0898aSmrg format = pcfGetLSB32(file); 73723a0898aSmrg if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) 73823a0898aSmrg goto Bail; 73923a0898aSmrg 74023a0898aSmrg pFontInfo->firstCol = pcfGetINT16(file, format); 74123a0898aSmrg pFontInfo->lastCol = pcfGetINT16(file, format); 74223a0898aSmrg pFontInfo->firstRow = pcfGetINT16(file, format); 74323a0898aSmrg pFontInfo->lastRow = pcfGetINT16(file, format); 74423a0898aSmrg pFontInfo->defaultCh = pcfGetINT16(file, format); 74523a0898aSmrg if (IS_EOF(file)) goto Bail; 74623a0898aSmrg if (pFontInfo->firstCol > pFontInfo->lastCol || 74723a0898aSmrg pFontInfo->firstRow > pFontInfo->lastRow || 74823a0898aSmrg pFontInfo->lastCol-pFontInfo->firstCol > 255) goto Bail; 74923a0898aSmrg 75023a0898aSmrg nencoding = (pFontInfo->lastCol - pFontInfo->firstCol + 1) * 75123a0898aSmrg (pFontInfo->lastRow - pFontInfo->firstRow + 1); 75223a0898aSmrg 75323a0898aSmrg pFontInfo->allExist = TRUE; 75423a0898aSmrg while (nencoding--) { 75523a0898aSmrg if (pcfGetINT16(file, format) == 0xFFFF) 75623a0898aSmrg pFontInfo->allExist = FALSE; 75723a0898aSmrg if (IS_EOF(file)) goto Bail; 75823a0898aSmrg } 75923a0898aSmrg if (IS_EOF(file)) goto Bail; 76023a0898aSmrg 76123a0898aSmrg /* BDF style accelerators (i.e. bounds based on encoded glyphs) */ 76223a0898aSmrg 76323a0898aSmrg if (hasBDFAccelerators) 76423a0898aSmrg if (!pcfGetAccel (pFontInfo, file, tables, ntables, PCF_BDF_ACCELERATORS)) 76523a0898aSmrg goto Bail; 76623a0898aSmrg 7677f7f5e4eSmrg free(tables); 76823a0898aSmrg return Successful; 76923a0898aSmrgBail: 77023a0898aSmrg pFontInfo->nprops = 0; 7717f7f5e4eSmrg free (pFontInfo->props); 7727f7f5e4eSmrg free (pFontInfo->isStringProp); 7737f7f5e4eSmrg free(tables); 77423a0898aSmrg return AllocError; 77523a0898aSmrg} 77623a0898aSmrg 77723a0898aSmrgstatic void 77823a0898aSmrgpcfUnloadFont(FontPtr pFont) 77923a0898aSmrg{ 78023a0898aSmrg BitmapFontPtr bitmapFont; 78123a0898aSmrg int i,nencoding; 78223a0898aSmrg 78323a0898aSmrg bitmapFont = (BitmapFontPtr) pFont->fontPrivate; 7847f7f5e4eSmrg free(bitmapFont->ink_metrics); 78523a0898aSmrg if(bitmapFont->encoding) { 78623a0898aSmrg nencoding = (pFont->info.lastCol - pFont->info.firstCol + 1) * 78723a0898aSmrg (pFont->info.lastRow - pFont->info.firstRow + 1); 78823a0898aSmrg for(i=0; i<NUM_SEGMENTS(nencoding); i++) 7897f7f5e4eSmrg free(bitmapFont->encoding[i]); 7907f7f5e4eSmrg } 7917f7f5e4eSmrg free(bitmapFont->encoding); 7927f7f5e4eSmrg free(bitmapFont->bitmaps); 7937f7f5e4eSmrg free(bitmapFont->metrics); 7947f7f5e4eSmrg free(pFont->info.isStringProp); 7957f7f5e4eSmrg free(pFont->info.props); 7967f7f5e4eSmrg free(bitmapFont); 79723a0898aSmrg DestroyFontRec(pFont); 79823a0898aSmrg} 799