[ Index ] |
PHP Cross Reference of vtigercrm-6.1.0 |
[Summary view] [Print] [Text view]
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! */ 40 typedef short t2b; /* 2-byte type */ 41 typedef int t4b; /* 4-byte type */ 42 typedef int tptr; /* integer type with the same size as pointer */ 43 44 struct bbox { /* bounding box */ 45 t2b llx; /* lower-left-x */ 46 t2b lly; 47 t2b urx; 48 t2b ury; /* upper-right-y */ 49 }; 50 51 struct glyphmetrics { /* metrics of one glyph */ 52 t2b width; 53 t2b unknown; 54 struct bbox bbox; 55 }; 56 57 struct 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 65 struct 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 77 struct font font[MAXFONTS]; 78 int nfonts=0; 79 80 char msg[MAXLINE]; 81 82 /*************************** PROTOTYPES **********************/ 83 84 void usage(void); 85 void readconfig( char *fn); 86 void readmetrics(void); 87 void replacefonts( char *fn); 88 89 /************************** main ****************************/ 90 91 main(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 108 void 109 usage(void) 110 { 111 fprintf(stderr,"Use:\n"); 112 fprintf(stderr," nsfix <netscape.bin> <config-file>\n"); 113 } 114 115 116 /************************** readconfig **********************/ 117 118 void 119 readconfig(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 165 void 166 readmetrics(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 249 void 250 replacefonts(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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:08:37 2014 | Cross-referenced by PHPXref 0.7.1 |