summaryrefslogtreecommitdiff
path: root/dviware/dvitops/pk.c
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /dviware/dvitops/pk.c
Initial commit
Diffstat (limited to 'dviware/dvitops/pk.c')
-rw-r--r--dviware/dvitops/pk.c523
1 files changed, 523 insertions, 0 deletions
diff --git a/dviware/dvitops/pk.c b/dviware/dvitops/pk.c
new file mode 100644
index 0000000000..123eb6964f
--- /dev/null
+++ b/dviware/dvitops/pk.c
@@ -0,0 +1,523 @@
+static char rcsid[] = "$Header: /usr/jjc/dvitops/RCS/pk.c,v 1.7 90/10/19 09:54:55 jjc Exp $";
+
+#include "dvitops.h"
+
+#define pk_id 89
+
+#if 0
+enum pk_command { pk_xxx1 = 240, pk_xxx2 = 241, pk_xxx3 = 242, pk_xxx4 = 243,
+pk_yyy = 244, pk_post = 245, pk_no_op = 246, pk_pre = 247 };
+#else
+#define pk_xxx1 240
+#define pk_xxx2 241
+#define pk_xxx3 242
+#define pk_xxx4 243
+#define pk_yyy 244
+#define pk_post 245
+#define pk_no_op 246
+#define pk_pre 247
+
+#endif
+static struct {
+ integer llx, lly, urx, ury;
+} bb; /* bounding box for the entire font */
+#ifdef PROTO
+static void out_byte(PROMOTED_UNSIGNED_CHAR c, FILE *psfp);
+static void blacken(integer start, integer n, unsigned char *buf);
+static integer packed_num(int dyn_f);
+static void bitmap_char(integer h, integer w, FILE *psfp);
+static integer makeinteger(unsigned char *p);
+static int generate_char(PROMOTED_UNSIGNED_CHAR flag, unsigned char *data,
+ size_t len, FILE *psfp);
+#else
+static void out_byte();
+static void blacken();
+static integer packed_num();
+static void bitmap_char();
+static integer makeinteger();
+static int generate_char();
+#endif
+
+static struct pk_info {
+ integer ds;
+ integer hppp;
+ integer vppp;
+ unsigned char flag[MAXCHARS];
+ size_t len[MAXCHARS];
+ unsigned char *data[MAXCHARS];
+} *pk_table[MAXFONTS];
+
+static integer nbytes;
+
+char *find_pk_file(name, mag)
+char *name;
+int mag;
+{
+ FILE *pkfp;
+ int i;
+ static char buf[10*FILENAME_MAX];
+ char *ptr = buf;
+ static char sep[2] = {AREA_LIST_SEP, '\0'};
+ for (i = 0; texpk[i] != '\0'; i++)
+ if (texpk[i] == '%') {
+ switch(texpk[i+1]) {
+ case 'f': case 'F':
+ strcpy(ptr, name);
+ break;
+ case 'd': case 'D':
+ sprintf(ptr, "%d", mag);
+ break;
+ default:
+ sprintf(ptr, "%c", texpk[i+1]);
+ }
+ ++i;
+ ptr += strlen(ptr);
+ }
+ else
+ *ptr++ = texpk[i];
+ *ptr = '\0';
+ for (ptr = strtok(buf, sep); ptr != NULL; ptr = strtok((char *)NULL, sep)) {
+ if ((pkfp = FOPEN_RB(ptr)) != NULL) {
+ fclose(pkfp);
+ return ptr;
+ }
+ }
+ return NULL;
+}
+
+
+int load_pk_font(f, name, used, at_size, checksum, width, rounded_width)
+int f;
+char *name, *used;
+integer at_size, checksum, *width, *rounded_width;
+{
+ FILE *pkfp;
+ integer n;
+ integer cs;
+ double sppp;
+ int i;
+ if ((pkfp = FOPEN_RB(name)) == NULL) {
+ message(ERROR,
+ "can't find pk file for %s: using white space instead", name);
+ return 0;
+ }
+#ifdef HAVE_SETVBUF
+ setvbuf(pkfp, (char *)NULL, _IOFBF, 8192);
+#endif
+ if ((pk_table[f] = (struct pk_info *)
+ calloc(1, sizeof(struct pk_info))) == NULL)
+ out_of_memory();
+ if (uread1(pkfp) != pk_pre)
+ goto bad;
+ if (uread1(pkfp) != pk_id)
+ goto bad;
+ n = uread1(pkfp);
+ fseek(pkfp, n, 1);
+ pk_table[f]->ds = sread4(pkfp);
+ cs = sread4(pkfp);
+ pk_table[f]->hppp = sread4(pkfp);
+ pk_table[f]->vppp = sread4(pkfp);
+ /* sppp = scaled points per pixel
+ sppp*dx = width in scaled points */
+ sppp = (double)at_size*1048576.0*65536.0
+ /((double)pk_table[f]->ds*(double)pk_table[f]->hppp);
+
+ if (cs != checksum)
+ message(WARNING, "%s: checksums don't match\n", name);
+ for (;;) {
+ unsigned char command = uread1(pkfp);
+ if (feof(pkfp) || ferror(pkfp))
+ goto bad;
+ if (((unsigned)command >> 4) == 15) {
+ switch (command) {
+ case pk_xxx1 :
+ n = uread1(pkfp); break;
+ case pk_xxx2 :
+ n = uread2(pkfp); break;
+ case pk_xxx3 :
+ n = uread3(pkfp); break;
+ case pk_xxx4 :
+ n = sread4(pkfp); break;
+ case pk_yyy :
+ (void) sread4(pkfp); break;
+ case pk_post :
+ for (i = 0; i < MAXCHARS; i++)
+ if (used[i] && width[i] == (integer) LONG_MAX)
+ goto bad;
+ fclose(pkfp);
+ return 1;
+ case pk_no_op :
+ break;
+ default:
+ goto bad;
+ }
+ if (pk_xxx1 <= command && command <= pk_xxx4)
+ fseek(pkfp, n, 1);
+ }
+ else {
+ integer cc, pl;
+ integer tfm;
+ double dx;
+ unsigned char c;
+ size_t len;
+ unsigned char flag = command;
+ command &= 0x07;
+ if (command == 0x07) {
+ pl = sread4(pkfp);
+ cc = sread4(pkfp);
+ tfm = sread4(pkfp);
+ dx = (double)sread4(pkfp)/65536.0;
+ fseek(pkfp, -4L, 1);
+ pl -= 4;
+ }
+ else if (command & 0x04) {
+ pl = uread2(pkfp);
+ pl |= (integer)(command & 0x03) << 16;
+ cc = uread1(pkfp);
+ tfm = uread3(pkfp);
+ dx = (double)uread2(pkfp);
+ fseek(pkfp, -2L, 1);
+ pl -= 3;
+ }
+ else {
+ pl = uread1(pkfp);
+ pl |= (command & 0x03) << 8;
+ cc = uread1(pkfp);
+ tfm = uread3(pkfp);
+ dx = (double)uread1(pkfp);
+ fseek(pkfp, -1L, 1);
+ pl -= 3;
+ }
+ if (cc < 0 || cc >= MAXCHARS) {
+ fseek(pkfp, pl, SEEK_CUR);
+ continue;
+ }
+ c = (unsigned char)cc;
+ if (!used[c]) {
+ pk_table[f]->data[c] = NULL;
+ fseek(pkfp, pl, SEEK_CUR);
+ }
+ else {
+ if (pl < 0 || pl > SIZE_MAX)
+ goto bad;
+ len = (size_t)pl;
+ width[c] = scale(tfm, at_size);
+ rounded_width[c] = (integer)(dx*sppp);
+ pk_table[f]->flag[c] = flag;
+ pk_table[f]->len[c] = len;
+ if ((pk_table[f]->data[c] = (unsigned char *)malloc(len))
+ == NULL)
+ out_of_memory();
+ if (fread((char *)pk_table[f]->data[c], 1, len, pkfp) != len)
+ goto bad;
+ }
+ }
+ }
+ /* can't get here */
+bad:
+ message(ERROR, "%s: bad pk file: using white space instead", name);
+ return 0;
+}
+
+static unsigned char *ptr;
+static char biti;
+static integer rc;
+
+#define get_nyb() (biti == 0 ? (biti=4, (unsigned)*ptr>>4) \
+: (biti = 0, *ptr++ & 0x0f))
+
+
+static integer packed_num(dyn_f)
+int dyn_f;
+{
+ integer i, j;
+ integer n;
+ i = get_nyb();
+ if (i == 0) {
+ do {
+ j = get_nyb();
+ i++;
+ } while (j == 0);
+ while (i > 0) {
+ j = (j << 4) + get_nyb();
+ i--;
+ }
+ n = (j - 15 + ((13 - dyn_f) << 4) + dyn_f);
+ }
+ else if (i <= dyn_f)
+ n = i;
+ else if (i < 14)
+ n = ((i - dyn_f - 1) << 4) + get_nyb() + dyn_f + 1;
+ else {
+ rc = i == 14 ? packed_num(dyn_f) : 1;
+ n = packed_num(dyn_f);
+ }
+ return n;
+}
+
+/* this can be made a lot more efficient later */
+
+static void blacken(start, n, buf)
+integer start, n;
+unsigned char *buf;
+{
+ integer i;
+ for (i = start; i < start + n; i++)
+ buf[(size_t)(i/8)] |= (unsigned)128 >> (int)(i & 7);
+}
+
+
+static char *hex = "0123456789ABCDEF";
+
+static void out_byte(c, psfp)
+unsigned char c;
+FILE *psfp;
+{
+ static int cols = 0;
+ putc(hex[(unsigned)(c) >> 4],psfp);
+ putc(hex[(c) & 15],psfp);
+ if ((cols += 2) > 70) {
+ cols = 0;
+ putc('\n', psfp);
+ }
+ ++nbytes;
+}
+
+/* postscript requires that the bitmap of each row be padded out to an
+integral number of bytes, so unfortunately we can't just copy the bitmap
+in the pk file; this function could probably be made faster, but most
+of the characters that pk format represents by bitmaps are fairly small */
+
+static void bitmap_char(h, w, psfp)
+integer h, w;
+FILE *psfp;
+{
+ integer i, j;
+ unsigned mask = 0x80;
+ unsigned char curbyte = 0;
+ unsigned curmask = 0x80;
+ for (i = 0; i < h; i++)
+ for (j = 0; j < w; j++) {
+ if (*ptr & mask)
+ curbyte |= curmask;
+ if ((mask >>= 1) == 0) {
+ mask = 0x80;
+ ptr++;
+ }
+ if ((curmask >>= 1) == 0 || j == w - 1) {
+ out_byte(curbyte, psfp);
+ curbyte = 0;
+ curmask = 0x80;
+ }
+ }
+/* the value of ptr is checked on return to make sure we have used the right
+number of bytes */
+ if (mask != 0x80)
+ ptr++;
+}
+
+static integer makeinteger(p)
+unsigned char *p;
+{
+ return (((integer)p[0]<<24) | ((integer)p[1]<<16) | (p[2]<<8) | p[3]);
+}
+
+/*
+output strings have one of the following forms:
+(4 byte integers are always signed)
+flag[1] dm[1] w[1] h[1] hoff[+1] voff[+1] flag = 0
+flag[1] dm[2] w[2] h[2] hoff[+2] voff[+2] flag = 1
+flag[1] dx[4] dy[4] w[4] h[4] hoff[4] voff[4] flag = 2
+*/
+
+/* returns 0 on error != 0 otherwise */
+static int generate_char(flag, data, len, psfp)
+unsigned char flag;
+unsigned char *data;
+size_t len;
+FILE *psfp;
+{
+ int black = (flag & 0x08) != 0;
+ integer h, w;
+ int dyn_f;
+ integer hoff, voff;
+ integer curcol, currow;
+ unsigned char *rowbuf;
+ size_t buflen;
+ dyn_f = (unsigned)flag >> 4;
+ ptr = data;
+ rc = 0;
+ biti = 0;
+ fputc('<',psfp);
+ if ((flag & 0x07) == 0x07) {
+ int i;
+ out_byte(2, psfp);
+ for (i = 0; i < 24; i++)
+ out_byte(ptr[i], psfp);
+ ptr += 8;
+ w = makeinteger(ptr); ptr += 4;
+ h = makeinteger(ptr); ptr += 4;
+ hoff = makeinteger(ptr); ptr += 4;
+ voff = makeinteger(ptr); ptr += 4;
+ }
+ else if (flag & 0x04) {
+ int i;
+ out_byte(1, psfp);
+ for (i = 0; i < 10; i++)
+ out_byte(ptr[i], psfp);
+ ptr += 2;
+ w = (ptr[0] << 8) | ptr[1]; ptr += 2;
+ h = (ptr[0] << 8) | ptr[1]; ptr += 2;
+ hoff = *ptr++;
+ if (hoff >= 128)
+ hoff -= 256;
+ hoff <<= 8;
+ hoff |= *ptr++;
+ voff = *ptr++;
+ if (voff >= 128)
+ voff -= 256;
+ voff <<= 8;
+ voff |= *ptr++;
+ }
+ else {
+ int i;
+ out_byte(0, psfp);
+ for (i = 0; i < 5; i++)
+ out_byte(ptr[i], psfp);
+ ptr++;
+ w = *ptr++;
+ h = *ptr++;
+ hoff = *ptr++;
+ if (hoff >= 128)
+ hoff -= 256;
+ voff = *ptr++;
+ if (voff >= 128)
+ voff -= 256;
+ }
+ if (-hoff < bb.llx)
+ bb.llx = -hoff;
+ if (w-hoff > bb.urx)
+ bb.urx = w-hoff;
+ if (voff + 1 - h < bb.lly)
+ bb.lly = voff + 1 - h;
+ if (voff + 1 > bb.ury)
+ bb.ury = voff + 1;
+ if (dyn_f == 14) {
+ bitmap_char(h, w, psfp);
+ if (data + len != ptr)
+ return 0;
+ fputc('>',psfp);
+ return 1;
+ }
+ currow = curcol = 0;
+ buflen = (size_t)((w + 7) / 8);
+ if (buflen == SIZE_MAX) /* we'd get an infinite loop if we allowed this */
+ return 0;
+ rowbuf = (unsigned char *)calloc(1, buflen);
+ if (rowbuf == NULL)
+ out_of_memory();
+ while (currow < h) {
+ integer run = packed_num(dyn_f);
+ while (curcol + run >= w) {
+ size_t i;
+ integer j;
+ if (black)
+ blacken(curcol, w - curcol, rowbuf);
+ for (j = 0; j <= rc; j++) {
+ for (i = 0; i < buflen; i++)
+ out_byte(rowbuf[i],psfp);
+ }
+ for (i = 0; i < buflen; i++)
+ rowbuf[i] = 0;
+ currow++; currow += rc; rc = 0;
+ run -= w - curcol;
+ curcol = 0;
+ }
+ if (black)
+ blacken(curcol, run, rowbuf);
+ curcol += run;
+ black = !black;
+ }
+ if (biti > 0)
+ ptr++;
+ if (data + len != ptr)
+ return 0;
+ fputc('>',psfp);
+ free((char *)rowbuf);
+ return 1;
+}
+
+
+integer emit_pk_font(f, name, used, psfp)
+int f;
+char *name;
+char *used;
+FILE *psfp;
+{
+ int i, nused;
+ nbytes = 0;
+ if (pk_table[f] == NULL)
+ cant_happen();
+ fprintf(psfp, "%%%%BeginFont: %s\n", name);
+ fprintf(psfp, "/%s %ld %ld %ld\n", name, (long)(pk_table[f]->ds),
+ (long)(pk_table[f]->hppp), (long)(pk_table[f]->vppp));
+ bb.llx = bb.lly = bb.urx = bb.ury = 0;
+ nused = 0;
+ fputs("EmptyEncoding 256 array copy\n", psfp);
+ for (i = 0; i < MAXCHARS; i++)
+ if (used[i]) {
+ fprintf(psfp, "dup %d /c%d put\n", i, i);
+ ++nused;
+ }
+ /* allow room for /.notdef */
+ fprintf(psfp, "\n%d dict dup begin\n", nused+1);
+ for (i = 0; i < MAXCHARS; i++)
+ if (used[i]) {
+ if (pk_table[f]->data[i] == NULL)
+ cant_happen();
+ fprintf(psfp, "/c%d", i);
+ if (!generate_char(pk_table[f]->flag[i], pk_table[f]->data[i],
+ pk_table[f]->len[i], psfp))
+ message(FATAL_ERROR,
+ "char %d in the .pk file for %s is bad: use pktype",
+ i, name);
+ fputs("def\n", psfp);
+ }
+ fprintf(psfp, "end %ld %ld %ld %ld DefinePKFont\n", (long)(bb.llx),
+ (long)(bb.lly), (long)(bb.urx), (long)(bb.ury));
+ fputs("%%EndFont\n", psfp);
+ /* this is a fairly good estimate of the overhead for each font */
+ return nbytes + 1024 + 2000 + 20*(nused+1);
+ /* nbytes for the strings, 1024 for the encoding vector,
+ 20 for each of the nused+1 entries in the dictionary
+ plus 2000 for general overhead */
+}
+
+
+
+
+void free_pk_font(n)
+int n;
+{
+ int i;
+ struct pk_info *p = pk_table[n];
+ if (pk_table[n] == NULL)
+ cant_happen();
+ for (i = 0; i < MAXCHARS; i++)
+ if (p->data[i] != NULL)
+ free((char *)(p->data[i]));
+ free((char *)p);
+ pk_table[n] = NULL;
+}
+
+/*
+Local Variables:
+c-indent-level: 4
+c-continued-statement-offset: 4
+c-brace-offset: -4
+c-argdecl-indent: 0
+c-label-offset: -4
+tab-width: 4
+End:
+*/
+