home *** CD-ROM | disk | FTP | other *** search
/ APDL Public Domain 1 / APDL_PD1A.iso / printing / ghostscrip / source / specific / c / gdevprn < prev    next >
Encoding:
Text File  |  1991-10-25  |  8.1 KB  |  278 lines

  1. /* Copyright (C) 1990, 1991 Aladdin Enterprises.  All rights reserved.
  2.    Distributed by Free Software Foundation, Inc.
  3.  
  4. This file is part of Ghostscript.
  5.  
  6. Ghostscript is distributed in the hope that it will be useful, but
  7. WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  8. to anyone for the consequences of using it or for whether it serves any
  9. particular purpose or works at all, unless he says so in writing.  Refer
  10. to the Ghostscript General Public License for full details.
  11.  
  12. Everyone is granted permission to copy, modify and redistribute
  13. Ghostscript, but only under the conditions described in the Ghostscript
  14. General Public License.  A copy of this license is supposed to have been
  15. given to you along with Ghostscript so you can know your rights and
  16. responsibilities.  It should be in a file named COPYING.  Among other
  17. things, the copyright notice and this notice must be preserved on all
  18. copies.  */
  19.  
  20. /* gdevprn.c */
  21. /* Generic printer support for Ghostscript */
  22. #ifdef __MSDOS__
  23. #  include <io.h>            /* for ioctl */
  24. #endif
  25. #include "gdevprn.h"
  26.  
  27. /* Define the scratch file name template for mktemp */
  28. extern char gp_scratch_file_name_template[];
  29. #define SCRATCH_TEMPLATE gp_scratch_file_name_template
  30.  
  31. /* Internal routine for opening a scratch file */
  32. private int
  33. open_scratch(char *fname, FILE **pfile)
  34. {    strcpy(fname, SCRATCH_TEMPLATE);
  35.     mktemp(fname);
  36.     *pfile = fopen(fname, "w+b");
  37.     if ( *pfile == NULL )
  38.        {    eprintf1("could not open the scratch file %s.\n", fname);
  39.         return -1;
  40.        }
  41.     return 0;
  42. }
  43.  
  44. /* ------ Standard device procedures ------ */
  45.  
  46. gx_device_procs prn_std_procs =
  47.   prn_procs(gdev_prn_open, gdev_prn_output_page, gdev_prn_close);
  48.  
  49. /* Generic initialization for the printer device. */
  50. /* Specific devices may wish to extend this. */
  51. int
  52. gdev_prn_open(gx_device *dev)
  53. {    gx_device *bdev;
  54.     byte *base;
  55.     gx_device_memory *mdev = &prn_dev->clist.mdev;
  56.     ulong mem_space;
  57.     *mdev = mem_mono_device;
  58.     mdev->width = dev->width;
  59.     mdev->height = dev->height;
  60.     mem_space = gdev_mem_bitmap_size(mdev);
  61.     if ( mem_space >= PRN_MAX_BITMAP )
  62.        {    /* Buffer the image in a command list. */
  63.         gx_device_clist *cdev = &prn_dev->clist;
  64.         uint space = prn_dev->buffer_space = PRN_BUFFER_SPACE;
  65.         bdev = (gx_device *)cdev;
  66.         *cdev = gs_clist_device;
  67.         base = (byte *)gs_malloc(space, 1, "command list buffer");
  68.         if ( base == 0 ) return -1;
  69.         prn_dev->buf = base;
  70.         cdev->data = base;
  71.         cdev->data_size = space;
  72.         if ( open_scratch(prn_dev->cfname, &prn_dev->cfile) < 0 )
  73.             return -1;
  74.         cdev->target = dev;
  75.         cdev->file = prn_dev->cfile;
  76.        }
  77.     else
  78.        {    /* Render entirely in memory. */
  79.         bdev = (gx_device *)mdev;
  80.         prn_dev->buffer_space = 0;
  81.         prn_dev->cfile = NULL;
  82.         if ( mem_space != (uint)mem_space ) return -1;    /* can't allocate */
  83.         base = (byte *)gs_malloc((uint)mem_space, 1, "printer buffer");
  84.         if ( base == 0 ) return -1;
  85.         mdev->base = base;
  86.        }
  87.     prn_dev->bdev = bdev;
  88.     if ( (*bdev->procs->open_device)(bdev) < 0 ) return -1;
  89.     return 0;
  90. }
  91.  
  92. /* Generic routine to send the page to the printer. */
  93. int
  94. gdev_prn_output_page(gx_device *dev)
  95. {    int code = gdev_prn_open_printer(dev);
  96.     if ( code < 0 ) return code;
  97.  
  98.     /* print the accumulated page description */
  99.     code = (*prn_dev->print_page)(prn_dev, prn_dev->file);
  100.     if ( code < 0 ) return code;
  101.  
  102.     code = gdev_prn_close_printer(dev);
  103.     if ( code < 0 ) return code;
  104.  
  105.     if ( prn_dev->buffer_space ) /* reinitialize clist for writing */
  106.       { gx_device *bdev = prn_dev->bdev;
  107.         code = (*bdev->procs->open_device)(bdev);
  108.       }
  109.  
  110.     return code;
  111. }
  112.  
  113. /* Generic closing for the printer device. */
  114. /* Specific devices may wish to extend this. */
  115. int
  116. gdev_prn_close(gx_device *dev)
  117. {    if ( prn_dev->cfile != NULL )
  118.        {    fclose(prn_dev->cfile);
  119.         prn_dev->cfile = NULL;
  120.         unlink(prn_dev->cfname);
  121.         gs_free((char *)prn_dev->buf, (uint)prn_dev->buffer_space, 1,
  122.             "command list buffer");
  123.        }
  124.     return 0;
  125. }
  126.  
  127. /* Map a r-g-b "color" to a printer color: 0 = white, 1 = black. */
  128. gx_color_index
  129. gdev_prn_map_rgb_color(gx_device *dev, ushort r, ushort g, ushort b)
  130. {    return ((r | g | b) ? 0 : 1);
  131. }
  132.  
  133. /* Map the printer color back to black or white */
  134. int
  135. gdev_prn_map_color_rgb(gx_device *dev, gx_color_index color, ushort prgb[3])
  136. {    prgb[0] = prgb[1] = prgb[2] = (color ? 0 : 1);
  137.     return 0;
  138. }
  139.  
  140. /* Delegate the painting operations to the buffer device. */
  141. int
  142. gdev_prn_fill_rectangle(gx_device *dev, int x, int y, int w, int h,
  143.   gx_color_index color)
  144. {    return (*prn_dev->bdev->procs->fill_rectangle)
  145.       (prn_dev->bdev, x, y, w, h, color);
  146. }
  147. int
  148. gdev_prn_tile_rectangle(gx_device *dev, gx_bitmap *tile,
  149.   int x, int y, int w, int h, gx_color_index color0, gx_color_index color1,
  150.   int px, int py)
  151. {    return (*prn_dev->bdev->procs->tile_rectangle)
  152.       (prn_dev->bdev, tile, x, y, w, h, color0, color1, px, py);
  153. }
  154. int
  155. gdev_prn_copy_mono(gx_device *dev, byte *data,
  156.   int dx, int raster, int x, int y, int w, int h,
  157.   gx_color_index zero, gx_color_index one)
  158. {    return (*prn_dev->bdev->procs->copy_mono)
  159.       (prn_dev->bdev, data, dx, raster, x, y, w, h, zero, one);
  160. }
  161. int
  162. gdev_prn_copy_color(gx_device *dev, byte *data,
  163.   int dx, int raster, int x, int y, int w, int h)
  164. {    return (*prn_dev->bdev->procs->copy_color)
  165.       (prn_dev->bdev, data, dx, raster, x, y, w, h);
  166. }
  167.  
  168. /* ------ Driver services ------ */
  169.  
  170. /* Open the printer device. */
  171. int
  172. gdev_prn_open_printer(gx_device *dev)
  173. {    if ( prn_dev->write_to_prn )
  174.        {
  175. #ifdef __MSDOS__
  176.         int fno = fileno(stdprn);
  177.         int ctrl = ioctl(fno, 0);
  178.         ioctl(fno, 1, (ctrl | 0x20) & 0xff); /* no ^Z intervention! */
  179.         prn_dev->file = stdprn;
  180. #else
  181.         dprintf("Can't print directly from memory to printer yet.\n");
  182. #endif
  183.        }
  184.     else
  185.        {    if ( open_scratch(prn_dev->fname, &prn_dev->file) < 0 )
  186.             return -1;
  187.        }
  188.     return 0;
  189. }
  190.  
  191. /* Copy scan lines from the buffer to the printer. */
  192. int
  193. gdev_prn_copy_scan_lines(gx_device_printer *pdev, int y, byte *str, uint size)
  194. {    int line_size = gdev_mem_bytes_per_scan_line((gx_device *)pdev);
  195.     static byte rmasks[8] =
  196.         { 0xff, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe };
  197.     byte last_mask = rmasks[pdev->width & 7];
  198.     int code, i;
  199.     byte *line_end = str + line_size - 1;
  200.     if ( pdev->buffer_space )
  201.        {    if ( pdev->clist.ymin < 0 )    /* not initialized */
  202.             clist_render_init(&pdev->clist);
  203.         code = clist_copy_scan_lines(&pdev->clist, y, str, size);
  204.        }
  205.     else
  206.       code = gdev_mem_copy_scan_lines((gx_device_memory *)pdev->bdev,
  207.                       y, str, size);
  208.     if ( code < 0 ) return code;
  209.     /* Trim off any trailing garbage. */
  210.     if ( last_mask == 0xff ) return code;
  211.     for ( i = 0; i < code; i++, line_end += line_size )
  212.         *line_end &= last_mask;
  213.     return code;
  214. }
  215.  
  216. /* Transpose an 8 x 8 block of bits.  line_size is the raster of */
  217. /* the input data.  dist is the distance between output bytes. */
  218. /* Not all printers need this, but some of the common ones do. */
  219. void
  220. gdev_prn_transpose_8x8(byte *inp, int line_size, byte *outp, int dist)
  221. {    register uint ae = (uint)*inp << 8;
  222.     register uint bf = (uint)*(inp += line_size) << 8;
  223.     register uint cg = (uint)*(inp += line_size) << 8;
  224.     register uint dh = (uint)*(inp += line_size) << 8;
  225.     register uint temp;
  226.     ae += *(inp += line_size);
  227.     bf += *(inp += line_size);
  228.     cg += *(inp += line_size);
  229.     dh += inp[line_size];
  230.  
  231. /* Transpose blocks of 4 x 4 */
  232. #define transpose4(r)\
  233.   r ^= (temp = ((r >> 4) ^ r) & 0x00f0);\
  234.   r ^= temp << 4
  235.     transpose4(ae);
  236.     transpose4(bf);
  237.     transpose4(cg);
  238.     transpose4(dh);
  239.  
  240. /* Transpose blocks of 2 x 2 */
  241. #define transpose(r,s,mask,shift)\
  242.   r ^= (temp = ((s >> shift) ^ r) & mask);\
  243.   s ^= temp << shift
  244.     transpose(ae, cg, 0x3333, 2);
  245.     transpose(bf, dh, 0x3333, 2);
  246.  
  247. /* Transpose blocks of 1 x 1 */
  248.     transpose(ae, bf, 0x5555, 1);
  249.     transpose(cg, dh, 0x5555, 1);
  250.  
  251.     *outp = ae >> 8;
  252.     outp += dist;
  253.     *outp = bf >> 8;
  254.     outp += dist;
  255.     *outp = cg >> 8;
  256.     outp += dist;
  257.     *outp = dh >> 8;
  258.     outp += dist;
  259.     *outp = (byte)ae;        /* low-order byte */
  260.     outp += dist;
  261.     *outp = (byte)bf;        /* ditto */
  262.     outp += dist;
  263.     *outp = (byte)cg;        /* ditto */
  264.     outp += dist;
  265.     *outp = (byte)dh;        /* ditto */
  266. }
  267.  
  268. /* Flush the printer output from the scratch file. */
  269. int
  270. gdev_prn_close_printer(gx_device *dev)
  271. {    if ( !prn_dev->write_to_prn )
  272.        {    fclose(prn_dev->file);
  273.         dprintf1("To print the page, copy the file %s to the printer\n",
  274.              prn_dev->fname);
  275.        }
  276.     return 0;
  277. }
  278.