source: trunk/filemanager/tp/dompdf/lib/ttf2ufm/ttf2ufm-src/app/netscape/nsfix.c @ 2000

Revision 2000, 11.5 KB checked in by amuller, 14 years ago (diff)

Ticket #597 - Implementação do módulo gerenciador de arquivos

Line 
1/*
2 * Fix the Netscape executable for specified font widths
3 *
4 * (c) 1999 Copyright by Sergey Babkin
5 * see COPYRIGHT
6 */
7
8#include <sys/types.h>
9#include <fcntl.h>
10#include <stdio.h>
11#include <locale.h>
12#include <unistd.h>
13
14/************************** DEFINES *************************/
15
16#undef DEBUG
17
18/* we can handle at most this many fonts */
19#define MAXFONTS        20
20
21/* maximal line buffer size */
22#define MAXLINE 512
23
24/* there may be multiple strings with the same contents */
25#define MAXDUPS 10
26
27/* file read buffer size */
28#define FILEBF  40960
29
30/* bits in the hardware page offset */
31#define BITSPERPAGE     12
32
33/* size of page in bytes */
34#define PAGESIZE (1<<BITSPERPAGE)
35
36/* mask of the in-page offset */
37#define PAGEMASK (PAGESIZE-1)
38
39/* this is machine-dependent! */
40typedef short t2b; /* 2-byte type */
41typedef int t4b; /* 4-byte type */
42typedef int tptr; /* integer type with the same size as pointer */
43
44struct bbox { /* bounding box */
45        t2b llx; /* lower-left-x */
46        t2b lly;
47        t2b urx;
48        t2b ury; /* upper-right-y */
49};
50
51struct glyphmetrics { /* metrics of one glyph */
52        t2b     width;
53        t2b     unknown;
54        struct bbox bbox;
55};
56
57struct fontmetrics { /* metrics of the wholefont */
58        tptr name;
59        struct bbox bbox;
60        t2b underlinepos;
61        t2b underlinethick;
62        struct glyphmetrics glyphs[256];
63};
64
65struct font {
66        char nsname[MAXLINE]; /* name in the Netscape binary */
67        char afmname[MAXLINE]; /* name of the .afm file */
68        char pfaname[MAXLINE]; /* name of the .pfa (or .pfb) file */
69        struct fontmetrics metrics;
70        off_t binoff; /* offset in the binary */
71};
72
73#define SCONST(x)       (x), ((sizeof (x))-1)
74
75/************************** GLOBALS *************************/
76
77struct font font[MAXFONTS];
78int nfonts=0;
79
80char msg[MAXLINE];
81
82/*************************** PROTOTYPES **********************/
83
84void usage(void);
85void readconfig( char *fn);
86void readmetrics(void);
87void replacefonts( char *fn);
88
89/************************** main ****************************/
90
91main(ac, av)
92        int ac;
93        char **av;
94{
95        setlocale(LC_ALL, "");
96
97        if(ac!=3) {
98                usage(); exit(1);
99        }
100
101        readconfig(av[2]);
102        readmetrics();
103        replacefonts( av[1]);
104}
105
106/************************** usage ***************************/
107
108void
109usage(void)
110{
111        fprintf(stderr,"Use:\n");
112        fprintf(stderr,"   nsfix <netscape.bin> <config-file>\n");
113}
114
115
116/************************** readconfig **********************/
117
118void
119readconfig(fn)
120        char *fn;
121{
122        char s[MAXLINE];
123        char afmsuffix[MAXLINE], pfasuffix[MAXLINE];
124        int lineno=0;
125        FILE *f;
126
127        if(( f=fopen(fn, "r") )==NULL) {
128                sprintf(msg,"nsfix: open %s",fn);
129                perror(msg);
130                exit(1);
131        }
132
133        while( fgets(s, MAXLINE, f) ) {
134                lineno++;
135                if(s[0]=='#' || s[0]=='\n')
136                        continue;
137
138                if(nfonts>=MAXFONTS) {
139                        fprintf(stderr, "nsfix: only %d fonts are supported at once\n",
140                                MAXFONTS);
141                        exit(1);
142                }
143
144                if( sscanf(s, "%s %s %s %s", font[nfonts].nsname,
145                                font[nfonts].afmname, afmsuffix, pfasuffix) != 4 ) {
146                        fprintf(stderr, "nsfix: syntax error at line %d of %s\n",
147                                lineno, fn);
148                        exit(1);
149                }
150                strcpy(font[nfonts].pfaname, font[nfonts].afmname);
151                strcat(font[nfonts].afmname, afmsuffix);
152                strcat(font[nfonts].pfaname, pfasuffix);
153                nfonts++;
154        }
155
156        if(nfonts==0) {
157                fprintf(stderr, "nsfix: no fonts are defined in %s\n", fn);
158                exit(1);
159        }
160        fclose(f);
161}
162
163/************************** readmetrics *********************/
164
165void
166readmetrics(void)
167{
168        int i;
169        char s[MAXLINE];
170        FILE *f;
171        int n;
172        int lineno;
173        int code, width, llx, lly, urx, ury;
174        char gn[MAXLINE];
175        struct glyphmetrics *gm;
176
177        for(i=0; i<nfonts; i++) {
178                if(( f=fopen(font[i].afmname, "r") )==NULL) {
179                        sprintf(msg,"nsfix: open %s", font[i].afmname);
180                        perror(msg);
181                        exit(1);
182                }
183                lineno=0;
184                while( fgets(s, MAXLINE, f) ) {
185                        lineno++;
186                        if( !strncmp(s, SCONST("UnderlineThickness ")) ) {
187                                if( sscanf(s, "UnderlineThickness %d", &n) <1) {
188                                        fprintf(stderr, "nsfix: weird UnderlineThickness at line %d in %s\n",
189                                                lineno, font[i].afmname);
190                                        exit(1);
191                                }
192                                font[i].metrics.underlinethick=n;
193                        } else if( !strncmp(s, SCONST("UnderlinePosition ")) ) {
194                                if( sscanf(s, "UnderlinePosition %d", &n) <1) {
195                                        fprintf(stderr, "nsfix: weird UnderlinePosition at line %d in %s\n",
196                                                lineno, font[i].afmname);
197                                        exit(1);
198                                }
199                                font[i].metrics.underlinepos=n;
200                        } else if( !strncmp(s, SCONST("FontBBox ")) ) {
201                                if( sscanf(s, "FontBBox %d %d %d %d", &llx, &lly, &urx, &ury) <4) {
202                                        fprintf(stderr, "nsfix: weird FontBBox at line %d in %s\n",
203                                                lineno, font[i].afmname);
204                                        exit(1);
205                                }
206                                font[i].metrics.bbox.llx=llx;
207                                font[i].metrics.bbox.lly=lly;
208                                font[i].metrics.bbox.urx=urx;
209                                font[i].metrics.bbox.ury=ury;
210                        } else if( !strncmp(s, SCONST("C ")) ) {
211                                if( sscanf(s, "C %d ; WX %d ; N %s ; B %d %d %d %d",
212                                        &code, &width, &gn, &llx, &lly, &urx, &ury) <7)
213                                {
214                                        fprintf(stderr, "nsfix: weird metrics at line %d in %s\n",
215                                                lineno, font[i].afmname);
216                                        exit(1);
217                                }
218                                if(code>=32 && code<=255) {
219                                        font[i].metrics.glyphs[code].width=width;
220                                        font[i].metrics.glyphs[code].bbox.llx=llx;
221                                        font[i].metrics.glyphs[code].bbox.lly=lly;
222                                        font[i].metrics.glyphs[code].bbox.urx=urx;
223                                        font[i].metrics.glyphs[code].bbox.ury=ury;
224                                }
225                        }
226                }
227                fclose(f);
228        }
229
230#ifdef DEBUG
231        for(i=0; i<nfonts; i++) {
232                printf("Font %s\n", font[i].nsname);
233                for(n=0; n<256; n++) {
234                        gm= &font[i].metrics.glyphs[n];
235                        printf("  %d w=%4d [%4d %4d %4d %4d]", n, gm->width,
236                                gm->bbox.llx, gm->bbox.lly, gm->bbox.urx, gm->bbox.ury);
237                        printf("  w=0x%04x [0x%04x 0x%04x 0x%04x 0x%04x]\n", gm->width & 0xffff,
238                                gm->bbox.llx & 0xffff, gm->bbox.lly & 0xffff, gm->bbox.urx & 0xffff, gm->bbox.ury & 0xffff);
239                }
240        }
241
242        exit(0);
243#endif
244
245}
246
247/************************** replacefonts ********************/
248
249void
250replacefonts(fn)
251        char *fn;
252{
253        int f; /* don't use stdio */
254        char bf[FILEBF];
255        char *bfend, *p;
256        int len;
257        off_t pos;
258
259        off_t zerooff[MAXFONTS*MAXDUPS]; /* offset of zero strings */
260        tptr nameaddr[MAXFONTS*MAXDUPS]; /* name pointers before these zero strings */
261        int zeroid[MAXFONTS*MAXDUPS]; /* font number for this zero block */
262        int nzeroes;
263        short matched[MAXFONTS]; /* counters how many matches we have for each requested font */
264        struct fontmetrics *fp;
265
266        struct {
267                int noff;
268                int nz;
269                off_t off[MAXDUPS]; /* there may be multiple strings with the same contents */
270        } o[MAXFONTS];
271        int maxnlen;
272        int i, j, k, n;
273
274        static struct glyphmetrics gm[32]; /* 0-initialized */
275
276
277        if(( f=open(fn, O_RDWR) )<0) {
278                sprintf(msg,"nsfix: open %s",fn);
279                perror(msg);
280                exit(1);
281        }
282
283
284        /* get the maximal font name length */
285        maxnlen=0;
286        for(i=0; i<nfonts; i++) {
287                o[i].noff=o[i].nz=0;
288                matched[i]=0;
289                len=strlen(font[i].nsname)+1;
290                if(len>maxnlen)
291                        maxnlen=len;
292        }
293
294        /* fprintf(stderr,"maxnlen= 0x%x\n", maxnlen); /* */
295        /* try to find the literal strings of the font names */
296        pos=0; bfend=bf;
297        while(( len=read(f, bfend, FILEBF-(bfend-bf)) )>=0 ) {
298                /* fprintf(stderr,"looking at 0x%lx\n", (long)pos); /* */
299                /* the last position to check */
300                if(len>=maxnlen)
301                        /* leave the rest with the next block */
302                        bfend+= len-maxnlen;
303                else {
304                        /* we are very near to the end of file, check
305                         * up to the very last byte */
306                        bfend+= len-2;
307                        memset(bfend+2, 0, maxnlen);
308                }
309
310                for(p=bf; p<=bfend; p++)
311                        for(i=0; i<nfonts; i++)
312                                if(!strcmp(font[i].nsname, p) && o[i].noff<MAXDUPS) {
313                                        o[i].off[ o[i].noff++ ] = pos + (p-bf);
314                                        fprintf(stderr,"found %s at 0x%lx\n", font[i].nsname, (long)pos + (p-bf));
315                                }
316
317                if(len==0)
318                        break;
319
320                memmove(bf, bfend, maxnlen);
321                pos+= (bfend-bf);
322                bfend= (bf+maxnlen);
323        }
324        if(len<0) {
325                sprintf(msg,"nsfix: read %s",fn);
326                perror(msg);
327                exit(1);
328        }
329        fprintf(stderr,"---\n");
330        /* if there are any dups try to resolve them */
331        for(i=0; i<nfonts; i++) {
332                if(o[i].noff==0) {
333                        fprintf(stderr, "nsfix: font %s (%d of %d) is missing in %s\n",
334                                font[i].nsname, i, nfonts, fn);
335                        exit(1);
336                }
337                if(o[i].noff!=1)
338                        continue;
339                /* good, only one entry */
340                fprintf(stderr,"found unique %s at 0x%lx\n", font[i].nsname, (long)o[i].off[0] );
341                /* if any dupped entry is right after this one then it's good */
342                /* if it's farther than PAGESIZE/2 then it's bad */
343                pos=o[i].off[0]+strlen(font[i].nsname)+1;
344                for(j=0; j<MAXFONTS; j++) {
345                        if(o[j].noff<=1)
346                                continue;
347                        for(k=0; k<o[j].noff; k++) {
348                                if(o[j].off[k]==pos) { /* good */
349                                        fprintf(stderr,"got unique %s at 0x%lx\n", font[j].nsname, (long)pos );
350                                        o[j].off[0]=pos;
351                                        o[j].noff=1;
352                                        break;
353                                }
354                                if(o[j].off[k] < pos - PAGESIZE/2
355                                || o[j].off[k] > pos + PAGESIZE/2) { /* bad */
356                                        fprintf(stderr, "eliminated %s at 0x%lx\n", font[j].nsname, (long)o[j].off[k] );
357                                        for(n=k+1; n<o[j].noff; n++)
358                                                o[j].off[n-1]=o[j].off[n];
359                                        o[j].noff--;
360                                        k--;
361                                }
362                        }
363                        if(o[j].noff==1 && j<i) { /* have to revisit this font */
364                                i=j-1; /* compensate for i++ */
365                                break;
366                        }
367                }
368        }
369
370
371        /* try to find the metric tables in the executable */
372        if(lseek(f, (off_t)0, SEEK_SET)<0) {
373                sprintf(msg,"nsfix: rewind %s",fn);
374                perror(msg);
375                exit(1);
376        }
377
378        /*
379         * search for the zeroes in place of the metrics for the codes 0-31:
380         * 4-byte aligned strings of (32*sizeof(struct glyphmetrics)) zero bytes
381         */
382        maxnlen=sizeof(struct fontmetrics);
383
384        pos=0; bfend=bf; nzeroes=0;
385        while(( len=read(f, bfend, FILEBF-(bfend-bf)) )>=0 ) {
386                /* fprintf(stderr,"looking at 0x%lx\n", (long)pos); /* */
387                /* the last position to check */
388                bfend+= len-maxnlen; /* don't look beyond the EOF */
389
390                for(p=bf; p<=bfend; p+=4 /* 4-byte aligned */ ) {
391                        fp=(struct fontmetrics *)p;
392                        if(fp->name==0)
393                                continue;
394                        if( memcmp(gm, fp->glyphs, sizeof gm) )
395                                continue;
396
397                        /* OK, looks like it, see if we can match it to any name */
398                        n= fp->name & PAGEMASK;
399                        for(i=0; i<nfonts; i++) {
400                                for(j=0; j<o[i].noff; j++)
401                                        if( n==(o[i].off[j] & PAGEMASK) )  {
402                                                zerooff[nzeroes]= pos + (p-bf);
403                                                nameaddr[nzeroes]= fp->name;
404                                                zeroid[nzeroes]=i;
405                                                o[i].nz++;
406                                                fprintf(stderr, "matched %s at 0x%lx\n",
407                                                        font[i].nsname, (long) zerooff[nzeroes]);
408                                                nzeroes++;
409                                                matched[i]++;
410                                                break;
411                                        }
412                        }
413
414                }
415
416                if(len==0)
417                        break;
418
419                memmove(bf, bfend, maxnlen);
420                pos+= (bfend-bf);
421                bfend= (bf+maxnlen);
422        }
423        if(len<0) {
424                sprintf(msg,"nsfix: read %s",fn);
425                perror(msg);
426                exit(1);
427        }
428        fprintf(stderr,"---\n");
429
430        /* make sure that all the fonts got one match */
431        k=0; /* flag: have non-matched fonts */ n=0; /* flag: have ambiguities */
432        for(i=0; i<nfonts; i++)
433                if(matched[i]==0)
434                        k=1;
435                else if(matched[i]>1)
436                        n=1;
437
438        if(k) {
439                fprintf(stderr,"nsfix: can't find match for some of the fonts\n");
440                fprintf(stderr,"nsfix: maybe wrong byte order, aborting\n");
441                exit(1);
442        }
443        if(n) {
444                fprintf(stderr,"nsfix: got multiple matches for some of the fonts\n");
445                fprintf(stderr,"nsfix: can't resolve, aborting\n");
446                exit(1);
447        }
448
449        /* now finally write the updated tables */
450        for(i=0; i<nzeroes; i++) {
451                j=zeroid[i];
452                fprintf(stderr, "nsfix: writing table for %s at 0x%lx\n", font[j].nsname,
453                        (long)zerooff[i]);
454
455                font[j].metrics.name=nameaddr[i];
456                if( lseek(f, zerooff[i], SEEK_SET)<0 ) {
457                        sprintf(msg,"nsfix: seek %s to 0x%lx",fn, (long)zerooff[i] );
458                        perror(msg);
459                        exit(1);
460                }
461                if( write(f, &font[j].metrics, sizeof font[j].metrics) != sizeof font[j].metrics ) {
462                        sprintf(msg,"nsfix: write to %s",fn );
463                        perror(msg);
464                        exit(1);
465                }
466        }
467
468        close(f);
469}
Note: See TracBrowser for help on using the repository browser.