|
|
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 "rune.h"
12: #include "ext.h"
13: #include "font.h"
14:
15: Font *mount[MAXFONTS+1]; /* mount table - pointers into fonts[] */
16: Font fonts[MAXFONTS+2]; /* font data - guarantee one empty slot */
17:
18: int fcount; /* entries in fonts[] */
19: int mcount; /* fonts currently in memory */
20: int mlimit = MAXFONTS+1; /* and the most we'll allow */
21:
22: char *chnames[SPECIALCHARS]; /* special character hash table */
23: int nchnames; /* number of entries in chnames[] */
24:
25: extern int devres;
26: extern int unitwidth;
27: extern int nfonts;
28:
29: /*****************************************************************************/
30:
31: checkdesc(path)
32:
33: char *path;
34:
35: {
36:
37: char buf[150];
38: FILE *fp;
39: int val = 0;
40:
41: /*
42: *
43: * Return non-zero if the typesetter description file path includes,
44: *
45: * PDL PostScript
46: *
47: * before the charset table.
48: *
49: */
50:
51: if ( (fp = fopen(path, "r")) != NULL ) {
52: while ( fscanf(fp, "%s", buf) != EOF ) {
53: if ( strcmp(buf, "PDL") == 0 ) {
54: fscanf(fp, "%s", buf);
55: val = strcmp(buf, "PostScript") == 0;
56: break;
57: } else if ( strcmp(buf, "charset") == 0 )
58: break;
59: skipline(fp);
60: } /* End while */
61: fclose(fp);
62: } /* End if */
63:
64: return(val);
65:
66: } /* End of checkdesc */
67:
68: /*****************************************************************************/
69:
70: getdesc(path)
71:
72: char *path;
73:
74: {
75:
76: char buf[150];
77: FILE *fp;
78: int n;
79:
80: if ( (fp = fopen(path, "r")) == NULL )
81: return(-1);
82:
83: while ( fscanf(fp, "%s", buf) != EOF ) {
84: if ( strcmp(buf, "res") == 0 )
85: fscanf(fp, "%d", &devres);
86: else if ( strcmp(buf, "unitwidth") == 0 )
87: fscanf(fp, "%d", &unitwidth);
88: else if ( strcmp(buf, "sizes") == 0 )
89: while ( fscanf(fp, "%d", &n) != EOF && n != 0 ) ;
90: else if ( strcmp(buf, "inmemory") == 0 )
91: fscanf(fp, "%d", &mlimit);
92: else if ( strcmp(buf, "Encoding") == 0 ) {
93: fscanf(fp, "%s", buf);
94: fontencoding = strsave(buf);
95: } else if ( strcmp(buf, "fonts") == 0 ) {
96: fscanf(fp, "%d", &nfonts);
97: for ( n = 0; n < nfonts; n++ )
98: fscanf(fp, "%s", buf);
99: } else if ( strcmp(buf, "charset") == 0 ) {
100: while ( fscanf(fp, "%s", buf) != EOF )
101: chadd(buf);
102: break;
103: } /* End if */
104: skipline(fp);
105: } /* End while */
106:
107: fclose(fp);
108: return(1);
109:
110: } /* End of getdesc */
111:
112: /*****************************************************************************/
113:
114: getfont(path, fpos)
115:
116: char *path;
117: Font *fpos;
118:
119: {
120:
121: FILE *fin;
122: Chwid chtemp[LARGESTFONT];
123: int next;
124: int i, n, num, wid, code;
125: char buf[300], ch[100], s1[100], s2[100], s3[100], cmd[100];
126:
127:
128: /*
129: *
130: * Read a font width table. Skip unnamed characters, spacewidth, ligatures,
131: * ascender/descender entries, and anything else not recognized. Charset
132: * entries for a new font are first stacked in chtemp[] and later copied
133: * to correct slots in a newly allocated wp array. All calls should come
134: * through mountfont().
135: *
136: */
137:
138: if ( fpos->state == INMEMORY )
139: return(1);
140:
141: if ( (fin = fopen(path, "r")) == NULL )
142: return(-1);
143:
144: if ( fpos->state == NEWFONT ) {
145: if ( ++fcount > MAXFONTS+1 )
146: return(-1);
147: fpos->path = strsave(path);
148: } /* End if */
149:
150: if ( ++mcount > mlimit && mcount > nfonts+1 )
151: freefonts();
152:
153: while ( fscanf(fin, "%s", cmd) != EOF ) {
154: if ( strcmp(cmd, "name") == 0 ) {
155: release(fpos->name);
156: fscanf(fin, "%s", buf);
157: fpos->name = strsave(buf);
158: } else if ( strcmp(cmd, "fontname") == 0 ) {
159: release(fpos->fontname);
160: fscanf(fin, "%s", buf);
161: fpos->fontname = strsave(buf);
162: } else if ( strcmp(cmd, "special") == 0 )
163: fpos->specfont = 1;
164: else if ( strcmp(cmd, "named") == 0 ) /* in prologue or somewhere else */
165: fpos->flags |= NAMED;
166: else if ( strcmp(cmd, "charset") == 0 ) {
167: skipline(fin);
168: next = 0;
169: fpos->nchars = 0; /* special characters */
170: fpos->first = LASTCODE;
171: fpos->last = FIRSTCODE;
172: while ( fgets(buf, sizeof(buf), fin) != NULL ) {
173: num = -1;
174: sscanf(buf, "%s %s %s %s", ch, s1, s2, s3);
175: if ( s1[0] != '"' ) { /* not a synonym */
176: sscanf(s1, "%d", &wid);
177: code = strtol(s3, 0, 0); /* dec/oct/hex */
178: } /* End if */
179: if ( strlen(ch) == 1 ) /* it's ascii */
180: num = ch[0];
181: else if ( ch[0] == '\\' && ch[1] == '0' )
182: num = strtol(ch+1, 0, 0);
183: /*
184: * Eventually consider something like,
185: *
186: * else if ( strlen(ch) == chartorune(&r, ch) )
187: * num = r;
188: */
189: else if ( strcmp(ch, "---") != 0 ) { /* ignore unnamed chars */
190: if ( (num = chindex(ch)) == INVALIDCODE )
191: num = chadd(ch);
192: } /* End else */
193: if ( ValidChar(num) ) {
194: if ( next < LARGESTFONT ) {
195: chtemp[next].num = num;
196: chtemp[next].wid = wid;
197: chtemp[next++].code = code;
198: if ( ValidCode(num) ) {
199: fpos->first = (num < fpos->first) ? num : fpos->first;
200: fpos->last = (num > fpos->last) ? num : fpos->last;
201: } else fpos->nchars++;
202: } else error(FATAL, "font %s too large", path);
203: } else if ( num != -1 )
204: error(FATAL, "invalid character in font %s\n", path);
205: } /* End while */
206: break;
207: } /* End else */
208: skipline(fin);
209: } /* End while */
210:
211: fclose(fin);
212:
213: if ( fpos->first > fpos->last )
214: fpos->last = fpos->first - 1;
215: fpos->nchars += fpos->last - fpos->first + 1;
216: fpos->wp = (Chwid *)allocate(fpos->nchars * sizeof(Chwid));
217:
218: for ( i = 0; i < fpos->nchars; i++ )
219: fpos->wp[i].num = INVALIDCODE;
220:
221: for ( i = 0, n = 1; i < next; i++ ) {
222: if ( chtemp[i].num <= fpos->last )
223: fpos->wp[chtemp[i].num - fpos->first] = chtemp[i];
224: else fpos->wp[fpos->last - fpos->first + n++] = chtemp[i];
225: } /* End for */
226:
227: fpos->state = INMEMORY;
228: return(1);
229:
230: } /* End of getfont */
231:
232: /*****************************************************************************/
233:
234: mountfont(path, m)
235:
236: char *path;
237: int m;
238:
239: {
240:
241: Font *fpos;
242:
243: if ( m < 0 || m > MAXFONTS )
244: return(-1);
245:
246: if ( mount[m] != NULL ) {
247: if ( mount[m]->path != NULL && strcmp(path, mount[m]->path) == 0 ) {
248: if ( mount[m]->state == INMEMORY )
249: return(1);
250: } else {
251: mount[m]->mounted--;
252: mount[m] = NULL;
253: } /* End else */
254: } /* End if */
255:
256: mount[m] = fpos = &fonts[findfont(path)];
257: mount[m]->mounted++;
258: return(getfont(path, fpos));
259:
260: } /* End of mountfont */
261:
262: /*****************************************************************************/
263:
264: freefonts()
265:
266: {
267:
268: int n;
269:
270: /*
271: *
272: * Don't release the path without resetting state to NEWFONT - findfont()
273: * assumes path is available.
274: *
275: */
276:
277: for ( n = 0; n < MAXFONTS+2; n++ )
278: if ( fonts[n].state == INMEMORY && fonts[n].mounted == 0 ) {
279: release(fonts[n].wp);
280: fonts[n].wp = NULL;
281: fonts[n].state = RELEASED;
282: mcount--;
283: } /* End if */
284:
285: } /* End of freefonts */
286:
287: /*****************************************************************************/
288:
289: findfont(path)
290:
291: char *path;
292:
293: {
294:
295: register n;
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: return(m >= 0 && m <= MAXFONTS && mount[m] != NULL);
313:
314: } /* End of mounted */
315:
316: /*****************************************************************************/
317:
318: onfont(c, m)
319:
320: int c;
321: int m;
322:
323: {
324:
325: Font *fp;
326: Chwid *cp, *ep;
327:
328: /*
329: *
330: * Returns the position of character c in the font mounted at m, or -1 if the
331: * character is not found.
332: *
333: */
334:
335: if ( mounted(m) ) {
336: fp = mount[m];
337: if ( c >= fp->first && c <= fp->last ) {
338: if ( fp->wp[c-fp->first].num == c )
339: return(c - fp->first);
340: else return(-1);
341: } /* End if */
342:
343: if ( ValidSpecial(c) ) {
344: cp = &fp->wp[fp->last - fp->first + 1];
345: ep = &fp->wp[fp->nchars];
346: for ( ; cp < ep; cp++ ) /* search others */
347: if ( cp->num == c )
348: return(cp - &fp->wp[0]);
349: } /* End if */
350: } /* End if */
351:
352: return(-1);
353:
354: } /* End of onfont */
355:
356: /*****************************************************************************/
357:
358: chindex(s)
359:
360: char *s;
361:
362: {
363:
364: register i;
365:
366: /*
367: *
368: * Return the code assigned to special character s or INVALIDCODE if s
369: * is not currently defined.
370: *
371: */
372:
373: for ( i = hash(s, SPECIALCHARS); chnames[i] != NULL; i = (i+1) % SPECIALCHARS )
374: if ( strcmp(s, chnames[i]) == 0 )
375: return(i+FIRSTSPECIAL);
376: return(INVALIDCODE);
377:
378: } /* End of chindex */
379:
380: /*****************************************************************************/
381:
382: chadd(s)
383:
384: char *s;
385:
386: {
387:
388: register i;
389:
390: if ( nchnames >= SPECIALCHARS - 1 ) /* guarantee one empty slot */
391: error(FATAL, "out of table space adding character %s", s);
392:
393: for ( i = hash(s, SPECIALCHARS); chnames[i] != NULL; i = (i+1) % SPECIALCHARS ) ;
394:
395: nchnames++;
396: chnames[i] = strsave(s);
397: return(i+FIRSTSPECIAL);
398:
399: } /* End of chadd */
400:
401: /*****************************************************************************/
402:
403: char *chname(n)
404:
405: int n;
406:
407: {
408:
409: return(chnames[n-FIRSTSPECIAL]);
410:
411: } /* End of chname */
412:
413: /*****************************************************************************/
414:
415: hash(s, l)
416:
417: char *s;
418: int l;
419:
420: {
421:
422: unsigned i;
423:
424: for ( i = 0; *s; s++ )
425: i = i*10 + *s;
426: return(i % l);
427:
428: } /* End of hash */
429:
430: /*****************************************************************************/
431:
432: char *strsave(s)
433:
434: char *s;
435:
436: {
437:
438: char *ptr = NULL;
439:
440: if ( s != NULL ) {
441: ptr = (char *)allocate(strlen(s)+1);
442: strcpy(ptr, s);
443: } /* End if */
444: return(ptr);
445:
446: } /* End of strsave */
447:
448: /*****************************************************************************/
449:
450: char *allocate(count)
451:
452: int count;
453:
454: {
455:
456: char *ptr;
457:
458: if ( (ptr = (char *)malloc(count)) == NULL ) {
459: freefonts();
460: if ( (ptr = (char *)malloc(count)) == NULL )
461: error(FATAL, "no memory");
462: } /* End if */
463: return(ptr);
464:
465: } /* End of allocate */
466:
467: /*****************************************************************************/
468:
469: release(ptr)
470:
471: char *ptr;
472:
473: {
474:
475: if ( ptr != NULL )
476: free(ptr);
477:
478: } /* End of release */
479:
480: /*****************************************************************************/
481:
482: dumpmount(m)
483:
484: int m;
485:
486: {
487:
488: if ( mount[m] != NULL )
489: dumpfont((mount[m] - &fonts[0]));
490: else fprintf(stderr, "no font mounted at %d\n", m);
491:
492: } /* End of dumpmount */
493:
494: /*****************************************************************************/
495:
496: dumpfont(n)
497:
498: int n;
499:
500: {
501:
502: int i;
503: Font *fpos;
504: char *str;
505:
506: fpos = &fonts[n];
507:
508: if ( fpos->state ) {
509: fprintf(stderr, "path %s\n", fpos->path);
510: fprintf(stderr, "state %d\n", fpos->state);
511: fprintf(stderr, "flags %d\n", fpos->flags);
512: fprintf(stderr, "mounted %d\n", fpos->mounted);
513: fprintf(stderr, "first %d\n", fpos->first);
514: fprintf(stderr, "last %d\n", fpos->last);
515: fprintf(stderr, "nchars %d\n", fpos->nchars);
516: fprintf(stderr, "special %d\n", fpos->specfont);
517: fprintf(stderr, "name %s\n", fpos->name);
518: fprintf(stderr, "fontname %s\n", fpos->fontname);
519: if ( fpos->state == INMEMORY ) {
520: fprintf(stderr, "charset\n");
521: for ( i = 0; i < fpos->nchars; i++ ) {
522: if ( fpos->wp[i].num > 0 ) {
523: if ( fpos->wp[i].num <= fpos->last )
524: fprintf(stderr, "%c\t%d\t%d\n", fpos->wp[i].num,
525: fpos->wp[i].wid, fpos->wp[i].code);
526: else {
527: str = chname(fpos->wp[i].num);
528: if ( *str == '#' && isdigit(*(str+1)) && isdigit(*(str+2)) )
529: str = "---";
530: fprintf(stderr, "%s\t%d\t%d\n", str, fpos->wp[i].wid,
531: fpos->wp[i].code);
532: } /* End else */
533: } /* End if */
534: } /* End for */
535: } else fprintf(stderr, "charset: not in memory\n");
536: } else fprintf(stderr, "empty font: %d\n", n);
537:
538: putc('\n', stderr);
539:
540: } /* End of dumpfont */
541:
542: /*****************************************************************************/
543:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.