summaryrefslogtreecommitdiff
path: root/gs/base/gdevdjtc.c
diff options
context:
space:
mode:
Diffstat (limited to 'gs/base/gdevdjtc.c')
-rw-r--r--gs/base/gdevdjtc.c270
1 files changed, 270 insertions, 0 deletions
diff --git a/gs/base/gdevdjtc.c b/gs/base/gdevdjtc.c
new file mode 100644
index 000000000..ef19cafd1
--- /dev/null
+++ b/gs/base/gdevdjtc.c
@@ -0,0 +1,270 @@
+/* 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$*/
+/* HP DeskJet 500C driver */
+#include "gdevprn.h"
+#include "gdevpcl.h"
+#include "malloc_.h"
+
+/***
+ *** Note: this driver was contributed by a user, Alfred Kayser:
+ *** please contact AKayser@et.tudelft.nl if you have questions.
+ ***/
+
+#ifndef SHINGLING /* Interlaced, multi-pass printing */
+#define SHINGLING 1 /* 0 = none, 1 = 50%, 2 = 25%, 2 is best & slowest */
+#endif
+
+#ifndef DEPLETION /* 'Intelligent' dot-removal */
+#define DEPLETION 1 /* 0 = none, 1 = 25%, 2 = 50%, 1 best for graphics? */
+#endif /* Use 0 for transparencies */
+
+#define X_DPI 300
+#define Y_DPI 300
+/* bytes per line for DeskJet Color */
+#define LINE_SIZE ((X_DPI * 85 / 10 + 63) / 64 * 8)
+
+/* The device descriptors */
+static dev_proc_print_page(djet500c_print_page);
+
+static gx_device_procs djet500c_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_djet500c_device =
+ prn_device(djet500c_procs, "djet500c",
+ 85, /* width_10ths, 8.5" */
+ 120, /* height_10ths, 12" */
+ X_DPI, Y_DPI,
+ 0.25, 0.25, 0.25, 0.25, /* margins */
+ 3, djet500c_print_page);
+
+/* Forward references */
+static int djet500c_print_page(gx_device_printer *, FILE *);
+
+static int mode2compress(byte *row, byte *end_row, byte *compressed);
+
+/* The DeskJet 500C uses additive colors in separate planes. */
+/* We only keep one bit of color, with 1 = R, 2 = G, 4 = B. */
+/* Because the buffering routines assume 0 = white, */
+/* we complement all the color components. */
+
+/* Send the page to the printer. For speed, compress each scan line, */
+/* since computer-to-printer communication time is often a bottleneck. */
+/* The DeskJet Color can compress (mode 2) */
+
+static int
+djet500c_print_page(gx_device_printer *pdev, FILE *fprn)
+{
+ byte *bitData=NULL;
+ byte *plane1=NULL;
+ byte *plane2=NULL;
+ byte *plane3=NULL;
+ int bitSize=0;
+ int planeSize=0;
+
+ /* select the most compressed mode available & clear tmp storage */
+ /* put printer in known state */
+ fputs("\033E",fprn);
+
+ /* ends raster graphics to set raster graphics resolution */
+ fputs("\033*rbC", fprn); /* was \033*rB */
+
+ /* set raster graphics resolution -- 300 dpi */
+ fputs("\033*t300R", fprn);
+
+ /* A4, skip perf, def. paper tray */
+ fputs("\033&l26a0l1H", fprn);
+
+ /* RGB Mode */
+ fputs("\033*r3U", fprn);
+
+ /* set depletion level */
+ fprintf(fprn, "\033*o%dD", DEPLETION);
+
+ /* set shingling level */
+ fprintf(fprn, "\033*o%dQ", SHINGLING);
+
+ /* move to top left of page & set current position */
+ fputs("\033*p0x0Y", fprn); /* cursor pos: 0,0 */
+
+ fputs("\033*b2M", fprn); /* mode 2 compression for now */
+
+ fputs("\033*r0A", fprn); /* start graf. left */
+
+ /* Send each scan line in turn */
+ { int lnum;
+ int num_blank_lines = 0;
+ int lineSize = gdev_mem_bytes_per_scan_line((gx_device *)pdev);
+ if (lineSize>bitSize)
+ {
+ if (bitData) free(bitData);
+ bitSize=lineSize;
+ bitData=(byte*)malloc(bitSize+16);
+ }
+ for (lnum=0; lnum<pdev->height; lnum++)
+ {
+ byte *endData;
+
+ gdev_prn_copy_scan_lines(pdev, lnum, bitData, lineSize);
+
+ /* Remove trailing 0s. */
+ endData = bitData + lineSize;
+ while ( (endData>bitData) && (endData[-1] == 0) )
+ endData--;
+ if (endData == bitData)
+ num_blank_lines++;
+ else
+ { int count, k, i, lineLen;
+
+ /* Pad with 0s to fill out the last */
+ /* block of 8 bytes. */
+ memset(endData, 0, 7);
+
+ lineLen=((endData-bitData)+7)/8; /* Round to next 8multiple */
+ if (planeSize<lineLen)
+ {
+ if (plane1) free(plane1);
+ if (plane2) free(plane2);
+ if (plane3) free(plane3);
+ planeSize=lineLen;
+ plane1=(byte*)malloc(planeSize+8);
+ plane2=(byte*)malloc(planeSize+8);
+ plane3=(byte*)malloc(planeSize+8);
+ }
+ /* Transpose the data to get pixel planes. */
+ for (k=i=0; k<lineLen; i+=8, k++)
+ {
+ register ushort t, c;
+
+ /* Three smaller loops are better optimizable and use less
+ vars, so most of them can be in registers even on pc's */
+ for (c=t=0;t<8;t++)
+ c = (c<<1) | (bitData[t+i]&4);
+ plane3[k] = ~(byte)(c>>2);
+ for (c=t=0;t<8;t++)
+ c = (c<<1) | (bitData[t+i]&2);
+ plane2[k] = ~(byte)(c>>1);
+ for (c=t=0;t<8;t++)
+ c = (c<<1) | (bitData[t+i]&1);
+ plane1[k] = ~(byte)(c);
+ }
+
+ /* Skip blank lines if any */
+ if (num_blank_lines > 0)
+ { /* move down from current position */
+ fprintf(fprn, "\033*b%dY", num_blank_lines);
+ num_blank_lines = 0;
+ }
+
+ /* Transfer raster graphics */
+ /* in the order R, G, B. */
+ /* lineLen is at least bitSize/8, so bitData can easily be used to store
+ lineLen of bytes */
+ /* P.s. mode9 compression is akward(??) to use, because the lineLenght's
+ are different, so we are stuck with mode 2, which is good enough */
+
+ /* set the line width */
+ fprintf(fprn, "\033*r%dS", lineLen*8);
+
+ count = mode2compress(plane1, plane1 + lineLen, bitData);
+ fprintf(fprn, "\033*b%dV", count);
+ fwrite(bitData, sizeof(byte), count, fprn);
+ count = mode2compress(plane2, plane2 + lineLen, bitData);
+ fprintf(fprn, "\033*b%dV", count);
+ fwrite(bitData, sizeof(byte), count, fprn);
+ count = mode2compress(plane3, plane3 + lineLen, bitData);
+ fprintf(fprn, "\033*b%dW", count);
+ fwrite(bitData, sizeof(byte), count, fprn);
+ }
+ }
+ }
+ /* end raster graphics */
+ fputs("\033*rbC", fprn); /* was \033*rB */
+ fputs("\033*r1U", fprn); /* back to 1 plane */
+
+ /* put printer in known state */
+ fputs("\033E",fprn);
+
+ /* eject page */
+ fputs("\033&l0H", fprn);
+
+ /* release allocated memory */
+ if (bitData) free(bitData);
+ if (plane1) free(plane1);
+ if (plane2) free(plane2);
+ if (plane3) free(plane3);
+
+ return 0;
+}
+
+
+/*
+ * Mode 2 Row compression routine for the HP DeskJet & LaserJet IIp.
+ * Compresses data from row up to end_row, storing the result
+ * starting at compressed. Returns the number of bytes stored.
+ * Runs of K<=127 literal bytes are encoded as K-1 followed by
+ * the bytes; runs of 2<=K<=127 identical bytes are encoded as
+ * 257-K followed by the byte.
+ * In the worst case, the result is N+(N/127)+1 bytes long,
+ * where N is the original byte count (end_row - row).
+ * I can't use the general pcl version, because it assume even linelength's
+ */
+
+static int
+mode2compress(byte *row, byte *end_row, byte *compressed)
+{
+ register byte *exam; /* word being examined in the row to compress */
+ register byte *cptr = compressed; /* output pointer into compressed bytes */
+ int i, count, len;
+ byte test;
+
+ exam = row;
+ while (1)
+ {
+ test = *exam++;
+ /* Advance exam until test==*exam or exam==end_row */
+ while ((test != *exam) && (exam < end_row))
+ test = *exam++;
+ /* row points to start of differing bytes,
+ exam points to start of consequtive series
+ or to end of row */
+ if (exam<end_row) exam--;
+ len=exam-row;
+ while (len>0)
+ {
+ count=len;
+ if (count>127) count=127;
+ *cptr++=count-1;
+ for (i=0;i<count;i++) *cptr++ = *row++;
+ len-=count;
+ }
+ if (exam>=end_row) break; /* done */
+ exam++; /* skip first same byte */
+ while ((test == *exam) && (exam < end_row)) /* skip all same bytes */
+ exam++;
+ /* exam points now first different word or to end of data */
+ len = exam-row;
+ while (len>0)
+ {
+ count=len;
+ if (count>127) count=127;
+ *cptr++=(257-count);
+ *cptr++=test;
+ len-=count;
+ }
+ if (exam>=end_row) break; /* end of data */
+ row = exam; /* row points to first dissimular byte */
+ }
+ return (cptr-compressed);
+}