src/cmd/mp/pcf.c
author hnhn
Wed, 08 Oct 2008 12:13:30 +0200
changeset 294 9f7722099844
parent 0 542988ea726d
permissions -rw-r--r--
6754368: mp.conf patch for OpenSolaris

/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").  
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright (c) 1999 by Sun Microsystems, Inc.
 * All rights reserved.
 */
/*
 * Copyright (C) 1994 X Consortium
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 * X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
 * TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Except as contained in this notice, the name of the X Consortium shall not
 * be used in advertising or otherwise to promote the sale, use or other deal-
 * ings in this Software without prior written authorization from the X Consor-
 * tium.
 *
 * X Window System is a trademark of X Consortium, Inc.
 */
#pragma ident   "@(#)pcf.c	1.3 00/02/02 SMI"
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <X11/Xmd.h>
#include <assert.h>
#include <errno.h>
#include "general_header.h"
#include "print_preprocess.h"
#include "pcf_private.h"
#include "pcf.h"
#define pcfGetINT8(file, format) (position++, FontFileGetc(file))
#define FileDes(f)  ((int) (f)->private)

extern print_info	*print_info_st;

static void dump_Fmetrics(pcffont_t *);
static code_int getcode(CompressedFile *);
static int BufFileClose(BufFilePtr,int);
static int get_font_property(FontPtr, char *, ulong_t *);
static BufFilePtr BufFileCreate ( char *, int (*)(), int (*)(),int (*)() );
static int BufCompressedClose(BufFilePtr, int);
static int BufCompressedSkip(BufFilePtr, int);
static int BufCompressedFill(BufFilePtr);
static BufFilePtr BufFilePushCompressed(BufFilePtr);
static FontFilePtr FontFileOpen(char *);
static void FontFileClose (FontFilePtr);
static int pcfGetLSB32(FontFilePtr);
static PCFTablePtr pcfReadTOC(FontFilePtr,int*);
static Bool pcfGetProperties(FontInfoPtr,FontFilePtr, PCFTablePtr, int);
static void pcfGetCompressedMetric(FontFilePtr,CARD32, xCharInfo*);
static Bool pcfSeekToType(FontFilePtr, PCFTablePtr, int, CARD32, CARD32*, CARD32*);
static int pcfGetINT16(FontFilePtr, CARD32);
static int pcfGetINT32(FontFilePtr, CARD32);
static Bool pcfGetAccel(FontInfoPtr, FontFilePtr, PCFTablePtr, int, CARD32);
static void pcfGetMetric(FontFilePtr, CARD32, xCharInfo *);
static int pcfReadFont(FontPtr, FontFilePtr, int, int, int, int);
static char *NameForAtom(Atom);
static BufFilePtr BufFileOpenRead(int);
static int BufFileRawFill(BufFilePtr);
static int BufFileRawSkip(BufFilePtr, int);
static int BufFileRawClose (BufFilePtr, int);
static int bitmapGetGlyphs(FontPtr, unsigned long, unsigned char *, FontEncoding , unsigned long * , CharInfoPtr *);
static int bitmapGetMetrics(FontPtr, unsigned long, unsigned char *, FontEncoding, unsigned long *, xCharInfo **);
static void pcfUnloadFont(FontPtr);
static int handle_cuferr(int , ucs4_t *, int *);
static int handle_illegalchar(ucs4_t *, int *);
static int handle_nonidentchar(ucs4_t *, int *);
static int handle_nobitmap(ucs4_t *, pcffont_t *, pcf_charmet_t *, pcf_bm_t **) ;
static int handle_nongraphchar(ucs4_t *, int *);
static pcf_bm_t * xpcf_getcbm(int , pcffont_t *, pcf_charmet_t *);
static void BitOrderInvert(unsigned char *, int);
static Bool pcfHasType ( PCFTablePtr, int, CARD32);
static void TwoByteSwap(unsigned char *, int);
static void FourByteSwap(unsigned char *, int);
static int RepadBitmap(char *, char *, unsigned int, unsigned int, int, int);
static Atom MakeAtom(char *, unsigned, int );
static Bool ResizeReverseMap ();
static NameEqual (char *, char *,int );
static Hash(char *, int);
static ResizeHashTable();
static void put_PSbitmap(ucs4_t , pcf_bm_t *, pcf_charmet_t *, pcf_SCcharmet_t *);
static int gzcatfile(char *);
void init_putPS(void);
unsigned long * Xrealloc(unsigned long   *, int);
unsigned long * Xalloc(int);
int BufFileRead (BufFilePtr, char *, int);
void pcf_postscript(ucs4_t c, pcf_bm_t *, pcf_charmet_t *, pcf_SCcharmet_t *);
int pres_pcfbm(ucs4_t *, pcffont_t *, pcf_bm_t **, pcf_charmet_t *, pcf_SCcharmet_t *, int);

double SPACINGwidth = -1;
ucs4_t SPACINGchar = (ucs4_t) 0x20;
ucs4_t REFERENCEchar = (ucs4_t) 0x20;

extern pcffont_t *pcf_fonts;
extern pcffont_t	*CurrentFont;
static int position;
static CharInfoRec nonExistantChar;
static AtomListPtr  *hashTable;
static int          hashMask;
static int          hashSize, hashUsed;
static int          hashMask;
static int          rehash;

/*
static ucs4_t	pcf_bmap[4][UCS4_MAXVAL/sizeof(ucs4_t)];
static int dictcnt = 0;
*/

static unsigned char _reverse_byte[0x100] = {
	0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
	0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
	0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
	0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
	0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
	0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
	0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
	0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
	0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
	0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
	0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
	0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
	0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
	0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
	0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
	0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
	0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
	0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
	0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
	0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
	0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
	0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
	0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
	0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
	0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
	0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
	0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
	0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
	0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
	0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
	0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
	0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
};

static void
put_PSbitmap(ucs4_t code, pcf_bm_t *bitmap, 
	pcf_charmet_t *Cmetrics, pcf_SCcharmet_t *Smetrics)
{
    int j;
    int k;

    if (bitmap == NULL)
	return;

    fprintf(stdout,"/C%x { GR %.2f %.2f S %d %d T [%d 0 0 -%d 0 %d]\n\t{<", 
    	    code,
    	    Smetrics->widthBits, Smetrics->height,
    	    Cmetrics->widthBits, Cmetrics->height,
    	    Cmetrics->widthBits, Cmetrics->height,
    	    Cmetrics->ascent);

    k = Cmetrics->widthBytes * Cmetrics->height;

#ifdef SDEBUG
	fprintf(stderr, "%d is -------Cmetrics->widthBytes for :C%x \n", Cmetrics->widthBytes, code);
	fprintf(stderr, "%d is -------Cmetrics->height for :C%x \n", Cmetrics->height, code);
	fprintf(stderr, "%d is ------ no. of glyph elems for:C%x \n", k, code);
#endif
    for (j = 0; j < k; j++)
	fprintf(stdout,"%.2x", bitmap[j]);

    fprintf(stdout,">} IG } def\n"); 
    fprintf(stdout,"C%x\n", code);

    /*
    dictcnt++;
    */
}

pcf_SCcharmet_t *
get_SCmetrics(ucs4_t val)
{
	int ndx;
	ucs4_t v;
	pcf_bm_t *bm;
	pcf_charmet_t cm;
	static pcf_SCcharmet_t sm;

	/* map ucs4 val to a 'pcf_fonts' array index */

	v = val;

	if ((ndx = presform_fontndx(val)) == XU_UCS4UNDEF) {
		return NULL;
	} else if ((pcf_ret <= -1 ) || ( pres_pcfbm(&v, &pcf_fonts[ndx], &bm, &cm, &sm, 1) < 0)) {
		return NULL;
	} else if (v != val) {	/* return NULL if val got mapped to */
				/* another character */
		return NULL; 
	} else {
		return &sm;
	}
}

void
init_putPS(void)
{
    pcf_SCcharmet_t *sm;

    if ((sm = get_SCmetrics(REFERENCEchar)) \
		|| (sm = get_SCmetrics(SPACINGchar))) {
		SPACINGwidth = sm->origin_xoff;
	} else SPACINGwidth = (float)SPACE_WIDTH_PER_PTSZ * current_pt_sz;
}
void
pcf_postscript(ucs4_t c, pcf_bm_t *pcfbm, 
    	pcf_charmet_t *Cmetrics, pcf_SCcharmet_t *scCmetrics)
{


    put_PSbitmap(c, pcfbm, Cmetrics, scCmetrics);

}
int
load_pcf_font(pcffont_t *font)
{
    FontRec fr;
    FontInfoPtr fi;
    FontFilePtr ff;
    ulong_t value;

    if ((ff = FontFileOpen(font->file)) == NULL)
        return -1;


    if (pcfReadFont(&fr, ff, MSBFirst, MSBFirst, 1, 1) != Successful)
    	return -1;
    fi = &(fr.info);

    font->Fmetrics.ascent = fi->fontAscent;
    font->Fmetrics.descent = fi->fontDescent;
    font->Fmetrics.linespace = fi->fontAscent + fi->fontDescent;
    font->Fmetrics.firstchar = (fi->firstRow * 256) + fi->firstCol;
    font->Fmetrics.lastchar = (fi->lastRow * 256) + fi->lastCol;
    font->Fmetrics.lastCol = fi->lastCol;
    font->Fmetrics.firstCol = fi->firstCol;
    
    font->bitmaps = ((BitmapFontPtr)(fr.fontPrivate))->encoding;

    if (get_font_property(&fr, "POINT_SIZE", &value) == -1)
    	return -1;
    font->Fmetrics.ptsz = (int) value;

    if (get_font_property(&fr, "RESOLUTION_X", &value) == -1)
    	return -1;
    font->Fmetrics.Xres = (int) value;

    if (get_font_property(&fr, "RESOLUTION_Y", &value) == -1)
    	return -1;
    font->Fmetrics.Yres = (int) value;

#ifdef SDEBUG
    fprintf(stderr,"Fmetrics: ascent:%d, descent:%d, linespace:%d, "
	"ptsz:%d, Xres:%d, Yres:%d\n", font->Fmetrics.ascent, font->Fmetrics.descent,
	(&(font->Fmetrics))->linespace, (&(font->Fmetrics))->ptsz, (&(font->Fmetrics))->Xres, (&(font->Fmetrics))->Yres);
#endif

    debug(dump_Fmetrics(&(font->Fmetrics)));

    FontFileClose(ff);
    return 0;
}

void
scaling_factors(pcffont_t *font, double ptsz, int Xres, int Yres)
{
    font->Yscale = ((ptsz * (double)Yres) 
	/ ((double)font->Fmetrics.ptsz * (double)font->Fmetrics.Xres));

    font->Xscale = ((((double)Xres * (double)font->Fmetrics.Yres)
	/ ((double)Yres * (double)font->Fmetrics.Xres))
	    * (font->Yscale));
#if 0
    if (xsflag == OPTARG_SET)
    	font->Xscale = xs_argval;
    else if (xsflag == OPTARG_ADD)
    	font->Xscale += xs_argval;
    else if (xsflag == OPTARG_SUB) 	/* for clarity, we subract a positive */
    	font->Xscale -= xs_argval; 	/* rather than add a negative. */

    if (ysflag == OPTARG_SET)
    	font->Yscale = ys_argval;
    else if (ysflag == OPTARG_ADD)
    	font->Yscale += ys_argval;
    else if (ysflag == OPTARG_SUB)
    	font->Yscale -= ys_argval;
#endif
#ifdef SDEBUG
	fprintf(stderr,"%f -- font->Yscale\n %f -- font->Xscale\n", font->Yscale, font->Xscale);
#endif
}

void
scale_Fmetrics(pcffont_t *font) {
	font->scFmetrics.ascent = font->Fmetrics.ascent * font->Yscale;
	font->scFmetrics.descent = font->Fmetrics.descent * font->Yscale;
	font->scFmetrics.linespace = font->Fmetrics.linespace * font->Yscale;

#ifdef SDEBUG
fprintf(stderr,"%f font->scFmetrics.ascent\n \
%f font->scFmetrics.descent\n\
%f font->scFmetrics.linespace\n", font->scFmetrics.ascent, font->scFmetrics.descent, font->scFmetrics.linespace);
#endif

}

void
scale_Cmetrics(pcf_charmet_t *Cm, pcf_SCcharmet_t *Sm)
{
	Sm->width = Cm->width * CurrentFont->Xscale;
	Sm->height = Cm->height * CurrentFont->Yscale;
	Sm->widthBits = Cm->widthBits * CurrentFont->Xscale;
	Sm->ascent = Cm->ascent * CurrentFont->Yscale;
	Sm->descent = Cm->descent * CurrentFont->Yscale;
	Sm->origin_xoff = Cm->origin_xoff * CurrentFont->Xscale;

#ifdef SDEBUG
	fprintf(stderr, "%f is CurrentFont->Xscale\n", CurrentFont->Xscale);
	fprintf(stderr, "%f is CurrentFont->Yscale\n", CurrentFont->Yscale);
	fprintf(stderr, "%d is Cm->widthBits\n", Cm->widthBits);
	fprintf(stderr, "%d is Cm->height\n", Cm->height);
	fprintf(stderr, "%f is Sm->widthBits\n", Sm->widthBits);
	fprintf(stderr, "%f is Sm->height\n", Sm->height);
#endif

	/*
	debug(dump_scCmetrics(Sm));
	*/
}
int
pres_pcfbm(ucs4_t *val, pcffont_t *font, pcf_bm_t **bitmap,
    	pcf_charmet_t *Cmetrics, pcf_SCcharmet_t *scCmetrics, int dontcache)
{
	int fv;
	ucs4_t v;
#if SDEBUG
	fprintf(stderr, "0x%08x -- ucs4val \n", *val);
#endif

	v = *val;
	if (is_motion_char(v)) {
		*bitmap = NULL;
		return XU_MOTION_CHAR;
	}

	if (non_graphic_char(v)) {
		int ndx;
		if ((fv = handle_nongraphchar(&v, &ndx)) == XU_IGNORE) {
			return XU_IGNORE;
		} else {
			font = &pcf_fonts[ndx];
			CurrentFont = font;
		}
	}

	if ((fv = font->cuf(v)) < 0) {
		int ndx;
		if ((fv = handle_cuferr(fv, &v, &ndx)) == XU_IGNORE) {
			return XU_IGNORE;
		} else {
			font = &pcf_fonts[ndx];
			CurrentFont = font;
		}
	}

	if ((*bitmap = (pcf_bm_t *)xpcf_getcbm(fv, font, Cmetrics)) == NULL) {
		if (handle_nobitmap(&v, font, Cmetrics, bitmap) == XU_IGNORE)
			return XU_IGNORE;
	}
#if SDEBUG
	fprintf(stderr, "0x%02x -- **bitmap \n", (unsigned char)**bitmap);
#endif
	*val = v;
	scale_Cmetrics(Cmetrics, scCmetrics);
	return(1);
}

#ifdef DEBUG

static void
dump_Cmetrics(pcf_charmet_t *cm)
{
    dprintf2("cmetrics: ascent:%d, descent:%d, ", cm->ascent, cm->descent);

    dprintf3("width:%d, height:%d, widthBytes:%d, ", 
    	cm->width, cm->height, cm->widthBytes);

    dprintf3("LSB:%d,RSB: %d, xoff:%d\n ", 
	cm->LSBearing, cm->RSBearing, cm->origin_xoff);
}
static void
dump_Fmetrics(pcffont_t *fm)
{
    dprintf6("Fmetrics: ascent:%d, descent:%d, linespace:%d, "
	"ptsz:%d, Xres:%d, Yres:%d\n", fm->ascent, fm->descent, 
    	fm->linespace, fm->ptsz, fm->Xres, fm->Yres);
}
#endif

unsigned long *
Xrealloc (n,m)
    unsigned long   *n;
{
    if (!n)
	return (unsigned long *) malloc (m);
    else
	return (unsigned long *) realloc ((char *) n, m);
}
unsigned long *
Xalloc (m)
{
    return (unsigned long *) malloc (m);
}

/*
 *	Invert byte order within each 16-bits of an array.
 */
void
TwoByteSwap(buf, nbytes)
    unsigned char *buf;
    int nbytes;
{
    register unsigned char c;

    for (; nbytes > 0; nbytes -= 2, buf += 2)
    {
	c = buf[0];
	buf[0] = buf[1];
	buf[1] = c;
    }
}
/*
 *	Invert byte order within each 32-bits of an array.
 */
static void
FourByteSwap(buf, nbytes)
    unsigned char *buf;
    int nbytes;
{
    register unsigned char c;

    for (; nbytes > 0; nbytes -= 4, buf += 4) 
    {
	c = buf[0];
	buf[0] = buf[3];
	buf[3] = c;
	c = buf[1];
	buf[1] = buf[2];
	buf[2] = c;
    }
}
static int
handle_nongraphchar(ucs4_t *val, int *ndx)
{
	return XU_IGNORE;
}

static Bool
pcfHasType (tables, ntables, type)
    PCFTablePtr tables;
    int         ntables;
    CARD32      type;
{
    int         i;

    for (i = 0; i < ntables; i++)
	if (tables[i].type == type)
	    return TRUE;
    return FALSE;
}
/*
 *	Invert bit order within each BYTE of an array.
 */
static void
BitOrderInvert(buf, nbytes)
    unsigned char *buf;
    int nbytes;
{
    register unsigned char *rev = _reverse_byte;

    for (; --nbytes >= 0; buf++)
	*buf = rev[*buf];
}

static pcf_bm_t *
xpcf_getcbm(int code, pcffont_t *font, pcf_charmet_t *Cmetrics)
{
    int j;
    CharInfoPtr ci;

    assert(font->loaded);
    /*
     * For the default no glyph character to appear in
     * output stream
     */
     onemoretime:
    if (code < font->Fmetrics.firstchar || code > font->Fmetrics.lastchar)
	return NULL;

    j = (code - (((code - font->Fmetrics.firstchar) / 256)
    	* (font->Fmetrics.firstCol + (255 - font->Fmetrics.lastCol))))
    	- font->Fmetrics.firstchar;
#ifdef SDEBUG
	fprintf(stderr, "%d is -- codewidth of C%x\n", wcwidth(code), code);
	fprintf(stderr, "%d is -- j value      C%x\n", wcwidth(code), code);
#endif
    assert(j >= 0);
    if (font->bitmaps[j] == NULL)
	{
			/*
			 * code added to replace the codepoints with
			 * no-glyph code
			 */

			if (wcwidth(code) == -1)
				{
				code = 0;
				goto onemoretime;
				}
        return NULL;
	}

    ci = font->bitmaps[j];
    Cmetrics->width = GLYPHWIDTHPIXELS(ci);
    Cmetrics->height = GLYPHHEIGHTPIXELS(ci);
    Cmetrics->widthBytes = GLYPHWIDTHBYTES(ci);
    Cmetrics->widthBits = GLYPHWIDTHBYTES(ci) * NBPB;
    Cmetrics->ascent = ci->metrics.ascent;
    Cmetrics->descent = ci->metrics.descent;
    Cmetrics->LSBearing = ci->metrics.leftSideBearing;
    Cmetrics->RSBearing = ci->metrics.rightSideBearing;
    Cmetrics->origin_xoff = ci->metrics.characterWidth;

#ifdef SDEBUG
	fprintf(stderr, "%d is -- Cmetrics->widthBytes of C%x\n", Cmetrics->widthBytes, code);
	fprintf(stderr, "%d is -- Cmetrics->height value  of C%x\n", Cmetrics->height, code);
#endif

#if 0
    if (cwflag) {
    	if (cwflag == OPTARG_ADD)
    	    Cmetrics->origin_xoff += cw_argval;
    	else if (cwflag == OPTARG_SUB)
    	    Cmetrics->origin_xoff -= cw_argval;
    	else if (cwflag == OPTARG_SET)
    	    Cmetrics->origin_xoff = cw_argval;
    }
#endif

    debug(dump_Cmetrics(Cmetrics));

    return (pcf_bm_t*) ci->bits;
}

/*
 *	Repad a bitmap
 */

static int
RepadBitmap (pSrc, pDst, srcPad, dstPad, width, height)
    char	*pSrc, *pDst;
    unsigned	srcPad, dstPad;
    int		width, height;
{
    int	    srcWidthBytes,dstWidthBytes;
    int	    row,col;
    char    *pTmpSrc,*pTmpDst;

    switch (srcPad) {
    case 1:	
	srcWidthBytes = (width+7)>>3;
	break;
    case 2:
	srcWidthBytes = ((width+15)>>4)<<1;
	break;
    case 4:	
	srcWidthBytes = ((width+31)>>5)<<2;
	break;
    case 8:	
	srcWidthBytes = ((width+63)>>6)<<3; 
	break;
    default:
	return 0;
    }
    switch (dstPad) {
    case 1:	
	dstWidthBytes = (width+7)>>3;
	break;
    case 2:
	dstWidthBytes = ((width+15)>>4)<<1;
	break;
    case 4:	
	dstWidthBytes = ((width+31)>>5)<<2;
	break;
    case 8:	
	dstWidthBytes = ((width+63)>>6)<<3; 
	break;
    default:
	return 0;
    }

    width = srcWidthBytes;
    if (width > dstWidthBytes)
	width = dstWidthBytes;
    pTmpSrc= pSrc;
    pTmpDst= pDst;
    for (row = 0; row < height; row++)
    {
	for (col = 0; col < width; col++)
	    *pTmpDst++ = *pTmpSrc++;
	while (col < dstWidthBytes)
 	{
	    *pTmpDst++ = '\0';
	    col++;
	}
	pTmpSrc += srcWidthBytes - width;
    }
    return dstWidthBytes * height;
}
static int
handle_cuferr(int err, ucs4_t *v, int *ndx)
{

	if (err == CUF_ILCH) {
		return handle_illegalchar(v, ndx);
	} else if (err == CUF_NICH) {
		return handle_nonidentchar(v, ndx);
	} else {
		err_exit( catgets(cat_fd, ERR_SET, 35, "%s: internal error: "
			"unable to get pcf glyph for 0x%08x\n"
			"file name:%s , line number:%d\n"), progname,
			*v, __FILE__, __LINE__ );
	}
}

static int
handle_illegalchar(ucs4_t *val, int *ndx)
{
	return XU_IGNORE;
}

static int
handle_nonidentchar(ucs4_t *val, int *ndx)
{
	return XU_IGNORE;
}

static int
handle_nobitmap(ucs4_t *val, pcffont_t *font, pcf_charmet_t *Cm, pcf_bm_t **bitmap) {
	int fv;
	/* Becasue NOBITMAPREPL is hard coded for FALLBACK_FONT */
	if(strstr(font->file, FALLBACK_FONT)==NULL)
		return XU_IGNORE;
	*val = NOBITMAPREPL;	
	if ((fv = font->cuf(*val)) < 0) return XU_IGNORE;
	if ((*bitmap = xpcf_getcbm(fv, font, Cm)) == NULL) return XU_IGNORE;
	return(1);
}


static int
BufFileRawFill (f)
    BufFilePtr	f;
{
    int	left;

    left = read (FileDes(f), f->buffer, BUFFILESIZE);
    if (left <= 0) {
	f->left = 0;
	return BUFFILEEOF;
    }
    f->left = left - 1;
    f->bufp = f->buffer + 1;
    return f->buffer[0];
}

static int
BufFileRawSkip (f, count)
    BufFilePtr	f;
    int		count;
{
    int	    curoff;
    int	    fileoff;
    int	    todo;

    curoff = f->bufp - f->buffer;
    fileoff = curoff + f->left;
    if (curoff + count <= fileoff) {
	f->bufp += count;
	f->left -= count;
    } else {
	todo = count - (fileoff - curoff);
	if (lseek (FileDes(f), todo, 1) == -1) {
	    if (errno != ESPIPE)
		return BUFFILEEOF;
	    while (todo) {
		curoff = BUFFILESIZE;
		if (curoff > todo)
		    curoff = todo;
		fileoff = read (FileDes(f), f->buffer, curoff);
		if (fileoff <= 0)
		    return BUFFILEEOF;
		todo -= fileoff;
	    }
	}
	f->left = 0;
    }
    return count;
}

static int
BufFileRawClose (f, doClose)
    BufFilePtr	f;
{
    if (doClose)
	close (FileDes (f));
    return 1;
}

static
NameEqual (a, b, l)
    char    *a, *b;
{
    while (l--)
	if (*a++ != *b++)
	    return FALSE;
    return TRUE;
}
static BufFilePtr
BufFileOpenRead(fd)
	 int fd;
{
return BufFileCreate ((char *) fd, BufFileRawFill, BufFileRawSkip, BufFileRawClose);
}

static AtomListPtr  *reverseMap;
static int          reverseMapSize;
static Atom         lastAtom;

static Bool ResizeReverseMap ()
{
    if (reverseMapSize == 0)
	reverseMapSize = 1000;
    else
	reverseMapSize *= 2;
    reverseMap = (AtomListPtr *) Xrealloc ((ulong_t *)reverseMap, reverseMapSize * sizeof (AtomListPtr));
    if (!reverseMap)
	return FALSE;
    else 
	return TRUE;
}

static char *
NameForAtom(atom)
    Atom atom;
{
    if (atom != None && atom <= lastAtom)
	return reverseMap[atom]->name;
    return 0;
}
/*****************************************************************
 * TAG( getcode )
 *
 * Read one code from the standard input.  If BUFFILEEOF, return -1.
 * Inputs:
 * 	stdin
 * Outputs:
 * 	code or -1 is returned.
 */

static char_type rmask[9] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};

static code_int
getcode(file)
    CompressedFile  *file;
{
    register code_int code;
    register int r_off, bits;
    register char_type *bp = file->buf;
    register BufFilePtr	raw;

    if ( file->clear_flg > 0 || file->offset >= file->size ||
	file->free_ent > file->maxcode )
    {
	/*
	 * If the next entry will be too big for the current code
	 * size, then we must increase the size.  This implies reading
	 * a new buffer full, too.
	 */
	if ( file->free_ent > file->maxcode ) {
	    file->n_bits++;
	    if ( file->n_bits == file->maxbits )
		file->maxcode = file->maxmaxcode;	/* won't get any bigger now */
	    else
		file->maxcode = MAXCODE(file->n_bits);
	}
	if ( file->clear_flg > 0) {
    	    file->maxcode = MAXCODE (file->n_bits = INIT_BITS);
	    file->clear_flg = 0;
	}
	bits = file->n_bits;
	raw = file->file;
	while (bits > 0 && (code = BufFileGet (raw)) != BUFFILEEOF)
	{
	    *bp++ = code;
	    --bits;
	}
	bp = file->buf;
	if (bits == file->n_bits)
	    return -1;			/* end of file */
	file->size = file->n_bits - bits;
	file->offset = 0;
	/* Round size down to integral number of codes */
	file->size = (file->size << 3) - (file->n_bits - 1);
    }
    r_off = file->offset;
    bits = file->n_bits;
    /*
     * Get to the first byte.
     */
    bp += (r_off >> 3);
    r_off &= 7;
    /* Get first part (low order bits) */
#ifdef NO_UCHAR
    code = ((*bp++ >> r_off) & rmask[8 - r_off]) & 0xff;
#else
    code = (*bp++ >> r_off);
#endif /* NO_UCHAR */
    bits -= (8 - r_off);
    r_off = 8 - r_off;		/* now, offset into code word */
    /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
    if ( bits >= 8 ) {
#ifdef NO_UCHAR
	code |= (*bp++ & 0xff) << r_off;
#else
	code |= *bp++ << r_off;
#endif /* NO_UCHAR */
	r_off += 8;
	bits -= 8;
    }
    /* high order bits. */
    if (rmask[bits])	
    	code |= (*bp & rmask[bits]) << r_off;
    file->offset += file->n_bits;

    return code;
}
int
BufFileClose (f, doClose)
    BufFilePtr  f;
{
	(void) (*f->close) (f, doClose);
	xfree (f);
}


static int
get_font_property(FontPtr Fp, char *name, ulong_t *value)
{
    int j;
    int n;
    char *prop_name;

    n = Fp->info.nprops;

    for (j = 0; j < n; j++) {
    	if (!(prop_name = NameForAtom(Fp->info.props[j].name)))
    	    continue;
    	if (eq(name, prop_name)) {
	    *value = (ulong_t) Fp->info.props[j].value;
    	    return 0;
    	}
    }

    return -1;
}


static BufFilePtr
BufFileCreate (private, io, skip, close)
    char    *private;
    int	    (*io)();
    int	    (*skip)();
    int	    (*close)();
{
    BufFilePtr	f;

    f = (BufFilePtr) xalloc (sizeof *f);
    if (!f)
	return 0;
    f->private = private;
    f->bufp = f->buffer;
    f->left = 0;
    f->io = io;
    f->skip = skip;
    f->close = close;
    return f;
}

int hsize_table[] = {
	5003,       /* 12 bits - 80% occupancy */
	9001,       /* 13 bits - 91% occupancy */
	18013,      /* 14 bits - 91% occupancy */
	35023,      /* 15 bits - 94% occupancy */
	69001       /* 16 bits - 95% occupancy */
};

static int  BufCompressedFill(), BufCompressedSkip(), BufCompressedClose();

static int
BufCompressedClose (f, doClose)
    BufFilePtr	f;
{
    CompressedFile  *file;
    BufFilePtr	    raw;

    file = (CompressedFile *) f->private;
    raw = file->file;
    xfree (file);
    BufFileClose (raw, doClose);
    return 1;
}

static int
BufCompressedSkip (f, bytes)
    BufFilePtr	f;
    int		bytes;
{
    int		    c;
    while (bytes--) { 
	if (BufFileGet(f) == BUFFILEEOF)
		return BUFFILEEOF;
    }
    return 0;
}

static int
BufCompressedFill (f)
    BufFilePtr	    f;
{
    CompressedFile  *file;
    register char_type *stackp, *de_stack;
    register char_type finchar;
    register code_int code, oldcode, incode;
    BufChar	    *buf, *bufend;

    file = (CompressedFile *) f->private;

    buf = f->buffer;
    bufend = buf + BUFFILESIZE;
    stackp = file->stackp;
    de_stack = file->de_stack;
    finchar = file->finchar;
    oldcode = file->oldcode;
    while (buf < bufend) {
	while (stackp > de_stack && buf < bufend)
	    *buf++ = *--stackp;

	if (buf == bufend)
	    break;

	if (oldcode == -1)
	    break;

	code = getcode (file);
	if (code == -1)
	    break;
    
    	if ( (code == CLEAR) && file->block_compress ) {
	    for ( code = 255; code >= 0; code-- )
	    	file->tab_prefix[code] = 0;
	    file->clear_flg = 1;
	    file->free_ent = FIRST - 1;
	    if ( (code = getcode (file)) == -1 )	/* O, untimely death! */
	    	break;
    	}
    	incode = code;
    	/*
     	 * Special case for KwKwK string.
     	 */
    	if ( code >= file->free_ent ) {
	    *stackp++ = finchar;
	    code = oldcode;
    	}
    
    	/*
     	 * Generate output characters in reverse order
     	 */
    	while ( code >= 256 )
    	{
	    *stackp++ = file->tab_suffix[code];
	    code = file->tab_prefix[code];
    	}
	finchar = file->tab_suffix[code];
	*stackp++ = finchar;
    
    	/*
     	 * Generate the new entry.
     	 */
    	if ( (code=file->free_ent) < file->maxmaxcode ) {
	    file->tab_prefix[code] = (unsigned short)oldcode;
	    file->tab_suffix[code] = finchar;
	    file->free_ent = code+1;
    	} 
	/*
	 * Remember previous code.
	 */
	oldcode = incode;
    }
    file->oldcode = oldcode;
    file->stackp = stackp;
    file->finchar = finchar;
    if (buf == f->buffer) {
	f->left = 0;
	return BUFFILEEOF;
    }
    f->bufp = f->buffer + 1;
    f->left = (buf - f->buffer) - 1;
    return f->buffer[0];
}

BufFilePtr
BufFilePushCompressed (f)
    BufFilePtr	f;
{
    int		    code;
    int		    maxbits;
    int		    hsize;
    CompressedFile  *file;
    int		    extra;

    if ((BufFileGet(f) != (magic_header[0] & 0xFF)) ||
	(BufFileGet(f) != (magic_header[1] & 0xFF)))
    {
	return 0;
    }
    code = BufFileGet (f);
    maxbits = code & BIT_MASK;
    if (maxbits > BITS || maxbits < 12)
	return 0;
    hsize = hsize_table[maxbits - 12];
    extra = (1 << maxbits) * sizeof (char_type) +
	    hsize * sizeof (unsigned short);
    file = (CompressedFile *) xalloc (sizeof (CompressedFile) + extra);
    if (!file)
	return 0;
    file->file = f;
    file->maxbits = maxbits;
    file->block_compress = code & BLOCK_MASK;
    file->maxmaxcode = 1 << file->maxbits;
    file->tab_suffix = (char_type *) &file[1];
    file->tab_prefix = (unsigned short *) (file->tab_suffix + file->maxmaxcode);
    /*
     * As above, initialize the first 256 entries in the table.
     */
    file->maxcode = MAXCODE(file->n_bits = INIT_BITS);
    for ( code = 255; code >= 0; code-- ) {
	file->tab_prefix[code] = 0;
	file->tab_suffix[code] = (char_type) code;
    }
    file->free_ent = ((file->block_compress) ? FIRST : 256 );
    file->clear_flg = 0;
    file->offset = 0;
    file->size = 0;
    file->stackp = file->de_stack;
    file->finchar = file->oldcode = getcode (file);
    if (file->oldcode != -1)
	*file->stackp++ = file->finchar;
    return BufFileCreate ((char *) file,
			  BufCompressedFill,
			  BufCompressedSkip,
			  BufCompressedClose);
}

static 
int gzcatfile(char *name) {
    int    fd[2];

    if (pipe (fd) < 0)
        return -1;

    switch (fork ())
    {
        case -1:
            return -1;
        case 0:
            close (fd[0]);
            close (1);
            if (dup (fd[1]) != 1)
                return -1;
            close (fd[1]);
            execlp ("gzcat", "gzcat", name, 0);
            return -1;
        default:
            close (fd[1]);
            break;
    }
    return fd[0];
}

static FontFilePtr
FontFileOpen (char *name) {
    int		fd;
    int		len;
    BufFilePtr	raw, cooked;

    len = strlen (name);

    /*
     * A little hack for .gz file support.
     * We gzcat the file and will treat the
     * resultant fd as a regular file's.
     */

    if (len > 3 && !strcmp (name + len - 3, ".gz"))
        fd = gzcatfile (name);
    else
        fd = open (name, 0);

    if (fd < 0)
	return 0;
    raw = BufFileOpenRead (fd);
    if (!raw)
    {
	close (fd);
	return 0;
    }
    if (len > 2 && !strcmp (name + len - 2, ".Z")) {
	cooked = BufFilePushCompressed (raw);
	if (!cooked) {
	    BufFileClose (raw, TRUE);
	    return 0;
	}
	raw = cooked;
    }
    return (FontFilePtr) raw;
}

static void FontFileClose (FontFilePtr f)
{
    BufFileClose ((BufFilePtr) f, TRUE);
}

static int
pcfGetLSB32(file)
    FontFilePtr file;
{
    int         c;

    c = FontFileGetc(file);
    c |= FontFileGetc(file) << 8;
    c |= FontFileGetc(file) << 16;
    c |= FontFileGetc(file) << 24;
    position += 4;
    return c;
}

static      PCFTablePtr
pcfReadTOC(file, countp)
    FontFilePtr file;
    int        *countp;
{
    CARD32      version;
    PCFTablePtr tables;
    int         count;
    int         i;

    position = 0;
    version = pcfGetLSB32(file);
    if (version != PCF_FILE_VERSION)
	return (PCFTablePtr) NULL;
    count = pcfGetLSB32(file);
    tables = (PCFTablePtr) xalloc(count * sizeof(PCFTableRec));
    if (!tables)
	return (PCFTablePtr) NULL;
    for (i = 0; i < count; i++) {
	tables[i].type = pcfGetLSB32(file);
	tables[i].format = pcfGetLSB32(file);
	tables[i].size = pcfGetLSB32(file);
	tables[i].offset = pcfGetLSB32(file);
    }
    *countp = count;
    return tables;
}


static
ResizeHashTable ()
{
    int		newHashSize;
    int		newHashMask;
    AtomListPtr	*newHashTable;
    int		i;
    int		h;
    int		newRehash;
    int		r;

    if (hashSize == 0)
	newHashSize = 1024;
    else
	newHashSize = hashSize * 2;
    newHashTable = (AtomListPtr *) xalloc (newHashSize * sizeof (AtomListPtr));
    if (!newHashTable)
	return FALSE;
    bzero ((char *) newHashTable, newHashSize * sizeof (AtomListPtr));
    newHashMask = newHashSize - 1;
    newRehash = (newHashMask - 2);
    for (i = 0; i < hashSize; i++)
    {
	if (hashTable[i])
	{
	    h = (hashTable[i]->hash) & newHashMask;
	    if (newHashTable[h])
	    {
		r = hashTable[i]->hash % newRehash | 1;
		do {
		    h += r;
		    if (h >= newHashSize)
			h -= newHashSize;
		} while (newHashTable[h]);
	    }
	    newHashTable[h] = hashTable[i];
	}
    }
    xfree (hashTable);
    hashTable = newHashTable;
    hashSize = newHashSize;
    hashMask = newHashMask;
    rehash = newRehash;
    return TRUE;
}

static
Hash(string, len)
    char    *string;
{
    int	h;

    h = 0;
    while (len--)
	h = (h << 3) ^ *string++;
    if (h < 0)
	return -h;
    return h;
}
static Atom 
MakeAtom(string, len, makeit)
    char *string;
    unsigned len;
    int makeit;
{
    AtomListPtr	a;
    int		hash;
    int		h;
    int		r;

    hash = Hash (string, len);
    if (hashTable)
    {
    	h = hash & hashMask;
	if (hashTable[h])
	{
	    if (hashTable[h]->hash == hash && hashTable[h]->len == len &&
	    	NameEqual (hashTable[h]->name, string, len))
	    {
	    	return hashTable[h]->atom;
	    }
	    r = (hash % rehash) | 1;
	    for (;;)
	    {
		h += r;
		if (h >= hashSize)
		    h -= hashSize;
		if (!hashTable[h])
		    break;
		if (hashTable[h]->hash == hash && hashTable[h]->len == len &&
		    NameEqual (hashTable[h]->name, string, len))
		{
		    return hashTable[h]->atom;
		}
	    }
    	}
    }
    if (!makeit)
	return None;
    a = (AtomListPtr) xalloc (sizeof (AtomListRec) + len + 1);
    a->name = (char *) (a + 1);
    a->len = len;
    strncpy (a->name, string, len);
    a->name[len] = '\0';
    a->atom = ++lastAtom;
    a->hash = hash;
    if (hashUsed >= hashSize / 2)
    {
	ResizeHashTable ();
	h = hash & hashMask;
	if (hashTable[h])
	{
	    r = (hash % rehash) | 1;
	    do {
		h += r;
		if (h >= hashSize)
		    h -= hashSize;
	    } while (hashTable[h]);
	}
    }
    hashTable[h] = a;
    hashUsed++;
    if (reverseMapSize <= a->atom)
	ResizeReverseMap();
    reverseMap[a->atom] = a;
    return a->atom;
}

BufFileRead (f, b, n)
    BufFilePtr	f;
    char	*b;
    int		n;
{
    int	    c, cnt;
    cnt = n;
    while (cnt--) {
	c = BufFileGet (f);
	if (c == BUFFILEEOF)
	    break;
	*b++ = c;
    }
    return n - cnt - 1;
}
static Bool
pcfGetProperties(pFontInfo, file, tables, ntables)
    FontInfoPtr pFontInfo;
    FontFilePtr file;
    PCFTablePtr tables;
    int         ntables;
{
    FontPropPtr props = 0;
    int         nprops;
    char       *isStringProp = 0;
    CARD32      format;
    int         i;
    /* changed by suresh 07/12/99 from int to CARD 32*/
    CARD32         size;
    int         string_size;
    char       *strings;

    /* font properties */

    if (!pcfSeekToType(file, tables, ntables, PCF_PROPERTIES, &format, &size))
	goto Bail;
    format = pcfGetLSB32(file);
    if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT))
	goto Bail;
    nprops = pcfGetINT32(file, format);
    props = (FontPropPtr) xalloc(nprops * sizeof(FontPropRec));
    if (!props)
	goto Bail;
    isStringProp = (char *) xalloc(nprops * sizeof(char));
    if (!isStringProp)
	goto Bail;
    for (i = 0; i < nprops; i++) {
	props[i].name = pcfGetINT32(file, format);
	isStringProp[i] = pcfGetINT8(file, format);
	props[i].value = pcfGetINT32(file, format);
    }
    /* pad the property array */
    /*
     * clever here - nprops is the same as the number of odd-units read, as
     * only isStringProp are odd length
     */
    if (nprops & 3)
    {
	i = 4 - (nprops & 3);
	FontFileSkip(file, i);
	position += i;
    }
    string_size = pcfGetINT32(file, format);
    strings = (char *) xalloc(string_size);
    if (!strings) {
	goto Bail;
    }
    FontFileRead(file, strings, string_size);
    position += string_size;
    for (i = 0; i < nprops; i++) {
	props[i].name = MakeAtom(strings + props[i].name,
				 strlen(strings + props[i].name), TRUE);
	if (isStringProp[i]) {
	    props[i].value = MakeAtom(strings + props[i].value,
				      strlen(strings + props[i].value), TRUE);
	}
    }
    xfree(strings);
    pFontInfo->isStringProp = isStringProp;
    pFontInfo->props = props;
    pFontInfo->nprops = nprops;
    return TRUE;
Bail:
    xfree(isStringProp);
    xfree(props);
    return FALSE;
}

static void
pcfGetCompressedMetric(file, format, metric)
    FontFilePtr file;
    CARD32      format;
    xCharInfo  *metric;
{
    metric->leftSideBearing = pcfGetINT8(file, format) - 0x80;
    metric->rightSideBearing = pcfGetINT8(file, format) - 0x80;
    metric->characterWidth = pcfGetINT8(file, format) - 0x80;
    metric->ascent = pcfGetINT8(file, format) - 0x80;
    metric->descent = pcfGetINT8(file, format) - 0x80;
    metric->attributes = 0;
}

static Bool
pcfSeekToType(file, tables, ntables, type, formatp, sizep)
    FontFilePtr file;
    PCFTablePtr tables;
    int         ntables;
    CARD32      type;
    CARD32     *formatp;
    CARD32     *sizep;
{
    int         i;

    for (i = 0; i < ntables; i++)
	if (tables[i].type == type) {
	    if (position > tables[i].offset)
		return FALSE;
	    if (!FontFileSkip(file, tables[i].offset - position))
		return FALSE;
	    position = tables[i].offset;
	    *sizep = tables[i].size;
	    *formatp = tables[i].format;
	    return TRUE;
	}
    return FALSE;
}

static int
pcfGetINT32(file, format)
    FontFilePtr file;
    CARD32      format;
{
    int         c;

    if (PCF_BYTE_ORDER(format) == MSBFirst) {
	c = FontFileGetc(file) << 24;
	c |= FontFileGetc(file) << 16;
	c |= FontFileGetc(file) << 8;
	c |= FontFileGetc(file);
    } else {
	c = FontFileGetc(file);
	c |= FontFileGetc(file) << 8;
	c |= FontFileGetc(file) << 16;
	c |= FontFileGetc(file) << 24;
    }
    position += 4;
    return c;
}
static int
pcfGetINT16(file, format)
    FontFilePtr file;
    CARD32      format;
{
    int         c;

    if (PCF_BYTE_ORDER(format) == MSBFirst) {
	c = FontFileGetc(file) << 8;
	c |= FontFileGetc(file);
    } else {
	c = FontFileGetc(file);
	c |= FontFileGetc(file) << 8;
    }
    position += 2;
    return c;
}

/*
 * pcfReadAccel
 *
 * Fill in the accelerator information from the font file; used
 * to read both BDF_ACCELERATORS and old style ACCELERATORS
 */

static Bool
pcfGetAccel(pFontInfo, file, tables, ntables, type)
    FontInfoPtr pFontInfo;
    FontFilePtr file;
    PCFTablePtr	tables;
    int		ntables;
    CARD32	type;
{
    CARD32      format;
    /* changed by suresh 07/12/99 from int to CARD 32*/
    CARD32		size;

    if (!pcfSeekToType(file, tables, ntables, type, &format, &size))
	goto Bail;
    format = pcfGetLSB32(file);
    if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT) &&
	!PCF_FORMAT_MATCH(format, PCF_ACCEL_W_INKBOUNDS)) 
    {
	goto Bail;
    }
    pFontInfo->noOverlap = pcfGetINT8(file, format);
    pFontInfo->constantMetrics = pcfGetINT8(file, format);
    pFontInfo->terminalFont = pcfGetINT8(file, format);
    pFontInfo->constantWidth = pcfGetINT8(file, format);
    pFontInfo->inkInside = pcfGetINT8(file, format);
    pFontInfo->inkMetrics = pcfGetINT8(file, format);
    pFontInfo->drawDirection = pcfGetINT8(file, format);
    pFontInfo->anamorphic = FALSE;
     /* natural alignment */ pcfGetINT8(file, format);
    pFontInfo->fontAscent = pcfGetINT32(file, format);
    pFontInfo->fontDescent = pcfGetINT32(file, format);
    pFontInfo->maxOverlap = pcfGetINT32(file, format);
    pcfGetMetric(file, format, &pFontInfo->minbounds);
    pcfGetMetric(file, format, &pFontInfo->maxbounds);
    if (PCF_FORMAT_MATCH(format, PCF_ACCEL_W_INKBOUNDS)) {
	pcfGetMetric(file, format, &pFontInfo->ink_minbounds);
	pcfGetMetric(file, format, &pFontInfo->ink_maxbounds);
    } else {
	pFontInfo->ink_minbounds = pFontInfo->minbounds;
	pFontInfo->ink_maxbounds = pFontInfo->maxbounds;
    }
    return TRUE;
Bail:
    return FALSE;
}

static void
pcfGetMetric(file, format, metric)
    FontFilePtr file;
    CARD32      format;
    xCharInfo  *metric;
{
    metric->leftSideBearing = pcfGetINT16(file, format);
    metric->rightSideBearing = pcfGetINT16(file, format);
    metric->characterWidth = pcfGetINT16(file, format);
    metric->ascent = pcfGetINT16(file, format);
    metric->descent = pcfGetINT16(file, format);
    metric->attributes = pcfGetINT16(file, format);
}

int
bitmapGetGlyphs(pFont, count, chars, charEncoding, glyphCount, glyphs)
    FontPtr     pFont;
    unsigned long count;
    unsigned char *chars;
    FontEncoding charEncoding;
    unsigned long *glyphCount;	/* RETURN */
    CharInfoPtr *glyphs;	/* RETURN */
{
    BitmapFontPtr  bitmapFont;
    unsigned int firstCol;
    register unsigned int numCols;
    unsigned int firstRow;
    unsigned int numRows;
    CharInfoPtr *glyphsBase;
    register unsigned int c;
    register CharInfoPtr pci;
    unsigned int r;
    CharInfoPtr *encoding;
    CharInfoPtr pDefault;

    bitmapFont = (BitmapFontPtr) pFont->fontPrivate;
    encoding = bitmapFont->encoding;
    pDefault = bitmapFont->pDefault;
    firstCol = pFont->info.firstCol;
    numCols = pFont->info.lastCol - firstCol + 1;
    glyphsBase = glyphs;
    switch (charEncoding) {

    case Linear8Bit:
    case TwoD8Bit:
	if (pFont->info.firstRow > 0)
	    break;
	if (pFont->info.allExist && pDefault) {
	    while (count--) {
		c = (*chars++) - firstCol;
		if (c < numCols)
		    *glyphs++ = encoding[c];
		else
		    *glyphs++ = pDefault;
	    }
	} else {
	    while (count--) {
		c = (*chars++) - firstCol;
		if (c < numCols && (pci = encoding[c]))
		    *glyphs++ = pci;
		else if (pDefault)
		    *glyphs++ = pDefault;
	    }
	}
	break;
    case Linear16Bit:
	if (pFont->info.allExist && pDefault) {
	    while (count--) {
		c = *chars++ << 8;
		c = (c | *chars++) - firstCol;
		if (c < numCols)
		    *glyphs++ = encoding[c];
		else
		    *glyphs++ = pDefault;
	    }
	} else {
	    while (count--) {
		c = *chars++ << 8;
		c = (c | *chars++) - firstCol;
		if (c < numCols && (pci = encoding[c]))
		    *glyphs++ = pci;
		else if (pDefault)
		    *glyphs++ = pDefault;
	    }
	}
	break;

    case TwoD16Bit:
	firstRow = pFont->info.firstRow;
	numRows = pFont->info.lastRow - firstRow + 1;
	while (count--) {
	    r = (*chars++) - firstRow;
	    c = (*chars++) - firstCol;
	    if (r < numRows && c < numCols &&
		    (pci = encoding[r * numCols + c]))
		*glyphs++ = pci;
	    else if (pDefault)
		*glyphs++ = pDefault;
	}
	break;
    }
    *glyphCount = glyphs - glyphsBase;
    return Successful;
}


int
bitmapGetMetrics(pFont, count, chars, charEncoding, glyphCount, glyphs)
    FontPtr     pFont;
    unsigned long count;
    unsigned char *chars;
    FontEncoding charEncoding;
    unsigned long *glyphCount;	/* RETURN */
    xCharInfo **glyphs;		/* RETURN */
{
    int         ret;
    xCharInfo  *ink_metrics;
    CharInfoPtr metrics;
    BitmapFontPtr  bitmapFont;
    CharInfoPtr	oldDefault;
    int         i;

    bitmapFont = (BitmapFontPtr) pFont->fontPrivate;
    oldDefault = bitmapFont->pDefault;
    bitmapFont->pDefault = &nonExistantChar;
    ret = bitmapGetGlyphs(pFont, count, chars, charEncoding, glyphCount, (CharInfoPtr *) glyphs);
    if (ret == Successful) {
	if (bitmapFont->ink_metrics) {
	    metrics = bitmapFont->metrics;
	    ink_metrics = bitmapFont->ink_metrics;
	    for (i = 0; i < *glyphCount; i++) {
		if (glyphs[i] != (xCharInfo *) & nonExistantChar)
		    glyphs[i] = ink_metrics + (((CharInfoPtr) glyphs[i]) - metrics);
	    }
	}
    }
    bitmapFont->pDefault = oldDefault;
    return ret;
}

void
pcfUnloadFont(pFont)
    FontPtr     pFont;
{
    BitmapFontPtr  bitmapFont;

    bitmapFont = (BitmapFontPtr) pFont->fontPrivate;
    xfree(bitmapFont->ink_metrics);
    xfree(bitmapFont->encoding);
    xfree(bitmapFont->bitmaps);
    xfree(bitmapFont->metrics);
    xfree(pFont->info.isStringProp);
    xfree(pFont->info.props);
    xfree(bitmapFont);
    xfree(pFont);
}
static int
pcfReadFont(pFont, file, bit, byte, glyph, scan)
    FontPtr     pFont;
    FontFilePtr file;
    int         bit,
                byte,
                glyph,
                scan;
{
    CARD32      format;
    CARD32      size;
    BitmapFontPtr  bitmapFont = 0;
    int         i;
    PCFTablePtr tables = 0;
    int         ntables;
    int         nmetrics;
    int         nbitmaps;
    int         sizebitmaps;
    int         nink_metrics;
    CharInfoPtr metrics = 0;
    xCharInfo  *ink_metrics = 0;
    char       *bitmaps = 0;
    CharInfoPtr *encoding = 0;
    int         nencoding;
    int         encodingOffset;
    CARD32      bitmapSizes[GLYPHPADOPTIONS];
    CARD32     *offsets = 0;
    Bool	hasBDFAccelerators;

    pFont->info.props = 0;
    if (!(tables = pcfReadTOC(file, &ntables)))
	goto Bail;

    /* properties */

    if (!pcfGetProperties(&pFont->info, file, tables, ntables))
	goto Bail;

    /* Use the old accelerators if no BDF accelerators are in the file */

    hasBDFAccelerators = pcfHasType (tables, ntables, PCF_BDF_ACCELERATORS);
    if (!hasBDFAccelerators)
	if (!pcfGetAccel (&pFont->info, file, tables, ntables, PCF_ACCELERATORS))
	    goto Bail;

    /* metrics */

    if (!pcfSeekToType(file, tables, ntables, PCF_METRICS, &format, &size)) {
	goto Bail;
    }
    format = pcfGetLSB32(file);
    if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT) &&
	    !PCF_FORMAT_MATCH(format, PCF_COMPRESSED_METRICS)) {
	goto Bail;
    }
    if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT))
	nmetrics = pcfGetINT32(file, format);
    else
	nmetrics = pcfGetINT16(file, format);
    metrics = (CharInfoPtr) xalloc(nmetrics * sizeof(CharInfoRec));
    if (!metrics) {
	goto Bail;
    }
    for (i = 0; i < nmetrics; i++)
	if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT))
	    pcfGetMetric(file, format, &(metrics + i)->metrics);
	else
	    pcfGetCompressedMetric(file, format, &(metrics + i)->metrics);

    /* bitmaps */

    if (!pcfSeekToType(file, tables, ntables, PCF_BITMAPS, &format, &size))
	goto Bail;
    format = pcfGetLSB32(file);
    if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT))
	goto Bail;

    nbitmaps = pcfGetINT32(file, format);
    if (nbitmaps != nmetrics)
	goto Bail;

    offsets = (CARD32 *) xalloc(nbitmaps * sizeof(CARD32));
    if (!offsets)
	goto Bail;

    for (i = 0; i < nbitmaps; i++)
	offsets[i] = pcfGetINT32(file, format);

    for (i = 0; i < GLYPHPADOPTIONS; i++)
	bitmapSizes[i] = pcfGetINT32(file, format);
    sizebitmaps = bitmapSizes[PCF_GLYPH_PAD_INDEX(format)];
    bitmaps = (char *) xalloc(sizebitmaps);
    if (!bitmaps)
	goto Bail;
    FontFileRead(file, bitmaps, sizebitmaps);
    position += sizebitmaps;

    if (PCF_BIT_ORDER(format) != bit)
	BitOrderInvert((unsigned char*)bitmaps, sizebitmaps);
    if ((PCF_BYTE_ORDER(format) == PCF_BIT_ORDER(format)) != (bit == byte)) {
	switch (bit == byte ? PCF_SCAN_UNIT(format) : scan) {
	case 1:
	    break;
	case 2:
	    TwoByteSwap((unsigned char*)bitmaps, sizebitmaps);
	    break;
	case 4:
	    FourByteSwap((unsigned char*)bitmaps, sizebitmaps);
	    break;
	}
    }
    if (PCF_GLYPH_PAD(format) != glyph) {
	char       *padbitmaps;
	int         sizepadbitmaps;
	int         old,
	            new;
	xCharInfo  *metric;

	sizepadbitmaps = bitmapSizes[PCF_SIZE_TO_INDEX(glyph)];
	padbitmaps = (char *) xalloc(sizepadbitmaps);
	if (!padbitmaps) {
	    goto Bail;
	}
	new = 0;
	for (i = 0; i < nbitmaps; i++) {
	    old = offsets[i];
	    metric = &metrics[i].metrics;
	    offsets[i] = new;
	    new += RepadBitmap(bitmaps + old, padbitmaps + new,
			       PCF_GLYPH_PAD(format), glyph,
			  metric->rightSideBearing - metric->leftSideBearing,
			       metric->ascent + metric->descent);
	}
	xfree(bitmaps);
	bitmaps = padbitmaps;
    }
    for (i = 0; i < nbitmaps; i++)
	metrics[i].bits = bitmaps + offsets[i];

    xfree(offsets);

    /* ink metrics ? */

    ink_metrics = NULL;
    if (pcfSeekToType(file, tables, ntables, PCF_INK_METRICS, &format, &size)) {
	format = pcfGetLSB32(file);
	if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT) &&
		!PCF_FORMAT_MATCH(format, PCF_COMPRESSED_METRICS)) {
	    goto Bail;
	}
	if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT))
	    nink_metrics = pcfGetINT32(file, format);
	else
	    nink_metrics = pcfGetINT16(file, format);
	if (nink_metrics != nmetrics)
	    goto Bail;
	ink_metrics = (xCharInfo *) xalloc(nink_metrics * sizeof(xCharInfo));
	if (!ink_metrics)
	    goto Bail;
	for (i = 0; i < nink_metrics; i++)
	    if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT))
		pcfGetMetric(file, format, ink_metrics + i);
	    else
		pcfGetCompressedMetric(file, format, ink_metrics + i);
    }

    /* encoding */

    if (!pcfSeekToType(file, tables, ntables, PCF_BDF_ENCODINGS, &format, &size))
	goto Bail;
    format = pcfGetLSB32(file);
    if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT))
	goto Bail;

    pFont->info.firstCol = pcfGetINT16(file, format);
    pFont->info.lastCol = pcfGetINT16(file, format);
    pFont->info.firstRow = pcfGetINT16(file, format);
    pFont->info.lastRow = pcfGetINT16(file, format);
    pFont->info.defaultCh = pcfGetINT16(file, format);

    nencoding = (pFont->info.lastCol - pFont->info.firstCol + 1) *
	(pFont->info.lastRow - pFont->info.firstRow + 1);

    encoding = (CharInfoPtr *) xalloc(nencoding * sizeof(CharInfoPtr));
    if (!encoding)
	goto Bail;

    pFont->info.allExist = TRUE;
    for (i = 0; i < nencoding; i++) {
	encodingOffset = pcfGetINT16(file, format);
	if (encodingOffset == 0xFFFF) {
	    pFont->info.allExist = FALSE;
	    encoding[i] = 0;
	} else
	    encoding[i] = metrics + encodingOffset;
    }

    /* BDF style accelerators (i.e. bounds based on encoded glyphs) */

    if (hasBDFAccelerators)
	if (!pcfGetAccel (&pFont->info, file, tables, ntables, PCF_BDF_ACCELERATORS))
	    goto Bail;

    bitmapFont = (BitmapFontPtr) xalloc(sizeof *bitmapFont);
    if (!bitmapFont)
	goto Bail;

    bitmapFont->version_num = PCF_FILE_VERSION;
    bitmapFont->num_chars = nmetrics;
    bitmapFont->num_tables = ntables;
    bitmapFont->metrics = metrics;
    bitmapFont->ink_metrics = ink_metrics;
    bitmapFont->bitmaps = bitmaps;
    bitmapFont->encoding = encoding;
    bitmapFont->pDefault = (CharInfoPtr) 0;
    if (pFont->info.defaultCh != (unsigned short) NO_SUCH_CHAR) {
	int         r,
	            c,
	            cols;

	r = pFont->info.defaultCh >> 8;
	c = pFont->info.defaultCh & 0xFF;
	if (pFont->info.firstRow <= r && r <= pFont->info.lastRow &&
		pFont->info.firstCol <= c && c <= pFont->info.lastCol) {
	    cols = pFont->info.lastCol - pFont->info.firstCol + 1;
	    r = r - pFont->info.firstRow;
	    c = c - pFont->info.firstCol;
	    bitmapFont->pDefault = encoding[r * cols + c];
	}
    }
    bitmapFont->bitmapExtra = (BitmapExtraPtr) 0;
    pFont->fontPrivate = (pointer) bitmapFont;
    pFont->get_glyphs = bitmapGetGlyphs;
    pFont->get_metrics = bitmapGetMetrics;
    pFont->unload_font = pcfUnloadFont;
    pFont->bit = bit;
    pFont->byte = byte;
    pFont->glyph = glyph;
    pFont->scan = scan;
    xfree(tables);
    return Successful;
Bail:
    xfree(ink_metrics);
    xfree(encoding);
    xfree(bitmaps);
    xfree(offsets);
    xfree(metrics);
    xfree(pFont->info.props);
    pFont->info.props = 0;
    xfree(bitmapFont);
    xfree(tables);
    return AllocError;
}