diff options
Diffstat (limited to 'dviware/quicspool/src/pk.c')
-rw-r--r-- | dviware/quicspool/src/pk.c | 475 |
1 files changed, 475 insertions, 0 deletions
diff --git a/dviware/quicspool/src/pk.c b/dviware/quicspool/src/pk.c new file mode 100644 index 0000000000..09d1b20866 --- /dev/null +++ b/dviware/quicspool/src/pk.c @@ -0,0 +1,475 @@ +#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; +} |