summaryrefslogtreecommitdiff
path: root/fonts/utilities/afmtopl/clark/aftopl.c
diff options
context:
space:
mode:
Diffstat (limited to 'fonts/utilities/afmtopl/clark/aftopl.c')
-rw-r--r--fonts/utilities/afmtopl/clark/aftopl.c510
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]");
+}