/* Copyright (C) 1991, 1992 artofcode LLC. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA, 02111-1307. */ /*$Id: gdevpjet.c,v 1.3.2.1.2.1 2003/01/17 00:49:01 giles Exp $*/ /* H-P PaintJet, PaintJet XL, and DEC LJ250 drivers. */ /* Thanks to Rob Reiss (rob@moray.berkeley.edu) for the PaintJet XL */ /* modifications. */ #include "gdevprn.h" #include "gdevpcl.h" /* X_DPI and Y_DPI must be the same, and may be either 90 or 180. */ #define X_DPI 180 #define Y_DPI 180 /* We round up LINE_SIZE to a multiple of 8 bytes */ /* because that's the unit of transposition from pixels to planes. */ #define LINE_SIZE ((X_DPI * 85 / 10 + 63) / 64 * 8) /* The device descriptors */ private dev_proc_print_page(lj250_print_page); private dev_proc_print_page(paintjet_print_page); private dev_proc_print_page(pjetxl_print_page); private int pj_common_print_page(P4(gx_device_printer *, FILE *, int, const char *)); private gx_device_procs paintjet_procs = prn_color_procs(gdev_prn_open, gdev_prn_output_page, gdev_prn_close, gdev_pcl_3bit_map_rgb_color, gdev_pcl_3bit_map_color_rgb); const gx_device_printer far_data gs_lj250_device = prn_device(paintjet_procs, "lj250", 85, /* width_10ths, 8.5" */ 110, /* height_10ths, 11" */ X_DPI, Y_DPI, 0.25, 0, 0.25, 0, /* margins */ 3, lj250_print_page); const gx_device_printer far_data gs_paintjet_device = prn_device(paintjet_procs, "paintjet", 85, /* width_10ths, 8.5" */ 110, /* height_10ths, 11" */ X_DPI, Y_DPI, 0.25, 0, 0.25, 0, /* margins */ 3, paintjet_print_page); private gx_device_procs pjetxl_procs = prn_color_procs(gdev_prn_open, gdev_prn_output_page, gdev_prn_close, gdev_pcl_3bit_map_rgb_color, gdev_pcl_3bit_map_color_rgb); const gx_device_printer far_data gs_pjetxl_device = prn_device(pjetxl_procs, "pjetxl", 85, /* width_10ths, 8.5" */ 110, /* height_10ths, 11" */ X_DPI, Y_DPI, 0.25, 0, 0, 0, /* margins */ 3, pjetxl_print_page); /* Forward references */ private int compress1_row(P3(const byte *, const byte *, byte *)); /* ------ Internal routines ------ */ /* Send a page to the LJ250. We need to enter and exit */ /* the PaintJet emulation mode. */ private int lj250_print_page(gx_device_printer *pdev, FILE *prn_stream) { fputs("\033%8", prn_stream); /* Enter PCL emulation mode */ /* ends raster graphics to set raster graphics resolution */ fputs("\033*rB", prn_stream); /* Exit PCL emulation mode after printing */ return pj_common_print_page(pdev, prn_stream, 0, "\033*r0B\014\033%@"); } /* Send a page to the PaintJet. */ private int paintjet_print_page(gx_device_printer *pdev, FILE *prn_stream) { /* ends raster graphics to set raster graphics resolution */ fputs("\033*rB", prn_stream); return pj_common_print_page(pdev, prn_stream, 0, "\033*r0B\014"); } /* Send a page to the PaintJet XL. */ private int pjetxl_print_page(gx_device_printer *pdev, FILE *prn_stream) { /* Initialize PaintJet XL for printing */ fputs("\033E", prn_stream); /* The XL has a different vertical origin, who knows why?? */ return pj_common_print_page(pdev, prn_stream, -360, "\033*rC"); } /* Send the page to the printer. Compress each scan line. */ private int pj_common_print_page(gx_device_printer *pdev, FILE *prn_stream, int y_origin, const char *end_page) { #define DATA_SIZE (LINE_SIZE * 8) byte *data = (byte *)gs_malloc(DATA_SIZE, 1, "paintjet_print_page(data)"); byte *plane_data = (byte *)gs_malloc(LINE_SIZE * 3, 1, "paintjet_print_page(plane_data)"); if ( data == 0 || plane_data == 0 ) { if ( data ) gs_free((char *)data, DATA_SIZE, 1, "paintjet_print_page(data)"); if ( plane_data ) gs_free((char *)plane_data, LINE_SIZE * 3, 1, "paintjet_print_page(plane_data)"); return_error(gs_error_VMerror); } /* set raster graphics resolution -- 90 or 180 dpi */ fprintf(prn_stream, "\033*t%dR", X_DPI); /* set the line width */ fprintf(prn_stream, "\033*r%dS", DATA_SIZE); /* set the number of color planes */ fprintf(prn_stream, "\033*r%dU", 3); /* always 3 */ /* move to top left of page */ fprintf(prn_stream, "\033&a0H\033&a%dV", y_origin); /* select data compression */ fputs("\033*b1M", prn_stream); /* start raster graphics */ fputs("\033*r1A", prn_stream); /* Send each scan line in turn */ { int lnum; int line_size = gdev_mem_bytes_per_scan_line((gx_device *)pdev); int num_blank_lines = 0; for ( lnum = 0; lnum < pdev->height; lnum++ ) { byte *end_data = data + line_size; gdev_prn_copy_scan_lines(pdev, lnum, (byte *)data, line_size); /* Remove trailing 0s. */ while ( end_data > data && end_data[-1] == 0 ) end_data--; if ( end_data == data ) { /* Blank line */ num_blank_lines++; } else { int i; byte *odp; byte *row; /* Pad with 0s to fill out the last */ /* block of 8 bytes. */ memset(end_data, 0, 7); /* Transpose the data to get pixel planes. */ for ( i = 0, odp = plane_data; i < DATA_SIZE; i += 8, odp++ ) { /* The following is for 16-bit machines */ #define spread3(c)\ { 0, c, c*0x100, c*0x101, c*0x10000L, c*0x10001L, c*0x10100L, c*0x10101L } static ulong spr40[8] = spread3(0x40); static ulong spr8[8] = spread3(8); static ulong spr2[8] = spread3(2); register byte *dp = data + i; register ulong pword = (spr40[dp[0]] << 1) + (spr40[dp[1]]) + (spr40[dp[2]] >> 1) + (spr8[dp[3]] << 1) + (spr8[dp[4]]) + (spr8[dp[5]] >> 1) + (spr2[dp[6]]) + (spr2[dp[7]] >> 1); odp[0] = (byte)(pword >> 16); odp[LINE_SIZE] = (byte)(pword >> 8); odp[LINE_SIZE*2] = (byte)(pword); } /* Skip blank lines if any */ if ( num_blank_lines > 0 ) { /* move down from current position */ fprintf(prn_stream, "\033&a+%dV", num_blank_lines * (720 / Y_DPI)); num_blank_lines = 0; } /* Transfer raster graphics */ /* in the order R, G, B. */ for ( row = plane_data + LINE_SIZE * 2, i = 0; i < 3; row -= LINE_SIZE, i++ ) { byte temp[LINE_SIZE * 2]; int count = compress1_row(row, row + LINE_SIZE, temp); fprintf(prn_stream, "\033*b%d%c", count, "VVW"[i]); fwrite(temp, sizeof(byte), count, prn_stream); } } } } /* end the page */ fputs(end_page, prn_stream); gs_free((char *)data, DATA_SIZE, 1, "paintjet_print_page(data)"); gs_free((char *)plane_data, LINE_SIZE * 3, 1, "paintjet_print_page(plane_data)"); return 0; } /* * Row compression for the H-P PaintJet. * Compresses data from row up to end_row, storing the result * starting at compressed. Returns the number of bytes stored. * The compressed format consists of a byte N followed by a * data byte that is to be repeated N+1 times. * In the worst case, the `compressed' representation is * twice as large as the input. * We complement the bytes at the same time, because * we accumulated the image in complemented form. */ private int compress1_row(const byte *row, const byte *end_row, byte *compressed) { register const byte *in = row; register byte *out = compressed; while ( in < end_row ) { byte test = *in++; const byte *run = in; while ( in < end_row && *in == test ) in++; /* Note that in - run + 1 is the repetition count. */ while ( in - run > 255 ) { *out++ = 255; *out++ = ~test; run += 256; } *out++ = in - run; *out++ = ~test; } return out - compressed; }