home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / clients / xpr / x2pmp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-25  |  9.0 KB  |  364 lines

  1. /*
  2.  *    $XConsortium: x2pmp.c,v 1.13 91/07/25 17:56:32 rws Exp $
  3.  */
  4.  
  5. /* x2pmp.c: Translate xwd window dump format into PMP format for the
  6.  * IBM 3812 PagePrinter.
  7.  */
  8. #include <stdio.h>
  9. #include <math.h>
  10. #include <X11/Xlib.h>
  11. #include <X11/XWDFile.h>
  12. #include <X11/Xfuncs.h>
  13. #include <errno.h>
  14.  
  15. #include "pmp.h"
  16. #include "xpr.h"
  17.  
  18. #define max_(a, b) (a) > (b) ? (a) : (b)
  19. #define min_(a, b) (a) < (b) ? (a) : (b)
  20. #define abs_(a) (a) < 0 ? -(a) : (a)
  21.  
  22. static void leave();
  23. static bits_set();
  24. static unsigned char *magnification_table();
  25.  
  26. /* global variables set by main() and used by x2pmp() */
  27. extern char *progname;
  28. extern int debug;
  29.  
  30. static plane = 0;
  31. #define FONT_HEIGHT 40
  32. #define FONT_HEIGHT_PIXELS (FONT_HEIGHT*75/PPI)
  33. #define FONT_WIDTH 24
  34.  
  35. void x2pmp(in, out, scale, p_width, p_length, x_pos, y_pos,
  36.           head, foot, orient, invert)
  37. FILE *in, *out;
  38. int scale;
  39. int p_width, p_length, x_pos, y_pos; /* in pels (units of PPI) */
  40. char *head, *foot;
  41. enum orientation orient;
  42. int invert;
  43. {
  44.     unsigned char *buffer, *win_name;
  45.     unsigned int win_name_size, width, height, ncolors;
  46.     unsigned int buffer_size, one_plane_size, byte_width, fixed_width;
  47.     int no_of_bits;
  48.     unsigned long swaptest = 1;
  49.     XWDFileHeader header;
  50.  
  51.     /* Read header from file */
  52.     if (fread((char *)&header, sizeof(header), 1, in) != 1)
  53.       if (feof(in)) 
  54.     return;
  55.       else
  56.     leave("fread");
  57.     if (*(char *) &swaptest)
  58.       _swaplong((char *) &header, sizeof(header));
  59.  
  60.     if (header.file_version != XWD_FILE_VERSION) {
  61.     fprintf(stderr,"%s: file format version %d, not %d\n", progname,
  62.         header.file_version, XWD_FILE_VERSION);
  63.     }
  64.  
  65.     win_name_size = abs_(header.header_size - sizeof(header));
  66.     if ((win_name = (unsigned char *)
  67.      calloc(win_name_size, (unsigned) sizeof(char))) == NULL)
  68.       leave("Can't calloc window name storage.");
  69.  
  70.     /* Read window name from file */
  71.     if (fread((char *) win_name, sizeof(char), (int) win_name_size, in) !=
  72.     win_name_size)
  73.       leave("Unable to read window name from dump file.");
  74.     DEBUG(>= 1)
  75.       fprintf(stderr,"win_name =%s\n", win_name);
  76.  
  77.     width = header.pixmap_width;
  78.     height = header.pixmap_height;
  79.     fixed_width = 8 * (byte_width = header.bytes_per_line);
  80.     one_plane_size = byte_width * height;
  81.     buffer_size = one_plane_size *
  82.       ((header.pixmap_format == ZPixmap)? header.pixmap_depth: 1);
  83.     
  84.     /* Determine orientation and scale if not specified */
  85.     if (orient == UNSPECIFIED)
  86.       orient = (fixed_width <= height)? PORTRAIT: LANDSCAPE;
  87.     if (scale <= 0) {
  88.         int real_height = height;
  89.     if (head) real_height += FONT_HEIGHT_PIXELS << 1;
  90.     if (foot) real_height += FONT_HEIGHT_PIXELS << 1;
  91.     switch(orient) {
  92.     case PORTRAIT:
  93.     case UPSIDE_DOWN:
  94.         scale = min_((p_width - 2*x_pos) / fixed_width,
  95.              (p_length - 2*y_pos) / real_height);
  96.         break;
  97.     case LANDSCAPE:
  98.     case LANDSCAPE_LEFT:
  99.         scale = min_((p_length - 2*y_pos) / fixed_width,
  100.              (p_width - 2*x_pos) / real_height);
  101.         break;
  102.     }
  103.     if (scale <= 0)
  104.       leave("PixMap doesn't fit on page.");
  105.     else DEBUG(>1)
  106.       fprintf(stderr, "scaling by %d to yield %d x %d image\n",
  107.           scale, fixed_width*scale, height*scale);
  108.     }
  109.  
  110.     ncolors = header.ncolors;
  111.     if (ncolors) {
  112.     int i;
  113.     XColor *colors = (XColor *)malloc((unsigned) (header.ncolors * sizeof(XColor)));
  114.  
  115.     if (fread((char *)colors, sizeof(XColor), ncolors, in) != ncolors)
  116.       leave("Unable to read colormap from dump file.");
  117.  
  118.     if (*(char *) &swaptest) {
  119.         for (i = 0; i < ncolors; i++) {
  120.         _swaplong((char *) &colors[i].pixel, (long)sizeof(long));
  121.         _swapshort((char *) &colors[i].red, (long) (3 * sizeof(short)));
  122.         }
  123.     }
  124.     if (ncolors == 2 && INTENSITY(&colors[0]) > INTENSITY(&colors[1]))
  125.         invert = !invert;
  126.     free( colors );
  127.     }
  128.  
  129.     invert = !invert;        /* 3812 puts ink (i.e. black) on 1-bits */
  130.  
  131.     if ((buffer = (unsigned char *) calloc(buffer_size, 1)) == NULL)
  132.       leave("Can't calloc data buffer.");
  133.     bzero((char *) buffer, (int) buffer_size);
  134.  
  135.     /* Read bitmap from file */
  136.     if (fread((char *) buffer, sizeof(char), (int) buffer_size, in)
  137.     != buffer_size)
  138.       leave("Unable to read pixmap from dump file.");
  139.  
  140.     if (header.bitmap_bit_order == LSBFirst)
  141.     {
  142.     unsigned char bitswap[256], *bp;
  143.     int c;
  144.     for(c = 256; c--;) {
  145.         bitswap[c] = ((c & 01) << 7) + ((c & 02) << 5) + ((c & 04) << 3) +
  146.           ((c & 010) << 1) + ((c & 020) >> 1) + ((c & 040) >> 3) +
  147.         ((c & 0100) >> 5) + ((c & 0200) >> 7);
  148.         if (invert)
  149.           bitswap[c] = ~bitswap[c];
  150.     }
  151.     /* Here's where we do the bitswapping. */
  152.     for(bp = buffer+buffer_size; bp-- > buffer;)
  153.       *bp = bitswap[*bp];
  154.     }
  155.     else if (invert) {
  156.         unsigned char *bp;
  157.     for(bp = buffer+buffer_size; bp-- > buffer;)
  158.       *bp = ~*bp;
  159.     }
  160.  
  161.     /* we don't want the last bits up to the byte/word alignment set */
  162.     if (no_of_bits = fixed_width - width) {
  163.     int i, j, mask = ~bits_set(no_of_bits % 8);
  164.     for(i = 0; i < height; i++) {
  165.         unsigned char *s = buffer + (i+1) * byte_width ;
  166.  
  167.         for(j = no_of_bits / 8; j--;)
  168.           *--s = 0;
  169.         *--s &= mask;
  170.     }
  171.     }
  172.  
  173.     DEBUG(>= 1)
  174.       fprintf(stderr,"read %d bytes for a %d (%d bytes) x %d image\n",
  175.           buffer_size, (int) width, byte_width, (int) height);
  176.     /* Scale the bitmap */
  177.     if (scale > 1) {
  178.     unsigned char *tbl = magnification_table(scale);
  179.     unsigned char *scale_buf;
  180.     int i, j, k;
  181.     
  182.     if ((scale_buf = (unsigned char *)
  183.          calloc((unsigned) (buffer_size *= scale*scale), sizeof(char)))
  184.         == NULL)
  185.       leave("Can't calloc scaled buffer.");
  186.     for(i = 0; i < height; i++) {
  187.         unsigned char *src, *ss;
  188.         src = buffer + i * byte_width ;
  189.         ss = scale_buf + i * scale * scale * byte_width;
  190.         for(j = 0; j < byte_width; j++) {
  191.         unsigned char *dst = ss+j*scale;
  192.         unsigned char *expansion = tbl+scale*src[j];
  193.         for(k = 0; k < scale; k++, dst += byte_width*scale) {
  194.             bcopy((char *) expansion, (char *) dst, scale);
  195.         }
  196.         }
  197.     }
  198.     free((char *) buffer);
  199.     free((char *) tbl);
  200.     buffer = scale_buf;
  201.     byte_width *= scale;
  202.     width *= scale;
  203.     fixed_width *= scale;
  204.     height *= scale;
  205.     one_plane_size *= scale*scale;
  206.     }
  207.     DEBUG(==3) {
  208.     int i, j, k;
  209.     unsigned char *s;
  210.  
  211.     fprintf(stderr, "dumping %d x %d grid\n", fixed_width, height);
  212.     for(i = 0; i < height; i++) {
  213.         s = buffer + i * byte_width ;
  214.         for(j = 0; j < byte_width; j++)
  215.           for(k = 8; k--;)
  216.         (void) putc((s[j] & 1<<k)? '*': '-', stderr);
  217.         (void) putc('\n', stderr);
  218.     }
  219.     }
  220.     p_set_orientation(out, orient);
  221.     p_restore_cursor(out, 0);
  222.     p_save_cursor(out, 3);
  223.     if (head != NULL) {
  224.     p_move_abs( out, x_pos + (width - strlen(foot)*FONT_WIDTH) >> 1,
  225.                  y_pos - FONT_HEIGHT );
  226.     fprintf(out, "%s\n", head);
  227.     }
  228.     if (foot != NULL) {
  229.     p_move_abs( out, x_pos + (width - strlen(foot)*FONT_WIDTH) >> 1,
  230.              y_pos + height + (FONT_HEIGHT << 1) );
  231.     fprintf(out, "%s\n", foot);
  232.     }
  233.     p_move_abs(out, x_pos, y_pos);
  234.     p_bitmap(out, height, fixed_width, (unsigned long) one_plane_size,
  235.          buffer + plane * one_plane_size);
  236.     free((char *) win_name);
  237.     free((char *) buffer);
  238. }
  239.  
  240. static unsigned char *magnification_table(scale)
  241. int scale;
  242. {
  243.     unsigned char *tbl;
  244.     int c;
  245.  
  246.     if ((tbl = (unsigned char *)
  247.      calloc((unsigned) (scale*256), sizeof(char))) == NULL)
  248.       leave("Can't calloc magnification table.");
  249.     bzero((char *) tbl, scale*256);
  250.     for(c = 256; c--;) {
  251.     int b = c, bit;
  252.     unsigned char *entry = tbl+c*scale;
  253.  
  254.     while (b) {
  255.         int i, last, mask;
  256.         bit = 1;
  257.         mask = b;
  258.         while (! (mask & 1)) {
  259.         bit++;
  260.         mask = mask >> 1;
  261.         }
  262.         last = scale*(bit-1);
  263.         for(i = scale*bit; i-- > last ;)
  264.           entry[(scale - 1) - i / 8] |= 1 << (i % 8);
  265.         b &= ~(1 << bit-1);
  266.     }
  267.     }
  268.     return tbl;
  269. }
  270.  
  271. /* returns 2^n-1, i.e. a number with bits n-1 through 0 set.
  272.  * (zero for n == 0) */
  273. static bits_set(n)
  274. int n;
  275. {
  276.     int ans = 0;
  277.     while(n--)
  278.       ans |= 1 << n;
  279.     return ans;
  280. }
  281.  
  282. static void leave(s)
  283. char *s;
  284. {
  285.     extern int errno;
  286.  
  287.     fprintf(stderr, "\n%s: ", progname);
  288.     if (errno != 0)
  289.       perror(s);
  290.     else
  291.       fprintf(stderr, "%s", s);
  292.     fprintf(stderr, "\n");
  293.     exit(1);
  294. }
  295.  
  296. /* move to coordinates x, y (in pels) */
  297. p_move_abs(p, x, y)
  298. FILE *p;
  299. int x, y;
  300. {
  301.     if (x >= 0)  {
  302.     PMP(p, 3);
  303.     (void) putc('\340', p);
  304.     p_wput(x, p);
  305.     }
  306.     if (y >= 0)  {
  307.     PMP(p, 3);
  308.     (void) putc('\341', p);
  309.     p_wput(y, p);
  310.     }
  311. }
  312.  
  313. /* save current cursor position into (printer) register reg */
  314. p_save_cursor(p, reg)
  315. FILE *p;
  316. int reg;
  317. {
  318.     PMP(p, 1);
  319.     (void) putc(reg + '\200', p);
  320. }
  321.  
  322. /* restore current cursor position from (printer) register reg */
  323. p_restore_cursor(p, reg)
  324. FILE *p;
  325. int reg;
  326. {
  327.     PMP(p, 1);
  328.     (void) putc(reg + '\220', p);
  329. }
  330.  
  331. /* set the page orientation to orient (see pmp.h) */
  332. p_set_orientation(p, orient)
  333. FILE *p;
  334. enum orientation orient;
  335. {
  336.     PMP(p, 2);
  337.     fprintf(p, "\322%c", (int) orient);
  338. }
  339.  
  340. /* generate bitmap */
  341. p_bitmap(p, h, w, buflen, buf)
  342. FILE *p;
  343. unsigned int h, w;
  344. unsigned long buflen;
  345. unsigned char *buf;
  346. {
  347.     PMP(p, 9);
  348.     (void) fwrite("\365\0", 1, 2, p);
  349.     puthl2(h, p);
  350.     puthl2(w, p);
  351.     puthl3(buflen, p);
  352.     
  353.     while(buflen) {
  354.     int len;
  355.     
  356.     len = min(buflen, MAX_VECTOR_LEN);
  357.     PMP(p, len);
  358.     (void) fwrite((char *) buf, 1, len, p);
  359.     buf += len;
  360.     buflen -= len;
  361.     }
  362.     (void) fflush(p);
  363. }
  364.