home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (C) 1990, 1991 Aladdin Enterprises. All rights reserved.
- Distributed by Free Software Foundation, Inc.
-
- This file is part of Ghostscript.
-
- Ghostscript is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
- to anyone for the consequences of using it or for whether it serves any
- particular purpose or works at all, unless he says so in writing. Refer
- to the Ghostscript General Public License for full details.
-
- Everyone is granted permission to copy, modify and redistribute
- Ghostscript, but only under the conditions described in the Ghostscript
- General Public License. A copy of this license is supposed to have been
- given to you along with Ghostscript so you can know your rights and
- responsibilities. It should be in a file named COPYING. Among other
- things, the copyright notice and this notice must be preserved on all
- copies. */
-
- /* gdevprn.c */
- /* Generic printer support for Ghostscript */
- #ifdef __MSDOS__
- # include <io.h> /* for ioctl */
- #endif
- #include "gdevprn.h"
-
- /* Define the scratch file name template for mktemp */
- extern char gp_scratch_file_name_template[];
- #define SCRATCH_TEMPLATE gp_scratch_file_name_template
-
- /* Internal routine for opening a scratch file */
- private int
- open_scratch(char *fname, FILE **pfile)
- { strcpy(fname, SCRATCH_TEMPLATE);
- mktemp(fname);
- *pfile = fopen(fname, "w+b");
- if ( *pfile == NULL )
- { eprintf1("could not open the scratch file %s.\n", fname);
- return -1;
- }
- return 0;
- }
-
- /* ------ Standard device procedures ------ */
-
- gx_device_procs prn_std_procs =
- prn_procs(gdev_prn_open, gdev_prn_output_page, gdev_prn_close);
-
- /* Generic initialization for the printer device. */
- /* Specific devices may wish to extend this. */
- int
- gdev_prn_open(gx_device *dev)
- { gx_device *bdev;
- byte *base;
- gx_device_memory *mdev = &prn_dev->clist.mdev;
- ulong mem_space;
- *mdev = mem_mono_device;
- mdev->width = dev->width;
- mdev->height = dev->height;
- mem_space = gdev_mem_bitmap_size(mdev);
- if ( mem_space >= PRN_MAX_BITMAP )
- { /* Buffer the image in a command list. */
- gx_device_clist *cdev = &prn_dev->clist;
- uint space = prn_dev->buffer_space = PRN_BUFFER_SPACE;
- bdev = (gx_device *)cdev;
- *cdev = gs_clist_device;
- base = (byte *)gs_malloc(space, 1, "command list buffer");
- if ( base == 0 ) return -1;
- prn_dev->buf = base;
- cdev->data = base;
- cdev->data_size = space;
- if ( open_scratch(prn_dev->cfname, &prn_dev->cfile) < 0 )
- return -1;
- cdev->target = dev;
- cdev->file = prn_dev->cfile;
- }
- else
- { /* Render entirely in memory. */
- bdev = (gx_device *)mdev;
- prn_dev->buffer_space = 0;
- prn_dev->cfile = NULL;
- if ( mem_space != (uint)mem_space ) return -1; /* can't allocate */
- base = (byte *)gs_malloc((uint)mem_space, 1, "printer buffer");
- if ( base == 0 ) return -1;
- mdev->base = base;
- }
- prn_dev->bdev = bdev;
- if ( (*bdev->procs->open_device)(bdev) < 0 ) return -1;
- return 0;
- }
-
- /* Generic routine to send the page to the printer. */
- int
- gdev_prn_output_page(gx_device *dev)
- { int code = gdev_prn_open_printer(dev);
- if ( code < 0 ) return code;
-
- /* print the accumulated page description */
- code = (*prn_dev->print_page)(prn_dev, prn_dev->file);
- if ( code < 0 ) return code;
-
- code = gdev_prn_close_printer(dev);
- if ( code < 0 ) return code;
-
- if ( prn_dev->buffer_space ) /* reinitialize clist for writing */
- { gx_device *bdev = prn_dev->bdev;
- code = (*bdev->procs->open_device)(bdev);
- }
-
- return code;
- }
-
- /* Generic closing for the printer device. */
- /* Specific devices may wish to extend this. */
- int
- gdev_prn_close(gx_device *dev)
- { if ( prn_dev->cfile != NULL )
- { fclose(prn_dev->cfile);
- prn_dev->cfile = NULL;
- unlink(prn_dev->cfname);
- gs_free((char *)prn_dev->buf, (uint)prn_dev->buffer_space, 1,
- "command list buffer");
- }
- return 0;
- }
-
- /* Map a r-g-b "color" to a printer color: 0 = white, 1 = black. */
- gx_color_index
- gdev_prn_map_rgb_color(gx_device *dev, ushort r, ushort g, ushort b)
- { return ((r | g | b) ? 0 : 1);
- }
-
- /* Map the printer color back to black or white */
- int
- gdev_prn_map_color_rgb(gx_device *dev, gx_color_index color, ushort prgb[3])
- { prgb[0] = prgb[1] = prgb[2] = (color ? 0 : 1);
- return 0;
- }
-
- /* Delegate the painting operations to the buffer device. */
- int
- gdev_prn_fill_rectangle(gx_device *dev, int x, int y, int w, int h,
- gx_color_index color)
- { return (*prn_dev->bdev->procs->fill_rectangle)
- (prn_dev->bdev, x, y, w, h, color);
- }
- int
- gdev_prn_tile_rectangle(gx_device *dev, gx_bitmap *tile,
- int x, int y, int w, int h, gx_color_index color0, gx_color_index color1,
- int px, int py)
- { return (*prn_dev->bdev->procs->tile_rectangle)
- (prn_dev->bdev, tile, x, y, w, h, color0, color1, px, py);
- }
- int
- gdev_prn_copy_mono(gx_device *dev, byte *data,
- int dx, int raster, int x, int y, int w, int h,
- gx_color_index zero, gx_color_index one)
- { return (*prn_dev->bdev->procs->copy_mono)
- (prn_dev->bdev, data, dx, raster, x, y, w, h, zero, one);
- }
- int
- gdev_prn_copy_color(gx_device *dev, byte *data,
- int dx, int raster, int x, int y, int w, int h)
- { return (*prn_dev->bdev->procs->copy_color)
- (prn_dev->bdev, data, dx, raster, x, y, w, h);
- }
-
- /* ------ Driver services ------ */
-
- /* Open the printer device. */
- int
- gdev_prn_open_printer(gx_device *dev)
- { if ( prn_dev->write_to_prn )
- {
- #ifdef __MSDOS__
- int fno = fileno(stdprn);
- int ctrl = ioctl(fno, 0);
- ioctl(fno, 1, (ctrl | 0x20) & 0xff); /* no ^Z intervention! */
- prn_dev->file = stdprn;
- #else
- dprintf("Can't print directly from memory to printer yet.\n");
- #endif
- }
- else
- { if ( open_scratch(prn_dev->fname, &prn_dev->file) < 0 )
- return -1;
- }
- return 0;
- }
-
- /* Copy scan lines from the buffer to the printer. */
- int
- gdev_prn_copy_scan_lines(gx_device_printer *pdev, int y, byte *str, uint size)
- { int line_size = gdev_mem_bytes_per_scan_line((gx_device *)pdev);
- static byte rmasks[8] =
- { 0xff, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe };
- byte last_mask = rmasks[pdev->width & 7];
- int code, i;
- byte *line_end = str + line_size - 1;
- if ( pdev->buffer_space )
- { if ( pdev->clist.ymin < 0 ) /* not initialized */
- clist_render_init(&pdev->clist);
- code = clist_copy_scan_lines(&pdev->clist, y, str, size);
- }
- else
- code = gdev_mem_copy_scan_lines((gx_device_memory *)pdev->bdev,
- y, str, size);
- if ( code < 0 ) return code;
- /* Trim off any trailing garbage. */
- if ( last_mask == 0xff ) return code;
- for ( i = 0; i < code; i++, line_end += line_size )
- *line_end &= last_mask;
- return code;
- }
-
- /* Transpose an 8 x 8 block of bits. line_size is the raster of */
- /* the input data. dist is the distance between output bytes. */
- /* Not all printers need this, but some of the common ones do. */
- void
- gdev_prn_transpose_8x8(byte *inp, int line_size, byte *outp, int dist)
- { register uint ae = (uint)*inp << 8;
- register uint bf = (uint)*(inp += line_size) << 8;
- register uint cg = (uint)*(inp += line_size) << 8;
- register uint dh = (uint)*(inp += line_size) << 8;
- register uint temp;
- ae += *(inp += line_size);
- bf += *(inp += line_size);
- cg += *(inp += line_size);
- dh += inp[line_size];
-
- /* Transpose blocks of 4 x 4 */
- #define transpose4(r)\
- r ^= (temp = ((r >> 4) ^ r) & 0x00f0);\
- r ^= temp << 4
- transpose4(ae);
- transpose4(bf);
- transpose4(cg);
- transpose4(dh);
-
- /* Transpose blocks of 2 x 2 */
- #define transpose(r,s,mask,shift)\
- r ^= (temp = ((s >> shift) ^ r) & mask);\
- s ^= temp << shift
- transpose(ae, cg, 0x3333, 2);
- transpose(bf, dh, 0x3333, 2);
-
- /* Transpose blocks of 1 x 1 */
- transpose(ae, bf, 0x5555, 1);
- transpose(cg, dh, 0x5555, 1);
-
- *outp = ae >> 8;
- outp += dist;
- *outp = bf >> 8;
- outp += dist;
- *outp = cg >> 8;
- outp += dist;
- *outp = dh >> 8;
- outp += dist;
- *outp = (byte)ae; /* low-order byte */
- outp += dist;
- *outp = (byte)bf; /* ditto */
- outp += dist;
- *outp = (byte)cg; /* ditto */
- outp += dist;
- *outp = (byte)dh; /* ditto */
- }
-
- /* Flush the printer output from the scratch file. */
- int
- gdev_prn_close_printer(gx_device *dev)
- { if ( !prn_dev->write_to_prn )
- { fclose(prn_dev->file);
- dprintf1("To print the page, copy the file %s to the printer\n",
- prn_dev->fname);
- }
- return 0;
- }
-