mark@monitor.plymouth.mi.us (Mark Harris) (07/26/90)
The following program converts Type 1 fonts from Mac format to NeXT
format. Type 3 fonts that are sent to the NeXT as text files, along
with their corresponding .afm file, should work fine without conversion.
#!/bin/sh
#
# This shell archive contains the following files:
# README
# Makefile
# mfrc.h
# mfrc.c
#
# To extract, remove all lines before the '#!/bin/sh' line and after
# the 'exit' line, and run the resulting file through sh.
#
echo x - README 1>&2
sed 's/.//' >README <<'*-*-END-of-README-*-*'
- "Can I use Adobe postscript fonts I purchased for the
- Mac and port them over to the cube, and if so, how?
-
- The answer to this question is, in practice, no."
- -- NeXT Answers, Apr '90
-
-But now you can, very easily with this program!
-
-Entitled "mfrc", for Macintosh Font Resource Converter, it takes
-Type 1 PostScript fonts and produces a version usable by the NeXT.
-(The fonts must have the accompanying AFM [Adobe Font Metric] file
-for it to be recognized by the cube.)
-
-The font can be transferred from the Macintosh to the NeXT by
-whatever means available; "mfrc" understands the MacBinary format.
-The quickest way to install a font from the Mac is to transfer the
-printer-downloadable version of the font (Macintosh file type
-'LWFN') and the AFM file (type 'TEXT') in MacBinary format. After
-the transfer, running "mfrc" will convert the downloadable font to
-a standard PostScript font format, and strip the MacBinary header
-off the AFM file.
-
-"mfrc" will also accept files that have been previously converted
-using 'mcvert' or other similar Macintosh file-conversion utilities.
-The AFM file is not required to be present for "mfrc" to run; if
-it is not found, only the font is converted. No messages or
-warnings about missing AFM files are given.
-
-A sample conversion run might look like this:
-
- # mkdirs /LocalLibrary/Fonts/{afm,outline}
-
- % mfrc foo* bar
- foo: converted to Foo-Roman.
- foo.afm: File not type LWFN.
- foodem: converted to Foo-Demi.
- foodem.afm: File not type LWFN.
- foodemita: converted to Foo-DemiItalic.
- foodemita.afm: File not type LWFN.
- foohea: converted to Foo-Heavy.
- foohea.afm: File not type LWFN.
- fooheaita: converted to Foo-HeavyItalic.
- fooheaita.afm: File not type LWFN.
- fooita: converted to Foo-Italic.
- fooita.afm: File not type LWFN.
- bar: converted to Bar-Medium.
- % mv [A-Z]*.afm /LocalLibrary/Fonts/afm
- % mv [A-Z]* /LocalLibrary/Fonts/outline
- % buildafmdir /LocalLibrary/Fonts
-
-
-"mfrc" Specifics:
-Create /LocalLibrary/Fonts if it does not exist. If you are not
-the administrator of your NeXT, you can create ~/Fonts, and install
-them there instead.
-
-PostScript font names are automatically extracted from the first
-POST text-resource block. If a font name definition is not found
-(i.e., a /FontName definition), the existing filename, appended
-with '.psf' is used. You should determine the correct PostScript
-name and rename any '.psf' files before installing them.
-
-If the file contains a MacBinary header, "mfrc" will only convert
-it if the type is 'LWFN'. If the MacBinary header has been stripped
-by another utility, "mfrc" will check for POST resources, and will
-give an error if none are found.
-
-The cube will not recognize any fonts until after the 'buildafmdir'
-command has been run. "The 'buildafmdir' utility lets the AppKit
-know that the fonts in that directory have changes, so that Font
-Panels will show the new font right away." (from the NeXT Manual)
-
-
-"mfrc" Information:
-Program written by Mark Harris -- Documentation by Eddy J. Gurney
-<mark@monitor.plymouth.mi.us> <eddy@jafus.mi.org>
- Aim your flamethrowers this way,
- not at Mark! (I'm taking the heat)
-
-"mfrc" is Copyright 1990 by Mark Harris. The program may be
-distributed without charge provided this notice and accompanying
-documentation is included. No warranties are expressed or implied.
*-*-END-of-README-*-*
echo x - Makefile 1>&2
sed 's/.//' >Makefile <<'*-*-END-of-Makefile-*-*'
-# simple mfrc makefile
-
-LIBS=-lsys_s
-CFLAGS=-O -s
-
-mfrc: mfrc.c mfrc.h
- $(CC) $(CFLAGS) -o $@ $*.c $(LIBS)
-
-install: mfrc
- chown root.wheel mfrc
- chmod 755 mfrc
- mv mfrc /usr/local/bin
*-*-END-of-Makefile-*-*
echo x - mfrc.h 1>&2
sed 's/.//' >mfrc.h <<'*-*-END-of-mfrc.h-*-*'
-typedef unsigned char byte;
-typedef unsigned short word;
-typedef unsigned long ulong;
-
-#define POST_TYPE (('P'<<24)+('O'<<16)+('S'<<8)+'T')
-
-/* Format of a bin file: (From mcvert by Doug Moore)
-A bin file is composed of 128 byte blocks. The first block is the
-info_header (see below). Then comes the data fork, null padded to fill the
-last block. Then comes the resource fork, padded to fill the last block. A
-proposal to follow with the text of the Get Info box has not been implemented,
-to the best of my knowledge. Version, zero1 and zero2 are what the receiving
-program looks at to determine if a MacBinary transfer is being initiated.
-*/
-typedef struct { /* info file header (128 bytes). Unfortunately, these
- longs don't align to word boundaries */
- byte version; /* there is only a version 0 at this time */
- byte nlen; /* Length of filename. */
- byte name[63]; /* Filename (only 1st nlen are significant)*/
- byte type[4]; /* File type. */
- byte auth[4]; /* File creator. */
- byte flags; /* file flags: LkIvBnSyBzByChIt */
- byte zero1; /* Locked, Invisible,Bundle, System */
- /* Bozo, Busy, Changed, Init */
- byte icon_vert[2]; /* Vertical icon position within window */
- byte icon_horiz[2]; /* Horizontal icon postion in window */
- byte window_id[2]; /* Window or folder ID. */
- byte protect; /* = 1 for protected file, 0 otherwise */
- byte zero2;
- byte dlen[4]; /* Data Fork length (bytes) - most sig. */
- byte rlen[4]; /* Resource Fork length byte first */
- byte ctim[4]; /* File's creation date. */
- byte mtim[4]; /* File's "last modified" date. */
- byte ilen[2]; /* GetInfo message length */
- byte flags2; /* Finder flags, bits 0-7 */
- byte unused[14];
- byte packlen[4]; /* length of total files when unpacked */
- byte headlen[2]; /* length of secondary header */
- byte uploadvers; /* Version of MacBinary II that the uploading program is written for */
- byte readvers; /* Minimum MacBinary II version needed to read this file */
- byte crc[2]; /* CRC of the previous 124 bytes */
- byte padding[2]; /* two trailing unused bytes */
- } info_header;
-
-typedef struct {
- long rtype;
- short nrsc;
- short offset;
- } type_info;
-
-typedef struct {
- short id;
- short name;
- long offset;
- long reserved;
- } ref_list;
-
-#define POST_TEXT 1
-#define POST_DATA 2
-#define POST_END 5
*-*-END-of-mfrc.h-*-*
echo x - mfrc.c 1>&2
sed 's/.//' >mfrc.c <<'*-*-END-of-mfrc.c-*-*'
-#include <stdio.h>
-#include <sys/types.h>
-#include <strings.h>
-#include <ctype.h>
-#include <stdlib.h>
-
-#include "mfrc.h"
-
-int cmpid(rl1,rl2)
-ref_list *rl1, *rl2;
-{
- return rl1->id - rl2->id;
-}
-
-int main(argc,argv)
-int argc;
-char **argv;
-{
- char *progname;
- FILE *fp, *of;
- info_header infobuf;
- type_info typbuf;
- ref_list *rfptr, *rfent;
- unsigned char *pdata, *cp, *cp2;
- char onm[BUFSIZ], anm[BUFSIZ];
- unsigned long rsrc,rsd,rsm;
- long rslen;
- unsigned short rstl;
- short rstypes;
- int c,len;
-
- progname = argv[0];
- if (argc < 2) {
- fprintf(stderr, "Usage: %s file ...\n", progname);
- exit(1);
- }
-
- while (--argc) {
- ++argv;
- fp = fopen(*argv,"r");
- if (fp == NULL) {
- perror(*argv);
- continue;
- }
-
- fprintf(stderr,"%s: ",*argv);
- if (fread(&infobuf,sizeof(info_header),1,fp) < 1 ) {
- fclose(fp);
- fprintf(stderr,"No header\n");
- continue;
- }
-
- if (infobuf.version || infobuf.nlen) {
- rsrc = sizeof(info_header) + (infobuf.dlen[0]<<24) +
- (infobuf.dlen[1]<<16) + (infobuf.dlen[2]<<8) +
- infobuf.dlen[3];
-
- if ((infobuf.type[0]!='L') || (infobuf.type[1]!='W')
- || (infobuf.type[2]!='F')
- || (infobuf.type[3]!='N')) {
- fclose(fp);
- fprintf(stderr,"File not type LWFN.\n");
- continue;
- }
-
- if (rsrc > sizeof(info_header))
- fseek(fp,rsrc,SEEK_SET);
- }
- else rsrc = 0;
-
- fread(&rsd,4,1,fp);
- fread(&rsm,4,1,fp);
- fseek(fp,rsrc+rsm+24,SEEK_SET);
- fread(&rstl,2,1,fp);
- fseek(fp,rsrc+rsm+rstl,SEEK_SET);
- fread(&rstypes,2,1,fp);
-
- while (rstypes >= 0) {
- fread(&typbuf,sizeof(typbuf),1,fp);
- if (typbuf.rtype == POST_TYPE)
- break;
- --rstypes;
- }
-
- if (rstypes < 0) {
- fclose(fp);
- fprintf(stderr,"No POST resources.\n");
- continue;
- }
-
- /* Read list of POST resources and sort by resource ID */
- fseek(fp,rsrc+rsm+rstl+typbuf.offset,SEEK_SET);
- rfptr = (ref_list *)malloc(sizeof(ref_list) * (typbuf.nrsc+1));
- fread(rfptr,sizeof(ref_list),typbuf.nrsc+1,fp);
- qsort(rfptr,typbuf.nrsc+1,sizeof(ref_list),cmpid);
-
- /* Process POST resources */
- of=NULL;
- onm[0] = '\0';
- rfent = rfptr;
- len=0;
- while (typbuf.nrsc-- >= 0) {
- fseek(fp,rsrc+rsd+(rfent->offset & 0xffffff),SEEK_SET);
- fread(&rslen,4,1,fp);
- pdata = (unsigned char *)malloc(rslen);
- fread(pdata,rslen,1,fp);
- switch (pdata[0]) {
- case POST_TEXT:
- if (!of) {
- cp=pdata+2;
- while (cp < pdata+rslen) {
- if (*cp == '/') {
- if (!strncmp((char *)cp,"/FontName",9)) {
- cp += 9;
- if (isspace(*cp)) {
- while (*cp++ != '/');
- cp2=(unsigned char *)onm;
- while (!isspace((char)*cp))
- *cp2++ = *cp++;
- *cp2 = '\0';
- break;
- }
- }
- }
- cp++;
- }
- if (!onm[0])
- sprintf(onm,"%s.psf",*argv);
- of=fopen(onm,"w");
- if (!of) {
- perror(onm);
- free(pdata);
- fprintf(stderr,"%s: ",*argv);
- continue;
- }
- }
- cp=pdata+2;
- while (cp < pdata+rslen) {
- if (*cp == '\r')
- *cp='\n';
- cp++;
- }
- if (len) {
- fprintf(of,"\n");
- len=0;
- }
- fwrite(pdata+2,rslen-2,1,of);
- break;
- case POST_DATA:
- if (!of) {
- fprintf(stderr, "Data before text.\n");
- free(pdata);
- fprintf(stderr,"%s: ",*argv);
- continue;
- }
- cp=pdata+2;
- while (cp < pdata+rslen) {
- fprintf(of,"%02x",*cp++);
- if (++len > 31) {
- fprintf(of,"\n");
- len = 0;
- }
- }
- break;
- case POST_END:
- break;
- default:
- fprintf(stderr, "Unknown POST resource type %d.\n",
- pdata[0]);
- } /* end switch */
- free(pdata);
- ++rfent;
- } /* while more POST resources */
- if (len)
- fprintf(of,"\n");
- fclose(of);
- fclose(fp);
- free(rfptr);
-
- /* check for afm file */
- if (!onm[0]) {
- fprintf(stderr,"no font data.\n");
- continue;
- }
- fprintf(stderr,"converted to %s.\n",onm);
- strcpy(anm,*argv);
- strcat(anm,".afm");
- fp=fopen(anm,"r");
- if (!fp)
- continue;
-
- if (fread(&infobuf,sizeof(info_header),1,fp) < 1) {
- fclose(fp);
- continue;
- }
-
- if (infobuf.version || infobuf.nlen) {
- rslen = (infobuf.dlen[0]<<24) + (infobuf.dlen[1]<<16)
- + (infobuf.dlen[2]<<8) + infobuf.dlen[3];
- if (rslen < 1) {
- fclose(fp);
- continue;
- }
- }
- else rslen=0;
-
- strcat(onm,".afm");
- of=fopen(onm,"w");
- if (!of) {
- fclose(fp);
- continue;
- }
- do {
- c=getc(fp);
- if (c=='\r')
- putc('\n',of);
- else
- putc(c,of);
- } while (--rslen);
- fclose(of);
- fclose(fp);
- } /* while more files */
-
- return 0;
-} /* end main */
*-*-END-of-mfrc.c-*-*
exit