|
|
1.1 root 1: #include <X11/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: * Modified by Marvin Solomon, Univeristy of Wisconsin, to handle Apple
10: * Laserwriter (PostScript) devices (-device ps).
11: * Also accepts the -compact flag that produces more compact output
12: * by using run-length encoding on white (1) pixels.
13: * This version does not (yet) support the following options
14: * -append -dump -noff -nosixopt -split
15: *
16: * Changes
17: * Copyright 1986 by Marvin Solomon and the University of Wisconsin
18: *
19: * Permission to use, copy, modify, and distribute this
20: * software and its documentation for any purpose and without
21: * fee is hereby granted, provided that the above copyright
22: * notice appear in all copies and that both that copyright
23: * notice and this permission notice appear in supporting
24: * documentation, and that the names of Marvin Solomon and
25: * the University of Wisconsin not be used in
26: * advertising or publicity pertaining to distribution of the
27: * software without specific, written prior permission.
28: * Neither Marvin Solomon nor the University of Wisconsin
29: * makes any representations about the suitability of
30: * this software for any purpose. It is provided "as is"
31: * without express or implied warranty.
32: *
33: */
34:
35: #ifndef lint
36: static char *rcsid_xpr_c = "$Header: xpr.c,v 1.18 87/09/11 20:02:55 toddb Exp $";
37: #endif
38:
39: #include <sys/types.h>
40: #include <sys/file.h>
41: #include <sys/uio.h>
42: #include <stdio.h>
43: #include <pwd.h>
44: #include "lncmd.h"
45: #include <X11/Xlib.h>
46: #include "X11/XWDFile.h"
47:
48: int debug = 0;
49:
50: enum device {LN01, LN03, LA100, PS};
51: enum orientation {PORTRAIT, LANDSCAPE};
52:
53: #define W_MAX 2400
54: #define H_MAX 3150
55: #define W_MARGIN 75
56: #define H_MARGIN 37
57: #define W_PAGE 2550
58: #define H_PAGE 3225
59:
60: #ifdef NOINLINE
61: #define min(x,y) (((x)<(y))?(x):(y))
62: #endif NOINLINE
63:
64: #define F_PORTRAIT 1
65: #define F_LANDSCAPE 2
66: #define F_DUMP 4
67: #define F_NOSIXOPT 8
68: #define F_APPEND 16
69: #define F_NOFF 32
70: #define F_REPORT 64
71: #define F_COMPACT 128
72:
73: char *infilename = "stdin";
74:
75: main(argc, argv)
76: char **argv;
77: {
78: unsigned long swaptest = 1;
79: XWDFileHeader win;
80: register unsigned char (*sixmap)[];
81: register int i;
82: register int iw;
83: register int ih;
84: register int sixel_count;
85: char *w_name;
86: char *filename;
87: char *output_filename;
88: int scale, width, height, flags, split;
89: int left, top;
90: int top_margin, left_margin;
91: int hpad;
92: char *header, *trailer;
93: enum orientation orientation;
94: enum device device;
95:
96: parse_args (argc, argv, &scale, &width, &height, &left, &top, &device,
97: &flags, &split, &header, &trailer);
98:
99: /* read in window header */
100: read(0, &win, sizeof win);
101: if (*(char *) &swaptest)
102: _swaplong((char *) &win, sizeof(win));
103:
104: if (win.file_version != XWD_FILE_VERSION) {
105: fprintf(stderr,"xpr: file format version missmatch.\n");
106: exit(1);
107: }
108: if (win.header_size < sizeof(win)) {
109: fprintf(stderr,"xpr: header size is too small.\n");
110: exit(1);
111: }
112:
113: if (win.pixmap_depth != 1 && win.pixmap_format != XYPixmap) {
114: fprintf(stderr,"xpr: image is not in XY format");
115: exit(1);
116: }
117:
118: if (win.byte_order != win.bitmap_bit_order)
119: fprintf(stderr,"xpr: image will be incorrect, byte swapping required but not performed.\n");
120:
121: w_name = (char *)malloc(win.header_size - sizeof win);
122: read(0, w_name, win.header_size - sizeof win);
123:
124: if(win.ncolors)
125: read(0,
126: malloc(win.ncolors * sizeof(XColor)),
127: win.ncolors * sizeof(XColor));
128:
129: /* calculate orientation and scale */
130: setup_layout(device, win.pixmap_width, win.pixmap_height, flags, width,
131: height, header, trailer, &scale, &orientation);
132:
133: if (device == PS) {
134: iw = win.pixmap_width;
135: ih = win.pixmap_height;
136: } else {
137: /* calculate w and h cell count */
138: iw = win.pixmap_width;
139: ih = (win.pixmap_height + 5) / 6;
140: hpad = (ih * 6) - win.pixmap_height;
141:
142: /* build pixcells from input file */
143: sixel_count = iw * ih;
144: sixmap = (unsigned char (*)[])malloc(sixel_count);
145: build_sixmap(iw, ih, sixmap, hpad, &win);
146: }
147:
148: /* output commands and sixel graphics */
149: if (device == LN03) {
150: /* ln03_grind_fonts(sixmap, iw, ih, scale, &pixmap); */
151: ln03_setup(iw, ih, orientation, scale, left, top,
152: &left_margin, &top_margin, flags, header, trailer);
153: ln03_output_sixels(sixmap, iw, ih, (flags & F_NOSIXOPT), split,
154: scale, top_margin, left_margin);
155: ln03_finish();
156: } else if (device == LA100) {
157: la100_setup(iw, ih, scale);
158: la100_output_sixels(sixmap, iw, ih, (flags & F_NOSIXOPT));
159: la100_finish();
160: } else if (device == PS) {
161: ps_setup(iw, ih, orientation, scale, left, top,
162: flags, header, trailer, w_name);
163: ps_output_bits(iw, ih, flags, orientation, &win);
164: ps_finish();
165: } else {
166: fprintf(stderr, "xpr: device not supported\n");
167: }
168:
169: /* print some statistics */
170: if (flags & F_REPORT) {
171: fprintf(stderr, "Name: %s\n", w_name);
172: fprintf(stderr, "Width: %d, Height: %d\n", win.pixmap_width,
173: win.pixmap_height);
174: fprintf(stderr, "Orientation: %s, Scale: %d\n",
175: (orientation==PORTRAIT) ? "Portrait" : "Landscape", scale);
176: }
177: if (device != PS && (flags & F_DUMP)) dump_sixmap(sixmap, iw, ih);
178: }
179:
180: parse_args(argc, argv, scale, width, height, left, top, device, flags,
181: split, header, trailer)
182: register int argc;
183: register char **argv;
184: int *scale;
185: int *width;
186: int *height;
187: int *left;
188: int *top;
189: enum device *device;
190: int *flags;
191: int *split;
192: char **header;
193: char **trailer;
194: {
195: register char *output_filename;
196: register int f;
197: register int len;
198: register int pos;
199: double atof();
200: int atoi();
201:
202: output_filename = NULL;
203: *device = LN03; /* default */
204: *flags = 0;
205: *split = 1;
206: *width = -1;
207: *height = -1;
208: *top = -1;
209: *left = -1;
210: *header = NULL;
211: *trailer = NULL;
212:
213: argc--;
214: argv++;
215:
216: while (argc > 0 && argv[0][0] == '-') {
217: len = strlen(*argv);
218: switch (argv[0][1]) {
219: case 'a': /* -append <filename> */
220: if (!bcmp(*argv, "-append", len)) {
221: argc--; argv++;
222: output_filename = *argv;
223: *flags |= F_APPEND;
224: }
225: break;
226:
227: case 'd': /* -device {ln03 | la100 | ps | lw} | -dump */
228: if (len <= 2) {
229: fprintf(stderr, "xpr: ambiguous option: \"%s\"\n", *argv);
230: exit(1);
231: }
232: if (!bcmp(*argv, "-device", len)) {
233: argc--; argv++;
234: len = strlen(*argv);
235: if (!bcmp(*argv, "ln03", len)) {
236: *device = LN03;
237: } else if (!bcmp(*argv, "la100", len)) {
238: *device = LA100;
239: } else if (!bcmp(*argv, "ps", len)) {
240: *device = PS;
241: } else if (!bcmp(*argv, "lw", len)) {
242: *device = PS;
243: } else {
244: fprintf(stderr,
245: "xpr: device \"%s\" not supported\n", *argv);
246: exit(1);
247: }
248: } else if (!bcmp(*argv, "-dump", len)) {
249: *flags |= F_DUMP;
250: }
251: break;
252:
253: case 'h': /* -height <inches> */
254: if (len <= 3) {
255: fprintf(stderr, "xpr: ambiguous option: \"%s\"\n", *argv);
256: exit(1);
257: }
258: if (!bcmp(*argv, "-height", len)) {
259: argc--; argv++;
260: *height = (int)(300.0 * atof(*argv));
261: } else if (!bcmp(*argv, "-header", len)) {
262: argc--; argv++;
263: *header = *argv;
264: }
265: break;
266:
267: case 'l': /* -landscape | -left <inches> */
268: if (!bcmp(*argv, "-landscape", len)) {
269: *flags |= F_LANDSCAPE;
270: } else if (!bcmp(*argv, "-left", len)) {
271: argc--; argv++;
272: *left = (int)(300.0 * atof(*argv));
273: }
274: break;
275:
276: case 'n': /* -nosixopt | -noff */
277: if (len <= 3) {
278: fprintf(stderr, "xpr: ambiguous option: \"%s\"\n", *argv);
279: exit(1);
280: }
281: if (!bcmp(*argv, "-nosixopt", len)) {
282: *flags |= F_NOSIXOPT;
283: } else if (!bcmp(*argv, "-noff", len)) {
284: *flags |= F_NOFF;
285: }
286: break;
287:
288: case 'o': /* -output <filename> */
289: if (!bcmp(*argv, "-output", len)) {
290: argc--; argv++;
291: output_filename = *argv;
292: }
293: break;
294:
295: case 'p': /* -portrait */
296: if (!bcmp(*argv, "-portrait", len)) {
297: *flags |= F_PORTRAIT;
298: }
299: break;
300:
301: case 'c': /* -compact */
302: if (!bcmp(*argv, "-compact", len)) {
303: *flags |= F_COMPACT;
304: }
305: break;
306:
307: case 'r': /* -report */
308: if (!bcmp(*argv, "-report", len)) {
309: *flags |= F_REPORT;
310: }
311: break;
312:
313: case 's': /* -scale <scale> | -split <n-pages> */
314: if (!bcmp(*argv, "-scale", len)) {
315: argc--; argv++;
316: *scale = atoi(*argv);
317: } else if (!bcmp(*argv, "-split", len)) {
318: argc--; argv++;
319: *split = atoi(*argv);
320: }
321: break;
322:
323: case 't': /* -top <inches> */
324: if (len <= 2) {
325: fprintf(stderr, "xpr: ambigous option: \"%s\"\n", *argv);
326: exit(1);
327: }
328: if (!bcmp(*argv, "-top", len)) {
329: argc--; argv++;
330: *top = (int)(300.0 * atof(*argv));
331: } else if (!bcmp(*argv, "-trailer", len)) {
332: argc--; argv++;
333: *trailer = *argv;
334: }
335: break;
336:
337: case 'w': /* -width <inches> */
338: if (!bcmp(*argv, "-width", len)) {
339: argc--; argv++;
340: *width = (int)(300.0 * atof(*argv));
341: }
342: break;
343:
344: }
345: argc--; argv++;
346: }
347:
348: if (argc > 0) {
349: f = open(*argv, O_RDONLY, 0);
350: if (f < 0) {
351: fprintf(stderr, "xpr: error opening \"%s\" for input\n", *argv);
352: perror("");
353: exit(1);
354: }
355: dup2(f, 0);
356: close(f);
357: infilename = *argv;
358: /* if (output_filename == NULL) {
359: output_filename = (char *)malloc(strlen(*argv)+10);
360: build_output_filename(*argv, *device, output_filename);
361: } */
362: }
363:
364: if (output_filename != NULL) {
365: if (!(*flags & F_APPEND)) {
366: f = open(output_filename, O_CREAT|O_WRONLY|O_TRUNC, 0664);
367: } else {
368: f = open(output_filename, O_WRONLY, 0);
369: }
370: if (f < 0) {
371: fprintf(stderr, "xpr: error opening \"%s\" for output\n",
372: output_filename);
373: perror("xpr");
374: exit(1);
375: }
376: if (*flags & F_APPEND) {
377: pos = lseek(f, 0, 2); /* get eof position */
378: if (*flags & F_NOFF) pos -= 3; /* set position before trailing */
379: /* formfeed and reset */
380: lseek(f, pos, 0); /* set pointer */
381: }
382: dup2(f, 1);
383: close(f);
384: }
385: }
386:
387: setup_layout(device, win_width, win_height, flags, width, height,
388: header, trailer, scale, orientation)
389: enum device device;
390: int win_width;
391: int win_height;
392: int flags;
393: int width;
394: int height;
395: char *header;
396: char *trailer;
397: int *scale;
398: enum orientation *orientation;
399: {
400: register int w_scale;
401: register int h_scale;
402: register int iscale = *scale;
403: register int w_max;
404: register int h_max;
405:
406: if (header != NULL) win_height += 75;
407: if (trailer != NULL) win_height += 75;
408:
409: /* check maximum width and height; set orientation and scale*/
410: if (device == LN03 || device == PS) {
411: if ((win_width < win_height || (flags & F_PORTRAIT)) &&
412: !(flags & F_LANDSCAPE)) {
413: *orientation = PORTRAIT;
414: w_max = (width > 0)? width : W_MAX;
415: h_max = (height > 0)? height : H_MAX;
416: w_scale = w_max / win_width;
417: h_scale = h_max / win_height;
418: *scale = min(w_scale, h_scale);
419: } else {
420: *orientation = LANDSCAPE;
421: w_max = (width > 0)? width : H_MAX;
422: h_max = (height > 0)? height : W_MAX;
423: w_scale = w_max / win_width;
424: h_scale = h_max / win_height;
425: *scale = min(w_scale, h_scale);
426: }
427: } else { /* device == LA100 */
428: *orientation = PORTRAIT;
429: *scale = W_MAX / win_width;
430: }
431: if (*scale == 0) *scale = 1;
432: if (*scale > 6) *scale = 6;
433: if (iscale > 0 && iscale < *scale) *scale = iscale;
434: }
435:
436: dump_sixmap(sixmap, iw, ih)
437: register unsigned char (*sixmap)[];
438: int iw;
439: int ih;
440: {
441: register int i, j;
442: register unsigned char *c;
443:
444: c = (unsigned char *)sixmap;
445: fprintf(stderr, "Sixmap:\n");
446: for (i = 0; i < ih; i++) {
447: for (j = 0; j < iw; j++) {
448: fprintf(stderr, "%02X ", *c++);
449: }
450: fprintf(stderr, "\n\n");
451: }
452: }
453:
454: build_sixmap(iw, ih, sixmap, hpad, win)
455: int ih;
456: int iw;
457: unsigned char (*sixmap)[];
458: int hpad;
459: XWDFileHeader *win;
460: {
461: int iwb = win->bytes_per_line;
462: int iww;
463: int rsize, cc;
464: int w, maxw;
465: struct iovec linevec[6];
466: unsigned char line[6][500];
467: register unsigned char *c;
468: register int i, j, k, m;
469: register int sixel;
470: static int mask[] = {~1, ~2, ~4, ~8, ~16, ~32, ~64, ~128};
471:
472: c = (unsigned char *)sixmap;
473:
474: for (i = 0; i <= 5; i++) {
475: linevec[i].iov_base = (caddr_t)line[i];
476: linevec[i].iov_len = iwb;
477: }
478:
479: while (--ih >= 0) {
480: if (ih > 0 || hpad == 0) {
481: rsize = iwb * 6;
482: while (rsize > 0) {
483: cc = readv(0, linevec, 6);
484: if (cc == 0) break;
485: rsize -= cc;
486: }
487: } else {
488: i = 6 - hpad;
489: rsize = iwb * i;
490: while (rsize > 0) {
491: cc = readv(0, linevec, i);
492: if (cc == 0) break;
493: rsize -= cc;
494: }
495: for (; i < 6; i++)
496: for (j = 0; j < iwb; j++) line[i][j] = 0xFF;
497: }
498:
499: if (win->bitmap_bit_order == MSBFirst)
500: for (i = 0; i <= 5; i++)
501: _swapbits((char *)&line[i][0], iwb);
502:
503: #ifndef NOINLINE
504: for (i = 0; i < iw; i++) {
505: sixel = extzv(line[0], i, 1);
506: sixel |= extzv(line[1], i, 1) << 1;
507: sixel |= extzv(line[2], i, 1) << 2;
508: sixel |= extzv(line[3], i, 1) << 3;
509: sixel |= extzv(line[4], i, 1) << 4;
510: sixel |= extzv(line[5], i, 1) << 5;
511: *c++ = sixel;
512: }
513: #else
514: for (i = 0, w = iw; w > 0; i++) {
515: for (j = 0; j <= 7; j++) {
516: m = mask[j];
517: k = -j;
518: sixel = ((line[0][i] & ~m) << k++);
519: sixel |= ((line[1][i] & ~m) << k++);
520: sixel |= ((line[2][i] & ~m) << k++);
521: sixel |= ((line[3][i] & ~m) << k++);
522: sixel |= ((line[4][i] & ~m) << k++);
523: sixel |= ((line[5][i] & ~m) << k);
524: *c++ = sixel;
525: if (--w == 0) break;
526: }
527: }
528: #endif
529: }
530: }
531:
532: build_output_filename(name, device, oname)
533: register char *name, *oname;
534: enum device device;
535: {
536: while (*name && *name != '.') *oname++ = *name++;
537: switch (device) {
538: case LN03: bcopy(".ln03", oname, 6); break;
539: case LA100: bcopy(".la100", oname, 7); break;
540: }
541: }
542:
543: /*
544: ln03_grind_fonts(sixmap, iw, ih, scale, pixmap)
545: unsigned char (*sixmap)[];
546: int iw;
547: int ih;
548: int scale;
549: struct pixmap (**pixmap)[];
550: {
551: }
552: */
553:
554: ln03_setup(iw, ih, orientation, scale, left, top, left_margin, top_margin,
555: flags, header, trailer)
556: int iw;
557: int ih;
558: enum orientation orientation;
559: int scale;
560: int left;
561: int top;
562: int *left_margin;
563: int *top_margin;
564: int flags;
565: char *header;
566: char *trailer;
567: {
568: register int i;
569: register int lm, tm, xm;
570: char fontname[6];
571: char buf[256];
572: register char *bp = buf;
573:
574: if (!(flags & F_APPEND)) {
575: sprintf(bp, LN_RIS); bp += 2;
576: sprintf(bp, LN_SSU, 7); bp += 5;
577: sprintf(bp, LN_PUM_SET); bp += sizeof LN_PUM_SET - 1;
578: }
579:
580: if (orientation == PORTRAIT) {
581: lm = (left > 0)? left : (((W_MAX - scale * iw) / 2) + W_MARGIN);
582: tm = (top > 0)? top : (((H_MAX - scale * ih * 6) / 2) + H_MARGIN);
583: sprintf(bp, LN_PFS, "?20"); bp += 7;
584: sprintf(bp, LN_DECOPM_SET); bp += sizeof LN_DECOPM_SET - 1;
585: sprintf(bp, LN_DECSLRM, lm, W_PAGE - lm); bp += strlen(bp);
586: } else {
587: lm = (left > 0)? left : (((H_MAX - scale * iw) / 2) + H_MARGIN);
588: tm = (top > 0)? top : (((W_MAX - scale * ih * 6) / 2) + W_MARGIN);
589: sprintf(bp, LN_PFS, "?21"); bp += 7;
590: sprintf(bp, LN_DECOPM_SET); bp += sizeof LN_DECOPM_SET - 1;
591: sprintf(bp, LN_DECSLRM, lm, H_PAGE - lm); bp += strlen(bp);
592: }
593:
594: if (header != NULL) {
595: sprintf(bp, LN_VPA, tm - 100); bp += strlen(bp);
596: i = strlen(header);
597: xm = (((scale * iw) - (i * 30)) / 2) + lm;
598: sprintf(bp, LN_HPA, xm); bp += strlen(bp);
599: sprintf(bp, LN_SGR, 3); bp += strlen(bp);
600: bcopy(header, bp, i);
601: bp += i;
602: }
603: if (trailer != NULL) {
604: sprintf(bp, LN_VPA, tm + (scale * ih * 6) + 75); bp += strlen(bp);
605: i = strlen(trailer);
606: xm = (((scale * iw) - (i * 30)) / 2) + lm;
607: sprintf(bp, LN_HPA, xm); bp += strlen(bp);
608: sprintf(bp, LN_SGR, 3); bp += strlen(bp);
609: bcopy(trailer, bp, i);
610: bp += i;
611: }
612:
613: sprintf(bp, LN_HPA, lm); bp += strlen(bp);
614: sprintf(bp, LN_VPA, tm); bp += strlen(bp);
615: sprintf(bp, LN_SIXEL_GRAPHICS, 9, 0, scale); bp += strlen(bp);
616: sprintf(bp, "\"1;1"); bp += 4; /* Pixel aspect ratio */
617: write(1, buf, bp-buf);
618: *top_margin = tm;
619: *left_margin = lm;
620: }
621:
622: #define LN03_RESET "\033c"
623:
624: ln03_finish()
625: {
626: write(1, LN03_RESET, sizeof LN03_RESET - 1);
627: }
628:
629: la100_setup(iw, ih, scale)
630: {
631: unsigned char buf[256];
632: register unsigned char *bp;
633: int lm, tm;
634:
635: bp = buf;
636: lm = ((80 - (int)((double)iw / 6.6)) / 2) - 1;
637: if (lm < 1) lm = 1;
638: tm = ((66 - (int)((double)ih / 2)) / 2) - 1;
639: if (tm < 1) tm = 1;
640: sprintf(bp, "\033[%d;%ds", lm, 81-lm); bp += strlen(bp);
641: sprintf(bp, "\033[?7l"); bp += 5;
642: sprintf(bp, "\033[%dd", tm); bp += strlen(bp);
643: sprintf(bp, "\033[%d`", lm); bp += strlen(bp);
644: sprintf(bp, "\033P0q"); bp += 4;
645: write(1, buf, bp-buf);
646: }
647:
648: #define LA100_RESET "\033[1;80s\033[?7h"
649:
650: la100_finish()
651: {
652: write(1, LA100_RESET, sizeof LA100_RESET - 1);
653: }
654:
655: #define COMMENTVERSION "PS-Adobe-1.0"
656:
657: #ifdef XPROLOG
658: /* for debugging, get the prolog from a file */
659: dump_prolog(flags) {
660: char *fname=(flags & F_COMPACT) ? "prolog.compact" : "prolog";
661: FILE *fi = fopen(fname,"r");
662: char buf[1024];
663:
664: if (fi==NULL) {
665: perror(fname);
666: exit(1);
667: }
668: while (fgets(buf,1024,fi)) fputs(buf,stdout);
669: fclose(fi);
670: }
671:
672: #else XPROLOG
673: /* postscript "programs" to unpack and print the bitmaps being sent */
674:
675: char *ps_prolog_compact[] = {
676: "%%Pages: 1",
677: "%%EndProlog",
678: "%%Page: 1 1",
679: "",
680: "/bitgen",
681: " {",
682: " /nextpos 0 def",
683: " currentfile bufspace readhexstring pop % get a chunk of input",
684: " % interpret each byte of the input",
685: " {",
686: " flag { % if the previous byte was FF",
687: " /len exch def % this byte is a count",
688: " result",
689: " nextpos",
690: " FFstring 0 len getinterval % grap a chunk of FF's",
691: " putinterval % and stuff them into the result",
692: " /nextpos nextpos len add def",
693: " /flag false def",
694: " }{ % otherwise",
695: " dup 255 eq { % if this byte is FF",
696: " /flag true def % just set the flag",
697: " pop % and toss the FF",
698: " }{ % otherwise",
699: " % move this byte to the result",
700: " result nextpos",
701: " 3 -1 roll % roll the current byte back to the top",
702: " put",
703: " /nextpos nextpos 1 add def",
704: " } ifelse",
705: " } ifelse",
706: " } forall",
707: " % trim unused space from end of result",
708: " result 0 nextpos getinterval",
709: " } def",
710: "",
711: "",
712: "/bitdump % stk: width, height, iscale",
713: " % dump a bit image with lower left corner at current origin,",
714: " % scaling by iscale (iscale=1 means 1/300 inch per pixel)",
715: " {",
716: " % read arguments",
717: " /iscale exch def",
718: " /height exch def",
719: " /width exch def",
720: "",
721: " % scale appropriately",
722: " width iscale mul height iscale mul scale",
723: "",
724: " % data structures:",
725: "",
726: " % allocate space for one line of input",
727: " /bufspace 36 string def",
728: "",
729: " % string of FF's",
730: " /FFstring 256 string def",
731: " % for all i FFstring[i]=255",
732: " 0 1 255 { FFstring exch 255 put } for",
733: "",
734: " % 'escape' flag",
735: " /flag false def",
736: "",
737: " % space for a chunk of generated bits",
738: " /result 1000 string def",
739: "",
740: " % read and dump the image",
741: " width height 1 [width 0 0 height neg 0 height]",
742: " { bitgen }",
743: " image",
744: " } def",
745: 0
746: };
747:
748: char *ps_prolog[] = {
749: "%%Pages: 1",
750: "%%EndProlog",
751: "%%Page: 1 1",
752: "",
753: "/bitdump % stk: width, height, iscale",
754: "% dump a bit image with lower left corner at current origin,",
755: "% scaling by iscale (iscale=1 means 1/300 inch per pixel)",
756: "{",
757: " % read arguments",
758: " /iscale exch def",
759: " /height exch def",
760: " /width exch def",
761: "",
762: " % scale appropriately",
763: " width iscale mul height iscale mul scale",
764: "",
765: " % allocate space for one scanline of input",
766: " /picstr % picstr holds one scan line",
767: " width 7 add 8 idiv % width of image in bytes = ceiling(width/8)",
768: " string",
769: " def",
770: "",
771: " % read and dump the image",
772: " width height 1 [width 0 0 height neg 0 height]",
773: " { currentfile picstr readhexstring pop }",
774: " image",
775: "} def",
776: 0
777: };
778:
779: dump_prolog(flags) {
780: char **p = (flags & F_COMPACT) ? ps_prolog_compact : ps_prolog;
781: while (*p) printf("%s\n",*p++);
782: }
783: #endif XPROLOG
784:
785: #define PAPER_WIDTH 85*30 /* 8.5 inches */
786: #define PAPER_LENGTH 11*300 /* 11 inches */
787:
788: static int
789: points(n)
790: {
791: /* scale n from pixels (1/300 inch) to points (1/72 inch) */
792: n *= 72;
793: return n/300;
794: }
795:
796: static char *
797: escape(s)
798: char *s;
799: {
800: /* make a version of s in which control characters are deleted and
801: * special characters are escaped.
802: */
803: static char buf[200];
804: char *p = buf;
805:
806: for (;*s;s++) {
807: if (*s < ' ' || *s > 0176) continue;
808: if (*s==')' || *s=='(' || *s == '\\') {
809: sprintf(p,"\\%03o",*s);
810: p += 4;
811: }
812: else *p++ = *s;
813: }
814: *p = 0;
815: return buf;
816: }
817:
818: /* ARGSUSED */
819: ps_setup(iw, ih, orientation, scale, left, top,
820: flags, header, trailer, name)
821: int iw;
822: int ih;
823: enum orientation orientation;
824: int scale;
825: int left;
826: int top;
827: int flags;
828: char *header;
829: char *trailer;
830: char *name;
831: {
832: char hostname[256];
833: struct passwd *pswd;
834: long clock;
835: int lm, bm; /* left (bottom) margin (paper in portrait orientation) */
836:
837: printf ("%%!%s\n", COMMENTVERSION);
838: pswd = getpwuid (getuid ());
839: (void) gethostname (hostname, sizeof hostname);
840: printf ("%%%%Creator: %s:%s (%s)\n", hostname,
841: pswd->pw_name, pswd->pw_gecos);
842: printf ("%%%%Title: %s (%s)\n", infilename,name);
843: printf ("%%%%CreationDate: %s",
844: (time (&clock), ctime (&clock)));
845: printf ("%%%%EndComments\n");
846:
847: dump_prolog(flags);
848:
849: if (orientation==PORTRAIT) {
850: lm = (left > 0)? left : ((PAPER_WIDTH - scale * iw) / 2);
851: bm = (top > 0)? (PAPER_LENGTH - top - scale * ih)
852: : ((PAPER_LENGTH - scale * ih) / 2);
853: if (header || trailer) {
854: printf("gsave\n");
855: printf("/Times-Roman findfont 15 scalefont setfont\n");
856: /* origin at bottom left corner of image */
857: printf("%d %d translate\n",points(lm),points(bm));
858: if (header) {
859: char *label = escape(header);
860: printf("%d (%s) stringwidth pop sub 2 div %d moveto\n",
861: points(iw*scale), label, points(ih*scale) + 10);
862: printf("(%s) show\n",label);
863: }
864: if (trailer) {
865: char *label = escape(trailer);
866: printf("%d (%s) stringwidth pop sub 2 div -20 moveto\n",
867: points(iw*scale), label);
868: printf("(%s) show\n",label);
869: }
870: printf("grestore\n");
871: }
872: /* set resolution to device units (300/inch) */
873: printf("72 300 div dup scale\n");
874: /* move to lower left corner of image */
875: printf("%d %d translate\n",lm,bm);
876: /* dump the bitmap */
877: printf("%d %d %d bitdump\n",iw,ih,scale);
878: } else { /* orientation == LANDSCAPE */
879: /* calculate margins */
880: lm = (top > 0)? (PAPER_WIDTH - top - scale * ih)
881: : ((PAPER_WIDTH - scale * ih) / 2);
882: bm = (left > 0)? (PAPER_LENGTH - left - scale * iw)
883: : ((PAPER_LENGTH - scale * iw) / 2);
884:
885: if (header || trailer) {
886: printf("gsave\n");
887: printf("/Times-Roman findfont 15 scalefont setfont\n");
888: /* origin at top left corner of image */
889: printf("%d %d translate\n",points(lm),points(bm + scale * iw));
890: /* rotate to print the titles */
891: printf("-90 rotate\n");
892: if (header) {
893: char *label = escape(header);
894: printf("%d (%s) stringwidth pop sub 2 div %d moveto\n",
895: points(iw*scale), label, points(ih*scale) + 10);
896: printf("(%s) show\n",label);
897: }
898: if (trailer) {
899: char *label = escape(trailer);
900: printf("%d (%s) stringwidth pop sub 2 div -20 moveto\n",
901: points(iw*scale), label);
902: printf("(%s) show\n",label);
903: }
904: printf("grestore\n");
905: }
906: /* set resolution to device units (300/inch) */
907: printf("72 300 div dup scale\n");
908: /* move to lower left corner of image */
909: printf("%d %d translate\n",lm,bm);
910: /* dump the bitmap */
911: printf("%d %d %d bitdump\n",ih,iw,scale);
912: }
913: }
914:
915: char *ps_epilog[] = {
916: "",
917: "showpage",
918: "%%Trailer",
919: 0
920: };
921:
922: ps_finish()
923: {
924: char **p = ps_epilog;
925:
926: while (*p) printf("%s\n",*p++);
927: }
928:
929: ln03_alter_background(sixmap, iw, ih)
930: unsigned char (*sixmap)[];
931: int iw;
932: int ih;
933: {
934: register int size;
935: register unsigned char *c, *stopc;
936: register unsigned char *startc;
937: register int n;
938:
939: c = (unsigned char *)sixmap;
940: stopc = c + (iw * ih);
941: n = 0;
942: while (c < stopc) {
943: switch (*c) {
944: case 0x08: case 0x11: case 0x04: case 0x22:
945: case 0x20: case 0x21: case 0x24: case 0x00:
946: if (n == 0) startc = c;
947: n++;
948: break;
949:
950: default:
951: if (n >= 2) {
952: while (n-- > 0) *startc++ = 0x00;
953: } else {
954: n = 0;
955: }
956: break;
957: }
958: c++;
959: }
960: }
961:
962: ln03_output_sixels(sixmap, iw, ih, nosixopt, split, scale, top_margin,
963: left_margin)
964: unsigned char (*sixmap)[];
965: int iw;
966: int ih;
967: int nosixopt;
968: int split;
969: int top_margin;
970: int left_margin;
971: {
972: unsigned char *buf;
973: register unsigned char *bp;
974: int i;
975: int j;
976: register int k;
977: register unsigned char *c;
978: register int lastc;
979: register int count;
980: char snum[6];
981: register char *snp;
982:
983: bp = (unsigned char *)malloc(iw*ih+512);
984: buf = bp;
985: count = 0;
986: lastc = -1;
987: c = (unsigned char *)sixmap;
988: split = ih / split; /* number of lines per page */
989:
990: iw--; /* optimization */
991: for (i = 0; i < ih; i++) {
992: for (j = 0; j <= iw; j++) {
993: if (!nosixopt) {
994: if (*c == lastc && j < iw) {
995: count++;
996: c++;
997: continue;
998: }
999: if (count >= 3) {
1000: bp--;
1001: count++;
1002: *bp++ = '!';
1003: snp = snum;
1004: while (count > 0) {
1005: k = count / 10;
1006: *snp++ = count - (k * 10) + '0';
1007: count = k;
1008: }
1009: while (--snp >= snum) *bp++ = *snp;
1010: *bp++ = (~lastc & 0x3F) + 0x3F;
1011: } else if (count > 0) {
1012: lastc = (~lastc & 0x3F) + 0x3F;
1013: do {
1014: *bp++ = lastc;
1015: } while (--count > 0);
1016: }
1017: }
1018: lastc = *c++;
1019: *bp++ = (~lastc & 0x3F) + 0x3F;
1020: }
1021: *bp++ = '-'; /* New line */
1022: lastc = -1;
1023: if ((i % split) == 0 && i != 0) {
1024: sprintf(bp, LN_ST); bp += sizeof LN_ST - 1;
1025: *bp++ = '\f';
1026: sprintf(bp, LN_VPA, top_margin + (i * 6 * scale)); bp += strlen(bp);
1027: sprintf(bp, LN_HPA, left_margin); bp += strlen(bp);
1028: sprintf(bp, LN_SIXEL_GRAPHICS, 9, 0, scale); bp += strlen(bp);
1029: sprintf(bp, "\"1;1"); bp += 4;
1030: }
1031: }
1032:
1033: sprintf(bp, LN_ST); bp += sizeof LN_ST - 1;
1034: *bp++ = '\f';
1035: write(1, buf, bp-buf);
1036: }
1037:
1038: la100_output_sixels(sixmap, iw, ih)
1039: unsigned char (*sixmap)[];
1040: int iw;
1041: int ih;
1042: {
1043: unsigned char *buf;
1044: register unsigned char *bp;
1045: int i;
1046: register int j, k;
1047: register unsigned char *c;
1048: register int lastc;
1049: register int count;
1050: char snum[6];
1051:
1052: bp = (unsigned char *)malloc(iw*ih+512);
1053: buf = bp;
1054: count = 0;
1055: lastc = -1;
1056: c = (unsigned char *)sixmap;
1057:
1058: for (i = 0; i < ih; i++) {
1059: for (j = 0; j < iw; j++) {
1060: if (*c == lastc && (j+1) < iw) {
1061: count++;
1062: c++;
1063: continue;
1064: }
1065: if (count >= 2) {
1066: bp -= 2;
1067: count = 2 * (count + 1);
1068: *bp++ = '!';
1069: k = 0;
1070: while (count > 0) {
1071: snum[k++] = (count % 10) + '0';
1072: count /= 10;
1073: }
1074: while (--k >= 0) *bp++ = snum[k];
1075: *bp++ = (~lastc & 0x3F) + 0x3F;
1076: count = 0;
1077: } else if (count > 0) {
1078: lastc = (~lastc & 0x3F) + 0x3F;
1079: do {
1080: *bp++ = lastc;
1081: *bp++ = lastc;
1082: } while (--count > 0);
1083: }
1084: lastc = (~*c & 0x3F) + 0x3F;
1085: *bp++ = lastc;
1086: *bp++ = lastc;
1087: lastc = *c++;
1088: }
1089: *bp++ = '-'; /* New line */
1090: lastc = -1;
1091: }
1092:
1093: sprintf(bp, LN_ST); bp += sizeof LN_ST - 1;
1094: *bp++ = '\f';
1095: write(1, buf, bp-buf);
1096: }
1097:
1098: #define LINELEN 72 /* number of CHARS (bytes*2) per line of bitmap output */
1099: char *obuf; /* buffer to contain entire rotated bit map */
1100:
1101: ps_output_bits(iw, ih, flags, orientation, win)
1102: int iw;
1103: int ih;
1104: int flags;
1105: XWDFileHeader *win;
1106: enum orientation orientation;
1107: {
1108: int iwb = win->bytes_per_line;
1109: register int i;
1110: int n,bytes;
1111: unsigned char *buffer;
1112: register int ocount=0;
1113: extern char hex1[],hex2[];
1114: static char hex[] = "0123456789abcdef";
1115:
1116: buffer = (unsigned char *)malloc((unsigned)(iwb + 3));
1117: if (orientation == LANDSCAPE) {
1118: /* read in and rotate the entire image */
1119: /* The Postscript language has a rotate operator, but using it
1120: * seem to make printing (at least on the Apple Laserwriter
1121: * take about 10 times as long (40 minutes for a 1024x864 full-screen
1122: * dump)! Therefore, we rotate the image here.
1123: */
1124: int ocol = ih;
1125: int owidth = (ih+31)/32; /* width of rotated image, in bytes */
1126: int oheight = (iw+31)/32; /* height of rotated image, in scanlines */
1127: register char *p, *q;
1128: owidth *= 4;
1129: oheight *= 32;
1130:
1131: /* Allocate buffer for the entire rotated image (output).
1132: * Owidth and Oheight are rounded up to a multiple of 32 bits,
1133: * to avoid special cases at the boundaries
1134: */
1135: obuf = (char *)malloc((unsigned)(owidth*oheight));
1136: if (obuf==0) {
1137: fprintf(stderr,"xpr: cannot allocate %d bytes\n",owidth*oheight);
1138: exit(1);
1139: }
1140: bzero(obuf,owidth*oheight);
1141:
1142: for (i=0;i<ih;i++) {
1143: n = read(0,(char *)buffer,iwb);
1144: if (n<0) {
1145: perror("read");
1146: exit(1);
1147: }
1148: if (n==0) {
1149: fprintf(stderr,"xpr: premature end of file\n");
1150: exit(1);
1151: }
1152: if (win->bitmap_bit_order == MSBFirst)
1153: _swapbits((char *)buffer, iwb);
1154: ps_bitrot(buffer,iw,--ocol,owidth);
1155: }
1156: q = &obuf[iw*owidth];
1157: bytes = (ih+7)/8;
1158: for (p=obuf;p<q;p+=owidth)
1159: ocount = ps_putbuf((unsigned char *)p,bytes,ocount,flags&F_COMPACT);
1160: }
1161: else {
1162: for (i=0;i<ih;i++) {
1163: n = read(0,(char *)buffer,iwb);
1164: if (n<0) {
1165: perror("read");
1166: exit(1);
1167: }
1168: if (n==0) {
1169: fprintf(stderr,"xpr: premature end of file\n");
1170: exit(1);
1171: }
1172: if (win->bitmap_bit_order == MSBFirst)
1173: _swapbits((char *)buffer, iwb);
1174: ocount = ps_putbuf(buffer,iwb,ocount,flags&F_COMPACT);
1175: }
1176: }
1177: if (flags & F_COMPACT) {
1178: if (ocount) {
1179: /* pad to an integral number of lines */
1180: while (ocount++ < LINELEN)
1181: /* for debugging, pad with a "random" value */
1182: putchar(hex[ocount&15]);
1183: putchar('\n');
1184: }
1185: }
1186: }
1187:
1188: /* Dump some bytes in hex, with bits in each byte reversed
1189: * Ocount is number of chacters that have been written to the current
1190: * output line. It's new value is returned as the result of the function.
1191: * Ocount is ignored (and the return value is meaningless) if compact==0.
1192: */
1193: int
1194: ps_putbuf(s, n, ocount, compact)
1195: register unsigned char *s; /* buffer to dump */
1196: register int n; /* number of BITS to dump */
1197: register int ocount; /* position on output line for next char */
1198: int compact; /* if non-zero, do compaction (see below) */
1199: {
1200: register int ffcount = 0;
1201: extern char hex1[],hex2[];
1202: static char hex[] = "0123456789abcdef";
1203: #define PUT(c) { putchar(c); if (++ocount>=LINELEN) \
1204: { putchar('\n'); ocount=0; }}
1205:
1206: if (compact) {
1207: /* The following loop puts out the bits of the image in hex,
1208: * compressing runs of white space (represented by one bits)
1209: * according the the following simple algorithm: A run of n
1210: * 'ff' bytes (i.e., bytes with value 255--all ones), where
1211: * 1<=n<=255, is represented by a single 'ff' byte followed by a
1212: * byte containing n.
1213: * On a typical dump of a full screen pretty much covered by
1214: * black-on-white text windows, this compression decreased the
1215: * size of the file from 223 Kbytes to 63 Kbytes.
1216: * Of course, another factor of two could be saved by sending
1217: * the bytes 'as is' rather than in hex, using some sort of
1218: * escape convention to avoid problems with control characters.
1219: * Another popular encoding is to pack three bytes into 4 'sixels'
1220: * as in the LN03, etc, but I'm too lazy to write the necessary
1221: * PostScript code to unpack fancier representations.
1222: */
1223: while (n--) {
1224: if (*s == 0xff) {
1225: if (++ffcount == 255) {
1226: PUT('f'); PUT('f');
1227: PUT('f'); PUT('f');
1228: ffcount = 0;
1229: }
1230: }
1231: else {
1232: if (ffcount) {
1233: PUT('f'); PUT('f');
1234: PUT(hex[ffcount >> 4]);
1235: PUT(hex[ffcount & 0xf]);
1236: ffcount = 0;
1237: }
1238: PUT(hex1[*s]);
1239: PUT(hex2[*s]);
1240: }
1241: s++;
1242: }
1243: if (ffcount) {
1244: PUT('f'); PUT('f');
1245: PUT(hex[ffcount >> 4]);
1246: PUT(hex[ffcount & 0xf]);
1247: ffcount = 0;
1248: }
1249: }
1250: else { /* no compaction: just dump the image in hex (bits reversed) */
1251: while (n--) {
1252: putchar(hex1[*s]);
1253: putchar(hex2[*s++]);
1254: }
1255: putchar('\n');
1256: }
1257: return ocount;
1258: }
1259:
1260: ps_bitrot(s,n,col,owidth)
1261: unsigned char *s;
1262: register int n;
1263: int col;
1264: register int owidth;
1265: /* s points to a chunk of memory and n is its width in bits.
1266: * The algorithm is, roughly,
1267: * for (i=0;i<n;i++) {
1268: * OR the ith bit of s into the ith row of the
1269: * (col)th column of obuf
1270: * }
1271: * Assume VAX bit and byte ordering for s:
1272: * The ith bit of s is s[j]&(1<<k) where i=8*j+k.
1273: * It can also be retrieved as t[j]&(1<<k), where t=(int*)s and i=32*j+k.
1274: * Also assume VAX bit and byte ordering for each row of obuf.
1275: * Ps_putbuf() takes care of converting to Motorola 68000 byte and bit
1276: * ordering. The following code is very carefully tuned to yield a very
1277: * tight loop on the VAX, since it easily dominates the entire running
1278: * time of this program. In particular, iwordp is declared last, since
1279: * there aren't enough registers, and iwordp is referenced only once
1280: * every 32 times through the loop.
1281: */
1282: {
1283: register int mask = 1<<(col%32);
1284: register int iword; /* current input word (*iwordp) */
1285: register int b = 0; /* number of bits in iword left to examine */
1286: register char *opos = obuf + (col/32)*4;
1287: /* pointer to word of obuf to receive next output bit */
1288: register int *iwordp = (int *) s; /* pointer to next word of s */
1289:
1290: while (--n>=0) {
1291: if (--b < 0) {
1292: iword = *iwordp++;
1293: b = 31;
1294: }
1295: if (iword & 1) {
1296: *(int *)opos |= mask;
1297: }
1298: opos += owidth;
1299: iword >>= 1;
1300: }
1301: }
1302:
1303: /* mapping tables to map a byte in to the hex representation of its
1304: * bit-reversal
1305: */
1306: char hex1[]="084c2a6e195d3b7f084c2a6e195d3b7f084c2a6e195d3b7f084c2a6e195d3b7f\
1307: 084c2a6e195d3b7f084c2a6e195d3b7f084c2a6e195d3b7f084c2a6e195d3b7f\
1308: 084c2a6e195d3b7f084c2a6e195d3b7f084c2a6e195d3b7f084c2a6e195d3b7f\
1309: 084c2a6e195d3b7f084c2a6e195d3b7f084c2a6e195d3b7f084c2a6e195d3b7f";
1310:
1311: char hex2[]="000000000000000088888888888888884444444444444444cccccccccccccccc\
1312: 2222222222222222aaaaaaaaaaaaaaaa6666666666666666eeeeeeeeeeeeeeee\
1313: 111111111111111199999999999999995555555555555555dddddddddddddddd\
1314: 3333333333333333bbbbbbbbbbbbbbbb7777777777777777ffffffffffffffff";
1315:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.