diff options
Diffstat (limited to 'fonts/utilities/afmtopl/clark/aftopl.c')
-rw-r--r-- | fonts/utilities/afmtopl/clark/aftopl.c | 510 |
1 files changed, 510 insertions, 0 deletions
diff --git a/fonts/utilities/afmtopl/clark/aftopl.c b/fonts/utilities/afmtopl/clark/aftopl.c new file mode 100644 index 0000000000..6e9aa5cd66 --- /dev/null +++ b/fonts/utilities/afmtopl/clark/aftopl.c @@ -0,0 +1,510 @@ +static char rcsid[] = "$Header: /u/jjc/dvitops/RCS/aftopl.c,v 1.3 89/02/22 11:40:31 jjc Rel $"; + +#include "util.h" + +#define MAXNAMES 500 +#define NOT_DEFINED 100000.0 +#ifndef PI +#define PI 3.14159265358979324 +#endif + +struct ligatures { + char *ch; + char *succ; + char *lig; +}; + +char *program_name = "aftopl"; + +static int lineno = 0; + +FILE *infp; +FILE *outfp; +#ifdef PROTO +int lookup(const char *); +char *getkeyvalue(char *, int); +void scan_char_metric(char *); +void compute_font_dimens(void); +void do_kern_pairs(int); +void do_char_metrics(int); +void do_afms(void); +void print_font_dimens(void); +void do_encoding(char *); +void print_char_metrics(void); +void print_lig_kerns(void); +void do_ligatures(struct ligatures *); +#endif + +#define bad_afm_file() message(FATAL_ERROR, "bad afm file, line %d", lineno) + +struct lig_kern_list { + struct lig_kern_list *next; + int succ; + int lig; /* -1 if its a kern */ + double x; +}; + + +struct { + struct lig_kern_list *p; + char *name; + int code; + double llx; + double lly; + double urx; + double ury; + double wx; +} table[MAXNAMES]; + +struct { + int is_fixed_pitch; + double italic_angle; + double x_height; + /* we use max(urx - wx + italic_correction_space, 0) + as the italic correction for each character */ + double italic_correction_space; + double normal_space; + double normal_stretch; + double normal_shrink; + double extra_space; + double quad; + double slant; +} font = { 0, 0.0, NOT_DEFINED, NOT_DEFINED, NOT_DEFINED, NOT_DEFINED, +NOT_DEFINED, NOT_DEFINED, NOT_DEFINED, NOT_DEFINED}; + + + +int lookup(s) +const char *s; +{ + int i; + for (i = 0; i < MAXNAMES; i++) + if (table[i].name == NULL) + break; + else if (strcmp(table[i].name, s) == 0) + return i; + if (i == MAXNAMES) + message(FATAL_ERROR, "too many names"); + if ((table[i].name = malloc(strlen(s) + 1)) == NULL) + message(FATAL_ERROR, "out of memory"); + strcpy(table[i].name, s); + table[i].code = -2; + table[i].llx = table[i].lly = 0.0; + table[i].urx = table[i].ury = 0.0; + table[i].wx = 0.0; + table[i].p = NULL; + return i; +} + + +char *getkeyvalue(s, c) +char *s; +char c; +{ + while (*s != '\0') { + while (isspace(*s)) + s++; + if (*s == c) + return s + 1; + while (*s != '\0') + if (*s++ == ';') + break; + } + return NULL; +} + +void scan_char_metric(s) +char *s; +{ + char name[128]; + int code, n; + double llx, lly, urx, ury; + double wx, wy; + char *p; + while (isspace(*s)) + s++; + if (*s == '\0') /* ignore blank line */ + return; + p = getkeyvalue(s, 'N'); + if (p == NULL) + bad_afm_file(); + /* sscanf(p, " %[A-Za-z0-9]", name); */ + /* Microsoft C scanf doesn't understand %[ */ + sscanf(p, "%s", name); + if ((p = strchr(name, ';')) != NULL) + *p = '\0'; + if ((p = getkeyvalue(s, 'C')) == NULL) + bad_afm_file(); + if (sscanf(p, "%d", &code) != 1) + bad_afm_file(); + p = getkeyvalue(s, 'B'); + if (p == NULL) + bad_afm_file(); + if (sscanf(p, "%lg %lg %lg %lg", &llx, &lly, &urx, &ury) != 4) + bad_afm_file(); + p = getkeyvalue(s, 'W'); + if (p == NULL) + bad_afm_file(); + if (*p == 'X') { + if (sscanf(p+1, "%lg", &wx) != 1) + bad_afm_file(); + wy = 0.0; + } + else if (sscanf(p, "%lg %lg", &wx, &wy) != 2) + bad_afm_file(); + n = lookup(name); + table[n].code = code; + table[n].wx = wx; + table[n].llx = llx; + table[n].lly = lly; + table[n].urx = urx; + table[n].ury = ury; + while ((p = getkeyvalue(s, 'L')) != NULL) { + char successor[128]; + char ligature[128]; + struct lig_kern_list *ptr; + if (sscanf(p, " %s %s", successor, ligature) != 2) + bad_afm_file(); + else if ((s = strchr(ligature, ';')) != NULL) + *s = '\0'; + if ((s = strchr(p, ';')) == NULL) + bad_afm_file(); + s++; + if ((ptr = (struct lig_kern_list *)malloc(sizeof(struct lig_kern_list))) == NULL) + message(FATAL_ERROR, "out of memory"); + ptr->succ = lookup(successor); + ptr->lig = lookup(ligature); + ptr->next = table[n].p; + table[n].p = ptr; + } +} + + +void compute_font_dimens() +{ + if (font.normal_space == NOT_DEFINED) { + int n = lookup("space"); + if (table[n].code == -2) + message(FATAL_ERROR, "no char metric for space character"); + else + font.normal_space = table[n].wx; + } + if (font.quad == NOT_DEFINED) + font.quad = (font.is_fixed_pitch?2.0:3.0)*font.normal_space; + if (font.italic_correction_space == NOT_DEFINED) + font.italic_correction_space = font.normal_space/12.0; + if (font.normal_shrink == NOT_DEFINED) + font.normal_shrink = font.is_fixed_pitch ? 0.0 : + font.normal_space/3.0; + if (font.normal_stretch == NOT_DEFINED) + font.normal_stretch = font.is_fixed_pitch ? 0.0 : + font.normal_space/2.0; + if (font.extra_space == NOT_DEFINED) + font.extra_space = (font.is_fixed_pitch ? 1.0 :0.5) + *font.normal_space; + if (font.slant == NOT_DEFINED) + if (font.italic_angle == 0.0) + font.slant = 0.0; + else + font.slant = sin(-font.italic_angle*PI/180.0); + if (font.x_height == NOT_DEFINED) + font.x_height = table[lookup("x")].ury; +} + +void do_kern_pairs(n) +int n; +{ + char buf[512]; + char name1[128]; + char name2[128]; + double x, y; + for (;;) { + int i; + struct lig_kern_list *ptr; + lineno++; + if (fgets(buf, 512, infp) == NULL) + bad_afm_file(); + if (buf[0] == '\n') + continue; + if (strcmp(buf, "EndKernPairs\n") == 0) + break; + if (sscanf(buf, "KPX %s %s %lg", name1, name2, &x) != 3) { + if (sscanf(buf, "KP %s %s %lg %lg", name1, name2, + &x, &y) != 4) + bad_afm_file(); + } + else + y = 0.0; + i = lookup(name1); + if ((ptr = (struct lig_kern_list *)malloc(sizeof(struct lig_kern_list))) == NULL) + message(FATAL_ERROR, "out of memory"); + ptr->succ = lookup(name2); + ptr->lig = -1; + ptr->x = x; + ptr->next = table[i].p; + table[i].p = ptr; + n--; + } + if (n != 0) + message(WARNING, "wrong number of kern pairs"); +} + + +void do_char_metrics(n) +int n; +{ + char buf[512]; + for (;;) { + char *ptr = buf; + lineno++; + if (fgets(buf, 512, infp) == NULL) + bad_afm_file(); + if (strcmp(buf, "EndCharMetrics\n") == 0) + break; + while (isspace(*ptr)) + ptr++; + if (*ptr == '\0') + continue; + scan_char_metric(buf); + n--; + } + if (n != 0) + message(WARNING, "wrong number of char metrics"); +} + +void do_afms() +{ + char buf[512]; + lineno = 0; + + while (fgets(buf, 512, infp) != NULL) { + char *key, *value; + key = buf; + lineno++; + while (isspace(*key)) + key++; + value = key; + while (*value != '\0' && !isspace(*value)) + value++; + if (*value != '\0') { + /* strip trailing white space */ + char *p; + *value++ = '\0'; + while (isspace(*value)) + value++; + p = value; + while (*p != '\0') + p++; + while (p > value && isspace(*(p-1))) + p--; + *p = '\0'; + } + if (strcmp(key, "IsFixedPitch") == 0) + font.is_fixed_pitch = (strcmp(value, "true") == 0); + else if (strcmp(key, "XHeight") == 0) + font.x_height = atof(value); + else if (strcmp(key, "StartCharMetrics") == 0) + do_char_metrics(atoi(value)); + else if (strcmp(key, "ItalicAngle") == 0) + font.italic_angle = atof(value); + else if (strcmp(key, "StartKernPairs") == 0) + do_kern_pairs(atoi(value)); + else if (strcmp(key, "italicCorrectionSpace") == 0) + font.italic_correction_space = atof(value); + } + +} + + +void print_font_dimens() +{ + fprintf(outfp, "(FONTDIMEN\n"); + fprintf(outfp, " (SLANT R %f)\n", font.slant); + fprintf(outfp, " (SPACE R %f)\n", font.normal_space/1000.0); + fprintf(outfp, " (SHRINK R %f)\n", font.normal_shrink/1000.0); + fprintf(outfp, " (STRETCH R %f)\n", font.normal_stretch/1000.0); + fprintf(outfp, " (EXTRASPACE R %f)\n", font.extra_space/1000.0); + fprintf(outfp, " (QUAD R %f)\n", font.quad/1000.0); + fprintf(outfp, " (XHEIGHT R %f)\n", font.x_height/1000.0); + fprintf(outfp, " )\n"); +} + + +void do_encoding(encoding) +char *encoding; +{ + int i; + char name[256]; + FILE *fp; + char *texfonts; + fprintf(outfp, "(CODINGSCHEME %s)\n", encoding); + texfonts = getenv("TEXFONTS"); + if (texfonts == NULL) + texfonts = TEXFONTS; + if ((fp = xfopen(encoding, FALSE, texfonts, ".enc")) == NULL) + message(FATAL_ERROR, "can't find %s", encoding); + for (i = 0; i < MAXNAMES; i++) + if (table[i].code >= -1) + table[i].code = -1; + for (i = 0; i < 256 && fscanf(fp, " %s ", name) == 1; i++) { + int n; + if (strcmp(".notdef", name) == 0) + continue; + n = lookup(name); + if (table[n].code == -2) + message(WARNING, "%s in encoding but not in font", name); + else if (table[n].code == -1) + table[n].code = i; + else + message(ERROR, "%s appears more than once in encoding", name); + } +} + + + +void print_char_metrics() +{ + int i; + for (i = 0; i < MAXNAMES; i++) + if (table[i].name != NULL && table[i].code > 0) { + double charic; + fprintf(outfp, "(CHARACTER O %03o\n", table[i].code); + fprintf(outfp, " (COMMENT %s)\n", table[i].name); + fprintf(outfp, " (CHARWD R %f)\n", + table[i].wx/1000.0); + /* negative heights and depths mess up \mathaccent */ + if (table[i].ury > 0.0) + fprintf(outfp, " (CHARHT R %f)\n", + table[i].ury/1000.0); + if (table[i].lly < 0.0) + fprintf(outfp, " (CHARDP R %f)\n", + -table[i].lly/1000.0); + charic = table[i].urx - table[i].wx + font.italic_correction_space; + if (charic > 0.0) + fprintf(outfp, " (CHARIC R %f)\n", + charic/1000.0); + fputs(" )\n", outfp); + } +} + + + +void print_lig_kerns() +{ + int i; + fputs("(LIGTABLE\n", outfp); + for (i = 0; i < MAXNAMES; i++) { + struct lig_kern_list *p; + char label_line[128]; + if (table[i].name == NULL || table[i].code < 0) + continue; + sprintf(label_line, " (LABEL O %03o)\n", table[i].code); + /* print the ligatures */ + for (p = table[i].p; p != NULL; p = p->next) + if (p->lig != -1 && table[p->lig].code > 0 + && table[p->succ].code > 0) { + fputs(label_line, outfp); + label_line[0]= '\0'; + fprintf(outfp," (LIG O %03o O %03o)\n", + table[p->succ].code, + table[p->lig].code); + } + for (p = table[i].p; p != NULL; p = p->next) + if (p->lig == -1 && table[p->succ].code > 0) { + fputs(label_line, outfp); + label_line[0] = '\0'; + fprintf(outfp, " (KRN O %03o R %f)\n", + table[p->succ].code, + p->x/1000.0); + } + if (label_line[0] == '\0') + fputs(" (STOP)\n", outfp); + } + fputs(" )\n", outfp); +} + + +struct ligatures standard_ligatures[] = { + "hyphen", "hyphen", "endash", + "endash", "hyphen", "emdash", + "quoteleft", "quoteleft", "quotedblleft", + "quoteright", "quoteright", "quotedblright", + "exclam", "quoteleft", "exclamdown", + "question", "quoteleft", "questiondown", + NULL, NULL, NULL + }; + +struct ligatures tt_ligatures[] = { + "exclam", "quoteleft", "exclamdown", + "question", "quoteleft", "questiondown", + NULL, NULL, NULL + }; + + +void do_ligatures(lig) +struct ligatures *lig; +{ + int i; + for (i = 0; lig[i].lig != NULL; i++) { + int n; + struct lig_kern_list *p; + n = lookup(lig[i].ch); + if ((p = (struct lig_kern_list *)malloc(sizeof(struct lig_kern_list))) == NULL) + message(FATAL_ERROR, "out_of_memory"); + p->succ = lookup(lig[i].succ); + p->lig = lookup(lig[i].lig); + p->next = table[n].p; + table[n].p = p; + } +} + + + +int main(argc, argv) +int argc; +char **argv; +{ + char filename[128]; + int c; + char *efile = NULL; + while ((c = getopt(argc, argv, "e:")) != EOF) + switch(c) { + case 'e': + efile = optarg; + break; + case '?': + goto usage; + } + if (argc - optind < 1) + goto usage; + strcpy(filename, argv[optind]); + if (strchr(filename, '.') == NULL) + strcat(filename, ".afm"); + if ((infp = fopen(filename, "r")) == NULL) + message(FATAL_ERROR, "can't open %s", filename); + if (argc - optind == 1) + strcpy(strchr(filename, '.'), ".pl"); + else if (argc - optind == 2) { + strcpy(filename, argv[optind+1]); + if (strchr(filename, '.') == NULL) + strcat(filename, ".pl"); + } + else + goto usage; + if ((outfp = fopen(filename, "w")) == NULL) + message(FATAL_ERROR, "can't open %s", filename); + do_afms(); + if (efile != NULL) + do_encoding(efile); + if (font.is_fixed_pitch) + do_ligatures(tt_ligatures); + else + do_ligatures(standard_ligatures); + compute_font_dimens(); + print_font_dimens(); + print_char_metrics(); + print_lig_kerns(); + exit(history); +usage: + message(FATAL_ERROR, "usage: aftopl [-e encoding] afmfile [plfile]"); +} |