/* © 2000 Compaq Computer Corporation COMPAQ Registered in U.S. Patent and Trademark Office. Confidential computer software. Valid license from Compaq required for possession, use or copying. Consistent with FAR 12.211 and 12.212, Commercial Computer Software, Computer Software Documentation, and Technical Data for Commercial Items are licensed to the U.S. Government under vendor's standard commercial license. */ /* * $XConsortium: x2pmp.c,v 1.13 91/07/25 17:56:32 rws Exp $ */ /* x2pmp.c: Translate xwd window dump format into PMP format for the * IBM 3812 PagePrinter. */ #include #include #include #include #include #ifdef VMS #include "XWDFile.h" #else #include #include #endif #include "pmp.h" #include "xpr.h" #define max_(a, b) (a) > (b) ? (a) : (b) #define min_(a, b) (a) < (b) ? (a) : (b) #define abs_(a) (a) < 0 ? -(a) : (a) static void leave(); static bits_set(); static unsigned char *magnification_table(); /* global variables set by main() and used by x2pmp() */ extern char *progname; extern int debug; static plane = 0; #define FONT_HEIGHT 40 #define FONT_HEIGHT_PIXELS (FONT_HEIGHT*75/PPI) #define FONT_WIDTH 24 void x2pmp(in, out, scale, p_width, p_length, x_pos, y_pos, head, foot, orient, invert) FILE *in, *out; int scale; int p_width, p_length, x_pos, y_pos; /* in pels (units of PPI) */ char *head, *foot; enum orientation orient; int invert; { unsigned char *buffer, *win_name; unsigned int win_name_size, width, height, ncolors; unsigned int buffer_size, one_plane_size, byte_width, fixed_width; int no_of_bits; unsigned long swaptest = 1; XWDFileHeader header; /* Read header from file */ if (fread((char *)&header, sizeof(header), 1, in) != 1) if (feof(in)) return; else leave("fread"); if (*(char *) &swaptest) _swaplong((char *) &header, sizeof(header)); if (header.file_version != XWD_FILE_VERSION) { fprintf(stderr,"%s: file format version %d, not %d\n", progname, header.file_version, XWD_FILE_VERSION); } win_name_size = abs_(header.header_size - sizeof(header)); if ((win_name = (unsigned char *) calloc(win_name_size, (unsigned) sizeof(char))) == NULL) leave("Can't calloc window name storage."); /* Read window name from file */ if (fread((char *) win_name, sizeof(char), (int) win_name_size, in) != win_name_size) leave("Unable to read window name from dump file."); DEBUG(>= 1) fprintf(stderr,"win_name =%s\n", win_name); width = header.pixmap_width; height = header.pixmap_height; fixed_width = 8 * (byte_width = header.bytes_per_line); one_plane_size = byte_width * height; buffer_size = one_plane_size * ((header.pixmap_format == ZPixmap)? header.pixmap_depth: 1); /* Determine orientation and scale if not specified */ if (orient == UNSPECIFIED) orient = (fixed_width <= height)? PORTRAIT: LANDSCAPE; if (scale <= 0) { int real_height = height; if (head) real_height += FONT_HEIGHT_PIXELS << 1; if (foot) real_height += FONT_HEIGHT_PIXELS << 1; switch(orient) { case PORTRAIT: case UPSIDE_DOWN: scale = min_((p_width - 2*x_pos) / fixed_width, (p_length - 2*y_pos) / real_height); break; case LANDSCAPE: case LANDSCAPE_LEFT: scale = min_((p_length - 2*y_pos) / fixed_width, (p_width - 2*x_pos) / real_height); break; } if (scale <= 0) leave("PixMap doesn't fit on page."); else DEBUG(>1) fprintf(stderr, "scaling by %d to yield %d x %d image\n", scale, fixed_width*scale, height*scale); } ncolors = header.ncolors; if (ncolors) { int i; XColor *colors = (XColor *)malloc((unsigned) (header.ncolors * sizeof(XColor))); if (fread((char *)colors, sizeof(XColor), ncolors, in) != ncolors) leave("Unable to read colormap from dump file."); if (*(char *) &swaptest) { for (i = 0; i < ncolors; i++) { _swaplong((char *) &colors[i].pixel, (long)sizeof(long)); _swapshort((char *) &colors[i].red, (long) (3 * sizeof(short))); } } if (ncolors == 2 && INTENSITY(&colors[0]) > INTENSITY(&colors[1])) invert = !invert; free( colors ); } invert = !invert; /* 3812 puts ink (i.e. black) on 1-bits */ if ((buffer = (unsigned char *) calloc(buffer_size, 1)) == NULL) leave("Can't calloc data buffer."); #ifdef VMS memset((char *) buffer, 0, (int) buffer_size); #else bzero((char *) buffer, (int) buffer_size); #endif /* Read bitmap from file */ if (fread((char *) buffer, sizeof(char), (int) buffer_size, in) != buffer_size) leave("Unable to read pixmap from dump file."); if (header.bitmap_bit_order == LSBFirst) { unsigned char bitswap[256], *bp; int c; for(c = 256; c--;) { bitswap[c] = ((c & 01) << 7) + ((c & 02) << 5) + ((c & 04) << 3) + ((c & 010) << 1) + ((c & 020) >> 1) + ((c & 040) >> 3) + ((c & 0100) >> 5) + ((c & 0200) >> 7); if (invert) bitswap[c] = ~bitswap[c]; } /* Here's where we do the bitswapping. */ for(bp = buffer+buffer_size; bp-- > buffer;) *bp = bitswap[*bp]; } else if (invert) { unsigned char *bp; for(bp = buffer+buffer_size; bp-- > buffer;) *bp = ~*bp; } /* we don't want the last bits up to the byte/word alignment set */ if (no_of_bits = fixed_width - width) { int i, j, mask = ~bits_set(no_of_bits % 8); for(i = 0; i < height; i++) { unsigned char *s = buffer + (i+1) * byte_width ; for(j = no_of_bits / 8; j--;) *--s = 0; *--s &= mask; } } DEBUG(>= 1) fprintf(stderr,"read %d bytes for a %d (%d bytes) x %d image\n", buffer_size, (int) width, byte_width, (int) height); /* Scale the bitmap */ if (scale > 1) { unsigned char *tbl = magnification_table(scale); unsigned char *scale_buf; int i, j, k; if ((scale_buf = (unsigned char *) calloc((unsigned) (buffer_size *= scale*scale), sizeof(char))) == NULL) leave("Can't calloc scaled buffer."); for(i = 0; i < height; i++) { unsigned char *src, *ss; src = buffer + i * byte_width ; ss = scale_buf + i * scale * scale * byte_width; for(j = 0; j < byte_width; j++) { unsigned char *dst = ss+j*scale; unsigned char *expansion = tbl+scale*src[j]; for(k = 0; k < scale; k++, dst += byte_width*scale) { #ifdef VMS memcpy((char *) dst, (char *) expansion, scale); #else bcopy((char *) expansion, (char *) dst, scale); #endif } } } free((char *) buffer); free((char *) tbl); buffer = scale_buf; byte_width *= scale; width *= scale; fixed_width *= scale; height *= scale; one_plane_size *= scale*scale; } DEBUG(==3) { int i, j, k; unsigned char *s; fprintf(stderr, "dumping %d x %d grid\n", fixed_width, height); for(i = 0; i < height; i++) { s = buffer + i * byte_width ; for(j = 0; j < byte_width; j++) for(k = 8; k--;) (void) putc((s[j] & 1<> 1, y_pos - FONT_HEIGHT ); fprintf(out, "%s\n", head); } if (foot != NULL) { p_move_abs( out, x_pos + (width - strlen(foot)*FONT_WIDTH) >> 1, y_pos + height + (FONT_HEIGHT << 1) ); fprintf(out, "%s\n", foot); } p_move_abs(out, x_pos, y_pos); p_bitmap(out, height, fixed_width, (unsigned long) one_plane_size, buffer + plane * one_plane_size); free((char *) win_name); free((char *) buffer); } static unsigned char *magnification_table(scale) int scale; { unsigned char *tbl; int c; if ((tbl = (unsigned char *) calloc((unsigned) (scale*256), sizeof(char))) == NULL) leave("Can't calloc magnification table."); #ifdef VMS memset((char *) tbl, 0, scale*256); #else bzero((char *) tbl, scale*256); #endif for(c = 256; c--;) { int b = c, bit; unsigned char *entry = tbl+c*scale; while (b) { int i, last, mask; bit = 1; mask = b; while (! (mask & 1)) { bit++; mask = mask >> 1; } last = scale*(bit-1); for(i = scale*bit; i-- > last ;) entry[(scale - 1) - i / 8] |= 1 << (i % 8); b &= ~(1 << bit-1); } } return tbl; } /* returns 2^n-1, i.e. a number with bits n-1 through 0 set. * (zero for n == 0) */ static bits_set(n) int n; { int ans = 0; while(n--) ans |= 1 << n; return ans; } static void leave(s) char *s; { extern int errno; fprintf(stderr, "\n%s: ", progname); if (errno != 0) perror(s); else fprintf(stderr, "%s", s); fprintf(stderr, "\n"); exit(1); } /* move to coordinates x, y (in pels) */ p_move_abs(p, x, y) FILE *p; int x, y; { if (x >= 0) { PMP(p, 3); (void) putc('\340', p); p_wput(x, p); } if (y >= 0) { PMP(p, 3); (void) putc('\341', p); p_wput(y, p); } } /* save current cursor position into (printer) register reg */ p_save_cursor(p, reg) FILE *p; int reg; { PMP(p, 1); (void) putc(reg + '\200', p); } /* restore current cursor position from (printer) register reg */ p_restore_cursor(p, reg) FILE *p; int reg; { PMP(p, 1); (void) putc(reg + '\220', p); } /* set the page orientation to orient (see pmp.h) */ p_set_orientation(p, orient) FILE *p; enum orientation orient; { PMP(p, 2); fprintf(p, "\322%c", (int) orient); } /* generate bitmap */ p_bitmap(p, h, w, buflen, buf) FILE *p; unsigned int h, w; unsigned long buflen; unsigned char *buf; { PMP(p, 9); (void) fwrite("\365\0", 1, 2, p); puthl2(h, p); puthl2(w, p); puthl3(buflen, p); while(buflen) { int len; len = min(buflen, MAX_VECTOR_LEN); PMP(p, len); (void) fwrite((char *) buf, 1, len, p); buf += len; buflen -= len; } (void) fflush(p); }