#ifndef lint static char *rcs = "$Header: tfm2difont.c,v 1.1 88/01/15 13:05:47 simpson Rel $"; #endif /* $Log: tfm2difont.c,v $ * Revision 1.1 88/01/15 13:05:47 simpson * initial release * * Revision 0.2 88/01/06 08:57:45 simpson * added l. and L. for pic dots * * Revision 0.1 87/12/11 18:31:24 simpson * beta test * */ #include #include #include "constants.h" #include "dev.h" /* An octal number designates that the character isn't normally in troff */ char *NormalSequences[][5] = { /* Troff representations */ /* Put the 1/6 em \| in the 000 position */ /* 000 */ "\\|", NULL, NULL, NULL, NULL, /* 001 */ "fi", NULL, NULL, NULL, NULL, /* 002 */ "fl", NULL, NULL, NULL, NULL, /* 003 */ "ff", NULL, NULL, NULL, NULL, /* 004 */ "\\-", "en", NULL, NULL, NULL, /* 005 */ "ru", NULL, NULL, NULL, NULL, /* 006 */ "em", NULL, NULL, NULL, NULL, /* 007 */ "bu", NULL, NULL, NULL, NULL, /* 010 */ "sq", NULL, NULL, NULL, NULL, /* 011 */ "fI", "Fi", NULL, NULL, NULL, /* 012 */ "fL", "Fl", NULL, NULL, NULL, /* 013 */ "de", NULL, NULL, NULL, NULL, /* 014 */ "dg", NULL, NULL, NULL, NULL, /* 015 */ "fm", NULL, NULL, NULL, NULL, /* 016 */ "co", NULL, NULL, NULL, NULL, /* 017 */ "rg", NULL, NULL, NULL, NULL, /* 020 */ "ct", NULL, NULL, NULL, NULL, /* 021 */ "14", NULL, NULL, NULL, NULL, /* 022 */ "12", NULL, NULL, NULL, NULL, /* 023 */ "34", NULL, NULL, NULL, NULL, /* The following four characters (box, open bullet, umlaut and cedilla) */ /* are not in otroff but are in ditroff. */ /* 024 */ "bx", NULL, NULL, NULL, NULL, /* 025 */ "ob", NULL, NULL, NULL, NULL, /* 026 */ "..", NULL, NULL, NULL, NULL, /* 027 */ "cd", NULL, NULL, NULL, NULL, /* 030 */ "L.", "l.", NULL, NULL, NULL, /* 031 */ "\031", NULL, NULL, NULL, NULL, /* 032 */ "\032", NULL, NULL, NULL, NULL, /* 033 */ "\033", NULL, NULL, NULL, NULL, /* 034 */ "\034", NULL, NULL, NULL, NULL, /* 035 */ "\035", NULL, NULL, NULL, NULL, /* 036 */ "\036", NULL, NULL, NULL, NULL, /* 037 */ "\037", NULL, NULL, NULL, NULL, /* 040 */ " ", NULL, NULL, NULL, NULL, /* 041 */ "!", NULL, NULL, NULL, NULL, /* 042 */ "\042", NULL, NULL, NULL, NULL, /* 043 */ "\043", NULL, NULL, NULL, NULL, /* 044 */ "$", NULL, NULL, NULL, NULL, /* 045 */ "%", NULL, NULL, NULL, NULL, /* 046 */ "&", NULL, NULL, NULL, NULL, /* 047 */ "\047", NULL, NULL, NULL, NULL, /* 050 */ "(", NULL, NULL, NULL, NULL, /* 051 */ ")", NULL, NULL, NULL, NULL, /* 052 */ "*", NULL, NULL, NULL, NULL, /* 053 */ "+", NULL, NULL, NULL, NULL, /* 054 */ ",", NULL, NULL, NULL, NULL, /* 055 */ "-", "hy", NULL, NULL, NULL, /* 056 */ ".", NULL, NULL, NULL, NULL, /* 057 */ "/", NULL, NULL, NULL, NULL, /* 060 */ "0", NULL, NULL, NULL, NULL, /* 061 */ "1", NULL, NULL, NULL, NULL, /* 062 */ "2", NULL, NULL, NULL, NULL, /* 063 */ "3", NULL, NULL, NULL, NULL, /* 064 */ "4", NULL, NULL, NULL, NULL, /* 065 */ "5", NULL, NULL, NULL, NULL, /* 066 */ "6", NULL, NULL, NULL, NULL, /* 067 */ "7", NULL, NULL, NULL, NULL, /* 070 */ "8", NULL, NULL, NULL, NULL, /* 071 */ "9", NULL, NULL, NULL, NULL, /* 072 */ ":", NULL, NULL, NULL, NULL, /* 073 */ ";", NULL, NULL, NULL, NULL, /* 074 */ "\074", NULL, NULL, NULL, NULL, /* 075 */ "\075", NULL, NULL, NULL, NULL, /* 076 */ "\076", NULL, NULL, NULL, NULL, /* 077 */ "?", NULL, NULL, NULL, NULL, /* 100 */ "\100", NULL, NULL, NULL, NULL, /* 101 */ "A", NULL, NULL, NULL, NULL, /* 102 */ "B", NULL, NULL, NULL, NULL, /* 103 */ "C", NULL, NULL, NULL, NULL, /* 104 */ "D", NULL, NULL, NULL, NULL, /* 105 */ "E", NULL, NULL, NULL, NULL, /* 106 */ "F", NULL, NULL, NULL, NULL, /* 107 */ "G", NULL, NULL, NULL, NULL, /* 110 */ "H", NULL, NULL, NULL, NULL, /* 111 */ "I", NULL, NULL, NULL, NULL, /* 112 */ "J", NULL, NULL, NULL, NULL, /* 113 */ "K", NULL, NULL, NULL, NULL, /* 114 */ "L", NULL, NULL, NULL, NULL, /* 115 */ "M", NULL, NULL, NULL, NULL, /* 116 */ "N", NULL, NULL, NULL, NULL, /* 117 */ "O", NULL, NULL, NULL, NULL, /* 120 */ "P", NULL, NULL, NULL, NULL, /* 121 */ "Q", NULL, NULL, NULL, NULL, /* 122 */ "R", NULL, NULL, NULL, NULL, /* 123 */ "S", NULL, NULL, NULL, NULL, /* 124 */ "T", NULL, NULL, NULL, NULL, /* 125 */ "U", NULL, NULL, NULL, NULL, /* 126 */ "V", NULL, NULL, NULL, NULL, /* 127 */ "W", NULL, NULL, NULL, NULL, /* 130 */ "X", NULL, NULL, NULL, NULL, /* 131 */ "Y", NULL, NULL, NULL, NULL, /* 132 */ "Z", NULL, NULL, NULL, NULL, /* 133 */ "[", NULL, NULL, NULL, NULL, /* 134 */ "\134", NULL, NULL, NULL, NULL, /* 135 */ "]", NULL, NULL, NULL, NULL, /* 136 */ "\136", NULL, NULL, NULL, NULL, /* 137 */ "_", NULL, NULL, NULL, NULL, /* 140 */ "\140", NULL, NULL, NULL, NULL, /* 141 */ "a", NULL, NULL, NULL, NULL, /* 142 */ "b", NULL, NULL, NULL, NULL, /* 143 */ "c", NULL, NULL, NULL, NULL, /* 144 */ "d", NULL, NULL, NULL, NULL, /* 145 */ "e", NULL, NULL, NULL, NULL, /* 146 */ "f", NULL, NULL, NULL, NULL, /* 147 */ "g", NULL, NULL, NULL, NULL, /* 150 */ "h", NULL, NULL, NULL, NULL, /* 151 */ "i", NULL, NULL, NULL, NULL, /* 152 */ "j", NULL, NULL, NULL, NULL, /* 153 */ "k", NULL, NULL, NULL, NULL, /* 154 */ "l", NULL, NULL, NULL, NULL, /* 155 */ "m", NULL, NULL, NULL, NULL, /* 156 */ "n", NULL, NULL, NULL, NULL, /* 157 */ "o", NULL, NULL, NULL, NULL, /* 160 */ "p", NULL, NULL, NULL, NULL, /* 161 */ "q", NULL, NULL, NULL, NULL, /* 162 */ "r", NULL, NULL, NULL, NULL, /* 163 */ "s", NULL, NULL, NULL, NULL, /* 164 */ "t", NULL, NULL, NULL, NULL, /* 165 */ "u", NULL, NULL, NULL, NULL, /* 166 */ "v", NULL, NULL, NULL, NULL, /* 167 */ "w", NULL, NULL, NULL, NULL, /* 170 */ "x", NULL, NULL, NULL, NULL, /* 171 */ "y", NULL, NULL, NULL, NULL, /* 172 */ "z", NULL, NULL, NULL, NULL, /* 173 */ "\173", NULL, NULL, NULL, NULL, /* 174 */ "|", NULL, NULL, NULL, NULL, /* 175 */ "\175", NULL, NULL, NULL, NULL, /* 176 */ "\176", NULL, NULL, NULL, NULL, /* Put the 1/12 em \^ in this position */ /* 177 */ "\\^", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; char *SpecialSequences[][5] = { /* Troff representations */ /* 000 */ "\000", NULL, NULL, NULL, NULL, /* 001 */ "if", NULL, NULL, NULL, NULL, /* 002 */ "ip", NULL, NULL, NULL, NULL, /* 003 */ "pt", NULL, NULL, NULL, NULL, /* 004 */ "rh", NULL, NULL, NULL, NULL, /* 005 */ "cu", NULL, NULL, NULL, NULL, /* 006 */ "rn", NULL, NULL, NULL, NULL, /* 007 */ "bs", NULL, NULL, NULL, NULL, /* 010 */ "+-", NULL, NULL, NULL, NULL, /* 011 */ "<=", NULL, NULL, NULL, NULL, /* 012 */ ">=", NULL, NULL, NULL, NULL, /* 013 */ "sr", NULL, NULL, NULL, NULL, /* 014 */ "ts", NULL, NULL, NULL, NULL, /* 015 */ "is", NULL, NULL, NULL, NULL, /* 016 */ "sl", NULL, NULL, NULL, NULL, /* 017 */ "bv", NULL, NULL, NULL, NULL, /* 020 */ "lf", NULL, NULL, NULL, NULL, /* 021 */ "rf", NULL, NULL, NULL, NULL, /* 022 */ "lc", NULL, NULL, NULL, NULL, /* 023 */ "rc", NULL, NULL, NULL, NULL, /* 024 */ "lt", NULL, NULL, NULL, NULL, /* 025 */ "lb", NULL, NULL, NULL, NULL, /* 026 */ "rt", NULL, NULL, NULL, NULL, /* 027 */ "rb", NULL, NULL, NULL, NULL, /* 030 */ "lk", NULL, NULL, NULL, NULL, /* 031 */ "rk", NULL, NULL, NULL, NULL, /* 032 */ "sb", NULL, NULL, NULL, NULL, /* 033 */ "sp", NULL, NULL, NULL, NULL, /* 034 */ "ca", NULL, NULL, NULL, NULL, /* 035 */ "no", NULL, NULL, NULL, NULL, /* 036 */ "lh", NULL, NULL, NULL, NULL, /* 037 */ "mo", NULL, NULL, NULL, NULL, /* 040 */ "\040", NULL, NULL, NULL, NULL, /* 041 */ "ul", "\\_", NULL, NULL, NULL, /* 042 */ "\"", NULL, NULL, NULL, NULL, /* 043 */ "#", NULL, NULL, NULL, NULL, /* 044 */ "Sl", NULL, NULL, NULL, NULL, /* 045 */ "\045", NULL, NULL, NULL, NULL, /* 046 */ "\046", NULL, NULL, NULL, NULL, /* 047 */ "'", "aa", NULL, NULL, NULL, /* 050 */ "gr", NULL, NULL, NULL, NULL, /* 051 */ "\051", NULL, NULL, NULL, NULL, /* 052 */ "mu", NULL, NULL, NULL, NULL, /* 053 */ "pl", NULL, NULL, NULL, NULL, /* 054 */ "\054", NULL, NULL, NULL, NULL, /* 055 */ "mi", NULL, NULL, NULL, NULL, /* 056 */ "\056", NULL, NULL, NULL, NULL, /* 057 */ "di", NULL, NULL, NULL, NULL, /* 060 */ "==", NULL, NULL, NULL, NULL, /* 061 */ "~=", "~~", NULL, NULL, NULL, /* 062 */ "ap", NULL, NULL, NULL, NULL, /* 063 */ "!=", NULL, NULL, NULL, NULL, /* 064 */ "<-", NULL, NULL, NULL, NULL, /* 065 */ "->", NULL, NULL, NULL, NULL, /* 066 */ "ua", NULL, NULL, NULL, NULL, /* 067 */ "da", NULL, NULL, NULL, NULL, /* 070 */ "sc", NULL, NULL, NULL, NULL, /* 071 */ "**", NULL, NULL, NULL, NULL, /* 072 */ "\072", NULL, NULL, NULL, NULL, /* 073 */ "\073", NULL, NULL, NULL, NULL, /* 074 */ "<", NULL, NULL, NULL, NULL, /* 075 */ "=", "eq", NULL, NULL, NULL, /* 076 */ ">", NULL, NULL, NULL, NULL, /* 077 */ "\077", NULL, NULL, NULL, NULL, /* 100 */ "@", NULL, NULL, NULL, NULL, /* 101 */ "*A", NULL, NULL, NULL, NULL, /* 102 */ "*B", NULL, NULL, NULL, NULL, /* 103 */ "*G", NULL, NULL, NULL, NULL, /* 104 */ "*D", NULL, NULL, NULL, NULL, /* 105 */ "*E", NULL, NULL, NULL, NULL, /* 106 */ "*Z", NULL, NULL, NULL, NULL, /* 107 */ "*Y", NULL, NULL, NULL, NULL, /* 110 */ "*H", NULL, NULL, NULL, NULL, /* 111 */ "*I", NULL, NULL, NULL, NULL, /* 112 */ "*K", NULL, NULL, NULL, NULL, /* 113 */ "*L", NULL, NULL, NULL, NULL, /* 114 */ "*M", NULL, NULL, NULL, NULL, /* 115 */ "*N", NULL, NULL, NULL, NULL, /* 116 */ "*C", NULL, NULL, NULL, NULL, /* 117 */ "*O", NULL, NULL, NULL, NULL, /* 120 */ "*P", NULL, NULL, NULL, NULL, /* 121 */ "*R", NULL, NULL, NULL, NULL, /* 122 */ "*S", NULL, NULL, NULL, NULL, /* 123 */ "*T", NULL, NULL, NULL, NULL, /* 124 */ "*U", "U", NULL, NULL, NULL, /* 125 */ "*F", NULL, NULL, NULL, NULL, /* 126 */ "*X", NULL, NULL, NULL, NULL, /* 127 */ "*Q", NULL, NULL, NULL, NULL, /* 130 */ "*W", NULL, NULL, NULL, NULL, /* 131 */ "dd", NULL, NULL, NULL, NULL, /* 132 */ "br", NULL, NULL, NULL, NULL, /* 133 */ "ib", NULL, NULL, NULL, NULL, /* 134 */ "\\", NULL, NULL, NULL, NULL, /* 135 */ "ci", NULL, NULL, NULL, NULL, /* 136 */ "^", NULL, NULL, NULL, NULL, /* 137 */ "_", NULL, NULL, NULL, NULL, /* 140 */ "`", "ga", NULL, NULL, NULL, /* 141 */ "*a", NULL, NULL, NULL, NULL, /* 142 */ "*b", NULL, NULL, NULL, NULL, /* 143 */ "*g", NULL, NULL, NULL, NULL, /* 144 */ "*d", NULL, NULL, NULL, NULL, /* 145 */ "*e", NULL, NULL, NULL, NULL, /* 146 */ "*z", NULL, NULL, NULL, NULL, /* 147 */ "*y", NULL, NULL, NULL, NULL, /* 150 */ "*h", NULL, NULL, NULL, NULL, /* 151 */ "*i", NULL, NULL, NULL, NULL, /* 152 */ "*k", NULL, NULL, NULL, NULL, /* 153 */ "*l", NULL, NULL, NULL, NULL, /* 154 */ "*m", NULL, NULL, NULL, NULL, /* 155 */ "*n", NULL, NULL, NULL, NULL, /* 156 */ "*c", NULL, NULL, NULL, NULL, /* 157 */ "*o", NULL, NULL, NULL, NULL, /* 160 */ "*p", NULL, NULL, NULL, NULL, /* 161 */ "*r", NULL, NULL, NULL, NULL, /* 162 */ "*s", NULL, NULL, NULL, NULL, /* 163 */ "*t", NULL, NULL, NULL, NULL, /* 164 */ "*u", NULL, NULL, NULL, NULL, /* 165 */ "*f", NULL, NULL, NULL, NULL, /* 166 */ "*x", NULL, NULL, NULL, NULL, /* 167 */ "*q", NULL, NULL, NULL, NULL, /* 170 */ "*w", NULL, NULL, NULL, NULL, /* 171 */ "pd", NULL, NULL, NULL, NULL, /* 172 */ "es", NULL, NULL, NULL, NULL, /* 173 */ "{", NULL, NULL, NULL, NULL, /* 174 */ "or", "vr", NULL, NULL, NULL, /* 175 */ "}", NULL, NULL, NULL, NULL, /* 176 */ "~", NULL, NULL, NULL, NULL, /* 177 */ "\177", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; char TfmName[81]; /* Only used in error routine */ char *WhoAmI; /* Argv[0] */ char *Usage = "Usage: %s [-s] [-w width] [-l ligature]... file...\n"; Boolean Special = FALSE; /* Designates whether font is special. */ Bits Ligatures; /* Ligatures the font does not contain. */ int ExitStatus = SUCCEED; int Width = -1; /* "spacewidth" in font desc. file. -1==omit */ main(argc,argv) int argc; char *argv[]; { extern int optind; extern char *optarg; int c; FILE *infile, *outfile; void seteoffunction(), tfmeofsoexit(), convert(); char *strcpy(); WhoAmI = argv[0]; while ((c = getopt(argc, argv, "sl:w:")) != EOF) switch (c) { case 's': Special = TRUE; break; case 'w': Width = atoi(optarg); break; case 'l': if (EQ(optarg, "ff")) Ligatures |= LFF; else if (EQ(optarg, "fi")) Ligatures |= LFI; else if (EQ(optarg, "fl")) Ligatures |= LFL; else if (EQ(optarg, "ffi")) Ligatures |= LFFI; else if (EQ(optarg, "ffl")) Ligatures |= LFFL; 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]); argv[optind][strlen(argv[optind])-4] = '\0'; if (!(outfile = fopen(argv[optind], "w"))) { fprintf(stderr, "%s: cannot open output file %s\n", WhoAmI, argv[optind]); 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 a troff width table file. */ void convert(infile, outfile, outname) FILE *infile, *outfile; char *outname; /* Output file name */ { int aheight, i, j, widthindex, heightanddepth, width, height, depth, kerning; unsigned long uinteger(), lh, bc, ec, nw, nh, designsize, utemp; long integer(), temp; fprintf(outfile, "name %s\ninternalname %s\n", outname, outname); if (Special) fputs("special\n", outfile); if (!Special && Ligatures != 0x1F) { fputs("ligatures ", outfile); if (!(Ligatures & LFF)) fputs("ff ", outfile); if (!(Ligatures & LFI)) fputs("fi ", outfile); if (!(Ligatures & LFL)) fputs("fl ", outfile); if (!(Ligatures & LFFI)) fputs("ffi ", outfile); if (!(Ligatures & LFFL)) fputs("ffl ", outfile); fputs("0\n", outfile); } if (Width != -1) fprintf(outfile, "spacewidth %d\n", Width); if (!Special) { if ((aheight = getaheight(infile)) == MAX_INTEGER) { fprintf(stderr, "%s: no letter 'a' in file %s.tfm\n", WhoAmI, outname); fprintf(stderr, "\tsetting height to zero\n"); aheight = 0; } (void)fseek(infile, 0L, 0); } fputs("charset\n", outfile); (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); temp = integer(infile, 4); width = ROUND((temp / (double)FIX * designsize) / PPI * RESOLUTION); (void)fseek(infile, 24L + 4*lh + (ec-bc+1)*4 + nw*4 + (heightanddepth>>4)*4, 0); utemp = uinteger(infile, 4); height = ROUND((utemp / (double)FIX * designsize) / PPI * RESOLUTION); (void)fseek(infile, 24L + 4*lh + (ec-bc+1)*4 + nw*4 + nh*4 + (heightanddepth&0xF)*4, 0); utemp = uinteger(infile, 4); depth = ROUND((utemp / (double)FIX * designsize) / PPI * RESOLUTION); kerning = 0; if (height > aheight) kerning |= 2; if (depth > 0) kerning |= 1; for (j = 0; Special ? SpecialSequences[i][j] : NormalSequences[i][j]; j++) if (j == 0) fprintf(outfile, "%s\t%d\t%d\t%d\n", Special ? SpecialSequences[i][j] : NormalSequences[i][j], width, Special ? 0 : kerning, i); else fprintf(outfile, "%s\t\"\n", Special ? SpecialSequences[i][j] : NormalSequences[i][j]); } } /* Returns the height of the letter 'a' in the font passed as a parameter. * The height is returned in pixels since troff likes to use pixels as its * unit. If the letter 'a' is not found, MAX_INTEGER is returned. */ int getaheight(in) FILE *in; { unsigned long lh, bc, ec, nw, uinteger(), designsize; (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 */ designsize = uinteger(in, 4) / FIX; /* Convert from FIXes */ (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 ROUND((uinteger(in, 4) / (double)FIX * designsize) / PPI * RESOLUTION); } void tfmeofsoexit() { fprintf(stderr, "%s: unexpected end of tfm file %s\n", WhoAmI, TfmName); exit(FAIL); }