PHP Classes

File: application/libraries/dompdf/lib/ttf2ufm/src/app/netscape/nsfix.c

Recommend this page to a friend!
  Classes of harold rita   PHP Thesis Proposal Hub   application/libraries/dompdf/lib/ttf2ufm/src/app/netscape/nsfix.c   Download  
File: application/libraries/dompdf/lib/ttf2ufm/src/app/netscape/nsfix.c
Role: Auxiliary data
Content type: text/plain
Description: Auxiliary data
Class: PHP Thesis Proposal Hub
Store and publish research thesis documents
Author: By
Last change:
Date: 6 years ago
Size: 11,355 bytes
 

Contents

Class file image Download
/* * Fix the Netscape executable for specified font widths * * (c) 1999 Copyright by Sergey Babkin * see COPYRIGHT */ #include <sys/types.h> #include <fcntl.h> #include <stdio.h> #include <locale.h> #include <unistd.h> /************************** DEFINES *************************/ #undef DEBUG /* we can handle at most this many fonts */ #define MAXFONTS 20 /* maximal line buffer size */ #define MAXLINE 512 /* there may be multiple strings with the same contents */ #define MAXDUPS 10 /* file read buffer size */ #define FILEBF 40960 /* bits in the hardware page offset */ #define BITSPERPAGE 12 /* size of page in bytes */ #define PAGESIZE (1<<BITSPERPAGE) /* mask of the in-page offset */ #define PAGEMASK (PAGESIZE-1) /* this is machine-dependent! */ typedef short t2b; /* 2-byte type */ typedef int t4b; /* 4-byte type */ typedef int tptr; /* integer type with the same size as pointer */ struct bbox { /* bounding box */ t2b llx; /* lower-left-x */ t2b lly; t2b urx; t2b ury; /* upper-right-y */ }; struct glyphmetrics { /* metrics of one glyph */ t2b width; t2b unknown; struct bbox bbox; }; struct fontmetrics { /* metrics of the wholefont */ tptr name; struct bbox bbox; t2b underlinepos; t2b underlinethick; struct glyphmetrics glyphs[256]; }; struct font { char nsname[MAXLINE]; /* name in the Netscape binary */ char afmname[MAXLINE]; /* name of the .afm file */ char pfaname[MAXLINE]; /* name of the .pfa (or .pfb) file */ struct fontmetrics metrics; off_t binoff; /* offset in the binary */ }; #define SCONST(x) (x), ((sizeof (x))-1) /************************** GLOBALS *************************/ struct font font[MAXFONTS]; int nfonts=0; char msg[MAXLINE]; /*************************** PROTOTYPES **********************/ void usage(void); void readconfig( char *fn); void readmetrics(void); void replacefonts( char *fn); /************************** main ****************************/ main(ac, av) int ac; char **av; { setlocale(LC_ALL, ""); if(ac!=3) { usage(); exit(1); } readconfig(av[2]); readmetrics(); replacefonts( av[1]); } /************************** usage ***************************/ void usage(void) { fprintf(stderr,"Use:\n"); fprintf(stderr," nsfix <netscape.bin> <config-file>\n"); } /************************** readconfig **********************/ void readconfig(fn) char *fn; { char s[MAXLINE]; char afmsuffix[MAXLINE], pfasuffix[MAXLINE]; int lineno=0; FILE *f; if(( f=fopen(fn, "r") )==NULL) { sprintf(msg,"nsfix: open %s",fn); perror(msg); exit(1); } while( fgets(s, MAXLINE, f) ) { lineno++; if(s[0]=='#' || s[0]=='\n') continue; if(nfonts>=MAXFONTS) { fprintf(stderr, "nsfix: only %d fonts are supported at once\n", MAXFONTS); exit(1); } if( sscanf(s, "%s %s %s %s", font[nfonts].nsname, font[nfonts].afmname, afmsuffix, pfasuffix) != 4 ) { fprintf(stderr, "nsfix: syntax error at line %d of %s\n", lineno, fn); exit(1); } strcpy(font[nfonts].pfaname, font[nfonts].afmname); strcat(font[nfonts].afmname, afmsuffix); strcat(font[nfonts].pfaname, pfasuffix); nfonts++; } if(nfonts==0) { fprintf(stderr, "nsfix: no fonts are defined in %s\n", fn); exit(1); } fclose(f); } /************************** readmetrics *********************/ void readmetrics(void) { int i; char s[MAXLINE]; FILE *f; int n; int lineno; int code, width, llx, lly, urx, ury; char gn[MAXLINE]; struct glyphmetrics *gm; for(i=0; i<nfonts; i++) { if(( f=fopen(font[i].afmname, "r") )==NULL) { sprintf(msg,"nsfix: open %s", font[i].afmname); perror(msg); exit(1); } lineno=0; while( fgets(s, MAXLINE, f) ) { lineno++; if( !strncmp(s, SCONST("UnderlineThickness ")) ) { if( sscanf(s, "UnderlineThickness %d", &n) <1) { fprintf(stderr, "nsfix: weird UnderlineThickness at line %d in %s\n", lineno, font[i].afmname); exit(1); } font[i].metrics.underlinethick=n; } else if( !strncmp(s, SCONST("UnderlinePosition ")) ) { if( sscanf(s, "UnderlinePosition %d", &n) <1) { fprintf(stderr, "nsfix: weird UnderlinePosition at line %d in %s\n", lineno, font[i].afmname); exit(1); } font[i].metrics.underlinepos=n; } else if( !strncmp(s, SCONST("FontBBox ")) ) { if( sscanf(s, "FontBBox %d %d %d %d", &llx, &lly, &urx, &ury) <4) { fprintf(stderr, "nsfix: weird FontBBox at line %d in %s\n", lineno, font[i].afmname); exit(1); } font[i].metrics.bbox.llx=llx; font[i].metrics.bbox.lly=lly; font[i].metrics.bbox.urx=urx; font[i].metrics.bbox.ury=ury; } else if( !strncmp(s, SCONST("C ")) ) { if( sscanf(s, "C %d ; WX %d ; N %s ; B %d %d %d %d", &code, &width, &gn, &llx, &lly, &urx, &ury) <7) { fprintf(stderr, "nsfix: weird metrics at line %d in %s\n", lineno, font[i].afmname); exit(1); } if(code>=32 && code<=255) { font[i].metrics.glyphs[code].width=width; font[i].metrics.glyphs[code].bbox.llx=llx; font[i].metrics.glyphs[code].bbox.lly=lly; font[i].metrics.glyphs[code].bbox.urx=urx; font[i].metrics.glyphs[code].bbox.ury=ury; } } } fclose(f); } #ifdef DEBUG for(i=0; i<nfonts; i++) { printf("Font %s\n", font[i].nsname); for(n=0; n<256; n++) { gm= &font[i].metrics.glyphs[n]; printf(" %d w=%4d [%4d %4d %4d %4d]", n, gm->width, gm->bbox.llx, gm->bbox.lly, gm->bbox.urx, gm->bbox.ury); printf(" w=0x%04x [0x%04x 0x%04x 0x%04x 0x%04x]\n", gm->width & 0xffff, gm->bbox.llx & 0xffff, gm->bbox.lly & 0xffff, gm->bbox.urx & 0xffff, gm->bbox.ury & 0xffff); } } exit(0); #endif } /************************** replacefonts ********************/ void replacefonts(fn) char *fn; { int f; /* don't use stdio */ char bf[FILEBF]; char *bfend, *p; int len; off_t pos; off_t zerooff[MAXFONTS*MAXDUPS]; /* offset of zero strings */ tptr nameaddr[MAXFONTS*MAXDUPS]; /* name pointers before these zero strings */ int zeroid[MAXFONTS*MAXDUPS]; /* font number for this zero block */ int nzeroes; short matched[MAXFONTS]; /* counters how many matches we have for each requested font */ struct fontmetrics *fp; struct { int noff; int nz; off_t off[MAXDUPS]; /* there may be multiple strings with the same contents */ } o[MAXFONTS]; int maxnlen; int i, j, k, n; static struct glyphmetrics gm[32]; /* 0-initialized */ if(( f=open(fn, O_RDWR) )<0) { sprintf(msg,"nsfix: open %s",fn); perror(msg); exit(1); } /* get the maximal font name length */ maxnlen=0; for(i=0; i<nfonts; i++) { o[i].noff=o[i].nz=0; matched[i]=0; len=strlen(font[i].nsname)+1; if(len>maxnlen) maxnlen=len; } /* fprintf(stderr,"maxnlen= 0x%x\n", maxnlen); /* */ /* try to find the literal strings of the font names */ pos=0; bfend=bf; while(( len=read(f, bfend, FILEBF-(bfend-bf)) )>=0 ) { /* fprintf(stderr,"looking at 0x%lx\n", (long)pos); /* */ /* the last position to check */ if(len>=maxnlen) /* leave the rest with the next block */ bfend+= len-maxnlen; else { /* we are very near to the end of file, check * up to the very last byte */ bfend+= len-2; memset(bfend+2, 0, maxnlen); } for(p=bf; p<=bfend; p++) for(i=0; i<nfonts; i++) if(!strcmp(font[i].nsname, p) && o[i].noff<MAXDUPS) { o[i].off[ o[i].noff++ ] = pos + (p-bf); fprintf(stderr,"found %s at 0x%lx\n", font[i].nsname, (long)pos + (p-bf)); } if(len==0) break; memmove(bf, bfend, maxnlen); pos+= (bfend-bf); bfend= (bf+maxnlen); } if(len<0) { sprintf(msg,"nsfix: read %s",fn); perror(msg); exit(1); } fprintf(stderr,"---\n"); /* if there are any dups try to resolve them */ for(i=0; i<nfonts; i++) { if(o[i].noff==0) { fprintf(stderr, "nsfix: font %s (%d of %d) is missing in %s\n", font[i].nsname, i, nfonts, fn); exit(1); } if(o[i].noff!=1) continue; /* good, only one entry */ fprintf(stderr,"found unique %s at 0x%lx\n", font[i].nsname, (long)o[i].off[0] ); /* if any dupped entry is right after this one then it's good */ /* if it's farther than PAGESIZE/2 then it's bad */ pos=o[i].off[0]+strlen(font[i].nsname)+1; for(j=0; j<MAXFONTS; j++) { if(o[j].noff<=1) continue; for(k=0; k<o[j].noff; k++) { if(o[j].off[k]==pos) { /* good */ fprintf(stderr,"got unique %s at 0x%lx\n", font[j].nsname, (long)pos ); o[j].off[0]=pos; o[j].noff=1; break; } if(o[j].off[k] < pos - PAGESIZE/2 || o[j].off[k] > pos + PAGESIZE/2) { /* bad */ fprintf(stderr, "eliminated %s at 0x%lx\n", font[j].nsname, (long)o[j].off[k] ); for(n=k+1; n<o[j].noff; n++) o[j].off[n-1]=o[j].off[n]; o[j].noff--; k--; } } if(o[j].noff==1 && j<i) { /* have to revisit this font */ i=j-1; /* compensate for i++ */ break; } } } /* try to find the metric tables in the executable */ if(lseek(f, (off_t)0, SEEK_SET)<0) { sprintf(msg,"nsfix: rewind %s",fn); perror(msg); exit(1); } /* * search for the zeroes in place of the metrics for the codes 0-31: * 4-byte aligned strings of (32*sizeof(struct glyphmetrics)) zero bytes */ maxnlen=sizeof(struct fontmetrics); pos=0; bfend=bf; nzeroes=0; while(( len=read(f, bfend, FILEBF-(bfend-bf)) )>=0 ) { /* fprintf(stderr,"looking at 0x%lx\n", (long)pos); /* */ /* the last position to check */ bfend+= len-maxnlen; /* don't look beyond the EOF */ for(p=bf; p<=bfend; p+=4 /* 4-byte aligned */ ) { fp=(struct fontmetrics *)p; if(fp->name==0) continue; if( memcmp(gm, fp->glyphs, sizeof gm) ) continue; /* OK, looks like it, see if we can match it to any name */ n= fp->name & PAGEMASK; for(i=0; i<nfonts; i++) { for(j=0; j<o[i].noff; j++) if( n==(o[i].off[j] & PAGEMASK) ) { zerooff[nzeroes]= pos + (p-bf); nameaddr[nzeroes]= fp->name; zeroid[nzeroes]=i; o[i].nz++; fprintf(stderr, "matched %s at 0x%lx\n", font[i].nsname, (long) zerooff[nzeroes]); nzeroes++; matched[i]++; break; } } } if(len==0) break; memmove(bf, bfend, maxnlen); pos+= (bfend-bf); bfend= (bf+maxnlen); } if(len<0) { sprintf(msg,"nsfix: read %s",fn); perror(msg); exit(1); } fprintf(stderr,"---\n"); /* make sure that all the fonts got one match */ k=0; /* flag: have non-matched fonts */ n=0; /* flag: have ambiguities */ for(i=0; i<nfonts; i++) if(matched[i]==0) k=1; else if(matched[i]>1) n=1; if(k) { fprintf(stderr,"nsfix: can't find match for some of the fonts\n"); fprintf(stderr,"nsfix: maybe wrong byte order, aborting\n"); exit(1); } if(n) { fprintf(stderr,"nsfix: got multiple matches for some of the fonts\n"); fprintf(stderr,"nsfix: can't resolve, aborting\n"); exit(1); } /* now finally write the updated tables */ for(i=0; i<nzeroes; i++) { j=zeroid[i]; fprintf(stderr, "nsfix: writing table for %s at 0x%lx\n", font[j].nsname, (long)zerooff[i]); font[j].metrics.name=nameaddr[i]; if( lseek(f, zerooff[i], SEEK_SET)<0 ) { sprintf(msg,"nsfix: seek %s to 0x%lx",fn, (long)zerooff[i] ); perror(msg); exit(1); } if( write(f, &font[j].metrics, sizeof font[j].metrics) != sizeof font[j].metrics ) { sprintf(msg,"nsfix: write to %s",fn ); perror(msg); exit(1); } } close(f); }