[comp.fonts] Format of Postscript type 1 fonts

john@gna.axis-design.fr (John Hughes) (05/17/91)

I have some PostScript type 1 fonts from a Mac and I would like to try using
them with GhostScript.  Unfortunatly GhostScript only understands the eexec
section in hex format but the fonts I have have a binary eexec section.  I 
have tried bashing it into hex in various dumb ways but I can't get anything
to work.  (E.g. the recently posted pfb2pf program doesn't work, the Mac fonts
don't have those "ascii section"/"binary section" markers).

Anybody have any clues?

rsm@math.arizona.edu (Robert S. Maier) (05/18/91)

In article <1991May17.155109.15604@gna.axis-design.fr> John Hughes writes:

>I have some PostScript type 1 fonts from a Mac and I would like to try
>using them with GhostScript.  Unfortunatly GhostScript only
>understands the eexec section in hex format but the fonts I have have
>a binary eexec section.  I have tried bashing it into hex in various
>dumb ways but I can't get anything to work.  (E.g. the recently posted
>pfb2pf program doesn't work, the Mac fonts don't have those "ascii
>section"/"binary section" markers).

The following program, though quick-and-dirty, may be useful.  I have
used it to decrypt Mac-style Type 1 fonts from such FTP servers as
mac.archive.umich.edu and sumex-aim.stanford.edu.  It hasn't choked on
anything yet.

It translates a Mac Type 1 font (stored in POST resources) to a decent
Unix-format ASCII file (\n instead of \r, no binary eexec section).  The
result can be used with such utilities as dvips.

-- 
Robert S. Maier   | Internet: rsm@math.arizona.edu, rsm@cs.arizona.edu
Dept. of Math.    | UUCP: uunet!arizona!amethyst!rsm
Univ. of Arizona  | Bitnet: maier@arizrvax
Tucson, AZ  85721 | FAX: +1 602 621 8322
U.S.A.            | Voice(POTS): +1 602 621 6893  /  +1 602 621 2617

======================================================================


/*
 * unresource.c -- translate Adobe's `Mac-format Type 1 fonts' 
 *			to decent ASCII PostScript, for Unix.
 *
 *		   Written by Robert S. Maier, rsm@math.arizona.edu
 *
 *                 Reads from stdin, writes to stdout.
 *
 *		   Should run on any big-endian machine with
 *		           32-bit long int's.
 *
 * For information on the font format, see Adobe's TR #5040,
 * "Supporting Downloadable PostScript Fonts".  
 * Available from the Adobe fileserver.
 *
 */

#include <stdio.h>

#define R_OFFSET	0x100	/* ignore initial R_OFFSET bytes of file */

#define RES_COMMENT	0	/* ignored */
#define RES_ASCII 	1	/* passed through */
#define RES_BINARY 	2	/* turned into decent hexadecimal */
#define RES_EOFILE  	3	/* should become a ^D?  I'm uncertain. */
#define RES_FOO		4	/* remainder of type 1 font in data fork */
#define RES_EOF		5

#define EEXEC_LINE_LEN	32	/* >=4.  Half of length of ASCII hex eexec lines */

#define NYB0(c)	    hex[((c) & 0x0f)]   /* cut nybbles out of a byte */
#define NYB1(c)	    NYB0((c) >> 4)
char hex[] = "0123456789ABCDEF";

#define min(a,b) ((a) < (b) ? (a) : (b))

#define TRUE 1
#define FALSE 0

void
main()
{
  
    unsigned char in_buff[BUFSIZ], out_buff[3*BUFSIZ]; 
				/* 3 not 2; make room for \n's */
    unsigned long len, in_size, i, o, bincount;
    unsigned char type = RES_COMMENT, prev_type;
			/* keep track of immy previous resource type too */  

    if (fseek(stdin, R_OFFSET, 0)<0) { /* discard initial 0x100 bytes */
	fprintf(stderr, "Premature EOF\n");
	exit(1);
    }

    while (TRUE) {		/* main resource-reading loop */
	
	prev_type = type;

				/* assume big-endian... */
	if (fread(&len, sizeof(unsigned long), 1, stdin)<0) {
	    fprintf(stderr, "Premature EOF in size field\n");
	    exit(1);
	}

	if (len > 0) {

	    if (fread(&type, 1, 1, stdin)<0) {
		fprintf(stderr, "Premature EOF, no type field\n");
		exit(1);
	    }
#ifdef DEBUG
	    fprintf(stderr, "Resource type = %d,\t len = %d\n", type, len);
#endif
	    len--;
	}
	else {
#ifdef DEBUG
	    fprintf(stderr, "Resource type = NONE,\t len = 0\n");
#endif
	    continue;		/* go to top of resource loop */
	}
	    
	if (type == RES_EOF)
	    break;			/* exit from resource loop */

	switch(type) {
	    
	case RES_COMMENT:
	    if (fseek (stdin, len, 1) < 0) {
		fprintf(stderr, "Premature EOF\n");
		exit(1);
	    }
	    continue;		/* go to top of resource loop */

	case RES_ASCII: 
	    if (fseek(stdin, 1, 1)<0) {
		fprintf(stderr, "Premature EOF, can't skip null byte\n");
		exit(1);
	    }
	    else
		len--;

	    while (TRUE) {
		len -= (in_size = min(len, BUFSIZ));
		if (in_size) {
		    if (fread(in_buff, 1, in_size, stdin) < 0) {
			fprintf(stderr, "Premature EOF in ASCII seg\n");
			exit(1);
		    }
		    for (i = 0; i < in_size; i++) /* CR -> LF */
			if (in_buff[i] == '\r')
			    in_buff[i] = '\n';
		    if (fwrite(in_buff, 1, in_size, stdout) < 0) {
			fprintf(stderr, "Problem writing stdout\n");
			exit(1);
		    }
		}
		else
		    break;		/* end of this resource */
	    }
	    continue;			/* go to top of resource loop */

	case RES_EOFILE:
	    fprintf (stderr, \
		     "End-of-file resource encountered.  Unsure how to deal with it.\n");
	    exit(1);
	    
	case RES_FOO:
	    fprintf (stderr, \
		     "Remaining portion of font is in data fork.\n");
	    exit(1);

	case RES_BINARY:
	    if (prev_type != RES_BINARY)
		bincount = 1;	/* we weren't in a binary resource, so reset */

	    if (fseek(stdin, 1, 1)<0) {
		fprintf(stderr, "Premature EOF, can't skip null byte\n");
		exit(1);
	    }
	    else
		len--;

	    while (TRUE) {
		len -= (in_size = min(len, BUFSIZ));
		if (in_size) {
		    if (fread(in_buff, 1, in_size, stdin) < 0) {
			fprintf(stderr, "Premature EOF in binary seg\n");
			exit(1);
		    }
		    i = o = 0;
		    while (i < in_size) {
			out_buff[o++] = NYB1(in_buff[i]);
			out_buff[o++] = NYB0(in_buff[i++]);
			if (((bincount++) % EEXEC_LINE_LEN) == 0)
			    out_buff[o++] = '\n'; /* break lines regularly */
		    }
		    if (fwrite(out_buff, 1, o, stdout) < 0) {
			fprintf(stderr, "Problem writing stdout\n");
			exit(1);
		    }
		}
		else
		    break;		/* end of this resource */
	    }
	    continue;			/* go to top of resource loop */

	default:		/* can't handle, so just punt */
	    fseek (stdin, len, 1); 
	    continue;		/* go to top of resource loop */

    }				/* end of switch{} */
    
  }				/* end of resource loop */

  exit(0);
}