/* Copyright (C) 2001-2003 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 #include #include #include #include #include #include #include #include "macfonts.h" int tolatin1 = false; static int force = false, inquire = false, doafm = false, trackps = false, show=false; int getushort(FILE *f) { int ch1 = getc(f); int ch2 = getc(f); if ( ch2==EOF ) return( EOF ); return( (ch1<<8)|ch2 ); } long getlong(FILE *f) { int ch1 = getc(f); int ch2 = getc(f); int ch3 = getc(f); int ch4 = getc(f); if ( ch4==EOF ) return( EOF ); return( (ch1<<24)|(ch2<<16)|(ch3<<8)|ch4 ); } static int _cleanfilename(char *filename) { char *pt, *npt; int ch, exists, ch2; for ( ch = *(pt=npt=filename); ch!='\0'; ch = *++pt ) { if ( ch>'!' && ch!='*' && ch!='?' && ch!='/' && ch!='\\' && ch!='[' && ch<0x7f ) *npt++ = ch; } *npt = '\0'; if ( force && !inquire ) return( true ); exists = access(filename,F_OK)==0; forever { if ( exists ) fprintf( stderr, "%s exists, do you want to overwrite it? (n) ", filename ); else if ( inquire ) fprintf( stderr, "Write %s? (y) ", filename ); 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'; else while ( (ch2=getchar())!='\n' && ch2!=EOF ); return( ch=='y' || ch=='Y' ); } else if ( ch=='=' ) { for ( pt=filename; (ch=getchar())!=EOF && ch!='\n'; ) *pt++ = ch; return( true ); } else { 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 */ forever { sprintf( temp, "fondu%04X-%d", getpid(), ++upos ); if ( access(temp,F_OK)==-1 ) return; } } /* 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 /*&& ptfontname==NULL ) { char *pt = strrchr(filename,'.'); char *ept = strrchr(filename,'/'); if ( pt!=NULL && pt>ept ) *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; 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"); strcpy(fontname,familyname); for ( i=0; styles[i]!=NULL ; ++i ) if ( style&(1<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 ii,i,j,k,l,dups; FILE *afm; time_t now; char fontname[256], familyname[256]; char buffer[32]; PSFONT psfont; 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; 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" ); 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 Date: %s", ctime(&now) ); fprintf( afm, "FontName %s\n", fontname ); fprintf( afm, "FamilyName %s\n", familyname ); fprintf( afm, "IsFixedPitch %s\n", isfixed?"true":"false"); 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, "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; } for ( l=0; lstylewidthcnt-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; kstylekerns[i].kernpairs; ++k ) { const char *name1, *name2; struct kerns *kp = &fond->stylekerns[i].kerns[k]; if ( 1 /* kp->ch1<=256 */ ) name1 = macnames[kp->ch1]; else { sprintf( buffer, "char%04x", kp->ch1 ); name1 = buffer; } if ( name1==NULL ) name1 = ".notdef"; if ( 1 /* 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 ); } fprintf( afm, "EndKernPairs\nEndKernData\n"); } fprintf( afm, "EndFontMetrics\n" ); fclose( afm ); } fseek(f,start,SEEK_SET); } /* There's probably only one fond in the file, but there could be more so be */ /* prepared... */ /* I want the fond: */ /* to get the fractional widths for the SWIDTH entry on bdf */ /* to get the font name */ /* to get the font association tables */ /* 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,char *origfilename) { long here, start = ftell(f); long offset; int rname = -1; char name[300]; int ch1, ch2; int i, j, k, cnt, isfixed; FOND *head=NULL, *cur; long widoff, kernoff, styleoff; fseek(f,rlistpos,SEEK_SET); for ( i=0; inext = head; head = cur; if ( rname!=-1 ) { fseek(f,name_list+rname,SEEK_SET); ch1 = getc(f); fread(name,1,ch1,f); name[ch1] = '\0'; cur->fondname = strdup(name); } offset += 4; fseek(f,offset,SEEK_SET); isfixed = getushort(f)&0x8000?1:0; /* family id = */ getushort(f); cur->first = getushort(f); cur->last = getushort(f); /* on a 1 point font... */ /* ascent = */ getushort(f); /* descent = */ (short) getushort(f); /* leading = */ getushort(f); /* widmax = */ getushort(f); if ( (widoff = getlong(f))!=0 ) widoff += offset; if ( (kernoff = getlong(f))!=0 ) kernoff += offset; if ( (styleoff = getlong(f))!=0 ) styleoff += offset; for ( j=0; j<9; ++j ) getushort(f); /* internal & undefined, for international scripts = */ getlong(f); /* version = */ getushort(f); cur->assoc_cnt = getushort(f)+1; cur->assoc = calloc(cur->assoc_cnt,sizeof(struct assoc)); for ( j=0; jassoc_cnt; ++j ) { cur->assoc[j].size = getushort(f); cur->assoc[j].style = getushort(f); cur->assoc[j].id = getushort(f); } if ( widoff!=0 ) { fseek(f,widoff,SEEK_SET); cnt = getushort(f)+1; cur->stylewidthcnt = cnt; cur->stylewidths = calloc(cnt,sizeof(struct stylewidths)); for ( j=0; jstylewidths[j].style = getushort(f); cur->stylewidths[j].widthtab = malloc((cur->last-cur->first+3)*sizeof(short)); for ( k=cur->first; k<=cur->last+2; ++k ) cur->stylewidths[j].widthtab[k] = getushort(f); } } if ( kernoff!=0 ) { fseek(f,kernoff,SEEK_SET); cnt = getushort(f)+1; cur->stylekerncnt = cnt; cur->stylekerns = calloc(cnt,sizeof(struct stylekerns)); for ( j=0; jstylekerns[j].style = getushort(f); cur->stylekerns[j].kernpairs = getushort(f); cur->stylekerns[j].kerns = malloc(cur->stylekerns[j].kernpairs*sizeof(struct kerns)); for ( k=0; kstylekerns[j].kernpairs; ++k ) { cur->stylekerns[j].kerns[k].ch1 = getc(f); cur->stylekerns[j].kerns[k].ch2 = getc(f); cur->stylekerns[j].kerns[k].offset = getushort(f); } } } if ( styleoff!=0 ) { unsigned char stringoffsets[48]; int strcnt, strlength, 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=0; --k ) if ( stringoffsets[j]==stringoffsets[k] ) break; if ( k!=-1 || stringoffsets[j]==0 ) continue; /* this style doesn't exist */ format = stringoffsets[j]-1; strlength = strings[0][0]; if ( format!=0 && format!=-1 ) for ( k=0; kpsnames[j] = malloc(strlength+1); strcpy(pt,strings[ 0 ]+1); pt += strings[ 0 ][0]; if ( format!=0 && format!=-1 ) for ( k=0; kfamily = strdup(strings[0]); for ( j=0; j>8)&0xff,pfb); putc((len>>16)&0xff,pfb); putc(len>>24,pfb); fseek(pfb,hold,SEEK_SET); if ( ch1==5 ) /* end of font mark */ break; putc(0x80,pfb); putc(ch1,pfb); lenpos = ftell(pfb); putc(0,pfb); putc(0,pfb); putc(0,pfb); putc(0,pfb); type = ch1; len = rlen; } if ( rlen>max ) { free(buffer); max = rlen; if ( max<0x800 ) max = 0x800; buffer=malloc(max); if ( buffer==NULL ) { fprintf( stderr, "Out of memory\n" ); exit( 1 ); } } fread(buffer,1,rlen,f); if ( type==1 ) { int j; char *pt; for ( j=0; j>8)&0xff,pfb); putc((len>>16)&0xff,pfb); putc(len>>24,pfb); if ( psfont!=NULL ) { rewind(pfb); ParsePfb(pfb,psfont); } fclose(pfb); if ( psfont==NULL ) { if ( cleanfilename(newname)) { if ( rename(name,newname)==-1 ) { fprintf( stderr, "Could not create %s\n", newname); unlink(name); } } else unlink(name); } fseek(f,here,SEEK_SET); } static int ttfnamefixup(FILE *ttf,char *buffer) { int version, isotf=false; int i,num, nameoffset, stringoffset; int fullval, famval, fullstr, famstr, fulllen, famlen, val, tag; int plat, spec, lang, name, len, off, ch; char *pt; rewind(ttf); if ( (version=getlong(ttf))==CHR('O','T','T','O')) isotf = true; else if ( version!=0x10000 && version!=CHR('t','r','u','e')) return(false); /* Not going to mess with ttc collections, or whatever else this might be */ num = getushort(ttf); /* srange = */ getushort(ttf); /* esel = */ getushort(ttf); /* rshift = */ getushort(ttf); for ( i=0; ifullval ) { fullval = val; fullstr = off; fulllen = len; if ( val==2 || val==3 ) break; } else if ( name==1 && val>famval ) { famval = val; famstr = off; famlen = len; } } if ( fullval==0 ) { if ( famval==0 ) return( false ); fullstr = famstr; fulllen = famlen; } fseek(ttf,stringoffset+fullstr,SEEK_SET); pt = buffer; if ( val==3 ) { for ( i=0; i'!' && ch!='*' && ch!='?' && ch!='/' && ch!='\\' && ch<0x7f ) *pt++ = ch; } } else { for ( i=0; i'!' && ch!='*' && ch!='?' && ch!='/' && ch!='\\' && ch<0x7f ) *pt++ = ch; } } strcpy(pt,isotf?".otf":".ttf"); return( true ); } static void ttfnameset(FILE *ttf,char *curname,char *patheticattempt) { char buffer[1024]; if ( !ttfnamefixup(ttf,buffer)) strcpy(buffer,patheticattempt); if ( !cleanfilename(buffer)) unlink(curname); else if ( rename(curname, buffer)==-1 ) { fprintf( stderr, "Could not create %s\n", buffer ); unlink(curname); } } static void SearchTtfResources(FILE *f,long rlistpos,int subcnt,long rdata_pos, long name_list, FOND *fonds) { long here, start = ftell(f); long roff; int rname = -1; char name[300], newname[300]; int ch1, ch2; static int ucnt; int len, i, rlen, ilen; /* I think (hope) the sfnt resource is just a copy of the ttf file */ char *buffer=NULL; int max = 0; FILE *ttf; fseek(f,rlistpos,SEEK_SET); for ( i=0; i16*1024 ) ilen = 16*1024; if ( ilen>max ) { free(buffer); max = ilen; if ( max<0x800 ) max = 0x800; buffer=malloc(max); } for ( len=0; len0 ) { len = dlen > 8192 ? 8192 : dlen; len = fread(buffer,1,dlen > 8192 ? 8192 : dlen,binary); if ( len==0 ) break; fwrite(buffer,1,len,out); dlen -= len; } fclose(out); free(buffer); return( true ); } 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 */ /* the resource fork will actually start somewhere in the middle of the */ /* file, not at the beginning */ unsigned char buffer[16], buffer2[16]; long rdata_pos, map_pos, type_list, name_list, rpos; long rdata_len, map_len; unsigned long tag; int i, cnt, subcnt; FOND *fondlist=NULL, *fl; fseek(f,offset,SEEK_SET); if ( fread(buffer,1,16,f)!=16 ) return( false ); rdata_pos = offset + ((buffer[0]<<24)|(buffer[1]<<16)|(buffer[2]<<8)|buffer[3]); map_pos = offset + ((buffer[4]<<24)|(buffer[5]<<16)|(buffer[6]<<8)|buffer[7]); rdata_len = ((buffer[8]<<24)|(buffer[9]<<16)|(buffer[10]<<8)|buffer[11]); map_len = ((buffer[12]<<24)|(buffer[13]<<16)|(buffer[14]<<8)|buffer[15]); if ( rdata_pos+rdata_len!=map_pos ) return( false ); fseek(f,map_pos,SEEK_SET); buffer2[15] = buffer[15]+1; /* make it be different */ if ( fread(buffer2,1,16,f)!=16 ) return( false ); /* Apple's data fork resources appear to have a bunch of zeroes here instead */ /* of a copy of the first 16 bytes */ for ( i=0; i<16; ++i ) if ( buffer2[i]!=0 ) break; if ( i!=16 ) { for ( i=0; i<16; ++i ) if ( buffer[i]!=buffer2[i] ) return( false ); } getlong(f); /* skip the handle to the next resource map */ getushort(f); /* skip the file resource number */ getushort(f); /* skip the attributes */ type_list = map_pos + getushort(f); name_list = map_pos + getushort(f); if ( psfont==NULL ) { fseek(f,type_list,SEEK_SET); cnt = getushort(f)+1; for ( i=0; inext ) for ( i=0; i<48; ++i ) if ( fl->psnames[i]!=NULL ) ProcessNestedPS( fl->psnames[i],filename, NULL ); } } fseek(f,type_list,SEEK_SET); cnt = getushort(f)+1; for ( i=0; i>24, (tag>>16)&0xff, (tag>>8)&0xff, tag&0xff );*/ 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,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')) SearchNFNTResources(f,rpos,subcnt,rdata_pos,name_list,fondlist); else if ( tag==CHR('s','f','n','t')) SearchTtfResources(f,rpos,subcnt,rdata_pos,name_list,fondlist); else if ( tag==CHR('F','O','N','D')) /* already parsed */; else /* Ignored */; } return( true ); } #ifndef OldMacintosh /* OS/X and linux with appropriate drivers */ static int HasResourceFork(char *filename,PSFONT *psfont) { char *respath = malloc(strlen(filename)+strlen("/..namedfork/rsrc")+1); FILE *temp; int ret=false; strcpy(respath,filename); strcat(respath,"/..namedfork/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, these calls depreciated in X.4 */ 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; short res; long cnt, ret; FILE *temp; char *buf; if ( FSPathMakeRef( (unsigned char *) filename,&ref,NULL)!=noErr ) return( 0 ); if ( FSGetCatalogInfo(&ref,0,NULL,NULL,&spec,NULL)!=noErr ) return( 0 ); if ( FSpOpenRF(&spec,fsRdPerm,&res)!=noErr ) return( 0 ); temp = tmpfile(); buf = malloc(8192); while ( 1 ) { cnt = 8192; ret = FSRead(res,&cnt,buf); if ( cnt!=0 ) fwrite(buf,1,cnt,temp); if ( ret==eofErr ) break; if ( ret!=noErr ) break; } free(buf); FSClose(res); rewind(temp); ret = IsResourceFork(temp,0,filename,psfont); fclose(temp); return( ret ); } #endif static int IsResourceInBinary(FILE *f,char *filename, PSFONT *psfont) { unsigned char header[128], first[8]; unsigned long offset, dlen, rlen; if ( fread(header,1,128,f)!=128 ) return( false ); if ( header[0]!=0 || header[74]!=0 || header[82]!=0 || header[1]<=0 || header[1]>33 || header[63]!=0 || header[2+header[1]]!=0 ) return( false ); dlen = ((header[0x53]<<24)|(header[0x54]<<16)|(header[0x55]<<8)|header[0x56]); rlen = ((header[0x57]<<24)|(header[0x58]<<16)|(header[0x59]<<8)|header[0x5a]); /* Look for a bare truetype font in a binhex/macbinary wrapper */ if ( dlen!=0 && rlen<=dlen) { int pos = ftell(f); fread(first,1,4,f); first[5] = '\0'; if ( strcmp((char *) first,"OTTO")==0 || strcmp((char *) first,"true")==0 || strcmp((char *) first,"ttcf")==0 || (first[0]==0 && first[1]==1 && first[2]==0 && first[3]==0)) { int len = header[1]; header[2+len] = '\0'; 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,filename,psfont)); } static int lastch=0, repeat = 0; static void outchr(FILE *binary, int ch) { int i; if ( repeat ) { if ( ch==0 ) { /* no repeat, output a literal 0x90 (the repeat flag) */ lastch=0x90; putc(lastch,binary); } else { for ( i=1; i>16)&0xff); outchr(binary,(val>>8)&0xff); outchr(binary,val&0xff); val = cnt = 0; } } if ( cnt!=0 ) { if ( cnt==1 ) outchr(binary,val<<2); else if ( cnt==2 ) { val<<=4; outchr(binary,(val>>8)&0xff); outchr(binary,val&0xff); } else if ( cnt==3 ) { val<<=6; outchr(binary,(val>>16)&0xff); outchr(binary,(val>>8)&0xff); outchr(binary,val&0xff); } } rewind(binary); ch = getc(binary); /* Name length */ /* skip name */ for ( i=0, pt=wrappedfilename; i8 || strlen(dpt)>4 ) { char exten[8]; strncpy(exten,dpt,7); exten[4] = '\0'; /* it includes the dot */ if ( dpt-spt>6 ) dpt = spt+6; *dpt++ = '~'; *dpt++ = '1'; strcpy(dpt,exten); } return( IsResourceInFile(buffer,NULL)); } int main(int argc, char **argv) { int i, ret = 0; for ( i=1; i