summaryrefslogtreecommitdiff
path: root/dviware/quicspool/src/pk.c
diff options
context:
space:
mode:
Diffstat (limited to 'dviware/quicspool/src/pk.c')
-rw-r--r--dviware/quicspool/src/pk.c475
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;
+}