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