|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T p
Length: 14658 (0x3942)
Types: TextFile
Names: »pk.c«
└─⟦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«
#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;
}