/* Program a2ac, Petr Olsak */ /* ************************* */ /* ver.0 The program was created. */ /* ver.1 - The new format of description file: the order of actions are not fixed - Abbverbations of kern data are allowed - The function k for kern value introduced - Mistake corrections: . correct the nestability of unix version of a2ac on DOS files (^M) . if the Composites field is missing on input, the program add its . the output is no created if an error in input occurs . the Czech docummentation corrected and English added */ /* for more information see the a2ac-cz.doc or a2ac-eng.doc file */ /* If your linker needs information about libraries, you have to load the math. libm.a explicitly. For example you can use the UNIX command: cc a2ac.c -lm -o a2ac */ #include #include #include #include #define POOLSIZE 6000 #define MAXLINE 256 #define MAXP 10 #define DOSCR 13 #define COMMENT "Converted by a2ac to obtain more composites and kerns" #define ISFIXEDPITCH "IsFixedPitch" #define ITALICANGLE "ItalicAngle" #define FONTNAME "FontName" #define CAPHEIGHT "CapHeight" #define XHEIGHT "XHeight" #define ASCENDER "Ascender" #define DESCENDER "Descender" #define STARTCHARMETRICS "StartCharMetrics" #define ENDCHARMETRICS "EndCharMetrics" #define STARTKERNPAIRS "StartKernPairs" #define ENDKERNPAIRS "EndKernPairs" #define STARTCOMPOSITES "StartComposites" #define ENDCOMPOSITES "EndComposites" #define ENDFONTMETRICS "EndFontMetrics" #define STARTDEFVARIABLES "StartDefVariables" #define ENDDEFVARIABLES "EndDefVariables" #define STARTNEWCOMPOSITES "StartNewComposites" #define ENDNEWCOMPOSITES "EndNewComposites" #define STARTNEWKERNS "StartNewKerns" #define ENDNEWKERNS "EndNewKerns" #define REDUCEKERNS "ReduceKerns" #define STARTWXCORRECTIONS "StartWXCorrections" #define ENDWXCORRECTIONS "EndWXCorrections" char pool[POOLSIZE] ; int lastpool, poolwrite ; char line[MAXLINE], buf[20] ; int currspace, eofline; typedef struct CHARINFO { int code ; char *name ; int wx ; int bb[4] ; char *rest ; } CHARINFO ; typedef struct CHARLIST { CHARINFO *chi ; struct CHARLIST *next ; } CHARLIST ; CHARLIST *firstchar, *lastchar; typedef struct KERNINFO { char *name ; int kern ; struct KERNINFO *next ; } KERNINFO ; typedef struct KERNLIST { char *name ; KERNINFO *ki ; struct KERNLIST *next ; } KERNLIST ; KERNLIST *firstkern, *lastkern; int sumkerns, rewkerns, onlysmall; int SUMkern, SUMrewritekern, SUMremovekern; int inputkerns=0; typedef struct COMLIST { char *name ; char *lin ; struct COMLIST *next ; } COMLIST ; COMLIST *firstcom, *lastcom; typedef struct VARLIST { char *name ; int value ; struct VARLIST *next ; } VARLIST ; VARLIST *firstvar, *lastvar; int ind, isfixed; char P[3][MAXP]; int S[2][MAXP]; char *N[MAXP]; FILE *input, *afminput, *output, *corrfile; #define FGETC(INPUT) (feof(INPUT)||i>=MAXLINE ? '\n' : fgetc(INPUT)) #define MAX(A,B) ((A>B) ? (A) : (B)) #define MIN(A,B) ((A>B) ? (B) : (A)) int endfile=0; double slant; #define ERROR(TEXT) {printf(">>>>ERROR<<<< %s\n",TEXT);printline();exit(1);} void printline () /* prints the line with error */ /*---------------*/ { int i=0; while (i < currspace) if (line[i++] == 0) line[i-1] = ' '; printf ("Line: %s\n", line); return; } int round (f) /* the round function */ /*-----------*/ double f; { return (int) (f >= 0) ? (f + 0.5) : (f - 0.5) ; } void *myalloc (size) /* alloc with own check */ /*------------------*/ int size; { void *p; p = malloc (size); if (myalloc == NULL) ERROR ("no memory, malloc failed"); return p; } char *newpool (s) /* adds the (probably) new string s to the pool */ /*---------------*/ char *s; { int i = 0; while (i < lastpool) { if (strcmp(&pool[i], s) == 0) return &pool[i] ; i += strlen(&pool[i]) + 1; } if (!poolwrite) ERROR ("Undefined identifier"); i = lastpool; strcpy (&pool[i], s); lastpool += strlen(&pool[i]) + 1; return &pool[i]; } char *readstr () /* returns the next string from line separated by ' ' */ /*--------------*/ { int i, j; if (eofline) return NULL; currspace++; while (line[currspace] == ' ' || line[currspace] == '\t') currspace++; i = currspace; while (line[i] != ' ' && line[i] != '\t' && line[i] != 0) i++; if (line[i] == 0) eofline = 1; line[i] = 0; j = currspace; currspace = i; return &line[j]; } void readline () /* reads line with check for MAXLINE and skip blank lines */ /*--------------*/ { register int i=0; do { while ((line[i]=FGETC(input)) != '\n') i++; if (i==MAXLINE) { printf ("a2ac: bad input file format\n"); exit (1); } if (feof(input)) { if (endfile) return ; printf ("a2ac: end of input not expected, bad format\n"); exit (1); } if (line[i-1] == DOSCR && i > 0) i--; i = line[i] = 0; while (line[i] == ' ' || line[i] == '\t') i++; } while (line[i] == 0) ; /* skipping blank line */ eofline = 0; while (line[i] != 0 && line[i] != ' ') i++; if (line[i] == 0) eofline = 1; line[i] = 0; currspace = i; return; } int rawreadline () /* reads line without skip blank lines */ /*----------------*/ { register int i=0; while ((line[i]=FGETC(input)) != '\n') i++; if (line[i-1] == DOSCR && i > 0) i--; i = line[i] = 0; while (line[i] != 0 && line[i] != ' ') i++; if (line[i] == 0) currspace = i+1; else currspace = i, line[i] = 0 ; return feof(input) ; } int lincmp (name) /* compares name with line, returns 1 if OK */ /*---------------*/ char *name ; { register int i=0, j=0; while (line[i] == name[j] && name[j]) i++, j++; return !name[j]; } void newchar (code, wx, name, b0, b1, b2, b3) /* allocates new char info */ /*-------------------------------------------*/ char *name ; int code, wx, b0, b1, b2, b3 ; { CHARINFO *c; int len; if (lastchar == NULL) firstchar = lastchar = myalloc (sizeof(CHARLIST)) ; else lastchar = lastchar->next = myalloc (sizeof(CHARLIST)) ; lastchar->next = NULL; c = lastchar->chi = myalloc (sizeof(CHARINFO)) ; c->name = newpool (name); c->code = code; c->wx = wx; c->bb[0] = b0; c->bb[1] = b1; c->bb[2] = b2; c->bb[3] = b3; readstr (); if (eofline) c->rest = NULL ; else len = strlen(&line[currspace+1]) + 1 , c->rest = myalloc(len) , strcpy (c->rest, &line[currspace+1]) ; return ; } void newkern (name1, name2, kern) /* allocates new kern info */ /*-------------------------------*/ char *name1, *name2; int kern; { KERNINFO *c, *cold; KERNLIST *p; /* Check of presence name1 */ p = firstkern ; while (p != NULL) { if (strcmp (p->name,name1) == 0) /* the name1 is present */ { c = p->ki ; do { if (strcmp (c->name,name2) == 0) { c->kern = kern ; return ; } cold = c ; c = c->next; } while (c != NULL) ; c = cold->next = myalloc (sizeof(KERNINFO)); c->name = newpool(name2); c->kern = kern; c->next = NULL; return; } p = p->next ; } /* Make new KERNLIST */ if (lastkern == NULL) firstkern = lastkern = myalloc (sizeof(KERNLIST)) ; else lastkern = lastkern->next = myalloc (sizeof(KERNLIST)) ; lastkern->next = NULL; lastkern->name = newpool(name1); c = lastkern->ki = myalloc (sizeof(KERNINFO)) ; c->name = newpool(name2); c->kern = kern; c->next = NULL; return; } void newcom (name) /* allocates new composite info */ /*----------------*/ char *name; { if (lastcom == NULL) firstcom = lastcom = myalloc (sizeof(COMLIST)) ; else lastcom = lastcom->next = myalloc (sizeof(COMLIST)) ; lastcom->next = NULL; lastcom->name = newpool(name); line[currspace] = ' '; lastcom->lin = myalloc(strlen(line)+1); strcpy (lastcom->lin, line); return; } void newvar (name, value) /* allocates new variable info */ /*-----------------------*/ char *name; int value; { VARLIST *p; p = firstvar; while (p != NULL) { if (strcmp (p->name, name) == 0) { p->value = value; printf (">> %s = %d\n", name, value); return; } p = p->next; } if (lastvar == NULL) firstvar = lastvar = myalloc (sizeof(VARLIST)) ; else lastvar = lastvar->next = myalloc (sizeof(VARLIST)) ; lastvar->next = NULL; lastvar->name = newpool(name); lastvar->value = value; printf (">> %s = %d\n", name, value); } void readafm () /* reads the afm input (first step) */ /*-------------*/ { int c, wx, b0, b1, b2, b3, kern; char *name, *name1, *name2; /* read CharMetrics */ isfixed = 0; slant = 0.0; do { readline() ; if (lincmp (FONTNAME)) printf ("%s %s\n", FONTNAME, &line[currspace+1]); if (lincmp (ISFIXEDPITCH) && line[currspace+1] == 't') isfixed = 1 ; if (lincmp (ITALICANGLE)) slant = tan (-0.0174532 * (double) atoi (readstr ())) ; if (lincmp (CAPHEIGHT)) newvar (CAPHEIGHT, atoi (readstr ())); if (lincmp (XHEIGHT)) newvar (XHEIGHT, atoi (readstr ())); if (lincmp (ASCENDER)) newvar (ASCENDER, atoi (readstr ())); if (lincmp (DESCENDER)) newvar (DESCENDER, atoi (readstr ())); } while (!lincmp (STARTCHARMETRICS)); while (1) { readline () ; if (lincmp(ENDCHARMETRICS)) break; c = atoi (readstr ()) ; while (!eofline && strcmp("WX",readstr()) != 0) ; if (eofline) ERROR("the WX attribute not present, bad AFM ??"); wx = atoi (readstr ()); while (!eofline && strcmp("N",readstr()) != 0) ; if (eofline) ERROR("the N attribute not present, bad AFM ??"); name = readstr (); while (!eofline && strcmp("B",readstr()) != 0) ; if (eofline) ERROR("the B attribute not present, bad AFM ??"); b0 = atoi (readstr ()); b1 = atoi (readstr ()); b2 = atoi (readstr ()); b3 = atoi (readstr ()); newchar (c, wx, name, b0, b1, b2, b3); } /* read KernPairs */ do { readline (); if (lincmp (ENDFONTMETRICS)) return ; if (lincmp (STARTCOMPOSITES)) break ; } while (!lincmp (STARTKERNPAIRS)) ; if (lincmp (STARTKERNPAIRS)) { while (1) { readline () ; if (lincmp (ENDKERNPAIRS)) break; name1 = readstr () ; name2 = readstr () ; if (eofline) ERROR("the kern pair not compleete, bad AFM ??") ; kern = atoi (readstr ()); newkern (name1, name2, kern); inputkerns++; } /* read Composites */ do { readline() ; if (lincmp (ENDFONTMETRICS)) return ; } while (!lincmp (STARTCOMPOSITES)); } while (1) { readline () ; if (lincmp (ENDCOMPOSITES)) break; line[currspace] = ' '; name = readstr (); newcom (name); } return; } int valvar(c) /* returns the value of variable c */ /*-----------*/ char *c; { int i=0; char save; VARLIST *p; while ( isalnum (c[i]) || c[i]=='_') i++; save = c[i]; c[i] = 0; p = firstvar; while (p != NULL) { if (strcmp (c,p->name) == 0) break; p = p->next; } if (p == NULL) ERROR ("Variable is not defined"); c[i] = save; ind += i; return p->value; } int valF(c) /* returns the value of function */ /*---------*/ char *c; { int i, i0, j, v; CHARLIST *p; i = 2; while (c[i] != ',' && c[i] != ')' && c[i] != 0) i++; if (c[i] == 0) ERROR ("Bad syntax for function"); j = c[i]; c[i] = 0; p = firstchar; while (p != NULL) { if (strcmp (p->chi->name, &c[2]) == 0) break ; p = p->next; } if (p == NULL) ERROR ("Uknown identifier as parameter of function"); switch (c[0]) { case 'b' : if (j != ',') ERROR ("two parameters expected in b function"); if (!isdigit (c[i+1])) ERROR ("Bad index in b function"); if (c[i+2] != ')') ERROR ("Long index in b function"); c[i+2] = 0; j = atoi (&c[i+1]) ; if (j > 4 || j == 0) ERROR ("Index must be in 1..4 in B function"); ind += i+3; return p->chi->bb[j-1]; case 'w' : v = p->chi->bb[2] - p->chi->bb[0]; break; case 'h' : v = p->chi->bb[3] - p->chi->bb[1]; break; case 'k' : if (j != ',') ERROR ("two parameters expected in b function"); i++; i0 = i; while (c[i] != ')' && c[i] != 0) i++; if (c[i] == 0) ERROR ("Bad syntax for function"); j = c[i]; c[i] = 0; v = searchkern (&c[2], &c[i0]); break; case 'W' : v = p->chi->wx; } if (j != ')') ERROR ("one parameter expected in function"); ind += i+1; return v ; } int number(c) /* evaluates the number in the simple expressinon */ /*-----------*/ char *c; { int i; double f; char save; if (!isdigit(c[0]) && c[0] != '.') ERROR ("Syntax error in expression"); i = 0; while (isdigit (c[i]) || c[i] == '.') i++; save = c[i]; c[i] = 0; f = atof (c); ind += i; c[i] = save; if (!isalpha (c[i])) return round (f); if ((c[i]=='b'||c[i]=='w'||c[i]=='h'||c[i]=='W'||c[i]=='k') && c[i+1] == '(') return round (f * valF(&c[i])) ; return round (f * valvar(&c[i])) ; } int eval (c) /* evaluates the simple expressinon */ /*----------*/ char *c; { int v, sg; ind = 0; v = 0; sg = 1; if (c[0] == '-') sg = -1 , ind++; if (c[0] == '+') ind++; while (1) { if ((c[ind]=='b'||c[ind]=='w'||c[ind]=='h'||c[ind]=='W'||c[ind]=='k') && c[ind+1] == '(') v += sg * valF(&c[ind]) ; else if (isalpha (c[ind])) v += sg * valvar(&c[ind]) ; else v += sg * number(&c[ind]) ; if (c[ind] == ' ' || c[ind] == 0) break ; switch (c[ind++]) { case '+' : sg = 1; break; case '.' : sg = 1; ind--; break; case '-' : sg = -1; break; default : ERROR ("Syntax error in expression"); } } return v; } void removespaces () /* shift the characters in line to remove spaces */ /*------------------*/ { register int i=0, j=0; while (1) { while (line[i] != ' ' && line[i] != '\t' && line[i] != 0) i++; if (line[i] == 0) return; j = i; while (line[j++] != 0) line[j-1] = line[j]; line[j-1] = 0; } } void calculatecompose (name, num) /* calculates new BoudingBox nad CC */ /*-------------------------------*/ char *name; int num; { int i, j; CHARLIST *p, *p1, *pc; COMLIST *pcc; int b0, b1, b2, b3; /* calculate new BoudingBoxes and recalculate CC parameters */ /* printf ("CC input: %s, %s: %d %d, %s: %d %d\n", name, N[0], S[0][0], S[1][0], N[1], S[0][1], S[1][1]); */ pc = firstchar; while (pc != NULL) { if (strcmp (name, pc->chi->name) == 0) { if (pc->chi->code > 0 && line[0] != '!') return ; if (line[0] == 'N') return ; break ; } pc = pc->next; } p = firstchar; while (p != NULL) { if (strcmp(N[0], p->chi->name) == 0) break ; p = p->next; } if (p == NULL) ERROR ("Undefined identifier"); b0 = p->chi->bb[0] + S[0][0] ; b2 = p->chi->bb[2] + S[0][0]; b1 = p->chi->bb[1] + S[1][0] ; b3 = p->chi->bb[3] + S[1][0]; for (i=1; ichi->name) == 0) break ; p1 = p1->next; } if (p1 == NULL) ERROR ("Undefined identifier"); if (P[2][i] != 'C') { if (P[2][i] != 'T') ERROR ("The third premisse have to be C or T"); S[1][i] -= p1->chi->bb[3] ; } b1 = MIN (b1, (p1->chi->bb[1] + S[1][i])); b3 = MAX (b3, (p1->chi->bb[3] + S[1][i])); if (P[1][i] != 'C') { if (P[1][i] != 'A') ERROR ("The second premisse have to be C or A"); S[0][i] += (p->chi->wx - p1->chi->wx)/2 + (int)(slant * S[1][i]) ; } b0 = MIN (b0, (p1->chi->bb[0] + S[0][i])); b2 = MAX (b2, (p1->chi->bb[2] + S[0][i])); } /* write results to line[] */ pcc = firstcom; while (pcc != NULL) { if (strcmp (name, pcc->name) == 0) { if (line[0] == 'N') break; } pcc = pcc->next; } sprintf (line, "CC %s %d ; PCC %s %d %d ; PCC %s %d %d ;", name, num, N[0], S[0][0], S[1][0], N[1], S[0][1], S[1][1]) ; j = strlen (line); for (i=2; ilin = myalloc (strlen (line) + 1); strcpy (pcc->lin, line); } /* save new Bouding Box parameters */ if (pc != NULL) { pc->chi->code = -1; pc->chi->wx = p->chi->wx; pc->chi->bb[0] = b0; pc->chi->bb[1] = b1; pc->chi->bb[2] = b2; pc->chi->bb[3] = b3; } else newchar (-1, p->chi->wx, name, b0, b1, b2, b3); return; } void reducekerns (value) /* removes kerns with abs value less than value */ /*----------------------*/ int value; { KERNLIST *p, **p0; KERNINFO *pi, **pi0; int i=0; char s[2]; printf ("ReduceKerns. Abs. value: %d .", value); p = firstkern; p0 = &firstkern; while (p != NULL) { pi = p->ki; pi0 = &(p->ki); while (pi != NULL) { if (abs(pi->kern) <= value) *pi0 = pi->next, i++, free(pi) ; else pi0 = &(pi->next) ; pi = *pi0; } if (p->ki == NULL) *p0 = p->next, free(p); else p0 = &(p->next); p = *p0; } p = firstkern; while (p != NULL) lastkern = p, p = p->next; s[1] = 0; if (i == 1) s[0] = 0; else s[0] = 's'; printf (" Removed: %d kern pair%s\n", i, s); SUMremovekern += i; return ; } void setnewkern (name1, name2, kern) /* creates new kern(s) */ /*----------------------------------*/ char *name1, *name2; int kern; { KERNLIST *p; KERNINFO *pi; p = firstkern; while (p != NULL) { if (strcmp (p->name, name1) == 0) { pi = p->ki; while (pi != NULL) { if (strcmp (pi->name, name2) == 0) /* rewrite orig. kern info ? */ { if (line[0] != 'N') pi->kern = kern, sumkerns++, rewkerns++; return; } if (pi->next == NULL) /* make new kern info */ { pi = pi->next = myalloc (sizeof (KERNINFO)); pi->next = NULL; pi->name = newpool (name2); pi->kern = kern; sumkerns++; return; } pi = pi->next; } } p = p->next; } newkern (name1, name2, kern); sumkerns++; return; } int searchkern (name1, name2) /* returns the kern value of pair name1 name2 */ /*---------------------------*/ char *name1, *name2; { KERNLIST *p; KERNINFO *pi; p = firstkern; while (p != NULL) { if (strcmp (p->name, name1) == 0) { pi = p->ki; while (pi != NULL) { if (strcmp (pi->name, name2) == 0) return pi->kern; pi = pi->next; } } p = p->next; } return 0; } void testkernline (name1, name2, name3, name4) /* test patterns */ /*--------------------------------------------*/ char *name1, *name2, *name3, *name4; { if (name3[0] == '.') onlysmall = 1, name3[0] = '*'; if (name4[0] == '.') onlysmall = 1, name4[0] = '*'; if (name1[0] == '.') onlysmall = 1, name1[0] = '*'; if (name2[0] == '.') onlysmall = 1, name2[0] = '*'; if (name1[0] == '*' && name2[0] == '*' || name3[0] != '*' && name1[0] == '*' || name4[0] != '*' && name2[0] == '*' ) ERROR ("inconsistent mask"); } void makenewkerns (name1, name2, name3, name4, expr) /* one pattern */ /*--------------------------------------------------*/ char *name1, *name2, *name3, *name4, *expr; { KERNLIST *p, *p1; KERNINFO *pi, *pi1, *spi; int v; int i; char *np; if (name1[0] == '(') { i = 1; np = &name1[i]; while (name1[i] != 0 && name1[i] != ')') { if (name1[i] == ',') { name1[i] = 0 ; makenewkerns (np, name2, name3, name4, expr); name1[i] = ','; np = &name1[i+1]; } i++; } if (name1[i] != ')') ERROR ("The ')' expected"); name1[i] = 0 ; makenewkerns (np, name2, name3, name4, expr); name1[i] = ')' ; return; } if (name2[0] == '(') { i = 1; np = &name2[i]; while (name2[i] != 0 && name2[i] != ')') { if (name2[i] == ',') { name2[i] = 0 ; makenewkerns (name1, np, name3, name4, expr); name2[i] = ','; np = &name2[i+1]; } i++; } if (name2[i] != ')') ERROR ("The ')' expected"); name2[i] = 0 ; makenewkerns (name1, np, name3, name4, expr); name2[i] = ')' ; return; } /* name1 and name2 are one symbolic name (or "*", "."), no a list */ if (expr == NULL) v = 0; else v = eval (expr); if (name3==NULL) { setnewkern (name1, name2, v); return; } if (name3[0] == '*') name3 = name1; if (name4[0] == '*') name4 = name2; if (name1[0] != '*' && name2[0] != '*') { setnewkern (name1, name2, searchkern (name3, name4)+v); return; } /* more kerns */ if (name2[0] == '*') { p = firstkern; while (p != NULL) { if (strcmp (p->name, name3) == 0) { pi = p->ki; while (pi != NULL) { if (!onlysmall || islower (pi->name[0])) setnewkern (name1, pi->name, pi->kern+v); pi = pi->next; } } p = p->next; } return; } p = firstkern; while (p != 0) { pi = p->ki; while (pi != NULL) { if (strcmp (pi->name, name4) == 0) { if (!onlysmall || islower (p->name[0])) setnewkern (p->name, name2, pi->kern+v); break; } pi = pi->next; } p = p->next; } return; } void makenews () /* variables, new composites, width corrs and kerns */ /*--------------*/ { int i, j; char *name, *name1, *name2, *name3, *name4, *expr, *p; VARLIST *pv; CHARLIST *pc; KERNLIST *pk; KERNINFO *pi; char s[2]; s[1]=0; SUMkern=0; SUMrewritekern=0; SUMremovekern=0; endfile = 1; do { readline (); if (lincmp (">>")) /* Variable setting */ { if (!eofline) line[currspace] = ' '; removespaces () ; i = 0; while (line[i] != '=' && line[i] != 0) i++; if (line[i] == 0 || i==2) ERROR ("Missing '=' or variable identifier"); line[i] = 0; name = newpool(&line[2]); line[i] = '='; newvar (name, eval(&line[i+1])); continue; } if (lincmp ("NC") || lincmp ("RC") || lincmp ("!C")) /* New composite */ { name = newpool(readstr ()); i = 0; poolwrite = 0; while (1) { while (!eofline && strcmp (readstr (), ";") != 0) ; p = readstr (); if (eofline) break; P[0][i] = p[0], P[1][i] = p[1]; P[2][i] = p[2]; N[i] = newpool (readstr ()); S[0][i] = eval (readstr ()); if (eofline) ERROR ("Uncomplete compose definition (param missing)"); S[1][i] = eval (readstr ()); if (eofline) ERROR ("Uncomplete compose definition (';' missing)"); i++; } if (i < 2) ERROR ("Uncomplete composite definition"); calculatecompose (name, i); poolwrite = 1; continue; } if (isfixed) continue; if (lincmp ("RWX")) /* Width correction */ { name = readstr (); if (eofline) ERROR ("Uncomplete WX correction line"); pc = firstchar; while (pc != NULL) { if (strcmp (pc->chi->name, name) == 0) { p = readstr (); pc->chi->wx = eval (p) ; printf ("RWX %s ; WX %d\n", name, pc->chi->wx) ; break; } pc = pc->next; } if (pc == NULL) ERROR ("Uknown identifier"); continue; } if (lincmp (REDUCEKERNS)) /* ReduceKerns */ { reducekerns (eval (readstr ())); continue; } if (lincmp("NK") || lincmp("RK")) /* Kern */ { poolwrite = 0; if (eofline) ERROR ("Short kern definition"); onlysmall = rewkerns = sumkerns = 0; name1 = readstr (); name2 = readstr (); if (eofline) ERROR ("Short kern definition"); if (name2[0] == ':') { name2 = readstr (); expr = readstr (); makenewkerns (name1, "*", name2, "*", expr); makenewkerns ("*", name1, "*", name2, expr); } else { expr = readstr (); if (expr[0] == ':') /* Mask definition */ { name3 = readstr (); name4 = readstr (); expr = readstr (); testkernline (name1, name2, name3, name4); makenewkerns (name1, name2, name3, name4, expr); } else /* only One new kern */ makenewkerns (name1, name2, NULL, NULL, expr); } SUMkern += sumkerns; SUMrewritekern += rewkerns; if (sumkerns > 0) { for (j=0; jki; while (pi != NULL) pi = pi->next, i++; pk = pk->next; } printf (" Total kerns: input %d, output %d.\n", inputkerns, i); } return; } void writeafm () /* writes the output */ /*--------------*/ { CHARLIST *p; KERNLIST *pk; KERNINFO *pi; COMLIST *c; int i; /* Write header */ rawreadline (); line[currspace] = ' '; fprintf(output, "%s\nComment %s\n", line, COMMENT); while (1) { rawreadline (); if (lincmp (STARTCHARMETRICS)) break ; line[currspace] = ' '; fprintf (output, "%s\n", line); } /* Write CharMetrics */ i = 0; p = firstchar; while (p != NULL) p = p->next, i++; fprintf (output, "%s %d\n", STARTCHARMETRICS, i); p = firstchar; while (p != NULL) { fprintf (output, "C %d ; WX %d ; N %s ; B %d %d %d %d ;", p->chi->code, p->chi->wx, p->chi->name, p->chi->bb[0], p->chi->bb[1], p->chi->bb[2], p->chi->bb[3]) ; if (p->chi->rest == NULL) fprintf (output, "\n") ; else fprintf (output, " %s\n", p->chi->rest) ; p = p->next; } while (!lincmp (ENDCHARMETRICS)) rawreadline (); fprintf (output, "%s\n", line); /* Write KernPairs */ while (1) { if (rawreadline ()) return; if (lincmp (ENDFONTMETRICS)) goto SKIP ; if (lincmp (STARTKERNPAIRS)) break ; if (lincmp (STARTCOMPOSITES)) goto SKIP ; line[currspace] = ' '; fprintf (output, "%s\n", line); } i = 0; pk = firstkern; while (pk != NULL) { pi = pk->ki; while (pi != NULL) pi = pi->next, i++; pk = pk->next; } fprintf (output, "%s %d\n\n", STARTKERNPAIRS, i); pk = firstkern; while (pk != NULL) { pi = pk->ki; while (pi != NULL) { fprintf (output, "KPX %s %s %d\n", pk->name, pi->name, pi->kern); pi = pi->next; } fprintf (output, "\n"); pk = pk->next; } while (!lincmp (ENDKERNPAIRS)) rawreadline (); fprintf (output, "%s\n", line); /* Write Composites */ while (1) { if (rawreadline ()) return; if (lincmp (ENDFONTMETRICS)) break ; if (lincmp (STARTCOMPOSITES)) break ; line[currspace] = ' '; fprintf (output, "%s\n", line); } SKIP: i = 0; c = firstcom; while (c != NULL) c = c->next, i++; fprintf (output, "%s %d\n", STARTCOMPOSITES, i); c = firstcom; while (c != NULL) fprintf (output, "%s\n", c->lin), c = c->next; fprintf (output, "%s\n", ENDCOMPOSITES); if (lincmp (STARTCOMPOSITES)) { while (!lincmp (ENDCOMPOSITES)) rawreadline (); while (rawreadline() == 0) { line[currspace] = ' '; fprintf (output, "%s\n", line); } } else fprintf (output, "%s\n", ENDFONTMETRICS); return; } int main (argc, argv) /* main program */ /*-------------------*/ int argc; char *argv[]; { lastpool = 0; firstchar = lastchar = NULL; firstkern = lastkern = NULL; firstcom = lastcom = NULL; firstvar = lastvar = NULL; poolwrite = 1; printf ("Program a2ac, ver.1, Copyright (C) 1994,1995, Petr Olsak\n"); if (argc != 4) return printf ("usage: a2ac input.afm corr.tab output.afm\n"), 2 ; afminput = fopen (argv[1], "r"); if (afminput == NULL) ERROR ("can't open afm input file"); corrfile = fopen (argv[2], "r"); if (corrfile == NULL) ERROR ("can't open corr file"); input = afminput; readafm () ; input = corrfile; makenews () ; input = afminput; rewind (input); output = fopen (argv[3], "w"); if (output == NULL) ERROR ("can't write to output file"); writeafm () ; return 0; }