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