diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /dviware/dvitops/pk.c |
Initial commit
Diffstat (limited to 'dviware/dvitops/pk.c')
-rw-r--r-- | dviware/dvitops/pk.c | 523 |
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: +*/ + |