summaryrefslogtreecommitdiff
path: root/gs/base/gdevpjet.c
diff options
context:
space:
mode:
Diffstat (limited to 'gs/base/gdevpjet.c')
-rw-r--r--gs/base/gdevpjet.c246
1 files changed, 246 insertions, 0 deletions
diff --git a/gs/base/gdevpjet.c b/gs/base/gdevpjet.c
new file mode 100644
index 000000000..f135342b6
--- /dev/null
+++ b/gs/base/gdevpjet.c
@@ -0,0 +1,246 @@
+/* Copyright (C) 2001-2006 Artifex Software, Inc.
+ All Rights Reserved.
+
+ This software is provided AS-IS with no warranty, either express or
+ implied.
+
+ This software is distributed under license and may not be copied, modified
+ or distributed except as expressly authorized under the terms of that
+ license. Refer to licensing information at http://www.artifex.com/
+ or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
+ San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
+*/
+
+/* $Id$*/
+/* 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 */
+static dev_proc_print_page(lj250_print_page);
+static dev_proc_print_page(paintjet_print_page);
+static dev_proc_print_page(pjetxl_print_page);
+static int pj_common_print_page(gx_device_printer *, FILE *, int, const char *);
+static 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);
+static 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 */
+static int compress1_row(const byte *, const byte *, byte *);
+
+/* ------ Internal routines ------ */
+
+/* Send a page to the LJ250. We need to enter and exit */
+/* the PaintJet emulation mode. */
+static 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. */
+static 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. */
+static 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. */
+static 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(pdev->memory, DATA_SIZE, 1,
+ "paintjet_print_page(data)");
+ byte *plane_data =
+ (byte *)gs_malloc(pdev->memory, LINE_SIZE * 3, 1,
+ "paintjet_print_page(plane_data)");
+ if ( data == 0 || plane_data == 0 )
+ { if ( data )
+ gs_free(pdev->memory, (char *)data, DATA_SIZE, 1,
+ "paintjet_print_page(data)");
+ if ( plane_data )
+ gs_free(pdev->memory, (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(pdev->memory, (char *)data, DATA_SIZE, 1, "paintjet_print_page(data)");
+ gs_free(pdev->memory, (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.
+ */
+static 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;
+}