|
|
1.1 root 1: /*
2: * dcan
3: * driver for impress/imagen canon laser printer
4: */
5:
6: /*
7: output language from troff:
8: all numbers are character strings
9:
10: sn size in points
11: fn font as number from 1-n
12: cx ascii character x
13: Cxyz funny char xyz. terminated by white space
14: Hn go to absolute horizontal position n
15: Vn go to absolute vertical position n (down is positive)
16: hn go n units horizontally (relative)
17: vn ditto vertically
18: nnc move right nn, then print c (exactly 2 digits!)
19: (this wart is an optimization that shrinks output file size
20: about 35% and run-time about 15% while preserving ascii-ness)
21: Dt ...\n draw operation 't':
22: Dl x y line from here by x,y
23: Dc d circle of diameter d with left side here
24: De x y ellipse of axes x,y with left side here
25: Da x y r arc counter-clockwise by x,y of radius r
26: D~ x y x y ... wiggly line by x,y then x,y ...
27: nb a end of line (information only -- no action needed)
28: b = space before line, a = after
29: p new page begins -- set v to 0
30: #...\n comment
31: x ...\n device control functions:
32: x i init
33: x T s name of device is s
34: x r n h v resolution is n/inch
35: h = min horizontal motion, v = min vert
36: x p pause (can restart)
37: x s stop -- done for ever
38: x t generate trailer
39: x f n s font position n contains font s
40: x H n set character height to n
41: x S n set slant to N
42:
43: Subcommands like "i" are often spelled out like "init".
44: */
45:
46: #include <stdio.h>
47: #include <signal.h>
48: #include <math.h>
49: #include <ctype.h>
50: #include "dev.h"
51: #include "/usr/bwk/imagen/src/imPcodes.h"
52: #include "glyph.h"
53:
54: #define abs(n) ((n) >= 0 ? (n) : -(n))
55:
56: #define NFONT 10
57:
58: int xx, yy;
59: int xoffset = 0; /* shift output right by this amount */
60: int yoffset = -120; /* shift down (!) by this amount */
61: /* -120 is 1/2 inch on canon */
62: /* allows for 10 inch page -- */
63: /* toss away 1/2 inch on top and bottom */
64: float xfac = 1.0; /* scaling factor for x */
65: float yfac = 1.0; /* scaling factor for y */
66: int inputarea = 3; /* input area = 3 * 8k bytes */
67: int rotate = 0; /* 0 => portrait, 1 => landscape */
68: int output = 0; /* do we do output at all? */
69: int pageno = -1; /* output page number */
70: int nolist = 0; /* output page list if > 0 */
71: int olist[20]; /* pairs of page numbers */
72:
73: int erase = 1;
74: float aspect = 1; /* default aspect ratio */
75:
76: struct dev dev;
77: struct font *fontbase[NFONT+1];
78: short *pstab;
79: int nsizes = 1;
80: int nfonts;
81: int smnt; /* index of first special font */
82: int nchtab;
83: char *chname;
84: short *chtab;
85: char *fitab[NFONT+1];
86: char *widthtab[NFONT+1]; /* widtab would be a better name */
87: char *codetab[NFONT+1]; /* device codes */
88:
89: #define FATAL 1
90: #define BMASK 0377
91: int dbg = 0;
92: long lineno = 0;
93: int res = 972; /* input assumed computed according to this resolution */
94: /* initial value to avoid 0 divide */
95: FILE *tf = NULL; /* output file pointer */
96: char *tempfile;
97: char *fontdir = "/usr/lib/font";
98: char *bitdir = "/usr/lib/font/devcan";
99: char *acctfile = "/usr/adm/dcanacct";
100: int acctpages = 0;
101: int copies = 1;
102: char *username = "???";
103: char *getlogin();
104: extern char devname[];
105:
106: FILE *fp = stdin; /* input file pointer */
107:
108: main(argc, argv)
109: char *argv[];
110: {
111: char buf[BUFSIZ];
112: char *mktemp();
113: int done();
114: extern int DX, DY;
115:
116: username = getlogin();
117: while (argc > 1 && argv[1][0] == '-') {
118: switch (argv[1][1]) {
119: case 'c':
120: copies = atoi(&argv[1][2]);
121: break;
122: case 'r':
123: rotate = !rotate;
124: break;
125: case 't':
126: tf = stdout;
127: break;
128: case 'x':
129: xoffset = atoi(&argv[1][2]);
130: break;
131: case 'y':
132: yoffset = atoi(&argv[1][2]);
133: break;
134: case 'f':
135: bitdir = argv[2];
136: argv++;
137: argc--;
138: break;
139: case 'a':
140: aspect = atof(&argv[1][2]);
141: break;
142: case 'e':
143: erase = 0;
144: break;
145: case 'o':
146: outlist(&argv[1][2]);
147: break;
148: case 'i': /* set input area parameter */
149: inputarea = atoi(&argv[1][2]);
150: if (inputarea < 1)
151: inputarea = 1;
152: else if (inputarea > 5)
153: inputarea = 5;
154: break;
155: case 'p': /* pixels of resolution */
156: DX = DY = atoi(&argv[1][2]);
157: if (DX == 0)
158: DX = DY = 1;
159: break;
160: case 'd':
161: dbg = atoi(&argv[1][2]);
162: if (dbg == 0) dbg = 1;
163: tf = stdout;
164: break;
165: }
166: argc--;
167: argv++;
168: }
169:
170: signal(SIGINT, done);
171: signal(SIGHUP, done);
172: signal(SIGQUIT, done);
173:
174: tempfile = mktemp("/tmp/dcanXXXXX");
175: if (tf != stdout)
176: if ((tf = fopen(tempfile, "w")) == NULL)
177: error(FATAL, "can't open temporary file %s", tempfile);
178:
179: if (argc <= 1)
180: conv(stdin);
181: else
182: while (--argc > 0) {
183: if (strcmp(*++argv, "-") == 0)
184: fp = stdin;
185: else if ((fp = fopen(*argv, "r")) == NULL)
186: error(FATAL, "can't open %s", *argv);
187: conv(fp);
188: fclose(fp);
189: }
190: fclose(tf);
191: sprintf(buf, "ipr -p %d -c %d %s", acctpages, copies, tempfile);
192: if(dbg){fprintf(stderr, "executing %s\n", buf); done();}
193: if (tf != stdout) {
194: system(buf);
195: account();
196: }
197: done();
198: }
199:
200: outlist(s) /* process list of page numbers to be printed */
201: char *s;
202: {
203: int n1, n2, i;
204:
205: nolist = 0;
206: while (*s) {
207: n1 = 0;
208: if (isdigit(*s))
209: do
210: n1 = 10 * n1 + *s++ - '0';
211: while (isdigit(*s));
212: else
213: n1 = -9999;
214: n2 = n1;
215: if (*s == '-') {
216: s++;
217: n2 = 0;
218: if (isdigit(*s))
219: do
220: n2 = 10 * n2 + *s++ - '0';
221: while (isdigit(*s));
222: else
223: n2 = 9999;
224: }
225: olist[nolist++] = n1;
226: olist[nolist++] = n2;
227: if (*s != '\0')
228: s++;
229: }
230: olist[nolist] = 0;
231: if (dbg)
232: for (i=0; i<nolist; i += 2)
233: printf("%3d %3d\n", olist[i], olist[i+1]);
234: }
235:
236: in_olist(n) /* is n in olist? */
237: int n;
238: {
239: int i;
240:
241: if (nolist == 0)
242: return(1); /* everything is included */
243: for (i = 0; i < nolist; i += 2)
244: if (n >= olist[i] && n <= olist[i+1])
245: return(1);
246: return(0);
247: }
248:
249: conv(fp)
250: register FILE *fp;
251: {
252: register int c, k;
253: int m, n, i, n1, m1;
254: char str[100], buf[300];
255:
256: while ((c = getc(fp)) != EOF) {
257: switch (c) {
258: case '\n': /* when input is text */
259: case ' ':
260: case 0: /* occasional noise creeps in */
261: break;
262: case '0': case '1': case '2': case '3': case '4':
263: case '5': case '6': case '7': case '8': case '9':
264: /* two motion digits plus a character */
265: hmot((c-'0')*10 + getc(fp)-'0');
266: put1(getc(fp));
267: break;
268: case 'c': /* single ascii character */
269: put1(getc(fp));
270: break;
271: case 'C':
272: fscanf(fp, "%s", str);
273: put1s(str);
274: break;
275: case 'D': /* draw function */
276: fgets(buf, sizeof(buf), fp);
277: switch (buf[0]) {
278: case 'l': /* draw a line */
279: sscanf(buf+1, "%d %d", &n, &m);
280: drawline(n, m, ".");
281: break;
282: case 'c': /* circle */
283: sscanf(buf+1, "%d", &n);
284: drawcirc(n);
285: break;
286: case 'e': /* ellipse */
287: sscanf(buf+1, "%d %d", &m, &n);
288: drawellip(m, n);
289: break;
290: case 'a': /* arc */
291: sscanf(buf+1, "%d %d %d %d", &n, &m, &n1, &m1);
292: drawarc(n, m, n1, m1);
293: break;
294: case '~': /* wiggly line */
295: drawwig(buf+1);
296: break;
297: default:
298: error(FATAL, "unknown drawing function %s\n", buf);
299: break;
300: }
301: break;
302: case 's':
303: fscanf(fp, "%d", &n); /* ignore fractional sizes */
304: setsize(t_size(n));
305: break;
306: case 'f':
307: fscanf(fp, "%s", str);
308: setfont(t_font(str));
309: break;
310: case 'H': /* absolute horizontal motion */
311: /* fscanf(fp, "%d", &n); */
312: while ((c = getc(fp)) == ' ')
313: ;
314: k = 0;
315: do {
316: k = 10 * k + c - '0';
317: } while (isdigit(c = getc(fp)));
318: ungetc(c, fp);
319: hgoto(k);
320: break;
321: case 'h': /* relative horizontal motion */
322: /* fscanf(fp, "%d", &n); */
323: while ((c = getc(fp)) == ' ')
324: ;
325: k = 0;
326: do {
327: k = 10 * k + c - '0';
328: } while (isdigit(c = getc(fp)));
329: ungetc(c, fp);
330: hmot(k);
331: break;
332: case 'w': /* word space */
333: break;
334: case 'V':
335: fscanf(fp, "%d", &n);
336: vgoto(n);
337: break;
338: case 'v':
339: fscanf(fp, "%d", &n);
340: vmot(n);
341: break;
342: case 'p': /* new page */
343: fscanf(fp, "%d", &n);
344: t_page(n);
345: break;
346: case 'n': /* end of line */
347: while (getc(fp) != '\n')
348: ;
349: t_newline();
350: break;
351: case '#': /* comment */
352: while (getc(fp) != '\n')
353: ;
354: break;
355: case 'x': /* device control */
356: devcntrl(fp);
357: break;
358: default:
359: error(!FATAL, "unknown input character %o %c\n", c, c);
360: done();
361: }
362: }
363: }
364:
365: devcntrl(fp) /* interpret device control functions */
366: FILE *fp;
367: {
368: char str[20], str1[50], buf[50];
369: int c, n;
370:
371: fscanf(fp, "%s", str);
372: switch (str[0]) { /* crude for now */
373: case 'i': /* initialize */
374: fileinit();
375: t_init(0);
376: break;
377: case 'T': /* device name */
378: fscanf(fp, "%s", devname);
379: break;
380: case 't': /* trailer */
381: t_trailer();
382: break;
383: case 'p': /* pause -- can restart */
384: t_reset('p');
385: break;
386: case 's': /* stop */
387: t_reset('s');
388: break;
389: case 'r': /* resolution assumed when prepared */
390: fscanf(fp, "%d", &res);
391: break;
392: case 'f': /* font used */
393: fscanf(fp, "%d %s", &n, str);
394: fgets(buf, sizeof buf, fp); /* in case there's a filename */
395: ungetc('\n', fp); /* fgets goes too far */
396: str1[0] = 0; /* in case there's nothing to come in */
397: sscanf(buf, "%s", str1);
398: loadfont(n, str, str1);
399: break;
400: /* these don't belong here... */
401: case 'H': /* char height */
402: fscanf(fp, "%d", &n);
403: t_charht(n);
404: break;
405: case 'S': /* slant */
406: fscanf(fp, "%d", &n);
407: t_slant(n);
408: break;
409: }
410: while ((c = getc(fp)) != '\n') /* skip rest of input line */
411: if (c == EOF)
412: break;
413: }
414:
415: fileinit() /* read in font and code files, etc. */
416: {
417: int i, fin, nw;
418: char *malloc(), *filebase, *p;
419: char temp[60];
420:
421: /* open table for device,
422: /* read in resolution, size info, font info, etc.
423: /* and set params
424: */
425: strcpy(devname, "202"); /* this is the only char set we have */
426: /* the resolution, etc., is already in */
427: sprintf(temp, "%s/dev%s/DESC.out", fontdir, devname);
428: if ((fin = open(temp, 0)) < 0)
429: error(FATAL, "can't open tables for %s\n", temp);
430: read(fin, &dev, sizeof(struct dev));
431: nfonts = dev.nfonts;
432: nsizes = dev.nsizes;
433: nchtab = dev.nchtab;
434: filebase = malloc(dev.filesize); /* enough room for whole file */
435: read(fin, filebase, dev.filesize); /* all at once */
436: pstab = (short *) filebase;
437: chtab = pstab + nsizes + 1;
438: chname = (char *) (chtab + dev.nchtab);
439: p = chname + dev.lchname;
440: for (i = 0; i <= nfonts; i++) {
441: fontbase[i] = NULL;
442: widthtab[i] = codetab[i] = fitab[i] = NULL;
443: }
444: close(fin);
445: }
446:
447: fontprint(i) /* debugging print of font i (0,...) */
448: {
449: int j, k, n;
450: char *p;
451:
452: printf("font %d:\n", i);
453: p = (char *) fontbase[i];
454: n = fontbase[i]->nwfont & BMASK;
455: printf("base=0%o, nchars=%d, spec=%d, name=%s, widtab=0%o, fitab=0%o\n",
456: p, n, fontbase[i]->specfont, fontbase[i]->namefont, widthtab[i], fitab[i]);
457: printf("widths:\n");
458: for (j=0; j <= n; j++) {
459: printf(" %2d", widthtab[i][j] & BMASK);
460: if (j % 20 == 19) printf("\n");
461: }
462: printf("\ncodetab:\n");
463: for (j=0; j <= n; j++) {
464: printf(" %2d", codetab[i][j] & BMASK);
465: if (j % 20 == 19) printf("\n");
466: }
467: printf("\nfitab:\n");
468: for (j=0; j <= dev.nchtab + 128-32; j++) {
469: printf(" %2d", fitab[i][j] & BMASK);
470: if (j % 20 == 19) printf("\n");
471: }
472: printf("\n");
473: }
474:
475: loadfont(n, s, s1) /* load font info for font s on position n (0...) */
476: int n;
477: char *s, *s1;
478: {
479: char temp[60];
480: int fin, nw, norig;
481:
482: if (n < 0 || n > NFONT)
483: error(FATAL, "illegal fp command %d %s", n, s);
484: if (fontbase[n] != NULL && strcmp(s, fontbase[n]->namefont) == 0)
485: return;
486: if (s1 == NULL || s1[0] == '\0')
487: sprintf(temp, "%s/dev%s/%s.out", fontdir, devname, s);
488: else
489: sprintf(temp, "%s/%s.out", s1, s);
490: if ((fin = open(temp, 0)) < 0) {
491: error(!FATAL, "can't open font table %s", temp);
492: return;
493: }
494: if (fontbase[n] != NULL)
495: free(fontbase[n]);
496: fontbase[n] = (struct font *) malloc(3*255 + dev.nchtab +
497: (128-32) + sizeof(struct font));
498: if (fontbase[n] == NULL)
499: error(FATAL, "Out of space in loadfont %s\n", s);
500: read(fin, fontbase[n], 3*255 + nchtab+128-32 + sizeof(struct font));
501: close(fin);
502: if (smnt == 0 && fontbase[n]->specfont == 1)
503: smnt = n;
504: nw = fontbase[n]->nwfont & BMASK;
505: widthtab[n] = (char *) fontbase[n] + sizeof(struct font);
506: codetab[n] = (char *) widthtab[n] + 2 * nw;
507: fitab[n] = (char *) widthtab[n] + 3 * nw;
508: t_fp(n, fontbase[n]->namefont, fontbase[n]->intname);
509: if (dbg > 1) fontprint(n);
510: }
511:
512:
513: error(f, s, a1, a2, a3, a4, a5, a6, a7) {
514: fprintf(stderr, "dcan: ");
515: fprintf(stderr, s, a1, a2, a3, a4, a5, a6, a7);
516: fprintf(stderr, " near line %ld\n", lineno);
517: if (f)
518: done();
519: }
520:
521:
522: /*
523: Here beginneth all the stuff that really depends
524: on the canon (we hope).
525: */
526:
527: #define RES 240 /* resolution of canon */
528: #define MAXX (8*RES + RES/2) /* 8-1/2 inches? */
529: #define MAXY (11 * RES)
530: #define WIDTH 8
531: #define LOGWID 3
532: #define K * 1024 /* clever, so watch out */
533:
534: char devname[20] = "can";
535:
536: int nglyph = 0; /* number of glyphs loaded */
537: int totglyph = 0; /* total space used by glyphs sent down */
538: int maxglyph = 16 K; /* maximum space for glyphs */
539:
540: #define oput(c) if (output) xychar(c); else;
541:
542: /* input coordinate system: */
543:
544: int size = 1;
545: int font = 1; /* current font */
546: int hpos; /* horizontal position where we are supposed to be next (left = 0) */
547: int vpos; /* current vertical position (down positive) */
548: int DX = 10; /* step size in x for drawing */
549: int DY = 10; /* step size in y for drawing */
550:
551: /* canon coordinate system: */
552:
553: int lastsize = -1;
554: int lastfont = -1;
555: int lastx = -1;
556: int lasty = -1;
557: int lastfam = -1;
558:
559: int drawdot = '.'; /* draw with this character */
560: int drawsize = 1; /* shrink by this factor when drawing */
561:
562: t_init(reinit) /* initialize device */
563: int reinit;
564: {
565: int i;
566:
567: if (! reinit) {
568: for (i = 0; i < nchtab; i++)
569: if (strcmp(&chname[chtab[i]], "l.") == 0)
570: break;
571: if (i < nchtab) {
572: drawdot = i + 128;
573: drawsize = 1;
574: } else {
575: drawdot = '.';
576: drawsize = 2; /* half size */
577: }
578:
579: /* some Imagen-specific junk: */
580: fprintf(tf, "%1d", inputarea); /* their kludge for setting */
581: /* input area to x * 8k */
582: maxglyph = 52 K - inputarea K - 4 K;
583: /* glyph area = 52K - input */
584: fprintf(tf, " %s\n", username);
585: putc(0, tf); /* terminate this [so they say] */
586: fprintf(tf, "%8.8s", "dcan1/24"); /* padding 8 bytes */
587: /* ignored but needed */
588: xfac = (float) RES / res * aspect;
589: yfac = (float) RES / res;
590: }
591: fflush(tf);
592: hpos = vpos = 0;
593: setsize(t_size(10)); /* start somewhere */
594: }
595:
596: t_page(pg) /* do whatever new page functions */
597: {
598: register int i, j, n;
599: register unsigned char *p;
600: static int firstpage = 1;
601:
602: pageno = pg;
603: if(dbg)fprintf(stderr, "t_page %d, output=%d\n", pg, output);
604: if (output != 0) {
605: /* beginning of first page, or */
606: /* have just printed something, and seen p<n> for next one */
607: /* ought to read in entire page, select needed glyphs */
608: putc(AEND, tf);
609: firstpage = 0;
610: fflush(tf);
611: }
612: output = in_olist(pg);
613: if (output) {
614: if (totglyph >= maxglyph) {
615: clearglyphs();
616: totglyph = 0;
617: }
618: putc(APAGE, tf);
619: acctpages++;
620: }
621: lastx = lasty = -1;
622: t_init(1);
623: }
624:
625: t_newline() /* do whatever for the end of a line */
626: {
627: hpos = 0;
628: }
629:
630: t_size(n) /* convert integer to internal size number*/
631: int n;
632: {
633: int i;
634:
635: if (n <= pstab[0])
636: return(1);
637: else if (n >= pstab[nsizes-1])
638: return(nsizes);
639: for (i = 0; n > pstab[i]; i++)
640: ;
641: return(i+1);
642: }
643:
644: t_charht(n) /* set character height to n */
645: int n;
646: {
647: /* punt for now */
648: }
649:
650: t_slant(n) /* set slant to n */
651: int n;
652: {
653: /* punt for now */
654: }
655:
656: t_font(s) /* convert string to internal font number */
657: char *s;
658: {
659: int n;
660:
661: n = atoi(s);
662: if (n < 1 || n > nfonts)
663: n = 1;
664: return(n);
665: }
666:
667: t_reset(c)
668: {
669: int n;
670:
671: if (output)
672: acctpages++;
673: if (c == 's') {
674: putc(AEND, tf);
675: putc(AEOF, tf);
676: }
677: }
678:
679: account() /* record paper use */
680: {
681: FILE *f = NULL;
682:
683: if (tf == stdout)
684: return;
685: f = fopen(acctfile, "a");
686: if (f != NULL) {
687: if (username == NULL)
688: username = "???";
689: fprintf(f, "%4d %s\n", acctpages, username);
690: }
691: }
692:
693:
694: t_trailer()
695: {
696: }
697:
698: hgoto(n)
699: {
700: hpos = n; /* this is where we want to be */
701: /* before printing a character, */
702: /* have to make sure it's true */
703: }
704:
705: hmot(n) /* generate n units of horizontal motion */
706: int n;
707: {
708: hpos += n;
709: }
710:
711: vgoto(n)
712: {
713: vpos = n;
714: }
715:
716: vmot(n) /* generate n units of vertical motion */
717: int n;
718: {
719: vgoto(vpos + n); /* ignores rounding */
720: }
721:
722: put1s(s) /* s is a funny char name */
723: register char *s;
724: {
725: static int i = 0;
726:
727: if (!output)
728: return;
729: if (dbg) printf("%s ", s);
730: if (strcmp(s, &chname[chtab[i]]) != 0)
731: for (i = 0; i < nchtab; i++)
732: if (strcmp(&chname[chtab[i]], s) == 0)
733: break;
734: if (i < nchtab)
735: put1(i + 128);
736: else
737: i = 0;
738: }
739:
740: put1(c) /* output char c */
741: register int c;
742: {
743: char *pw;
744: register char *p;
745: register int i, j, k;
746: int ofont, code, w;
747:
748: if (!output)
749: return;
750: c -= 32;
751: if (c <= 0) {
752: if (dbg) printf("non-exist 0%o\n", c+32);
753: return;
754: }
755: k = ofont = font;
756: i = fitab[font][c] & BMASK;
757: if (i != 0) { /* it's on this font */
758: p = codetab[font];
759: pw = widthtab[font];
760: } else if (smnt > 0) { /* on special (we hope) */
761: for (k=smnt, j=0; j <= nfonts; j++, k = (k+1) % (nfonts+1))
762: if ((i = fitab[k][c] & BMASK) != 0) {
763: p = codetab[k];
764: pw = widthtab[k];
765: setfont(k);
766: break;
767: }
768: }
769: if (i == 0 || (code = p[i] & BMASK) == 0 || k > nfonts) {
770: if (dbg) printf("not found 0%o\n", c+32);
771: return;
772: }
773: if (dbg) {
774: if (isprint(c+32))
775: printf("%c %d\n", c+32, code);
776: else
777: printf("%03o %d\n", c+32, code);
778: } else
779: oput(code);
780: if (font != ofont)
781: setfont(ofont);
782: }
783:
784: setsize(n) /* set point size to n (internal) */
785: int n;
786: {
787: size = n;
788: }
789:
790: /* font position info: */
791:
792: struct {
793: char *name;
794: int number;
795: } fontname[NFONT+1];
796:
797: t_fp(n, s, si) /* font position n now contains font s, intname si */
798: int n;
799: char *s, *si;
800: {
801: fontname[n].name = s;
802: fontname[n].number = atoi(si);
803: }
804:
805: setfont(n) /* set font to n */
806: int n;
807: {
808: if (!output)
809: return;
810: if (n < 0 || n > NFONT)
811: error(FATAL, "illegal font %d\n", n);
812: font = n;
813: }
814:
815: done()
816: {
817: exit(0);
818: }
819:
820: /*
821: The following things manage raster font information.
822: The big problem is mapping desired font + size into
823: available font + size. For now, a file RASTERLIST
824: contains entries like
825: R 6 8 10 14 999
826: I 8 10 12 999
827: ...
828: This data is used to create an array "fontdata" that
829: describes legal fonts and sizes, and pointers to any
830: data from files that has actually been loaded.
831: */
832:
833: struct fontdata {
834: char name[4]; /* e.g., "R" or "PA" */
835: int size[10]; /* e.g., 6 8 10 14 0 */
836: struct fontset *fsp[10]; /* either NULL or block of data */
837: };
838:
839: #define MAXFONT 20 /* no more than this many fonts forever */
840:
841: struct fontdata fontdata[MAXFONT];
842: int maxfonts = 0; /* how many actually used; set in initfontdata() */
843:
844: struct Fontheader fh;
845: struct fontset {
846: int size;
847: int family;
848: struct Charparam *chp;
849: unsigned char *cdp; /* char data pointer */
850: unsigned char *chused; /* bit-indexed; 1 if char downloaded */
851: };
852:
853: /* A global variable for the current font+size */
854: struct fontset *fs;
855: int nfamily = 0; /* number of "families" (font+size) */
856:
857: initfontdata() /* read RASTERLIST information */
858: {
859: char name[100];
860: FILE *fp;
861: int i, j, n;
862:
863: sprintf(name, "%s/RASTERLIST", bitdir);
864: if ((fp = fopen(name, "r")) == NULL)
865: error(FATAL, "can't open %s\n", name);
866: maxfonts = 0;
867: while (fscanf(fp, "%s", fontdata[maxfonts].name) != EOF) {
868: i = 0;
869: while (fscanf(fp, "%d", &n) != EOF && n < 100) {
870: fontdata[maxfonts].size[i] = n;
871: fontdata[maxfonts].fsp[i] = NULL;
872: i++;
873: }
874: fontdata[maxfonts].size[i] = 999;
875: if (++maxfonts > MAXFONT)
876: error(FATAL, "Too many fonts in RASTERLIST");
877: }
878: fclose(fp);
879: if (dbg) {
880: fprintf(stderr, "initfontdata(): maxfonts=%d\n", maxfonts);
881: for (i = 0; i < maxfonts; i++) {
882: fprintf(stderr, "%.4s ", fontdata[i].name);
883: for (j = 0; fontdata[i].size[j] < 100; j++)
884: fprintf(stderr, " %3d", fontdata[i].size[j]);
885: fprintf(stderr, "\n");
886: }
887: }
888: }
889:
890: getfontdata(f, s) /* causes loading of font information if needed */
891: char *f;
892: int s;
893: {
894: int fd, n, i, j;
895: char name[100];
896: static int first = 1;
897:
898: if (first) {
899: initfontdata();
900: first = 0;
901: }
902:
903: for (i = 0; i < maxfonts; i++)
904: if (strcmp(f, fontdata[i].name) == 0)
905: break;
906: if (i >= maxfonts) /* the requested font wasn't there */
907: i = 0; /* use the first one (probably R) */
908:
909: /* find the best approximation to size s */
910: for (j = 1; s >= fontdata[i].size[j]; j++)
911: ;
912: j--;
913:
914: /* open file if necessary */
915: if (fontdata[i].fsp[j] == NULL) {
916: fs = (struct fontset *) malloc(sizeof(struct fontset));
917: fontdata[i].fsp[j] = fs;
918: fs->chp = (struct Charparam *) malloc(256*sizeof(struct Charparam));
919: sprintf(name, "%s/%s.%d%s", bitdir,
920: f, fontdata[i].size[j], rotate? "r" : "");
921: fd = open(name, 0);
922: if (fd == -1)
923: error(FATAL, "can't open %s\n", name);
924: read(fd, &fh, sizeof(struct Fontheader));
925: read(fd, fs->chp, 256*sizeof(struct Charparam));
926: fs->size = fontdata[i].size[j];
927: fs->family = nfamily;
928: nfamily += 2; /* even-odd leaves room for big fonts */
929: fs->cdp = (unsigned char *) malloc(fh.f_size);
930: fs->chused = (unsigned char *) malloc(256/8);
931: read(fd, fs->cdp, fh.f_size);
932: close(fd);
933: }
934: fs = fontdata[i].fsp[j];
935: }
936:
937: xychar(c)
938: register int c;
939: {
940: register unsigned char *p;
941: register struct Charparam *par;
942: register int x, y;
943: int i, n, rwid, ht, fam;
944:
945: x = hpos * xfac + 0.5;
946: x += xoffset;
947: y = vpos * yfac + 0.5;
948: y += yoffset;
949:
950: if (font != lastfont || size != lastsize) {
951: getfontdata(fontname[font].name, pstab[size-1]);
952: lastsize = size;
953: lastfont = font;
954: }
955: par = fs->chp + c;
956: p = fs->cdp + par->c_addr;
957:
958: fam = fs->family;
959: if (c > 127)
960: fam++;
961: if (fam != lastfam) {
962: putc(AF, tf);
963: putc(lastfam = fam, tf);
964: }
965:
966: /* first cut: ship each glyph as needed. */
967: /* ignore memory use, efficiency, etc. */
968:
969: if ( !bit(fs->chused, c) ) { /* 1st use of this character */
970: nglyph++;
971: totglyph += glspace(par);
972: setbit(fs->chused, c);
973: putc(ASGLY, tf);
974: putint((fam << 7) | c, tf);
975: /* putc(par->c_width, tf); /* character width */
976: putc(0, tf); /* zap nominal width because it's wrong */
977: putc(par->c_left + par->c_right + 1, tf);
978: putc(par->c_left, tf);
979: /* this nonsense fixes a bug in output produced by rec.c: */
980: /* when up is < 0 (and = 0?) size is one too big */
981: rwid = (1 + par->c_left + par->c_right + WIDTH-1) / WIDTH;
982: ht = par->c_size / rwid;
983: par->c_down = ht - par->c_up;
984: putc(par->c_down + par->c_up, tf);
985: putc(par->c_up, tf);
986: for (i = par->c_size; i--; )
987: putc(*p++, tf);
988: }
989:
990: if (y != lasty) {
991: putc(AV, tf);
992: putint(y<<1, tf);
993: lasty = y;
994: }
995: if (x != lastx) {
996: if (abs(x-lastx) > 127) {
997: putc(AH, tf);
998: putint(x<<1, tf);
999: } else {
1000: putc(AM, tf);
1001: putc(x-lastx, tf);
1002: putc(AM, tf);
1003: }
1004: }
1005:
1006: if (c <= 127)
1007: putc(c, tf); /* fails if c > 127, probably disastrously */
1008: else
1009: putc(c-128, tf);
1010: /* lastx = x + par->c_width; */
1011: lastx = x;
1012: }
1013:
1014: glspace(par)
1015: struct Charparam *par;
1016: {
1017: int n;
1018:
1019: /* works only for small glyphs right now */
1020:
1021: n = 12
1022: + ((par->c_left+par->c_right+1+15)/16 ) * (par->c_up+par->c_down)
1023: + 2;
1024: return n;
1025: }
1026:
1027: clearglyphs() /* remove "used" bits from all glyphs */
1028: /* delete all families */
1029: /* very conservative policy */
1030: {
1031: int i, j, k;
1032: struct fontset *f;
1033:
1034: if (tf == stdout) fprintf(stderr, "clear %d glyphs (%d/%d) on page %d\n",
1035: nglyph, totglyph, maxglyph, pageno);
1036: for (i = 0; i < maxfonts; i++)
1037: for (j = 0; fontdata[i].size[j] < 999; j++) {
1038: f = fontdata[i].fsp[j];
1039: if (f != NULL) {
1040: putc(ADELF, tf);
1041: putc(f->family, tf);
1042: for (k = 0; k < 256/8; k++)
1043: f->chused[k] = 0;
1044: }
1045: }
1046: }
1047:
1048: bit(p, n) /* return n-th bit of p[] */
1049: char *p;
1050: int n;
1051: {
1052: return (p[n/8] >> (7 - n%8)) & 01;
1053: }
1054:
1055: setbit(p, n) /* set bit n of p[] */
1056: char *p;
1057: int n;
1058: {
1059: p[n/8] |= 01 << (7 - n%8);
1060: }
1061:
1062: putint(n, f)
1063: int n;
1064: FILE *f;
1065: {
1066: putc(n >> 8, f);
1067: putc(n & 0377, f);
1068: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.