summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorge Williams <gww@silcom.com>2004-05-28 02:47:55 +0000
committerGeorge Williams <gww@silcom.com>2004-05-28 02:47:55 +0000
commit44d1fe300a104abb076897cc4d61e25ab22a66af (patch)
treedff7929110b44406297fa663d879b2a95d284027
parent2bb9ad2eb10060d99f20376640324e38e1bada13 (diff)
Real support for afm output.
Ability to find a post resource file given the FOND. A couple of extra options to fondu.
-rw-r--r--Makefile.Mac14
-rw-r--r--Makefile.in14
-rw-r--r--Makefile.unix14
-rw-r--r--fondu.120
-rw-r--r--fondu.c495
-rw-r--r--fondups.c3075
-rw-r--r--macfonts.h22
-rw-r--r--psfont.h192
-rw-r--r--showfond.c3
9 files changed, 3692 insertions, 157 deletions
diff --git a/Makefile.Mac b/Makefile.Mac
index ed9713f..41120c1 100644
--- a/Makefile.Mac
+++ b/Makefile.Mac
@@ -5,22 +5,23 @@ CC = cc
# #include, #if, etc.
WFLAGS = -Wmissing-prototypes -Wunused -Wimplicit -Wreturn-type -Wparentheses
CFLAGS = -g $(WFLAGS) -D__Mac -I/Developer/Headers/FlatCarbon/
-FONDUOBJS = fondu.o readnfnt.o
+FONDUOBJS = fondu.o readnfnt.o fondups.o
UFONDOBJS = ufond.o ufondbdf.o ufondpfb.o ufondttf.o crctab.o
DFONT2RESOBJS = dfont2res.o crctab.o
SHOWOBJS = showfond.o
TOBINOBJS = tomacbinary.o crctab.o
FROMBINOBJS = frommacbinary.o
LUMPEROBJS = lumper.o
+SETFONDNAMEOBJS = setfondname.o
#CORE = /System/Library/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/CarbonCore
CORE = /System/Library/Frameworks/CoreServices.framework/CoreServices
bindir = /usr/local/bin
-all: fondu ufond showfond dfont2res tobin frombin lumper
+all: fondu ufond showfond dfont2res tobin frombin lumper setfondname
fondu: $(FONDUOBJS)
- $(CC) $(CFLAGS) -o fondu $(FONDUOBJS) $(CORE)
+ $(CC) $(CFLAGS) -o fondu $(FONDUOBJS) -lm $(CORE)
ufond: $(UFONDOBJS)
$(CC) $(CFLAGS) -o ufond $(UFONDOBJS)
@@ -40,11 +41,14 @@ frombin: $(FROMBINOBJS)
lumper: $(LUMPEROBJS)
$(CC) $(CFLAGS) -o lumper $(LUMPEROBJS)
+setfondname: $(SETFONDNAMEOBJS)
+ $(CC) $(CFLAGS) -o setfondname $(SETFONDNAMEOBJS)
+
clean:
- -rm -f *.o fondu ufond showfond dfont2res tobin frombin lumper
+ -rm -f *.o fondu ufond showfond dfont2res tobin frombin lumper setfondname
distclean: clean
-rm Makefile
install: all
- cp fondu ufond showfond dfont2res tobin frombin lumper $(bindir)
+ cp fondu ufond showfond dfont2res tobin frombin lumper setfondname $(bindir)
diff --git a/Makefile.in b/Makefile.in
index f0dbf33..802295b 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -6,18 +6,19 @@ CC = @CC@
WFLAGS = -Wmissing-prototypes -Wunused -Wimplicit -Wreturn-type -Wparentheses -pedantic
CFLAGS = -g $(WFLAGS)
-FONDUOBJS = fondu.o readnfnt.o
+FONDUOBJS = fondu.o readnfnt.o fondups.o
UFONDOBJS = ufond.o ufondbdf.o ufondpfb.o ufondttf.o crctab.o
DFONT2RESOBJS = dfont2res.o crctab.o
SHOWOBJS = showfond.o
TOBINOBJS = tomacbinary.o crctab.o
FROMBINOBJS = frommacbinary.o
LUMPEROBJS = lumper.o
+SETFONDNAMEOBJS = setfondname.o
-all: fondu ufond showfond dfont2res tobin frombin lumper
+all: fondu ufond showfond dfont2res tobin frombin lumper setfondname
fondu: $(FONDUOBJS)
- $(CC) $(CFLAGS) -o fondu $(FONDUOBJS)
+ $(CC) $(CFLAGS) -o fondu $(FONDUOBJS) -lm
ufond: $(UFONDOBJS)
$(CC) $(CFLAGS) -o ufond $(UFONDOBJS)
@@ -37,11 +38,14 @@ frombin: $(FROMBINOBJS)
lumper: $(LUMPEROBJS)
$(CC) $(CFLAGS) -o lumper $(LUMPEROBJS)
+setfondname: $(SETFONDNAMEOBJS)
+ $(CC) $(CFLAGS) -o setfondname $(SETFONDNAMEOBJS)
+
clean:
- -rm -f *.o fondu ufond showfond dfont2res tobin frombin lumper
+ -rm -f *.o fondu ufond showfond dfont2res tobin frombin lumper setfondname
distclean: clean
-rm Makefile
install: all
- cp fondu ufond showfond dfont2res tobin frombin lumper $(bindir)
+ cp fondu ufond showfond dfont2res tobin frombin lumper setfondname $(bindir)
diff --git a/Makefile.unix b/Makefile.unix
index 83a70b3..ffbfb25 100644
--- a/Makefile.unix
+++ b/Makefile.unix
@@ -1,20 +1,21 @@
CC = gcc
WFLAGS = -Wmissing-prototypes -Wunused -Wimplicit -Wreturn-type -Wparentheses -pedantic
CFLAGS = -g $(WFLAGS)
-FONDUOBJS = fondu.o readnfnt.o
+FONDUOBJS = fondu.o readnfnt.o fondups.o
UFONDOBJS = ufond.o ufondbdf.o ufondpfb.o ufondttf.o crctab.o
DFONT2RESOBJS = dfont2res.o crctab.o
SHOWOBJS = showfond.o
TOBINOBJS = tomacbinary.o crctab.o
FROMBINOBJS = frommacbinary.o
LUMPEROBJS = lumper.o
+SETFONDNAMEOBJS = setfondname.o
bindir = /usr/local/bin
-all: fondu ufond showfond dfont2res tobin frombin lumper
+all: fondu ufond showfond dfont2res tobin frombin lumper setfondname
fondu: $(FONDUOBJS)
- $(CC) $(CFLAGS) -o fondu $(FONDUOBJS)
+ $(CC) $(CFLAGS) -o fondu $(FONDUOBJS) -lm
ufond: $(UFONDOBJS)
$(CC) $(CFLAGS) -o ufond $(UFONDOBJS)
@@ -34,11 +35,14 @@ frombin: $(FROMBINOBJS)
lumper: $(LUMPEROBJS)
$(CC) $(CFLAGS) -o lumper $(LUMPEROBJS)
+setfondname: $(SETFONDNAMEOBJS)
+ $(CC) $(CFLAGS) -o setfondname $(SETFONDNAMEOBJS)
+
clean:
- -rm -f *.o fondu ufond showfond dfont2res tobin frombin lumper
+ -rm -f *.o fondu ufond showfond dfont2res tobin frombin lumper setfondname
distclean: clean
-rm Makefile
install: all
- cp fondu ufond showfond dfont2res tobin frombin lumper $(bindir)
+ cp fondu ufond showfond dfont2res tobin frombin lumper setfondname $(bindir)
diff --git a/fondu.1 b/fondu.1
index 3980d99..c3da88c 100644
--- a/fondu.1
+++ b/fondu.1
@@ -1,12 +1,14 @@
-.TH FONDU 1 "23 October 2002"
+.TH FONDU 1 "27 May 2004"
.SH NAME
fondu \- convert Macintosh font files to UNIX font format
.SH SYNOPSIS
.B fondu
.RB [ \-force ]
.RB [ \-inquire ]
+.RB [ \-show ]
.RB [ \-latin1 ]
.RB [ \-afm ]
+.RB [ \-trackps ]
.BR macfile ...
.SH DESCRIPTION
The program
@@ -36,14 +38,24 @@ or bare resource fork files.
Force overwriting of the original file.
.TP
.B \-inquire
-Prompt for input before overwriting files.
+Prompt for input before overwriting files. This overrides -force.
+.TP
+.B \-show
+Print out each file as it is created.
.TP
.BI \-latin1
Recode any macintosh bitmap fonts (NFNTs) from the macintosh roman encoding to latin1.
.TP
+.BI \-trackps
+If the macfiles argument mentions a file containing a FOND, and that FOND
+mentions external PostScript resource files, then attempt to open those
+PostScript files as well as processing the original file.
+.TP
.B \-afm
-Create an incomplete Adobe Font Metrics (afm) file,
-containing font width and kerning information, but lacking character bounding box information.
+For any macfile which contains a FOND and points to at least one PostScript
+resource file create an Adobe Font Metrics (afm) file. Fondu will merge
+width and bounding box information from the PostScript files, and kerning
+data from the FOND.
.SH AUTHOR
George Williams (gww@silcom.com).
.LP
diff --git a/fondu.c b/fondu.c
index d88213b..8979dd7 100644
--- a/fondu.c
+++ b/fondu.c
@@ -31,11 +31,12 @@
#include <sys/types.h>
#include <unistd.h>
#include <time.h>
+#include <math.h>
#include "macfonts.h"
int tolatin1 = false;
-static int force = false, inquire = false, doafm = false;
+static int force = false, inquire = false, doafm = false, trackps = false, show=false;
int getushort(FILE *f) {
int ch1 = getc(f);
@@ -55,7 +56,7 @@ return( EOF );
return( (ch1<<24)|(ch2<<16)|(ch3<<8)|ch4 );
}
-int cleanfilename(char *filename) {
+static int _cleanfilename(char *filename) {
char *pt, *npt;
int ch, exists, ch2;
@@ -77,6 +78,13 @@ return( true );
else
return( true );
ch = getchar();
+ if ( ch=='q' || ch=='Q' )
+exit(0);
+ if ( ch=='a' || ch=='A' ) {
+ force = true;
+ inquire = false;
+return( true );
+ }
if ( ch=='y' || ch=='Y' || ch=='n' || ch=='N' || ch==EOF || ch=='\n' ) {
if ( ch=='\n' || ch==EOF )
ch = exists ? 'n' : 'y';
@@ -88,11 +96,18 @@ return( ch=='y' || ch=='Y' );
*pt++ = ch;
return( true );
} else {
- fprintf( stderr, "Please answer with 'y'(es), 'n'(o) or '=new-filename'.\n" );
+ fprintf( stderr, "Please answer with 'y'(es), 'n'(o), 'q'(uit), 'a'(ll), or '=new-filename'.\n" );
}
}
}
+int cleanfilename(char *filename) {
+ int ret = _cleanfilename(filename);
+ if ( ret && show )
+ fprintf( stderr, "Creating %s\n", filename );
+return( ret );
+}
+
static void mytmpname(char *temp) {
static int upos;
/* build up a temporary filename that doesn't match anything else */
@@ -104,14 +119,87 @@ return;
}
}
-static FILE *CreateAfmFile(FILE *f,FOND *fond,long styleoff,int style,
- char *fontname,char *familyname) {
- char namebuf[300], **strings;
- int i,cnt, len,j, index;
+/* The mac has rules about what the filename should be for a postscript*/
+/* font. If you deviate from those rules the font will not be found */
+/* The font name must begin with a capital letter */
+/* The filename is designed by modifying the font name */
+/* After the initial capital there can be at most 4 lower case letters (or digits) */
+/* in the filename, any additional lc letters (or digits) in the fontname are ignored */
+/* Every subsequent capital will be followed by at most 2 lc letters */
+/* special characters ("-$", etc.) are removed entirely */
+/* So Times-Bold => TimesBol, HelveticaDemiBold => HelveDemBol */
+static char *FileNameFromPSFontName(char *fontname) {
+ char *filename = strdup(fontname);
+ char *pt, *spt, *lcpt;
+
+ for ( pt = filename, spt = fontname; *spt /*&& pt<filename+63-1*/; ++spt ) {
+ if ( isupper(*spt) || spt==fontname ) {
+ *pt++ = *spt;
+ lcpt = (spt==fontname?spt+5:spt+3);
+ } else if ( (islower(*spt) || isdigit(*spt)) && spt<lcpt )
+ *pt++ = *spt;
+ }
+ *pt = '\0';
+return( filename );
+}
+
+static int IsResourceInFile(char *filename,PSFONT *psfont);
+
+static void ProcessNestedPS( char *fontname, char *origfilename, PSFONT *psfont ) {
+ char *filename = FileNameFromPSFontName(fontname);
+
+ if ( filename!=NULL && *filename!='\0' ) {
+ char *dirend = strrchr(origfilename,'/');
+ if ( dirend!=NULL ) {
+ char *newfn = malloc(strlen(filename)+strlen(origfilename)+1);
+ strcpy(newfn,origfilename);
+ strcpy(newfn + (dirend-origfilename)+1, filename);
+ free(filename);
+ filename = newfn;
+ }
+ if ( access(filename,R_OK)==0 )
+ IsResourceInFile(filename,psfont);
+ else {
+ char *end;
+ filename = realloc(filename,strlen(filename)+10);
+ end = filename+strlen(filename);
+ strcpy(end,".bin");
+ if ( access(filename,R_OK)==0 )
+ IsResourceInFile(filename,psfont);
+ else {
+ strcpy(end,".hqx");
+ if ( access(filename,R_OK)==0 )
+ IsResourceInFile(filename,psfont);
+ }
+ }
+ }
+ if ( psfont!=NULL && psfont->fontname==NULL ) {
+ char *pt = strrchr(filename,'.');
+ if ( pt!=NULL ) *pt = '\0';
+ fprintf( stderr, "Failed to find file %s when searching for a postscript resource\n", filename );
+ }
+ free(filename);
+}
+
+static FILE *CreateAfmFile(FILE *f,FOND *fond,int style,
+ char *fontname,char *familyname, PSFONT *psfont, char *origfilename) {
+ char namebuf[300];
+ int i;
FILE *afm;
- if ( styleoff==0 || style>=48 ) {
- if ( fond->fondname!=NULL )
+ memset(psfont,0,sizeof(PSFONT));
+ if ( !(style&4) && fond->psnames[(style&3)|((style&~7)>>1)]!=NULL ) {
+ /* postscript name table doesn't include underline styles */
+ char *fn = fond->psnames[(style&3)|((style&~7)>>1)];
+ strcpy(familyname,fond->family);
+ strcpy(fontname,fn);
+ ProcessNestedPS( fn, origfilename, psfont );
+ if ( psfont->familyname!=NULL )
+ strcpy(familyname,psfont->familyname); /* Different in URW fonts */
+ } else {
+ if ( fond->family!=NULL )
+ strcpy(familyname,fond->family);
+ else if ( fond->fondname!=NULL )
strcpy(familyname,fond->fondname);
else
strcpy(familyname,"Nameless");
@@ -119,39 +207,6 @@ static FILE *CreateAfmFile(FILE *f,FOND *fond,long styleoff,int style,
for ( i=0; styles[i]!=NULL ; ++i )
if ( style&(1<<i))
strcat(fontname,styles[i]);
- } else {
- fseek(f,styleoff+2+4+4,SEEK_SET);
- index = 0;
- for ( i=0; i<48; ++i )
- if ( i==style )
- index = getc(f);
- else
- getc(f);
- cnt = getushort(f);
- /* well the docs say that there's a STR255 here, but actually there's */
- /* a more compressed pascal string */
- strings = calloc(cnt,sizeof(char *));
- /* Apple uses a 1based array index, I use a 0based. */
- for ( i=0; i<cnt; ++i ) {
- len = getc(f);
- strings[i] = malloc(len+1);
- for ( j=0; j<len; ++j )
- strings[i][j] = getc(f);
- strings[i][j] = '\0';
- }
- strcpy(familyname,strings[0]);
- strcpy(fontname,familyname);
- if ( index>1 && index-1<cnt ) {
- char *ctl = strings[index-1];
- while ( *ctl ) {
- if ( *ctl-1<cnt )
- strcat(fontname,strings[*ctl-1]);
- ++ctl;
- }
- }
- for ( i=1; i<cnt; ++i )
- free(strings[i]);
- free(strings);
}
strcpy(namebuf,fontname);
strcat(namebuf,".afm");
@@ -163,77 +218,159 @@ return( NULL );
return( afm );
}
-static void MakeAfmFiles(FOND *fond,FILE *f, int styleoff, int isfixed) {
+static void AfmBB(FILE *afm, struct bbglyph *bb,int enc, double em) {
+ fprintf( afm, "C %d ; WX %d ; ", enc, (int) (bb->hadvance*1000/em) );
+ fprintf( afm, "N %s ; B %d %d %d %d ;",
+ bb->glyphname,
+ (int) floor(bb->left*1000/em), (int) floor(bb->bottom*1000/em),
+ (int) ceil(bb->right*1000/em), (int) ceil(bb->top*1000/em) );
+ if ( strcmp(bb->glyphname,"fi")==0 )
+ fprintf( afm, " L f i ;" );
+ else if ( strcmp(bb->glyphname,"fl")==0 )
+ fprintf( afm, " L f l ;" );
+ else if ( strcmp(bb->glyphname,"ff")==0 )
+ fprintf( afm, " L f f ;" );
+ putc('\n',afm);
+}
+
+static void MakeAfmFiles(FOND *fond,FILE *f, int isfixed,char *origfilename) {
long start = ftell(f);
- int i,j,k;
+ int ii,i,j,k,l,dups;
FILE *afm;
time_t now;
char fontname[256], familyname[256];
char buffer[32];
+ PSFONT psfont;
- for ( i=0; i<fond->stylekerncnt; ++i ) {
- for ( j=fond->stylewidthcnt-1; j>=0; --j )
- if ( fond->stylekerns[i].style==fond->stylewidths[j].style )
+ for ( ii=0; ii<48; ++ii ) {
+ int style = ((ii&3)|((ii&~3)<<1));
+ for ( i=fond->stylekerncnt-1; i>=0; --i )
+ if ( fond->stylekerns[i].style==style )
break;
- afm = CreateAfmFile(f,fond,styleoff,fond->stylekerns[i].style,fontname,familyname);
+ if ( i==-1 && fond->psnames[ii]==NULL )
+ continue;
+ afm = CreateAfmFile(f,fond,style,
+ fontname,familyname,&psfont,origfilename);
if ( afm==NULL )
continue;
fprintf( afm, "StartFontMetrics 2.0\n" );
- fprintf( afm, "Comment Caveat: This does not contain all the information generally found in an AFM file\n" );
+ if ( psfont.fontname==NULL )
+ fprintf( afm, "Comment Caveat: This does not contain all the information generally found in an AFM file\n" );
fprintf( afm, "Comment Generated by Fondu from a mac FOND resource\n" );
time(&now);
fprintf( afm, "Comment Creation Data: %s", ctime(&now) );
fprintf( afm, "FontName %s\n", fontname );
fprintf( afm, "FamilyName %s\n", familyname );
- fprintf( afm, "Weight %s\n", ( fond->stylekerns[i].style&sf_bold )?"Bold":"Medium" );
- if ( !( fond->stylekerns[i].style&sf_italic ))
- fprintf( afm, "ItalicAngle 0\n" );
fprintf( afm, "IsFixedPitch %s\n", isfixed?"true":"false");
- fprintf( afm, "EncodingScheme MacRoman\n" ); /* I assume */
- /* I could check to see if there's an offset table, and check it to */
- /* see if there's a bounding box table and then read that in and */
- /* convert it and output a proper FontBBox. But it might not be there*/
- /* and it's a pain, and pfaedit never looks at it anyway */
- if ( j!=-1 ) {
- fprintf( afm, "StartCharMetrics %d\n", fond->last-fond->first+1 );
- for ( k=fond->first; k<=fond->last; ++k ) {
- const char *name;
- if ( k<=256 && macnames[k]!=NULL )
- name = macnames[k];
- else {
- sprintf( buffer, "char%04x", k );
- name = buffer;
- }
- fprintf( afm, "C %d ; WX %d ; N %s ;\n", /* No bounding box info */
- k>=256?-1:k,
- (fond->stylewidths[j].widthtab[k-fond->first]*1000 + (1<<11))>>12,
- name );
+ if ( psfont.fontname!=NULL ) {
+ if ( psfont.fullname )
+ fprintf( afm, "FullName %s\n", psfont.fullname );
+ if ( psfont.weight )
+ fprintf( afm, "Weight %s\n", psfont.weight );
+ if ( psfont.notice )
+ fprintf( afm, "Notice (%s)\n", psfont.notice );
+ if ( psfont.version )
+ fprintf( afm, "Version (%s)\n", psfont.version );
+ fprintf( afm, "ItalicAngle %g\n", psfont.italicangle );
+ fprintf( afm, "EncodingScheme %s\n", psfont.isadobestd ?
+ "AdobeStandardEncoding" : "FontSpecific" );
+ fprintf( afm, "FontBBox %g %g %g %g\n",
+ psfont.fbb[0], psfont.fbb[1], psfont.fbb[2], psfont.fbb[3] );
+ if ( psfont.xh!=0 )
+ fprintf( afm, "XHeight %d\n", psfont.xh );
+ if ( psfont.ch!=0 )
+ fprintf( afm, "CapHeight %d\n", psfont.ch );
+ if ( psfont.as!=0 )
+ fprintf( afm, "Ascender %d\n", psfont.as );
+ if ( psfont.ds!=0 )
+ fprintf( afm, "Descender %d\n", psfont.ds );
+ dups = 0;
+ for ( k=0; k<256; ++k ) {
+ if ( strcmp(psfont.glyphs[psfont.encoding[k]].glyphname,".notdef")==0 && psfont.glyphs[0].isref )
+ continue;
+ for ( l=psfont.glyphcnt-1; l>=0; --l )
+ if ( strcmp(psfont.glyphs[psfont.encoding[k]].glyphname,psfont.glyphs[l].glyphname)==0 )
+ break;
+ if ( l==-1 )
+ continue;
+ else if ( !psfont.glyphs[l].isref )
+ psfont.glyphs[l].isref = true;
+ else
+ ++dups;
}
- fprintf( afm, "EndCharMetrics\n" );
- } else
- fprintf( afm, "StartCharMetrics 0\nEndCharMetrics\n" );
- fprintf( afm, "StartKernData\nStartKernPairs %d\n",
- fond->stylekerns[i].kernpairs );
- for ( k=0; k<fond->stylekerns[i].kernpairs; ++k ) {
- const char *name1, *name2;
- struct kerns *kp = &fond->stylekerns[i].kerns[k];
- if ( kp->ch1<=256 )
- name1 = macnames[kp->ch1];
- else {
- sprintf( buffer, "char%04x", kp->ch1 );
- name1 = buffer;
+ fprintf( afm, "StartCharMetrics %d\n", psfont.glyphcnt+dups );
+ psfont.glyphs[0].isref = false;
+ for ( k=0; k<256; ++k ) {
+ if ( strcmp(psfont.glyphs[psfont.encoding[k]].glyphname,".notdef")==0 && psfont.glyphs[0].isref )
+ continue;
+ for ( l=psfont.glyphcnt-1; l>=0; --l )
+ if ( strcmp(psfont.glyphs[psfont.encoding[k]].glyphname,psfont.glyphs[l].glyphname)==0 )
+ break;
+ if ( l==-1 )
+ continue;
+ AfmBB(afm,&psfont.glyphs[l],k,psfont.em);
+ psfont.glyphs[l].isref = true;
}
- if ( name1==NULL ) name1 = ".notdef";
- if ( kp->ch2<=256 )
- name2 = macnames[kp->ch2];
- else {
- sprintf( fontname, "char%04x", kp->ch2 );
- name2 = fontname;
+ for ( l=0; l<psfont.glyphcnt; ++l ) if ( !psfont.glyphs[l].isref )
+ AfmBB(afm,&psfont.glyphs[l],-1,psfont.em);
+ } else {
+ fprintf( afm, "Weight %s\n", ( style&sf_bold )?"Bold":"Medium" );
+ if ( !( style&sf_italic ))
+ fprintf( afm, "ItalicAngle 0\n" );
+ fprintf( afm, "EncodingScheme FontSpecific\n" );
+ /* I could check to see if there's an offset table, and check it to */
+ /* see if there's a bounding box table and then read that in and */
+ /* convert it and output a proper FontBBox. But it might not be there*/
+ /* and it's a pain, and pfaedit never looks at it anyway */
+ for ( j=fond->stylewidthcnt-1; j>=0; --j )
+ if ( style==fond->stylewidths[j].style )
+ break;
+ if ( j!=-1 ) {
+ fprintf( afm, "StartCharMetrics %d\n", fond->last-fond->first+1 );
+ for ( k=fond->first; k<=fond->last; ++k ) {
+ const char *name;
+ if ( k<=256 && macnames[k]!=NULL )
+ name = macnames[k];
+ else {
+ sprintf( buffer, "char%04x", k );
+ name = buffer;
+ }
+ fprintf( afm, "C %d ; WX %d ; N %s ;\n", /* No bounding box info */
+ k>=256?-1:k,
+ (fond->stylewidths[j].widthtab[k-fond->first]*1000 + (1<<11))>>12,
+ name );
+ }
+ } else
+ fprintf( afm, "StartCharMetrics 0\n" );
+ }
+ fprintf( afm, "EndCharMetrics\n" );
+ if ( i!=-1 ) {
+ /* kerning data are from the fond. so they are in mac encoding */
+ /* the pfb's encoding is irrelevant in this section */
+ fprintf( afm, "StartKernData\nStartKernPairs %d\n",
+ fond->stylekerns[i].kernpairs );
+ for ( k=0; k<fond->stylekerns[i].kernpairs; ++k ) {
+ const char *name1, *name2;
+ struct kerns *kp = &fond->stylekerns[i].kerns[k];
+ if ( kp->ch1<=256 )
+ name1 = macnames[kp->ch1];
+ else {
+ sprintf( buffer, "char%04x", kp->ch1 );
+ name1 = buffer;
+ }
+ if ( name1==NULL ) name1 = ".notdef";
+ if ( kp->ch2<=256 )
+ name2 = macnames[kp->ch2];
+ else {
+ sprintf( fontname, "char%04x", kp->ch2 );
+ name2 = fontname;
+ }
+ if ( name2==NULL ) name2 = ".notdef";
+ fprintf( afm, "KPX %s %s %d\n", name1, name2, (kp->offset*1000+(1<<11))>>12 );
}
- if ( name2==NULL ) name2 = ".notdef";
- fprintf( afm, "KPX %s %s %d\n", name1, name2, (kp->offset*1000+(1<<11))>>12 );
+ fprintf( afm, "EndKernPairs\nEndKernData\n");
}
- fprintf( afm, "EndKernPairs\nEndKernData\nEndFontMetrics\n" );
+ fprintf( afm, "EndFontMetrics\n" );
fclose( afm );
}
fseek(f,start,SEEK_SET);
@@ -248,7 +385,7 @@ static void MakeAfmFiles(FOND *fond,FILE *f, int styleoff, int isfixed) {
/* to get the style flags */
/* http://developer.apple.com/techpubs/mac/Text/Text-269.html */
static FOND *BuildFondList(FILE *f,long rlistpos,int subcnt,long rdata_pos,
- long name_list) {
+ long name_list,char *origfilename) {
long here, start = ftell(f);
long offset;
int rname = -1;
@@ -317,9 +454,7 @@ static FOND *BuildFondList(FILE *f,long rlistpos,int subcnt,long rdata_pos,
cur->stylewidths[j].widthtab[k] = getushort(f);
}
}
- if ( kernoff!=0 && doafm ) {
- /* The only point of generating an afm file is to make the kerning*/
- /* info available to pfaedit. So we only do this if there is kern*/
+ if ( kernoff!=0 ) {
fseek(f,kernoff,SEEK_SET);
cnt = getushort(f)+1;
cur->stylekerncnt = cnt;
@@ -334,8 +469,55 @@ static FOND *BuildFondList(FILE *f,long rlistpos,int subcnt,long rdata_pos,
cur->stylekerns[j].kerns[k].offset = getushort(f);
}
}
- MakeAfmFiles(cur,f,styleoff,isfixed);
}
+ if ( styleoff!=0 ) {
+ unsigned char stringoffsets[48];
+ int strcnt, strlen, format;
+ char **strings, *pt;
+ fseek(f,styleoff,SEEK_SET);
+ /* class = */ getushort(f);
+ /* glyph encoding offset = */ getlong(f);
+ /* reserved = */ getlong(f);
+ for ( j=0; j<48; ++j )
+ stringoffsets[j] = getc(f);
+ strcnt = getushort(f);
+ strings = malloc(strcnt*sizeof(char *));
+ for ( j=0; j<strcnt; ++j ) {
+ strlen = getc(f);
+ strings[j] = malloc(strlen+2);
+ strings[j][0] = strlen;
+ strings[j][strlen+1] = '\0';
+ for ( k=0; k<strlen; ++k )
+ strings[j][k+1] = getc(f);
+ }
+ for ( j=0; j<48; ++j ) {
+ for ( k=j-1; k>=0; --k )
+ if ( stringoffsets[j]==stringoffsets[k] )
+ break;
+ if ( k!=-1 )
+ continue; /* this style doesn't exist */
+ format = stringoffsets[j]-1;
+ strlen = strings[0][0];
+ if ( format!=0 )
+ for ( k=0; k<strings[format][0]; ++k )
+ strlen += strings[ strings[format][k+1]-1 ][0];
+ pt = cur->psnames[j] = malloc(strlen+1);
+ strcpy(pt,strings[ 0 ]+1);
+ pt += strings[ 0 ][0];
+ if ( format!=0 )
+ for ( k=0; k<strings[format][0]; ++k ) {
+ strcpy(pt,strings[ strings[format][k+1]-1 ]+1);
+ pt += strings[ strings[format][k+1]-1 ][0];
+ }
+ *pt = '\0';
+ }
+ cur->family = strdup(strings[0]);
+ for ( j=0; j<strcnt; ++j )
+ free(strings[j]);
+ free(strings);
+ }
+ if ( doafm )
+ MakeAfmFiles(cur,f,isfixed,origfilename);
fseek(f,here,SEEK_SET);
}
fseek(f,start,SEEK_SET);
@@ -343,7 +525,7 @@ return( head );
}
static void SearchPostscriptResources(FILE *f,long rlistpos,int subcnt,long rdata_pos,
- long name_list, FOND *fonds) {
+ long name_list, PSFONT *psfont) {
long here = ftell(f);
long *offsets, lenpos;
int rname = -1, tmp;
@@ -380,7 +562,7 @@ static void SearchPostscriptResources(FILE *f,long rlistpos,int subcnt,long rdat
} else
sprintf(newname,"Untitled-%d.pfb", ++ucnt );
- pfb = fopen( name,"w" );
+ pfb = psfont!=NULL ? tmpfile() : fopen( name,"w" );
if ( pfb==NULL ) {
fprintf( stderr, "Can't open temporary file for postscript output\n" );
fseek(f,here,SEEK_SET );
@@ -460,14 +642,20 @@ return;
putc((len>>8)&0xff,pfb);
putc((len>>16)&0xff,pfb);
putc(len>>24,pfb);
+ if ( psfont!=NULL ) {
+ rewind(pfb);
+ ParsePfb(pfb,psfont);
+ }
fclose(pfb);
- if ( cleanfilename(newname)) {
- if ( rename(name,newname)==-1 ) {
- fprintf( stderr, "Could not create %s\n", newname);
+ if ( psfont==NULL ) {
+ if ( cleanfilename(newname)) {
+ if ( rename(name,newname)==-1 ) {
+ fprintf( stderr, "Could not create %s\n", newname);
+ unlink(name);
+ }
+ } else
unlink(name);
- }
- } else
- unlink(name);
+ }
fseek(f,here,SEEK_SET);
}
@@ -662,7 +850,7 @@ exit( 1 );
return( true );
}
-static int IsResourceFork(FILE *f, long offset) {
+static int IsResourceFork(FILE *f, long offset,char *filename, PSFONT *psfont) {
/* If it is a good resource fork then the first 16 bytes are repeated */
/* at the location specified in bytes 4-7 */
/* We include an offset because if we are looking at a mac binary file */
@@ -673,7 +861,7 @@ static int IsResourceFork(FILE *f, long offset) {
long rdata_len, map_len;
unsigned long tag;
int i, cnt, subcnt;
- FOND *fondlist=NULL;
+ FOND *fondlist=NULL, *fl;
fseek(f,offset,SEEK_SET);
if ( fread(buffer,1,16,f)!=16 )
@@ -705,14 +893,22 @@ return( false );
type_list = map_pos + getushort(f);
name_list = map_pos + getushort(f);
- fseek(f,type_list,SEEK_SET);
- cnt = getushort(f)+1;
- for ( i=0; i<cnt; ++i ) {
- tag = getlong(f);
- subcnt = getushort(f)+1;
- rpos = type_list+getushort(f);
- if ( tag==CHR('F','O','N','D'))
- fondlist = BuildFondList(f,rpos,subcnt,rdata_pos,name_list);
+ if ( psfont==NULL ) {
+ fseek(f,type_list,SEEK_SET);
+ cnt = getushort(f)+1;
+ for ( i=0; i<cnt; ++i ) {
+ tag = getlong(f);
+ subcnt = getushort(f)+1;
+ rpos = type_list+getushort(f);
+ if ( tag==CHR('F','O','N','D'))
+ fondlist = BuildFondList(f,rpos,subcnt,rdata_pos,name_list,filename);
+ }
+
+ if ( trackps ) {
+ for ( fl = fondlist; fl!=NULL; fl=fl->next )
+ for ( i=0; i<48; ++i ) if ( fl->psnames[i]!=NULL )
+ ProcessNestedPS( fl->psnames[i],filename, NULL );
+ }
}
fseek(f,type_list,SEEK_SET);
@@ -723,7 +919,9 @@ return( false );
subcnt = getushort(f)+1;
rpos = type_list+getushort(f);
if ( tag==CHR('P','O','S','T')) /* No FOND */
- SearchPostscriptResources(f,rpos,subcnt,rdata_pos,name_list,fondlist);
+ SearchPostscriptResources(f,rpos,subcnt,rdata_pos,name_list,psfont);
+ else if ( psfont!=NULL )
+ /* No Op */;
else if ( tag==CHR('F','O','N','T'))
SearchNFNTResources(f,rpos,subcnt,rdata_pos,name_list,fondlist);
else if ( tag==CHR('N','F','N','T'))
@@ -738,10 +936,28 @@ return( false );
return( true );
}
-#ifdef __Mac
+#ifndef OldMacintosh
+ /* OS/X and linux with appropriate drivers */
+static int HasResourceFork(char *filename,PSFONT *psfont) {
+ char *respath = malloc(strlen(filename)+strlen("/rsrc")+1);
+ FILE *temp;
+ int ret;
+
+ strcpy(respath,filename);
+ strcat(respath,"/rsrc");
+ temp = fopen(respath,"r");
+ free(respath);
+ if ( temp!=NULL ) {
+ ret = IsResourceFork(temp,0,filename,psfont);
+ fclose(temp);
+ }
+return( ret );
+}
+#else
+ /* OS/9 and before */
#include "MacFiles.h"
-static int HasResourceFork(char *filename) {
+static int HasResourceFork(char *filename,PSFONT *psfont) {
/* If we're on a mac, we can try to see if we've got a real resource fork */
FSRef ref;
FSSpec spec;
@@ -771,13 +987,13 @@ return( 0 );
free(buf);
FSClose(res);
rewind(temp);
- ret = IsResourceFork(temp,0);
+ ret = IsResourceFork(temp,0,filename,psfont);
fclose(temp);
return( ret );
}
#endif
-static int IsResourceInBinary(FILE *f) {
+static int IsResourceInBinary(FILE *f,char *filename, PSFONT *psfont) {
unsigned char header[128], first[8];
unsigned long offset, dlen, rlen;
@@ -803,7 +1019,7 @@ return( MightBeTrueType(f,pos,dlen,(char *) header+2));
}
/* 128 bytes for header, then the dlen is padded to a 128 byte boundary */
offset = 128 + ((dlen+127)&~127);
-return( IsResourceFork(f,offset));
+return( IsResourceFork(f,offset,filename,psfont));
}
static int lastch=0, repeat = 0;
@@ -828,7 +1044,7 @@ static void outchr(FILE *binary, int ch) {
}
}
-static int IsResourceInHex(FILE *f) {
+static int IsResourceInHex(FILE *f,char *filename, PSFONT *psfont) {
/* convert file from 6bit to 8bit */
/* interesting data is enclosed between two colons */
FILE *binary = tmpfile();
@@ -907,13 +1123,13 @@ return( ret );
return( false );
}
- ret = IsResourceFork(binary,ftell(binary)+dlen+2);
+ ret = IsResourceFork(binary,ftell(binary)+dlen+2, filename,psfont);
fclose(binary);
return( ret );
}
-static int IsResourceInFile(char *filename) {
+static int IsResourceInFile(char *filename,PSFONT *psfont) {
FILE *f;
char *spt, *pt;
int ret;
@@ -926,24 +1142,22 @@ return( false );
pt = strrchr(spt,'.');
if ( pt!=NULL && (pt[1]=='b' || pt[1]=='B') && (pt[2]=='i' || pt[2]=='I') &&
(pt[3]=='n' || pt[3]=='N') && pt[4]=='\0' ) {
- if ( IsResourceInBinary(f)) {
+ if ( IsResourceInBinary(f,filename,psfont)) {
fclose(f);
return( true );
}
} else if ( pt!=NULL && (pt[1]=='h' || pt[1]=='H') && (pt[2]=='q' || pt[2]=='Q') &&
(pt[3]=='x' || pt[3]=='X') && pt[4]=='\0' ) {
- if ( IsResourceInHex(f)) {
+ if ( IsResourceInHex(f,filename,psfont)) {
fclose(f);
return( true );
}
}
- ret = IsResourceFork(f,0);
+ ret = IsResourceFork(f,0,filename,psfont);
fclose(f);
-#ifdef __Mac
if ( !ret )
- ret = HasResourceFork(filename);
-#endif
+ ret = HasResourceFork(filename,psfont);
return( ret );
}
@@ -951,7 +1165,7 @@ static int FindResourceFile(char *filename) {
char *spt, *pt, *dpt;
char buffer[1400];
- if ( IsResourceInFile(filename))
+ if ( IsResourceInFile(filename,NULL))
return( true );
/* Well, look in the resource fork directory (if it exists), the resource */
@@ -962,7 +1176,7 @@ return( true );
else { ++spt; pt = filename + (spt-buffer); }
strcpy(spt,"resource.frk/");
strcat(spt,pt);
- if ( IsResourceInFile(buffer))
+ if ( IsResourceInFile(buffer,NULL))
return( true );
/* however the resource fork does not appear to long names properly */
@@ -983,7 +1197,7 @@ return( true );
*dpt++ = '1';
strcpy(dpt,exten);
}
-return( IsResourceInFile(buffer));
+return( IsResourceInFile(buffer,NULL));
}
int main(int argc, char **argv) {
@@ -998,16 +1212,23 @@ int main(int argc, char **argv) {
else if (strcmp(pt,"-force")==0 || strcmp(pt,"-f")==0 )
force = true;
else if (strcmp(pt,"-inquire")==0 || strcmp(pt,"-i")==0 )
- force = true;
- else if (strcmp(pt,"-afm")==0 )
+ inquire = true;
+ else if (strcmp(pt,"-afm")==0 || strcmp(pt,"-a")==0 )
doafm = true;
+ else if (strcmp(pt,"-trackps")==0 || strcmp(pt,"-t")==0 )
+ trackps = true;
+ else if (strcmp(pt,"-show")==0 || strcmp(pt,"-s")==0 )
+ show = true;
else {
- fprintf( stderr, "Usage: %s [-force] [-inquire] [-latin1] [-afm] macfiles\n",
+ fprintf( stderr, "Usage: %s [-force] [-inquire] [-latin1] [-afm] [-trackps] [-show] macfiles\n",
argv[0] );
fprintf( stderr, " if -force is given you will not be asked about replacing existing files\n" );
fprintf( stderr, " if -inquire is given you will be asked about writing each file (whether\n" );
fprintf( stderr, "\tit exists or not). -inquire overrides -force.\n" );
+ fprintf( stderr, " if -show is given you will not be told about each file created.\n" );
fprintf( stderr, " if -latin1 is given nfnts will be reencoded to latin1 (else left in mac roman)\n" );
+ fprintf( stderr, " if -trackps is given then any postscript files referenced by a FOND\n" );
+ fprintf( stderr, "\twill be loaded and processed.\n" );
fprintf( stderr, " if -afm is given then an incomplete afm file will be generated from any fonds.\n" );
fprintf( stderr, " macfile may be a macbinary (.bin), binhex (.hqx) or bare resource fork.\n" );
exit(0);
diff --git a/fondups.c b/fondups.c
new file mode 100644
index 0000000..2c8d556
--- /dev/null
+++ b/fondups.c
@@ -0,0 +1,3075 @@
+/* Copyright (C) 2000-2004 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include "psfont.h"
+#include "macfonts.h"
+#include <locale.h>
+#include <math.h>
+
+struct fontparse {
+ FontDict *fd, *mainfd;
+ /* always in font data */
+ unsigned int infi:1;
+ unsigned int inchars:1;
+ unsigned int inprivate:1;
+ unsigned int insubs:1;
+ unsigned int inmetrics: 1;
+ unsigned int inmetrics2: 1;
+ unsigned int inbb: 1;
+ unsigned int inencoding: 1;
+ unsigned int multiline: 1;
+ unsigned int incidsysteminfo: 1;
+ unsigned int inblendfi:1;
+ unsigned int inblendprivate:1;
+ unsigned int skipping_mbf: 1;
+ unsigned int inblend: 1;
+ unsigned int iscid: 1;
+ unsigned int iscff: 1;
+ unsigned int useshexstrings: 1;
+ unsigned int doneencoding: 1;
+ unsigned int ignore: 1;
+ int instring;
+ int fdindex;
+ char **pending_parse;
+
+ unsigned int alreadycomplained: 1;
+
+ char *vbuf, *vmax, *vpt;
+ int depth;
+};
+
+static char *copyn(const char *str,long n) {
+ char *ret;
+
+ if ( str==NULL )
+return( NULL );
+ ret = malloc(n+1);
+ memcpy(ret,str,n);
+ ret[n]='\0';
+return( ret );
+}
+
+static char *PSDictHasEntry(struct psdict *dict, char *key) {
+ int i;
+
+ if ( dict==NULL )
+return( NULL );
+
+ for ( i=0; i<dict->next; ++i )
+ if ( strcmp(dict->keys[i],key)==0 )
+return( dict->values[i] );
+
+return( NULL );
+}
+
+static int PSDictRemoveEntry(struct psdict *dict, char *key) {
+ int i;
+
+ if ( dict==NULL )
+return( false );
+
+ for ( i=0; i<dict->next; ++i )
+ if ( strcmp(dict->keys[i],key)==0 )
+ break;
+ if ( i==dict->next )
+return( false );
+ free( dict->keys[i]);
+ free( dict->values[i] );
+ --dict->next;
+ while ( i<dict->next ) {
+ dict->keys[i] = dict->keys[i+1];
+ dict->values[i] = dict->values[i+1];
+ ++i;
+ }
+
+return( true );
+}
+
+static void copyenc(char *encoding[256],char *std[256]) {
+ int i;
+ for ( i=0; i<256; ++i )
+ encoding[i] = strdup(std[i]);
+}
+
+char *AdobeStandardEncoding[] = {
+/* 0000 */ ".notdef",
+/* 0001 */ ".notdef",
+/* 0002 */ ".notdef",
+/* 0003 */ ".notdef",
+/* 0004 */ ".notdef",
+/* 0005 */ ".notdef",
+/* 0006 */ ".notdef",
+/* 0007 */ ".notdef",
+/* 0008 */ ".notdef",
+/* 0009 */ ".notdef",
+/* 000a */ ".notdef",
+/* 000b */ ".notdef",
+/* 000c */ ".notdef",
+/* 000d */ ".notdef",
+/* 000e */ ".notdef",
+/* 000f */ ".notdef",
+/* 0010 */ ".notdef",
+/* 0011 */ ".notdef",
+/* 0012 */ ".notdef",
+/* 0013 */ ".notdef",
+/* 0014 */ ".notdef",
+/* 0015 */ ".notdef",
+/* 0016 */ ".notdef",
+/* 0017 */ ".notdef",
+/* 0018 */ ".notdef",
+/* 0019 */ ".notdef",
+/* 001a */ ".notdef",
+/* 001b */ ".notdef",
+/* 001c */ ".notdef",
+/* 001d */ ".notdef",
+/* 001e */ ".notdef",
+/* 001f */ ".notdef",
+/* 0020 */ "space",
+/* 0021 */ "exclam",
+/* 0022 */ "quotedbl",
+/* 0023 */ "numbersign",
+/* 0024 */ "dollar",
+/* 0025 */ "percent",
+/* 0026 */ "ampersand",
+/* 0027 */ "quoteright",
+/* 0028 */ "parenleft",
+/* 0029 */ "parenright",
+/* 002a */ "asterisk",
+/* 002b */ "plus",
+/* 002c */ "comma",
+/* 002d */ "hyphen",
+/* 002e */ "period",
+/* 002f */ "slash",
+/* 0030 */ "zero",
+/* 0031 */ "one",
+/* 0032 */ "two",
+/* 0033 */ "three",
+/* 0034 */ "four",
+/* 0035 */ "five",
+/* 0036 */ "six",
+/* 0037 */ "seven",
+/* 0038 */ "eight",
+/* 0039 */ "nine",
+/* 003a */ "colon",
+/* 003b */ "semicolon",
+/* 003c */ "less",
+/* 003d */ "equal",
+/* 003e */ "greater",
+/* 003f */ "question",
+/* 0040 */ "at",
+/* 0041 */ "A",
+/* 0042 */ "B",
+/* 0043 */ "C",
+/* 0044 */ "D",
+/* 0045 */ "E",
+/* 0046 */ "F",
+/* 0047 */ "G",
+/* 0048 */ "H",
+/* 0049 */ "I",
+/* 004a */ "J",
+/* 004b */ "K",
+/* 004c */ "L",
+/* 004d */ "M",
+/* 004e */ "N",
+/* 004f */ "O",
+/* 0050 */ "P",
+/* 0051 */ "Q",
+/* 0052 */ "R",
+/* 0053 */ "S",
+/* 0054 */ "T",
+/* 0055 */ "U",
+/* 0056 */ "V",
+/* 0057 */ "W",
+/* 0058 */ "X",
+/* 0059 */ "Y",
+/* 005a */ "Z",
+/* 005b */ "bracketleft",
+/* 005c */ "backslash",
+/* 005d */ "bracketright",
+/* 005e */ "asciicircum",
+/* 005f */ "underscore",
+/* 0060 */ "quoteleft",
+/* 0061 */ "a",
+/* 0062 */ "b",
+/* 0063 */ "c",
+/* 0064 */ "d",
+/* 0065 */ "e",
+/* 0066 */ "f",
+/* 0067 */ "g",
+/* 0068 */ "h",
+/* 0069 */ "i",
+/* 006a */ "j",
+/* 006b */ "k",
+/* 006c */ "l",
+/* 006d */ "m",
+/* 006e */ "n",
+/* 006f */ "o",
+/* 0070 */ "p",
+/* 0071 */ "q",
+/* 0072 */ "r",
+/* 0073 */ "s",
+/* 0074 */ "t",
+/* 0075 */ "u",
+/* 0076 */ "v",
+/* 0077 */ "w",
+/* 0078 */ "x",
+/* 0079 */ "y",
+/* 007a */ "z",
+/* 007b */ "braceleft",
+/* 007c */ "bar",
+/* 007d */ "braceright",
+/* 007e */ "asciitilde",
+/* 007f */ ".notdef",
+/* 0080 */ ".notdef",
+/* 0081 */ ".notdef",
+/* 0082 */ ".notdef",
+/* 0083 */ ".notdef",
+/* 0084 */ ".notdef",
+/* 0085 */ ".notdef",
+/* 0086 */ ".notdef",
+/* 0087 */ ".notdef",
+/* 0088 */ ".notdef",
+/* 0089 */ ".notdef",
+/* 008a */ ".notdef",
+/* 008b */ ".notdef",
+/* 008c */ ".notdef",
+/* 008d */ ".notdef",
+/* 008e */ ".notdef",
+/* 008f */ ".notdef",
+/* 0090 */ ".notdef",
+/* 0091 */ ".notdef",
+/* 0092 */ ".notdef",
+/* 0093 */ ".notdef",
+/* 0094 */ ".notdef",
+/* 0095 */ ".notdef",
+/* 0096 */ ".notdef",
+/* 0097 */ ".notdef",
+/* 0098 */ ".notdef",
+/* 0099 */ ".notdef",
+/* 009a */ ".notdef",
+/* 009b */ ".notdef",
+/* 009c */ ".notdef",
+/* 009d */ ".notdef",
+/* 009e */ ".notdef",
+/* 009f */ ".notdef",
+/* 00a0 */ ".notdef",
+/* 00a1 */ "exclamdown",
+/* 00a2 */ "cent",
+/* 00a3 */ "sterling",
+/* 00a4 */ "fraction",
+/* 00a5 */ "yen",
+/* 00a6 */ "florin",
+/* 00a7 */ "section",
+/* 00a8 */ "currency",
+/* 00a9 */ "quotesingle",
+/* 00aa */ "quotedblleft",
+/* 00ab */ "guillemotleft",
+/* 00ac */ "guilsinglleft",
+/* 00ad */ "guilsinglright",
+/* 00ae */ "fi",
+/* 00af */ "fl",
+/* 00b0 */ ".notdef",
+/* 00b1 */ "endash",
+/* 00b2 */ "dagger",
+/* 00b3 */ "daggerdbl",
+/* 00b4 */ "periodcentered",
+/* 00b5 */ ".notdef",
+/* 00b6 */ "paragraph",
+/* 00b7 */ "bullet",
+/* 00b8 */ "quotesinglbase",
+/* 00b9 */ "quotedblbase",
+/* 00ba */ "quotedblright",
+/* 00bb */ "guillemotright",
+/* 00bc */ "ellipsis",
+/* 00bd */ "perthousand",
+/* 00be */ ".notdef",
+/* 00bf */ "questiondown",
+/* 00c0 */ ".notdef",
+/* 00c1 */ "grave",
+/* 00c2 */ "acute",
+/* 00c3 */ "circumflex",
+/* 00c4 */ "tilde",
+/* 00c5 */ "macron",
+/* 00c6 */ "breve",
+/* 00c7 */ "dotaccent",
+/* 00c8 */ "dieresis",
+/* 00c9 */ ".notdef",
+/* 00ca */ "ring",
+/* 00cb */ "cedilla",
+/* 00cc */ ".notdef",
+/* 00cd */ "hungarumlaut",
+/* 00ce */ "ogonek",
+/* 00cf */ "caron",
+/* 00d0 */ "emdash",
+/* 00d1 */ ".notdef",
+/* 00d2 */ ".notdef",
+/* 00d3 */ ".notdef",
+/* 00d4 */ ".notdef",
+/* 00d5 */ ".notdef",
+/* 00d6 */ ".notdef",
+/* 00d7 */ ".notdef",
+/* 00d8 */ ".notdef",
+/* 00d9 */ ".notdef",
+/* 00da */ ".notdef",
+/* 00db */ ".notdef",
+/* 00dc */ ".notdef",
+/* 00dd */ ".notdef",
+/* 00de */ ".notdef",
+/* 00df */ ".notdef",
+/* 00e0 */ ".notdef",
+/* 00e1 */ "AE",
+/* 00e2 */ ".notdef",
+/* 00e3 */ "ordfeminine",
+/* 00e4 */ ".notdef",
+/* 00e5 */ ".notdef",
+/* 00e6 */ ".notdef",
+/* 00e7 */ ".notdef",
+/* 00e8 */ "Lslash",
+/* 00e9 */ "Oslash",
+/* 00ea */ "OE",
+/* 00eb */ "ordmasculine",
+/* 00ec */ ".notdef",
+/* 00ed */ ".notdef",
+/* 00ee */ ".notdef",
+/* 00ef */ ".notdef",
+/* 00f0 */ ".notdef",
+/* 00f1 */ "ae",
+/* 00f2 */ ".notdef",
+/* 00f3 */ ".notdef",
+/* 00f4 */ ".notdef",
+/* 00f5 */ "dotlessi",
+/* 00f6 */ ".notdef",
+/* 00f7 */ ".notdef",
+/* 00f8 */ "lslash",
+/* 00f9 */ "oslash",
+/* 00fa */ "oe",
+/* 00fb */ "germandbls",
+/* 00fc */ ".notdef",
+/* 00fd */ ".notdef",
+/* 00fe */ ".notdef",
+/* 00ff */ ".notdef"
+};
+static void setStdEnc(char *encoding[256]) {
+ copyenc(encoding,AdobeStandardEncoding);
+}
+
+static void setLatin1Enc(char *encoding[256]) {
+ static char *latin1enc[] = {
+/* 0000 */ ".notdef",
+/* 0001 */ ".notdef",
+/* 0002 */ ".notdef",
+/* 0003 */ ".notdef",
+/* 0004 */ ".notdef",
+/* 0005 */ ".notdef",
+/* 0006 */ ".notdef",
+/* 0007 */ ".notdef",
+/* 0008 */ ".notdef",
+/* 0009 */ ".notdef",
+/* 000a */ ".notdef",
+/* 000b */ ".notdef",
+/* 000c */ ".notdef",
+/* 000d */ ".notdef",
+/* 000e */ ".notdef",
+/* 000f */ ".notdef",
+/* 0010 */ ".notdef",
+/* 0011 */ ".notdef",
+/* 0012 */ ".notdef",
+/* 0013 */ ".notdef",
+/* 0014 */ ".notdef",
+/* 0015 */ ".notdef",
+/* 0016 */ ".notdef",
+/* 0017 */ ".notdef",
+/* 0018 */ ".notdef",
+/* 0019 */ ".notdef",
+/* 001a */ ".notdef",
+/* 001b */ ".notdef",
+/* 001c */ ".notdef",
+/* 001d */ ".notdef",
+/* 001e */ ".notdef",
+/* 001f */ ".notdef",
+/* 0020 */ "space",
+/* 0021 */ "exclam",
+/* 0022 */ "quotedbl",
+/* 0023 */ "numbersign",
+/* 0024 */ "dollar",
+/* 0025 */ "percent",
+/* 0026 */ "ampersand",
+/* 0027 */ "quoteright",
+/* 0028 */ "parenleft",
+/* 0029 */ "parenright",
+/* 002a */ "asterisk",
+/* 002b */ "plus",
+/* 002c */ "comma",
+/* 002d */ "hyphen",
+/* 002e */ "period",
+/* 002f */ "slash",
+/* 0030 */ "zero",
+/* 0031 */ "one",
+/* 0032 */ "two",
+/* 0033 */ "three",
+/* 0034 */ "four",
+/* 0035 */ "five",
+/* 0036 */ "six",
+/* 0037 */ "seven",
+/* 0038 */ "eight",
+/* 0039 */ "nine",
+/* 003a */ "colon",
+/* 003b */ "semicolon",
+/* 003c */ "less",
+/* 003d */ "equal",
+/* 003e */ "greater",
+/* 003f */ "question",
+/* 0040 */ "at",
+/* 0041 */ "A",
+/* 0042 */ "B",
+/* 0043 */ "C",
+/* 0044 */ "D",
+/* 0045 */ "E",
+/* 0046 */ "F",
+/* 0047 */ "G",
+/* 0048 */ "H",
+/* 0049 */ "I",
+/* 004a */ "J",
+/* 004b */ "K",
+/* 004c */ "L",
+/* 004d */ "M",
+/* 004e */ "N",
+/* 004f */ "O",
+/* 0050 */ "P",
+/* 0051 */ "Q",
+/* 0052 */ "R",
+/* 0053 */ "S",
+/* 0054 */ "T",
+/* 0055 */ "U",
+/* 0056 */ "V",
+/* 0057 */ "W",
+/* 0058 */ "X",
+/* 0059 */ "Y",
+/* 005a */ "Z",
+/* 005b */ "bracketleft",
+/* 005c */ "backslash",
+/* 005d */ "bracketright",
+/* 005e */ "asciicircum",
+/* 005f */ "underscore",
+/* 0060 */ "grave",
+/* 0061 */ "a",
+/* 0062 */ "b",
+/* 0063 */ "c",
+/* 0064 */ "d",
+/* 0065 */ "e",
+/* 0066 */ "f",
+/* 0067 */ "g",
+/* 0068 */ "h",
+/* 0069 */ "i",
+/* 006a */ "j",
+/* 006b */ "k",
+/* 006c */ "l",
+/* 006d */ "m",
+/* 006e */ "n",
+/* 006f */ "o",
+/* 0070 */ "p",
+/* 0071 */ "q",
+/* 0072 */ "r",
+/* 0073 */ "s",
+/* 0074 */ "t",
+/* 0075 */ "u",
+/* 0076 */ "v",
+/* 0077 */ "w",
+/* 0078 */ "x",
+/* 0079 */ "y",
+/* 007a */ "z",
+/* 007b */ "braceleft",
+/* 007c */ "bar",
+/* 007d */ "braceright",
+/* 007e */ "asciitilde",
+/* 007f */ ".notdef",
+/* 0080 */ ".notdef",
+/* 0081 */ ".notdef",
+/* 0082 */ ".notdef",
+/* 0083 */ ".notdef",
+/* 0084 */ ".notdef",
+/* 0085 */ ".notdef",
+/* 0086 */ ".notdef",
+/* 0087 */ ".notdef",
+/* 0088 */ ".notdef",
+/* 0089 */ ".notdef",
+/* 008a */ ".notdef",
+/* 008b */ ".notdef",
+/* 008c */ ".notdef",
+/* 008d */ ".notdef",
+/* 008e */ ".notdef",
+/* 008f */ ".notdef",
+/* 0090 */ "dotlessi", /* Um, Adobe's Latin1 has some extra chars */
+/* 0091 */ "grave",
+/* 0092 */ "accute", /* This is a duplicate... */
+/* 0093 */ "circumflex",
+/* 0094 */ "tilde",
+/* 0095 */ "macron",
+/* 0096 */ "breve",
+/* 0097 */ "dotaccent",
+/* 0098 */ "dieresis",
+/* 0099 */ ".notdef",
+/* 009a */ "ring",
+/* 009b */ "cedilla",
+/* 009c */ ".notdef",
+/* 009d */ "hungarumlaut",
+/* 009e */ "ogonek",
+/* 009f */ "caron",
+/* 00a0 */ "space",
+/* 00a1 */ "exclamdown",
+/* 00a2 */ "cent",
+/* 00a3 */ "sterling",
+/* 00a4 */ "currency",
+/* 00a5 */ "yen",
+/* 00a6 */ "brokenbar",
+/* 00a7 */ "section",
+/* 00a8 */ "dieresis",
+/* 00a9 */ "copyright",
+/* 00aa */ "ordfeminine",
+/* 00ab */ "guillemotleft",
+/* 00ac */ "logicalnot",
+/* 00ad */ "hyphen",
+/* 00ae */ "registered",
+/* 00af */ "macron",
+/* 00b0 */ "degree",
+/* 00b1 */ "plusminus",
+/* 00b2 */ "twosuperior",
+/* 00b3 */ "threesuperior",
+/* 00b4 */ "acute",
+/* 00b5 */ "mu",
+/* 00b6 */ "paragraph",
+/* 00b7 */ "periodcentered",
+/* 00b8 */ "cedilla",
+/* 00b9 */ "onesuperior",
+/* 00ba */ "ordmasculine",
+/* 00bb */ "guillemotright",
+/* 00bc */ "onequarter",
+/* 00bd */ "onehalf",
+/* 00be */ "threequarters",
+/* 00bf */ "questiondown",
+/* 00c0 */ "Agrave",
+/* 00c1 */ "Aacute",
+/* 00c2 */ "Acircumflex",
+/* 00c3 */ "Atilde",
+/* 00c4 */ "Adieresis",
+/* 00c5 */ "Aring",
+/* 00c6 */ "AE",
+/* 00c7 */ "Ccedilla",
+/* 00c8 */ "Egrave",
+/* 00c9 */ "Eacute",
+/* 00ca */ "Ecircumflex",
+/* 00cb */ "Edieresis",
+/* 00cc */ "Igrave",
+/* 00cd */ "Iacute",
+/* 00ce */ "Icircumflex",
+/* 00cf */ "Idieresis",
+/* 00d0 */ "Eth",
+/* 00d1 */ "Ntilde",
+/* 00d2 */ "Ograve",
+/* 00d3 */ "Oacute",
+/* 00d4 */ "Ocircumflex",
+/* 00d5 */ "Otilde",
+/* 00d6 */ "Odieresis",
+/* 00d7 */ "multiply",
+/* 00d8 */ "Oslash",
+/* 00d9 */ "Ugrave",
+/* 00da */ "Uacute",
+/* 00db */ "Ucircumflex",
+/* 00dc */ "Udieresis",
+/* 00dd */ "Yacute",
+/* 00de */ "Thorn",
+/* 00df */ "germandbls",
+/* 00e0 */ "agrave",
+/* 00e1 */ "aacute",
+/* 00e2 */ "acircumflex",
+/* 00e3 */ "atilde",
+/* 00e4 */ "adieresis",
+/* 00e5 */ "aring",
+/* 00e6 */ "ae",
+/* 00e7 */ "ccedilla",
+/* 00e8 */ "egrave",
+/* 00e9 */ "eacute",
+/* 00ea */ "ecircumflex",
+/* 00eb */ "edieresis",
+/* 00ec */ "igrave",
+/* 00ed */ "iacute",
+/* 00ee */ "icircumflex",
+/* 00ef */ "idieresis",
+/* 00f0 */ "eth",
+/* 00f1 */ "ntilde",
+/* 00f2 */ "ograve",
+/* 00f3 */ "oacute",
+/* 00f4 */ "ocircumflex",
+/* 00f5 */ "otilde",
+/* 00f6 */ "odieresis",
+/* 00f7 */ "divide",
+/* 00f8 */ "oslash",
+/* 00f9 */ "ugrave",
+/* 00fa */ "uacute",
+/* 00fb */ "ucircumflex",
+/* 00fc */ "udieresis",
+/* 00fd */ "yacute",
+/* 00fe */ "thorn",
+/* 00ff */ "ydieresis"
+ };
+ copyenc(encoding,latin1enc);
+}
+
+char *AdobeExpertEncoding[] = {
+/* 0000 */ ".notdef",
+/* 0001 */ ".notdef",
+/* 0002 */ ".notdef",
+/* 0003 */ ".notdef",
+/* 0004 */ ".notdef",
+/* 0005 */ ".notdef",
+/* 0006 */ ".notdef",
+/* 0007 */ ".notdef",
+/* 0008 */ ".notdef",
+/* 0009 */ ".notdef",
+/* 000a */ ".notdef",
+/* 000b */ ".notdef",
+/* 000c */ ".notdef",
+/* 000d */ ".notdef",
+/* 000e */ ".notdef",
+/* 000f */ ".notdef",
+/* 0010 */ ".notdef",
+/* 0011 */ ".notdef",
+/* 0012 */ ".notdef",
+/* 0013 */ ".notdef",
+/* 0014 */ ".notdef",
+/* 0015 */ ".notdef",
+/* 0016 */ ".notdef",
+/* 0017 */ ".notdef",
+/* 0018 */ ".notdef",
+/* 0019 */ ".notdef",
+/* 001a */ ".notdef",
+/* 001b */ ".notdef",
+/* 001c */ ".notdef",
+/* 001d */ ".notdef",
+/* 001e */ ".notdef",
+/* 001f */ ".notdef",
+/* 0020 */ "space",
+/* 0021 */ "exclamsmall",
+/* 0022 */ "Hungarumlautsmal",
+/* 0023 */ ".notdef",
+/* 0024 */ "dollaroldstyle",
+/* 0025 */ "dollarsuperior",
+/* 0026 */ "ampersandsmall",
+/* 0027 */ "Acutesmall",
+/* 0028 */ "parenleftsuperior",
+/* 0029 */ "parenrightsuperior",
+/* 002a */ "twodotenleader",
+/* 002b */ "onedotenleader",
+/* 002c */ "comma",
+/* 002d */ "hyphen",
+/* 002e */ "period",
+/* 002f */ "fraction",
+/* 0030 */ "zerooldstyle",
+/* 0031 */ "oneoldstyle",
+/* 0032 */ "twooldstyle",
+/* 0033 */ "threeoldstyle",
+/* 0034 */ "fouroldstyle",
+/* 0035 */ "fiveoldstyle",
+/* 0036 */ "sixoldstyle",
+/* 0037 */ "sevenoldstyle",
+/* 0038 */ "eightoldstyle",
+/* 0039 */ "nineoldstyle",
+/* 003a */ "colon",
+/* 003b */ "semicolon",
+/* 003c */ "commasuperior",
+/* 003d */ "threequartersemdash",
+/* 003e */ "periodsuperior",
+/* 003f */ "questionsmall",
+/* 0040 */ ".notdef",
+/* 0041 */ "asuperior",
+/* 0042 */ "bsuperior",
+/* 0043 */ "centsuperior",
+/* 0044 */ "dsuperior",
+/* 0045 */ "esuperior",
+/* 0046 */ ".notdef",
+/* 0047 */ ".notdef",
+/* 0048 */ ".notdef",
+/* 0049 */ "isuperior",
+/* 004a */ ".notdef",
+/* 004b */ ".notdef",
+/* 004c */ "lsuperior",
+/* 004d */ "msuperior",
+/* 004e */ "nsuperior",
+/* 004f */ "osuperior",
+/* 0050 */ ".notdef",
+/* 0051 */ ".notdef",
+/* 0052 */ "rsuperior",
+/* 0053 */ "ssuperior",
+/* 0054 */ "tsuperior",
+/* 0055 */ ".notdef",
+/* 0056 */ "ff",
+/* 0057 */ "fi",
+/* 0058 */ "fl",
+/* 0059 */ "ffi",
+/* 005a */ "ffl",
+/* 005b */ "parenleftinferior",
+/* 005c */ ".notdef",
+/* 005d */ "parenrightinferior",
+/* 005e */ "Circumflexsmall",
+/* 005f */ "hyphensuperior",
+/* 0060 */ "Gravesmall",
+/* 0061 */ "Asmall",
+/* 0062 */ "Bsmall",
+/* 0063 */ "Csmall",
+/* 0064 */ "Dsmall",
+/* 0065 */ "Esmall",
+/* 0066 */ "Fsmall",
+/* 0067 */ "Gsmall",
+/* 0068 */ "Hsmall",
+/* 0069 */ "Ismall",
+/* 006a */ "Jsmall",
+/* 006b */ "Ksmall",
+/* 006c */ "Lsmall",
+/* 006d */ "Msmall",
+/* 006e */ "Nsmall",
+/* 006f */ "Osmall",
+/* 0070 */ "Psmall",
+/* 0071 */ "Qsmall",
+/* 0072 */ "Rsmall",
+/* 0073 */ "Ssmall",
+/* 0074 */ "Tsmall",
+/* 0075 */ "Usmall",
+/* 0076 */ "Vsmall",
+/* 0077 */ "Wsmall",
+/* 0078 */ "Xsmall",
+/* 0079 */ "Ysmall",
+/* 007a */ "Zsmall",
+/* 007b */ "colonmonetary",
+/* 007c */ "onefitted",
+/* 007d */ "rupiah",
+/* 007e */ "Tildesmall",
+/* 007f */ ".notdef",
+/* 0080 */ ".notdef",
+/* 0081 */ ".notdef",
+/* 0082 */ ".notdef",
+/* 0083 */ ".notdef",
+/* 0084 */ ".notdef",
+/* 0085 */ ".notdef",
+/* 0086 */ ".notdef",
+/* 0087 */ ".notdef",
+/* 0088 */ ".notdef",
+/* 0089 */ ".notdef",
+/* 008a */ ".notdef",
+/* 008b */ ".notdef",
+/* 008c */ ".notdef",
+/* 008d */ ".notdef",
+/* 008e */ ".notdef",
+/* 008f */ ".notdef",
+/* 0090 */ ".notdef",
+/* 0091 */ ".notdef",
+/* 0092 */ ".notdef",
+/* 0093 */ ".notdef",
+/* 0094 */ ".notdef",
+/* 0095 */ ".notdef",
+/* 0096 */ ".notdef",
+/* 0097 */ ".notdef",
+/* 0098 */ ".notdef",
+/* 0099 */ ".notdef",
+/* 009a */ ".notdef",
+/* 009b */ ".notdef",
+/* 009c */ ".notdef",
+/* 009d */ ".notdef",
+/* 009e */ ".notdef",
+/* 009f */ ".notdef",
+/* 00a0 */ ".notdef",
+/* 00a1 */ "exclamdownsmall",
+/* 00a2 */ "centoldstyle",
+/* 00a3 */ "Lslashsmall",
+/* 00a4 */ ".notdef",
+/* 00a5 */ ".notdef",
+/* 00a6 */ "Scaronsmall",
+/* 00a7 */ "Zcaronsmall",
+/* 00a8 */ "Dieresissmall",
+/* 00a9 */ "Brevesmall",
+/* 00aa */ "Caronsmall",
+/* 00ab */ ".notdef",
+/* 00ac */ "Dotaccentsmall",
+/* 00ad */ ".notdef",
+/* 00ae */ ".notdef",
+/* 00af */ "Macronsmall",
+/* 00b0 */ ".notdef",
+/* 00b1 */ ".notdef",
+/* 00b2 */ "figuredash",
+/* 00b3 */ "hypheninferior",
+/* 00b4 */ ".notdef",
+/* 00b5 */ ".notdef",
+/* 00b6 */ "Ogoneksmall",
+/* 00b7 */ "Ringsmall",
+/* 00b8 */ "Cedillasmall",
+/* 00b9 */ ".notdef",
+/* 00ba */ ".notdef",
+/* 00bb */ ".notdef",
+/* 00bc */ "onequarter",
+/* 00bd */ "onehalf",
+/* 00be */ "threequarters",
+/* 00bf */ "questiondownsmall",
+/* 00c0 */ "oneeighth",
+/* 00c1 */ "threeeighths",
+/* 00c2 */ "fiveeighths",
+/* 00c3 */ "seveneighths",
+/* 00c4 */ "onethird",
+/* 00c5 */ "twothirds",
+/* 00c6 */ ".notdef",
+/* 00c7 */ ".notdef",
+/* 00c8 */ "zerosuperior",
+/* 00c9 */ "onesuperior",
+/* 00ca */ "twosuperior",
+/* 00cb */ "threesuperior",
+/* 00cc */ "foursuperior",
+/* 00cd */ "fivesuperior",
+/* 00ce */ "sixsuperior",
+/* 00cf */ "sevensuperior",
+/* 00d0 */ "eightsuperior",
+/* 00d1 */ "ninesuperior",
+/* 00d2 */ "zeroinferior",
+/* 00d3 */ "oneinferior",
+/* 00d4 */ "twoinferior",
+/* 00d5 */ "threeinferior",
+/* 00d6 */ "fourinferior",
+/* 00d7 */ "fiveinferior",
+/* 00d8 */ "sixinferior",
+/* 00d9 */ "seveninferior",
+/* 00da */ "eightinferior",
+/* 00db */ "nineinferior",
+/* 00dc */ "centinferior",
+/* 00dd */ "dollarinferior",
+/* 00de */ "periodinferior",
+/* 00df */ "commainferior",
+/* 00e0 */ "Agravesmall",
+/* 00e1 */ "Aacutesmall",
+/* 00e2 */ "Acircumflexsmall",
+/* 00e3 */ "Atildesmall",
+/* 00e4 */ "Adieresissmall",
+/* 00e5 */ "Aringsmall",
+/* 00e6 */ "AEsmall",
+/* 00e7 */ "Ccedillasmall",
+/* 00e8 */ "Egravesmall",
+/* 00e9 */ "Eacutesmall",
+/* 00ea */ "Ecircumflexsmall",
+/* 00eb */ "Edieresissmall",
+/* 00ec */ "Igravesmall",
+/* 00ed */ "Iacutesmall",
+/* 00ee */ "Icircumflexsmall",
+/* 00ef */ "Idieresissmall",
+/* 00f0 */ "Ethsmall",
+/* 00f1 */ "Ntildesmall",
+/* 00f2 */ "Ogravesmall",
+/* 00f3 */ "Oacutesmall",
+/* 00f4 */ "Ocircumflexsmall",
+/* 00f5 */ "Otildesmall",
+/* 00f6 */ "Odieresissmall",
+/* 00f7 */ "OEsmall",
+/* 00f8 */ "Oslashsmall",
+/* 00f9 */ "Ugravesmall",
+/* 00fa */ "Uacutesmall",
+/* 00fb */ "Ucircumflexsmall",
+/* 00fc */ "Udieresissmall",
+/* 00fd */ "Yacutesmall",
+/* 00fe */ "Thornsmall",
+/* 00ff */ "Ydieresissmall"
+};
+
+static struct fontdict *MakeEmptyFont(void) {
+ struct fontdict *ret;
+
+ ret = calloc(1,sizeof(struct fontdict));
+ ret->fontinfo = calloc(1,sizeof(struct fontinfo));
+ ret->chars = calloc(1,sizeof(struct pschars));
+ ret->private = calloc(1,sizeof(struct private));
+ ret->private->subrs = calloc(1,sizeof(struct pschars));
+ ret->private->private = calloc(1,sizeof(struct psdict));
+ ret->private->leniv = 4;
+ ret->fontinfo->fstype = -1;
+return( ret );
+}
+
+static struct fontdict *PSMakeEmptyFont(void) {
+ struct fontdict *ret;
+
+ ret = calloc(1,sizeof(struct fontdict));
+ ret->fontinfo = calloc(1,sizeof(struct fontinfo));
+ ret->chars = calloc(1,sizeof(struct pschars));
+ ret->private = calloc(1,sizeof(struct private));
+ ret->private->subrs = calloc(1,sizeof(struct pschars));
+ ret->private->private = calloc(1,sizeof(struct psdict));
+ ret->private->leniv = 4;
+ ret->charprocs = calloc(1,sizeof(struct charprocs));
+ ret->fontinfo->fstype = -1;
+return( ret );
+}
+
+static char *myfgets(char *str, int len, FILE *file) {
+ char *pt, *end;
+ int ch=0;
+
+ for ( pt = str, end = str+len-1; pt<end && (ch=getc(file))!=EOF && ch!='\r' && ch!='\n';
+ *pt++ = ch );
+ if ( ch=='\n' )
+ *pt++ = '\n';
+ else if ( ch=='\r' ) {
+ *pt++ = '\r';
+ if ((ch=getc(file))!='\n' )
+ ungetc(ch,file);
+ else
+ *pt++ = '\n';
+ }
+ if ( pt==str )
+return( NULL );
+ *pt = '\0';
+return( str );
+}
+
+static char *getstring(char *start,FILE *in) {
+ char *end, *ret;
+ int parencnt=0, len=0;
+ char buffer[512];
+
+ forever {
+ while ( *start!='\0' && *start!='(' ) ++start;
+ if ( *start=='\0' ) {
+ if ( myfgets(buffer,sizeof(buffer),in)==NULL )
+return( strdup(""));
+ start = buffer;
+ } else
+ break;
+ }
+ ++start;
+ ret = NULL; len = 1;
+ forever {
+ for ( end = start; *end!='\0' && (*end!=')' || parencnt>0); ++end ) {
+ if ( *end=='\\' && (end[1]=='(' || end[1]==')'))
+ ++end;
+ else if ( *end=='(' ) ++parencnt;
+ else if ( *end==')' ) --parencnt;
+ }
+ if ( end>start ) {
+ if ( ret==NULL )
+ ret = malloc(end-start+1);
+ else
+ ret = realloc(ret,len+end-start);
+ strncpy(ret+len-1,start,end-start);
+ len += end-start;
+ ret[len-1] = '\0';
+ }
+ if ( *end!='\0' )
+ break;
+ if ( myfgets(buffer,sizeof(buffer),in)==NULL )
+return( ret );
+ start = buffer;
+ }
+return( ret );
+}
+
+static char *gettoken(char *start) {
+ char *end, *ret;
+
+ while ( *start!='\0' && *start!='/' ) ++start;
+ if ( *start=='/' ) ++start;
+ for ( end = start; *end!='\0' && !isspace(*end) && *end!='[' && *end!='/' && *end!='{' && *end!='(' ; ++end );
+ ret = malloc(end-start+1);
+ if ( end>start )
+ strncpy(ret,start,end-start);
+ ret[end-start] = '\0';
+return( ret );
+}
+
+static int getbool(char *start) {
+
+ while ( isspace(*start) ) ++start;
+ if ( *start=='T' || *start=='t' )
+return( 1 );
+
+return( 0 );
+}
+
+static void fillintarray(int *array,char *start,int maxentries) {
+ int i;
+ char *end;
+
+ while ( *start!='\0' && *start!='[' && *start!='{' ) ++start;
+ if ( *start=='[' || *start=='{' ) ++start;
+ for ( i=0; i<maxentries && *start!=']' && *start!='}'; ++i ) {
+ array[i] = (int) strtod(start,&end);
+ if ( start==end )
+return;
+ start = end;
+ while ( isspace(*start) ) ++start;
+ }
+}
+
+static void filldoublearray(double *array,char *start,int maxentries) {
+ int i;
+ char *end;
+
+ while ( *start!='\0' && *start!='[' && *start!='{' ) ++start;
+ if ( *start=='[' || *start=='{' ) ++start;
+ for ( i=0; i<maxentries && *start!=']' && *start!='}'; ++i ) {
+ while ( isspace( *start )) ++start;
+ if ( isdigit(*start) || *start=='-' || *start=='.' )
+ array[i] = strtod(start,&end);
+ else if ( strncmp(start,"div",3)==0 && i>=2 ) {
+ /* Some of Luc Devroye's fonts have a "div" in the FontMatrix */
+ array[i-2] /= array[i-1];
+ i -= 2;
+ end = start+3;
+ } else
+return;
+ if ( start==end )
+return;
+ start = end;
+ while ( isspace(*start) ) ++start;
+ }
+}
+
+static void InitDict(struct psdict *dict,char *line) {
+ while ( *line!='/' && *line!='\0' ) ++line;
+ while ( !isspace(*line) && *line!='\0' ) ++line;
+ dict->cnt += strtol(line,NULL,10);
+ if ( dict->next>0 ) { int i; /* Shouldn't happen, but did in a bad file */
+ dict->keys = realloc(dict->keys,dict->cnt*sizeof(char *));
+ dict->values = realloc(dict->values,dict->cnt*sizeof(char *));
+ for ( i=dict->next; i<dict->cnt; ++i ) {
+ dict->keys[i] = NULL; dict->values[i] = NULL;
+ }
+ } else {
+ dict->keys = calloc(dict->cnt,sizeof(char *));
+ dict->values = calloc(dict->cnt,sizeof(char *));
+ }
+}
+
+static void InitChars(struct pschars *chars,char *line) {
+ while ( *line!='/' && *line!='\0' ) ++line;
+ while ( !isspace(*line) && *line!='\0' ) ++line;
+ chars->cnt = strtol(line,NULL,10);
+ if ( chars->cnt>0 ) {
+ chars->keys = calloc(chars->cnt,sizeof(char *));
+ chars->values = calloc(chars->cnt,sizeof(char *));
+ chars->lens = calloc(chars->cnt,sizeof(int));
+ }
+}
+
+static void InitCharProcs(struct charprocs *cp, char *line) {
+ while ( *line!='/' && *line!='\0' ) ++line;
+ while ( !isspace(*line) && *line!='\0' ) ++line;
+ cp->cnt = strtol(line,NULL,10);
+ if ( cp->cnt>0 ) {
+ cp->keys = calloc(cp->cnt,sizeof(char *));
+ cp->values = NULL;
+ }
+}
+
+static int mycmp(char *str,char *within, char *end ) {
+ while ( within<end ) {
+ if ( *str!=*within )
+return( *str-*within );
+ ++str; ++within;
+ }
+return( *str=='\0'?0:1 );
+}
+
+static void ContinueValue(struct fontparse *fp, struct psdict *dict, char *line) {
+ int incomment = false;
+
+ while ( *line ) {
+ if ( !fp->instring && fp->depth==0 &&
+ (strncmp(line,"def",3)==0 ||
+ strncmp(line,"|-",2)==0 || strncmp(line,"ND",2)==0)) {
+ while ( 1 ) {
+ while ( fp->vpt>fp->vbuf+1 && isspace(fp->vpt[-1]) )
+ --fp->vpt;
+ if ( fp->vpt>fp->vbuf+8 && strncmp(fp->vpt-8,"noaccess",8)==0 )
+ fp->vpt -= 8;
+ else if ( fp->vpt>fp->vbuf+8 && strncmp(fp->vpt-8,"readonly",8)==0 )
+ fp->vpt -= 8;
+ else if ( fp->vpt>fp->vbuf+4 && strncmp(fp->vpt-4,"bind",4)==0 )
+ fp->vpt -= 4;
+ else
+ break;
+ }
+ /* In some URW fonts (Nimbus Sans L, n019003l) we get a complex */
+ /* expression rather than just an array. This is ok. The expression */
+ /* converts itself into an array. We could just truncate to the */
+ /* default array, but I don't see any reason to do so */
+ if ( fp->pending_parse!=NULL ) {
+ *fp->pending_parse = copyn(fp->vbuf,fp->vpt-fp->vbuf);
+ fp->pending_parse = NULL;
+ } else {
+ dict->values[dict->next] = copyn(fp->vbuf,fp->vpt-fp->vbuf);
+ ++dict->next;
+ }
+ fp->vpt = fp->vbuf;
+ fp->multiline = false;
+return;
+ }
+ if ( fp->vpt>=fp->vmax ) {
+ int len = fp->vmax-fp->vbuf+1000, off=fp->vpt-fp->vbuf;
+ fp->vbuf = realloc(fp->vbuf,len);
+ fp->vpt = fp->vbuf+off;
+ fp->vmax = fp->vbuf+len;
+ }
+ if ( fp->instring ) {
+ if ( *line==')' ) --fp->instring;
+ } else if ( incomment ) {
+ /* Do Nothing */;
+ } else if ( *line=='(' )
+ ++fp->instring;
+ else if ( *line=='%' )
+ incomment = true;
+ else if ( *line=='[' || *line=='{' )
+ ++fp->depth;
+ else if ( *line=='}' || *line==']' )
+ --fp->depth;
+ *fp->vpt++ = *line++;
+ }
+}
+
+static void AddValue(struct fontparse *fp, struct psdict *dict, char *line, char *endtok) {
+ char *pt;
+
+ if ( dict!=NULL ) {
+ if ( dict->next>=dict->cnt ) {
+ dict->cnt += 10;
+ dict->keys = realloc(dict->keys,dict->cnt*sizeof(char *));
+ dict->values = realloc(dict->values,dict->cnt*sizeof(char *));
+ }
+ dict->keys[dict->next] = copyn(line+1,endtok-(line+1));
+ }
+ pt = line+strlen(line)-1;
+ while ( isspace(*endtok)) ++endtok;
+ while ( pt>endtok && isspace(*pt)) --pt;
+ ++pt;
+ if ( strncmp(pt-3,"def",3)==0 )
+ pt -= 3;
+ else if ( strncmp(pt-2,"|-",2)==0 || strncmp(pt-2,"ND",2)==0 )
+ pt -= 2;
+ else {
+ fp->multiline = true;
+ ContinueValue(fp,dict,endtok);
+return;
+ }
+ forever {
+ while ( pt-1>endtok && isspace(pt[-1])) --pt;
+ if ( pt-8>endtok && strncmp(pt-8,"noaccess",8)==0 )
+ pt -= 8;
+ else if ( pt-8>endtok && strncmp(pt-8,"readonly",8)==0 )
+ pt -= 8;
+ else if ( pt-4>endtok && strncmp(pt-4,"bind",4)==0 )
+ pt -= 4;
+ else
+ break;
+ }
+ if ( dict!=NULL ) {
+ dict->values[dict->next] = copyn(endtok,pt-endtok);
+ ++dict->next;
+ } else {
+ *fp->pending_parse = copyn(endtok,pt-endtok);
+ fp->pending_parse = NULL;
+ }
+}
+
+static int hex(int ch1, int ch2) {
+ if ( ch1>='0' && ch1<='9' )
+ ch1 -= '0';
+ else if ( ch1>='a' )
+ ch1 -= 'a'-10;
+ else
+ ch1 -= 'A'-10;
+ if ( ch2>='0' && ch2<='9' )
+ ch2 -= '0';
+ else if ( ch2>='a' )
+ ch2 -= 'a'-10;
+ else
+ ch2 -= 'A'-10;
+return( (ch1<<4)|ch2 );
+}
+
+unsigned short r;
+#define c1 52845
+#define c2 22719
+
+static void initcode(void) {
+ r = 55665;
+}
+
+static int decode(unsigned char cypher) {
+ unsigned char plain = ( cypher ^ (r>>8));
+ r = (cypher + r) * c1 + c2;
+return( plain );
+}
+
+static void dumpzeros(FILE *out, unsigned char *zeros, int zcnt) {
+ while ( --zcnt >= 0 )
+ fputc(*zeros++,out);
+}
+
+static void decodestr(unsigned char *str, int len) {
+ unsigned short r = 4330;
+ unsigned char plain, cypher;
+
+ while ( len-->0 ) {
+ cypher = *str;
+ plain = ( cypher ^ (r>>8));
+ r = (cypher + r) * c1 + c2;
+ *str++ = plain;
+ }
+}
+
+static void findstring(struct fontparse *fp,struct pschars *subrs,int index,char *nametok,char *str) {
+ char buffer[1024], *bpt, *bs, *end = buffer+sizeof(buffer)-1;
+ int val;
+
+ while ( isspace(*str)) ++str;
+ if ( *str=='(' ) {
+ ++str;
+ bpt = buffer;
+ while ( *str!=')' ) {
+ if ( *str!='\\' )
+ val = *str++;
+ else {
+ if ( isdigit( *++str )) {
+ val = *str++-'0';
+ if ( isdigit( *str )) {
+ val = (val<<3) | (*str++-'0');
+ if ( isdigit( *str ))
+ val = (val<<3) | (*str++-'0');
+ }
+ } else
+ val = *str++;
+ }
+ if ( bpt<end )
+ *bpt++ = val;
+ }
+ decodestr((unsigned char *) buffer,bpt-buffer);
+ bs = buffer + fp->fd->private->leniv;
+ subrs->lens[index] = bpt-bs;
+ subrs->keys[index] = strdup(nametok);
+ subrs->values[index] = malloc(bpt-bs);
+ memcpy(subrs->values[index],bs,bpt-bs);
+ if ( index>=subrs->next ) subrs->next = index+1;
+ }
+}
+
+static char *rmbinary(char *line) {
+ char *pt;
+
+ for ( pt=line; *pt; ++pt ) {
+ if (( *pt<' ' || *pt>=0x7f ) && *pt!='\n' ) {
+ if ( strlen(pt)>5 ) {
+ pt[0] = '.';
+ pt[1] = '.';
+ pt[2] = '.';
+ pt[3] = '\n';
+ pt[4] = '\0';
+ } else {
+ pt[0] = '\n';
+ pt[1] = '\0';
+ }
+ break;
+ }
+ }
+return( line );
+}
+
+static void parseline(struct fontparse *fp,char *line,FILE *in) {
+ char buffer[200], *pt, *endtok;
+
+ while ( *line==' ' || *line=='\t' ) ++line;
+ if ( line[0]=='%' && !fp->multiline )
+return;
+
+ if ( fp->inencoding && strncmp(line,"dup",3)==0 ) {
+ /* Metamorphasis has multiple entries on a line */
+ while ( strncmp(line,"dup",3)==0 ) {
+ char *end;
+ int pos = strtol(line+3,&end,10);
+ line = end;
+ while ( isspace( *line )) ++line;
+ if ( *line=='/' ) ++line;
+ for ( pt = buffer; !isspace(*line); *pt++ = *line++ );
+ *pt = '\0';
+ if ( pos>=0 && pos<256 )
+ fp->fd->encoding[pos] = strdup(buffer);
+ while ( isspace(*line)) ++line;
+ if ( strncmp(line,"put",3)==0 ) line+=3;
+ while ( isspace(*line)) ++line;
+ }
+return;
+ } else if ( fp->inencoding && strstr(line,"for")!=NULL && strstr(line,"/.notdef")!=NULL ) {
+ /* the T1 spec I've got doesn't allow for this, but I've seen it anyway*/
+ /* 0 1 255 {1 index exch /.notdef put} for */
+ /* 0 1 31 { 1 index exch /.notdef put } bind for */
+ int i;
+ for ( i=0; i<256; ++i )
+ if ( fp->fd->encoding[i]==NULL )
+ fp->fd->encoding[i] = strdup(".notdef");
+return;
+ } else if ( fp->inencoding && strstr(line,"Encoding")!=NULL && strstr(line,"put")!=NULL ) {
+ /* Saw a type 3 font with lines like "Encoding 1 /_a0 put" */
+ char *end;
+ int pos;
+ while ( isspace(*line)) ++line;
+ if ( strncmp(line,"Encoding ",9)==0 ) {
+ line+=9;
+ pos = strtol(line,&end,10);
+ line = end;
+ while ( isspace(*line)) ++line;
+ if ( *line=='/' ) {
+ ++line;
+ for ( pt = buffer; !isspace(*line); *pt++ = *line++ );
+ *pt = '\0';
+ if ( pos>=0 && pos<256 )
+ fp->fd->encoding[pos] = strdup(buffer);
+ }
+ }
+return;
+ } else if ( fp->insubs ) {
+ struct pschars *subrs = fp->fd->private->subrs;
+ while ( isspace(*line)) ++line;
+ if ( strncmp(line,"dup ",4)==0 ) {
+ int i;
+ char *ept;
+ for ( line += 4; *line==' '; ++line );
+ i = strtol(line,&ept,10);
+ if ( fp->ignore )
+ /* Do Nothing */;
+ else if ( i<subrs->cnt ) {
+ findstring(fp,subrs,i,NULL,ept);
+ } else if ( !fp->alreadycomplained ) {
+ fprintf( stderr, "Index too big (must be <%d) |%s", subrs->cnt, rmbinary(line));
+ fp->alreadycomplained = true;
+ }
+ } else if ( strncmp(line, "readonly put", 12)==0 || strncmp(line, "ND", 2)==0 || strncmp(line, "|-", 2)==0 ) {
+ fp->insubs = false;
+ fp->ignore = false;
+ } else if ( *line=='\n' || *line=='\0' ) {
+ /* Ignore blank lines */;
+ } else if ( !fp->alreadycomplained ) {
+ fprintf( stderr, "Didn't understand |%s", rmbinary(line) );
+ fp->alreadycomplained = true;
+ }
+ } else if ( fp->inchars ) {
+ struct pschars *chars = fp->fd->chars;
+ while ( isspace(*line)) ++line;
+ if ( strncmp(line,"end",3)==0 )
+ fp->ignore = fp->inchars = false;
+ else if ( *line!='\n' || *line=='\0' )
+ /* Ignore it */;
+ else if ( *line!='/' || !(isalpha(line[1]) || line[1]=='.')) {
+ fprintf( stderr, "No name for CharStrings dictionary |%s", rmbinary(line) );
+ fp->alreadycomplained = true;
+ } else if ( fp->ignore ) {
+ /* Do Nothing */;
+ } else if ( chars->next>=chars->cnt )
+ fprintf( stderr, "Too many entries in CharStrings dictionary |%s", rmbinary(line) );
+ else {
+ int i = chars->next;
+ char *namestrt = ++line;
+ while ( isalnum(*line) || *line=='.' ) ++line;
+ *line = '\0';
+ findstring(fp,chars,i,namestrt,line+1);
+ }
+ }
+ fp->inencoding = 0;
+
+ while ( isspace(*line)) ++line;
+ endtok = NULL;
+ if ( *line=='/' )
+ for ( endtok=line+1; !isspace(*endtok) && *endtok!='(' &&
+ *endtok!='{' && *endtok!='[' && *endtok!='\0'; ++endtok );
+
+ if ( strstr(line,"/shareddict")!=NULL && strstr(line,"where")!=NULL ) {
+ fp->infi = fp->inbb = fp->inmetrics = fp->inmetrics2 = false;
+ fp->inprivate = fp->inblendprivate = fp->inblendfi = false;
+ fp->skipping_mbf = true;
+return;
+ }
+
+ if ( mycmp("Encoding",line+1,endtok)==0 && !fp->doneencoding ) {
+ if ( strstr(endtok,"StandardEncoding")!=NULL ) {
+ setStdEnc(fp->fd->encoding);
+ fp->fd->isadobestd = true;
+ } else if ( strstr(endtok,"ISOLatin1Encoding")!=NULL ) {
+ setLatin1Enc(fp->fd->encoding);
+ } else {
+ fp->inencoding = 1;
+ }
+ fp->infi = fp->inprivate = fp->inbb = fp->inmetrics = fp->inmetrics2 = false;
+ fp->doneencoding = true;
+ } else if ( mycmp("BoundingBoxes",line+1,endtok)==0 ) {
+ fp->infi = fp->inprivate = fp->inencoding = fp->inmetrics = fp->inmetrics2 = false;
+ fp->inbb = true;
+ } else if ( mycmp("Metrics",line+1,endtok)==0 ) {
+ fp->infi = fp->inprivate = fp->inbb = fp->inencoding = fp->inmetrics2 = false;
+ fp->inmetrics = true;
+ fp->fd->metrics = calloc(1,sizeof(struct psdict));
+ fp->fd->metrics->cnt = strtol(endtok,NULL,10);
+ fp->fd->metrics->keys = malloc(fp->fd->metrics->cnt*sizeof(char *));
+ fp->fd->metrics->values = malloc(fp->fd->metrics->cnt*sizeof(char *));
+ } else if ( strstr(line,"/Private")!=NULL && strstr(line,"/Blend")!=NULL ) {
+ fp->infi = fp->inbb = fp->inmetrics = fp->inmetrics2 = false;
+ fp->inprivate = fp->inblendprivate = fp->inblendfi = false;
+ fp->inblendprivate = 1;
+ fp->fd->blendprivate = calloc(1,sizeof(struct psdict));
+ InitDict(fp->fd->blendprivate,line);
+return;
+ } else if ( strstr(line,"/FontInfo")!=NULL && strstr(line,"/Blend")!=NULL ) {
+ fp->infi = fp->inbb = fp->inmetrics = fp->inmetrics2 = false;
+ fp->inprivate = fp->inblendprivate = fp->inblendfi = false;
+ fp->inblendfi = 1;
+ fp->fd->blendfontinfo = calloc(1,sizeof(struct psdict));
+ InitDict(fp->fd->blendfontinfo,line);
+return;
+ } else if ( fp->infi ) {
+ if ( fp->multiline ) {
+ ContinueValue(fp,NULL,line);
+return;
+ }
+ if ( endtok==NULL && strncmp(line,"end", 3)==0 ) {
+ fp->infi=0;
+return;
+ } else if ( endtok==NULL )
+return;
+ if ( mycmp("version",line+1,endtok)==0 )
+ fp->fd->fontinfo->version = getstring(endtok,in);
+ else if ( mycmp("Notice",line+1,endtok)==0 ) {
+ if ( fp->fd->fontinfo->notice!=NULL )
+ free(fp->fd->fontinfo->notice);
+ fp->fd->fontinfo->notice = getstring(endtok,in);
+ } else if ( mycmp("Copyright",line+1,endtok)==0 ) { /* cff spec allows for copyright and notice */
+ if ( fp->fd->fontinfo->notice!=NULL )
+ free(fp->fd->fontinfo->notice);
+ fp->fd->fontinfo->notice = getstring(endtok,in);
+ } else if ( mycmp("FullName",line+1,endtok)==0 ) {
+ if ( fp->fd->fontinfo->fullname==NULL )
+ fp->fd->fontinfo->fullname = getstring(endtok,in);
+ else
+ getstring(endtok,in);
+ } else if ( mycmp("FamilyName",line+1,endtok)==0 )
+ fp->fd->fontinfo->familyname = getstring(endtok,in);
+ else if ( mycmp("Weight",line+1,endtok)==0 )
+ fp->fd->fontinfo->weight = getstring(endtok,in);
+ else if ( mycmp("ItalicAngle",line+1,endtok)==0 )
+ fp->fd->fontinfo->italicangle = strtod(endtok,NULL);
+ else if ( mycmp("UnderlinePosition",line+1,endtok)==0 )
+ fp->fd->fontinfo->underlineposition = strtod(endtok,NULL);
+ else if ( mycmp("UnderlineThickness",line+1,endtok)==0 )
+ fp->fd->fontinfo->underlinethickness = strtod(endtok,NULL);
+ else if ( mycmp("isFixedPitch",line+1,endtok)==0 )
+ fp->fd->fontinfo->isfixedpitch = getbool(endtok);
+ else if ( mycmp("em",line+1,endtok)==0 )
+ fp->fd->fontinfo->em = strtol(endtok,NULL,10);
+ else if ( mycmp("ascent",line+1,endtok)==0 )
+ fp->fd->fontinfo->ascent = strtol(endtok,NULL,10);
+ else if ( mycmp("descent",line+1,endtok)==0 )
+ fp->fd->fontinfo->descent = strtol(endtok,NULL,10);
+ else if ( mycmp("FSType",line+1,endtok)==0 )
+ fp->fd->fontinfo->fstype = strtol(endtok,NULL,10);
+ else if ( mycmp("BlendDesignPositions",line+1,endtok)==0 ) {
+ fp->pending_parse = &fp->fd->fontinfo->blenddesignpositions;
+ AddValue(fp,NULL,line,endtok);
+ } else if ( mycmp("BlendDesignMap",line+1,endtok)==0 ) {
+ fp->pending_parse = &fp->fd->fontinfo->blenddesignmap;
+ AddValue(fp,NULL,line,endtok);
+ } else if ( mycmp("BlendAxisTypes",line+1,endtok)==0 ) {
+ fp->pending_parse = &fp->fd->fontinfo->blendaxistypes;
+ AddValue(fp,NULL,line,endtok);
+ } else if ( !fp->alreadycomplained ) {
+ fprintf( stderr, "Didn't understand |%s", rmbinary(line) );
+ fp->alreadycomplained = true;
+ }
+ } else if ( fp->inblend ) {
+ if ( endtok==NULL ) {
+ if ( *line!='/' && strstr(line,"end")!=NULL )
+ fp->inblend = false;
+return;
+ }
+ /* Ignore anything in the blend dict defn */
+ } else if ( fp->inblendprivate || fp->inblendfi ) {
+ struct psdict *subdict = fp->inblendfi ? fp->fd->blendfontinfo : fp->fd->blendprivate;
+ if ( fp->multiline ) {
+ ContinueValue(fp,subdict,line);
+return;
+ } else if ( endtok==NULL ) {
+ if ( *line!='/' && strstr(line,"end")!=NULL ) {
+ fp->inblendprivate = fp->inblendfi = false;
+ fp->inprivate = true;
+ }
+return;
+ } else
+ AddValue(fp,subdict,line,endtok);
+ } else if ( fp->inprivate ) {
+ if ( strstr(line,"/CharStrings")!=NULL && strstr(line,"dict")!=NULL ) {
+ if ( fp->fd->chars->next==0 ) {
+ InitChars(fp->fd->chars,line);
+ fp->ignore = false;
+ } else {
+ fp->ignore = true;
+ fprintf( stderr, "Ignoring duplicate /CharStrings entry\n" );
+ }
+ fp->inchars = 1;
+ fp->insubs = 0;
+return;
+ } else if ( strstr(line,"/Subrs")!=NULL ) {
+ if ( fp->fd->private->subrs->next>0 ) {
+ fp->ignore = true;
+ fprintf( stderr, "Ignoring duplicate /Subrs entry\n" );
+ } else {
+ InitChars(fp->fd->private->subrs,line);
+ fp->ignore = false;
+ }
+ fp->insubs = 1;
+ fp->inchars = 0;
+return;
+ } else if ( fp->multiline ) {
+ ContinueValue(fp,fp->fd->private->private,line);
+return;
+ }
+ if ( endtok==NULL ) {
+ char *pt = line;
+ if ( *pt!='/' ) while ( (pt=strstr(pt,"end"))!=NULL ) {
+ if ( fp->inchars ) fp->inchars = false;
+ else fp->inprivate = false;
+ pt += 3;
+ }
+return;
+ }
+ if ( mycmp("ND",line+1,endtok)==0 || mycmp("|-",line+1,endtok)==0 ||
+ mycmp("NP",line+1,endtok)==0 || mycmp("|",line+1,endtok)==0 ||
+ mycmp("RD",line+1,endtok)==0 || mycmp("-|",line+1,endtok)==0 ||
+ mycmp("password",line+1,endtok)==0 ||
+ mycmp("MinFeature",line+1,endtok)==0 )
+ /* These conveigh no information, but are required */;
+ else if ( mycmp("UniqueID",line+1,endtok)==0 ) {
+ if ( fp->fd->uniqueid==0 )
+ fp->fd->uniqueid = strtol(endtok,NULL,10);
+ } else {
+ if ( mycmp("lenIV",line+1,endtok)==0 )
+ fp->fd->private->leniv = strtol(endtok,NULL,10); /* We need this value */
+ AddValue(fp,fp->fd->private->private,line,endtok);
+ }
+ } else if ( fp->incidsysteminfo ) {
+ if ( endtok==NULL && strncmp(line,"end", 3)==0 ) {
+ fp->incidsysteminfo=0;
+return;
+ } else if ( endtok==NULL )
+return;
+ if ( mycmp("Registry",line+1,endtok)==0 )
+ fp->fd->registry = getstring(endtok,in);
+ else if ( mycmp("Ordering",line+1,endtok)==0 )
+ fp->fd->ordering = getstring(endtok,in);
+ else if ( mycmp("Supplement",line+1,endtok)==0 ) /* cff spec allows for copyright and notice */
+ fp->fd->supplement = strtol(endtok,NULL,0);
+ } else {
+ if ( strstr(line,"/Private")!=NULL && strstr(line,"dict")!=NULL ) {
+ fp->infi = fp->inbb = fp->inmetrics = fp->inmetrics2 = false;
+ fp->inprivate = fp->inblendprivate = fp->inblendfi = false;
+ if ( strstr(line,"/Blend")!=NULL ) {
+ fp->inblendprivate = 1;
+ fp->fd->blendprivate = calloc(1,sizeof(struct psdict));
+ InitDict(fp->fd->blendprivate,line);
+ } else {
+ fp->inprivate = 1;
+ InitDict(fp->fd->private->private,line);
+ }
+return;
+ } else if ( strstr(line,"/FontInfo")!=NULL && strstr(line,"dict")!=NULL ) {
+ fp->inprivate = fp->inbb = fp->inmetrics = fp->inmetrics2 = false;
+ fp->infi = fp->inblendprivate = fp->inblendfi = false;
+ if ( strstr(line,"/Blend")!=NULL ) {
+ fp->inblendfi = 1;
+ fp->fd->blendfontinfo = calloc(1,sizeof(struct psdict));
+ InitDict(fp->fd->blendfontinfo,line);
+ } else {
+ fp->infi = 1;
+ }
+return;
+ } else if ( strstr(line,"/Blend")!=NULL && strstr(line,"dict")!=NULL ) {
+ fp->inprivate = fp->inbb = fp->inmetrics = fp->inmetrics2 = false;
+ fp->infi = fp->inblendprivate = fp->inblendfi = false;
+ fp->inblend = true;
+return;
+ } else if ( strstr(line,"/CharStrings")!=NULL && strstr(line,"dict")!=NULL ) {
+ if ( fp->fd->chars->next==0 ) {
+ InitChars(fp->fd->chars,line);
+ fp->ignore = false;
+ } else {
+ fp->ignore = true;
+ fprintf( stderr, "Ignoring duplicate /CharStrings entry\n" );
+ }
+ fp->inchars = 1;
+ fp->insubs = 0;
+ fp->infi = fp->inprivate = fp->inbb = fp->inmetrics = fp->inmetrics2 = false;
+ fp->inblendprivate = fp->inblendfi = false;
+return;
+ } else if ( mycmp("/CharProcs",line,endtok)==0 ) {
+ InitCharProcs(fp->fd->charprocs,line);
+ fp->infi = fp->inprivate = fp->inbb = fp->inmetrics = fp->inmetrics2 = false;
+ fp->insubs = 0;
+return;
+ } else if ( strstr(line,"/CIDSystemInfo")!=NULL ) {
+ fp->incidsysteminfo = 1;
+return;
+ } else if ( fp->inmetrics ) {
+ if ( endtok!=NULL )
+ AddValue(fp,fp->fd->metrics,line,endtok);
+return;
+ } else if ( fp->inbb ) {
+ /* Ignore it */;
+return;
+ }
+
+ if ( fp->multiline ) {
+ ContinueValue(fp,NULL,line);
+return;
+ }
+
+ if ( endtok==NULL ) {
+ if ( fp->skipping_mbf )
+ ;
+ else if ( fp->fdindex!=-1 && strstr(line,"end")!=NULL ) {
+ if ( ++fp->fdindex>=fp->mainfd->fdcnt )
+ fp->fd = fp->mainfd;
+ else
+ fp->fd = fp->mainfd->fds[fp->fdindex];
+ }
+return;
+ }
+ if ( mycmp("FontName",line+1,endtok)==0 ) {
+ if ( fp->fd->fontname==NULL )
+ fp->fd->fontname = gettoken(endtok);
+ else
+ gettoken(endtok); /* skip it */
+ } else if ( mycmp("PaintType",line+1,endtok)==0 )
+ fp->fd->painttype = strtol(endtok,NULL,10);
+ else if ( mycmp("FontType",line+1,endtok)==0 )
+ fp->fd->fonttype = strtol(endtok,NULL,10);
+ else if ( mycmp("FontMatrix",line+1,endtok)==0 ) {
+ if ( fp->fd->fontmatrix[0]==0 )
+ filldoublearray(fp->fd->fontmatrix,endtok,6);
+ else {
+ double temp[6];
+ filldoublearray(temp,endtok,6);
+ }
+ } else if ( mycmp("LanguageLevel",line+1,endtok)==0 )
+ fp->fd->languagelevel = strtol(endtok,NULL,10);
+ else if ( mycmp("WMode",line+1,endtok)==0 )
+ fp->fd->wmode = strtol(endtok,NULL,10);
+ else if ( mycmp("FontBBox",line+1,endtok)==0 )
+ filldoublearray(fp->fd->fontbb,endtok,4);
+ else if ( mycmp("UniqueID",line+1,endtok)==0 ) {
+ if ( fp->fd->uniqueid==0 )
+ fp->fd->uniqueid = strtol(endtok,NULL,10);
+ } else if ( mycmp("UniqueId",line+1,endtok)==0 ) {
+ fprintf(stderr,"This font contains a \"UniqueId\" variable, but the correct name for it is\n\t\"UniqueID\" (postscript is case concious)\n" );
+ if ( fp->fd->uniqueid==0 )
+ fp->fd->uniqueid = strtol(endtok,NULL,10);
+ } else if ( mycmp("XUID",line+1,endtok)==0 ) {
+ if ( fp->fd->xuid[0]==0 )
+ fillintarray(fp->fd->xuid,endtok,20);
+ } else if ( mycmp("StrokeWidth",line+1,endtok)==0 )
+ fp->fd->strokewidth = strtod(endtok,NULL);
+ else if ( mycmp("WeightVector",line+1,endtok)==0 ) {
+ fp->pending_parse = &fp->fd->weightvector;
+ AddValue(fp,NULL,line,endtok);
+ } else if ( mycmp("$Blend",line+1,endtok)==0 ) {
+ fp->pending_parse = &fp->fd->blendfunc;
+ AddValue(fp,NULL,line,endtok);
+ } else if ( strstr( line,"/NormalizeDesignVector" )!=NULL ) {
+ fp->pending_parse = &fp->fd->ndv;
+ AddValue(fp,NULL,line,endtok);
+ } else if ( strstr( line,"/ConvertDesignVector" )!=NULL ) {
+ fp->pending_parse = &fp->fd->cdv;
+ AddValue(fp,NULL,line,endtok);
+ } else if ( mycmp("BuildChar",line+1,endtok)==0 )
+ /* Do Nothing */;
+ else if ( mycmp("BuildGlyph",line+1,endtok)==0 )
+ /* Do Nothing */;
+ else if ( mycmp("CIDFontName",line+1,endtok)==0 )
+ fp->fd->cidfontname = gettoken(endtok);
+ else if ( mycmp("CIDFontVersion",line+1,endtok)==0 ) {
+ fp->fd->cidversion = strtod(endtok,NULL);
+#if 0
+ if ( fp->fd->fontinfo->version==NULL ) {
+ char temp[40];
+ sprintf(temp,"%f", fp->fd->cidversion);
+ fp->fd->fontinfo->version = strdup(temp);
+ }
+#endif
+ } else if ( mycmp("CIDFontType",line+1,endtok)==0 )
+ fp->fd->cidfonttype = strtol(endtok,NULL,10);
+ else if ( mycmp("UIDBase",line+1,endtok)==0 )
+ fp->fd->uniqueid = strtol(endtok,NULL,10);
+ else if ( mycmp("CIDMapOffset",line+1,endtok)==0 )
+ fp->fd->mapoffset = strtol(endtok,NULL,10);
+ else if ( mycmp("FDBytes",line+1,endtok)==0 )
+ fp->fd->fdbytes = strtol(endtok,NULL,10);
+ else if ( mycmp("GDBytes",line+1,endtok)==0 )
+ fp->fd->gdbytes = strtol(endtok,NULL,10);
+ else if ( mycmp("CIDCount",line+1,endtok)==0 )
+ fp->fd->cidcnt = strtol(endtok,NULL,10);
+ else if ( mycmp("FDArray",line+1,endtok)==0 ) { int i;
+ fp->mainfd = fp->fd;
+ fp->fd->fdcnt = strtol(endtok,NULL,10);
+ fp->fd->fds = calloc(fp->fd->fdcnt,sizeof(struct fontdict *));
+ for ( i=0; i<fp->fd->fdcnt; ++i )
+ fp->fd->fds[i] = MakeEmptyFont();
+ fp->fdindex = 0;
+ fp->fd = fp->fd->fds[0];
+ } else if ( mycmp("FontSetInit",line+1,endtok)==0 ) {
+ fp->iscff = true;
+ fp->iscid = false;
+ } else if ( mycmp("CIDInit",line+1,endtok)==0 ) {
+ fp->iscid = true;
+ fp->iscff = false;
+ } else if ( fp->skipping_mbf ) { /* Skip over the makeblendedfont defn in a multimaster font */
+ /* Do Nothing */
+ } else if ( !fp->alreadycomplained ) {
+ fprintf( stderr, "Didn't understand |%s", rmbinary(line) );
+ fp->alreadycomplained = true;
+ }
+ }
+}
+
+static void addinfo(struct fontparse *fp,char *line,char *tok,char *binstart,int binlen,FILE *in) {
+ char *pt;
+
+ decodestr((unsigned char *) binstart,binlen);
+ binstart += fp->fd->private->leniv;
+ binlen -= fp->fd->private->leniv;
+
+ retry:
+ if ( fp->insubs ) {
+ struct pschars *chars = /*fp->insubs ?*/ fp->fd->private->subrs /*: fp->fd->private->othersubrs*/;
+ while ( isspace(*line)) ++line;
+ if ( strncmp(line,"dup ",4)==0 ) {
+ int i = strtol(line+4,NULL,10);
+ if ( fp->ignore )
+ /* Do Nothing */;
+ else if ( i<chars->cnt ) {
+ if ( chars->values[i]!=NULL )
+ fprintf( stderr, "Duplicate definition of subroutine %d\n", i );
+ chars->lens[i] = binlen;
+ chars->values[i] = malloc(binlen);
+ memcpy(chars->values[i],binstart,binlen);
+ if ( i>=chars->next ) chars->next = i+1;
+ } else if ( !fp->alreadycomplained ) {
+ fprintf( stderr, "Index too big (must be <%d) |%s", chars->cnt, rmbinary(line));
+ fp->alreadycomplained = true;
+ }
+ } else if ( !fp->alreadycomplained ) {
+ fprintf( stderr, "Didn't understand |%s", rmbinary(line) );
+ fp->alreadycomplained = true;
+ }
+ } else if ( fp->inchars ) {
+ struct pschars *chars = fp->fd->chars;
+ if ( *tok=='\0' )
+ fprintf( stderr, "No name for CharStrings dictionary |%s", rmbinary(line) );
+ else if ( fp->ignore )
+ /* Do Nothing */;
+ else if ( chars->next>=chars->cnt )
+ fprintf( stderr, "Too many entries in CharStrings dictionary |%s", rmbinary(line) );
+ else {
+ int i = chars->next;
+ chars->lens[i] = binlen;
+ chars->keys[i] = strdup(tok);
+ chars->values[i] = malloc(binlen);
+ memcpy(chars->values[i],binstart,binlen);
+ ++chars->next;
+ }
+ } else if ( !fp->alreadycomplained ) {
+ /* Special hacks for known badly formatted fonts */
+ if ( strstr(line,"/CharStrings")!=NULL ) {
+ for ( pt=line; *pt!='/'; ++pt );
+ pt = strchr(pt+1,'/');
+ if ( pt!=NULL )
+ *pt = '\0';
+ parseline(fp,line,in);
+ if ( pt!=NULL ) {
+ *pt = '/';
+ line = pt;
+ goto retry;
+ }
+return;
+ } else if ( strstr(line,"/Subrs")!=NULL ) {
+ pt = strstr(line,"dup");
+ if ( pt!=NULL )
+ *pt = '\0';
+ parseline(fp,line,in);
+ if ( pt!=NULL ) {
+ *pt = 'd';
+ line = pt;
+ goto retry;
+ }
+return;
+ }
+ fprintf( stderr, "Shouldn't be in addinfo |%s", rmbinary(line) );
+ fp->alreadycomplained = true;
+ }
+}
+
+/* In the book the token which starts a character description is always RD but*/
+/* it's just the name of a subroutine which is defined in the private diction*/
+/* and it could be anything. in one case it was "-|" (hyphen bar) so we can't*/
+/* just look for RD we must be a bit smarter and figure out what the token is*/
+/* (oh. I see now. it's allowed to be either one "RD" or "-|", but nothing else*/
+/* right) */
+/* It's defined as {string currentfile exch readstring pop} so look for that */
+/* Except that in gsf files we've also got "/-!{string currentfile exch readhexstring pop} readonly def" */
+/* NOTE: readhexstring!!! */
+/* And in files generated by GNU fontutils */
+static int glorpline(struct fontparse *fp, FILE *temp, char *rdtok) {
+ static char *buffer=NULL, *end;
+ char *pt, *binstart;
+ int binlen;
+ int ch;
+ int innum, val=0, inbinary, cnt=0, inr, wasspace, nownum, nowr, nowspace, sptok;
+ char *rdline = "{string currentfile exch readstring pop}", *rpt;
+ char *rdline2 = "{string currentfile exch readhexstring pop}";
+ char *tokpt = NULL, *rdpt;
+ char temptok[255];
+ int intok, first;
+ int wasminus=false, isminus, nibble, firstnibble, inhex;
+ int willbehex = false;
+
+ ch = getc(temp);
+ if ( ch==EOF )
+return( 0 );
+ ungetc(ch,temp);
+
+ if ( buffer==NULL ) {
+ buffer = malloc(3000);
+ end = buffer+3000;
+ }
+ innum = inr = 0; wasspace = 0; inbinary = 0; rpt = NULL; rdpt = NULL;
+ inhex = 0;
+ pt = buffer; binstart=NULL; binlen = 0; intok=0; sptok=0; first=1;
+ temptok[0] = '\0';
+ while ( (ch=getc(temp))!=EOF ) {
+ if ( pt>=end ) {
+ char *old = buffer;
+ int len = (end-buffer)+2000;
+ buffer = realloc(buffer,len);
+ end = buffer+len;
+ pt = buffer+(pt-old);
+ if ( binstart!=NULL )
+ binstart = buffer+(binstart-old);
+ }
+ *pt++ = ch;
+ isminus = ch=='-' && wasspace;
+ nownum = nowspace = nowr = 0;
+ if ( rpt!=NULL && ch!=*rpt && ch=='h' && rpt-rdline>25 && rpt-rdline<30 &&
+ rdline2[rpt-rdline]=='h' ) {
+ rpt = rdline2 + (rpt-rdline);
+ willbehex = true;
+ }
+ if ( inbinary ) {
+ if ( --cnt==0 )
+ inbinary = 0;
+ } else if ( inhex ) {
+ if ( isxdigit(ch)) {
+ int h;
+ if ( isdigit(ch)) h = ch-'0';
+ else if ( ch>='a' && ch<='f' ) h = ch-'a'+10;
+ else h = ch-'A'+10;
+ if ( firstnibble ) {
+ nibble = h;
+ --pt;
+ } else {
+ pt[-1] = (nibble<<4)|h;
+ if ( --cnt==0 )
+ inbinary = inhex = 0;
+ }
+ firstnibble = !firstnibble;
+ } else {
+ --pt;
+ /* skip everything not hex */
+ }
+ } else if ( ch=='/' ) {
+ intok = 1;
+ tokpt = temptok;
+ } else if ( intok && !isspace(ch) && ch!='{' && ch!='[' ) {
+ *tokpt++ = ch;
+ } else if ( (intok||sptok) && (ch=='{' || ch=='[')) {
+ *tokpt = '\0';
+ rpt = rdline+1;
+ intok = sptok = 0;
+ } else if ( intok ) {
+ *tokpt = '\0';
+ intok = 0;
+ sptok = 1;
+ } else if ( sptok && isspace(ch)) {
+ nowspace = 1;
+ if ( ch=='\n' || ch=='\r' )
+ break;
+ } else if ( sptok && !isdigit(ch))
+ sptok = 0;
+ else if ( rpt!=NULL && ch==*rpt ) {
+ if ( *++rpt=='\0' ) {
+ /* it matched the character definition string so this is the */
+ /* token we want to search for */
+ strcpy(rdtok,temptok);
+ fp->useshexstrings = willbehex;
+ rpt = NULL;
+ }
+ } else if ( rpt!=NULL && ch==' ' ) {
+ /* Extra spaces are ok */
+ } else if ( rpt!=NULL ) {
+ rpt = NULL;
+ willbehex = false;
+ } else if ( isdigit(ch)) {
+ sptok = 0;
+ nownum = 1;
+ if ( innum )
+ val = 10*val + ch-'0';
+ else
+ val = ch-'0';
+ } else if ( isspace(ch)) {
+ nowspace = 1;
+ if ( ch=='\n' || ch=='\r' )
+ break;
+ } else if ( wasspace && ch==*rdtok ) {
+ nowr = 1;
+ fp->useshexstrings = willbehex;
+ rdpt = rdtok+1;
+ } else if ( wasspace && ch=='-' ) { /* fonts produced by type1fix seem to define both "RD" and "-|" which confused me. so just respond to either */
+ nowr = 1;
+ fp->useshexstrings = false;
+ rdpt = "|";
+ } else if ( wasspace && ch=='R' ) { /* fonts produced by type1fix seem to define both "RD" and "-|" which confused me. so just respond to either */
+ nowr = 1;
+ fp->useshexstrings = false;
+ rdpt = "D";
+ } else if ( inr && ch==*rdpt ) {
+ if ( *++rdpt =='\0' ) {
+ ch = getc(temp);
+ *pt++ = ch;
+ if ( isspace(ch) && val!=0 ) {
+ inhex = fp->useshexstrings;
+ inbinary = !fp->useshexstrings;
+ firstnibble = true;
+ cnt = val;
+ binstart = pt;
+ binlen = val;
+ }
+ } else
+ nowr = 1;
+ } else if ( wasminus && ch=='!' ) {
+ ch = getc(temp);
+ *pt++ = ch;
+ if ( isspace(ch) && val!=0 ) {
+ inhex = 1;
+ cnt = val;
+ binstart = pt;
+ binlen = val;
+ firstnibble = true;
+ }
+ }
+ innum = nownum; wasspace = nowspace; inr = nowr;
+ wasminus = isminus;
+ first = 0;
+ }
+ *pt = '\0';
+ if ( binstart==NULL ) {
+ parseline(fp,buffer,temp);
+ } else {
+ addinfo(fp,buffer,temptok,binstart,binlen,temp);
+ }
+return( 1 );
+}
+
+static int nrandombytes[4];
+#define EODMARKLEN 16
+
+#define bgetc(extra,in) (*(extra)=='\0' ? getc(in) : (unsigned char ) *(extra)++ )
+
+static void decrypteexec(FILE *in,FILE *temp, int hassectionheads,char *extra) {
+ int ch1, ch2, ch3, ch4, binary;
+ int zcnt;
+ unsigned char zeros[EODMARKLEN+6+1];
+ int sect_len;
+
+ if ( extra==(void *) 5 ) extra = "";
+
+ while ( (ch1=bgetc(extra,in))!=EOF && isspace(ch1));
+ if ( ch1==0200 && hassectionheads ) {
+ /* skip the 6 byte section header in pfb files that follows eexec */
+ ch1 = bgetc(extra,in);
+ sect_len = bgetc(extra,in);
+ sect_len |= bgetc(extra,in)<<8;
+ sect_len |= bgetc(extra,in)<<16;
+ sect_len |= bgetc(extra,in)<<24;
+ sect_len -= 3;
+ ch1 = bgetc(extra,in);
+ }
+ ch2 = bgetc(extra,in); ch3 = bgetc(extra,in); ch4 = bgetc(extra,in);
+ binary = 0;
+ if ( ch1<'0' || (ch1>'9' && ch1<'A') || ( ch1>'F' && ch1<'a') || (ch1>'f') ||
+ ch2<'0' || (ch2>'9' && ch2<'A') || (ch2>'F' && ch2<'a') || (ch2>'f') ||
+ ch3<'0' || (ch3>'9' && ch3<'A') || (ch3>'F' && ch3<'a') || (ch3>'f') ||
+ ch4<'0' || (ch4>'9' && ch4<'A') || (ch4>'F' && ch4<'a') || (ch4>'f') )
+ binary = 1;
+ if ( ch1==EOF || ch2==EOF || ch3==EOF || ch4==EOF ) {
+return;
+ }
+
+ initcode();
+ if ( binary ) {
+ nrandombytes[0] = decode(ch1);
+ nrandombytes[1] = decode(ch2);
+ nrandombytes[2] = decode(ch3);
+ nrandombytes[3] = decode(ch4);
+ zcnt = 0;
+ while (( ch1=bgetc(extra,in))!=EOF ) {
+ --sect_len;
+ if ( hassectionheads ) {
+ if ( sect_len==0 && ch1==0200 ) {
+ ch1 = bgetc(extra,in);
+ sect_len = bgetc(extra,in);
+ sect_len |= bgetc(extra,in)<<8;
+ sect_len |= bgetc(extra,in)<<16;
+ sect_len |= bgetc(extra,in)<<24;
+ sect_len += 1;
+ if ( ch1=='\1' )
+ break;
+ } else {
+ dumpzeros(temp,zeros,zcnt);
+ zcnt = 0;
+ putc(decode(ch1),temp);
+ }
+ } else {
+ if ( ch1=='0' ) ++zcnt; else {dumpzeros(temp,zeros,zcnt); zcnt = 0; }
+ if ( zcnt>EODMARKLEN )
+ break;
+ if ( zcnt==0 )
+ putc(decode(ch1),temp);
+ else
+ zeros[zcnt-1] = decode(ch1);
+ }
+ }
+ } else {
+ nrandombytes[0] = decode(hex(ch1,ch2));
+ nrandombytes[1] = decode(hex(ch3,ch4));
+ ch1 = bgetc(extra,in); ch2 = bgetc(extra,in); ch3 = bgetc(extra,in); ch4 = bgetc(extra,in);
+ nrandombytes[2] = decode(hex(ch1,ch2));
+ nrandombytes[3] = decode(hex(ch3,ch4));
+ zcnt = 0;
+ while (( ch1=bgetc(extra,in))!=EOF ) {
+ while ( ch1!=EOF && isspace(ch1)) ch1 = bgetc(extra,in);
+ while ( (ch2=bgetc(extra,in))!=EOF && isspace(ch2));
+ if ( ch1=='0' && ch2=='0' ) ++zcnt; else { dumpzeros(temp,zeros,zcnt); zcnt = 0;}
+ if ( zcnt>EODMARKLEN )
+ break;
+ if ( zcnt==0 )
+ putc(decode(hex(ch1,ch2)),temp);
+ else
+ zeros[zcnt-1] = decode(hex(ch1,ch2));
+ }
+ }
+ while (( ch1=bgetc(extra,in))=='0' || isspace(ch1) );
+ if ( ch1!=EOF ) ungetc(ch1,in);
+}
+
+static void decryptagain(struct fontparse *fp,FILE *temp,char *rdtok) {
+ while ( glorpline(fp,temp,rdtok));
+}
+
+static void parsetype3(struct fontparse *fp,FILE *in) {
+ /*PSFontInterpretPS(in,fp->fd->charprocs);*/
+}
+
+static unsigned char *readt1str(FILE *temp,int offset,int len,int leniv) {
+ int i;
+ unsigned char *str, *pt;
+ unsigned short r = 4330;
+ unsigned char plain, cypher;
+ /* The CID spec doesn't mention this, but the type 1 strings are all */
+ /* eexec encrupted (with the nested encryption). Remember leniv varies */
+ /* from fd to fd (potentially) */
+ /* I'm told (by Ian Kemmish) that leniv==-1 => no eexec encryption */
+
+ fseek(temp,offset,SEEK_SET);
+ if ( leniv<0 ) {
+ str = pt = malloc(len+1);
+ for (; i<len; ++i )
+ *pt++ = getc(temp);
+ } else {
+ for ( i=0; i<leniv; ++i ) {
+ cypher = getc(temp);
+ plain = ( cypher ^ (r>>8));
+ r = (cypher + r) * c1 + c2;
+ }
+ str = pt = malloc(len-leniv+1);
+ for (; i<len; ++i ) {
+ cypher = getc(temp);
+ plain = ( cypher ^ (r>>8));
+ r = (cypher + r) * c1 + c2;
+ *pt++ = plain;
+ }
+ }
+ *pt = '\0';
+return( str );
+}
+
+static void figurecids(struct fontparse *fp,FILE *temp) {
+ struct fontdict *fd = fp->mainfd;
+ int i,j,k,val;
+ int *offsets;
+ int cidcnt = fd->cidcnt;
+ int leniv;
+ /* Some cid formats don't have any of these */
+
+ fd->cidstrs = malloc(cidcnt*sizeof(unsigned char *));
+ fd->cidlens = malloc(cidcnt*sizeof(short));
+ fd->cidfds = malloc((cidcnt+1)*sizeof(short));
+ offsets = malloc((cidcnt+1)*sizeof(int));
+
+ fseek(temp,fd->mapoffset,SEEK_SET);
+ for ( i=0; i<=fd->cidcnt; ++i ) {
+ for ( j=val=0; j<fd->fdbytes; ++j )
+ val = (val<<8) + getc(temp);
+ fd->cidfds[i] = val;
+ for ( j=val=0; j<fd->gdbytes; ++j )
+ val = (val<<8) + getc(temp);
+ offsets[i] = val;
+ if ( i!=0 )
+ fd->cidlens[i-1] = offsets[i]-offsets[i-1];
+ }
+
+ for ( i=0; i<fd->cidcnt; ++i ) {
+ if ( fd->cidlens[i]== 0 )
+ fd->cidstrs[i] = NULL;
+ else {
+ fd->cidstrs[i] = readt1str(temp,offsets[i],fd->cidlens[i],
+ fd->fds[fd->cidfds[i]]->private->leniv);
+ fd->cidlens[i] -= fd->fds[fd->cidfds[i]]->private->leniv;
+ }
+ }
+ free(offsets);
+
+ for ( k=0; k<fd->fdcnt; ++k ) {
+ struct private *private = fd->fds[k]->private;
+ char *ssubroff = PSDictHasEntry(private->private,"SubrMapOffset");
+ char *ssdbytes = PSDictHasEntry(private->private,"SDBytes");
+ char *ssubrcnt = PSDictHasEntry(private->private,"SubrCount");
+ int subroff, sdbytes, subrcnt;
+
+ if ( ssubroff!=NULL && ssdbytes!=NULL && ssubrcnt!=NULL &&
+ (subroff=strtol(ssubroff,NULL,10))>=0 &&
+ (sdbytes=strtol(ssdbytes,NULL,10))>0 &&
+ (subrcnt=strtol(ssubrcnt,NULL,10))>0 ) {
+ private->subrs->cnt = subrcnt;
+ private->subrs->values = calloc(subrcnt,sizeof(char *));
+ private->subrs->lens = calloc(subrcnt,sizeof(int));
+ leniv = private->leniv;
+ offsets = malloc((subrcnt+1)*sizeof(int));
+ fseek(temp,subroff,SEEK_SET);
+ for ( i=0; i<=subrcnt; ++i ) {
+ for ( j=val=0; j<sdbytes; ++j )
+ val = (val<<8) + getc(temp);
+ offsets[i] = val;
+ if ( i!=0 )
+ private->subrs->lens[i-1] = offsets[i]-offsets[i-1];
+ }
+ for ( i=0; i<subrcnt; ++i ) {
+ private->subrs->values[i] = readt1str(temp,offsets[i],
+ private->subrs->lens[i],leniv);
+ }
+ private->subrs->next = i;
+ free(offsets);
+ }
+ PSDictRemoveEntry(private->private,"SubrMapOffset");
+ PSDictRemoveEntry(private->private,"SDBytes");
+ PSDictRemoveEntry(private->private,"SubrCount");
+ }
+}
+
+static void dodata( struct fontparse *fp, FILE *in, FILE *temp) {
+ int binary, cnt, len;
+ int ch, ch2;
+ char *pt;
+ char fontsetname[256];
+
+ while ( (ch=getc(in))!='(' && ch!='/' && ch!=EOF );
+ if ( ch=='/' ) {
+ /* There appears to be no provision for a hex encoding here */
+ /* Why can't they use the same format for routines with the same name? */
+ binary = true;
+ for ( pt=fontsetname; (ch=getc(in))!=' ' && ch!=EOF; )
+ if ( pt<fontsetname+sizeof(fontsetname)-1 )
+ *pt++= ch;
+ *pt = '\0';
+ } else {
+ if ( (ch=getc(in))=='B' || ch=='b' ) binary = true;
+ else if ( ch=='H' || ch=='h' ) binary = false;
+ else {
+ binary = true; /* Who knows? */
+ fprintf( stderr, "Failed to parse the StartData command properly\n" );
+ }
+ fontsetname[0] = '\0';
+ }
+ while ( (ch=getc(in))!=')' && ch!=EOF );
+ if ( fscanf( in, "%d", &len )!=1 || len<=0 ) {
+ len = 0;
+ fprintf( stderr, "Failed to parse the StartData command properly, bad cnt\n" );
+ }
+ cnt = len;
+ while ( isspace(ch=getc(in)) );
+ ungetc(ch,in);
+ for ( pt="StartData "; *pt; ++pt )
+ getc(in); /* And if it didn't match, what could I do about it? */
+ if ( binary ) {
+ while ( cnt>0 ) {
+ ch = getc(in);
+ putc(ch,temp);
+ --cnt;
+ }
+ } else {
+ while ( cnt>0 ) {
+ /* Hex data are allowed to contain whitespace */
+ while ( isspace(ch=getc(in)) );
+ while ( isspace(ch2=getc(in)) );
+ ch = hex(ch,ch2);
+ putc(ch,temp);
+ --cnt;
+ }
+ if ( (ch=getc(in))!='>' ) ungetc(ch,in);
+ }
+ rewind(temp);
+ if ( fp->iscid )
+ figurecids(fp,temp);
+ else {
+ /*fp->fd->sf = _CFFParse(temp,len,fontsetname);*/
+ fp->fd->wascff = true;
+ }
+}
+
+static void doubledecrypt(struct fontparse *fp,FILE *in, FILE *temp) {
+ char buffer[256];
+ int first, hassectionheads;
+ char rdtok[20];
+ int saw_blend = false;
+
+ strcpy(rdtok,"RD");
+
+ first = 1; hassectionheads = 0;
+ while ( myfgets(buffer,sizeof(buffer),in)!=NULL ) {
+ if ( strstr(buffer, "Blend")!=NULL )
+ saw_blend = true;
+ if ( first && buffer[0]=='\200' ) {
+ hassectionheads = 1;
+ fp->fd->wasbinary = true;
+ parseline(fp,buffer+6,in);
+ } else if ( strstr(buffer,"CharProcs")!=NULL && strstr(buffer,"begin")!=NULL ) {
+ parsetype3(fp,in);
+return;
+ } else if ( !fp->iscid ) {
+ if ( saw_blend )
+ parseline(fp,buffer,in);
+ /* But if it's a multi master font, don't do the special private hack */
+ else if ( strstr(buffer,"/CharStrings")!=NULL && strstr(buffer,"begin")!=NULL ) {
+ /* gsf files are not eexec encoded, but the charstrings are encoded*/
+ InitChars(fp->fd->chars,buffer);
+ fp->inchars = 1;
+ decryptagain(fp,in,rdtok);
+return;
+ } else if ( strstr(buffer,"/Subrs")!=NULL && strstr(buffer,"array")!=NULL ) {
+ /* Same case as above */
+ InitChars(fp->fd->private->subrs,buffer);
+ fp->insubs = 1;
+ decryptagain(fp,in,rdtok);
+return;
+ } else if ( strstr(buffer,"/Private")!=NULL && strstr(buffer,"dict")!=NULL ) {
+ /* files produced by GNU fontutils have some of the same issues */
+ fp->inprivate = 1;
+ fp->infi = false;
+ decryptagain(fp,in,rdtok);
+return;
+ } else
+ parseline(fp,buffer,in);
+ } else
+ parseline(fp,buffer,in);
+ first = 0;
+ if ( strstr(buffer,"%%BeginData: ")!=NULL )
+ break;
+ if ( strstr(buffer,"currentfile")!=NULL && strstr(buffer, "eexec")!=NULL ) {
+ fp->skipping_mbf = false;
+ break;
+ }
+ }
+
+ if ( strstr(buffer,"%%BeginData: ")!=NULL ) {
+ /* used by both CID fonts and CFF fonts (and chameleons, whatever they are) */
+ dodata(fp,in,temp);
+ } else {
+ decrypteexec(in,temp,hassectionheads,strstr(buffer, "eexec")+5);
+ rewind(temp);
+ decryptagain(fp,temp,rdtok);
+ while ( myfgets(buffer,sizeof(buffer),in)!=NULL ) {
+ if ( buffer[0]!='\200' || !hassectionheads )
+ parseline(fp,buffer,in);
+ }
+ }
+}
+
+static FontDict *_ReadPSFont(FILE *in) {
+ FILE *temp;
+ struct fontparse fp;
+ char *oldloc;
+
+ temp = tmpfile();
+ if ( temp==NULL ) {
+ fprintf( stderr, "Cannot open a temporary file\n" );
+ fclose(in);
+return(NULL);
+ }
+
+ oldloc = setlocale(LC_NUMERIC,"C");
+ memset(&fp,'\0',sizeof(fp));
+ fp.fd = fp.mainfd = PSMakeEmptyFont();
+ fp.fdindex = -1;
+ doubledecrypt(&fp,in,temp);
+ free(fp.vbuf);
+ setlocale(LC_NUMERIC,oldloc);
+
+ fclose(temp);
+return( fp.fd );
+}
+
+
+static void PSCharsFree(struct pschars *chrs) {
+ int i;
+
+ if ( chrs==NULL )
+return;
+ for ( i=0; i<chrs->next; ++i ) {
+ if ( chrs->keys!=NULL ) free(chrs->keys[i]);
+ free(chrs->values[i]);
+ }
+ free(chrs->lens);
+ free(chrs->keys);
+ free(chrs->values);
+ free(chrs);
+}
+
+static void PSDictFree(struct psdict *dict) {
+ int i;
+
+ if ( dict==NULL )
+return;
+ for ( i=0; i<dict->next; ++i ) {
+ if ( dict->keys!=NULL ) free(dict->keys[i]);
+ free(dict->values[i]);
+ }
+ free(dict->keys);
+ free(dict->values);
+ free(dict);
+}
+
+static void PrivateFree(struct private *prv) {
+ PSCharsFree(prv->subrs);
+#if 1
+ PSDictFree(prv->private);
+#else
+ PSCharsFree(prv->othersubrs);
+ free(prv->minfeature);
+ free(prv->nd);
+ free(prv->np);
+ free(prv->rd);
+#endif
+ free(prv);
+}
+
+static void FontInfoFree(struct fontinfo *fi) {
+ free(fi->familyname);
+ free(fi->fullname);
+ free(fi->notice);
+ free(fi->weight);
+ free(fi->version);
+ free(fi->blenddesignpositions);
+ free(fi->blenddesignmap);
+ free(fi->blendaxistypes);
+ free(fi);
+}
+
+static void PSFontFree(FontDict *fd) {
+ int i;
+
+ if ( fd->encoding!=NULL )
+ for ( i=0; i<256; ++i )
+ free( fd->encoding[i]);
+ free(fd->fontname);
+ free(fd->cidfontname);
+ free(fd->registry);
+ free(fd->ordering);
+ FontInfoFree(fd->fontinfo);
+ PSCharsFree(fd->chars);
+ PrivateFree(fd->private);
+ if ( fd->charprocs!=NULL ) {
+ for ( i=0; i<fd->charprocs->cnt; ++i )
+ free(fd->charprocs->keys[i]);
+ free(fd->charprocs->keys);
+ free(fd->charprocs->values);
+ free(fd->charprocs);
+ }
+ if ( fd->cidstrs!=NULL ) {
+ for ( i=0; i<fd->cidcnt; ++i )
+ free( fd->cidstrs[i]);
+ free(fd->cidstrs);
+ }
+ free(fd->cidlens);
+ free(fd->cidfds);
+ if ( fd->fds!=NULL ) {
+ for ( i=0; i<fd->fdcnt; ++i )
+ PSFontFree(fd->fds[i]);
+ free(fd->fds);
+ }
+ free(fd->blendfunc);
+ free(fd->weightvector);
+ free(fd->cdv);
+ free(fd->ndv);
+
+ PSDictFree(fd->blendprivate);
+ PSDictFree(fd->blendfontinfo);
+
+ free(fd);
+}
+
+static struct bbglyph *FindAdobeGlyph(PSFONT *psfont,int adobe_enc) {
+ char *search_name;
+ struct pschars *chars = psfont->temp;
+ int i;
+
+ if ( adobe_enc>=256 || adobe_enc<0 )
+return( &psfont->glyphs[0] ); /* Return .notdef */
+ search_name = AdobeStandardEncoding[adobe_enc];
+ for ( i=0; i<chars->cnt; ++i ) {
+ if ( strcmp(search_name,chars->keys[i])==0 ) {
+ if ( psfont->glyphs[i].isref )
+return( NULL );
+
+return( &psfont->glyphs[i] );
+ }
+ }
+
+ for ( i=0; i<chars->cnt; ++i ) {
+ if ( strcmp(".notdef",chars->keys[i])==0 )
+return( &psfont->glyphs[i] );
+ }
+
+return( &psfont->glyphs[0] ); /* Return something. font doesn't even have notdef */
+}
+
+static void FindBB(PSFONT *psfont, struct bbglyph *bb, unsigned char *type1, int len,
+ struct pschars *subrs, char *name ) {
+ double stack[50]; int sp=0, v; /* Type1 stack is about 25 long, Type2 stack is 48 */
+ double transient[32];
+ struct { double x,y; } current;
+ double dx, dy, dx2, dy2, dx3, dy3;
+ /* subroutines may be nested to a depth of 10 */
+ struct substate { unsigned char *type1; int len; int subnum; } pcstack[11];
+ int pcsp=0;
+ double pops[30];
+ int popsp=0;
+ int base, polarity;
+ struct pschars *s;
+ int first = true;
+ int lsidebearing;
+ struct bbglyph *bb1, *bb2;
+ int offx, offy;
+
+ current.x = current.y = 0;
+ while ( len>0 ) {
+ if ( sp>48 ) {
+ fprintf( stderr, "Stack got too big in %s\n", name );
+ sp = 48;
+ }
+ base = 0;
+ --len;
+ if ( (v = *type1++)>=32 ) {
+ if ( v<=246) {
+ stack[sp++] = v - 139;
+ } else if ( v<=250 ) {
+ stack[sp++] = (v-247)*256 + *type1++ + 108;
+ --len;
+ } else if ( v<=254 ) {
+ stack[sp++] = -(v-251)*256 - *type1++ - 108;
+ --len;
+ } else {
+ int val = (*type1<<24) | (type1[1]<<16) | (type1[2]<<8) | type1[3];
+ stack[sp++] = val;
+ type1 += 4;
+ len -= 4;
+ }
+ } else if ( v==28 ) {
+ stack[sp++] = (short) ((type1[0]<<8) | type1[1]);
+ type1 += 2;
+ len -= 2;
+ /* In the Dict tables of CFF, a 5byte fixed value is prefixed by a */
+ /* 29 code. In Type2 strings the prefix is 255. */
+ } else if ( v==12 ) {
+ v = *type1++;
+ --len;
+ switch ( v ) {
+ case 0: /* dotsection */
+ sp = 0;
+ break;
+ case 1: /* vstem3 */ /* specifies three v hints zones at once */
+ if ( sp<6 ) fprintf(stderr, "Stack underflow on vstem3 in %s\n", name );
+ /* according to the standard, if there is a vstem3 there can't */
+ /* be any vstems, so there can't be any confusion about hint order */
+ /* so we don't need to worry about unblended stuff */
+ sp = 0;
+ break;
+ case 2: /* hstem3 */ /* specifies three h hints zones at once */
+ if ( sp<6 ) fprintf(stderr, "Stack underflow on hstem3 in %s\n", name );
+ sp = 0;
+ break;
+ case 6: /* seac */ /* build accented characters */
+ seac:
+ if ( sp<5 ) fprintf(stderr, "Stack underflow on seac in %s\n", name );
+ /* stack[0] must be the lsidebearing of the accent. I'm not sure why */
+ bb1 = FindAdobeGlyph(psfont,stack[3]);
+ bb2 = FindAdobeGlyph(psfont,stack[4]);
+ offx = stack[1] - (stack[0]-lsidebearing);
+ offy = stack[2];
+ if ( bb1==NULL || bb2==NULL )
+ bb->isref = true;
+ else {
+ bb->top = bb1->top > bb2->top+offy ? bb1->top : bb2->top+offy;
+ bb->bottom = bb1->bottom < bb2->bottom+offy ? bb1->bottom : bb2->bottom+offy;
+ bb->right = bb1->right > bb2->right+offx ? bb1->right : bb2->right+offx;
+ bb->left = bb1->left < bb2->left+offx ? bb1->left : bb2->left+offx;
+ }
+ sp = 0;
+ break;
+ case 7: /* sbw */ /* generalized width/sidebearing command */
+ if ( sp<4 ) fprintf(stderr, "Stack underflow on sbw in %s\n", name );
+ lsidebearing = stack[0];
+ /* stack[1] is lsidebearing y (only for vertical writing styles, CJK) */
+ bb->hadvance = stack[2];
+ /* stack[3] is height (for vertical writing styles, CJK) */
+ sp = 0;
+ break;
+ case 5: case 9: case 14: case 26:
+ if ( sp<1 ) fprintf(stderr, "Stack underflow on unary operator in %s\n", name );
+ switch ( v ) {
+ case 5: stack[sp-1] = (stack[sp-1]==0); break; /* not */
+ case 9: if ( stack[sp-1]<0 ) stack[sp-1]= -stack[sp-1]; break; /* abs */
+ case 14: stack[sp-1] = -stack[sp-1]; break; /* neg */
+ case 26: stack[sp-1] = sqrt(stack[sp-1]); break; /* sqrt */
+ }
+ break;
+ case 3: case 4: case 10: case 11: case 12: case 15: case 24:
+ if ( sp<2 ) fprintf(stderr, "Stack underflow on binary operator in %s\n", name );
+ else switch ( v ) {
+ case 3: /* and */
+ stack[sp-2] = (stack[sp-1]!=0 && stack[sp-2]!=0);
+ break;
+ case 4: /* and */
+ stack[sp-2] = (stack[sp-1]!=0 || stack[sp-2]!=0);
+ break;
+ case 10: /* add */
+ stack[sp-2] += stack[sp-1];
+ break;
+ case 11: /* sub */
+ stack[sp-2] -= stack[sp-1];
+ break;
+ case 12: /* div */
+ stack[sp-2] /= stack[sp-1];
+ break;
+ case 24: /* mul */
+ stack[sp-2] *= stack[sp-1];
+ break;
+ case 15: /* eq */
+ stack[sp-2] = (stack[sp-1]==stack[sp-2]);
+ break;
+ }
+ --sp;
+ break;
+ case 22: /* ifelse */
+ if ( sp<4 ) fprintf(stderr, "Stack underflow on ifelse in %s\n", name );
+ else {
+ if ( stack[sp-2]>stack[sp-1] )
+ stack[sp-4] = stack[sp-3];
+ sp -= 3;
+ }
+ break;
+ case 23: /* random */
+ /* This function returns something (0,1]. It's not clear to me*/
+ /* if rand includes 0 and RAND_MAX or not, but this approach */
+ /* should work no matter what */
+ do {
+ stack[sp] = (rand()/(RAND_MAX-1));
+ } while ( stack[sp]==0 || stack[sp]>1 );
+ ++sp;
+ break;
+ case 16: /* callothersubr */
+ /* stack[sp-1] is the number of the thing to call in the othersubr array */
+ /* stack[sp-2] is the number of args to grab off our stack and put on the */
+ /* double postscript stack */
+ if ( sp<2 || sp < 2+stack[sp-2] ) {
+ fprintf(stderr, "Stack underflow on callothersubr in %s\n", name );
+ sp = 0;
+ } else {
+ int tot = stack[sp-2], k;
+ popsp = 0;
+ for ( k=sp-3; k>=sp-2-tot; --k )
+ pops[popsp++] = stack[k];
+ /* othersubrs 0-3 must be interpretted. 0-2 are Flex, 3 is Hint Replacement */
+ /* othersubrs 12,13 are for counter hints. We don't need to */
+ /* do anything to ignore them */
+ /* Subroutines 14-18 are multiple master blenders. We need */
+ /* to pay attention to them too */
+ switch ( (int) stack[sp-1] ) {
+ case 3: {
+ /* when we weren't capabable of hint replacement we */
+ /* punted by putting 3 on the stack (T1 spec page 70) */
+ /* subroutine 3 is a noop */
+ pops[popsp-1] = 3;
+ } break;
+ case 1: { /* Flex */
+ } break;
+ case 2: {
+ /* No op */;
+ } break;
+ case 0:
+ break;
+ }
+ sp = k+1;
+ }
+ break;
+ case 20: /* put */
+ if ( sp<2 ) fprintf(stderr, "Too few items on stack for put in %s\n", name );
+ else if ( stack[sp-1]<0 || stack[sp-1]>=32 ) fprintf(stderr,"Reference to transient memory out of bounds in put in %s\n", name );
+ else {
+ transient[(int)stack[sp-1]] = stack[sp-2];
+ sp -= 2;
+ }
+ break;
+ case 21: /* get */
+ if ( sp<1 ) fprintf(stderr, "Too few items on stack for get in %s\n", name );
+ else if ( stack[sp-1]<0 || stack[sp-1]>=32 ) fprintf(stderr,"Reference to transient memory out of bounds in put in %s\n", name );
+ else
+ stack[sp-1] = transient[(int)stack[sp-1]];
+ break;
+ case 17: /* pop */
+ /* pops something from the postscript stack and pushes it on ours */
+ /* used to get a return value from an othersubr call */
+ /* Bleah. Adobe wants the pops to return the arguments if we */
+ /* don't understand the call. What use is the subroutine then?*/
+ if ( popsp<=0 )
+ fprintf(stderr, "Pop stack underflow on pop in %s\n", name );
+ else
+ stack[sp++] = pops[--popsp];
+ break;
+ case 18: /* drop */
+ if ( sp>0 ) --sp;
+ break;
+ case 27: /* dup */
+ if ( sp>=1 ) {
+ stack[sp] = stack[sp-1];
+ ++sp;
+ }
+ break;
+ case 28: /* exch */
+ if ( sp>=2 ) {
+ double temp = stack[sp-1];
+ stack[sp-1] = stack[sp-2]; stack[sp-2] = temp;
+ }
+ break;
+ case 29: /* index */
+ if ( sp>=1 ) {
+ int index = stack[--sp];
+ if ( index<0 || sp<index+1 )
+ fprintf( stderr, "Index out of range in %s\n", name );
+ else {
+ stack[sp] = stack[sp-index-1];
+ ++sp;
+ }
+ }
+ break;
+ case 30: /* roll */
+ if ( sp>=2 ) {
+ int j = stack[sp-1], N=stack[sp-2];
+ if ( N>sp || j>=N || j<0 || N<0 )
+ fprintf( stderr, "roll out of range in %s\n", name );
+ else if ( j==0 || N==0 )
+ /* No op */;
+ else {
+ double *temp = malloc(N*sizeof(double));
+ int i;
+ for ( i=0; i<N; ++i )
+ temp[i] = stack[sp-N+i];
+ for ( i=0; i<N; ++i )
+ stack[sp-N+i] = temp[(i+j)%N];
+ free(temp);
+ }
+ }
+ break;
+ case 33: /* setcurrentpoint */
+ if ( sp<2 ) fprintf(stderr, "Stack underflow on setcurrentpoint in %s\n", name );
+ else {
+ current.x = stack[0];
+ current.y = stack[1];
+ if ( current.y>bb->top ) bb->top = current.y;
+ if ( current.y<bb->bottom ) bb->bottom = current.y;
+ if ( current.x>bb->right ) bb->right = current.x;
+ if ( current.x<bb->left ) bb->left = current.x;
+ }
+ sp = 0;
+ break;
+ case 34: /* hflex */
+ case 35: /* flex */
+ case 36: /* hflex1 */
+ case 37: /* flex1 */
+ sp = 0;
+ break;
+ default:
+ fprintf( stderr, "Uninterpreted opcode 12,%d in %s\n", v, name );
+ break;
+ }
+ } else switch ( v ) {
+ case 1: /* hstem */
+ case 18: /* hstemhm */
+ base = 0;
+ if ( sp&1 ) {
+ bb->hadvance = stack[0];
+ base=1;
+ }
+ if ( sp-base<2 )
+ fprintf(stderr, "Stack underflow on hstem in %s\n", name );
+ /* stack[0] is absolute y for start of horizontal hint */
+ /* (actually relative to the y specified as lsidebearing y in sbw*/
+ /* stack[1] is relative y for height of hint zone */
+ sp = 0;
+ break;
+ case 19: /* hintmask */
+ case 20: /* cntrmask */
+ /* If there's anything on the stack treat it as a vstem hint */
+ base = 0;
+ case 3: /* vstem */
+ case 23: /* vstemhm */
+ break;
+ case 14: /* endchar */
+ /* endchar is allowed to terminate processing even within a subroutine */
+ pcsp = 0;
+ if ( sp==4 ) {
+ /* In Type2 strings endchar has a depreciated function of doing */
+ /* a seac (which doesn't exist at all). Except enchar takes */
+ /* 4 args and seac takes 5. Bleah */
+ stack[4] = stack[3]; stack[3] = stack[2]; stack[2] = stack[1]; stack[1] = stack[0];
+ stack[0] = 0;
+ sp = 5;
+ goto seac;
+ }
+ /* the docs say that endchar must be the last command in a char */
+ /* (or the last command in a subroutine which is the last in the */
+ /* char) So in theory if there's anything left we should complain*/
+ /* In practice though, the EuroFont has a return statement after */
+ /* the endchar in a subroutine. So we won't try to catch that err*/
+ /* and just stop. */
+ /* Adobe says it's not an error, but I can't understand their */
+ /* logic */
+ goto done;
+ break;
+ case 13: /* hsbw (set left sidebearing and width) */
+ if ( sp<2 ) fprintf(stderr, "Stack underflow on hsbw in %s\n", name );
+ lsidebearing = stack[0];
+ current.x = stack[0]; /* sets the current point too */
+ bb->hadvance = stack[1];
+ sp = 0;
+ break;
+ case 9: /* closepath */
+ sp = 0;
+ break;
+ case 21: /* rmoveto */
+ case 22: /* hmoveto */
+ case 4: /* vmoveto */
+ case 5: /* rlineto */
+ case 6: /* hlineto */
+ case 7: /* vlineto */
+ polarity = 0;
+ base = 0;
+ while ( base<sp ) {
+ dx = dy = 0;
+ if ( v==5 || v==21 ) {
+ if ( sp<2 ) fprintf(stderr, "Stack underflow on rlineto/rmoveto in %s\n", name );
+ dx = stack[base++];
+ dy = stack[base++];
+ } else if ( (v==6 && !(polarity&1)) || (v==7 && (polarity&1)) || v==22 ) {
+ if ( sp<1 ) fprintf(stderr, "Stack underflow on hlineto/hmoveto in %s\n", name );
+ dx = stack[base++];
+ } else /*if ( (v==7 && !(parity&1)) || (v==6 && (parity&1) || v==4 )*/ {
+ if ( sp<1 ) fprintf(stderr, "Stack underflow on vlineto/vmoveto in %s\n", name );
+ dy = stack[base++];
+ }
+ ++polarity;
+ current.x += dx; current.y += dy;
+ if ( first ) {
+ bb->top = bb->bottom = current.y;
+ bb->left = bb->right = current.x;
+ first = false;
+ } else {
+ if ( current.y>bb->top ) bb->top = current.y;
+ if ( current.y<bb->bottom ) bb->bottom = current.y;
+ if ( current.x>bb->right ) bb->right = current.x;
+ if ( current.x<bb->left ) bb->left = current.x;
+ }
+ }
+ sp = 0;
+ break;
+ case 25: /* rlinecurve */
+ base = 0;
+ while ( sp>base+6 ) {
+ current.x += stack[base++]; current.y += stack[base++];
+ if ( current.y>bb->top ) bb->top = current.y;
+ if ( current.y<bb->bottom ) bb->bottom = current.y;
+ if ( current.x>bb->right ) bb->right = current.x;
+ if ( current.x<bb->left ) bb->left = current.x;
+ }
+ case 24: /* rcurveline */
+ case 8: /* rrcurveto */
+ case 31: /* hvcurveto */
+ case 30: /* vhcurveto */
+ case 27: /* hhcurveto */
+ case 26: /* vvcurveto */
+ polarity = 0;
+ while ( sp>base+2 ) {
+ dx = dy = dx2 = dy2 = dx3 = dy3 = 0;
+ if ( v==8 || v==25 || v==24 ) {
+ if ( sp<6+base ) {
+ fprintf(stderr, "Stack underflow on rrcurveto in %s\n", name );
+ base = sp;
+ } else {
+ dx = stack[base++];
+ dy = stack[base++];
+ dx2 = stack[base++];
+ dy2 = stack[base++];
+ dx3 = stack[base++];
+ dy3 = stack[base++];
+ }
+ } else if ( v==27 ) { /* hhcurveto */
+ if ( sp<4+base ) {
+ fprintf(stderr, "Stack underflow on hhcurveto in %s\n", name );
+ base = sp;
+ } else {
+ if ( (sp-base)&1 ) dy = stack[base++];
+ dx = stack[base++];
+ dx2 = stack[base++];
+ dy2 = stack[base++];
+ dx3 = stack[base++];
+ }
+ } else if ( v==26 ) { /* vvcurveto */
+ if ( sp<4+base ) {
+ fprintf(stderr, "Stack underflow on hhcurveto in %s\n", name );
+ base = sp;
+ } else {
+ if ( (sp-base)&1 ) dx = stack[base++];
+ dy = stack[base++];
+ dx2 = stack[base++];
+ dy2 = stack[base++];
+ dy3 = stack[base++];
+ }
+ } else if ( (v==31 && !(polarity&1)) || (v==30 && (polarity&1)) ) {
+ if ( sp<4+base ) {
+ fprintf(stderr, "Stack underflow on hvcurveto in %s\n", name );
+ base = sp;
+ } else {
+ dx = stack[base++];
+ dx2 = stack[base++];
+ dy2 = stack[base++];
+ dy3 = stack[base++];
+ if ( sp==base+1 )
+ dx3 = stack[base++];
+ }
+ } else /*if ( (v==30 && !(polarity&1)) || (v==31 && (polarity&1)) )*/ {
+ if ( sp<4+base ) {
+ fprintf(stderr, "Stack underflow on vhcurveto in %s\n", name );
+ base = sp;
+ } else {
+ dy = stack[base++];
+ dx2 = stack[base++];
+ dy2 = stack[base++];
+ dx3 = stack[base++];
+ if ( sp==base+1 )
+ dy3 = stack[base++];
+ }
+ }
+ ++polarity;
+ current.x += dx; current.y += dy;
+ if ( current.y>bb->top ) bb->top = current.y;
+ if ( current.y<bb->bottom ) bb->bottom = current.y;
+ if ( current.x>bb->right ) bb->right = current.x;
+ if ( current.x<bb->left ) bb->left = current.x;
+ current.x += dx2; current.y += dy2;
+ if ( current.y>bb->top ) bb->top = current.y;
+ if ( current.y<bb->bottom ) bb->bottom = current.y;
+ if ( current.x>bb->right ) bb->right = current.x;
+ if ( current.x<bb->left ) bb->left = current.x;
+ current.x += dx3; current.y += dy3;
+ if ( current.y>bb->top ) bb->top = current.y;
+ if ( current.y<bb->bottom ) bb->bottom = current.y;
+ if ( current.x>bb->right ) bb->right = current.x;
+ if ( current.x<bb->left ) bb->left = current.x;
+ }
+ if ( v==24 ) {
+ current.x += stack[base++]; current.y += stack[base++];
+ if ( current.y>bb->top ) bb->top = current.y;
+ if ( current.y<bb->bottom ) bb->bottom = current.y;
+ if ( current.x>bb->right ) bb->right = current.x;
+ if ( current.x<bb->left ) bb->left = current.x;
+ }
+ sp = 0;
+ break;
+ case 29: /* callgsubr */
+ case 10: /* callsubr */
+ /* stack[sp-1] contains the number of the subroutine to call */
+ if ( sp<1 ) {
+ fprintf(stderr, "Stack underflow on callsubr in %s\n", name );
+ break;
+ } else if ( pcsp>10 ) {
+ fprintf( stderr, "Too many subroutine calls in %s\n", name );
+ break;
+ }
+ s=subrs;
+ if ( s==NULL || stack[sp-1]>=s->cnt || stack[sp-1]<0 ||
+ s->values[(int) stack[sp-1]]==NULL )
+ fprintf(stderr,"Subroutine number out of bounds in %s\n", name );
+ else {
+ pcstack[pcsp].type1 = type1;
+ pcstack[pcsp].len = len;
+ pcstack[pcsp].subnum = stack[sp-1];
+ ++pcsp;
+ type1 = s->values[(int) stack[sp-1]];
+ len = s->lens[(int) stack[sp-1]];
+ }
+ if ( --sp<0 ) sp = 0;
+ break;
+ case 11: /* return */
+ /* return from a subr outine */
+ if ( pcsp<1 ) fprintf(stderr, "return when not in subroutine in %s\n", name );
+ else {
+ --pcsp;
+ type1 = pcstack[pcsp].type1;
+ len = pcstack[pcsp].len;
+ }
+ break;
+ default:
+ fprintf( stderr, "Uninterpreted opcode %d in %s\n", v, name );
+ break;
+ }
+ }
+ done:
+ if ( pcsp!=0 )
+ fprintf(stderr, "end of subroutine reached with no return in %s\n", name );
+}
+
+
+void ParsePfb(FILE *pfb,PSFONT *psfont) {
+ FontDict *fd = _ReadPSFont(pfb);
+ char *pt;
+ int i,j, anyrefs, attempts;
+
+ memset(psfont,0,sizeof(PSFONT));
+ if ( fd==NULL || fd->fontname==NULL )
+return;
+ psfont->glyphcnt = fd->chars->cnt;
+ psfont->glyphs = calloc(psfont->glyphcnt,sizeof(struct bbglyph));
+ psfont->temp = fd->chars;
+ for ( i=0; i<256; ++i ) {
+ for ( j=fd->chars->cnt-1; j>=0; --j )
+ if ( strcmp(fd->encoding[i],fd->chars->keys[j])==0 )
+ break;
+ if ( j==-1 )
+ for ( j=fd->chars->cnt-1; j>0; --j )
+ if ( strcmp(".notdef",fd->chars->keys[j])==0 )
+ break;
+ psfont->encoding[i] = j;
+ }
+ psfont->fontname = strdup(fd->fontname);
+ if ( fd->fontinfo!=NULL ) {
+ psfont->familyname = strdup(fd->fontinfo->familyname);
+ psfont->fullname = strdup(fd->fontinfo->fullname);
+ psfont->weight = strdup(fd->fontinfo->weight);
+ psfont->notice = strdup(fd->fontinfo->notice);
+ psfont->version = strdup(fd->fontinfo->version);
+ psfont->italicangle = fd->fontinfo->italicangle;
+ } else {
+ psfont->familyname = strdup(fd->fontname);
+ if ( (pt = strchr(psfont->familyname,'-'))!=NULL )
+ *pt = '\0';
+ psfont->fullname = strdup(fd->fontname);
+ psfont->weight = strdup("Regular");
+ }
+ psfont->isadobestd = fd->isadobestd;
+ psfont->em = 1000;
+ if ( fd->fontmatrix[0]!=0 )
+ psfont->em = 1.0/fd->fontmatrix[0];
+ memcpy(psfont->fbb,fd->fontbb,sizeof(psfont->fbb));
+
+ anyrefs = true;
+ for ( i=0; i<psfont->glyphcnt; ++i )
+ psfont->glyphs[i].isref = true;
+ attempts = 0;
+ while ( anyrefs && attempts<psfont->glyphcnt ) {
+ anyrefs = false;
+ for ( i=0; i<psfont->glyphcnt; ++i ) if ( psfont->glyphs[i].isref ) {
+ psfont->glyphs[i].isref = false;
+ FindBB(psfont,&psfont->glyphs[i],fd->chars->values[i],fd->chars->lens[i],
+ fd->private->subrs, fd->chars->keys[i]);
+ if ( psfont->glyphs[i].isref )
+ anyrefs = true;
+ else
+ psfont->glyphs[i].glyphname = strdup(fd->chars->keys[i]);
+ }
+ ++attempts;
+ }
+ for ( i=0; i<psfont->glyphcnt; ++i ) if ( !psfont->glyphs[i].isref ) {
+ if ( strcmp(psfont->glyphs[i].glyphname,"X")==0 )
+ psfont->ch = psfont->glyphs[i].top;
+ else if ( strcmp(psfont->glyphs[i].glyphname,"x")==0 )
+ psfont->xh = psfont->glyphs[i].top;
+ else if ( strcmp(psfont->glyphs[i].glyphname,"l")==0 )
+ psfont->as = psfont->glyphs[i].top;
+ else if ( strcmp(psfont->glyphs[i].glyphname,"p")==0 )
+ psfont->ds = psfont->glyphs[i].bottom;
+ }
+ for ( i=0; i<psfont->glyphcnt; ++i ) if ( psfont->glyphs[i].isref ) {
+ -- psfont->glyphcnt;
+ memcpy(&psfont->glyphs[i],&psfont->glyphs[i+1],(psfont->glyphcnt-i)*sizeof(struct bbglyph));
+ }
+ PSFontFree(fd);
+}
diff --git a/macfonts.h b/macfonts.h
index e05199e..160af3d 100644
--- a/macfonts.h
+++ b/macfonts.h
@@ -58,9 +58,29 @@ typedef struct fond {
short offset; /* 4.12 */
} *kerns;
} *stylekerns;
+ char *psnames[48];
+ char *family;
struct fond *next;
} FOND;
+typedef struct PSFONT {
+ char *fontname, *familyname, *weight, *fullname, *notice, *version;
+ double italicangle;
+ double em;
+ double fbb[4];
+ int as, ds, ch, xh;
+ int isadobestd;
+ int glyphcnt;
+ struct bbglyph {
+ char *glyphname;
+ int top, bottom, left, right;
+ int hadvance;
+ int isref;
+ } *glyphs;
+ short encoding[256]; /* glyph ids */
+ void *temp;
+} PSFONT;
+
extern int tolatin1;
extern const char *macnames[];
extern const char *styles[];
@@ -71,3 +91,5 @@ extern int cleanfilename(char *filename);
extern void SearchNFNTResources(FILE *f,long rlistpos,int subcnt,long rdata_pos,
long name_list, FOND *fonds);
+
+extern void ParsePfb(FILE *pfb,PSFONT *psfont);
diff --git a/psfont.h b/psfont.h
new file mode 100644
index 0000000..0d79d20
--- /dev/null
+++ b/psfont.h
@@ -0,0 +1,192 @@
+/* Copyright (C) 2000-2004 by George Williams */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _PSFONT_H_
+#define _PSFONT_H_
+
+/* pfb section headers.
+ There seem to be three and a half of them. the first is a the start of the
+ file and is 6 bytes long "\200\001x\005\000\000", the second is right after
+ the newline after eexec and is 6 bytes "\200\002I\224\000\000", the third
+ is right before the zeros (after the encoded data) and is "\200\001\024\002\000\000"
+ the last is at the end of file and is only two bytes "\200\003"
+ I think that the \200 byte indicates a header, the next byte is 1 for ascii,
+ 2 for binary and 3 for eof, then next 4 bytes are the length (not present
+ for eof headers) with the first byte the least significant.
+*/
+
+struct charprocs {
+ int cnt, next;
+ char **keys;
+ void **values;
+};
+
+struct psdict {
+ int cnt, next;
+ char **keys;
+ char **values;
+};
+
+struct pschars {
+ int cnt, next;
+ char **keys;
+ unsigned char **values;
+ int *lens;
+ int bias; /* for type2 strings */
+};
+
+struct fontinfo {
+ char *familyname;
+ char *fullname;
+ char *notice;
+ char *weight;
+ char *version;
+ double italicangle;
+ unsigned int isfixedpitch:1;
+ double underlineposition;
+ double underlinethickness;
+ int em, ascent, descent; /* Generated by Fontographer (and us) */
+ int fstype; /* 2=>no embedding, 4=>print, 8=>edit */
+ /* Multiple master */
+ char *blenddesignpositions;
+ char *blenddesignmap;
+ char *blendaxistypes;
+};
+
+struct private {
+ struct psdict *private;
+ struct pschars *subrs; /* (optional, required if othersubrs is present) */
+ /* 0-2 part of Flex, 3 hint replacement, 4 and up for charstrings */
+ int leniv; /* (optional) must be 4 for old interpreters (number of rand chars at start of charstrings entries) */
+#if 0
+ int bluefuzz; /* (optional) (expand bluezones by this much, def=1) */
+ double bluescale; /* (optional) if the current pointsize in pixels is less than this value then do overshoot hinting */
+ int blueshift; /* (optional) */
+ double bluevalues[14]; /* <=7 pairs of integers, first less than second, (may be empty) */
+ /* first pair is baseline overshoots, other pairs above baseline */
+ double expansionfactor; /* (optional) only for languagegroup==1 (CJK) */
+ double familyblues[14]; /* (optional) bluevalues for family, can override local entry at small pointsizes */
+ double familyotherblues[10];/* (optional) otherblues for family */
+ unsigned int forcebold:1; /* (optional) */
+ int languagegroup; /* (optional) (0=>latin, greek, cyril, etc.), (1=>CJK)*/
+ int leniv; /* (optional) must be 4 for old interpreters (number of rand chars at start of charstrings entries) */
+ char *minfeature; /* obsolete, required must be {16 16} */
+ char *nd; /* "noaccess def" (may also be named "|-") */
+ char *np; /* "noaccess put" (may also be named "|") */
+ double otherblues[10]; /* (optional) descender blue zones */
+ struct pschars *othersubrs; /* (optional) shouldn't contain user defined subs */
+ int password; /* obsolete, required must be 5839 */
+ char *rd; /* "{string currentfile exch readstring pop}" (may also be named "-|") */
+ unsigned int rndstemup:1; /* (optional) obsolete, false if languagegroud==1 */
+ double stdhw[1]; /* (optional) dominant horizontal stem width */
+ double stdvw[1]; /* (optional) dominant vert */
+ double stemsnaph[12]; /* (optional) common h stem widths (at most 12, includes stdhw, sorted by increasing size) */
+ double stemsnapv[12]; /* (optional) common v stem widths*/
+ struct pschars *subrs; /* (optional, required if othersubrs is present) */
+ /* 0-2 part of Flex, 3 hint replacement, 4 and up for charstrings */
+ int uniqueid; /* (optional) seems same as fontdict entry. why's it here too? what of XUID? */
+/* CID entries */
+ int subrmapoffset; /* Offset to the start of this font's subr strings map */
+ int sdbytes; /* bytes in each pointer in the map */
+ int subrcnt; /* number of subroutines, number of pointers-1 in the map */
+#endif
+};
+
+typedef struct fontdict {
+ int fonttype;
+ double fontmatrix[6];
+ char *fontname; /* (optional) */
+ struct fontinfo *fontinfo;
+ int languagelevel; /* (optional) */
+ int wmode; /* (optional) chooses between alternate metric sets */
+/* non-type0 entries */
+ int isadobestd;
+ char *encoding[256];
+ double fontbb[4];
+ int uniqueid; /* (optional) open range between 4,000,000 and 4,999,999 */
+ int xuid[20]; /* (optional) */
+/* Type1 specific values */
+ int painttype; /* 0 (filled) 2 (stroked) */
+ double strokewidth; /* (optional) only if painttype==2 */
+ struct psdict *metrics; /* (optional) */
+ struct psdict *metrics2; /* (optional) */
+ struct pschars *chars;
+ struct charprocs *charprocs;
+ struct private *private;
+ unsigned int wasbinary: 1;
+ unsigned int wascff: 1;
+/* CID stuff */
+ int fdcnt; /* For the underlying dictionaries */
+ struct fontdict **fds;
+ char *cidfontname;
+ int cidfonttype;
+ double cidversion;
+ char *registry;
+ char *ordering;
+ int supplement;
+ int mapoffset;
+ int fdbytes;
+ int gdbytes;
+ int cidcnt;
+ unsigned char **cidstrs;
+ short *cidlens;
+ short *cidfds;
+/* CFF stuff */
+ struct splinefont *sf;
+/* MM stuff */
+ char *blendfunc;
+ char *weightvector;
+ char *cdv;
+ char *ndv;
+ struct psdict *blendprivate;
+ struct psdict *blendfontinfo;
+} FontDict;
+
+struct cidbytes {
+ int fdbytes, gdbytes, cidcnt;
+ int cidmapoffset;
+ int fdcnt;
+ struct fddata {
+ int leniv;
+ int subrmapoff, sdbytes, subrcnt;
+ int flexmax;
+ unsigned int iscjk:1;
+ struct pschars *subrs;
+ } *fds;
+ int *fdind;
+ int errors;
+};
+
+struct fd2data {
+ int defwid, nomwid; /* For Type2 charstrings */
+ struct pschars *subrs;
+ FILE *private; /* Subroutines get stored in the private file immediately after the private dict */
+ int eodictmark, fillindictmark;
+ int privatelen;
+};
+
+extern char *AdobeStandardEncoding[256];
+#endif
diff --git a/showfond.c b/showfond.c
index 9f6dab1..47890ac 100644
--- a/showfond.c
+++ b/showfond.c
@@ -74,7 +74,7 @@ static FOND *BuildFondList(FILE *f,long rlistpos,int subcnt,long rdata_pos,
fseek(f,rlistpos,SEEK_SET);
for ( i=0; i<subcnt; ++i ) {
- printf( "FOND ResId=%d\n", getushort(f));
+ printf( "\nFOND ResId=%d\n", getushort(f));
if ( feof(f)) {
fprintf(stderr, "EOF found in FOND list after reading %d resources of %d.\n", i, subcnt );
break;
@@ -513,6 +513,7 @@ return( false );
*pt++ = ch;
}
}
+ *pt = '\0';
/* strcpy(pt,isotf?".otf":".ttf"); */
return( true );
}