pcfread.c revision 1a17810d
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>
4723a0898aSmrg
4823a0898aSmrgvoid
4923a0898aSmrgpcfError(const char* message, ...)
5023a0898aSmrg{
5123a0898aSmrg    va_list args;
5223a0898aSmrg
5323a0898aSmrg    va_start(args, message);
5423a0898aSmrg
5523a0898aSmrg    fprintf(stderr, "PCF Error: ");
5623a0898aSmrg    vfprintf(stderr, message, args);
5723a0898aSmrg    va_end(args);
5823a0898aSmrg}
591a17810dSmrg
6023a0898aSmrg/* Read PCF font files */
6123a0898aSmrg
6223a0898aSmrgstatic void pcfUnloadFont ( FontPtr pFont );
6323a0898aSmrgstatic int  position;
6423a0898aSmrg
6523a0898aSmrg
6623a0898aSmrg#define IS_EOF(file) ((file)->eof == BUFFILEEOF)
6723a0898aSmrg
6823a0898aSmrg#define FONT_FILE_GETC_ERR(f)  (tmp = FontFileGetc(f), BAIL_ON_EOF)
6923a0898aSmrg
7023a0898aSmrgstatic int
7123a0898aSmrgpcfGetLSB32(FontFilePtr file)
7223a0898aSmrg{
7323a0898aSmrg    int         c;
7423a0898aSmrg
7523a0898aSmrg    c = FontFileGetc(file);
7623a0898aSmrg    c |= FontFileGetc(file) << 8;
7723a0898aSmrg    c |= FontFileGetc(file) << 16;
7823a0898aSmrg    c |= FontFileGetc(file) << 24;
7923a0898aSmrg    position += 4;
8023a0898aSmrg    return c;
8123a0898aSmrg}
8223a0898aSmrg
8323a0898aSmrgstatic int
8423a0898aSmrgpcfGetINT32(FontFilePtr file, CARD32 format)
8523a0898aSmrg{
8623a0898aSmrg    int         c;
8723a0898aSmrg
8823a0898aSmrg    if (PCF_BYTE_ORDER(format) == MSBFirst) {
8923a0898aSmrg	c = FontFileGetc(file) << 24;
9023a0898aSmrg	c |= FontFileGetc(file) << 16;
9123a0898aSmrg	c |= FontFileGetc(file) << 8;
9223a0898aSmrg	c |= FontFileGetc(file);
9323a0898aSmrg    } else {
9423a0898aSmrg	c = FontFileGetc(file);
9523a0898aSmrg	c |= FontFileGetc(file) << 8;
9623a0898aSmrg	c |= FontFileGetc(file) << 16;
9723a0898aSmrg	c |= FontFileGetc(file) << 24;
9823a0898aSmrg    }
9923a0898aSmrg    position += 4;
10023a0898aSmrg    return c;
10123a0898aSmrg}
10223a0898aSmrg
10323a0898aSmrgstatic int
10423a0898aSmrgpcfGetINT16(FontFilePtr file, CARD32 format)
10523a0898aSmrg{
10623a0898aSmrg    int         c;
10723a0898aSmrg
10823a0898aSmrg    if (PCF_BYTE_ORDER(format) == MSBFirst) {
10923a0898aSmrg	c = FontFileGetc(file) << 8;
11023a0898aSmrg	c |= FontFileGetc(file);
11123a0898aSmrg    } else {
11223a0898aSmrg	c = FontFileGetc(file);
11323a0898aSmrg	c |= FontFileGetc(file) << 8;
11423a0898aSmrg    }
11523a0898aSmrg    position += 2;
11623a0898aSmrg    return c;
11723a0898aSmrg}
11823a0898aSmrg
11923a0898aSmrg#define pcfGetINT8(file, format) (position++, FontFileGetc(file))
12023a0898aSmrg
12123a0898aSmrgstatic      PCFTablePtr
12223a0898aSmrgpcfReadTOC(FontFilePtr file, int *countp)
12323a0898aSmrg{
12423a0898aSmrg    CARD32      version;
12523a0898aSmrg    PCFTablePtr tables;
12623a0898aSmrg    int         count;
12723a0898aSmrg    int         i;
12823a0898aSmrg
12923a0898aSmrg    position = 0;
13023a0898aSmrg    version = pcfGetLSB32(file);
13123a0898aSmrg    if (version != PCF_FILE_VERSION)
13223a0898aSmrg	return (PCFTablePtr) NULL;
13323a0898aSmrg    count = pcfGetLSB32(file);
13423a0898aSmrg    if (IS_EOF(file)) return (PCFTablePtr) NULL;
13523a0898aSmrg    if (count < 0 || count > INT32_MAX / sizeof(PCFTableRec)) {
13623a0898aSmrg	pcfError("pcfReadTOC(): invalid file format\n");
13723a0898aSmrg	return NULL;
13823a0898aSmrg    }
1397f7f5e4eSmrg    tables = malloc(count * sizeof(PCFTableRec));
14023a0898aSmrg    if (!tables) {
1411a17810dSmrg	pcfError("pcfReadTOC(): Couldn't allocate tables (%d*%d)\n",
1421a17810dSmrg		 count, (int) 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
2011a17810dSmrgpcfSeekToType(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/*
2321a17810dSmrg * 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
2391a17810dSmrgpcfGetProperties(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) {
2661a17810dSmrg	pcfError("pcfGetProperties(): Couldn't allocate props (%d*%d)\n",
2671a17810dSmrg	       nprops, (int) sizeof(FontPropRec));
26823a0898aSmrg	goto Bail;
26923a0898aSmrg    }
2707f7f5e4eSmrg    isStringProp = malloc(nprops * sizeof(char));
27123a0898aSmrg    if (!isStringProp) {
2721a17810dSmrg	pcfError("pcfGetProperties(): Couldn't allocate isStringProp (%d*%d)\n",
2731a17810dSmrg	       nprops, (int) sizeof(char));
27423a0898aSmrg	goto Bail;
27523a0898aSmrg    }
27623a0898aSmrg    for (i = 0; i < nprops; i++) {
27723a0898aSmrg	props[i].name = pcfGetINT32(file, format);
27823a0898aSmrg	isStringProp[i] = pcfGetINT8(file, format);
27923a0898aSmrg	props[i].value = pcfGetINT32(file, format);
2801a17810dSmrg	if (props[i].name < 0
28123a0898aSmrg	    || (isStringProp[i] != 0 && isStringProp[i] != 1)
28223a0898aSmrg	    || (isStringProp[i] && props[i].value < 0)) {
2831a17810dSmrg	    pcfError("pcfGetProperties(): invalid file format %ld %d %ld\n",
28423a0898aSmrg		     props[i].name, isStringProp[i], props[i].value);
28523a0898aSmrg	    goto Bail;
28623a0898aSmrg	}
28723a0898aSmrg	if (IS_EOF(file)) goto Bail;
28823a0898aSmrg    }
28923a0898aSmrg    /* pad the property array */
29023a0898aSmrg    /*
29123a0898aSmrg     * clever here - nprops is the same as the number of odd-units read, as
29223a0898aSmrg     * only isStringProp are odd length
29323a0898aSmrg     */
29423a0898aSmrg    if (nprops & 3)
29523a0898aSmrg    {
29623a0898aSmrg	i = 4 - (nprops & 3);
29723a0898aSmrg	(void)FontFileSkip(file, i);
29823a0898aSmrg	position += i;
29923a0898aSmrg    }
30023a0898aSmrg    if (IS_EOF(file)) goto Bail;
30123a0898aSmrg    string_size = pcfGetINT32(file, format);
30223a0898aSmrg    if (string_size < 0) goto Bail;
30323a0898aSmrg    if (IS_EOF(file)) goto Bail;
3047f7f5e4eSmrg    strings = malloc(string_size);
30523a0898aSmrg    if (!strings) {
30623a0898aSmrg      pcfError("pcfGetProperties(): Couldn't allocate strings (%d)\n", string_size);
30723a0898aSmrg	goto Bail;
30823a0898aSmrg    }
30923a0898aSmrg    FontFileRead(file, strings, string_size);
31023a0898aSmrg    if (IS_EOF(file)) goto Bail;
31123a0898aSmrg    position += string_size;
31223a0898aSmrg    for (i = 0; i < nprops; i++) {
31323a0898aSmrg	props[i].name = MakeAtom(strings + props[i].name,
31423a0898aSmrg				 strlen(strings + props[i].name), TRUE);
31523a0898aSmrg	if (isStringProp[i]) {
31623a0898aSmrg	    props[i].value = MakeAtom(strings + props[i].value,
31723a0898aSmrg				      strlen(strings + props[i].value), TRUE);
31823a0898aSmrg	}
31923a0898aSmrg    }
3207f7f5e4eSmrg    free(strings);
32123a0898aSmrg    pFontInfo->isStringProp = isStringProp;
32223a0898aSmrg    pFontInfo->props = props;
32323a0898aSmrg    pFontInfo->nprops = nprops;
32423a0898aSmrg    return TRUE;
32523a0898aSmrgBail:
3267f7f5e4eSmrg    free(isStringProp);
3277f7f5e4eSmrg    free(props);
32823a0898aSmrg    return FALSE;
32923a0898aSmrg}
33023a0898aSmrg
33123a0898aSmrg
33223a0898aSmrg/*
33323a0898aSmrg * pcfReadAccel
33423a0898aSmrg *
33523a0898aSmrg * Fill in the accelerator information from the font file; used
33623a0898aSmrg * to read both BDF_ACCELERATORS and old style ACCELERATORS
33723a0898aSmrg */
33823a0898aSmrg
33923a0898aSmrgstatic Bool
3401a17810dSmrgpcfGetAccel(FontInfoPtr pFontInfo, FontFilePtr file,
34123a0898aSmrg	    PCFTablePtr tables, int ntables, CARD32 type)
34223a0898aSmrg{
34323a0898aSmrg    CARD32      format;
34423a0898aSmrg    CARD32	size;
34523a0898aSmrg
34623a0898aSmrg    if (!pcfSeekToType(file, tables, ntables, type, &format, &size) ||
34723a0898aSmrg	IS_EOF(file))
34823a0898aSmrg	goto Bail;
34923a0898aSmrg    format = pcfGetLSB32(file);
35023a0898aSmrg    if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT) &&
3511a17810dSmrg	!PCF_FORMAT_MATCH(format, PCF_ACCEL_W_INKBOUNDS))
35223a0898aSmrg    {
35323a0898aSmrg	goto Bail;
35423a0898aSmrg    }
35523a0898aSmrg    pFontInfo->noOverlap = pcfGetINT8(file, format);
35623a0898aSmrg    pFontInfo->constantMetrics = pcfGetINT8(file, format);
35723a0898aSmrg    pFontInfo->terminalFont = pcfGetINT8(file, format);
35823a0898aSmrg    pFontInfo->constantWidth = pcfGetINT8(file, format);
35923a0898aSmrg    pFontInfo->inkInside = pcfGetINT8(file, format);
36023a0898aSmrg    pFontInfo->inkMetrics = pcfGetINT8(file, format);
36123a0898aSmrg    pFontInfo->drawDirection = pcfGetINT8(file, format);
36223a0898aSmrg    pFontInfo->anamorphic = FALSE;
36323a0898aSmrg    pFontInfo->cachable = TRUE;
36423a0898aSmrg     /* natural alignment */ pcfGetINT8(file, format);
36523a0898aSmrg    pFontInfo->fontAscent = pcfGetINT32(file, format);
36623a0898aSmrg    pFontInfo->fontDescent = pcfGetINT32(file, format);
36723a0898aSmrg    pFontInfo->maxOverlap = pcfGetINT32(file, format);
36823a0898aSmrg    if (IS_EOF(file)) goto Bail;
36923a0898aSmrg    if (!pcfGetMetric(file, format, &pFontInfo->minbounds))
37023a0898aSmrg	goto Bail;
37123a0898aSmrg    if (!pcfGetMetric(file, format, &pFontInfo->maxbounds))
37223a0898aSmrg	goto Bail;
37323a0898aSmrg    if (PCF_FORMAT_MATCH(format, PCF_ACCEL_W_INKBOUNDS)) {
37423a0898aSmrg	if (!pcfGetMetric(file, format, &pFontInfo->ink_minbounds))
37523a0898aSmrg	    goto Bail;
37623a0898aSmrg	if (!pcfGetMetric(file, format, &pFontInfo->ink_maxbounds))
37723a0898aSmrg	    goto Bail;
37823a0898aSmrg    } else {
37923a0898aSmrg	pFontInfo->ink_minbounds = pFontInfo->minbounds;
38023a0898aSmrg	pFontInfo->ink_maxbounds = pFontInfo->maxbounds;
38123a0898aSmrg    }
38223a0898aSmrg    return TRUE;
38323a0898aSmrgBail:
38423a0898aSmrg    return FALSE;
38523a0898aSmrg}
38623a0898aSmrg
38723a0898aSmrgint
3881a17810dSmrgpcfReadFont(FontPtr pFont, FontFilePtr file,
38923a0898aSmrg	    int bit, int byte, int glyph, int scan)
39023a0898aSmrg{
39123a0898aSmrg    CARD32      format;
39223a0898aSmrg    CARD32      size;
39323a0898aSmrg    BitmapFontPtr  bitmapFont = 0;
39423a0898aSmrg    int         i;
39523a0898aSmrg    PCFTablePtr tables = 0;
39623a0898aSmrg    int         ntables;
39723a0898aSmrg    int         nmetrics;
39823a0898aSmrg    int         nbitmaps;
39923a0898aSmrg    int         sizebitmaps;
40023a0898aSmrg    int         nink_metrics;
40123a0898aSmrg    CharInfoPtr metrics = 0;
40223a0898aSmrg    xCharInfo  *ink_metrics = 0;
40323a0898aSmrg    char       *bitmaps = 0;
40423a0898aSmrg    CharInfoPtr **encoding = 0;
40523a0898aSmrg    int         nencoding = 0;
40623a0898aSmrg    int         encodingOffset;
40723a0898aSmrg    CARD32      bitmapSizes[GLYPHPADOPTIONS];
40823a0898aSmrg    CARD32     *offsets = 0;
40923a0898aSmrg    Bool	hasBDFAccelerators;
41023a0898aSmrg
41123a0898aSmrg    pFont->info.nprops = 0;
41223a0898aSmrg    pFont->info.props = 0;
4134b1cd807Scheusov    pFont->info.isStringProp=0;
4144b1cd807Scheusov
41523a0898aSmrg    if (!(tables = pcfReadTOC(file, &ntables)))
41623a0898aSmrg	goto Bail;
41723a0898aSmrg
41823a0898aSmrg    /* properties */
41923a0898aSmrg
42023a0898aSmrg    if (!pcfGetProperties(&pFont->info, file, tables, ntables))
42123a0898aSmrg	goto Bail;
42223a0898aSmrg
42323a0898aSmrg    /* Use the old accelerators if no BDF accelerators are in the file */
42423a0898aSmrg
42523a0898aSmrg    hasBDFAccelerators = pcfHasType (tables, ntables, PCF_BDF_ACCELERATORS);
42623a0898aSmrg    if (!hasBDFAccelerators)
42723a0898aSmrg	if (!pcfGetAccel (&pFont->info, file, tables, ntables, PCF_ACCELERATORS))
42823a0898aSmrg	    goto Bail;
42923a0898aSmrg
43023a0898aSmrg    /* metrics */
43123a0898aSmrg
43223a0898aSmrg    if (!pcfSeekToType(file, tables, ntables, PCF_METRICS, &format, &size)) {
43323a0898aSmrg	goto Bail;
43423a0898aSmrg    }
43523a0898aSmrg    format = pcfGetLSB32(file);
43623a0898aSmrg    if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT) &&
43723a0898aSmrg	    !PCF_FORMAT_MATCH(format, PCF_COMPRESSED_METRICS)) {
43823a0898aSmrg	goto Bail;
43923a0898aSmrg    }
44023a0898aSmrg    if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT))
44123a0898aSmrg	nmetrics = pcfGetINT32(file, format);
44223a0898aSmrg    else
44323a0898aSmrg	nmetrics = pcfGetINT16(file, format);
44423a0898aSmrg    if (IS_EOF(file)) goto Bail;
44523a0898aSmrg    if (nmetrics < 0 || nmetrics > INT32_MAX / sizeof(CharInfoRec)) {
44623a0898aSmrg	pcfError("pcfReadFont(): invalid file format\n");
44723a0898aSmrg	goto Bail;
44823a0898aSmrg    }
4497f7f5e4eSmrg    metrics = malloc(nmetrics * sizeof(CharInfoRec));
45023a0898aSmrg    if (!metrics) {
4511a17810dSmrg	pcfError("pcfReadFont(): Couldn't allocate metrics (%d*%d)\n",
4521a17810dSmrg		 nmetrics, (int) sizeof(CharInfoRec));
45323a0898aSmrg	goto Bail;
45423a0898aSmrg    }
45523a0898aSmrg    for (i = 0; i < nmetrics; i++)
45623a0898aSmrg	if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) {
45723a0898aSmrg	    if (!pcfGetMetric(file, format, &(metrics + i)->metrics))
45823a0898aSmrg		goto Bail;
45923a0898aSmrg	} else {
46023a0898aSmrg	    if (!pcfGetCompressedMetric(file, format, &(metrics + i)->metrics))
46123a0898aSmrg		goto Bail;
46223a0898aSmrg	}
4631a17810dSmrg
46423a0898aSmrg    /* bitmaps */
46523a0898aSmrg
46623a0898aSmrg    if (!pcfSeekToType(file, tables, ntables, PCF_BITMAPS, &format, &size))
46723a0898aSmrg	goto Bail;
46823a0898aSmrg    format = pcfGetLSB32(file);
46923a0898aSmrg    if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT))
47023a0898aSmrg	goto Bail;
47123a0898aSmrg
47223a0898aSmrg    nbitmaps = pcfGetINT32(file, format);
47323a0898aSmrg    if (nbitmaps != nmetrics || IS_EOF(file))
47423a0898aSmrg	goto Bail;
47523a0898aSmrg    /* nmetrics is already ok, so nbitmap also is */
4767f7f5e4eSmrg    offsets = malloc(nbitmaps * sizeof(CARD32));
47723a0898aSmrg    if (!offsets) {
4781a17810dSmrg	pcfError("pcfReadFont(): Couldn't allocate offsets (%d*%d)\n",
4791a17810dSmrg		 nbitmaps, (int) sizeof(CARD32));
48023a0898aSmrg	goto Bail;
48123a0898aSmrg    }
48223a0898aSmrg    for (i = 0; i < nbitmaps; i++) {
48323a0898aSmrg	offsets[i] = pcfGetINT32(file, format);
48423a0898aSmrg	if (IS_EOF(file)) goto Bail;
48523a0898aSmrg    }
48623a0898aSmrg
48723a0898aSmrg    for (i = 0; i < GLYPHPADOPTIONS; i++) {
48823a0898aSmrg	bitmapSizes[i] = pcfGetINT32(file, format);
48923a0898aSmrg	if (IS_EOF(file)) goto Bail;
49023a0898aSmrg	if (bitmapSizes[i] < 0) goto Bail;
49123a0898aSmrg    }
4921a17810dSmrg
49323a0898aSmrg    sizebitmaps = bitmapSizes[PCF_GLYPH_PAD_INDEX(format)];
49423a0898aSmrg    /* guard against completely empty font */
4957f7f5e4eSmrg    bitmaps = malloc(sizebitmaps ? sizebitmaps : 1);
49623a0898aSmrg    if (!bitmaps) {
49723a0898aSmrg      pcfError("pcfReadFont(): Couldn't allocate bitmaps (%d)\n", sizebitmaps ? sizebitmaps : 1);
49823a0898aSmrg	goto Bail;
49923a0898aSmrg    }
50023a0898aSmrg    FontFileRead(file, bitmaps, sizebitmaps);
50123a0898aSmrg    if (IS_EOF(file)) goto Bail;
50223a0898aSmrg    position += sizebitmaps;
50323a0898aSmrg
50423a0898aSmrg    if (PCF_BIT_ORDER(format) != bit)
50523a0898aSmrg	BitOrderInvert((unsigned char *)bitmaps, sizebitmaps);
50623a0898aSmrg    if ((PCF_BYTE_ORDER(format) == PCF_BIT_ORDER(format)) != (bit == byte)) {
50723a0898aSmrg	switch (bit == byte ? PCF_SCAN_UNIT(format) : scan) {
50823a0898aSmrg	case 1:
50923a0898aSmrg	    break;
51023a0898aSmrg	case 2:
51123a0898aSmrg	    TwoByteSwap((unsigned char *)bitmaps, sizebitmaps);
51223a0898aSmrg	    break;
51323a0898aSmrg	case 4:
51423a0898aSmrg	    FourByteSwap((unsigned char *)bitmaps, sizebitmaps);
51523a0898aSmrg	    break;
51623a0898aSmrg	}
51723a0898aSmrg    }
51823a0898aSmrg    if (PCF_GLYPH_PAD(format) != glyph) {
51923a0898aSmrg	char       *padbitmaps;
52023a0898aSmrg	int         sizepadbitmaps;
52123a0898aSmrg	int         old,
52223a0898aSmrg	            new;
52323a0898aSmrg	xCharInfo  *metric;
52423a0898aSmrg
52523a0898aSmrg	sizepadbitmaps = bitmapSizes[PCF_SIZE_TO_INDEX(glyph)];
5267f7f5e4eSmrg	padbitmaps = malloc(sizepadbitmaps);
52723a0898aSmrg	if (!padbitmaps) {
52823a0898aSmrg          pcfError("pcfReadFont(): Couldn't allocate padbitmaps (%d)\n", sizepadbitmaps);
52923a0898aSmrg	    goto Bail;
53023a0898aSmrg	}
53123a0898aSmrg	new = 0;
53223a0898aSmrg	for (i = 0; i < nbitmaps; i++) {
53323a0898aSmrg	    old = offsets[i];
53423a0898aSmrg	    metric = &metrics[i].metrics;
53523a0898aSmrg	    offsets[i] = new;
53623a0898aSmrg	    new += RepadBitmap(bitmaps + old, padbitmaps + new,
53723a0898aSmrg			       PCF_GLYPH_PAD(format), glyph,
53823a0898aSmrg			  metric->rightSideBearing - metric->leftSideBearing,
53923a0898aSmrg			       metric->ascent + metric->descent);
54023a0898aSmrg	}
5417f7f5e4eSmrg	free(bitmaps);
54223a0898aSmrg	bitmaps = padbitmaps;
54323a0898aSmrg    }
54423a0898aSmrg    for (i = 0; i < nbitmaps; i++)
54523a0898aSmrg	metrics[i].bits = bitmaps + offsets[i];
54623a0898aSmrg
5477f7f5e4eSmrg    free(offsets);
54823a0898aSmrg    offsets = NULL;
54923a0898aSmrg
55023a0898aSmrg    /* ink metrics ? */
55123a0898aSmrg
55223a0898aSmrg    ink_metrics = NULL;
55323a0898aSmrg    if (pcfSeekToType(file, tables, ntables, PCF_INK_METRICS, &format, &size)) {
55423a0898aSmrg	format = pcfGetLSB32(file);
55523a0898aSmrg	if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT) &&
55623a0898aSmrg		!PCF_FORMAT_MATCH(format, PCF_COMPRESSED_METRICS)) {
55723a0898aSmrg	    goto Bail;
55823a0898aSmrg	}
55923a0898aSmrg	if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT))
56023a0898aSmrg	    nink_metrics = pcfGetINT32(file, format);
56123a0898aSmrg	else
56223a0898aSmrg	    nink_metrics = pcfGetINT16(file, format);
56323a0898aSmrg	if (IS_EOF(file)) goto Bail;
56423a0898aSmrg	if (nink_metrics != nmetrics)
56523a0898aSmrg	    goto Bail;
56623a0898aSmrg	/* nmetrics already checked */
5677f7f5e4eSmrg	ink_metrics = malloc(nink_metrics * sizeof(xCharInfo));
5681a17810dSmrg	if (!ink_metrics) {
5691a17810dSmrg            pcfError("pcfReadFont(): Couldn't allocate ink_metrics (%d*%d)\n",
5701a17810dSmrg		     nink_metrics, (int) sizeof(xCharInfo));
57123a0898aSmrg	    goto Bail;
5721a17810dSmrg	}
57323a0898aSmrg	for (i = 0; i < nink_metrics; i++)
57423a0898aSmrg	    if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) {
57523a0898aSmrg		if (!pcfGetMetric(file, format, ink_metrics + i))
57623a0898aSmrg		    goto Bail;
57723a0898aSmrg	    } else {
57823a0898aSmrg		if (!pcfGetCompressedMetric(file, format, ink_metrics + i))
57923a0898aSmrg		    goto Bail;
58023a0898aSmrg	    }
58123a0898aSmrg    }
58223a0898aSmrg
58323a0898aSmrg    /* encoding */
58423a0898aSmrg
58523a0898aSmrg    if (!pcfSeekToType(file, tables, ntables, PCF_BDF_ENCODINGS, &format, &size))
58623a0898aSmrg	goto Bail;
58723a0898aSmrg    format = pcfGetLSB32(file);
58823a0898aSmrg    if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT))
58923a0898aSmrg	goto Bail;
59023a0898aSmrg
59123a0898aSmrg    pFont->info.firstCol = pcfGetINT16(file, format);
59223a0898aSmrg    pFont->info.lastCol = pcfGetINT16(file, format);
59323a0898aSmrg    pFont->info.firstRow = pcfGetINT16(file, format);
59423a0898aSmrg    pFont->info.lastRow = pcfGetINT16(file, format);
59523a0898aSmrg    pFont->info.defaultCh = pcfGetINT16(file, format);
59623a0898aSmrg    if (IS_EOF(file)) goto Bail;
59723a0898aSmrg    if (pFont->info.firstCol > pFont->info.lastCol ||
59823a0898aSmrg       pFont->info.firstRow > pFont->info.lastRow ||
59923a0898aSmrg       pFont->info.lastCol-pFont->info.firstCol > 255) goto Bail;
60023a0898aSmrg
60123a0898aSmrg    nencoding = (pFont->info.lastCol - pFont->info.firstCol + 1) *
60223a0898aSmrg	(pFont->info.lastRow - pFont->info.firstRow + 1);
60323a0898aSmrg
6047f7f5e4eSmrg    encoding = calloc(NUM_SEGMENTS(nencoding), sizeof(CharInfoPtr*));
60523a0898aSmrg    if (!encoding) {
6061a17810dSmrg	pcfError("pcfReadFont(): Couldn't allocate encoding (%d*%d)\n",
6071a17810dSmrg		 nencoding, (int) sizeof(CharInfoPtr));
60823a0898aSmrg	goto Bail;
60923a0898aSmrg    }
6101a17810dSmrg
61123a0898aSmrg    pFont->info.allExist = TRUE;
61223a0898aSmrg    for (i = 0; i < nencoding; i++) {
61323a0898aSmrg	encodingOffset = pcfGetINT16(file, format);
61423a0898aSmrg	if (IS_EOF(file)) goto Bail;
61523a0898aSmrg	if (encodingOffset == 0xFFFF) {
61623a0898aSmrg	    pFont->info.allExist = FALSE;
61723a0898aSmrg	} else {
61823a0898aSmrg            if(!encoding[SEGMENT_MAJOR(i)]) {
61923a0898aSmrg                encoding[SEGMENT_MAJOR(i)]=
6207f7f5e4eSmrg                    calloc(BITMAP_FONT_SEGMENT_SIZE, sizeof(CharInfoPtr));
62123a0898aSmrg                if(!encoding[SEGMENT_MAJOR(i)])
62223a0898aSmrg                    goto Bail;
62323a0898aSmrg            }
62423a0898aSmrg	    ACCESSENCODINGL(encoding, i) = metrics + encodingOffset;
62523a0898aSmrg        }
62623a0898aSmrg    }
62723a0898aSmrg
62823a0898aSmrg    /* BDF style accelerators (i.e. bounds based on encoded glyphs) */
62923a0898aSmrg
63023a0898aSmrg    if (hasBDFAccelerators)
63123a0898aSmrg	if (!pcfGetAccel (&pFont->info, file, tables, ntables, PCF_BDF_ACCELERATORS))
63223a0898aSmrg	    goto Bail;
63323a0898aSmrg
6347f7f5e4eSmrg    bitmapFont = malloc(sizeof *bitmapFont);
63523a0898aSmrg    if (!bitmapFont) {
6361a17810dSmrg	pcfError("pcfReadFont(): Couldn't allocate bitmapFont (%d)\n",
6371a17810dSmrg		 (int) sizeof *bitmapFont);
63823a0898aSmrg	goto Bail;
63923a0898aSmrg    }
64023a0898aSmrg
64123a0898aSmrg    bitmapFont->version_num = PCF_FILE_VERSION;
64223a0898aSmrg    bitmapFont->num_chars = nmetrics;
64323a0898aSmrg    bitmapFont->num_tables = ntables;
64423a0898aSmrg    bitmapFont->metrics = metrics;
64523a0898aSmrg    bitmapFont->ink_metrics = ink_metrics;
64623a0898aSmrg    bitmapFont->bitmaps = bitmaps;
64723a0898aSmrg    bitmapFont->encoding = encoding;
64823a0898aSmrg    bitmapFont->pDefault = (CharInfoPtr) 0;
64923a0898aSmrg    if (pFont->info.defaultCh != (unsigned short) NO_SUCH_CHAR) {
65023a0898aSmrg	unsigned int r,
65123a0898aSmrg	            c,
65223a0898aSmrg	            cols;
65323a0898aSmrg
65423a0898aSmrg	r = pFont->info.defaultCh >> 8;
65523a0898aSmrg	c = pFont->info.defaultCh & 0xFF;
65623a0898aSmrg	if (pFont->info.firstRow <= r && r <= pFont->info.lastRow &&
65723a0898aSmrg		pFont->info.firstCol <= c && c <= pFont->info.lastCol) {
65823a0898aSmrg	    cols = pFont->info.lastCol - pFont->info.firstCol + 1;
65923a0898aSmrg	    r = r - pFont->info.firstRow;
66023a0898aSmrg	    c = c - pFont->info.firstCol;
66123a0898aSmrg	    bitmapFont->pDefault = ACCESSENCODING(encoding, r * cols + c);
66223a0898aSmrg	}
66323a0898aSmrg    }
66423a0898aSmrg    bitmapFont->bitmapExtra = (BitmapExtraPtr) 0;
66523a0898aSmrg    pFont->fontPrivate = (pointer) bitmapFont;
66623a0898aSmrg    pFont->get_glyphs = bitmapGetGlyphs;
66723a0898aSmrg    pFont->get_metrics = bitmapGetMetrics;
66823a0898aSmrg    pFont->unload_font = pcfUnloadFont;
66923a0898aSmrg    pFont->unload_glyphs = NULL;
67023a0898aSmrg    pFont->bit = bit;
67123a0898aSmrg    pFont->byte = byte;
67223a0898aSmrg    pFont->glyph = glyph;
67323a0898aSmrg    pFont->scan = scan;
6747f7f5e4eSmrg    free(tables);
67523a0898aSmrg    return Successful;
67623a0898aSmrgBail:
6777f7f5e4eSmrg    free(ink_metrics);
67823a0898aSmrg    if(encoding) {
67923a0898aSmrg        for(i=0; i<NUM_SEGMENTS(nencoding); i++)
6807f7f5e4eSmrg            free(encoding[i]);
68123a0898aSmrg    }
6827f7f5e4eSmrg    free(encoding);
6837f7f5e4eSmrg    free(bitmaps);
6847f7f5e4eSmrg    free(metrics);
6857f7f5e4eSmrg    free(pFont->info.props);
68623a0898aSmrg    pFont->info.nprops = 0;
68723a0898aSmrg    pFont->info.props = 0;
6887f7f5e4eSmrg    free (pFont->info.isStringProp);
6897f7f5e4eSmrg    free(bitmapFont);
6907f7f5e4eSmrg    free(tables);
6917f7f5e4eSmrg    free(offsets);
69223a0898aSmrg    return AllocError;
69323a0898aSmrg}
69423a0898aSmrg
69523a0898aSmrgint
69623a0898aSmrgpcfReadFontInfo(FontInfoPtr pFontInfo, FontFilePtr file)
69723a0898aSmrg{
69823a0898aSmrg    PCFTablePtr tables;
69923a0898aSmrg    int         ntables;
70023a0898aSmrg    CARD32      format;
70123a0898aSmrg    CARD32      size;
70223a0898aSmrg    int         nencoding;
70323a0898aSmrg    Bool	hasBDFAccelerators;
70423a0898aSmrg
70523a0898aSmrg    pFontInfo->isStringProp = NULL;
70623a0898aSmrg    pFontInfo->props = NULL;
70723a0898aSmrg    pFontInfo->nprops = 0;
70823a0898aSmrg
70923a0898aSmrg    if (!(tables = pcfReadTOC(file, &ntables)))
71023a0898aSmrg	goto Bail;
71123a0898aSmrg
71223a0898aSmrg    /* properties */
71323a0898aSmrg
71423a0898aSmrg    if (!pcfGetProperties(pFontInfo, file, tables, ntables))
71523a0898aSmrg	goto Bail;
71623a0898aSmrg
71723a0898aSmrg    /* Use the old accelerators if no BDF accelerators are in the file */
71823a0898aSmrg
71923a0898aSmrg    hasBDFAccelerators = pcfHasType (tables, ntables, PCF_BDF_ACCELERATORS);
72023a0898aSmrg    if (!hasBDFAccelerators)
72123a0898aSmrg	if (!pcfGetAccel (pFontInfo, file, tables, ntables, PCF_ACCELERATORS))
72223a0898aSmrg	    goto Bail;
72323a0898aSmrg
72423a0898aSmrg    /* encoding */
72523a0898aSmrg
72623a0898aSmrg    if (!pcfSeekToType(file, tables, ntables, PCF_BDF_ENCODINGS, &format, &size))
72723a0898aSmrg	goto Bail;
72823a0898aSmrg    format = pcfGetLSB32(file);
72923a0898aSmrg    if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT))
73023a0898aSmrg	goto Bail;
73123a0898aSmrg
73223a0898aSmrg    pFontInfo->firstCol = pcfGetINT16(file, format);
73323a0898aSmrg    pFontInfo->lastCol = pcfGetINT16(file, format);
73423a0898aSmrg    pFontInfo->firstRow = pcfGetINT16(file, format);
73523a0898aSmrg    pFontInfo->lastRow = pcfGetINT16(file, format);
73623a0898aSmrg    pFontInfo->defaultCh = pcfGetINT16(file, format);
73723a0898aSmrg    if (IS_EOF(file)) goto Bail;
73823a0898aSmrg    if (pFontInfo->firstCol > pFontInfo->lastCol ||
73923a0898aSmrg       pFontInfo->firstRow > pFontInfo->lastRow ||
74023a0898aSmrg       pFontInfo->lastCol-pFontInfo->firstCol > 255) goto Bail;
74123a0898aSmrg
74223a0898aSmrg    nencoding = (pFontInfo->lastCol - pFontInfo->firstCol + 1) *
74323a0898aSmrg	(pFontInfo->lastRow - pFontInfo->firstRow + 1);
74423a0898aSmrg
74523a0898aSmrg    pFontInfo->allExist = TRUE;
74623a0898aSmrg    while (nencoding--) {
74723a0898aSmrg	if (pcfGetINT16(file, format) == 0xFFFF)
74823a0898aSmrg	    pFontInfo->allExist = FALSE;
74923a0898aSmrg	if (IS_EOF(file)) goto Bail;
75023a0898aSmrg    }
75123a0898aSmrg    if (IS_EOF(file)) goto Bail;
75223a0898aSmrg
75323a0898aSmrg    /* BDF style accelerators (i.e. bounds based on encoded glyphs) */
75423a0898aSmrg
75523a0898aSmrg    if (hasBDFAccelerators)
75623a0898aSmrg	if (!pcfGetAccel (pFontInfo, file, tables, ntables, PCF_BDF_ACCELERATORS))
75723a0898aSmrg	    goto Bail;
75823a0898aSmrg
7597f7f5e4eSmrg    free(tables);
76023a0898aSmrg    return Successful;
76123a0898aSmrgBail:
76223a0898aSmrg    pFontInfo->nprops = 0;
7637f7f5e4eSmrg    free (pFontInfo->props);
7647f7f5e4eSmrg    free (pFontInfo->isStringProp);
7657f7f5e4eSmrg    free(tables);
76623a0898aSmrg    return AllocError;
76723a0898aSmrg}
76823a0898aSmrg
76923a0898aSmrgstatic void
77023a0898aSmrgpcfUnloadFont(FontPtr pFont)
77123a0898aSmrg{
77223a0898aSmrg    BitmapFontPtr  bitmapFont;
77323a0898aSmrg    int i,nencoding;
77423a0898aSmrg
77523a0898aSmrg    bitmapFont = (BitmapFontPtr) pFont->fontPrivate;
7767f7f5e4eSmrg    free(bitmapFont->ink_metrics);
77723a0898aSmrg    if(bitmapFont->encoding) {
77823a0898aSmrg        nencoding = (pFont->info.lastCol - pFont->info.firstCol + 1) *
77923a0898aSmrg	    (pFont->info.lastRow - pFont->info.firstRow + 1);
78023a0898aSmrg        for(i=0; i<NUM_SEGMENTS(nencoding); i++)
7817f7f5e4eSmrg            free(bitmapFont->encoding[i]);
7827f7f5e4eSmrg    }
7837f7f5e4eSmrg    free(bitmapFont->encoding);
7847f7f5e4eSmrg    free(bitmapFont->bitmaps);
7857f7f5e4eSmrg    free(bitmapFont->metrics);
7867f7f5e4eSmrg    free(pFont->info.isStringProp);
7877f7f5e4eSmrg    free(pFont->info.props);
7887f7f5e4eSmrg    free(bitmapFont);
78923a0898aSmrg    DestroyFontRec(pFont);
79023a0898aSmrg}
791