|
|
1.1 root 1: #include <X/mit-copyright.h>
2:
3: /*
4: * XPR - process xwd(1) files for the LN03 or LA100 printer
5: *
6: * Author: Michael R. Gretzinger, MIT Project Athena
7: * Copyright (C) 1985, Massachusetts Institute of Technology
8: */
9:
10: #ifndef lint
11: static char *rcsid_xpr_c = "$Header: xpr.c,v 10.4 86/02/01 16:03:38 tony Rel $";
12: #endif
13:
14: #include <sys/types.h>
15: #include <sys/file.h>
16: #include <sys/uio.h>
17: #include <stdio.h>
18: #include "lncmd.h"
19: #include "XWDFile.h"
20:
21: int debug = 0;
22:
23: enum device {LN01, LN03, LA100};
24: enum orientation {PORTRAIT, LANDSCAPE};
25:
26: #define W_MAX 2400
27: #define H_MAX 3150
28: #define W_MARGIN 75
29: #define H_MARGIN 37
30: #define W_PAGE 2550
31: #define H_PAGE 3225
32:
33: #ifdef NOINLINE
34: #define min(x,y) (((x)<(y))?(x):(y))
35: #endif NOINLINE
36:
37: #define F_PORTRAIT 1
38: #define F_LANDSCAPE 2
39: #define F_DUMP 4
40: #define F_NOSIXOPT 8
41: #define F_APPEND 16
42: #define F_NOFF 32
43: #define F_REPORT 64
44:
45:
46: main(argc, argv)
47: char **argv;
48: {
49: XWDFileHeader win;
50: register unsigned char (*sixmap)[];
51: register int i;
52: register int iw;
53: register int ih;
54: register int sixel_count;
55: char *w_name;
56: char *filename;
57: char *output_filename;
58: int scale, width, height, flags, split;
59: int left, top;
60: int top_margin, left_margin;
61: int wpad, hpad;
62: char *header, *trailer;
63: enum orientation orientation;
64: enum device device;
65:
66: parse_args (argc, argv, &scale, &width, &height, &left, &top, &device,
67: &flags, &split, &header, &trailer);
68:
69: /* read in window header */
70: read(0, &win, sizeof win);
71: w_name = (char *)malloc(win.header_size - sizeof win);
72: read(0, w_name, win.header_size - sizeof win);
73:
74: /* calculate orientation and scale */
75: setup_layout(device, win.pixmap_width, win.pixmap_height, flags, width,
76: height, header, trailer, &scale, &orientation);
77:
78: /* calculate w and h cell count */
79: wpad = (16 - (win.pixmap_width & 15)) & 15;
80: iw = win.pixmap_width;
81: ih = (win.pixmap_height + 5) / 6;
82: hpad = (ih * 6) - win.pixmap_height;
83:
84: /* build pixcells from input file */
85: sixel_count = iw * ih;
86: sixmap = (unsigned char (*)[])malloc(sixel_count);
87: build_sixmap(iw, ih, sixmap, wpad, hpad);
88:
89: /* output commands and sixel graphics */
90: if (device == LN03) {
91: /* ln03_grind_fonts(sixmap, iw, ih, scale, &pixmap); */
92: ln03_setup(iw, ih, orientation, scale, left, top,
93: &left_margin, &top_margin, flags, header, trailer);
94: ln03_output_sixels(sixmap, iw, ih, (flags & F_NOSIXOPT), split,
95: scale, top_margin, left_margin);
96: ln03_finish();
97: } else if (device == LA100) {
98: la100_setup(iw, ih, scale);
99: la100_output_sixels(sixmap, iw, ih, (flags & F_NOSIXOPT));
100: la100_finish();
101: } else {
102: fprintf(stderr, "xwd2: device not supported\n");
103: }
104:
105: /* print some statistics */
106: if (flags & F_REPORT) {
107: fprintf(stderr, "Name: %s\n", w_name);
108: fprintf(stderr, "Width: %d, Height: %d\n", win.pixmap_width,
109: win.pixmap_height);
110: fprintf(stderr, "Orientation: %s, Scale: %d\n",
111: (orientation==PORTRAIT) ? "Portrait" : "Landscape", scale);
112: }
113: if (flags & F_DUMP) dump_sixmap(sixmap, iw, ih);
114: }
115:
116: parse_args(argc, argv, scale, width, height, left, top, device, flags,
117: split, header, trailer)
118: register int argc;
119: register char **argv;
120: int *scale;
121: int *width;
122: int *height;
123: int *left;
124: int *top;
125: enum device *device;
126: int *flags;
127: int *split;
128: char **header;
129: char **trailer;
130: {
131: register char *output_filename;
132: register int f;
133: register int len;
134: register int pos;
135: double atof();
136: int atoi();
137:
138: output_filename = NULL;
139: *device = LN03; /* default */
140: *flags = 0;
141: *split = 1;
142: *width = -1;
143: *height = -1;
144: *top = -1;
145: *left = -1;
146: *header = NULL;
147: *trailer = NULL;
148:
149: argc--;
150: argv++;
151:
152: while (argc > 0 && argv[0][0] == '-') {
153: len = strlen(*argv);
154: switch (argv[0][1]) {
155: case 'a': /* -append <filename> */
156: if (!bcmp(*argv, "-append", len)) {
157: argc--; argv++;
158: output_filename = *argv;
159: *flags |= F_APPEND;
160: }
161: break;
162:
163: case 'd': /* -device {ln03 | la100} | -dump */
164: if (len <= 2) {
165: fprintf(stderr, "xwd2: ambiguous option: \"%s\"\n", *argv);
166: exit(1);
167: }
168: if (!bcmp(*argv, "-device", len)) {
169: argc--; argv++;
170: len = strlen(*argv);
171: if (!bcmp(*argv, "ln03", len)) {
172: *device = LN03;
173: } else if (!bcmp(*argv, "la100", len)) {
174: *device = LA100;
175: } else {
176: fprintf(stderr,
177: "xwd2: device \"%s\" not supported\n", *argv);
178: exit(1);
179: }
180: } else if (!bcmp(*argv, "-dump", len)) {
181: *flags |= F_DUMP;
182: }
183: break;
184:
185: case 'h': /* -height <inches> */
186: if (len <= 3) {
187: fprintf(stderr, "xwd2: ambiguous option: \"%s\"\n", *argv);
188: exit(1);
189: }
190: if (!bcmp(*argv, "-height", len)) {
191: argc--; argv++;
192: *height = (int)(300.0 * atof(*argv));
193: } else if (!bcmp(*argv, "-header", len)) {
194: argc--; argv++;
195: *header = *argv;
196: }
197: break;
198:
199: case 'l': /* -landscape | -left <inches> */
200: if (!bcmp(*argv, "-landscape", len)) {
201: *flags |= F_LANDSCAPE;
202: } else if (!bcmp(*argv, "-left", len)) {
203: argc--; argv++;
204: *left = (int)(300.0 * atof(*argv));
205: }
206: break;
207:
208: case 'n': /* -nosixopt | -noff */
209: if (len <= 3) {
210: fprintf(stderr, "xwd2: ambiguous option: \"%s\"\n", *argv);
211: exit(1);
212: }
213: if (!bcmp(*argv, "-nosixopt", len)) {
214: *flags |= F_NOSIXOPT;
215: } else if (!bcmp(*argv, "-noff", len)) {
216: *flags |= F_NOFF;
217: }
218: break;
219:
220: case 'o': /* -output <filename> */
221: if (!bcmp(*argv, "-output", len)) {
222: argc--; argv++;
223: output_filename = *argv;
224: }
225: break;
226:
227: case 'p': /* -portrait */
228: if (!bcmp(*argv, "-portrait", len)) {
229: *flags |= F_PORTRAIT;
230: }
231: break;
232:
233: case 'r': /* -report */
234: if (!bcmp(*argv, "-report", len)) {
235: *flags |= F_REPORT;
236: }
237: break;
238:
239: case 's': /* -scale <scale> | -split <n-pages> */
240: if (!bcmp(*argv, "-scale", len)) {
241: argc--; argv++;
242: *scale = atoi(*argv);
243: } else if (!bcmp(*argv, "-split", len)) {
244: argc--; argv++;
245: *split = atoi(*argv);
246: }
247: break;
248:
249: case 't': /* -top <inches> */
250: if (len <= 2) {
251: fprintf(stderr, "xwd2: ambigous option: \"%s\"\n", *argv);
252: exit(1);
253: }
254: if (!bcmp(*argv, "-top", len)) {
255: argc--; argv++;
256: *top = (int)(300.0 * atof(*argv));
257: } else if (!bcmp(*argv, "-trailer", len)) {
258: argc--; argv++;
259: *trailer = *argv;
260: }
261: break;
262:
263: case 'w': /* -width <inches> */
264: if (!bcmp(*argv, "-width", len)) {
265: argc--; argv++;
266: *width = (int)(300.0 * atof(*argv));
267: }
268: break;
269:
270: }
271: argc--; argv++;
272: }
273:
274: if (argc > 0) {
275: f = open(*argv, O_RDONLY, 0);
276: if (f < 0) {
277: fprintf(stderr, "xwd2: error opening \"%s\" for input\n", *argv);
278: perror("");
279: exit(1);
280: }
281: dup2(f, 0);
282: close(f);
283: /* if (output_filename == NULL) {
284: output_filename = (char *)malloc(strlen(*argv)+10);
285: build_output_filename(*argv, *device, output_filename);
286: } */
287: }
288:
289: if (output_filename != NULL) {
290: if (!(*flags & F_APPEND)) {
291: f = open(output_filename, O_CREAT|O_WRONLY|O_TRUNC, 0664);
292: } else {
293: f = open(output_filename, O_WRONLY, 0);
294: }
295: if (f < 0) {
296: fprintf(stderr, "xwd2: error opening \"%s\" for output\n",
297: output_filename);
298: perror("xwd2");
299: exit(1);
300: }
301: if (*flags & F_APPEND) {
302: pos = lseek(f, 0, 2); /* get eof position */
303: if (*flags & F_NOFF) pos -= 3; /* set position before trailing */
304: /* formfeed and reset */
305: lseek(f, pos, 0); /* set pointer */
306: }
307: dup2(f, 1);
308: close(f);
309: }
310: }
311:
312: setup_layout(device, win_width, win_height, flags, width, height,
313: header, trailer, scale, orientation)
314: enum device device;
315: int win_width;
316: int win_height;
317: int flags;
318: int width;
319: int height;
320: char *header;
321: char *trailer;
322: int *scale;
323: enum orientation *orientation;
324: {
325: register int w_scale;
326: register int h_scale;
327: register int iscale = *scale;
328: register int w_max;
329: register int h_max;
330:
331: if (header != NULL) win_height += 75;
332: if (trailer != NULL) win_height += 75;
333:
334: /* check maximum width and height; set orientation and scale*/
335: if (device == LN03) {
336: if ((win_width < win_height || (flags & F_PORTRAIT)) &&
337: !(flags & F_LANDSCAPE)) {
338: *orientation = PORTRAIT;
339: w_max = (width > 0)? width : W_MAX;
340: h_max = (height > 0)? height : H_MAX;
341: w_scale = w_max / win_width;
342: h_scale = h_max / win_height;
343: *scale = min(w_scale, h_scale);
344: } else {
345: *orientation = LANDSCAPE;
346: w_max = (width > 0)? width : H_MAX;
347: h_max = (height > 0)? height : W_MAX;
348: w_scale = w_max / win_width;
349: h_scale = h_max / win_height;
350: *scale = min(w_scale, h_scale);
351: }
352: } else { /* device == LA100 */
353: *orientation = PORTRAIT;
354: *scale = W_MAX / win_width;
355: }
356: if (*scale == 0) *scale = 1;
357: if (*scale > 6) *scale = 6;
358: if (iscale > 0 && iscale < *scale) *scale = iscale;
359: }
360:
361: dump_sixmap(sixmap, iw, ih)
362: register unsigned char (*sixmap)[];
363: int iw;
364: int ih;
365: {
366: register int i, j;
367: register unsigned char *c;
368:
369: c = (unsigned char *)sixmap;
370: fprintf(stderr, "Sixmap:\n");
371: for (i = 0; i < ih; i++) {
372: for (j = 0; j < iw; j++) {
373: fprintf(stderr, "%02X ", *c++);
374: }
375: fprintf(stderr, "\n\n");
376: }
377: }
378:
379: build_sixmap(iw, ih, sixmap, wpad, hpad)
380: int ih;
381: int iw;
382: unsigned char (*sixmap)[];
383: int wpad;
384: int hpad;
385: {
386: int iwb, iww;
387: int rsize, cc;
388: int w, maxw;
389: struct iovec linevec[6];
390: unsigned char line[6][150];
391: register unsigned char *c;
392: register int i, j, k, m;
393: register int sixel;
394: static int mask[] = {~1, ~2, ~4, ~8, ~16, ~32, ~64, ~128};
395:
396: c = (unsigned char *)sixmap;
397: iwb = (iw + wpad) / 8;
398:
399: for (i = 0; i <= 5; i++) {
400: linevec[i].iov_base = (caddr_t)line[i];
401: linevec[i].iov_len = iwb;
402: }
403:
404: while (--ih >= 0) {
405: if (ih > 0 || hpad == 0) {
406: rsize = iwb * 6;
407: while (rsize > 0) {
408: cc = readv(0, linevec, 6);
409: if (cc == 0) break;
410: rsize -= cc;
411: }
412: } else {
413: i = 6 - hpad;
414: rsize = iwb * i;
415: while (rsize > 0) {
416: cc = readv(0, linevec, i);
417: if (cc == 0) break;
418: rsize -= cc;
419: }
420: for (; i < 6; i++)
421: for (j = 0; j < iwb; j++) line[i][j] = 0xFF;
422: }
423:
424: #ifndef NOINLINE
425: for (i = 0; i < iw; i++) {
426: sixel = extzv(line[0], i, 1);
427: sixel |= extzv(line[1], i, 1) << 1;
428: sixel |= extzv(line[2], i, 1) << 2;
429: sixel |= extzv(line[3], i, 1) << 3;
430: sixel |= extzv(line[4], i, 1) << 4;
431: sixel |= extzv(line[5], i, 1) << 5;
432: *c++ = sixel;
433: }
434: #else
435: for (i = 0, w = iw; w > 0; i++) {
436: for (j = 0; j <= 7; j++) {
437: m = mask[j];
438: k = -j;
439: sixel = ((line[0][i] & ~m) << k++);
440: sixel |= ((line[1][i] & ~m) << k++);
441: sixel |= ((line[2][i] & ~m) << k++);
442: sixel |= ((line[3][i] & ~m) << k++);
443: sixel |= ((line[4][i] & ~m) << k++);
444: sixel |= ((line[5][i] & ~m) << k);
445: *c++ = sixel;
446: if (--w == 0) break;
447: }
448: }
449: #endif
450: }
451: }
452:
453: build_output_filename(name, device, oname)
454: register char *name, *oname;
455: enum device device;
456: {
457: while (*name && *name != '.') *oname++ = *name++;
458: switch (device) {
459: case LN03: bcopy(".ln03", oname, 6); break;
460: case LA100: bcopy(".la100", oname, 7); break;
461: }
462: }
463:
464:
465: ln03_grind_fonts(sixmap, iw, ih, scale, pixmap)
466: unsigned char (*sixmap)[];
467: int iw;
468: int ih;
469: int scale;
470: struct pixmap (**pixmap)[];
471: {
472: }
473:
474:
475: ln03_setup(iw, ih, orientation, scale, left, top, left_margin, top_margin,
476: flags, header, trailer)
477: int iw;
478: int ih;
479: enum orientation orientation;
480: int scale;
481: int left;
482: int top;
483: int *left_margin;
484: int *top_margin;
485: int flags;
486: char *header;
487: char *trailer;
488: {
489: register int i;
490: register int lm, tm, xm;
491: char fontname[6];
492: char buf[256];
493: register char *bp = buf;
494:
495: if (!(flags & F_APPEND)) {
496: sprintf(bp, LN_RIS); bp += 2;
497: sprintf(bp, LN_SSU, 7); bp += 5;
498: sprintf(bp, LN_PUM_SET); bp += sizeof LN_PUM_SET - 1;
499: }
500:
501: if (orientation == PORTRAIT) {
502: lm = (left > 0)? left : (((W_MAX - scale * iw) / 2) + W_MARGIN);
503: tm = (top > 0)? top : (((H_MAX - scale * ih * 6) / 2) + H_MARGIN);
504: sprintf(bp, LN_PFS, "?20"); bp += 7;
505: sprintf(bp, LN_DECOPM_SET); bp += sizeof LN_DECOPM_SET - 1;
506: sprintf(bp, LN_DECSLRM, lm, W_PAGE - lm); bp += strlen(bp);
507: } else {
508: lm = (left > 0)? left : (((H_MAX - scale * iw) / 2) + H_MARGIN);
509: tm = (top > 0)? top : (((W_MAX - scale * ih * 6) / 2) + W_MARGIN);
510: sprintf(bp, LN_PFS, "?21"); bp += 7;
511: sprintf(bp, LN_DECOPM_SET); bp += sizeof LN_DECOPM_SET - 1;
512: sprintf(bp, LN_DECSLRM, lm, H_PAGE - lm); bp += strlen(bp);
513: }
514:
515: if (header != NULL) {
516: sprintf(bp, LN_VPA, tm - 100); bp += strlen(bp);
517: i = strlen(header);
518: xm = (((scale * iw) - (i * 30)) / 2) + lm;
519: sprintf(bp, LN_HPA, xm); bp += strlen(bp);
520: sprintf(bp, LN_SGR, 3); bp += strlen(bp);
521: bcopy(header, bp, i);
522: bp += i;
523: }
524: if (trailer != NULL) {
525: sprintf(bp, LN_VPA, tm + (scale * ih * 6) + 75); bp += strlen(bp);
526: i = strlen(trailer);
527: xm = (((scale * iw) - (i * 30)) / 2) + lm;
528: sprintf(bp, LN_HPA, xm); bp += strlen(bp);
529: sprintf(bp, LN_SGR, 3); bp += strlen(bp);
530: bcopy(trailer, bp, i);
531: bp += i;
532: }
533:
534: sprintf(bp, LN_HPA, lm); bp += strlen(bp);
535: sprintf(bp, LN_VPA, tm); bp += strlen(bp);
536: sprintf(bp, LN_SIXEL_GRAPHICS, 9, 0, scale); bp += strlen(bp);
537: sprintf(bp, "\"1;1"); bp += 4; /* Pixel aspect ratio */
538: write(1, buf, bp-buf);
539: *top_margin = tm;
540: *left_margin = lm;
541: }
542:
543: #define LN03_RESET "\033c"
544:
545: ln03_finish()
546: {
547: write(1, LN03_RESET, sizeof LN03_RESET - 1);
548: }
549:
550: la100_setup(iw, ih, scale)
551: {
552: unsigned char buf[256];
553: register unsigned char *bp;
554: int lm, tm;
555:
556: bp = buf;
557: lm = ((80 - (int)((double)iw / 6.6)) / 2) - 1;
558: if (lm < 1) lm = 1;
559: tm = ((66 - (int)((double)ih / 2)) / 2) - 1;
560: if (tm < 1) tm = 1;
561: sprintf(bp, "\033[%d;%ds", lm, 81-lm); bp += strlen(bp);
562: sprintf(bp, "\033[?7l"); bp += 5;
563: sprintf(bp, "\033[%dd", tm); bp += strlen(bp);
564: sprintf(bp, "\033[%d`", lm); bp += strlen(bp);
565: sprintf(bp, "\033P0q"); bp += 4;
566: write(1, buf, bp-buf);
567: }
568:
569: #define LA100_RESET "\033[1;80s\033[?7h"
570:
571: la100_finish()
572: {
573: write(1, LA100_RESET, sizeof LA100_RESET - 1);
574: }
575:
576: ln03_alter_background(sixmap, iw, ih)
577: unsigned char (*sixmap)[];
578: int iw;
579: int ih;
580: {
581: register int size;
582: register unsigned char *c, *stopc;
583: register unsigned char *startc;
584: register int n;
585:
586: c = (unsigned char *)sixmap;
587: stopc = c + (iw * ih);
588: n = 0;
589: while (c < stopc) {
590: switch (*c) {
591: case 0x08: case 0x11: case 0x04: case 0x22:
592: case 0x20: case 0x21: case 0x24: case 0x00:
593: if (n == 0) startc = c;
594: n++;
595: break;
596:
597: default:
598: if (n >= 2) {
599: while (n-- > 0) *startc++ = 0x00;
600: } else {
601: n = 0;
602: }
603: break;
604: }
605: c++;
606: }
607: }
608:
609: ln03_output_sixels(sixmap, iw, ih, nosixopt, split, scale, top_margin,
610: left_margin)
611: unsigned char (*sixmap)[];
612: int iw;
613: int ih;
614: int nosixopt;
615: int split;
616: int top_margin;
617: int left_margin;
618: {
619: unsigned char *buf;
620: register unsigned char *bp;
621: int i;
622: int j;
623: register int k;
624: register unsigned char *c;
625: register int lastc;
626: register int count;
627: char snum[6];
628: register char *snp;
629:
630: bp = (unsigned char *)malloc(iw*ih+512);
631: buf = bp;
632: count = 0;
633: lastc = -1;
634: c = (unsigned char *)sixmap;
635: split = ih / split; /* number of lines per page */
636:
637: iw--; /* optimization */
638: for (i = 0; i < ih; i++) {
639: for (j = 0; j <= iw; j++) {
640: if (!nosixopt) {
641: if (*c == lastc && j < iw) {
642: count++;
643: c++;
644: continue;
645: }
646: if (count >= 3) {
647: bp--;
648: count++;
649: *bp++ = '!';
650: snp = snum;
651: while (count > 0) {
652: k = count / 10;
653: *snp++ = count - (k * 10) + '0';
654: count = k;
655: }
656: while (--snp >= snum) *bp++ = *snp;
657: *bp++ = (~lastc & 0x3F) + 0x3F;
658: } else if (count > 0) {
659: lastc = (~lastc & 0x3F) + 0x3F;
660: do {
661: *bp++ = lastc;
662: } while (--count > 0);
663: }
664: }
665: lastc = *c++;
666: *bp++ = (~lastc & 0x3F) + 0x3F;
667: }
668: *bp++ = '-'; /* New line */
669: lastc = -1;
670: if ((i % split) == 0 && i != 0) {
671: sprintf(bp, LN_ST); bp += sizeof LN_ST - 1;
672: *bp++ = '\f';
673: sprintf(bp, LN_VPA, top_margin + (i * 6 * scale)); bp += strlen(bp);
674: sprintf(bp, LN_HPA, left_margin); bp += strlen(bp);
675: sprintf(bp, LN_SIXEL_GRAPHICS, 9, 0, scale); bp += strlen(bp);
676: sprintf(bp, "\"1;1"); bp += 4;
677: }
678: }
679:
680: sprintf(bp, LN_ST); bp += sizeof LN_ST - 1;
681: *bp++ = '\f';
682: write(1, buf, bp-buf);
683: }
684:
685: la100_output_sixels(sixmap, iw, ih)
686: unsigned char (*sixmap)[];
687: int iw;
688: int ih;
689: {
690: unsigned char *buf;
691: register unsigned char *bp;
692: int i;
693: register int j, k;
694: register unsigned char *c;
695: register int lastc;
696: register int count;
697: char snum[6];
698:
699: bp = (unsigned char *)malloc(iw*ih+512);
700: buf = bp;
701: count = 0;
702: lastc = -1;
703: c = (unsigned char *)sixmap;
704:
705: for (i = 0; i < ih; i++) {
706: for (j = 0; j < iw; j++) {
707: if (*c == lastc && (j+1) < iw) {
708: count++;
709: c++;
710: continue;
711: }
712: if (count >= 2) {
713: bp -= 2;
714: count = 2 * (count + 1);
715: *bp++ = '!';
716: k = 0;
717: while (count > 0) {
718: snum[k++] = (count % 10) + '0';
719: count /= 10;
720: }
721: while (--k >= 0) *bp++ = snum[k];
722: *bp++ = (~lastc & 0x3F) + 0x3F;
723: count = 0;
724: } else if (count > 0) {
725: lastc = (~lastc & 0x3F) + 0x3F;
726: do {
727: *bp++ = lastc;
728: *bp++ = lastc;
729: } while (--count > 0);
730: }
731: lastc = (~*c & 0x3F) + 0x3F;
732: *bp++ = lastc;
733: *bp++ = lastc;
734: lastc = *c++;
735: }
736: *bp++ = '-'; /* New line */
737: lastc = -1;
738: }
739:
740: sprintf(bp, LN_ST); bp += sizeof LN_ST - 1;
741: *bp++ = '\f';
742: write(1, buf, bp-buf);
743: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.