/* pbmtopk, adapted from "pxtopk.c by tomas rokicki" by AJCD 1/8/90 References (retrieved May 31 2015): Packed (PK) Font File Format https://www.tug.org/TUGboat/tb06-3/tb13pk.pdf Tex Font Metric Files (TFM) https://www.tug.org/TUGboat/tb06-1/tb11gf.pdf */ #define _DEFAULT_SOURCE 1 /* New name for SVID & BSD source defines */ #define _BSD_SOURCE 1 /* Make sure strdup() is in string.h */ #define _XOPEN_SOURCE 500 /* Make sure strdup() is in string.h */ #include #include #include #include #include "pm_c_util.h" #include "pbm.h" #include "nstring.h" #include "mallocvar.h" #define MAXPKCHAR 256 #define MAXOPTLINE 200 #define MAXWIDTHTAB 256 #define MAXHEIGHTTAB 16 #define MAXDEPTHTAB 16 #define MAXITALICTAB 64 #define MAXPARAMS 30 #define NAMELENGTH 80 /*----------------------------------------------------------------------- Macros to handle fixed point numbers This program uses uses fixed-point numbers to store data where normally a floating-point data type (float or double) would be employed. Numbers that contain fractions are stored as signed integers. The 20 least-significant bits are for the fractional part, the rest (12 bits assuming that int is 32 bit) are for the integer part. The technical term for this is "Q20" or "Q12.20" notation. Float/double data is converted to Q20 fixed point by multiplying by 2^20 (= 1048576). The opposite conversion is conducted by dividing by 2^20. The Q20 data must be within the range -16 < r < 16. The reason behind this restriction is unclear. The program generally writes Q20 data to the output files in 32 bits. (Exception: in function shipchar() there is a provision to write Q20 data in 24 bits, provided that 24 bits is sufficient.) ---------------------------------------------------------------------*/ #define fixword(d) ((int)((double)(d)*1048576)) #define unfixword(f) ((double)(f) / 1048576) #define fixrange(f) ((f) < 16777216 && (f) > -16777216) #define designunits(p) ((p)*72.27/(double)resolution/unfixword(designsize)) /* character flags: in order of appearance in option files. */ #define XOFFSET 1 #define YOFFSET 2 #define HORZESC 4 #define VERTESC 8 #define TFMWIDTH 16 #define TFMHEIGHT 32 #define TFMDEPTH 64 #define TFMITALIC 128 typedef int integer ; typedef char quarterword ; typedef char boolean ; typedef quarterword ASCIIcode ; typedef quarterword eightbits ; typedef unsigned char byte ; static integer resolution, designsize ; static char *filename[MAXPKCHAR] ; static integer xoffset[MAXPKCHAR] ; static integer yoffset[MAXPKCHAR] ; static integer horzesc[MAXPKCHAR] ; static integer vertesc[MAXPKCHAR] ; static byte tfmindex[MAXPKCHAR] ; static byte hgtindex[MAXPKCHAR] ; static byte depindex[MAXPKCHAR] ; static byte italindex[MAXPKCHAR] ; static byte charflags[MAXPKCHAR] ; static bit **bitmap ; static integer smallestch = MAXPKCHAR ; static integer largestch = -1; static integer emwidth = 0; static integer checksum ; static const char *codingscheme = "GRAPHIC" ; static const char *familyname = "PBM" ; static integer widthtab[MAXWIDTHTAB] = {0}; /* TFM widths */ static integer numwidth = 1; /* number of entries in width table */ static integer heighttab[MAXHEIGHTTAB] = {0}; static integer numheight = 1; static integer depthtab[MAXDEPTHTAB] = {0}; static integer numdepth = 1; static integer italictab[MAXITALICTAB] = {0}; static integer numitalic = 1; static integer parameters[MAXPARAMS] = {0}; static integer numparam = 0; static ASCIIcode xord[128] ; static char xchr[256] = { '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', ' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', '?' }; static FILE *tfmfile, *pkfile ; static char tfmname[NAMELENGTH+1], pkname[NAMELENGTH+1] ; static integer pbmtopk_pkloc = 0 ; static integer bitweight ; static integer outputbyte ; static integer car ; static integer hppp ; static integer width ; static integer height ; /* check sum algorithm (in Pascal): compute_checksum() begin c0:=bc; c1:=ec; c2:=bc; c3:=ec; for c:=bc to ec do if char_wd[c]>0 then begin temp_width:=memory[char_wd[c]]; if design_units<>unity then temp_width:=round((temp_width/design_units)*1048576.0); temp_width:=temp_width + (c+4)*@'20000000; {this should be positive} c0:=(c0+c0+temp_width) mod 255; c1:=(c1+c1+temp_width) mod 253; c2:=(c2+c2+temp_width) mod 251; c3:=(c3+c3+temp_width) mod 247; end; header_bytes[check_sum_loc]:=c0; header_bytes[check_sum_loc+1]:=c1; header_bytes[check_sum_loc+2]:=c2; header_bytes[check_sum_loc+3]:=c3; end */ #define add_tfmwidth(v) (add_tfmtable(widthtab, &numwidth, v, MAXWIDTHTAB,\ "TFM width")) #define add_tfmheight(v) (add_tfmtable(heighttab, &numheight, v, MAXHEIGHTTAB,\ "TFM height")) #define add_tfmdepth(v) (add_tfmtable(depthtab, &numdepth, v, MAXDEPTHTAB,\ "TFM depth")) #define add_tfmitalic(v) (add_tfmtable(italictab, &numitalic, v, MAXITALICTAB,\ "Italic correction")) static byte add_tfmtable(int * const table, int * const count, int const value, int const max_count, const char * const name) { integer i; for (i = 0; i < *count; i++) /* search for value in tfm table */ if (table[i] == value) return (byte)i; if (*count >= max_count) pm_error("too many values in %s table", name) ; if (!fixrange(value)) pm_error("%s %f for char %d out of range", name, unfixword(value), car); table[*count] = value ; return (*count)++ ; } /* add a suffix to a filename in an allocated space */ static void pbmtopk_add_suffix(char * const name, const char * const suffix) { char *slash = strrchr(name, '/'); char *dot = strrchr(name, '.'); if ((dot && slash ? dot < slash : !dot) && !streq(name, "-")) strcat(name, suffix); } /* initialize the PK parameters */ static void initialize_pk(void) { integer i ; pm_message("This is PBMtoPK, version 2.4") ; for (i = 127 ; i <= 255 ; i ++) xchr[i] = '?' ; for (i = 0 ; i <= 127 ; i ++) xord[i] = 32 ; for (i = 32 ; i < 127 ; i ++) xord[(int)xchr[i]] = i ; for (i = 0; i < MAXPKCHAR; i++) { filename[i] = NULL; charflags[i] = 0; } designsize = fixword(1.0) ; } /* write a single byte to the PK file */ static void pbmtopk_pkbyte(integer const b_in) { integer b; b = b_in; /* initial value */ if (b < 0) b += 256 ; putc(b, pkfile) ; pbmtopk_pkloc++ ; } /* write two bytes to the PK file */ static void pkhalfword(integer const a_in) { integer a; a = a_in; if (a < 0) a += 65536 ; pbmtopk_pkbyte(a >> 8) ; pbmtopk_pkbyte(a & 255) ; } /* write three bytes to the PK file */ static void pkthreebytes(integer const a) { pbmtopk_pkbyte((a>>16) & 255) ; pbmtopk_pkbyte((a>>8) & 255) ; pbmtopk_pkbyte(a & 255) ; } /* write four bytes to the PK file */ static void pkword(integer const a) { pbmtopk_pkbyte((a>>24) & 255) ; pbmtopk_pkbyte((a>>16) & 255) ; pbmtopk_pkbyte((a>>8) & 255) ; pbmtopk_pkbyte(a & 255) ; } /* write a nibble to the PK file */ static void pknyb(integer const a) { if (bitweight == 16) { outputbyte = (a<<4) ; bitweight = 1 ; } else { pbmtopk_pkbyte(outputbyte + a) ; bitweight = 16 ; } } /* write preamble to PK file */ static void writepreamble(void) { integer i ; const char * const comment = "PBMtoPK 2.4 output" ; pbmtopk_pkbyte(247) ; /* PRE command */ pbmtopk_pkbyte(89) ; /* PK file type */ pbmtopk_pkbyte(strlen(comment)) ; /* output comment */ for (i = 0 ; i < strlen(comment); i++) pbmtopk_pkbyte(xord[(int)comment[i]]) ; pkword(designsize) ; /* write designsize */ pkword(checksum) ; /* write checksum; calculate if possible */ pkword(hppp) ; /* write H pixels per point */ pkword(hppp) ; /* write V pixels per point */ } /* write postamble to PK file, padded to word length */ static void writepostamble(void) { pbmtopk_pkbyte(245) ; /* POST command */ while (pbmtopk_pkloc % 4) pbmtopk_pkbyte(246) ; /* pad with no-ops */ pm_message("%d bytes written to packed file.", pbmtopk_pkloc) ; } /* write a byte to the TFM file */ static void tfmbyte(integer const b_in) { integer b; b = b_in; if (b < 0) b += 256 ; putc(b, tfmfile) ; } /* write a half word to the TFM file */ static void tfmhalfword(integer const a_in) { integer a; a = a_in; if (a < 0) a += 65536 ; tfmbyte(a >> 8) ; tfmbyte(a & 255) ; } /* write a word to the TFM file */ static void tfmword(integer const a) { tfmbyte((a>>24) & 255) ; tfmbyte((a>>16) & 255) ; tfmbyte((a>>8) & 255) ; tfmbyte(a & 255) ; } /* write the whole TFM file for the font */ static void writetfmfile(void) { integer totallength ; integer headersize = 17; integer i ; if (largestch - smallestch < 0) { largestch = 0; smallestch = 1; } if (numparam < 7) /* set default parameters */ switch (numparam) { case 0: /* slant */ parameters[numparam++] = 0 ; case 1: /* space */ parameters[numparam++] = fixword(designunits(emwidth/3.0)); case 2: /* space_stretch */ parameters[numparam++] = fixword(unfixword(parameters[1])/2.0) ; case 3: /* space_shrink */ parameters[numparam++] = fixword(unfixword(parameters[1])/3.0) ; case 4: /* x_height */ parameters[numparam++] = fixword(0.45); case 5: /* quad */ parameters[numparam++] = fixword(designunits(emwidth)) ; case 6: /* extra_space */ parameters[numparam++] = fixword(unfixword(parameters[1])/3.0) ; } totallength = 6 + headersize + (largestch+1-smallestch) + numwidth + numheight + numdepth + numitalic + numparam ; /* lengths */ tfmhalfword(totallength) ; /* write file TFM length */ tfmhalfword(headersize) ; /* write TFM header length */ tfmhalfword(smallestch) ; /* write lowest char index */ tfmhalfword(largestch) ; /* write highest char index */ tfmhalfword(numwidth) ; /* write number of widths */ tfmhalfword(numheight) ; /* write number of heights */ tfmhalfword(numdepth) ; /* write number of depths */ tfmhalfword(numitalic) ; /* write number of italcorrs */ tfmhalfword(0) ; /* lig/kern table */ tfmhalfword(0) ; /* kern table */ tfmhalfword(0) ; /* extensible char table */ tfmhalfword(numparam) ; /* number of fontdimens */ /* header */ tfmword(checksum) ; /* write checksum */ tfmword(designsize) ; /* write designsize */ if (strlen(codingscheme) > 39) tfmbyte(39) ; /* write coding scheme len */ else tfmbyte(strlen(codingscheme)) ; for (i = 0; i < 39; i++) /* write coding scheme */ if (*codingscheme) tfmbyte(xord[(int)(*codingscheme++)]) ; else tfmbyte(0) ; if (strlen(familyname) > 19) tfmbyte(19) ; /* write family length */ else tfmbyte(strlen(familyname)) ; for (i = 0; i < 19; i++) /* write family */ if (*familyname) tfmbyte(xord[(int)(*familyname++)]) ; else tfmbyte(0) ; /* char_info */ for (car = smallestch; car <= largestch; car++) if (filename[car]) { /* write character info */ tfmbyte(tfmindex[car]) ; tfmbyte((hgtindex[car]<<4) + depindex[car]) ; tfmbyte(italindex[car]<<2) ; tfmbyte(0) ; } else tfmword(0) ; /* width table */ for (i = 0; i < numwidth; i++) tfmword(widthtab[i]) ; /* height table */ for (i = 0; i < numheight; i++) tfmword(heighttab[i]) ; /* depth table */ for (i = 0; i < numdepth; i++) tfmword(depthtab[i]) ; /* italic correction table */ for (i = 0; i < numitalic; i++) tfmword(italictab[i]) ; /* no lig_kern, kern, or extent tables */ /* fontdimen table */ for (i = 0; i < numparam; i++) if (i && !fixrange(parameters[i])) pm_error("parameter %d out of range (-p)", i); else tfmword(parameters[i]) ; pm_message("%d bytes written to tfm file.", totallength*4) ; } /* read a character from a PBM file */ static void readcharacter(void) { FILE *fp; fp = pm_openr(filename[car]); bitmap = pbm_readpbm(fp, &width, &height) ; pm_close(fp) ; if ((charflags[car] & HORZESC) == 0) horzesc[car] = width ; if ((charflags[car] & VERTESC) == 0) vertesc[car] = 0; if ((charflags[car] & XOFFSET) == 0) xoffset[car] = 0; if ((charflags[car] & YOFFSET) == 0) yoffset[car] = height-1; if ((charflags[car] & TFMWIDTH) == 0) tfmindex[car] = add_tfmwidth(fixword(designunits(width))); if ((charflags[car] & TFMHEIGHT) == 0) hgtindex[car] = add_tfmheight(fixword(designunits(yoffset[car]+1))); if ((charflags[car] & TFMDEPTH) == 0) depindex[car] = add_tfmdepth(fixword(designunits(height-1-yoffset[car]))); if ((charflags[car] & TFMITALIC) == 0) italindex[car] = 0; if (car < smallestch) smallestch = car; if (car > largestch) largestch = car; if (width > emwidth) emwidth = width ; } /* test if two rows of the PBM are the same */ static int equal(const bit * const row1, const bit * const row2) { integer i ; for (i = 0; i < width; i++) if (row1[i] != row2[i]) return (0) ; return(1) ; } static void shipcharacter(void) { integer compsize ; integer i, j, k ; bit *zerorow, *onesrow ; integer *repeatptr, *bitcounts ; integer count ; integer test ; integer curptr, rowptr ; integer bitval ; integer repeatflag ; integer colptr ; integer currepeat ; integer dynf ; integer deriv[14] ; integer bcompsize ; boolean firston ; integer flagbyte ; boolean state ; boolean on ; integer hbit ; integer pbit ; boolean ron, son ; integer rcount, scount ; integer ri, si ; integer max2 ; integer predpkloc ; integer buff ; integer tfwid = widthtab[tfmindex[car]] ; integer hesc = horzesc[car] ; integer vesc = vertesc[car] ; integer xoff = xoffset[car] ; integer yoff = yoffset[car] ; MALLOCARRAY(repeatptr, height + 1); MALLOCARRAY(bitcounts, height * width); if (repeatptr == NULL || bitcounts == NULL) pm_error("out of memory while allocating bit counts"); zerorow = pbm_allocrow(width) ; /* initialize plain rows */ onesrow = pbm_allocrow(width) ; for (i = 0 ; i < width ; i++) { zerorow[i] = PBM_WHITE ; onesrow[i] = PBM_BLACK ; } for (i=0; i < height; i = k) { /* set repeat pointers */ k = i + 1; if (!equal(bitmap[i], zerorow) && !equal(bitmap[i], onesrow)) { while (k < height && equal(bitmap[i], bitmap[k])) k++; repeatptr[i] = k - i - 1; } else { repeatptr[i] = 0; } } repeatptr[height] = 0 ; colptr = width - 1 ; repeatflag = currepeat = curptr = count = rowptr = 0 ; test = PBM_WHITE ; do { colptr++ ; if (colptr == width) { /* end of row, get next row */ colptr = 0 ; rowptr = currepeat ; if (repeatptr[currepeat] > 0) { repeatflag = repeatptr[currepeat] ; currepeat += repeatflag ; rowptr += repeatflag ; } currepeat++ ; } if (rowptr >= height) bitval = -1 ; else bitval = bitmap[rowptr][colptr] ; if (bitval == test) count++ ; /* count repeated pixels */ else { /* end of pixel run */ bitcounts[curptr++] = count ; if (curptr+3 >= height*width) pm_error("out of memory while saving character counts"); count = 1 ; test = bitval ; if (repeatflag > 0) { bitcounts[curptr++] = -repeatflag ; repeatflag = 0 ; } } } while (test != -1) ; bitcounts[curptr] = 0 ; bitcounts[curptr + 1] = 0 ; for (i = 1 ; i <= 13 ; i ++) deriv[i] = 0 ; i = firston = (bitcounts[0] == 0) ; compsize = 0 ; while (bitcounts[i] != 0) { /* calculate dyn_f */ j = bitcounts[i] ; if (j == -1) compsize++ ; else { if (j < 0) { compsize++ ; j = -j ; } if (j < 209) compsize += 2 ; else { k = j - 193 ; while (k >= 16) { k >>= 4 ; compsize += 2 ; } compsize++ ; } if (j < 14) (deriv[j])-- ; else if (j < 209) (deriv[(223 - j) / 15])++ ; else { k = 16 ; while (((k<<4) < j + 3)) k <<= 4 ; if (j - k <= 192) deriv[(207 - j + k) / 15] += 2 ; } } i++ ; } bcompsize = compsize ; dynf = 0 ; for (i = 1 ; i <= 13 ; i ++) { compsize += deriv[i] ; if (compsize <= bcompsize) { bcompsize = compsize ; dynf = i ; } } compsize = ((bcompsize + 1)>>1) ; if ((compsize > ((height*width+7)>>3)) || (height*width == 0)) { compsize = ((height*width+7)>>3) ; dynf = 14 ; } flagbyte = (dynf<<4) ; if (firston) flagbyte |= 8 ; if (tfwid > 16777215 || tfwid < 0 || hesc < 0 || vesc != 0 || compsize > 196579 || width > 65535 || height > 65535 || xoff > 32767 || yoff > 32767 || xoff < -32768 || yoff < -32768) { flagbyte |= 7 ; /* long form preamble */ pbmtopk_pkbyte(flagbyte) ; compsize += 28 ; pkword(compsize) ; /* char packet size */ pkword(car) ; /* character number */ predpkloc = pbmtopk_pkloc + compsize ; pkword(tfwid) ; /* TFM width */ pkword(hesc<<16) ; /* horiz escapement */ pkword(vesc<<16) ; /* vert escapement */ pkword(width) ; /* bounding box width */ pkword(height) ; /* bounding box height */ pkword(xoff) ; /* horiz offset */ pkword(yoff) ; /* vert offset */ } else if (hesc > 255 || width > 255 || height > 255 || xoff > 127 || yoff > 127 || xoff < -128 || yoff < -128 || compsize > 1016) { compsize += 13 ; /* extended short preamble */ flagbyte += (compsize>>16) + 4 ; pbmtopk_pkbyte(flagbyte) ; pkhalfword(compsize & 65535) ; /* char packet size */ pbmtopk_pkbyte(car) ; /* character number */ predpkloc = pbmtopk_pkloc + compsize ; pkthreebytes(tfwid) ; /* TFM width */ pkhalfword(hesc) ; /* horiz escapement */ pkhalfword(width) ; /* bounding box width */ pkhalfword(height) ; /* bounding box height */ pkhalfword(xoff) ; /* horiz offset */ pkhalfword(yoff) ; /* vert offset */ } else { compsize += 8 ; /* short form preamble */ flagbyte = flagbyte + (compsize>>8) ; pbmtopk_pkbyte(flagbyte) ; pbmtopk_pkbyte(compsize & 255) ; /* char packet size */ pbmtopk_pkbyte(car) ; /* character number */ predpkloc = pbmtopk_pkloc + compsize ; pkthreebytes(tfwid) ; /* TFM width */ pbmtopk_pkbyte(hesc) ; /* horiz escapement */ pbmtopk_pkbyte(width) ; /* bounding box width */ pbmtopk_pkbyte(height) ; /* bounding box height */ pbmtopk_pkbyte(xoff) ; /* horiz offset */ pbmtopk_pkbyte(yoff) ; /* vert offset */ } if (dynf != 14) { /* write packed character */ bitweight = 16 ; max2 = 208 - 15 * dynf ; i = firston ; while (bitcounts[i] != 0) { j = bitcounts[i] ; if (j == - 1) pknyb(15) ; else { if (j < 0) { pknyb(14) ; j = -j ; } if (j <= dynf) pknyb(j) ; else if (j <= max2) { j -= dynf + 1 ; pknyb((j >> 4) + dynf + 1) ; pknyb((j & 15)) ; } else { j -= max2 - 15 ; k = 16 ; while (k <= j) { k <<= 4 ; pknyb(0) ; } while (k > 1) { k >>= 4 ; pknyb(j / k) ; j = j % k ; } } } i++ ; } if (bitweight != 16) pbmtopk_pkbyte(outputbyte) ; } else { /* write bitmap character */ buff = 0 ; pbit = 8 ; i = firston ; hbit = width ; on = ! firston ; state = 0 ; count = repeatflag = 0 ; while ((bitcounts[i] != 0) || state || (count > 0)) { if (state) { count = rcount ; i = ri ; on = ron ; repeatflag-- ; } else { rcount = count ; ri = i ; ron = on ; } do { if (count == 0) { if (bitcounts[i] < 0) { if (! state) repeatflag = -bitcounts[i] ; i++ ; } count = bitcounts[i] ; i++ ; on = !on ; } if ((count >= pbit) && (pbit < hbit)) { if (on) buff += (1 << pbit) - 1 ; pbmtopk_pkbyte(buff) ; buff = 0 ; hbit -= pbit ; count -= pbit ; pbit = 8 ; } else if ((count < pbit) && (count < hbit)) { if (on) buff += (1 << pbit) - (1 << (pbit - count)) ; pbit -= count ; hbit -= count ; count = 0 ; } else { if (on) buff += (1 << pbit) - (1 << (pbit - hbit)) ; count -= hbit ; pbit -= hbit ; hbit = width ; if (pbit == 0) { pbmtopk_pkbyte(buff) ; buff = 0 ; pbit = 8 ; } } } while (hbit != width) ; if (state && (repeatflag == 0)) { count = scount ; i = si ; on = son ; state = 0 ; } else if (! state && (repeatflag > 0)) { scount = count ; si = i ; son = on ; state = 1 ; } } if (pbit != 8) pbmtopk_pkbyte(buff) ; } if (predpkloc != pbmtopk_pkloc) pm_error("bad predicted character length: character %d", car); pbm_freerow(zerorow); pbm_freerow(onesrow); free((char *)repeatptr); free((char *)bitcounts); } /* check that character is in valid range */ static void checkchar(void) { if (car < 0 || car >= MAXPKCHAR) pm_error("character must be in range 0 to %d", MAXPKCHAR-1) ; } /* read character information from an option file */ static void optionfile(const char * const name) { FILE *fp ; char buffer[MAXOPTLINE] ; fp = pm_openr(name); while (!feof(fp)) { char *here = buffer; if (fgets(buffer, MAXOPTLINE, fp) == NULL) break ; while (ISSPACE(*here)) here++ ; if (*here && *here == '=') { if (sscanf(here+1, "%d", &car) != 1) pm_error("bad option file line %s", buffer) ; } else if (*here && *here != '%' && *here != '#') { char str[NAMELENGTH] ; integer i, n; checkchar() ; if (sscanf(here, "%s%n", str, &n) != 1) pm_error("bad option file line %s", buffer) ; filename[car] = strdup(str); if (filename[car] == NULL) pm_error("out of memory allocating filename %s", str); for (i = 1; i < 256; i<<=1) { here += n; if (sscanf(here, "%s%n", str, &n) != 1) break ; if (strcmp(str, "*")) { charflags[car] |= i ; switch (i) { case XOFFSET: xoffset[car] = atoi(str) ; break ; case YOFFSET: yoffset[car] = atoi(str) ; break ; case HORZESC: horzesc[car] = atoi(str) ; break ; case VERTESC: vertesc[car] = atoi(str) ; break ; case TFMWIDTH: tfmindex[car] = add_tfmwidth(fixword(atof(str))) ; break ; case TFMHEIGHT: hgtindex[car] = add_tfmheight(fixword(atof(str))) ; break ; case TFMDEPTH: depindex[car] = add_tfmdepth(fixword(atof(str))) ; break ; case TFMITALIC: italindex[car] = add_tfmitalic(fixword(atof(str))) ; break ; } } } car++ ; } } pm_close(fp) ; } int main(int argc, char *argv[]) { integer i, hesc, vesc, xoff, yoff, tfwid, tfdep, tfhgt, tfital ; byte flags ; const char * const usage = "pkfile[.pk] tfmfile[.tfm] dpi " "[-s designsize] [-p num param...]\n" "[-C codingscheme ] [-F family] [-c num | ]...\n" " is:\n" "[-W tfmwidth] [-H tfmheight] [-D tfmdepth] [-I ital_corr] " "[-h horiz]\n" "[-v vert] [-x xoffset] [-y yoffset] file\n" "or:\n" "-f optfile\n" ; pbm_init(&argc, argv); initialize_pk() ; if (--argc < 1) pm_usage(usage) ; ++argv; if(strlen(*argv) + 4 > NAMELENGTH) pm_error("pkname is too long"); strcpy(pkname, *argv) ; pbmtopk_add_suffix(pkname, ".pk") ; if (--argc < 1) pm_usage(usage); ++argv; if(strlen(*argv) + 4 > NAMELENGTH) pm_error("tfmname is too long"); strcpy(tfmname, *argv) ; pbmtopk_add_suffix(tfmname, ".tfm") ; if (--argc < 1) pm_usage(usage) ; resolution = atoi(*++argv) ; if (resolution < 1 || resolution > 32767) pm_error("unlikely resolution %d dpi", resolution); car = flags = hesc = vesc = xoff = yoff = tfwid = 0; while (++argv, --argc) { if (argv[0][0] == '-' && argv[0][1]) { char c, *p; c = argv[0][1] ; if (argv[0][2]) p = *argv + 2 ; /* set argument pointer */ else if (++argv, --argc) p = *argv ; else pm_usage(usage) ; switch (c) { case 'C': codingscheme = p; break ; case 'F': familyname = p; break ; case 'c': car = atoi(p) ; break ; case 's': designsize = fixword(atof(p)); if (designsize < 1048576) pm_error("design size %f out of range", unfixword(designsize)); case 'h': hesc = atoi(p) ; flags |= HORZESC ; break ; case 'v': vesc = atoi(p) ; flags |= VERTESC ; break ; case 'x': xoff = atoi(p) ; flags |= XOFFSET ; break ; case 'y': yoff = atoi(p) ; flags |= YOFFSET ; break ; case 'W': tfwid = fixword(atof(p)) ; flags |= TFMWIDTH ; break ; case 'H': tfhgt = fixword(atof(p)) ; flags |= TFMHEIGHT ; break ; case 'D': tfdep = fixword(atof(p)) ; flags |= TFMDEPTH ; break ; case 'I': tfital = fixword(atof(p)) ; flags |= TFMITALIC ; break ; case 'f': optionfile(p) ; break ; case 'p': numparam = atoi(p); if (numparam < 1 || numparam > MAXPARAMS) pm_error("parameter count %d out of range", numparam); for (i=0; i