xref: /plan9/sys/src/cmd/gs/src/gdevlbp8.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
17dd7cddfSDavid du Colombier /* Copyright (C) 1991, 1994, 1996, 1997 Aladdin Enterprises.  All rights reserved.
27dd7cddfSDavid du Colombier 
3*593dc095SDavid du Colombier   This software is provided AS-IS with no warranty, either express or
4*593dc095SDavid du Colombier   implied.
57dd7cddfSDavid du Colombier 
6*593dc095SDavid du Colombier   This software is distributed under license and may not be copied,
7*593dc095SDavid du Colombier   modified or distributed except as expressly authorized under the terms
8*593dc095SDavid du Colombier   of the license contained in the file LICENSE in this distribution.
97dd7cddfSDavid du Colombier 
10*593dc095SDavid du Colombier   For more information about licensing, please refer to
11*593dc095SDavid du Colombier   http://www.ghostscript.com/licensing/. For information on
12*593dc095SDavid du Colombier   commercial licensing, go to http://www.artifex.com/licensing/ or
13*593dc095SDavid du Colombier   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14*593dc095SDavid du Colombier   San Rafael, CA  94903, U.S.A., +1(415)492-9861.
157dd7cddfSDavid du Colombier */
167dd7cddfSDavid du Colombier 
17*593dc095SDavid du Colombier /* $Id: gdevlbp8.c,v 1.6 2002/10/07 08:28:56 ghostgum Exp $*/
187dd7cddfSDavid du Colombier /* Canon LBP-8II and LIPS III driver */
197dd7cddfSDavid du Colombier #include "gdevprn.h"
207dd7cddfSDavid du Colombier 
217dd7cddfSDavid du Colombier /*
227dd7cddfSDavid du Colombier   Modifications:
237dd7cddfSDavid du Colombier     2.2.97  Lauri Paatero
247dd7cddfSDavid du Colombier             Changed CSI command into ESC [. DCS commands may still need to be changed
257dd7cddfSDavid du Colombier             (to ESC P).
267dd7cddfSDavid du Colombier     4.9.96  Lauri Paatero
277dd7cddfSDavid du Colombier 	    Corrected LBP-8II margins again. Real problem was that (0,0) is NOT
287dd7cddfSDavid du Colombier                 in upper left corner.
297dd7cddfSDavid du Colombier 	    Now using relative addressing for vertical addressing. This avoids
307dd7cddfSDavid du Colombier problems
317dd7cddfSDavid du Colombier                 when printing to paper with wrong size.
327dd7cddfSDavid du Colombier     18.6.96 Lauri Paatero, lauri.paatero@paatero.pp.fi
337dd7cddfSDavid du Colombier             Corrected LBP-8II margins.
347dd7cddfSDavid du Colombier             Added logic to recognize (and optimize away) long strings of 00's in data.
357dd7cddfSDavid du Colombier             For LBP-8II removed use of 8-bit CSI (this does not work if 8-bit character
367dd7cddfSDavid du Colombier                 set has been configured in LBP-8II. (Perhaps this should also be done
377dd7cddfSDavid du Colombier                 for LBP-8III?)
387dd7cddfSDavid du Colombier   Original versions:
397dd7cddfSDavid du Colombier     LBP8 driver: Tom Quinn (trq@prg.oxford.ac.uk)
407dd7cddfSDavid du Colombier     LIPS III driver: Kenji Okamoto (okamoto@okamoto.cias.osakafu-u.ac.jp)
417dd7cddfSDavid du Colombier */
427dd7cddfSDavid du Colombier 
437dd7cddfSDavid du Colombier 
447dd7cddfSDavid du Colombier #define X_DPI 300
457dd7cddfSDavid du Colombier #define Y_DPI 300
467dd7cddfSDavid du Colombier #define LINE_SIZE ((X_DPI * 85 / 10 + 7) / 8)	/* bytes per line */
477dd7cddfSDavid du Colombier 
487dd7cddfSDavid du Colombier /* The device descriptors */
497dd7cddfSDavid du Colombier private dev_proc_print_page(lbp8_print_page);
507dd7cddfSDavid du Colombier private dev_proc_print_page(lips3_print_page);
517dd7cddfSDavid du Colombier 
523ff48bf5SDavid du Colombier const gx_device_printer far_data gs_lbp8_device =
537dd7cddfSDavid du Colombier   prn_device(prn_std_procs, "lbp8",
547dd7cddfSDavid du Colombier 	DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
557dd7cddfSDavid du Colombier 	X_DPI, Y_DPI,
567dd7cddfSDavid du Colombier 	0.16, 0.2, 0.32, 0.21,		/* margins: left, bottom, right, top */
577dd7cddfSDavid du Colombier 	1, lbp8_print_page);
587dd7cddfSDavid du Colombier 
593ff48bf5SDavid du Colombier const gx_device_printer far_data gs_lips3_device =
607dd7cddfSDavid du Colombier   prn_device(prn_std_procs, "lips3",
617dd7cddfSDavid du Colombier 	82,				/* width_10ths, 8.3" */
627dd7cddfSDavid du Colombier 	117,				/* height_10ths, 11.7" */
637dd7cddfSDavid du Colombier 	X_DPI, Y_DPI,
647dd7cddfSDavid du Colombier 	0.16, 0.27, 0.23, 0.27,		/* margins */
657dd7cddfSDavid du Colombier 	1, lips3_print_page);
667dd7cddfSDavid du Colombier 
677dd7cddfSDavid du Colombier /* ------ Internal routines ------ */
687dd7cddfSDavid du Colombier 
69*593dc095SDavid du Colombier #define ESC (char)0x1b
70*593dc095SDavid du Colombier #define CSI '\233'
71*593dc095SDavid du Colombier #define DCS '\220'
72*593dc095SDavid du Colombier #define ST '\234'
737dd7cddfSDavid du Colombier 
747dd7cddfSDavid du Colombier static const char lbp8_init[] = {
757dd7cddfSDavid du Colombier   ESC, ';', ESC, 'c', ESC, ';', /* reset, ISO */
767dd7cddfSDavid du Colombier   ESC, '[', '2', '&', 'z',	/* fullpaint mode */
777dd7cddfSDavid du Colombier   ESC, '[', '1', '4', 'p',	/* select page type (A4) */
787dd7cddfSDavid du Colombier   ESC, '[', '1', '1', 'h',	/* set mode */
797dd7cddfSDavid du Colombier   ESC, '[', '7', ' ', 'I',	/* select unit size (300dpi)*/
807dd7cddfSDavid du Colombier   ESC, '[', '6', '3', 'k', 	/* Move 63 dots up (to top of printable area) */
817dd7cddfSDavid du Colombier };
827dd7cddfSDavid du Colombier 
837dd7cddfSDavid du Colombier static const char *lbp8_end = NULL;
847dd7cddfSDavid du Colombier 
857dd7cddfSDavid du Colombier static const char lips3_init[] = {
867dd7cddfSDavid du Colombier   ESC, '<', /* soft reset */
877dd7cddfSDavid du Colombier   DCS, '0', 'J', ST, /* JOB END */
887dd7cddfSDavid du Colombier   DCS, '3', '1', ';', '3', '0', '0', ';', '2', 'J', ST, /* 300dpi, LIPS3 JOB START */
897dd7cddfSDavid du Colombier   ESC, '<',  /* soft reset */
907dd7cddfSDavid du Colombier   DCS, '2', 'y', 'P', 'r', 'i', 'n', 't', 'i', 'n', 'g', '(', 'g', 's', ')', ST,  /* Printing (gs) display */
917dd7cddfSDavid du Colombier   ESC, '[', '?', '1', 'l',  /* auto cr-lf disable */
927dd7cddfSDavid du Colombier   ESC, '[', '?', '2', 'h', /* auto ff disable */
937dd7cddfSDavid du Colombier   ESC, '[', '1', '1', 'h', /* set mode */
947dd7cddfSDavid du Colombier   ESC, '[', '7', ' ', 'I', /* select unit size (300dpi)*/
957dd7cddfSDavid du Colombier   ESC, '[', 'f' /* move to home position */
967dd7cddfSDavid du Colombier };
977dd7cddfSDavid du Colombier 
987dd7cddfSDavid du Colombier static const char lips3_end[] = {
997dd7cddfSDavid du Colombier   DCS, '0', 'J', ST  /* JOB END */
1007dd7cddfSDavid du Colombier };
1017dd7cddfSDavid du Colombier 
1027dd7cddfSDavid du Colombier /* Send the page to the printer.  */
1037dd7cddfSDavid du Colombier private int
can_print_page(gx_device_printer * pdev,FILE * prn_stream,const char * init,int init_size,const char * end,int end_size)1047dd7cddfSDavid du Colombier can_print_page(gx_device_printer *pdev, FILE *prn_stream,
1057dd7cddfSDavid du Colombier   const char *init, int init_size, const char *end, int end_size)
1067dd7cddfSDavid du Colombier {
1077dd7cddfSDavid du Colombier 	char data[LINE_SIZE*2];
1087dd7cddfSDavid du Colombier 	char *out_data;
1097dd7cddfSDavid du Colombier 	int last_line_nro = 0;
1107dd7cddfSDavid du Colombier 
1117dd7cddfSDavid du Colombier 	fwrite(init, init_size, 1, prn_stream);		/* initialize */
1127dd7cddfSDavid du Colombier 
1137dd7cddfSDavid du Colombier 	/* Send each scan line in turn */
1147dd7cddfSDavid du Colombier 	{
1157dd7cddfSDavid du Colombier 	    int lnum;
1167dd7cddfSDavid du Colombier 	    int line_size = gdev_mem_bytes_per_scan_line((gx_device *)pdev);
1177dd7cddfSDavid du Colombier 	    byte rmask = (byte)(0xff << (-pdev->width & 7));
1187dd7cddfSDavid du Colombier 
1197dd7cddfSDavid du Colombier 	    for ( lnum = 0; lnum < pdev->height; lnum++ ) {
1207dd7cddfSDavid du Colombier     		char *end_data = data + LINE_SIZE;
1217dd7cddfSDavid du Colombier 		gdev_prn_copy_scan_lines(pdev, lnum,
1227dd7cddfSDavid du Colombier 					 (byte *)data, line_size);
1237dd7cddfSDavid du Colombier 	   	/* Mask off 1-bits beyond the line width. */
1247dd7cddfSDavid du Colombier 		end_data[-1] &= rmask;
1257dd7cddfSDavid du Colombier 		/* Remove trailing 0s. */
1267dd7cddfSDavid du Colombier 		while ( end_data > data && end_data[-1] == 0 )
1277dd7cddfSDavid du Colombier 			end_data--;
1287dd7cddfSDavid du Colombier 		if ( end_data != data ) {
1297dd7cddfSDavid du Colombier 		    int num_cols = 0;
1307dd7cddfSDavid du Colombier 		    int out_count;
1317dd7cddfSDavid du Colombier 		    int zero_count;
1327dd7cddfSDavid du Colombier 		    out_data = data;
1337dd7cddfSDavid du Colombier 
1347dd7cddfSDavid du Colombier 		    /* move down */
1357dd7cddfSDavid du Colombier 		    fprintf(prn_stream, "%c[%de",
1367dd7cddfSDavid du Colombier 			    ESC, lnum-last_line_nro );
1377dd7cddfSDavid du Colombier 		    last_line_nro = lnum;
1387dd7cddfSDavid du Colombier 
1397dd7cddfSDavid du Colombier 		    while (out_data < end_data) {
1407dd7cddfSDavid du Colombier 			/* Remove leading 0s*/
1417dd7cddfSDavid du Colombier 			while(out_data < end_data && *out_data == 0) {
1427dd7cddfSDavid du Colombier 		            num_cols += 8;
1437dd7cddfSDavid du Colombier                             out_data++;
1447dd7cddfSDavid du Colombier                         }
1457dd7cddfSDavid du Colombier 
1467dd7cddfSDavid du Colombier 			out_count = end_data - out_data;
1477dd7cddfSDavid du Colombier 			zero_count = 0;
1487dd7cddfSDavid du Colombier 
1497dd7cddfSDavid du Colombier 			/* if there is a lot data, find if there is sequence of zeros */
1507dd7cddfSDavid du Colombier 			if (out_count>22) {
1517dd7cddfSDavid du Colombier 
1527dd7cddfSDavid du Colombier 				out_count = 1;
1537dd7cddfSDavid du Colombier 
1547dd7cddfSDavid du Colombier 				while(out_data+out_count+zero_count < end_data) {
1557dd7cddfSDavid du Colombier 					if (out_data[zero_count+out_count] != 0) {
1567dd7cddfSDavid du Colombier 						out_count += 1+zero_count;
1577dd7cddfSDavid du Colombier 						zero_count = 0;
1587dd7cddfSDavid du Colombier 					}
1597dd7cddfSDavid du Colombier 					else {
1607dd7cddfSDavid du Colombier 						zero_count++;
1617dd7cddfSDavid du Colombier 						if (zero_count>20)
1627dd7cddfSDavid du Colombier 							break;
1637dd7cddfSDavid du Colombier 					}
1647dd7cddfSDavid du Colombier 				}
1657dd7cddfSDavid du Colombier 
1667dd7cddfSDavid du Colombier 			}
1677dd7cddfSDavid du Colombier 
1687dd7cddfSDavid du Colombier 			if (out_count==0)
1697dd7cddfSDavid du Colombier 				break;
1707dd7cddfSDavid du Colombier 
1717dd7cddfSDavid du Colombier 			/* move down and across*/
1727dd7cddfSDavid du Colombier 			fprintf(prn_stream, "%c[%d`",
1737dd7cddfSDavid du Colombier 				ESC, num_cols );
1747dd7cddfSDavid du Colombier 			/* transfer raster graphic command */
1757dd7cddfSDavid du Colombier 			fprintf(prn_stream, "%c[%d;%d;300;.r",
1767dd7cddfSDavid du Colombier 				ESC, out_count, out_count);
1777dd7cddfSDavid du Colombier 
1787dd7cddfSDavid du Colombier 			/* send the row */
1797dd7cddfSDavid du Colombier 			fwrite(out_data, sizeof(char),
1807dd7cddfSDavid du Colombier                                out_count, prn_stream);
1817dd7cddfSDavid du Colombier 
1827dd7cddfSDavid du Colombier 			out_data += out_count+zero_count;
1837dd7cddfSDavid du Colombier                	        num_cols += 8*(out_count+zero_count);
1847dd7cddfSDavid du Colombier 		    }
1857dd7cddfSDavid du Colombier 		}
1867dd7cddfSDavid du Colombier 	    }
1877dd7cddfSDavid du Colombier 	}
1887dd7cddfSDavid du Colombier 
1897dd7cddfSDavid du Colombier 	/* eject page */
1907dd7cddfSDavid du Colombier 	fprintf(prn_stream, "%c=", ESC);
1917dd7cddfSDavid du Colombier 
1927dd7cddfSDavid du Colombier 	/* terminate */
1937dd7cddfSDavid du Colombier 	if (end != NULL)
1947dd7cddfSDavid du Colombier 	    fwrite(end, end_size, 1, prn_stream);
1957dd7cddfSDavid du Colombier 
1967dd7cddfSDavid du Colombier 	return 0;
1977dd7cddfSDavid du Colombier }
1987dd7cddfSDavid du Colombier 
1997dd7cddfSDavid du Colombier /* Print an LBP-8 page. */
2007dd7cddfSDavid du Colombier private int
lbp8_print_page(gx_device_printer * pdev,FILE * prn_stream)2017dd7cddfSDavid du Colombier lbp8_print_page(gx_device_printer *pdev, FILE *prn_stream)
2027dd7cddfSDavid du Colombier {	return can_print_page(pdev, prn_stream, lbp8_init, sizeof(lbp8_init),
2037dd7cddfSDavid du Colombier 			      lbp8_end, sizeof(lbp8_end));
2047dd7cddfSDavid du Colombier }
2057dd7cddfSDavid du Colombier 
2067dd7cddfSDavid du Colombier /* Print a LIPS III page. */
2077dd7cddfSDavid du Colombier private int
lips3_print_page(gx_device_printer * pdev,FILE * prn_stream)2087dd7cddfSDavid du Colombier lips3_print_page(gx_device_printer *pdev, FILE *prn_stream)
2097dd7cddfSDavid du Colombier {	return can_print_page(pdev, prn_stream, lips3_init, sizeof(lips3_init),
2107dd7cddfSDavid du Colombier 			      lips3_end, sizeof(lips3_end));
2117dd7cddfSDavid du Colombier }
212