|
|
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.