1 #include "gdevprn.h"
2 /* Copyright (C) 1989-1994, 1998, 1999 Aladdin Enterprises.  All rights reserved.
3    This file is part of GNU Ghostscript.
4 
5   GNU Ghostscript is distributed in the hope that it will be useful, but
6   WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility to
7   anyone for the consequences of using it or for whether it serves any
8   particular purpose or works at all, unless he says so in writing.  Refer to
9   the GNU General Public License for full details.
10 
11   Everyone is granted permission to copy, modify and redistribute GNU
12   Ghostscript, but only under the conditions described in the GNU General
13   Public License.  A copy of this license is supposed to have been given to
14   you along with GNU Ghostscript so you can know your rights and
15   responsibilities.  It should be in a file named COPYING.  Among other
16   things, the copyright notice and this notice must be preserved on all
17   copies.
18 
19   Aladdin Enterprises is not affiliated with the Free Software Foundation or
20   the GNU Project.  GNU Ghostscript, as distributed by Aladdin Enterprises,
21   does not depend on any other GNU software.
22 */
23 /*
24  * $Id: gdevlx7.c,v 1.5 2002/08/03 03:08:26 tillkamppeter Exp $
25  * Lexmark 7000 ink-jet  "GDI" printer driver
26  *   * just started...
27  *
28  * Henryk Paluch paluch@bimbo.fjfi.cvut.cz
29  * http://bimbo.fjfi.cvut.cz/~paluch/l7kdriver/
30  *
31  * BIG thanks to Peter B. West that discovered and described many
32  * "funny" things of the Lexmark 5xxx protocol.
33  *
34  * THIS GHOSTSCRIPT DRIVER USES MANY THINGS FROM
35  * STEPHEN'S LEXMARK 5700 GHOSCRIPT DRIVER:
36  *
37  * Stephen Taylor  setaylor@ma.ultranet.com  staylor@cs.wpi.edu
38  * http://www.ultranet.com/~setaylor/papers.htm
39  *
40  * ALL INTRODUCED BUGS ARE PROPERTY OF HENRYK :-)
41  */
42 
43 /* our private driver constants */
44    /* Lexmark 7xxx,5xxx swipe height of Black & White cartridge */
45 #define LX7_BSW_H 208
46 
47    /* Lexmark 7xxx,5xxx swipe height of Colour cartridge */
48 #define LX7_CSW_H 192
49 
50   /* maximum data bytes per packet: 13 * 2 = 26
51    * 13 - compression bits, 2 = data words
52    */
53 #define LX7_MAX_SWBYTES 26
54  /* 13 * 2 databytes + 2 bytes for header = 28 bytes */
55 #define LX7_MAX_PACKET  28
56 #define LX7_MAX_SWWORDS 13
57 
58 /* interlaced printing for 1200dpi - vertical offset of lines */
59 /* they must be odd. The sum must be 208 */
60 /* these are for Ink Jet distance */
61 #define LXH_SKIP1   99
62 #define LXH_SKIP2   109
63 /* doubled values for real paper shift */
64 #define LXH_DSKIP1 (LXH_SKIP1*2-1)
65 #define LXH_DSKIP2 (LXH_SKIP2*2+1)
66 /* Lexmark 7000 prologue */
67 /* 1st time initialization - INIT1 is common for all modes */
68 #define LX7_INIT1 0x1b,0x2a,0x6d,0x00,0x40,0x10,0x03,0x10,0x11
69 
70 /* LX_INIT2 - for 1200dpi - currently not needed */
71 #define LX7_INIT2 0xa5,0x00,0x06,0x50,0x03,0x03,0xc0,0x0f,0x0f, \
72                   0xa5,0x00,0x03,0x50,0x04,0x05, \
73 		  0xa5,0x00,0x03,0x50,0x04,0x06, \
74 		  0xa5,0x00,0x03,0x50,0x04,0x07, \
75 		  0xa5,0x00,0x03,0x50,0x04,0x08, \
76 		  0xa5,0x00,0x04,0x50,0x04,0x0c,0x00, \
77 		  0xa5,0x00,0x04,0x50,0xe0,0x0b,0x03
78 /* LX_INIT3 - after 1200dpi prologue, or immediately after INIT1
79  * in other modes
80  */
81 #define  LX7_INIT3 0xa5,0x00,0x0b,0x50,0xe0,0x41,0x00,\
82                         0x00,0x00,0x00,0x00,0x00,0x00,0x02,\
83 		   0xa5,0x00,0x06,0x50,0x05,0x00,0x00,0x80,0x00, \
84                    0xa5,0x00,0x04,0x50,0x04,0x0c,0x00
85 /* this is used also for new page prologue ... */
86 #define LX7_INIT4 0x1b,0x2a,0x07,0x73,0x30
87 #define LX7_INIT5 0x1b,0x2a,0x07,0x63
88 /* mysterious reinitialization ???? */
89 #define LX7_INIT6 0x1b,0x2a,0x6d,0x00,0x42,0x00,0x00
90 #define LX7_INIT7 0xa5,0x00,0x05,0x40,0xe0,0x80,0x07,0x08
91 
92 static byte lx7_fullinit[]={LX7_INIT1, /*LX7_INIT2, LX7_INIT3,*/ LX7_INIT4,
93                              LX7_INIT5, LX7_INIT6};
94 static byte lx7_pageinit[]={LX7_INIT4, LX7_INIT4, LX7_INIT5, LX7_INIT6};
95 
96 #ifndef MIN
97 #define MIN(x,y) ( (x) < (y) ? (x) : (y))
98 #endif
99 #ifndef MAX
100 #define MAX(x,y) ( (x) > (y) ? (x) : (y))
101 #endif
102 
103 /* The procedure descriptors */
104 /* declare functions */
105 static dev_proc_print_page(lxmgen_print_page);
106 static dev_proc_get_params(lxm_get_params);
107 static dev_proc_put_params(lxm_put_params);
108 
109 /* set up dispatch table.  I follow gdevdjet in using gdev_prn_output_page */
110 static const gx_device_procs lxm7000m_procs =
111     prn_params_procs(gdev_prn_open, gdev_prn_output_page, gdev_prn_close,
112                      lxm_get_params, lxm_put_params);
113 
114 /* The device descriptors */
115 
116 /* define a subclass with useful state in it. */
117 typedef struct lxm_device_s { /* a sub-class of gx_device_printer */
118     gx_device_common;
119     gx_prn_device_common;
120     int headSeparation;
121     byte *fullInit;
122     int  nfullInit;
123     byte *pageInit;
124     int npageInit;
125     int printertype;
126 } lxm_device;
127 
128 /* Lexmark types (faster lookup than strcmp("lex7000",...) ...
129  * stored in 'printertype' variable
130  */
131 
132 #define LXT_7000 0
133 #define LXT_5700 1
134 #define LXT_3200 2
135 #define LXT_2050 3
136 
137 /* resolution map - used by "associate" arrays - do not modify */
138 #define LXR_300  0
139 #define LXR_600  1
140 #define LXR_1200 2
141 
142 lxm_device far_data gs_lex7000_device = {
143     prn_device_std_body(lxm_device, lxm7000m_procs, "lex7000",
144 	DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
145 	/* total width & height in 10x " - A4 or letter compiled in.
146 	 * may be overriden by -sPAPERSIZE=a4 of -sPAPERSIZE=letter
147 	 */
148 	600, 600,	/* x dpi, y dpi */
149 	0.0, 0.1, 0.3, 0.1,			/* margins */
150 	/* unlike most other Ink printers Lexmark is able to print at
151 	 * whole top and bottom of paper :-)
152 	 */
153 	1, lxmgen_print_page),
154 	/* 1 = bits per color, generic routines*/
155 
156     /* our extended attributes follow...*/
157     16,   /* default headSeparation value */
158     lx7_fullinit,
159     sizeof(lx7_fullinit),
160     lx7_pageinit,
161     sizeof(lx7_pageinit),
162     LXT_7000
163 };
164 
165 lxm_device far_data gs_lex5700_device = {
166     prn_device_std_body(lxm_device, lxm7000m_procs, "lex5700",
167 	DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
168 	/* total width & height in 10x " - A4 or letter compiled in.
169 	 * may be overriden by -sPAPERSIZE=a4 of -sPAPERSIZE=letter
170 	 */
171 	600, 600,	/* x dpi, y dpi */
172 	0.1, 0.1, 0.1, 0.0,			/* margins */
173 	/* unlike most other Ink printers Lexmark is able to print at
174 	 * whole top and bottom of paper :-)
175 	 */
176 	1, lxmgen_print_page),
177 	/* 1 = bits per color, generic routines*/
178 
179     /* our extended attributes follow...*/
180     16,   /* default headSeparation value */
181     lx7_fullinit,
182     sizeof(lx7_fullinit),
183     lx7_pageinit,
184     sizeof(lx7_pageinit),
185     LXT_5700
186 };
187 
188 lxm_device far_data gs_lex3200_device = {
189     prn_device_std_body(lxm_device, lxm7000m_procs, "lex3200",
190 	DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
191 	/* total width & height in 10x " - A4 or letter compiled in.
192 	 * may be overriden by -sPAPERSIZE=a4 of -sPAPERSIZE=letter
193 	 */
194 	600, 600,	/* x dpi, y dpi */
195 	0.1, 0.1, 0.1, 0.0,			/* margins */
196 	/* unlike most other Ink printers Lexmark is able to print at
197 	 * whole top and bottom of paper :-)
198 	 */
199 	1, lxmgen_print_page),
200 	/* 1 = bits per color, generic routines*/
201 
202     /* our extended attributes follow...*/
203     16,   /* default headSeparation value */
204     lx7_fullinit,
205     sizeof(lx7_fullinit),
206     lx7_pageinit,
207     sizeof(lx7_pageinit),
208     LXT_3200
209 };
210 
211 lxm_device far_data gs_lex2050_device = {
212     prn_device_std_body(lxm_device, lxm7000m_procs, "lex2050",
213 	DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
214 	/* total width & height in 10x " - A4 or letter compiled in.
215 	 * may be overriden by -sPAPERSIZE=a4 of -sPAPERSIZE=letter
216 	 */
217 	600, 600,	/* x dpi, y dpi */
218 	0.1, 0.1, 0.1, 0.0,			/* margins */
219 	/* unlike most other Ink printers Lexmark is able to print at
220 	 * whole top and bottom of paper :-)
221 	 */
222 	1, lxmgen_print_page),
223 	/* 1 = bits per color, generic routines*/
224 
225     /* our extended attributes follow...*/
226     16,   /* default headSeparation value */
227     lx7_fullinit,
228     sizeof(lx7_fullinit),
229     lx7_pageinit,
230     sizeof(lx7_pageinit),
231     LXT_2050
232 };
233 
234 
235 
236 
237 #define get_lx_type(pdev) \
238   (((lxm_device*)pdev)->printertype)
239 
240 
241 
242 /* ------ Local Lexmark printer utilities ------*/
243 
244 #define LX_LINE_EMPTY(buf,len) \
245    (buf[0]==0 && memcmp(buf,buf+1,len-1)==0)
246 
247 static byte ofs8[8]={128,64,32,16,8,4,2,1};
248 /* Lexmark 5xxx, 7xxx page eject */
lex_eject(FILE * out)249 static void lex_eject(FILE *out)
250 {
251    byte buf[4]={0x1b,0x2a,0x7,0x65};
252 #ifdef DEBUG
253    dprintf("Sending page eject.\n");
254 #endif
255    fwrite(buf,sizeof(buf),1,out);
256 }
257 
258 /*
259  * shift paper (skip empty lines)
260  * offset is in pixels in 1200 dpi resolution, i. e.,
261  * 384 for 192 pixels or
262  * 416 for 208 pixels etc...
263  */
paper_shift(FILE * out,int offset)264 static void paper_shift(FILE *out,int offset)
265 {
266    byte buf[5]={0x1b,0x2a,0x3,0x0,0x0};
267    buf[3]=(byte)(offset >> 8);   /* just to be endian safe we don't use short */
268    buf[4]=(byte)(offset & 0xFF);
269 #ifdef DEBUG
270    dprintf3("paper_shift() %d 1200dpi = %d 600dpi = %d 300dpi pixels\n",
271 	 offset,offset/2,offset/4);
272 #endif
273    fwrite(buf,sizeof(buf),1,out);
274 }
275 
276 /* return coordinate of leftmost pixel (in pixels) */
leftmost_pixel(byte * buf,int bytelen)277 static int leftmost_pixel(byte *buf, int bytelen)
278 {
279    int i;
280    byte *r=buf;
281    byte b;
282    if (LX_LINE_EMPTY(buf,bytelen)) /* catch empty line */
283       return bytelen*8-1;
284 
285    while( *r==0 && bytelen>0)
286    {
287       r++;
288       bytelen--;
289    }
290 
291    b= *r;
292    for(i=0;i<8;i++)
293       if ( ( b & ofs8[i])!=0)
294 	 break;
295    return  (r-buf)*8+i;
296 }
297 
298 /* return coordinate of rightmost pixel (in pixels) */
rightmost_pixel(byte * buf,int bytelen)299 static int rightmost_pixel(byte *buf, int bytelen)
300 {
301    int i;
302    byte *r=buf+(bytelen-1);
303    byte b;
304    if (LX_LINE_EMPTY(buf,bytelen)) /* catch empty line */
305       return 0;
306 
307    while( *r==0 && bytelen>1)
308    {
309       r--;
310       bytelen--;
311    }
312 
313    b= *r;
314    for(i=7;i>=0;i--)
315       if ( ( b & ofs8[i])!=0)
316 	 break;
317    return  (r-buf)*8+i;
318 }
319 
320 /* find leftmost and rightmost pixel in whole pass
321  * buf        - pixel buffer
322  * bytelen    - width of line (in bytes)
323  * bufheight  - buffer height (pixels)
324  * interlaced - if even lines have different horizontal offset
325  *              than odd lines
326  * intershift - horizontal offset between even/odd lines
327  * leftmost,
328  *  rightmost - output
329  */
find_lr_pixels(byte * buf[],int bytelen,int bufheight,int interlaced,int intershift,int * leftmost,int * rightmost)330 static void find_lr_pixels(byte *buf[],int bytelen,int bufheight,
331       int interlaced, int intershift,
332       int *leftmost, int *rightmost)
333 {
334    int maxright=bytelen*8-1;
335    int left=maxright;
336    int right=0;
337    int i;
338 
339    for(i=0;i<bufheight;i++)
340    {
341       int ltmp,rtmp;
342       ltmp=leftmost_pixel(buf[i],bytelen);
343       rtmp=rightmost_pixel(buf[i],bytelen);
344 #if 0
345       dprintf3("buf[%d]: leftmost %d, rightmost %d\n",
346 	    i,ltmp,rtmp);
347 #endif
348       if (interlaced && (i & 1)==1) /* interlaced && line is odd */
349       {
350 	 ltmp=MAX((ltmp-intershift),0);
351 	 rtmp=MIN((rtmp+intershift),maxright);
352 	 if (ltmp==maxright)
353 	    ltmp--; /* print at least one pixel to avoid races ?? */
354       }
355       if (ltmp<left)
356 	 left=ltmp;
357       if (rtmp>right)
358 	 right=rtmp;
359    }
360 
361    *leftmost  = left;
362    *rightmost = right;
363    return;
364 }
365 
366 
367 /* ------ Driver procedures ------ */
368 
369 /*** THIS NEED TO BE REWORKED SOON ***/
370 static const int LEFT_MARGIN=50;
371 static const int VERTSIZE=LX7_BSW_H;
372 /* offsets to print line sequence (defined in outbuf)
373  */
374 static const int IDX_SEQLEN=5;
375 static const int IDX_HORRES=8;
376 static const int IDX_PACKETS=13;
377 static const int IDX_5700DIF=12;
378 static const int IDX_HSTART=15;
379 static const int IDX_HEND=17;
380 static const int IDX_DATA=26;
381 static const int IDX_CARTRIDGE=10;
382 
383 #define DIV8(x) ( (x) >> 3 )
384 #define MOD8(x) ( (x) & 0x7 )
385 #define DIV16(x) ( (x) >> 4 )
386 #define MOD16(x) ( (x) & 0xf )
387    /* too large buffer may hang the printer ?! */
388 #define OUT_BUF_SIZE 256000
389 /* most important print packet
390  * see lexmarkprotocol.txt for more information */
391 /*          length of complete sequence ---  vvvvvvvvv */
392 /* this is template now. Outbuf is allocated and initialized
393  * by lxmgen_print_page() to avoid large static array
394  * in gs binary
395  */
396 static byte outb[]={0x1B,0x2A,0x04,0x00,0x00,0xFF,0xFF,
397    /* number of packets ----     vvvvvvvvv */
398    0x00,0x02,0x01,0x01,0x1A,0x11,0xFF,0xFF,
399    /* horiz start, horiz end: packets = (horiz end - horiz start) +1 */
400    0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x22,0x33,0x44,0x55,0x01};
401 
402 #define BITSTART12 4096
403 
print_cols(FILE * prn_stream,gx_device_printer * pdev,byte * outbuf,int left,int right,int vstart,int vend,byte * buf[],int width,int LR_SHIFT)404 static int print_cols(FILE *prn_stream,gx_device_printer *pdev,
405       byte *outbuf,
406       int left,int right,int vstart, int vend,byte *buf[],
407       int width,int LR_SHIFT)
408 {
409    unsigned char mask[8]={128,64,32,16,8,4,2,1};
410    unsigned int  mask16[16]={0x8000,0x4000,0x2000,0x1000,
411                              0x0800,0x0400,0x0200,0x0100,
412 			     0x0080,0x0040,0x0020,0x0010,
413 			     0x0008,0x0004,0x0002,0x0001};
414    int l8,r8,packets;
415    byte *p=outbuf+IDX_DATA;
416    int clen;
417    int i,k;
418    unsigned int vbuf[LX7_MAX_SWWORDS];
419    int vi;
420    unsigned char *vp,*vp2;
421    int smask,smask2;
422 
423    l8=left+LEFT_MARGIN;
424    r8=right+LEFT_MARGIN;
425 
426    packets=r8-l8+1;
427 
428 
429    outbuf[IDX_PACKETS]  =(unsigned char)(packets >> 8);
430    outbuf[IDX_PACKETS+1]=(unsigned char)(packets & 0xFF);
431    outbuf[IDX_HSTART]   =(unsigned char)(l8 >> 8);
432    outbuf[IDX_HSTART+1] =(unsigned char)(l8 & 0xFF);
433    outbuf[IDX_HEND]     =(unsigned char)(r8 >> 8);
434    outbuf[IDX_HEND+1]   =(unsigned char)(r8 & 0xFF);
435 
436    outbuf[IDX_5700DIF]= ( get_lx_type(pdev)==LXT_7000 ? 0x11 : 0x1 );
437    /* fill columns */
438    for(i=left;i<=right;i++)
439    {
440       int rle1size,rle2size;
441       int bits=0;
442       byte *tbits;
443 
444       if ( (p-outbuf)>=OUT_BUF_SIZE-28 ) /* 13*2+2 */
445       {
446 	 return -1;
447       }
448       tbits=p;
449       p+=2; /* add room for RLE packet (2 bytes) */
450 
451       /* clear buffer of vertical points */
452       memset(vbuf,0,sizeof(vbuf));
453 
454       smask=mask[MOD8(i)];
455       smask2=mask[MOD8(i+LR_SHIFT)];
456 
457       vi=vstart*2; /* vbuf index in pixels (not array index) */
458       for(k=vstart;k<vend;k++)
459       {
460 	 vp=buf[k*2]+DIV8(i);
461 	 /* vp points to current column for Left Ink */
462 	 vp2=buf[k*2+1]+DIV8(i+LR_SHIFT);
463 	 /* vp2 for right Ink jets */
464 	 if ( ( vp[0] & smask) != 0)
465 	    vbuf[DIV16(vi)] |= mask16[MOD16(vi)];
466 	 vi++;
467 	 if (i+LR_SHIFT<width*8)
468 	 {
469 	    if ( (vp2[0] & smask2) !=0 )
470 	       vbuf[DIV16(vi)] |=mask16[MOD16(vi)];
471 	 }
472 	 vi++;
473       }
474 
475       /* every packet contains 13 info bits
476        * 1 = 8x left white, 8x right white
477        * 0 = 2 data bytes follow (8 bits left, 8 bits right)
478        */
479 
480       for(k=0;k<LX7_MAX_SWWORDS;k++)
481       {
482 	 unsigned int t=vbuf[k];
483 
484 	 bits= (bits>>1);
485 	 if (t==0) /* packet is empty */
486 	 {
487 	    bits+=BITSTART12;
488 	 }
489 	 else
490 	 {
491 	    *(p++)=(t >> 8) & 0xFF;
492 	    *(p++)=(t & 0xFF);
493 	 }
494       }
495      tbits[1]=(unsigned char)( (bits) & 0xFF);
496      *tbits  =(unsigned char)( ((bits>>8) & 0x1f) | 0x20 );
497      rle1size=(p-tbits);
498 #if 0
499      dprintf1("RLE1(%d), ",rle1size);
500 #endif
501      if (rle1size>6) /* try to use RLE2 compression for larger packets */
502      {
503 	byte ob[LX7_MAX_PACKET];
504 	unsigned int lastword=0x8FFF; /* impossible value */
505 	int byts=0;
506 	byte *pp=ob+2;
507 
508 	memset(ob,0,LX7_MAX_PACKET);
509 	for(k=0;k<LX7_MAX_SWWORDS;k++)
510 	{
511 	 unsigned int t=vbuf[k];
512 
513 	 byts= (byts>>1);
514 	 if (t==lastword)
515 	 {
516 	   byts+=BITSTART12;
517 	 }
518 	 else
519 	 {
520 	    *(pp++)=(t >> 8) & 0xFF;
521 	    *(pp++)=(t & 0xFF);
522 	    lastword=t;
523 	 }
524 	}
525      ob[1]=(unsigned char)( (byts) & 0xFF);
526      ob[0]=(unsigned char)( (byts>>8) & 0x1f );
527      rle2size=(pp-ob);
528 #if 0
529      dprintf1("RLE2(%d), ",rle2size);
530 #endif
531 
532      if (rle1size>rle2size)
533      {
534 #if 0
535 	dprintf2("\n**RLE2 WIN** %d > %d \n",rle1size,rle2size);
536 	dprintf("\nUsing RLE2 compression\n");
537 #endif
538 	memcpy(tbits,ob,rle2size);
539 	p=tbits+rle2size;
540      }
541      }
542    }
543 
544 
545    /* ------------ */
546    clen=p-outbuf;
547    outbuf[IDX_SEQLEN-1]  =(unsigned char)(clen >> 16);
548    outbuf[IDX_SEQLEN]  =(unsigned char)(clen >> 8);
549    outbuf[IDX_SEQLEN+1]=(unsigned char)(clen & 0xFF);
550    fwrite(outbuf,1,clen,prn_stream);
551 #ifdef DEBUG
552    dprintf1("\nSent %d data bytes\n",clen);
553 #endif
554    return 0;
555 }
556 
557 
558 /*** THIS NEED TO BE REWORKED SOON - END ***/
559 
560 /* Send the page to the printer. */
561 /* Lexmark generic print page routine */
562 static int
lxmgen_print_page(gx_device_printer * pdev,FILE * prn_stream)563 lxmgen_print_page(gx_device_printer *pdev, FILE *prn_stream)
564 {
565    int pheight=pdev->height; /* page height (pixels) */
566 #ifdef DEBUG
567    int pwidth=pdev->width;   /* page width (pixels) */
568 #endif
569    int bwidth=gdev_mem_bytes_per_scan_line((gx_device*)pdev);
570    /* page width (bytes) */
571 
572    int prest=pheight;        /* Page Rest number of lines to remain ... */
573    int brest;                /* Buffer rest for buffer copy */
574    int skipline=208;           /* number of empty lines, e.g. skip them */
575    /* we need to move paper under cartridge..
576     * about 208 pixels... */
577    byte *pbuf;               /* printer buffer - dynamic allocation */
578    byte *ppbuf,*ppbuf2;              /* pointer returned by _prn_get_bits() */
579    byte *outbuf;             /* output buffer - used by print_cols(),
580 			      * but allocated here, to avoid unnecessary
581 			      * de & allocation
582 			      */
583    int pbufsize,rpbufsize;             /* printer buffer size */
584    int hres,vres;
585    int interlaced;
586    int lr_shift=((lxm_device*)pdev)->headSeparation;
587    byte *obp[LX7_BSW_H];    /* pointers to buffer lines */
588    int bufHeight;
589 
590    /* initiate vres mapping variable */
591    vres=LXR_600; /* default vertical resolution */
592    if (pdev->y_pixels_per_inch<301.0)
593       vres=LXR_300;
594    if (pdev->y_pixels_per_inch>=601.0)
595       vres=LXR_1200;
596 
597    bufHeight=LX7_BSW_H;
598    if (vres==LXR_300)
599    {
600       bufHeight /= 2;
601       skipline  /= 2;
602    }
603    if (vres==LXR_1200)
604    {
605       bufHeight *= 2;
606       skipline *=2;
607    }
608 
609    pbufsize = bwidth * bufHeight;
610    rpbufsize = bwidth * (bufHeight+1);
611 #ifdef DEBUG
612    dprintf1("[%s] print_page() start\n",pdev->dname);
613    dprintf1("Is first page? %d\n",gdev_prn_file_is_new(pdev));
614    dprintf1("Head Separation %d\n",((lxm_device*)pdev)->headSeparation);
615    dprintf2("Width %d pixels, %d bytes\n",pwidth,bwidth);
616    dprintf1("Height %d pixels\n",pheight);
617    dprintf1("One pass buffer size %d\n",pbufsize);
618    dprintf1("Output buffer size %d\n",OUT_BUF_SIZE);
619    dprintf2("Current resolution is %f width x %f height dpi\n",
620 	 pdev->x_pixels_per_inch, pdev->y_pixels_per_inch );
621 #endif
622    pbuf = (byte *)gs_malloc(gs_lib_ctx_get_non_gc_memory_t(), rpbufsize, 1, "lxmgen_print_page(pbuf)");
623    if (pbuf == NULL)
624       return_error(gs_error_VMerror);
625 
626    outbuf = (byte *)gs_malloc(gs_lib_ctx_get_non_gc_memory_t(), OUT_BUF_SIZE, 1, "lxmgen_print_page(outbuf)");
627    if (outbuf == NULL)
628    {
629       gs_free(gs_lib_ctx_get_non_gc_memory_t(), (char*)pbuf,pbufsize, 1, "lxmgen_print_page(pbuf)");
630       return_error(gs_error_VMerror);
631    }
632    /* initialize begin of outbuf ... */
633    memcpy(outbuf,outb,sizeof(outb));
634 
635    /* zero fake line (used for non-interlaced resolutions etc)...*/
636    memset(pbuf+pbufsize,0,bwidth);
637 
638 
639    /* initiate hres mapping variable */
640    hres=LXR_600; /* default horizontal resolution */
641    if (pdev->x_pixels_per_inch<301.0)
642       hres=LXR_300;
643    if (pdev->x_pixels_per_inch>=601.0)
644       hres=LXR_1200;
645    /* adjust headSeparation according to horizontal resolution */
646    if (hres==LXR_300)
647       lr_shift >>=1;
648    if (hres==LXR_1200)
649       lr_shift <<=1;
650 
651    interlaced=1; /* all resolutions except vert 300dpi are interlaced*/
652 
653    /* adjust horizontal motor speed for current resolution */
654    if (get_lx_type(pdev)==LXT_7000 || get_lx_type(pdev)==LXT_5700)
655    {
656       byte mspeed[3]={1,2,5}; /* LXR_300=0, LXR_600=1, LXR_1200=2 */
657       outbuf[IDX_HORRES]=mspeed[hres];
658    }
659 
660 #ifdef DEBUG
661    dprintf1("Choosed motor speed %d\n",(int)outbuf[IDX_HORRES]);
662 #endif
663 
664 
665    if(vres==LXR_600)
666    {
667       int i;
668       for(i=0;i<LX7_BSW_H;i++)
669 	 obp[i]=pbuf+(i*bwidth);
670    }
671 
672    if(vres==LXR_300)
673    {
674       int i;
675       for(i=0;i<LX7_BSW_H;i++)
676 	 if ( (i & 1)!=0)
677 	    obp[i]=pbuf+pbufsize; /* odd line is empty for 300dpi */
678 	 else
679 	    obp[i]=pbuf+(i/2*bwidth);
680    }
681 
682 
683 
684 
685    if(gdev_prn_file_is_new(pdev))
686       fwrite(((lxm_device*)pdev)->fullInit,
687 	    ((lxm_device*)pdev)->nfullInit,
688 	    1,prn_stream);
689    else
690       fwrite(((lxm_device*)pdev)->pageInit,
691 	    ((lxm_device*)pdev)->npageInit,
692 	    1,prn_stream);
693 
694 
695    while(prest>0)
696    {
697       int i;
698       int leftmost;  /* position of leftmost pixel */
699       int rightmost; /* position of rightmost pixel */
700       int c1200;     /* testing empty line for 1200dpi... */
701 
702       /* copy one line & test for all zeroes */
703       gdev_prn_get_bits(pdev, pheight-prest, /* current line No. */
704 	    pbuf,                /* our buffer if needed */
705 	    &ppbuf);             /* returns pointer to scanline
706 				  * either our buffer or
707 				  * gs internal data buffer
708 				  */
709       if (vres==LXR_1200 && (pheight-prest+LXH_DSKIP1<pheight))
710       {
711 	 gdev_prn_get_bits(pdev, pheight-prest+LXH_DSKIP1,
712 	                          /* current line No. */
713 	    pbuf+bwidth,                /* our buffer if needed */
714 	    &ppbuf2);
715        c1200=LX_LINE_EMPTY(ppbuf2,bwidth);
716       }
717       else
718 	 c1200=1;
719 
720       /* test for empty line (nice Stephen's trick w/ memcmp() :-) */
721       if (LX_LINE_EMPTY(ppbuf,bwidth) && c1200)
722       {  /* line empty */
723 	 prest--;
724 	 skipline++;
725 	 continue; /* Loop thgrough the while(prest>0) ... */
726       }
727 
728       /* 1pass printing for 300 & 600 dpi */
729       /* 2pass printing for 1200dpi */
730       for(i=0;i<(vres==LXR_1200 ? 2 : 1);i++)
731       {
732 	 /* skip empty lines on paper, if any */
733 	 if (skipline>0)
734 	 {
735 	    int mult[3]={4,2,1}; /* multiply: 300dpi=4, 600dpi=2, 1200dpi=1 */
736 	    paper_shift(prn_stream,skipline*mult[vres]);
737 	    skipline=0;
738 	 }
739 
740 	 /* for 1200dpi we need to setup interlaced buffer entries */
741 	 if (vres==LXR_1200)
742 	 {
743 	    int j;
744 	    for(j=0;j<LX7_BSW_H;j++)
745 	       if ( (j & 1)!=i) /* i==0 for 1st pass i==1 for 2nd pass */
746 		  obp[j]=pbuf+pbufsize; /* "odd" line is empty for 300dpi */
747 	       else
748 		  obp[j]=pbuf+(j*2*bwidth);
749 	 }
750 
751 
752 	 /* copy remaining lines to buffer */
753 	 brest=MIN(bufHeight,prest);
754 
755 #ifdef DEBUG
756 	 dprintf2("Copying %d lines to buffer, vertpos %d\n",brest,
757 	       pheight-prest);
758 #endif
759 	 gdev_prn_copy_scan_lines(pdev,pheight-prest,pbuf,pbufsize);
760 	 /* zero unused lines (on bottom of page) */
761 	 if (bufHeight-brest>0)
762 	    memset(pbuf+(brest*bwidth),0,(bufHeight-brest)*bwidth);
763 
764 	 /* look for leftmost and rightmost pixels */
765 	 find_lr_pixels(obp,bwidth,LX7_BSW_H,interlaced,
766 	       ((lxm_device*)pdev)->headSeparation,
767 	       &leftmost,&rightmost);
768 #ifdef DEBUG
769 	 dprintf2("Leftmost pixel %d, rightmost pixel %d\n",
770 	       leftmost,rightmost);
771 #endif
772 
773 	 /* print the data */
774 	 if (leftmost<rightmost)
775 	 if (print_cols(prn_stream,pdev,outbuf,leftmost,rightmost,
776 		  0,VERTSIZE/2,obp,bwidth,lr_shift)==-1)
777 	 {
778 	    print_cols(prn_stream,pdev,outbuf,leftmost,rightmost,0,
779 		  VERTSIZE/4,obp,bwidth,lr_shift);
780 
781 	    print_cols(prn_stream,pdev,outbuf,leftmost,rightmost,
782 		  VERTSIZE/4,VERTSIZE/2,
783 		  obp,bwidth,lr_shift);
784 
785 #ifdef DEBUG
786 	    dprintf("Overflow workaround used\n");
787 #endif
788 	 }
789 
790 	 if (vres!=LXR_1200)
791 	 {
792 	    skipline=brest; /* skip already printed lines */
793 	 }
794 	 else
795 	 {
796 	    skipline+=( i==0 ? LXH_DSKIP1 : LXH_DSKIP2 );
797 	 }
798          prest-=skipline; /* decrease number of remaining lines */
799 	 if (prest<=0)
800 	    break;
801       }
802    }
803 
804    /* eject page */
805    lex_eject(prn_stream);
806    gs_free(gs_lib_ctx_get_non_gc_memory_t(), (char*)pbuf,rpbufsize, 1, "lxmgen_print_page(pbuf)");
807    gs_free(gs_lib_ctx_get_non_gc_memory_t(), (char*)outbuf,OUT_BUF_SIZE, 1, "lxmgen_print_page(outbuf)");
808 
809 #ifdef DEBUG
810    dprintf1("[%s] print_page() end\n",pdev->dname);
811 #endif
812    return 0;
813 }
814 
815    static int
lxm_get_params(gx_device * pdev,gs_param_list * plist)816 lxm_get_params(gx_device *pdev, gs_param_list *plist)
817 {
818     lxm_device* const ldev = (lxm_device*)pdev;
819     int code = gdev_prn_get_params(pdev, plist);
820 
821     if ( code < 0 ) return code;
822     code = param_write_int(plist,
823 			   "HeadSeparation",
824 			   (int *)&(ldev->headSeparation));
825 
826     return code;
827 }
828 
829 /* put_params is supposed to check all the parameters before setting any. */
830 static int
lxm_put_params(gx_device * pdev,gs_param_list * plist)831 lxm_put_params(gx_device *pdev, gs_param_list *plist)
832 {
833     int ecode;
834     lxm_device* const ldev = (lxm_device*)pdev;
835     int trialHeadSeparation=ldev->headSeparation;
836     int code = param_read_int(plist, "HeadSeparation", &trialHeadSeparation);
837 
838     if ( trialHeadSeparation < 1 || trialHeadSeparation > 32 )
839 	param_signal_error(plist, "HeadSeparation", gs_error_rangecheck);
840     /* looks like param_signal_error is not expected to return */
841     ecode = gdev_prn_put_params(pdev, plist);	/* call super class put_params */
842     if ( code < 0 ) return code;
843     if (ecode < 0) return ecode;
844 
845     /* looks like everything okay; go ahead and set headSeparation */
846     ldev->headSeparation = trialHeadSeparation;
847     if ( code == 1) return ecode; /* I guess this means there is no "HeadSeparation" parameter */
848     return 0;
849 }
850 
851