|
|
1.1 ! root 1: /* ! 2: * ! 3: * Typesetter font tables routines - for postprocessors. ! 4: * ! 5: */ ! 6: ! 7: #include <stdio.h> ! 8: #include <ctype.h> ! 9: ! 10: #include "gen.h" ! 11: #include "ext.h" ! 12: #include "font.h" ! 13: ! 14: Font *mount[MAXFONTS+1]; /* mount table - pointers into fonts[] */ ! 15: Font fonts[MAXFONTS+2]; /* font data - guarantee one empty slot */ ! 16: ! 17: int fcount; /* entries in fonts[] */ ! 18: int mcount; /* fonts currently in memory */ ! 19: int mlimit = MAXFONTS+1; /* and the most we'll allow */ ! 20: ! 21: char *chnames[MAXCH]; /* special character hash table */ ! 22: int nchnames; /* number of entries in chnames[] */ ! 23: ! 24: extern int devres; ! 25: extern int unitwidth; ! 26: extern int nfonts; ! 27: ! 28: /*****************************************************************************/ ! 29: ! 30: checkdesc(path) ! 31: ! 32: char *path; ! 33: ! 34: { ! 35: ! 36: char buf[150]; ! 37: FILE *fp; ! 38: int val = 0; ! 39: ! 40: /* ! 41: * ! 42: * Return non-zero if the typesetter description file path includes, ! 43: * ! 44: * PDL PostScript ! 45: * ! 46: * before the charset table. ! 47: * ! 48: */ ! 49: ! 50: if ( (fp = fopen(path, "r")) != NULL ) { ! 51: while ( fscanf(fp, "%s", buf) != EOF ) { ! 52: if ( strcmp(buf, "PDL") == 0 ) { ! 53: fscanf(fp, "%s", buf); ! 54: val = strcmp(buf, "PostScript") == 0; ! 55: break; ! 56: } else if ( strcmp(buf, "charset") == 0 ) ! 57: break; ! 58: skipline(fp); ! 59: } /* End while */ ! 60: fclose(fp); ! 61: } /* End if */ ! 62: ! 63: return(val); ! 64: ! 65: } /* End of checkdesc */ ! 66: ! 67: /*****************************************************************************/ ! 68: ! 69: getdesc(path) ! 70: ! 71: char *path; ! 72: ! 73: { ! 74: ! 75: char buf[150]; ! 76: FILE *fp; ! 77: int n; ! 78: ! 79: /* ! 80: * ! 81: * Read a typesetter description file. Font and size lists are discarded. Only ! 82: * used to get to the start of the next command. ! 83: * ! 84: */ ! 85: ! 86: if ( (fp = fopen(path, "r")) == NULL ) ! 87: return(-1); ! 88: ! 89: while ( fscanf(fp, "%s", buf) != EOF ) { ! 90: if ( strcmp(buf, "res") == 0 ) ! 91: fscanf(fp, "%d", &devres); ! 92: else if ( strcmp(buf, "unitwidth") == 0 ) ! 93: fscanf(fp, "%d", &unitwidth); ! 94: else if ( strcmp(buf, "sizes") == 0 ) ! 95: while ( fscanf(fp, "%d", &n) != EOF && n != 0 ) ; ! 96: else if ( strcmp(buf, "inmemory") == 0 ) ! 97: fscanf(fp, "%d", &mlimit); ! 98: else if ( strcmp(buf, "Encoding") == 0 ) { ! 99: fscanf(fp, "%s", buf); ! 100: fontencoding = strsave(buf); ! 101: } else if ( strcmp(buf, "fonts") == 0 ) { ! 102: fscanf(fp, "%d", &nfonts); ! 103: for ( n = 0; n < nfonts; n++ ) ! 104: fscanf(fp, "%s", buf); ! 105: } else if ( strcmp(buf, "charset") == 0 ) { ! 106: while ( fscanf(fp, "%s", buf) != EOF ) ! 107: chadd(buf); ! 108: break; ! 109: } /* End if */ ! 110: skipline(fp); ! 111: } /* End while */ ! 112: ! 113: fclose(fp); ! 114: return(1); ! 115: ! 116: } /* End of getdesc */ ! 117: ! 118: /*****************************************************************************/ ! 119: ! 120: getfont(path, fpos) ! 121: ! 122: char *path; ! 123: Font *fpos; ! 124: ! 125: { ! 126: ! 127: FILE *fin; ! 128: Chwid chtemp[MAXCH]; ! 129: static Chwid chinit; ! 130: int i, nw, n, wid, code; ! 131: char buf[300], ch[100], s1[100], s2[100], s3[100], cmd[100]; ! 132: ! 133: ! 134: /* ! 135: * ! 136: * Read a width table from path into *fpos. Skip unnamed characters, spacewidth, ! 137: * ligatures, ascender/descender entries, and anything else not recognized. All ! 138: * calls should come through mountfont(). ! 139: * ! 140: */ ! 141: ! 142: if ( fpos->state == INMEMORY ) ! 143: return(1); ! 144: ! 145: if ( (fin = fopen(path, "r")) == NULL ) ! 146: return(-1); ! 147: ! 148: if ( fpos->state == NEWFONT ) { ! 149: if ( ++fcount > MAXFONTS+1 ) ! 150: return(-1); ! 151: fpos->path = strsave(path); ! 152: } /* End if */ ! 153: ! 154: if ( ++mcount > mlimit && mcount > nfonts+1 ) ! 155: freefonts(); ! 156: ! 157: for ( i = 0; i < ALPHABET-32; i++ ) ! 158: chtemp[i] = chinit; ! 159: ! 160: while ( fscanf(fin, "%s", cmd) != EOF ) { ! 161: if ( strcmp(cmd, "name") == 0 ) { ! 162: release(fpos->name); ! 163: fscanf(fin, "%s", buf); ! 164: fpos->name = strsave(buf); ! 165: } else if ( strcmp(cmd, "fontname") == 0 ) { ! 166: release(fpos->fontname); ! 167: fscanf(fin, "%s", buf); ! 168: fpos->fontname = strsave(buf); ! 169: } else if ( strcmp(cmd, "special") == 0 ) ! 170: fpos->specfont = 1; ! 171: else if ( strcmp(cmd, "named") == 0 ) /* in prologue or somewhere else */ ! 172: fpos->flags |= NAMED; ! 173: else if ( strcmp(cmd, "charset") == 0 ) { ! 174: skipline(fin); ! 175: nw = ALPHABET-32; ! 176: while ( fgets(buf, sizeof(buf), fin) != NULL ) { ! 177: sscanf(buf, "%s %s %s %s", ch, s1, s2, s3); ! 178: if ( s1[0] != '"' ) { /* not a synonym */ ! 179: sscanf(s1, "%d", &wid); ! 180: code = strtol(s3, 0, 0); /* dec/oct/hex */ ! 181: } /* End if */ ! 182: if ( strlen(ch) == 1 ) { /* it's ascii */ ! 183: n = ch[0] - 32; /* origin omits non-graphics */ ! 184: chtemp[n].num = ch[0]; ! 185: chtemp[n].wid = wid; ! 186: chtemp[n].code = code; ! 187: } else if ( ch[0] == '\\' && ch[1] == '0' ) { ! 188: n = strtol(ch+1, 0, 0) - 32; /* check against ALPHABET? */ ! 189: chtemp[n].num = n + 32; ! 190: chtemp[n].wid = wid; ! 191: chtemp[n].code = code; ! 192: } else if ( strcmp(ch, "---") != 0 ) { /* ignore unnamed chars */ ! 193: if ( (n = chindex(ch)) == -1 ) /* global? */ ! 194: n = chadd(ch); ! 195: chtemp[nw].num = n; ! 196: chtemp[nw].wid = wid; ! 197: chtemp[nw].code = code; ! 198: nw++; ! 199: } /* End else */ ! 200: } /* End while */ ! 201: break; ! 202: } /* End else */ ! 203: skipline(fin); ! 204: } /* End while */ ! 205: ! 206: fclose(fin); ! 207: ! 208: fpos->wp = (Chwid *)allocate(nw * sizeof(Chwid)); ! 209: for ( i = 0; i < nw; i++ ) ! 210: fpos->wp[i] = chtemp[i]; ! 211: ! 212: fpos->nchars = nw; ! 213: fpos->state = INMEMORY; ! 214: ! 215: return(1); ! 216: ! 217: } /* End of getfont */ ! 218: ! 219: /*****************************************************************************/ ! 220: ! 221: mountfont(path, m) ! 222: ! 223: char *path; ! 224: int m; ! 225: ! 226: { ! 227: ! 228: Font *fpos; ! 229: ! 230: /* ! 231: * ! 232: * Mount font table from file path at position m. Mounted fonts are guaranteed ! 233: * to be in memory. ! 234: * ! 235: */ ! 236: ! 237: if ( m < 0 || m > MAXFONTS ) ! 238: return(-1); ! 239: ! 240: if ( mount[m] != NULL ) { ! 241: if ( strcmp(path, mount[m]->path) == 0 ) { ! 242: if ( mount[m]->state == INMEMORY ) ! 243: return(1); ! 244: } else { ! 245: mount[m]->mounted--; ! 246: mount[m] = NULL; ! 247: } /* End else */ ! 248: } /* End if */ ! 249: ! 250: mount[m] = fpos = &fonts[findfont(path)]; ! 251: mount[m]->mounted++; ! 252: return(getfont(path, fpos)); ! 253: ! 254: } /* End of mountfont */ ! 255: ! 256: /*****************************************************************************/ ! 257: ! 258: freefonts() ! 259: ! 260: { ! 261: ! 262: int n; ! 263: ! 264: /* ! 265: * ! 266: * Release memory used by all unmounted fonts - except for the path string. ! 267: * ! 268: */ ! 269: ! 270: for ( n = 0; n < MAXFONTS+2; n++ ) ! 271: if ( fonts[n].state == INMEMORY && fonts[n].mounted == 0 ) { ! 272: release(fonts[n].wp); ! 273: fonts[n].wp = NULL; ! 274: fonts[n].state = RELEASED; ! 275: mcount--; ! 276: } /* End if */ ! 277: ! 278: } /* End of freefonts */ ! 279: ! 280: /*****************************************************************************/ ! 281: ! 282: findfont(path) ! 283: ! 284: char *path; ! 285: ! 286: { ! 287: ! 288: register n; ! 289: ! 290: /* ! 291: * ! 292: * Look for path in the fonts table. Returns the index where it was found or can ! 293: * be inserted (if not found). ! 294: * ! 295: */ ! 296: ! 297: for ( n = hash(path, MAXFONTS+2); fonts[n].state != NEWFONT; n = (n+1) % (MAXFONTS+2) ) ! 298: if ( strcmp(path, fonts[n].path) == 0 ) ! 299: break; ! 300: return(n); ! 301: ! 302: } /* End of findfont */ ! 303: ! 304: /*****************************************************************************/ ! 305: ! 306: mounted(m) ! 307: ! 308: int m; ! 309: ! 310: { ! 311: ! 312: /* ! 313: * ! 314: * Return 1 if a font is mounted at position m. ! 315: * ! 316: */ ! 317: ! 318: return((m >= 0 && m <= MAXFONTS && mount[m] != NULL) ? 1 : 0); ! 319: ! 320: } /* End of mounted */ ! 321: ! 322: /*****************************************************************************/ ! 323: ! 324: onfont(c, m) ! 325: ! 326: int c; ! 327: int m; ! 328: ! 329: { ! 330: ! 331: register Font *fp; ! 332: register Chwid *cp, *ep; ! 333: ! 334: /* ! 335: * ! 336: * Returns the position of character c in the font mounted at m, or -1 if the ! 337: * character is not found. ! 338: * ! 339: */ ! 340: ! 341: if ( mounted(m) ) { ! 342: fp = mount[m]; ! 343: if ( c < ALPHABET ) { ! 344: if ( fp->wp[c-32].num == c ) /* ascii at front */ ! 345: return c - 32; ! 346: else return -1; ! 347: } /* End if */ ! 348: ! 349: cp = &fp->wp[ALPHABET-32]; ! 350: ep = &fp->wp[fp->nchars]; ! 351: for ( ; cp < ep; cp++ ) /* search others */ ! 352: if ( cp->num == c ) ! 353: return cp - &fp->wp[0]; ! 354: } /* End if */ ! 355: ! 356: return -1; ! 357: ! 358: } /* End of onfont */ ! 359: ! 360: /*****************************************************************************/ ! 361: ! 362: chwidth(n, m) ! 363: ! 364: int n; ! 365: int m; ! 366: ! 367: { ! 368: ! 369: /* ! 370: * ! 371: * Return width of the character at position n in the font mounted at m. Skip ! 372: * bounds checks - assume it's already been done. ! 373: * ! 374: */ ! 375: ! 376: return(mount[m]->wp[n].wid); ! 377: ! 378: } /* End of chwidth */ ! 379: ! 380: /*****************************************************************************/ ! 381: ! 382: chcode(n, m) ! 383: ! 384: int n; ! 385: int m; ! 386: ! 387: { ! 388: ! 389: /* ! 390: * ! 391: * Return typesetter code for the character at position n in the font mounted ! 392: * at m. Skip bounds checks - assume it's already been done. ! 393: * ! 394: */ ! 395: ! 396: return(mount[m]->wp[n].code); ! 397: ! 398: } /* End of chcode */ ! 399: ! 400: /*****************************************************************************/ ! 401: ! 402: chindex(s) ! 403: ! 404: char *s; ! 405: ! 406: { ! 407: ! 408: register i; ! 409: ! 410: /* ! 411: * ! 412: * Look for s in global character name table. Hash table is guaranteed to have ! 413: * at least one empty slot (by chadd()) so the loop terminate. ! 414: * ! 415: */ ! 416: ! 417: for ( i = hash(s, MAXCH); chnames[i] != NULL; i = (i+1) % MAXCH ) ! 418: if ( strcmp(s, chnames[i]) == 0 ) ! 419: return(i+ALPHABET); ! 420: return(-1); ! 421: ! 422: } /* End of chindex */ ! 423: ! 424: /*****************************************************************************/ ! 425: ! 426: chadd(s) ! 427: ! 428: char *s; ! 429: ! 430: { ! 431: ! 432: register i; ! 433: ! 434: /* ! 435: * ! 436: * Add s to the global character name table. Leave one empty slot so loops ! 437: * terminate. ! 438: * ! 439: */ ! 440: ! 441: if ( nchnames >= MAXCH - 1 ) ! 442: error(FATAL, "out of table space adding character %s", s); ! 443: ! 444: for ( i = hash(s, MAXCH); chnames[i] != NULL; i = (i+1) % MAXCH ) ; ! 445: ! 446: nchnames++; ! 447: chnames[i] = strsave(s); ! 448: ! 449: return(i+ALPHABET); ! 450: ! 451: } /* End of chadd */ ! 452: ! 453: /*****************************************************************************/ ! 454: ! 455: char *chname(n) ! 456: ! 457: int n; ! 458: ! 459: { ! 460: ! 461: /* ! 462: * ! 463: * Returns string for the character with index n. ! 464: * ! 465: */ ! 466: ! 467: return(chnames[n-ALPHABET]); ! 468: ! 469: } /* End of chname */ ! 470: ! 471: /*****************************************************************************/ ! 472: ! 473: hash(s, l) ! 474: ! 475: char *s; ! 476: int l; ! 477: ! 478: { ! 479: ! 480: register i; ! 481: ! 482: /* ! 483: * ! 484: * Return the hash index for string s in a table of length l. Probably should ! 485: * make i unsigned and mod once at the end. ! 486: * ! 487: */ ! 488: ! 489: for ( i = 0; *s != '\0'; s++ ) ! 490: i = (i * 10 + *s) % l; ! 491: return(i); ! 492: ! 493: } /* End of hash */ ! 494: ! 495: /*****************************************************************************/ ! 496: ! 497: char *strsave(s) ! 498: ! 499: char *s; ! 500: ! 501: { ! 502: ! 503: char *ptr = NULL; ! 504: ! 505: /* ! 506: * ! 507: * Make a permanent copy of string s. ! 508: * ! 509: */ ! 510: ! 511: if ( s != NULL ) { ! 512: ptr = (char *)allocate(strlen(s)+1); ! 513: strcpy(ptr, s); ! 514: } /* End if */ ! 515: return(ptr); ! 516: ! 517: } /* End of strsave */ ! 518: ! 519: /*****************************************************************************/ ! 520: ! 521: char *allocate(count) ! 522: ! 523: int count; ! 524: ! 525: { ! 526: ! 527: char *ptr; ! 528: ! 529: /* ! 530: * ! 531: * Allocates count bytes. Free unmounted fonts if the first attempt fails. To ! 532: * be absolutely correct all memory allocation should be done by this routine. ! 533: * ! 534: */ ! 535: ! 536: if ( (ptr = (char *)malloc(count)) == NULL ) { ! 537: freefonts(); ! 538: if ( (ptr = (char *)malloc(count)) == NULL ) ! 539: error(FATAL, "no memory"); ! 540: } /* End if */ ! 541: return(ptr); ! 542: ! 543: } /* End of allocate */ ! 544: ! 545: /*****************************************************************************/ ! 546: ! 547: release(ptr) ! 548: ! 549: char *ptr; ! 550: ! 551: { ! 552: ! 553: /* ! 554: * ! 555: * Free memory provided ptr isn't NULL. ! 556: * ! 557: */ ! 558: ! 559: if ( ptr != NULL ) ! 560: free(ptr); ! 561: ! 562: } /* End of release */ ! 563: ! 564: /*****************************************************************************/ ! 565: ! 566: dumpmount(m) ! 567: ! 568: int m; ! 569: ! 570: { ! 571: ! 572: /* ! 573: * ! 574: * Dumps the font mounted at position n. ! 575: * ! 576: */ ! 577: ! 578: if ( mount[m] != NULL ) ! 579: dumpfont((mount[m] - &fonts[0])); ! 580: else fprintf(stderr, "no font mounted at %d\n", m); ! 581: ! 582: } /* End of dumpmount */ ! 583: ! 584: /*****************************************************************************/ ! 585: ! 586: dumpfont(n) ! 587: ! 588: int n; ! 589: ! 590: { ! 591: ! 592: int i; ! 593: Font *fpos; ! 594: char *str; ! 595: ! 596: /* ! 597: * ! 598: * Dump of everything known about the font saved at fonts[n]. ! 599: * ! 600: */ ! 601: ! 602: fpos = &fonts[n]; ! 603: ! 604: if ( fpos->state ) { ! 605: fprintf(stderr, "path %s\n", fpos->path); ! 606: fprintf(stderr, "state %d\n", fpos->state); ! 607: fprintf(stderr, "flags %d\n", fpos->flags); ! 608: fprintf(stderr, "mounted %d\n", fpos->mounted); ! 609: fprintf(stderr, "nchars %d\n", fpos->nchars); ! 610: fprintf(stderr, "special %d\n", fpos->specfont); ! 611: fprintf(stderr, "name %s\n", fpos->name); ! 612: fprintf(stderr, "fontname %s\n", fpos->fontname); ! 613: if ( fpos->state == INMEMORY ) { ! 614: fprintf(stderr, "charset\n"); ! 615: for ( i = 0; i < fpos->nchars; i++ ) { ! 616: if ( fpos->wp[i].num > 0 ) { ! 617: if ( fpos->wp[i].num < ALPHABET ) ! 618: fprintf(stderr, "%c\t%d\t%d\n", fpos->wp[i].num, ! 619: fpos->wp[i].wid, fpos->wp[i].code); ! 620: else { ! 621: str = chname(fpos->wp[i].num); ! 622: if ( *str == '#' && isdigit(*(str+1)) && isdigit(*(str+2)) ) ! 623: str = "---"; ! 624: fprintf(stderr, "%s\t%d\t%d\n", str, fpos->wp[i].wid, ! 625: fpos->wp[i].code); ! 626: } /* End else */ ! 627: } /* End if */ ! 628: } /* End for */ ! 629: } else fprintf(stderr, "charset: not in memory\n"); ! 630: } else fprintf(stderr, "empty font: %d\n", n); ! 631: ! 632: putc('\n', stderr); ! 633: ! 634: } /* End of dumpfont */ ! 635: ! 636: /*****************************************************************************/ ! 637:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.