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