#ifndef lint static char *rcs = "$Header: tfm2ofont.c,v 1.1 88/01/15 13:05:54 simpson Rel $"; #endif /* $Log: tfm2ofont.c,v $ * Revision 1.1 88/01/15 13:05:54 simpson * initial release * * Revision 0.1 87/12/11 18:31:26 simpson * beta test * */ #include #include #include #include "constants.h" extern char RegularOrder[], SpecialOrder[]; /* Order we want to output */ char OutputFile[81]; char TfmName[81]; /* Only used in error routine */ char *WhoAmI; /* Argv[0] */ char *Usage = "Usage: %s [-s] file...\n"; Boolean Special = FALSE; /* Designates whether font is special */ int ExitStatus = SUCCEED; main(argc, argv) int argc; char *argv[]; { extern int optind; extern char *optarg; int c; FILE *infile, *outfile; void seteoffunction(), tfmeofsoexit(), convert(); char *strcpy(), *strcat(), *strncat(); WhoAmI = argv[0]; while ((c = getopt(argc, argv, "s")) != EOF) switch (c) { case 's': Special = TRUE; break; case '?': fprintf(stderr, Usage, WhoAmI); exit(FAIL); } seteoffunction(tfmeofsoexit); for (; optind < argc; optind++) { if (strlen(argv[optind]) < 5 || !EQ(".tfm", &argv[optind][strlen( argv[optind])-4])) { fprintf(stderr, "%s: invalid input file name %s\n", WhoAmI, argv[optind]); ExitStatus = FAIL; continue; } if (!(infile = fopen(argv[optind], "r"))) { fprintf(stderr, "%s: cannot open input file %s\n", WhoAmI, argv[optind]); ExitStatus = FAIL; continue; } (void)strcpy(TfmName, argv[optind]); (void)strcpy(OutputFile, "ft"); (void)strncat(OutputFile, argv[optind], strlen(argv[optind])-4); (void)strcat(OutputFile, ".c"); if (!(outfile = fopen(OutputFile, "w"))) { fprintf(stderr, "%s: cannot open output file %s\n", WhoAmI, OutputFile); ExitStatus = FAIL; continue; } convert(infile, outfile, argv[optind]); (void)fclose(infile), (void)fclose(outfile); } exit(ExitStatus); } /* The main routine which converts a tfm file to an otroff width table file. */ void convert(infile, outfile, inname) FILE *infile, *outfile; char *inname; { long aheight, i, j, widthindex, heightanddepth, zero, height, depth, charpos; long widths[256][2]; /* Width of char in FIX/designsize & kern */ unsigned long uinteger(), lh, bc, ec, nw, nh, designsize; long integer(), getaheight(); fprintf(outfile, "char font[256-32] = {\n"); if ((aheight = getaheight(infile)) == MAX_INTEGER) { fprintf(stderr, "%s: no letter 'a' in file %s\n", WhoAmI, inname); fprintf(stderr, "\tsetting height to zero\n"); aheight = 0; } rewind(infile); bzero((char *)widths, sizeof(widths)); (void)uinteger(infile, 2); /* lf */ lh = uinteger(infile, 2); bc = uinteger(infile, 2); ec = uinteger(infile, 2); nw = uinteger(infile, 2); nh = uinteger(infile, 2); (void)uinteger(infile, 2); /* nd */ (void)uinteger(infile, 2); /* ni */ (void)uinteger(infile, 2); /* nl */ (void)uinteger(infile, 2); /* nk */ (void)uinteger(infile, 2); /* ne */ (void)uinteger(infile, 2); /* np */ (void)uinteger(infile, 4); /* Skip checksum */ designsize = uinteger(infile, 4) / FIX; for (i = bc; i <= ec; i++) { (void)fseek(infile, 24L + 4 * lh + (i - bc) * 4, 0); widthindex = uinteger(infile, 1); heightanddepth = uinteger(infile, 1); if (widthindex == 0) continue; (void)fseek(infile, 24L + 4 * lh + (ec - bc + 1) * 4 + widthindex * 4, 0); widths[i][0] = integer(infile, 4); (void)fseek(infile, 24L + 4 * lh + (ec - bc + 1) * 4 + nw * 4 + (heightanddepth >> 4) * 4, 0); height = uinteger(infile, 4); (void)fseek(infile, 24L + 4 * lh + (ec - bc + 1) * 4 + nw * 4 + nh * 4 + (heightanddepth & 0xF) * 4, 0); depth = uinteger(infile, 4); if (!Special && isalnum(i) || Special && (0101 <= i && i <= 0130 || 0141 <= i && i <= 0170 || i == 014 || i == 050)) { if (height > aheight) /* Letters taller than 'a' get 0200 */ widths[i][1] |= 0200; /* turned on. */ if (depth > 0) /* Letters below baseline get 0100 */ widths[i][1] |= 0100; /* turned on. */ } } for (i = 040, zero = 0; i < 256; i++) { if (i == 0177 && !Special) { /* 1/16em is always 6 units */ if (zero) { zero = 0; putc('\n', outfile); } fprintf(outfile, "6,\n"); continue; } if (i == 0226 && !Special) { /* 1/12em is always 3 units */ if (zero) { zero = 0; putc('\n', outfile); } fprintf(outfile, "3,\n"); continue; } if (i == ' ' && !Special) { /* Space is always 12 units */ if (zero) { zero = 0; putc('\n', outfile); } fprintf(outfile, "12,\n"); continue; } charpos = (Special ? SpecialOrder[i - 32] : RegularOrder[i - 32]); if (charpos == 0 || widths[charpos][0] == 0) { fprintf(outfile, "0,"); zero++; if (!((i+1)%8)) { putc('\n', outfile); zero = 0; } } else { if (zero) { zero = 0; putc('\n', outfile); } j = ROUND((widths[charpos][0] / (double)FIX * designsize) / PPI * 254.6457); /* Don't ask where the 254.6457 came from. I haven't the faintest * notion why troff uses this constant, but it works, and that * is fine enough with me. Otroff can't handle widths over * 63 (2^6). If you give it something greater, it take the * lower six bits. This screws up the TRW logo which is 79 but * there is nothing we can do. */ fprintf(outfile, "%d", j > 63 ? 63 : j); if (widths[charpos][1]) fprintf(outfile, "+0%o,\n", widths[charpos][1]); else fprintf(outfile, ",\n"); } } fprintf(outfile, "};\n"); } /* Returns the height of the letter 'a' in the font passed as a parameter. * The height is returned in FIXes/designsize. If the letter 'a' is not * found, MAX_INTEGER is returned. */ long getaheight(in) FILE *in; { unsigned long lh, bc, ec, nw, uinteger(); (void)fseek(in, 0L, 0); (void)uinteger(in, 2); /* lf */ lh = uinteger(in, 2); bc = uinteger(in, 2); ec = uinteger(in, 2); nw = uinteger(in, 2); (void)uinteger(in, 2); /* nh */ (void)uinteger(in, 2); /* nd */ (void)uinteger(in, 2); /* ni */ (void)uinteger(in, 2); /* nl */ (void)uinteger(in, 2); /* nk */ (void)uinteger(in, 2); /* ne */ (void)uinteger(in, 2); /* np */ if (bc > 'a' || ec < 'a') return MAX_INTEGER; (void)uinteger(in, 4); /* Skip checksum */ (void)uinteger(in, 4); /* Width */ (void)fseek(in, 24L + lh*4 + ('a'-bc)*4, 0); if (uinteger(in, 1) == 0) return MAX_INTEGER; (void)fseek(in, 24L + lh*4 + (ec-bc+1)*4 + nw*4 + (uinteger(in,1) >> 4)*4, 0); return uinteger(in, 4); } void tfmeofsoexit() { fprintf(stderr, "%s: unexpected end of tfm file %s\n", WhoAmI, TfmName); exit(FAIL); }