pcfread.c revision f262af57
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