summaryrefslogtreecommitdiff
path: root/Build/source/texk/dvipsk/afm2tfm.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/dvipsk/afm2tfm.c')
-rw-r--r--Build/source/texk/dvipsk/afm2tfm.c2170
1 files changed, 0 insertions, 2170 deletions
diff --git a/Build/source/texk/dvipsk/afm2tfm.c b/Build/source/texk/dvipsk/afm2tfm.c
deleted file mode 100644
index 47e0e6c4a1f..00000000000
--- a/Build/source/texk/dvipsk/afm2tfm.c
+++ /dev/null
@@ -1,2170 +0,0 @@
-/* $Id$ */
-
-/* Public domain, originally written by Tom Rokicki.
- * This program converts AFM files to TeX TFM files, and optionally
- * to TeX VPL files that retain all kerning and ligature information.
- * Both files make the characters not normally encoded by TeX available
- * by character codes greater than 127.
- */
-
-/* (Modified by Don Knuth from Tom Rokicki's pre-VPL version.) */
-/* VM/CMS port by J. Hafner (hafner@almaden.ibm.com), based on
- * the port by Alessio Guglielmi (guglielmi@ipisnsib.bitnet)
- * and Marco Prevedelli (prevedelli@ipisnsva.bitnet).
- * This port is still in test state. No guarantees.
- * 11/3/92: more corrections to VM/CMS port. Now it looks correct
- * and will be supported by J. Hafner.
- *
- */
-/*
- * More changes, primarily from Karl Berry, enough for a new version
- * number to 8.0; 1 December 1996. Note that this version computes
- * checksums differently (more intelligently).
- */
-
-#ifdef KPATHSEA
-#include "config.h"
-#include <kpathsea/c-ctype.h>
-#include <kpathsea/progname.h>
-#include <kpathsea/version.h>
-#include <math.h>
-#else /* ! KPATHSEA */
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#if defined(SYSV) || defined(VMS) || defined(__THINK__) || defined(MSDOS) || defined(OS2) || defined(ATARIST) || defined(WIN32)
-#include <string.h>
-#else
-#include <strings.h>
-#endif
-#include <math.h>
-#ifdef ATARIST
-#include <float.h>
-#endif
-#endif /* KPATHSEA */
-
-/* JLH: added these to make the code easier to read and remove some
- ascii<->ebcdic dependencies */
-#define ASCII_A 65
-#define ASCII_Z 90
-#define ASCII_a 97
-#define ASCII_z 122
-#define ASCII_0 48
-#define ASCII_9 57
-
-#ifdef VMCMS
-#define interesting lookstr /* for 8 character truncation conflicts */
-#include "dvipscms.h"
-extern FILE *cmsfopen();
-extern char ebcdic2ascii[];
-extern char ascii2ebcdic[];
-#ifdef fopen
-#undef fopen
-#endif
-#define fopen cmsfopen
-#endif /* VMCMS */
-
-#include "dvips.h"
-/* debug.h redefines fopen to my_real_fopen, but it's still a FILE * */
-#ifdef fopen
-#undef fopen
-extern FILE *fopen ();
-#endif
-
-struct encoding {
- const char *name;
- const char *vec[256];
-};
-struct encoding staticencoding = {
- "TeX text",
- {"Gamma", "Delta", "Theta", "Lambda", "Xi", "Pi", "Sigma",
- "Upsilon", "Phi", "Psi", "Omega", "arrowup", "arrowdown", "quotesingle",
- "exclamdown", "questiondown", "dotlessi", "dotlessj", "grave", "acute",
- "caron", "breve", "macron", "ring", "cedilla", "germandbls", "ae", "oe",
- "oslash", "AE", "OE", "Oslash", "space", "exclam", "quotedbl", "numbersign",
- "dollar", "percent", "ampersand", "quoteright", "parenleft", "parenright",
- "asterisk", "plus", "comma", "hyphen", "period", "slash", "zero", "one",
- "two", "three", "four", "five", "six", "seven", "eight", "nine", "colon",
- "semicolon", "less", "equal", "greater", "question", "at", "A", "B", "C",
- "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R",
- "S", "T", "U", "V", "W", "X", "Y", "Z", "bracketleft", "backslash",
- "bracketright", "circumflex", "underscore", "quoteleft", "a", "b", "c", "d",
- "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s",
- "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar", "braceright",
- "tilde", "dieresis", "", "", "", "", "", "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "" } };
-/*
- * It's easier to put this in static storage and parse it as we go
- * than to build the structures ourselves.
- */
-const char *staticligkern[] = {
- "% LIGKERN space l =: lslash ; space L =: Lslash ;",
- "% LIGKERN question quoteleft =: questiondown ;",
- "% LIGKERN exclam quoteleft =: exclamdown ;",
- "% LIGKERN hyphen hyphen =: endash ; endash hyphen =: emdash ;",
- "% LIGKERN quoteleft quoteleft =: quotedblleft ;",
- "% LIGKERN quoteright quoteright =: quotedblright ;",
- "% LIGKERN space {} * ; * {} space ; zero {} * ; * {} zero ;",
- "% LIGKERN one {} * ; * {} one ; two {} * ; * {} two ;",
- "% LIGKERN three {} * ; * {} three ; four {} * ; * {} four ;",
- "% LIGKERN five {} * ; * {} five ; six {} * ; * {} six ;",
- "% LIGKERN seven {} * ; * {} seven ; eight {} * ; * {} eight ;",
- "% LIGKERN nine {} * ; * {} nine ;",
-/* Kern accented characters the same way as their base. */
- "% LIGKERN Aacute <> A ; aacute <> a ;",
- "% LIGKERN Acircumflex <> A ; acircumflex <> a ;",
- "% LIGKERN Adieresis <> A ; adieresis <> a ;",
- "% LIGKERN Agrave <> A ; agrave <> a ;",
- "% LIGKERN Aring <> A ; aring <> a ;",
- "% LIGKERN Atilde <> A ; atilde <> a ;",
- "% LIGKERN Ccedilla <> C ; ccedilla <> c ;",
- "% LIGKERN Eacute <> E ; eacute <> e ;",
- "% LIGKERN Ecircumflex <> E ; ecircumflex <> e ;",
- "% LIGKERN Edieresis <> E ; edieresis <> e ;",
- "% LIGKERN Egrave <> E ; egrave <> e ;",
- "% LIGKERN Iacute <> I ; iacute <> i ;",
- "% LIGKERN Icircumflex <> I ; icircumflex <> i ;",
- "% LIGKERN Idieresis <> I ; idieresis <> i ;",
- "% LIGKERN Igrave <> I ; igrave <> i ;",
- "% LIGKERN Ntilde <> N ; ntilde <> n ;",
- "% LIGKERN Oacute <> O ; oacute <> o ;",
- "% LIGKERN Ocircumflex <> O ; ocircumflex <> o ;",
- "% LIGKERN Odieresis <> O ; odieresis <> o ;",
- "% LIGKERN Ograve <> O ; ograve <> o ;",
- "% LIGKERN Oslash <> O ; oslash <> o ;",
- "% LIGKERN Otilde <> O ; otilde <> o ;",
- "% LIGKERN Scaron <> S ; scaron <> s ;",
- "% LIGKERN Uacute <> U ; uacute <> u ;",
- "% LIGKERN Ucircumflex <> U ; ucircumflex <> u ;",
- "% LIGKERN Udieresis <> U ; udieresis <> u ;",
- "% LIGKERN Ugrave <> U ; ugrave <> u ;",
- "% LIGKERN Yacute <> Y ; yacute <> y ;",
- "% LIGKERN Ydieresis <> Y ; ydieresis <> y ;",
- "% LIGKERN Zcaron <> Z ; zcaron <> z ;",
-/*
- * These next are only included for deficient afm files that
- * have the lig characters but not the lig commands.
- */
- "% LIGKERN f i =: fi ; f l =: fl ; f f =: ff ; ff i =: ffi ;",
- "% LIGKERN ff l =: ffl ;",
- 0 };
-/*
- * The above layout corresponds to TeX Typewriter Type and is compatible
- * with TeX Text because the position of ligatures is immaterial.
- */
-struct encoding *outencoding = 0;
-struct encoding *inencoding = 0;
-char *outenname = NULL,
- *inenname = NULL;/* the file names for input and output encodings */
-int boundarychar = -1; /* the boundary character */
-int ignoreligkern; /* do we look at ligkern info in the encoding? */
-/*
- * This is what we store Adobe data in.
- */
-struct adobeinfo {
- struct adobeinfo *next;
- int adobenum, texnum, width;
- const char *adobename;
- int llx, lly, urx, ury;
- struct lig *ligs;
- struct kern *kerns;
- struct adobeptr *kern_equivs;
- struct pcc *pccs;
- int wptr, hptr, dptr, iptr;
-} *adobechars, *adobeptrs[256], *texptrs[256],
- *uppercase[256], *lowercase[256];
-int nexttex[256]; /* for characters encoded multiple times in output */
-/*
- * These are the eight ligature ops, in VPL terms and in METAFONT terms.
- */
-const char *vplligops[] = {
- "LIG", "/LIG", "/LIG>", "LIG/", "LIG/>", "/LIG/", "/LIG/>", "/LIG/>>", 0
-};
-const char *encligops[] = {
- "=:", "|=:", "|=:>", "=:|", "=:|>", "|=:|", "|=:|>", "|=:|>>", 0
-};
-struct lig {
- struct lig *next;
- const char *succ, *sub;
- short op, boundleft;
-};
-struct kern {
- struct kern *next;
- const char *succ;
- int delta;
-};
-struct adobeptr {
- struct adobeptr *next;
- struct adobeinfo *ch;
-};
-struct pcc {
- struct pcc *next;
- const char * partname;
- int xoffset, yoffset;
-};
-
-FILE *afmin, *vplout, *tfmout;
-#define MAXNAME 256
-char inname[MAXNAME], outname[MAXNAME]; /* names of input and output files */
-char tmpstr[MAXNAME]; /* a buffer for one string */
-#define INBUFSIZE 1024
-char buffer[INBUFSIZE+10]; /* input buffer (modified while parsing) */
-char obuffer[INBUFSIZE+10]; /* unmodified copy of input buffer */
-char *param; /* current position in input buffer */
-const char *fontname = "Unknown";
-const char *codingscheme = "Unspecified";
-#ifdef VMCMS
-char *ebfontname;
-char *ebcodingscheme;
-#endif
-float italicangle = 0.0;
-char fixedpitch;
-char makevpl;
-char pedantic;
-int noaccentheightadjust;
-int xheight = 400;
-int fontspace;
-int bc, ec;
-long cksum;
-float efactor = 1.0, slant = 0.0;
-float capheight = 0.8;
-char *efactorparam, *slantparam;
-double newslant;
-char titlebuf[500];
-
-static void
-error(const char *s)
-{
- fprintf(stderr, "%s\n", s);
- if (obuffer[0]) {
- fprintf(stderr, "%s\n", obuffer);
- while (param > buffer) {
- fprintf(stderr, " ");
- param--;
- }
- fprintf(stderr, "^\n");
- }
- if (*s == '!')
- exit(1);
-}
-
-static int
-transform(register int x, register int y)
-{
- register double acc;
- acc = efactor * x + slant *y;
- return (int)(acc>=0? floor(acc+0.5) : ceil(acc-0.5) );
-}
-
-static int
-texlive_getline(void) {
- register char *p;
- register int c;
-
- param = buffer;
- for (p=buffer; (c=getc(afmin)) != EOF;) {
- if (p - buffer >= INBUFSIZE)
- error("! input line too long; perhaps input file is malformed?");
- *p++ = c;
- if (c == '\r') {
- c = getc(afmin);
- if (c != EOF) {
- if (c == '\n') {
- *p++ = c;
- } else {
- ungetc(c, afmin);
- }
- }
- break;
- } else if (c == '\n') {
- break;
- }
- }
- *p = 0;
- strcpy(obuffer, buffer);
- if (p == buffer && c == EOF)
- return(0);
- else
- return(1);
-}
-
-const char *interesting[] = { "FontName", "ItalicAngle", "IsFixedPitch",
- "XHeight", "C", "KPX", "CC", "EncodingScheme", NULL};
-#define FontName (0)
-#define ItalicAngle (1)
-#define IsFixedPitch (2)
-#define XHeight (3)
-#define C (4)
-#define KPX (5)
-#define CC (6)
-#define EncodingScheme (7)
-#define NONE (-1)
-static int
-interest(const char *s)
-{
- register const char **p;
- register int n;
-
- for (p=interesting, n=0; *p; p++, n++)
- if (strcmp(s, *p)==0)
- return(n);
- return(NONE);
-}
-
-static char *
-mymalloc(unsigned long len)
-{
- register char *p;
- int i;
-
-#ifdef SMALLMALLOC
- if (len > 65500L)
- error("! can't allocate more than 64K!");
-#endif
- p = (char *) malloc((unsigned)len);
- if (p==NULL)
- error("! out of memory");
- for (i=0; i<len; i++)
- p[i] = 0;
- return(p);
-}
-
-static char *
-newstring(char *s)
-{
- char *q = mymalloc((unsigned long)(strlen(s) + 1));
- strcpy(q, s);
- return q;
-}
-
-static char *
-paramnewstring(void) {
- register char *p, *q;
-
- p = param;
- while (*p > ' ')
- p++;
- if (*p != 0)
- *p++ = 0;
- q = newstring(param);
- while (*p && *p <= ' ')
- p++;
- param = p;
- return(q);
-}
-
-static char *
-paramstring(void) {
- register char *p, *q;
-
- p = param;
- while (*p > ' ')
- p++;
- q = param;
- if (*p != 0)
- *p++ = 0;
- while (*p && *p <= ' ')
- p++;
- param = p;
- return(q);
-}
-
-static int
-paramnum(void) {
- register char *p;
- int i;
-
- p = paramstring();
- if (sscanf(p, "%d", &i) != 1)
- error("! integer expected");
- return(i);
-}
-
-static float
-paramfloat(void) {
- register char *p;
- float i;
-
- p = paramstring();
- if (sscanf(p, "%f", &i) != 1)
- error("! number expected");
- return(i);
-}
-
-static struct adobeinfo *
-newchar(void) {
- register struct adobeinfo *ai;
-
- ai = (struct adobeinfo *)mymalloc((unsigned long)sizeof(struct adobeinfo));
- ai->adobenum = -1;
- ai->texnum = -1;
- ai->width = -1;
- ai->adobename = NULL;
- ai->llx = -1;
- ai->lly = -1;
- ai->urx = -1;
- ai->ury = -1;
- ai->ligs = NULL;
- ai->kerns = NULL;
- ai->kern_equivs = NULL;
- ai->pccs = NULL;
- ai->next = adobechars;
- adobechars = ai;
- return(ai);
-}
-
-static struct kern *
-newkern(void) {
- register struct kern *nk;
-
- nk = (struct kern *)mymalloc((unsigned long)sizeof(struct kern));
- nk->next = NULL;
- nk->succ = NULL;
- nk->delta = 0;
- return(nk);
-}
-
-static struct pcc *
-newpcc(void) {
- register struct pcc *np;
-
- np = (struct pcc *)mymalloc((unsigned long)sizeof(struct pcc));
- np->next = NULL;
- np->partname = NULL;
- np->xoffset = 0;
- np->yoffset = 0;
- return(np);
-}
-
-static struct lig *
-newlig(void) {
- register struct lig *nl;
-
- nl = (struct lig *)mymalloc((unsigned long)sizeof(struct lig));
- nl->next = NULL;
- nl->succ = NULL;
- nl->sub = NULL;
- nl->op = 0; /* the default =: op */
- nl->boundleft = 0;
- return(nl);
-}
-
-static void
-expect(const char *s)
-{
- if (strcmp(paramstring(), s) != 0) {
- fprintf(stderr, "%s expected: ", s);
- error("! syntax error");
- }
-}
-
-static void
-handlechar(void) { /* an input line beginning with C */
- register struct adobeinfo *ai;
- register struct lig *nl;
-
- ai = newchar();
- ai->adobenum = paramnum();
- expect(";");
- expect("WX");
- ai->width = transform(paramnum(),0);
- if (ai->adobenum >= 0 && ai->adobenum < 256) {
- adobeptrs[ai->adobenum] = ai;
- }
- expect(";");
-/* Ignore vertical metrics information */
- if (*param == 'W' && *(param + 1) == 'Y') {
- expect("WY");
- paramnum();
- expect(";");
- }
- expect("N");
- ai->adobename = paramnewstring();
- expect(";");
- expect("B");
- ai->llx = paramnum();
- ai->lly = paramnum();
- ai->llx = transform(ai->llx, ai->lly);
- ai->urx = paramnum();
- ai->ury = paramnum();
- ai->urx = transform(ai->urx, ai->ury);
-/* We need to avoid negative heights or depths. They break accents in
- math mode, among other things. */
- if (ai->lly > 0)
- ai->lly = 0;
- if (ai->ury < 0)
- ai->ury = 0;
- expect(";");
-/* Now look for ligatures (which aren't present in fixedpitch fonts) */
- while (*param == 'L' && !fixedpitch) {
- expect("L");
- nl = newlig();
- nl->succ = paramnewstring();
- nl->sub = paramnewstring();
- nl->next = ai->ligs;
- ai->ligs = nl;
- expect(";");
- }
-}
-
-static struct adobeinfo *
-findadobe(const char *p)
-{
- register struct adobeinfo *ai;
-
- for (ai=adobechars; ai; ai = ai->next)
- if (strcmp(p, ai->adobename)==0)
- return(ai);
- return(NULL);
-}
-
-
-/*
- * The following comment no longer applies; we rely on the LIGKERN
- * entries to kill space kerns. Also, the same applies to numbers.
- *
- * We ignore kerns before and after space characters, because (1) TeX
- * is using the space only for Polish ligatures, and (2) TeX's
- * boundarychar mechanisms are not oriented to kerns (they apply
- * to both spaces and punctuation) so we don't want to use them.
- */
-static void
-handlekern(void) { /* an input line beginning with KPX */
- register struct adobeinfo *ai;
- register char *p;
- register struct kern *nk;
-
- p = paramstring();
- ai = findadobe(p);
- if (ai == NULL)
- error("kern char not found");
- else {
- nk = newkern();
- nk->succ = paramnewstring();
- nk->delta = transform(paramnum(),0);
- nk->next = ai->kerns;
- ai->kerns = nk;
- }
-}
-
-static void
-handleconstruct(void) { /* an input line beginning with CC */
- register struct adobeinfo *ai;
- register char *p;
- register struct pcc *np;
- register int n;
- struct pcc *npp = NULL;
-
- p = paramstring();
- ai = findadobe(p);
- if (ai == NULL)
- error("! composite character name not found");
- n = paramnum();
- expect(";");
- while (n--) {
- if (strcmp(paramstring(),"PCC") != 0) return;
- /* maybe I should expect("PCC") instead, but I'm playing it safe */
- np = newpcc();
- np->partname = paramnewstring();
- if (findadobe(np->partname)==NULL) return;
- np->xoffset = paramnum();
- np->yoffset = paramnum();
- np->xoffset = transform(np->xoffset, np->yoffset);
- if (npp) npp->next = np;
- else ai->pccs = np;
- npp = np;
- expect(";");
- }
-}
-
-static struct encoding *readencoding(char *);
-
-#if 0
-/* Not used */
-static void
-makeaccentligs(void) {
- register struct adobeinfo *ai, *aci;
- register char *p;
- register struct lig *nl;
- for (ai=adobechars; ai; ai=ai->next) {
- p = ai->adobename;
- if (strlen(p)>2)
- if ((aci=findadobe(p+1)) && (aci->adobenum > 127)) {
- nl = newlig();
- nl->succ = mymalloc((unsigned long)2);
- *(nl->succ + 1) = 0;
- *(nl->succ) = *p;
- nl->sub = ai->adobename;
- nl->next = aci->ligs;
- aci->ligs = nl;
- }
- }
-}
-#endif
-
-static void
-readadobe(void) {
- struct adobeinfo *ai;
-#ifdef VMCMS
- int i;
-#endif
-
-/*
- * We allocate a placeholder boundary char.
- */
- ai = newchar();
- ai->adobenum = -1;
- ai->adobename = "||"; /* boundary character name */
- while (texlive_getline()) {
- switch(interest(paramstring())) {
-case FontName:
- fontname = paramnewstring();
-#ifdef VMCMS
-/* fontname comes in as ebcdic but we need it asciified for tfm file
- so we save it in ebfontname and change it in fontname */
- ebfontname = newstring(fontname);
- i=0;
- while(fontname[i] != '\0') {
- fontname[i]=ebcdic2ascii[fontname[i]];
- i++;
- };
-#endif
- break;
-case EncodingScheme:
- codingscheme = paramnewstring();
-#ifdef VMCMS
-/* for codingscheme, we do the same as we did for fontname */
- ebcodingscheme = newstring(codingscheme);
- i=0;
- while(codingscheme[i] != '\0') {
- codingscheme[i]=ebcdic2ascii[codingscheme[i]];
- i++;
- }
-#endif
- break;
-case ItalicAngle:
- italicangle = paramfloat();
- break;
-case IsFixedPitch:
- if (*param == 't' || *param == 'T')
- fixedpitch = 1;
- else
- fixedpitch = 0;
- break;
-case XHeight:
- xheight = paramnum();
- break;
-case C:
- handlechar();
- break;
-case KPX:
- handlekern();
- break;
-case CC:
- handleconstruct();
- break;
-default:
- break;
- }
- }
- fclose(afmin);
- afmin = 0;
-}
-/*
- * Re-encode the adobe font. Assumes that the header file will
- * also contain the appropriate instructions!
- */
-static void
-handlereencoding(void) {
- if (inenname) {
- int i;
- struct adobeinfo *ai;
- const char *p;
-
- ignoreligkern = 1;
- inencoding = readencoding(inenname);
- for (i=0; i<256; i++)
- if (0 != (ai=adobeptrs[i])) {
- ai->adobenum = -1;
- adobeptrs[i] = NULL;
- }
- for (i=0; i<256; i++) {
- p = inencoding->vec[i];
- if (p && *p && strcmp(p, ".notdef") != 0 && 0 != (ai = findadobe(p))) {
- ai->adobenum = i;
- adobeptrs[i] = ai;
- }
- }
- codingscheme = inencoding->name;
- }
- ignoreligkern = 0;
- if (outenname) {
- outencoding = readencoding(outenname);
- } else {
- outencoding = readencoding((char *)0);
- }
-}
-
-/*
- * This routine reverses a list. We use it because we accumulate the
- * adobeinfo list in reverse order, but when we go to map the
- * characters, we would prefer to use the original ordering. It just
- * makes more sense.
- */
-static struct adobeinfo *
-revlist (struct adobeinfo *p)
-{
- struct adobeinfo *q = 0, *t;
-
- while (p) {
- t = p->next;
- p->next = q;
- q = p;
- p = t;
- }
- return q;
-}
-
-static void
-assignchars(void) {
- register const char **p;
- register int i, j;
- register struct adobeinfo *ai, *pai;
- int nextfree = 128;
- struct pcc *pcp;
-
-/*
- * First, we assign all those that match perfectly.
- */
- for (i=0, p=outencoding->vec; i<256; i++, p++)
- if (*p && strcmp(*p, ".notdef") != 0 &&
- (ai=findadobe(*p)) && (ai->adobenum >= 0 || ai->pccs != NULL)) {
- if (ai->texnum >= 0)
- nexttex[i] = ai->texnum; /* linked list */
- ai->texnum = i;
- texptrs[i] = ai;
- }
- if (pedantic)
- return;
-/*
- * Next, we assign all the others, retaining the adobe positions, possibly
- * multiply assigning characters. Unless the output encoding was
- * precisely specified.
- */
- for (ai=adobechars; ai; ai=ai->next)
- if (ai->adobenum >= 0 && ai->adobenum <256
- && ai->texnum < 0 && texptrs[ai->adobenum] == 0) {
- ai->texnum = ai->adobenum;
- texptrs[ai->adobenum] = ai;
- }
-/*
- * Finally, we map all remaining characters into free locations beginning
- * with 128, if we know how to construct those characters. We need to
- * make sure the component pieces are mapped.
- */
- adobechars = revlist(adobechars);
- for (ai=adobechars; ai; ai=ai->next)
- if (ai->texnum<0 && (ai->adobenum>=0 || ai->pccs != NULL)) {
- while (texptrs[nextfree]) {
- nextfree=(nextfree+1)&255;
- if (nextfree==128) goto finishup; /* all slots full */
- }
- ai->texnum = nextfree;
- texptrs[nextfree] = ai;
- }
-finishup:
-/*
- * We now check all of the composite characters. If any of the
- * components are not mapped, we unmap the composite character.
- */
- for (i=0; i<256; i++) {
- ai = texptrs[i];
- if (ai && ai->pccs != NULL && ai->texnum >= 0) {
- for (pcp = ai->pccs; pcp; pcp = pcp->next) {
- pai = findadobe(pcp->partname);
- if (pai == NULL || pai->texnum < 0) {
- texptrs[ai->texnum] = 0;
- ai->texnum = -1;
- break;
- }
- }
- }
- }
-/*
- * Now, if any of the characters are encoded multiple times, we want
- * ai->texnum to be the first one assigned, since that is most likely
- * to be the most important one. So we reverse the above lists.
- */
- for (ai=adobechars; ai; ai=ai->next)
- if (ai->texnum >= 0 && ai->texnum < 256) {
- j = -1;
- while (nexttex[ai->texnum] >= 0) {
- i = nexttex[ai->texnum];
- nexttex[ai->texnum] = j;
- j = ai->texnum;
- ai->texnum = i;
- }
- nexttex[ai->texnum] = j;
- }
-}
-
-static void
-upmap(void) { /* Compute uppercase mapping, when making a small caps font */
- register struct adobeinfo *ai, *Ai;
- register const char *p;
- register char *q;
- register struct pcc *np, *nq;
- int i;
- char lwr[50];
-
-/* JLH: changed some lines below to be ascii<->ebcdic independent
- any reason we don't use 'isupper'?.
- Looks like we should use isupper to me --karl. */
- for (Ai=adobechars; Ai; Ai=Ai->next) {
- p = Ai->adobename;
- if (isupper ((unsigned char)*p)) {
- q = lwr;
- for (; *p; p++)
- *q++ = TOLOWER (*p);
- *q = '\0'; /* changed this too! */
-
- if (0 != (ai=findadobe(lwr))) {
- for (i = ai->texnum; i >= 0; i = nexttex[i])
- uppercase[i] = Ai;
- for (i = Ai->texnum; i >= 0; i = nexttex[i])
- lowercase[i] = ai;
- }
- }
- }
-/* Note that, contrary to the normal true/false conventions,
- * uppercase[i] is NULL and lowercase[i] is non-NULL when i is the
- * ASCII code of an uppercase letter; and vice versa for lowercase letters */
-
- if (0 != (ai=findadobe("germandbls")))
- if (0 != (Ai=findadobe("S"))) { /* we also construct SS */
- for (i=ai->texnum; i >= 0; i = nexttex[i])
- uppercase[i] = ai;
- ai->adobenum = -1;
- ai->width = Ai->width << 1;
- ai->llx = Ai->llx;
- ai->lly = Ai->lly;
- ai->urx = Ai->width + Ai->urx;
- ai->ury = Ai->ury;
- ai->kerns = Ai->kerns;
- np = newpcc();
- np->partname = "S";
- nq = newpcc();
- nq->partname = "S";
- nq->xoffset = Ai->width;
- np->next = nq;
- ai->pccs = np;
- }
- if ((ai=findadobe("dotlessi")))
- for (i=ai->texnum; i >= 0; i = nexttex[i])
- uppercase[i] = findadobe("I");
- if ((ai=findadobe("dotlessj")))
- for (i=ai->texnum; i >= 0; i = nexttex[i])
- uppercase[i] = findadobe("J");
-}
-/* The logic above seems to work well enough, but it leaves useless characters
- * like `fi' and `fl' in the font if they were present initially,
- * and it omits characters like `dotlessj' if they are absent initially */
-
-/* Now we turn to computing the TFM file */
-
-int lf, lh, nw, nh, nd, ni, nl, nk, ne, np;
-
-static void
-write16(register short what)
-{
- fputc(what >> 8, tfmout);
- fputc(what & 255, tfmout);
-}
-
-static void
-writearr(register long *p, register int n)
-{
- while (n) {
- write16((short)(*p >> 16));
- write16((short)(*p & 65535));
- p++;
- n--;
- }
-}
-
-static void
-makebcpl(register long *p, register const char *s, register int n)
-{
- register long t;
- register long sc;
-
- if (strlen(s) < n)
- n = strlen(s);
- t = ((long)n) << 24;
- sc = 16;
- while (n > 0) {
- t |= ((long)(*(unsigned const char *)s++)) << sc;
- sc -= 8;
- if (sc < 0) {
- *p++ = t;
- t = 0;
- sc = 24;
- }
- n--;
- }
- *p++ = t;
-}
-
-int source[257];
-int unsort[257];
-
-/*
- * Next we need a routine to reduce the number of distinct dimensions
- * in a TFM file. Given an array what[0]...what[oldn-1], we want to
- * group its elements into newn clusters, in such a way that the maximum
- * difference between elements of a cluster is as small as possible.
- * Furthermore, what[0]=0, and this value must remain in a cluster by
- * itself. Data such as `0 4 6 7 9' with newn=3 shows that an iterative
- * scheme in which 6 is first clustered with 7 will not work. So we
- * borrow a neat algorithm from METAFONT to find the true optimum.
- * Memory location what[oldn] is set to 0x7fffffffL for convenience.
- */
-long nextd; /* smallest value that will give a different mincover */
-static int
-mincover(long *what,
- register long d) /* tells how many clusters result, given max difference d */
-{
- register int m;
- register long l;
- register long *p;
-
- nextd = 0x7fffffffL;
- p = what+1;
- m = 1;
- while (*p<0x7fffffffL) {
- m++;
- l = *p;
- while (*++p <= l+d);
- if (*p-l < nextd) nextd = *p-l;
- }
- return (m);
-}
-
-static void
-remap(long * what, int oldn, int newn)
-{
- register int i, j;
- register long d, l;
-
- what[oldn] = 0x7fffffffL;
- for (i=oldn-1; i>0; i--) {
- d = what[i];
- for (j=i; what[j+1]<d; j++) {
- what[j] = what[j+1];
- source[j] = source[j+1];
- }
- what[j] = d;
- source[j] = i;
- } /* Tom, don't let me ever catch you using bubblesort again! -- Don */
-
- i = mincover(what, 0L);
- d = nextd;
- while (mincover(what,d+d)>newn) d += d;
- while (mincover(what,d)>newn) d = nextd;
-
- i = 1;
- j = 0;
- while (i<oldn) {
- j++;
- l = what[i];
- unsort[source[i]] = j;
- while (what[++i] <= l+d) {
- unsort[source[i]] = j;
- if (i-j == oldn-newn) d = 0;
- }
- what[j] = (l+what[i-1])/2;
- }
-}
-
-static long
-checksum(void) {
- int i;
- unsigned long s1 = 0, s2 = 0;
- const char *p;
- struct adobeinfo *ai;
-
- for (i=0; i<256; i++)
- if (0 != (ai=adobeptrs[i])) {
- s1 = ((s1 << 1) ^ (s1>>31)) ^ ai->width; /* cyclic left shift */
- s1 &= 0xffffffff; /* in case we're on a 64-bit machine */
- for (p=ai->adobename; *p; p++)
-#ifndef VMCMS
- s2 = (s2 * 3) + *p;
-#else
- s2 = (s2 * 3) + ebcdic2ascii[*p];
-#endif
- }
- s1 = (s1 << 1) ^ s2;
- return s1;
-}
-
-/*
- * The next routine simply scales something.
- * Input is in 1000ths of an em. Output is in FIXFACTORths of 1000.
- */
-#define FIXFACTOR (0x100000L) /* 2^{20}, the unit fixnum */
-static long
-scale(long what)
-{
- return(((what / 1000) << 20) +
- (((what % 1000) << 20) + 500) / 1000);
-}
-
-long *header, *charinfo, *width, *height, *depth, *ligkern, *kern, *tparam,
- *italic;
-long *tfmdata;
-
-static void
-buildtfm(void) {
- register int i, j;
- register struct adobeinfo *ai;
-
- header = tfmdata;
- cksum = checksum();
- header[0] = cksum;
- header[1] = 0xa00000; /* 10pt design size */
- makebcpl(header+2, codingscheme, 39);
- makebcpl(header+12, fontname, 19);
- lh = 17;
- charinfo = header + lh;
-
- for (i=0; i<256 && adobeptrs[i]==NULL; i++);
- bc = i;
- for (i=255; i>=0 && adobeptrs[i]==NULL; i--);
- ec = i;
- if (ec < bc)
- error("! no Adobe characters");
-
- width = charinfo + (ec - bc + 1);
- width[0] = 0;
- nw++;
- for (i=bc; i<=ec; i++)
- if (0 != (ai=adobeptrs[i])) {
- width[nw]=ai->width;
- for (j=1; width[j]!=ai->width; j++);
- ai->wptr = j;
- if (j==nw)
- nw++;
- }
- if (nw>256)
- error("! 256 chars with different widths");
- depth = width + nw;
- depth[0] = 0;
- nd = 1;
- for (i=bc; i<=ec; i++)
- if (0 != (ai=adobeptrs[i])) {
- depth[nd] = -ai->lly;
- for (j=0; depth[j]!=-ai->lly; j++);
- ai->dptr = j;
- if (j==nd)
- nd++;
- }
- if (nd > 16) {
- remap(depth, nd, 16);
- nd = 16;
- for (i=bc; i<=ec; i++)
- if (0 != (ai=adobeptrs[i]))
- ai->dptr = unsort[ai->dptr];
- }
- height = depth + nd;
- height[0] = 0;
- nh = 1;
- for (i=bc; i<=ec; i++)
- if (0 != (ai=adobeptrs[i])) {
- height[nh]=ai->ury;
- for (j=0; height[j]!=ai->ury; j++);
- ai->hptr = j;
- if (j==nh)
- nh++;
- }
- if (nh > 16) {
- remap(height, nh, 16);
- nh = 16;
- for (i=bc; i<=ec; i++)
- if (0 != (ai=adobeptrs[i]))
- ai->hptr = unsort[ai->hptr];
- }
- italic = height + nh;
- italic[0] = 0;
- ni = 1;
- for (i=bc; i<=ec; i++)
- if (0 != (ai=adobeptrs[i])) {
- italic[ni] = ai->urx - ai->width;
- if (italic[ni]<0)
- italic[ni] = 0;
- for (j=0; italic[j]!=italic[ni]; j++);
- ai->iptr = j;
- if (j==ni)
- ni++;
- }
- if (ni > 64) {
- remap(italic, ni, 64);
- ni = 64;
- for (i=bc; i<=ec; i++)
- if (0 != (ai=adobeptrs[i]))
- ai->iptr = unsort[ai->iptr];
- }
-
- for (i=bc; i<=ec; i++)
- if (0 != (ai=adobeptrs[i]))
- charinfo[i-bc] = ((long)(ai->wptr)<<24) +
- ((long)(ai->hptr)<<20) +
- ((long)(ai->dptr)<<16) +
- ((long)(ai->iptr)<<10);
-
- ligkern = italic + ni;
- nl = 0; /* ligatures and kerns omitted from raw Adobe font */
- kern = ligkern + nl;
- nk = 0;
-
- newslant = (double)slant - efactor * tan(italicangle*(3.1415926535/180.0));
- tparam = kern + nk;
- tparam[0] = (long)(FIXFACTOR * newslant + 0.5);
- tparam[1] = scale((long)fontspace);
- tparam[2] = (fixedpitch ? 0 : scale((long)(300*efactor+0.5)));
- tparam[3] = (fixedpitch ? 0 : scale((long)(100*efactor+0.5)));
- tparam[4] = scale((long)xheight);
- tparam[5] = scale((long)(1000*efactor+0.5));
- np = 6;
-}
-
-static void
-writesarr(long *what, int len)
-{
- register long *p;
- int i;
-
- p = what;
- i = len;
- while (i) {
- *p = scale(*p);
- scale(*p); /* need this kludge for some compilers */
- p++;
- i--;
- }
- writearr(what, len);
-}
-
-static void
-writetfm(void) {
- lf = 6 + lh + (ec - bc + 1) + nw + nh + nd + ni + nl + nk + ne + np;
- write16((short)lf);
- write16((short)lh);
- write16((short)bc);
- write16((short)ec);
- write16((short)nw);
- write16((short)nh);
- write16((short)nd);
- write16((short)ni);
- write16((short)nl);
- write16((short)nk);
- write16((short)ne);
- write16((short)np);
- writearr(header, lh);
- writearr(charinfo, ec-bc+1);
- writesarr(width, nw);
- writesarr(height, nh);
- writesarr(depth, nd);
- writesarr(italic, ni);
- writearr(ligkern, nl);
- writesarr(kern, nk);
- writearr(tparam, np);
-}
-
-/* OK, the TFM file is done! Now for our next trick, the VPL file. */
-
-/* For TeX we want to compute a character height that works properly
- with accents. We only do this if the xheight has a reasonable value
- (>50), and only if the -a flag is not given. Furthermore, we never
- return a height less than the height of the original character.
-
- The idea of this routine is to adjust the heights of bare characters
- (say, t) so that the result of using the \accent primitive (say, \"t)
- is the same as a precomposed tdieresis character. This is done in
- the vpl output, so the vf+tfm generated from the vpl are affected,
- but not the original tfm.
-
- This idea is reasonable, but the downside is that changing the height
- of the base character at all, but especially downward, has
- undesirable consequences: when putting a rule over the character or
- constructing a math bar-over accent, for example, the rule will be
- too close to (or too far from, if the height is increased) the
- character.
-
- Furthermore, these days, except when using the original CM fonts,
- precomposed accent glyphs are widely available and used. And afm2tfm
- is not used much with the original CM fonts, as they don't come with
- afm files :).
-
- In any case, there is one situation where adjusting the height of the
- base character by looking at the standalone accent is definitely
- wrong: the dcaron, tcaron, and [Ll]caron glyphs. In these cases, the
- usual check-above shape is replaced by (approximately) an apostrophe
- to the right of the character. Therefore looking at the standalone
- check glyph is inapplicable.
-
- In general, it seems wrong to ever decrease the height from the
- original, since that will almost certainly result in crashes with
- \bar and the like. That seems worse than a mispositioned accent.
- So the routine returns the original height if the heuristic would
- decrease it.
-
- Nevertheless, despite all the above, the original behavior has been
- around for so many years that it seems bad to change it now. So
- adjustments upward are still made, unless -a is given.
-
- The following list of accents doesn't need to be complete. */
-const char *accents[] = { "acute", "tilde", "caron", "dieresis", NULL };
-
-static int
-texheight(struct adobeinfo *ai)
-{
- const char **p;
- struct adobeinfo *aci, *acci;
- /* The `ai' argument is the base letter, e.g., "d".
- `aci' is the accent, e.g., "caron".
- `acci' is the pre-composed accented letter, e.g., "dcaron". */
-
- /* If -a was given, or the xheight is too small, or the character
- name is more than one letter long, return the original height. */
- if (noaccentheightadjust
- || xheight <= 50
- || *(ai->adobename + 1))
- return ai->ury;
-
- for (p = accents; *p; p++) { /* otherwise we look for accented letters */
- aci = findadobe(*p);
- if (aci) {
- strcpy(buffer, ai->adobename);
- strcat(buffer, *p);
- acci = findadobe(buffer);
- if (acci) {
- /* height heuristic since \accent assumes x-height positioning */
- int guess = acci->ury - aci->ury + xheight;
- if (guess > ai->ury) { /* ignore guess if it reduces height */
- return guess;
- }
- }
- }
- }
-
- /* didn't find anything to adjust, return original */
- return ai->ury;
-}
-
-/* modified tgr to eliminate varargs problems */
-
-#define vout(s) fprintf(vplout, s)
-int level; /* the depth of parenthesis nesting in VPL file being written */
-static void
-vlevout(void)
-{
- register int l = level;
- while (l--) vout(" ");
-}
-static void
-vlevnlout(void)
-{
- vout("\n");
- vlevout();
-}
-#define voutln(str) {fprintf(vplout,"%s\n",str);vlevout();}
-#define voutln2(f,s) {fprintf(vplout,f,s);vlevnlout();}
-#define voutln3(f,a,b) {fprintf(vplout,f,a,b);vlevnlout();}
-#define voutln4(f,a,b,c) {fprintf(vplout,f,a,b,c);vlevnlout();}
-static void
-vleft(void)
-{
- level++;
- vout("(");
-}
-
-static void
-vright(void)
-{
- level--;
- voutln(")");
-}
-
-int forceoctal = 0;
-
-char vcharbuf[100];
-static char *
-vchar(int c)
-{
- if (forceoctal == 0 && ISALNUM (c))
- sprintf(vcharbuf,"C %c",
-#ifndef VMCMS
- c);
-#else
- ascii2ebcdic[c]);
-#endif
- else sprintf(vcharbuf,"O %o", (unsigned)c);
- return vcharbuf;
-}
-
-char vnamebuf[1000];
-static char *
-vname(int c)
-{
- if (!forceoctal && ISALNUM (c)) {
- vnamebuf[0] = 0;
- } else if (c >= 0 && c < 256) {
- snprintf (vnamebuf, sizeof (vnamebuf),
- " (comment %s)", texptrs[c]->adobename);
- }
- return vnamebuf;
-}
-
-static void
-writevpl(void)
-{
- register int i, j, k;
- register struct adobeinfo *ai;
- register struct lig *nlig;
- register struct kern *nkern;
- register struct pcc *npcc;
- struct adobeinfo *asucc, *asub, *api;
- struct adobeptr *kern_eq;
- int xoff, yoff, ht;
- char unlabeled;
-
- voutln2("(VTITLE Created by %s)", titlebuf);
- voutln("(COMMENT Please edit that VTITLE if you edit this file)");
- snprintf(obuffer, sizeof(obuffer), "TeX-%s%s%s%s", outname,
- (efactor==1.0? "" : "-E"), (slant==0.0? "" : "-S"),
- (makevpl==1? "" : "-CSC"));
- if (strlen(obuffer)>19) { /* too long, will retain first 9 and last 10 */
- register char *p, *q;
- for (p = &obuffer[9], q = &obuffer[strlen(obuffer)-10]; p<&obuffer[19];
- p++, q++) *p = *q;
- obuffer[19] = '\0';
- }
- voutln2("(FAMILY %s)" , obuffer);
- {
- char tbuf[300];
- const char *base_encoding =
-#ifndef VMCMS
- codingscheme;
-#else
- ebcodingscheme;
-#endif
-
- if (strcmp (outencoding->name, base_encoding) == 0) {
- snprintf(tbuf, sizeof(tbuf), "%s", outencoding->name);
- } else {
- snprintf(tbuf, sizeof(tbuf), "%s + %s", base_encoding,
- outencoding->name);
- }
-
- if (strlen(tbuf) > 39) {
- error("Coding scheme too long; shortening to 39 characters.");
- tbuf[39] = 0;
- }
- voutln2("(CODINGSCHEME %s)", tbuf);
- }
- voutln("(DESIGNSIZE R 10.0)");
- voutln("(DESIGNUNITS R 1000)");
- voutln("(COMMENT DESIGNSIZE (1 em) IS IN POINTS)");
- voutln("(COMMENT OTHER DIMENSIONS ARE MULTIPLES OF DESIGNSIZE/1000)");
- /* Let vptovf compute the checksum. */
- /* voutln2("(CHECKSUM O %lo)",cksum ^ 0xffffffff); */
- if (boundarychar >= 0)
- voutln2("(BOUNDARYCHAR O %lo)", (unsigned long)boundarychar);
- vleft(); voutln("FONTDIMEN");
- if (newslant)
- voutln2("(SLANT R %f)", newslant);
- voutln2("(SPACE D %d)", fontspace);
- if (! fixedpitch) {
- voutln2("(STRETCH D %d)", transform(200,0));
- voutln2("(SHRINK D %d)", transform(100,0));
- }
- voutln2("(XHEIGHT D %d)", xheight);
- voutln2("(QUAD D %d)", transform(1000,0));
- voutln2("(EXTRASPACE D %d)", fixedpitch ? fontspace : transform(111, 0));
- vright();
- vleft(); voutln("MAPFONT D 0");
- voutln2("(FONTNAME %s)", outname);
- /* voutln2("(FONTCHECKSUM O %lo)", (unsigned long)cksum); */
- vright();
- if (makevpl>1) {
- vleft(); voutln("MAPFONT D 1");
- voutln2("(FONTNAME %s)", outname);
- voutln2("(FONTAT D %d)", (int)(1000.0*capheight+0.5));
- /* voutln2("(FONTCHECKSUM O %lo)", (unsigned long)cksum); */
- vright();
- }
-
- for (i=0; i<256 && texptrs[i]==NULL; i++);
- bc = i;
- for (i=255; i>=0 && texptrs[i]==NULL; i--);
- ec = i;
-
- vleft(); voutln("LIGTABLE");
- ai = findadobe("||");
- unlabeled = 1;
- for (nlig=ai->ligs; nlig; nlig=nlig->next)
- if (0 != (asucc=findadobe(nlig->succ))) {
- if (0 != (asub=findadobe(nlig->sub)))
- if (asucc->texnum>=0)
- if (asub->texnum>=0) {
- if (unlabeled) {
- voutln("(LABEL BOUNDARYCHAR)");
- unlabeled = 0;
- }
- for (j = asucc->texnum; j >= 0; j = nexttex[j]) {
- voutln4("(%s %s O %o)", vplligops[nlig->op],
- vchar(j), (unsigned)asub->texnum);
- }
- }
- }
- if (! unlabeled) voutln("(STOP)");
- for (i=bc; i<=ec; i++)
- if ((ai=texptrs[i]) && ai->texnum == i) {
- unlabeled = 1;
- if (uppercase[i]==NULL) /* omit ligatures from smallcap lowercase */
- for (nlig=ai->ligs; nlig; nlig=nlig->next)
- if (0 != (asucc=findadobe(nlig->succ)))
- if (0 != (asub=findadobe(nlig->sub)))
- if (asucc->texnum>=0)
- if (asub->texnum>=0) {
- if (unlabeled) {
- for (j = ai->texnum; j >= 0; j = nexttex[j])
- voutln3("(LABEL %s)%s", vchar(j), vname(j));
- unlabeled = 0;
- }
- for (j = asucc->texnum; j >= 0; j = nexttex[j]) {
- voutln4("(%s %s O %o)", vplligops[nlig->op],
- vchar(j), (unsigned)asub->texnum);
- if (nlig->boundleft)
- break;
- }
- }
- for (nkern = (uppercase[i] ? uppercase[i]->kerns : ai->kerns);
- nkern; nkern=nkern->next)
- if (0 != (asucc=findadobe(nkern->succ)))
- for (j = asucc->texnum; j >= 0; j = nexttex[j]) {
- if (uppercase[j]==NULL) {
- if (unlabeled) {
- for (k = ai->texnum; k >= 0; k = nexttex[k])
- voutln3("(LABEL %s)%s", vchar(k), vname(k));
- unlabeled = 0;
- }
- /* If other characters have the same kerns as this
- one, output the label here. This makes the TFM
- file much smaller than if we output all the
- kerns again under a different label. */
- for (kern_eq = ai->kern_equivs; kern_eq;
- kern_eq = kern_eq->next) {
- k = kern_eq->ch->texnum;
- if (k >= 0 && k < 256)
- voutln3("(LABEL %s)%s", vchar(k), vname(k));
- }
- ai->kern_equivs = 0; /* Only output those labels once. */
- if (uppercase[i]) {
- if (lowercase[j]) {
- for (k=lowercase[j]->texnum; k >= 0; k = nexttex[k])
- voutln4("(KRN %s R %.1f)%s", vchar(k),
- capheight*nkern->delta, vname(k));
- } else voutln4("(KRN %s R %.1f)%s",
- vchar(j), capheight*nkern->delta, vname(j));
- } else {
- voutln4("(KRN %s R %d)%s", vchar(j),
- nkern->delta, vname(j));
- if (lowercase[j])
- for (k=lowercase[j]->texnum; k >= 0; k = nexttex[k])
- voutln4("(KRN %s R %.1f)%s", vchar(k),
- capheight*nkern->delta, vname(k));
- }
- }
- }
- if (! unlabeled) voutln("(STOP)");
- }
- vright();
-
- for (i=bc; i<=ec; i++)
- if (0 != (ai=texptrs[i])) {
- vleft(); fprintf(vplout, "CHARACTER %s", vchar(i));
- if (*vcharbuf=='C') {
- voutln("");
- } else
- voutln2(" (comment %s)", ai->adobename);
- if (uppercase[i]) {
- ai=uppercase[i];
- voutln2("(CHARWD R %.1f)", capheight * (ai->width));
- if (0 != (ht=texheight(ai)))
- voutln2("(CHARHT R %.1f)", capheight * ht);
- if (ai->lly)
- voutln2("(CHARDP R %.1f)", -capheight * ai->lly);
- if (ai->urx > ai->width)
- voutln2("(CHARIC R %.1f)", capheight * (ai->urx - ai->width));
- } else {
- voutln2("(CHARWD R %d)", ai->width);
- if (0 != (ht=texheight(ai)))
- voutln2("(CHARHT R %d)", ht);
- if (ai->lly)
- voutln2("(CHARDP R %d)", -ai->lly);
- if (ai->urx > ai->width)
- voutln2("(CHARIC R %d)", ai->urx - ai->width);
- }
- if (ai->adobenum != i || uppercase[i]) {
- vleft(); voutln("MAP");
- if (uppercase[i]) voutln("(SELECTFONT D 1)");
- if (ai->pccs && ai->adobenum < 0) {
- xoff = 0; yoff = 0;
- for (npcc = ai->pccs; npcc; npcc=npcc->next)
- if (0 != (api=findadobe(npcc->partname)))
- if (api->texnum>=0) {
- if (npcc->xoffset != xoff) {
- if (uppercase[i]) {
- voutln2("(MOVERIGHT R %.1f)",
- capheight * (npcc->xoffset - xoff));
- } else voutln2("(MOVERIGHT R %d)",
- npcc->xoffset - xoff);
- xoff = npcc->xoffset;
- }
- if (npcc->yoffset != yoff) {
- if (uppercase[i]) {
- voutln2("(MOVEUP R %.1f)",
- capheight * (npcc->yoffset - yoff));
- } else voutln2("(MOVEUP R %d)",
- npcc->yoffset - yoff);
- yoff = npcc->yoffset;
- }
- voutln2("(SETCHAR O %o)", (unsigned)api->adobenum);
- xoff += texptrs[api->texnum]->width;
- }
- } else voutln2("(SETCHAR O %o)", (unsigned)ai->adobenum);
- vright();
- }
- vright();
- }
- if (level) error("! I forgot to match the parentheses");
-}
-
-#ifdef KPATHSEA
-static void
-version(FILE *f)
-{
- fputs ("afm2tfm(k) (dvips(k) 2021.1) 8.4\n", f);
- fprintf (f, "%s\n", kpathsea_version_string);
- fputs ("Copyright 2021 Radical Eye Software.\n\
-There is NO warranty. You may redistribute this software\n\
-under the terms of the GNU General Public License\n\
-and the Dvips copyright.\n\
-For more information about these matters, see the files\n\
-named COPYING and afm2tfm.c.\n\
-Original author of afm2tfm: T. Rokicki.\n", f);
-}
-
-#define USAGE "\
- Convert an Adobe font metric file to TeX font metric format.\n\
-\n\
--a omit heuristic adjustment of heights for accents\n\
--c REAL use REAL for height of small caps made with -V [0.8]\n\
--e REAL widen (extend) characters by a factor of REAL\n\
--O use octal for all character codes in the vpl file\n\
--p ENCFILE read/download ENCFILE for the PostScript encoding\n\
--s REAL oblique (slant) characters by REAL, generally <<1\n\
--t ENCFILE read ENCFILE for the encoding of the vpl file\n\
--T ENCFILE equivalent to -p ENCFILE -t ENCFILE\n\
--u output only characters from encodings, nothing extra\n\
--v FILE[.vpl] make a VPL file for conversion to VF\n\
--V SCFILE[.vpl] like -v, but synthesize smallcaps as lowercase\n\
---help print this message and exit.\n\
---version print version number and exit.\n\
-"
-
-static void
-usage(FILE *f)
-{
- fputs ("Usage: afm2tfm FILE[.afm] [OPTION]... [FILE[.tfm]]\n", f);
- fputs (USAGE, f);
- putc ('\n', f);
- fputs (kpse_bug_address, f);
-}
-#else /* ! KPATHSEA */
-static void
-usage(FILE *f)
-{
- fprintf(f,
- "afm2tfm 8.1, Copyright 1990-97 by Radical Eye Software\n");
- fprintf(f,
- "Usage: afm2tfm foo[.afm] [-O] [-u] [-v|-V bar[.vpl]]\n");
- fprintf(f,
- " [-e expansion] [-s slant] [-c capheight]\n");
- fprintf(f,
- " [-p|-t|-T encodingfile] [foo[.tfm]]\n");
-}
-#endif
-
-#define CHECKARG3 if (argc < 4) { usage(stderr); exit(1); }
-
-static void
-openfiles(int argc, char **argv)
-{
-#ifndef KPATHSEA
- register int lastext;
-#else
- const char *q;
-#endif
- register int i;
- const char *p;
- int arginc;
-
- tfmout = (FILE *)NULL;
-
- if (argc == 1) {
- usage(stdout);
- exit(0);
- }
-
-#if defined(MSDOS) || defined(OS2) || defined(ATARIST)
- /* Make VPL file identical to that created under Unix */
- snprintf(titlebuf, sizeof(titlebuf), "afm2tfm %s", argv[1]);
-#else
-#ifdef VMCMS
- /* Make VPL file identical to that created under Unix */
- snprintf(titlebuf, sizeof(titlebuf), "afm2tfm %s", argv[1]);
-#else
- snprintf(titlebuf, sizeof(titlebuf), "%s %s", argv[0], argv[1]);
-#endif
-#endif
- if(strlen(argv[1]) >= MAXNAME - 4)
- error("! too long input file name");
- strcpy(inname, argv[1]);
-#ifdef KPATHSEA
- if (find_suffix(inname) == NULL)
- strcat(inname, ".afm");
-#else
- lastext = -1;
- for (i=0; inname[i]; i++)
- if (inname[i] == '.')
- lastext = i;
- else if (inname[i] == '/' || inname[i] == ':')
- lastext = -1;
- if (lastext == -1) strcat(inname, ".afm");
-#endif
- while (argc>2 && *argv[2]=='-') {
- arginc = 2;
- i = argv[2][1];
- if (i == '/')
- i = argv[2][2] - 32; /* /a ==> A for VMS */
- switch (i) {
-case 'V': makevpl++;
-case 'v': makevpl++;
- CHECKARG3
- if(strlen(argv[3]) >= MAXNAME - 4)
- error("! too long output VPL file name");
- strcpy(outname, argv[3]);
-#ifdef KPATHSEA
- if (find_suffix(outname) == NULL)
- strcat(outname, ".vpl");
-#else
- lastext = -1;
- for (i=0; outname[i]; i++)
- if (outname[i] == '.')
- lastext = i;
- else if (outname[i] == '/' || outname[i] == ':')
- lastext = -1;
- if (lastext == -1) strcat(outname, ".vpl");
-#endif
-#ifndef VMCMS
-#ifndef ATARIST
- if ((vplout=fopen(outname, WRITEBIN))==NULL)
-#else
- if ((vplout=fopen(outname, "w"))==NULL)
-#endif
-#else
- if ((vplout=fopen(outname, "w"))==NULL)
-#endif
- error("! can't open vpl output file");
- break;
-case 'a':
- noaccentheightadjust = 1;
- arginc = 1;
- break;
-case 'c':
- CHECKARG3
- if (sscanf(argv[3], "%f", &capheight)==0 || capheight<0.01)
- error("! Bad small caps height");
- break;
-case 'e': CHECKARG3
- if (sscanf(argv[3], "%f", &efactor)==0 || efactor<0.01)
- error("! Bad extension factor");
- efactorparam = argv[3];
- break;
-case 'O':
- forceoctal = 1;
- arginc = 1;
- break;
-case 'P':
-case 'p':
- CHECKARG3
- inenname = argv[3];
- break;
-case 's':
- CHECKARG3
- if (sscanf(argv[3], "%f", &slant)==0)
- error("! Bad slant parameter");
- slantparam = argv[3];
- break;
-case 'T':
- CHECKARG3
- inenname = outenname = argv[3];
- break;
-case 't':
- CHECKARG3
- outenname = argv[3];
- break;
-case 'u':
- pedantic = 1;
- arginc = 1;
- break;
-default: fprintf(stderr, "Unknown option %s %s ignored.\n", argv[2], argv[3]);
- }
- for (i=0; i<arginc; i++) {
- snprintf(titlebuf + strlen(titlebuf),
- sizeof(titlebuf) - strlen(titlebuf), " %s", argv[2]);
- argv++;
- argc--;
- }
- }
-
-#ifdef KPATHSEA
- afmin = kpse_open_file (inname, kpse_afm_format);
-#else /* ! KPATHSEA */
- if ((afmin=fopen(inname, "r"))==NULL)
- error("! can't open afm input file");
-#endif /* KPATHSEA */
- SET_BINARY(fileno(afmin));
-
- if (argc>3 || (argc==3 && *argv[2]=='-')) {
- error("! need at most two non-option arguments");
- usage(stderr);
- }
-
- if (argc == 2) strcpy(outname, inname);
- else strcpy(outname, argv[2]);
-
-#ifdef KPATHSEA
- if ((p = find_suffix(outname)) != NULL)
- outname[p-outname-1] = 0;
- strcat(outname, ".tfm");
- if (tfmout == NULL && (tfmout=fopen(outname, WRITEBIN))==NULL)
- error("! can't open tfm output file");
-/*
- * Now we strip off any directory information, so we only use the
- * base name in the vf file.
- */
- if (p == NULL)
- p = find_suffix(outname);
- outname[p-outname-1] = 0;
-
- q = xbasename(outname);
- strcpy(tmpstr, q); /* be careful, q and outname are overlapping */
- strcpy(outname, tmpstr);
-#else
- lastext = -1;
- for (i=0; outname[i]; i++)
- if (outname[i] == '.')
- lastext = i;
- else if (outname[i] == '/' || outname[i] == ':' || outname[i] == '\\')
- lastext = -1;
- if (argc == 2) {
- outname[lastext] = 0;
- lastext = -1;
- }
- if (lastext == -1) {
- lastext = strlen(outname);
- strcat(outname, ".tfm");
- }
- if (tfmout == NULL && (tfmout=fopen(outname, WRITEBIN))==NULL)
- error("! can't open tfm output file");
- outname[lastext] = 0;
-/*
- * Now we strip off any directory information, so we only use the
- * base name in the vf file. We accept any of /, :, or \ as directory
- * delimiters, so none of these are available for use inside the
- * base name; this shouldn't be a problem.
- */
- for (i=0, lastext=0; outname[i]; i++)
- if (outname[i] == '/' || outname[i] == ':' || outname[i] == '\\')
- lastext = i + 1;
- if (lastext)
- strcpy(outname, outname + lastext);
-#endif
-}
-/*
- * Some routines to remove kerns that match certain patterns.
- */
-static struct kern *
-rmkernmatch(struct kern *k, char *s)
-{
- struct kern *nkern;
-
- while (k && strcmp(k->succ, s)==0)
- k = k->next;
- if (k) {
- for (nkern = k; nkern; nkern = nkern->next)
- while (nkern->next && strcmp(nkern->next->succ, s)==0)
- nkern->next = nkern->next->next;
- }
- return k;
-}
-/*
- * Recursive to one level.
- */
-static void
-rmkern(char *s1, char *s2, struct adobeinfo *ai)
-{
- if (ai == 0) {
- if (strcmp(s1, "*") == 0) {
- for (ai=adobechars; ai; ai = ai->next)
- rmkern(s1, s2, ai);
- return;
- } else {
- ai = findadobe(s1);
- if (ai == 0)
- return;
- }
- }
- if (strcmp(s2, "*")==0)
- ai->kerns = 0; /* drop them on the floor */
- else
- ai->kerns = rmkernmatch(ai->kerns, s2);
-}
-
-/* Make the kerning for character S1 equivalent to that for S2.
- If either S1 or S2 do not exist, do nothing.
- If S1 already has kerning, do nothing. */
-static void
-addkern(char *s1, char *s2)
-{
- struct adobeinfo *ai1 = findadobe (s1);
- struct adobeinfo *ai2 = findadobe (s2);
- if (ai1 && ai2 && !ai1->kerns) {
- /* Put the new one at the head of the list, since order is immaterial. */
- struct adobeptr *ap
- = (struct adobeptr *) mymalloc((unsigned long)sizeof(struct adobeptr));
- ap->next = ai2->kern_equivs;
- ap->ch = ai1;
- ai2->kern_equivs = ap;
- }
-}
-int sawligkern;
-/*
- * Reads a ligkern line, if this is one. Assumes the first character
- * passed is `%'.
- */
-static void
-checkligkern(char *s)
-{
- char *oparam = param;
- char *mlist[5];
- int n;
-
- s++;
- while (*s && *s <= ' ')
- s++;
- if (strncmp(s, "LIGKERN", 7)==0) {
- sawligkern = 1;
- s += 7;
- while (*s && *s <= ' ')
- s++;
- param = s;
- while (*param) {
- for (n=0; n<5;) {
- if (*param == 0)
- break;
- mlist[n] = paramstring();
- if (strcmp(mlist[n], ";") == 0)
- break;
- n++;
- }
- if (n > 4)
- error("! too many parameters in lig kern data");
- if (n < 3)
- error("! too few parameters in lig kern data");
- if (n == 3 && strcmp(mlist[1], "{}") == 0) { /* rmkern command */
- rmkern(mlist[0], mlist[2], (struct adobeinfo *)0);
- } else if (n == 3 && strcmp(mlist[1], "<>") == 0) { /* addkern */
- addkern(mlist[0], mlist[2]);
- } else if (n == 3 && strcmp(mlist[0], "||") == 0 &&
- strcmp(mlist[1], "=") == 0) { /* bc command */
- struct adobeinfo *ai = findadobe("||");
-
- if (boundarychar != -1)
- error("! multiple boundary character commands?");
- if (sscanf(mlist[2], "%d", &n) != 1)
- error("! expected number assignment for boundary char");
- if (n < 0 || n > 255)
- error("! boundary character number must be 0..255");
- boundarychar = n;
- if (ai == 0)
- error("! internal error: boundary char");
- ai->texnum = n; /* prime the pump, so to speak, for lig/kerns */
- } else if (n == 4) {
- int op = -1;
- struct adobeinfo *ai;
-
- for (n=0; encligops[n]; n++)
- if (strcmp(mlist[2], encligops[n])==0) {
- op = n;
- break;
- }
- if (op < 0)
- error("! bad ligature op specified");
- if (0 != (ai = findadobe(mlist[0]))) {
- struct lig *lig;
-
- if (findadobe(mlist[2])) /* remove coincident kerns */
- rmkern(mlist[0], mlist[1], ai);
- if (strcmp(mlist[3], "||") == 0)
- error("! you can't lig to the boundary character!");
- if (! fixedpitch) { /* fixed pitch fonts get *0* ligs */
- for (lig=ai->ligs; lig; lig = lig->next)
- if (strcmp(lig->succ, mlist[1]) == 0)
- break; /* we'll re-use this structure */
- if (lig == 0) {
- lig = newlig();
- lig->succ = newstring(mlist[1]);
- lig->next = ai->ligs;
- ai->ligs = lig;
- }
- lig->sub = newstring(mlist[3]);
- lig->op = op;
- if (strcmp(mlist[1], "||")==0) {
- lig->boundleft = 1;
- if (strcmp(mlist[0], "||")==0)
- error("! you can't lig boundarychar boundarychar!");
- } else
- lig->boundleft = 0;
- }
- }
- } else
- error("! bad form in LIGKERN command");
- }
- }
- param = oparam;
-}
-/*
- * Here we get a token from the AFM file. We parse just as much PostScript
- * as we expect to find in an encoding file. We allow commented lines and
- * names like 0, .notdef, _foo_. We do not allow //abc.
- */
-char smbuffer[100]; /* for tokens */
-static char *
-gettoken(void) {
- char *p, *q;
-
- while (1) {
- while (param == 0 || *param == 0) {
- if (texlive_getline() == 0)
- error("! premature end in encoding file");
- for (p=buffer; *p; p++)
- if (*p == '%') {
- if (ignoreligkern == 0)
- checkligkern(p);
- *p = 0;
- break;
- }
- }
- while (*param && *param <= ' ')
- param++;
- if (*param) {
- if (*param == '[' || *param == ']' ||
- *param == '{' || *param == '}') {
- smbuffer[0] = *param++;
- smbuffer[1] = 0;
- return smbuffer;
- } else if (*param == '/' || *param == '-' || *param == '_' ||
- *param == '.' ||
- ('0' <= *param && *param <= '9') ||
- ('a' <= *param && *param <= 'z') ||
- ('A' <= *param && *param <= 'Z')) {
- smbuffer[0] = *param;
- for (p=param+1, q=smbuffer+1;
- *p == '-' || *p == '_' || *p == '.' ||
- ('0' <= *p && *p <= '9') ||
- ('a' <= *p && *p <= 'z') ||
- ('A' <= *p && *p <= 'Z'); p++, q++)
- *q = *p;
- *q = 0;
- param = p;
- return smbuffer;
- }
- }
- }
-}
-static void
-getligkerndefaults(void) {
- int i;
-
- for (i=0; staticligkern[i]; i++) {
- strcpy(buffer, staticligkern[i]);
- strcpy(obuffer, staticligkern[i]);
- param = buffer;
- checkligkern(buffer);
- }
-}
-/*
- * This routine reads in an encoding file, given the name. It returns
- * the final total structure. It performs a number of consistency checks.
- */
-static struct encoding *
-readencoding(char *enc)
-{
- char *p;
- int i;
- struct encoding *e =
- (struct encoding *)mymalloc((unsigned long)sizeof(struct encoding));
-
- sawligkern = 0;
- if (afmin)
- error("! oops; internal afmin error");
- if (enc) {
-#ifdef KPATHSEA
- afmin = kpse_open_file(enc, kpse_enc_format);
-#else
- afmin = fopen(enc, "r");
-#endif
- SET_BINARY(fileno(afmin));
- param = 0;
- if (afmin == 0)
-#ifdef KPATHSEA
- FATAL1 ("couldn't open encoding file `%s'", enc);
-#else
- error("! couldn't open that encoding file");
-#endif
- p = gettoken();
- if (*p != '/' || p[1] == 0)
- error("! first token in encoding must be literal encoding name");
- e->name = newstring(p+1);
- p = gettoken();
- if (strcmp(p, "["))
- error("! second token in encoding must be mark ([) token");
- for (i=0; i<256; i++) {
- p = gettoken();
- if (*p != '/' || p[1] == 0)
- error("! tokens 3 to 257 in encoding must be literal names");
- e->vec[i] = newstring(p+1);
- }
- p = gettoken();
- if (strcmp(p, "]"))
- error("! token 258 in encoding must be make-array (])");
- while (texlive_getline()) {
- for (p=buffer; *p; p++)
- if (*p == '%') {
- if (ignoreligkern == 0)
- checkligkern(p);
- *p = 0;
- break;
- }
- }
- fclose(afmin);
- afmin = 0;
- if (ignoreligkern == 0 && sawligkern == 0)
- getligkerndefaults();
- } else {
- e = &staticencoding;
- getligkerndefaults();
- }
- param = 0;
- return e;
-}
-/*
- * This routine prints out the line that needs to be added to psfonts.map.
- */
-static void
-conspsfonts(void) {
-#ifndef VMCMS
- printf("%s %s", outname,
- fontname);
-#else /* VM/CMS: fontname is ascii, so we use ebfontname */
- printf("%s %s", outname,
- ebfontname);
-#endif
- if (slantparam || efactorparam || inenname) {
- printf(" \"");
- if (slantparam)
- printf(" %s SlantFont", slantparam);
- if (efactorparam)
- printf(" %s ExtendFont", efactorparam);
- if (inenname)
- printf(" %s ReEncodeFont", inencoding->name);
- printf(" \"");
- if (inenname)
- printf(" <%s", inenname);
- }
- printf("\n");
-}
-#ifndef VMS
-int
-#endif
-main(int argc, char **argv)
-{
- int i;
-
-#ifdef KPATHSEA
- kpse_set_program_name (argv[0], "afm2tfm");
-
- if (argc == 1) {
- fputs ("afm2tfm: Need at least one file argument.\n", stderr);
- fputs ("Try `afm2tfm --help' for more information.\n", stderr);
- exit(1);
- }
- if (argc == 2) {
- if (strcmp (argv[1], "--help") == 0) {
- usage (stdout);
- exit (0);
- } else if (strcmp (argv[1], "--version") == 0) {
- version (stdout);
- exit (0);
- }
- }
-#endif /* KPATHSEA */
- for (i=0; i<256; i++)
- nexttex[i] = -1; /* encoding chains have length 0 */
- tfmdata = (long *)mymalloc((unsigned long)40000L);
- openfiles(argc, argv);
- readadobe();
- if (fontspace == 0) {
- struct adobeinfo *ai;
-
- if (0 != (ai = findadobe("space")))
- fontspace = ai->width;
- else if (adobeptrs[32])
- fontspace = adobeptrs[32]->width;
- else
- fontspace = transform(500, 0);
- }
- handlereencoding();
- buildtfm();
- writetfm();
- conspsfonts();
- if (makevpl) {
- assignchars();
- if (makevpl>1) upmap();
- writevpl();
- }
- return 0;
- /*NOTREACHED*/
-}
-