/* * NAME * pkfonts - generate missing PK fonts from dvifiles * * SYNOPSIS: * pkfonts [-adhm] [-x] [-B] [-M] dvifile[.dvi] ... * * DESCRIPTION * This program reads the specified dvifiles and generates the * PK fonts that are missing by calling an external program * MTPK. If the DVI file references a virtual font, one for which * a VF file exists, all fonts referenced in that virtual font * are also generated even if the DVI file does not acces a single * character from it. * With pkfonts you can easily preinstall a complete set of PK * fonts for your favourite previewer and TeX macro package. For * example to create all 11pt LaTeX fonts for the PostScript * times font style you could use: * \documentstyle[times,11pt]{article} * \input textfonts * * In textfonts you add commands like {\VARIANT\SIZE bla} for all * possible VARIANTS (\rm, \bf, etc.) and SIZES (\small, \large, etc.) * there are. The letters `bla' need to be choosen so that all virtual * fonts for VARIANT and SIZE are represented. The command pklatex * uses this approach to automatically build all 10pt, 11pt and 12pt * PK fonts for any LaTeX font style. Generation of PK fonts can best * be done at quiet hours because one can easily overload a computer. * * When the -a option is specified all fonts used in the * dvifiles are reported but not generated. With -m all missing * fonts are shown, not generated. With the -i option all existing * PK fonts referenced from the DVI file are matched against the TFM * and VF font and font with incompatible checksums are reported so * that they can be regenerated separatley. * * OPTIONS * -a show all fonts from DVI files without making * -h give a short help and exit * -i show incompatible fonts (checksum mismatches) * -d show stat calls * -v provide verbose information ('a la dvips -d2) * -m show all missing fonts from DVI files without making * -x overrule default magnification of 1000 with * -B * look for printer with basic resolution of . If * not supplied the default printer from mtpk.cfg will be used. * -M * look for printer with mode definition . * ENVIRONMENTS * TFMFONTS * Overrules TFM path. * VFFONTS * Overrules VF path. * TEXPKS * Overrules PK path. * FLIPATH * Overrules FLI. * * SEE ALSO * mtpk(1), mtpk(5), dvips(1) * AUTHOR * Piet Tutelaers * rcpt@urc.tue.nl */ #include /* fopen(), fclose(), fseek(), ... */ #include /* atoi(), malloc(), system() */ #include /* strcpy(), strcmp(), strlen() */ #include "basics.h" /* fatal(), msg() */ #include "filenames.h" /* newname() */ #include "psearch.h" /* init_pksearch(), search_file(), search_flipath(), search_pkfile(), substitute() */ #include "dvifonts.h" /* pk_fonts() */ #include "cfg.h" /* read_cfg(), cfg_value() */ #include "texfiles.h" /* four(), sone() */ #ifdef MSDOS #include "system.h" /* emx_system() */ #endif int MAG = 1000; int bdpi = 0; char *res = NULL; char *mode = NULL; int margin; char *tolerance; char *flipath; char *texconfig; char *tfmpath; char *vfpath; char *pkpath; char *mtpk; char *MTPK = "mtpk %F %d %b"; /* %F: leftadjusted in 8 chars */ short verbose = 0, debug = 0; /* forward definition */ #define UINT32 unsigned int int checksum_texfont(char *name, UINT32 *checksum); int main(int argc, char *argv[]) { int done, c; unsigned int all = 0, missing = 0, inc = 0; char *myname = "pkfonts", *dvi_name; char *p, cmd[128]; /* prototypes */ void short_help(); void add_font(char *, int); int delete_font(char *, int); void print_all_fonts(); void print_inc_fonts(); void print_miss_fonts(); void make_miss_fonts(); #if EMX /* allow UNIX style wild cards */ _wildcard(&argc, &argv); #endif /* allow `-ams', `-x1200' and `-x 1200' as options */ while (--argc > 0 && (*++argv)[0] == '-') { done=0; while ((!done) && (c = (*++argv[0]))) switch (c) { case 'a': all = 1; break; case 'd': debug = 1; pstat = my_stat; break; case 'h': short_help(); break; case 'i': inc = 1; break; case 'm': missing = 1; break; case 'v': verbose = 1; pfopen = my_fopen; break; case 'x': /* magnification */ if (*++argv[0] == '\0') { argc--; argv++; } MAG = atoi(argv[0]); done = 1; break; case 'B': /* basic resolution */ if (*++argv[0] == '\0') { argc--; argv++; } res = argv[0]; done = 1; break; case 'M': /* mode */ if (*++argv[0] == '\0') { argc--; argv++; } mode = argv[0]; done = 1; break; default: fatal("%s: %c illegal option\n", myname, c); } } if (argc == 0) fatal("Usage: %s [-adhimv] [-x] [-B] " "[-M] dvi_file[.dvi] ...\n", myname, myname); /* read configuration parameters for res and mode */ if (read_cfg(res, mode)) if (res == NULL && mode == NULL) fatal("No default printer data available in mtpk.cfg\n"); else if (mode == NULL) fatal("No data available for %s dpi in mtpk.cfg\n", res); else if (res == NULL) fatal("No data available for %s in mtpk.cfg\n", mode); /* get the basic defaults from mtpk.cfg */ bdpi = atoi(cfg_value("res")); mode = cfg_value("mode"); if ((p = cfg_value("margin")) == NULL) margin = 0; else margin = atoi(p); tolerance = cfg_value("tolerance"); /* set global PK search parameters */ init_pksearch(bdpi, mode, margin, tolerance); /* get default paths */ if ((tfmpath = cfg_value("tfmpath")) == NULL) fatal("definition of tfmpath missing in mtpk.cfg\n"); if ((pkpath = cfg_value("pkpath")) == NULL) fatal("definition of pkpath missing in mtpk.cfg\n"); if ((vfpath = cfg_value("vfpath")) == NULL) fatal("definition of vfpath missing in mtpk.cfg\n"); flipath = cfg_value("flipath"); /* Show them whith -v flag */ if (verbose) { msg("Printer: resolution = %d dpi, mode = %s\n", bdpi, mode); msg("tfmpath = %s\n", tfmpath); msg(" pkpath = %s\n", pkpath); msg(" vfpath = %s\n", vfpath); if (flipath) msg("flipath = %s\n", flipath); } /* get name and arguments for mtpk(1) */ mtpk = cfg_value("mtpk"); if (mtpk == NULL) mtpk = MTPK; /* propagate -v and -d flags through mtpk */ if ((verbose || debug) && strncmp(mtpk, "mtpk", 4) == 0) { char cmd[128]; strcpy(cmd, "mtpk -"); if (verbose) strcat(cmd, "v"); if (debug) strcat(cmd, "d"); strcat(cmd, mtpk+4); if ((mtpk = malloc(strlen(cmd)+1)) == NULL) fatal("Out of memory\n"); strcpy(mtpk, cmd); } while (argc--) { char *fnt; int dpi; dvi_name = newname(argv[0], ".dvi"); argv++; pk_fonts(dvi_name, bdpi, MAG, (void (*)(char *, int)) add_font); } if (all) print_all_fonts(); else if (missing) print_miss_fonts(); else if (inc) print_inc_fonts(); else make_miss_fonts(); exit(0); } /* refresh our poor memories */ void short_help() { fprintf(stderr, "\n" " PKFONTS (VERSION 1.1, Nov 1995)\n" "\n" " generates missing PK fonts for TeX DVI files\n" "\n" " Usage: pkfonts [] dvifile[.dvi] ...\n" "\n" " With the following no fonts are made:\n" " -h provide short help -i show checksum mismatches\n" " -a show all fonts -m show all missing fonts\n" "\n" " The following overrule values from the DVI files:\n" " -x overrule default magnification of 1000 with \n" " -B overrule default base resolution with \n" " -M overrule default mode definition with \n" "\n" " (Use -v option if you need verbose info)\n" "\n"); exit(0); } /* keep track of fonts (to prevent reporting fonts twice) */ int fn = 0; struct fontinfo { char *name; int dpi; } fonts[256]; /* * Add font to our list */ void add_font(char *name, int dpi) { int i, trydpi; trydpi = nearesthalf(dpi); for (i=0; i < fn; i++) if (strcmp(fonts[i].name, name) == 0 && fonts[i].dpi == trydpi) return; fonts[fn].name = (char *) malloc(strlen(name)+1); strcpy(fonts[fn].name, name); fonts[fn].dpi = trydpi; fn++; if (fn == 257) fatal("overflow in font table (more than 256 fonts)\n"); } /* * Remove font from our list */ int delete_font(char *name, int dpi) { int i, trydpi; for (i=0; i < fn; i++) { trydpi = nearesthalf(dpi); if (strcmp(fonts[i].name, name) == 0 && fonts[i].dpi == trydpi) { /* whoops PK found in .fli file */ fonts[i].name = fonts[fn-1].name; fonts[i].dpi = fonts[fn-1].dpi; fn--; return 0; } } return 0; } void print_all_fonts() { int i; char cmd[128]; for (i=0; i < fn; i++) { strcpy(cmd, mtpk); substitute(&cmd[0], "%F%f%d%b", fonts[i].name, fonts[i].name, fonts[i].dpi, bdpi); printf("%s\n", cmd); } } void print_miss_fonts() { int i; char *pkfile, cmd[128]; /* remove PK fonts found in .fli files from flipath */ if (flipath) search_flipath(flipath, (int (*)(char *, int)) delete_font); for (i=0; i < fn; i++) { pkfile = search_pkfile(pkpath, fonts[i].name, fonts[i].dpi); if (pkfile == NULL) { strcpy(cmd, mtpk); substitute(&cmd[0], "%F%f%d%b", fonts[i].name, fonts[i].name, fonts[i].dpi, bdpi); printf("%s\n", cmd); } } } /* print incompatible fonts */ void print_inc_fonts() { int i, vf; UINT32 cs_tfm, cs_vf, cs_pk; char *fname, *nn, cmd[128]; /* remove PK fonts found in .fli files from flipath */ if (flipath) search_flipath(flipath, (int (*)(char *, int)) delete_font); for (i=0; i < fn; i++) { nn = newname(fonts[i].name, ".tfm"); fname = search_file(tfmpath, nn, NONFATAL); if (fname == NULL) { msg("%s: not found in %s\n", nn, tfmpath); continue; } if (checksum_texfont(fname, &cs_tfm) == 0) fatal("%s: can not read checksum\n", fname); nn = newname(fonts[i].name, ".vf"); fname = search_file(vfpath, nn, NONFATAL); vf = 0; if (fname != NULL) { if (checksum_texfont(fname, &cs_vf) == 0) fatal("%s: can not read checksum\n", fname); vf = 1; } fname = search_pkfile(pkpath, fonts[i].name, fonts[i].dpi); if (fname == NULL) continue; if (checksum_texfont(fname, &cs_pk) == 0) fatal("%s: can not read checksum\n", fname); if ((cs_tfm != cs_pk) || (vf && cs_tfm != cs_vf) || (vf && cs_vf != cs_pk)) { strcpy(cmd, mtpk); substitute(&cmd[0], "%F%f%d%b", fonts[i].name, fonts[i].name, fonts[i].dpi, bdpi); printf("%s\n", cmd); } } } void make_miss_fonts() { int i, dontmake = 0; char *pkname; char cmd[128]; /* remove PK fonts found in .fli files from flipath */ if (flipath) search_flipath(flipath, (int (*)(char *, int)) delete_font); for (i=0; i < fn; i++) { pkname = search_pkfile(pkpath, fonts[i].name, fonts[i].dpi); if (pkname == NULL) { strcpy(cmd, mtpk); substitute(cmd, "%F%f%d%b", fonts[i].name, fonts[i].name, fonts[i].dpi, bdpi); printf("%s\n", cmd); if (dontmake) continue; #ifdef MSDOS if (emx_system(cmd) == -1) { #else if (system(cmd) == -1) { #endif msg("%s: failed\n", cmd); dontmake = 1; continue; } pkname = search_pkfile(pkpath, fonts[i].name, fonts[i].dpi); if (pkname == NULL) { msg("can not find %s at size %d\n", fonts[i].name, fonts[i].dpi); msg("automatic font generation stopped\n"); dontmake = 1; } } } } #define PKPRE 247 #define PKID 89 #define VFID 202 /* * Checksum_texfont() reads the of a TFM file (if filename ends * with ".tfm"), PK file (if magic code equals PK) or or VF file (if magic * code equals VF). Function returns 1 upon succes otherwise (no TFM, PK or * VF file) 0. */ int checksum_texfont(char *name, UINT32 *checksum) { FILE *fontfp; int id, i; if ((fontfp= fopen(name, RB)) == NULL) fatal("%s: can't open file\n", name); if (strcmp(name+strlen(name)-4, ".tfm") ==0) { if (fseek(fontfp, 24L, 0)) { fclose(fontfp); fatal("%s: really a TFM font?\n", name); } *checksum = four(fontfp); /* checksum */ fclose(fontfp); return(1); } /* PK or VF font? */ if (sone(fontfp) != PKPRE) return 0; id = sone(fontfp); if (id == VFID) { /* skip header */ for(i=sone(fontfp); i>0; i--) (void)sone(fontfp) ; *checksum = four(fontfp); /* checksum */ } else if (id == PKID) { /* skip header */ for(i=sone(fontfp); i>0; i--) (void)sone(fontfp) ; (void) four(fontfp); /* design size */ *checksum = four(fontfp); /* checksum */ } else return 0; fclose(fontfp); return(1); }