1 /*
2 * Lexmark 3200 Color Jetprinter driver
3 *
4 * version 0.4.1
5 *
6 * Copyright 2000 by Daniel Gordini (dgordin@tin.it)
7 *
8 * --------------------------------------------------------------------
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 * --------------------------------------------------------------------
25 *
26 * This driver is almost 100% original code but it is based
27 * on protocol information partly discovered by Andrew Onifer III
28 * (http://www.mindspring.com/~aonifer) and Peter B. West
29 * (http://www.powerup.com.au/~pbwest) that were used as a starting
30 * base for the reverse-engineering of the protocol.
31 *
32 * Please mail me bug reports, comments and suggestions.
33 *
34 * Don't forget to read the release notes before installing !!
35 *
36 */
37
38 #include "gdevprn.h"
39 #include "gsparams.h"
40
41 #ifndef TRUE
42 #define TRUE 1
43 #endif
44
45 #ifndef FALSE
46 #define FALSE 0
47 #endif
48
49 /* Prototypes for public routines */
50 static dev_proc_map_rgb_color(lxm3200_map_rgb_color);
51 static dev_proc_map_color_rgb(lxm3200_map_color_rgb);
52 static dev_proc_print_page(lxm3200_print_page);
53 static dev_proc_get_params(lxm3200_get_params);
54 static dev_proc_put_params(lxm3200_put_params);
55 static dev_proc_open_device(lxm3200_open);
56
57 /* Prototypes for internal routines */
58 static void freeresources(gx_device *pdev);
59 static byte calccheck8(byte *data);
60 static void outputepilogue(void);
61 static void skiplines(int skipcol, int skipin);
62 static void fillheader(int head, int numcol, int firstcol, int bytes);
63 static void finalizeheader(int vskip, int newhead);
64 static void convbuf(int head, int numcols, int firstcol);
65 static void encode_bw_buf(void);
66 static void encode_col_buf(int head);
67 static int fill_mono_buffer(int vline);
68 static int init_buffer(void);
69 static int qualify_buffer(void);
70 static int roll_buffer(void);
71 static void calclinemargins(byte *data, int mask, int *left, int *right);
72 static void calcbufmargins(int head);
73 static void print_color_page(void);
74 static void print_mono_page(void);
75 static void print_photo_page(void);
76
77 /* Codes for the color indexes. */
78 #define WHITE 0x00 /* Pure white */
79 #define MAGENTA 0x01 /* Standard magenta */
80 #define CYAN 0x02 /* Standard cyan */
81 #define YELLOW 0x04 /* Standard yellow */
82 #define LIGHTCYAN 0x10 /* Light cyan (photo mode) */
83 #define LIGHTMAGENTA 0x20 /* Light magenta (photo mode) */
84 #define BLACK 0x40 /* Pure black */
85
86 /* Modes for rendering: used by the common procedures to
87 * discriminate from mono to color and photo modes.
88 */
89 #define LXM3200_M 0 /* Monochrome mode */
90 #define LXM3200_C 1 /* Standard color mode */
91 #define LXM3200_P 2 /* Photo color mode */
92
93 /* Initial horizontal position for the printheads,
94 * in 1200ths of an inch. Note that "left" and "right"
95 * head here refers to paper margin, and so looking at
96 * them from the front of printer they will appear reversed.
97 */
98
99 /* Left head (B&W/photo) start position */
100 #define LHSTART (gendata.leftoffset+6254)
101 /* added for Lexmark Z12 28.09.2002 */
102 #define LHSTART_z12 (gendata.leftoffset+5000)
103
104 /* Right head (color) start position. This is relative to
105 * LHSTART so we only need to change one parameter to adjust
106 * the head starting position. In the case of the Lexmark Z12
107 * we have only one cartridge: black or color, so
108 * LHSTART_Z12 = RHSTART_Z12
109 */
110 #define RHSTART (LHSTART-2120)
111 #define RHSTART_z12 (LHSTART_z12) /* added for Lexmark Z12 28.9.2002 */
112
113 /* Difference in starting position between left-to-right
114 * and right-to-left passes, in 1200ths of an inch.
115 * Obviously only used in bidirectional mode.
116 */
117 #define LRPASSHOFS 62
118
119 /* Initial vertical position of the printheads,
120 * in 1200ths of an inch.
121 */
122 #define BWTOPSTART (gendata.topoffset+420)
123 #define COLTOPSTART (gendata.topoffset+476)
124
125 /* Base alignment offset between the color cartridge
126 * and the B&W cartridge in 192 nozzles mode.
127 */
128 #define COLORVALIGN_V 8
129 #define BLACKVALIGN_V (gendata.vertalign+30)
130 #define PHOTOVALIGN_V (gendata.vertalign)
131
132 /* Values used to index the vertical aligment array */
133 #define COLORVALIGN 0
134 #define BLACKVALIGN 1
135 #define PHOTOVALIGN 2
136
137 /* Offset of color pens from first row, in 1/600ths of an inch.
138 * Pen 0 is the topmost and is the CYAN or LIGHTCYAN pen (depending
139 * on the cartridge: standard color or photo). Pen 1 is the middle
140 * one, which carries MAGENTA or LIGHTMAGENTA color. Pen 2 is the
141 * bottom one, which is YELLOW or BLACK.
142 */
143 #define PEN0OFS 0
144 #define PEN1OFS 92
145 #define PEN2OFS 184
146
147 /* Number of nozzles in each pen type */
148 #define COLORPEN 64 /* Each color pen of a color/photo cartridge */
149 #define BWCOLPEN 192 /* Black cartridge used in color or 1200dpi modes */
150 #define BWSTDPEN 208 /* Black cartridge used in mono non-1200dpi mode */
151
152 /* Values used by the color mapping routines */
153 #define HALFTONE (gx_max_color_value/2)
154 #define FULLTONE (gx_max_color_value)
155 #define ONETHIRD (FULLTONE/3)
156 #define TWOTHIRD ((2*FULLTONE)/3)
157
158 /* Printer head and printing direction selectors */
159 #define LEFT 0 /* Left head (B/W or photo) or left-to-right direction */
160 #define RIGHT 1 /* Right head (colour) or right-to-left direction */
161
162 /* Qualificators for the scan buffer */
163 #define LAST 0x01 /* The buffer is the last on the page */
164 #define LHDATA 0x02 /* The buffer contains data for the left head */
165 #define RHDATA 0x04 /* The buffer contains data for the right head */
166
167 /* Printer's margins, in inches. The Lexmark 3200 has two settings
168 * for the side margins: one is used with A4-sized paper and one
169 * (here called conventionally "LETTER") is used for all other paper
170 * sizes. Envelopes have different margins as well, but under ghostscript
171 * it's quite hard to know, from inside a printer driver, if we are
172 * printing on envelopes or on standard paper, so we just ignore that.
173 */
174 #define LXM3200_TOP_MARGIN 0.070
175 #define LXM3200_BOTTOM_MARGIN 0.200
176 #define LXM3200_A4_LEFT_MARGIN 0.135
177 #define LXM3200_LETTER_LEFT_MARGIN 0.250
178 #define LXM3200_A4_RIGHT_MARGIN 0.135
179 #define LXM3200_LETTER_RIGHT_MARGIN 0.250
180
181 /* Offsets for the top and bootom start of the printing frame. */
182 #define LXM3200_A4_TOPOFFSET 84
183 #define LXM3200_A4_LEFTOFFSET 162
184 #define LXM3200_LETTER_TOPOFFSET 84
185 #define LXM3200_LETTER_LEFTOFFSET 300
186
187 /*
188 * ------ The device descriptor ------
189 */
190
191 /* Device procedures */
192 static gx_device_procs lxm3200_procs =
193 prn_color_params_procs(lxm3200_open, gdev_prn_output_page, gdev_prn_close,
194 lxm3200_map_rgb_color, lxm3200_map_color_rgb, lxm3200_get_params,
195 lxm3200_put_params);
196
197 /* Define an extension (subclass) of gx_device_printer. */
198 typedef struct lxm_device_s
199 {
200 gx_device_common;
201 gx_prn_device_common;
202 int rendermode; /* Rendering mode (BW, CMYK, CcMmYK) */
203 int algnA; /* Horizontal alignment between left and right cartridges */
204 int algnB; /* Vertical alignment between left and right cartridges */
205 int algnC; /* Nozzle column separation of left cartridge */
206 int algnD; /* Nozzle column separation of right cartridge */
207 int bidir; /* Bidirectional printing active ? */
208 int numpass; /* Number of head passes for each stripe */
209 int leftoffset; /* Offset of first column from left side of paper */
210 int topoffset; /* Offset of first row from top of paper */
211 int model; /* Parameter to choose the model - lxm3200=0, z12=1, z31=2 */
212 int z31m; /* Alignment parameter for the Z31 */
213 } lxm_device;
214
215 /* Device definition: Lexmark 3200 */
216 lxm_device far_data gs_lxm3200_device =
217 {
218 prn_device_body(lxm_device,
219 lxm3200_procs,
220 "lxm3200",
221 DEFAULT_WIDTH_10THS,
222 DEFAULT_HEIGHT_10THS,
223 600, /* default x dpi */
224 600, /* default y dpi */
225 0.0, /* left margin, inches (filled-in later) */
226 0.0, /* bottom margin, inches (filled-in later) */
227 0.0, /* right margin, inches (filled-in later) */
228 0.0, /* top margin, inches (filled-in later) */
229 1, /* number of color components (mono) */
230 8, /* bits per pixel */
231 1, /* number of gray levels-1: B&W only */
232 0, /* number of color levels-1: no color */
233 2, /* dither gray: maximum 2 distinct gray levels */
234 0, /* dither rgb: no RGB dithering in this mode */
235 lxm3200_print_page),
236 LXM3200_C, /* default printing mode */
237 16, 8, 16, 16, /* default aligment parameters value */
238 0, 1, /* default bidirectional and numpasses value */
239 0, 0, /* left and top offsets (filled-in later) */
240 0, /* default model = Lexmark 3200 */
241 100 /* default z31m */
242 };
243
244 /* --------- Static data --------- */
245
246 /* Lookup tables to speed up bitwise operations */
247 static byte bits[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
248 static byte ibits[8] = { 0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0xfe };
249
250 /* Lookup table for masking color pens in color/photo cartridges.
251 * This is used to check the raster buffer for the presence of a
252 * particular color in the pixel we are encoding.
253 * The first index is the head (LEFT or RIGHT) which is used to
254 * distinguish between photo and color cartridges. The second index
255 * is the pen number (0 is the upper pen, 1 the middle pen, 2 the
256 * lower pen) on that cartridge.
257 */
258 static byte colmask[2][3] =
259 {
260 { LIGHTCYAN, LIGHTMAGENTA, BLACK},
261 { CYAN, MAGENTA, YELLOW }
262 };
263
264 /* Lookup table for pen position offsets of color/photo cartridges.
265 * Parameter is the pen number, as defined by the pen offsets above:
266 * pen 0 is CYAN/LIGHTCYAN, pen 1 is MAGENTA/LIGHTMAGENTA, pen 2 is
267 * YELLOW/BLACK. This is used to properly take account the position
268 * of each color pen relative to the vertical position of the
269 * color/photo cartridge.
270 */
271 static int penofs[3];
272
273 /* Lookup table for vertical alignment of the cartridges relative to
274 * each other. Parameter is the cartridge type: 0 = color cartridge,
275 * 1 = black cartridge in color mode, 2 = photo cartridge.
276 * Black cartridge in monochromatic mode is always aligned at 0
277 * because in that mode we print with only one cartridge so there can
278 * be no alignment problems (a single cartridge is always aligned
279 * with itself, otherwise the printer tray is faulty).
280 */
281 static int valign[3];
282
283 /* Lookup table for horizontal offsets. First parameter is the
284 * head, second parameter the printing direction.
285 */
286 static int hoffset[2][2];
287
288 /* Initialization sequence needed at the beginning of the data stream.
289 * This is invariant and contains a reset sequence, meaning each single
290 * page in a multiple page output is sent to the printer as an independent
291 * print job.
292 */
293 static byte init_sequence[] =
294 {
295 0x1b, 0x2a, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
296 0x1b, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33,
297 0x1b, 0x30, 0x80, 0x0C, 0x02, 0x00, 0x00, 0xbe,
298 0x1b, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21
299 };
300
301 static byte z12_init_sequence[] =
302 {
303 0x1b, 0x2a, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
304 0x1b, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33,
305 0x1b, 0x63, 0x00, 0x01, 0x40, 0x02, 0x0d, 0xb3,
306 0x1b, 0x30, 0x80, 0x0c, 0x01, 0x00, 0x00, 0xbd,
307 0x1b, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21
308 };
309
310 /* General global data that must be accessible
311 * by all routines.
312 */
313 typedef struct pagedata_s
314 {
315 /* General invariant data */
316 int numbytes; /* Number of bytes in a scanline of the buffer */
317 int numrbytes; /* Width (in bytes) of one rasterized scanline */
318 int goffset; /* Guard offset at each side of each scanline (columns) */
319 int numblines; /* Number of lines in a buffer */
320 int numlines; /* Number of lines in a vertical head pass */
321 int rendermode; /* Type of rendering */
322 int numvlines; /* Number of lines in the page */
323 int numcols; /* Number of columns in a row */
324 int numpasses; /* Number of passes used to print one stripe */
325 int bidirprint; /* Bidirectional printing enabled ? */
326 int select; /* Resolution selector */
327 int modelprint; /* which printer? - lxm3200=0, z12=1, z31=2 */
328 int z31margin; /* margin for the Z31 */
329
330 /* Printing offsets */
331 int leftoffset; /* Start printing offset from left margin */
332 int topoffset; /* Start printing offset from top margin */
333
334 /* Resolution settings */
335 int xres; /* Horizontal dots per inch */
336 int yres; /* Vertical dots per inch */
337 int xrmul; /* Horizontal coordinate multiplier */
338 int yrmul; /* Vertical coordinate multiplier */
339
340 /* Pagewide status */
341 int curheadpos; /* Current absolute printhead position */
342 int linetoeject; /* Number of lines for the eject command */
343 int direction; /* Printing direction for next stripe */
344
345 /* Alignment data */
346 int bwsep; /* Nozzle columns separation in B&W/photo cartridge */
347 int colsep; /* Nozzle columns separation in color cartridge */
348 int vertalign; /* Vertical alignment offset of the two cartridges */
349 int lrhalign; /* Horizontal alignment between left and right cartridges */
350
351 /* Data pointers */
352 byte *outdata; /* Buffer to output data codes for one full stripe */
353 byte *scanbuf; /* Buffer to contain the rasterized scanlines */
354 FILE *stream; /* Output stream */
355 lxm_device *dev; /* Pointer to our device */
356
357 /* Buffer data */
358 int left, right; /* Actual left and right margins */
359 int firstline; /* Head of the circular scanline buffer */
360 int lastblack; /* Line of last black pass rendered in a color print */
361 int curvline; /* Current vertical position */
362
363 /* Stripe related data */
364 byte header[24]; /* Stripe header data */
365 int fullflag; /* A stripe is ready to be output */
366 int stripebytes; /* Number of bytes in a stripe */
367 int ileave; /* Interleaving pass: 0=even lines, 1=odd lines */
368
369 } pagedata;
370
371 static pagedata gendata;
372
373 /* --------- Interface routines --------- */
374
375 /* Function called by ghostscript to open the
376 * printer device. We set the margins and offsets
377 * here. Note that to guess which paper is loaded
378 * into the printer, we calculate the line width
379 * and then anything between 8.25 and 8.4 inches
380 * is considered to be A4.
381 * This routine is inspired by the omologous
382 * routine from the "gdevbj10" driver.
383 */
384 static int
lxm3200_open(gx_device * pdev)385 lxm3200_open(gx_device *pdev)
386 {
387 float linewidth;
388
389 static const float a4_margins[4] =
390 {
391 LXM3200_A4_LEFT_MARGIN, LXM3200_BOTTOM_MARGIN,
392 LXM3200_A4_RIGHT_MARGIN, LXM3200_TOP_MARGIN
393 };
394
395 static const float letter_margins[4] =
396 {
397 LXM3200_LETTER_LEFT_MARGIN, LXM3200_BOTTOM_MARGIN,
398 LXM3200_LETTER_RIGHT_MARGIN, LXM3200_TOP_MARGIN
399 };
400
401 linewidth = (float)(pdev->width) / (float)(pdev->x_pixels_per_inch);
402
403 if(linewidth >= 8.25 && linewidth <= 8.4)
404 {
405 gx_device_set_margins(pdev, a4_margins, true);
406 ((lxm_device *)pdev)->topoffset = LXM3200_A4_TOPOFFSET;
407 ((lxm_device *)pdev)->leftoffset = LXM3200_A4_LEFTOFFSET;
408 }
409 else
410 {
411 gx_device_set_margins(pdev, letter_margins, true);
412 ((lxm_device *)pdev)->topoffset = LXM3200_LETTER_TOPOFFSET;
413 ((lxm_device *)pdev)->leftoffset = LXM3200_LETTER_LEFTOFFSET;
414 }
415
416 return gdev_prn_open(pdev);
417 }
418
419 /* Function used by ghostscript to map a RGB
420 * value to the driver's internal representation
421 * of the nearest color.
422 */
423 static gx_color_index
lxm3200_map_rgb_color(gx_device * dev,const gx_color_value cv[])424 lxm3200_map_rgb_color(gx_device *dev, const gx_color_value cv[])
425 {
426 gx_color_index col;
427 gx_color_value r, g, b;
428 int c, m, y;
429 gx_color_value tmpcv[3];
430
431 r = cv[0]; g = cv[1]; b = cv[2];
432 /* In case R, G and B values are equal, ghostscript
433 * prescribes that the color value must be turned
434 * into a gray shade. In our case this means either
435 * black or white
436 */
437 if(r == g && r == b)
438 {
439 if(r > HALFTONE)
440 return(WHITE);
441 else
442 return(BLACK);
443 }
444
445 /* Calculate CMY values from RGB. This is *overly*
446 * simple, but it's enough to print something.
447 */
448 c = FULLTONE - r;
449 m = FULLTONE - g;
450 y = FULLTONE - b;
451
452 /* Now encode the calculated color into the internal
453 * format. This means simply to turn on or off the
454 * bits representing each color depending on the value
455 * of the appropriate CMY component.
456 * Note that we are not doing black separation or any
457 * other fancy stuff: this is spartane code just to
458 * make the printer work.
459 */
460 col = 0;
461 if(y > HALFTONE)col |= YELLOW;
462
463 switch(((lxm_device *)dev)->rendermode)
464 {
465 case LXM3200_C:
466 if(c > HALFTONE)col |= CYAN;
467 if(m > HALFTONE)col |= MAGENTA;
468 break;
469
470 case LXM3200_P:
471 if(c > TWOTHIRD)
472 col |= CYAN;
473 else
474 if(c > ONETHIRD)col |= LIGHTCYAN;
475
476 if(m > TWOTHIRD)
477 col |= MAGENTA;
478 else
479 if(m > ONETHIRD)col |= LIGHTMAGENTA;
480 break;
481
482 default:
483 tmpcv[0] = r; tmpcv[1] = g; tmpcv[2] = b;
484 col = gdev_prn_map_rgb_color(dev, tmpcv);
485 break;
486 }
487
488 return(col);
489 }
490
491 /* Function called by ghostscript to map the
492 * internal representation of a color to a
493 * RGB value.
494 */
495 static int
lxm3200_map_color_rgb(gx_device * dev,gx_color_index color,gx_color_value prgb[3])496 lxm3200_map_color_rgb(gx_device *dev, gx_color_index color,
497 gx_color_value prgb[3])
498 {
499 int c, m, y;
500
501 if(color == WHITE)
502 {
503 prgb[0] = FULLTONE;
504 prgb[1] = FULLTONE;
505 prgb[2] = FULLTONE;
506 return(0);
507 }
508
509 if(color & BLACK)
510 {
511 prgb[0] = 0;
512 prgb[1] = 0;
513 prgb[2] = 0;
514 return(0);
515 }
516
517 /* Calculate back CMY components from the internal
518 * representation of the color
519 */
520 c = 0;
521 m = 0;
522 y = 0;
523
524 switch(((lxm_device *)dev)->rendermode)
525 {
526 case LXM3200_C:
527 color &= (CYAN|MAGENTA|YELLOW);
528 if(color & CYAN)c = 2;
529 if(color & MAGENTA)m = 2;
530 if(color & YELLOW)y = 2;
531 break;
532
533 case LXM3200_P:
534 default:
535 color &= (CYAN|MAGENTA|YELLOW|LIGHTCYAN|LIGHTMAGENTA);
536 if(color & LIGHTCYAN)c = 1;
537 if(color & LIGHTMAGENTA)m = 1;
538 if(color & YELLOW)y = 2;
539 if(color & CYAN)c = 2;
540 if(color & MAGENTA)m = 2;
541 break;
542 }
543
544 /* And now turn CMY to RGB, in the usual spartane way */
545
546 prgb[0] = (gx_color_value)((2 - c) * HALFTONE);
547 prgb[1] = (gx_color_value)((2 - m) * HALFTONE);
548 prgb[2] = (gx_color_value)((2 - y) * HALFTONE);
549
550 return(0);
551 }
552
553 /* Main routine of the driver. This takes care of
554 * all parameters and static data initialization
555 * and calls the proper page printing routines
556 * depending on the selected printing mode.
557 */
558 static int
lxm3200_print_page(gx_device_printer * pdev,FILE * prn_stream)559 lxm3200_print_page(gx_device_printer *pdev, FILE *prn_stream)
560 {
561 /* Store data passed by ghostscript to the driver */
562 gendata.dev = (lxm_device *)pdev;
563 gendata.stream = prn_stream;
564 gendata.rendermode = (gendata.dev)->rendermode;
565
566 /* Snap resolution on one of the three supported setting
567 * (300, 600, 1200 dpi) depending on the input resoution value.
568 * Horizontal and vertical resolution are treated independently.
569 */
570 gendata.xres = 600;
571 if((gendata.dev)->x_pixels_per_inch < 450)gendata.xres = 300;
572 if((gendata.dev)->x_pixels_per_inch > 900)gendata.xres = 1200;
573 gendata.xrmul = 1200 / gendata.xres;
574
575 gendata.yres = 600;
576 if((gendata.dev)->y_pixels_per_inch < 450)gendata.yres = 300;
577 if((gendata.dev)->y_pixels_per_inch > 900)gendata.yres = 1200;
578 gendata.yrmul = 1200 / gendata.yres;
579
580 /* Cache horizontal and vertical starting offsets */
581 gendata.topoffset = (gendata.dev)->topoffset;
582 gendata.leftoffset = (gendata.dev)->leftoffset;
583
584 /* Build lookup table for pen offset, adjusting for
585 * vertical resolution setting
586 */
587 penofs[0] = (PEN0OFS * 2) / gendata.yrmul;
588 penofs[1] = (PEN1OFS * 2) / gendata.yrmul;
589 penofs[2] = (PEN2OFS * 2) / gendata.yrmul;
590
591 /* Build lookup table for vertical heads alignment,
592 * adjusting for vertical resolution setting
593 */
594 valign[COLORVALIGN] = (COLORVALIGN_V * 2) / gendata.yrmul;
595 valign[BLACKVALIGN] = (BLACKVALIGN_V * 2) / gendata.yrmul;
596 valign[PHOTOVALIGN] = (PHOTOVALIGN_V * 2) / gendata.yrmul;
597
598 /* Build lookup tables for initial horizontal offsets,
599 * adjusting for horizontal resolution setting
600 */
601 /* choose whether to use lxm3200 or Z12 settings */
602 gendata.modelprint=(gendata.dev)->model; /* which model? */
603 gendata.z31margin=(gendata.dev)->z31m; /*which additional margin for z31*/
604 switch(gendata.modelprint){
605 case 1: /* we use the Lexmark Z12 */
606 hoffset[LEFT][LEFT] = LHSTART_z12;
607 hoffset[RIGHT][LEFT] = RHSTART_z12 + gendata.lrhalign;
608 break;
609 default: /* default (if one uses the Lexmark 3200 or the Lexmark Z31) */
610 hoffset[LEFT][LEFT] = LHSTART;
611 hoffset[RIGHT][LEFT] = RHSTART + gendata.lrhalign;
612 break;
613 }
614 hoffset[LEFT][RIGHT] = hoffset[LEFT][LEFT] - LRPASSHOFS;
615 hoffset[RIGHT][RIGHT] = hoffset[RIGHT][LEFT] - LRPASSHOFS;
616
617 /* Initialization of general parameters */
618 gendata.outdata = NULL;
619 gendata.scanbuf = NULL;
620 gendata.curheadpos = 0;
621 gendata.left = 0;
622 gendata.right = 0;
623 gendata.lastblack = 0;
624 gendata.curvline = 0;
625 gendata.firstline = 0;
626 gendata.fullflag = FALSE;
627 gendata.direction = LEFT;
628 gendata.ileave = 0;
629
630 gendata.bidirprint = (gendata.dev)->bidir;
631 gendata.numpasses = (gendata.dev)->numpass;
632
633 /* Set some parameters that depend on resolution and
634 * printing mode. We calculate all at 600dpi (the native
635 * resolution) and then correct later for different
636 * resolution settings.
637 */
638 switch(gendata.rendermode)
639 {
640 /* In monochrome mode we try to use all 208 nozzles of
641 * the black cartridge to speed up printing. But if we
642 * are printing at 1200 dpi horizontal, only 192 nozzles
643 * are available anyway (it seems an hardware limitation).
644 * We print a full buffer at every pass, so the number of
645 * lines in the buffer is the same as the number of nozzles
646 * of the head.
647 */
648 case LXM3200_M:
649 gendata.numblines = 208;
650 gendata.numlines = 208;
651 gendata.select = 0x10;
652 if(gendata.xres == 1200)
653 {
654 gendata.numblines = 192;
655 gendata.numlines = 192;
656 gendata.select = 0x00;
657 }
658 break;
659
660 /* In color or photo mode we must use 192 nozzles only in
661 * the black cartridge, to cope with the color and photo
662 * cartridges (which have 3 color pen of 64 nozzles each,
663 * for a total of 192 nozzles). But the color pens are
664 * vertically spaced and misaligned with respect to the
665 * black pen. To solve this problem, we need a buffer which
666 * is larger than 192 lines and then we print only the
667 * proper "windows" from it. We choose to set the buffer
668 * height to 256, which is the smallest power of two large
669 * enough to hold all the needed data. We use a power of
670 * two for speed, since in this way the modulo operation
671 * in the inner loops (needed to take care of buffer rolling)
672 * becomes a simple and much faster bitwise AND.
673 */
674 case LXM3200_P:
675 case LXM3200_C:
676 gendata.numblines = 256;
677 gendata.numlines = 192;
678 gendata.select = 0x00;
679 break;
680 }
681
682 /* Correct the number of lines of the buffer to take care
683 * of different vertical resolution modes. Since the buffer
684 * does cover a constant vertical spacing, we must double the
685 * number of lines at 1200dpi and half it at 300dpi, to take
686 * into account the different thickness of the lines at the
687 * three different vertical resolutions.
688 */
689 gendata.numblines = (gendata.numblines * 2) / gendata.yrmul;
690
691 /* Now correct the "select" field to adjust the horizontal
692 * motor speed depending on position. Meanwhile, if we are
693 * at 1200 dpi, double the number of horizontal passes
694 * because each stripe at 1200 dpi horizontal must be printed
695 * in two passes.
696 */
697 switch(gendata.xres)
698 {
699 case 300:
700 gendata.select |= 0x60;
701 break;
702
703 case 1200:
704 gendata.select |= 0x40;
705 gendata.numpasses *= 2;
706 break;
707 }
708
709 /* Now store some useful info taken from the ghostscript
710 * device structure to speed up access.
711 */
712 gendata.numcols = (gendata.dev)->width;
713 gendata.numvlines = (gendata.dev)->height;
714 gendata.lrhalign = (gendata.dev)->algnA;
715 gendata.vertalign = (gendata.dev)->algnB;
716 gendata.bwsep = (gendata.dev)->algnC;
717 gendata.colsep = (gendata.dev)->algnD;
718 gendata.goffset = (max(gendata.bwsep, gendata.colsep) * 2) / gendata.xrmul;
719 gendata.numbytes = gendata.numcols + (2 * gendata.goffset);
720 gendata.numrbytes = gdev_mem_bytes_per_scan_line(gendata.dev);
721
722 /* Calculate number of lines in the page and initialize the
723 * counter of the lines to eject. At the end of the printing,
724 * to eject the paper sheet we must send to the printer a
725 * command to move the paper forward. The amount to move is
726 * the length of paper which is still inside the printer plus
727 * two inches (the number is expressed in 1200ths of an inch,
728 * so "plus two inches" means "add 2400").
729 */
730 gendata.linetoeject = gendata.numvlines * gendata.yrmul;
731 gendata.linetoeject += 2400;
732
733 /* Allocate memory for the buffers and
734 * verify that the allocation was done properly.
735 */
736 gendata.scanbuf = (byte *)gs_malloc(gs_lib_ctx_get_non_gc_memory_t(), gendata.numbytes, gendata.numblines,
737 "lxm3200_print_page(scanbuf)");
738
739 gendata.outdata = (byte *)gs_malloc(gs_lib_ctx_get_non_gc_memory_t(), gendata.numbytes, 30,
740 "lxm3200_print_page(outdata)");
741
742 if(gendata.scanbuf == NULL ||
743 gendata.outdata == NULL)
744 {
745 freeresources(pdev);
746 return_error(gs_error_VMerror);
747 }
748
749 /* Send initialization sequence to the printer */
750 if(gendata.modelprint==1) fwrite(z12_init_sequence, sizeof(z12_init_sequence), 1, prn_stream);
751 else fwrite(init_sequence, sizeof(init_sequence), 1, prn_stream);
752
753 /* Choose the right page printing routine
754 * depending on the printing mode.
755 */
756 switch(gendata.rendermode)
757 {
758 case LXM3200_P:
759 print_photo_page();
760 break;
761
762 case LXM3200_C:
763 print_color_page();
764 break;
765
766 case LXM3200_M:
767 default:
768 print_mono_page();
769 break;
770 }
771
772 /* Output the end-of-page epilogue */
773 outputepilogue();
774
775 /* Free the allocated resources */
776 freeresources(pdev);
777
778 /* Done. Bye bye, see you on next page. */
779 return(0);
780 }
781
782 /* Function that Ghostscript calls to ask the driver
783 * the value of its parameters. This function is based
784 * on the equivalent from the HP850 driver (gdevcd8.c)
785 * by Uli Wortmann.
786 * I won't comment it because I haven't even tried
787 * to understand this code... :)
788 */
789 static int
lxm3200_get_params(gx_device * pdev,gs_param_list * plist)790 lxm3200_get_params(gx_device *pdev, gs_param_list *plist)
791 {
792 int code;
793
794 code = gdev_prn_get_params(pdev, plist);
795
796 if(code < 0)return(code);
797
798 code = param_write_int(plist, "algnA", &((lxm_device *)pdev)->algnA);
799 if(code < 0)return(code);
800
801 code = param_write_int(plist, "algnB", &((lxm_device *)pdev)->algnB);
802 if(code < 0)return(code);
803
804 code = param_write_int(plist, "algnC", &((lxm_device *)pdev)->algnC);
805 if(code < 0)return(code);
806
807 code = param_write_int(plist, "algnD", &((lxm_device *)pdev)->algnD);
808 if(code < 0)return(code);
809
810 code = param_write_int(plist, "bidir", &((lxm_device *)pdev)->bidir);
811 if(code < 0)return(code);
812
813 code = param_write_int(plist, "numpass", &((lxm_device *)pdev)->numpass);
814 if(code < 0)return(code);
815
816 code = param_write_int(plist, "mode", &((lxm_device *)pdev)->rendermode);
817 if(code < 0)return(code);
818
819 code = param_write_int(plist, "model", &((lxm_device *)pdev)->model);
820 if(code < 0)return(code);
821
822 code = param_write_int(plist, "z31m", &((lxm_device *)pdev)->z31m);
823
824 return code;
825 }
826
827 /* Function that Ghostscript calls to let the driver
828 * set the value of its parameters. This function is
829 * based on the equivalent from the HP850 driver
830 * (gdevcd8.c) by Uli Wortmann.
831 * I won't comment it because I haven't even tried
832 * to understand this code... :)
833 */
834 static int
lxm3200_put_params(gx_device * pdev,gs_param_list * plist)835 lxm3200_put_params(gx_device *pdev, gs_param_list *plist)
836 {
837 int algnA = ((lxm_device *)pdev)->algnA;
838 int algnB = ((lxm_device *)pdev)->algnB;
839 int algnC = ((lxm_device *)pdev)->algnC;
840 int algnD = ((lxm_device *)pdev)->algnD;
841 int bidir = ((lxm_device *)pdev)->bidir;
842 int numpass = ((lxm_device *)pdev)->numpass;
843 int mode = ((lxm_device *)pdev)->rendermode;
844 int code = 0;
845 int model = ((lxm_device *)pdev)->model; /* for model selection */
846 int z31m = ((lxm_device *)pdev)->z31m; /* additional margin for the z31 */
847
848 code = param_read_int(plist, "algnA", &algnA);
849 if(code < 0)return(code);
850 if(algnA < 0 || algnA > 30)
851 param_signal_error(plist, "algnA", gs_error_rangecheck);
852
853 code = param_read_int(plist, "algnB", &algnB);
854 if(code < 0)return(code);
855 if(algnB < 0 || algnB > 15)
856 param_signal_error(plist, "algnB", gs_error_rangecheck);
857
858 code = param_read_int(plist, "algnC", &algnC);
859 if(code < 0)return(code);
860 if(algnC < 0 || algnC > 30)
861 param_signal_error(plist, "algnC", gs_error_rangecheck);
862
863 code = param_read_int(plist, "algnD", &algnD);
864 if(code < 0)return(code);
865 if(algnD < 0 || algnD > 30)
866 param_signal_error(plist, "algnD", gs_error_rangecheck);
867
868 code = param_read_int(plist, "bidir", &bidir);
869 if(code < 0)return(code);
870 if(bidir != 0 && bidir != 1)
871 param_signal_error(plist, "bidir", gs_error_rangecheck);
872
873 code = param_read_int(plist, "numpass", &numpass);
874 if(code < 0)return(code);
875 if(numpass < 1 || numpass > 16)
876 param_signal_error(plist, "numpass", gs_error_rangecheck);
877
878 code = param_read_int(plist, "mode", &mode);
879 if(code < 0)return(code);
880 if(mode != LXM3200_M && mode != LXM3200_C && mode != LXM3200_P)
881 param_signal_error(plist, "mode", gs_error_rangecheck);
882
883 code = param_read_int(plist, "model", &model); /* asking for the model of printer: lxm3200 , Z12, Z31 */
884 if(code < 0)return(code);
885 if(model < 0 || model > 2 )
886 param_signal_error(plist, "model", gs_error_rangecheck);
887
888 code = param_read_int(plist, "z31m", &z31m); /* What additional margin for the Z31 */
889 if(code < 0)return(code);
890
891 code = gdev_prn_put_params(pdev, plist);
892 if(code < 0)return code;
893
894 ((lxm_device *)pdev)->algnA = algnA;
895 ((lxm_device *)pdev)->algnB = algnB;
896 ((lxm_device *)pdev)->algnC = algnC;
897 ((lxm_device *)pdev)->algnD = algnD;
898 ((lxm_device *)pdev)->bidir = bidir;
899 ((lxm_device *)pdev)->numpass = numpass;
900 ((lxm_device *)pdev)->rendermode = mode;
901 ((lxm_device *)pdev)->model = model; /* Model selection: lxm3200, Z12, Z31. */
902 ((lxm_device *)pdev)->z31m = z31m; /* Additional margin for the Z31 */
903
904 /* Depending on the selected rendering mode, change the
905 * driver's parameters that ghostscript needs for the
906 * dithering. We need to do it here because the "get_params"
907 * and "put_params" are the only routines in the driver that
908 * ghostscript calls before using the dithering parameters.
909 */
910 switch(mode)
911 {
912 case LXM3200_M:
913 pdev->color_info.num_components = 1;
914 pdev->color_info.max_gray = 1;
915 pdev->color_info.max_color = 0;
916 pdev->color_info.dither_grays = 2;
917 pdev->color_info.dither_colors = 0;
918 break;
919
920 case LXM3200_C:
921 pdev->color_info.num_components = 3;
922 pdev->color_info.max_gray = 1;
923 pdev->color_info.max_color = 1;
924 pdev->color_info.dither_grays = 2;
925 pdev->color_info.dither_colors = 2;
926 break;
927
928 case LXM3200_P:
929 pdev->color_info.num_components = 3;
930 pdev->color_info.max_gray = 1;
931 pdev->color_info.max_color = 2;
932 pdev->color_info.dither_grays = 2;
933 pdev->color_info.dither_colors = 3;
934 break;
935 }
936
937 return 0;
938 }
939
940 /* --------- Internal routines --------- */
941
942 /* Free the resources allocated by the driver */
943 static void
freeresources(gx_device * pdev)944 freeresources(gx_device *pdev)
945 {
946 if(gendata.scanbuf)
947 gs_free(gs_lib_ctx_get_non_gc_memory_t(), (char *)gendata.scanbuf, gendata.numbytes, gendata.numblines,
948 "lxm3200:freeresources(scanbuf)");
949
950 if(gendata.outdata)
951 gs_free(gs_lib_ctx_get_non_gc_memory_t(), (char *)gendata.outdata, gendata.numbytes, 30,
952 "lxm3200:freeresources(outdata)");
953 }
954
955 /* Calculate the checksum of an escape sequence.
956 * It is defined as the sum modulo 256 of the
957 * six bytes following the escape character.
958 *
959 * data: pointer to the first of the 8 characters
960 * of an escape sequence.
961 */
962 static byte
calccheck8(byte * data)963 calccheck8(byte *data)
964 {
965 int ck, i;
966
967 ck = 0;
968 for(i=1; i<7; i++)ck += data[i];
969
970 return(ck);
971 }
972
973 /* Output the page epilogue. This procedure outputs
974 * the escape sequence needed to eject the page and
975 * take the printheads to the "park" position.
976 */
977 static void
outputepilogue(void)978 outputepilogue(void)
979 {
980 byte trailer[24];
981 int pos;
982
983 /* Page eject sequence */
984 trailer[0] = 0x1b;
985 trailer[1] = 0x22;
986 trailer[2] = 0x80;
987 trailer[3] = gendata.linetoeject >> 8;
988 trailer[4] = gendata.linetoeject & 0xff;
989 trailer[5] = 0x00;
990 trailer[6] = 0x00;
991 trailer[7] = calccheck8(trailer);
992
993 /* Calculate the value we need to take the head back
994 * to the park position. This is the current head position
995 * if we printed the last stripe left-to-right, and the
996 * current head position minus 168 (0xa8) if we printed the
997 * last stripe right-to-left.
998 */
999 pos = gendata.curheadpos;
1000 if(gendata.bidirprint && gendata.direction == LEFT)pos -= 0xa8;
1001 if(pos < 0)pos = 0;
1002
1003 /* Horizontal back sequence */
1004 trailer[8] = 0x1b;
1005 trailer[9] = 0x31;
1006 trailer[10] = 0x10;
1007 trailer[11] = pos >> 8;
1008 trailer[12] = pos & 0xff;
1009 trailer[13] = 0x00;
1010 trailer[14] = 0x00;
1011 trailer[15] = calccheck8(trailer+8);
1012
1013 /* Reset sequence */
1014 trailer[16] = 0x1b;
1015 trailer[17] = 0x33;
1016 trailer[18] = 0x00;
1017 trailer[19] = 0x00;
1018 trailer[20] = 0x00;
1019 trailer[21] = 0x00;
1020 trailer[22] = 0x00;
1021 trailer[23] = 0x33;
1022
1023 fwrite(trailer, 8, 3, gendata.stream);
1024 }
1025
1026 /* Output a "page forward" escape sequence,
1027 * needed to move the paper forward some lines.
1028 *
1029 * skiprow: number of buffer lines to skip
1030 * vskip : fixed offset, in 1200ths of an inch
1031 */
1032 static void
skiplines(int skiprow,int skipin)1033 skiplines(int skiprow, int skipin)
1034 {
1035 byte escape[8];
1036 int vskip;
1037
1038 /* The vertical skip command accepts a spacing expressed in
1039 * 1200ths of an inch, so we must convert lines to 1200ths
1040 * of an inch. After the conversion we sum an offset directly
1041 * expressed in 1200ths of an inch: this way we can use this
1042 * routine to skip both a certain amount of lines (which exact
1043 * spacing value depends on the vertical resolution) and a
1044 * fixed offset that we directly know in spacing units.
1045 */
1046 vskip = skiprow*gendata.yrmul + skipin;
1047
1048 escape[0] = 0x1b;
1049 escape[1] = 0x23;
1050 escape[2] = 0x80;
1051 escape[3] = vskip >> 8;
1052 escape[4] = vskip & 0xff;
1053 escape[5] = 0x00;
1054 escape[6] = 0x00;
1055 escape[7] = calccheck8(escape);
1056
1057 /* Adjust the number of lines still inside the printer */
1058 gendata.linetoeject -= vskip;
1059
1060 fwrite(escape, 8, 1, gendata.stream);
1061 }
1062
1063 /* Fill a stripe header with data.
1064 *
1065 * head: LEFT or RIGHT, chooses which head we are "feeding"
1066 * numcol: number of data columns in this stripe, including blank ones
1067 * firstcol: position of the first column in the stripe (the *very first*,
1068 * even if it's blank).
1069 * bytes: total number of bytes in the stripe, including directories
1070 * (but excluding the 24 bytes of the header).
1071 */
1072 static void
fillheader(int head,int numcol,int firstcol,int bytes)1073 fillheader(int head, int numcol, int firstcol, int bytes)
1074 {
1075 int len, offs1, startabs;
1076 int endabs, select, fwd;
1077 int back, nabspos, sep;
1078 byte *header;
1079
1080 header = gendata.header;
1081
1082 /* Correct the measures: firstcol and len need to
1083 * be in 1200ths of an inch.
1084 */
1085 firstcol *= gendata.xrmul;
1086 len = numcol * gendata.xrmul;
1087
1088 /* Alter select to choose direction */
1089 select = gendata.select | (gendata.direction == LEFT ? 0x01 : 0x00);
1090
1091 /* Calculate the proper horizontal offset */
1092 offs1 = hoffset[head][gendata.direction];
1093
1094 /* Now calculate the correct separation depending on the
1095 * head type and adjust "select" to choose between left
1096 * or right head.
1097 */
1098 if(head == LEFT)
1099 {
1100 sep = (gendata.bwsep * 2) / gendata.xrmul;
1101 }
1102 else
1103 {
1104 sep = (gendata.colsep * 2) / gendata.xrmul;
1105 select |= 0x80;
1106 }
1107
1108 /* Now calculate absolute starting and ending positions
1109 * of this stripe, taking into account the printing direction
1110 */
1111 startabs = firstcol + offs1;
1112
1113 if(gendata.direction == LEFT)
1114 endabs = startabs + len;
1115 else
1116 endabs = startabs - len;
1117
1118 /* And now, basing on current head position,
1119 * transform the absolute coordinates in a
1120 * relative movement of the head.
1121 * The formulas used for this are "black magic",
1122 * since this is a part of the protocol which is
1123 * still not well known. What you see here is an
1124 * empyrical formula devised by examination and
1125 * parameter fitting on the data output by the
1126 * Windows driver.
1127 */
1128 if(gendata.direction == LEFT)
1129 {
1130 nabspos = (((endabs - 3600) >> 3) & 0xfff0) + 9;
1131 fwd = nabspos - gendata.curheadpos;
1132 }
1133 else
1134 {
1135 if(endabs > 4816)
1136 nabspos = (((endabs - 4800) >> 3) & 0xfff0) + 9;
1137 else
1138 nabspos = (((endabs - 3600) >> 3) & 0xfff0) + 9;
1139 fwd = gendata.curheadpos - nabspos;
1140 }
1141
1142 gendata.curheadpos += (gendata.direction == LEFT ? fwd : -fwd);
1143
1144 /* If we are printing unidirectionally, calculate
1145 * the backward movement to return the printing head
1146 * at the beginning of this stripe.
1147 */
1148 back = 0;
1149 if(gendata.bidirprint == FALSE)
1150 {
1151 if(startabs > 4816)
1152 nabspos = ((startabs - 4800) >> 3) & 0xfff0;
1153 else
1154 nabspos = ((startabs - 3600) >> 3) & 0xfff0;
1155
1156 if(gendata.direction == LEFT)
1157 back = gendata.curheadpos - nabspos;
1158 else
1159 back = nabspos - gendata.curheadpos;
1160 }
1161
1162 gendata.curheadpos -= (gendata.direction == LEFT ? back : -back);
1163
1164 /* First part of the header */
1165 header[0] = 0x1b;
1166 header[1] = 0x40;
1167 header[2] = select; /* Printing type flags */
1168 header[3] = numcol >> 8; /* MSB of the number of columns to print */
1169 header[4] = numcol & 0xff; /* LSB of the number of columns to print */
1170 header[5] = fwd >> 8; /* MSB of the relative forward head motion */
1171 header[6] = fwd & 0xff; /* LSB of the relative forward head motion */
1172 header[7] = calccheck8(&header[0]);
1173
1174 /* Second part of the header */
1175 header[8] = 0x1b;
1176 header[9] = 0x42;
1177 header[10] = 0x00;
1178 if(gendata.modelprint==1) header[10] = 0x10; /* Lexmark Z12 protocol */
1179 header[11] = back >> 8; /* MSB of the relative backward head motion */
1180 header[12] = back & 0xff; /* LSB of the relative backward head motion */
1181 header[13] = 0x00; /* MSB of the relative downward head motion */
1182 header[14] = 0x00; /* LSB of the relative downward head motion */
1183 header[15] = calccheck8(&header[8]);
1184
1185 /* Third (and last) part of the header */
1186 header[16] = 0x1b;
1187 header[17] = 0x43;
1188 header[18] = (bytes >> 16) & 0xff;
1189 header[19] = (bytes >> 8) & 0xff;
1190 header[20] = bytes & 0xff; /* LSB of the number of bytes in this stripe */
1191 header[21] = startabs >> 8; /* MSB of the starting column of this stripe */
1192 header[22] = startabs & 0xff; /* LSB of the starting column of this stripe */
1193 header[23] = calccheck8(&header[16]);
1194
1195 /* Signal to other routines that the output buffer
1196 * is full and how many bytes it is long.
1197 */
1198 gendata.stripebytes = bytes;
1199 gendata.fullflag = TRUE;
1200
1201 /* If bidirectional printing is in effect, change
1202 * the printing direction for the next stripe
1203 */
1204 if(gendata.bidirprint)
1205 gendata.direction = (gendata.direction == LEFT ? RIGHT : LEFT);
1206 }
1207
1208 /* Set final information in the header and output all
1209 * the data passes. This routine is needed because the
1210 * actual values of two fields of the header (final
1211 * head position and number of vertical lines to reach
1212 * the next stripe) depend on the next stripe and are
1213 * therefore unknown when "fillheader" is called.
1214 *
1215 * vskip : number of lines to skip to reach next stripe
1216 * newhead: head used for the next stripe (LEFT or RIGHT)
1217 */
1218 static void
finalizeheader(int vskip,int newhead)1219 finalizeheader(int vskip, int newhead)
1220 {
1221 int offs2, nstartabs, back, fwd;
1222 int habs, p, dir, endabs, col;
1223 int newstart, sep;
1224 byte *header;
1225
1226 header = gendata.header;
1227
1228 /* Check the printing direction this stripe
1229 * was originally intended for.
1230 */
1231 dir = (header[2] & 0x01 ? LEFT : RIGHT);
1232
1233 /* Retrieve the horizontal offset for the next stripe */
1234 offs2 = hoffset[newhead][gendata.direction];
1235
1236 /* Calculate the separation adjust in 1200ths of an inch */
1237 if(newhead == LEFT)
1238 sep = (gendata.bwsep * 2) / gendata.xrmul;
1239 else
1240 sep = (gendata.colsep * 2) / gendata.xrmul;
1241
1242 /* Now calculate the correct starting column
1243 * of the next stripe
1244 */
1245 if(gendata.direction == LEFT)
1246 newstart = (gendata.left * gendata.xrmul) - sep;
1247 else
1248 newstart = (gendata.right * gendata.xrmul);
1249
1250 vskip *= gendata.yrmul;
1251
1252 /* Calculate absolute starting position of new stripe */
1253 nstartabs = newstart + offs2;
1254
1255 /* Calculate absolute ending position of this stripe
1256 * by summing (with proper sign) the starting position
1257 * and the width.
1258 */
1259 endabs = header[21]*256 + header[22]; /* Starting position */
1260 col = (header[3]*256 + header[4]); /* Width in columns */
1261 col *= gendata.xrmul; /* Transformed in 1200ths of an inch */
1262
1263 if(dir == LEFT)
1264 endabs += col; /* Printing left-to-right */
1265 else
1266 endabs -= col; /* Printing right-to-left */
1267
1268 /* Correct head position neutralizing the effect
1269 * of the last issued head movement commands. The
1270 * head movement for this stripe needs to be
1271 * recalculated from scratch to take into account
1272 * the correct beginning position of the next stripe.
1273 */
1274 if(dir == LEFT)
1275 {
1276 gendata.curheadpos += header[11]*256 + header[12]; /* Back movement */
1277 gendata.curheadpos -= header[5]*256 + header[6]; /* Forward movement */
1278 }
1279 else
1280 {
1281 gendata.curheadpos -= header[11]*256 + header[12]; /* Back movement */
1282 gendata.curheadpos += header[5]*256 + header[6]; /* Forward movement */
1283 }
1284
1285 /* We use a convention of passing a negative value for
1286 * "newhead" to mean that this is the last stripe of the
1287 * sheet, so we don't need to care for the next stripe.
1288 */
1289 if(newhead < 0)
1290 {
1291 /* Last stripe: we only need to calculate proper forward
1292 * motion to print all the current stripe.
1293 */
1294 fwd = ((header[5]*256 + header[6]) & 0xfff0) + 9;
1295 }
1296 else
1297 {
1298 /* This is not the last stripe, so we need to calculate
1299 * the forward (in the printing direction) movement
1300 * that will take the printing head at the end of the
1301 * current stripe or at the beginning of the next,
1302 * whichever is farther. Note that we are always
1303 * talking relative to printing direction, so we must
1304 * take into proper account if we are printing from left
1305 * to right or from right to left.
1306 */
1307 if(dir == LEFT)
1308 {
1309 p = max(endabs, nstartabs);
1310 habs = (((p - 3600) >> 3) & 0xfff0) + 9;
1311 fwd = habs - gendata.curheadpos;
1312
1313 /* part for the Lexmark Z31!!! */
1314 if(gendata.modelprint==2) fwd += gendata.z31margin;
1315
1316 }
1317 else
1318 {
1319 p = min(endabs, nstartabs);
1320 if(p > 4816)
1321 habs = (((p - 4800) >> 3) & 0xfff0);
1322 else
1323 habs = (((p - 3600) >> 3) & 0xfff0);
1324 fwd = gendata.curheadpos - habs;
1325 }
1326 }
1327
1328 /* Now update the current head position to take into
1329 * account the forward movement just computed
1330 */
1331 gendata.curheadpos += (dir == LEFT ? fwd : -fwd);
1332
1333 /* Now calculate the value of the needed backward movement
1334 * to poisition the head correctly for the start of the
1335 * next stripe.
1336 */
1337 if(newhead < 0 || gendata.bidirprint)
1338 {
1339 /* If this is the last stripe of the page,
1340 * there is no need to take back the head:
1341 * it will be done by the parking command.
1342 * Or if we are printing bidirectionally,
1343 * the forward command has taken the head to
1344 * the correct position, so no need to move it.
1345 */
1346 back = 0;
1347 }
1348 else
1349 {
1350 /* Calculate the right backward movement basing
1351 * on the start of the next stripe.
1352 */
1353 if(nstartabs > 4856)
1354 habs = ((nstartabs - 4840) >> 3) & 0xfff0;
1355 else
1356 habs = ((nstartabs - 3600) >> 3) & 0xfff0;
1357
1358 back = gendata.curheadpos - habs;
1359
1360 /* If the next stripe starts at the right
1361 * of this one, "back" will be too small or
1362 * negative, so correct it.
1363 * It appears that 16 is the minimum allowable
1364 * backward movement that does not make the 3200
1365 * misbehave in the next stripe. This does not hold
1366 * if we are changing printing direction (in such a
1367 * case backward movement may be zero). This means
1368 * we are moving the head a little more than needed,
1369 * but it seems unavoidable.
1370 */
1371 if(back < 16)back = 16;
1372 }
1373
1374 /* Lastly, update the current head position with the
1375 * backward movement just calculated.
1376 */
1377 gendata.curheadpos -= (dir == LEFT ? back : -back);
1378
1379 /* Modify first part of the header */
1380 header[5] = fwd >> 8;
1381 header[6] = fwd & 0xff;
1382 header[7] = calccheck8(&header[0]);
1383
1384 /* Modify second part of the header */
1385 header[8] = 0x1b;
1386 header[9] = 0x42;
1387 header[10] = 0x00;
1388 if(gendata.modelprint==1) header[10] = 0x10; /* Lexmark Z12 protocol */
1389 header[11] = back >> 8; /* MSB of the relative backward head motion */
1390 header[12] = back & 0xff; /* LSB of the relative backward head motion */
1391 header[13] = vskip >> 8; /* MSB of the relative downward head motion */
1392 header[14] = vskip & 0xff; /* LSB of the relative downward head motion */
1393 header[15] = calccheck8(&header[8]);
1394
1395 /* Now output the data, signalling that the output
1396 * buffer is now empty.
1397 */
1398 fwrite(header, 3, 8, gendata.stream);
1399 fwrite(gendata.outdata, gendata.stripebytes, 1, gendata.stream);
1400 gendata.fullflag = FALSE;
1401 }
1402
1403 /* Convert a buffer data stream into
1404 * directory/data representation, using the
1405 * shortest coding (either direct or RLE)
1406 *
1407 * head : head we are printing with (left or right).
1408 * numcols : number of columns in the buffer.
1409 * firstcol: first column to print.
1410 */
1411 static void
convbuf(int head,int numcols,int firstcol)1412 convbuf(int head, int numcols, int firstcol)
1413 {
1414 byte *read, *write;
1415 int x, i, c, p, q, cnt, rle, std;
1416 int nby, ofs, dts0, dtr0, dtr1;
1417 int bytes;
1418
1419 /* Initialize the pointers. We use the same buffer
1420 * for both input and output (we can do it because
1421 * the output data is at most as long as the input).
1422 * Note that the encode routines skipped 4 bytes at
1423 * each column to make room for the directory word.
1424 */
1425 read = gendata.outdata + 4;
1426 write = gendata.outdata;
1427
1428 /* Set the parameters that will be used to create the directory and
1429 * to access the data. These parameters define the structure of the
1430 * directory word (32 bit) and depend on the number of nozzles that
1431 * are used. Note that the directory bitfield is initialized to all
1432 * ones (but read below for further info) because it works in negative
1433 * logic (i.e. a change is marked by a zero bit).
1434 * Below, nby is the number of bytes needed in the input data to map
1435 * a column (each nozzle is 1 bit, so 208 nozzles are 26 bytes and
1436 * 192 nozzles are 24 bytes). Ofs is the number of the first bit of
1437 * the directory bitfield in the directory word (with 208 nozzles we
1438 * need 26 bits, from 6 to 31, with 192 nozzles we need 24 bits, from
1439 * 8 to 31). The other three parameters are the values needed to
1440 * initialize the directory word properly: the key is the first two
1441 * bits, which must be "10" for a directly encoded stripe and "01" for
1442 * a RLE encoded one. In the lexmark directory, each bit represents a
1443 * group of 8 nozzles: in a directly encoded stripe if the bit is "1"
1444 * it means none of the nozzles in the group are used, if it is a "0"
1445 * it means at least one is used and we need to append a data byte to
1446 * define the exact usage pattern. So, for direct encoded stripes we
1447 * start with the first two bits set to "10" and all the directory
1448 * bitfield set to "1" (we will unset to "0" only the needed bits in
1449 * the encoding loop). If we are using RLE encoding, each "0" bits
1450 * means that there is a data byte that defines a pattern for the
1451 * group of 8 nozzles associated to that bit, and an "1" means that
1452 * the pattern for the associated group of nozzles is the same as the
1453 * previous group. This means that for RLE encoded stripes we start the
1454 * directory word with two bits set to "01" and then initialize to "1"
1455 * all the directory bitfield, except the first one which must be 0
1456 * because we must have at least one data byte to define the initial
1457 * pattern that will be eventually repeated.
1458 */
1459 if(gendata.numlines == 208)
1460 {
1461 nby = 26;
1462 ofs = 6;
1463 dts0 = 0x83;
1464 dtr0 = 0x41;
1465 dtr1 = 0xff;
1466 }
1467 else
1468 {
1469 nby = 24;
1470 ofs = 8;
1471 dts0 = 0x80;
1472 dtr0 = 0x40;
1473 dtr1 = 0x7f;
1474 }
1475
1476 /* The variable "bytes" will contain the total
1477 * number of output bytes in the data stripe.
1478 */
1479 bytes = 0;
1480
1481 /* For all the columns in the stripe */
1482 for(x = 0; x < numcols; x++)
1483 {
1484 /* Calculate which representation is smaller by counting
1485 * the number of non zero data bytes for the direct encoding
1486 * and the number of changes between data bytes for the RLE.
1487 * At the end we have in "std" the length of the output data
1488 * if encoded with standard encoding, and in "rle" the length
1489 * of the output data if encoded with RLE.
1490 */
1491 rle = 1;
1492 c = read[0];
1493 std = (c ? 1 : 0);
1494 for(i=1; i<nby; i++)
1495 {
1496 if((p = read[i]))std++;
1497 if(p != c)
1498 {
1499 rle++;
1500 c = read[i];
1501 }
1502 }
1503
1504 /* Now initialize the last two bytes in the directory
1505 * word. These always belong to the directory bitfield
1506 * and must be set to all ones.
1507 */
1508 write[2] = 0xff;
1509 write[3] = 0xff;
1510
1511 /* And now encode the column, using the shortest encoding.
1512 * If the two encodings are of equal length we prefer the
1513 * standard encoding to the RLE one. No real reason for
1514 * this: it could have been done the other way, but it
1515 * seems the Windows driver does this way as well...
1516 */
1517 if(std > rle)
1518 {
1519 /* Run-length encoding */
1520
1521 write[0] = dtr0;
1522 write[1] = dtr1;
1523
1524 p = read[0];
1525 write[4] = p;
1526 cnt = 5;
1527 q = ofs + 1;
1528
1529 for(i=1; i<nby; i++)
1530 {
1531 if(read[i] != p)
1532 {
1533 p = read[i];
1534 write[cnt] = p;
1535 write[q>>3] &= ibits[q & 7];
1536 cnt++;
1537 }
1538 q++;
1539 }
1540 }
1541 else
1542 {
1543 /* Standard encoding */
1544
1545 write[0] = dts0;
1546 write[1] = 0xff;
1547
1548 cnt = 4;
1549 q = ofs;
1550
1551 for(i=0; i<nby; i++)
1552 {
1553 p = read[i];
1554 if(p)
1555 {
1556 write[cnt] = p;
1557 write[q>>3] &= ibits[q & 7];
1558 cnt++;
1559 }
1560 q++;
1561 }
1562 }
1563
1564 /* Update the counters and pointers. Note that when
1565 * we are here "cnt" is the number of bytes that we
1566 * have actually output, including the directory word.
1567 */
1568 read += (nby + 4);
1569 write += cnt;
1570 bytes += cnt;
1571 }
1572
1573 fillheader(head, numcols, firstcol, bytes);
1574 }
1575
1576 /* This routine takes one full buffer of data and
1577 * prints the black part, which of course is the only
1578 * one if we are printing in monochrome mode.
1579 */
1580 static void
encode_bw_buf(void)1581 encode_bw_buf(void)
1582 {
1583 int left, right, x, y, nn, mod;
1584 int nxp, yy, numcols, incr;
1585 int dy, dy2, csep, pass, f1;
1586 int f2, start, s1, s2, yincr;
1587 int q, mask, lines;
1588 byte *scan, *data;
1589
1590 /* Set some parameters that depend on resolution and are
1591 * used in the inner loop to select lines to print.
1592 * We basically encode all the even nozzles in a loop and
1593 * all the odd nozzles in another loop. The values of s1
1594 * and s2 are the starting offset in the line buffer for
1595 * the first and second loop, and yincr is the number of lines
1596 * in the buffer we move on at each cycle.
1597 */
1598 switch(gendata.yres)
1599 {
1600 /* At 300 dpi we use only one nozzle column, and
1601 * each line in the buffer is printed. So both offsets
1602 * are zero (only one is used, actually) and yincr is 1.
1603 * The mask is set to 127 because the buffer is 128 lines.
1604 */
1605 case 300:
1606 yincr = 1;
1607 s1 = 0;
1608 s2 = 0;
1609 mask = 127;
1610 break;
1611
1612 /* At 600 dpi we use both nozzle columns: each row goes
1613 * alternatively to the left or right nozzle column. So
1614 * the even offset is zero, the odd offset is 1 and the
1615 * increment is 2: in this way the even loop scans lines
1616 * 0, 2, 4, ... and the odd loop lines 1, 3, 5, ...
1617 * Here the buffer is 256 lines so mask is set to 255.
1618 */
1619 default:
1620 case 600:
1621 yincr = 2;
1622 s1 = 0;
1623 s2 = 1;
1624 mask = 255;
1625 break;
1626
1627 /* At 1200 dpi we are printing two interleaved passes. Each
1628 * nozzle column sees every fourth line in the buffer (so
1629 * yincr is 4) and the starting offset varies depending on
1630 * which interleaved pass we are doing.
1631 * During the first pass, even nozzles are used to print
1632 * lines 0, 4, 8, ... and odd nozzles are used to print
1633 * lines 2, 6, 10, ... while in the second pass the even
1634 * nozzles print lines 1, 5, 9, ... and the odd nozzles
1635 * print lines 3, 7, 11, ...
1636 * The buffer is 512 lines, so mask is set to 511 */
1637 case 1200:
1638 yincr = 4;
1639 s1 = (gendata.ileave ? 1 : 0);
1640 s2 = (gendata.ileave ? 3 : 2);
1641 mask = 511;
1642 break;
1643 }
1644
1645 /* Now we must calculate the offset q from the beginning of
1646 * the buffer of the first line to print in this pass, and
1647 * the total number of lines to be printed. We print as many
1648 * lines as we can in a single pass, i.e. the value of "lines"
1649 * is simply the number of lines that at the current vertical
1650 * resolution fully cover the printing pen.
1651 * Note that in case of monochrome printing we print all
1652 * buffer lines, from first to last, so we also need to set
1653 * the mask to a neutral value because we don't use wrapping.
1654 */
1655 if(gendata.rendermode == LXM3200_M)
1656 {
1657 mask = 511;
1658 q = 0;
1659 lines = gendata.numblines;
1660 }
1661 else
1662 {
1663 q = gendata.firstline + valign[BLACKVALIGN];
1664 lines = (BWCOLPEN * 2) / gendata.yrmul;
1665 }
1666
1667 /* Adjust the value of the nozzle column separation to the
1668 * horizontal resolution we are using now.
1669 */
1670 csep = (gendata.bwsep * 2) / gendata.xrmul;
1671
1672 /* Here we calculate how many "real" passes we are doing.
1673 * A "real" pass is a pass where a full column is printed
1674 * and then some columns (maybe zero) are skipped before
1675 * printing another one. If we are at 1200 dpi horizontal
1676 * then we must use only one nozzle column at a time, so each
1677 * real pass comprises two subpasses, one where we print with
1678 * even nozzles only and another where we print with odd
1679 * nozzles only. So at 1200 dpi the "real" passes are half the
1680 * total number of passes. Another way of looking at it: the
1681 * "nxp" variable holds the separation, in columns, between two
1682 * dot columns printed in the same head sweep.
1683 */
1684 nxp = gendata.numpasses;
1685 if(gendata.xres == 1200)nxp /= 2;
1686
1687 /* Now calculate the byte increments for the *output* data
1688 * buffer (i.e. the encoded buffer). The first variable,
1689 * dy, is the number of bytes taken by a single data burst
1690 * (both even and odd nozzle columns). The second variable,
1691 * dy2, tells how many bytes we must skip from one column
1692 * to the other (if we are printing multipass we skip some
1693 * columns that will be printed in subsequent passes).
1694 */
1695 dy = (gendata.numlines / 8) + 4;
1696 dy2 = dy * nxp;
1697
1698 /* Calculate the starting and ending horizontal positions for
1699 * this head pass. There are the margins corrected to take
1700 * into account the displacement between the odd and even
1701 * nozzle columns (csep). Moreover we start "csep" pixels
1702 * before the margin to give the head a little more room to
1703 * accelerate properly (not sure if this really works, but it
1704 * doesn't cost much, so I've left it in).
1705 */
1706 if(gendata.direction == LEFT)
1707 {
1708 left = gendata.left - 2*csep;
1709 right = gendata.right + csep;
1710 }
1711 else
1712 {
1713 left = gendata.left - csep;
1714 right = gendata.right + 2*csep;
1715 }
1716
1717 /* Number of columns in a full row */
1718 numcols = right - left;
1719
1720 /* Calculate the last pixel of the first pass of the
1721 * stripe. If we are printing bidirectionally, this
1722 * will be the base to calculate the start of the
1723 * passes printed right-to-left.
1724 */
1725 mod = numcols - (numcols % nxp);
1726
1727 /* f1 and f2 are two flags that define which nozzle columns
1728 * we are using in this stripe, f1 for the even nozzle column
1729 * and f2 for the odd nozzle column: if they are zero that
1730 * nozzle column is not used in this pass.
1731 */
1732 f1 = 1;
1733 f2 = 1;
1734 if(gendata.yres == 300)
1735 {
1736 /* At 300 dpi we use only one nozzle column. As of now this
1737 * is always the even one, but maybe it could be tried to
1738 * alternate between columns at each pass, to improve the
1739 * output quality.
1740 */
1741 f1 = 1;
1742 f2 = 0;
1743 }
1744
1745 /* Now start the passes to fill all the stripe */
1746 for(pass = 0; pass < gendata.numpasses; pass++)
1747 {
1748 /* If there is data in the buffer which has not been
1749 * sent to the printer yet, send it now.
1750 */
1751 if(gendata.fullflag)
1752 {
1753 fwrite(gendata.header, 3, 8, gendata.stream);
1754 fwrite(gendata.outdata, gendata.stripebytes, 1, gendata.stream);
1755 gendata.fullflag = FALSE;
1756 }
1757
1758 /* Clear the output buffer to avoid problems with the bitwise
1759 * operations we will do later on.
1760 */
1761 memset(gendata.outdata, 0, gendata.numbytes * 30);
1762
1763 /* Calculate standard increments, starting column
1764 * and start of output data. They will be corrected
1765 * later for 1200dpi or right-to-left printing direction.
1766 */
1767 incr = nxp;
1768 start = left + pass;
1769 data = gendata.outdata + (pass*dy) + 4;
1770
1771 /* It appears that at 1200dpi, in addition of not being able
1772 * to use 208 nozzles mode for the black cartridge, the Lexmark
1773 * 3200 cannot print at full rate with all the 192 useable nozzles.
1774 * Maybe the reason is that the data rate of 1200dpi horizontal
1775 * resolution exceeds the mechanical/thermal limits of the heads.
1776 * So if we are printing at 1200dpi we need to use alternatively
1777 * only odd or even numbered nozzles, for each printed column, to
1778 * half the data rate towards the head.
1779 * This obviously means that, at 1200dpi horizontal, a minimum of
1780 * two passes are required to print each stripe. Since if we are
1781 * printing at 1200dpi vertical we need two interlaced passes, a
1782 * minimum grand total of 4 passes are needed to print one full
1783 * 1200x1200 dpi stripe with the Lexmark 3200.
1784 */
1785 if(gendata.xres == 1200)
1786 {
1787 f1 = pass & 1;
1788 f2 = 1 - f1;
1789
1790 start = left + (pass/2);
1791 data = gendata.outdata + ((pass/2)*dy) + 4;
1792 }
1793
1794 /* If printing right-to-left we need to present data
1795 * to the printer in that direction, inverting the
1796 * normal flow of data.
1797 */
1798 if(gendata.direction == RIGHT)
1799 {
1800 incr = -nxp;
1801 start += mod;
1802 }
1803
1804 /* Start column scanning */
1805 x = start;
1806
1807 /* Now we split the behaviour depending on the printing
1808 * direction. To be honest, the inner loops are almost
1809 * identical between left-to-right and right-to-left
1810 * directions. The only difference is where is computed
1811 * the contribute of the nozzle columns separation ("csep"),
1812 * but having the "if" outside the loop it's somehow better.
1813 */
1814 if(gendata.direction == LEFT)
1815 {
1816 /* For all the columns in this pass */
1817 for(nn = 0; nn < numcols; nn += nxp)
1818 {
1819 /* Encode the even numbered nozzles */
1820 if((x >= 0) && f1)
1821 {
1822 scan = gendata.scanbuf + x;
1823 yy = 0;
1824 for(y = s1; y < lines; y += yincr)
1825 {
1826 if(scan[((y+q) & mask) * gendata.numbytes] & BLACK)
1827 data[yy/8] |= bits[yy&7];
1828 yy += 2;
1829 }
1830 }
1831
1832 /* Encode the odd numbered nozzles */
1833 if(((x+csep) < gendata.numbytes) && f2)
1834 {
1835 scan = gendata.scanbuf + x + csep;
1836 yy = 1;
1837 for(y = s2; y < lines; y += yincr)
1838 {
1839 if(scan[((y+q) & mask) * gendata.numbytes] & BLACK)
1840 data[yy/8] |= bits[yy&7];
1841 yy += 2;
1842 }
1843 }
1844
1845 /* If we are in 1200dpi horizontal resolution,
1846 * alternate between nozzle columns to avoid
1847 * overstressing the printing head.
1848 */
1849 if(gendata.xres == 1200)
1850 {
1851 f1 = 1 - f1;
1852 f2 = 1 - f2;
1853 }
1854
1855 /* Adjust data pointers */
1856 data += dy2;
1857 x += incr;
1858 }
1859 }
1860 else /* direction == RIGHT */
1861 {
1862 /* For all the columns in this pass */
1863 for(nn = 0; nn < numcols; nn += nxp)
1864 {
1865 /* Encode the odd numbered nozzles */
1866 if((x < gendata.numbytes) && f1)
1867 {
1868 scan = gendata.scanbuf + x;
1869 yy = 1;
1870 for(y = s1; y < lines; y += yincr)
1871 {
1872 if(scan[((y+q) & mask) * gendata.numbytes] & BLACK)
1873 data[yy/8] |= bits[yy&7];
1874 yy += 2;
1875 }
1876 }
1877
1878 /* Encode the even numbered nozzles */
1879 if(((x-csep) >= 0) && f2)
1880 {
1881 scan = gendata.scanbuf + x - csep;
1882 yy = 0;
1883 for(y = s2; y < lines; y += yincr)
1884 {
1885 if(scan[((y+q) & mask)*gendata.numbytes] & BLACK)
1886 data[yy/8] |= bits[yy&7];
1887 yy += 2;
1888 }
1889 }
1890
1891 /* If we are in 1200dpi horizontal resolution,
1892 * alternate between nozzle columns to avoid
1893 * overstressing the printing head.
1894 */
1895 if(gendata.xres == 1200)
1896 {
1897 f1 = 1 - f1;
1898 f2 = 1 - f2;
1899 }
1900
1901 /* Adjust data pointers */
1902 data += dy2;
1903 x += incr;
1904 }
1905 }
1906
1907 /* Convert the buffer to the shortest output format.
1908 * Which is the first column of the output depends
1909 * on the printing direction: it will be the left
1910 * margin if we are printing left to right or the
1911 * right margin if we are printing right to left.
1912 */
1913 if(gendata.direction == LEFT)
1914 convbuf(LEFT, numcols, left);
1915 else
1916 convbuf(LEFT, numcols, right);
1917 }
1918 }
1919
1920 /* This routine is the equivalent of encode_bw_buf() but
1921 * for color or photo cartridge. Since this routine is
1922 * heavily based on the B/W one, the comments here will
1923 * be somewhat less esaurient. Please have a look at
1924 * encode_bw_buf() to understand better how this routine
1925 * works: I will only pinpoint the differences between this
1926 * routine and encode_bw_buf().
1927 *
1928 * head: the head we are calculating the buffer for. It will
1929 * be LEFT for a photo cartridge or RIGHT for a color one.
1930 */
1931 static void
encode_col_buf(int head)1932 encode_col_buf(int head)
1933 {
1934 int left, right, x, y, nn, mod;
1935 int nxp, yy, numcols, incr;
1936 int dy, dy2, csep, pass, f1;
1937 int f2, start, s1, s2, yincr;
1938 int q, mask, k, align, lines;
1939 byte *scan, *data;
1940
1941 /* Here there are two more parameters: mask and lines, that
1942 * for color cartridges are both dependent on vertical
1943 * resolution. Since the buffer is "rolling", i.e. it is
1944 * implemented as a circular array, all the coordinates of
1945 * the buffer lines must be taken modulo the buffer length.
1946 * We choose a buffer length that is a power of two to be
1947 * able to turn the modulo operation into a bitwise AND, so
1948 * we need to set "mask" to the correct value for the AND.
1949 * Another difference is that "lines", i.e. the number of
1950 * lines to print in each pass, is based on the height of a
1951 * color pen. Since there are three color pens in each cartridge,
1952 * each color pen is treated separately to fully cover the
1953 * printing head.
1954 */
1955 switch(gendata.yres)
1956 {
1957 case 300:
1958 yincr = 1;
1959 s1 = 0;
1960 s2 = 0;
1961 mask = 127;
1962 lines = COLORPEN/2;
1963 break;
1964
1965 default:
1966 case 600:
1967 yincr = 2;
1968 s1 = 0;
1969 s2 = 1;
1970 mask = 255;
1971 lines = COLORPEN;
1972 break;
1973
1974 case 1200:
1975 yincr = 4;
1976 s1 = (gendata.ileave ? 1 : 0);
1977 s2 = (gendata.ileave ? 3 : 2);
1978 mask = 511;
1979 lines = COLORPEN*2;
1980 break;
1981 }
1982
1983 /* Choose the vertical alignment depending on the head.
1984 * This is needed to vertically align the color cartridge
1985 * with the photo or black cartridge.
1986 */
1987 if(head == LEFT)
1988 align = valign[PHOTOVALIGN];
1989 else
1990 align = valign[COLORVALIGN];
1991
1992 /* All the stuff below is exactly the same as in
1993 * encode_bw_buf(), and is therefore commented there.
1994 */
1995
1996 csep = (gendata.bwsep * 2) / gendata.xrmul;
1997 nxp = gendata.numpasses;
1998 if(gendata.xres == 1200)nxp /= 2;
1999
2000 dy = (gendata.numlines / 8) + 4;
2001 dy2 = dy * nxp;
2002
2003 if(gendata.direction == LEFT)
2004 {
2005 left = gendata.left - 2*csep;
2006 right = gendata.right + csep;
2007 }
2008 else
2009 {
2010 left = gendata.left - csep;
2011 right = gendata.right + 2*csep;
2012 }
2013
2014 numcols = right - left;
2015 mod = numcols - (numcols % nxp);
2016
2017 f1 = 1;
2018 f2 = 1;
2019 if(gendata.yres == 300)
2020 {
2021 f1 = 1;
2022 f2 = 0;
2023 }
2024
2025 /* For all passes */
2026 for(pass = 0; pass < gendata.numpasses; pass++)
2027 {
2028 /* If there is data in the buffer which has not been
2029 * sent to the printer yet, do it now.
2030 */
2031 if(gendata.fullflag)
2032 {
2033 fwrite(gendata.header, 3, 8, gendata.stream);
2034 fwrite(gendata.outdata, gendata.stripebytes, 1, gendata.stream);
2035 gendata.fullflag = FALSE;
2036 }
2037
2038 /* All the stuff below is exactly the same as in
2039 * encode_bw_buf(), and is therefore commented there.
2040 */
2041
2042 memset(gendata.outdata, 0, gendata.numbytes * 30);
2043
2044 incr = nxp;
2045 start = left + pass;
2046 data = gendata.outdata + (pass*dy) + 4;
2047
2048 if(gendata.xres == 1200)
2049 {
2050 f1 = pass & 1;
2051 f2 = 1 - f1;
2052
2053 start = left + (pass/2);
2054 data = gendata.outdata + ((pass/2)*dy) + 4;
2055 }
2056
2057 if(gendata.direction == RIGHT)
2058 {
2059 incr = -nxp;
2060 start += mod;
2061 }
2062
2063 /* Start column scanning */
2064 x = start;
2065
2066 if(gendata.direction == LEFT)
2067 {
2068 /* For all the columns */
2069 for(nn = 0; nn < numcols; nn += nxp)
2070 {
2071 /* Encode the even numbered nozzles */
2072 if((x >= 0) && f1)
2073 {
2074 scan = gendata.scanbuf + x;
2075 yy = 0;
2076
2077 /* In color printing there is one more loop to scan
2078 * all three color pens. We have to do exactly the
2079 * same things for all pens: the only differences are
2080 * the color encoding bit we are testing and the offset
2081 * from the beginning of the buffer and the offset of the
2082 * output data. All of this is stored into arrays. The
2083 * "penofs" array stores the offset of the first line of
2084 * each pen in the raster buffer. The array "colmask" stores
2085 * the encoding bits for the color of each pen, and it
2086 * is bidimensional because pen masks are different between
2087 * a color cartridge (where pens are Cyan, Magenta, Yellow)
2088 * and a photo cartridge (where pens are LightCyan,
2089 * LightMagenta and Black).
2090 */
2091 for(k=0; k<3; k++)
2092 {
2093 q = gendata.firstline + align + penofs[k];
2094 for(y = s1; y < lines; y += yincr)
2095 {
2096 if(scan[((y+q) & mask) * gendata.numbytes] & colmask[head][k])
2097 data[yy/8] |= bits[yy&7];
2098 yy += 2;
2099 }
2100 }
2101 }
2102
2103 /* Encode the odd numbered nozzles */
2104 if(((x+csep) < gendata.numbytes) && f2)
2105 {
2106 scan = gendata.scanbuf + x + csep;
2107 yy = 1;
2108 for(k=0; k<3; k++)
2109 {
2110 q = gendata.firstline + align + penofs[k];
2111 for(y = s2; y < lines; y += yincr)
2112 {
2113 if(scan[((y+q) & mask) * gendata.numbytes] & colmask[head][k])
2114 data[yy/8] |= bits[yy&7];
2115 yy += 2;
2116 }
2117 }
2118 }
2119
2120 /* If we are in 1200dpi horizontal resolution,
2121 * alternate between nozzle columns to avoid
2122 * overstressing the printing head.
2123 */
2124 if(gendata.xres == 1200)
2125 {
2126 f1 = 1 - f1;
2127 f2 = 1 - f2;
2128 }
2129
2130 /* Adjust data pointers */
2131 data += dy2;
2132 x += incr;
2133 }
2134 }
2135 else
2136 {
2137 /* For all the columns */
2138 for(nn = 0; nn < numcols; nn += nxp)
2139 {
2140 /* Encode the odd numbered nozzles */
2141 if((x < gendata.numbytes) && f1)
2142 {
2143 scan = gendata.scanbuf + x;
2144 yy = 1;
2145 for(k=0; k<3; k++)
2146 {
2147 q = gendata.firstline + align + penofs[k];
2148 for(y = s1; y < lines; y += yincr)
2149 {
2150 if(scan[((y+q) & mask) * gendata.numbytes] & colmask[head][k])
2151 data[yy/8] |= bits[yy&7];
2152 yy += 2;
2153 }
2154 }
2155 }
2156
2157 /* Encode the even numbered nozzles */
2158 if(((x-csep) >= 0) && f2)
2159 {
2160 scan = gendata.scanbuf + x - csep;
2161 yy = 0;
2162 for(k=0; k<3; k++)
2163 {
2164 q = gendata.firstline + align + penofs[k];
2165 for(y = s2; y < lines; y += yincr)
2166 {
2167 if(scan[((y+q) & mask) * gendata.numbytes] & colmask[head][k])
2168 data[yy/8] |= bits[yy&7];
2169 yy += 2;
2170 }
2171 }
2172 }
2173
2174 /* If we are in 1200dpi horizontal resolution,
2175 * alternate between nozzle columns to avoid
2176 * overstressing the printing head.
2177 */
2178 if(gendata.xres == 1200)
2179 {
2180 f1 = 1 - f1;
2181 f2 = 1 - f2;
2182 }
2183
2184 /* Adjust data pointers */
2185 data += dy2;
2186 x += incr;
2187 }
2188 }
2189
2190 if(gendata.direction == LEFT)
2191 convbuf(head, numcols, left);
2192 else
2193 convbuf(head, numcols, right);
2194 }
2195 }
2196
2197 /* Fill monochrome buffer: this routine fills the buffer
2198 * with rasterized lines, skipping over vertical spacing
2199 * (i.e. completely blank lines). The routine is only
2200 * used in monochrome mode, where we print a full buffer
2201 * at each stripe. The color printing needs a different
2202 * routine which makes use of a circular buffer.
2203 *
2204 * vline: the line from which to start searching for data.
2205 */
2206 static int
fill_mono_buffer(int vline)2207 fill_mono_buffer(int vline)
2208 {
2209 byte *in_data, *data;
2210 int i, ret, ofs;
2211
2212 /* Initialize the "data" pointer, that will be used to
2213 * scan all the lines in the buffer, and the "ofs" pointer
2214 * that will be used to mark the start of the "real" rasterized
2215 * data into the buffer (see below). To compensate for the offsets
2216 * caused by the horizontal spacing between nozzle columns on a
2217 * cartridge, the head must start before the horizontal margin, so
2218 * the buffer width is slightly bigger than the width of the
2219 * rasterized lines. The difference is the "guard offset", and the
2220 * variables gendata.numbytes and gendata.numrbytes hold respectively
2221 * the number of bytes in a buffer line and the number of bytes in a
2222 * rasterized scanline, while gendata.goffset contains the number of
2223 * bytes reserved to the guard offset on each side of the scanline.
2224 */
2225 data = gendata.scanbuf;
2226 ofs = gendata.goffset;
2227
2228 /* Cycle until we have no more lines on the page */
2229 while(vline < gendata.numvlines)
2230 {
2231 /* Ask Ghostscript for one rasterized line */
2232 gdev_prn_get_bits((gx_device_printer *)gendata.dev,
2233 vline, data+ofs, &in_data);
2234
2235 /* And check if it's all zero: if not, break out of
2236 * the loop. This nice trick with memcpy it's by Stephen
2237 * Taylor (if I'm not wrong...)
2238
2239 */
2240 if(in_data[0] != 0 ||
2241 memcmp(in_data, in_data+1,gendata.numrbytes-1))break;
2242 vline++;
2243 }
2244
2245 /* If we are here because no non-empty lines were found before
2246 * the end of the page, our work is over. Return to the caller
2247 * saying that this is the last buffer (LAST bit set) and it's
2248 * empty (no LHDATA or RHDATA bit set).
2249 */
2250 if(vline >= gendata.numvlines)return(LAST);
2251
2252 /* This buffer contains at least one non-empty line.
2253 * Adjust the current vertical position and load the first
2254 * line into the buffer.
2255 */
2256 gendata.curvline = vline;
2257 memset(data, 0, gendata.numbytes);
2258 if(in_data != data+ofs)memcpy(data+ofs, in_data, gendata.numrbytes);
2259
2260 vline++;
2261 data += gendata.numbytes;
2262
2263 /* Now initialize the return value to LHDATA (since at least
2264 * one non-blank line was found, this buffer contains data, and
2265 * it is obviously left-head data because we are in monochromatic
2266 * mode and so we are printing with left head only).
2267 * After that, get as many rasterized lines as needed to fill the
2268 * buffer, checking if in the process we have reached the end of
2269 * the page.
2270 */
2271 ret = LHDATA;
2272 for(i=1; i<gendata.numblines; i++)
2273 {
2274 memset(data, 0, gendata.numbytes);
2275 if(vline > gendata.numvlines)
2276 {
2277 /* Ok, we are at the end of the page, so set the LAST bit
2278 * in the return value but don't exit the loop because we
2279 * need to make sure all remaining lines in the buffer will
2280 * be blanked (exiting now would leave them untouched from
2281 * the previous stripe). This is needed to avoid printing
2282 * random data under the bottom margin.
2283 */
2284 ret = LHDATA | LAST;
2285 }
2286 else
2287 {
2288 /* If we are not at the end of the page, copy one more
2289 * scanline into the buffer.
2290 */
2291 gdev_prn_get_bits((gx_device_printer *)gendata.dev,
2292 vline, data+ofs, &in_data);
2293 if(in_data != data+ofs)memcpy(data+ofs, in_data, gendata.numrbytes);
2294 }
2295
2296 vline++;
2297 data += gendata.numbytes;
2298
2299 }
2300
2301 return(ret);
2302 }
2303
2304 /* Fill the buffer with initial data.
2305 * This routine is used to load the first buffer at the
2306 * beginning of the page. If we are printing in monochromatic
2307 * mode, we just call fill_mono_buffer for the first line.
2308 * If we are printing in color mode, we have a problem to
2309 * solve: since the color pen are stacked vertically, we
2310 * need multiple head passes to print all colors on the
2311 * same line. So, to simplify all, we start with the paper
2312 * at a fixed vertical position, even if it's blank, and
2313 * then we go down in fixed increments, equal to the height
2314 * of a color pen. This means we check all buffers without
2315 * skipping over blank ones, but since we actually send the
2316 * printing commands to the printer only when there is something
2317 * to print, there is no speed impact.
2318 */
2319 static int
init_buffer(void)2320 init_buffer(void)
2321 {
2322 byte *in_data, *data;
2323 int i, ret, p1, p2, ofs;
2324
2325 data = gendata.scanbuf;
2326 ofs = gendata.goffset;
2327
2328 if(gendata.rendermode == LXM3200_M)return(fill_mono_buffer(0));
2329
2330 /* We position the heads with the bottom color pen (the
2331 * yellow one in the color cartridge and the black one
2332 * in the photo cartridge) just covering the first lines
2333 * of the paper sheet. So the first buffer is divided in
2334 * two parts: "p1" is the number of lines above the top
2335 * border and "p2" the number of lines below.
2336 */
2337 p1 = 368 / gendata.yrmul;
2338 p2 = 144 / gendata.yrmul;
2339
2340 /* Initialize the counters */
2341 gendata.curvline = -p1;
2342 gendata.lastblack = gendata.curvline - 1;
2343 data = gendata.scanbuf;
2344
2345 /* Clear the lines of the buffer that correspond to
2346 * lines above the top margin: of course we don't
2347 * want to print anything on the air...
2348 */
2349 for(i=0; i<p1; i++)
2350 {
2351 memset(data, 0, gendata.numbytes);
2352 data += gendata.numbytes;
2353 }
2354
2355 /* And now load the last part of the buffer.
2356 * Note that here we don't check for blank lines,
2357 * this will be cared for later.
2358 */
2359 for(i=0; i<p2; i++)
2360 {
2361 memset(data, 0, gendata.numbytes);
2362
2363 if(i < gendata.numvlines)
2364 {
2365 gdev_prn_get_bits((gx_device_printer *)gendata.dev,
2366 i, data+ofs, &in_data);
2367 if(in_data != data+ofs)memcpy(data+ofs, in_data, gendata.numrbytes);
2368 }
2369
2370 data += gendata.numbytes;
2371 }
2372
2373 gendata.firstline = 0;
2374
2375 /* Now check the return value. If by chance we are under
2376 * the bottom margin, add the LAST bit to the return value.
2377 * Of course, since this is the first buffer of the page,
2378 * it's not likely we will reach the bottom margin in
2379 * this pass. Anyway this is code that will be executed
2380 * only once per page, so better safe than sorry.
2381 */
2382 ret = (gendata.numvlines < p2 ? LAST : 0) | qualify_buffer();
2383
2384 return(ret);
2385 }
2386
2387 /* This function checks if the current buffer contains
2388 * data to be printed with the left or right head.
2389 * It assumes that we are printing in color mode, and it
2390 * is useful to minimize the number of needed passes.
2391 * When we are printing in monochrome mode we directly skip
2392 * over blank lines, so this routine is not needed.
2393 */
2394 static int
qualify_buffer(void)2395 qualify_buffer(void)
2396 {
2397 int i, j, k, ret;
2398 int rmsk, q, v1;
2399 int bpsz, cpsz;
2400 byte *data;
2401
2402 ret = 0;
2403
2404 /* Set variables which contains the size, in rows, of
2405 * each color pen and of the black pen in color mode,
2406 * adjusting for different resolution settings.
2407 * Also set the mask used to rollover the buffer.
2408 */
2409 cpsz = (COLORPEN * 2) / gendata.yrmul;
2410 bpsz = (BWCOLPEN * 2) / gendata.yrmul;
2411 rmsk = gendata.numblines - 1;
2412
2413 /* Check the right head data, it is always a color cartridge */
2414 for(k=0; k<3 && ret==0; k++)
2415 {
2416 /* For each pen, scan all the bytes on each row of
2417 * the buffer that is covered by the current pen,
2418 * ORing together all the bits.
2419 */
2420 v1 = 0;
2421 q = gendata.firstline + valign[COLORVALIGN] + penofs[k];
2422 for(i=0; i<cpsz; i++)
2423 {
2424 data = gendata.scanbuf + ((q+i) & rmsk)*gendata.numbytes;
2425 for(j=0; j<gendata.numbytes; j++)v1 |= *data++;
2426 }
2427 /* If the result of the OR has the proper color bit
2428 * set, it means that this buffer contains at least
2429 * one pixel of this pen, so we need a color pass.
2430 * Note that we exit as soon as we find a color bit
2431 * set, because if at least one color pen is used
2432 * in this buffer we need to do a color pass anyway,
2433 * so there's no need to check the other two pens.
2434 */
2435 if(v1 & colmask[RIGHT][k])ret |= RHDATA;
2436 }
2437
2438 /* Check the left head data: it could be a black or
2439 * a photo cartridge, depending on the printing mode.
2440 */
2441 if(gendata.rendermode == LXM3200_C)
2442 {
2443 /* We are in standard color mode: the left cartridge
2444 * is a black cartridge used in 192 nozzles mode.
2445 * This is done exactly in the same way as above, but
2446 * without the outer loop because we have only one
2447 * color pen on this cartridge.
2448 */
2449 v1 = 0;
2450 q = gendata.firstline + valign[BLACKVALIGN];
2451 for(i=0; i<bpsz; i++)
2452 {
2453 data = gendata.scanbuf + ((q+i) & rmsk)*gendata.numbytes;
2454 for(j=0; j<gendata.numbytes; j++)v1 |= *data++;
2455 }
2456 if(v1 & BLACK)ret |= LHDATA;
2457 }
2458 else
2459 {
2460 /* If we are here we need to check for a photo cartridge
2461 * (this routine is never called in monochrome mode, so
2462 * if we are not in color mode we must be in photo mode).
2463 * This routine is identical to the color routine above.
2464 */
2465 for(k=0; k<3 && !(ret & LHDATA); k++)
2466 {
2467 v1 = 0;
2468 q = gendata.firstline + valign[PHOTOVALIGN] + penofs[k];
2469 for(i=0; i<cpsz; i++)
2470 {
2471 data = gendata.scanbuf + ((q+i) & rmsk)*gendata.numbytes;
2472 for(j=0; j<gendata.numbytes; j++)v1 |= *data++;
2473 }
2474 if(v1 & colmask[LEFT][k])ret |= LHDATA;
2475 }
2476 }
2477
2478 return(ret);
2479 }
2480
2481 /* This functions rolls the circular buffer by the
2482 * number of lines of one color pen, reading new
2483 * lines to refill the buffer.
2484 * In color mode we use a circular buffer because
2485 * we need to read the same lines more than once.
2486 * So when we are forwarding to the next pass we
2487 * simply read in the new lines and then update the
2488 * pointers, without actually moving data into memory.
2489 * The need to read the same data more than once arises
2490 * from the fact that the color pens are vertically
2491 * stacked, so we need to read a data line to lay down
2492 * the yellow component at the first pass. We need to
2493 * read it again at the next pass to lay down magenta,
2494 * and on the last pass we read the same line once more
2495 * to lay down the cyan component.
2496 */
2497 static int
roll_buffer(void)2498 roll_buffer(void)
2499 {
2500 int i, ret, fline, vl, ofs;
2501 int cpen, cmask, lline;
2502 byte *data, *in_data;
2503
2504 /* Adjust the size of the color pen and the
2505 * mask to take into account the current resolution
2506 */
2507 cpen = (COLORPEN * 2) / gendata.yrmul;
2508 cmask = (gendata.numblines) - 1;
2509
2510 /* Calculate the line number corresponding to
2511 * the last buffer we can print before being
2512 * forced to eject the page. At 600dpi this
2513 * has been experimentally determined to be
2514 * 112 lines from the bottom of the page.
2515 */
2516 lline = gendata.numvlines - (224 / gendata.yrmul);
2517
2518 /* Roll the buffer by advancing the first line
2519 * pointer by the height of one color pen.
2520 */
2521 fline = gendata.firstline;
2522 gendata.firstline = (fline + cpen) & cmask;
2523
2524 /* Now calculate the pointer to the first "fresh"
2525 * line on the page, i.e. the first line we must
2526 * read into the buffer at this pass.
2527 */
2528 vl = gendata.curvline + cmask + 1;
2529
2530 /* Take into account the guard offset */
2531 ofs = gendata.goffset;
2532
2533 /* Initialize the return value and update the
2534 * current vertical position on the page, while
2535 * checking if we have reached the last printable
2536 * buffer.
2537 */
2538 ret = 0;
2539 gendata.curvline += cpen;
2540 if(gendata.curvline >= lline)ret = LAST;
2541
2542 /* Now read "fresh" rasterized scanlines into the
2543 * input buffer.
2544 */
2545 for(i=0; i<cpen; i++)
2546 {
2547 data = gendata.scanbuf + ((fline + i) & cmask) * gendata.numbytes;
2548
2549 memset(data, 0, gendata.numbytes);
2550 if(vl < gendata.numvlines)
2551 {
2552 gdev_prn_get_bits((gx_device_printer *)gendata.dev,
2553 vl, data+ofs, &in_data);
2554 if(in_data != data+ofs)memcpy(data+ofs, in_data, gendata.numrbytes);
2555 }
2556 vl++;
2557 }
2558
2559 /* And test for the presence of actual data to print */
2560 ret |= qualify_buffer();
2561
2562 return(ret);
2563 }
2564
2565 /* Calculate the margins of one line, i.e. the leftmost
2566 * and the rightmost non-blank pixel on the line.
2567 *
2568 * data: the pointer to the data for this line
2569 * mask: the mask with the bits to check for: if the buffer
2570 * contains data which is not on the mask it will be
2571 * ignored (for the purpose of calculating margins)
2572 * left: calculated left margin (output variable)
2573 * right: calculated right margin (output variable)
2574 */
2575 static void
calclinemargins(byte * data,int mask,int * left,int * right)2576 calclinemargins(byte *data, int mask, int *left, int *right)
2577 {
2578 int l,r,num;
2579
2580 num = gendata.numbytes - 1;
2581
2582 l = 0;
2583 while((l <= num) && ((data[l] & mask) == 0))l++;
2584
2585 r = num;
2586 while((r >= 0) && ((data[r] & mask) == 0))r--;
2587
2588 *left = l;
2589 *right = r;
2590 }
2591
2592 /* Calculate the margins of the whole buffer. The
2593 * calculation accounts separately for the data to
2594 * be printed with the left or with the right head,
2595 * so we can try to minimize the head movement even
2596 * on multiple passes.
2597 *
2598 * head: the code of the head we are calculating
2599 * margins for (LEFT or RIGHT)
2600 */
2601 static void
calcbufmargins(int head)2602 calcbufmargins(int head)
2603 {
2604 int i, l1, r1, q, k;
2605 int mleft, mright, nl;
2606 int cpen, cmask, al;
2607 byte *scan;
2608
2609 /* Adjust mask and pen height according to vertical resolution */
2610 cpen = (COLORPEN * 2) / gendata.yrmul;
2611 cmask = (gendata.numblines) - 1;
2612
2613 /* Calculate margins for a color or photo cartridge */
2614 if(head == RIGHT || (gendata.rendermode == LXM3200_P))
2615 {
2616 /* Get correct vertical aligment */
2617 al = (head == LEFT ? PHOTOVALIGN : COLORVALIGN);
2618
2619 q = gendata.firstline + valign[al];
2620
2621 /* Calculate margins for first line, using those values
2622 * to initialize the max and min values.
2623 */
2624 scan = gendata.scanbuf + ((q+penofs[0]) & cmask)*gendata.numbytes;
2625 calclinemargins(scan, colmask[head][0], &mleft, &mright);
2626
2627 /* And now scan all the remaining buffer. We scan according
2628 * to color pens, i.e. we calculate the margin on the rows
2629 * where magenta will be laid down taking into account magenta
2630 * pixels only, and this will be the magenta submargin. After
2631 * having done that for cyan and yellow as well, we take as the
2632 * global margin the smaller space that contains all the three
2633 * submargins.
2634 */
2635 for(k=0; k<3; k++)
2636 {
2637 for(i=0; i<cpen; i++)
2638 {
2639 scan = gendata.scanbuf + ((q+i+penofs[k]) & cmask)*gendata.numbytes;
2640 calclinemargins(scan, colmask[head][k], &l1, &r1);
2641 mleft = min(mleft, l1);
2642 mright = max(mright, r1);
2643 }
2644 }
2645
2646 gendata.left = mleft;
2647 gendata.right = mright;
2648
2649 return;
2650 }
2651
2652 /* Calculate buffer margins for a black head. This is
2653 * almost exactly the same as before, but now we do
2654 * a single pass because we have only one black pen.
2655 */
2656 if(gendata.rendermode == LXM3200_M)
2657 {
2658 /* Monochromatic mode: we use 208 nozzles and
2659 * all the buffer, so the initial offset is zero.
2660 */
2661
2662 scan = gendata.scanbuf;
2663 calclinemargins(scan, BLACK, &mleft, &mright);
2664
2665 for(i=1; i<gendata.numblines; i++)
2666 {
2667 scan += gendata.numbytes;
2668 calclinemargins(scan, BLACK, &l1, &r1);
2669 mleft = min(mleft, l1);
2670 mright = max(mright, r1);
2671 }
2672
2673 gendata.left = mleft;
2674 gendata.right = mright;
2675
2676 return;
2677 }
2678
2679 /* Standard color mode: we use 192 nozzles and must
2680 * take into account the vertical alignment.
2681 */
2682
2683 nl = (gendata.numlines * 2) / gendata.yrmul;
2684 q = gendata.firstline + valign[BLACKVALIGN];
2685
2686 scan = gendata.scanbuf + (q & cmask)*gendata.numbytes;
2687 calclinemargins(scan, BLACK, &mleft, &mright);
2688
2689 for(i=1; i<nl; i++)
2690 {
2691 scan = gendata.scanbuf + ((q+i) & cmask)*gendata.numbytes;
2692 calclinemargins(scan, BLACK, &l1, &r1);
2693 mleft = min(mleft, l1);
2694 mright = max(mright, r1);
2695 }
2696 gendata.left = mleft;
2697 gendata.right = mright;
2698 }
2699
2700 /*
2701 * This is the main routine that prints in
2702 * standard color mode.
2703 */
2704 static void
print_color_page(void)2705 print_color_page(void)
2706 {
2707 int res, lline, cmask;
2708 int i, j, nl, q, sk;
2709 byte *scan;
2710
2711 /* Set the blackskip value depending on vertical resolution.
2712 * Since we have a black pen which is 3 times as high as
2713 * each color pen, we must print black only once every three
2714 * passes. So we take into account on which line we printed
2715 * the last black stripe and then we print another only if
2716 * the current line is at least "sk" lines after that.
2717 */
2718 sk = (BWCOLPEN * 2) / gendata.yrmul;
2719
2720 /* Get the first buffer, and if it's empty continue
2721 * to skip forward without doing anything.
2722 */
2723 res = init_buffer();
2724 while(res == 0)res = roll_buffer();
2725
2726 /* If this buffer happens to be the last one,
2727 * and empty as well, we had a blank page.
2728 * Just exit without ado.
2729 */
2730 if(res == LAST)return;
2731
2732 /* This is the first non-blank line of the
2733 * page: issue a vertical skip command to
2734 * advance the paper to proper position.
2735 */
2736 skiplines(gendata.curvline, COLTOPSTART);
2737
2738 /* "lline" holds the number of the first line of
2739 * the last buffer printed, either with left or
2740 * right head. This is needed to keep track of
2741 * how many lines we must skip from one stripe to
2742 * the next (if we encounter blank buffers we just
2743 * ignore them without moving the head, so we need
2744 * to do the proper vertical motion in one single
2745 * pass as soon as we encounter a non-blank buffer).
2746 */
2747 lline = gendata.curvline;
2748
2749 /* Now depending on the data we have into the
2750 * buffer, print with the left head, right
2751 * head or both.
2752 * NOTE: this is the first buffer, and it needs
2753 * to be treated specially from the others.
2754 * The main difference is that we usually finalize
2755 * the buffer (issuing the print commands) at the
2756 * start of the next buffer, and not at the end of
2757 * the current one. This is because the Lexmark 3200
2758 * wants to know where to leave the printing head
2759 * at the end of each printing command, but we can't
2760 * know that until we start the next buffer so discovering
2761 * its margins and position. The solution is that we keep
2762 * "suspended" each buffer until we find another valid one.
2763 * The first buffer is special since there is no previous
2764 * buffer to finalize.
2765 * NOTE: I will comment the general case below, because
2766 * this code is simply a subset of the main loop.
2767 */
2768 switch(res)
2769 {
2770 case LHDATA:
2771 calcbufmargins(LEFT);
2772 gendata.ileave = 0;
2773 encode_bw_buf();
2774 gendata.lastblack = gendata.curvline + sk;
2775 lline = gendata.curvline;
2776 if(gendata.yres == 1200)
2777 {
2778 finalizeheader(1, LEFT);
2779 gendata.ileave = 1;
2780 encode_bw_buf();
2781 lline++;
2782 }
2783 break;
2784
2785 case RHDATA:
2786 calcbufmargins(RIGHT);
2787 gendata.ileave = 0;
2788 encode_col_buf(RIGHT);
2789 lline = gendata.curvline;
2790 if(gendata.yres == 1200)
2791 {
2792 finalizeheader(1, RIGHT);
2793 gendata.ileave = 1;
2794 encode_col_buf(RIGHT);
2795 lline++;
2796 }
2797 break;
2798
2799 case LHDATA|RHDATA:
2800 calcbufmargins(LEFT);
2801 gendata.ileave = 0;
2802 encode_bw_buf();
2803 gendata.lastblack = gendata.curvline + sk;
2804 calcbufmargins(RIGHT);
2805 finalizeheader(0, RIGHT);
2806 encode_col_buf(RIGHT);
2807 lline = gendata.curvline;
2808 if(gendata.yres == 1200)
2809 {
2810 calcbufmargins(LEFT);
2811 finalizeheader(1, LEFT);
2812 gendata.ileave = 1;
2813 encode_bw_buf();
2814 calcbufmargins(RIGHT);
2815 finalizeheader(0, RIGHT);
2816 encode_col_buf(RIGHT);
2817 lline++;
2818 }
2819 break;
2820 }
2821
2822 /* Skip to next buffer */
2823 res = roll_buffer();
2824
2825 /* Start the main loop. Here we do all the stuff required
2826 * to print buffers properly.
2827 */
2828 while(!(res & LAST))
2829 {
2830 /* If we haven't forwarded until "lastblack", do not
2831 * print black data because it has been printed on
2832 * previous passes. So, if we are below gendata.lastblack
2833 * clear the LHDATA flag to ignore left-head data.
2834 */
2835 if(gendata.curvline < gendata.lastblack)res &= ~LHDATA;
2836
2837 /* And now start examining the buffer for data */
2838 switch(res)
2839 {
2840 /* We have left head data */
2841 case LHDATA:
2842
2843 /* Calculate the margins of this buffer */
2844 calcbufmargins(LEFT);
2845
2846 /* And then finalize the previous buffer. We can't
2847 * do this until now, because only now we know the
2848 * margins and vertical position of the next buffer,
2849 * which are required data to calculate the final
2850 * head position at the end of the previous buffer.
2851 */
2852 finalizeheader(gendata.curvline - lline, LEFT);
2853
2854 /* Set interleave to zero (only meaningful in 1200dpi
2855 * vertical mode.
2856 */
2857 gendata.ileave = 0;
2858
2859 /* Encode this buffer making it the current buffer */
2860 encode_bw_buf();
2861
2862 /* Since we are printing a black buffer, update
2863 * gendata.lastblack to point to the first line
2864 * not covered by this black pass.
2865 */
2866 gendata.lastblack = gendata.curvline + sk;
2867
2868 /* And update "lline" as well */
2869 lline = gendata.curvline;
2870
2871 /* If we are printing at 1200 dpi vertical, we must
2872 * do one more pass, interleaved with the one before.
2873 */
2874 if(gendata.yres == 1200)
2875 {
2876 /* Finalize previous buffer, moving down 1/1200th
2877 * of an inch to properly interleave the two passes.
2878 * This is naive: we should do something here, because
2879 * this way two adjacent lines are printed by the same
2880 * nozzle, and there is the danger of having a slight
2881 * banding on output (no more than 1/600th of an inch,
2882 * but maybe noticeable).
2883 */
2884 finalizeheader(1, LEFT);
2885
2886 /* Set interleave to 1 to start an interleaved pass */
2887 gendata.ileave = 1;
2888
2889 /* Encode the buffer, and not finalize it: we leave
2890 * the buffer suspended until we find another buffer
2891 * to print.
2892 */
2893 encode_bw_buf();
2894
2895 /* And adjust "lline" because to print the interleaved
2896 * pass we have moved down one line, so we need to
2897 * skip one line less to print the next buffer.
2898 */
2899 lline++;
2900 }
2901 break;
2902
2903 /* Right head data. This is absolutely identical to the
2904 * code above for left head data, with two exceptions: all
2905 * the "LEFT" codes are changed to "RIGHT" and we don't
2906 * update gendata.lastblack because we are printing a
2907 * color stripe and not a black one.
2908 */
2909 case RHDATA:
2910 calcbufmargins(RIGHT);
2911 finalizeheader(gendata.curvline - lline, RIGHT);
2912 gendata.ileave = 0;
2913 encode_col_buf(RIGHT);
2914 lline = gendata.curvline;
2915 if(gendata.yres == 1200)
2916 {
2917 finalizeheader(1, RIGHT);
2918 gendata.ileave = 1;
2919 encode_col_buf(RIGHT);
2920 lline++;
2921 }
2922 break;
2923
2924 /* We have both left and right head data (i.e. black and
2925 * color on the same stripe).
2926 * The code here is identical to the code for the left data
2927 * only and right data only cases above. But they are
2928 * interleaved, because since we can't take back the paper
2929 * once it's advanced, in case we are printing at 1200 dpi
2930 * vertical (and so we need two interlaced passes) we need
2931 * to do both the first black and the first color pass,
2932 * advance the paper and then do the second black and the
2933 * second color pass. Simply appendig the two code pieces
2934 * above would not work.
2935 */
2936 case LHDATA|RHDATA:
2937 calcbufmargins(LEFT);
2938 finalizeheader(gendata.curvline - lline, LEFT);
2939 gendata.ileave = 0;
2940 encode_bw_buf();
2941 gendata.lastblack = gendata.curvline + sk;
2942 calcbufmargins(RIGHT);
2943 finalizeheader(0, RIGHT);
2944 encode_col_buf(RIGHT);
2945 lline = gendata.curvline;
2946 if(gendata.yres == 1200)
2947 {
2948 calcbufmargins(LEFT);
2949 finalizeheader(1, LEFT);
2950 gendata.ileave = 1;
2951 encode_bw_buf();
2952 calcbufmargins(RIGHT);
2953 finalizeheader(0, RIGHT);
2954 encode_col_buf(RIGHT);
2955 lline++;
2956 }
2957 break;
2958 }
2959
2960 /* Get another buffer */
2961 res = roll_buffer();
2962 }
2963
2964 /* Last buffer. We treat this one specially as well,
2965 * because we don't have a subsequent buffer to print,
2966 * and so we need to finalize this buffers as soon as
2967 * possible.
2968 */
2969 res = qualify_buffer();
2970
2971 /* Void the printed blacks. Since we are printing the
2972 * last buffer, it could happen that we have advanced
2973 * from the last time we printed a black stripe but
2974 * we are not yet at the point where another black
2975 * stripe would have been triggered. This would cause
2976 * an eventual black component in the last lines of
2977 * the page to be ignored.
2978 * To avoid the problem we do an unconditional black
2979 * pass, but we also must clear the black bits from the
2980 * lines we have already printed otherwise we would
2981 * print them twice.
2982 */
2983 if((res & LHDATA) && (gendata.curvline <= gendata.lastblack))
2984 {
2985 /* Find how many black lines we have yet printed
2986 * are still in the buffer
2987 */
2988 nl = gendata.lastblack - gendata.curvline;
2989
2990 /* And now remove the BLACK bit from them */
2991
2992 q = gendata.firstline + valign[BLACKVALIGN];
2993 cmask = (gendata.numblines) - 1;
2994 for(i=0; i<nl; i++)
2995 {
2996 scan = gendata.scanbuf + ((i+q) & cmask)*gendata.numbytes;
2997 for(j=0; j<gendata.numbytes; j++)
2998 {
2999 *scan &= ~BLACK;
3000 scan++;
3001 }
3002 }
3003 }
3004
3005 /* Now we can print the last buffer as usual.
3006 * This is perfectly identical to the code
3007 * into the loop above: we are replicating it
3008 * only because we need the blanking code above
3009 * to be executed before this code.
3010 * Maybe there is a better way to do it...
3011 */
3012 switch(res)
3013 {
3014 case LHDATA:
3015 calcbufmargins(LEFT);
3016 finalizeheader(gendata.curvline - lline, LEFT);
3017 gendata.ileave = 0;
3018 encode_bw_buf();
3019 if(gendata.yres == 1200)
3020 {
3021 finalizeheader(1, LEFT);
3022 gendata.ileave = 1;
3023 encode_bw_buf();
3024 lline++;
3025 }
3026 break;
3027
3028 case RHDATA:
3029 calcbufmargins(RIGHT);
3030 finalizeheader(gendata.curvline - lline, RIGHT);
3031 gendata.ileave = 0;
3032 encode_col_buf(RIGHT);
3033 if(gendata.yres == 1200)
3034 {
3035 finalizeheader(1, RIGHT);
3036 gendata.ileave = 1;
3037 encode_col_buf(RIGHT);
3038 lline++;
3039 }
3040 break;
3041
3042 case LHDATA|RHDATA:
3043 calcbufmargins(LEFT);
3044 finalizeheader(gendata.curvline - lline, LEFT);
3045 gendata.ileave = 0;
3046 encode_bw_buf();
3047 calcbufmargins(RIGHT);
3048 finalizeheader(0, RIGHT);
3049 encode_col_buf(RIGHT);
3050 if(gendata.yres == 1200)
3051 {
3052 calcbufmargins(LEFT);
3053 finalizeheader(1, LEFT);
3054 gendata.ileave = 1;
3055 encode_bw_buf();
3056 calcbufmargins(RIGHT);
3057 finalizeheader(0, RIGHT);
3058 encode_col_buf(RIGHT);
3059 lline++;
3060 }
3061 break;
3062 }
3063
3064 /* Now finalize the header using a value of "0" for
3065 * the vertical skip (no need to move down: the
3066 * paper is about to be ejected) and -1 for the
3067 * head (meaning: last buffer, don't care for the
3068 * final head position, it will be reset unconditionally
3069 * by the trailing sequence).
3070 */
3071 finalizeheader(0, -1);
3072 }
3073
3074 /* This is the equivalent of print_color_page()
3075 * for monochrome output. It is almost identical,
3076 * only much simpler because now we are printing
3077 * with only one head.
3078 */
3079 static void
print_mono_page(void)3080 print_mono_page(void)
3081 {
3082 int res, lline;
3083
3084 /* Load the first buffer, skipping over
3085 * blank lines (if any).
3086 */
3087 res = init_buffer();
3088
3089 /* If we happen to have a buffer which is LAST
3090 * and empty, we have a blank page to print:
3091 * just say goodbye.
3092 */
3093 if(res == LAST)return;
3094
3095 /* Skip enough lines to reach the start of
3096 * the first stripe to print.
3097 */
3098 skiplines(gendata.curvline, BWTOPSTART);
3099 lline = gendata.curvline;
3100
3101 /* And now print the first buffer. This part of
3102 * the code is identical to the LHDATA part in
3103 * print_color_page()
3104 */
3105 calcbufmargins(LEFT);
3106 gendata.ileave = 0;
3107 encode_bw_buf();
3108 lline = gendata.curvline;
3109 if(gendata.yres == 1200)
3110 {
3111 finalizeheader(1, LEFT);
3112 gendata.ileave = 1;
3113 encode_bw_buf();
3114 lline++;
3115 }
3116
3117 /* And now load another buffer, starting to
3118 * look for it from the first line after the
3119 * pass we have just done.
3120 */
3121 res = fill_mono_buffer(gendata.curvline + gendata.numblines);
3122
3123 /* Now loop. Even this code is identical
3124 * to the code above: the only difference
3125 * is that here we also finalize the previous
3126 * buffer before encoding this one. No need
3127 * to check if the buffer is empty because
3128 * a buffer is reported only if it's full
3129 * or if it is the last one, so if it's not
3130 * the last it must be full.
3131 */
3132 while(!(res & LAST))
3133 {
3134 calcbufmargins(LEFT);
3135 finalizeheader(gendata.curvline - lline, LEFT);
3136 gendata.ileave = 0;
3137 encode_bw_buf();
3138 lline = gendata.curvline;
3139 if(gendata.yres == 1200)
3140 {
3141 finalizeheader(1, LEFT);
3142 gendata.ileave = 1;
3143 encode_bw_buf();
3144 lline++;
3145 }
3146
3147 /* Get another buffer, and so on */
3148 res = fill_mono_buffer(gendata.curvline + gendata.numblines);
3149 }
3150
3151 /* Last buffer. This can be either empty or full.
3152 * If it's not empty (LHDATA bit set), print it.
3153 */
3154 if(res & LHDATA)
3155 {
3156 calcbufmargins(LEFT);
3157 finalizeheader(gendata.curvline - lline, LEFT);
3158 encode_bw_buf();
3159 if(gendata.yres == 1200)
3160 {
3161 finalizeheader(1, LEFT);
3162 gendata.ileave = 1;
3163 encode_bw_buf();
3164 lline++;
3165 }
3166 }
3167
3168 /* Finalize the last buffer */
3169 finalizeheader(0, -1);
3170 }
3171
3172 /* This is the equivalent of print_color_page()
3173 * for photoquality output. They are almost identical,
3174 * the only real difference is that we now are
3175 * printing with two identical heads, so there is
3176 * no need to care for different heights of the
3177 * printing pens (i.e.: no "lastblack" tricks).
3178 */
3179 static void
print_photo_page(void)3180 print_photo_page(void)
3181 {
3182 int res, lline;
3183
3184 res = init_buffer();
3185 while(res == 0)res = roll_buffer();
3186
3187 if(res == LAST)return;
3188
3189 skiplines(gendata.curvline, COLTOPSTART);
3190 lline = gendata.curvline;
3191
3192 switch(res)
3193 {
3194 case LHDATA:
3195 calcbufmargins(LEFT);
3196 gendata.ileave = 0;
3197 encode_col_buf(LEFT);
3198 lline = gendata.curvline;
3199 if(gendata.yres == 1200)
3200 {
3201 finalizeheader(1, LEFT);
3202 gendata.ileave = 1;
3203 encode_col_buf(LEFT);
3204 lline++;
3205 }
3206 break;
3207
3208 case RHDATA:
3209 calcbufmargins(RIGHT);
3210 gendata.ileave = 0;
3211 encode_col_buf(RIGHT);
3212 lline = gendata.curvline;
3213 if(gendata.yres == 1200)
3214 {
3215 finalizeheader(1, RIGHT);
3216 gendata.ileave = 1;
3217 encode_col_buf(RIGHT);
3218 lline++;
3219 }
3220 break;
3221
3222 case LHDATA|RHDATA:
3223 calcbufmargins(LEFT);
3224 gendata.ileave = 0;
3225 encode_col_buf(LEFT);
3226 calcbufmargins(RIGHT);
3227 finalizeheader(0, RIGHT);
3228 encode_col_buf(RIGHT);
3229 lline = gendata.curvline;
3230 if(gendata.yres == 1200)
3231 {
3232 calcbufmargins(LEFT);
3233 finalizeheader(1, LEFT);
3234 gendata.ileave = 1;
3235 encode_col_buf(LEFT);
3236 calcbufmargins(RIGHT);
3237 finalizeheader(0, RIGHT);
3238 encode_col_buf(RIGHT);
3239 lline++;
3240 }
3241
3242 break;
3243 }
3244
3245 res = roll_buffer();
3246
3247 while(!(res & LAST))
3248 {
3249 switch(res)
3250 {
3251 case LHDATA:
3252 calcbufmargins(LEFT);
3253 finalizeheader(gendata.curvline - lline, LEFT);
3254 gendata.ileave = 0;
3255 encode_col_buf(LEFT);
3256 lline = gendata.curvline;
3257 if(gendata.yres == 1200)
3258 {
3259 finalizeheader(1, LEFT);
3260 gendata.ileave = 1;
3261 encode_col_buf(LEFT);
3262 lline++;
3263 }
3264 break;
3265
3266 case RHDATA:
3267 calcbufmargins(RIGHT);
3268 finalizeheader(gendata.curvline - lline, RIGHT);
3269 gendata.ileave = 0;
3270 encode_col_buf(RIGHT);
3271 lline = gendata.curvline;
3272 if(gendata.yres == 1200)
3273 {
3274 finalizeheader(1, RIGHT);
3275 gendata.ileave = 1;
3276 encode_col_buf(RIGHT);
3277 lline++;
3278 }
3279 break;
3280
3281 case LHDATA|RHDATA:
3282 calcbufmargins(LEFT);
3283 finalizeheader(gendata.curvline - lline, LEFT);
3284 gendata.ileave = 0;
3285 encode_col_buf(LEFT);
3286 calcbufmargins(RIGHT);
3287 finalizeheader(0, RIGHT);
3288 encode_col_buf(RIGHT);
3289 lline = gendata.curvline;
3290 if(gendata.yres == 1200)
3291 {
3292 calcbufmargins(LEFT);
3293 finalizeheader(1, LEFT);
3294 gendata.ileave = 1;
3295 encode_col_buf(LEFT);
3296 calcbufmargins(RIGHT);
3297 finalizeheader(0, RIGHT);
3298 encode_col_buf(RIGHT);
3299 lline++;
3300 }
3301 break;
3302 }
3303
3304 res = roll_buffer();
3305 }
3306
3307 switch(res)
3308 {
3309 case LHDATA:
3310 calcbufmargins(LEFT);
3311 finalizeheader(gendata.curvline - lline, LEFT);
3312 gendata.ileave = 0;
3313 encode_col_buf(LEFT);
3314 if(gendata.yres == 1200)
3315 {
3316 finalizeheader(1, LEFT);
3317 gendata.ileave = 1;
3318 encode_col_buf(LEFT);
3319 lline++;
3320 }
3321
3322 case RHDATA:
3323 calcbufmargins(RIGHT);
3324 finalizeheader(gendata.curvline - lline, RIGHT);
3325 gendata.ileave = 0;
3326 encode_col_buf(RIGHT);
3327 if(gendata.yres == 1200)
3328 {
3329 finalizeheader(1, RIGHT);
3330 gendata.ileave = 1;
3331 encode_col_buf(RIGHT);
3332 lline++;
3333 }
3334 break;
3335
3336 case LHDATA|RHDATA:
3337 calcbufmargins(LEFT);
3338 finalizeheader(gendata.curvline - lline, LEFT);
3339 gendata.ileave = 0;
3340 encode_col_buf(LEFT);
3341 calcbufmargins(RIGHT);
3342 finalizeheader(0, RIGHT);
3343 encode_col_buf(RIGHT);
3344 if(gendata.yres == 1200)
3345 {
3346 calcbufmargins(LEFT);
3347 finalizeheader(1, LEFT);
3348 gendata.ileave = 1;
3349 encode_col_buf(LEFT);
3350 calcbufmargins(RIGHT);
3351 finalizeheader(0, RIGHT);
3352 encode_col_buf(RIGHT);
3353 lline++;
3354 }
3355 break;
3356 }
3357
3358 finalizeheader(0, -1);
3359 }
3360