/* Copyright (C) 1989, 1990, 1991 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: gdevdjtc.c,v 1.3.2.1.2.1 2003/01/17 00:49:00 giles Exp $*/ /* 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 */ private dev_proc_print_page(djet500c_print_page); private 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 */ private int djet500c_print_page(P2(gx_device_printer *, FILE *)); static int mode2compress(P3(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) */ private 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; lnumheight; 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>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 (exam0) { count=len; if (count>127) count=127; *cptr++=count-1; for (i=0;i=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); }