DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T p

⟦4522bca6c⟧ TextFile

    Length: 14658 (0x3942)
    Types: TextFile
    Names: »pk.c«

Derivation

└─⟦060c9c824⟧ Bits:30007080 DKUUG TeX 2/12/89
    └─⟦this⟧ »./DVIware/laser-setters/quicspool/src/pk.c« 
└─⟦52210d11f⟧ Bits:30007239 EUUGD2: TeX 3 1992-12
    └─⟦af5ba6c8e⟧ »unix3.0/DVIWARE.tar.Z« 
        └─⟦ca79c7339⟧ 
            └─⟦this⟧ »DVIware/laser-setters/quicspool/src/pk.c« 

TextFile

#ifndef lint
static char	*rcs = "$Header: pk.c,v 1.1 88/01/15 13:04:52 simpson Rel $";
#endif
/*
$Log:	pk.c,v $
 * Revision 1.1  88/01/15  13:04:52  simpson
 * initial release
 * 
 * Revision 0.1  87/12/11  18:31:09  simpson
 * beta test
 * 
*/
#include <stdio.h>
#include <assert.h>
#include <local/standard.h>
#include "constants.h"
#include "fontinfo.h"
#include "pk.h"

/* Routines pertaining to PK files. */

static int  BitNumber;	/* Count of bits read in a byte */
static int  Byte;	/* Byte currently reading bits or nybbles from */
static int  RepeatCount; /* Count found during unpacking of packed number */

/* Resets the bit count so bit and nybble reading start on a byte boundary. */
static void resetbitcount()
{
    BitNumber = 0;
}

/* Returns the next nybble from the file.  This routine uses the cgetc()
 * function so an appropriate error routine will need to be set.
 */
static int getnyb(f)
FILE	*f;
{
    if (BitNumber == 0) {
	Byte = cgetc(f);
	BitNumber = 8;
    }
    if (BitNumber == 8) {
	BitNumber -= 4;
	return Byte >> 4 & 0xF;
    } else {
	BitNumber -= 4;
	return Byte & 0xF;
    }
}

/* Returns true if the next bit is on, false otherwise.  This routine uses the
 * cgetc() function so an appropriate error routine will need to be set.
 */
static Boolean getbit(f)
FILE	*f;
{
    if (BitNumber == 0) {
	Byte = cgetc(f);
	BitNumber = 8;
    }
    return Byte & 1 << --BitNumber ? TRUE : FALSE;
}

/* Returns the next packed number from the file f.  The global variable
 * RepeatCount is set appropriately if a repeat count is found.  This routine
 * uses the cgetc() function so an appropriate error routine will need to be
 * set.
 */
static int pkpackednum(f, dynf)
register FILE	*f;
register int	dynf;
{
    register int    i, j;

    i = getnyb(f);
    if (i == 0) {
	do {
	    j = getnyb(f);
	    i++;
	} while (j == 0);
	while (i-- > 0)
	    j = (j << 4) + getnyb(f);
	return j - 15 + ((13 - dynf) << 4) + dynf;
    } else if (i <= dynf)
	return i;
    else if (i < 14)
	return ((i - dynf - 1) << 4) + getnyb(f) + dynf + 1;
    else {
	if (i == 14)
	    RepeatCount = pkpackednum(f, dynf);
	else
	    RepeatCount = 1;
	return pkpackednum(f, dynf);
    }
    /* NOTREACHED */
}

/* Returns information about a PK file or NULL if it couldn't open the file
 * or the file is an invalid PK file.  The information returned is static and
 * is overwritten with each call.  Downloadtype should be 'X' or 'Y' (see the
 * QMS Programming Manual).  This function uses the cgetc() routine so an
 * appropriate error recovery function should be set.
 */
struct FontInfo *getfontinfo(filename, downloadtype)
char *filename;
int  downloadtype;
{
    unsigned long	    uinteger(), li, lk;
    long		    integer(), pl, cc;
    static struct FontInfo  fi;
    FILE		    *f;
    int			    wordsneeded = 0, i, j, command, flag;
    int			    heightstorage[256][2]; /* 0=h,1=voff f/each char*/
    int			    largestvoff;    /* Largest voff of all chars */

    if (!(f = fopen(filename, "r")))
	return NULL;
    if (cgetc(f) != PKPRE || cgetc(f) != PKID) {
	(void)fclose(f);
	return NULL;
    }
    bzero((char *)&fi, sizeof(struct FontInfo));
    bzero((char *)heightstorage, sizeof(heightstorage));
    for (i = 0, j = cgetc(f); i < j; i++)
	fi.comment[i] = cgetc(f);
    fi.comment[i] = '\0';
    fi.ds = integer(f, 4);
    fi.cs = integer(f, 4);
    fi.hppp = integer(f, 4);
    fi.vppp = integer(f, 4);
    fi.numchars = fi.qmsheight = largestvoff = 0;
    while ((command = cgetc(f)) != PKPOST)
	if (0 <= command && command <= 239) {
	    flag = command;
	    if ((flag & 0x7) == 0x7) {	/* Long format preamble */
		pl = integer(f, 4);
		cc = integer(f, 4);
		fi.chararray[cc].tfm = integer(f, 4);
		fi.chararray[cc].dx = integer(f, 4);
		fi.chararray[cc].dy = integer(f, 4);
		fi.chararray[cc].w = integer(f, 4);
		fi.chararray[cc].h = integer(f, 4);
		fi.chararray[cc].hoff = integer(f, 4);
		fi.chararray[cc].voff = integer(f, 4);
		(void)fseek(f, pl - 28, 1);
	    } else if (0 <= (flag & 0x7) && (flag & 0x7) <= 3) { /* Short */
		pl = cgetc(f) | (flag & 0x3) << 8;
		cc = cgetc(f);
		fi.chararray[cc].tfm = uinteger(f, 3);
		fi.chararray[cc].dx = fi.chararray[cc].dy = cgetc(f) * SPOINT;
		fi.chararray[cc].w = cgetc(f);
		fi.chararray[cc].h = cgetc(f);
		fi.chararray[cc].hoff = integer(f, 1);
		fi.chararray[cc].voff = integer(f, 1);
		(void)fseek(f, pl - 8, 1);
	    } else {			/* Extended short form */
		pl = uinteger(f, 2) | (flag & 0x3) << 16;
		cc = cgetc(f);
		fi.chararray[cc].tfm = uinteger(f, 3);
		fi.chararray[cc].dx = fi.chararray[cc].dy = uinteger(f, 2)
		* SPOINT;
		fi.chararray[cc].w = uinteger(f, 2);
		fi.chararray[cc].h = uinteger(f, 2);
		fi.chararray[cc].hoff = integer(f, 2);
		fi.chararray[cc].voff = integer(f, 2);
		(void)fseek(f, pl - 13, 1);
	    }
	    assert(0 <= cc && cc <=255);
	    fi.numchars++;
	    fi.qmsheight = MAX(fi.qmsheight, fi.chararray[cc].h);
	    largestvoff = MAX(largestvoff, fi.chararray[cc].voff);
	    heightstorage[cc][0] = fi.chararray[cc].h;
	    heightstorage[cc][1] = fi.chararray[cc].voff;
	    if (downloadtype == 'Y')
		wordsneeded += (int)((fi.chararray[cc].h + 15.0) / 16.0) *
		fi.chararray[cc].w;
	    else
		wordsneeded += (int)((fi.chararray[cc].w + 15.0) / 16.0) *
		fi.chararray[cc].h;
	} else
	    switch (command) {
	    case PKXXX1:
	    case PKXXX2:
	    case PKXXX3:
	    case PKXXX4:
		for (li = 0, lk = uinteger(f, command - PKXXX1 + 1); li <
		lk; li++)
		    (void)cgetc(f);
		break;
	    case PKYYY:
		(void)uinteger(f, 4);
		break;
	    case PKNOOP:
		break;
	    default:
		(void)fclose(f);
		return NULL;
	    }
    wordsneeded += 800.0 / 2.0 + (fi.numchars * (14.0 + 12.0)) / 2.0;
    fi.blocksize = CEILING((wordsneeded * 2.0) / 1024.0);
    fi.qmsbaseline = largestvoff;
    for (li = 0; li < 256; li++)
	fi.qmsheight = MAX(fi.qmsheight, largestvoff + (heightstorage[li][0]
	- heightstorage[li][1]));
    (void)fclose(f);
    return &fi;
}

/* This routine takes a PK font name and extracts the information
 * contained in its naming convention.  PK fonts are named like
 * <font name><optional design size>.<magnification>pk.  The first
 * parameter is the font name.  This is the only input parameter.  The
 * following output parameters are the name of the font (including the
 * optional design size), the name of the font (without the design size),
 * the design size and the magnification.  For example, parameter
 * cmr10.200pk would return the values
 *	fontname	"cmr10"
 *	shortfontname	"cmr"
 *	designsize	10
 *	magnification	200
 * The function returns TRUE if it was successful parsing the name, FALSE
 * otherwise.  The designsize returned will be -1 if it is left out.
 */
Boolean extractinfo(fullfontname, fontname, shortfontname, designsize,
magnification)
char	*fullfontname;
char	*fontname;
char	*shortfontname;
int	*designsize;
int	*magnification;
{
    char	*p, *strcpy();

    if (sscanf(fullfontname, "%[^0123456789.]", shortfontname) != 1)
	return FALSE;
    p = &fullfontname[strlen(shortfontname)];
    if ('0' <= *p && *p <= '9') {
	if (sscanf(p, "%d", designsize) != 1)
	    return FALSE;
	while ('0' <= *p && *p <= '9')
	    p++;
    } else
	*designsize = -1;
    if (*designsize != -1)
	(void)sprintf(fontname, "%s%d", shortfontname, *designsize);
    else
	(void)strcpy(fontname, shortfontname);
    if (*p != '.')
	return FALSE;
    else
	p++;
    if (sscanf(p, "%d", magnification) != 1)
	return FALSE;
    while ('0' <= *p && *p <= '9')
	p++;
    if (!EQ(p, "pk"))
	return FALSE;
    return TRUE;
}

static FILE		*PkFilePtr;	/* File pointer used in resetpkfile()
					 * and getnextcharinfo() */
static struct CharInfo	CInfo;		/* Structure returned to the user */

/* Resets the getnextcharinfo() function so it reopens the PK file */
void resetpkfile()
{
    if (PkFilePtr) {
	(void)fclose(PkFilePtr), PkFilePtr = NULL;
	if (CInfo.bitmap)
	    free(CInfo.bitmap), CInfo.bitmap = NULL;
    }
}

/* This function gets information on the next character in a font.  If the
 * font file is not already opened, it will open the font file. The 
 * downloadtype should be 'X' or 'Y'.  The routine allocates and deallocates
 * memory for the character bitmap itself, so you needn't worry about it.
 * The filename parameter is only consulted when the routine is first called
 * to get the information on the first character.  If you wish to read from a 
 * new PK file, you must use the resetpkfile() function.  The routine returns
 * 0 on success, 1 if there are no more characters, 2 if the PK file could not
 * be opened, 3 if the file is not a PK file and 4 if the PK version is 
 * incorrect.  This routine calls the cgetc() function so the error routine
 * should be set appropriately.
 */
int getnextcharinfo(filename, downloadtype, charinfo)
char		*filename;
int		downloadtype;
struct CharInfo **charinfo;
{
    unsigned long	uinteger();
    char	    	*malloc();
    int		    	command, flag, dynf, packednum;
    long                pl, li, lj, integer();
    register Boolean	black;
    register char	*bitmap, *rowmap, *putbyte;
    register int	i, j, k, currentw, currenth, mask;
    register long	w, h;

    if (!PkFilePtr) {
	if (!(PkFilePtr = fopen(filename, "r")))
	    return 2;
	if (cgetc(PkFilePtr) != PKPRE) {
	    (void)fclose(PkFilePtr), PkFilePtr = NULL;
	    return 3;
	}
	if (cgetc(PkFilePtr) != PKID) {
	    (void)fclose(PkFilePtr), PkFilePtr = NULL;
	    return 4;
	}
	for (i = 0, j = cgetc(PkFilePtr); i < j; i++)	/* Comment */
	    (void)cgetc(PkFilePtr);
	(void)integer(PkFilePtr, 4);		/* Design size */
	(void)integer(PkFilePtr, 4);		/* Checksum */
	(void)integer(PkFilePtr, 4);		/* hppp */
	(void)integer(PkFilePtr, 4);		/* vppp */
    } else if (CInfo.bitmap)
	free(CInfo.bitmap), CInfo.bitmap = NULL;
tryagain:
    if ((command = cgetc(PkFilePtr)) == PKPOST) {	/* No more chars */
	(void)fseek(PkFilePtr, -1L, 1);	/* Back up by 1 byte */
	return 1;
    }
    if (0 <= command && command <= 239) {
	flag = command;
	dynf = (flag & DYNF) >> 4;
	if ((flag & 0x7) == 0x7) {	/* Long format preamble */
	    CInfo.preambletype = plong;
	    pl = integer(PkFilePtr, 4);
	    CInfo.cc = integer(PkFilePtr, 4);
	    CInfo.tfm = integer(PkFilePtr, 4);
	    CInfo.dxordm = integer(PkFilePtr, 4);
	    CInfo.dy = integer(PkFilePtr, 4);
	    CInfo.w = integer(PkFilePtr, 4);
	    CInfo.h = integer(PkFilePtr, 4);
	    CInfo.hoff = integer(PkFilePtr, 4);
	    CInfo.voff = integer(PkFilePtr, 4);
	    if (CInfo.h == 0 || CInfo.w == 0)
	    	(void)fseek(PkFilePtr, pl - 28L, 1);
	} else if (0 <= (flag & 0x7) && (flag & 0x7) <= 3) { /* Short */
	    CInfo.preambletype = pshort;
	    pl = cgetc(PkFilePtr) | (flag & 0x3) << 8;
	    CInfo.cc = cgetc(PkFilePtr);
	    CInfo.tfm = uinteger(PkFilePtr, 3);
	    CInfo.dxordm = cgetc(PkFilePtr);
	    CInfo.w = cgetc(PkFilePtr);
	    CInfo.h = cgetc(PkFilePtr);
	    CInfo.hoff = integer(PkFilePtr, 1); /* integer() returns */
	    CInfo.voff = integer(PkFilePtr, 1); /* signed values */
	    if (CInfo.h == 0 || CInfo.w == 0)
	    	(void)fseek(PkFilePtr, pl - 8L, 1);
	} else {			/* Extended short form */
	    CInfo.preambletype = pexshort;
	    pl = uinteger(PkFilePtr, 2) | (flag & 0x3) << 16;
	    CInfo.cc = cgetc(PkFilePtr);
	    CInfo.tfm = uinteger(PkFilePtr, 3);
	    CInfo.dxordm = uinteger(PkFilePtr, 2);
	    CInfo.w = uinteger(PkFilePtr, 2);
	    CInfo.h = uinteger(PkFilePtr, 2);
	    CInfo.hoff = integer(PkFilePtr, 2);
	    CInfo.voff = integer(PkFilePtr, 2);
	    if (CInfo.h == 0 || CInfo.w == 0)
	    	(void)fseek(PkFilePtr, pl - 13L, 1);
	}
	assert(pl > 0);
	assert(CInfo.h >= 0 && CInfo.w >= 0);
	assert(0 <= CInfo.cc && CInfo.cc <= 255);
	*charinfo = &CInfo;
	h = CInfo.h, w = CInfo.w;
	if (h == 0 || w == 0)
	    return 0;
	if (downloadtype == 'X') {
	    /* Shifting right 3 divides by 8 faster than division */
	    bitmap = CInfo.bitmap = malloc((unsigned)((w+7>>3)*h));
	    if (dynf == 14) {
		bzero(bitmap, (int)((w+7>>3)*h));
		for (i = 0; i < h; i++)
		    for (j = 0; j < w; j++)
		    	if (getbit(PkFilePtr))
			    *(bitmap + i*(w+7>>3) + (j>>3)) |= 1<<7-j%8;
	    } else {			/* Get normally packed raster */
		black = flag & BRUNCOUNT;
		rowmap = malloc((unsigned)(w+7>>3));
		bzero(rowmap,(int)(w+7>>3));
		currenth = currentw = RepeatCount = 0;
		while (currenth < h && currentw < w) {
		    packednum = pkpackednum(PkFilePtr, dynf);
		    for (i = 0; i < packednum; i++) {
			if (black)
			    *(rowmap + (currentw>>3)) |= 1<<7-currentw%8;
			if (++currentw == w) {
			    for (j = 0; j < RepeatCount + 1; j++)
			    	bcopy(rowmap, bitmap + currenth++ * (w+7>>3),
				(w+7>>3));
			    bzero(rowmap, (int)(w+7>>3));
			    currentw = RepeatCount = 0;
			}
		    }
		    black = !black;
		}
		free(rowmap);
	    }
	} else {			/* Y orientation */
	    bitmap = CInfo.bitmap = malloc((unsigned)((h+7>>3)*w));
	    bzero(bitmap, (int)((h+7>>3)*w));
	    if (dynf == 14) {			/* Get raster by bits */
		for (i = 0; i < h; i++)
		    for (j = 0; j < w; j++)
		    	if (getbit(PkFilePtr)) {
			    putbyte = bitmap + j*(h+7>>3) + (h-(i+1)>>3);
			    *putbyte |= 1<<7-((h+7)-i)%8;
			}
	    } else {			/* Get normally packed raster */
		black = flag & BRUNCOUNT;
		rowmap = malloc((unsigned)(w+7>>3));
		bzero(rowmap, (int)(w+7>>3));
		currenth = currentw = RepeatCount = 0;
		while (currenth < h && currentw < w) {
		    packednum = pkpackednum(PkFilePtr, dynf);
		    for (i = 0; i < packednum; i++) {
			if (black) {
			    *(rowmap + (currentw>>3)) |= 1<<7-currentw%8;
			    putbyte = bitmap + currentw*(h+7>>3)+
			    (h-(currenth+1)>>3);
			    *putbyte |= 1<<7-((h+7)-currenth)%8;
			}
			if (++currentw == w) {
			    currenth++;
			    for (j = 0; j < RepeatCount; j++) {
				for (k = 0; k < w; k++) {
				    if (k % 8 == 0)
				    	mask = 0x80;
				    else
				    	mask >>= 1;
				    if (*(rowmap + (k>>3)) & mask) {
					putbyte = bitmap + k*(h+7>>3) +
					(h-(currenth+1)>>3);
					*putbyte |= 1<<7-((h+7)-currenth)%8;
				    }
				}
				currenth++;
			    }
			    bzero(rowmap, (int)(w+7>>3));
			    currentw = RepeatCount = 0;
			}
		    }
		    black = !black;
		}
		free(rowmap);
	    }			/* End get normally packed raster */
	}			/* End Y orientation */
	resetbitcount();
    } else	    /* End of if (0 <= command && command <= 239) { */
	switch (command) {
	case PKXXX1:
	case PKXXX2:
	case PKXXX3:
	case PKXXX4:
	    for (li = 0, lj = uinteger(PkFilePtr, command - PKXXX1 + 1);
	    li < lj; li++)
		(void)cgetc(PkFilePtr);
	    goto tryagain;
	case PKYYY:
	    (void)uinteger(PkFilePtr, 4);
	    goto tryagain;
	default:
#ifndef lint
	    assert(FALSE);
#else
	    ;
#endif
	}
    return 0;
}